jmp SWInterruptHandlerTable2[eax*4]
.endfunc
-.globl @KfLowerIrql@4
-.func @KfLowerIrql@4
-_@KfLowerIrql@4:
-@KfLowerIrql@4:
-
- /* Cleanup IRQL */
- and ecx, 0xFF
-
- /* Validate IRQL */
- #if DBG
- cmp cl, PCR[KPCR_IRQL]
- ja InvalidIrql
- #endif
-
- /* Save flags since we'll disable interrupts */
- pushf
- cli
-
- /* Disable interrupts and check if IRQL is below DISPATCH_LEVEL */
- cmp dword ptr PCR[KPCR_IRQL], DISPATCH_LEVEL
- jbe SkipMask
-
- /* Clear interrupt masks since there's a pending hardware interrupt */
- mov eax, KiI8259MaskTable[ecx*4]
- or eax, PCR[KPCR_IDR]
- out 0x21, al
- shr eax, 8
- out 0xA1, al
-
-SkipMask:
-
- /* Set the new IRQL and check if there's a pending software interrupt */
- mov PCR[KPCR_IRQL], ecx
- mov eax, PCR[KPCR_IRR]
- mov al, SWInterruptLookUpTable[eax]
- cmp al, cl
- ja DoCall3
-
- /* Restore interrupts and return */
- popf
- ret
-
-#if DBG
-InvalidIrql:
- /* Set HIGH_LEVEL */
- mov eax, PCR[KPCR_IRQL]
- mov dword ptr PCR[KPCR_IRQL], HIGH_LEVEL
-
- /* Bugcheck the system */
- push 3
- push 0
- push ecx
- push eax
- push IRQL_NOT_LESS_OR_EQUAL
- call _KeBugCheckEx@20
-#endif
-
-DoCall3:
- /* There is, call it */
- call SWInterruptHandlerTable[eax*4]
-
- /* Restore interrupts and return */
- popf
- ret
-.endfunc
-
.globl _HalpApcInterrupt
.func HalpApcInterrupt
TRAP_FIXUPS hapc_a, hapc_t, DoFixupV86, DoFixupAbios
#endif
};
+/* Denotes minimum required IRQL before we can process pending SW interrupts */
+KIRQL SWInterruptLookUpTable[8] =
+{
+ PASSIVE_LEVEL, /* IRR 0 */
+ PASSIVE_LEVEL, /* IRR 1 */
+ APC_LEVEL, /* IRR 2 */
+ APC_LEVEL, /* IRR 3 */
+ DISPATCH_LEVEL, /* IRR 4 */
+ DISPATCH_LEVEL, /* IRR 5 */
+ DISPATCH_LEVEL, /* IRR 6 */
+ DISPATCH_LEVEL /* IRR 7 */
+};
+
+/* Handlers for pending software interrupts */
+PHAL_SW_INTERRUPT_HANDLER SWInterruptHandlerTable[3] =
+{
+ KiUnexpectedInterrupt,
+ HalpApcInterrupt,
+ HalpDispatchInterrupt
+};
+
USHORT HalpEisaELCR;
/* FUNCTIONS ******************************************************************/
return CurrentIrql;
}
+
+/*
+ * @implemented
+ */
+VOID
+FASTCALL
+KfLowerIrql(IN KIRQL OldIrql)
+{
+ ULONG EFlags;
+ KIRQL PendingIrql;
+ PKPCR Pcr = KeGetPcr();
+ PIC_MASK Mask;
+
+#ifdef IRQL_DEBUG
+ /* Validate correct lower */
+ if (OldIrql > Pcr->Irql)
+ {
+ /* Crash system */
+ KIRQL CurrentIrql = Pcr->Irql;
+ Pcr->Irql = HIGH_LEVEL;
+ KeBugCheckEx(IRQL_NOT_LESS_OR_EQUAL,
+ CurrentIrql,
+ OldIrql,
+ 0,
+ 3);
+ }
+#endif
+
+ /* Save EFlags and disable interrupts */
+ EFlags = __readeflags();
+ _disable();
+
+ /* Check if currentl IRQL affects hardware state */
+ if (Pcr->Irql > DISPATCH_LEVEL)
+ {
+ /* Set new PIC mask */
+ Mask.Both = KiI8259MaskTable[OldIrql] | Pcr->IDR;
+ __outbyte(PIC1_DATA_PORT, Mask.Master);
+ __outbyte(PIC2_DATA_PORT, Mask.Slave);
+ }
+
+ /* Set old IRQL */
+ Pcr->Irql = OldIrql;
+
+ /* Check for pending software interrupts and compare with current IRQL */
+ PendingIrql = SWInterruptLookUpTable[Pcr->IRR];
+ if (PendingIrql > OldIrql) SWInterruptHandlerTable[PendingIrql]();
+
+ /* Restore interrupt state */
+ __writeeflags(EFlags);
+}
+
/* SOFTWARE INTERRUPTS ********************************************************/
/*