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

📄 ndiswdm.c

📁 网络驱动开发
💻 C
📖 第 1 页 / 共 2 页
字号:
        //
        if(Adapter->nBusyRecv)
        {
            DEBUGP(MP_INFO, ("nBusyRecv = %d\n", Adapter->nBusyRecv));
            bDone = FALSE;
        }
        
        //
        // Are there any outstanding send packets?                                                         
        //
        if(Adapter->nBusySend)
        {
            DEBUGP(MP_INFO, ("nBusySend = %d\n", Adapter->nBusySend));
            bDone = FALSE;
        }

        if(bDone)
        {
            break;   
        }

        if((++nHaltCount % 100) == 0)
        {
            DEBUGP(MP_ERROR, ("Halt timed out!!!\n"));
            ASSERT(FALSE);       
        }
        
        DEBUGP(MP_INFO, ("MPHalt - waiting ...\n"));
        NdisMSleep(1000);        
    }

    ASSERT(bDone);
    
#ifdef NDIS50_MINIPORT
    //
    // Deregister shutdown handler as it's being halted
    //
    NdisMDeregisterAdapterShutdownHandler(Adapter->AdapterHandle);
#endif  

    NICDetachAdapter(Adapter);
    NICFreeRecvResources(Adapter);
    NICFreeSendResources(Adapter);
    NICFreeAdapter(Adapter);
    
    DEBUGP(MP_WARNING, ("<--- MPHalt\n"));
}

NDIS_STATUS 
MPReset(
    OUT PBOOLEAN AddressingReset,
    IN  NDIS_HANDLE MiniportAdapterContext
    )
/*++

Routine Description:

    MiniportReset is a required to issue a hardware reset to the NIC 
    and/or to reset the driver's software state. 

    1) The miniport driver can optionally complete any pending
        OID requests. NDIS will submit no further OID requests 
        to the miniport driver for the NIC being reset until 
        the reset operation has finished. If you return Status_success
        and still have any pending OIDs, NDIS will complete the OID
        on your behalf. So make sure to complete the pending OIDs
        before returning SUCCESS.
        
    2) A deserialized miniport driver must complete any pending send 
        operations. NDIS will not requeue pending send packets for 
        a deserialized driver since NDIS does not maintain the send 
        queue for such a driver. 
        
    3) If MiniportReset returns NDIS_STATUS_PENDING, the driver must 
        complete the original request subsequently with a call to 
        NdisMResetComplete.

    MiniportReset runs at IRQL = DISPATCH_LEVEL.

Arguments:

AddressingReset - If multicast or functional addressing information 
                  or the lookahead size, is changed by a reset, 
                  MiniportReset must set the variable at AddressingReset 
                  to TRUE before it returns control. This causes NDIS to
                  call the MiniportSetInformation function to restore 
                  the information. 

MiniportAdapterContext - Pointer to our adapter

Return Value:

    NDIS_STATUS

--*/
{
    PMP_ADAPTER       Adapter = (PMP_ADAPTER) MiniportAdapterContext;
    NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
    
    DEBUGP(MP_TRACE, ("---> MPReset\n"));

    *AddressingReset = FALSE;

    ASSERT(Adapter->ResetPending == FALSE);
    ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
    
    NdisDprAcquireSpinLock(&Adapter->Lock);

    //
    // If there is a pending request, we must wait for it to complete
    // before completing the reset. Since the reset handler is called
    // at DISPATCH_LEVEL, we can't really wait here. So we will return
    // STATUS_PENDING, and in the completion handler for forwarded
    // OID requests, we will call NdisMResetComplete().
    //
    if(Adapter->RequestPending){
        Adapter->ResetPending = TRUE;
        Status = NDIS_STATUS_PENDING;
    }

    NdisDprReleaseSpinLock(&Adapter->Lock);

    DEBUGP(MP_TRACE, ("<--- MPReset\n"));
    
    return Status;
}

VOID 
MPUnload(
    IN  PDRIVER_OBJECT  DriverObject
    )
/*++

Routine Description:
    
    The unload handler is called during driver unload to free up resources
    acquired in DriverEntry. This handler is registered through 
    NdisMRegisterUnloadHandler. Note that an unload handler differs from 
    a MiniportHalt function in that the unload handler has a more global
    scope, whereas the scope of the MiniportHalt function is restricted 
    to a particular miniport driver instance.

    Runs at IRQL = PASSIVE_LEVEL. 
    
Arguments:

    DriverObject        Not used

Return Value:

    None
    
--*/
{
    DEBUGP(MP_WARNING, ("--> MPUnload\n"));

    PAGED_CODE();

    ASSERT(IsListEmpty(&GlobalData.AdapterList));
    NdisFreeSpinLock(&GlobalData.Lock);
    
    DEBUGP(MP_WARNING, ("<--- MPUnload\n"));   
}

VOID 
MPShutdown(
    IN NDIS_HANDLE MiniportAdapterContext
    )
/*++

Routine Description:
    
    The MiniportShutdown handler restores a NIC to its initial state when
    the system is shut down, whether by the user or because an unrecoverable
    system error occurred. This is to ensure that the NIC is in a known 
    state and ready to be reinitialized when the machine is rebooted after
    a system shutdown occurs for any reason, including a crash dump.

    Here just disable the interrupt and stop the DMA engine.
    Do not free memory resources or wait for any packet transfers
    to complete.


    Runs at an arbitrary IRQL <= DIRQL. So do not call any passive-level
    function.
    
Arguments:

    MiniportAdapterContext  Pointer to our adapter

Return Value:

    None
    
--*/
{
    PMP_ADAPTER Adapter = (PMP_ADAPTER) MiniportAdapterContext;
    
    DEBUGP(MP_TRACE, ("---> MPShutdown\n"));
    
    DEBUGP(MP_TRACE, ("<--- MPShutdown\n"));

}

BOOLEAN 
MPCheckForHang(
    IN NDIS_HANDLE MiniportAdapterContext
    )
/*++

Routine Description:
    
    The MiniportCheckForHang handler is called to report the state of the
    NIC, or to monitor the responsiveness of an underlying device driver. 
    This is an optional function. If this handler is not specified, NDIS
    judges the driver unresponsive when the driver holds 
    MiniportQueryInformation or MiniportSetInformation requests for a 
    time-out interval (deafult 4 sec), and then calls the driver's 
    MiniportReset function. A NIC driver's MiniportInitialize function can
    extend NDIS's time-out interval by calling NdisMSetAttributesEx to 
    avoid unnecessary resets. 

    Always runs at IRQL = DISPATCH_LEVEL.
    
Arguments:

    MiniportAdapterContext  Pointer to our adapter

Return Value:

    TRUE    NDIS calls the driver's MiniportReset function.
    FALSE   Everything is fine

Note: 
    CheckForHang handler is called in the context of a timer DPC. 
    take advantage of this fact when acquiring/releasing spinlocks

--*/
{
    //DEBUGP(MP_LOUD, ("---> MPCheckForHang\n"));
    //DEBUGP(MP_LOUD, ("<--- MPCheckForHang\n"));
    return(FALSE);
}


#ifdef NDIS51_MINIPORT
VOID 
MPCancelSendPackets(
    IN  NDIS_HANDLE     MiniportAdapterContext,
    IN  PVOID           CancelId
    )
/*++

Routine Description:
    
    MiniportCancelSendPackets cancels the transmission of all packets that
    are marked with a specified cancellation identifier. Miniport drivers
    that queue send packets for more than one second should export this
    handler. When a protocol driver or intermediate driver calls the
    NdisCancelSendPackets function, NDIS calls the MiniportCancelSendPackets 
    function of the appropriate lower-level driver (miniport driver or 
    intermediate driver) on the binding.

    Runs at IRQL <= DISPATCH_LEVEL.
  
    Available - NDIS5.1 (WinXP) and later.
    
Arguments:

    MiniportAdapterContext      Pointer to our adapter
    CancelId                    All the packets with this Id should be cancelled

Return Value:

    None
    
--*/
{
    PNDIS_PACKET    Packet;
    PVOID           PacketId;
    PLIST_ENTRY     thisEntry, nextEntry, listHead;
    SINGLE_LIST_ENTRY SendCancelList;
    PSINGLE_LIST_ENTRY entry;
    
    PMP_ADAPTER     Adapter = (PMP_ADAPTER)MiniportAdapterContext;

#define MP_GET_PACKET_MR(_p)    (PSINGLE_LIST_ENTRY)(&(_p)->MiniportReserved[0]) 

    DEBUGP(MP_TRACE, ("---> MPCancelSendPackets\n"));

    SendCancelList.Next = NULL;
    
    NdisAcquireSpinLock(&Adapter->SendLock);

    //
    // Walk through the send wait queue and complete the sends with matching Id
    //
    listHead = &Adapter->SendWaitList;
    
    for(thisEntry = listHead->Flink,nextEntry = thisEntry->Flink;
       thisEntry != listHead;
       thisEntry = nextEntry,nextEntry = thisEntry->Flink) {
        Packet = CONTAINING_RECORD(thisEntry, NDIS_PACKET, MiniportReserved);

        PacketId = NdisGetPacketCancelId(Packet);
        if (PacketId == CancelId)
        {       
            //
            // This packet has the right CancelId
            //
            RemoveEntryList(thisEntry);
            //
            // Put this packet on SendCancelList
            //
            PushEntryList(&SendCancelList, MP_GET_PACKET_MR(Packet));
        }
    }
       
    NdisReleaseSpinLock(&Adapter->SendLock);

    //
    // Get the packets from SendCancelList and complete them if any
    //

    entry = PopEntryList(&SendCancelList);
    
    while (entry)
    {
        Packet = CONTAINING_RECORD(entry, NDIS_PACKET, MiniportReserved);

        NdisMSendComplete(
            Adapter->AdapterHandle,
            Packet,
            NDIS_STATUS_REQUEST_ABORTED);
        
        entry = PopEntryList(&SendCancelList);        
    }

    DEBUGP(MP_TRACE, ("<--- MPCancelSendPackets\n"));

}

VOID MPPnPEventNotify(
    IN  NDIS_HANDLE             MiniportAdapterContext,
    IN  NDIS_DEVICE_PNP_EVENT   PnPEvent,
    IN  PVOID                   InformationBuffer,
    IN  ULONG                   InformationBufferLength
    )
/*++

Routine Description:
    
    MPPnPEventNotify is to handle PnP notification messages.
    An NDIS miniport driver with a WDM lower edge should export a
    MiniportPnPEventNotify function so that it can be notified
    when its NIC is removed without prior notification through
    the user interface. When a miniport driver receives 
    notification of a surprise removal, it should note internally
    that the device has been removed and cancel any pending IRPs
    that it sent down to the underlying bus driver. After calling
    the MiniportPnPEventNotify function to indicate the surprise
    removal, NDIS calls the miniport抯 MiniportHalt function. 
    If the miniport driver receives any requests to send packets
    or query or set OIDs before its MiniportHalt function is
    called, it should immediately complete such requests with a
    status value of NDIS_STATUS_NOT_ACCEPTED.

    All NDIS 5.1 miniport drivers must export a MPPnPEventNotify
    function. 
    
    Runs at IRQL = PASSIVE_LEVEL in the context of system thread.

    Available - NDIS5.1 (WinXP) and later.
    
Arguments:

    MiniportAdapterContext      Pointer to our adapter
    PnPEvent                    Self-explanatory 
    InformationBuffer           Self-explanatory 
    InformationBufferLength     Self-explanatory 

Return Value:

    None
    
--*/
{
    PMP_ADAPTER     Adapter = (PMP_ADAPTER)MiniportAdapterContext;
    PNDIS_POWER_PROFILE NdisPowerProfile;
    
    DEBUGP(MP_TRACE, ("---> MPPnPEventNotify\n"));

    //
    // NDIS currently sends only SurpriseRemoved and 
    // PowerProfileChange Notification events.
    //
    switch (PnPEvent)
    {
        case NdisDevicePnPEventQueryRemoved:
            //
            // Called when NDIS receives IRP_MN_QUERY_REMOVE_DEVICE.
            //
            DEBUGP(MP_LOUD, ("MPPnPEventNotify: NdisDevicePnPEventQueryRemoved\n"));
            break;

        case NdisDevicePnPEventRemoved:
            //
            // Called when NDIS receives IRP_MN_REMOVE_DEVICE.
            // NDIS calls MiniportHalt function after this call returns.
            //
            DEBUGP(MP_LOUD, ("MPPnPEventNotify: NdisDevicePnPEventRemoved\n"));
            break;       

        case NdisDevicePnPEventSurpriseRemoved:
            //
            // Called when NDIS receives IRP_MN_SUPRISE_REMOVAL. 
            // NDIS calls MiniportHalt function after this call returns.
            //
            MP_SET_FLAG(Adapter, fMP_SURPRISE_REMOVED);
            DEBUGP(MP_LOUD, ("MPPnPEventNotify: NdisDevicePnPEventSurpriseRemoved\n"));
            break;

        case NdisDevicePnPEventQueryStopped:
            //
            // Called when NDIS receives IRP_MN_QUERY_STOP_DEVICE. ??
            //
            DEBUGP(MP_LOUD, ("MPPnPEventNotify: NdisDevicePnPEventQueryStopped\n"));
            break;

        case NdisDevicePnPEventStopped:
            //
            // Called when NDIS receives IRP_MN_STOP_DEVICE.
            // NDIS calls MiniportHalt function after this call returns.
            // 
            //
            DEBUGP(MP_LOUD, ("MPPnPEventNotify: NdisDevicePnPEventStopped\n"));
            break;      
            
        case NdisDevicePnPEventPowerProfileChanged:
            //
            // After initializing a miniport driver and after miniport driver
            // receives an OID_PNP_SET_POWER notification that specifies 
            // a device power state of NdisDeviceStateD0 (the powered-on state), 
            // NDIS calls the miniport's MiniportPnPEventNotify function with 
            // PnPEvent set to NdisDevicePnPEventPowerProfileChanged. 
            //            
            DEBUGP(MP_LOUD, ("MPPnPEventNotify: NdisDevicePnPEventPowerProfileChanged\n"));
            
            if(InformationBufferLength == sizeof(NDIS_POWER_PROFILE)) {
                NdisPowerProfile = (PNDIS_POWER_PROFILE)InformationBuffer;
                if(*NdisPowerProfile == NdisPowerProfileBattery) {
                    DEBUGP(MP_LOUD, 
                        ("The host system is running on battery power\n"));
                }
                if(*NdisPowerProfile == NdisPowerProfileAcOnLine) {
                    DEBUGP(MP_LOUD, 
                        ("The host system is running on AC power\n"));
               }
            }
            break;      
            
        default:
            DEBUGP(MP_ERROR, ("MPPnPEventNotify: unknown PnP event %x \n", PnPEvent));
            break;         
    }

    DEBUGP(MP_TRACE, ("<--- MPPnPEventNotify\n"));

}

#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -