#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
+};
+
+/* Handlers for pending software interrupts when we already have a trap frame*/
+PHAL_SW_INTERRUPT_HANDLER_2ND_ENTRY SWInterruptHandlerTable2[3] =
+{
+ (PHAL_SW_INTERRUPT_HANDLER_2ND_ENTRY)KiUnexpectedInterrupt,
+ HalpApcInterrupt2ndEntry,
+ HalpDispatchInterrupt2ndEntry
+};
+
+
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 ********************************************************/
+/*
+ * @implemented
+ */
+VOID
+FASTCALL
+HalRequestSoftwareInterrupt(IN KIRQL Irql)
+{
+ ULONG EFlags;
+ PKPCR Pcr = KeGetPcr();
+ KIRQL PendingIrql;
+
+ /* Save EFlags and disable interrupts */
+ EFlags = __readeflags();
+ _disable();
+
+ /* Mask out the requested bit */
+ Pcr->IRR |= (1 << Irql);
+
+ /* Check for pending software interrupts and compare with current IRQL */
+ PendingIrql = SWInterruptLookUpTable[Pcr->IRR & 3];
+ if (PendingIrql > Pcr->Irql) SWInterruptHandlerTable[PendingIrql]();
+
+ /* Restore interrupt state */
+ __writeeflags(EFlags);
+}
+
/*
* @implemented
*/
KeGetPcr()->IRR &= ~(1 << Irql);
}
+VOID
+NTAPI
+HalpEndSoftwareInterrupt(IN KIRQL OldIrql)
+{
+ KIRQL PendingIrql;
+ PKPCR Pcr = KeGetPcr();
+ PIC_MASK Mask;
+
+ /* 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) HalpNestedTrap(PendingIrql);
+}
+
/* INTERRUPT DISMISSAL FUNCTIONS **********************************************/
BOOLEAN
Irq = Vector - PRIMARY_VECTOR_BASE;
return HalpSpecialDismissTable[Irq](Irql, Irq, OldIrql);
}
+
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+HalEndSystemInterrupt(IN KIRQL OldIrql,
+ IN UCHAR Vector)
+{
+ KIRQL PendingIrql;
+ PKPCR Pcr = KeGetPcr();
+ PIC_MASK Mask;
+
+ /* 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) HalpNestedTrap(PendingIrql);
+}
+
+/* SOFTWARE INTERRUPT TRAPS ***************************************************/
+
+VOID
+FORCEINLINE
+DECLSPEC_NORETURN
+_HalpApcInterruptHandler(IN PKTRAP_FRAME TrapFrame)
+{
+ KIRQL CurrentIrql;
+ PKPCR Pcr = KeGetPcr();
+
+ /* Save the current IRQL and update it */
+ CurrentIrql = Pcr->Irql;
+ Pcr->Irql = APC_LEVEL;
+
+ /* Remove DPC from IRR */
+ Pcr->IRR &= ~(1 << APC_LEVEL);
+
+ /* Enable interrupts and call the kernel's APC interrupt handler */
+ _enable();
+ KiDeliverApc(((KiUserTrap(TrapFrame)) || (TrapFrame->EFlags & EFLAGS_V86_MASK)) ?
+ UserMode : KernelMode,
+ NULL,
+ TrapFrame);
+
+ /* Disable interrupts and end the interrupt */
+ _disable();
+ Pcr->VdmAlert = (ULONG_PTR)TrapFrame;
+ HalpEndSoftwareInterrupt(CurrentIrql);
+
+ /* Exit the interrupt */
+ KiEoiHelper(TrapFrame);
+}
+
+VOID
+FASTCALL
+DECLSPEC_NORETURN
+HalpApcInterrupt2ndEntry(IN PKTRAP_FRAME TrapFrame)
+{
+ /* Do the work */
+ _HalpApcInterruptHandler(TrapFrame);
+}
+
+VOID
+FASTCALL
+DECLSPEC_NORETURN
+HalpApcInterruptHandler(IN PKTRAP_FRAME TrapFrame)
+{
+ /* Set up a fake INT Stack */
+ TrapFrame->EFlags = __readeflags();
+ TrapFrame->SegCs = KGDT_R0_CODE;
+ TrapFrame->Eip = TrapFrame->Eax;
+
+ /* Build the trap frame */
+ KiEnterInterruptTrap(TrapFrame);
+
+ /* Do the work */
+ _HalpApcInterruptHandler(TrapFrame);
+}
+
+VOID
+FORCEINLINE
+DECLSPEC_NORETURN
+_HalpDispatchInterruptHandler(IN PKTRAP_FRAME TrapFrame)
+{
+ KIRQL CurrentIrql;
+ PKPCR Pcr = KeGetPcr();
+
+ /* Save the current IRQL and update it */
+ CurrentIrql = Pcr->Irql;
+ Pcr->Irql = DISPATCH_LEVEL;
+
+ /* Remove DPC from IRR */
+ Pcr->IRR &= ~(1 << DISPATCH_LEVEL);
+
+ /* Enable interrupts and call the kernel's DPC interrupt handler */
+ _enable();
+ KiDispatchInterrupt();
+
+ /* Disable interrupts and end the interrupt */
+ _disable();
+ Pcr->VdmAlert = (ULONG_PTR)TrapFrame;
+ HalpEndSoftwareInterrupt(CurrentIrql);
+
+ /* Exit the interrupt */
+ KiEoiHelper(TrapFrame);
+}
+
+VOID
+FASTCALL
+DECLSPEC_NORETURN
+HalpDispatchInterrupt2ndEntry(IN PKTRAP_FRAME TrapFrame)
+{
+ /* Do the work */
+ _HalpDispatchInterruptHandler(TrapFrame);
+}
+
+VOID
+FASTCALL
+DECLSPEC_NORETURN
+HalpDispatchInterruptHandler(IN PKTRAP_FRAME TrapFrame)
+{
+ /* Set up a fake INT Stack */
+ TrapFrame->EFlags = __readeflags();
+ TrapFrame->SegCs = KGDT_R0_CODE;
+ TrapFrame->Eip = TrapFrame->Eax;
+
+ /* Build the trap frame */
+ KiEnterInterruptTrap(TrapFrame);
+
+ /* Do the work */
+ _HalpDispatchInterruptHandler(TrapFrame);
+}
+
+KiTrap(HalpApcInterrupt, KI_SOFTWARE_TRAP);
+KiTrap(HalpDispatchInterrupt, KI_SOFTWARE_TRAP);