Author: arty
Date: Sun Dec  3 14:25:56 2006
New Revision: 25030
URL: 
http://svn.reactos.org/svn/reactos?rev=25030&view=rev
Log:
After a clean, these seem to be needed.  Probably due to my patchy import.
Added:
    branches/arty-stable/reactos/ntoskrnl/deprecated/
    branches/arty-stable/reactos/ntoskrnl/deprecated/irq.c
    branches/arty-stable/reactos/ntoskrnl/deprecated/irqhand.S
Added: branches/arty-stable/reactos/ntoskrnl/deprecated/irq.c
URL:
http://svn.reactos.org/svn/reactos/branches/arty-stable/reactos/ntoskrnl/de…
==============================================================================
--- branches/arty-stable/reactos/ntoskrnl/deprecated/irq.c (added)
+++ branches/arty-stable/reactos/ntoskrnl/deprecated/irq.c Sun Dec  3 14:25:56 2006
@@ -1,0 +1,779 @@
+/* $Id$
+ *
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS kernel
+ * FILE:            ntoskrnl/ke/i386/irq.c
+ * PURPOSE:         IRQ handling
+ *
+ * PROGRAMMERS:     David Welch (welch(a)mcmail.com)
+ */
+
+/*
+ * NOTE: In general the PIC interrupt priority facilities are used to
+ * preserve the NT IRQL semantics, global interrupt disables are only used
+ * to keep the PIC in a consistent state
+ *
+ */
+
+/* INCLUDES ****************************************************************/
+
+#include <ntoskrnl.h>
+#include <../hal/halx86/include/halirq.h>
+#include <../hal/halx86/include/mps.h>
+
+#define NDEBUG
+#include <internal/debug.h>
+
+extern KDPC KiExpireTimerDpc;
+extern ULONG KiMaximumDpcQueueDepth;
+extern ULONG KiMinimumDpcRate;
+extern ULONG KiAdjustDpcThreshold;
+extern ULONG KiIdealDpcRate;
+extern LONG KiTickOffset;
+extern ULONG KeMaximumIncrement;
+extern ULONG KeMinimumIncrement;
+extern ULONG KeTimeAdjustment;
+extern BOOLEAN KiClockSetupComplete;
+
+/* GLOBALS *****************************************************************/
+
+/* Interrupt handler list */
+
+#ifdef CONFIG_SMP
+
+#define INT_NAME2(intnum) KiUnexpectedInterrupt##intnum
+
+#define BUILD_INTERRUPT_HANDLER(intnum) \
+VOID INT_NAME2(intnum)(VOID);
+
+#define D(x,y) \
+  BUILD_INTERRUPT_HANDLER(x##y)
+
+#define D16(x) \
+  D(x,0) D(x,1) D(x,2) D(x,3) \
+  D(x,4) D(x,5) D(x,6) D(x,7) \
+  D(x,8) D(x,9) D(x,A) D(x,B) \
+  D(x,C) D(x,D) D(x,E) D(x,F)
+
+D16(3) D16(4) D16(5) D16(6)
+D16(7) D16(8) D16(9) D16(A)
+D16(B) D16(C) D16(D) D16(E)
+D16(F)
+
+#define L(x,y) \
+  (ULONG)& INT_NAME2(x##y)
+
+#define L16(x) \
+        L(x,0), L(x,1), L(x,2), L(x,3), \
+        L(x,4), L(x,5), L(x,6), L(x,7), \
+        L(x,8), L(x,9), L(x,A), L(x,B), \
+        L(x,C), L(x,D), L(x,E), L(x,F)
+
+static ULONG irq_handler[ROUND_UP(NR_IRQS, 16)] = {
+  L16(3), L16(4), L16(5), L16(6),
+  L16(7), L16(8), L16(9), L16(A),
+  L16(B), L16(C), L16(D), L16(E)
+};
+
+#undef L
+#undef L16
+#undef D
+#undef D16
+
+#else /* CONFIG_SMP */
+
+void irq_handler_0(void);
+void irq_handler_1(void);
+void irq_handler_2(void);
+void irq_handler_3(void);
+void irq_handler_4(void);
+void irq_handler_5(void);
+void irq_handler_6(void);
+void irq_handler_7(void);
+void irq_handler_8(void);
+void irq_handler_9(void);
+void irq_handler_10(void);
+void irq_handler_11(void);
+void irq_handler_12(void);
+void irq_handler_13(void);
+void irq_handler_14(void);
+void irq_handler_15(void);
+
+static unsigned int irq_handler[NR_IRQS]=
+{
+   (int)&irq_handler_0,
+   (int)&irq_handler_1,
+   (int)&irq_handler_2,
+   (int)&irq_handler_3,
+   (int)&irq_handler_4,
+   (int)&irq_handler_5,
+   (int)&irq_handler_6,
+   (int)&irq_handler_7,
+   (int)&irq_handler_8,
+   (int)&irq_handler_9,
+   (int)&irq_handler_10,
+   (int)&irq_handler_11,
+   (int)&irq_handler_12,
+   (int)&irq_handler_13,
+   (int)&irq_handler_14,
+   (int)&irq_handler_15,
+};
+
+#endif /* CONFIG_SMP */
+
+/*
+ * PURPOSE: Object describing each isr
+ * NOTE: The data in this table is only modified at passsive level but can
+ * be accessed at any irq level.
+ */
+
+typedef struct
+{
+   LIST_ENTRY ListHead;
+   KSPIN_LOCK Lock;
+   ULONG Count;
+}
+ISR_TABLE, *PISR_TABLE;
+
+#ifdef CONFIG_SMP
+static ISR_TABLE IsrTable[NR_IRQS][MAXIMUM_PROCESSORS];
+#else
+static ISR_TABLE IsrTable[NR_IRQS][1];
+#endif
+
+#define TAG_ISR_LOCK     TAG('I', 'S', 'R', 'L')
+
+/* FUNCTIONS ****************************************************************/
+
+#define PRESENT (0x8000)
+#define I486_INTERRUPT_GATE (0xe00)
+
+VOID
+INIT_FUNCTION
+NTAPI
+KeInitInterrupts (VOID)
+{
+   int i, j;
+
+
+   /*
+    * Setup the IDT entries to point to the interrupt handlers
+    */
+   for (i=0;i<NR_IRQS;i++)
+     {
+
((IDT_DESCRIPTOR*)&KiIdt[IRQ_BASE+i])->a=(irq_handler[i]&0xffff)+(KGDT_R0_CODE<<16);
+
((IDT_DESCRIPTOR*)&KiIdt[IRQ_BASE+i])->b=(irq_handler[i]&0xffff0000)+PRESENT+
+                            I486_INTERRUPT_GATE;
+#ifdef CONFIG_SMP
+        for (j = 0; j < MAXIMUM_PROCESSORS; j++)
+#else
+        j = 0;
+#endif
+          {
+            InitializeListHead(&IsrTable[i][j].ListHead);
+            KeInitializeSpinLock(&IsrTable[i][j].Lock);
+            IsrTable[i][j].Count = 0;
+          }
+     }
+}
+
+static VOID
+KeIRQTrapFrameToTrapFrame(PKIRQ_TRAPFRAME IrqTrapFrame,
+                          PKTRAP_FRAME TrapFrame)
+{
+   TrapFrame->SegGs     = (USHORT)IrqTrapFrame->Gs;
+   TrapFrame->SegFs     = (USHORT)IrqTrapFrame->Fs;
+   TrapFrame->SegEs     = (USHORT)IrqTrapFrame->Es;
+   TrapFrame->SegDs     = (USHORT)IrqTrapFrame->Ds;
+   TrapFrame->Eax    = IrqTrapFrame->Eax;
+   TrapFrame->Ecx    = IrqTrapFrame->Ecx;
+   TrapFrame->Edx    = IrqTrapFrame->Edx;
+   TrapFrame->Ebx    = IrqTrapFrame->Ebx;
+   TrapFrame->HardwareEsp    = IrqTrapFrame->Esp;
+   TrapFrame->Ebp    = IrqTrapFrame->Ebp;
+   TrapFrame->Esi    = IrqTrapFrame->Esi;
+   TrapFrame->Edi    = IrqTrapFrame->Edi;
+   TrapFrame->Eip    = IrqTrapFrame->Eip;
+   TrapFrame->SegCs     = IrqTrapFrame->Cs;
+   TrapFrame->EFlags = IrqTrapFrame->Eflags;
+}
+
+static VOID
+KeTrapFrameToIRQTrapFrame(PKTRAP_FRAME TrapFrame,
+                          PKIRQ_TRAPFRAME IrqTrapFrame)
+{
+   IrqTrapFrame->Gs     = TrapFrame->SegGs;
+   IrqTrapFrame->Fs     = TrapFrame->SegFs;
+   IrqTrapFrame->Es     = TrapFrame->SegEs;
+   IrqTrapFrame->Ds     = TrapFrame->SegDs;
+   IrqTrapFrame->Eax    = TrapFrame->Eax;
+   IrqTrapFrame->Ecx    = TrapFrame->Ecx;
+   IrqTrapFrame->Edx    = TrapFrame->Edx;
+   IrqTrapFrame->Ebx    = TrapFrame->Ebx;
+   IrqTrapFrame->Esp    = TrapFrame->HardwareEsp;
+   IrqTrapFrame->Ebp    = TrapFrame->Ebp;
+   IrqTrapFrame->Esi    = TrapFrame->Esi;
+   IrqTrapFrame->Edi    = TrapFrame->Edi;
+   IrqTrapFrame->Eip    = TrapFrame->Eip;
+   IrqTrapFrame->Cs     = TrapFrame->SegCs;
+   IrqTrapFrame->Eflags = TrapFrame->EFlags;
+}
+
+/*
+ * NOTE: On Windows this function takes exactly one parameter and EBP is
+ *       guaranteed to point to KTRAP_FRAME. The function is used only
+ *       by HAL, so there's no point in keeping that prototype.
+ *
+ * @implemented
+ */
+VOID
+STDCALL
+KeUpdateRunTime(IN PKTRAP_FRAME  TrapFrame,
+                IN KIRQL  Irql)
+{
+    PKPRCB Prcb = KeGetCurrentPrcb();
+    PKTHREAD CurrentThread;
+    PKPROCESS CurrentProcess;
+
+    /* Make sure we don't go further if we're in early boot phase. */
+    if (!(Prcb) || !(Prcb->CurrentThread)) return;
+
+    /* Get the current thread and process */
+    CurrentThread = Prcb->CurrentThread;
+    CurrentProcess = CurrentThread->ApcState.Process;
+
+    /* Check if we came from user mode */
+    if (TrapFrame->PreviousPreviousMode != KernelMode)
+    {
+        /* Update user times */
+        CurrentThread->UserTime++;
+        InterlockedIncrement((PLONG)&CurrentProcess->UserTime);
+        Prcb->UserTime++;
+    }
+    else
+    {
+        /* Check IRQ */
+        if (Irql > DISPATCH_LEVEL)
+        {
+            /* This was an interrupt */
+            Prcb->InterruptTime++;
+        }
+        else if ((Irql < DISPATCH_LEVEL) || !(Prcb->DpcRoutineActive))
+        {
+            /* This was normal kernel time */
+            CurrentThread->KernelTime++;
+            InterlockedIncrement((PLONG)&CurrentProcess->KernelTime);
+        }
+        else if (Irql == DISPATCH_LEVEL)
+        {
+            /* This was DPC time */
+            Prcb->DpcTime++;
+        }
+
+        /* Update CPU kernel time in all cases */
+        Prcb->KernelTime++;
+   }
+
+    /* Set the last DPC Count and request rate */
+    Prcb->DpcLastCount = Prcb->DpcData[0].DpcCount;
+    Prcb->DpcRequestRate = ((Prcb->DpcData[0].DpcCount - Prcb->DpcLastCount) +
+                             Prcb->DpcRequestRate) / 2;
+
+    /* Check if we should request a DPC */
+    if ((Prcb->DpcData[0].DpcQueueDepth) && !(Prcb->DpcRoutineActive))
+    {
+        /* Request one */
+        HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
+
+        /* Update the depth if needed */
+        if ((Prcb->DpcRequestRate < KiIdealDpcRate) &&
+            (Prcb->MaximumDpcQueueDepth > 1))
+        {
+            /* Decrease the maximum depth by one */
+            Prcb->MaximumDpcQueueDepth--;
+        }
+    }
+    else
+    {
+        /* Decrease the adjustment threshold */
+        if (!(--Prcb->AdjustDpcThreshold))
+        {
+            /* We've hit 0, reset it */
+            Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold;
+
+            /* Check if we've hit queue maximum */
+            if (KiMaximumDpcQueueDepth != Prcb->MaximumDpcQueueDepth)
+            {
+                /* Increase maximum by one */
+                Prcb->MaximumDpcQueueDepth++;
+            }
+        }
+    }
+
+   /*
+    * If we're at end of quantum request software interrupt. The rest
+    * is handled in KiDispatchInterrupt.
+    *
+    * NOTE: If one stays at DISPATCH_LEVEL for a long time the DPC routine
+    * which checks for quantum end will not be executed and decrementing
+    * the quantum here can result in overflow. This is not a problem since
+    * we don't care about the quantum value anymore after the QuantumEnd
+    * flag is set.
+    */
+    if ((CurrentThread->Quantum -= 3) <= 0)
+    {
+        Prcb->QuantumEnd = TRUE;
+        HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
+    }
+}
+
+
+/*
+ * NOTE: On Windows this function takes exactly zero parameters and EBP is
+ *       guaranteed to point to KTRAP_FRAME. Also [esp+0] contains an IRQL.
+ *       The function is used only by HAL, so there's no point in keeping
+ *       that prototype.
+ *
+ * @implemented
+ */
+VOID
+STDCALL
+KeUpdateSystemTime(IN PKTRAP_FRAME TrapFrame,
+                   IN KIRQL Irql,
+                   IN ULONG Increment)
+{
+    LONG OldOffset;
+    LARGE_INTEGER Time;
+    ASSERT(KeGetCurrentIrql() == PROFILE_LEVEL);
+    if (!KiClockSetupComplete) return;
+
+    /* Update interrupt time */
+    Time.LowPart = SharedUserData->InterruptTime.LowPart;
+    Time.HighPart = SharedUserData->InterruptTime.High1Time;
+    Time.QuadPart += Increment;
+    SharedUserData->InterruptTime.High2Time = Time.u.HighPart;
+    SharedUserData->InterruptTime.LowPart = Time.u.LowPart;
+    SharedUserData->InterruptTime.High1Time = Time.u.HighPart;
+
+    /* Increase the tick offset */
+    KiTickOffset -= Increment;
+    OldOffset = KiTickOffset;
+
+    /* Check if this isn't a tick yet */
+    if (KiTickOffset > 0)
+    {
+        /* Expire timers */
+        KeInsertQueueDpc(&KiExpireTimerDpc, (PVOID)TrapFrame->Eip, 0);
+    }
+    else
+    {
+        /* Setup time structure for system time */
+        Time.LowPart = SharedUserData->SystemTime.LowPart;
+        Time.HighPart = SharedUserData->SystemTime.High1Time;
+        Time.QuadPart += KeTimeAdjustment;
+        SharedUserData->SystemTime.High2Time = Time.HighPart;
+        SharedUserData->SystemTime.LowPart = Time.LowPart;
+        SharedUserData->SystemTime.High1Time = Time.HighPart;
+
+        /* Setup time structure for tick time */
+        Time.LowPart = KeTickCount.LowPart;
+        Time.HighPart = KeTickCount.High1Time;
+        Time.QuadPart += 1;
+        KeTickCount.High2Time = Time.HighPart;
+        KeTickCount.LowPart = Time.LowPart;
+        KeTickCount.High1Time = Time.HighPart;
+        SharedUserData->TickCount.High2Time = Time.HighPart;
+        SharedUserData->TickCount.LowPart = Time.LowPart;
+        SharedUserData->TickCount.High1Time = Time.HighPart;
+
+        /* Update tick count in shared user data as well */
+        SharedUserData->TickCountLowDeprecated++;
+
+        /* Queue a DPC that will expire timers */
+        KeInsertQueueDpc(&KiExpireTimerDpc, (PVOID)TrapFrame->Eip, 0);
+    }
+
+    /* Update process and thread times */
+    if (OldOffset <= 0)
+    {
+        /* This was a tick, calculate the next one */
+        KiTickOffset += KeMaximumIncrement;
+        KeUpdateRunTime(TrapFrame, Irql);
+    }
+}
+
+VOID STDCALL
+KiInterruptDispatch2 (ULONG vector, KIRQL old_level)
+/*
+ * FUNCTION: Calls all the interrupt handlers for a given irq.
+ * ARGUMENTS:
+ *        vector - The number of the vector to call handlers for.
+ *        old_level - The irql of the processor when the irq took place.
+ * NOTES: Must be called at DIRQL.
+ */
+{
+  PKINTERRUPT isr;
+  PLIST_ENTRY current;
+  KIRQL oldlvl;
+  PISR_TABLE CurrentIsr;
+
+  DPRINT("I(0x%.08x, 0x%.08x)\n", vector, old_level);
+
+  /*
+   * Iterate the list until one of the isr tells us its device interrupted
+   */
+  CurrentIsr = &IsrTable[vector - IRQ_BASE][(ULONG)KeGetCurrentProcessorNumber()];
+
+  KiAcquireSpinLock(&CurrentIsr->Lock);
+
+  CurrentIsr->Count++;
+  current = CurrentIsr->ListHead.Flink;
+
+  while (current != &CurrentIsr->ListHead)
+    {
+      isr = CONTAINING_RECORD(current,KINTERRUPT,InterruptListEntry);
+      oldlvl = KeAcquireInterruptSpinLock(isr);
+      if (isr->ServiceRoutine(isr, isr->ServiceContext))
+        {
+          KeReleaseInterruptSpinLock(isr, oldlvl);
+          break;
+        }
+      KeReleaseInterruptSpinLock(isr, oldlvl);
+      current = current->Flink;
+    }
+  KiReleaseSpinLock(&CurrentIsr->Lock);
+}
+
+VOID
+KiInterruptDispatch3 (ULONG vector, PKIRQ_TRAPFRAME Trapframe)
+/*
+ * FUNCTION: Calls the irq specific handler for an irq
+ * ARGUMENTS:
+ *         irq = IRQ that has interrupted
+ */
+{
+   KIRQL old_level;
+   KTRAP_FRAME KernelTrapFrame;
+   PKTHREAD CurrentThread;
+   PKTRAP_FRAME OldTrapFrame=NULL;
+
+   /*
+    * At this point we have interrupts disabled, nothing has been done to
+    * the PIC.
+    */
+
+   KeGetCurrentPrcb()->InterruptCount++;
+
+   /*
+    * Notify the rest of the kernel of the raised irq level. For the
+    * default HAL this will send an EOI to the PIC and alter the IRQL.
+    */
+   if (!HalBeginSystemInterrupt (VECTOR2IRQL(vector),
+                                 vector,
+                                 &old_level))
+     {
+       return;
+     }
+
+
+   /*
+    * Enable interrupts
+    * NOTE: Only higher priority interrupts will get through
+    */
+   _enable();
+
+#ifndef CONFIG_SMP
+   if (VECTOR2IRQ(vector) == 0)
+   {
+      KeIRQTrapFrameToTrapFrame(Trapframe, &KernelTrapFrame);
+      KeUpdateSystemTime(&KernelTrapFrame, old_level, 100000);
+   }
+   else
+#endif
+   {
+     /*
+      * Actually call the ISR.
+      */
+     KiInterruptDispatch2(vector, old_level);
+   }
+
+   /*
+    * End the system interrupt.
+    */
+   _disable();
+
+   if (old_level==PASSIVE_LEVEL && Trapframe->Cs != KGDT_R0_CODE)
+     {
+       HalEndSystemInterrupt (APC_LEVEL, 0);
+
+       CurrentThread = KeGetCurrentThread();
+       if (CurrentThread!=NULL && CurrentThread->ApcState.UserApcPending)
+         {
+           DPRINT("PID: %d, TID: %d CS %04x/%04x\n",
+                  ((PETHREAD)CurrentThread)->ThreadsProcess->UniqueProcessId,
+                  ((PETHREAD)CurrentThread)->Cid.UniqueThread,
+                  Trapframe->Cs,
+                  CurrentThread->TrapFrame ? CurrentThread->TrapFrame->SegCs :
0);
+           if (CurrentThread->TrapFrame == NULL)
+             {
+               OldTrapFrame = CurrentThread->TrapFrame;
+               KeIRQTrapFrameToTrapFrame(Trapframe, &KernelTrapFrame);
+               CurrentThread->TrapFrame = &KernelTrapFrame;
+             }
+
+           _enable();
+           KiDeliverApc(UserMode, NULL, NULL);
+           _disable();
+
+           ASSERT(KeGetCurrentThread() == CurrentThread);
+           if (CurrentThread->TrapFrame == &KernelTrapFrame)
+             {
+               KeTrapFrameToIRQTrapFrame(&KernelTrapFrame, Trapframe);
+               CurrentThread->TrapFrame = OldTrapFrame;
+             }
+         }
+       KeLowerIrql(PASSIVE_LEVEL);
+     }
+   else
+     {
+       HalEndSystemInterrupt (old_level, 0);
+     }
+
+}
+
+static VOID
+KeDumpIrqList(VOID)
+{
+   PKINTERRUPT current;
+   PLIST_ENTRY current_entry;
+   LONG i, j;
+   KIRQL oldlvl;
+   BOOLEAN printed;
+
+   for (i=0;i<NR_IRQS;i++)
+     {
+        printed = FALSE;
+        KeRaiseIrql(VECTOR2IRQL(i + IRQ_BASE),&oldlvl);
+
+        for (j=0; j < KeNumberProcessors; j++)
+          {
+            KiAcquireSpinLock(&IsrTable[i][j].Lock);
+
+            current_entry = IsrTable[i][j].ListHead.Flink;
+            current = CONTAINING_RECORD(current_entry,KINTERRUPT,InterruptListEntry);
+            while (current_entry!=&(IsrTable[i][j].ListHead))
+              {
+                if (printed == FALSE)
+                  {
+                    printed = TRUE;
+                    DPRINT("For irq %x:\n",i);
+                  }
+                DPRINT("   Isr %x\n",current);
+                current_entry = current_entry->Flink;
+                current = CONTAINING_RECORD(current_entry,KINTERRUPT,InterruptListEntry);
+              }
+            KiReleaseSpinLock(&IsrTable[i][j].Lock);
+          }
+        KeLowerIrql(oldlvl);
+     }
+}
+
+/*
+ * @implemented
+ */
+BOOLEAN
+STDCALL
+KeConnectInterrupt(PKINTERRUPT InterruptObject)
+{
+   KIRQL oldlvl,synch_oldlvl;
+   PKINTERRUPT ListHead;
+   ULONG Vector;
+   PISR_TABLE CurrentIsr;
+   BOOLEAN Result;
+
+   DPRINT("KeConnectInterrupt()\n");
+
+   Vector = InterruptObject->Vector;
+
+   if (Vector < IRQ_BASE || Vector >= IRQ_BASE + NR_IRQS)
+      return FALSE;
+
+   Vector -= IRQ_BASE;
+
+   ASSERT (InterruptObject->Number < KeNumberProcessors);
+
+   KeSetSystemAffinityThread(1 << InterruptObject->Number);
+
+   CurrentIsr = &IsrTable[Vector][(ULONG)InterruptObject->Number];
+
+   KeRaiseIrql(VECTOR2IRQL(Vector + IRQ_BASE),&oldlvl);
+   KiAcquireSpinLock(&CurrentIsr->Lock);
+
+   /*
+    * Check if the vector is already in use that we can share it
+    */
+   if (!IsListEmpty(&CurrentIsr->ListHead))
+   {
+      ListHead =
CONTAINING_RECORD(CurrentIsr->ListHead.Flink,KINTERRUPT,InterruptListEntry);
+      if (InterruptObject->ShareVector == FALSE || ListHead->ShareVector==FALSE)
+      {
+         KiReleaseSpinLock(&CurrentIsr->Lock);
+         KeLowerIrql(oldlvl);
+         KeRevertToUserAffinityThread();
+         return FALSE;
+      }
+   }
+
+   synch_oldlvl = KeAcquireInterruptSpinLock(InterruptObject);
+
+   DPRINT("%x %x\n",CurrentIsr->ListHead.Flink,
CurrentIsr->ListHead.Blink);
+
+   Result = HalEnableSystemInterrupt(Vector + IRQ_BASE, InterruptObject->Irql,
InterruptObject->Mode);
+   if (Result)
+   {
+
InsertTailList(&CurrentIsr->ListHead,&InterruptObject->InterruptListEntry);
+      DPRINT("%x %x\n",InterruptObject->InterruptListEntry.Flink,
InterruptObject->InterruptListEntry.Blink);
+   }
+
+   InterruptObject->Connected = TRUE;
+   KeReleaseInterruptSpinLock(InterruptObject, synch_oldlvl);
+
+   /*
+    * Release the table spinlock
+    */
+   KiReleaseSpinLock(&CurrentIsr->Lock);
+   KeLowerIrql(oldlvl);
+
+   KeDumpIrqList();
+
+   KeRevertToUserAffinityThread();
+
+   return Result;
+}
+
+/*
+ * @implemented
+ *
+ * FUNCTION: Releases a drivers isr
+ * ARGUMENTS:
+ *        InterruptObject = isr to release
+ */
+BOOLEAN
+STDCALL
+KeDisconnectInterrupt(PKINTERRUPT InterruptObject)
+{
+    KIRQL oldlvl,synch_oldlvl;
+    PISR_TABLE CurrentIsr;
+    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);
+
+    /* 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);
+        }
+
+        /* 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 */
+    KeRevertToUserAffinityThread();
+
+    /* Return Old Interrupt State */
+    return State;
+}
+
+/*
+ * @implemented
+ */
+VOID
+STDCALL
+KeInitializeInterrupt(PKINTERRUPT Interrupt,
+                      PKSERVICE_ROUTINE ServiceRoutine,
+                      PVOID ServiceContext,
+                      PKSPIN_LOCK SpinLock,
+                      ULONG Vector,
+                      KIRQL Irql,
+                      KIRQL SynchronizeIrql,
+                      KINTERRUPT_MODE InterruptMode,
+                      BOOLEAN ShareVector,
+                      CHAR ProcessorNumber,
+                      BOOLEAN FloatingSave)
+{
+    /* Set the Interrupt Header */
+    Interrupt->Type = InterruptObject;
+    Interrupt->Size = sizeof(KINTERRUPT);
+
+    /* Check if we got a spinlock */
+    if (SpinLock)
+    {
+        Interrupt->ActualLock = SpinLock;
+    }
+    else
+    {
+        /* This means we'll be usin the built-in one */
+        KeInitializeSpinLock(&Interrupt->SpinLock);
+        Interrupt->ActualLock = &Interrupt->SpinLock;
+    }
+
+    /* Set the other settings */
+    Interrupt->ServiceRoutine = ServiceRoutine;
+    Interrupt->ServiceContext = ServiceContext;
+    Interrupt->Vector = Vector;
+    Interrupt->Irql = Irql;
+    Interrupt->SynchronizeIrql = SynchronizeIrql;
+    Interrupt->Mode = InterruptMode;
+    Interrupt->ShareVector = ShareVector;
+    Interrupt->Number = ProcessorNumber;
+    Interrupt->FloatingSave = FloatingSave;
+
+    /* Disconnect it at first */
+    Interrupt->Connected = FALSE;
+}
+
+VOID KePrintInterruptStatistic(VOID)
+{
+   LONG i, j;
+
+   for (j = 0; j < KeNumberProcessors; j++)
+   {
+      DPRINT1("CPU%d:\n", j);
+      for (i = 0; i < NR_IRQS; i++)
+      {
+         if (IsrTable[i][j].Count)
+         {
+             DPRINT1("  Irq %x(%d): %d\n", i, VECTOR2IRQ(i + IRQ_BASE),
IsrTable[i][j].Count);
+         }
+      }
+   }
+}
+
+/* EOF */
Added: branches/arty-stable/reactos/ntoskrnl/deprecated/irqhand.S
URL:
http://svn.reactos.org/svn/reactos/branches/arty-stable/reactos/ntoskrnl/de…
==============================================================================
--- branches/arty-stable/reactos/ntoskrnl/deprecated/irqhand.S (added)
+++ branches/arty-stable/reactos/ntoskrnl/deprecated/irqhand.S Sun Dec  3 14:25:56 2006
@@ -1,0 +1,99 @@
+#include <ndk/asm.h>
+#include <../hal/halx86/include/halirq.h>
+
+_KiCommonInterrupt:
+       cld
+       pushl   %ds
+       pushl   %es
+       pushl   %fs
+       pushl   %gs
+       pushl   $0xceafbeef
+
+    /* Load DS/ES (with override) */
+    .intel_syntax noprefix
+    mov eax, KGDT_R3_DATA + RPL_MASK
+    .byte 0x66
+    mov ds, ax
+    .byte 0x66
+    mov es, ax
+
+    /* Clear gs */
+    xor eax, eax
+    .byte 0x66
+    mov gs, ax
+    .att_syntax
+       movl    $KGDT_R0_PCR,%eax
+       movl    %eax,%fs
+       pushl   %esp
+       pushl   %ebx
+       call    _KiInterruptDispatch3
+       addl    $0xC, %esp
+       popl    %gs
+       popl    %fs
+       popl    %es
+       popl    %ds
+       popa
+       iret
+
+
+#ifdef CONFIG_SMP
+
+#define BUILD_INTERRUPT_HANDLER(intnum) \
+  .global _KiUnexpectedInterrupt##intnum; \
+  _KiUnexpectedInterrupt##intnum:; \
+  pusha; \
+  movl $0x##intnum, %ebx; \
+  jmp _KiCommonInterrupt;
+
+/* Interrupt handlers and declarations */
+
+#define B(x,y) \
+  BUILD_INTERRUPT_HANDLER(x##y)
+
+#define B16(x) \
+  B(x,0) B(x,1) B(x,2) B(x,3) \
+  B(x,4) B(x,5) B(x,6) B(x,7) \
+  B(x,8) B(x,9) B(x,A) B(x,B) \
+  B(x,C) B(x,D) B(x,E) B(x,F)
+
+B16(3) B16(4) B16(5) B16(6)
+B16(7) B16(8) B16(9) B16(A)
+B16(B) B16(C) B16(D) B16(E)
+B16(F)
+
+#undef B
+#undef B16
+#undef BUILD_INTERRUPT_HANDLER
+
+#else /* CONFIG_SMP */
+
+#define BUILD_INTERRUPT_HANDLER(intnum) \
+  .global _irq_handler_##intnum; \
+  _irq_handler_##intnum:; \
+  pusha; \
+  movl $(##intnum + IRQ_BASE), %ebx; \
+  jmp _KiCommonInterrupt;
+
+/* Interrupt handlers and declarations */
+
+#define B(x) \
+  BUILD_INTERRUPT_HANDLER(x)
+
+B(0) B(1) B(2) B(3)
+B(4) B(5) B(6) B(7)
+B(8) B(9) B(10) B(11)
+B(12) B(13) B(14) B(15)
+
+#undef B
+#undef BUILD_INTERRUPT_HANDLER
+
+#endif /* CONFIG_SMP */
+
+.intel_syntax noprefix
+.globl _KiUnexpectedInterrupt@0
+_KiUnexpectedInterrupt@0:
+
+    /* Bugcheck with invalid interrupt code */
+    push 0x12
+    call _KeBugCheck@4
+