X-Git-Url: https://git.reactos.org/?p=reactos.git;a=blobdiff_plain;f=hal%2Fhalx86%2Fup%2Fpic.c;h=186548c1b9d5eacb8ce091cd8c4277eb8a9523c1;hp=91b902b1a3566d303dbe8cc6308cb7d1f64981c3;hb=040d78354e7da85350629a8b28f303d959a81f9c;hpb=5f2d67cb359d16ef3713e96975e0416c07b00dd8 diff --git a/hal/halx86/up/pic.c b/hal/halx86/up/pic.c index 91b902b1a35..f61bf738d0a 100644 --- a/hal/halx86/up/pic.c +++ b/hal/halx86/up/pic.c @@ -1,7 +1,7 @@ /* * PROJECT: ReactOS HAL * LICENSE: BSD - See COPYING.ARM in the top level directory - * FILE: hal/halx86/generic/pic.c + * FILE: hal/halx86/up/pic.c * PURPOSE: HAL PIC Management and Control Code * PROGRAMMERS: ReactOS Portable Systems Group */ @@ -12,6 +12,11 @@ #define NDEBUG #include +VOID +NTAPI +HalpEndSoftwareInterrupt(IN KIRQL OldIrql, + IN PKTRAP_FRAME TrapFrame); + /* GLOBALS ********************************************************************/ #ifndef _MINIHAL_ @@ -44,7 +49,7 @@ * IRQ2 since the line was asserted by the slave when it received the spurious * IRQ15! * - * - When the 80287/80387 math co-processor generates an FPU/NPX trap, this is + * - When the 80287/80387 math co-processor generates an FPU/NPX trap, this is * connected to IRQ13, so we have to clear the busy latch on the NPX port. */ PHAL_DISMISS_INTERRUPT HalpSpecialDismissTable[16] = @@ -94,8 +99,7 @@ PHAL_DISMISS_INTERRUPT HalpSpecialDismissLevelTable[16] = /* This table contains the static x86 PIC mapping between IRQLs and IRQs */ ULONG KiI8259MaskTable[32] = { -#if defined(__GNUC__) && \ - (__GNUC__ * 100 + __GNUC_MINOR__ >= 404) +#if defined(__GNUC__) || defined(__clang__) || (defined(_MSC_VER) && _MSC_VER >= 1900) /* * It Device IRQLs only start at 4 or higher, so these are just software * IRQLs that don't really change anything on the hardware @@ -104,7 +108,7 @@ ULONG KiI8259MaskTable[32] = 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 @@ -118,7 +122,7 @@ ULONG KiI8259MaskTable[32] = 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 @@ -132,7 +136,7 @@ ULONG KiI8259MaskTable[32] = 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 @@ -149,7 +153,7 @@ ULONG KiI8259MaskTable[32] = 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 @@ -160,7 +164,7 @@ ULONG KiI8259MaskTable[32] = * 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. @@ -211,8 +215,7 @@ ULONG KiI8259MaskTable[32] = /* This table indicates which IRQs, if pending, can preempt a given IRQL level */ ULONG FindHigherIrqlMask[32] = { -#if defined(__GNUC__) && \ - (__GNUC__ * 100 + __GNUC_MINOR__ >= 404) +#if defined(__GNUC__) || defined(__clang__) || (defined(_MSC_VER) && _MSC_VER >= 1900) /* * Software IRQLs, at these levels all hardware interrupts can preempt. * Each higher IRQL simply enables which software IRQL can preempt the @@ -221,13 +224,13 @@ ULONG FindHigherIrqlMask[32] = 0b11111111111111111111111111111110, /* IRQL 0 */ 0b11111111111111111111111111111100, /* IRQL 1 */ 0b11111111111111111111111111111000, /* IRQL 2 */ - + /* * IRQL3 means only hardware IRQLs can now preempt. These last 4 zeros will * then continue throughout the rest of the list, trickling down. */ 0b11111111111111111111111111110000, /* IRQL 3 */ - + /* * Just like in the previous list, these masks don't really mean anything * since we've only got two PICs with 16 possible IRQs total @@ -239,7 +242,7 @@ ULONG FindHigherIrqlMask[32] = 0b00000000011111111111111111110000, /* IRQL 8 */ 0b00000000001111111111111111110000, /* IRQL 9 */ 0b00000000000111111111111111110000, /* IRQL 10 */ - + /* * Now we start progressivly limiting which slave PIC interrupts have the * right to preempt us at each level. @@ -253,7 +256,7 @@ ULONG FindHigherIrqlMask[32] = 0b00000000000000000011111111110000, /* IRQL 17 */ 0b00000000000000000001111111110000, /* IRQL 18 */ 0b00000000000000000001111111110000, /* IRQL 19 */ - + /* * Also recall from the earlier table that IRQL 18/19 are treated the same * in order to spread the masks better thoughout the 32 IRQLs and to reflect @@ -263,21 +266,21 @@ ULONG FindHigherIrqlMask[32] = * so it will always preempt until we reach PROFILE_LEVEL. */ 0b00000000000000000001011111110000, /* IRQL 20 */ - 0b00000000000000000001001111110000, /* IRQL 20 */ + 0b00000000000000000001001111110000, /* IRQL 21 */ 0b00000000000000000001000111110000, /* IRQL 22 */ 0b00000000000000000001000011110000, /* IRQL 23 */ 0b00000000000000000001000001110000, /* IRQL 24 */ 0b00000000000000000001000000110000, /* IRQL 25 */ 0b00000000000000000001000000010000, /* IRQL 26 */ - + /* At this point, only the clock (IRQ0) can still preempt... */ 0b00000000000000000000000000010000, /* IRQL 27 */ - + /* And any higher than that there's no relation with hardware PICs anymore */ 0b00000000000000000000000000000000, /* IRQL 28 */ 0b00000000000000000000000000000000, /* IRQL 29 */ 0b00000000000000000000000000000000, /* IRQL 30 */ - 0b00000000000000000000000000000000, /* IRQL 31 */ + 0b00000000000000000000000000000000 /* IRQL 31 */ #else 0xFFFFFFFE, /* IRQL 0 */ 0xFFFFFFFC, /* IRQL 1 */ @@ -330,8 +333,9 @@ KIRQL SWInterruptLookUpTable[8] = #if defined(__GNUC__) #define HalpDelayedHardwareInterrupt(x) \ - VOID HalpHardwareInterrupt##x(VOID); \ + VOID __cdecl HalpHardwareInterrupt##x(VOID); \ VOID \ + __cdecl \ HalpHardwareInterrupt##x(VOID) \ { \ asm volatile ("int $%c0\n"::"i"(PRIMARY_VECTOR_BASE + x)); \ @@ -340,8 +344,9 @@ KIRQL SWInterruptLookUpTable[8] = #elif defined(_MSC_VER) #define HalpDelayedHardwareInterrupt(x) \ - VOID HalpHardwareInterrupt##x(VOID); \ + VOID __cdecl HalpHardwareInterrupt##x(VOID); \ VOID \ + __cdecl \ HalpHardwareInterrupt##x(VOID) \ { \ __asm \ @@ -375,10 +380,10 @@ HalpDelayedHardwareInterrupt(15); /* Handlers for pending interrupts */ PHAL_SW_INTERRUPT_HANDLER SWInterruptHandlerTable[20] = { - KiUnexpectedInterrupt, + (PHAL_SW_INTERRUPT_HANDLER)KiUnexpectedInterrupt, HalpApcInterrupt, HalpDispatchInterrupt2, - KiUnexpectedInterrupt, + (PHAL_SW_INTERRUPT_HANDLER)KiUnexpectedInterrupt, HalpHardwareInterrupt0, HalpHardwareInterrupt1, HalpHardwareInterrupt2, @@ -414,85 +419,26 @@ NTAPI HalpInitializePICs(IN BOOLEAN EnableInterrupts) { ULONG EFlags; - I8259_ICW1 Icw1; - I8259_ICW2 Icw2; - I8259_ICW3 Icw3; - I8259_ICW4 Icw4; EISA_ELCR Elcr; ULONG i, j; - + /* Save EFlags and disable interrupts */ EFlags = __readeflags(); _disable(); - - /* Initialize ICW1 for master, interval 8, edge-triggered mode with ICW4 */ - Icw1.NeedIcw4 = TRUE; - Icw1.InterruptMode = EdgeTriggered; - Icw1.OperatingMode = Cascade; - Icw1.Interval = Interval8; - Icw1.Init = TRUE; - Icw1.InterruptVectorAddress = 0; /* This is only used in MCS80/85 mode */ - __outbyte(PIC1_CONTROL_PORT, Icw1.Bits); - - /* Set interrupt vector base */ - Icw2.Bits = PRIMARY_VECTOR_BASE; - __outbyte(PIC1_DATA_PORT, Icw2.Bits); - - /* Connect slave to IRQ 2 */ - Icw3.Bits = 0; - Icw3.SlaveIrq2 = TRUE; - __outbyte(PIC1_DATA_PORT, Icw3.Bits); - - /* Enable 8086 mode, non-automatic EOI, non-buffered mode, non special fully nested mode */ - Icw4.Reserved = 0; - Icw4.SystemMode = New8086Mode; - Icw4.EoiMode = NormalEoi; - Icw4.BufferedMode = NonBuffered; - Icw4.SpecialFullyNestedMode = FALSE; - __outbyte(PIC1_DATA_PORT, Icw4.Bits); - - /* Mask all interrupts */ - __outbyte(PIC1_DATA_PORT, 0xFF); - - /* Initialize ICW1 for master, interval 8, edge-triggered mode with ICW4 */ - Icw1.NeedIcw4 = TRUE; - Icw1.InterruptMode = EdgeTriggered; - Icw1.OperatingMode = Cascade; - Icw1.Interval = Interval8; - Icw1.Init = TRUE; - Icw1.InterruptVectorAddress = 0; /* This is only used in MCS80/85 mode */ - __outbyte(PIC2_CONTROL_PORT, Icw1.Bits); - - /* Set interrupt vector base */ - Icw2.Bits = PRIMARY_VECTOR_BASE + 8; - __outbyte(PIC2_DATA_PORT, Icw2.Bits); - - /* Slave ID */ - Icw3.Bits = 0; - Icw3.SlaveId = 2; - __outbyte(PIC2_DATA_PORT, Icw3.Bits); - - /* Enable 8086 mode, non-automatic EOI, non-buffered mode, non special fully nested mode */ - Icw4.Reserved = 0; - Icw4.SystemMode = New8086Mode; - Icw4.EoiMode = NormalEoi; - Icw4.BufferedMode = NonBuffered; - Icw4.SpecialFullyNestedMode = FALSE; - __outbyte(PIC2_DATA_PORT, Icw4.Bits); - - /* Mask all interrupts */ - __outbyte(PIC2_DATA_PORT, 0xFF); - + + /* Initialize and mask the PIC */ + HalpInitializeLegacyPICs(); + /* Read EISA Edge/Level Register for master and slave */ Elcr.Bits = (__inbyte(EISA_ELCR_SLAVE) << 8) | __inbyte(EISA_ELCR_MASTER); - + /* IRQs 0, 1, 2, 8, and 13 are system-reserved and must be edge */ if (!(Elcr.Master.Irq0Level) && !(Elcr.Master.Irq1Level) && !(Elcr.Master.Irq2Level) && !(Elcr.Slave.Irq8Level) && !(Elcr.Slave.Irq13Level)) { /* ELCR is as it's supposed to be, save it */ HalpEisaELCR = Elcr.Bits; - + /* Scan for level interrupts */ for (i = 1, j = 0; j < 16; i <<= 1, j++) { @@ -506,12 +452,39 @@ HalpInitializePICs(IN BOOLEAN EnableInterrupts) } } } - + + /* Register IRQ 2 */ + HalpRegisterVector(IDT_INTERNAL, + PRIMARY_VECTOR_BASE + 2, + PRIMARY_VECTOR_BASE + 2, + HIGH_LEVEL); + /* Restore interrupt state */ if (EnableInterrupts) EFlags |= EFLAGS_INTERRUPT_MASK; __writeeflags(EFlags); } +UCHAR +FASTCALL +HalpIrqToVector(UCHAR Irq) +{ + return (PRIMARY_VECTOR_BASE + Irq); +} + +UCHAR +FASTCALL +HalpVectorToIrq(UCHAR Vector) +{ + return (Vector - PRIMARY_VECTOR_BASE); +} + +KIRQL +FASTCALL +HalpVectorToIrql(UCHAR Vector) +{ + return (PROFILE_LEVEL - (Vector - PRIMARY_VECTOR_BASE)); +} + /* IRQL MANAGEMENT ************************************************************/ /* @@ -534,11 +507,11 @@ KeRaiseIrqlToDpcLevel(VOID) { PKPCR Pcr = KeGetPcr(); KIRQL CurrentIrql; - + /* Save and update IRQL */ CurrentIrql = Pcr->Irql; Pcr->Irql = DISPATCH_LEVEL; - + #if DBG /* Validate correct raise */ if (CurrentIrql > DISPATCH_LEVEL) KeBugCheck(IRQL_NOT_GREATER_OR_EQUAL); @@ -557,11 +530,11 @@ KeRaiseIrqlToSynchLevel(VOID) { PKPCR Pcr = KeGetPcr(); KIRQL CurrentIrql; - + /* Save and update IRQL */ CurrentIrql = Pcr->Irql; Pcr->Irql = SYNCH_LEVEL; - + #if DBG /* Validate correct raise */ if (CurrentIrql > SYNCH_LEVEL) @@ -591,7 +564,7 @@ KfRaiseIrql(IN KIRQL NewIrql) /* Read current IRQL */ CurrentIrql = Pcr->Irql; - + #if DBG /* Validate correct raise */ if (CurrentIrql > NewIrql) @@ -604,7 +577,7 @@ KfRaiseIrql(IN KIRQL NewIrql) /* Set new IRQL */ Pcr->Irql = NewIrql; - + /* Return old IRQL */ return CurrentIrql; } @@ -621,7 +594,7 @@ KfLowerIrql(IN KIRQL OldIrql) ULONG PendingIrql, PendingIrqlMask; PKPCR Pcr = KeGetPcr(); PIC_MASK Mask; - + #if DBG /* Validate correct lower */ if (OldIrql > Pcr->Irql) @@ -631,14 +604,14 @@ KfLowerIrql(IN KIRQL OldIrql) KeBugCheck(IRQL_NOT_LESS_OR_EQUAL); } #endif - + /* Save EFlags and disable interrupts */ EFlags = __readeflags(); _disable(); /* Set old IRQL */ Pcr->Irql = OldIrql; - + /* Check for pending software interrupts and compare with current IRQL */ PendingIrqlMask = Pcr->IRR & FindHigherIrqlMask[OldIrql]; if (PendingIrqlMask) @@ -648,14 +621,14 @@ KfLowerIrql(IN KIRQL OldIrql) if (PendingIrql > DISPATCH_LEVEL) { /* Set new PIC mask */ - Mask.Both = Pcr->IDR; + Mask.Both = Pcr->IDR & 0xFFFF; __outbyte(PIC1_DATA_PORT, Mask.Master); __outbyte(PIC2_DATA_PORT, Mask.Slave); - + /* Clear IRR bit */ Pcr->IRR ^= (1 << PendingIrql); } - + /* Now handle pending interrupt */ SWInterruptHandlerTable[PendingIrql](); } @@ -676,18 +649,18 @@ HalRequestSoftwareInterrupt(IN KIRQL Irql) ULONG EFlags; PKPCR Pcr = KeGetPcr(); KIRQL PendingIrql; - + /* Save EFlags and disable interrupts */ EFlags = __readeflags(); _disable(); - + /* Mask out the requested bit */ Pcr->IRR |= (1 << Irql); /* Check for pending software interrupts and compare with current IRQL */ PendingIrql = SWInterruptLookUpTable[Pcr->IRR & 3]; if (PendingIrql > Pcr->Irql) SWInterruptHandlerTable[PendingIrql](); - + /* Restore interrupt state */ __writeeflags(EFlags); } @@ -703,15 +676,17 @@ HalClearSoftwareInterrupt(IN KIRQL Irql) KeGetPcr()->IRR &= ~(1 << Irql); } -VOID -NTAPI -HalpEndSoftwareInterrupt(IN KIRQL OldIrql, - IN PKTRAP_FRAME TrapFrame) +PHAL_SW_INTERRUPT_HANDLER_2ND_ENTRY +FASTCALL +HalpEndSoftwareInterrupt2(IN KIRQL OldIrql, + IN PKTRAP_FRAME TrapFrame) { ULONG PendingIrql, PendingIrqlMask, PendingIrqMask; PKPCR Pcr = KeGetPcr(); PIC_MASK Mask; + UNREFERENCED_PARAMETER(TrapFrame); + /* Set old IRQL */ Pcr->Irql = OldIrql; @@ -720,17 +695,17 @@ HalpEndSoftwareInterrupt(IN KIRQL OldIrql, { /* Check for pending software interrupts and compare with current IRQL */ PendingIrqlMask = Pcr->IRR & FindHigherIrqlMask[OldIrql]; - if (!PendingIrqlMask) return; - + if (!PendingIrqlMask) return NULL; + /* Check for in-service delayed interrupt */ - if (Pcr->IrrActive & 0xFFFFFFF0) return; - + if (Pcr->IrrActive & 0xFFFFFFF0) return NULL; + /* Check if pending IRQL affects hardware state */ BitScanReverse(&PendingIrql, PendingIrqlMask); if (PendingIrql > DISPATCH_LEVEL) { /* Set new PIC mask */ - Mask.Both = Pcr->IDR; + Mask.Both = Pcr->IDR & 0xFFFF; __outbyte(PIC1_DATA_PORT, Mask.Master); __outbyte(PIC2_DATA_PORT, Mask.Slave); @@ -738,25 +713,27 @@ HalpEndSoftwareInterrupt(IN KIRQL OldIrql, PendingIrqMask = (1 << PendingIrql); Pcr->IrrActive |= PendingIrqMask; Pcr->IRR ^= PendingIrqMask; - + /* Handle delayed hardware interrupt */ SWInterruptHandlerTable[PendingIrql](); - + /* Handling complete */ Pcr->IrrActive ^= PendingIrqMask; } else { /* No need to loop checking for hardware interrupts */ - SWInterruptHandlerTable2[PendingIrql](TrapFrame); + return SWInterruptHandlerTable2[PendingIrql]; } } + + return NULL; } /* EDGE INTERRUPT DISMISSAL FUNCTIONS *****************************************/ -BOOLEAN FORCEINLINE +BOOLEAN _HalpDismissIrqGeneric(IN KIRQL Irql, IN ULONG Irq, OUT PKIRQL OldIrql) @@ -768,52 +745,52 @@ _HalpDismissIrqGeneric(IN KIRQL Irql, /* First save current IRQL and compare it to the requested one */ CurrentIrql = Pcr->Irql; - + /* Check if this interrupt is really allowed to happen */ if (Irql > CurrentIrql) { /* Set the new IRQL and return the current one */ Pcr->Irql = Irql; *OldIrql = CurrentIrql; - + /* Prepare OCW2 for EOI */ Ocw2.Bits = 0; Ocw2.EoiMode = SpecificEoi; /* Check which PIC needs the EOI */ - if (Irq > 8) + if (Irq >= 8) { /* Send the EOI for the IRQ */ - __outbyte(PIC2_CONTROL_PORT, Ocw2.Bits | (Irq - 8)); - + __outbyte(PIC2_CONTROL_PORT, Ocw2.Bits | ((Irq - 8) & 0xFF)); + /* Send the EOI for IRQ2 on the master because this was cascaded */ __outbyte(PIC1_CONTROL_PORT, Ocw2.Bits | 2); } else { /* Send the EOI for the IRQ */ - __outbyte(PIC1_CONTROL_PORT, Ocw2.Bits | Irq); + __outbyte(PIC1_CONTROL_PORT, Ocw2.Bits | (Irq &0xFF)); } - + /* Enable interrupts and return success */ _enable(); return TRUE; } - + /* Update the IRR so that we deliver this interrupt when the IRQL is proper */ Pcr->IRR |= (1 << (Irq + 4)); - + /* Set new PIC mask to real IRQL level, since the optimization is lost now */ - Mask.Both = KiI8259MaskTable[CurrentIrql] | Pcr->IDR; + Mask.Both = (KiI8259MaskTable[CurrentIrql] | Pcr->IDR) & 0xFFFF; __outbyte(PIC1_DATA_PORT, Mask.Master); __outbyte(PIC2_DATA_PORT, Mask.Slave); - + /* Now lie and say this was spurious */ return FALSE; } BOOLEAN -__attribute__((regparm(3))) +NTAPI HalpDismissIrqGeneric(IN KIRQL Irql, IN ULONG Irq, OUT PKIRQL OldIrql) @@ -823,7 +800,7 @@ HalpDismissIrqGeneric(IN KIRQL Irql, } BOOLEAN -__attribute__((regparm(3))) +NTAPI HalpDismissIrq15(IN KIRQL Irql, IN ULONG Irq, OUT PKIRQL OldIrql) @@ -831,16 +808,16 @@ HalpDismissIrq15(IN KIRQL Irql, I8259_OCW3 Ocw3; I8259_OCW2 Ocw2; I8259_ISR Isr; - + /* Request the ISR */ Ocw3.Bits = 0; Ocw3.Sbo = 1; /* This encodes an OCW3 vs. an OCW2 */ Ocw3.ReadRequest = ReadIsr; __outbyte(PIC2_CONTROL_PORT, Ocw3.Bits); - + /* Read the ISR */ Isr.Bits = __inbyte(PIC2_CONTROL_PORT); - + /* Is IRQ15 really active (this is IR7) */ if (Isr.Irq7 == FALSE) { @@ -848,7 +825,7 @@ HalpDismissIrq15(IN KIRQL Irql, Ocw2.Bits = 0; Ocw2.EoiMode = SpecificEoi; __outbyte(PIC1_CONTROL_PORT, Ocw2.Bits | 2); - + /* And now fail since this was spurious */ return FALSE; } @@ -859,47 +836,47 @@ HalpDismissIrq15(IN KIRQL Irql, BOOLEAN -__attribute__((regparm(3))) +NTAPI HalpDismissIrq13(IN KIRQL Irql, IN ULONG Irq, OUT PKIRQL OldIrql) { /* Clear the FPU busy latch */ __outbyte(0xF0, 0); - + /* Do normal interrupt dismiss */ return _HalpDismissIrqGeneric(Irql, Irq, OldIrql); } BOOLEAN -__attribute__((regparm(3))) +NTAPI HalpDismissIrq07(IN KIRQL Irql, IN ULONG Irq, OUT PKIRQL OldIrql) { I8259_OCW3 Ocw3; I8259_ISR Isr; - + /* Request the ISR */ Ocw3.Bits = 0; Ocw3.Sbo = 1; Ocw3.ReadRequest = ReadIsr; __outbyte(PIC1_CONTROL_PORT, Ocw3.Bits); - + /* Read the ISR */ Isr.Bits = __inbyte(PIC1_CONTROL_PORT); - + /* Is IRQ 7 really active? If it isn't, this is spurious so fail */ if (Isr.Irq7 == FALSE) return FALSE; - + /* Do normal interrupt dismiss */ return _HalpDismissIrqGeneric(Irql, Irq, OldIrql); } /* LEVEL INTERRUPT DISMISSAL FUNCTIONS ****************************************/ -BOOLEAN FORCEINLINE +BOOLEAN _HalpDismissIrqLevel(IN KIRQL Irql, IN ULONG Irq, OUT PKIRQL OldIrql) @@ -910,25 +887,25 @@ _HalpDismissIrqLevel(IN KIRQL Irql, PKPCR Pcr = KeGetPcr(); /* Update the PIC */ - Mask.Both = KiI8259MaskTable[Irql] | Pcr->IDR; + Mask.Both = (KiI8259MaskTable[Irql] | Pcr->IDR) & 0xFFFF; __outbyte(PIC1_DATA_PORT, Mask.Master); __outbyte(PIC2_DATA_PORT, Mask.Slave); - + /* Update the IRR so that we clear this interrupt when the IRQL is proper */ Pcr->IRR |= (1 << (Irq + 4)); - + /* Save current IRQL */ CurrentIrql = Pcr->Irql; - + /* Prepare OCW2 for EOI */ Ocw2.Bits = 0; Ocw2.EoiMode = SpecificEoi; /* Check which PIC needs the EOI */ - if (Irq > 8) + if (Irq >= 8) { /* Send the EOI for the IRQ */ - __outbyte(PIC2_CONTROL_PORT, Ocw2.Bits | (Irq - 8)); + __outbyte(PIC2_CONTROL_PORT, Ocw2.Bits | ((Irq - 8) & 0xFF)); /* Send the EOI for IRQ2 on the master because this was cascaded */ __outbyte(PIC1_CONTROL_PORT, Ocw2.Bits | 2); @@ -936,7 +913,7 @@ _HalpDismissIrqLevel(IN KIRQL Irql, else { /* Send the EOI for the IRQ */ - __outbyte(PIC1_CONTROL_PORT, Ocw2.Bits | Irq); + __outbyte(PIC1_CONTROL_PORT, Ocw2.Bits | (Irq & 0xFF)); } /* Check if this interrupt should be allowed to happen */ @@ -945,18 +922,18 @@ _HalpDismissIrqLevel(IN KIRQL Irql, /* Set the new IRQL and return the current one */ Pcr->Irql = Irql; *OldIrql = CurrentIrql; - + /* Enable interrupts and return success */ _enable(); return TRUE; } - + /* Now lie and say this was spurious */ return FALSE; } BOOLEAN -__attribute__((regparm(3))) +NTAPI HalpDismissIrqLevel(IN KIRQL Irql, IN ULONG Irq, OUT PKIRQL OldIrql) @@ -966,7 +943,7 @@ HalpDismissIrqLevel(IN KIRQL Irql, } BOOLEAN -__attribute__((regparm(3))) +NTAPI HalpDismissIrq15Level(IN KIRQL Irql, IN ULONG Irq, OUT PKIRQL OldIrql) @@ -974,16 +951,16 @@ HalpDismissIrq15Level(IN KIRQL Irql, I8259_OCW3 Ocw3; I8259_OCW2 Ocw2; I8259_ISR Isr; - + /* Request the ISR */ Ocw3.Bits = 0; Ocw3.Sbo = 1; /* This encodes an OCW3 vs. an OCW2 */ Ocw3.ReadRequest = ReadIsr; __outbyte(PIC2_CONTROL_PORT, Ocw3.Bits); - + /* Read the ISR */ Isr.Bits = __inbyte(PIC2_CONTROL_PORT); - + /* Is IRQ15 really active (this is IR7) */ if (Isr.Irq7 == FALSE) { @@ -991,7 +968,7 @@ HalpDismissIrq15Level(IN KIRQL Irql, Ocw2.Bits = 0; Ocw2.EoiMode = SpecificEoi; __outbyte(PIC1_CONTROL_PORT, Ocw2.Bits | 2); - + /* And now fail since this was spurious */ return FALSE; } @@ -1001,59 +978,60 @@ HalpDismissIrq15Level(IN KIRQL Irql, } BOOLEAN -__attribute__((regparm(3))) +NTAPI HalpDismissIrq13Level(IN KIRQL Irql, IN ULONG Irq, OUT PKIRQL OldIrql) { /* Clear the FPU busy latch */ __outbyte(0xF0, 0); - + /* Do normal interrupt dismiss */ return _HalpDismissIrqLevel(Irql, Irq, OldIrql); } BOOLEAN -__attribute__((regparm(3))) +NTAPI HalpDismissIrq07Level(IN KIRQL Irql, IN ULONG Irq, OUT PKIRQL OldIrql) { I8259_OCW3 Ocw3; I8259_ISR Isr; - + /* Request the ISR */ Ocw3.Bits = 0; Ocw3.Sbo = 1; Ocw3.ReadRequest = ReadIsr; __outbyte(PIC1_CONTROL_PORT, Ocw3.Bits); - + /* Read the ISR */ Isr.Bits = __inbyte(PIC1_CONTROL_PORT); - + /* Is IRQ 7 really active? If it isn't, this is spurious so fail */ if (Isr.Irq7 == FALSE) return FALSE; - + /* Do normal interrupt dismiss */ return _HalpDismissIrqLevel(Irql, Irq, OldIrql); } VOID +__cdecl HalpHardwareInterruptLevel(VOID) { PKPCR Pcr = KeGetPcr(); ULONG PendingIrqlMask, PendingIrql; - + /* Check for pending software interrupts and compare with current IRQL */ PendingIrqlMask = Pcr->IRR & FindHigherIrqlMask[Pcr->Irql]; if (PendingIrqlMask) { /* Check for in-service delayed interrupt */ if (Pcr->IrrActive & 0xFFFFFFF0) return; - + /* Check if pending IRQL affects hardware state */ BitScanReverse(&PendingIrql, PendingIrqlMask); - + /* Clear IRR bit */ Pcr->IRR ^= (1 << PendingIrql); @@ -1069,39 +1047,39 @@ HalpHardwareInterruptLevel(VOID) */ BOOLEAN NTAPI -HalEnableSystemInterrupt(IN UCHAR Vector, +HalEnableSystemInterrupt(IN ULONG Vector, IN KIRQL Irql, IN KINTERRUPT_MODE InterruptMode) { ULONG Irq; PKPCR Pcr = KeGetPcr(); PIC_MASK PicMask; - + /* Validate the IRQ */ Irq = Vector - PRIMARY_VECTOR_BASE; if (Irq >= CLOCK2_LEVEL) return FALSE; - + /* Check for level interrupt */ if (InterruptMode == LevelSensitive) { /* Switch handler to level */ SWInterruptHandlerTable[Irq + 4] = HalpHardwareInterruptLevel; - + /* Switch dismiss to level */ HalpSpecialDismissTable[Irq] = HalpSpecialDismissLevelTable[Irq]; } - + /* Disable interrupts */ _disable(); - + /* Update software IDR */ Pcr->IDR &= ~(1 << Irq); /* Set new PIC mask */ - PicMask.Both = KiI8259MaskTable[Pcr->Irql] | Pcr->IDR; + PicMask.Both = (KiI8259MaskTable[Pcr->Irql] | Pcr->IDR) & 0xFFFF; __outbyte(PIC1_DATA_PORT, PicMask.Master); __outbyte(PIC2_DATA_PORT, PicMask.Slave); - + /* Enable interrupts and exit */ _enable(); return TRUE; @@ -1112,7 +1090,7 @@ HalEnableSystemInterrupt(IN UCHAR Vector, */ VOID NTAPI -HalDisableSystemInterrupt(IN UCHAR Vector, +HalDisableSystemInterrupt(IN ULONG Vector, IN KIRQL Irql) { ULONG IrqMask; @@ -1120,24 +1098,24 @@ HalDisableSystemInterrupt(IN UCHAR Vector, /* Compute new combined IRQ mask */ IrqMask = 1 << (Vector - PRIMARY_VECTOR_BASE); - + /* Disable interrupts */ _disable(); - + /* Update software IDR */ KeGetPcr()->IDR |= IrqMask; - + /* Read current interrupt mask */ PicMask.Master = __inbyte(PIC1_DATA_PORT); PicMask.Slave = __inbyte(PIC2_DATA_PORT); - + /* Add the new disabled interrupt */ PicMask.Both |= IrqMask; - + /* Write new interrupt mask */ __outbyte(PIC1_DATA_PORT, PicMask.Master); __outbyte(PIC2_DATA_PORT, PicMask.Slave); - + /* Bring interrupts back */ _enable(); } @@ -1148,11 +1126,11 @@ HalDisableSystemInterrupt(IN UCHAR Vector, BOOLEAN NTAPI HalBeginSystemInterrupt(IN KIRQL Irql, - IN UCHAR Vector, + IN ULONG Vector, OUT PKIRQL OldIrql) { ULONG Irq; - + /* Get the IRQ and call the proper routine to handle it */ Irq = Vector - PRIMARY_VECTOR_BASE; return HalpSpecialDismissTable[Irq](Irql, Irq, OldIrql); @@ -1179,7 +1157,7 @@ HalEndSystemInterrupt(IN KIRQL OldIrql, { /* Check for in-service delayed interrupt */ if (Pcr->IrrActive & 0xFFFFFFF0) return; - + /* Loop checking for pending interrupts */ while (TRUE) { @@ -1188,24 +1166,24 @@ HalEndSystemInterrupt(IN KIRQL OldIrql, if (PendingIrql > DISPATCH_LEVEL) { /* Set new PIC mask */ - Mask.Both = Pcr->IDR; + Mask.Both = Pcr->IDR & 0xFFFF; __outbyte(PIC1_DATA_PORT, Mask.Master); __outbyte(PIC2_DATA_PORT, Mask.Slave); - + /* Now check if this specific interrupt is already in-service */ PendingIrqMask = (1 << PendingIrql); if (Pcr->IrrActive & PendingIrqMask) return; - + /* Set active bit otherwise, and clear it from IRR */ Pcr->IrrActive |= PendingIrqMask; Pcr->IRR ^= PendingIrqMask; - + /* Handle delayed hardware interrupt */ SWInterruptHandlerTable[PendingIrql](); - + /* Handling complete */ Pcr->IrrActive ^= PendingIrqMask; - + /* Check if there's still interrupts pending */ PendingIrqlMask = Pcr->IRR & FindHigherIrqlMask[Pcr->Irql]; if (!PendingIrqlMask) break; @@ -1214,6 +1192,7 @@ HalEndSystemInterrupt(IN KIRQL OldIrql, { /* Now handle pending software interrupt */ SWInterruptHandlerTable2[PendingIrql](TrapFrame); + UNREACHABLE; } } } @@ -1221,14 +1200,14 @@ HalEndSystemInterrupt(IN KIRQL OldIrql, /* SOFTWARE INTERRUPT TRAPS ***************************************************/ -VOID FORCEINLINE DECLSPEC_NORETURN +VOID _HalpApcInterruptHandler(IN PKTRAP_FRAME TrapFrame) { KIRQL CurrentIrql; PKPCR Pcr = KeGetPcr(); - + /* Save the current IRQL and update it */ CurrentIrql = Pcr->Irql; Pcr->Irql = APC_LEVEL; @@ -1248,76 +1227,77 @@ _HalpApcInterruptHandler(IN PKTRAP_FRAME TrapFrame) HalpEndSoftwareInterrupt(CurrentIrql, TrapFrame); /* Exit the interrupt */ - KiEoiHelper(TrapFrame); + KiEoiHelper(TrapFrame); } +DECLSPEC_NORETURN VOID FASTCALL -DECLSPEC_NORETURN HalpApcInterrupt2ndEntry(IN PKTRAP_FRAME TrapFrame) { /* Do the work */ _HalpApcInterruptHandler(TrapFrame); } +DECLSPEC_NORETURN VOID FASTCALL -DECLSPEC_NORETURN HalpApcInterruptHandler(IN PKTRAP_FRAME TrapFrame) { /* Set up a fake INT Stack */ TrapFrame->EFlags = __readeflags(); TrapFrame->SegCs = KGDT_R0_CODE; TrapFrame->Eip = TrapFrame->Eax; - + /* Build the trap frame */ KiEnterInterruptTrap(TrapFrame); - + /* Do the work */ _HalpApcInterruptHandler(TrapFrame); } -KIRQL FORCEINLINE +KIRQL _HalpDispatchInterruptHandler(VOID) { KIRQL CurrentIrql; PKPCR Pcr = KeGetPcr(); - + /* Save the current IRQL and update it */ CurrentIrql = Pcr->Irql; Pcr->Irql = DISPATCH_LEVEL; - + /* Remove DPC from IRR */ Pcr->IRR &= ~(1 << DISPATCH_LEVEL); - + /* Enable interrupts and call the kernel's DPC interrupt handler */ _enable(); KiDispatchInterrupt(); _disable(); - + /* Return IRQL */ return CurrentIrql; } +DECLSPEC_NORETURN VOID FASTCALL -DECLSPEC_NORETURN HalpDispatchInterrupt2ndEntry(IN PKTRAP_FRAME TrapFrame) { KIRQL CurrentIrql; - + /* Do the work */ CurrentIrql = _HalpDispatchInterruptHandler(); - + /* End the interrupt */ HalpEndSoftwareInterrupt(CurrentIrql, TrapFrame); - + /* Exit the interrupt */ KiEoiHelper(TrapFrame); } VOID +__cdecl HalpDispatchInterrupt2(VOID) { ULONG PendingIrqlMask, PendingIrql; @@ -1327,7 +1307,7 @@ HalpDispatchInterrupt2(VOID) /* Do the work */ OldIrql = _HalpDispatchInterruptHandler(); - + /* Restore IRQL */ Pcr->Irql = OldIrql; @@ -1340,14 +1320,14 @@ HalpDispatchInterrupt2(VOID) if (PendingIrql > DISPATCH_LEVEL) { /* Set new PIC mask */ - Mask.Both = Pcr->IDR; + Mask.Both = Pcr->IDR & 0xFFFF; __outbyte(PIC1_DATA_PORT, Mask.Master); __outbyte(PIC2_DATA_PORT, Mask.Slave); - + /* Clear IRR bit */ Pcr->IRR ^= (1 << PendingIrql); } - + /* Now handle pending interrupt */ SWInterruptHandlerTable[PendingIrql](); }