From 3d6e5848c1eb3433e91382bbeef81053bd42e973 Mon Sep 17 00:00:00 2001 From: Sir Richard Date: Fri, 29 Jan 2010 01:37:25 +0000 Subject: [PATCH] [NTOS]: Implement chained interrupt dispatch. For level interrupts, the first interrupt handler should process the interrupt and no other handlers are called. Edge interrupts are another matter, but since they aren't yet supported, I haven't implemented that code path (it wasn't implemented previously). I seriously hope we don't have edge/chained interrupts because the HAL/NTOS could never handle this! svn path=/trunk/; revision=45310 --- reactos/ntoskrnl/ke/i386/irqobj.c | 74 +++++++++++++++++++++++++++++-- 1 file changed, 71 insertions(+), 3 deletions(-) diff --git a/reactos/ntoskrnl/ke/i386/irqobj.c b/reactos/ntoskrnl/ke/i386/irqobj.c index b58b1dac951..05dc85bc2cc 100644 --- a/reactos/ntoskrnl/ke/i386/irqobj.c +++ b/reactos/ntoskrnl/ke/i386/irqobj.c @@ -233,11 +233,79 @@ FASTCALL KiChainedDispatch(IN PKTRAP_FRAME TrapFrame, IN PKINTERRUPT Interrupt) { + KIRQL OldIrql; + BOOLEAN Handled; + PLIST_ENTRY NextEntry, ListHead; + /* Increase interrupt count */ KeGetCurrentPrcb()->InterruptCount++; - UNIMPLEMENTED; - while (TRUE); -} + + /* 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 */ + OldIrql = KfRaiseIrql(Interrupt->Irql); + } + + /* 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 */ + KfLowerIrql(OldIrql); + } + + /* Check if the interrupt got handled */ + if (Handled) + { + /* Edge shared interrupts are not handled (they never were) */ + ASSERT(Interrupt->Mode == LevelSensitive); + break; + } + else + { + /* This code path was never tested, and shouldn't be reached */ + DPRINT1("Edge shared interrupt. ReactOS cannot handle these\n"); + + /* What's next? */ + NextEntry = NextEntry->Flink; + + /* Is this the last one? */ + if (NextEntry == ListHead) break; + + /* Get the actual interrupt object */ + 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); + } + } VOID FASTCALL -- 2.17.1