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

📄 miniport.c

📁 网络驱动开发
💻 C
📖 第 1 页 / 共 3 页
字号:

    //
    // Free the packets on SendWaitList 
    //
    NICFreeQueuedSendPackets(Adapter);

    //
    // Cancel the ResetTimer.
    //    
    NdisCancelTimer(&Adapter->ResetTimer, &bCancelled);

    //
    // Cancel the ReceiveIndication Timer.
    //    
    NdisCancelTimer(&Adapter->RecvTimer, &bCancelled);
    if(bCancelled) {
        //
        // We are able to cancel a queued Timer. So there is a
        // possibility for the packets to be waiting in the 
        // RecvWaitList. So let us free them by calling..
        //
        NICFreeQueuedRecvPackets(Adapter);
    }            
    
    //
    // Decrement the ref count which was incremented in MPInitialize
    //

    MP_DEC_REF(Adapter);
    
    //
    // Possible non-zero ref counts mean one or more of the following conditions: 
    // 1) Reset DPC is still running.
    // 2) Receive Indication DPC is still running.
    //

    DEBUGP(MP_INFO, ("RefCount=%d --- waiting!\n", MP_GET_REF(Adapter)));

    NdisWaitEvent(&Adapter->RemoveEvent, 0);

    while(TRUE)
    {
        bDone = TRUE;
        
        //
        // Are all the packets indicated up returned?
        //
        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)
        {
            DEBUGP(MP_ERROR, ("Halt timed out!!!\n"));
            DEBUGP(MP_ERROR, ("RecvWaitList = %p\n", &Adapter->RecvWaitList));
            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  

    //
    // Unregister the ioctl interface.
    //
    NICDeregisterDevice();

    NICDetachAdapter(Adapter);

    NICFreeAdapter(Adapter);
    
    DEBUGP(MP_TRACE, ("<--- 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. After the reset, 
        NDIS will resubmit to the miniport driver any OID requests
        that were pending but not completed by the miniport driver
        before the reset.
    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

--*/
{
    NDIS_STATUS       Status;
    PMP_ADAPTER       Adapter = (PMP_ADAPTER) MiniportAdapterContext;

    BOOLEAN           bDone = TRUE;

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

    do
    {
        ASSERT(!MP_TEST_FLAG(Adapter, fMP_ADAPTER_HALT_IN_PROGRESS));
        
        if(MP_TEST_FLAG(Adapter, fMP_RESET_IN_PROGRESS))
        {
            Status = NDIS_STATUS_RESET_IN_PROGRESS;
            break;   
        }

        MP_SET_FLAG(Adapter, fMP_RESET_IN_PROGRESS);

        //
        // Complete all the queued up send packets
        //
        NICFreeQueuedSendPackets(Adapter);

        //
        // Check to see if all the packets indicated up are returned.
        //
        if(Adapter->nBusyRecv)
        {
            DEBUGP(MP_INFO, ("nBusyRecv = %d\n", Adapter->nBusyRecv));
            bDone = FALSE;
        }

        //
        // Are there any send packets in the processes of being 
        // transmitted?
        //
        if(Adapter->nBusySend)
        {
            DEBUGP(MP_INFO, ("nBusySend = %d\n", Adapter->nBusySend));
            bDone = FALSE;
        }

        if(!bDone)
        {
            Adapter->nResetTimerCount = 0;
            //
            // We can't complete the reset request now. So let us queue
            // a timer callback for 500ms and check again whether we can 
            // successfully reset the hardware.
            //
            NdisSetTimer(&Adapter->ResetTimer, 500);

            //
            // By returning NDIS_STATUS_PENDING, we are promising NDIS that
            // we will complete the reset request by calling NdisMResetComplete.
            //
            Status = NDIS_STATUS_PENDING;
            break;
        }

        *AddressingReset = FALSE;
        MP_CLEAR_FLAG(Adapter, fMP_RESET_IN_PROGRESS);
        Status = NDIS_STATUS_SUCCESS;

    } while(FALSE);
    
    DEBUGP(MP_TRACE, ("<--- MPReset Status = 0x%08x\n", Status));
    
    return(Status);
}


VOID 
NICResetCompleteTimerDpc(
    IN PVOID             SystemSpecific1,
    IN PVOID             FunctionContext,
    IN PVOID             SystemSpecific2,
    IN PVOID             SystemSpecific3)
/*++

Routine Description:

    Timer callback function for Reset operation. 
        
Arguments:

FunctionContext - Pointer to our adapter

Return Value:

    VOID

--*/
{
    PMP_ADAPTER Adapter = (PMP_ADAPTER)FunctionContext;
    BOOLEAN bDone = TRUE;
    NDIS_STATUS Status = NDIS_STATUS_SUCCESS;

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

    //
    // Increment the ref count on the adapter to prevent the driver from
    // unloding while the DPC is running. The Halt handler waits for the
    // ref count to drop to zero before returning. 
    //
    MP_INC_REF(Adapter);            

    //
    // Check to see if all the packets indicated up are returned.
    //
    if(Adapter->nBusyRecv)
    {
        DEBUGP(MP_INFO, ("nBusyRecv = %d\n", Adapter->nBusyRecv));
        bDone = FALSE;
    }

    //
    // Are there any send packets in the processes of being 
    // transmitted?
    //
    if(Adapter->nBusySend)
    {
        DEBUGP(MP_INFO, ("nBusySend = %d\n", Adapter->nBusySend));
        bDone = FALSE;
    }

    if(!bDone && ++Adapter->nResetTimerCount <= 20)
    {
        //
        // Let us try one more time.
        //
        NdisSetTimer(&Adapter->ResetTimer, 500);
    }
    else
    {
        if(!bDone)
        {
        
            //
            // We have tried enough. Something is wrong. Let us
            // just complete the reset request with failure.
            //
            DEBUGP(MP_ERROR, ("Reset timed out!!!\n"));
            DEBUGP(MP_ERROR, ("nBusySend = %d\n", Adapter->nBusySend));
            DEBUGP(MP_ERROR, ("RecvWaitList = %p\n", &Adapter->RecvWaitList));
            DEBUGP(MP_ERROR, ("nBusyRecv = %d\n", Adapter->nBusyRecv));
            
            ASSERT(FALSE);       

            Status = NDIS_STATUS_FAILURE;
        }

        DEBUGP(MP_INFO, ("Done - NdisMResetComplete\n"));

        MP_CLEAR_FLAG(Adapter, fMP_RESET_IN_PROGRESS);
        NdisMResetComplete(
            Adapter->AdapterHandle,
            Status,
            FALSE);
        
    }

    MP_DEC_REF(Adapter);     

    DEBUGP(MP_TRACE, ("<-- NICResetCompleteTimerDpc Status = 0x%08x\n", 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_TRACE, ("--> MPUnload\n"));

    ASSERT(IsListEmpty(&GlobalData.AdapterList));
    NdisFreeSpinLock(&GlobalData.Lock);
    
    DEBUGP(MP_TRACE, ("<--- 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: 

⌨️ 快捷键说明

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