- Add inital support for PCI and ISA interrupts.

- Use different register allocation to be more efficient on certain systems.
- Add tables and initial code for Lazy IRQL support.

svn path=/trunk/; revision=44115
This commit is contained in:
Stefan Ginsberg 2009-11-11 22:29:16 +00:00
parent 8e510a0ea2
commit c02b96254e
2 changed files with 333 additions and 89 deletions

View file

@ -69,25 +69,73 @@ KiI8259MaskTable:
.long 0xFFFFFFFB /* IRQL 30 */ .long 0xFFFFFFFB /* IRQL 30 */
.long 0xFFFFFFFB /* IRQL 31 */ .long 0xFFFFFFFB /* IRQL 31 */
HalpSysIntHandler: FindHigherIrqlMask:
.rept 7 .long 0xFFFFFFFE /* IRQL 0 */
.long 0xFFFFFFFC /* IRQL 1 */
.long 0xFFFFFFF8 /* IRQL 2 */
.long 0xFFFFFFF0 /* IRQL 3 */
.long 0x7FFFFF0 /* IRQL 4 */
.long 0x3FFFFF0 /* IRQL 5 */
.long 0x1FFFFF0 /* IRQL 6 */
.long 0x0FFFFF0 /* IRQL 7 */
.long 0x7FFFF0 /* IRQL 8 */
.long 0x3FFFF0 /* IRQL 9 */
.long 0x1FFFF0 /* IRQL 10 */
.long 0x0FFFF0 /* IRQL 11 */
.long 0x7FFF0 /* IRQL 12 */
.long 0x3FFF0 /* IRQL 13 */
.long 0x1FFF0 /* IRQL 14 */
.long 0x0FFF0 /* IRQL 15 */
.long 0x7FF0 /* IRQL 16 */
.long 0x3FF0 /* IRQL 17 */
.long 0x1FF0 /* IRQL 18 */
.long 0x1FF0 /* IRQL 19 */
.long 0x17F0 /* IRQL 20 */
.long 0x13F0 /* IRQL 21 */
.long 0x11F0 /* IRQL 22 */
.long 0x10F0 /* IRQL 23 */
.long 0x1070 /* IRQL 24 */
.long 0x1030 /* IRQL 25 */
.long 0x1010 /* IRQL 26 */
.long 0x10 /* IRQL 27 */
.long 0 /* IRQL 28 */
.long 0 /* IRQL 29 */
.long 0 /* IRQL 30 */
.long 0 /* IRQL 31 */
HalpSpecialDismissTable:
.rept 7
.long GenericIRQ /* IRQ 0-7 */ .long GenericIRQ /* IRQ 0-7 */
.endr .endr
.long IRQ7 /* IRQ 7 */ .long IRQ7 /* IRQ 7 */
.rept 7 .rept 5
.long GenericIRQ /* IRQ 8-15 */ .long GenericIRQ /* IRQ 8-12 */
.endr .endr
.long IRQ13 /* IRQ 13 */
.long GenericIRQ /* IRQ 14 */
.long IRQ15 /* IRQ 15 */ .long IRQ15 /* IRQ 15 */
.rept 20 .rept 20
.long GenericIRQ /* IRQ 16-35 */ .long GenericIRQ /* IRQ 16-35 */
.endr .endr
#if DBG #if DBG
.rept 172 .rept 172
.long InvalidIRQ /* IRQ 36-207 */ .long InvalidIRQ /* IRQ 36-207 */
.endr .endr
#endif #endif
SoftIntByteTable: HalpSpecialDismissLevelTable:
.rept 7
.long GenericIRQLevel /* IRQ 0-7 */
.endr
.long IRQ7Level /* IRQ 7 */
.rept 5
.long GenericIRQLevel /* IRQ 8-12 */
.endr
.long IRQ13Level /* IRQ 13 */
.long GenericIRQLevel /* IRQ 14 */
.long IRQ15Level /* IRQ 15 */
SWInterruptLookUpTable:
.byte PASSIVE_LEVEL /* IRR 0 */ .byte PASSIVE_LEVEL /* IRR 0 */
.byte PASSIVE_LEVEL /* IRR 1 */ .byte PASSIVE_LEVEL /* IRR 1 */
.byte APC_LEVEL /* IRR 2 */ .byte APC_LEVEL /* IRR 2 */
@ -97,12 +145,12 @@ SoftIntByteTable:
.byte DISPATCH_LEVEL /* IRR 6 */ .byte DISPATCH_LEVEL /* IRR 6 */
.byte DISPATCH_LEVEL /* IRR 7 */ .byte DISPATCH_LEVEL /* IRR 7 */
SoftIntHandlerTable: SWInterruptHandlerTable:
.long _KiUnexpectedInterrupt /* PASSIVE_LEVEL */ .long _KiUnexpectedInterrupt /* PASSIVE_LEVEL */
.long _HalpApcInterrupt /* APC_LEVEL */ .long _HalpApcInterrupt /* APC_LEVEL */
.long _HalpDispatchInterrupt /* DISPATCH_LEVEL */ .long _HalpDispatchInterrupt /* DISPATCH_LEVEL */
SoftIntHandlerTable2: SWInterruptHandlerTable2:
.long _KiUnexpectedInterrupt /* PASSIVE_LEVEL */ .long _KiUnexpectedInterrupt /* PASSIVE_LEVEL */
.long _HalpApcInterrupt2ndEntry /* APC_LEVEL */ .long _HalpApcInterrupt2ndEntry /* APC_LEVEL */
.long _HalpDispatchInterrupt2ndEntry /* DISPATCH_LEVEL */ .long _HalpDispatchInterrupt2ndEntry /* DISPATCH_LEVEL */
@ -112,6 +160,39 @@ _UnhandledMsg:
/* FUNCTIONS *****************************************************************/ /* FUNCTIONS *****************************************************************/
/* HAL interrupt handlers */
GENERATE_HAL_INT_HANDLERS
.globl _HalpHardwareInterruptLevel
.func HalpHardwareInterruptLevel
_HalpHardwareInterruptLevel:
/* Get IRQL and check for pending interrupts */
mov eax, PCR[KPCR_IRQL]
mov ecx, PCR[KPCR_IRR]
and ecx, FindHigherIrqlMask[eax*4]
jz NothingHardware
/* Check the active IRR */
test dword ptr PCR[KPCR_IRR_ACTIVE], 0xFFFFFFF0
jnz NothingHardware
/* Check for pending software interrupts */
mov eax, ecx
bsr ecx, eax
mov eax, 1
shl eax, cl
/* Clear IRR */
xor PCR[KPCR_IRR], eax
/* Now dispatch the interrupt */
call SWInterruptHandlerTable[ecx*4]
NothingHardware:
ret
.endfunc
.globl _HalpInitPICs@0 .globl _HalpInitPICs@0
.func HalpInitPICs@0 .func HalpInitPICs@0
_HalpInitPICs@0: _HalpInitPICs@0:
@ -150,7 +231,23 @@ InitLoop:
cmp ax, 0 cmp ax, 0
jnz InitLoop jnz InitLoop
/* Restore interrupts and return */ /* Read EISA Edge/Level Register */
mov edx, 0x4D1
in al, dx
mov ah, al
dec edx
in al, dx
/* Clear reserved bits and see if there's anything there */
and eax, 0xDEF8
cmp eax, 0xDEF8
jz NoEisa
/* FIXME */
//UNHANDLED_PATH
/* Restore interrupts and return */
NoEisa:
popf popf
pop esi pop esi
ret ret
@ -192,12 +289,12 @@ InitLoop:
/* Get highest pending software interrupt and check if it's higher */ /* Get highest pending software interrupt and check if it's higher */
xor edx, edx xor edx, edx
mov dl, SoftIntByteTable[eax] mov dl, SWInterruptLookUpTable[eax]
cmp dl, cl cmp dl, cl
jbe AfterCall jbe AfterCall
/* Call the pending interrupt */ /* Call the pending interrupt */
call SoftIntHandlerTable[edx*4] call SWInterruptHandlerTable[edx*4]
AfterCall: AfterCall:
@ -249,38 +346,53 @@ _HalEnableSystemInterrupt@12:
cmp ecx, CLOCK2_LEVEL cmp ecx, CLOCK2_LEVEL
jnb Invalid jnb Invalid
/* Get the current PCI Edge/Level control registers */ #if 0
mov edx, 0x4D1 /* Is PCI IRQ Routing enabled? */
in al, dx cmp byte ptr _HalpIrqMiniportInitialized, 0
shl ax, 8 jz NoMiniport
mov edx, 0x4D0
in al, dx
mov dx, 1
shl dx, cl
and dx, 0xDEF8
/* Check if this is a latched interrupt */ /* UNHANDLED */
cmp dword ptr [esp+12], 0 UNHANDLED_PATH
NoMiniport:
/* Check if this is an EISA IRQ */
bt _HalpEisaIrqIgnore, ecx
jb IgnoredIrq
/* Clear the EISA Edge/Level Control Register */
btr _HalpEisaELCR, ecx
/* Get the interrupt type */
mov al, [esp+12]
cmp al, 0
jnz Latched jnz Latched
/* Use OR for edge interrupt */ /* Check the register again */
or ax, dx bt _HalpEisaELCR, ecx
jmp AfterMask jb Dismiss
/* Check if the miniport is active */
cmp byte ptr _HalpIrqMiniportInitialized, 0
jz Dismiss
/* Update the EISA Edge/Level Control Register */
bts _HalpEisaELCR, ecx
Dismiss:
/* Use the level hardware interrupt handler */
mov dword ptr SWInterruptHandlerTableHardware[ecx*4], offset _HalpHardwareInterruptLevel
mov edx, HalpSpecialDismissLevelTable[ecx*4]
mov HalpSpecialDismissTable[ecx*4], edx
Latched: Latched:
/* Is PCI IRQ Routing enabled? */
cmp byte ptr _HalpIrqMiniportInitialized, 0
jz IgnoredIrq
/* Mask it out for level interrupt */ /* UNHANDLED */
not dx UNHANDLED_PATH
and ax, dx #endif
IgnoredIrq:
AfterMask:
/* Set the PCI Edge/Level control registers */
mov edx, 0x4D0
out dx, al
shr ax, 8
mov edx, 0x4D1
out dx, al
/* Calculate the new IDR */ /* Calculate the new IDR */
mov eax, 1 mov eax, 1
shl eax, cl shl eax, cl
@ -316,9 +428,10 @@ Invalid:
_HalBeginSystemInterrupt@12: _HalBeginSystemInterrupt@12:
/* Convert to IRQ and call the handler */ /* Convert to IRQ and call the handler */
movzx ebx, byte ptr [esp+8] xor ecx, ecx
sub ebx, PRIMARY_VECTOR_BASE mov cl, byte ptr [esp+8]
jmp HalpSysIntHandler[ebx*4] sub ecx, PRIMARY_VECTOR_BASE
jmp HalpSpecialDismissTable[ecx*4]
IRQ15: IRQ15:
/* This is IRQ 15, check if it's spurious */ /* This is IRQ 15, check if it's spurious */
@ -330,6 +443,7 @@ IRQ15:
jnz GenericIRQ jnz GenericIRQ
/* Cascaded interrupt... dismiss it and return FALSE */ /* Cascaded interrupt... dismiss it and return FALSE */
CascadedInterrupt:
mov al, 0x62 mov al, 0x62
out 0x20, al out 0x20, al
mov eax, 0 mov eax, 0
@ -348,15 +462,21 @@ IRQ7:
mov eax, 0 mov eax, 0
ret 12 ret 12
GenericIRQ: IRQ13:
/* Return the current IRQL */ /* AT 80287 latch clear */
mov eax, [esp+12] xor al, al
mov ecx, PCR[KPCR_IRQL] out 0xF0, al
mov [eax], cl
/* Set the new IRQL */ GenericIRQ:
movzx eax, byte ptr [esp+4] /* Get current and new IRQL */
xor eax, eax
mov al, byte ptr [esp+4]
mov ebx, PCR[KPCR_IRQL]
/* Set and save old */
mov PCR[KPCR_IRQL], eax mov PCR[KPCR_IRQL], eax
mov edx, [esp+12]
mov [edx], bl
/* Set IRQ mask in the PIC */ /* Set IRQ mask in the PIC */
mov eax, KiI8259MaskTable[eax*4] mov eax, KiI8259MaskTable[eax*4]
@ -366,14 +486,18 @@ GenericIRQ:
out 0xA1, al out 0xA1, al
/* Check to which PIC the EOI was sent */ /* Check to which PIC the EOI was sent */
mov eax, ebx mov eax, ecx
cmp eax, 8 cmp eax, 8
jnb Pic1 jnb Pic1
/* Write mask to master PIC */ /* Write mask to master PIC */
or al, 0x60 or al, 0x60
out 0x20, al out 0x20, al
jmp DoneBegin
/* Enable interrupts and return TRUE */
sti
mov eax, 1
ret 12
Pic1: Pic1:
/* Write mask to slave PIC */ /* Write mask to slave PIC */
@ -382,9 +506,7 @@ Pic1:
mov al, 0x62 mov al, 0x62
out 0x20, al out 0x20, al
DoneBegin:
/* Enable interrupts and return TRUE */ /* Enable interrupts and return TRUE */
in al, 0x21
sti sti
mov eax, 1 mov eax, 1
ret 12 ret 12
@ -397,12 +519,111 @@ InvalidIRQ:
#endif #endif
.endfunc .endfunc
IRQ15Level:
/* This is IRQ 15, check if it's spurious */
mov al, 0xB
out 0xA0, al
jmp $+2
in al, 0xA0
test al, 0x80
jnz GenericIRQLevel
jmp CascadedInterrupt
IRQ7Level:
/* This is IRQ 7, check if it's spurious */
mov al, 0xB
out 0x20, al
jmp $+2
in al, 0x20
test al, 0x80
jnz GenericIRQLevel
/* It is, return FALSE */
SpuriousInterrupt:
mov eax, 0
ret 12
IRQ13Level:
/* AT 80287 latch clear */
xor al, al
out 0xF0, al
GenericIRQLevel:
/* Save IRQL */
xor eax, eax
mov al, [esp+4]
/* Set IRQ mask in the PIC */
mov eax, KiI8259MaskTable[eax*4]
or eax, PCR[KPCR_IDR]
out 0x21, al
shr eax, 8
out 0xA1, al
/* Compute new IRR */
mov eax, ecx
mov ebx, 1
add ecx, 4
shl ebx, cl
or PCR[KPCR_IRR], ebx
/* Get IRQLs */
mov cl, [esp+4]
mov bl, PCR[KPCR_IRQL]
mov edx, [esp+12]
/* Check to which PIC the EOI was sent */
cmp eax, 8
jnb Pic1Level
/* Write mask to master PIC */
or al, 0x60
out 0x20, al
/* Check for spurious */
cmp cl, bl
jbe SpuriousInterrupt
/* Write IRQL values */
movzx ecx, cl
mov PCR[KPCR_IRQL], ecx
mov [edx], bl
/* Enable interrupts and return TRUE */
sti
mov eax, 1
ret 12
Pic1Level:
/* Write mask to slave and master PIC */
add al, 0x58
out 0xA0, al
mov al, 0x62
out 0x20, al
/* Was this a lower interrupt? */
cmp cl, bl
jbe SpuriousInterrupt
/* Write IRQL values */
movzx ecx, cl
mov PCR[KPCR_IRQL], ecx
mov [edx], bl
/* Enable interrupts and return TRUE */
sti
mov eax, 1
ret 12
.globl _HalEndSystemInterrupt@8 .globl _HalEndSystemInterrupt@8
.func HalEndSystemInterrupt@8 .func HalEndSystemInterrupt@8
_HalEndSystemInterrupt@8: _HalEndSystemInterrupt@8:
/* Get the IRQL and check if it's a software interrupt */ /* Read IRQL */
movzx ecx, byte ptr [esp+4] xor ecx, ecx
mov cl, [esp+4]
/* Check if it's a software interrupt */
cmp dword ptr PCR[KPCR_IRQL], DISPATCH_LEVEL cmp dword ptr PCR[KPCR_IRQL], DISPATCH_LEVEL
jbe SkipMask2 jbe SkipMask2
@ -418,7 +639,7 @@ SkipMask2:
/* Set IRQL and check if there are pending software interrupts */ /* Set IRQL and check if there are pending software interrupts */
mov PCR[KPCR_IRQL], ecx mov PCR[KPCR_IRQL], ecx
mov eax, PCR[KPCR_IRR] mov eax, PCR[KPCR_IRR]
mov al, SoftIntByteTable[eax] mov al, SWInterruptLookUpTable[eax]
cmp al, cl cmp al, cl
ja DoCall ja DoCall
ret 8 ret 8
@ -427,7 +648,7 @@ DoCall:
/* There are pending software interrupts, call their handlers */ /* There are pending software interrupts, call their handlers */
add esp, 12 add esp, 12
jmp SoftIntHandlerTable2[eax*4] jmp SWInterruptHandlerTable2[eax*4]
.endfunc .endfunc
.globl @KfLowerIrql@4 .globl @KfLowerIrql@4
@ -435,19 +656,21 @@ DoCall:
_@KfLowerIrql@4: _@KfLowerIrql@4:
@KfLowerIrql@4: @KfLowerIrql@4:
/* Save flags since we'll disable interrupts */ /* Cleanup IRQL */
pushf and ecx, 0xFF
/* Validate IRQL */ /* Validate IRQL */
movzx ecx, cl #if DBG
#if DBG
cmp cl, PCR[KPCR_IRQL] cmp cl, PCR[KPCR_IRQL]
ja InvalidIrql ja InvalidIrql
#endif #endif
/* Save flags since we'll disable interrupts */
pushf
cli
/* Disable interrupts and check if IRQL is below DISPATCH_LEVEL */ /* Disable interrupts and check if IRQL is below DISPATCH_LEVEL */
cmp dword ptr PCR[KPCR_IRQL], DISPATCH_LEVEL cmp dword ptr PCR[KPCR_IRQL], DISPATCH_LEVEL
cli
jbe SkipMask jbe SkipMask
/* Clear interrupt masks since there's a pending hardware interrupt */ /* Clear interrupt masks since there's a pending hardware interrupt */
@ -462,7 +685,7 @@ SkipMask:
/* Set the new IRQL and check if there's a pending software interrupt */ /* Set the new IRQL and check if there's a pending software interrupt */
mov PCR[KPCR_IRQL], ecx mov PCR[KPCR_IRQL], ecx
mov eax, PCR[KPCR_IRR] mov eax, PCR[KPCR_IRR]
mov al, SoftIntByteTable[eax] mov al, SWInterruptLookUpTable[eax]
cmp al, cl cmp al, cl
ja DoCall3 ja DoCall3
@ -487,7 +710,7 @@ InvalidIrql:
DoCall3: DoCall3:
/* There is, call it */ /* There is, call it */
call SoftIntHandlerTable[eax*4] call SWInterruptHandlerTable[eax*4]
/* Restore interrupts and return */ /* Restore interrupts and return */
popf popf
@ -499,9 +722,9 @@ DoCall3:
_@KfRaiseIrql@4: _@KfRaiseIrql@4:
@KfRaiseIrql@4: @KfRaiseIrql@4:
/* Get the IRQL */ /* Get the IRQL */
mov eax, PCR[KPCR_IRQL]
movzx ecx, cl movzx ecx, cl
mov eax, PCR[KPCR_IRQL]
#if DBG #if DBG
/* Validate it */ /* Validate it */
@ -521,7 +744,7 @@ _@KfRaiseIrql@4:
cli cli
/* Set the new IRQL */ /* Set the new IRQL */
mov PCR[KPCR_IRQL], cl mov PCR[KPCR_IRQL], ecx
/* Mask the interrupts in the PIC */ /* Mask the interrupts in the PIC */
mov eax, KiI8259MaskTable[ecx*4] mov eax, KiI8259MaskTable[ecx*4]
@ -536,7 +759,6 @@ _@KfRaiseIrql@4:
ret ret
SetIrql: SetIrql:
/* Set the IRQL and return */ /* Set the IRQL and return */
mov PCR[KPCR_IRQL], ecx mov PCR[KPCR_IRQL], ecx
ret ret
@ -598,29 +820,17 @@ InvalidRaise:
.func KeRaiseIrqlToSynchLevel@0 .func KeRaiseIrqlToSynchLevel@0
_KeRaiseIrqlToSynchLevel@0: _KeRaiseIrqlToSynchLevel@0:
/* Disable interrupts */ /* Get the current IRQL */
pushf
cli
/* Mask out interrupts */
mov eax, KiI8259MaskTable[SYNCH_LEVEL*4]
or eax, PCR[KPCR_IDR]
out 0x21, al
shr eax, 8
out 0xA1, al
/* Return the old IRQL, enable interrupts and set to SYNCH */
mov eax, PCR[KPCR_IRQL] mov eax, PCR[KPCR_IRQL]
/* Set SYNCH_LEVEL */
mov dword ptr PCR[KPCR_IRQL], SYNCH_LEVEL mov dword ptr PCR[KPCR_IRQL], SYNCH_LEVEL
popf
#if DBG #if DBG
/* Validate raise */ /* Make sure we were not higher then dispatch */
cmp eax, SYNCH_LEVEL cmp eax, SYNCH_LEVEL
ja InvalidSyRaise ja InvalidSyRaise
#endif #endif
/* Return */
ret ret
#if DBG #if DBG
@ -737,7 +947,7 @@ SoftwareInt:
/* Check if there are pending software interrupts */ /* Check if there are pending software interrupts */
mov PCR[KPCR_IRQL], ecx mov PCR[KPCR_IRQL], ecx
mov eax, PCR[KPCR_IRR] mov eax, PCR[KPCR_IRR]
mov al, SoftIntByteTable[eax] mov al, SWInterruptLookUpTable[eax]
cmp al, cl cmp al, cl
ja DoCall2 ja DoCall2
ret 4 ret 4
@ -745,5 +955,5 @@ SoftwareInt:
DoCall2: DoCall2:
/* There are pending softwate interrupts, call their handlers */ /* There are pending softwate interrupts, call their handlers */
add esp, 8 add esp, 8
jmp SoftIntHandlerTable2[eax*4] jmp SWInterruptHandlerTable2[eax*4]
.endfunc .endfunc

View file

@ -191,6 +191,40 @@ _KiUnexpectedInterrupt&Number:
.endr .endr
.endm .endm
//
// @name GENERATE_HAL_INT_HANDLER
//
// This macro creates a HAL hardware interrupt handler.
//
// @param None.
//
// @remark None.
//
.macro GENERATE_HAL_INT_HANDLER Number
.func HalpHardwareInterrupt&Number
_HalpHardwareInterrupt&Number:
int PRIMARY_VECTOR_BASE + Number
ret
.endfunc
.endm
//
// @name GENERATE_HAL_INT_HANDLERS
//
// This macro creates the unexpected interrupt handlers.
//
// @param None.
//
// @remark None.
//
.macro GENERATE_HAL_INT_HANDLERS
.set i, 0
.rept 16
GENERATE_HAL_INT_HANDLER %i
.set i, i + 1
.endr
.endm
// //
// @name INVALID_V86_OPCODE // @name INVALID_V86_OPCODE
// //