Author: sir_richard
Date: Mon Jan 25 00:19:40 2010
New Revision: 45235
URL:
http://svn.reactos.org/svn/reactos?rev=45235&view=rev
Log:
[HAL]: Document and implement KiI8259MaskTable in C using actual bit positions. Each
mapping is best to the best of my ability.
[HAL]: Implement KfRaiseIrql in C, remove ASM version.
Modified:
trunk/reactos/hal/halx86/generic/irq.S
trunk/reactos/hal/halx86/generic/pic.c
trunk/reactos/hal/halx86/include/halp.h
Modified: trunk/reactos/hal/halx86/generic/irq.S
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halx86/generic/irq.S?r…
==============================================================================
--- trunk/reactos/hal/halx86/generic/irq.S [iso-8859-1] (original)
+++ trunk/reactos/hal/halx86/generic/irq.S [iso-8859-1] Mon Jan 25 00:19:40 2010
@@ -624,67 +624,6 @@
ret
.endfunc
-.globl @KfRaiseIrql@4
-.func @KfRaiseIrql@4
-_@KfRaiseIrql@4:
-@KfRaiseIrql@4:
-
- /* Get the IRQL */
- movzx ecx, cl
- mov eax, PCR[KPCR_IRQL]
-
-#if DBG
- /* Validate it */
- cmp eax, ecx
- ja InvalidKfRaise
-#endif
-
- /* Check if it's in the software level */
- cmp cl, DISPATCH_LEVEL
- jbe SetIrql
-
- /* Save the current IRQL */
- mov edx, eax
-
- /* It's a hardware IRQL, so disable interrupts */
- pushf
- cli
-
- /* Set the new IRQL */
- mov PCR[KPCR_IRQL], ecx
-
- /* Mask the interrupts in the PIC */
- mov eax, KiI8259MaskTable[ecx*4]
- or eax, PCR[KPCR_IDR]
- out 0x21, al
- shr eax, 8
- out 0xA1, al
-
- /* Restore interrupts and return old IRQL */
- popf
- mov eax, edx
- ret
-
-SetIrql:
- /* Set the IRQL and return */
- mov PCR[KPCR_IRQL], ecx
- ret
-
-#if DBG
-InvalidKfRaise:
- /* Set to passive */
- mov dword ptr PCR[KPCR_IRQL], PASSIVE_LEVEL
-
- /* Bugcheck the system */
- push 9
- push 0
- push ecx
- push eax
- push IRQL_NOT_GREATER_OR_EQUAL
- call _KeBugCheckEx@20
-#endif
-.endfunc
-
.globl _HalpApcInterrupt
.func HalpApcInterrupt
TRAP_FIXUPS hapc_a, hapc_t, DoFixupV86, DoFixupAbios
Modified: trunk/reactos/hal/halx86/generic/pic.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halx86/generic/pic.c?r…
==============================================================================
--- trunk/reactos/hal/halx86/generic/pic.c [iso-8859-1] (original)
+++ trunk/reactos/hal/halx86/generic/pic.c [iso-8859-1] Mon Jan 25 00:19:40 2010
@@ -13,6 +13,87 @@
#include <debug.h>
/* GLOBALS ********************************************************************/
+
+/* This table contains the static x86 PIC mapping between IRQLs and IRQs */
+ULONG KiI8259MaskTable[32] =
+{
+ /*
+ * It Device IRQLs only start at 4 or higher, so these are just software
+ * IRQLs that don't really change anything on the hardware
+ */
+ 0b00000000000000000000000000000000, /* IRQL 0 */
+ 0b00000000000000000000000000000000, /* IRQL 1 */
+ 0b00000000000000000000000000000000, /* IRQL 2 */
+ 0b00000000000000000000000000000000, /* IRQL 3 */
+
+ /*
+ * These next IRQLs are actually useless from the PIC perspective, because
+ * with only 2 PICs, the mask you can send them is only 8 bits each, for 16
+ * bits total, so these IRQLs are masking off a phantom PIC.
+ */
+ 0b11111111100000000000000000000000, /* IRQL 4 */
+ 0b11111111110000000000000000000000, /* IRQL 5 */
+ 0b11111111111000000000000000000000, /* IRQL 6 */
+ 0b11111111111100000000000000000000, /* IRQL 7 */
+ 0b11111111111110000000000000000000, /* IRQL 8 */
+ 0b11111111111111000000000000000000, /* IRQL 9 */
+ 0b11111111111111100000000000000000, /* IRQL 10 */
+ 0b11111111111111110000000000000000, /* IRQL 11 */
+
+ /*
+ * Okay, now we're finally starting to mask off IRQs on the slave PIC, from
+ * IRQ15 to IRQ8. This means the higher-level IRQs get less priority in the
+ * IRQL sense.
+ */
+ 0b11111111111111111000000000000000, /* IRQL 12 */
+ 0b11111111111111111100000000000000, /* IRQL 13 */
+ 0b11111111111111111110000000000000, /* IRQL 14 */
+ 0b11111111111111111111000000000000, /* IRQL 15 */
+ 0b11111111111111111111100000000000, /* IRQL 16 */
+ 0b11111111111111111111110000000000, /* IRQL 17 */
+ 0b11111111111111111111111000000000, /* IRQL 18 */
+ 0b11111111111111111111111000000000, /* IRQL 19 */
+
+ /*
+ * Now we mask off the IRQs on the master. Notice the 0 "droplet"? You
might
+ * have also seen that IRQL 18 and 19 are essentially equal as far as the
+ * PIC is concerned. That bit is actually IRQ8, which happens to be the RTC.
+ * The RTC will keep firing as long as we don't reach PROFILE_LEVEL which
+ * actually kills it. The RTC clock (unlike the system clock) is used by the
+ * profiling APIs in the HAL, so that explains the logic.
+ */
+ 0b11111111111111111111111010000000, /* IRQL 20 */
+ 0b11111111111111111111111011000000, /* IRQL 21 */
+ 0b11111111111111111111111011100000, /* IRQL 22 */
+ 0b11111111111111111111111011110000, /* IRQL 23 */
+ 0b11111111111111111111111011111000, /* IRQL 24 */
+ 0b11111111111111111111111011111000, /* IRQL 25 */
+ 0b11111111111111111111111011111010, /* IRQL 26 */
+ 0b11111111111111111111111111111010, /* IRQL 27 */
+
+ /*
+ * IRQL 24 and 25 are actually identical, so IRQL 28 is actually the last
+ * IRQL to modify a bit on the master PIC. It happens to modify the very
+ * last of the IRQs, IRQ0, which corresponds to the system clock interval
+ * timer that keeps track of time (the Windows heartbeat). We only want to
+ * turn this off at a high-enough IRQL, which is why IRQLs 24 and 25 are the
+ * same to give this guy a chance to come up higher. Note that IRQL 28 is
+ * called CLOCK2_LEVEL, which explains the usage we just explained.
+ */
+ 0b11111111111111111111111111111011, /* IRQL 28 */
+
+ /*
+ * We have finished off with the PIC so there's nothing left to mask at the
+ * level of these IRQLs, making them only logical IRQLs on x86 machines.
+ * Note that we have another 0 "droplet" you might've caught since IRQL
26.
+ * In this case, it's the 2nd bit that never gets turned off, which is IRQ2,
+ * the cascade IRQ that we use to bridge the slave PIC with the master PIC.
+ * We never want to turn it off, so no matter the IRQL, it will be set to 0.
+ */
+ 0b11111111111111111111111111111011, /* IRQL 29 */
+ 0b11111111111111111111111111111011, /* IRQL 30 */
+ 0b11111111111111111111111111111011 /* IRQL 31 */
+};
USHORT HalpEisaELCR;
@@ -191,6 +272,62 @@
return CurrentIrql;
}
+/*
+ * @implemented
+ */
+KIRQL
+FASTCALL
+KfRaiseIrql(IN KIRQL NewIrql)
+{
+ PKPCR Pcr = KeGetPcr();
+ ULONG EFlags;
+ KIRQL CurrentIrql;
+ PIC_MASK Mask;
+
+ /* Read current IRQL */
+ CurrentIrql = Pcr->Irql;
+
+#ifdef IRQL_DEBUG
+ /* Validate correct raise */
+ if (CurrentIrql > NewIrql)
+ {
+ /* Crash system */
+ Pcr->Irql = PASSIVE_LEVEL;
+ KeBugCheckEx(IRQL_NOT_GREATER_OR_EQUAL,
+ CurrentIrql,
+ NewIrql,
+ 0,
+ 9);
+ }
+#endif
+
+ /* Check if new IRQL affects hardware state */
+ if (NewIrql > DISPATCH_LEVEL)
+ {
+ /* Save current interrupt state and disable interrupts */
+ EFlags = __readeflags();
+ _disable();
+
+ /* Update the IRQL */
+ Pcr->Irql = NewIrql;
+
+ /* Set new PIC mask */
+ Mask.Both = KiI8259MaskTable[NewIrql] | Pcr->IDR;
+ __outbyte(PIC1_DATA_PORT, Mask.Master);
+ __outbyte(PIC2_DATA_PORT, Mask.Slave);
+
+ /* Restore interrupt state */
+ __writeeflags(EFlags);
+ }
+ else
+ {
+ /* Set new IRQL */
+ Pcr->Irql = NewIrql;
+ }
+
+ /* Return old IRQL */
+ return CurrentIrql;
+}
/* SOFTWARE INTERRUPTS ********************************************************/
Modified: trunk/reactos/hal/halx86/include/halp.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halx86/include/halp.h?…
==============================================================================
--- trunk/reactos/hal/halx86/include/halp.h [iso-8859-1] (original)
+++ trunk/reactos/hal/halx86/include/halp.h [iso-8859-1] Mon Jan 25 00:19:40 2010
@@ -282,6 +282,19 @@
USHORT Bits;
} EISA_ELCR, *PEISA_ELCR;
+typedef struct _PIC_MASK
+{
+ union
+ {
+ struct
+ {
+ UCHAR Master;
+ UCHAR Slave;
+ };
+ USHORT Both;
+ };
+} PIC_MASK, *PPIC_MASK;
+
//
// Mm PTE/PDE to Hal PTE/PDE
//