--- /dev/null
+/*++\r
+\r
+Copyright (c) 1992-2000 Microsoft Corporation\r
+\r
+Module Name:\r
+\r
+ miniport.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
+#include "precomp.h"\r
+#pragma hdrstop\r
+\r
+\r
+\r
+NDIS_STATUS\r
+MPInitialize(\r
+ OUT PNDIS_STATUS OpenErrorStatus,\r
+ OUT PUINT SelectedMediumIndex,\r
+ IN PNDIS_MEDIUM MediumArray,\r
+ IN UINT MediumArraySize,\r
+ IN NDIS_HANDLE MiniportAdapterHandle,\r
+ IN NDIS_HANDLE WrapperConfigurationContext\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ This is the initialize handler which gets called as a result of\r
+ the BindAdapter handler calling NdisIMInitializeDeviceInstanceEx.\r
+ The context parameter which we pass there is the adapter structure\r
+ which we retrieve here.\r
+\r
+ Arguments:\r
+\r
+ OpenErrorStatus Not used by us.\r
+ SelectedMediumIndex Place-holder for what media we are using\r
+ MediumArray Array of ndis media passed down to us to pick from\r
+ MediumArraySize Size of the array\r
+ MiniportAdapterHandle The handle NDIS uses to refer to us\r
+ WrapperConfigurationContext For use by NdisOpenConfiguration\r
+\r
+Return Value:\r
+\r
+ NDIS_STATUS_SUCCESS unless something goes wrong\r
+\r
+--*/\r
+{\r
+ UINT i;\r
+ PADAPT pAdapt;\r
+ NDIS_STATUS Status = NDIS_STATUS_FAILURE;\r
+ NDIS_MEDIUM Medium;\r
+\r
+ UNREFERENCED_PARAMETER(WrapperConfigurationContext);\r
+ \r
+ do\r
+ {\r
+ //\r
+ // Start off by retrieving our adapter context and storing\r
+ // the Miniport handle in it.\r
+ //\r
+ pAdapt = NdisIMGetDeviceContext(MiniportAdapterHandle);\r
+ pAdapt->MiniportIsHalted = FALSE;\r
+\r
+ DBGPRINT(("==> Miniport Initialize: Adapt %p\n", pAdapt));\r
+\r
+ //\r
+ // Usually we export the medium type of the adapter below as our\r
+ // virtual miniport's medium type. However if the adapter below us\r
+ // is a WAN device, then we claim to be of medium type 802.3.\r
+ //\r
+ Medium = pAdapt->Medium;\r
+\r
+ if (Medium == NdisMediumWan)\r
+ {\r
+ Medium = NdisMedium802_3;\r
+ }\r
+\r
+ for (i = 0; i < MediumArraySize; i++)\r
+ {\r
+ if (MediumArray[i] == Medium)\r
+ {\r
+ *SelectedMediumIndex = i;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (i == MediumArraySize)\r
+ {\r
+ Status = NDIS_STATUS_UNSUPPORTED_MEDIA;\r
+ break;\r
+ }\r
+\r
+\r
+ //\r
+ // Set the attributes now. NDIS_ATTRIBUTE_DESERIALIZE enables us\r
+ // to make up-calls to NDIS without having to call NdisIMSwitchToMiniport\r
+ // or NdisIMQueueCallBack. This also forces us to protect our data using\r
+ // spinlocks where appropriate. Also in this case NDIS does not queue\r
+ // packets on our behalf. Since this is a very simple pass-thru\r
+ // miniport, we do not have a need to protect anything. However in\r
+ // a general case there will be a need to use per-adapter spin-locks\r
+ // for the packet queues at the very least.\r
+ //\r
+ NdisMSetAttributesEx(MiniportAdapterHandle,\r
+ pAdapt,\r
+ 0, // CheckForHangTimeInSeconds\r
+ NDIS_ATTRIBUTE_IGNORE_PACKET_TIMEOUT |\r
+ NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT|\r
+ NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER |\r
+ NDIS_ATTRIBUTE_DESERIALIZE |\r
+ NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND,\r
+ 0);\r
+\r
+ pAdapt->MiniportHandle = MiniportAdapterHandle;\r
+ //\r
+ // Initialize LastIndicatedStatus to be NDIS_STATUS_MEDIA_CONNECT\r
+ //\r
+ pAdapt->LastIndicatedStatus = NDIS_STATUS_MEDIA_CONNECT;\r
+ \r
+ //\r
+ // Initialize the power states for both the lower binding (PTDeviceState)\r
+ // and our miniport edge to Powered On.\r
+ //\r
+ pAdapt->MPDeviceState = NdisDeviceStateD0;\r
+ pAdapt->PTDeviceState = NdisDeviceStateD0;\r
+\r
+ //\r
+ // Add this adapter to the global pAdapt List\r
+ //\r
+ NdisAcquireSpinLock(&GlobalLock);\r
+\r
+ pAdapt->Next = pAdaptList;\r
+ pAdaptList = pAdapt;\r
+\r
+ NdisReleaseSpinLock(&GlobalLock);\r
+ \r
+ //\r
+ // Create an ioctl interface\r
+ //\r
+ (VOID)PtRegisterDevice();\r
+\r
+ Status = NDIS_STATUS_SUCCESS;\r
+ }\r
+ while (FALSE);\r
+\r
+ //\r
+ // If we had received an UnbindAdapter notification on the underlying\r
+ // adapter, we would have blocked that thread waiting for the IM Init\r
+ // process to complete. Wake up any such thread.\r
+ //\r
+ ASSERT(pAdapt->MiniportInitPending == TRUE);\r
+ pAdapt->MiniportInitPending = FALSE;\r
+ NdisSetEvent(&pAdapt->MiniportInitEvent);\r
+\r
+ if (Status == NDIS_STATUS_SUCCESS)\r
+ {\r
+ PtReferenceAdapt(pAdapt);\r
+ }\r
+\r
+ DBGPRINT(("<== Miniport Initialize: Adapt %p, Status %x\n", pAdapt, Status));\r
+\r
+ *OpenErrorStatus = Status;\r
+\r
+ \r
+ return Status;\r
+}\r
+\r
+\r
+NDIS_STATUS\r
+MPSend(\r
+ IN NDIS_HANDLE MiniportAdapterContext,\r
+ IN PNDIS_PACKET Packet,\r
+ IN UINT Flags\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Send Packet handler. Either this or our SendPackets (array) handler is called\r
+ based on which one is enabled in our Miniport Characteristics.\r
+\r
+Arguments:\r
+\r
+ MiniportAdapterContext Pointer to the adapter\r
+ Packet Packet to send\r
+ Flags Unused, passed down below\r
+\r
+Return Value:\r
+\r
+ Return code from NdisSend\r
+\r
+--*/\r
+{\r
+ PADAPT pAdapt = (PADAPT)MiniportAdapterContext;\r
+ NDIS_STATUS Status;\r
+ PNDIS_PACKET MyPacket;\r
+ PVOID MediaSpecificInfo = NULL;\r
+ ULONG MediaSpecificInfoSize = 0;\r
+\r
+ //\r
+ // The driver should fail the send if the virtual miniport is in low \r
+ // power state\r
+ //\r
+ if (pAdapt->MPDeviceState > NdisDeviceStateD0)\r
+ {\r
+ return NDIS_STATUS_FAILURE;\r
+ }\r
+\r
+#ifdef NDIS51\r
+ //\r
+ // Use NDIS 5.1 packet stacking:\r
+ //\r
+ {\r
+ PNDIS_PACKET_STACK pStack;\r
+ BOOLEAN Remaining;\r
+\r
+ //\r
+ // Packet stacks: Check if we can use the same packet for sending down.\r
+ //\r
+\r
+ pStack = NdisIMGetCurrentPacketStack(Packet, &Remaining);\r
+ if (Remaining)\r
+ {\r
+ //\r
+ // We can reuse "Packet".\r
+ //\r
+ // NOTE: if we needed to keep per-packet information in packets\r
+ // sent down, we can use pStack->IMReserved[].\r
+ //\r
+ ASSERT(pStack);\r
+ //\r
+ // If the below miniport is going to low power state, stop sending down any packet.\r
+ //\r
+ NdisAcquireSpinLock(&pAdapt->Lock);\r
+ if (pAdapt->PTDeviceState > NdisDeviceStateD0)\r
+ {\r
+ NdisReleaseSpinLock(&pAdapt->Lock);\r
+ return NDIS_STATUS_FAILURE;\r
+ }\r
+ pAdapt->OutstandingSends++;\r
+ NdisReleaseSpinLock(&pAdapt->Lock);\r
+ NdisSend(&Status,\r
+ pAdapt->BindingHandle,\r
+ Packet);\r
+\r
+ if (Status != NDIS_STATUS_PENDING)\r
+ {\r
+ ADAPT_DECR_PENDING_SENDS(pAdapt);\r
+ }\r
+\r
+ return(Status);\r
+ }\r
+ }\r
+#endif // NDIS51\r
+\r
+ //\r
+ // We are either not using packet stacks, or there isn't stack space\r
+ // in the original packet passed down to us. Allocate a new packet\r
+ // to wrap the data with.\r
+ //\r
+ //\r
+ // If the below miniport is going to low power state, stop sending down any packet.\r
+ //\r
+ NdisAcquireSpinLock(&pAdapt->Lock);\r
+ if (pAdapt->PTDeviceState > NdisDeviceStateD0)\r
+ {\r
+ NdisReleaseSpinLock(&pAdapt->Lock);\r
+ return NDIS_STATUS_FAILURE;\r
+ \r
+ }\r
+ pAdapt->OutstandingSends++;\r
+ NdisReleaseSpinLock(&pAdapt->Lock);\r
+ \r
+ NdisAllocatePacket(&Status,\r
+ &MyPacket,\r
+ pAdapt->SendPacketPoolHandle);\r
+\r
+ if (Status == NDIS_STATUS_SUCCESS)\r
+ {\r
+ PSEND_RSVD SendRsvd;\r
+\r
+ //\r
+ // Save a pointer to the original packet in our reserved\r
+ // area in the new packet. This is needed so that we can\r
+ // get back to the original packet when the new packet's send\r
+ // is completed.\r
+ //\r
+ SendRsvd = (PSEND_RSVD)(MyPacket->ProtocolReserved);\r
+ SendRsvd->OriginalPkt = Packet;\r
+\r
+ NdisGetPacketFlags(MyPacket) = Flags;\r
+\r
+ //\r
+ // Set up the new packet so that it describes the same\r
+ // data as the original 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
+#ifdef WIN9X\r
+ //\r
+ // Work around the fact that NDIS does not initialize this\r
+ // to FALSE on Win9x.\r
+ //\r
+ NDIS_PACKET_VALID_COUNTS(MyPacket) = FALSE;\r
+#endif\r
+\r
+ //\r
+ // Copy the OOB Offset from the original packet to the new\r
+ // packet.\r
+ //\r
+ NdisMoveMemory(NDIS_OOB_DATA_FROM_PACKET(MyPacket),\r
+ NDIS_OOB_DATA_FROM_PACKET(Packet),\r
+ sizeof(NDIS_PACKET_OOB_DATA));\r
+\r
+#ifndef WIN9X\r
+ //\r
+ // Copy the right parts of per packet info into the new packet.\r
+ // This API is not available on Win9x since task offload is\r
+ // not supported on that platform.\r
+ //\r
+ NdisIMCopySendPerPacketInfo(MyPacket, Packet);\r
+#endif\r
+ \r
+ //\r
+ // Copy the Media specific information\r
+ //\r
+ NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO(Packet,\r
+ &MediaSpecificInfo,\r
+ &MediaSpecificInfoSize);\r
+\r
+ if (MediaSpecificInfo || MediaSpecificInfoSize)\r
+ {\r
+ NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO(MyPacket,\r
+ MediaSpecificInfo,\r
+ MediaSpecificInfoSize);\r
+ }\r
+\r
+ NdisSend(&Status,\r
+ pAdapt->BindingHandle,\r
+ MyPacket);\r
+\r
+\r
+ if (Status != NDIS_STATUS_PENDING)\r
+ {\r
+#ifndef WIN9X\r
+ NdisIMCopySendCompletePerPacketInfo (Packet, MyPacket);\r
+#endif\r
+ NdisFreePacket(MyPacket);\r
+ ADAPT_DECR_PENDING_SENDS(pAdapt);\r
+ }\r
+ }\r
+ else\r
+ {\r
+ ADAPT_DECR_PENDING_SENDS(pAdapt);\r
+ //\r
+ // We are out of packets. Silently drop it. Alternatively we can deal with it:\r
+ // - By keeping separate send and receive pools\r
+ // - Dynamically allocate more pools as needed and free them when not needed\r
+ //\r
+ }\r
+\r
+ return(Status);\r
+}\r
+\r
+\r
+VOID\r
+MPSendPackets(\r
+ IN NDIS_HANDLE MiniportAdapterContext,\r
+ IN PPNDIS_PACKET PacketArray,\r
+ IN UINT NumberOfPackets\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Send Packet Array handler. Either this or our SendPacket handler is called\r
+ based on which one is enabled in our Miniport Characteristics.\r
+\r
+Arguments:\r
+\r
+ MiniportAdapterContext Pointer to our adapter\r
+ PacketArray Set of packets to send\r
+ NumberOfPackets Self-explanatory\r
+\r
+Return Value:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ PADAPT pAdapt = (PADAPT)MiniportAdapterContext;\r
+ NDIS_STATUS Status;\r
+ UINT i;\r
+ PVOID MediaSpecificInfo = NULL;\r
+ UINT MediaSpecificInfoSize = 0;\r
+ \r
+\r
+ for (i = 0; i < NumberOfPackets; i++)\r
+ {\r
+ PNDIS_PACKET Packet, MyPacket;\r
+\r
+ Packet = PacketArray[i];\r
+ //\r
+ // The driver should fail the send if the virtual miniport is in low \r
+ // power state\r
+ //\r
+ if (pAdapt->MPDeviceState > NdisDeviceStateD0)\r
+ {\r
+ NdisMSendComplete(ADAPT_MINIPORT_HANDLE(pAdapt),\r
+ Packet,\r
+ NDIS_STATUS_FAILURE);\r
+ continue;\r
+ }\r
+\r
+#ifdef NDIS51\r
+\r
+ //\r
+ // Use NDIS 5.1 packet stacking:\r
+ //\r
+ {\r
+ PNDIS_PACKET_STACK pStack;\r
+ BOOLEAN Remaining;\r
+\r
+ //\r
+ // Packet stacks: Check if we can use the same packet for sending down.\r
+ //\r
+ pStack = NdisIMGetCurrentPacketStack(Packet, &Remaining);\r
+ if (Remaining)\r
+ {\r
+ //\r
+ // We can reuse "Packet".\r
+ //\r
+ // NOTE: if we needed to keep per-packet information in packets\r
+ // sent down, we can use pStack->IMReserved[].\r
+ //\r
+ ASSERT(pStack);\r
+ //\r
+ // If the below miniport is going to low power state, stop sending down any packet.\r
+ //\r
+ NdisAcquireSpinLock(&pAdapt->Lock);\r
+ if (pAdapt->PTDeviceState > NdisDeviceStateD0)\r
+ {\r
+ NdisReleaseSpinLock(&pAdapt->Lock);\r
+ NdisMSendComplete(ADAPT_MINIPORT_HANDLE(pAdapt),\r
+ Packet,\r
+ NDIS_STATUS_FAILURE);\r
+ }\r
+ else\r
+ {\r
+ pAdapt->OutstandingSends++;\r
+ NdisReleaseSpinLock(&pAdapt->Lock);\r
+ \r
+ NdisSend(&Status,\r
+ pAdapt->BindingHandle,\r
+ Packet);\r
+ \r
+ if (Status != NDIS_STATUS_PENDING)\r
+ {\r
+ NdisMSendComplete(ADAPT_MINIPORT_HANDLE(pAdapt),\r
+ Packet,\r
+ Status);\r
+ \r
+ ADAPT_DECR_PENDING_SENDS(pAdapt);\r
+ }\r
+ }\r
+ continue;\r
+ }\r
+ }\r
+#endif\r
+ do \r
+ {\r
+ NdisAcquireSpinLock(&pAdapt->Lock);\r
+ //\r
+ // If the below miniport is going to low power state, stop sending down any packet.\r
+ //\r
+ if (pAdapt->PTDeviceState > NdisDeviceStateD0)\r
+ {\r
+ NdisReleaseSpinLock(&pAdapt->Lock);\r
+ Status = NDIS_STATUS_FAILURE;\r
+ break;\r
+ }\r
+ pAdapt->OutstandingSends++;\r
+ NdisReleaseSpinLock(&pAdapt->Lock);\r
+ \r
+ NdisAllocatePacket(&Status,\r
+ &MyPacket,\r
+ pAdapt->SendPacketPoolHandle);\r
+\r
+ if (Status == NDIS_STATUS_SUCCESS)\r
+ {\r
+ PSEND_RSVD SendRsvd;\r
+\r
+ SendRsvd = (PSEND_RSVD)(MyPacket->ProtocolReserved);\r
+ SendRsvd->OriginalPkt = Packet;\r
+\r
+ NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(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
+#ifdef WIN9X\r
+ //\r
+ // Work around the fact that NDIS does not initialize this\r
+ // to FALSE on Win9x.\r
+ //\r
+ NDIS_PACKET_VALID_COUNTS(MyPacket) = FALSE;\r
+#endif // WIN9X\r
+\r
+ //\r
+ // Copy the OOB data from the original packet to the new\r
+ // packet.\r
+ //\r
+ NdisMoveMemory(NDIS_OOB_DATA_FROM_PACKET(MyPacket),\r
+ NDIS_OOB_DATA_FROM_PACKET(Packet),\r
+ sizeof(NDIS_PACKET_OOB_DATA));\r
+ //\r
+ // Copy relevant parts of the per packet info into the new packet\r
+ //\r
+#ifndef WIN9X\r
+ NdisIMCopySendPerPacketInfo(MyPacket, Packet);\r
+#endif\r
+\r
+ //\r
+ // Copy the Media specific information\r
+ //\r
+ NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO(Packet,\r
+ &MediaSpecificInfo,\r
+ &MediaSpecificInfoSize);\r
+\r
+ if (MediaSpecificInfo || MediaSpecificInfoSize)\r
+ {\r
+ NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO(MyPacket,\r
+ MediaSpecificInfo,\r
+ MediaSpecificInfoSize);\r
+ }\r
+\r
+ NdisSend(&Status,\r
+ pAdapt->BindingHandle,\r
+ MyPacket);\r
+\r
+ if (Status != NDIS_STATUS_PENDING)\r
+ {\r
+#ifndef WIN9X\r
+ NdisIMCopySendCompletePerPacketInfo (Packet, MyPacket);\r
+#endif\r
+ NdisFreePacket(MyPacket);\r
+ ADAPT_DECR_PENDING_SENDS(pAdapt);\r
+ }\r
+ }\r
+ else\r
+ {\r
+ //\r
+ // The driver cannot allocate a packet.\r
+ // \r
+ ADAPT_DECR_PENDING_SENDS(pAdapt);\r
+ }\r
+ }\r
+ while (FALSE);\r
+\r
+ if (Status != NDIS_STATUS_PENDING)\r
+ {\r
+ NdisMSendComplete(ADAPT_MINIPORT_HANDLE(pAdapt),\r
+ Packet,\r
+ Status);\r
+ }\r
+ }\r
+}\r
+\r
+\r
+NDIS_STATUS\r
+MPQueryInformation(\r
+ IN NDIS_HANDLE MiniportAdapterContext,\r
+ IN NDIS_OID Oid,\r
+ IN PVOID InformationBuffer,\r
+ IN ULONG InformationBufferLength,\r
+ OUT PULONG BytesWritten,\r
+ OUT PULONG BytesNeeded\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Entry point called by NDIS to query for the value of the specified OID.\r
+ Typical processing is to forward the query down to the underlying miniport.\r
+\r
+ The following OIDs are filtered here:\r
+\r
+ OID_PNP_QUERY_POWER - return success right here\r
+\r
+ OID_GEN_SUPPORTED_GUIDS - do not forward, otherwise we will show up\r
+ multiple instances of private GUIDs supported by the underlying miniport.\r
+\r
+ OID_PNP_CAPABILITIES - we do send this down to the lower miniport, but\r
+ the values returned are postprocessed before we complete this request;\r
+ see PtRequestComplete.\r
+\r
+ NOTE on OID_TCP_TASK_OFFLOAD - if this IM driver modifies the contents\r
+ of data it passes through such that a lower miniport may not be able\r
+ to perform TCP task offload, then it should not forward this OID down,\r
+ but fail it here with the status NDIS_STATUS_NOT_SUPPORTED. This is to\r
+ avoid performing incorrect transformations on data.\r
+\r
+ If our miniport edge (upper edge) is at a low-power state, fail the request.\r
+\r
+ If our protocol edge (lower edge) has been notified of a low-power state,\r
+ we pend this request until the miniport below has been set to D0. Since\r
+ requests to miniports are serialized always, at most a single request will\r
+ be pended.\r
+\r
+Arguments:\r
+\r
+ MiniportAdapterContext Pointer to the adapter structure\r
+ Oid Oid for this query\r
+ InformationBuffer Buffer for information\r
+ InformationBufferLength Size of this buffer\r
+ BytesWritten Specifies how much info is written\r
+ BytesNeeded In case the buffer is smaller than what we need, tell them how much is needed\r
+\r
+\r
+Return Value:\r
+\r
+ Return code from the NdisRequest below.\r
+\r
+--*/\r
+{\r
+ PADAPT pAdapt = (PADAPT)MiniportAdapterContext;\r
+ NDIS_STATUS Status = NDIS_STATUS_FAILURE;\r
+\r
+ do\r
+ {\r
+ if (Oid == OID_PNP_QUERY_POWER)\r
+ {\r
+ //\r
+ // Do not forward this.\r
+ //\r
+ Status = NDIS_STATUS_SUCCESS;\r
+ break;\r
+ }\r
+\r
+ if (Oid == OID_GEN_SUPPORTED_GUIDS)\r
+ {\r
+ //\r
+ // Do not forward this, otherwise we will end up with multiple\r
+ // instances of private GUIDs that the underlying miniport\r
+ // supports.\r
+ //\r
+ Status = NDIS_STATUS_NOT_SUPPORTED;\r
+ break;\r
+ }\r
+\r
+ if (Oid == OID_TCP_TASK_OFFLOAD)\r
+ {\r
+ //\r
+ // Fail this -if- this driver performs data transformations\r
+ // that can interfere with a lower driver's ability to offload\r
+ // TCP tasks.\r
+ //\r
+ // Status = NDIS_STATUS_NOT_SUPPORTED;\r
+ // break;\r
+ //\r
+ }\r
+ //\r
+ // If the miniport below is unbinding, just fail any request\r
+ //\r
+ NdisAcquireSpinLock(&pAdapt->Lock);\r
+ if (pAdapt->UnbindingInProcess == TRUE)\r
+ {\r
+ NdisReleaseSpinLock(&pAdapt->Lock);\r
+ Status = NDIS_STATUS_FAILURE;\r
+ break;\r
+ }\r
+ NdisReleaseSpinLock(&pAdapt->Lock);\r
+ //\r
+ // All other queries are failed, if the miniport is not at D0,\r
+ //\r
+ if (pAdapt->MPDeviceState > NdisDeviceStateD0) \r
+ {\r
+ Status = NDIS_STATUS_FAILURE;\r
+ break;\r
+ }\r
+\r
+ pAdapt->Request.RequestType = NdisRequestQueryInformation;\r
+ pAdapt->Request.DATA.QUERY_INFORMATION.Oid = Oid;\r
+ pAdapt->Request.DATA.QUERY_INFORMATION.InformationBuffer = InformationBuffer;\r
+ pAdapt->Request.DATA.QUERY_INFORMATION.InformationBufferLength = InformationBufferLength;\r
+ pAdapt->BytesNeeded = BytesNeeded;\r
+ pAdapt->BytesReadOrWritten = BytesWritten;\r
+\r
+ //\r
+ // If the miniport below is binding, fail the request\r
+ //\r
+ NdisAcquireSpinLock(&pAdapt->Lock);\r
+ \r
+ if (pAdapt->UnbindingInProcess == TRUE)\r
+ {\r
+ NdisReleaseSpinLock(&pAdapt->Lock);\r
+ Status = NDIS_STATUS_FAILURE;\r
+ break;\r
+ }\r
+ //\r
+ // If the Protocol device state is OFF, mark this request as being \r
+ // pended. We queue this until the device state is back to D0. \r
+ //\r
+ if ((pAdapt->PTDeviceState > NdisDeviceStateD0) \r
+ && (pAdapt->StandingBy == FALSE))\r
+ {\r
+ pAdapt->QueuedRequest = TRUE;\r
+ NdisReleaseSpinLock(&pAdapt->Lock);\r
+ Status = NDIS_STATUS_PENDING;\r
+ break;\r
+ }\r
+ //\r
+ // This is in the process of powering down the system, always fail the request\r
+ // \r
+ if (pAdapt->StandingBy == TRUE)\r
+ {\r
+ NdisReleaseSpinLock(&pAdapt->Lock);\r
+ Status = NDIS_STATUS_FAILURE;\r
+ break;\r
+ }\r
+ pAdapt->OutstandingRequests = TRUE;\r
+ \r
+ NdisReleaseSpinLock(&pAdapt->Lock);\r
+\r
+ //\r
+ // default case, most requests will be passed to the miniport below\r
+ //\r
+ NdisRequest(&Status,\r
+ pAdapt->BindingHandle,\r
+ &pAdapt->Request);\r
+\r
+\r
+ if (Status != NDIS_STATUS_PENDING)\r
+ {\r
+ PtRequestComplete(pAdapt, &pAdapt->Request, Status);\r
+ Status = NDIS_STATUS_PENDING;\r
+ }\r
+\r
+ } while (FALSE);\r
+\r
+ return(Status);\r
+\r
+}\r
+\r
+\r
+VOID\r
+MPQueryPNPCapabilities(\r
+ IN OUT PADAPT pAdapt,\r
+ OUT PNDIS_STATUS pStatus\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Postprocess a request for OID_PNP_CAPABILITIES that was forwarded\r
+ down to the underlying miniport, and has been completed by it.\r
+\r
+Arguments:\r
+\r
+ pAdapt - Pointer to the adapter structure\r
+ pStatus - Place to return final status\r
+\r
+Return Value:\r
+\r
+ None.\r
+\r
+--*/\r
+\r
+{\r
+ PNDIS_PNP_CAPABILITIES pPNPCapabilities;\r
+ PNDIS_PM_WAKE_UP_CAPABILITIES pPMstruct;\r
+\r
+ if (pAdapt->Request.DATA.QUERY_INFORMATION.InformationBufferLength >= sizeof(NDIS_PNP_CAPABILITIES))\r
+ {\r
+ pPNPCapabilities = (PNDIS_PNP_CAPABILITIES)(pAdapt->Request.DATA.QUERY_INFORMATION.InformationBuffer);\r
+\r
+ //\r
+ // The following fields must be overwritten by an IM driver.\r
+ //\r
+ pPMstruct= & pPNPCapabilities->WakeUpCapabilities;\r
+ pPMstruct->MinMagicPacketWakeUp = NdisDeviceStateUnspecified;\r
+ pPMstruct->MinPatternWakeUp = NdisDeviceStateUnspecified;\r
+ pPMstruct->MinLinkChangeWakeUp = NdisDeviceStateUnspecified;\r
+ *pAdapt->BytesReadOrWritten = sizeof(NDIS_PNP_CAPABILITIES);\r
+ *pAdapt->BytesNeeded = 0;\r
+\r
+\r
+ //\r
+ // Setting our internal flags\r
+ // Default, device is ON\r
+ //\r
+ pAdapt->MPDeviceState = NdisDeviceStateD0;\r
+ pAdapt->PTDeviceState = NdisDeviceStateD0;\r
+\r
+ *pStatus = NDIS_STATUS_SUCCESS;\r
+ }\r
+ else\r
+ {\r
+ *pAdapt->BytesNeeded= sizeof(NDIS_PNP_CAPABILITIES);\r
+ *pStatus = NDIS_STATUS_RESOURCES;\r
+ }\r
+}\r
+\r
+\r
+NDIS_STATUS\r
+MPSetInformation(\r
+ IN NDIS_HANDLE MiniportAdapterContext,\r
+ IN NDIS_OID Oid,\r
+ __in_bcount(InformationBufferLength) IN PVOID InformationBuffer,\r
+ IN ULONG InformationBufferLength,\r
+ OUT PULONG BytesRead,\r
+ OUT PULONG BytesNeeded\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Miniport SetInfo handler.\r
+\r
+ In the case of OID_PNP_SET_POWER, record the power state and return the OID. \r
+ Do not pass below\r
+ If the device is suspended, do not block the SET_POWER_OID \r
+ as it is used to reactivate the Passthru miniport\r
+\r
+ \r
+ PM- If the MP is not ON (DeviceState > D0) return immediately (except for 'query power' and 'set power')\r
+ If MP is ON, but the PT is not at D0, then queue the queue the request for later processing\r
+\r
+ Requests to miniports are always serialized\r
+\r
+\r
+Arguments:\r
+\r
+ MiniportAdapterContext Pointer to the adapter structure\r
+ Oid Oid for this query\r
+ InformationBuffer Buffer for information\r
+ InformationBufferLength Size of this buffer\r
+ BytesRead Specifies how much info is read\r
+ BytesNeeded In case the buffer is smaller than what we need, tell them how much is needed\r
+\r
+Return Value:\r
+\r
+ Return code from the NdisRequest below.\r
+\r
+--*/\r
+{\r
+ PADAPT pAdapt = (PADAPT)MiniportAdapterContext;\r
+ NDIS_STATUS Status;\r
+\r
+ Status = NDIS_STATUS_FAILURE;\r
+\r
+ do\r
+ {\r
+ //\r
+ // The Set Power should not be sent to the miniport below the Passthru, but is handled internally\r
+ //\r
+ if (Oid == OID_PNP_SET_POWER)\r
+ {\r
+ MPProcessSetPowerOid(&Status, \r
+ pAdapt, \r
+ InformationBuffer, \r
+ InformationBufferLength, \r
+ BytesRead, \r
+ BytesNeeded);\r
+ break;\r
+\r
+ }\r
+\r
+ //\r
+ // If the miniport below is unbinding, fail the request\r
+ //\r
+ NdisAcquireSpinLock(&pAdapt->Lock); \r
+ if (pAdapt->UnbindingInProcess == TRUE)\r
+ {\r
+ NdisReleaseSpinLock(&pAdapt->Lock);\r
+ Status = NDIS_STATUS_FAILURE;\r
+ break;\r
+ }\r
+ NdisReleaseSpinLock(&pAdapt->Lock);\r
+ //\r
+ // All other Set Information requests are failed, if the miniport is\r
+ // not at D0 or is transitioning to a device state greater than D0.\r
+ //\r
+ if (pAdapt->MPDeviceState > NdisDeviceStateD0)\r
+ {\r
+ Status = NDIS_STATUS_FAILURE;\r
+ break;\r
+ }\r
+\r
+ // Set up the Request and return the result\r
+ pAdapt->Request.RequestType = NdisRequestSetInformation;\r
+ pAdapt->Request.DATA.SET_INFORMATION.Oid = Oid;\r
+ pAdapt->Request.DATA.SET_INFORMATION.InformationBuffer = InformationBuffer;\r
+ pAdapt->Request.DATA.SET_INFORMATION.InformationBufferLength = InformationBufferLength;\r
+ pAdapt->BytesNeeded = BytesNeeded;\r
+ pAdapt->BytesReadOrWritten = BytesRead;\r
+\r
+ //\r
+ // If the miniport below is unbinding, fail the request\r
+ //\r
+ NdisAcquireSpinLock(&pAdapt->Lock); \r
+ if (pAdapt->UnbindingInProcess == TRUE)\r
+ {\r
+ NdisReleaseSpinLock(&pAdapt->Lock);\r
+ Status = NDIS_STATUS_FAILURE;\r
+ break;\r
+ }\r
+ \r
+ //\r
+ // If the device below is at a low power state, we cannot send it the\r
+ // request now, and must pend it.\r
+ //\r
+ if ((pAdapt->PTDeviceState > NdisDeviceStateD0) \r
+ && (pAdapt->StandingBy == FALSE))\r
+ {\r
+ pAdapt->QueuedRequest = TRUE;\r
+ NdisReleaseSpinLock(&pAdapt->Lock);\r
+ Status = NDIS_STATUS_PENDING;\r
+ break;\r
+ }\r
+ //\r
+ // This is in the process of powering down the system, always fail the request\r
+ // \r
+ if (pAdapt->StandingBy == TRUE)\r
+ {\r
+ NdisReleaseSpinLock(&pAdapt->Lock);\r
+ Status = NDIS_STATUS_FAILURE;\r
+ break;\r
+ }\r
+ pAdapt->OutstandingRequests = TRUE;\r
+ \r
+ NdisReleaseSpinLock(&pAdapt->Lock);\r
+ //\r
+ // Forward the request to the device below.\r
+ //\r
+ NdisRequest(&Status,\r
+ pAdapt->BindingHandle,\r
+ &pAdapt->Request);\r
+\r
+ if (Status != NDIS_STATUS_PENDING)\r
+ {\r
+ *BytesRead = pAdapt->Request.DATA.SET_INFORMATION.BytesRead;\r
+ *BytesNeeded = pAdapt->Request.DATA.SET_INFORMATION.BytesNeeded;\r
+ pAdapt->OutstandingRequests = FALSE;\r
+ }\r
+\r
+ } while (FALSE);\r
+\r
+ return(Status);\r
+}\r
+\r
+\r
+VOID\r
+MPProcessSetPowerOid(\r
+ IN OUT PNDIS_STATUS pNdisStatus,\r
+ IN PADAPT pAdapt,\r
+ __in_bcount(InformationBufferLength) IN PVOID InformationBuffer,\r
+ IN ULONG InformationBufferLength,\r
+ OUT PULONG BytesRead,\r
+ OUT PULONG BytesNeeded\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ This routine does all the procssing for a request with a SetPower Oid\r
+ The miniport shoud accept the Set Power and transition to the new state\r
+\r
+ The Set Power should not be passed to the miniport below\r
+\r
+ If the IM miniport is going into a low power state, then there is no guarantee if it will ever\r
+ be asked go back to D0, before getting halted. No requests should be pended or queued.\r
+\r
+ \r
+Arguments:\r
+ pNdisStatus - Status of the operation\r
+ pAdapt - The Adapter structure\r
+ InformationBuffer - The New DeviceState\r
+ InformationBufferLength\r
+ BytesRead - No of bytes read\r
+ BytesNeeded - No of bytes needed\r
+\r
+\r
+Return Value:\r
+ Status - NDIS_STATUS_SUCCESS if all the wait events succeed.\r
+\r
+--*/\r
+{\r
+\r
+ \r
+ NDIS_DEVICE_POWER_STATE NewDeviceState;\r
+\r
+ DBGPRINT(("==>MPProcessSetPowerOid: Adapt %p\n", pAdapt)); \r
+\r
+ ASSERT (InformationBuffer != NULL);\r
+\r
+ *pNdisStatus = NDIS_STATUS_FAILURE;\r
+\r
+ do \r
+ {\r
+ //\r
+ // Check for invalid length\r
+ //\r
+ if (InformationBufferLength < sizeof(NDIS_DEVICE_POWER_STATE))\r
+ {\r
+ *pNdisStatus = NDIS_STATUS_INVALID_LENGTH;\r
+ break;\r
+ }\r
+\r
+ NewDeviceState = (*(PNDIS_DEVICE_POWER_STATE)InformationBuffer);\r
+\r
+ //\r
+ // Check for invalid device state\r
+ //\r
+ if ((pAdapt->MPDeviceState > NdisDeviceStateD0) && (NewDeviceState != NdisDeviceStateD0))\r
+ {\r
+ //\r
+ // If the miniport is in a non-D0 state, the miniport can only receive a Set Power to D0\r
+ //\r
+ ASSERT (!(pAdapt->MPDeviceState > NdisDeviceStateD0) && (NewDeviceState != NdisDeviceStateD0));\r
+\r
+ *pNdisStatus = NDIS_STATUS_FAILURE;\r
+ break;\r
+ } \r
+\r
+ //\r
+ // Is the miniport transitioning from an On (D0) state to an Low Power State (>D0)\r
+ // If so, then set the StandingBy Flag - (Block all incoming requests)\r
+ //\r
+ if (pAdapt->MPDeviceState == NdisDeviceStateD0 && NewDeviceState > NdisDeviceStateD0)\r
+ {\r
+ pAdapt->StandingBy = TRUE;\r
+ }\r
+\r
+ //\r
+ // If the miniport is transitioning from a low power state to ON (D0), then clear the StandingBy flag\r
+ // All incoming requests will be pended until the physical miniport turns ON.\r
+ //\r
+ if (pAdapt->MPDeviceState > NdisDeviceStateD0 && NewDeviceState == NdisDeviceStateD0)\r
+ {\r
+ pAdapt->StandingBy = FALSE;\r
+ }\r
+ \r
+ //\r
+ // Now update the state in the pAdapt structure;\r
+ //\r
+ pAdapt->MPDeviceState = NewDeviceState;\r
+ \r
+ *pNdisStatus = NDIS_STATUS_SUCCESS;\r
+ \r
+\r
+ } while (FALSE); \r
+ \r
+ if (*pNdisStatus == NDIS_STATUS_SUCCESS)\r
+ {\r
+ //\r
+ // The miniport resume from low power state\r
+ // \r
+ if (pAdapt->StandingBy == FALSE)\r
+ {\r
+ //\r
+ // If we need to indicate the media connect state\r
+ // \r
+ if (pAdapt->LastIndicatedStatus != pAdapt->LatestUnIndicateStatus)\r
+ {\r
+ if (pAdapt->MiniportHandle != NULL)\r
+ {\r
+ NdisMIndicateStatus(pAdapt->MiniportHandle,\r
+ pAdapt->LatestUnIndicateStatus,\r
+ (PVOID)NULL,\r
+ 0);\r
+ NdisMIndicateStatusComplete(pAdapt->MiniportHandle);\r
+ pAdapt->LastIndicatedStatus = pAdapt->LatestUnIndicateStatus;\r
+ }\r
+ }\r
+ }\r
+ else\r
+ {\r
+ //\r
+ // Initialize LatestUnIndicatedStatus\r
+ //\r
+ pAdapt->LatestUnIndicateStatus = pAdapt->LastIndicatedStatus;\r
+ }\r
+ *BytesRead = sizeof(NDIS_DEVICE_POWER_STATE);\r
+ *BytesNeeded = 0;\r
+ }\r
+ else\r
+ {\r
+ *BytesRead = 0;\r
+ *BytesNeeded = sizeof (NDIS_DEVICE_POWER_STATE);\r
+ }\r
+\r
+ DBGPRINT(("<==MPProcessSetPowerOid: Adapt %p\n", pAdapt)); \r
+}\r
+\r
+\r
+VOID\r
+MPReturnPacket(\r
+ IN NDIS_HANDLE MiniportAdapterContext,\r
+ IN PNDIS_PACKET Packet\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ NDIS Miniport entry point called whenever protocols are done with\r
+ a packet that we had indicated up and they had queued up for returning\r
+ later.\r
+\r
+Arguments:\r
+\r
+ MiniportAdapterContext - pointer to ADAPT structure\r
+ Packet - packet being returned.\r
+\r
+Return Value:\r
+\r
+ None.\r
+\r
+--*/\r
+{\r
+ PADAPT pAdapt = (PADAPT)MiniportAdapterContext;\r
+\r
+#ifdef NDIS51\r
+ //\r
+ // Packet stacking: Check if this packet belongs to us.\r
+ //\r
+ if (NdisGetPoolFromPacket(Packet) != pAdapt->RecvPacketPoolHandle)\r
+ {\r
+ //\r
+ // We reused the original packet in a receive indication.\r
+ // Simply return it to the miniport below us.\r
+ //\r
+ NdisReturnPackets(&Packet, 1);\r
+ }\r
+ else\r
+#endif // NDIS51\r
+ {\r
+ //\r
+ // This is a packet allocated from this IM's receive packet pool.\r
+ // Reclaim our packet, and return the original to the driver below.\r
+ //\r
+\r
+ PNDIS_PACKET MyPacket;\r
+ PRECV_RSVD RecvRsvd;\r
+ \r
+ RecvRsvd = (PRECV_RSVD)(Packet->MiniportReserved);\r
+ MyPacket = RecvRsvd->OriginalPkt;\r
+ \r
+ NdisFreePacket(Packet);\r
+ NdisReturnPackets(&MyPacket, 1);\r
+ }\r
+}\r
+\r
+\r
+NDIS_STATUS\r
+MPTransferData(\r
+ OUT PNDIS_PACKET Packet,\r
+ OUT PUINT BytesTransferred,\r
+ IN NDIS_HANDLE MiniportAdapterContext,\r
+ IN NDIS_HANDLE MiniportReceiveContext,\r
+ IN UINT ByteOffset,\r
+ IN UINT BytesToTransfer\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Miniport's transfer data handler.\r
+\r
+Arguments:\r
+\r
+ Packet Destination packet\r
+ BytesTransferred Place-holder for how much data was copied\r
+ MiniportAdapterContext Pointer to the adapter structure\r
+ MiniportReceiveContext Context\r
+ ByteOffset Offset into the packet for copying data\r
+ BytesToTransfer How much to copy.\r
+\r
+Return Value:\r
+\r
+ Status of transfer\r
+\r
+--*/\r
+{\r
+ PADAPT pAdapt = (PADAPT)MiniportAdapterContext;\r
+ NDIS_STATUS Status;\r
+\r
+ //\r
+ // Return, if the device is OFF\r
+ //\r
+\r
+ if (IsIMDeviceStateOn(pAdapt) == FALSE)\r
+ {\r
+ return NDIS_STATUS_FAILURE;\r
+ }\r
+\r
+ NdisTransferData(&Status,\r
+ pAdapt->BindingHandle,\r
+ MiniportReceiveContext,\r
+ ByteOffset,\r
+ BytesToTransfer,\r
+ Packet,\r
+ BytesTransferred);\r
+\r
+ return(Status);\r
+}\r
+\r
+VOID\r
+MPHalt(\r
+ IN NDIS_HANDLE MiniportAdapterContext\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Halt handler. All the hard-work for clean-up is done here.\r
+\r
+Arguments:\r
+\r
+ MiniportAdapterContext Pointer to the Adapter\r
+\r
+Return Value:\r
+\r
+ None.\r
+\r
+--*/\r
+{\r
+ PADAPT pAdapt = (PADAPT)MiniportAdapterContext;\r
+ NDIS_STATUS Status;\r
+ PADAPT *ppCursor;\r
+\r
+ DBGPRINT(("==>MiniportHalt: Adapt %p\n", pAdapt));\r
+\r
+ pAdapt->MiniportHandle = NULL;\r
+ pAdapt->MiniportIsHalted = TRUE;\r
+\r
+ //\r
+ // Remove this adapter from the global list\r
+ //\r
+ NdisAcquireSpinLock(&GlobalLock);\r
+\r
+ for (ppCursor = &pAdaptList; *ppCursor != NULL; ppCursor = &(*ppCursor)->Next)\r
+ {\r
+ if (*ppCursor == pAdapt)\r
+ {\r
+ *ppCursor = pAdapt->Next;\r
+ break;\r
+ }\r
+ }\r
+\r
+ NdisReleaseSpinLock(&GlobalLock);\r
+\r
+ //\r
+ // Delete the ioctl interface that was created when the miniport\r
+ // was created.\r
+ //\r
+ (VOID)PtDeregisterDevice();\r
+\r
+ //\r
+ // If we have a valid bind, close the miniport below the protocol\r
+ //\r
+#pragma prefast(suppress: __WARNING_DEREF_NULL_PTR, "pAdapt cannot be NULL")\r
+ if (pAdapt->BindingHandle != NULL)\r
+ {\r
+ //\r
+ // Close the binding below. and wait for it to complete\r
+ //\r
+ NdisResetEvent(&pAdapt->Event);\r
+\r
+ NdisCloseAdapter(&Status, pAdapt->BindingHandle);\r
+\r
+ if (Status == NDIS_STATUS_PENDING)\r
+ {\r
+ NdisWaitEvent(&pAdapt->Event, 0);\r
+ Status = pAdapt->Status;\r
+ }\r
+\r
+ ASSERT (Status == NDIS_STATUS_SUCCESS);\r
+\r
+ pAdapt->BindingHandle = NULL;\r
+ \r
+ PtDereferenceAdapt(pAdapt);\r
+ }\r
+\r
+ if (PtDereferenceAdapt(pAdapt))\r
+ {\r
+ pAdapt = NULL;\r
+ }\r
+ \r
+ \r
+ DBGPRINT(("<== MiniportHalt: pAdapt %p\n", pAdapt));\r
+}\r
+\r
+\r
+#ifdef NDIS51_MINIPORT\r
+\r
+VOID\r
+MPCancelSendPackets(\r
+ IN NDIS_HANDLE MiniportAdapterContext,\r
+ IN PVOID CancelId\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ The miniport entry point to handle cancellation of all send packets\r
+ that match the given CancelId. If we have queued any packets that match\r
+ this, then we should dequeue them and call NdisMSendComplete for all\r
+ such packets, with a status of NDIS_STATUS_REQUEST_ABORTED.\r
+\r
+ We should also call NdisCancelSendPackets in turn, on each lower binding\r
+ that this adapter corresponds to. This is to let miniports below cancel\r
+ any matching packets.\r
+\r
+Arguments:\r
+\r
+ MiniportAdapterContext - pointer to ADAPT structure\r
+ CancelId - ID of packets to be cancelled.\r
+\r
+Return Value:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ PADAPT pAdapt = (PADAPT)MiniportAdapterContext;\r
+\r
+ //\r
+ // If we queue packets on our adapter structure, this would be \r
+ // the place to acquire a spinlock to it, unlink any packets whose\r
+ // Id matches CancelId, release the spinlock and call NdisMSendComplete\r
+ // with NDIS_STATUS_REQUEST_ABORTED for all unlinked packets.\r
+ //\r
+\r
+ //\r
+ // Next, pass this down so that we let the miniport(s) below cancel\r
+ // any packets that they might have queued.\r
+ //\r
+ NdisCancelSendPackets(pAdapt->BindingHandle, CancelId);\r
+\r
+ return;\r
+}\r
+\r
+VOID\r
+MPDevicePnPEvent(\r
+ IN NDIS_HANDLE MiniportAdapterContext,\r
+ IN NDIS_DEVICE_PNP_EVENT DevicePnPEvent,\r
+ IN PVOID InformationBuffer,\r
+ IN ULONG InformationBufferLength\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ This handler is called to notify us of PnP events directed to\r
+ our miniport device object.\r
+\r
+Arguments:\r
+\r
+ MiniportAdapterContext - pointer to ADAPT structure\r
+ DevicePnPEvent - the event\r
+ InformationBuffer - Points to additional event-specific information\r
+ InformationBufferLength - length of above\r
+\r
+Return Value:\r
+\r
+ None\r
+--*/\r
+{\r
+ // TBD - add code/comments about processing this.\r
+\r
+ UNREFERENCED_PARAMETER(MiniportAdapterContext);\r
+ UNREFERENCED_PARAMETER(DevicePnPEvent);\r
+ UNREFERENCED_PARAMETER(InformationBuffer);\r
+ UNREFERENCED_PARAMETER(InformationBufferLength);\r
+ \r
+ return;\r
+}\r
+\r
+VOID\r
+MPAdapterShutdown(\r
+ IN NDIS_HANDLE MiniportAdapterContext\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ This handler is called to notify us of an impending system shutdown.\r
+\r
+Arguments:\r
+\r
+ MiniportAdapterContext - pointer to ADAPT structure\r
+\r
+Return Value:\r
+\r
+ None\r
+--*/\r
+{\r
+ UNREFERENCED_PARAMETER(MiniportAdapterContext);\r
+ \r
+ return;\r
+}\r
+\r
+#endif\r
+\r
+\r
+VOID\r
+MPFreeAllPacketPools(\r
+ IN PADAPT pAdapt\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Free all packet pools on the specified adapter.\r
+ \r
+Arguments:\r
+\r
+ pAdapt - pointer to ADAPT structure\r
+\r
+Return Value:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ if (pAdapt->RecvPacketPoolHandle != NULL)\r
+ {\r
+ //\r
+ // Free the packet pool that is used to indicate receives\r
+ //\r
+ NdisFreePacketPool(pAdapt->RecvPacketPoolHandle);\r
+\r
+ pAdapt->RecvPacketPoolHandle = NULL;\r
+ }\r
+\r
+ if (pAdapt->SendPacketPoolHandle != NULL)\r
+ {\r
+\r
+ //\r
+ // Free the packet pool that is used to send packets below\r
+ //\r
+\r
+ NdisFreePacketPool(pAdapt->SendPacketPoolHandle);\r
+\r
+ pAdapt->SendPacketPoolHandle = NULL;\r
+\r
+ }\r
+}\r
+\r