mirror of
https://github.com/reactos/reactos.git
synced 2025-08-06 02:53:10 +00:00
225 lines
6.6 KiB
ArmAsm
225 lines
6.6 KiB
ArmAsm
/*
|
|
* 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 ******************************************************************/
|
|
|
|
/* Enable this (and the define in spinlock.c) to make UP HAL work for MP Kernel */
|
|
/* #define CONFIG_SMP */
|
|
|
|
#include <asm.h>
|
|
#include <internal/i386/asmmacro.S>
|
|
.intel_syntax noprefix
|
|
|
|
/* GLOBALS *******************************************************************/
|
|
|
|
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 */
|
|
|
|
SWInterruptLookUpTable:
|
|
.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 */
|
|
|
|
SWInterruptHandlerTable:
|
|
.long _KiUnexpectedInterrupt /* PASSIVE_LEVEL */
|
|
.long _HalpApcInterrupt /* APC_LEVEL */
|
|
.long _HalpDispatchInterrupt /* DISPATCH_LEVEL */
|
|
|
|
SWInterruptHandlerTable2:
|
|
.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 _HalEndSystemInterrupt@8
|
|
.func HalEndSystemInterrupt@8
|
|
_HalEndSystemInterrupt@8:
|
|
|
|
/* 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
|
|
|
|
/* Hardware interrupt, mask the appropriate IRQs in the PIC */
|
|
mov eax, KiI8259MaskTable[ecx*4]
|
|
or eax, PCR[KPCR_IDR]
|
|
out 0x21, al
|
|
shr eax, 8
|
|
out 0xA1, al
|
|
|
|
SkipMask2:
|
|
|
|
/* Set IRQL and check if there are pending software interrupts */
|
|
mov PCR[KPCR_IRQL], ecx
|
|
mov eax, PCR[KPCR_IRR]
|
|
mov al, SWInterruptLookUpTable[eax]
|
|
cmp al, cl
|
|
ja DoCall
|
|
ret 8
|
|
|
|
DoCall:
|
|
|
|
/* There are pending software interrupts, call their handlers */
|
|
add esp, 12
|
|
jmp SWInterruptHandlerTable2[eax*4]
|
|
.endfunc
|
|
|
|
.globl _HalpApcInterrupt
|
|
.func HalpApcInterrupt
|
|
TRAP_FIXUPS hapc_a, hapc_t, DoFixupV86, DoFixupAbios
|
|
_HalpApcInterrupt:
|
|
|
|
/* Create fake interrupt stack */
|
|
pop eax
|
|
pushf
|
|
push cs
|
|
push eax
|
|
|
|
/* Enter interrupt */
|
|
INT_PROLOG hapc_a, hapc_t, DoPushFakeErrorCode
|
|
.endfunc
|
|
|
|
.globl _HalpApcInterrupt2ndEntry
|
|
.func HalpApcInterrupt2ndEntry
|
|
_HalpApcInterrupt2ndEntry:
|
|
|
|
/* Save current IRQL and set to APC level */
|
|
push PCR[KPCR_IRQL]
|
|
mov dword ptr PCR[KPCR_IRQL], APC_LEVEL
|
|
and dword ptr PCR[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
|
|
TRAP_FIXUPS hdpc_a, hdpc_t, DoFixupV86, DoFixupAbios
|
|
_HalpDispatchInterrupt:
|
|
|
|
/* Create fake interrupt stack */
|
|
pop eax
|
|
pushf
|
|
push cs
|
|
push eax
|
|
|
|
/* Enter interrupt */
|
|
INT_PROLOG hdpc_a, hdpc_t, DoPushFakeErrorCode
|
|
.endfunc
|
|
|
|
.globl _HalpDispatchInterrupt2ndEntry
|
|
.func HalpDispatchInterrupt2ndEntry
|
|
_HalpDispatchInterrupt2ndEntry:
|
|
|
|
/* Save current IRQL and set to DPC level */
|
|
push PCR[KPCR_IRQL]
|
|
mov dword ptr PCR[KPCR_IRQL], DISPATCH_LEVEL
|
|
and dword ptr PCR[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 dword ptr PCR[KPCR_IRQL], DISPATCH_LEVEL
|
|
jbe SoftwareInt
|
|
|
|
/* Set the right mask in the PIC for the hardware IRQ */
|
|
mov eax, KiI8259MaskTable[ecx*4]
|
|
or eax, PCR[KPCR_IDR]
|
|
out 0x21, al
|
|
shr eax, 8
|
|
out 0xA1, al
|
|
|
|
SoftwareInt:
|
|
/* Check if there are pending software interrupts */
|
|
mov PCR[KPCR_IRQL], ecx
|
|
mov eax, PCR[KPCR_IRR]
|
|
mov al, SWInterruptLookUpTable[eax]
|
|
cmp al, cl
|
|
ja DoCall2
|
|
ret 4
|
|
|
|
DoCall2:
|
|
/* There are pending softwate interrupts, call their handlers */
|
|
add esp, 8
|
|
jmp SWInterruptHandlerTable2[eax*4]
|
|
.endfunc
|