Author: sginsberg Date: Wed Nov 11 23:29:16 2009 New Revision: 44115
URL: http://svn.reactos.org/svn/reactos?rev=44115&view=rev Log: - 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.
Modified: trunk/reactos/hal/halx86/generic/irq.S trunk/reactos/ntoskrnl/include/internal/i386/asmmacro.S
Modified: trunk/reactos/hal/halx86/generic/irq.S URL: http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halx86/generic/irq.S?re... ============================================================================== --- trunk/reactos/hal/halx86/generic/irq.S [iso-8859-1] (original) +++ trunk/reactos/hal/halx86/generic/irq.S [iso-8859-1] Wed Nov 11 23:29:16 2009 @@ -69,25 +69,73 @@ .long 0xFFFFFFFB /* IRQL 30 */ .long 0xFFFFFFFB /* IRQL 31 */
-HalpSysIntHandler: -.rept 7 +FindHigherIrqlMask: + .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 */ -.endr + .endr .long IRQ7 /* IRQ 7 */ -.rept 7 - .long GenericIRQ /* IRQ 8-15 */ -.endr + .rept 5 + .long GenericIRQ /* IRQ 8-12 */ + .endr + .long IRQ13 /* IRQ 13 */ + .long GenericIRQ /* IRQ 14 */ .long IRQ15 /* IRQ 15 */ -.rept 20 + .rept 20 .long GenericIRQ /* IRQ 16-35 */ -.endr + .endr #if DBG .rept 172 .long InvalidIRQ /* IRQ 36-207 */ .endr #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 1 */ .byte APC_LEVEL /* IRR 2 */ @@ -97,12 +145,12 @@ .byte DISPATCH_LEVEL /* IRR 6 */ .byte DISPATCH_LEVEL /* IRR 7 */
-SoftIntHandlerTable: +SWInterruptHandlerTable: .long _KiUnexpectedInterrupt /* PASSIVE_LEVEL */ .long _HalpApcInterrupt /* APC_LEVEL */ .long _HalpDispatchInterrupt /* DISPATCH_LEVEL */
-SoftIntHandlerTable2: +SWInterruptHandlerTable2: .long _KiUnexpectedInterrupt /* PASSIVE_LEVEL */ .long _HalpApcInterrupt2ndEntry /* APC_LEVEL */ .long _HalpDispatchInterrupt2ndEntry /* DISPATCH_LEVEL */ @@ -111,6 +159,39 @@ .asciz "\n\x7\x7!!! Unhandled or Unexpected Code at line: %lx!!!\n"
/* 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 .func HalpInitPICs@0 @@ -150,7 +231,23 @@ cmp ax, 0 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 pop esi ret @@ -192,12 +289,12 @@
/* Get highest pending software interrupt and check if it's higher */ xor edx, edx - mov dl, SoftIntByteTable[eax] + mov dl, SWInterruptLookUpTable[eax] cmp dl, cl jbe AfterCall
/* Call the pending interrupt */ - call SoftIntHandlerTable[edx*4] + call SWInterruptHandlerTable[edx*4]
AfterCall:
@@ -249,38 +346,53 @@ cmp ecx, CLOCK2_LEVEL jnb Invalid
- /* Get the current PCI Edge/Level control registers */ - mov edx, 0x4D1 - in al, dx - shl ax, 8 - mov edx, 0x4D0 - in al, dx - mov dx, 1 - shl dx, cl - and dx, 0xDEF8 - - /* Check if this is a latched interrupt */ - cmp dword ptr [esp+12], 0 +#if 0 + /* Is PCI IRQ Routing enabled? */ + cmp byte ptr _HalpIrqMiniportInitialized, 0 + jz NoMiniport + + /* UNHANDLED */ + 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
- /* Use OR for edge interrupt */ - or ax, dx - jmp AfterMask + /* Check the register again */ + bt _HalpEisaELCR, ecx + 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: - - /* Mask it out for level interrupt */ - not dx - and ax, dx - -AfterMask: - - /* Set the PCI Edge/Level control registers */ - mov edx, 0x4D0 - out dx, al - shr ax, 8 - mov edx, 0x4D1 - out dx, al - + /* Is PCI IRQ Routing enabled? */ + cmp byte ptr _HalpIrqMiniportInitialized, 0 + jz IgnoredIrq + + /* UNHANDLED */ + UNHANDLED_PATH +#endif +IgnoredIrq: /* Calculate the new IDR */ mov eax, 1 shl eax, cl @@ -316,9 +428,10 @@ _HalBeginSystemInterrupt@12:
/* Convert to IRQ and call the handler */ - movzx ebx, byte ptr [esp+8] - sub ebx, PRIMARY_VECTOR_BASE - jmp HalpSysIntHandler[ebx*4] + xor ecx, ecx + mov cl, byte ptr [esp+8] + sub ecx, PRIMARY_VECTOR_BASE + jmp HalpSpecialDismissTable[ecx*4]
IRQ15: /* This is IRQ 15, check if it's spurious */ @@ -330,6 +443,7 @@ jnz GenericIRQ
/* Cascaded interrupt... dismiss it and return FALSE */ +CascadedInterrupt: mov al, 0x62 out 0x20, al mov eax, 0 @@ -348,15 +462,21 @@ mov eax, 0 ret 12
+IRQ13: + /* AT 80287 latch clear */ + xor al, al + out 0xF0, al + GenericIRQ: - /* Return the current IRQL */ - mov eax, [esp+12] - mov ecx, PCR[KPCR_IRQL] - mov [eax], cl - - /* Set the new IRQL */ - 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 edx, [esp+12] + mov [edx], bl
/* Set IRQ mask in the PIC */ mov eax, KiI8259MaskTable[eax*4] @@ -366,14 +486,18 @@ out 0xA1, al
/* Check to which PIC the EOI was sent */ - mov eax, ebx + mov eax, ecx cmp eax, 8 jnb Pic1
/* Write mask to master PIC */ or al, 0x60 out 0x20, al - jmp DoneBegin + + /* Enable interrupts and return TRUE */ + sti + mov eax, 1 + ret 12
Pic1: /* Write mask to slave PIC */ @@ -382,9 +506,7 @@ mov al, 0x62 out 0x20, al
-DoneBegin: /* Enable interrupts and return TRUE */ - in al, 0x21 sti mov eax, 1 ret 12 @@ -397,12 +519,111 @@ #endif .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 .func HalEndSystemInterrupt@8 _HalEndSystemInterrupt@8:
- /* Get the IRQL and check if it's a software interrupt */ - movzx ecx, byte ptr [esp+4] + /* Read IRQL */ + xor ecx, ecx + mov cl, [esp+4] + + /* Check if it's a software interrupt */ cmp dword ptr PCR[KPCR_IRQL], DISPATCH_LEVEL jbe SkipMask2
@@ -418,7 +639,7 @@ /* Set IRQL and check if there are pending software interrupts */ mov PCR[KPCR_IRQL], ecx mov eax, PCR[KPCR_IRR] - mov al, SoftIntByteTable[eax] + mov al, SWInterruptLookUpTable[eax] cmp al, cl ja DoCall ret 8 @@ -427,7 +648,7 @@
/* There are pending software interrupts, call their handlers */ add esp, 12 - jmp SoftIntHandlerTable2[eax*4] + jmp SWInterruptHandlerTable2[eax*4] .endfunc
.globl @KfLowerIrql@4 @@ -435,19 +656,21 @@ _@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 - - /* Validate IRQL */ - movzx ecx, cl -#if DBG - cmp cl, PCR[KPCR_IRQL] - ja InvalidIrql -#endif + cli
/* Disable interrupts and check if IRQL is below DISPATCH_LEVEL */ cmp dword ptr PCR[KPCR_IRQL], DISPATCH_LEVEL - cli jbe SkipMask
/* Clear interrupt masks since there's a pending hardware interrupt */ @@ -462,7 +685,7 @@ /* 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, SoftIntByteTable[eax] + mov al, SWInterruptLookUpTable[eax] cmp al, cl ja DoCall3
@@ -487,7 +710,7 @@
DoCall3: /* There is, call it */ - call SoftIntHandlerTable[eax*4] + call SWInterruptHandlerTable[eax*4]
/* Restore interrupts and return */ popf @@ -499,9 +722,9 @@ _@KfRaiseIrql@4: @KfRaiseIrql@4:
- /* Get the IRQL */ + /* Get the IRQL */ + movzx ecx, cl mov eax, PCR[KPCR_IRQL] - movzx ecx, cl
#if DBG /* Validate it */ @@ -521,7 +744,7 @@ cli
/* Set the new IRQL */ - mov PCR[KPCR_IRQL], cl + mov PCR[KPCR_IRQL], ecx
/* Mask the interrupts in the PIC */ mov eax, KiI8259MaskTable[ecx*4] @@ -536,7 +759,6 @@ ret
SetIrql: - /* Set the IRQL and return */ mov PCR[KPCR_IRQL], ecx ret @@ -598,29 +820,17 @@ .func KeRaiseIrqlToSynchLevel@0 _KeRaiseIrqlToSynchLevel@0:
- /* Disable interrupts */ - 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 */ + /* Get the current IRQL */ mov eax, PCR[KPCR_IRQL] + + /* Set SYNCH_LEVEL */ mov dword ptr PCR[KPCR_IRQL], SYNCH_LEVEL - popf
#if DBG - /* Validate raise */ + /* Make sure we were not higher then dispatch */ cmp eax, SYNCH_LEVEL ja InvalidSyRaise #endif - - /* Return */ ret
#if DBG @@ -737,7 +947,7 @@ /* Check if there are pending software interrupts */ mov PCR[KPCR_IRQL], ecx mov eax, PCR[KPCR_IRR] - mov al, SoftIntByteTable[eax] + mov al, SWInterruptLookUpTable[eax] cmp al, cl ja DoCall2 ret 4 @@ -745,5 +955,5 @@ DoCall2: /* There are pending softwate interrupts, call their handlers */ add esp, 8 - jmp SoftIntHandlerTable2[eax*4] -.endfunc + jmp SWInterruptHandlerTable2[eax*4] +.endfunc
Modified: trunk/reactos/ntoskrnl/include/internal/i386/asmmacro.S URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/i... ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/i386/asmmacro.S [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/include/internal/i386/asmmacro.S [iso-8859-1] Wed Nov 11 23:29:16 2009 @@ -192,6 +192,40 @@ .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 // // This macro creates one or more entries for unhandled V86 Opcodes