+++ /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