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?re... ============================================================================== --- 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?re... ============================================================================== --- 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?r... ============================================================================== --- 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 //