[ros-diffs] [sginsberg] 44115: - 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.

sginsberg at svn.reactos.org sginsberg at svn.reactos.org
Wed Nov 11 23:29:16 CET 2009


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?rev=44115&r1=44114&r2=44115&view=diff
==============================================================================
--- 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 at 0
 .func HalpInitPICs at 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 at 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 at 8
 .func HalEndSystemInterrupt at 8
 _HalEndSystemInterrupt at 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 at 4
@@ -435,19 +656,21 @@
 _ at KfLowerIrql@4:
 @KfLowerIrql at 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 @@
 _ at KfRaiseIrql@4:
 @KfRaiseIrql at 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 at 0
 _KeRaiseIrqlToSynchLevel at 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/i386/asmmacro.S?rev=44115&r1=44114&r2=44115&view=diff
==============================================================================
--- 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




More information about the Ros-diffs mailing list