update for HEAD-2003021201
[reactos.git] / hal / halx86 / irql.c
index a18a5aa..578432c 100644 (file)
@@ -1,4 +1,5 @@
-/*
+/* $Id$
+ *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
  * FILE:            ntoskrnl/hal/x86/irql.c
  */
 static KIRQL CurrentIrql = HIGH_LEVEL;
 
+typedef union
+{
+   USHORT both;
+   struct
+   {
+      BYTE master;
+      BYTE slave;
+   };
+}
+PIC_MASK;
+   
+/* 
+ * PURPOSE: - Mask for HalEnableSystemInterrupt and HalDisableSystemInterrupt
+ *          - At startup enable timer and cascade 
+ */
+static PIC_MASK pic_mask = {.both = 0xFFFA};
+
+
+/*
+ * PURPOSE: Mask for disabling of acknowledged interrupts 
+ */
+static PIC_MASK pic_mask_intr = {.both = 0x0000};
+
 extern IMPORTED ULONG DpcQueueSize;
 
 static ULONG HalpPendingInterruptCount[NR_IRQS];
@@ -64,14 +88,36 @@ VOID HalpInitPICs(VOID)
   /* 8086 mode */
   WRITE_PORT_UCHAR((PUCHAR)0x21, 0x1);
   WRITE_PORT_UCHAR((PUCHAR)0xa1, 0x1);   
-  /* Enable all interrupts from PICs */
-  WRITE_PORT_UCHAR((PUCHAR)0x21, 0x0);
-  WRITE_PORT_UCHAR((PUCHAR)0xa1, 0x0);
+  /* Enable interrupts */
+  WRITE_PORT_UCHAR((PUCHAR)0x21, pic_mask.master);
+  WRITE_PORT_UCHAR((PUCHAR)0xa1, pic_mask.slave);
   
   /* We can now enable interrupts */
   __asm__ __volatile__ ("sti\n\t");
 }
 
+VOID HalpEndSystemInterrupt(KIRQL Irql)
+/*
+ * FUNCTION: Enable all irqs with higher priority.
+ */
+{
+  const USHORT mask[] = 
+  {
+     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+     0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0xc000, 0xe000, 0xf000,
+     0xf800, 0xfc00, 0xfe00, 0xff00, 0xff80, 0xffc0, 0xffe0, 0xfff0,
+     0xfff8, 0xfffc, 0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+  };     
+
+  /* Interrupts should be disable while enabling irqs of both pics */
+  __asm__("pushf\n\t");
+  __asm__("cli\n\t");
+  pic_mask_intr.both &= mask[Irql];
+  WRITE_PORT_UCHAR((PUCHAR)0x21, pic_mask.master|pic_mask_intr.master);
+  WRITE_PORT_UCHAR((PUCHAR)0xa1, pic_mask.slave|pic_mask_intr.slave);
+  __asm__("popf\n\t");
+}
+
 VOID STATIC
 HalpExecuteIrqs(KIRQL NewIrql)
 {
@@ -85,22 +131,29 @@ HalpExecuteIrqs(KIRQL NewIrql)
    */
   for (i = 0; i < IrqLimit; i++)
     {
-      while (HalpPendingInterruptCount[i] > 0)
+      if (HalpPendingInterruptCount[i] > 0)
        {
-         /*
-          * For each deferred interrupt execute all the handlers at DIRQL.
-          */
-         CurrentIrql = IRQ_TO_DIRQL(i);
-         KiInterruptDispatch2(i, NewIrql);
-         HalpPendingInterruptCount[i]--;
+          CurrentIrql = IRQ_TO_DIRQL(i);
+
+           while (HalpPendingInterruptCount[i] > 0)
+            {
+              /*
+               * For each deferred interrupt execute all the handlers at DIRQL.
+               */
+              KiInterruptDispatch2(i, NewIrql);
+              HalpPendingInterruptCount[i]--;
+            }
+          CurrentIrql--;
+          HalpEndSystemInterrupt(CurrentIrql);
        }
     }
+
 }
 
 VOID STATIC
 HalpLowerIrql(KIRQL NewIrql)
 {
-  if (NewIrql > PROFILE_LEVEL)
+  if (NewIrql >= PROFILE_LEVEL)
     {
       CurrentIrql = NewIrql;
       return;
@@ -116,12 +169,11 @@ HalpLowerIrql(KIRQL NewIrql)
     {
       KiDispatchInterrupt();
     }
+  CurrentIrql = APC_LEVEL;
   if (NewIrql == APC_LEVEL)
     {
-      CurrentIrql = NewIrql;
       return;
     }
-  CurrentIrql = APC_LEVEL;
   if (KeGetCurrentThread() != NULL && 
       KeGetCurrentThread()->ApcState.KernelApcPending)
     {
@@ -304,21 +356,30 @@ HalBeginSystemInterrupt (ULONG Vector,
                         KIRQL Irql,
                         PKIRQL OldIrql)
 {
-  if (Vector < IRQ_BASE || Vector > IRQ_BASE + NR_IRQS)
+  ULONG irq;
+  if (Vector < IRQ_BASE || Vector >= IRQ_BASE + NR_IRQS)
     {
       return(FALSE);
     }
-  
-  /* Send EOI to the PICs */
-  WRITE_PORT_UCHAR((PUCHAR)0x20,0x20);
-  if ((Vector-IRQ_BASE)>=8)
-    {
-      WRITE_PORT_UCHAR((PUCHAR)0xa0,0x20);
-    }
+  irq = Vector - IRQ_BASE;
+  pic_mask_intr.both |= ((1 << irq) & 0xfffe); // do not disable the timer interrupt
+
+  if (irq < 8)
+  {
+     WRITE_PORT_UCHAR((PUCHAR)0x21, pic_mask.master|pic_mask_intr.master);
+     WRITE_PORT_UCHAR((PUCHAR)0x20, 0x20);
+  }
+  else
+  {
+     WRITE_PORT_UCHAR((PUCHAR)0xa1, pic_mask.slave|pic_mask_intr.slave);
+     /* Send EOI to the PICs */
+     WRITE_PORT_UCHAR((PUCHAR)0x20,0x20);
+     WRITE_PORT_UCHAR((PUCHAR)0xa0,0x20);
+  }
   
   if (CurrentIrql >= Irql)
     {
-      HalpPendingInterruptCount[Vector - IRQ_BASE]++;
+      HalpPendingInterruptCount[irq]++;
       return(FALSE);
     }
   *OldIrql = CurrentIrql;
@@ -334,26 +395,26 @@ VOID STDCALL HalEndSystemInterrupt (KIRQL Irql, ULONG Unknown2)
  */
 {
   HalpLowerIrql(Irql);
+  HalpEndSystemInterrupt(Irql);
 }
-
+  
 BOOLEAN STDCALL HalDisableSystemInterrupt (ULONG Vector,
                                           ULONG Unknown2)
 {
   ULONG irq;
   
-  if (Vector < IRQ_BASE || Vector > IRQ_BASE + NR_IRQS)
+  if (Vector < IRQ_BASE || Vector >= IRQ_BASE + NR_IRQS)
     return FALSE;
 
   irq = Vector - IRQ_BASE;
+  pic_mask.both |= (1 << irq);
   if (irq < 8)
      {
-       WRITE_PORT_UCHAR((PUCHAR)0x21, 
-                       READ_PORT_UCHAR((PUCHAR)0x21)|(1<<irq));
+      WRITE_PORT_UCHAR((PUCHAR)0x21, pic_mask.master|pic_mask_intr.slave);
      }
   else
     {
-      WRITE_PORT_UCHAR((PUCHAR)0xa1, 
-                      READ_PORT_UCHAR((PUCHAR)0xa1)|(1<<(irq-8)));
+      WRITE_PORT_UCHAR((PUCHAR)0xa1, pic_mask.slave|pic_mask_intr.slave);
     }
   
   return TRUE;
@@ -366,19 +427,18 @@ BOOLEAN STDCALL HalEnableSystemInterrupt (ULONG Vector,
 {
   ULONG irq;
 
-  if (Vector < IRQ_BASE || Vector > IRQ_BASE + NR_IRQS)
+  if (Vector < IRQ_BASE || Vector >= IRQ_BASE + NR_IRQS)
     return FALSE;
 
   irq = Vector - IRQ_BASE;
+  pic_mask.both &= ~(1 << irq);
   if (irq < 8)
     {
-      WRITE_PORT_UCHAR((PUCHAR)0x21, 
-                      READ_PORT_UCHAR((PUCHAR)0x21)&(~(1<<irq)));
+      WRITE_PORT_UCHAR((PUCHAR)0x21, pic_mask.master|pic_mask_intr.master);
     }
   else
      {
-       WRITE_PORT_UCHAR((PUCHAR)0xa1, 
-                       READ_PORT_UCHAR((PUCHAR)0xa1)&(~(1<<(irq-8))));
+       WRITE_PORT_UCHAR((PUCHAR)0xa1, pic_mask.slave|pic_mask_intr.slave);
      }
 
   return TRUE;