Author: ion
Date: Thu Aug 24 09:36:50 2006
New Revision: 23678
URL: 
http://svn.reactos.org/svn/reactos?rev=23678&view=rev
Log:
- 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.
Modified:
    trunk/reactos/hal/halx86/generic/halinit.c
    trunk/reactos/hal/halx86/generic/systimer.S
    trunk/reactos/hal/halx86/up/halinit_up.c
    trunk/reactos/ntoskrnl/ke/clock.c
    trunk/reactos/ntoskrnl/ke/i386/irq.c
    trunk/reactos/ntoskrnl/ke/i386/trap.s
Modified: trunk/reactos/hal/halx86/generic/halinit.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halx86/generic/halinit…
==============================================================================
--- trunk/reactos/hal/halx86/generic/halinit.c (original)
+++ trunk/reactos/hal/halx86/generic/halinit.c Thu Aug 24 09:36:50 2006
@@ -19,6 +19,7 @@
 PVOID HalpZeroPageMapping = NULL;
 HALP_HOOKS HalpHooks;
+VOID NTAPI HalpClockInterrupt(VOID);
 /* FUNCTIONS ***************************************************************/
@@ -31,6 +32,10 @@
        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 @@
     }
   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();
Modified: trunk/reactos/hal/halx86/generic/systimer.S
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halx86/generic/systime…
==============================================================================
--- trunk/reactos/hal/halx86/generic/systimer.S (original)
+++ trunk/reactos/hal/halx86/generic/systimer.S Thu Aug 24 09:36:50 2006
@@ -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
Modified: trunk/reactos/hal/halx86/up/halinit_up.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halx86/up/halinit_up.c…
==============================================================================
--- trunk/reactos/hal/halx86/up/halinit_up.c (original)
+++ trunk/reactos/hal/halx86/up/halinit_up.c Thu Aug 24 09:36:50 2006
@@ -15,8 +15,6 @@
 #define NDEBUG
 #include <debug.h>
-VOID NTAPI HalpClockInterrupt(VOID);
-
 /* FUNCTIONS ***************************************************************/
 VOID
@@ -24,15 +22,6 @@
 {
   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();
 }
Modified: trunk/reactos/ntoskrnl/ke/clock.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/clock.c?rev=23…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/clock.c (original)
+++ trunk/reactos/ntoskrnl/ke/clock.c Thu Aug 24 09:36:50 2006
@@ -37,7 +37,7 @@
 CHAR KiTimerSystemAuditing = 0;
 static KDPC KiExpireTimerDpc;
-static BOOLEAN KiClockSetupComplete = FALSE;
+BOOLEAN KiClockSetupComplete = FALSE;
 extern ULONG KiMaximumDpcQueueDepth;
 extern ULONG KiMinimumDpcRate;
Modified: trunk/reactos/ntoskrnl/ke/i386/irq.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/irq.c?rev…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/i386/irq.c (original)
+++ trunk/reactos/ntoskrnl/ke/i386/irq.c Thu Aug 24 09:36:50 2006
@@ -65,15 +65,10 @@
 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 @@
    HalEndSystemInterrupt (old_level, 0);
 }
+/* PRIVATE FUNCTIONS *********************************************************/
+
 VOID
 NTAPI
 KiGetVectorDispatch(IN ULONG Vector,
@@ -274,6 +271,8 @@
     ((PKIPCR)KeGetPcr())->IDT[Interrupt->Vector].Offset =
         (USHORT)PtrToUlong(Handler);
 }
+
+/* PUBLIC FUNCTIONS **********************************************************/
 /*
  * @implemented
@@ -430,65 +429,84 @@
 /*
  * @implemented
- *
- * FUNCTION: Releases a drivers isr
- * ARGUMENTS:
- *        InterruptObject = isr to release
  */
-BOOLEAN
+BOOLEAN
 STDCALL
-KeDisconnectInterrupt(PKINTERRUPT InterruptObject)
-{
-#if 0
-    KIRQL oldlvl,synch_oldlvl;
-    PISR_TABLE CurrentIsr;
+KeDisconnectInterrupt(PKINTERRUPT Interrupt)
+{
+    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);
-
-    /* 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);
+    KeSetSystemAffinityThread(1 << Interrupt->Number);
+
+    /* Lock the dispatcher */
+    OldIrql = KeAcquireDispatcherDatabaseLock();
     /* Check if it's actually connected */
-    if ((State = InterruptObject->Connected))
-    {
-        /* Lock the Interrupt */
-        synch_oldlvl = KeAcquireInterruptSpinLock(InterruptObject);
-
-        /* Remove this one, and check if all are gone */
-        RemoveEntryList(&InterruptObject->InterruptListEntry);
-        if (IsListEmpty(&CurrentIsr->ListHead))
-        {
-            /* Completely Disable the Interrupt */
-            HalDisableSystemInterrupt(InterruptObject->Vector,
InterruptObject->Irql);
-        }
-
+    State = Interrupt->Connected;
+    if (State)
+    {
+        /* Get the vector and IRQL */
+        Irql = Interrupt->Irql;
+        Vector = Interrupt->Vector;
+
+        /* Get vector dispatch data */
+        KiGetVectorDispatch(Vector, &Dispatch);
+
+        /* Check if it was chained */
+        if (Dispatch.Type == ChainConnect)
+        {
+            /* 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);
+
+                /* 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 */
-        InterruptObject->Connected = FALSE;
-
-        /* Release the interrupt lock */
-        KeReleaseInterruptSpinLock(InterruptObject, synch_oldlvl);
-    }
-    /* Release the table spinlock */
-    KiReleaseSpinLock(&CurrentIsr->Lock);
-    KeLowerIrql(oldlvl);
-
-    /* Go back to default affinity */
+        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 */
Modified: trunk/reactos/ntoskrnl/ke/i386/trap.s
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/trap.s?re…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/i386/trap.s (original)
+++ trunk/reactos/ntoskrnl/ke/i386/trap.s Thu Aug 24 09:36:50 2006
@@ -81,6 +81,9 @@
 _KiUnexpectedEntrySize:
     .long _KiUnexpectedInterrupt1 - _KiUnexpectedInterrupt0
+_UnexpectedMsg:
+    .asciz "\n\x7\x7!!! Unexpected Interrupt %02lx !!!\n"
+
 /* SOFTWARE INTERRUPT SERVICES ***********************************************/
 _KiGetTickCount:
@@ -1348,76 +1351,13 @@
     jmp _Kei386EoiHelper2ndEntry
 Handled:
-    /* Unexpected, exit the interrupt */
-    mov esi, $
-    cli
-    call _HalEndSystemInterrupt@8
-    jmp _Kei386EoiHelper@0
-.endfunc
-
-.globl _KiUnexpectedInterrupt
-_KiUnexpectedInterrupt:
-
-    /* Bugcheck with invalid interrupt code */
-    push 0x12
-    call _KeBugCheck@4
-
-/* INTERRUPT HANDLERS ********************************************************/
-
-.func KiInterruptTemplate
-_KiInterruptTemplate:
-
-    /* Enter interrupt trap */
-    INT_PROLOG kit, DoPushFakeErrorCode
-.endfunc
-
-_KiInterruptTemplate2ndDispatch:
-    /* Dummy code, will be replaced by the address of the KINTERRUPT */
-    mov edi, 0
-
-_KiInterruptTemplateObject:
-    /* Dummy jump, will be replaced by the actual jump */
-    jmp _KeSynchronizeExecution@12
-
-_KiInterruptTemplateDispatch:
-    /* Marks the end of the template so that the jump above can be edited */
-
-.func KiChainedDispatch2ndLvl@0
-_KiChainedDispatch2ndLvl@0:
-
-    /* Not yet supported */
-    int 3
-.endfunc
-
-.func KiChainedDispatch@0
-_KiChainedDispatch@0:
-
-    /* Increase interrupt count */
-    inc dword ptr [fs:KPCR_PRCB_INTERRUPT_COUNT]
-
-    /* Save trap frame */
-    mov ebp, esp
-
-    /* Save vector and IRQL */
-    mov eax, [edi+KINTERRUPT_VECTOR]
-    mov ecx, [edi+KINTERRUPT_IRQL]
-
-    /* Save old irql */
-    push eax
-    sub esp, 4
-
-    /* Begin interrupt */
-    push eax
-    push ecx
-    call _HalBeginSystemInterrupt@12
-
-    /* Check if it was handled */
-    or eax, eax
-    jz SpuriousInt
-    sub esp, 12
-
-    /* Call the 2nd-level handler */
-    call _KiChainedDispatch2ndLvl@0
+    /* 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, $
@@ -1426,6 +1366,77 @@
     jmp _Kei386EoiHelper@0
 .endfunc
+.globl _KiUnexpectedInterrupt
+_KiUnexpectedInterrupt:
+
+    /* Bugcheck with invalid interrupt code */
+    push 0x12
+    call _KeBugCheck@4
+
+/* INTERRUPT HANDLERS ********************************************************/
+
+.func KiInterruptTemplate
+_KiInterruptTemplate:
+
+    /* Enter interrupt trap */
+    INT_PROLOG kit, DoPushFakeErrorCode
+.endfunc
+
+_KiInterruptTemplate2ndDispatch:
+    /* Dummy code, will be replaced by the address of the KINTERRUPT */
+    mov edi, 0
+
+_KiInterruptTemplateObject:
+    /* Dummy jump, will be replaced by the actual jump */
+    jmp _KeSynchronizeExecution@12
+
+_KiInterruptTemplateDispatch:
+    /* Marks the end of the template so that the jump above can be edited */
+
+.func KiChainedDispatch2ndLvl@0
+_KiChainedDispatch2ndLvl@0:
+
+    /* Not yet supported */
+    int 3
+.endfunc
+
+.func KiChainedDispatch@0
+_KiChainedDispatch@0:
+
+    /* Increase interrupt count */
+    inc dword ptr [fs:KPCR_PRCB_INTERRUPT_COUNT]
+
+    /* Save trap frame */
+    mov ebp, esp
+
+    /* Save vector and IRQL */
+    mov eax, [edi+KINTERRUPT_VECTOR]
+    mov ecx, [edi+KINTERRUPT_IRQL]
+
+    /* Save old irql */
+    push eax
+    sub esp, 4
+
+    /* Begin interrupt */
+    push eax
+    push ecx
+    call _HalBeginSystemInterrupt@12
+
+    /* Check if it was handled */
+    or eax, eax
+    jz SpuriousInt
+    sub esp, 12
+
+    /* Call the 2nd-level handler */
+    call _KiChainedDispatch2ndLvl@0
+
+    /* Exit the interrupt */
+    mov esi, $
+    cli
+    call _HalEndSystemInterrupt@8
+    jmp _Kei386EoiHelper@0
+.endfunc
+
 .func KiInterruptDispatch3@0
 _KiInterruptDispatch3@0: