Implemented missing KeRaiseIrqlToXxLevel() functions
[reactos.git] / reactos / ntoskrnl / hal / x86 / irql.c
index bce3623..fcfe713 100644 (file)
 #include <internal/bitops.h>
 #include <internal/halio.h>
 #include <internal/ke.h>
+#include <internal/ps.h>
 
 #define NDEBUG
 #include <internal/debug.h>
 
 /* GLOBALS ******************************************************************/
 
+/* FIXME: this should be in a header file */
+#define NR_IRQS         (16)
+#define IRQ_BASE        (0x40)
+
 /*
  * PURPOSE: Current irq level
  */
@@ -25,8 +30,30 @@ static KIRQL CurrentIrql = HIGH_LEVEL;
 
 extern ULONG DpcQueueSize;
 
+static VOID KeSetCurrentIrql(KIRQL newlvl);
+
 /* FUNCTIONS ****************************************************************/
 
+VOID HalpInitPICs(VOID)
+{
+   /* Initialization sequence */
+   WRITE_PORT_UCHAR((PUCHAR)0x20, 0x11);
+   WRITE_PORT_UCHAR((PUCHAR)0xa0, 0x11);
+   /* Start of hardware irqs (0x20) */
+   WRITE_PORT_UCHAR((PUCHAR)0x21, 0x40);
+   WRITE_PORT_UCHAR((PUCHAR)0xa1, 0x48);
+   /* 8259-1 is master */
+   WRITE_PORT_UCHAR((PUCHAR)0x21, 0x4);
+   /* 8259-2 is slave */
+   WRITE_PORT_UCHAR((PUCHAR)0xa1, 0x2);
+   /* 8086 mode */
+   WRITE_PORT_UCHAR((PUCHAR)0x21, 0x1);
+   WRITE_PORT_UCHAR((PUCHAR)0xa1, 0x1);   
+   /* Mask off all interrupts from PICs */
+   WRITE_PORT_UCHAR((PUCHAR)0x21, 0xff);
+   WRITE_PORT_UCHAR((PUCHAR)0xa1, 0xff);
+}
+
 #if 0
 static unsigned int HiGetCurrentPICMask(void)
 {
@@ -47,8 +74,6 @@ static unsigned int HiSetCurrentPICMask(unsigned int mask)
    return mask;
 }
 
-extern VOID KeApcProlog2();
-
 static VOID HiSwitchIrql(KIRQL oldIrql)
 /*
  * FUNCTION: Switches to the current irql
@@ -69,9 +94,9 @@ static VOID HiSwitchIrql(KIRQL oldIrql)
      {
        unsigned int current_mask = 0;
        
-       for (i=(CurrentIrql-DISPATCH_LEVEL);i>DISPATCH_LEVEL;i--)
+       for (i=CurrentIrql; i>DISPATCH_LEVEL; i--)
          {
-            set_bit(NR_DEVICE_SPECIFIC_LEVELS - i,&current_mask);
+            current_mask = current_mask | (1 << (HIGH_LEVEL - i));
          }
        
        HiSetCurrentPICMask(current_mask);
@@ -85,31 +110,51 @@ static VOID HiSwitchIrql(KIRQL oldIrql)
        __asm__("sti\n\t");
        return;
      }
-       HiSetCurrentPICMask(0);
-       if(CurrentIrql == APC_LEVEL)
-       {
-               if (DpcQueueSize > 0 )
-               {
-                       KeSetCurrentIrql(DISPATCH_LEVEL);
-                       __asm__("sti\n\t");
-                       KeDrainDpcQueue();
-                       __asm__("cli\n\t");
-                       KeSetCurrentIrql(PASSIVE_LEVEL);
-               }
-               __asm__("sti\n\t");
-               return;
-       }
-   if( CurrentIrql == PASSIVE_LEVEL && CurrentThread && CurrentThread->ApcState.KernelApcPending )
-   {
-          KeSetCurrentIrql( APC_LEVEL );
-          KeApcProlog2();
-          KeSetCurrentIrql( PASSIVE_LEVEL );
-   }
+   
+   HiSetCurrentPICMask(0);
+   if (CurrentIrql == APC_LEVEL)
+     {
+       if (DpcQueueSize > 0 )
+         {
+            KeSetCurrentIrql(DISPATCH_LEVEL);
+            __asm__("sti\n\t");
+            KiDispatchInterrupt();
+            __asm__("cli\n\t");
+            KeSetCurrentIrql(PASSIVE_LEVEL);
+         }
+       __asm__("sti\n\t");
+       return;
+     }
+   
+   if (CurrentIrql == PASSIVE_LEVEL && 
+       CurrentThread != NULL && 
+       CurrentThread->ApcState.KernelApcPending)
+     {
+       KeSetCurrentIrql(APC_LEVEL);
+       __asm__("sti\n\t");
+       KiDeliverApc(0, 0, 0);
+       __asm__("cli\n\t");
+       KeSetCurrentIrql(PASSIVE_LEVEL);
+       __asm__("sti\n\t");
+     }
+   else
+     {
+       __asm__("sti\n\t");
+     }
+}
+
 
-   __asm__("sti\n\t");
+KIRQL STDCALL KeGetCurrentIrql (VOID)
+/*
+ * PURPOSE: Returns the current irq level
+ * RETURNS: The current irq level
+ */
+{
+   return(CurrentIrql);
 }
 
-VOID KeSetCurrentIrql(KIRQL newlvl)
+
+static VOID KeSetCurrentIrql(KIRQL newlvl)
 /*
  * PURPOSE: Sets the current irq level without taking any action
  */
@@ -118,82 +163,277 @@ VOID KeSetCurrentIrql(KIRQL newlvl)
    CurrentIrql = newlvl;
 }
 
-KIRQL KeGetCurrentIrql()
-/*
- * PURPOSE: Returns the current irq level
- * RETURNS: The current irq level
+
+/**********************************************************************
+ * NAME                                                        EXPORTED
+ *     KfLowerIrql
+ *
+ * DESCRIPTION
+ *     Restores the irq level on the current processor
+ *
+ * ARGUMENTS
+ *     NewIrql = Irql to lower to
+ *
+ * RETURN VALUE
+ *     None
+ *
+ * NOTES
+ *     Uses fastcall convention
  */
+
+VOID
+FASTCALL
+KfLowerIrql (
+       KIRQL   NewIrql
+       )
 {
-   return(CurrentIrql);
+       KIRQL OldIrql;
+
+       __asm__("cli\n\t");
+
+       DPRINT("KfLowerIrql(NewIrql %d)\n", NewIrql);
+
+       if (NewIrql > CurrentIrql)
+       {
+               DbgPrint ("(%s:%d) NewIrql %x CurrentIrql %x\n",
+                         __FILE__, __LINE__, NewIrql, CurrentIrql);
+               KeDumpStackFrames (0, 32);
+               for(;;);
+       }
+
+       OldIrql = CurrentIrql;
+       CurrentIrql = NewIrql;
+       HiSwitchIrql(OldIrql);
 }
 
-VOID KeLowerIrql(KIRQL NewIrql)
-/*
- * PURPOSE: Restores the irq level on the current processor
- * ARGUMENTS:
- *        NewIrql = Irql to lower to
+
+/**********************************************************************
+ * NAME                                                        EXPORTED
+ *     KeLowerIrql
+ *
+ * DESCRIPTION
+ *     Restores the irq level on the current processor
+ *
+ * ARGUMENTS
+ *     NewIrql = Irql to lower to
+ *
+ * RETURN VALUE
+ *     None
+ *
+ * NOTES
  */
+
+VOID
+STDCALL
+KeLowerIrql (
+       KIRQL   NewIrql
+       )
 {
-   KIRQL oldIrql;
-   
-//   DbgPrint(">");
-   
-   __asm__("cli\n\t");
-   
-   DPRINT("KeLowerIrql(NewIrql %d)\n", NewIrql);
-//   DbgPrint("{");
-//   KeDumpStackFrames(0,32);
-//   DbgPrint("}\n");
-   //DPRINT("NewIrql %x CurrentIrql %x\n",NewIrql,CurrentIrql);
-   if (NewIrql > CurrentIrql)
+       KfLowerIrql (NewIrql);
+}
+
+
+/**********************************************************************
+ * NAME                                                        EXPORTED
+ *     KfRaiseIrql
+ *
+ * DESCRIPTION
+ *     Raises the hardware priority (irql)
+ *
+ * ARGUMENTS
+ *     NewIrql = Irql to raise to
+ *
+ * RETURN VALUE
+ *     previous irq level
+ *
+ * NOTES
+ *     Uses fastcall convention
+ */
+
+KIRQL
+FASTCALL
+KfRaiseIrql (
+       KIRQL   NewIrql
+       )
+{
+       KIRQL OldIrql;
+
+       DPRINT("KfRaiseIrql(NewIrql %d)\n", NewIrql);
+
+       if (NewIrql < CurrentIrql)
+       {
+               DbgPrint ("%s:%d CurrentIrql %x NewIrql %x\n",
+                         __FILE__,__LINE__,CurrentIrql,NewIrql);
+               KeBugCheck (0);
+               for(;;);
+       }
+
+       __asm__("cli\n\t");
+       OldIrql = CurrentIrql;
+       CurrentIrql = NewIrql;
+
+       DPRINT ("NewIrql %x OldIrql %x CurrentIrql %x\n",
+               NewIrql, OldIrql, CurrentIrql);
+       HiSwitchIrql(OldIrql);
+
+       return OldIrql;
+}
+
+
+/**********************************************************************
+ * NAME                                                        EXPORTED
+ *     KeRaiseIrql
+ *
+ * DESCRIPTION
+ *     Raises the hardware priority (irql)
+ *
+ * ARGUMENTS
+ *     NewIrql = Irql to raise to
+ *     OldIrql (OUT) = Caller supplied storage for the previous irql
+ *
+ * RETURN VALUE
+ *     None
+ *
+ * NOTES
+ *     Calls KfRaiseIrql
+ */
+
+VOID
+STDCALL
+KeRaiseIrql (
+       KIRQL   NewIrql,
+       PKIRQL  OldIrql
+       )
+{
+       *OldIrql = KfRaiseIrql (NewIrql);
+}
+
+
+/**********************************************************************
+ * NAME                                                        EXPORTED
+ *     KeRaiseIrqlToDpcLevel
+ *
+ * DESCRIPTION
+ *     Raises the hardware priority (irql) to DISPATCH level
+ *
+ * ARGUMENTS
+ *     None
+ *
+ * RETURN VALUE
+ *     Previous irq level
+ *
+ * NOTES
+ *     Calls KfRaiseIrql
+ */
+
+KIRQL
+STDCALL
+KeRaiseIrqlToDpcLevel (VOID)
+{
+       return KfRaiseIrql (DISPATCH_LEVEL);
+}
+
+
+/**********************************************************************
+ * NAME                                                        EXPORTED
+ *     KeRaiseIrqlToSynchLevel
+ *
+ * DESCRIPTION
+ *     Raises the hardware priority (irql) to CLOCK2 level
+ *
+ * ARGUMENTS
+ *     None
+ *
+ * RETURN VALUE
+ *     Previous irq level
+ *
+ * NOTES
+ *     Calls KfRaiseIrql
+ */
+
+KIRQL
+STDCALL
+KeRaiseIrqlToSynchLevel (VOID)
+{
+//     return KfRaiseIrql (CLOCK2_LEVEL);
+       UNIMPLEMENTED;
+}
+
+
+BOOLEAN STDCALL HalBeginSystemInterrupt (ULONG Vector,
+                                        KIRQL Irql,
+                                        PKIRQL OldIrql)
+{
+   if (Vector < IRQ_BASE || Vector > IRQ_BASE + NR_IRQS)
+       return FALSE;
+
+   /* Send EOI to the PICs */
+   outb(0x20,0x20);
+   if ((Vector-IRQ_BASE)>=8)
      {
-       DbgPrint("(%s:%d) NewIrql %x CurrentIrql %x\n",
-                __FILE__, __LINE__, NewIrql,CurrentIrql);
-       KeDumpStackFrames(0,32);
-       for(;;);
+       outb(0xa0,0x20);
      }
-   oldIrql = CurrentIrql;
-   CurrentIrql = NewIrql;
-   HiSwitchIrql(oldIrql);
+
+   *OldIrql = KeGetCurrentIrql();
+   if (Vector-IRQ_BASE != 0)
+     {
+       DPRINT("old_level %d\n",*OldIrql);
+     }
+   KeSetCurrentIrql(Irql);
+
+   return TRUE;
 }
 
-VOID KeRaiseIrql(KIRQL NewIrql, PKIRQL OldIrql)
-/*
- * FUNCTION: Raises the hardware priority (irql) 
- * ARGUMENTS:
- *         NewIrql = Irql to raise to
- *         OldIrql (OUT) = Caller supplied storage for the previous irql
- */
+
+VOID STDCALL HalEndSystemInterrupt (KIRQL Irql,
+                                   ULONG Unknown2)
 {
-   /*
-    * sanity check
-    */
-   
-//   DbgPrint("<");
-   
-//  DPRINT("CurrentIrql %x NewIrql %x OldIrql %x\n",CurrentIrql,NewIrql,
-//      OldIrql);
-//   DbgPrint("{");
-//   KeDumpStackFrames(0,32);
-//   DbgPrint("}\n");
-   DPRINT("KeRaiseIrql(NewIrql %d, OldIrql %x, *OldIrql %d)\n",
-           NewIrql, OldIrql, *OldIrql);
-   if (NewIrql < CurrentIrql)
+   KeSetCurrentIrql(Irql);
+}
+
+
+BOOLEAN STDCALL HalDisableSystemInterrupt (ULONG Vector,
+                                          ULONG Unknown2)
+{
+   ULONG irq;
+
+   if (Vector < IRQ_BASE || Vector > IRQ_BASE + NR_IRQS)
+       return FALSE;
+
+   irq = Vector - IRQ_BASE;
+   if (irq<8)
      {
-       DbgPrint("%s:%d CurrentIrql %x NewIrql %x OldIrql %x\n",
-                __FILE__,__LINE__,CurrentIrql,NewIrql,OldIrql);
-       KeBugCheck(0);
-       for(;;);
+       outb(0x21,inb(0x21)|(1<<irq));
      }
-   
-   __asm__("cli\n\t");
-   *OldIrql = CurrentIrql;
-   CurrentIrql = NewIrql;
-//   *OldIrql = InterlockedExchange(&CurrentIrql,NewIrql);
-   DPRINT("NewIrql %x OldIrql %x CurrentIrql %x\n",NewIrql,*OldIrql,
-          CurrentIrql);
-   HiSwitchIrql(*OldIrql);
+   else
+     {
+       outb(0xa1,inb(0xa1)|(1<<(irq-8)));
+     }
+
+   return TRUE;
 }
 
 
+BOOLEAN STDCALL HalEnableSystemInterrupt (ULONG Vector,
+                                         ULONG Unknown2,
+                                         ULONG Unknown3)
+{
+   ULONG irq;
+
+   if (Vector < IRQ_BASE || Vector > IRQ_BASE + NR_IRQS)
+       return FALSE;
+
+   irq = Vector - IRQ_BASE;
+   if (irq<8)
+     {
+       outb(0x21,inb(0x21)&(~(1<<irq)));
+     }
+   else
+     {
+       outb(0xa1,inb(0xa1)&(~(1<<(irq-8))));
+     }
+
+   return TRUE;
+}
 
+/* EOF */