📄 protocol.c
字号:
PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
DBGPRINT(("PtPnPHandler: Adapt %p, Event %d\n", pAdapt, pNetPnPEvent->NetEvent));
switch (pNetPnPEvent->NetEvent)
{
case NetEventSetPower:
Status = PtPnPNetEventSetPower(pAdapt, pNetPnPEvent);
break;
case NetEventReconfigure:
Status = PtPnPNetEventReconfigure(pAdapt, pNetPnPEvent);
break;
default:
#ifdef NDIS51
//
// Pass on this notification to protocol(s) above, before
// doing anything else with it.
//
if (pAdapt && pAdapt->MiniportHandle)
{
Status = NdisIMNotifyPnPEvent(pAdapt->MiniportHandle, pNetPnPEvent);
}
#else
Status = NDIS_STATUS_SUCCESS;
#endif // NDIS51
break;
}
return Status;
}
NDIS_STATUS
PtPnPNetEventReconfigure(
IN PADAPT pAdapt,
IN PNET_PNP_EVENT pNetPnPEvent
)
/*++
Routine Description:
This routine is called from NDIS to notify our protocol edge of a
reconfiguration of parameters for either a specific binding (pAdapt
is not NULL), or global parameters if any (pAdapt is NULL).
Arguments:
pAdapt - Pointer to our adapter structure.
pNetPnPEvent - the reconfigure event
Return Value:
NDIS_STATUS_SUCCESS
--*/
{
NDIS_STATUS ReconfigStatus = NDIS_STATUS_SUCCESS;
NDIS_STATUS ReturnStatus = NDIS_STATUS_SUCCESS;
do
{
//
// Is this is a global reconfiguration notification ?
//
if (pAdapt == NULL)
{
//
// An important event that causes this notification to us is if
// one of our upper-edge miniport instances was enabled after being
// disabled earlier, e.g. from Device Manager in Win2000. Note that
// NDIS calls this because we had set up an association between our
// miniport and protocol entities by calling NdisIMAssociateMiniport.
//
// Since we would have torn down the lower binding for that miniport,
// we need NDIS' assistance to re-bind to the lower miniport. The
// call to NdisReEnumerateProtocolBindings does exactly that.
//
NdisReEnumerateProtocolBindings (ProtHandle);
break;
}
#ifdef NDIS51
//
// Pass on this notification to protocol(s) above before doing anything
// with it.
//
if (pAdapt->MiniportHandle)
{
ReturnStatus = NdisIMNotifyPnPEvent(pAdapt->MiniportHandle, pNetPnPEvent);
}
#endif // NDIS51
ReconfigStatus = NDIS_STATUS_SUCCESS;
} while(FALSE);
DBGPRINT(("<==PtPNPNetEventReconfigure: pAdapt %p\n", pAdapt));
#ifdef NDIS51
//
// Overwrite status with what upper-layer protocol(s) returned.
//
ReconfigStatus = ReturnStatus;
#endif
return ReconfigStatus;
}
NDIS_STATUS
PtPnPNetEventSetPower(
IN PADAPT pAdapt,
IN PNET_PNP_EVENT pNetPnPEvent
)
/*++
Routine Description:
This is a notification to our protocol edge of the power state
of the lower miniport. If it is going to a low-power state, we must
wait here for all outstanding sends and requests to complete.
NDIS 5.1: Since we use packet stacking, it is not sufficient to
check usage of our local send packet pool to detect whether or not
all outstanding sends have completed. For this, use the new API
NdisQueryPendingIOCount.
NDIS 5.1: Use the 5.1 API NdisIMNotifyPnPEvent to pass on PnP
notifications to upper protocol(s).
Arguments:
pAdapt - Pointer to the adpater structure
pNetPnPEvent - The Net Pnp Event. this contains the new device state
Return Value:
NDIS_STATUS_SUCCESS or the status returned by upper-layer protocols.
--*/
{
PNDIS_DEVICE_POWER_STATE pDeviceState =(PNDIS_DEVICE_POWER_STATE)(pNetPnPEvent->Buffer);
NDIS_DEVICE_POWER_STATE PrevDeviceState = pAdapt->PTDeviceState;
NDIS_STATUS Status;
NDIS_STATUS ReturnStatus;
#ifdef NDIS51
ULONG PendingIoCount = 0;
#endif // NDIS51
ReturnStatus = NDIS_STATUS_SUCCESS;
//
// Set the Internal Device State, this blocks all new sends or receives
//
NdisAcquireSpinLock(&pAdapt->Lock);
pAdapt->PTDeviceState = *pDeviceState;
//
// Check if the miniport below is going to a low power state.
//
if (pAdapt->PTDeviceState > NdisDeviceStateD0)
{
//
// If the miniport below is going to standby, fail all incoming requests
//
if (PrevDeviceState == NdisDeviceStateD0)
{
pAdapt->StandingBy = TRUE;
}
NdisReleaseSpinLock(&pAdapt->Lock);
#ifdef NDIS51
//
// Notify upper layer protocol(s) first.
//
if (pAdapt->MiniportHandle != NULL)
{
ReturnStatus = NdisIMNotifyPnPEvent(pAdapt->MiniportHandle, pNetPnPEvent);
}
#endif // NDIS51
//
// Wait for outstanding sends and requests to complete.
//
while (pAdapt->OutstandingSends != 0)
{
NdisMSleep(2);
}
while (pAdapt->OutstandingRequests == TRUE)
{
//
// sleep till outstanding requests complete
//
NdisMSleep(2);
}
//
// If the below miniport is going to low power state, complete the queued request
//
NdisAcquireSpinLock(&pAdapt->Lock);
if (pAdapt->QueuedRequest)
{
pAdapt->QueuedRequest = FALSE;
NdisReleaseSpinLock(&pAdapt->Lock);
PtRequestComplete(pAdapt, &pAdapt->Request, NDIS_STATUS_FAILURE);
}
else
{
NdisReleaseSpinLock(&pAdapt->Lock);
}
ASSERT(NdisPacketPoolUsage(pAdapt->SendPacketPoolHandle) == 0);
ASSERT(pAdapt->OutstandingRequests == FALSE);
}
else
{
//
// If the physical miniport is powering up (from Low power state to D0),
// clear the flag
//
if (PrevDeviceState > NdisDeviceStateD0)
{
pAdapt->StandingBy = FALSE;
}
//
// The device below is being turned on. If we had a request
// pending, send it down now.
//
if (pAdapt->QueuedRequest == TRUE)
{
pAdapt->QueuedRequest = FALSE;
pAdapt->OutstandingRequests = TRUE;
NdisReleaseSpinLock(&pAdapt->Lock);
NdisRequest(&Status,
pAdapt->BindingHandle,
&pAdapt->Request);
if (Status != NDIS_STATUS_PENDING)
{
PtRequestComplete(pAdapt,
&pAdapt->Request,
Status);
}
}
else
{
NdisReleaseSpinLock(&pAdapt->Lock);
}
#ifdef NDIS51
//
// Pass on this notification to protocol(s) above
//
if (pAdapt->MiniportHandle)
{
ReturnStatus = NdisIMNotifyPnPEvent(pAdapt->MiniportHandle, pNetPnPEvent);
}
#endif // NDIS51
}
return ReturnStatus;
}
VOID
PtQueueReceivedPacket(
IN PADAPT pAdapt,
IN PNDIS_PACKET Packet,
IN BOOLEAN DoIndicate
)
/*++
Routine Description:
This is to queue the received packets and indicates them up if the given Packet
status is NDIS_STATUS_RESOURCES, or the array is full.
Arguments:
pAdapt - Pointer to the adpater structure.
Packet - Pointer to the indicated packet.
DoIndicate - Do the indication now.
Return Value:
None.
--*/
{
PNDIS_PACKET PacketArray[MAX_RECEIVE_PACKET_ARRAY_SIZE];
ULONG NumberOfPackets = 0, i;
NdisDprAcquireSpinLock(&pAdapt->Lock);
ASSERT(pAdapt->ReceivedPacketCount < MAX_RECEIVE_PACKET_ARRAY_SIZE);
//
// pAdapt->ReceviePacketCount must be less than MAX_RECEIVE_PACKET_ARRAY_SIZE because
// the thread which held the pVElan->Lock before should already indicate the packet(s)
// up if pAdapt->ReceviePacketCount == MAX_RECEIVE_PACKET_ARRAY_SIZE.
//
pAdapt->ReceivedPackets[pAdapt->ReceivedPacketCount] = Packet;
pAdapt->ReceivedPacketCount++;
//
// If our receive packet array is full, or the miniport below indicated the packets
// with resources, do the indicatin now.
//
if ((pAdapt->ReceivedPacketCount == MAX_RECEIVE_PACKET_ARRAY_SIZE) || DoIndicate)
{
NdisMoveMemory(PacketArray,
pAdapt->ReceivedPackets,
pAdapt->ReceivedPacketCount * sizeof(PNDIS_PACKET));
NumberOfPackets = pAdapt->ReceivedPacketCount;
//
// So other thread can queue the received packets
//
pAdapt->ReceivedPacketCount = 0;
NdisDprReleaseSpinLock(&pAdapt->Lock);
//
// Here the driver checks if the miniport adapter is in lower power state, do not indicate the
// packets, but the check does not close the window, it only minimizes the window. To close
// the window completely, we need to add synchronization in the receive code path; because
// NDIS can handle the case that miniport drivers indicate packets in lower power state,
// we don't add the synchronization in the hot code path.
//
if ((pAdapt->MiniportHandle != NULL)
&& (pAdapt->MPDeviceState == NdisDeviceStateD0))
{
NdisMIndicateReceivePacket(pAdapt->MiniportHandle, PacketArray, NumberOfPackets);
}
else
{
if (DoIndicate)
{
NumberOfPackets -= 1;
}
for (i = 0; i < NumberOfPackets; i++)
{
MPReturnPacket(pAdapt, PacketArray[i]);
}
}
}
else
{
NdisDprReleaseSpinLock(&pAdapt->Lock);
}
}
VOID
PtFlushReceiveQueue(
IN PADAPT pAdapt
)
/*++
Routine Description:
This routine process the queued the packet, if anything is fine, indicate the packet
up, otherwise, return the packet to the underlying miniports.
Arguments:
pAdapt - Pointer to the adpater structure.
Return Value:
None.
*/
{
PNDIS_PACKET PacketArray[MAX_RECEIVE_PACKET_ARRAY_SIZE];
ULONG NumberOfPackets = 0, i;
do
{
NdisDprAcquireSpinLock(&pAdapt->Lock);
if (pAdapt->ReceivedPacketCount > 0)
{
NdisMoveMemory(PacketArray,
pAdapt->ReceivedPackets,
pAdapt->ReceivedPacketCount * sizeof(PNDIS_PACKET));
NumberOfPackets = pAdapt->ReceivedPacketCount;
//
// So other thread can queue the received packets
//
pAdapt->ReceivedPacketCount = 0;
NdisDprReleaseSpinLock(&pAdapt->Lock);
//
// Here the driver checks if the miniport adapter is in lower power state, do not indicate the
// packets, but the check does not close the window, it only minimizes the window. To close
// the window completely, we need to add synchronization in the receive code path; because
// NDIS can handle the case that miniport drivers indicate packets in lower power state,
// we don't add the synchronization in the hot code path.
//
if ((pAdapt->MiniportHandle)
&& (pAdapt->MPDeviceState == NdisDeviceStateD0))
{
NdisMIndicateReceivePacket(pAdapt->MiniportHandle,
PacketArray,
NumberOfPackets);
break;
}
//
// We need return the packet here
//
for (i = 0; i < NumberOfPackets; i ++)
{
MPReturnPacket(pAdapt, PacketArray[i]);
}
break;
}
NdisDprReleaseSpinLock(&pAdapt->Lock);
} while (FALSE);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -