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