[HAL]: KfLowerIrql in C instead of ASM. Add the SWInterruptLookUpTable and SWInterruptHandlerTable to the code and keep the same mechanism as the ASM code used.

svn path=/trunk/; revision=45240
This commit is contained in:
Sir Richard 2010-01-25 01:20:43 +00:00
parent 8e91a3a3f9
commit fdae8b5c9c
3 changed files with 75 additions and 66 deletions

View file

@ -214,72 +214,6 @@ DoCall:
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

View file

@ -184,6 +184,27 @@ ULONG KiI8259MaskTable[32] =
#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 ******************************************************************/
@ -418,6 +439,58 @@ KfRaiseIrql(IN KIRQL NewIrql)
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 ********************************************************/
/*

View file

@ -459,6 +459,8 @@ HalpEnableInterruptHandler(IN UCHAR Flags,
/* pic.c */
VOID NTAPI HalpInitializePICs(IN BOOLEAN EnableInterrupts);
VOID HalpApcInterrupt(VOID);
VOID HalpDispatchInterrupt(VOID);
/* udelay.c */
VOID NTAPI HalpInitializeClock(VOID);