VOID FASTCALL KiInterruptDispatch(IN PKTRAP_FRAME TrapFrame, IN PKINTERRUPT Interrupt) { KIRQL OldIrql; /* Increase interrupt count */ KeGetCurrentPrcb()->InterruptCount++; /* Begin the interrupt, making sure it's not spurious */ if (HalBeginSystemInterrupt(Interrupt->SynchronizeIrql, Interrupt->Vector, &OldIrql)) { /* Acquire interrupt lock */ KxAcquireSpinLock(Interrupt->ActualLock); /* Call the ISR */ Interrupt->ServiceRoutine(Interrupt, Interrupt->ServiceContext); /* Release interrupt lock */ KxReleaseSpinLock(Interrupt->ActualLock); /* Now call the epilogue code */ KiExitInterrupt(TrapFrame, OldIrql, FALSE); } else { /* Now call the epilogue code */ KiExitInterrupt(TrapFrame, OldIrql, TRUE); } }
VOID FASTCALL KiUnexpectedInterruptTailHandler(IN PKTRAP_FRAME TrapFrame) { KIRQL OldIrql; /* Enter trap */ KiEnterInterruptTrap(TrapFrame); /* Increase interrupt count */ KeGetCurrentPrcb()->InterruptCount++; /* Start the interrupt */ if (HalBeginSystemInterrupt(HIGH_LEVEL, TrapFrame->ErrCode, &OldIrql)) { /* Warn user */ DPRINT1("\n\x7\x7!!! Unexpected Interrupt 0x%02lx !!!\n", TrapFrame->ErrCode); /* Now call the epilogue code */ KiExitInterrupt(TrapFrame, OldIrql, FALSE); } else { /* Now call the epilogue code */ KiExitInterrupt(TrapFrame, OldIrql, TRUE); } }
VOID DECLSPEC_NORETURN FASTCALL HalpApcInterruptHandler(IN PKTRAP_FRAME TrapFrame) { KPROCESSOR_MODE ProcessorMode; KIRQL OldIrql; ASSERT(ApicGetProcessorIrql() == APC_LEVEL); /* Enter trap */ KiEnterInterruptTrap(TrapFrame); #ifdef APIC_LAZY_IRQL if (!HalBeginSystemInterrupt(APC_LEVEL, APC_VECTOR, &OldIrql)) { /* "Spurious" interrupt, exit the interrupt */ KiEoiHelper(TrapFrame); } #else /* Save the old IRQL */ OldIrql = ApicGetCurrentIrql(); ASSERT(OldIrql < APC_LEVEL); #endif /* Raise to APC_LEVEL */ ApicRaiseIrql(APC_LEVEL); /* End the interrupt */ ApicSendEOI(); /* Kernel or user APC? */ if (KiUserTrap(TrapFrame)) ProcessorMode = UserMode; else if (TrapFrame->EFlags & EFLAGS_V86_MASK) ProcessorMode = UserMode; else ProcessorMode = KernelMode; /* Enable interrupts and call the kernel's APC interrupt handler */ _enable(); KiDeliverApc(ProcessorMode, NULL, TrapFrame); /* Disable interrupts */ _disable(); /* Restore the old IRQL */ ApicLowerIrql(OldIrql); /* Exit the interrupt */ KiEoiHelper(TrapFrame); }
VOID DECLSPEC_NORETURN FASTCALL HalpDispatchInterruptHandler(IN PKTRAP_FRAME TrapFrame) { KIRQL OldIrql; ASSERT(ApicGetProcessorIrql() == DISPATCH_LEVEL); /* Enter trap */ KiEnterInterruptTrap(TrapFrame); #ifdef APIC_LAZY_IRQL if (!HalBeginSystemInterrupt(DISPATCH_LEVEL, DISPATCH_VECTOR, &OldIrql)) { /* "Spurious" interrupt, exit the interrupt */ KiEoiHelper(TrapFrame); } #else /* Get the current IRQL */ OldIrql = ApicGetCurrentIrql(); ASSERT(OldIrql < DISPATCH_LEVEL); #endif /* Raise to DISPATCH_LEVEL */ ApicRaiseIrql(DISPATCH_LEVEL); /* End the interrupt */ ApicSendEOI(); /* Enable interrupts and call the kernel's DPC interrupt handler */ _enable(); KiDispatchInterrupt(); _disable(); /* Restore the old IRQL */ ApicLowerIrql(OldIrql); /* Exit the interrupt */ KiEoiHelper(TrapFrame); }
VOID FASTCALL KiChainedDispatch(IN PKTRAP_FRAME TrapFrame, IN PKINTERRUPT Interrupt) { KIRQL OldIrql, OldInterruptIrql = 0; BOOLEAN Handled; PLIST_ENTRY NextEntry, ListHead; /* Increase interrupt count */ KeGetCurrentPrcb()->InterruptCount++; /* Begin the interrupt, making sure it's not spurious */ if (HalBeginSystemInterrupt(Interrupt->Irql, Interrupt->Vector, &OldIrql)) { /* Get list pointers */ ListHead = &Interrupt->InterruptListEntry; NextEntry = ListHead; /* The head is an entry! */ while (TRUE) { /* Check if this interrupt's IRQL is higher than the current one */ if (Interrupt->SynchronizeIrql > Interrupt->Irql) { /* Raise to higher IRQL */ OldInterruptIrql = KfRaiseIrql(Interrupt->SynchronizeIrql); } /* Acquire interrupt lock */ KxAcquireSpinLock(Interrupt->ActualLock); /* Call the ISR */ Handled = Interrupt->ServiceRoutine(Interrupt, Interrupt->ServiceContext); /* Release interrupt lock */ KxReleaseSpinLock(Interrupt->ActualLock); /* Check if this interrupt's IRQL is higher than the current one */ if (Interrupt->SynchronizeIrql > Interrupt->Irql) { /* Lower the IRQL back */ ASSERT(OldInterruptIrql == Interrupt->Irql); KfLowerIrql(OldInterruptIrql); } /* Check if the interrupt got handled and it's level */ if ((Handled) && (Interrupt->Mode == LevelSensitive)) break; /* What's next? */ NextEntry = NextEntry->Flink; /* Is this the last one? */ if (NextEntry == ListHead) { /* Level should not have gotten here */ if (Interrupt->Mode == LevelSensitive) break; /* As for edge, we can only exit once nobody can handle the interrupt */ if (!Handled) break; } /* Get the interrupt object for the next pass */ Interrupt = CONTAINING_RECORD(NextEntry, KINTERRUPT, InterruptListEntry); } /* Now call the epilogue code */ KiExitInterrupt(TrapFrame, OldIrql, FALSE); } else { /* Now call the epilogue code */ KiExitInterrupt(TrapFrame, OldIrql, TRUE); } }