Splited HalEndSystemInterrupt in two functions. HalEndSystemInterrupt,
authorHartmut Birr <osexpert@googlemail.com>
Thu, 2 Jan 2003 16:07:49 +0000 (16:07 +0000)
committerHartmut Birr <osexpert@googlemail.com>
Thu, 2 Jan 2003 16:07:49 +0000 (16:07 +0000)
HalpLowerIrql and HalpExecuteIrqs was called recursively.

svn path=/trunk/; revision=3921

reactos/hal/halx86/irql.c

index acd655c..0e46e76 100644 (file)
@@ -1,4 +1,5 @@
-/*
+/* $Id: irql.c,v 1.8 2003/01/02 16:07:49 hbirr Exp $
+ *
  * 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 USHORT pic_mask = 0xFFFA;
+static PIC_MASK pic_mask = {.both = 0xFFFA};
+
 
 /*
  * PURPOSE: Mask for disabling of acknowledged interrupts 
  */
-static USHORT pic_mask_intr = 0x0000;
+static PIC_MASK pic_mask_intr = {.both = 0x0000};
 
 extern IMPORTED ULONG DpcQueueSize;
 
@@ -76,13 +89,35 @@ VOID HalpInitPICs(VOID)
   WRITE_PORT_UCHAR((PUCHAR)0x21, 0x1);
   WRITE_PORT_UCHAR((PUCHAR)0xa1, 0x1);   
   /* Enable interrupts */
-  WRITE_PORT_UCHAR((PUCHAR)0x21, pic_mask & 0xFF);
-  WRITE_PORT_UCHAR((PUCHAR)0xa1, (pic_mask >> 8) & 0xFF);
+  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)
 {
@@ -96,26 +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]--;
-         if (HalpPendingInterruptCount[i] == 0)
-         {
-            HalEndSystemInterrupt(CurrentIrql, 0);
-         }
+          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;
@@ -131,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)
     {
@@ -325,16 +362,16 @@ HalBeginSystemInterrupt (ULONG Vector,
       return(FALSE);
     }
   irq = Vector - IRQ_BASE;
-  pic_mask_intr |= (1 << irq);
+  pic_mask_intr.both |= ((1 << irq) & 0xfffe); // do not disable the timer interrupt
 
   if (irq < 8)
   {
-     WRITE_PORT_UCHAR((PUCHAR)0x21, (pic_mask|pic_mask_intr) & 0xff);
+     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|pic_mask_intr) >> 8) & 0xff);
+     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);
@@ -357,29 +394,8 @@ VOID STDCALL HalEndSystemInterrupt (KIRQL Irql, ULONG Unknown2)
  * FUNCTION: Finish a system interrupt and restore the specified irq level.
  */
 {
-  ULONG mask;
-
   HalpLowerIrql(Irql);
-
-  if (Irql > PROFILE_LEVEL)
-  {
-     mask = 0xffff;
-  }
-  else if (Irql > PROFILE_LEVEL - NR_IRQS)
-  {
-     mask = ~((1 << (PROFILE_LEVEL - Irql + 1)) - 1);
-  }
-  else 
-  {
-     mask = 0;
-  }
-  /* Interrupts should be disable while enabling irqs of both pics */
-  __asm__("pushf\n\t");
-  __asm__("cli\n\t");
-  pic_mask_intr &= mask;
-  WRITE_PORT_UCHAR((PUCHAR)0x21, (pic_mask|pic_mask_intr) & 0xff);
-  WRITE_PORT_UCHAR((PUCHAR)0xa1, ((pic_mask|pic_mask_intr) >> 8) & 0xff);
-  __asm__("popf\n\t");
+  HalpEndSystemInterrupt(Irql);
 }
   
 BOOLEAN STDCALL HalDisableSystemInterrupt (ULONG Vector,
@@ -391,14 +407,14 @@ BOOLEAN STDCALL HalDisableSystemInterrupt (ULONG Vector,
     return FALSE;
 
   irq = Vector - IRQ_BASE;
-  pic_mask |= (1 << irq);
+  pic_mask.both |= (1 << irq);
   if (irq < 8)
      {
-      WRITE_PORT_UCHAR((PUCHAR)0x21, (pic_mask|pic_mask_intr) & 0xff);
+      WRITE_PORT_UCHAR((PUCHAR)0x21, pic_mask.master|pic_mask_intr.slave);
      }
   else
     {
-      WRITE_PORT_UCHAR((PUCHAR)0xa1, ((pic_mask|pic_mask_intr) >> 8) & 0xff);
+      WRITE_PORT_UCHAR((PUCHAR)0xa1, pic_mask.slave|pic_mask_intr.slave);
     }
   
   return TRUE;
@@ -415,14 +431,14 @@ BOOLEAN STDCALL HalEnableSystemInterrupt (ULONG Vector,
     return FALSE;
 
   irq = Vector - IRQ_BASE;
-  pic_mask &= ~(1 << irq);
+  pic_mask.both &= ~(1 << irq);
   if (irq < 8)
     {
-      WRITE_PORT_UCHAR((PUCHAR)0x21, (pic_mask|pic_mask_intr) & 0xff);
+      WRITE_PORT_UCHAR((PUCHAR)0x21, pic_mask.master|pic_mask_intr.master);
     }
   else
      {
-       WRITE_PORT_UCHAR((PUCHAR)0xa1, ((pic_mask|pic_mask_intr) >> 8) & 0xff);
+       WRITE_PORT_UCHAR((PUCHAR)0xa1, pic_mask.slave|pic_mask_intr.slave);
      }
 
   return TRUE;