xref: /reactos/hal/halx86/pic/pic.c (revision 9393fc32)
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