mirror of
https://github.com/reactos/reactos.git
synced 2025-02-24 17:34:57 +00:00
- Commit current work on IRQ rewrite. Currently in a very ugly/dirty state of flux between the new ASM code (with tiny hacks) and the old C code (with giant hacks). I feel that this is a good/stable middle ground before continuing further with the changes.
svn path=/trunk/; revision=23649
This commit is contained in:
parent
746195690d
commit
4e5173d7d0
7 changed files with 715 additions and 276 deletions
|
@ -32,6 +32,7 @@
|
|||
<define name="__USE_W32API" />
|
||||
<file>ipi.c</file>
|
||||
<file>irql.c</file>
|
||||
<file>irq.S</file>
|
||||
<file>processor.c</file>
|
||||
<file>resource.c</file>
|
||||
<file>spinlock.c</file>
|
||||
|
|
649
reactos/hal/halx86/generic/irq.S
Normal file
649
reactos/hal/halx86/generic/irq.S
Normal file
|
@ -0,0 +1,649 @@
|
|||
/*
|
||||
* FILE: hal/halx86/generic/irql.S
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PURPOSE: Software, System and Hardware IRQ Management
|
||||
* PROGRAMMER: Alex Ionescu (alex@relsoft.net)
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include <asm.h>
|
||||
#include <internal/i386/asmmacro.S>
|
||||
.intel_syntax noprefix
|
||||
|
||||
.extern _Kei386EoiHelper@0
|
||||
.extern _KiUnexpectedInterrupt
|
||||
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
PICInitTable:
|
||||
|
||||
/* Master PIC */
|
||||
.short 0x20 /* Port */
|
||||
.byte 0x11 /* Edge,, cascade, CAI 8, ICW4 */
|
||||
.byte 0x40 /* Base */
|
||||
.byte 4 /* IRQ 4 connected to slave */
|
||||
.byte 1 /* Non buffered, not nested, 8086 */
|
||||
|
||||
/* Slave PIC */
|
||||
.short 0xA0 /* Port */
|
||||
.byte 0x11 /* Edge, cascade, CAI 8, ICW4 */
|
||||
.byte 0x48 /* Base */
|
||||
.byte 2 /* Slave ID: Slave 2 */
|
||||
.byte 1 /* Non buffered, not nested, 8086 */
|
||||
|
||||
/* End of initialization table */
|
||||
.short 0
|
||||
|
||||
.globl _KiI8259MaskTable
|
||||
_KiI8259MaskTable:
|
||||
.long 0 /* IRQL 0 */
|
||||
.long 0 /* IRQL 1 */
|
||||
.long 0 /* IRQL 2 */
|
||||
.long 0 /* IRQL 3 */
|
||||
.long 0xFF800000 /* IRQL 4 */
|
||||
.long 0xFFC00000 /* IRQL 5 */
|
||||
.long 0xFFE00000 /* IRQL 6 */
|
||||
.long 0xFFF00000 /* IRQL 7 */
|
||||
.long 0xFFF80000 /* IRQL 8 */
|
||||
.long 0xFFFC0000 /* IRQL 9 */
|
||||
.long 0xFFFE0000 /* IRQL 10 */
|
||||
.long 0xFFFF0000 /* IRQL 11 */
|
||||
.long 0xFFFF8000 /* IRQL 12 */
|
||||
.long 0xFFFFC000 /* IRQL 13 */
|
||||
.long 0xFFFFE000 /* IRQL 14 */
|
||||
.long 0xFFFFF000 /* IRQL 15 */
|
||||
.long 0xFFFFF800 /* IRQL 16 */
|
||||
.long 0xFFFFFC00 /* IRQL 17 */
|
||||
.long 0xFFFFFE00 /* IRQL 18 */
|
||||
.long 0xFFFFFE00 /* IRQL 19 */
|
||||
.long 0xFFFFFE80 /* IRQL 20 */
|
||||
.long 0xFFFFFEC0 /* IRQL 21 */
|
||||
.long 0xFFFFFEE0 /* IRQL 22 */
|
||||
.long 0xFFFFFEF0 /* IRQL 23 */
|
||||
.long 0xFFFFFEF8 /* IRQL 24 */
|
||||
.long 0xFFFFFEF8 /* IRQL 25 */
|
||||
.long 0xFFFFFEFA /* IRQL 26 */
|
||||
.long 0xFFFFFFFA /* IRQL 27 */
|
||||
.long 0xFFFFFFFB /* IRQL 28 */
|
||||
.long 0xFFFFFFFB /* IRQL 29 */
|
||||
.long 0xFFFFFFFB /* IRQL 30 */
|
||||
.long 0xFFFFFFFB /* IRQL 31 */
|
||||
|
||||
#if 0
|
||||
HalpSysIntHandler:
|
||||
.rept 8
|
||||
.long GenericIRQ /* IRQ 0-7 */
|
||||
.endr
|
||||
.long IRQ7 /* IRQ 7 */
|
||||
.rept 8
|
||||
.long GenericIRQ /* IRQ 8-15 */
|
||||
.endr
|
||||
.long IRQ15 /* IRQ 15 */
|
||||
.rept 20
|
||||
.long GenericIRQ /* IRQ 16-35 */
|
||||
.endr
|
||||
#endif
|
||||
|
||||
SoftIntByteTable:
|
||||
.byte PASSIVE_LEVEL /* IRR 0 */
|
||||
.byte PASSIVE_LEVEL /* IRR 1 */
|
||||
.byte APC_LEVEL /* IRR 2 */
|
||||
.byte APC_LEVEL /* IRR 3 */
|
||||
.byte DISPATCH_LEVEL /* IRR 4 */
|
||||
.byte DISPATCH_LEVEL /* IRR 5 */
|
||||
.byte DISPATCH_LEVEL /* IRR 6 */
|
||||
.byte DISPATCH_LEVEL /* IRR 7 */
|
||||
|
||||
SoftIntHandlerTable:
|
||||
.long _KiUnexpectedInterrupt /* PASSIVE_LEVEL */
|
||||
.long _HalpApcInterrupt /* APC_LEVEL */
|
||||
.long _HalpDispatchInterrupt /* DISPATCH_LEVEL */
|
||||
|
||||
SoftIntHandlerTable2:
|
||||
.long _KiUnexpectedInterrupt /* PASSIVE_LEVEL */
|
||||
.long _HalpApcInterrupt2ndEntry /* APC_LEVEL */
|
||||
.long _HalpDispatchInterrupt2ndEntry /* DISPATCH_LEVEL */
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
.globl _HalpInitPICs@0
|
||||
.func HalpInitPICs@0
|
||||
_HalpInitPICs@0:
|
||||
|
||||
/* Save ESI and disable interrupts */
|
||||
push esi
|
||||
pushf
|
||||
cli
|
||||
|
||||
/* Read the init table */
|
||||
lea esi, PICInitTable
|
||||
lodsw
|
||||
|
||||
InitLoop:
|
||||
|
||||
/* Put the port in EDX */
|
||||
movzx edx, ax
|
||||
|
||||
/* Initialize the PIC, using a delay for each command */
|
||||
outsb
|
||||
jmp $+2
|
||||
inc edx
|
||||
outsb
|
||||
jmp $+2
|
||||
outsb
|
||||
jmp $+2
|
||||
outsb
|
||||
jmp $+2
|
||||
|
||||
/* Mask all interrupts */
|
||||
mov al, 0xFA // FIXME: Should be 0xFF
|
||||
out dx, al
|
||||
|
||||
/* Check if we're done, otherwise initialize next PIC */
|
||||
lodsw
|
||||
cmp ax, 0
|
||||
jnz InitLoop
|
||||
|
||||
/* Restore interrupts and return */
|
||||
or dword ptr [esp], EFLAGS_INTERRUPT_MASK
|
||||
popf
|
||||
pop esi
|
||||
ret
|
||||
.endfunc
|
||||
|
||||
.globl @HalRequestSoftwareInterrupt@4
|
||||
.func @HalRequestSoftwareInterrupt@4
|
||||
_@HalRequestSoftwareInterrupt@4:
|
||||
@HalRequestSoftwareInterrupt@4:
|
||||
|
||||
/* Get IRR mask */
|
||||
mov eax, 1
|
||||
shl eax, cl
|
||||
|
||||
/* Disable interrupts */
|
||||
pushf
|
||||
cli
|
||||
|
||||
/* Set IRR and get IRQL */
|
||||
or [fs:KPCR_IRR], eax
|
||||
mov cl, [fs:KPCR_IRQL]
|
||||
|
||||
/* Get software IRR mask */
|
||||
mov eax, [fs:KPCR_IRR]
|
||||
and eax, 3
|
||||
|
||||
/* Get highest pending software interrupt and check if it's higher */
|
||||
xor edx, edx
|
||||
mov dl, SoftIntByteTable[eax]
|
||||
cmp dl, cl
|
||||
jbe AfterCall
|
||||
|
||||
/* Call the pending interrupt */
|
||||
jmp $
|
||||
call SoftIntHandlerTable[edx*4]
|
||||
|
||||
AfterCall:
|
||||
|
||||
/* Retore interrupts and return */
|
||||
popf
|
||||
ret
|
||||
.endfunc
|
||||
|
||||
.globl _HalDisableSystemInterrupt@8
|
||||
.func HalDisableSystemInterrupt@8
|
||||
_HalDisableSystemInterrupt@8:
|
||||
|
||||
/* Convert to vector */
|
||||
movzx ecx, byte ptr [esp+4]
|
||||
sub ecx, PRIMARY_VECTOR_BASE
|
||||
|
||||
/* Disable interrupts and set the new IDR */
|
||||
mov edx, 1
|
||||
shl edx, cl
|
||||
cli
|
||||
or [fs+KPCR_IDR], edx
|
||||
|
||||
/* Get the current mask */
|
||||
xor eax, eax
|
||||
in al, 0xA1
|
||||
shl eax, 8
|
||||
in al, 0x21
|
||||
|
||||
/* Mask off the interrupt and write the new mask */
|
||||
or eax, edx
|
||||
out 0x21, al
|
||||
shr eax, 8
|
||||
out 0xA1, al
|
||||
|
||||
/* Return with interrupts enabled */
|
||||
in al, 0xA1
|
||||
sti
|
||||
ret 8
|
||||
.endfunc
|
||||
|
||||
#if 0
|
||||
.globl _HalEnableSystemInterrupt@12
|
||||
.func HalEnableSystemInterrupt@12
|
||||
_HalEnableSystemInterrupt@12:
|
||||
|
||||
/* Get the vector and validate it */
|
||||
jmp $
|
||||
movzx ecx, byte ptr [esp+4]
|
||||
sub ecx, PRIMARY_VECTOR_BASE
|
||||
jb Invalid
|
||||
cmp ecx, CLOCK2_LEVEL
|
||||
jnb Invalid
|
||||
|
||||
/* Get the current PCI Edge/Level control registers */
|
||||
mov edx, 0x4D1
|
||||
in al, dx
|
||||
shl ax, 8
|
||||
mov eax, 0x4D0
|
||||
in al, dx
|
||||
mov dx, 1
|
||||
shl dx, cl
|
||||
|
||||
/* Check if this is a latched interrupt */
|
||||
cmp dword ptr [esp+12], 0
|
||||
jnz Latched
|
||||
|
||||
/* Use OR for edge interrupt */
|
||||
or ax, dx
|
||||
jmp AfterMask
|
||||
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
|
||||
|
||||
/* Calculate the new IDR */
|
||||
mov eax, 1
|
||||
shl eax, cl
|
||||
not eax
|
||||
cli
|
||||
and [fs:KPCR_IDR], eax
|
||||
|
||||
/* Get the current IRQL and mask the IRQs in the PIC */
|
||||
movzx eax, byte ptr [fs:KPCR_IRQL]
|
||||
mov eax, _KiI8259MaskTable[eax*4]
|
||||
or eax, [fs:KPCR_IDR]
|
||||
out 0x21, al
|
||||
shr eax, 8
|
||||
out 0xA1, al
|
||||
|
||||
/* Enable interrupts and return TRUE */
|
||||
sti
|
||||
mov eax, 1
|
||||
ret 12
|
||||
|
||||
Invalid:
|
||||
|
||||
/* Fail, invalid IRQ */
|
||||
xor eax, eax
|
||||
ret 12
|
||||
.endfunc
|
||||
|
||||
.globl _HalBeginSystemInterrupt@12
|
||||
.func HalBeginSystemInterrupt@12
|
||||
_HalBeginSystemInterrupt@12:
|
||||
|
||||
/* Convert to vector and call the handler */
|
||||
movzx ebx, byte ptr [esp+8]
|
||||
sub ebx, PRIMARY_VECTOR_BASE
|
||||
jmp HalpSysIntHandler[ebx*4]
|
||||
|
||||
IRQ15:
|
||||
|
||||
/* This is IRQ 15, check if it's spurious */
|
||||
mov al, 0xB
|
||||
out 0xA0, al
|
||||
in al, 0xA0
|
||||
test al, 0x80
|
||||
jnz GenericIRQ
|
||||
|
||||
/* Cascaded interrupt... dismiss it and return FALSE */
|
||||
mov al, 0x62
|
||||
out 0x20, al
|
||||
mov eax, 0
|
||||
ret 12
|
||||
|
||||
IRQ7:
|
||||
|
||||
/* This is IRQ 7, check if it's spurious */
|
||||
mov al, 0xB
|
||||
out 0x20, al
|
||||
in al, 0x20
|
||||
test al, 0x80
|
||||
jnz GenericIRQ
|
||||
|
||||
/* It is, return FALSE */
|
||||
mov eax, 0
|
||||
ret 12
|
||||
|
||||
GenericIRQ:
|
||||
|
||||
/* Return the current IRQL */
|
||||
mov eax, [esp+12]
|
||||
movzx ecx, word ptr [fs:KPCR_IRQL]
|
||||
mov [eax], cl
|
||||
|
||||
/* Set the new IRQL */
|
||||
movzx eax, byte ptr [esp+4]
|
||||
mov [fs:KPCR_IRQL], al
|
||||
|
||||
/* Set IRQ mask in the PIC */
|
||||
mov eax, _KiI8259MaskTable[eax*4]
|
||||
or eax, [fs:KPCR_IDR]
|
||||
out 0x21, al
|
||||
shr eax, 8
|
||||
out 0xA1, al
|
||||
|
||||
/* Check to which PIC the EOI was sent */
|
||||
mov eax, ebx
|
||||
cmp eax, 8
|
||||
jnb Pic1
|
||||
|
||||
/* Write mask to master PIC */
|
||||
or al, 0x60
|
||||
out 0x20, al
|
||||
jmp DoneBegin
|
||||
|
||||
Pic1:
|
||||
/* Write mask to slave PIC */
|
||||
mov al, 0x20
|
||||
out 0xA0, al
|
||||
mov al, 0x62
|
||||
out 0x20, al
|
||||
|
||||
DoneBegin:
|
||||
|
||||
/* Enable interrupts and return TRUE */
|
||||
in al, 0x21
|
||||
sti
|
||||
mov eax, 1
|
||||
ret 12
|
||||
.endfunc
|
||||
|
||||
.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]
|
||||
cmp byte ptr [fs:KPCR_IRQL], DISPATCH_LEVEL
|
||||
jbe SkipMask2
|
||||
|
||||
/* Hardware interrupt, mask the appropriate IRQs in the PIC */
|
||||
mov eax, _KiI8259MaskTable[ecx*4]
|
||||
or eax, [fs:KPCR_IDR]
|
||||
out 0x21, al
|
||||
shr eax, 8
|
||||
out 0xA1, al
|
||||
|
||||
SkipMask2:
|
||||
|
||||
/* Set IRQL and check if there are pending software interrupts */
|
||||
mov [fs:KPCR_IRQL], cl
|
||||
mov eax, [fs:KPCR_IDR]
|
||||
mov al, SoftIntByteTable[eax]
|
||||
cmp al, cl
|
||||
ja DoCall
|
||||
ret 8
|
||||
|
||||
DoCall:
|
||||
|
||||
/* There are pending softwate interrupts, call their handlers */
|
||||
add esp, 8
|
||||
jmp SoftIntHandlerTable2[eax*4]
|
||||
.endfunc
|
||||
|
||||
.globl @KfLowerIrql@4
|
||||
.func @KfLowerIrql@4
|
||||
_@KfLowerIrql@4:
|
||||
@KfLowerIrql@4:
|
||||
|
||||
/* Save flags since we'll disable interrupts */
|
||||
pushf
|
||||
|
||||
/* Disable interrupts and check if IRQL is below DISPATCH_LEVEL */
|
||||
movzx ecx, cl
|
||||
cmp byte ptr [fs:KPCR_IRQL], DISPATCH_LEVEL
|
||||
cli
|
||||
jbe SkipMask
|
||||
|
||||
/* Clear interrupt masks since there's a pending hardware interrupt */
|
||||
mov eax, _KiI8259MaskTable[ecx*4]
|
||||
or eax, [fs:KPCR_IDR]
|
||||
out 0x21, al
|
||||
shr eax, 8
|
||||
out 0xA1, al
|
||||
|
||||
SkipMask:
|
||||
|
||||
/* Set the new IRQL and check if there's a pending software interrupt */
|
||||
mov [fs:KPCR_IRQL], cl
|
||||
mov eax, [fs:KPCR_IDR]
|
||||
mov al, SoftIntByteTable[eax]
|
||||
cmp al, cl
|
||||
jbe AfterCall2
|
||||
|
||||
/* There is, call it */
|
||||
call SoftIntHandlerTable[eax*4]
|
||||
|
||||
AfterCall2:
|
||||
|
||||
/* Restore interrupts and return */
|
||||
popf
|
||||
ret
|
||||
.endfunc
|
||||
#endif
|
||||
|
||||
.globl @KfRaiseIrql@4
|
||||
.func @KfRaiseIrql@4
|
||||
_@KfRaiseIrql@4:
|
||||
@KfRaiseIrql@4:
|
||||
|
||||
/* Get the IRQL and check if it's Software level only */
|
||||
xor eax, eax
|
||||
mov al, [fs:KPCR_IRQL]
|
||||
|
||||
movzx ecx, cl
|
||||
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 [fs:KPCR_IRQL], cl
|
||||
|
||||
#if 0
|
||||
/* Mask the interrupts in the PIC */
|
||||
mov eax, _KiI8259MaskTable[ecx*4]
|
||||
or eax, [fs:KPCR_IDR]
|
||||
out 0x21, al
|
||||
shr eax, 8
|
||||
out 0xA1, al
|
||||
#endif
|
||||
|
||||
/* Restore interrupts and return old IRQL */
|
||||
popf
|
||||
mov eax, edx
|
||||
ret
|
||||
|
||||
SetIrql:
|
||||
|
||||
/* Set the IRQL and return */
|
||||
mov [fs:KPCR_IRQL], cl
|
||||
ret
|
||||
.endfunc
|
||||
|
||||
.globl _KeGetCurrentIrql@0
|
||||
.func KeGetCurrentIrql@0
|
||||
_KeGetCurrentIrql@0:
|
||||
|
||||
/* Return the IRQL */
|
||||
movzx eax, word ptr [fs:KPCR_IRQL]
|
||||
ret
|
||||
.endfunc
|
||||
|
||||
.globl _KeRaiseIrqlToDpcLevel@0
|
||||
.func KeRaiseIrqlToDpcLevel@0
|
||||
_KeRaiseIrqlToDpcLevel@0:
|
||||
|
||||
/* Get the current IRQL */
|
||||
xor eax, eax
|
||||
mov al, [fs:KPCR_IRQL]
|
||||
|
||||
/* Set DISPATCH_LEVEL */
|
||||
mov byte ptr [fs:KPCR_IRQL], DISPATCH_LEVEL
|
||||
ret
|
||||
.endfunc
|
||||
|
||||
.globl _KeRaiseIrqlToSynchLevel@0
|
||||
.func KeRaiseIrqlToSynchLevel@0
|
||||
_KeRaiseIrqlToSynchLevel@0:
|
||||
|
||||
/* Disable interrupts */
|
||||
pushf
|
||||
cli
|
||||
|
||||
/* Mask out interrupts */
|
||||
mov eax, _KiI8259MaskTable + DISPATCH_LEVEL * 2
|
||||
or eax, [fs:KPCR_IDR]
|
||||
out 0x21, al
|
||||
shr eax, 8
|
||||
out 0xA1, al
|
||||
|
||||
/* Return the old IRQL, enable interrupts and set to DISPATCH */
|
||||
mov al, [fs:KPCR_IRQL]
|
||||
mov byte ptr [fs:KPCR_IRQL], DISPATCH_LEVEL
|
||||
popf
|
||||
ret
|
||||
.endfunc
|
||||
|
||||
.globl _HalpApcInterrupt
|
||||
.func HalpApcInterrupt
|
||||
_HalpApcInterrupt:
|
||||
|
||||
/* Create fake interrupt stack */
|
||||
pop eax
|
||||
pushf
|
||||
push cs
|
||||
push eax
|
||||
|
||||
/* Enter interrupt */
|
||||
INT_PROLOG(hapc)
|
||||
.endfunc
|
||||
|
||||
.globl _HalpApcInterrupt2ndEntry
|
||||
.func HalpApcInterrupt2ndEntry
|
||||
_HalpApcInterrupt2ndEntry:
|
||||
|
||||
/* Save current IRQL and set to APC level */
|
||||
push [fs:KPCR_IRQL]
|
||||
mov byte ptr [fs:KPCR_IRQL], APC_LEVEL
|
||||
and dword ptr [fs:KPCR_IRR], ~(1 << APC_LEVEL)
|
||||
|
||||
/* Enable interrupts and check if we came from User/V86 mode */
|
||||
sti
|
||||
mov eax, [ebp+KTRAP_FRAME_CS]
|
||||
and eax, MODE_MASK
|
||||
test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
|
||||
jz DeliverApc
|
||||
|
||||
/* Set user mode delivery */
|
||||
or eax, UserMode
|
||||
|
||||
DeliverApc:
|
||||
|
||||
/* Deliver the APCs */
|
||||
push ebp
|
||||
push 0
|
||||
push eax
|
||||
call _KiDeliverApc@12
|
||||
|
||||
/* Disable interrupts and end it */
|
||||
cli
|
||||
call _HalpEndSoftwareInterrupt@4
|
||||
jmp _Kei386EoiHelper@0
|
||||
.endfunc
|
||||
|
||||
.globl _HalpDispatchInterrupt
|
||||
.func HalpDispatchInterrupt
|
||||
_HalpDispatchInterrupt:
|
||||
|
||||
/* Create fake interrupt stack */
|
||||
pop eax
|
||||
pushf
|
||||
push cs
|
||||
push eax
|
||||
|
||||
/* Enter interrupt */
|
||||
INT_PROLOG(hapc)
|
||||
.endfunc
|
||||
|
||||
.globl _HalpDispatchInterrupt2ndEntry
|
||||
.func HalpDispatchInterrupt2ndEntry
|
||||
_HalpDispatchInterrupt2ndEntry:
|
||||
|
||||
/* Save current IRQL and set to DPC level */
|
||||
push [fs:KPCR_IRQL]
|
||||
mov byte ptr [fs:KPCR_IRQL], DISPATCH_LEVEL
|
||||
and dword ptr [fs:KPCR_IRR], ~(1 << DISPATCH_LEVEL)
|
||||
|
||||
/* Enable interrupts and let the kernel handle this */
|
||||
sti
|
||||
call _KiDispatchInterrupt@0
|
||||
|
||||
/* Disable interrupts and end it */
|
||||
cli
|
||||
call _HalpEndSoftwareInterrupt@4
|
||||
jmp _Kei386EoiHelper@0
|
||||
.endfunc
|
||||
|
||||
.globl _HalpEndSoftwareInterrupt@4
|
||||
.func HalpEndSoftwareInterrupt@4
|
||||
_HalpEndSoftwareInterrupt@4:
|
||||
|
||||
/* Get the IRQL and check if we're in the software region */
|
||||
movzx ecx, byte ptr [esp+4]
|
||||
cmp byte ptr [fs:KPCR_IRQL], DISPATCH_LEVEL
|
||||
jbe SoftwareInt
|
||||
|
||||
/* Set the right mask in the PIC for the hardware IRQ */
|
||||
mov eax, _KiI8259MaskTable[ecx*4]
|
||||
or eax, [fs:KPCR_IDR]
|
||||
out 0x21, al
|
||||
shr eax, 8
|
||||
out 0xA1, al
|
||||
|
||||
SoftwareInt:
|
||||
/* Check if there are pending software interrupts */
|
||||
mov [fs:KPCR_IRQL], cl
|
||||
mov eax, [fs:KPCR_IDR]
|
||||
mov al, SoftIntByteTable[eax]
|
||||
cmp al, cl
|
||||
ja DoCall2
|
||||
ret 4
|
||||
|
||||
DoCall2:
|
||||
|
||||
/* There are pending softwate interrupts, call their handlers */
|
||||
add esp, 8
|
||||
jmp SoftIntHandlerTable2[eax*4]
|
||||
.endfunc
|
|
@ -19,38 +19,16 @@
|
|||
* FIXME: Use EISA_CONTROL STRUCTURE INSTEAD OF HARD-CODED OFFSETS
|
||||
*/
|
||||
|
||||
typedef union
|
||||
UCHAR Table[8] =
|
||||
{
|
||||
USHORT both;
|
||||
struct
|
||||
{
|
||||
BYTE master;
|
||||
BYTE slave;
|
||||
};
|
||||
}
|
||||
PIC_MASK;
|
||||
0, 0,
|
||||
1, 1,
|
||||
2, 2, 2, 2
|
||||
};
|
||||
|
||||
/*
|
||||
* PURPOSE: - Mask for HalEnableSystemInterrupt and HalDisableSystemInterrupt
|
||||
* - At startup enable timer and cascade
|
||||
*/
|
||||
#if defined(__GNUC__)
|
||||
static PIC_MASK pic_mask = {.both = 0xFFFA};
|
||||
#else
|
||||
static PIC_MASK pic_mask = { 0xFFFA };
|
||||
#endif
|
||||
ULONG pic_mask = {0xFFFFFFFA};
|
||||
|
||||
|
||||
/*
|
||||
* PURPOSE: Mask for disabling of acknowledged interrupts
|
||||
*/
|
||||
#if defined(__GNUC__)
|
||||
static PIC_MASK pic_mask_intr = {.both = 0x0000};
|
||||
#else
|
||||
static PIC_MASK pic_mask_intr = { 0 };
|
||||
#endif
|
||||
|
||||
static ULONG HalpPendingInterruptCount[NR_IRQS];
|
||||
static ULONG HalpPendingInterruptCount[NR_IRQS] = {0};
|
||||
|
||||
#define DIRQL_TO_IRQ(x) (PROFILE_LEVEL - x)
|
||||
#define IRQ_TO_DIRQL(x) (PROFILE_LEVEL - x)
|
||||
|
@ -60,40 +38,7 @@ KiInterruptDispatch2 (ULONG Irq, KIRQL old_level);
|
|||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
#undef KeGetCurrentIrql
|
||||
KIRQL STDCALL KeGetCurrentIrql (VOID)
|
||||
/*
|
||||
* PURPOSE: Returns the current irq level
|
||||
* RETURNS: The current irq level
|
||||
*/
|
||||
{
|
||||
return(KeGetPcr()->Irql);
|
||||
}
|
||||
|
||||
VOID HalpInitPICs(VOID)
|
||||
{
|
||||
memset(HalpPendingInterruptCount, 0, sizeof(HalpPendingInterruptCount));
|
||||
|
||||
/* Initialization sequence */
|
||||
WRITE_PORT_UCHAR((PUCHAR)0x20, 0x11);
|
||||
WRITE_PORT_UCHAR((PUCHAR)0xa0, 0x11);
|
||||
/* Start of hardware irqs (0x24) */
|
||||
WRITE_PORT_UCHAR((PUCHAR)0x21, IRQ_BASE);
|
||||
WRITE_PORT_UCHAR((PUCHAR)0xa1, IRQ_BASE + 8);
|
||||
/* 8259-1 is master */
|
||||
WRITE_PORT_UCHAR((PUCHAR)0x21, 0x4);
|
||||
/* 8259-2 is slave */
|
||||
WRITE_PORT_UCHAR((PUCHAR)0xa1, 0x2);
|
||||
/* 8086 mode */
|
||||
WRITE_PORT_UCHAR((PUCHAR)0x21, 0x1);
|
||||
WRITE_PORT_UCHAR((PUCHAR)0xa1, 0x1);
|
||||
/* Enable interrupts */
|
||||
WRITE_PORT_UCHAR((PUCHAR)0x21, pic_mask.master);
|
||||
WRITE_PORT_UCHAR((PUCHAR)0xa1, pic_mask.slave);
|
||||
|
||||
/* We can now enable interrupts */
|
||||
Ki386EnableInterrupts();
|
||||
}
|
||||
extern ULONG KiI8259MaskTable[];
|
||||
|
||||
VOID HalpEndSystemInterrupt(KIRQL Irql)
|
||||
/*
|
||||
|
@ -101,21 +46,16 @@ VOID HalpEndSystemInterrupt(KIRQL Irql)
|
|||
*/
|
||||
{
|
||||
ULONG flags;
|
||||
const USHORT mask[] =
|
||||
{
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0xc000, 0xe000, 0xf000,
|
||||
0xf800, 0xfc00, 0xfe00, 0xff00, 0xff80, 0xffc0, 0xffe0, 0xfff0,
|
||||
0xfff8, 0xfffc, 0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
};
|
||||
ULONG Mask;
|
||||
|
||||
/* Interrupts should be disable while enabling irqs of both pics */
|
||||
Ki386SaveFlags(flags);
|
||||
Ki386DisableInterrupts();
|
||||
|
||||
pic_mask_intr.both &= mask[Irql];
|
||||
WRITE_PORT_UCHAR((PUCHAR)0x21, (UCHAR)(pic_mask.master|pic_mask_intr.master));
|
||||
WRITE_PORT_UCHAR((PUCHAR)0xa1, (UCHAR)(pic_mask.slave|pic_mask_intr.slave));
|
||||
Mask = pic_mask | KiI8259MaskTable[Irql];
|
||||
WRITE_PORT_UCHAR((PUCHAR)0x21, (UCHAR)Mask);
|
||||
Mask >>= 8;
|
||||
WRITE_PORT_UCHAR((PUCHAR)0xa1, (UCHAR)Mask);
|
||||
|
||||
/* restore flags */
|
||||
Ki386RestoreFlags(flags);
|
||||
|
@ -168,9 +108,9 @@ HalpLowerIrql(KIRQL NewIrql)
|
|||
return;
|
||||
}
|
||||
KeGetPcr()->Irql = DISPATCH_LEVEL;
|
||||
if (((PKIPCR)KeGetPcr())->HalReserved[HAL_DPC_REQUEST])
|
||||
if (Table[KeGetPcr()->IRR] >= NewIrql)
|
||||
{
|
||||
((PKIPCR)KeGetPcr())->HalReserved[HAL_DPC_REQUEST] = FALSE;
|
||||
KeGetPcr()->IRR &= ~4;
|
||||
KiDispatchInterrupt();
|
||||
}
|
||||
KeGetPcr()->Irql = APC_LEVEL;
|
||||
|
@ -219,172 +159,36 @@ KfLowerIrql (KIRQL NewIrql)
|
|||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* NAME EXPORTED
|
||||
* KeLowerIrql
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Restores the irq level on the current processor
|
||||
*
|
||||
* ARGUMENTS
|
||||
* NewIrql = Irql to lower to
|
||||
*
|
||||
* RETURN VALUE
|
||||
* None
|
||||
*
|
||||
* NOTES
|
||||
*/
|
||||
#undef KeLowerIrql
|
||||
VOID STDCALL
|
||||
KeLowerIrql (KIRQL NewIrql)
|
||||
{
|
||||
KfLowerIrql (NewIrql);
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* NAME EXPORTED
|
||||
* KfRaiseIrql
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Raises the hardware priority (irql)
|
||||
*
|
||||
* ARGUMENTS
|
||||
* NewIrql = Irql to raise to
|
||||
*
|
||||
* RETURN VALUE
|
||||
* previous irq level
|
||||
*
|
||||
* NOTES
|
||||
* Uses fastcall convention
|
||||
*/
|
||||
|
||||
KIRQL FASTCALL
|
||||
KfRaiseIrql (KIRQL NewIrql)
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
|
||||
DPRINT("KfRaiseIrql(NewIrql %d)\n", NewIrql);
|
||||
|
||||
if (NewIrql < KeGetPcr()->Irql)
|
||||
{
|
||||
DbgPrint ("%s:%d CurrentIrql %x NewIrql %x\n",
|
||||
__FILE__,__LINE__,KeGetPcr()->Irql,NewIrql);
|
||||
KEBUGCHECK (0);
|
||||
for(;;);
|
||||
}
|
||||
|
||||
OldIrql = KeGetPcr()->Irql;
|
||||
KeGetPcr()->Irql = NewIrql;
|
||||
return OldIrql;
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* NAME EXPORTED
|
||||
* KeRaiseIrql
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Raises the hardware priority (irql)
|
||||
*
|
||||
* ARGUMENTS
|
||||
* NewIrql = Irql to raise to
|
||||
* OldIrql (OUT) = Caller supplied storage for the previous irql
|
||||
*
|
||||
* RETURN VALUE
|
||||
* None
|
||||
*
|
||||
* NOTES
|
||||
* Calls KfRaiseIrql
|
||||
*/
|
||||
#undef KeRaiseIrql
|
||||
VOID STDCALL
|
||||
KeRaiseIrql (KIRQL NewIrql,
|
||||
PKIRQL OldIrql)
|
||||
{
|
||||
*OldIrql = KfRaiseIrql (NewIrql);
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* NAME EXPORTED
|
||||
* KeRaiseIrqlToDpcLevel
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Raises the hardware priority (irql) to DISPATCH level
|
||||
*
|
||||
* ARGUMENTS
|
||||
* None
|
||||
*
|
||||
* RETURN VALUE
|
||||
* Previous irq level
|
||||
*
|
||||
* NOTES
|
||||
* Calls KfRaiseIrql
|
||||
*/
|
||||
|
||||
KIRQL STDCALL
|
||||
KeRaiseIrqlToDpcLevel (VOID)
|
||||
{
|
||||
return KfRaiseIrql (DISPATCH_LEVEL);
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* NAME EXPORTED
|
||||
* KeRaiseIrqlToSynchLevel
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Raises the hardware priority (irql) to CLOCK2 level
|
||||
*
|
||||
* ARGUMENTS
|
||||
* None
|
||||
*
|
||||
* RETURN VALUE
|
||||
* Previous irq level
|
||||
*
|
||||
* NOTES
|
||||
* Calls KfRaiseIrql
|
||||
*/
|
||||
|
||||
KIRQL STDCALL
|
||||
KeRaiseIrqlToSynchLevel (VOID)
|
||||
{
|
||||
return KfRaiseIrql (CLOCK2_LEVEL);
|
||||
}
|
||||
|
||||
|
||||
BOOLEAN STDCALL
|
||||
HalBeginSystemInterrupt (KIRQL Irql,
|
||||
ULONG Vector,
|
||||
PKIRQL OldIrql)
|
||||
{
|
||||
ULONG irq;
|
||||
ULONG Mask;
|
||||
|
||||
if (Vector < IRQ_BASE || Vector >= IRQ_BASE + NR_IRQS)
|
||||
{
|
||||
return(FALSE);
|
||||
}
|
||||
irq = Vector - IRQ_BASE;
|
||||
pic_mask_intr.both |= ((1 << irq) & 0xfffe); // do not disable the timer interrupt
|
||||
|
||||
Mask = pic_mask | KiI8259MaskTable[Irql];
|
||||
WRITE_PORT_UCHAR((PUCHAR)0x21, (UCHAR)Mask);
|
||||
Mask >>= 8;
|
||||
WRITE_PORT_UCHAR((PUCHAR)0xa1, (UCHAR)Mask);
|
||||
|
||||
if (irq < 8)
|
||||
{
|
||||
WRITE_PORT_UCHAR((PUCHAR)0x21, (UCHAR)(pic_mask.master|pic_mask_intr.master));
|
||||
WRITE_PORT_UCHAR((PUCHAR)0x20, 0x20);
|
||||
WRITE_PORT_UCHAR((PUCHAR)0x20, 0x60 | irq);
|
||||
}
|
||||
else
|
||||
{
|
||||
WRITE_PORT_UCHAR((PUCHAR)0xa1, (UCHAR)(pic_mask.slave|pic_mask_intr.slave));
|
||||
/* Send EOI to the PICs */
|
||||
WRITE_PORT_UCHAR((PUCHAR)0x20,0x20);
|
||||
WRITE_PORT_UCHAR((PUCHAR)0x20,0x62);
|
||||
WRITE_PORT_UCHAR((PUCHAR)0xa0,0x20);
|
||||
}
|
||||
|
||||
if (KeGetPcr()->Irql >= Irql)
|
||||
{
|
||||
HalpPendingInterruptCount[irq]++;
|
||||
return(FALSE);
|
||||
}
|
||||
*OldIrql = KeGetPcr()->Irql;
|
||||
KeGetPcr()->Irql = Irql;
|
||||
|
||||
|
@ -397,36 +201,11 @@ VOID STDCALL HalEndSystemInterrupt (KIRQL Irql, ULONG Unknown2)
|
|||
* FUNCTION: Finish a system interrupt and restore the specified irq level.
|
||||
*/
|
||||
{
|
||||
//DPRINT1("ENDING: %lx %lx\n", Irql, Unknown2);
|
||||
HalpLowerIrql(Irql);
|
||||
HalpEndSystemInterrupt(Irql);
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
STDCALL
|
||||
HalDisableSystemInterrupt(
|
||||
ULONG Vector,
|
||||
KIRQL Irql)
|
||||
{
|
||||
ULONG irq;
|
||||
|
||||
if (Vector < IRQ_BASE || Vector >= IRQ_BASE + NR_IRQS)
|
||||
return FALSE;
|
||||
|
||||
irq = Vector - IRQ_BASE;
|
||||
pic_mask.both |= (1 << irq);
|
||||
if (irq < 8)
|
||||
{
|
||||
WRITE_PORT_UCHAR((PUCHAR)0x21, (UCHAR)(pic_mask.master|pic_mask_intr.slave));
|
||||
}
|
||||
else
|
||||
{
|
||||
WRITE_PORT_UCHAR((PUCHAR)0xa1, (UCHAR)(pic_mask.slave|pic_mask_intr.slave));
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
BOOLEAN
|
||||
STDCALL
|
||||
HalEnableSystemInterrupt(
|
||||
|
@ -435,42 +214,22 @@ HalEnableSystemInterrupt(
|
|||
KINTERRUPT_MODE InterruptMode)
|
||||
{
|
||||
ULONG irq;
|
||||
ULONG Mask;
|
||||
|
||||
if (Vector < IRQ_BASE || Vector >= IRQ_BASE + NR_IRQS)
|
||||
return FALSE;
|
||||
|
||||
irq = Vector - IRQ_BASE;
|
||||
pic_mask.both &= ~(1 << irq);
|
||||
if (irq < 8)
|
||||
{
|
||||
WRITE_PORT_UCHAR((PUCHAR)0x21, (UCHAR)(pic_mask.master|pic_mask_intr.master));
|
||||
}
|
||||
else
|
||||
{
|
||||
WRITE_PORT_UCHAR((PUCHAR)0xa1, (UCHAR)(pic_mask.slave|pic_mask_intr.slave));
|
||||
}
|
||||
pic_mask &= ~(1 << irq);
|
||||
|
||||
Mask = pic_mask | KiI8259MaskTable[KeGetPcr()->Irql];
|
||||
WRITE_PORT_UCHAR((PUCHAR)0x21, (UCHAR)Mask);
|
||||
Mask >>= 8;
|
||||
WRITE_PORT_UCHAR((PUCHAR)0xa1, (UCHAR)Mask);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
VOID FASTCALL
|
||||
HalRequestSoftwareInterrupt(
|
||||
IN KIRQL Request)
|
||||
{
|
||||
switch (Request)
|
||||
{
|
||||
case APC_LEVEL:
|
||||
((PKIPCR)KeGetPcr())->HalReserved[HAL_APC_REQUEST] = TRUE;
|
||||
break;
|
||||
|
||||
case DISPATCH_LEVEL:
|
||||
((PKIPCR)KeGetPcr())->HalReserved[HAL_DPC_REQUEST] = TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -14,9 +14,34 @@
|
|||
|
||||
#undef KeAcquireSpinLock
|
||||
#undef KeReleaseSpinLock
|
||||
#undef KeLowerIrql
|
||||
#undef KeRaiseIrql
|
||||
|
||||
/* FUNCTIONS ***************************************************************/
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID
|
||||
NTAPI
|
||||
KeLowerIrql(KIRQL NewIrql)
|
||||
{
|
||||
/* Call the fastcall function */
|
||||
KfLowerIrql(NewIrql);
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID
|
||||
NTAPI
|
||||
KeRaiseIrql(KIRQL NewIrql,
|
||||
PKIRQL OldIrql)
|
||||
{
|
||||
/* Call the fastcall function */
|
||||
*OldIrql = KfRaiseIrql(NewIrql);
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
|
|
|
@ -29,7 +29,7 @@ PADAPTER_OBJECT STDCALL HalpAllocateAdapterEx(ULONG NumberOfMapRegisters,BOOLEAN
|
|||
VOID HalpInitBusHandlers (VOID);
|
||||
|
||||
/* irql.c */
|
||||
VOID HalpInitPICs(VOID);
|
||||
VOID NTAPI HalpInitPICs(VOID);
|
||||
|
||||
/* udelay.c */
|
||||
VOID HalpCalibrateStallExecution(VOID);
|
||||
|
|
|
@ -433,8 +433,9 @@ Author:
|
|||
|
||||
//
|
||||
// Vector base
|
||||
// ROS HACK HACK HACK
|
||||
//
|
||||
#define PRIMARY_VECTOR_BASE 0x30
|
||||
#define PRIMARY_VECTOR_BASE 0x40
|
||||
|
||||
//
|
||||
// Kernel Feature Bits
|
||||
|
|
|
@ -260,6 +260,10 @@ ExecuteRuntimeAsserts(VOID)
|
|||
ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME, orig_ebp) == TF_ORIG_EBP);
|
||||
ASSERT(FIELD_OFFSET(KPCR, Tib.ExceptionList) == KPCR_EXCEPTION_LIST);
|
||||
ASSERT(FIELD_OFFSET(KPCR, Self) == KPCR_SELF);
|
||||
ASSERT(FIELD_OFFSET(KPCR, IRR) == KPCR_IRR);
|
||||
ASSERT(KeGetPcr()->IRR == 0);
|
||||
ASSERT(FIELD_OFFSET(KPCR, IDR) == KPCR_IDR);
|
||||
ASSERT(FIELD_OFFSET(KPCR, Irql) == KPCR_IRQL);
|
||||
ASSERT(FIELD_OFFSET(KIPCR, PrcbData) + FIELD_OFFSET(KPRCB, CurrentThread) == KPCR_CURRENT_THREAD);
|
||||
ASSERT(FIELD_OFFSET(KIPCR, PrcbData) + FIELD_OFFSET(KPRCB, NpxThread) == KPCR_NPX_THREAD);
|
||||
ASSERT(FIELD_OFFSET(KTSS, Esp0) == KTSS_ESP0);
|
||||
|
|
Loading…
Reference in a new issue