Sync with the new ipfw3 version.
[ipfw.git] / original_passthru / protocol.c
diff --git a/original_passthru/protocol.c b/original_passthru/protocol.c
new file mode 100644 (file)
index 0000000..213924c
--- /dev/null
@@ -0,0 +1,1626 @@
+/*++\r
+\r
+Copyright(c) 1992-2000  Microsoft Corporation\r
+\r
+Module Name:\r
+\r
+    protocol.c\r
+\r
+Abstract:\r
+\r
+    Ndis Intermediate Miniport driver sample. This is a passthru driver.\r
+\r
+Author:\r
+\r
+Environment:\r
+\r
+\r
+Revision History:\r
+\r
+\r
+--*/\r
+\r
+\r
+#include "precomp.h"\r
+#pragma hdrstop\r
+\r
+#define MAX_PACKET_POOL_SIZE 0x0000FFFF\r
+#define MIN_PACKET_POOL_SIZE 0x000000FF\r
+\r
+//\r
+// NDIS version as 0xMMMMmmmm, where M=Major/m=minor (0x00050001 = 5.1); \r
+// initially unknown (0)\r
+// \r
+ULONG       NdisDotSysVersion =  0x0;\r
+\r
+\r
+#define NDIS_SYS_VERSION_51       0x00050001\r
+\r
+\r
+VOID\r
+PtBindAdapter(\r
+    OUT PNDIS_STATUS            Status,\r
+    IN  NDIS_HANDLE             BindContext,\r
+    IN  PNDIS_STRING            DeviceName,\r
+    IN  PVOID                   SystemSpecific1,\r
+    IN  PVOID                   SystemSpecific2\r
+    )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    Called by NDIS to bind to a miniport below.\r
+\r
+Arguments:\r
+\r
+    Status            - Return status of bind here.\r
+    BindContext        - Can be passed to NdisCompleteBindAdapter if this call is pended.\r
+    DeviceName         - Device name to bind to. This is passed to NdisOpenAdapter.\r
+    SystemSpecific1    - Can be passed to NdisOpenProtocolConfiguration to read per-binding information\r
+    SystemSpecific2    - Unused\r
+\r
+Return Value:\r
+\r
+    NDIS_STATUS_PENDING    if this call is pended. In this case call NdisCompleteBindAdapter\r
+    to complete.\r
+    Anything else          Completes this call synchronously\r
+\r
+--*/\r
+{\r
+    NDIS_HANDLE                     ConfigHandle = NULL;\r
+    PNDIS_CONFIGURATION_PARAMETER   Param;\r
+    NDIS_STRING                     DeviceStr = NDIS_STRING_CONST("UpperBindings");\r
+    NDIS_STRING                     NdisVersionStr = NDIS_STRING_CONST("NdisVersion");\r
+    PADAPT                          pAdapt = NULL;\r
+    NDIS_STATUS                     Sts;\r
+    UINT                            MediumIndex;\r
+    ULONG                           TotalSize;\r
+    BOOLEAN                         NoCleanUpNeeded = FALSE;\r
+\r
+\r
+    UNREFERENCED_PARAMETER(BindContext);\r
+    UNREFERENCED_PARAMETER(SystemSpecific2);\r
+    \r
+    DBGPRINT(("==> Protocol BindAdapter\n"));\r
+\r
+    do\r
+    {\r
+        //\r
+        // Access the configuration section for our binding-specific\r
+        // parameters.\r
+        //\r
+        NdisOpenProtocolConfiguration(Status,\r
+                                       &ConfigHandle,\r
+                                       SystemSpecific1);\r
+\r
+        if (*Status != NDIS_STATUS_SUCCESS)\r
+        {\r
+            break;\r
+        }\r
+        if (NdisDotSysVersion == 0)\r
+        {\r
+            NdisReadConfiguration(Status,\r
+                                  &Param,\r
+                                  ConfigHandle,\r
+                                  &NdisVersionStr,        // "NdisVersion"\r
+                                  NdisParameterInteger);\r
+            if (*Status != NDIS_STATUS_SUCCESS)\r
+            {\r
+                break;\r
+            }\r
+            \r
+            NdisDotSysVersion = Param->ParameterData.IntegerData;\r
+        }\r
+                        \r
+\r
+        //\r
+        // Read the "UpperBindings" reserved key that contains a list\r
+        // of device names representing our miniport instances corresponding\r
+        // to this lower binding. Since this is a 1:1 IM driver, this key\r
+        // contains exactly one name.\r
+        //\r
+        // If we want to implement a N:1 mux driver (N adapter instances\r
+        // over a single lower binding), then UpperBindings will be a\r
+        // MULTI_SZ containing a list of device names - we would loop through\r
+        // this list, calling NdisIMInitializeDeviceInstanceEx once for\r
+        // each name in it.\r
+        //\r
+        NdisReadConfiguration(Status,\r
+                              &Param,\r
+                              ConfigHandle,\r
+                              &DeviceStr,\r
+                              NdisParameterString);\r
+        if (*Status != NDIS_STATUS_SUCCESS)\r
+        {\r
+            break;\r
+        }\r
+\r
+        //\r
+        // Allocate memory for the Adapter structure. This represents both the\r
+        // protocol context as well as the adapter structure when the miniport\r
+        // is initialized.\r
+        //\r
+        // In addition to the base structure, allocate space for the device\r
+        // instance string.\r
+        //\r
+        TotalSize = sizeof(ADAPT) + Param->ParameterData.StringData.MaximumLength;\r
+\r
+        NdisAllocateMemoryWithTag(&pAdapt, TotalSize, TAG);\r
+\r
+        if (pAdapt == NULL)\r
+        {\r
+            *Status = NDIS_STATUS_RESOURCES;\r
+            break;\r
+        }\r
+\r
+        //\r
+        // Initialize the adapter structure. We copy in the IM device\r
+        // name as well, because we may need to use it in a call to\r
+        // NdisIMCancelInitializeDeviceInstance. The string returned\r
+        // by NdisReadConfiguration is active (i.e. available) only\r
+        // for the duration of this call to our BindAdapter handler.\r
+        //\r
+        NdisZeroMemory(pAdapt, TotalSize);\r
+        pAdapt->DeviceName.MaximumLength = Param->ParameterData.StringData.MaximumLength;\r
+        pAdapt->DeviceName.Length = Param->ParameterData.StringData.Length;\r
+        pAdapt->DeviceName.Buffer = (PWCHAR)((ULONG_PTR)pAdapt + sizeof(ADAPT));\r
+        NdisMoveMemory(pAdapt->DeviceName.Buffer,\r
+                       Param->ParameterData.StringData.Buffer,\r
+                       Param->ParameterData.StringData.MaximumLength);\r
+\r
+\r
+\r
+        NdisInitializeEvent(&pAdapt->Event);\r
+        NdisAllocateSpinLock(&pAdapt->Lock);\r
+\r
+        //\r
+        // Allocate a packet pool for sends. We need this to pass sends down.\r
+        // We cannot use the same packet descriptor that came down to our send\r
+        // handler (see also NDIS 5.1 packet stacking).\r
+        //\r
+        NdisAllocatePacketPoolEx(Status,\r
+                                   &pAdapt->SendPacketPoolHandle,\r
+                                   MIN_PACKET_POOL_SIZE,\r
+                                   MAX_PACKET_POOL_SIZE - MIN_PACKET_POOL_SIZE,\r
+                                   sizeof(SEND_RSVD));\r
+\r
+        if (*Status != NDIS_STATUS_SUCCESS)\r
+        {\r
+            break;\r
+        }\r
+\r
+        //\r
+        // Allocate a packet pool for receives. We need this to indicate receives.\r
+        // Same consideration as sends (see also NDIS 5.1 packet stacking).\r
+        //\r
+        NdisAllocatePacketPoolEx(Status,\r
+                                   &pAdapt->RecvPacketPoolHandle,\r
+                                   MIN_PACKET_POOL_SIZE,\r
+                                   MAX_PACKET_POOL_SIZE - MIN_PACKET_POOL_SIZE,\r
+                                   PROTOCOL_RESERVED_SIZE_IN_PACKET);\r
+\r
+        if (*Status != NDIS_STATUS_SUCCESS)\r
+        {\r
+            break;\r
+        }\r
+\r
+        //\r
+        // Now open the adapter below and complete the initialization\r
+        //\r
+        NdisOpenAdapter(Status,\r
+                          &Sts,\r
+                          &pAdapt->BindingHandle,\r
+                          &MediumIndex,\r
+                          MediumArray,\r
+                          sizeof(MediumArray)/sizeof(NDIS_MEDIUM),\r
+                          ProtHandle,\r
+                          pAdapt,\r
+                          DeviceName,\r
+                          0,\r
+                          NULL);\r
+\r
+        if (*Status == NDIS_STATUS_PENDING)\r
+        {\r
+            NdisWaitEvent(&pAdapt->Event, 0);\r
+            *Status = pAdapt->Status;\r
+        }\r
+\r
+        if (*Status != NDIS_STATUS_SUCCESS)\r
+        {\r
+            break;\r
+        }\r
+        PtReferenceAdapt(pAdapt);\r
+\r
+#pragma prefast(suppress: __WARNING_POTENTIAL_BUFFER_OVERFLOW, "Ndis guarantees MediumIndex to be within bounds");\r
+        pAdapt->Medium = MediumArray[MediumIndex];\r
+\r
+        //\r
+        // Now ask NDIS to initialize our miniport (upper) edge.\r
+        // Set the flag below to synchronize with a possible call\r
+        // to our protocol Unbind handler that may come in before\r
+        // our miniport initialization happens.\r
+        //\r
+        pAdapt->MiniportInitPending = TRUE;\r
+        NdisInitializeEvent(&pAdapt->MiniportInitEvent);\r
+\r
+        PtReferenceAdapt(pAdapt);\r
+\r
+        *Status = NdisIMInitializeDeviceInstanceEx(DriverHandle,\r
+                                           &pAdapt->DeviceName,\r
+                                           pAdapt);\r
+\r
+        if (*Status != NDIS_STATUS_SUCCESS)\r
+        {\r
+            if (pAdapt->MiniportIsHalted == TRUE)\r
+            {\r
+                NoCleanUpNeeded = TRUE;\r
+            }\r
+            \r
+            DBGPRINT(("BindAdapter: Adapt %p, IMInitializeDeviceInstance error %x\n",\r
+                pAdapt, *Status));\r
+            \r
+            if (PtDereferenceAdapt(pAdapt))\r
+            {\r
+                pAdapt = NULL;\r
+            }\r
+            \r
+            break;\r
+        }\r
+        \r
+        PtDereferenceAdapt(pAdapt);\r
+\r
+    } while(FALSE);\r
+\r
+    //\r
+    // Close the configuration handle now - see comments above with\r
+    // the call to NdisIMInitializeDeviceInstanceEx.\r
+    //\r
+    if (ConfigHandle != NULL)\r
+    {\r
+        NdisCloseConfiguration(ConfigHandle);\r
+    }\r
+\r
+    if ((*Status != NDIS_STATUS_SUCCESS) && (NoCleanUpNeeded == FALSE))\r
+    {\r
+        if (pAdapt != NULL)\r
+        {\r
+            if (pAdapt->BindingHandle != NULL)\r
+            {\r
+                NDIS_STATUS    LocalStatus;\r
+\r
+                //\r
+                // Close the binding we opened above.\r
+                //\r
+\r
+                NdisResetEvent(&pAdapt->Event);\r
+                \r
+                NdisCloseAdapter(&LocalStatus, pAdapt->BindingHandle);\r
+                pAdapt->BindingHandle = NULL;\r
+\r
+                if (LocalStatus == NDIS_STATUS_PENDING)\r
+                {\r
+                     NdisWaitEvent(&pAdapt->Event, 0);\r
+                     LocalStatus = pAdapt->Status;\r
+\r
+                     \r
+                }\r
+                if (PtDereferenceAdapt(pAdapt))\r
+                {\r
+                     pAdapt = NULL;\r
+                }\r
+            }\r
+        }\r
+    }\r
+\r
+\r
+    DBGPRINT(("<== Protocol BindAdapter: pAdapt %p, Status %x\n", pAdapt, *Status));\r
+}\r
+\r
+\r
+VOID\r
+PtOpenAdapterComplete(\r
+    IN  NDIS_HANDLE             ProtocolBindingContext,\r
+    IN  NDIS_STATUS             Status,\r
+    IN  NDIS_STATUS             OpenErrorStatus\r
+    )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    Completion routine for NdisOpenAdapter issued from within the PtBindAdapter. Simply\r
+    unblock the caller.\r
+\r
+Arguments:\r
+\r
+    ProtocolBindingContext    Pointer to the adapter\r
+    Status                    Status of the NdisOpenAdapter call\r
+    OpenErrorStatus            Secondary status(ignored by us).\r
+\r
+Return Value:\r
+\r
+    None\r
+\r
+--*/\r
+{\r
+    PADAPT      pAdapt =(PADAPT)ProtocolBindingContext;\r
+    \r
+    UNREFERENCED_PARAMETER(OpenErrorStatus);\r
+    \r
+    DBGPRINT(("==> PtOpenAdapterComplete: Adapt %p, Status %x\n", pAdapt, Status));\r
+    pAdapt->Status = Status;\r
+    NdisSetEvent(&pAdapt->Event);\r
+}\r
+\r
+\r
+VOID\r
+PtUnbindAdapter(\r
+    OUT PNDIS_STATUS           Status,\r
+    IN  NDIS_HANDLE            ProtocolBindingContext,\r
+    IN  NDIS_HANDLE            UnbindContext\r
+    )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    Called by NDIS when we are required to unbind to the adapter below.\r
+    This functions shares functionality with the miniport's HaltHandler.\r
+    The code should ensure that NdisCloseAdapter and NdisFreeMemory is called\r
+    only once between the two functions\r
+\r
+Arguments:\r
+\r
+    Status                    Placeholder for return status\r
+    ProtocolBindingContext    Pointer to the adapter structure\r
+    UnbindContext            Context for NdisUnbindComplete() if this pends\r
+\r
+Return Value:\r
+\r
+    Status for NdisIMDeinitializeDeviceContext\r
+\r
+--*/\r
+{\r
+    PADAPT         pAdapt =(PADAPT)ProtocolBindingContext;\r
+    NDIS_STATUS    LocalStatus;\r
+\r
+    UNREFERENCED_PARAMETER(UnbindContext);\r
+    \r
+    DBGPRINT(("==> PtUnbindAdapter: Adapt %p\n", pAdapt));\r
+\r
+    //\r
+    // Set the flag that the miniport below is unbinding, so the request handlers will\r
+    // fail any request comming later\r
+    // \r
+    NdisAcquireSpinLock(&pAdapt->Lock);\r
+    pAdapt->UnbindingInProcess = TRUE;\r
+    if (pAdapt->QueuedRequest == TRUE)\r
+    {\r
+        pAdapt->QueuedRequest = FALSE;\r
+        NdisReleaseSpinLock(&pAdapt->Lock);\r
+\r
+        PtRequestComplete(pAdapt,\r
+                         &pAdapt->Request,\r
+                         NDIS_STATUS_FAILURE );\r
+\r
+    }\r
+    else\r
+    {\r
+        NdisReleaseSpinLock(&pAdapt->Lock);\r
+    }\r
+#ifndef WIN9X\r
+    //\r
+    // Check if we had called NdisIMInitializeDeviceInstanceEx and\r
+    // we are awaiting a call to MiniportInitialize.\r
+    //\r
+    if (pAdapt->MiniportInitPending == TRUE)\r
+    {\r
+        //\r
+        // Try to cancel the pending IMInit process.\r
+        //\r
+        LocalStatus = NdisIMCancelInitializeDeviceInstance(\r
+                        DriverHandle,\r
+                        &pAdapt->DeviceName);\r
+\r
+        if (LocalStatus == NDIS_STATUS_SUCCESS)\r
+        {\r
+            //\r
+            // Successfully cancelled IM Initialization; our\r
+            // Miniport Initialize routine will not be called\r
+            // for this device.\r
+            //\r
+            pAdapt->MiniportInitPending = FALSE;\r
+            ASSERT(pAdapt->MiniportHandle == NULL);\r
+        }\r
+        else\r
+        {\r
+            //\r
+            // Our Miniport Initialize routine will be called\r
+            // (may be running on another thread at this time).\r
+            // Wait for it to finish.\r
+            //\r
+            NdisWaitEvent(&pAdapt->MiniportInitEvent, 0);\r
+            ASSERT(pAdapt->MiniportInitPending == FALSE);\r
+        }\r
+\r
+    }\r
+#endif // !WIN9X\r
+\r
+    //\r
+    // Call NDIS to remove our device-instance. We do most of the work\r
+    // inside the HaltHandler.\r
+    //\r
+    // The Handle will be NULL if our miniport Halt Handler has been called or\r
+    // if the IM device was never initialized\r
+    //\r
+    \r
+    if (pAdapt->MiniportHandle != NULL)\r
+    {\r
+        *Status = NdisIMDeInitializeDeviceInstance(pAdapt->MiniportHandle);\r
+\r
+        if (*Status != NDIS_STATUS_SUCCESS)\r
+        {\r
+            *Status = NDIS_STATUS_FAILURE;\r
+        }\r
+    }\r
+    else\r
+    {\r
+        //\r
+        // We need to do some work here. \r
+        // Close the binding below us \r
+        // and release the memory allocated.\r
+        //\r
+        \r
+        if(pAdapt->BindingHandle != NULL)\r
+        {\r
+            NdisResetEvent(&pAdapt->Event);\r
+\r
+            NdisCloseAdapter(Status, pAdapt->BindingHandle);\r
+\r
+            //\r
+            // Wait for it to complete\r
+            //\r
+            if(*Status == NDIS_STATUS_PENDING)\r
+            {\r
+                 NdisWaitEvent(&pAdapt->Event, 0);\r
+                 *Status = pAdapt->Status;\r
+            }\r
+            pAdapt->BindingHandle = NULL;\r
+        }\r
+        else\r
+        {\r
+            //\r
+            // Both Our MiniportHandle and Binding Handle  should not be NULL.\r
+            //\r
+            *Status = NDIS_STATUS_FAILURE;\r
+            ASSERT(0);\r
+        }\r
+\r
+        //\r
+        //    Free the memory here, if was not released earlier(by calling the HaltHandler)\r
+        //\r
+        MPFreeAllPacketPools(pAdapt);\r
+        NdisFreeSpinLock(&pAdapt->Lock);\r
+        NdisFreeMemory(pAdapt, 0, 0);\r
+    }\r
+\r
+    DBGPRINT(("<== PtUnbindAdapter: Adapt %p\n", pAdapt));\r
+}\r
+\r
+VOID\r
+PtUnloadProtocol(\r
+    VOID\r
+)\r
+{\r
+    NDIS_STATUS Status;\r
+\r
+    if (ProtHandle != NULL)\r
+    {\r
+        NdisDeregisterProtocol(&Status, ProtHandle);\r
+        ProtHandle = NULL;\r
+    }\r
+\r
+    DBGPRINT(("PtUnloadProtocol: done!\n"));\r
+}\r
+\r
+\r
+\r
+VOID\r
+PtCloseAdapterComplete(\r
+    IN    NDIS_HANDLE            ProtocolBindingContext,\r
+    IN    NDIS_STATUS            Status\r
+    )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    Completion for the CloseAdapter call.\r
+\r
+Arguments:\r
+\r
+    ProtocolBindingContext    Pointer to the adapter structure\r
+    Status                    Completion status\r
+\r
+Return Value:\r
+\r
+    None.\r
+\r
+--*/\r
+{\r
+    PADAPT      pAdapt =(PADAPT)ProtocolBindingContext;\r
+\r
+    DBGPRINT(("CloseAdapterComplete: Adapt %p, Status %x\n", pAdapt, Status));\r
+    pAdapt->Status = Status;\r
+    NdisSetEvent(&pAdapt->Event);\r
+}\r
+\r
+\r
+VOID\r
+PtResetComplete(\r
+    IN  NDIS_HANDLE            ProtocolBindingContext,\r
+    IN  NDIS_STATUS            Status\r
+    )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    Completion for the reset.\r
+\r
+Arguments:\r
+\r
+    ProtocolBindingContext    Pointer to the adapter structure\r
+    Status                    Completion status\r
+\r
+Return Value:\r
+\r
+    None.\r
+\r
+--*/\r
+{\r
+\r
+    UNREFERENCED_PARAMETER(ProtocolBindingContext);\r
+    UNREFERENCED_PARAMETER(Status);\r
+    //\r
+    // We never issue a reset, so we should not be here.\r
+    //\r
+    ASSERT(0);\r
+}\r
+\r
+\r
+VOID\r
+PtRequestComplete(\r
+    IN  NDIS_HANDLE            ProtocolBindingContext,\r
+    IN  PNDIS_REQUEST          NdisRequest,\r
+    IN  NDIS_STATUS            Status\r
+    )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    Completion handler for the previously posted request. All OIDS\r
+    are completed by and sent to the same miniport that they were requested for.\r
+    If Oid == OID_PNP_QUERY_POWER then the data structure needs to returned with all entries =\r
+    NdisDeviceStateUnspecified\r
+\r
+Arguments:\r
+\r
+    ProtocolBindingContext    Pointer to the adapter structure\r
+    NdisRequest                The posted request\r
+    Status                    Completion status\r
+\r
+Return Value:\r
+\r
+    None\r
+\r
+--*/\r
+{\r
+    PADAPT        pAdapt = (PADAPT)ProtocolBindingContext;\r
+    NDIS_OID      Oid = pAdapt->Request.DATA.SET_INFORMATION.Oid ;\r
+\r
+    //\r
+    // Since our request is not outstanding anymore\r
+    //\r
+    ASSERT(pAdapt->OutstandingRequests == TRUE);\r
+\r
+    pAdapt->OutstandingRequests = FALSE;\r
+\r
+    //\r
+    // Complete the Set or Query, and fill in the buffer for OID_PNP_CAPABILITIES, if need be.\r
+    //\r
+    switch (NdisRequest->RequestType)\r
+    {\r
+      case NdisRequestQueryInformation:\r
+\r
+        //\r
+        // We never pass OID_PNP_QUERY_POWER down.\r
+        //\r
+        ASSERT(Oid != OID_PNP_QUERY_POWER);\r
+\r
+        if ((Oid == OID_PNP_CAPABILITIES) && (Status == NDIS_STATUS_SUCCESS))\r
+        {\r
+            MPQueryPNPCapabilities(pAdapt, &Status);\r
+        }\r
+        *pAdapt->BytesReadOrWritten = NdisRequest->DATA.QUERY_INFORMATION.BytesWritten;\r
+        *pAdapt->BytesNeeded = NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded;\r
+\r
+        if (((Oid == OID_GEN_MAC_OPTIONS) \r
+              && (Status == NDIS_STATUS_SUCCESS))\r
+              && (NdisDotSysVersion >= NDIS_SYS_VERSION_51))\r
+        {\r
+            //\r
+            // Only do this on Windows XP or greater (NDIS.SYS v 5.1); \r
+            // do not do in Windows 2000 (NDIS.SYS v 5.0))\r
+            //\r
+                \r
+            //\r
+            // Remove the no-loopback bit from mac-options. In essence we are\r
+            // telling NDIS that we can handle loopback. We don't, but the\r
+            // interface below us does. If we do not do this, then loopback\r
+            // processing happens both below us and above us. This is wasteful\r
+            // at best and if Netmon is running, it will see multiple copies\r
+            // of loopback packets when sniffing above us.\r
+            //\r
+            // Only the lowest miniport is a stack of layered miniports should\r
+            // ever report this bit set to NDIS.\r
+            //\r
+            *(PULONG)NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer &= ~NDIS_MAC_OPTION_NO_LOOPBACK;\r
+        }\r
+\r
+        NdisMQueryInformationComplete(pAdapt->MiniportHandle,\r
+                                      Status);\r
+        break;\r
+\r
+      case NdisRequestSetInformation:\r
+\r
+        ASSERT( Oid != OID_PNP_SET_POWER);\r
+\r
+        *pAdapt->BytesReadOrWritten = NdisRequest->DATA.SET_INFORMATION.BytesRead;\r
+        *pAdapt->BytesNeeded = NdisRequest->DATA.SET_INFORMATION.BytesNeeded;\r
+        NdisMSetInformationComplete(pAdapt->MiniportHandle,\r
+                                    Status);\r
+        break;\r
+\r
+      default:\r
+        ASSERT(0);\r
+        break;\r
+    }\r
+    \r
+}\r
+\r
+\r
+VOID\r
+PtStatus(\r
+    IN  NDIS_HANDLE         ProtocolBindingContext,\r
+    IN  NDIS_STATUS         GeneralStatus,\r
+    IN  PVOID               StatusBuffer,\r
+    IN  UINT                StatusBufferSize\r
+    )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    Status handler for the lower-edge(protocol).\r
+\r
+Arguments:\r
+\r
+    ProtocolBindingContext    Pointer to the adapter structure\r
+    GeneralStatus             Status code\r
+    StatusBuffer              Status buffer\r
+    StatusBufferSize          Size of the status buffer\r
+\r
+Return Value:\r
+\r
+    None\r
+\r
+--*/\r
+{\r
+    PADAPT      pAdapt = (PADAPT)ProtocolBindingContext;\r
+\r
+    //\r
+    // Pass up this indication only if the upper edge miniport is initialized\r
+    // and powered on. Also ignore indications that might be sent by the lower\r
+    // miniport when it isn't at D0.\r
+    //\r
+    if ((pAdapt->MiniportHandle != NULL)  &&\r
+        (pAdapt->MPDeviceState == NdisDeviceStateD0) &&\r
+        (pAdapt->PTDeviceState == NdisDeviceStateD0))    \r
+    {\r
+        if ((GeneralStatus == NDIS_STATUS_MEDIA_CONNECT) || \r
+            (GeneralStatus == NDIS_STATUS_MEDIA_DISCONNECT))\r
+        {\r
+            \r
+            pAdapt->LastIndicatedStatus = GeneralStatus;\r
+        }\r
+        NdisMIndicateStatus(pAdapt->MiniportHandle,\r
+                            GeneralStatus,\r
+                            StatusBuffer,\r
+                            StatusBufferSize);\r
+    }\r
+    //\r
+    // Save the last indicated media status \r
+    //\r
+    else\r
+    {\r
+        if ((pAdapt->MiniportHandle != NULL) && \r
+        ((GeneralStatus == NDIS_STATUS_MEDIA_CONNECT) || \r
+            (GeneralStatus == NDIS_STATUS_MEDIA_DISCONNECT)))\r
+        {\r
+            pAdapt->LatestUnIndicateStatus = GeneralStatus;\r
+        }\r
+    }\r
+    \r
+}\r
+\r
+\r
+VOID\r
+PtStatusComplete(\r
+    IN NDIS_HANDLE            ProtocolBindingContext\r
+    )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+\r
+Arguments:\r
+\r
+\r
+Return Value:\r
+\r
+\r
+--*/\r
+{\r
+    PADAPT      pAdapt = (PADAPT)ProtocolBindingContext;\r
+\r
+    //\r
+    // Pass up this indication only if the upper edge miniport is initialized\r
+    // and powered on. Also ignore indications that might be sent by the lower\r
+    // miniport when it isn't at D0.\r
+    //\r
+    if ((pAdapt->MiniportHandle != NULL)  &&\r
+        (pAdapt->MPDeviceState == NdisDeviceStateD0) &&\r
+        (pAdapt->PTDeviceState == NdisDeviceStateD0))    \r
+    {\r
+        NdisMIndicateStatusComplete(pAdapt->MiniportHandle);\r
+    }\r
+}\r
+\r
+\r
+VOID\r
+PtSendComplete(\r
+    IN  NDIS_HANDLE            ProtocolBindingContext,\r
+    IN  PNDIS_PACKET           Packet,\r
+    IN  NDIS_STATUS            Status\r
+    )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    Called by NDIS when the miniport below had completed a send. We should\r
+    complete the corresponding upper-edge send this represents.\r
+\r
+Arguments:\r
+\r
+    ProtocolBindingContext - Points to ADAPT structure\r
+    Packet - Low level packet being completed\r
+    Status - status of send\r
+\r
+Return Value:\r
+\r
+    None\r
+\r
+--*/\r
+{\r
+    PADAPT            pAdapt = (PADAPT)ProtocolBindingContext;\r
+    PNDIS_PACKET      Pkt; \r
+    NDIS_HANDLE       PoolHandle;\r
+\r
+#ifdef NDIS51\r
+    //\r
+    // Packet stacking:\r
+    //\r
+    // Determine if the packet we are completing is the one we allocated. If so, then\r
+    // get the original packet from the reserved area and completed it and free the\r
+    // allocated packet. If this is the packet that was sent down to us, then just\r
+    // complete it\r
+    //\r
+    PoolHandle = NdisGetPoolFromPacket(Packet);\r
+    if (PoolHandle != pAdapt->SendPacketPoolHandle)\r
+    {\r
+        //\r
+        // We had passed down a packet belonging to the protocol above us.\r
+        //\r
+        // DBGPRINT(("PtSendComp: Adapt %p, Stacked Packet %p\n", pAdapt, Packet));\r
+\r
+        NdisMSendComplete(pAdapt->MiniportHandle,\r
+                          Packet,\r
+                          Status);\r
+    }\r
+    else\r
+#endif // NDIS51\r
+    {\r
+        PSEND_RSVD        SendRsvd;\r
+\r
+        SendRsvd = (PSEND_RSVD)(Packet->ProtocolReserved);\r
+        Pkt = SendRsvd->OriginalPkt;\r
+    \r
+#ifndef WIN9X\r
+        NdisIMCopySendCompletePerPacketInfo (Pkt, Packet);\r
+#endif\r
+    \r
+        NdisDprFreePacket(Packet);\r
+\r
+        NdisMSendComplete(pAdapt->MiniportHandle,\r
+                                 Pkt,\r
+                                 Status);\r
+    }\r
+    //\r
+    // Decrease the outstanding send count\r
+    //\r
+    ADAPT_DECR_PENDING_SENDS(pAdapt);\r
+}       \r
+\r
+\r
+VOID\r
+PtTransferDataComplete(\r
+    IN  NDIS_HANDLE         ProtocolBindingContext,\r
+    IN  PNDIS_PACKET        Packet,\r
+    IN  NDIS_STATUS         Status,\r
+    IN  UINT                BytesTransferred\r
+    )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    Entry point called by NDIS to indicate completion of a call by us\r
+    to NdisTransferData.\r
+\r
+    See notes under SendComplete.\r
+\r
+Arguments:\r
+\r
+Return Value:\r
+\r
+--*/\r
+{\r
+    PADAPT      pAdapt =(PADAPT)ProtocolBindingContext;\r
+\r
+    if(pAdapt->MiniportHandle)\r
+    {\r
+        NdisMTransferDataComplete(pAdapt->MiniportHandle,\r
+                                  Packet,\r
+                                  Status,\r
+                                  BytesTransferred);\r
+    }\r
+}\r
+\r
+\r
+NDIS_STATUS\r
+PtReceive(\r
+    IN  NDIS_HANDLE         ProtocolBindingContext,\r
+    IN  NDIS_HANDLE         MacReceiveContext,\r
+    IN  PVOID               HeaderBuffer,\r
+    IN  UINT                HeaderBufferSize,\r
+    IN  PVOID               LookAheadBuffer,\r
+    IN  UINT                LookAheadBufferSize,\r
+    IN  UINT                PacketSize\r
+    )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    Handle receive data indicated up by the miniport below. We pass\r
+    it along to the protocol above us.\r
+\r
+    If the miniport below indicates packets, NDIS would more\r
+    likely call us at our ReceivePacket handler. However we\r
+    might be called here in certain situations even though\r
+    the miniport below has indicated a receive packet, e.g.\r
+    if the miniport had set packet status to NDIS_STATUS_RESOURCES.\r
+        \r
+Arguments:\r
+\r
+    <see DDK ref page for ProtocolReceive>\r
+\r
+Return Value:\r
+\r
+    NDIS_STATUS_SUCCESS if we processed the receive successfully,\r
+    NDIS_STATUS_XXX error code if we discarded it.\r
+\r
+--*/\r
+{\r
+    PADAPT            pAdapt = (PADAPT)ProtocolBindingContext;\r
+    PNDIS_PACKET      MyPacket, Packet = NULL;\r
+    NDIS_STATUS       Status = NDIS_STATUS_SUCCESS;\r
+    ULONG             Proc = KeGetCurrentProcessorNumber();      \r
+    \r
+    if ((!pAdapt->MiniportHandle) || (pAdapt->MPDeviceState > NdisDeviceStateD0))\r
+    {\r
+        Status = NDIS_STATUS_FAILURE;\r
+    }\r
+    else do\r
+    {\r
+        //\r
+        // Get at the packet, if any, indicated up by the miniport below.\r
+        //\r
+        Packet = NdisGetReceivedPacket(pAdapt->BindingHandle, MacReceiveContext);\r
+        if (Packet != NULL)\r
+        {\r
+            //\r
+            // The miniport below did indicate up a packet. Use information\r
+            // from that packet to construct a new packet to indicate up.\r
+            //\r
+\r
+#ifdef NDIS51\r
+            //\r
+            // NDIS 5.1 NOTE: Do not reuse the original packet in indicating\r
+            // up a receive, even if there is sufficient packet stack space.\r
+            // If we had to do so, we would have had to overwrite the\r
+            // status field in the original packet to NDIS_STATUS_RESOURCES,\r
+            // and it is not allowed for protocols to overwrite this field\r
+            // in received packets.\r
+            //\r
+#endif // NDIS51\r
+\r
+            //\r
+            // Get a packet off the pool and indicate that up\r
+            //\r
+            NdisDprAllocatePacket(&Status,\r
+                                &MyPacket,\r
+                                pAdapt->RecvPacketPoolHandle);\r
+\r
+            if (Status == NDIS_STATUS_SUCCESS)\r
+            {\r
+                //\r
+                // Make our packet point to data from the original\r
+                // packet. NOTE: this works only because we are\r
+                // indicating a receive directly from the context of\r
+                // our receive indication. If we need to queue this\r
+                // packet and indicate it from another thread context,\r
+                // we will also have to allocate a new buffer and copy\r
+                // over the packet contents, OOB data and per-packet\r
+                // information. This is because the packet data\r
+                // is available only for the duration of this\r
+                // receive indication call.\r
+                //\r
+                NDIS_PACKET_FIRST_NDIS_BUFFER(MyPacket) = NDIS_PACKET_FIRST_NDIS_BUFFER(Packet);\r
+                NDIS_PACKET_LAST_NDIS_BUFFER(MyPacket) = NDIS_PACKET_LAST_NDIS_BUFFER(Packet);\r
+\r
+                //\r
+                // Get the original packet (it could be the same packet as the\r
+                // one received or a different one based on the number of layered\r
+                // miniports below) and set it on the indicated packet so the OOB\r
+                // data is visible correctly at protocols above.  If the IM driver \r
+                // modifies the packet in any way it should not set the new packet's\r
+                // original packet equal to the original packet of the packet that \r
+                // was indicated to it from the underlying driver, in this case, the \r
+                // IM driver should also ensure that the related per packet info should\r
+                // be copied to the new packet.\r
+                // we can set the original packet to the original packet of the packet\r
+                // indicated from the underlying driver because the driver doesn't modify\r
+                // the data content in the packet.\r
+                //\r
+                NDIS_SET_ORIGINAL_PACKET(MyPacket, NDIS_GET_ORIGINAL_PACKET(Packet));\r
+                NDIS_SET_PACKET_HEADER_SIZE(MyPacket, HeaderBufferSize);\r
+\r
+                //\r
+                // Copy packet flags.\r
+                //\r
+                NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(Packet);\r
+\r
+                //\r
+                // Force protocols above to make a copy if they want to hang\r
+                // on to data in this packet. This is because we are in our\r
+                // Receive handler (not ReceivePacket) and we can't return a\r
+                // ref count from here.\r
+                //\r
+                NDIS_SET_PACKET_STATUS(MyPacket, NDIS_STATUS_RESOURCES);\r
+\r
+                //\r
+                // By setting NDIS_STATUS_RESOURCES, we also know that we can reclaim\r
+                // this packet as soon as the call to NdisMIndicateReceivePacket\r
+                // returns.\r
+                //\r
+\r
+                if (pAdapt->MiniportHandle != NULL)\r
+                {\r
+                    NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &MyPacket, 1);\r
+                }\r
+\r
+                //\r
+                // Reclaim the indicated packet. Since we had set its status\r
+                // to NDIS_STATUS_RESOURCES, we are guaranteed that protocols\r
+                // above are done with it.\r
+                //\r
+                NdisDprFreePacket(MyPacket);\r
+\r
+                break;\r
+            }\r
+        }\r
+        else\r
+        {\r
+            //\r
+            // The miniport below us uses the old-style (not packet)\r
+            // receive indication. Fall through.\r
+            //\r
+        }\r
+\r
+        //\r
+        // Fall through if the miniport below us has either not\r
+        // indicated a packet or we could not allocate one\r
+        //\r
+        pAdapt->ReceivedIndicationFlags[Proc] = TRUE;\r
+        if (pAdapt->MiniportHandle == NULL)\r
+        {\r
+            break;\r
+        }\r
+        switch (pAdapt->Medium)\r
+        {\r
+            case NdisMedium802_3:\r
+            case NdisMediumWan:\r
+                NdisMEthIndicateReceive(pAdapt->MiniportHandle,\r
+                                             MacReceiveContext,\r
+                                             HeaderBuffer,\r
+                                             HeaderBufferSize,\r
+                                             LookAheadBuffer,\r
+                                             LookAheadBufferSize,\r
+                                             PacketSize);\r
+                break;\r
+\r
+            case NdisMedium802_5:\r
+                NdisMTrIndicateReceive(pAdapt->MiniportHandle,\r
+                                            MacReceiveContext,\r
+                                            HeaderBuffer,\r
+                                            HeaderBufferSize,\r
+                                            LookAheadBuffer,\r
+                                            LookAheadBufferSize,\r
+                                            PacketSize);\r
+                break;\r
+\r
+#if FDDI\r
+                 case NdisMediumFddi:\r
+                        NdisMFddiIndicateReceive(pAdapt->MiniportHandle,\r
+                                                                                         MacReceiveContext,\r
+                                                                                         HeaderBuffer,\r
+                                                                                         HeaderBufferSize,\r
+                                                                                         LookAheadBuffer,\r
+                                                                                         LookAheadBufferSize,\r
+                                                                                         PacketSize);\r
+                        break;\r
+#endif\r
+                 default:\r
+                        ASSERT(FALSE);\r
+                        break;\r
+               }\r
+\r
+    } while(FALSE);\r
+\r
+    return Status;\r
+}\r
+\r
+\r
+VOID\r
+PtReceiveComplete(\r
+    IN NDIS_HANDLE        ProtocolBindingContext\r
+    )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    Called by the adapter below us when it is done indicating a batch of\r
+    received packets.\r
+\r
+Arguments:\r
+\r
+    ProtocolBindingContext    Pointer to our adapter structure.\r
+\r
+Return Value:\r
+\r
+    None\r
+\r
+--*/\r
+{\r
+    PADAPT        pAdapt =(PADAPT)ProtocolBindingContext;\r
+    ULONG         Proc = KeGetCurrentProcessorNumber();      \r
+\r
+    if (((pAdapt->MiniportHandle != NULL)\r
+                && (pAdapt->MPDeviceState == NdisDeviceStateD0))\r
+                && (pAdapt->ReceivedIndicationFlags[Proc]))\r
+    {\r
+        switch (pAdapt->Medium)\r
+        {\r
+            case NdisMedium802_3:\r
+            case NdisMediumWan:\r
+                NdisMEthIndicateReceiveComplete(pAdapt->MiniportHandle);\r
+                break;\r
+\r
+                 case NdisMedium802_5:\r
+                       NdisMTrIndicateReceiveComplete(pAdapt->MiniportHandle);\r
+                       break;\r
+#if FDDI\r
+                 case NdisMediumFddi:\r
+                       NdisMFddiIndicateReceiveComplete(pAdapt->MiniportHandle);\r
+                       break;\r
+#endif\r
+                 default:\r
+                       ASSERT(FALSE);\r
+                       break;\r
+               }\r
+       }\r
+\r
+    pAdapt->ReceivedIndicationFlags[Proc] = FALSE;\r
+}\r
+\r
+\r
+INT\r
+PtReceivePacket(\r
+    IN NDIS_HANDLE            ProtocolBindingContext,\r
+    IN PNDIS_PACKET           Packet\r
+    )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    ReceivePacket handler. Called by NDIS if the miniport below supports\r
+    NDIS 4.0 style receives. Re-package the buffer chain in a new packet\r
+    and indicate the new packet to protocols above us. Any context for\r
+    packets indicated up must be kept in the MiniportReserved field.\r
+\r
+    NDIS 5.1 - packet stacking - if there is sufficient "stack space" in\r
+    the packet passed to us, we can use the same packet in a receive\r
+    indication.\r
+\r
+Arguments:\r
+\r
+    ProtocolBindingContext - Pointer to our adapter structure.\r
+    Packet - Pointer to the packet\r
+\r
+Return Value:\r
+\r
+    == 0 -> We are done with the packet\r
+    != 0 -> We will keep the packet and call NdisReturnPackets() this\r
+            many times when done.\r
+--*/\r
+{\r
+    PADAPT              pAdapt =(PADAPT)ProtocolBindingContext;\r
+    NDIS_STATUS         Status;\r
+    PNDIS_PACKET        MyPacket;\r
+    BOOLEAN             Remaining;\r
+\r
+    //\r
+    // Drop the packet silently if the upper miniport edge isn't initialized or\r
+    // the miniport edge is in low power state\r
+    //\r
+    if ((!pAdapt->MiniportHandle) || (pAdapt->MPDeviceState > NdisDeviceStateD0))\r
+    {\r
+          return 0;\r
+    }\r
+\r
+#ifdef NDIS51\r
+    //\r
+    // Check if we can reuse the same packet for indicating up.\r
+    // See also: PtReceive(). \r
+    //\r
+    (VOID)NdisIMGetCurrentPacketStack(Packet, &Remaining);\r
+    if (Remaining)\r
+    {\r
+        //\r
+        // We can reuse "Packet". Indicate it up and be done with it.\r
+        //\r
+        Status = NDIS_GET_PACKET_STATUS(Packet);\r
+        NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &Packet, 1);\r
+        return((Status != NDIS_STATUS_RESOURCES) ? 1 : 0);\r
+    }\r
+#endif // NDIS51\r
+\r
+    //\r
+    // Get a packet off the pool and indicate that up\r
+    //\r
+    NdisDprAllocatePacket(&Status,\r
+                           &MyPacket,\r
+                           pAdapt->RecvPacketPoolHandle);\r
+\r
+    if (Status == NDIS_STATUS_SUCCESS)\r
+    {\r
+        PRECV_RSVD            RecvRsvd;\r
+\r
+        RecvRsvd = (PRECV_RSVD)(MyPacket->MiniportReserved);\r
+        RecvRsvd->OriginalPkt = Packet;\r
+\r
+        NDIS_PACKET_FIRST_NDIS_BUFFER(MyPacket) = NDIS_PACKET_FIRST_NDIS_BUFFER(Packet);\r
+        NDIS_PACKET_LAST_NDIS_BUFFER(MyPacket) = NDIS_PACKET_LAST_NDIS_BUFFER(Packet);\r
+\r
+        //\r
+        // Get the original packet (it could be the same packet as the one\r
+        // received or a different one based on the number of layered miniports\r
+        // below) and set it on the indicated packet so the OOB data is visible\r
+        // correctly to protocols above us.\r
+        //\r
+        NDIS_SET_ORIGINAL_PACKET(MyPacket, NDIS_GET_ORIGINAL_PACKET(Packet));\r
+\r
+        //\r
+        // Set Packet Flags\r
+        //\r
+        NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(Packet);\r
+\r
+        Status = NDIS_GET_PACKET_STATUS(Packet);\r
+\r
+        NDIS_SET_PACKET_STATUS(MyPacket, Status);\r
+        NDIS_SET_PACKET_HEADER_SIZE(MyPacket, NDIS_GET_PACKET_HEADER_SIZE(Packet));\r
+\r
+        if (pAdapt->MiniportHandle != NULL)\r
+        {\r
+            NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &MyPacket, 1);\r
+        }\r
+\r
+        //\r
+        // Check if we had indicated up the packet with NDIS_STATUS_RESOURCES\r
+        // NOTE -- do not use NDIS_GET_PACKET_STATUS(MyPacket) for this since\r
+        // it might have changed! Use the value saved in the local variable.\r
+        //\r
+        if (Status == NDIS_STATUS_RESOURCES)\r
+        {\r
+            //\r
+            // Our ReturnPackets handler will not be called for this packet.\r
+            // We should reclaim it right here.\r
+            //\r
+            NdisDprFreePacket(MyPacket);\r
+        }\r
+\r
+        return((Status != NDIS_STATUS_RESOURCES) ? 1 : 0);\r
+    }\r
+    else\r
+    {\r
+        //\r
+        // We are out of packets. Silently drop it.\r
+        //\r
+        return(0);\r
+    }\r
+}\r
+\r
+\r
+NDIS_STATUS\r
+PtPNPHandler(\r
+    IN NDIS_HANDLE        ProtocolBindingContext,\r
+    IN PNET_PNP_EVENT     pNetPnPEvent\r
+    )\r
+\r
+/*++\r
+Routine Description:\r
+\r
+    This is called by NDIS to notify us of a PNP event related to a lower\r
+    binding. Based on the event, this dispatches to other helper routines.\r
+\r
+    NDIS 5.1: forward this event to the upper protocol(s) by calling\r
+    NdisIMNotifyPnPEvent.\r
+\r
+Arguments:\r
+\r
+    ProtocolBindingContext - Pointer to our adapter structure. Can be NULL\r
+                for "global" notifications\r
+\r
+    pNetPnPEvent - Pointer to the PNP event to be processed.\r
+\r
+Return Value:\r
+\r
+    NDIS_STATUS code indicating status of event processing.\r
+\r
+--*/\r
+{\r
+    PADAPT            pAdapt  =(PADAPT)ProtocolBindingContext;\r
+    NDIS_STATUS       Status  = NDIS_STATUS_SUCCESS;\r
+\r
+    DBGPRINT(("PtPnPHandler: Adapt %p, Event %d\n", pAdapt, pNetPnPEvent->NetEvent));\r
+\r
+    switch (pNetPnPEvent->NetEvent)\r
+    {\r
+        case NetEventSetPower:\r
+            Status = PtPnPNetEventSetPower(pAdapt, pNetPnPEvent);\r
+            break;\r
+\r
+         case NetEventReconfigure:\r
+            Status = PtPnPNetEventReconfigure(pAdapt, pNetPnPEvent);\r
+            break;\r
+\r
+         default:\r
+#ifdef NDIS51\r
+            //\r
+            // Pass on this notification to protocol(s) above, before\r
+            // doing anything else with it.\r
+            //\r
+            if (pAdapt && pAdapt->MiniportHandle)\r
+            {\r
+                Status = NdisIMNotifyPnPEvent(pAdapt->MiniportHandle, pNetPnPEvent);\r
+            }\r
+#else\r
+            Status = NDIS_STATUS_SUCCESS;\r
+\r
+#endif // NDIS51\r
+\r
+            break;\r
+    }\r
+\r
+    return Status;\r
+}\r
+\r
+\r
+NDIS_STATUS\r
+PtPnPNetEventReconfigure(\r
+    IN PADAPT            pAdapt,\r
+    IN PNET_PNP_EVENT    pNetPnPEvent\r
+    )\r
+/*++\r
+Routine Description:\r
+\r
+    This routine is called from NDIS to notify our protocol edge of a\r
+    reconfiguration of parameters for either a specific binding (pAdapt\r
+    is not NULL), or global parameters if any (pAdapt is NULL).\r
+\r
+Arguments:\r
+\r
+    pAdapt - Pointer to our adapter structure.\r
+    pNetPnPEvent - the reconfigure event\r
+\r
+Return Value:\r
+\r
+    NDIS_STATUS_SUCCESS\r
+\r
+--*/\r
+{\r
+    NDIS_STATUS    ReconfigStatus = NDIS_STATUS_SUCCESS;\r
+    NDIS_STATUS    ReturnStatus = NDIS_STATUS_SUCCESS;\r
+\r
+    do\r
+    {\r
+        //\r
+        // Is this is a global reconfiguration notification ?\r
+        //\r
+        if (pAdapt == NULL)\r
+        {\r
+            //\r
+            // An important event that causes this notification to us is if\r
+            // one of our upper-edge miniport instances was enabled after being\r
+            // disabled earlier, e.g. from Device Manager in Win2000. Note that\r
+            // NDIS calls this because we had set up an association between our\r
+            // miniport and protocol entities by calling NdisIMAssociateMiniport.\r
+            //\r
+            // Since we would have torn down the lower binding for that miniport,\r
+            // we need NDIS' assistance to re-bind to the lower miniport. The\r
+            // call to NdisReEnumerateProtocolBindings does exactly that.\r
+            //\r
+            NdisReEnumerateProtocolBindings (ProtHandle);        \r
+            \r
+            break;\r
+        }\r
+\r
+#ifdef NDIS51\r
+        //\r
+        // Pass on this notification to protocol(s) above before doing anything\r
+        // with it.\r
+        //\r
+        if (pAdapt->MiniportHandle)\r
+        {\r
+            ReturnStatus = NdisIMNotifyPnPEvent(pAdapt->MiniportHandle, pNetPnPEvent);\r
+        }\r
+#endif // NDIS51\r
+\r
+        ReconfigStatus = NDIS_STATUS_SUCCESS;\r
+\r
+    } while(FALSE);\r
+\r
+    DBGPRINT(("<==PtPNPNetEventReconfigure: pAdapt %p\n", pAdapt));\r
+\r
+#ifdef NDIS51\r
+    //\r
+    // Overwrite status with what upper-layer protocol(s) returned.\r
+    //\r
+    ReconfigStatus = ReturnStatus;\r
+#endif\r
+\r
+    return ReconfigStatus;\r
+}\r
+\r
+\r
+NDIS_STATUS\r
+PtPnPNetEventSetPower(\r
+    IN PADAPT            pAdapt,\r
+    IN PNET_PNP_EVENT    pNetPnPEvent\r
+    )\r
+/*++\r
+Routine Description:\r
+\r
+    This is a notification to our protocol edge of the power state\r
+    of the lower miniport. If it is going to a low-power state, we must\r
+    wait here for all outstanding sends and requests to complete.\r
+\r
+    NDIS 5.1:  Since we use packet stacking, it is not sufficient to\r
+    check usage of our local send packet pool to detect whether or not\r
+    all outstanding sends have completed. For this, use the new API\r
+    NdisQueryPendingIOCount.\r
+\r
+    NDIS 5.1: Use the 5.1 API NdisIMNotifyPnPEvent to pass on PnP\r
+    notifications to upper protocol(s).\r
+\r
+Arguments:\r
+\r
+    pAdapt            -    Pointer to the adpater structure\r
+    pNetPnPEvent    -    The Net Pnp Event. this contains the new device state\r
+\r
+Return Value:\r
+\r
+    NDIS_STATUS_SUCCESS or the status returned by upper-layer protocols.\r
+\r
+--*/\r
+{\r
+    PNDIS_DEVICE_POWER_STATE       pDeviceState  =(PNDIS_DEVICE_POWER_STATE)(pNetPnPEvent->Buffer);\r
+    NDIS_DEVICE_POWER_STATE        PrevDeviceState = pAdapt->PTDeviceState;  \r
+    NDIS_STATUS                    Status;\r
+    NDIS_STATUS                    ReturnStatus;\r
+\r
+    ReturnStatus = NDIS_STATUS_SUCCESS;\r
+\r
+    //\r
+    // Set the Internal Device State, this blocks all new sends or receives\r
+    //\r
+    NdisAcquireSpinLock(&pAdapt->Lock);\r
+    pAdapt->PTDeviceState = *pDeviceState;\r
+\r
+    //\r
+    // Check if the miniport below is going to a low power state.\r
+    //\r
+    if (pAdapt->PTDeviceState > NdisDeviceStateD0)\r
+    {\r
+        //\r
+        // If the miniport below is going to standby, fail all incoming requests\r
+        //\r
+        if (PrevDeviceState == NdisDeviceStateD0)\r
+        {\r
+            pAdapt->StandingBy = TRUE;\r
+        }\r
+\r
+        NdisReleaseSpinLock(&pAdapt->Lock);\r
+\r
+#ifdef NDIS51\r
+        //\r
+        // Notify upper layer protocol(s) first.\r
+        //\r
+        if (pAdapt->MiniportHandle != NULL)\r
+        {\r
+            ReturnStatus = NdisIMNotifyPnPEvent(pAdapt->MiniportHandle, pNetPnPEvent);\r
+        }\r
+#endif // NDIS51\r
+\r
+        //\r
+        // Wait for outstanding sends and requests to complete.\r
+        //\r
+        while (pAdapt->OutstandingSends != 0)\r
+        {\r
+            NdisMSleep(2);\r
+        }\r
+\r
+        while (pAdapt->OutstandingRequests == TRUE)\r
+        {\r
+            //\r
+            // sleep till outstanding requests complete\r
+            //\r
+            NdisMSleep(2);\r
+        }\r
+\r
+        //\r
+        // If the below miniport is going to low power state, complete the queued request\r
+        //\r
+        NdisAcquireSpinLock(&pAdapt->Lock);\r
+        if (pAdapt->QueuedRequest)\r
+        {\r
+            pAdapt->QueuedRequest = FALSE;\r
+            NdisReleaseSpinLock(&pAdapt->Lock);\r
+            PtRequestComplete(pAdapt, &pAdapt->Request, NDIS_STATUS_FAILURE);\r
+        }\r
+        else\r
+        {\r
+            NdisReleaseSpinLock(&pAdapt->Lock);\r
+        }\r
+            \r
+\r
+        ASSERT(NdisPacketPoolUsage(pAdapt->SendPacketPoolHandle) == 0);\r
+        ASSERT(pAdapt->OutstandingRequests == FALSE);\r
+    }\r
+    else\r
+    {\r
+        //\r
+        // If the physical miniport is powering up (from Low power state to D0), \r
+        // clear the flag\r
+        //\r
+        if (PrevDeviceState > NdisDeviceStateD0)\r
+        {\r
+            pAdapt->StandingBy = FALSE;\r
+        }\r
+        //\r
+        // The device below is being turned on. If we had a request\r
+        // pending, send it down now.\r
+        //\r
+        if (pAdapt->QueuedRequest == TRUE)\r
+        {\r
+            pAdapt->QueuedRequest = FALSE;\r
+        \r
+            pAdapt->OutstandingRequests = TRUE;\r
+            NdisReleaseSpinLock(&pAdapt->Lock);\r
+\r
+            NdisRequest(&Status,\r
+                        pAdapt->BindingHandle,\r
+                        &pAdapt->Request);\r
+\r
+            if (Status != NDIS_STATUS_PENDING)\r
+            {\r
+                PtRequestComplete(pAdapt,\r
+                                  &pAdapt->Request,\r
+                                  Status);\r
+                \r
+            }\r
+        }\r
+        else\r
+        {\r
+            NdisReleaseSpinLock(&pAdapt->Lock);\r
+        }\r
+\r
+\r
+#ifdef NDIS51\r
+        //\r
+        // Pass on this notification to protocol(s) above\r
+        //\r
+        if (pAdapt->MiniportHandle)\r
+        {\r
+            ReturnStatus = NdisIMNotifyPnPEvent(pAdapt->MiniportHandle, pNetPnPEvent);\r
+        }\r
+#endif // NDIS51\r
+\r
+    }\r
+\r
+    return ReturnStatus;\r
+}\r
+\r
+VOID\r
+PtReferenceAdapt(\r
+    IN PADAPT     pAdapt\r
+    )\r
+{\r
+    NdisAcquireSpinLock(&pAdapt->Lock);\r
+    \r
+    ASSERT(pAdapt->RefCount >= 0);\r
+\r
+    pAdapt->RefCount ++;\r
+    NdisReleaseSpinLock(&pAdapt->Lock);\r
+}\r
+\r
+\r
+BOOLEAN\r
+PtDereferenceAdapt(\r
+    IN PADAPT     pAdapt\r
+    )\r
+{\r
+    NdisAcquireSpinLock(&pAdapt->Lock);\r
+\r
+    ASSERT(pAdapt->RefCount > 0);\r
+\r
+    pAdapt->RefCount--;\r
+\r
+    if (pAdapt->RefCount == 0)\r
+    {\r
+        NdisReleaseSpinLock(&pAdapt->Lock);\r
+        \r
+        //\r
+        // Free all resources on this adapter structure.\r
+        //\r
+        MPFreeAllPacketPools (pAdapt);;\r
+        NdisFreeSpinLock(&pAdapt->Lock);\r
+        NdisFreeMemory(pAdapt, 0 , 0);\r
+        \r
+        return TRUE;\r
+        \r
+    }\r
+    else\r
+    {\r
+        NdisReleaseSpinLock(&pAdapt->Lock);\r
+\r
+        return FALSE;\r
+    }\r
+}\r
+\r
+\r