17601fb54SVictor Perevertkin /*
27601fb54SVictor Perevertkin * PROJECT: ReactOS HAL
37601fb54SVictor Perevertkin * LICENSE: BSD - See COPYING.ARM in the top level directory
47601fb54SVictor Perevertkin * PURPOSE: HAL PIC Management and Control Code
57601fb54SVictor Perevertkin * PROGRAMMERS: ReactOS Portable Systems Group
67601fb54SVictor Perevertkin */
77601fb54SVictor Perevertkin
87601fb54SVictor Perevertkin /* INCLUDES *******************************************************************/
97601fb54SVictor Perevertkin
107601fb54SVictor Perevertkin #include <hal.h>
117601fb54SVictor Perevertkin
127601fb54SVictor Perevertkin #define NDEBUG
137601fb54SVictor Perevertkin #include <debug.h>
147601fb54SVictor Perevertkin
157601fb54SVictor Perevertkin VOID
167601fb54SVictor Perevertkin NTAPI
177601fb54SVictor Perevertkin HalpEndSoftwareInterrupt(IN KIRQL OldIrql,
187601fb54SVictor Perevertkin IN PKTRAP_FRAME TrapFrame);
197601fb54SVictor Perevertkin
207601fb54SVictor Perevertkin /* GLOBALS ********************************************************************/
217601fb54SVictor Perevertkin
227601fb54SVictor Perevertkin #ifndef _MINIHAL_
237601fb54SVictor Perevertkin /*
247601fb54SVictor Perevertkin * This table basically keeps track of level vs edge triggered interrupts.
257601fb54SVictor Perevertkin * Windows has 250+ entries, but it seems stupid to replicate that since the PIC
267601fb54SVictor Perevertkin * can't actually have that many.
277601fb54SVictor Perevertkin *
287601fb54SVictor Perevertkin * When a level interrupt is registered, the respective pointer in this table is
297601fb54SVictor Perevertkin * modified to point to a dimiss routine for level interrupts instead.
307601fb54SVictor Perevertkin *
317601fb54SVictor Perevertkin * The other thing this table does is special case IRQ7, IRQ13 and IRQ15:
327601fb54SVictor Perevertkin *
337601fb54SVictor Perevertkin * - If an IRQ line is deasserted before it is acknowledged due to a noise spike
347601fb54SVictor Perevertkin * generated by an expansion device (since the IRQ line is low during the 1st
357601fb54SVictor Perevertkin * acknowledge bus cycle), the i8259 will keep the line low for at least 100ns
367601fb54SVictor Perevertkin * When the spike passes, a pull-up resistor will return the IRQ line to high.
377601fb54SVictor Perevertkin * Since the PIC requires the input be high until the first acknowledge, the
387601fb54SVictor Perevertkin * i8259 knows that this was a spurious interrupt, and on the second interrupt
397601fb54SVictor Perevertkin * acknowledge cycle, it reports this to the CPU. Since no valid interrupt has
407601fb54SVictor Perevertkin * actually happened Intel hardcoded the chip to report IRQ7 on the master PIC
417601fb54SVictor Perevertkin * and IRQ15 on the slave PIC (IR7 either way).
427601fb54SVictor Perevertkin *
437601fb54SVictor Perevertkin * "ISA System Architecture", 3rd Edition, states that these cases should be
447601fb54SVictor Perevertkin * handled by reading the respective Interrupt Service Request (ISR) bits from
457601fb54SVictor Perevertkin * the affected PIC, and validate whether or not IR7 is set. If it isn't, then
467601fb54SVictor Perevertkin * the interrupt is spurious and should be ignored.
477601fb54SVictor Perevertkin *
487601fb54SVictor Perevertkin * Note that for a spurious IRQ15, we DO have to send an EOI to the master for
497601fb54SVictor Perevertkin * IRQ2 since the line was asserted by the slave when it received the spurious
507601fb54SVictor Perevertkin * IRQ15!
517601fb54SVictor Perevertkin *
527601fb54SVictor Perevertkin * - When the 80287/80387 math co-processor generates an FPU/NPX trap, this is
537601fb54SVictor Perevertkin * connected to IRQ13, so we have to clear the busy latch on the NPX port.
547601fb54SVictor Perevertkin */
557601fb54SVictor Perevertkin PHAL_DISMISS_INTERRUPT HalpSpecialDismissTable[16] =
567601fb54SVictor Perevertkin {
577601fb54SVictor Perevertkin HalpDismissIrqGeneric,
587601fb54SVictor Perevertkin HalpDismissIrqGeneric,
597601fb54SVictor Perevertkin HalpDismissIrqGeneric,
607601fb54SVictor Perevertkin HalpDismissIrqGeneric,
617601fb54SVictor Perevertkin HalpDismissIrqGeneric,
627601fb54SVictor Perevertkin HalpDismissIrqGeneric,
637601fb54SVictor Perevertkin HalpDismissIrqGeneric,
647601fb54SVictor Perevertkin HalpDismissIrq07,
657601fb54SVictor Perevertkin #if defined(SARCH_PC98)
667601fb54SVictor Perevertkin HalpDismissIrq08,
677601fb54SVictor Perevertkin #else
687601fb54SVictor Perevertkin HalpDismissIrqGeneric,
697601fb54SVictor Perevertkin #endif
707601fb54SVictor Perevertkin HalpDismissIrqGeneric,
717601fb54SVictor Perevertkin HalpDismissIrqGeneric,
727601fb54SVictor Perevertkin HalpDismissIrqGeneric,
737601fb54SVictor Perevertkin HalpDismissIrqGeneric,
747601fb54SVictor Perevertkin #if defined(SARCH_PC98)
757601fb54SVictor Perevertkin HalpDismissIrqGeneric,
767601fb54SVictor Perevertkin #else
777601fb54SVictor Perevertkin HalpDismissIrq13,
787601fb54SVictor Perevertkin #endif
797601fb54SVictor Perevertkin HalpDismissIrqGeneric,
807601fb54SVictor Perevertkin HalpDismissIrq15
817601fb54SVictor Perevertkin };
827601fb54SVictor Perevertkin
837601fb54SVictor Perevertkin /*
847601fb54SVictor Perevertkin * These are the level IRQ dismissal functions that get copied in the table
857601fb54SVictor Perevertkin * above if the given IRQ is actually level triggered.
867601fb54SVictor Perevertkin */
877601fb54SVictor Perevertkin PHAL_DISMISS_INTERRUPT HalpSpecialDismissLevelTable[16] =
887601fb54SVictor Perevertkin {
897601fb54SVictor Perevertkin HalpDismissIrqLevel,
907601fb54SVictor Perevertkin HalpDismissIrqLevel,
917601fb54SVictor Perevertkin HalpDismissIrqLevel,
927601fb54SVictor Perevertkin HalpDismissIrqLevel,
937601fb54SVictor Perevertkin HalpDismissIrqLevel,
947601fb54SVictor Perevertkin HalpDismissIrqLevel,
957601fb54SVictor Perevertkin HalpDismissIrqLevel,
967601fb54SVictor Perevertkin HalpDismissIrq07Level,
977601fb54SVictor Perevertkin #if defined(SARCH_PC98)
987601fb54SVictor Perevertkin HalpDismissIrq08Level,
997601fb54SVictor Perevertkin #else
1007601fb54SVictor Perevertkin HalpDismissIrqLevel,
1017601fb54SVictor Perevertkin #endif
1027601fb54SVictor Perevertkin HalpDismissIrqLevel,
1037601fb54SVictor Perevertkin HalpDismissIrqLevel,
1047601fb54SVictor Perevertkin HalpDismissIrqLevel,
1057601fb54SVictor Perevertkin HalpDismissIrqLevel,
1067601fb54SVictor Perevertkin #if defined(SARCH_PC98)
1077601fb54SVictor Perevertkin HalpDismissIrqLevel,
1087601fb54SVictor Perevertkin #else
1097601fb54SVictor Perevertkin HalpDismissIrq13Level,
1107601fb54SVictor Perevertkin #endif
1117601fb54SVictor Perevertkin HalpDismissIrqLevel,
1127601fb54SVictor Perevertkin HalpDismissIrq15Level
1137601fb54SVictor Perevertkin };
1147601fb54SVictor Perevertkin
1157601fb54SVictor Perevertkin /* This table contains the static x86 PIC mapping between IRQLs and IRQs */
1167601fb54SVictor Perevertkin extern ULONG KiI8259MaskTable[32];
1177601fb54SVictor Perevertkin
1187601fb54SVictor Perevertkin /* This table indicates which IRQs, if pending, can preempt a given IRQL level */
1197601fb54SVictor Perevertkin extern ULONG FindHigherIrqlMask[32];
1207601fb54SVictor Perevertkin
1217601fb54SVictor Perevertkin /* Denotes minimum required IRQL before we can process pending SW interrupts */
1227601fb54SVictor Perevertkin KIRQL SWInterruptLookUpTable[8] =
1237601fb54SVictor Perevertkin {
1247601fb54SVictor Perevertkin PASSIVE_LEVEL, /* IRR 0 */
1257601fb54SVictor Perevertkin PASSIVE_LEVEL, /* IRR 1 */
1267601fb54SVictor Perevertkin APC_LEVEL, /* IRR 2 */
1277601fb54SVictor Perevertkin APC_LEVEL, /* IRR 3 */
1287601fb54SVictor Perevertkin DISPATCH_LEVEL, /* IRR 4 */
1297601fb54SVictor Perevertkin DISPATCH_LEVEL, /* IRR 5 */
1307601fb54SVictor Perevertkin DISPATCH_LEVEL, /* IRR 6 */
1317601fb54SVictor Perevertkin DISPATCH_LEVEL /* IRR 7 */
1327601fb54SVictor Perevertkin };
1337601fb54SVictor Perevertkin
1347601fb54SVictor Perevertkin #if defined(__GNUC__)
1357601fb54SVictor Perevertkin
1367601fb54SVictor Perevertkin #define HalpDelayedHardwareInterrupt(x) \
1377601fb54SVictor Perevertkin VOID __cdecl HalpHardwareInterrupt##x(VOID); \
1387601fb54SVictor Perevertkin VOID \
1397601fb54SVictor Perevertkin __cdecl \
1407601fb54SVictor Perevertkin HalpHardwareInterrupt##x(VOID) \
1417601fb54SVictor Perevertkin { \
1427601fb54SVictor Perevertkin asm volatile ("int $%c0\n"::"i"(PRIMARY_VECTOR_BASE + x)); \
1437601fb54SVictor Perevertkin }
1447601fb54SVictor Perevertkin
1457601fb54SVictor Perevertkin #elif defined(_MSC_VER)
1467601fb54SVictor Perevertkin
1477601fb54SVictor Perevertkin #define HalpDelayedHardwareInterrupt(x) \
1487601fb54SVictor Perevertkin VOID __cdecl HalpHardwareInterrupt##x(VOID); \
1497601fb54SVictor Perevertkin VOID \
1507601fb54SVictor Perevertkin __cdecl \
1517601fb54SVictor Perevertkin HalpHardwareInterrupt##x(VOID) \
1527601fb54SVictor Perevertkin { \
1537601fb54SVictor Perevertkin __asm \
1547601fb54SVictor Perevertkin { \
1557601fb54SVictor Perevertkin int PRIMARY_VECTOR_BASE + x \
1567601fb54SVictor Perevertkin } \
1577601fb54SVictor Perevertkin }
1587601fb54SVictor Perevertkin
1597601fb54SVictor Perevertkin #else
1607601fb54SVictor Perevertkin #error Unsupported compiler
1617601fb54SVictor Perevertkin #endif
1627601fb54SVictor Perevertkin
1637601fb54SVictor Perevertkin /* Pending/delayed hardware interrupt handlers */
1647601fb54SVictor Perevertkin HalpDelayedHardwareInterrupt(0);
1657601fb54SVictor Perevertkin HalpDelayedHardwareInterrupt(1);
1667601fb54SVictor Perevertkin HalpDelayedHardwareInterrupt(2);
1677601fb54SVictor Perevertkin HalpDelayedHardwareInterrupt(3);
1687601fb54SVictor Perevertkin HalpDelayedHardwareInterrupt(4);
1697601fb54SVictor Perevertkin HalpDelayedHardwareInterrupt(5);
1707601fb54SVictor Perevertkin HalpDelayedHardwareInterrupt(6);
1717601fb54SVictor Perevertkin HalpDelayedHardwareInterrupt(7);
1727601fb54SVictor Perevertkin HalpDelayedHardwareInterrupt(8);
1737601fb54SVictor Perevertkin HalpDelayedHardwareInterrupt(9);
1747601fb54SVictor Perevertkin HalpDelayedHardwareInterrupt(10);
1757601fb54SVictor Perevertkin HalpDelayedHardwareInterrupt(11);
1767601fb54SVictor Perevertkin HalpDelayedHardwareInterrupt(12);
1777601fb54SVictor Perevertkin HalpDelayedHardwareInterrupt(13);
1787601fb54SVictor Perevertkin HalpDelayedHardwareInterrupt(14);
1797601fb54SVictor Perevertkin HalpDelayedHardwareInterrupt(15);
1807601fb54SVictor Perevertkin
1817601fb54SVictor Perevertkin /* Handlers for pending interrupts */
1827601fb54SVictor Perevertkin PHAL_SW_INTERRUPT_HANDLER SWInterruptHandlerTable[20] =
1837601fb54SVictor Perevertkin {
1847601fb54SVictor Perevertkin (PHAL_SW_INTERRUPT_HANDLER)KiUnexpectedInterrupt,
1857601fb54SVictor Perevertkin HalpApcInterrupt,
1867601fb54SVictor Perevertkin HalpDispatchInterrupt,
1877601fb54SVictor Perevertkin (PHAL_SW_INTERRUPT_HANDLER)KiUnexpectedInterrupt,
1887601fb54SVictor Perevertkin HalpHardwareInterrupt0,
1897601fb54SVictor Perevertkin HalpHardwareInterrupt1,
1907601fb54SVictor Perevertkin HalpHardwareInterrupt2,
1917601fb54SVictor Perevertkin HalpHardwareInterrupt3,
1927601fb54SVictor Perevertkin HalpHardwareInterrupt4,
1937601fb54SVictor Perevertkin HalpHardwareInterrupt5,
1947601fb54SVictor Perevertkin HalpHardwareInterrupt6,
1957601fb54SVictor Perevertkin HalpHardwareInterrupt7,
1967601fb54SVictor Perevertkin HalpHardwareInterrupt8,
1977601fb54SVictor Perevertkin HalpHardwareInterrupt9,
1987601fb54SVictor Perevertkin HalpHardwareInterrupt10,
1997601fb54SVictor Perevertkin HalpHardwareInterrupt11,
2007601fb54SVictor Perevertkin HalpHardwareInterrupt12,
2017601fb54SVictor Perevertkin HalpHardwareInterrupt13,
2027601fb54SVictor Perevertkin HalpHardwareInterrupt14,
2037601fb54SVictor Perevertkin HalpHardwareInterrupt15
2047601fb54SVictor Perevertkin };
2057601fb54SVictor Perevertkin
2067601fb54SVictor Perevertkin /* Handlers for pending software interrupts when we already have a trap frame*/
2077601fb54SVictor Perevertkin PHAL_SW_INTERRUPT_HANDLER_2ND_ENTRY SWInterruptHandlerTable2[3] =
2087601fb54SVictor Perevertkin {
2097601fb54SVictor Perevertkin (PHAL_SW_INTERRUPT_HANDLER_2ND_ENTRY)(PVOID)KiUnexpectedInterrupt,
2107601fb54SVictor Perevertkin HalpApcInterrupt2ndEntry,
2117601fb54SVictor Perevertkin HalpDispatchInterrupt2ndEntry
2127601fb54SVictor Perevertkin };
2137601fb54SVictor Perevertkin
2147601fb54SVictor Perevertkin LONG HalpEisaELCR;
2157601fb54SVictor Perevertkin
2167601fb54SVictor Perevertkin /* FUNCTIONS ******************************************************************/
2177601fb54SVictor Perevertkin
2187601fb54SVictor Perevertkin VOID
2197601fb54SVictor Perevertkin NTAPI
HalpInitializePICs(IN BOOLEAN EnableInterrupts)2207601fb54SVictor Perevertkin HalpInitializePICs(IN BOOLEAN EnableInterrupts)
2217601fb54SVictor Perevertkin {
2227601fb54SVictor Perevertkin ULONG EFlags;
2237601fb54SVictor Perevertkin EISA_ELCR Elcr;
2247601fb54SVictor Perevertkin ULONG i, j;
2257601fb54SVictor Perevertkin BOOLEAN ElcrFound;
2267601fb54SVictor Perevertkin
2277601fb54SVictor Perevertkin /* Save EFlags and disable interrupts */
2287601fb54SVictor Perevertkin EFlags = __readeflags();
2297601fb54SVictor Perevertkin _disable();
2307601fb54SVictor Perevertkin
2317601fb54SVictor Perevertkin /* Initialize and mask the PIC */
2327601fb54SVictor Perevertkin HalpInitializeLegacyPICs();
2337601fb54SVictor Perevertkin
2347601fb54SVictor Perevertkin /* Read EISA Edge/Level Register for master and slave */
2357601fb54SVictor Perevertkin Elcr.Bits = (__inbyte(EISA_ELCR_SLAVE) << 8) | __inbyte(EISA_ELCR_MASTER);
2367601fb54SVictor Perevertkin
2377601fb54SVictor Perevertkin #if defined(SARCH_PC98)
2387601fb54SVictor Perevertkin /* Force defaults when ELCR is not supported */
2397601fb54SVictor Perevertkin if (Elcr.Bits == 0xFFFF)
2407601fb54SVictor Perevertkin {
2417601fb54SVictor Perevertkin Elcr.Master.Irq0Level = 0;
2427601fb54SVictor Perevertkin Elcr.Master.Irq1Level = 0;
2437601fb54SVictor Perevertkin Elcr.Master.Irq7Level = 0;
2447601fb54SVictor Perevertkin Elcr.Slave.Irq8Level = 0;
2457601fb54SVictor Perevertkin }
2467601fb54SVictor Perevertkin ElcrFound = TRUE;
2477601fb54SVictor Perevertkin #else
2487601fb54SVictor Perevertkin /* IRQs 0, 1, 2, 8, and 13 are system-reserved and must be edge */
2497601fb54SVictor Perevertkin ElcrFound = (!(Elcr.Master.Irq0Level) && !(Elcr.Master.Irq1Level) && !(Elcr.Master.Irq2Level) &&
2507601fb54SVictor Perevertkin !(Elcr.Slave.Irq8Level) && !(Elcr.Slave.Irq13Level));
2517601fb54SVictor Perevertkin #endif
2527601fb54SVictor Perevertkin
2537601fb54SVictor Perevertkin if (ElcrFound)
2547601fb54SVictor Perevertkin {
2557601fb54SVictor Perevertkin /* ELCR is as it's supposed to be, save it */
2567601fb54SVictor Perevertkin HalpEisaELCR = Elcr.Bits;
2577601fb54SVictor Perevertkin
2587601fb54SVictor Perevertkin /* Scan for level interrupts */
2597601fb54SVictor Perevertkin for (i = 1, j = 0; j < 16; i <<= 1, j++)
2607601fb54SVictor Perevertkin {
2617601fb54SVictor Perevertkin if (HalpEisaELCR & i)
2627601fb54SVictor Perevertkin {
2637601fb54SVictor Perevertkin /* Switch handler to level */
2647601fb54SVictor Perevertkin SWInterruptHandlerTable[j + 4] = HalpHardwareInterruptLevel;
2657601fb54SVictor Perevertkin
2667601fb54SVictor Perevertkin /* Switch dismiss to level */
2677601fb54SVictor Perevertkin HalpSpecialDismissTable[j] = HalpSpecialDismissLevelTable[j];
2687601fb54SVictor Perevertkin }
2697601fb54SVictor Perevertkin }
2707601fb54SVictor Perevertkin }
2717601fb54SVictor Perevertkin
2727601fb54SVictor Perevertkin /* Report cascade IRQ usage */
2737601fb54SVictor Perevertkin HalpRegisterVector(IDT_INTERNAL,
2747601fb54SVictor Perevertkin PRIMARY_VECTOR_BASE + PIC_CASCADE_IRQ,
2757601fb54SVictor Perevertkin PRIMARY_VECTOR_BASE + PIC_CASCADE_IRQ,
2767601fb54SVictor Perevertkin HIGH_LEVEL);
2777601fb54SVictor Perevertkin
2787601fb54SVictor Perevertkin /* Restore interrupt state */
2797601fb54SVictor Perevertkin if (EnableInterrupts) EFlags |= EFLAGS_INTERRUPT_MASK;
2807601fb54SVictor Perevertkin __writeeflags(EFlags);
2817601fb54SVictor Perevertkin }
2827601fb54SVictor Perevertkin
2837601fb54SVictor Perevertkin UCHAR
2847601fb54SVictor Perevertkin FASTCALL
HalpIrqToVector(UCHAR Irq)2857601fb54SVictor Perevertkin HalpIrqToVector(UCHAR Irq)
2867601fb54SVictor Perevertkin {
2877601fb54SVictor Perevertkin return (PRIMARY_VECTOR_BASE + Irq);
2887601fb54SVictor Perevertkin }
2897601fb54SVictor Perevertkin
2907601fb54SVictor Perevertkin UCHAR
2917601fb54SVictor Perevertkin FASTCALL
HalpVectorToIrq(UCHAR Vector)2927601fb54SVictor Perevertkin HalpVectorToIrq(UCHAR Vector)
2937601fb54SVictor Perevertkin {
2947601fb54SVictor Perevertkin return (Vector - PRIMARY_VECTOR_BASE);
2957601fb54SVictor Perevertkin }
2967601fb54SVictor Perevertkin
2977601fb54SVictor Perevertkin KIRQL
2987601fb54SVictor Perevertkin FASTCALL
HalpVectorToIrql(UCHAR Vector)2997601fb54SVictor Perevertkin HalpVectorToIrql(UCHAR Vector)
3007601fb54SVictor Perevertkin {
3017601fb54SVictor Perevertkin return (PROFILE_LEVEL - (Vector - PRIMARY_VECTOR_BASE));
3027601fb54SVictor Perevertkin }
3037601fb54SVictor Perevertkin
3047601fb54SVictor Perevertkin /* IRQL MANAGEMENT ************************************************************/
3057601fb54SVictor Perevertkin
3067601fb54SVictor Perevertkin /*
3077601fb54SVictor Perevertkin * @implemented
3087601fb54SVictor Perevertkin */
3097601fb54SVictor Perevertkin KIRQL
3107601fb54SVictor Perevertkin NTAPI
KeGetCurrentIrql(VOID)3117601fb54SVictor Perevertkin KeGetCurrentIrql(VOID)
3127601fb54SVictor Perevertkin {
3137601fb54SVictor Perevertkin /* Return the IRQL */
3147601fb54SVictor Perevertkin return KeGetPcr()->Irql;
3157601fb54SVictor Perevertkin }
3167601fb54SVictor Perevertkin
3177601fb54SVictor Perevertkin /*
3187601fb54SVictor Perevertkin * @implemented
3197601fb54SVictor Perevertkin */
3207601fb54SVictor Perevertkin KIRQL
3217601fb54SVictor Perevertkin NTAPI
KeRaiseIrqlToDpcLevel(VOID)3227601fb54SVictor Perevertkin KeRaiseIrqlToDpcLevel(VOID)
3237601fb54SVictor Perevertkin {
3247601fb54SVictor Perevertkin PKPCR Pcr = KeGetPcr();
3257601fb54SVictor Perevertkin KIRQL CurrentIrql;
3267601fb54SVictor Perevertkin
3277601fb54SVictor Perevertkin /* Save and update IRQL */
3287601fb54SVictor Perevertkin CurrentIrql = Pcr->Irql;
3297601fb54SVictor Perevertkin Pcr->Irql = DISPATCH_LEVEL;
3307601fb54SVictor Perevertkin
3317601fb54SVictor Perevertkin #if DBG
3327601fb54SVictor Perevertkin /* Validate correct raise */
3337601fb54SVictor Perevertkin if (CurrentIrql > DISPATCH_LEVEL) KeBugCheck(IRQL_NOT_GREATER_OR_EQUAL);
3347601fb54SVictor Perevertkin #endif
3357601fb54SVictor Perevertkin
3367601fb54SVictor Perevertkin /* Return the previous value */
3377601fb54SVictor Perevertkin return CurrentIrql;
3387601fb54SVictor Perevertkin }
3397601fb54SVictor Perevertkin
3407601fb54SVictor Perevertkin /*
3417601fb54SVictor Perevertkin * @implemented
3427601fb54SVictor Perevertkin */
3437601fb54SVictor Perevertkin KIRQL
3447601fb54SVictor Perevertkin NTAPI
KeRaiseIrqlToSynchLevel(VOID)3457601fb54SVictor Perevertkin KeRaiseIrqlToSynchLevel(VOID)
3467601fb54SVictor Perevertkin {
3477601fb54SVictor Perevertkin PKPCR Pcr = KeGetPcr();
3487601fb54SVictor Perevertkin KIRQL CurrentIrql;
3497601fb54SVictor Perevertkin
3507601fb54SVictor Perevertkin /* Save and update IRQL */
3517601fb54SVictor Perevertkin CurrentIrql = Pcr->Irql;
3527601fb54SVictor Perevertkin Pcr->Irql = SYNCH_LEVEL;
3537601fb54SVictor Perevertkin
3547601fb54SVictor Perevertkin #if DBG
3557601fb54SVictor Perevertkin /* Validate correct raise */
3567601fb54SVictor Perevertkin if (CurrentIrql > SYNCH_LEVEL)
3577601fb54SVictor Perevertkin {
3587601fb54SVictor Perevertkin /* Crash system */
3597601fb54SVictor Perevertkin KeBugCheckEx(IRQL_NOT_GREATER_OR_EQUAL,
3607601fb54SVictor Perevertkin CurrentIrql,
3617601fb54SVictor Perevertkin SYNCH_LEVEL,
3627601fb54SVictor Perevertkin 0,
3637601fb54SVictor Perevertkin 1);
3647601fb54SVictor Perevertkin }
3657601fb54SVictor Perevertkin #endif
3667601fb54SVictor Perevertkin
3677601fb54SVictor Perevertkin /* Return the previous value */
3687601fb54SVictor Perevertkin return CurrentIrql;
3697601fb54SVictor Perevertkin }
3707601fb54SVictor Perevertkin
3717601fb54SVictor Perevertkin /*
3727601fb54SVictor Perevertkin * @implemented
3737601fb54SVictor Perevertkin */
3747601fb54SVictor Perevertkin KIRQL
3757601fb54SVictor Perevertkin FASTCALL
KfRaiseIrql(IN KIRQL NewIrql)3767601fb54SVictor Perevertkin KfRaiseIrql(IN KIRQL NewIrql)
3777601fb54SVictor Perevertkin {
3787601fb54SVictor Perevertkin PKPCR Pcr = KeGetPcr();
3797601fb54SVictor Perevertkin KIRQL CurrentIrql;
3807601fb54SVictor Perevertkin
3817601fb54SVictor Perevertkin /* Read current IRQL */
3827601fb54SVictor Perevertkin CurrentIrql = Pcr->Irql;
3837601fb54SVictor Perevertkin
3847601fb54SVictor Perevertkin #if DBG
3857601fb54SVictor Perevertkin /* Validate correct raise */
3867601fb54SVictor Perevertkin if (CurrentIrql > NewIrql)
3877601fb54SVictor Perevertkin {
3887601fb54SVictor Perevertkin /* Crash system */
3897601fb54SVictor Perevertkin Pcr->Irql = PASSIVE_LEVEL;
3907601fb54SVictor Perevertkin KeBugCheck(IRQL_NOT_GREATER_OR_EQUAL);
3917601fb54SVictor Perevertkin }
3927601fb54SVictor Perevertkin #endif
3937601fb54SVictor Perevertkin
3947601fb54SVictor Perevertkin /* Set new IRQL */
3957601fb54SVictor Perevertkin Pcr->Irql = NewIrql;
3967601fb54SVictor Perevertkin
3977601fb54SVictor Perevertkin /* Return old IRQL */
3987601fb54SVictor Perevertkin return CurrentIrql;
3997601fb54SVictor Perevertkin }
4007601fb54SVictor Perevertkin
4017601fb54SVictor Perevertkin
4027601fb54SVictor Perevertkin /*
4037601fb54SVictor Perevertkin * @implemented
4047601fb54SVictor Perevertkin */
4057601fb54SVictor Perevertkin VOID
4067601fb54SVictor Perevertkin FASTCALL
KfLowerIrql(IN KIRQL OldIrql)4077601fb54SVictor Perevertkin KfLowerIrql(IN KIRQL OldIrql)
4087601fb54SVictor Perevertkin {
4097601fb54SVictor Perevertkin ULONG EFlags;
4107601fb54SVictor Perevertkin ULONG PendingIrql, PendingIrqlMask;
4117601fb54SVictor Perevertkin PKPCR Pcr = KeGetPcr();
4127601fb54SVictor Perevertkin PIC_MASK Mask;
4137601fb54SVictor Perevertkin
4147601fb54SVictor Perevertkin #if DBG
4157601fb54SVictor Perevertkin /* Validate correct lower */
4167601fb54SVictor Perevertkin if (OldIrql > Pcr->Irql)
4177601fb54SVictor Perevertkin {
4187601fb54SVictor Perevertkin /* Crash system */
4197601fb54SVictor Perevertkin Pcr->Irql = HIGH_LEVEL;
4207601fb54SVictor Perevertkin KeBugCheck(IRQL_NOT_LESS_OR_EQUAL);
4217601fb54SVictor Perevertkin }
4227601fb54SVictor Perevertkin #endif
4237601fb54SVictor Perevertkin
4247601fb54SVictor Perevertkin /* Save EFlags and disable interrupts */
4257601fb54SVictor Perevertkin EFlags = __readeflags();
4267601fb54SVictor Perevertkin _disable();
4277601fb54SVictor Perevertkin
4287601fb54SVictor Perevertkin /* Set old IRQL */
4297601fb54SVictor Perevertkin Pcr->Irql = OldIrql;
4307601fb54SVictor Perevertkin
4317601fb54SVictor Perevertkin /* Check for pending software interrupts and compare with current IRQL */
4327601fb54SVictor Perevertkin PendingIrqlMask = Pcr->IRR & FindHigherIrqlMask[OldIrql];
4337601fb54SVictor Perevertkin if (PendingIrqlMask)
4347601fb54SVictor Perevertkin {
4357601fb54SVictor Perevertkin /* Check if pending IRQL affects hardware state */
4367601fb54SVictor Perevertkin BitScanReverse(&PendingIrql, PendingIrqlMask);
4377601fb54SVictor Perevertkin if (PendingIrql > DISPATCH_LEVEL)
4387601fb54SVictor Perevertkin {
4397601fb54SVictor Perevertkin /* Set new PIC mask */
4407601fb54SVictor Perevertkin Mask.Both = Pcr->IDR & 0xFFFF;
4417601fb54SVictor Perevertkin __outbyte(PIC1_DATA_PORT, Mask.Master);
4427601fb54SVictor Perevertkin __outbyte(PIC2_DATA_PORT, Mask.Slave);
4437601fb54SVictor Perevertkin
4447601fb54SVictor Perevertkin /* Clear IRR bit */
4457601fb54SVictor Perevertkin Pcr->IRR ^= (1 << PendingIrql);
4467601fb54SVictor Perevertkin }
4477601fb54SVictor Perevertkin
4487601fb54SVictor Perevertkin /* Now handle pending interrupt */
4497601fb54SVictor Perevertkin SWInterruptHandlerTable[PendingIrql]();
4507601fb54SVictor Perevertkin }
4517601fb54SVictor Perevertkin
4527601fb54SVictor Perevertkin /* Restore interrupt state */
4537601fb54SVictor Perevertkin __writeeflags(EFlags);
4547601fb54SVictor Perevertkin }
4557601fb54SVictor Perevertkin
4567601fb54SVictor Perevertkin /* SOFTWARE INTERRUPTS ********************************************************/
4577601fb54SVictor Perevertkin
4587601fb54SVictor Perevertkin /*
4597601fb54SVictor Perevertkin * @implemented
4607601fb54SVictor Perevertkin */
4617601fb54SVictor Perevertkin VOID
4627601fb54SVictor Perevertkin FASTCALL
HalRequestSoftwareInterrupt(IN KIRQL Irql)4637601fb54SVictor Perevertkin HalRequestSoftwareInterrupt(IN KIRQL Irql)
4647601fb54SVictor Perevertkin {
4657601fb54SVictor Perevertkin ULONG EFlags;
4667601fb54SVictor Perevertkin PKPCR Pcr = KeGetPcr();
4677601fb54SVictor Perevertkin KIRQL PendingIrql;
4687601fb54SVictor Perevertkin
4697601fb54SVictor Perevertkin /* Save EFlags and disable interrupts */
4707601fb54SVictor Perevertkin EFlags = __readeflags();
4717601fb54SVictor Perevertkin _disable();
4727601fb54SVictor Perevertkin
4737601fb54SVictor Perevertkin /* Mask out the requested bit */
4747601fb54SVictor Perevertkin Pcr->IRR |= (1 << Irql);
4757601fb54SVictor Perevertkin
4767601fb54SVictor Perevertkin /* Check for pending software interrupts and compare with current IRQL */
4777601fb54SVictor Perevertkin PendingIrql = SWInterruptLookUpTable[Pcr->IRR & 3];
4787601fb54SVictor Perevertkin if (PendingIrql > Pcr->Irql) SWInterruptHandlerTable[PendingIrql]();
4797601fb54SVictor Perevertkin
4807601fb54SVictor Perevertkin /* Restore interrupt state */
4817601fb54SVictor Perevertkin __writeeflags(EFlags);
4827601fb54SVictor Perevertkin }
4837601fb54SVictor Perevertkin
4847601fb54SVictor Perevertkin /*
4857601fb54SVictor Perevertkin * @implemented
4867601fb54SVictor Perevertkin */
4877601fb54SVictor Perevertkin VOID
4887601fb54SVictor Perevertkin FASTCALL
HalClearSoftwareInterrupt(IN KIRQL Irql)4897601fb54SVictor Perevertkin HalClearSoftwareInterrupt(IN KIRQL Irql)
4907601fb54SVictor Perevertkin {
4917601fb54SVictor Perevertkin /* Mask out the requested bit */
4927601fb54SVictor Perevertkin KeGetPcr()->IRR &= ~(1 << Irql);
4937601fb54SVictor Perevertkin }
4947601fb54SVictor Perevertkin
4957601fb54SVictor Perevertkin PHAL_SW_INTERRUPT_HANDLER_2ND_ENTRY
4967601fb54SVictor Perevertkin FASTCALL
HalpEndSoftwareInterrupt2(IN KIRQL OldIrql,IN PKTRAP_FRAME TrapFrame)4977601fb54SVictor Perevertkin HalpEndSoftwareInterrupt2(IN KIRQL OldIrql,
4987601fb54SVictor Perevertkin IN PKTRAP_FRAME TrapFrame)
4997601fb54SVictor Perevertkin {
5007601fb54SVictor Perevertkin ULONG PendingIrql, PendingIrqlMask, PendingIrqMask;
5017601fb54SVictor Perevertkin PKPCR Pcr = KeGetPcr();
5027601fb54SVictor Perevertkin PIC_MASK Mask;
5037601fb54SVictor Perevertkin
5047601fb54SVictor Perevertkin UNREFERENCED_PARAMETER(TrapFrame);
5057601fb54SVictor Perevertkin
5067601fb54SVictor Perevertkin /* Set old IRQL */
5077601fb54SVictor Perevertkin Pcr->Irql = OldIrql;
5087601fb54SVictor Perevertkin
5097601fb54SVictor Perevertkin /* Loop checking for pending interrupts */
5107601fb54SVictor Perevertkin while (TRUE)
5117601fb54SVictor Perevertkin {
5127601fb54SVictor Perevertkin /* Check for pending software interrupts and compare with current IRQL */
5137601fb54SVictor Perevertkin PendingIrqlMask = Pcr->IRR & FindHigherIrqlMask[OldIrql];
5147601fb54SVictor Perevertkin if (!PendingIrqlMask) return NULL;
5157601fb54SVictor Perevertkin
5167601fb54SVictor Perevertkin /* Check for in-service delayed interrupt */
5177601fb54SVictor Perevertkin if (Pcr->IrrActive & 0xFFFFFFF0) return NULL;
5187601fb54SVictor Perevertkin
5197601fb54SVictor Perevertkin /* Check if pending IRQL affects hardware state */
5207601fb54SVictor Perevertkin BitScanReverse(&PendingIrql, PendingIrqlMask);
5217601fb54SVictor Perevertkin if (PendingIrql > DISPATCH_LEVEL)
5227601fb54SVictor Perevertkin {
5237601fb54SVictor Perevertkin /* Set new PIC mask */
5247601fb54SVictor Perevertkin Mask.Both = Pcr->IDR & 0xFFFF;
5257601fb54SVictor Perevertkin __outbyte(PIC1_DATA_PORT, Mask.Master);
5267601fb54SVictor Perevertkin __outbyte(PIC2_DATA_PORT, Mask.Slave);
5277601fb54SVictor Perevertkin
5287601fb54SVictor Perevertkin /* Set active bit otherwise, and clear it from IRR */
5297601fb54SVictor Perevertkin PendingIrqMask = (1 << PendingIrql);
5307601fb54SVictor Perevertkin Pcr->IrrActive |= PendingIrqMask;
5317601fb54SVictor Perevertkin Pcr->IRR ^= PendingIrqMask;
5327601fb54SVictor Perevertkin
5337601fb54SVictor Perevertkin /* Handle delayed hardware interrupt */
5347601fb54SVictor Perevertkin SWInterruptHandlerTable[PendingIrql]();
5357601fb54SVictor Perevertkin
5367601fb54SVictor Perevertkin /* Handling complete */
5377601fb54SVictor Perevertkin Pcr->IrrActive ^= PendingIrqMask;
5387601fb54SVictor Perevertkin }
5397601fb54SVictor Perevertkin else
5407601fb54SVictor Perevertkin {
5417601fb54SVictor Perevertkin /* No need to loop checking for hardware interrupts */
5427601fb54SVictor Perevertkin return SWInterruptHandlerTable2[PendingIrql];
5437601fb54SVictor Perevertkin }
5447601fb54SVictor Perevertkin }
5457601fb54SVictor Perevertkin
5467601fb54SVictor Perevertkin return NULL;
5477601fb54SVictor Perevertkin }
5487601fb54SVictor Perevertkin
5497601fb54SVictor Perevertkin /* EDGE INTERRUPT DISMISSAL FUNCTIONS *****************************************/
5507601fb54SVictor Perevertkin
5517601fb54SVictor Perevertkin FORCEINLINE
5527601fb54SVictor Perevertkin BOOLEAN
_HalpDismissIrqGeneric(IN KIRQL Irql,IN ULONG Irq,OUT PKIRQL OldIrql)5537601fb54SVictor Perevertkin _HalpDismissIrqGeneric(IN KIRQL Irql,
5547601fb54SVictor Perevertkin IN ULONG Irq,
5557601fb54SVictor Perevertkin OUT PKIRQL OldIrql)
5567601fb54SVictor Perevertkin {
5577601fb54SVictor Perevertkin PIC_MASK Mask;
5587601fb54SVictor Perevertkin KIRQL CurrentIrql;
5597601fb54SVictor Perevertkin I8259_OCW2 Ocw2;
5607601fb54SVictor Perevertkin PKPCR Pcr = KeGetPcr();
5617601fb54SVictor Perevertkin
5627601fb54SVictor Perevertkin /* First save current IRQL and compare it to the requested one */
5637601fb54SVictor Perevertkin CurrentIrql = Pcr->Irql;
5647601fb54SVictor Perevertkin
5657601fb54SVictor Perevertkin /* Check if this interrupt is really allowed to happen */
5667601fb54SVictor Perevertkin if (Irql > CurrentIrql)
5677601fb54SVictor Perevertkin {
5687601fb54SVictor Perevertkin /* Set the new IRQL and return the current one */
5697601fb54SVictor Perevertkin Pcr->Irql = Irql;
5707601fb54SVictor Perevertkin *OldIrql = CurrentIrql;
5717601fb54SVictor Perevertkin
5727601fb54SVictor Perevertkin /* Prepare OCW2 for EOI */
5737601fb54SVictor Perevertkin Ocw2.Bits = 0;
5747601fb54SVictor Perevertkin Ocw2.EoiMode = SpecificEoi;
5757601fb54SVictor Perevertkin
5767601fb54SVictor Perevertkin /* Check which PIC needs the EOI */
5777601fb54SVictor Perevertkin if (Irq >= 8)
5787601fb54SVictor Perevertkin {
5797601fb54SVictor Perevertkin #if defined(SARCH_PC98)
5807601fb54SVictor Perevertkin I8259_OCW3 Ocw3;
5817601fb54SVictor Perevertkin I8259_ISR Isr;
5827601fb54SVictor Perevertkin
5837601fb54SVictor Perevertkin /* Send the EOI for the IRQ */
5847601fb54SVictor Perevertkin __outbyte(PIC2_CONTROL_PORT, Ocw2.Bits | ((Irq - 8) & 0xFF));
5857601fb54SVictor Perevertkin
5867601fb54SVictor Perevertkin /* Request the ISR */
5877601fb54SVictor Perevertkin Ocw3.Bits = 0;
5887601fb54SVictor Perevertkin Ocw3.Sbo = 1;
5897601fb54SVictor Perevertkin Ocw3.ReadRequest = ReadIsr;
5907601fb54SVictor Perevertkin __outbyte(PIC2_CONTROL_PORT, Ocw3.Bits);
5917601fb54SVictor Perevertkin
5927601fb54SVictor Perevertkin /* Read the ISR */
5937601fb54SVictor Perevertkin Isr.Bits = __inbyte(PIC2_CONTROL_PORT);
5947601fb54SVictor Perevertkin
5957601fb54SVictor Perevertkin /* Check if the interrupt serviced was the only one from the slave PIC */
5967601fb54SVictor Perevertkin if (Isr.Bits == 0)
5977601fb54SVictor Perevertkin {
5987601fb54SVictor Perevertkin /* If ISR is empty, send the EOI for cascade IRQ on the master PIC */
5997601fb54SVictor Perevertkin __outbyte(PIC1_CONTROL_PORT, Ocw2.Bits | PIC_CASCADE_IRQ);
6007601fb54SVictor Perevertkin }
6017601fb54SVictor Perevertkin #else
6027601fb54SVictor Perevertkin /* Send the EOI for the IRQ */
6037601fb54SVictor Perevertkin __outbyte(PIC2_CONTROL_PORT, Ocw2.Bits | ((Irq - 8) & 0xFF));
6047601fb54SVictor Perevertkin
6057601fb54SVictor Perevertkin /* Send the EOI for cascade IRQ on the master PIC */
6067601fb54SVictor Perevertkin __outbyte(PIC1_CONTROL_PORT, Ocw2.Bits | PIC_CASCADE_IRQ);
6077601fb54SVictor Perevertkin #endif
6087601fb54SVictor Perevertkin }
6097601fb54SVictor Perevertkin else
6107601fb54SVictor Perevertkin {
6117601fb54SVictor Perevertkin /* Send the EOI for the IRQ */
6127601fb54SVictor Perevertkin __outbyte(PIC1_CONTROL_PORT, Ocw2.Bits | (Irq & 0xFF));
6137601fb54SVictor Perevertkin }
6147601fb54SVictor Perevertkin
6157601fb54SVictor Perevertkin /* Enable interrupts and return success */
6167601fb54SVictor Perevertkin _enable();
6177601fb54SVictor Perevertkin return TRUE;
6187601fb54SVictor Perevertkin }
6197601fb54SVictor Perevertkin
6207601fb54SVictor Perevertkin /* Update the IRR so that we deliver this interrupt when the IRQL is proper */
6217601fb54SVictor Perevertkin Pcr->IRR |= (1 << (Irq + 4));
6227601fb54SVictor Perevertkin
6237601fb54SVictor Perevertkin /* Set new PIC mask to real IRQL level, since the optimization is lost now */
6247601fb54SVictor Perevertkin Mask.Both = (KiI8259MaskTable[CurrentIrql] | Pcr->IDR) & 0xFFFF;
6257601fb54SVictor Perevertkin __outbyte(PIC1_DATA_PORT, Mask.Master);
6267601fb54SVictor Perevertkin __outbyte(PIC2_DATA_PORT, Mask.Slave);
6277601fb54SVictor Perevertkin
6287601fb54SVictor Perevertkin /* Now lie and say this was spurious */
6297601fb54SVictor Perevertkin return FALSE;
6307601fb54SVictor Perevertkin }
6317601fb54SVictor Perevertkin
6327601fb54SVictor Perevertkin BOOLEAN
6337601fb54SVictor Perevertkin NTAPI
HalpDismissIrqGeneric(IN KIRQL Irql,IN ULONG Irq,OUT PKIRQL OldIrql)6347601fb54SVictor Perevertkin HalpDismissIrqGeneric(IN KIRQL Irql,
6357601fb54SVictor Perevertkin IN ULONG Irq,
6367601fb54SVictor Perevertkin OUT PKIRQL OldIrql)
6377601fb54SVictor Perevertkin {
6387601fb54SVictor Perevertkin /* Run the inline code */
6397601fb54SVictor Perevertkin return _HalpDismissIrqGeneric(Irql, Irq, OldIrql);
6407601fb54SVictor Perevertkin }
6417601fb54SVictor Perevertkin
6427601fb54SVictor Perevertkin BOOLEAN
6437601fb54SVictor Perevertkin NTAPI
HalpDismissIrq15(IN KIRQL Irql,IN ULONG Irq,OUT PKIRQL OldIrql)6447601fb54SVictor Perevertkin HalpDismissIrq15(IN KIRQL Irql,
6457601fb54SVictor Perevertkin IN ULONG Irq,
6467601fb54SVictor Perevertkin OUT PKIRQL OldIrql)
6477601fb54SVictor Perevertkin {
6487601fb54SVictor Perevertkin I8259_OCW3 Ocw3;
6497601fb54SVictor Perevertkin I8259_OCW2 Ocw2;
6507601fb54SVictor Perevertkin I8259_ISR Isr;
6517601fb54SVictor Perevertkin
6527601fb54SVictor Perevertkin /* Request the ISR */
6537601fb54SVictor Perevertkin Ocw3.Bits = 0;
6547601fb54SVictor Perevertkin Ocw3.Sbo = 1; /* This encodes an OCW3 vs. an OCW2 */
6557601fb54SVictor Perevertkin Ocw3.ReadRequest = ReadIsr;
6567601fb54SVictor Perevertkin __outbyte(PIC2_CONTROL_PORT, Ocw3.Bits);
6577601fb54SVictor Perevertkin
6587601fb54SVictor Perevertkin /* Read the ISR */
6597601fb54SVictor Perevertkin Isr.Bits = __inbyte(PIC2_CONTROL_PORT);
6607601fb54SVictor Perevertkin
6617601fb54SVictor Perevertkin /* Is IRQ15 really active (this is IR7) */
6627601fb54SVictor Perevertkin if (Isr.Irq7 == FALSE)
6637601fb54SVictor Perevertkin {
6647601fb54SVictor Perevertkin /* It isn't, so we have to EOI cascade IRQ */
6657601fb54SVictor Perevertkin Ocw2.Bits = 0;
6667601fb54SVictor Perevertkin Ocw2.EoiMode = SpecificEoi;
6677601fb54SVictor Perevertkin __outbyte(PIC1_CONTROL_PORT, Ocw2.Bits | PIC_CASCADE_IRQ);
6687601fb54SVictor Perevertkin
6697601fb54SVictor Perevertkin /* And now fail since this was spurious */
6707601fb54SVictor Perevertkin return FALSE;
6717601fb54SVictor Perevertkin }
6727601fb54SVictor Perevertkin
6737601fb54SVictor Perevertkin /* Do normal interrupt dismiss */
6747601fb54SVictor Perevertkin return _HalpDismissIrqGeneric(Irql, Irq, OldIrql);
6757601fb54SVictor Perevertkin }
6767601fb54SVictor Perevertkin
6777601fb54SVictor Perevertkin BOOLEAN
6787601fb54SVictor Perevertkin NTAPI
HalpDismissIrq13(IN KIRQL Irql,IN ULONG Irq,OUT PKIRQL OldIrql)6797601fb54SVictor Perevertkin HalpDismissIrq13(IN KIRQL Irql,
6807601fb54SVictor Perevertkin IN ULONG Irq,
6817601fb54SVictor Perevertkin OUT PKIRQL OldIrql)
6827601fb54SVictor Perevertkin {
6837601fb54SVictor Perevertkin /* Clear the FPU busy latch */
6847601fb54SVictor Perevertkin __outbyte(0xF0, 0);
6857601fb54SVictor Perevertkin
6867601fb54SVictor Perevertkin /* Do normal interrupt dismiss */
6877601fb54SVictor Perevertkin return _HalpDismissIrqGeneric(Irql, Irq, OldIrql);
6887601fb54SVictor Perevertkin }
6897601fb54SVictor Perevertkin
6907601fb54SVictor Perevertkin #if defined(SARCH_PC98)
6917601fb54SVictor Perevertkin BOOLEAN
6927601fb54SVictor Perevertkin NTAPI
HalpDismissIrq08(_In_ KIRQL Irql,_In_ ULONG Irq,_Out_ PKIRQL OldIrql)6937601fb54SVictor Perevertkin HalpDismissIrq08(
6947601fb54SVictor Perevertkin _In_ KIRQL Irql,
6957601fb54SVictor Perevertkin _In_ ULONG Irq,
6967601fb54SVictor Perevertkin _Out_ PKIRQL OldIrql)
6977601fb54SVictor Perevertkin {
6987601fb54SVictor Perevertkin /* Clear the FPU busy latch */
6997601fb54SVictor Perevertkin __outbyte(CPU_IO_o_FPU_BUSY_LATCH, 0);
7007601fb54SVictor Perevertkin
7017601fb54SVictor Perevertkin /* Do normal interrupt dismiss */
7027601fb54SVictor Perevertkin return _HalpDismissIrqGeneric(Irql, Irq, OldIrql);
7037601fb54SVictor Perevertkin }
7047601fb54SVictor Perevertkin #endif
7057601fb54SVictor Perevertkin
7067601fb54SVictor Perevertkin BOOLEAN
7077601fb54SVictor Perevertkin NTAPI
HalpDismissIrq07(IN KIRQL Irql,IN ULONG Irq,OUT PKIRQL OldIrql)7087601fb54SVictor Perevertkin HalpDismissIrq07(IN KIRQL Irql,
7097601fb54SVictor Perevertkin IN ULONG Irq,
7107601fb54SVictor Perevertkin OUT PKIRQL OldIrql)
7117601fb54SVictor Perevertkin {
7127601fb54SVictor Perevertkin I8259_OCW3 Ocw3;
7137601fb54SVictor Perevertkin I8259_ISR Isr;
7147601fb54SVictor Perevertkin
7157601fb54SVictor Perevertkin /* Request the ISR */
7167601fb54SVictor Perevertkin Ocw3.Bits = 0;
7177601fb54SVictor Perevertkin Ocw3.Sbo = 1;
7187601fb54SVictor Perevertkin Ocw3.ReadRequest = ReadIsr;
7197601fb54SVictor Perevertkin __outbyte(PIC1_CONTROL_PORT, Ocw3.Bits);
7207601fb54SVictor Perevertkin
7217601fb54SVictor Perevertkin /* Read the ISR */
7227601fb54SVictor Perevertkin Isr.Bits = __inbyte(PIC1_CONTROL_PORT);
7237601fb54SVictor Perevertkin
7247601fb54SVictor Perevertkin /* Is IRQ 7 really active? If it isn't, this is spurious so fail */
7257601fb54SVictor Perevertkin if (Isr.Irq7 == FALSE) return FALSE;
7267601fb54SVictor Perevertkin
7277601fb54SVictor Perevertkin /* Do normal interrupt dismiss */
7287601fb54SVictor Perevertkin return _HalpDismissIrqGeneric(Irql, Irq, OldIrql);
7297601fb54SVictor Perevertkin }
7307601fb54SVictor Perevertkin
7317601fb54SVictor Perevertkin /* LEVEL INTERRUPT DISMISSAL FUNCTIONS ****************************************/
7327601fb54SVictor Perevertkin
7337601fb54SVictor Perevertkin FORCEINLINE
7347601fb54SVictor Perevertkin BOOLEAN
_HalpDismissIrqLevel(IN KIRQL Irql,IN ULONG Irq,OUT PKIRQL OldIrql)7357601fb54SVictor Perevertkin _HalpDismissIrqLevel(IN KIRQL Irql,
7367601fb54SVictor Perevertkin IN ULONG Irq,
7377601fb54SVictor Perevertkin OUT PKIRQL OldIrql)
7387601fb54SVictor Perevertkin {
7397601fb54SVictor Perevertkin PIC_MASK Mask;
7407601fb54SVictor Perevertkin KIRQL CurrentIrql;
7417601fb54SVictor Perevertkin I8259_OCW2 Ocw2;
7427601fb54SVictor Perevertkin PKPCR Pcr = KeGetPcr();
7437601fb54SVictor Perevertkin
7447601fb54SVictor Perevertkin /* Update the PIC */
7457601fb54SVictor Perevertkin Mask.Both = (KiI8259MaskTable[Irql] | Pcr->IDR) & 0xFFFF;
7467601fb54SVictor Perevertkin __outbyte(PIC1_DATA_PORT, Mask.Master);
7477601fb54SVictor Perevertkin __outbyte(PIC2_DATA_PORT, Mask.Slave);
7487601fb54SVictor Perevertkin
7497601fb54SVictor Perevertkin /* Update the IRR so that we clear this interrupt when the IRQL is proper */
7507601fb54SVictor Perevertkin Pcr->IRR |= (1 << (Irq + 4));
7517601fb54SVictor Perevertkin
7527601fb54SVictor Perevertkin /* Save current IRQL */
7537601fb54SVictor Perevertkin CurrentIrql = Pcr->Irql;
7547601fb54SVictor Perevertkin
7557601fb54SVictor Perevertkin /* Prepare OCW2 for EOI */
7567601fb54SVictor Perevertkin Ocw2.Bits = 0;
7577601fb54SVictor Perevertkin Ocw2.EoiMode = SpecificEoi;
7587601fb54SVictor Perevertkin
7597601fb54SVictor Perevertkin /* Check which PIC needs the EOI */
7607601fb54SVictor Perevertkin if (Irq >= 8)
7617601fb54SVictor Perevertkin {
7627601fb54SVictor Perevertkin #if defined(SARCH_PC98)
7637601fb54SVictor Perevertkin I8259_OCW3 Ocw3;
7647601fb54SVictor Perevertkin I8259_ISR Isr;
7657601fb54SVictor Perevertkin
7667601fb54SVictor Perevertkin /* Send the EOI for the IRQ */
7677601fb54SVictor Perevertkin __outbyte(PIC2_CONTROL_PORT, Ocw2.Bits | ((Irq - 8) & 0xFF));
7687601fb54SVictor Perevertkin
7697601fb54SVictor Perevertkin /* Request the ISR */
7707601fb54SVictor Perevertkin Ocw3.Bits = 0;
7717601fb54SVictor Perevertkin Ocw3.Sbo = 1;
7727601fb54SVictor Perevertkin Ocw3.ReadRequest = ReadIsr;
7737601fb54SVictor Perevertkin __outbyte(PIC2_CONTROL_PORT, Ocw3.Bits);
7747601fb54SVictor Perevertkin
7757601fb54SVictor Perevertkin /* Read the ISR */
7767601fb54SVictor Perevertkin Isr.Bits = __inbyte(PIC2_CONTROL_PORT);
7777601fb54SVictor Perevertkin
7787601fb54SVictor Perevertkin /* Check if the interrupt serviced was the only one from the slave PIC */
7797601fb54SVictor Perevertkin if (Isr.Bits == 0)
7807601fb54SVictor Perevertkin {
7817601fb54SVictor Perevertkin /* If ISR is empty, send the EOI for cascade IRQ on the master PIC */
7827601fb54SVictor Perevertkin __outbyte(PIC1_CONTROL_PORT, Ocw2.Bits | PIC_CASCADE_IRQ);
7837601fb54SVictor Perevertkin }
7847601fb54SVictor Perevertkin #else
7857601fb54SVictor Perevertkin /* Send the EOI for the IRQ */
7867601fb54SVictor Perevertkin __outbyte(PIC2_CONTROL_PORT, Ocw2.Bits | ((Irq - 8) & 0xFF));
7877601fb54SVictor Perevertkin
7887601fb54SVictor Perevertkin /* Send the EOI for cascade IRQ on the master PIC */
7897601fb54SVictor Perevertkin __outbyte(PIC1_CONTROL_PORT, Ocw2.Bits | PIC_CASCADE_IRQ);
7907601fb54SVictor Perevertkin #endif
7917601fb54SVictor Perevertkin }
7927601fb54SVictor Perevertkin else
7937601fb54SVictor Perevertkin {
7947601fb54SVictor Perevertkin /* Send the EOI for the IRQ */
7957601fb54SVictor Perevertkin __outbyte(PIC1_CONTROL_PORT, Ocw2.Bits | (Irq & 0xFF));
7967601fb54SVictor Perevertkin }
7977601fb54SVictor Perevertkin
7987601fb54SVictor Perevertkin /* Check if this interrupt should be allowed to happen */
7997601fb54SVictor Perevertkin if (Irql > CurrentIrql)
8007601fb54SVictor Perevertkin {
8017601fb54SVictor Perevertkin /* Set the new IRQL and return the current one */
8027601fb54SVictor Perevertkin Pcr->Irql = Irql;
8037601fb54SVictor Perevertkin *OldIrql = CurrentIrql;
8047601fb54SVictor Perevertkin
8057601fb54SVictor Perevertkin /* Enable interrupts and return success */
8067601fb54SVictor Perevertkin _enable();
8077601fb54SVictor Perevertkin return TRUE;
8087601fb54SVictor Perevertkin }
8097601fb54SVictor Perevertkin
8107601fb54SVictor Perevertkin /* Now lie and say this was spurious */
8117601fb54SVictor Perevertkin return FALSE;
8127601fb54SVictor Perevertkin }
8137601fb54SVictor Perevertkin
8147601fb54SVictor Perevertkin BOOLEAN
8157601fb54SVictor Perevertkin NTAPI
HalpDismissIrqLevel(IN KIRQL Irql,IN ULONG Irq,OUT PKIRQL OldIrql)8167601fb54SVictor Perevertkin HalpDismissIrqLevel(IN KIRQL Irql,
8177601fb54SVictor Perevertkin IN ULONG Irq,
8187601fb54SVictor Perevertkin OUT PKIRQL OldIrql)
8197601fb54SVictor Perevertkin {
8207601fb54SVictor Perevertkin /* Run the inline code */
8217601fb54SVictor Perevertkin return _HalpDismissIrqLevel(Irql, Irq, OldIrql);
8227601fb54SVictor Perevertkin }
8237601fb54SVictor Perevertkin
8247601fb54SVictor Perevertkin BOOLEAN
8257601fb54SVictor Perevertkin NTAPI
HalpDismissIrq15Level(IN KIRQL Irql,IN ULONG Irq,OUT PKIRQL OldIrql)8267601fb54SVictor Perevertkin HalpDismissIrq15Level(IN KIRQL Irql,
8277601fb54SVictor Perevertkin IN ULONG Irq,
8287601fb54SVictor Perevertkin OUT PKIRQL OldIrql)
8297601fb54SVictor Perevertkin {
8307601fb54SVictor Perevertkin I8259_OCW3 Ocw3;
8317601fb54SVictor Perevertkin I8259_OCW2 Ocw2;
8327601fb54SVictor Perevertkin I8259_ISR Isr;
8337601fb54SVictor Perevertkin
8347601fb54SVictor Perevertkin /* Request the ISR */
8357601fb54SVictor Perevertkin Ocw3.Bits = 0;
8367601fb54SVictor Perevertkin Ocw3.Sbo = 1; /* This encodes an OCW3 vs. an OCW2 */
8377601fb54SVictor Perevertkin Ocw3.ReadRequest = ReadIsr;
8387601fb54SVictor Perevertkin __outbyte(PIC2_CONTROL_PORT, Ocw3.Bits);
8397601fb54SVictor Perevertkin
8407601fb54SVictor Perevertkin /* Read the ISR */
8417601fb54SVictor Perevertkin Isr.Bits = __inbyte(PIC2_CONTROL_PORT);
8427601fb54SVictor Perevertkin
8437601fb54SVictor Perevertkin /* Is IRQ15 really active (this is IR7) */
8447601fb54SVictor Perevertkin if (Isr.Irq7 == FALSE)
8457601fb54SVictor Perevertkin {
8467601fb54SVictor Perevertkin /* It isn't, so we have to EOI cascade IRQ */
8477601fb54SVictor Perevertkin Ocw2.Bits = 0;
8487601fb54SVictor Perevertkin Ocw2.EoiMode = SpecificEoi;
8497601fb54SVictor Perevertkin __outbyte(PIC1_CONTROL_PORT, Ocw2.Bits | PIC_CASCADE_IRQ);
8507601fb54SVictor Perevertkin
8517601fb54SVictor Perevertkin /* And now fail since this was spurious */
8527601fb54SVictor Perevertkin return FALSE;
8537601fb54SVictor Perevertkin }
8547601fb54SVictor Perevertkin
8557601fb54SVictor Perevertkin /* Do normal interrupt dismiss */
8567601fb54SVictor Perevertkin return _HalpDismissIrqLevel(Irql, Irq, OldIrql);
8577601fb54SVictor Perevertkin }
8587601fb54SVictor Perevertkin
8597601fb54SVictor Perevertkin BOOLEAN
8607601fb54SVictor Perevertkin NTAPI
HalpDismissIrq13Level(IN KIRQL Irql,IN ULONG Irq,OUT PKIRQL OldIrql)8617601fb54SVictor Perevertkin HalpDismissIrq13Level(IN KIRQL Irql,
8627601fb54SVictor Perevertkin IN ULONG Irq,
8637601fb54SVictor Perevertkin OUT PKIRQL OldIrql)
8647601fb54SVictor Perevertkin {
8657601fb54SVictor Perevertkin /* Clear the FPU busy latch */
8667601fb54SVictor Perevertkin __outbyte(0xF0, 0);
8677601fb54SVictor Perevertkin
8687601fb54SVictor Perevertkin /* Do normal interrupt dismiss */
8697601fb54SVictor Perevertkin return _HalpDismissIrqLevel(Irql, Irq, OldIrql);
8707601fb54SVictor Perevertkin }
8717601fb54SVictor Perevertkin
8727601fb54SVictor Perevertkin #if defined(SARCH_PC98)
8737601fb54SVictor Perevertkin BOOLEAN
8747601fb54SVictor Perevertkin NTAPI
HalpDismissIrq08Level(_In_ KIRQL Irql,_In_ ULONG Irq,_Out_ PKIRQL OldIrql)8757601fb54SVictor Perevertkin HalpDismissIrq08Level(
8767601fb54SVictor Perevertkin _In_ KIRQL Irql,
8777601fb54SVictor Perevertkin _In_ ULONG Irq,
8787601fb54SVictor Perevertkin _Out_ PKIRQL OldIrql)
8797601fb54SVictor Perevertkin {
8807601fb54SVictor Perevertkin /* Clear the FPU busy latch */
8817601fb54SVictor Perevertkin __outbyte(CPU_IO_o_FPU_BUSY_LATCH, 0);
8827601fb54SVictor Perevertkin
8837601fb54SVictor Perevertkin /* Do normal interrupt dismiss */
8847601fb54SVictor Perevertkin return _HalpDismissIrqLevel(Irql, Irq, OldIrql);
8857601fb54SVictor Perevertkin }
8867601fb54SVictor Perevertkin #endif
8877601fb54SVictor Perevertkin
8887601fb54SVictor Perevertkin BOOLEAN
8897601fb54SVictor Perevertkin NTAPI
HalpDismissIrq07Level(IN KIRQL Irql,IN ULONG Irq,OUT PKIRQL OldIrql)8907601fb54SVictor Perevertkin HalpDismissIrq07Level(IN KIRQL Irql,
8917601fb54SVictor Perevertkin IN ULONG Irq,
8927601fb54SVictor Perevertkin OUT PKIRQL OldIrql)
8937601fb54SVictor Perevertkin {
8947601fb54SVictor Perevertkin I8259_OCW3 Ocw3;
8957601fb54SVictor Perevertkin I8259_ISR Isr;
8967601fb54SVictor Perevertkin
8977601fb54SVictor Perevertkin /* Request the ISR */
8987601fb54SVictor Perevertkin Ocw3.Bits = 0;
8997601fb54SVictor Perevertkin Ocw3.Sbo = 1;
9007601fb54SVictor Perevertkin Ocw3.ReadRequest = ReadIsr;
9017601fb54SVictor Perevertkin __outbyte(PIC1_CONTROL_PORT, Ocw3.Bits);
9027601fb54SVictor Perevertkin
9037601fb54SVictor Perevertkin /* Read the ISR */
9047601fb54SVictor Perevertkin Isr.Bits = __inbyte(PIC1_CONTROL_PORT);
9057601fb54SVictor Perevertkin
9067601fb54SVictor Perevertkin /* Is IRQ 7 really active? If it isn't, this is spurious so fail */
9077601fb54SVictor Perevertkin if (Isr.Irq7 == FALSE) return FALSE;
9087601fb54SVictor Perevertkin
9097601fb54SVictor Perevertkin /* Do normal interrupt dismiss */
9107601fb54SVictor Perevertkin return _HalpDismissIrqLevel(Irql, Irq, OldIrql);
9117601fb54SVictor Perevertkin }
9127601fb54SVictor Perevertkin
9137601fb54SVictor Perevertkin PHAL_SW_INTERRUPT_HANDLER
9147601fb54SVictor Perevertkin __cdecl
HalpHardwareInterruptLevel2(VOID)9157601fb54SVictor Perevertkin HalpHardwareInterruptLevel2(VOID)
9167601fb54SVictor Perevertkin {
9177601fb54SVictor Perevertkin PKPCR Pcr = KeGetPcr();
9187601fb54SVictor Perevertkin ULONG PendingIrqlMask, PendingIrql;
9197601fb54SVictor Perevertkin
9207601fb54SVictor Perevertkin /* Check for pending software interrupts and compare with current IRQL */
9217601fb54SVictor Perevertkin PendingIrqlMask = Pcr->IRR & FindHigherIrqlMask[Pcr->Irql];
9227601fb54SVictor Perevertkin if (PendingIrqlMask)
9237601fb54SVictor Perevertkin {
9247601fb54SVictor Perevertkin /* Check for in-service delayed interrupt */
9257601fb54SVictor Perevertkin if (Pcr->IrrActive & 0xFFFFFFF0) return NULL;
9267601fb54SVictor Perevertkin
9277601fb54SVictor Perevertkin /* Check if pending IRQL affects hardware state */
9287601fb54SVictor Perevertkin BitScanReverse(&PendingIrql, PendingIrqlMask);
9297601fb54SVictor Perevertkin
9307601fb54SVictor Perevertkin /* Clear IRR bit */
9317601fb54SVictor Perevertkin Pcr->IRR ^= (1 << PendingIrql);
9327601fb54SVictor Perevertkin
9337601fb54SVictor Perevertkin /* Now handle pending interrupt */
9347601fb54SVictor Perevertkin return SWInterruptHandlerTable[PendingIrql];
9357601fb54SVictor Perevertkin }
9367601fb54SVictor Perevertkin
9377601fb54SVictor Perevertkin return NULL;
9387601fb54SVictor Perevertkin }
9397601fb54SVictor Perevertkin
9407601fb54SVictor Perevertkin /* SYSTEM INTERRUPTS **********************************************************/
9417601fb54SVictor Perevertkin
9427601fb54SVictor Perevertkin /*
9437601fb54SVictor Perevertkin * @implemented
9447601fb54SVictor Perevertkin */
9457601fb54SVictor Perevertkin BOOLEAN
9467601fb54SVictor Perevertkin NTAPI
HalEnableSystemInterrupt(IN ULONG Vector,IN KIRQL Irql,IN KINTERRUPT_MODE InterruptMode)9477601fb54SVictor Perevertkin HalEnableSystemInterrupt(IN ULONG Vector,
9487601fb54SVictor Perevertkin IN KIRQL Irql,
9497601fb54SVictor Perevertkin IN KINTERRUPT_MODE InterruptMode)
9507601fb54SVictor Perevertkin {
9517601fb54SVictor Perevertkin ULONG Irq;
9527601fb54SVictor Perevertkin PKPCR Pcr = KeGetPcr();
9537601fb54SVictor Perevertkin PIC_MASK PicMask;
9547601fb54SVictor Perevertkin
9557601fb54SVictor Perevertkin /* Validate the IRQ */
9567601fb54SVictor Perevertkin Irq = Vector - PRIMARY_VECTOR_BASE;
9577601fb54SVictor Perevertkin if (Irq >= CLOCK2_LEVEL) return FALSE;
9587601fb54SVictor Perevertkin
9597601fb54SVictor Perevertkin /* Check for level interrupt */
9607601fb54SVictor Perevertkin if (InterruptMode == LevelSensitive)
9617601fb54SVictor Perevertkin {
9627601fb54SVictor Perevertkin /* Switch handler to level */
9637601fb54SVictor Perevertkin SWInterruptHandlerTable[Irq + 4] = HalpHardwareInterruptLevel;
9647601fb54SVictor Perevertkin
9657601fb54SVictor Perevertkin /* Switch dismiss to level */
9667601fb54SVictor Perevertkin HalpSpecialDismissTable[Irq] = HalpSpecialDismissLevelTable[Irq];
9677601fb54SVictor Perevertkin }
9687601fb54SVictor Perevertkin
9697601fb54SVictor Perevertkin /* Disable interrupts */
9707601fb54SVictor Perevertkin _disable();
9717601fb54SVictor Perevertkin
9727601fb54SVictor Perevertkin /* Update software IDR */
9737601fb54SVictor Perevertkin Pcr->IDR &= ~(1 << Irq);
9747601fb54SVictor Perevertkin
9757601fb54SVictor Perevertkin /* Set new PIC mask */
9767601fb54SVictor Perevertkin PicMask.Both = (KiI8259MaskTable[Pcr->Irql] | Pcr->IDR) & 0xFFFF;
9777601fb54SVictor Perevertkin __outbyte(PIC1_DATA_PORT, PicMask.Master);
9787601fb54SVictor Perevertkin __outbyte(PIC2_DATA_PORT, PicMask.Slave);
9797601fb54SVictor Perevertkin
9807601fb54SVictor Perevertkin /* Enable interrupts and exit */
9817601fb54SVictor Perevertkin _enable();
9827601fb54SVictor Perevertkin return TRUE;
9837601fb54SVictor Perevertkin }
9847601fb54SVictor Perevertkin
9857601fb54SVictor Perevertkin /*
9867601fb54SVictor Perevertkin * @implemented
9877601fb54SVictor Perevertkin */
9887601fb54SVictor Perevertkin VOID
9897601fb54SVictor Perevertkin NTAPI
HalDisableSystemInterrupt(IN ULONG Vector,IN KIRQL Irql)9907601fb54SVictor Perevertkin HalDisableSystemInterrupt(IN ULONG Vector,
9917601fb54SVictor Perevertkin IN KIRQL Irql)
9927601fb54SVictor Perevertkin {
9937601fb54SVictor Perevertkin ULONG IrqMask;
9947601fb54SVictor Perevertkin PIC_MASK PicMask;
9957601fb54SVictor Perevertkin
9967601fb54SVictor Perevertkin /* Compute new combined IRQ mask */
9977601fb54SVictor Perevertkin IrqMask = 1 << (Vector - PRIMARY_VECTOR_BASE);
9987601fb54SVictor Perevertkin
9997601fb54SVictor Perevertkin /* Disable interrupts */
10007601fb54SVictor Perevertkin _disable();
10017601fb54SVictor Perevertkin
10027601fb54SVictor Perevertkin /* Update software IDR */
10037601fb54SVictor Perevertkin KeGetPcr()->IDR |= IrqMask;
10047601fb54SVictor Perevertkin
10057601fb54SVictor Perevertkin /* Read current interrupt mask */
10067601fb54SVictor Perevertkin PicMask.Master = __inbyte(PIC1_DATA_PORT);
10077601fb54SVictor Perevertkin PicMask.Slave = __inbyte(PIC2_DATA_PORT);
10087601fb54SVictor Perevertkin
10097601fb54SVictor Perevertkin /* Add the new disabled interrupt */
10107601fb54SVictor Perevertkin PicMask.Both |= IrqMask;
10117601fb54SVictor Perevertkin
10127601fb54SVictor Perevertkin /* Write new interrupt mask */
10137601fb54SVictor Perevertkin __outbyte(PIC1_DATA_PORT, PicMask.Master);
10147601fb54SVictor Perevertkin __outbyte(PIC2_DATA_PORT, PicMask.Slave);
10157601fb54SVictor Perevertkin
10167601fb54SVictor Perevertkin /* Bring interrupts back */
10177601fb54SVictor Perevertkin _enable();
10187601fb54SVictor Perevertkin }
10197601fb54SVictor Perevertkin
10207601fb54SVictor Perevertkin /*
10217601fb54SVictor Perevertkin * @implemented
10227601fb54SVictor Perevertkin */
10237601fb54SVictor Perevertkin BOOLEAN
10247601fb54SVictor Perevertkin NTAPI
HalBeginSystemInterrupt(IN KIRQL Irql,IN ULONG Vector,OUT PKIRQL OldIrql)10257601fb54SVictor Perevertkin HalBeginSystemInterrupt(IN KIRQL Irql,
10267601fb54SVictor Perevertkin IN ULONG Vector,
10277601fb54SVictor Perevertkin OUT PKIRQL OldIrql)
10287601fb54SVictor Perevertkin {
10297601fb54SVictor Perevertkin ULONG Irq;
10307601fb54SVictor Perevertkin
10317601fb54SVictor Perevertkin /* Get the IRQ and call the proper routine to handle it */
10327601fb54SVictor Perevertkin Irq = Vector - PRIMARY_VECTOR_BASE;
10337601fb54SVictor Perevertkin return HalpSpecialDismissTable[Irq](Irql, Irq, OldIrql);
10347601fb54SVictor Perevertkin }
10357601fb54SVictor Perevertkin
10367601fb54SVictor Perevertkin /*
10377601fb54SVictor Perevertkin * @implemented
10387601fb54SVictor Perevertkin */
10397601fb54SVictor Perevertkin PHAL_SW_INTERRUPT_HANDLER_2ND_ENTRY
10407601fb54SVictor Perevertkin FASTCALL
HalEndSystemInterrupt2(IN KIRQL OldIrql,IN PKTRAP_FRAME TrapFrame)10417601fb54SVictor Perevertkin HalEndSystemInterrupt2(IN KIRQL OldIrql,
10427601fb54SVictor Perevertkin IN PKTRAP_FRAME TrapFrame)
10437601fb54SVictor Perevertkin {
10447601fb54SVictor Perevertkin ULONG PendingIrql, PendingIrqlMask, PendingIrqMask;
10457601fb54SVictor Perevertkin PKPCR Pcr = KeGetPcr();
10467601fb54SVictor Perevertkin PIC_MASK Mask;
10477601fb54SVictor Perevertkin
10487601fb54SVictor Perevertkin /* Set old IRQL */
10497601fb54SVictor Perevertkin Pcr->Irql = OldIrql;
10507601fb54SVictor Perevertkin
10517601fb54SVictor Perevertkin /* Check for pending software interrupts and compare with current IRQL */
10527601fb54SVictor Perevertkin PendingIrqlMask = Pcr->IRR & FindHigherIrqlMask[OldIrql];
10537601fb54SVictor Perevertkin if (PendingIrqlMask)
10547601fb54SVictor Perevertkin {
10557601fb54SVictor Perevertkin /* Check for in-service delayed interrupt */
10567601fb54SVictor Perevertkin if (Pcr->IrrActive & 0xFFFFFFF0) return NULL;
10577601fb54SVictor Perevertkin
10587601fb54SVictor Perevertkin /* Loop checking for pending interrupts */
10597601fb54SVictor Perevertkin while (TRUE)
10607601fb54SVictor Perevertkin {
10617601fb54SVictor Perevertkin /* Check if pending IRQL affects hardware state */
10627601fb54SVictor Perevertkin BitScanReverse(&PendingIrql, PendingIrqlMask);
10637601fb54SVictor Perevertkin if (PendingIrql > DISPATCH_LEVEL)
10647601fb54SVictor Perevertkin {
10657601fb54SVictor Perevertkin /* Set new PIC mask */
10667601fb54SVictor Perevertkin Mask.Both = Pcr->IDR & 0xFFFF;
10677601fb54SVictor Perevertkin __outbyte(PIC1_DATA_PORT, Mask.Master);
10687601fb54SVictor Perevertkin __outbyte(PIC2_DATA_PORT, Mask.Slave);
10697601fb54SVictor Perevertkin
10707601fb54SVictor Perevertkin /* Now check if this specific interrupt is already in-service */
10717601fb54SVictor Perevertkin PendingIrqMask = (1 << PendingIrql);
10727601fb54SVictor Perevertkin if (Pcr->IrrActive & PendingIrqMask) return NULL;
10737601fb54SVictor Perevertkin
10747601fb54SVictor Perevertkin /* Set active bit otherwise, and clear it from IRR */
10757601fb54SVictor Perevertkin Pcr->IrrActive |= PendingIrqMask;
10767601fb54SVictor Perevertkin Pcr->IRR ^= PendingIrqMask;
10777601fb54SVictor Perevertkin
10787601fb54SVictor Perevertkin /* Handle delayed hardware interrupt */
10797601fb54SVictor Perevertkin SWInterruptHandlerTable[PendingIrql]();
10807601fb54SVictor Perevertkin
10817601fb54SVictor Perevertkin /* Handling complete */
10827601fb54SVictor Perevertkin Pcr->IrrActive ^= PendingIrqMask;
10837601fb54SVictor Perevertkin
10847601fb54SVictor Perevertkin /* Check if there's still interrupts pending */
10857601fb54SVictor Perevertkin PendingIrqlMask = Pcr->IRR & FindHigherIrqlMask[Pcr->Irql];
10867601fb54SVictor Perevertkin if (!PendingIrqlMask) break;
10877601fb54SVictor Perevertkin }
10887601fb54SVictor Perevertkin else
10897601fb54SVictor Perevertkin {
10907601fb54SVictor Perevertkin /* Now handle pending software interrupt */
10917601fb54SVictor Perevertkin return SWInterruptHandlerTable2[PendingIrql];
10927601fb54SVictor Perevertkin }
10937601fb54SVictor Perevertkin }
10947601fb54SVictor Perevertkin }
10957601fb54SVictor Perevertkin
10967601fb54SVictor Perevertkin return NULL;
10977601fb54SVictor Perevertkin }
10987601fb54SVictor Perevertkin
10997601fb54SVictor Perevertkin /* SOFTWARE INTERRUPT TRAPS ***************************************************/
11007601fb54SVictor Perevertkin
11017601fb54SVictor Perevertkin FORCEINLINE
11027601fb54SVictor Perevertkin DECLSPEC_NORETURN
11037601fb54SVictor Perevertkin VOID
_HalpApcInterruptHandler(IN PKTRAP_FRAME TrapFrame)11047601fb54SVictor Perevertkin _HalpApcInterruptHandler(IN PKTRAP_FRAME TrapFrame)
11057601fb54SVictor Perevertkin {
11067601fb54SVictor Perevertkin KIRQL CurrentIrql;
11077601fb54SVictor Perevertkin PKPCR Pcr = KeGetPcr();
11087601fb54SVictor Perevertkin
11097601fb54SVictor Perevertkin /* Save the current IRQL and update it */
11107601fb54SVictor Perevertkin CurrentIrql = Pcr->Irql;
11117601fb54SVictor Perevertkin Pcr->Irql = APC_LEVEL;
11127601fb54SVictor Perevertkin
11137601fb54SVictor Perevertkin /* Remove DPC from IRR */
11147601fb54SVictor Perevertkin Pcr->IRR &= ~(1 << APC_LEVEL);
11157601fb54SVictor Perevertkin
11167601fb54SVictor Perevertkin /* Enable interrupts and call the kernel's APC interrupt handler */
11177601fb54SVictor Perevertkin _enable();
11187601fb54SVictor Perevertkin KiDeliverApc(((KiUserTrap(TrapFrame)) || (TrapFrame->EFlags & EFLAGS_V86_MASK)) ?
11197601fb54SVictor Perevertkin UserMode : KernelMode,
11207601fb54SVictor Perevertkin NULL,
11217601fb54SVictor Perevertkin TrapFrame);
11227601fb54SVictor Perevertkin
11237601fb54SVictor Perevertkin /* Disable interrupts and end the interrupt */
11247601fb54SVictor Perevertkin _disable();
11257601fb54SVictor Perevertkin HalpEndSoftwareInterrupt(CurrentIrql, TrapFrame);
11267601fb54SVictor Perevertkin
11277601fb54SVictor Perevertkin /* Exit the interrupt */
11287601fb54SVictor Perevertkin KiEoiHelper(TrapFrame);
11297601fb54SVictor Perevertkin }
11307601fb54SVictor Perevertkin
11317601fb54SVictor Perevertkin DECLSPEC_NORETURN
11327601fb54SVictor Perevertkin VOID
11337601fb54SVictor Perevertkin FASTCALL
HalpApcInterrupt2ndEntry(IN PKTRAP_FRAME TrapFrame)11347601fb54SVictor Perevertkin HalpApcInterrupt2ndEntry(IN PKTRAP_FRAME TrapFrame)
11357601fb54SVictor Perevertkin {
11367601fb54SVictor Perevertkin /* Do the work */
11377601fb54SVictor Perevertkin _HalpApcInterruptHandler(TrapFrame);
11387601fb54SVictor Perevertkin }
11397601fb54SVictor Perevertkin
11407601fb54SVictor Perevertkin DECLSPEC_NORETURN
11417601fb54SVictor Perevertkin VOID
11427601fb54SVictor Perevertkin FASTCALL
HalpApcInterruptHandler(IN PKTRAP_FRAME TrapFrame)11437601fb54SVictor Perevertkin HalpApcInterruptHandler(IN PKTRAP_FRAME TrapFrame)
11447601fb54SVictor Perevertkin {
11457601fb54SVictor Perevertkin /* Set up a fake INT Stack */
11467601fb54SVictor Perevertkin TrapFrame->EFlags = __readeflags();
11477601fb54SVictor Perevertkin TrapFrame->SegCs = KGDT_R0_CODE;
11487601fb54SVictor Perevertkin TrapFrame->Eip = TrapFrame->Eax;
11497601fb54SVictor Perevertkin
11507601fb54SVictor Perevertkin /* Build the trap frame */
11517601fb54SVictor Perevertkin KiEnterInterruptTrap(TrapFrame);
11527601fb54SVictor Perevertkin
11537601fb54SVictor Perevertkin /* Do the work */
11547601fb54SVictor Perevertkin _HalpApcInterruptHandler(TrapFrame);
11557601fb54SVictor Perevertkin }
11567601fb54SVictor Perevertkin
11577601fb54SVictor Perevertkin FORCEINLINE
11587601fb54SVictor Perevertkin KIRQL
_HalpDispatchInterruptHandler(VOID)11597601fb54SVictor Perevertkin _HalpDispatchInterruptHandler(VOID)
11607601fb54SVictor Perevertkin {
11617601fb54SVictor Perevertkin KIRQL CurrentIrql;
11627601fb54SVictor Perevertkin PKPCR Pcr = KeGetPcr();
11637601fb54SVictor Perevertkin
11647601fb54SVictor Perevertkin /* Save the current IRQL and update it */
11657601fb54SVictor Perevertkin CurrentIrql = Pcr->Irql;
11667601fb54SVictor Perevertkin Pcr->Irql = DISPATCH_LEVEL;
11677601fb54SVictor Perevertkin
11687601fb54SVictor Perevertkin /* Remove DPC from IRR */
11697601fb54SVictor Perevertkin Pcr->IRR &= ~(1 << DISPATCH_LEVEL);
11707601fb54SVictor Perevertkin
11717601fb54SVictor Perevertkin /* Enable interrupts and call the kernel's DPC interrupt handler */
11727601fb54SVictor Perevertkin _enable();
11737601fb54SVictor Perevertkin KiDispatchInterrupt();
11747601fb54SVictor Perevertkin _disable();
11757601fb54SVictor Perevertkin
11767601fb54SVictor Perevertkin /* Return IRQL */
11777601fb54SVictor Perevertkin return CurrentIrql;
11787601fb54SVictor Perevertkin }
11797601fb54SVictor Perevertkin
11807601fb54SVictor Perevertkin DECLSPEC_NORETURN
11817601fb54SVictor Perevertkin VOID
11827601fb54SVictor Perevertkin FASTCALL
HalpDispatchInterrupt2ndEntry(IN PKTRAP_FRAME TrapFrame)11837601fb54SVictor Perevertkin HalpDispatchInterrupt2ndEntry(IN PKTRAP_FRAME TrapFrame)
11847601fb54SVictor Perevertkin {
11857601fb54SVictor Perevertkin KIRQL CurrentIrql;
11867601fb54SVictor Perevertkin
11877601fb54SVictor Perevertkin /* Do the work */
11887601fb54SVictor Perevertkin CurrentIrql = _HalpDispatchInterruptHandler();
11897601fb54SVictor Perevertkin
11907601fb54SVictor Perevertkin /* End the interrupt */
11917601fb54SVictor Perevertkin HalpEndSoftwareInterrupt(CurrentIrql, TrapFrame);
11927601fb54SVictor Perevertkin
11937601fb54SVictor Perevertkin /* Exit the interrupt */
11947601fb54SVictor Perevertkin KiEoiHelper(TrapFrame);
11957601fb54SVictor Perevertkin }
11967601fb54SVictor Perevertkin
11977601fb54SVictor Perevertkin PHAL_SW_INTERRUPT_HANDLER
11987601fb54SVictor Perevertkin __cdecl
HalpDispatchInterrupt2(VOID)11997601fb54SVictor Perevertkin HalpDispatchInterrupt2(VOID)
12007601fb54SVictor Perevertkin {
12017601fb54SVictor Perevertkin ULONG PendingIrqlMask, PendingIrql;
12027601fb54SVictor Perevertkin KIRQL OldIrql;
12037601fb54SVictor Perevertkin PIC_MASK Mask;
12047601fb54SVictor Perevertkin PKPCR Pcr = KeGetPcr();
12057601fb54SVictor Perevertkin
12067601fb54SVictor Perevertkin /* Do the work */
12077601fb54SVictor Perevertkin OldIrql = _HalpDispatchInterruptHandler();
12087601fb54SVictor Perevertkin
12097601fb54SVictor Perevertkin /* Restore IRQL */
12107601fb54SVictor Perevertkin Pcr->Irql = OldIrql;
12117601fb54SVictor Perevertkin
12127601fb54SVictor Perevertkin /* Check for pending software interrupts and compare with current IRQL */
12137601fb54SVictor Perevertkin PendingIrqlMask = Pcr->IRR & FindHigherIrqlMask[OldIrql];
12147601fb54SVictor Perevertkin if (PendingIrqlMask)
12157601fb54SVictor Perevertkin {
12167601fb54SVictor Perevertkin /* Check if pending IRQL affects hardware state */
12177601fb54SVictor Perevertkin BitScanReverse(&PendingIrql, PendingIrqlMask);
12187601fb54SVictor Perevertkin if (PendingIrql > DISPATCH_LEVEL)
12197601fb54SVictor Perevertkin {
12207601fb54SVictor Perevertkin /* Set new PIC mask */
12217601fb54SVictor Perevertkin Mask.Both = Pcr->IDR & 0xFFFF;
12227601fb54SVictor Perevertkin __outbyte(PIC1_DATA_PORT, Mask.Master);
12237601fb54SVictor Perevertkin __outbyte(PIC2_DATA_PORT, Mask.Slave);
12247601fb54SVictor Perevertkin
12257601fb54SVictor Perevertkin /* Clear IRR bit */
12267601fb54SVictor Perevertkin Pcr->IRR ^= (1 << PendingIrql);
12277601fb54SVictor Perevertkin }
12287601fb54SVictor Perevertkin
12297601fb54SVictor Perevertkin /* Now handle pending interrupt */
12307601fb54SVictor Perevertkin return SWInterruptHandlerTable[PendingIrql];
12317601fb54SVictor Perevertkin }
12327601fb54SVictor Perevertkin
12337601fb54SVictor Perevertkin return NULL;
12347601fb54SVictor Perevertkin }
12357601fb54SVictor Perevertkin
1236*64e52088STimo Kreuzer ULONG
1237*64e52088STimo Kreuzer NTAPI
HalpGetRootInterruptVector(IN ULONG BusInterruptLevel,IN ULONG BusInterruptVector,OUT PKIRQL Irql,OUT PKAFFINITY Affinity)1238*64e52088STimo Kreuzer HalpGetRootInterruptVector(IN ULONG BusInterruptLevel,
1239*64e52088STimo Kreuzer IN ULONG BusInterruptVector,
1240*64e52088STimo Kreuzer OUT PKIRQL Irql,
1241*64e52088STimo Kreuzer OUT PKAFFINITY Affinity)
1242*64e52088STimo Kreuzer {
1243*64e52088STimo Kreuzer UCHAR SystemVector;
1244*64e52088STimo Kreuzer
1245*64e52088STimo Kreuzer /* Validate the IRQ */
1246*64e52088STimo Kreuzer if (BusInterruptLevel > 23)
1247*64e52088STimo Kreuzer {
1248*64e52088STimo Kreuzer /* Invalid vector */
1249*64e52088STimo Kreuzer DPRINT1("IRQ %lx is too high!\n", BusInterruptLevel);
1250*64e52088STimo Kreuzer return 0;
1251*64e52088STimo Kreuzer }
1252*64e52088STimo Kreuzer
1253*64e52088STimo Kreuzer /* Get the system vector */
1254*64e52088STimo Kreuzer SystemVector = HalpIrqToVector((UCHAR)BusInterruptLevel);
1255*64e52088STimo Kreuzer
1256*64e52088STimo Kreuzer /* Return the IRQL and affinity */
1257*64e52088STimo Kreuzer *Irql = HalpVectorToIrql(SystemVector);
1258*64e52088STimo Kreuzer *Affinity = HalpDefaultInterruptAffinity;
1259*64e52088STimo Kreuzer ASSERT(HalpDefaultInterruptAffinity);
1260*64e52088STimo Kreuzer
1261*64e52088STimo Kreuzer /* Return the vector */
1262*64e52088STimo Kreuzer return SystemVector;
1263*64e52088STimo Kreuzer }
1264*64e52088STimo Kreuzer
12657601fb54SVictor Perevertkin #else /* _MINIHAL_ */
12667601fb54SVictor Perevertkin
12677601fb54SVictor Perevertkin KIRQL
12687601fb54SVictor Perevertkin NTAPI
KeGetCurrentIrql(VOID)12697601fb54SVictor Perevertkin KeGetCurrentIrql(VOID)
12707601fb54SVictor Perevertkin {
12717601fb54SVictor Perevertkin return PASSIVE_LEVEL;
12727601fb54SVictor Perevertkin }
12737601fb54SVictor Perevertkin
12747601fb54SVictor Perevertkin VOID
12757601fb54SVictor Perevertkin FASTCALL
KfLowerIrql(IN KIRQL OldIrql)12767601fb54SVictor Perevertkin KfLowerIrql(
12777601fb54SVictor Perevertkin IN KIRQL OldIrql)
12787601fb54SVictor Perevertkin {
12797601fb54SVictor Perevertkin }
12807601fb54SVictor Perevertkin
12817601fb54SVictor Perevertkin KIRQL
12827601fb54SVictor Perevertkin FASTCALL
KfRaiseIrql(IN KIRQL NewIrql)12837601fb54SVictor Perevertkin KfRaiseIrql(
12847601fb54SVictor Perevertkin IN KIRQL NewIrql)
12857601fb54SVictor Perevertkin {
12867601fb54SVictor Perevertkin return NewIrql;
12877601fb54SVictor Perevertkin }
12887601fb54SVictor Perevertkin
12897601fb54SVictor Perevertkin #endif /* !_MINIHAL_ */
1290