From 8b82c0d6413fa7a2f0be0d6c4bfbcfcd4d6a80ee Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Thu, 24 Aug 2006 05:36:50 +0000 Subject: [PATCH] - Write a basic Clock Interrupt handler in the HAL (doesn't deal with changing increments yet, just like current ROS). It will call KeUpdateSystemTime once ready. - Implement KeDisconnectInterrupt with the new implementation. - Put Clock Interrupt initialization in the right place (might still be too late: must investigate more). - Added a debug print when unexpected interrupts are called, just noticed this happens on my checked machine, and it's a useful tracing tool. svn path=/trunk/; revision=23678 --- reactos/hal/halx86/generic/halinit.c | 13 +++ reactos/hal/halx86/generic/systimer.S | 30 ++++++- reactos/hal/halx86/up/halinit_up.c | 11 --- reactos/ntoskrnl/ke/clock.c | 2 +- reactos/ntoskrnl/ke/i386/irq.c | 118 +++++++++++++++----------- reactos/ntoskrnl/ke/i386/trap.s | 13 ++- 6 files changed, 121 insertions(+), 66 deletions(-) diff --git a/reactos/hal/halx86/generic/halinit.c b/reactos/hal/halx86/generic/halinit.c index 8abdda47fd9..60af79fc294 100644 --- a/reactos/hal/halx86/generic/halinit.c +++ b/reactos/hal/halx86/generic/halinit.c @@ -19,6 +19,7 @@ PVOID HalpZeroPageMapping = NULL; HALP_HOOKS HalpHooks; +VOID NTAPI HalpClockInterrupt(VOID); /* FUNCTIONS ***************************************************************/ @@ -31,6 +32,10 @@ DriverEntry( return STATUS_SUCCESS; } +#define MAKEULONG(x, y) \ + (((((ULONG)(x))<<16) & 0xffff0000) | \ + ((ULONG)(y) & 0xffff)) + BOOLEAN STDCALL HalInitSystem (ULONG BootPhase, PLOADER_PARAMETER_BLOCK LoaderBlock) @@ -42,6 +47,14 @@ HalInitSystem (ULONG BootPhase, } else if (BootPhase == 1) { +#if 0 + /* Enable the clock interrupt */ + ((PKIPCR)KeGetPcr())->IDT[IRQ2VECTOR(0)].ExtendedOffset = + (USHORT)(((ULONG_PTR)HalpClockInterrupt >> 16) & 0xFFFF); + ((PKIPCR)KeGetPcr())->IDT[IRQ2VECTOR(0)].Offset = + (USHORT)HalpClockInterrupt; + HalEnableSystemInterrupt(IRQ2VECTOR(0), CLOCK2_LEVEL, Latched); +#endif /* Initialize display and make the screen black */ HalInitializeDisplay ((PROS_LOADER_PARAMETER_BLOCK)LoaderBlock); HalpInitBusHandlers(); diff --git a/reactos/hal/halx86/generic/systimer.S b/reactos/hal/halx86/generic/systimer.S index 019f909f8df..f2dfebbfd27 100644 --- a/reactos/hal/halx86/generic/systimer.S +++ b/reactos/hal/halx86/generic/systimer.S @@ -12,8 +12,7 @@ .intel_syntax noprefix .extern _Kei386EoiHelper@0 - -/* GLOBALS *******************************************************************/ +.extern _KeUpdateSystemTime@0 /* FUNCTIONS *****************************************************************/ @@ -21,6 +20,31 @@ .func HalpClockInterrupt@0 _HalpClockInterrupt@0: - jmp $ + /* Enter trap */ + INT_PROLOG Hci, DoPushFakeErrorCode + + /* Push vector and make stack for IRQL */ + push 0x30 + sub esp, 4 + + /* Begin the interrupt */ + push esp + push 0x30 + push CLOCK2_LEVEL + call _HalBeginSystemInterrupt@12 + + /* Check if it's spurious */ + or al, al + jz Spurious + + /* Do a tick */ + //jmp _KeUpdateSystemTime@0 + +Spurious: + + /* Exit the interrupt */ + add esp, 8 + mov esi, $ + jmp _Kei386EoiHelper@0 .endfunc diff --git a/reactos/hal/halx86/up/halinit_up.c b/reactos/hal/halx86/up/halinit_up.c index 1709cf00d2e..8b4824abf32 100644 --- a/reactos/hal/halx86/up/halinit_up.c +++ b/reactos/hal/halx86/up/halinit_up.c @@ -15,8 +15,6 @@ #define NDEBUG #include -VOID NTAPI HalpClockInterrupt(VOID); - /* FUNCTIONS ***************************************************************/ VOID @@ -24,15 +22,6 @@ HalpInitPhase0(PROS_LOADER_PARAMETER_BLOCK LoaderBlock) { HalpInitPICs(); - /* Enable the clock interrupt */ -#if 0 - ((PKIPCR)KeGetPcr())->IDT[IRQ2VECTOR(0)].ExtendedOffset = - (USHORT)(((ULONG_PTR)HalpClockInterrupt >> 16) & 0xFFFF); - ((PKIPCR)KeGetPcr())->IDT[IRQ2VECTOR(0)].Offset = - (USHORT)HalpClockInterrupt; -#endif - HalEnableSystemInterrupt(IRQ2VECTOR(0), CLOCK2_LEVEL, Latched); - /* Setup busy waiting */ HalpCalibrateStallExecution(); } diff --git a/reactos/ntoskrnl/ke/clock.c b/reactos/ntoskrnl/ke/clock.c index 3fea5e0c2f6..13628814be3 100644 --- a/reactos/ntoskrnl/ke/clock.c +++ b/reactos/ntoskrnl/ke/clock.c @@ -37,7 +37,7 @@ LARGE_INTEGER SystemBootTime = { 0 }; CHAR KiTimerSystemAuditing = 0; static KDPC KiExpireTimerDpc; -static BOOLEAN KiClockSetupComplete = FALSE; +BOOLEAN KiClockSetupComplete = FALSE; extern ULONG KiMaximumDpcQueueDepth; extern ULONG KiMinimumDpcRate; diff --git a/reactos/ntoskrnl/ke/i386/irq.c b/reactos/ntoskrnl/ke/i386/irq.c index 5924d7c1fe0..b75cc3a1720 100644 --- a/reactos/ntoskrnl/ke/i386/irq.c +++ b/reactos/ntoskrnl/ke/i386/irq.c @@ -65,15 +65,10 @@ VOID NTAPI KiChainedDispatch(VOID); - -/* GLOBALS *****************************************************************/ +/* DEPRECATED FUNCTIONS ******************************************************/ void irq_handler_0(void); - extern IDT_DESCRIPTOR KiIdt[256]; - -/* FUNCTIONS ****************************************************************/ - #define PRESENT (0x8000) #define I486_INTERRUPT_GATE (0xe00) @@ -168,6 +163,8 @@ KiInterruptDispatch (ULONG vector, PKIRQ_TRAPFRAME Trapframe) HalEndSystemInterrupt (old_level, 0); } +/* PRIVATE FUNCTIONS *********************************************************/ + VOID NTAPI KiGetVectorDispatch(IN ULONG Vector, @@ -275,6 +272,8 @@ KiConnectVectorToInterrupt(IN PKINTERRUPT Interrupt, (USHORT)PtrToUlong(Handler); } +/* PUBLIC FUNCTIONS **********************************************************/ + /* * @implemented */ @@ -430,65 +429,84 @@ KeConnectInterrupt(IN PKINTERRUPT Interrupt) /* * @implemented - * - * FUNCTION: Releases a drivers isr - * ARGUMENTS: - * InterruptObject = isr to release */ -BOOLEAN +BOOLEAN STDCALL -KeDisconnectInterrupt(PKINTERRUPT InterruptObject) +KeDisconnectInterrupt(PKINTERRUPT Interrupt) { -#if 0 - KIRQL oldlvl,synch_oldlvl; - PISR_TABLE CurrentIsr; + KIRQL OldIrql, Irql; + ULONG Vector; + DISPATCH_INFO Dispatch; + PKINTERRUPT NextInterrupt; BOOLEAN State; - DPRINT1("KeDisconnectInterrupt\n"); - ASSERT (InterruptObject->Number < KeNumberProcessors); - /* Set the affinity */ - KeSetSystemAffinityThread(1 << InterruptObject->Number); + KeSetSystemAffinityThread(1 << Interrupt->Number); - /* Get the ISR Tabe */ - CurrentIsr = &IsrTable[InterruptObject->Vector - IRQ_BASE] - [(ULONG)InterruptObject->Number]; - - /* Raise IRQL to required level and lock table */ - KeRaiseIrql(VECTOR2IRQL(InterruptObject->Vector),&oldlvl); - KiAcquireSpinLock(&CurrentIsr->Lock); + /* Lock the dispatcher */ + OldIrql = KeAcquireDispatcherDatabaseLock(); /* Check if it's actually connected */ - if ((State = InterruptObject->Connected)) + State = Interrupt->Connected; + if (State) { - /* Lock the Interrupt */ - synch_oldlvl = KeAcquireInterruptSpinLock(InterruptObject); + /* Get the vector and IRQL */ + Irql = Interrupt->Irql; + Vector = Interrupt->Vector; - /* Remove this one, and check if all are gone */ - RemoveEntryList(&InterruptObject->InterruptListEntry); - if (IsListEmpty(&CurrentIsr->ListHead)) + /* Get vector dispatch data */ + KiGetVectorDispatch(Vector, &Dispatch); + + /* Check if it was chained */ + if (Dispatch.Type == ChainConnect) { - /* Completely Disable the Interrupt */ - HalDisableSystemInterrupt(InterruptObject->Vector, InterruptObject->Irql); - } - - /* Disconnect it */ - InterruptObject->Connected = FALSE; - - /* Release the interrupt lock */ - KeReleaseInterruptSpinLock(InterruptObject, synch_oldlvl); - } - /* Release the table spinlock */ - KiReleaseSpinLock(&CurrentIsr->Lock); - KeLowerIrql(oldlvl); + /* Check if the top-level interrupt is being removed */ + ASSERT(Irql <= SYNCH_LEVEL); + if (Interrupt == Dispatch.Interrupt) + { + /* Get the next one */ + Dispatch.Interrupt = CONTAINING_RECORD(Dispatch.Interrupt-> + InterruptListEntry.Flink, + KINTERRUPT, + InterruptListEntry); - /* Go back to default affinity */ + /* Reconnect it */ + KiConnectVectorToInterrupt(Dispatch.Interrupt, ChainConnect); + } + + /* Remove it */ + RemoveEntryList(&Interrupt->InterruptListEntry); + + /* Get the next one */ + NextInterrupt = CONTAINING_RECORD(Dispatch.Interrupt-> + InterruptListEntry.Flink, + KINTERRUPT, + InterruptListEntry); + + /* Check if this is the only one left */ + if (Dispatch.Interrupt == NextInterrupt) + { + /* Connect it in non-chained mode */ + KiConnectVectorToInterrupt(Dispatch.Interrupt, NormalConnect); + } + } + else + { + /* Only one left, disable and remove it */ + HalDisableSystemInterrupt(Interrupt->Vector, Irql); + KiConnectVectorToInterrupt(Interrupt, NoConnect); + } + + /* Disconnect it */ + Interrupt->Connected = FALSE; + } + + /* Unlock the dispatcher and revert affinity */ + KeReleaseDispatcherDatabaseLock(OldIrql); KeRevertToUserAffinityThread(); - - /* Return Old Interrupt State */ + + /* Return to caller */ return State; -#endif - return 0; } /* EOF */ diff --git a/reactos/ntoskrnl/ke/i386/trap.s b/reactos/ntoskrnl/ke/i386/trap.s index 662cc3bd520..8be13bffd47 100644 --- a/reactos/ntoskrnl/ke/i386/trap.s +++ b/reactos/ntoskrnl/ke/i386/trap.s @@ -81,6 +81,9 @@ _KiIdtDescriptor: _KiUnexpectedEntrySize: .long _KiUnexpectedInterrupt1 - _KiUnexpectedInterrupt0 +_UnexpectedMsg: + .asciz "\n\x7\x7!!! Unexpected Interrupt %02lx !!!\n" + /* SOFTWARE INTERRUPT SERVICES ***********************************************/ _KiGetTickCount: @@ -1348,7 +1351,15 @@ _KiUnexpectedInterruptTail: jmp _Kei386EoiHelper2ndEntry Handled: - /* Unexpected, exit the interrupt */ + /* Unexpected interrupt, print a message on debug builds */ +#if DBG + push [esp+4] + push offset _UnexpectedMsg + call _DbgPrint + add esp, 8 +#endif + + /* Exit the interrupt */ mov esi, $ cli call _HalEndSystemInterrupt@8