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?r…
==============================================================================
--- 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/…
==============================================================================
--- 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