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

📄 isrdpc.c

📁 plx9054的WDM驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/*++

Copyright (c) Microsoft Corporation.  All rights reserved.

    THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY      
    KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
    IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
    PURPOSE.

Module Name:

    ISRDPC.C

Abstract:

    Contains routine to handle interrupts, interrupt DPCs and WatchDogTimer DPC

Environment:

    Kernel mode


Revision History:

    Eliyas Yakub Feb 13, 2003

--*/

#include "precomp.h"

#if defined(EVENT_TRACING)
#include "ISRDPC.tmh"
#endif

BOOLEAN 
NICInterruptHandler(
    IN PKINTERRUPT  Interupt, 
    IN PVOID        ServiceContext
    )
/*++
Routine Description:

    Interrupt handler for the device.

Arguments:

    Interupt - Address of the KINTERRUPT Object for our device.
    ServiceContext - Pointer to our adapter

Return Value:

     TRUE if our device is interrupting, FALSE otherwise.                                                    

--*/    
{
    BOOLEAN     InterruptRecognized = FALSE;
    PFDO_DATA   FdoData = (PFDO_DATA)ServiceContext;
    USHORT      IntStatus;

    DebugPrint(TRACE, DBG_INTERRUPT, "--> NICInterruptHandler\n");
    
    do 
    {
        //
        // If the adapter is in low power state, then it should not 
        // recognize any interrupt
        // 
        if (FdoData->DevicePowerState > PowerDeviceD0)
        {
            break;
        }
        //
        // We process the interrupt if it's not disabled and it's active                  
        //
        if (!NIC_INTERRUPT_DISABLED(FdoData) && NIC_INTERRUPT_ACTIVE(FdoData))
        {
            InterruptRecognized = TRUE;
        
            //
            // Disable the interrupt (will be re-enabled in NICDpcForIsr
            //
            NICDisableInterrupt(FdoData);
                
            //
            // Acknowledge the interrupt(s) and get the interrupt status
            //

            NIC_ACK_INTERRUPT(FdoData, IntStatus);

            DebugPrint(TRACE, DBG_INTERRUPT, "Requesting DPC\n");

            IoRequestDpc(FdoData->Self, NULL, FdoData);
            
        }
    }while (FALSE);    

    DebugPrint(TRACE, DBG_INTERRUPT, "<-- NICInterruptHandler\n");

    return InterruptRecognized;
}

VOID 
NICDpcForIsr(
    IN PKDPC            Dpc,
    IN PDEVICE_OBJECT   DeviceObject,
    IN PIRP             Irp, //Unused
    IN PVOID            Context
    )

/*++

Routine Description:

    DPC callback for ISR. 

Arguments:

    DeviceObject - Pointer to the device object.

    Context - MiniportAdapterContext.

    Irp - Unused.

    Context - Pointer to FDO_DATA.

Return Value:

--*/
{
    PFDO_DATA fdoData = (PFDO_DATA) Context;

    DebugPrint(TRACE, DBG_DPC, "--> NICDpcForIsr\n");

    KeAcquireSpinLockAtDpcLevel(&fdoData->RcvLock);

    NICHandleRecvInterrupt(fdoData);

    KeReleaseSpinLockFromDpcLevel(&fdoData->RcvLock);

    //
    // Handle send interrupt    
    //
    KeAcquireSpinLockAtDpcLevel(&fdoData->SendLock);

    (VOID)NICHandleSendInterrupt(fdoData);

    KeReleaseSpinLockFromDpcLevel(&fdoData->SendLock);

    //
    // Start the receive unit if it had stopped
    //
    KeAcquireSpinLockAtDpcLevel(&fdoData->RcvLock);

    (VOID)NICStartRecv(fdoData);

    KeReleaseSpinLockFromDpcLevel(&fdoData->RcvLock);
    
    //
    // Re-enable the interrupt (disabled in MPIsr)
    //
    KeSynchronizeExecution(
        fdoData->Interrupt,
        (PKSYNCHRONIZE_ROUTINE)NICEnableInterrupt,
        fdoData);

    DebugPrint(TRACE, DBG_DPC, "<-- NICDpcForIsr\n");

}


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

Routine Description:
    
    This DPC is used to do both link detection during hardware init and
    after that for hardware hang detection.
    
Arguments:

    SystemSpecific1     Not used
    FunctionContext     Pointer to our FdoData
    SystemSpecific2     Not used
    SystemSpecific3     Not used

Return Value:

    None
    
--*/
{
    PFDO_DATA           FdoData = (PFDO_DATA)FunctionContext;
    LARGE_INTEGER       DueTime;
    NTSTATUS            status = STATUS_SUCCESS;
    
    UNREFERENCED_PARAMETER(SystemSpecific1);
    UNREFERENCED_PARAMETER(SystemSpecific2);
    UNREFERENCED_PARAMETER(SystemSpecific3);

    DueTime.QuadPart = NIC_CHECK_FOR_HANG_DELAY;

    PciDrvIoIncrement(FdoData);

    if(MP_TEST_FLAG(FdoData, fMP_ADAPTER_HALT_IN_PROGRESS)){
        status = STATUS_DEVICE_REMOVED;
        goto Exit;
    }

    //
    // If the device has been power down, we will return without
    // touching the hardware. The timer will be restarted when
    // the device powers up.
    //
    if(FdoData->DevicePowerState == PowerDeviceD0)
    {
        if(!FdoData->CheckForHang){
            //
            // We are still doing link detection
            //            
            status = NICLinkDetection(FdoData);
            if(status == STATUS_PENDING) {
                // Wait for 100 ms   
                FdoData->bLinkDetectionWait = TRUE;
                DueTime.QuadPart = NIC_LINK_DETECTION_DELAY;
            }else {
                FdoData->CheckForHang = TRUE;
            }        
        }else {
            //
            // Link detection is over, let us check to see
            // if the hardware is hung.
            //
            if(NICCheckForHang(FdoData)){
                
                status = NICReset(FdoData);
                if(!NT_SUCCESS(status)){                    
                    goto Exit;
                }
            }
        }

        KeSetTimer( &FdoData->WatchDogTimer,   // Timer
                            DueTime,         // DueTime
                            &FdoData->WatchDogTimerDpc      // Dpc  
                            );           
     } else{
        goto Exit;
     }

     
     PciDrvIoDecrement(FdoData);
     return;
    
Exit:
    PciDrvIoDecrement(FdoData);  
    KeSetEvent(&FdoData->WatchDogTimerEvent, IO_NO_INCREMENT, FALSE);    
    DebugPrint(INFO, DBG_DPC, "WatchDogTimer is exiting %x\n", status);    
    return;
    
}


BOOLEAN 
NICCheckForHang(
    IN  PFDO_DATA     FdoData
    )
/*++

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

    FdoData  Pointer to our adapter

Return Value:

    TRUE    This NIC needs a reset
    FALSE   Everything is fine

--*/
{
    PMP_TCB             pMpTcb;
    
    //
    // Just skip this part if the adapter is doing link detection
    //
    if (MP_TEST_FLAG(FdoData, fMP_ADAPTER_LINK_DETECTION))
    {
        return(FALSE);   
    }

    //
    // any nonrecoverable hardware error?
    //
    if (MP_TEST_FLAG(FdoData, fMP_ADAPTER_NON_RECOVER_ERROR))
    {
        DebugPrint(WARNING, DBG_DPC, "Non recoverable error - remove\n");
        return (TRUE);
    }
            
    //
    // hardware failure?
    //
    if (MP_TEST_FLAG(FdoData, fMP_ADAPTER_HARDWARE_ERROR))
    {
        DebugPrint(WARNING, DBG_DPC, "hardware error - reset\n");
        return(TRUE);
    }
          
    //
    // Is send stuck?                  
    //
    
    KeAcquireSpinLockAtDpcLevel(&FdoData->SendLock);

    if (FdoData->nBusySend > 0)
    {
        pMpTcb = FdoData->CurrSendHead;
        pMpTcb->Count++;
        if (pMpTcb->Count > NIC_SEND_HANG_THRESHOLD)
        {
            KeReleaseSpinLockFromDpcLevel(&FdoData->SendLock);
            DebugPrint(WARNING, DBG_DPC, "Send is stuck - reset\n");
            return(TRUE);
        }
    }
    
    KeReleaseSpinLockFromDpcLevel(&FdoData->SendLock);

    KeAcquireSpinLockAtDpcLevel(&FdoData->RcvLock);

    //
    // Update the RFD shrink count                                          
    //
    if (FdoData->CurrNumRfd > FdoData->NumRfd)
    {
        FdoData->RfdShrinkCount++;          
    }

    KeReleaseSpinLockFromDpcLevel(&FdoData->RcvLock);

    NICIndicateMediaState(FdoData);
    
    return(FALSE);
}

NTSTATUS 
NICReset(
    IN PFDO_DATA FdoData
    )
/*++

Routine Description:
    
    Function to reset the device.
    
Arguments:

    FdoData  Pointer to our adapter


Return Value:

    NT Status code.
    
Note:
    NICReset is called at DPC. Take advantage of this fact 
    when acquiring or releasing spinlocks
    
--*/

⌨️ 快捷键说明

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