⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 protocol.c

📁 NDIS Intermediate Driver
💻 C
📖 第 1 页 / 共 4 页
字号:
    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 + -