📄 irq.s
字号:
/*
* FILE: hal/halx86/generic/irq.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
/* GLOBALS *******************************************************************/
PICInitTable:
/* Master PIC */
.short 0x20 /* Port */
.byte 0x11 /* Edge,, cascade, CAI 8, ICW4 */
.byte PRIMARY_VECTOR_BASE /* 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 PRIMARY_VECTOR_BASE + 8 /* Base */
.byte 2 /* Slave ID: Slave 2 */
.byte 1 /* Non buffered, not nested, 8086 */
/* End of initialization table */
.short 0
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 */
HalpSysIntHandler:
.rept 7
.long GenericIRQ /* IRQ 0-7 */
.endr
.long IRQ7 /* IRQ 7 */
.rept 7
.long GenericIRQ /* IRQ 8-15 */
.endr
.long IRQ15 /* IRQ 15 */
.rept 20
.long GenericIRQ /* IRQ 16-35 */
.endr
#if DBG
.rept 172
.long InvalidIRQ /* IRQ 36-207 */
#endif
.endr
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 */
_UnhandledMsg:
.asciz "\n\x7\x7!!! Unhandled or Unexpected Code at line: %lx!!!\n"
/* 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, 0xFF
out dx, al
/* Check if we're done, otherwise initialize next PIC */
lodsw
cmp ax, 0
jnz InitLoop
/* Restore interrupts and return */
popf
pop esi
ret
.endfunc
.globl @HalClearSoftwareInterrupt@4
.func @HalClearSoftwareInterrupt@4, @HalClearSoftwareInterrupt@4
@HalClearSoftwareInterrupt@4:
/* Get IRR mask */
mov eax, 1
shl eax, cl
not eax
/* Set IRR */
and PCR[KPCR_IRR], eax
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 PCR[KPCR_IRR], eax
mov ecx, PCR[KPCR_IRQL]
/* Get software IRR mask */
mov eax, PCR[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 */
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 PCR[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
.globl _HalEnableSystemInterrupt@12
.func HalEnableSystemInterrupt@12
_HalEnableSystemInterrupt@12:
/* Get the vector and validate it */
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 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
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 PCR[KPCR_IDR], eax
/* Get the current IRQL and mask the IRQs in the PIC */
mov eax, PCR[KPCR_IRQL]
mov eax, KiI8259MaskTable[eax*4]
or eax, PCR[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 */
#if DBG
int 3
#endif
xor eax, eax
ret 12
.endfunc
.globl _HalBeginSystemInterrupt@12
.func HalBeginSystemInterrupt@12
_HalBeginSystemInterrupt@12:
/* Convert to IRQ 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
jmp $+2
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
jmp $+2
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]
mov ecx, PCR[KPCR_IRQL]
mov [eax], cl
/* Set the new IRQL */
movzx eax, byte ptr [esp+4]
mov PCR[KPCR_IRQL], eax
/* 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
/* 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -