?? isrdpc.c
字號:
/*++
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 + -