[HAL]: Document and implement KiI8259MaskTable in C using actual bit positions. Each mapping is best to the best of my ability.

[HAL]: Implement KfRaiseIrql in C, remove ASM version.

svn path=/trunk/; revision=45235
This commit is contained in:
Sir Richard 2010-01-24 23:19:40 +00:00
parent 575fd458f2
commit 9c976d58e7
3 changed files with 150 additions and 61 deletions

View file

@ -624,67 +624,6 @@ DoCall3:
ret
.endfunc
.globl @KfRaiseIrql@4
.func @KfRaiseIrql@4
_@KfRaiseIrql@4:
@KfRaiseIrql@4:
/* Get the IRQL */
movzx ecx, cl
mov eax, PCR[KPCR_IRQL]
#if DBG
/* Validate it */
cmp eax, ecx
ja InvalidKfRaise
#endif
/* Check if it's in the software level */
cmp cl, DISPATCH_LEVEL
jbe SetIrql
/* Save the current IRQL */
mov edx, eax
/* It's a hardware IRQL, so disable interrupts */
pushf
cli
/* Set the new IRQL */
mov PCR[KPCR_IRQL], ecx
/* Mask the interrupts in the PIC */
mov eax, KiI8259MaskTable[ecx*4]
or eax, PCR[KPCR_IDR]
out 0x21, al
shr eax, 8
out 0xA1, al
/* Restore interrupts and return old IRQL */
popf
mov eax, edx
ret
SetIrql:
/* Set the IRQL and return */
mov PCR[KPCR_IRQL], ecx
ret
#if DBG
InvalidKfRaise:
/* Set to passive */
mov dword ptr PCR[KPCR_IRQL], PASSIVE_LEVEL
/* Bugcheck the system */
push 9
push 0
push ecx
push eax
push IRQL_NOT_GREATER_OR_EQUAL
call _KeBugCheckEx@20
#endif
.endfunc
.globl _HalpApcInterrupt
.func HalpApcInterrupt
TRAP_FIXUPS hapc_a, hapc_t, DoFixupV86, DoFixupAbios

View file

@ -14,6 +14,87 @@
/* GLOBALS ********************************************************************/
/* This table contains the static x86 PIC mapping between IRQLs and IRQs */
ULONG KiI8259MaskTable[32] =
{
/*
* It Device IRQLs only start at 4 or higher, so these are just software
* IRQLs that don't really change anything on the hardware
*/
0b00000000000000000000000000000000, /* IRQL 0 */
0b00000000000000000000000000000000, /* IRQL 1 */
0b00000000000000000000000000000000, /* IRQL 2 */
0b00000000000000000000000000000000, /* IRQL 3 */
/*
* These next IRQLs are actually useless from the PIC perspective, because
* with only 2 PICs, the mask you can send them is only 8 bits each, for 16
* bits total, so these IRQLs are masking off a phantom PIC.
*/
0b11111111100000000000000000000000, /* IRQL 4 */
0b11111111110000000000000000000000, /* IRQL 5 */
0b11111111111000000000000000000000, /* IRQL 6 */
0b11111111111100000000000000000000, /* IRQL 7 */
0b11111111111110000000000000000000, /* IRQL 8 */
0b11111111111111000000000000000000, /* IRQL 9 */
0b11111111111111100000000000000000, /* IRQL 10 */
0b11111111111111110000000000000000, /* IRQL 11 */
/*
* Okay, now we're finally starting to mask off IRQs on the slave PIC, from
* IRQ15 to IRQ8. This means the higher-level IRQs get less priority in the
* IRQL sense.
*/
0b11111111111111111000000000000000, /* IRQL 12 */
0b11111111111111111100000000000000, /* IRQL 13 */
0b11111111111111111110000000000000, /* IRQL 14 */
0b11111111111111111111000000000000, /* IRQL 15 */
0b11111111111111111111100000000000, /* IRQL 16 */
0b11111111111111111111110000000000, /* IRQL 17 */
0b11111111111111111111111000000000, /* IRQL 18 */
0b11111111111111111111111000000000, /* IRQL 19 */
/*
* Now we mask off the IRQs on the master. Notice the 0 "droplet"? You might
* have also seen that IRQL 18 and 19 are essentially equal as far as the
* PIC is concerned. That bit is actually IRQ8, which happens to be the RTC.
* The RTC will keep firing as long as we don't reach PROFILE_LEVEL which
* actually kills it. The RTC clock (unlike the system clock) is used by the
* profiling APIs in the HAL, so that explains the logic.
*/
0b11111111111111111111111010000000, /* IRQL 20 */
0b11111111111111111111111011000000, /* IRQL 21 */
0b11111111111111111111111011100000, /* IRQL 22 */
0b11111111111111111111111011110000, /* IRQL 23 */
0b11111111111111111111111011111000, /* IRQL 24 */
0b11111111111111111111111011111000, /* IRQL 25 */
0b11111111111111111111111011111010, /* IRQL 26 */
0b11111111111111111111111111111010, /* IRQL 27 */
/*
* IRQL 24 and 25 are actually identical, so IRQL 28 is actually the last
* IRQL to modify a bit on the master PIC. It happens to modify the very
* last of the IRQs, IRQ0, which corresponds to the system clock interval
* timer that keeps track of time (the Windows heartbeat). We only want to
* turn this off at a high-enough IRQL, which is why IRQLs 24 and 25 are the
* same to give this guy a chance to come up higher. Note that IRQL 28 is
* called CLOCK2_LEVEL, which explains the usage we just explained.
*/
0b11111111111111111111111111111011, /* IRQL 28 */
/*
* We have finished off with the PIC so there's nothing left to mask at the
* level of these IRQLs, making them only logical IRQLs on x86 machines.
* Note that we have another 0 "droplet" you might've caught since IRQL 26.
* In this case, it's the 2nd bit that never gets turned off, which is IRQ2,
* the cascade IRQ that we use to bridge the slave PIC with the master PIC.
* We never want to turn it off, so no matter the IRQL, it will be set to 0.
*/
0b11111111111111111111111111111011, /* IRQL 29 */
0b11111111111111111111111111111011, /* IRQL 30 */
0b11111111111111111111111111111011 /* IRQL 31 */
};
USHORT HalpEisaELCR;
/* FUNCTIONS ******************************************************************/
@ -191,6 +272,62 @@ KeRaiseIrqlToSynchLevel(VOID)
return CurrentIrql;
}
/*
* @implemented
*/
KIRQL
FASTCALL
KfRaiseIrql(IN KIRQL NewIrql)
{
PKPCR Pcr = KeGetPcr();
ULONG EFlags;
KIRQL CurrentIrql;
PIC_MASK Mask;
/* Read current IRQL */
CurrentIrql = Pcr->Irql;
#ifdef IRQL_DEBUG
/* Validate correct raise */
if (CurrentIrql > NewIrql)
{
/* Crash system */
Pcr->Irql = PASSIVE_LEVEL;
KeBugCheckEx(IRQL_NOT_GREATER_OR_EQUAL,
CurrentIrql,
NewIrql,
0,
9);
}
#endif
/* Check if new IRQL affects hardware state */
if (NewIrql > DISPATCH_LEVEL)
{
/* Save current interrupt state and disable interrupts */
EFlags = __readeflags();
_disable();
/* Update the IRQL */
Pcr->Irql = NewIrql;
/* Set new PIC mask */
Mask.Both = KiI8259MaskTable[NewIrql] | Pcr->IDR;
__outbyte(PIC1_DATA_PORT, Mask.Master);
__outbyte(PIC2_DATA_PORT, Mask.Slave);
/* Restore interrupt state */
__writeeflags(EFlags);
}
else
{
/* Set new IRQL */
Pcr->Irql = NewIrql;
}
/* Return old IRQL */
return CurrentIrql;
}
/* SOFTWARE INTERRUPTS ********************************************************/

View file

@ -282,6 +282,19 @@ typedef union _EISA_ELCR
USHORT Bits;
} EISA_ELCR, *PEISA_ELCR;
typedef struct _PIC_MASK
{
union
{
struct
{
UCHAR Master;
UCHAR Slave;
};
USHORT Both;
};
} PIC_MASK, *PPIC_MASK;
//
// Mm PTE/PDE to Hal PTE/PDE
//