Implemented missing KeRaiseIrqlToXxLevel() functions
[reactos.git] / reactos / ntoskrnl / hal / x86 / irql.c
index 878d3f5..fcfe713 100644 (file)
 /*
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
- * FILE:            mkernel/hal/irql.c
+ * FILE:            ntoskrnl/hal/x86/irql.c
  * PURPOSE:         Implements IRQLs
- * PROGRAMMER:      David Welch (welch@mcmail.com)
+ * PROGRAMMER:      David Welch (welch@cwcom.net)
  */
 
 /* INCLUDES *****************************************************************/
 
-#include <windows.h>
 #include <ddk/ntddk.h>
 #include <internal/bitops.h>
-#include <internal/hal/io.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
  */
 static KIRQL CurrentIrql = HIGH_LEVEL;
 
+extern ULONG DpcQueueSize;
+
+static VOID KeSetCurrentIrql(KIRQL newlvl);
+
 /* FUNCTIONS ****************************************************************/
 
-static unsigned int pic_get_current_mask(void)
+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)
 {
    unsigned int mask;
    
    mask = inb_p(0x21);
    mask = mask | (inb_p(0xa1)<<8);
+
+   return mask;
 }
+#endif
 
-static unsigned int pic_set_current_mask(unsigned int mask)
+static unsigned int HiSetCurrentPICMask(unsigned int mask)
 {
    outb_p(0x21,mask & 0xff);
    outb_p(0xa1,(mask >> 8) & 0xff);
+
+   return mask;
 }
 
-static void switch_irql(void)
+static VOID HiSwitchIrql(KIRQL oldIrql)
 /*
  * FUNCTION: Switches to the current irql
  * NOTE: Must be called with interrupt disabled
  */
 {
    unsigned int i;
+   PKTHREAD CurrentThread;
+   
+   CurrentThread = KeGetCurrentThread();
    
    if (CurrentIrql == HIGH_LEVEL)
      {
-       pic_set_current_mask(0xffff);
+       HiSetCurrentPICMask(0xffff);
        return;
      }
    if (CurrentIrql > DISPATCH_LEVEL)
      {
        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));
          }
        
-       pic_set_current_mask(current_mask);
+       HiSetCurrentPICMask(current_mask);
        __asm__("sti\n\t");
        return;
      }
    
-   if (CurrentIrql <= DISPATCH_LEVEL)
+   if (CurrentIrql == DISPATCH_LEVEL)
      {
-       pic_set_current_mask(0);
+       HiSetCurrentPICMask(0);
        __asm__("sti\n\t");
        return;
      }
+   
+   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");
+     }
+}
+
+
+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
  */
 {
-   DPRINT("KeSetCurrentIrql(newlvl %x)\n",newlvl);
+//   DPRINT("KeSetCurrentIrql(newlvl %x)\n",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
+       )
 {
-   __asm__("cli\n\t");
-   
-   DPRINT("NewIrql %x CurrentIrql %x\n",NewIrql,CurrentIrql);
-   assert(NewIrql <= CurrentIrql);
-   CurrentIrql = NewIrql;
-   switch_irql();
+       KfLowerIrql (NewIrql);
 }
 
-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
+
+/**********************************************************************
+ * 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)
 {
-   /*
-    * sanity check
-    */
-//   printk("CurrentIrql %x NewIrql %x OldIrql %x\n",CurrentIrql,NewIrql,
-//       OldIrql);
-   if (NewIrql < CurrentIrql)
+       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)
      {
-       printk("%s:%d\n",__FILE__,__LINE__);
-       for(;;);
+       outb(0xa0,0x20);
      }
-   
-   __asm__("cli\n\t");
-   *OldIrql = CurrentIrql;
-   CurrentIrql = NewIrql;
-//   *OldIrql = InterlockedExchange(&CurrentIrql,NewIrql);
-   DPRINT("NewIrql %x OldIrql %x CurrentIrql %x\n",NewIrql,*OldIrql,
-          CurrentIrql);
-   switch_irql();
+
+   *OldIrql = KeGetCurrentIrql();
+   if (Vector-IRQ_BASE != 0)
+     {
+       DPRINT("old_level %d\n",*OldIrql);
+     }
+   KeSetCurrentIrql(Irql);
+
+   return TRUE;
+}
+
+
+VOID STDCALL HalEndSystemInterrupt (KIRQL Irql,
+                                   ULONG Unknown2)
+{
+   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)
+     {
+       outb(0x21,inb(0x21)|(1<<irq));
+     }
+   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 */