mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
613 lines
16 KiB
613 lines
16 KiB
title "System Interrupt"
|
|
;++
|
|
;
|
|
; Copyright (c) 1991 Microsoft Corporation
|
|
; Copyright (c) 1993 Sequent Computer Systems, Inc.
|
|
;
|
|
; Module Name:
|
|
;
|
|
; w3sysint.asm
|
|
;
|
|
; Abstract:
|
|
;
|
|
; This module implements the HAL routines to begin a system interrupt,
|
|
; end a system interrupt, and enable/disable system interrupts
|
|
; for the WinServer 3000.
|
|
;
|
|
; Author:
|
|
;
|
|
; Phil Hochstetler ([email protected]) 3-30-93
|
|
;
|
|
; Environment:
|
|
;
|
|
; Kernel Mode
|
|
;
|
|
; Revision History:
|
|
;
|
|
;--
|
|
|
|
.386p
|
|
.xlist
|
|
include hal386.inc
|
|
include callconv.inc ; calling convention macros
|
|
include i386\kimacro.inc
|
|
include mac386.inc
|
|
include i386\apic.inc
|
|
include i386\w3.inc
|
|
.list
|
|
|
|
EXTRNP _KeBugCheck,1
|
|
EXTRNP _KeLowerIrql,1
|
|
extrn _HalpIrql2TPR:byte
|
|
extrn _HalpLocalUnitBase:dword
|
|
extrn _HalpIOunitTwoBase:dword
|
|
extrn _HalpIOunitBase:dword
|
|
extrn _HalpK2Rdir2Irq:byte
|
|
extrn _HalpELCRImage:word
|
|
extrn _HalpK2EbsIOunitRedirectionTable:dword
|
|
extrn _HalpBeginW3InterruptTable:dword
|
|
extrn _HalpK2Vector2RdirTabEntry:byte
|
|
extrn _HalpK2EISAIrq2Irql:byte
|
|
extrn _HalpK2Irql2Eisa:byte
|
|
extrn _HalpK2Vector2EISA:byte
|
|
extrn FindHigherIrqlMask:dword
|
|
extrn HalpDispatchInterrupt2ndEntry:NEAR
|
|
extrn HalpApcInterrupt2ndEntry:NEAR
|
|
extrn _HalpMASKED:WORD
|
|
|
|
_DATA SEGMENT DWORD PUBLIC 'DATA'
|
|
|
|
_DATA ENDS
|
|
|
|
_TEXT SEGMENT DWORD PUBLIC 'CODE'
|
|
ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
|
|
|
|
;++
|
|
; BOOLEAN
|
|
; HalBeginSystemInterrupt(
|
|
; IN KIRQL Irql
|
|
; IN CCHAR Vector,
|
|
; OUT PKIRQL OldIrql
|
|
; )
|
|
;
|
|
;
|
|
;
|
|
;Routine Description:
|
|
;
|
|
; This routine handles the initial interrupt sequence for all
|
|
; external APIC interrupts for both single processor and multiple
|
|
; processor WinServer 3000 systems. On the WinServer 3000 we use
|
|
; the APIC to generate all I/O interrupts and their respective
|
|
; priorities. We do not abstract the prioritization of interrupts
|
|
; from the hardware since the APIC accomodates all Windows NT
|
|
; requirements for IRQLs. In addition to I/O interrupts the APIC
|
|
; is used to generate software interrupts for APCs and DPCs.
|
|
; The APCs and DPCs are generated by a CPU via it's
|
|
; local APIC interrupt command register. The interrupts are sent
|
|
; as a self directed interrupt. It is required by NT that software
|
|
; interrupts are always handled by the CPU which issues them.
|
|
;
|
|
; Note: Wakeup is included also in the above fashion
|
|
;
|
|
; This routine does not process an 8259 generated interrupt which
|
|
; is not tied to the APIC. This processing is done in the w3ipi.asm
|
|
; module. A subset of IRQs 0-15 are not wired through the EBS APIC.
|
|
; This is because the APIC on the EBS only accomodates 16 interrupts
|
|
; We have a total of 24 on a WS3000. We chose to have all system bus
|
|
; generated interrupts 16-23 tied to the EBS APIC. The remaining
|
|
; 8 are divided up for EISA cards. TheHalpK2EbsIounitRedirectionTable
|
|
; in k2space.asm describes the EISA IRQs chosen for the EBS APIC.
|
|
;
|
|
; Prioritization of 8259 interrupts is done by generating an APIC
|
|
; interrupt with the appropriate APIC vector which corresponds to
|
|
; the incoming 8259 IRQ number. Thus, 2 interrupts are always
|
|
; generated by an 8259 interrupt. The first is the 8259 interrupt
|
|
; and the second is the APIC interrupt.
|
|
;
|
|
; The APIC interrupt is then appropriately prioritized by the hardware
|
|
; and received accordingly via this routine.
|
|
;
|
|
|
|
;Arguments:
|
|
;
|
|
; Irql - Supplies the IRQL to raise to
|
|
;
|
|
; Vector - Supplies the vector of the interrupt to be dismissed
|
|
;
|
|
; OldIrql- Location to return OldIrql
|
|
;
|
|
;
|
|
;Return Value:
|
|
;
|
|
; FALSE - Interrupt is spurious and should be ignored
|
|
;
|
|
; TRUE - Valid interrupt and Irql raised appropriately.
|
|
;
|
|
;--
|
|
HbsiOldIrql equ dword ptr [esp+16]
|
|
HbsiVector equ byte ptr [esp+12]
|
|
HbsiIrql equ byte ptr [esp+8]
|
|
|
|
align 4
|
|
cPublicProc _HalBeginSystemInterrupt ,3
|
|
push ebx
|
|
movzx ebx, HbsiVector ; (ebx) = System Vector
|
|
jmp _HalpBeginW3InterruptTable[ebx*4]
|
|
;
|
|
; --- Process APIC external interrupt, i.e., generated via EBS I/O APIC
|
|
; - simply raise the Irql to the interrupt level of the
|
|
; current interrupt, EOI APIC, and return TRUE
|
|
;
|
|
align 4
|
|
public _HalpBeginW3APICInterrupt
|
|
|
|
_HalpBeginW3APICInterrupt:
|
|
mov edx, _HalpLocalUnitBase ; Get address of Local APIC
|
|
movzx eax, HbsiIrql ; Get New IRQL
|
|
mov cl, PCR[PcHal.ProcIrql] ; Get current irql
|
|
cli ; Don't trust caller..
|
|
if DBG
|
|
cmp al, cl
|
|
ja @f ; New IRQL is > Current
|
|
push eax ; New IRQL
|
|
push ebx ; Vector
|
|
push ecx ; Old IRQL
|
|
push [edx+LU_TPR] ;
|
|
mov dword ptr [edx+LU_TPR], 0FFH
|
|
mov PCR[PcHal.ProcIrql], HIGH_LEVEL ; Set to avoid recursive error
|
|
stdCall _KeBugCheck, <0Bh>
|
|
@@:
|
|
endif
|
|
|
|
;
|
|
; --- Do to the fact that some drivers like the i8042prt driver
|
|
; and possibly other foolhardy drivers which don't use the IRQL
|
|
; returned by the HalGetInterrupt routine when they do an IoConnectInt
|
|
; we have to use the IRQL passed and not use the vector to set the
|
|
; TPR...THESE TYPE OF DRIVERS HAVE TO BE EDGE SENSITIVE DEVICES TO
|
|
; WORK IF THEY DO THIS CRAP....We allow changes in the IRQL as long
|
|
; as it is a higher IRQL than the one returned by the HAL
|
|
;
|
|
mov PCR[PcHal.ProcIrql], al ; Set new irql
|
|
movzx eax, _HalpIrql2TPR[eax]
|
|
mov [edx+LU_TPR], eax ; Set task priority register
|
|
mov eax, [edx+LU_TPR] ; Read it to make sure write occurs
|
|
mov eax, HbsiOldIrql ; get addr to store old irql
|
|
mov [eax], cl ; save old irql in the return variable
|
|
;
|
|
; --- EOI the APIC if the interrupt is not a level sensitive EISA interrupt
|
|
; Level sensitive interrupts are EOI'ed in EndSystemInterrupt
|
|
;
|
|
xor ah, ah
|
|
mov al, _HalpK2Vector2EISA[ebx] ; Get EISA IRQ #
|
|
mov cx, _HalpELCRImage ; Get edge/level register value
|
|
mov bx, _HalpMASKED ; get PIC level interrupts
|
|
not bx
|
|
and cx, bx ; clear level bits from PIC
|
|
bt cx, ax ; test appropriate bit
|
|
jc short @f
|
|
mov [edx+LU_EOI], eax ; EOI APIC
|
|
@@:
|
|
mov eax, 1 ; True interrupt
|
|
sti ; Let interrupts go
|
|
pop ebx
|
|
|
|
stdRET _HalBeginSystemInterrupt
|
|
;
|
|
; --- Invalid or illegal vector
|
|
;
|
|
align 4
|
|
public _HalpBeginW3InvalidInterrupt
|
|
_HalpBeginW3InvalidInterrupt:
|
|
mov eax,0 ; return False
|
|
pop ebx
|
|
|
|
stdRET _HalBeginSystemInterrupt
|
|
stdENDP _HalBeginSystemInterrupt
|
|
|
|
;++
|
|
;VOID
|
|
;HalDisableSystemInterrupt(
|
|
; IN CCHAR Vector,
|
|
; IN KIRQL Irql
|
|
; )
|
|
;
|
|
;
|
|
;
|
|
;Routine Description:
|
|
;
|
|
; Disables a system interrupt via the EBS APIC Redirection table
|
|
; entries or the 8259 Interrupt mask registers
|
|
;
|
|
;Arguments:
|
|
;
|
|
; Vector - Supplies the vector of the interrupt to be disabled
|
|
;
|
|
; Irql - Supplies the interrupt level of the interrupt to be disabled
|
|
;
|
|
;Return Value:
|
|
;
|
|
; None.
|
|
;
|
|
;--
|
|
cPublicProc _HalDisableSystemInterrupt ,2
|
|
cPublicFpo 2, 0
|
|
|
|
;
|
|
; --- Exit if this is not the base processor
|
|
;
|
|
movzx ecx, byte ptr [esp+4] ; (ecx) = Vector
|
|
movzx eax, byte ptr PCR[PcHal.PcrNumber]
|
|
cmp al, 0
|
|
jne HalDisableInt999 ; Exit if not base proc
|
|
cPublicFpo 2, 1
|
|
pushfd
|
|
cli ; Disable interrupts
|
|
|
|
;
|
|
; --- Enable/Disable does not get called for the interrupt vectors
|
|
; which are used for the 8259 generated interrupts. It only gets
|
|
; called for the the APIC vectors which correspond to the 8259 ints...
|
|
;
|
|
cmp ecx, APIC_DMA_VECTOR ; Is this for the 8259 DMA?
|
|
jne short HalDisableInt10 ; No - branch
|
|
mov ecx, 13 ; EISA DMA IRQ
|
|
jmp HalDisableInt60 ; Enable 8259 Int
|
|
HalDisableInt10:
|
|
cmp ecx, APIC_KBD_VECTOR ; Is this the keyboard vector?
|
|
jne short HalDisableInt20 ; Yes - branch
|
|
mov ecx, 1 ; Keyboard IRQ
|
|
jmp HalDisableInt60 ; Enable 8259 Int
|
|
HalDisableInt20:
|
|
cmp ecx, APIC_CLOCK_VECTOR ; 8259 clock?
|
|
jne short HalDisableInt30 ; Yes - branch
|
|
mov ecx, 0 ; Clock IRQ
|
|
jmp HalDisableInt60
|
|
HalDisableInt30:
|
|
cmp ecx, APIC_RTC_VECTOR ; Real-time clock?
|
|
jne short HalDisableInt31 ; No -branch
|
|
mov ecx, 8 ; RTC IRQ
|
|
jmp HalDisableInt60
|
|
HalDisableInt31:
|
|
cmp ecx, APIC_FLOPPY_VECTOR ; Floppy?
|
|
jne short HalDisableInt32 ; No -branch
|
|
mov ecx, 6 ; Floppy IRQ
|
|
jmp HalDisableInt60
|
|
HalDisableInt32:
|
|
cmp ecx, APIC_IDE_VECTOR ; IDE Disk?
|
|
jne short HalDisableInt33 ; No -branch
|
|
mov ecx, 14 ; IDE Disk IRQ
|
|
jmp HalDisableInt60
|
|
HalDisableInt33:
|
|
cmp ecx, APIC_MOUSE_VECTOR ; IRQ12 vector
|
|
jne short HalDisableInt34 ; No -branch
|
|
mov ecx, 12 ; IRQ12
|
|
jmp HalDisableInt60
|
|
HalDisableInt34:
|
|
|
|
;
|
|
; --- Process other APIC vectors
|
|
;
|
|
xor eax,eax
|
|
mov al, _HalpK2Vector2RdirTabEntry[ecx] ; Get EBS RDIR entry
|
|
cmp al, 0FFH ; No RDIR entry..exit
|
|
je HalDisableInt50 ; ..exit
|
|
cmp al, 0 ; Not used vector
|
|
je HalDisableInt50 ; ..exit
|
|
btr eax, 7 ; EBS I/O APIC RDIR??
|
|
jnc HalDisableInt35 ; Yes
|
|
mov edx, _HalpIOunitTwoBase ; Boot processor I/O APIC RDIR
|
|
jmp HalDisableInt40 ; continue
|
|
HalDisableInt35:
|
|
mov edx, _HalpIOunitBase ; Address of EBS I/O APIC
|
|
HalDisableInt40:
|
|
;
|
|
; No need for a lock here since only the base manipulates these registers
|
|
;
|
|
mov [edx+IO_REGISTER_SELECT], eax ; Select register
|
|
or dword ptr [edx+IO_REGISTER_WINDOW], IOMPIC_RT_MASK ; mask it
|
|
HalDisableInt50:
|
|
cPublicFpo 2, 0
|
|
popfd
|
|
stdRET _HalDisableSystemInterrupt
|
|
;
|
|
; --- 8259 interrupt enable...
|
|
;
|
|
HalDisableInt60:
|
|
;
|
|
; --- 8259 interrupt disable...
|
|
;
|
|
mov edx, 1
|
|
shl edx, cl ; (ebx) = bit in IMR to disable
|
|
xor eax, eax
|
|
;
|
|
; Get the current interrupt mask register from the 8259
|
|
;
|
|
in al, PIC2_PORT1
|
|
shl eax, 8
|
|
in al, PIC1_PORT1
|
|
;
|
|
; Mask off the interrupt to be disabled
|
|
;
|
|
or eax, edx
|
|
;
|
|
; Write the new interrupt mask register back to the 8259
|
|
;
|
|
out PIC1_PORT1, al
|
|
shr eax, 8
|
|
out PIC2_PORT1, al
|
|
PIC2DELAY
|
|
cPublicFpo 2, 0
|
|
popfd
|
|
HalDisableInt999:
|
|
stdRET _HalDisableSystemInterrupt
|
|
|
|
stdENDP _HalDisableSystemInterrupt
|
|
|
|
;++
|
|
;
|
|
;BOOLEAN
|
|
;HalEnableSystemInterrupt(
|
|
; IN ULONG Vector,
|
|
; IN KIRQL Irql,
|
|
; IN KINTERRUPT_MODE InterruptMode
|
|
; )
|
|
;
|
|
;
|
|
;Routine Description:
|
|
;
|
|
; Enables a system interrupt via PIC or APIC hardware masks
|
|
;
|
|
;Arguments:
|
|
;
|
|
; Vector - Supplies the vector of the interrupt to be enabled
|
|
;
|
|
; Irql - Supplies the interrupt level of the interrupt to be enabled.
|
|
;
|
|
;Return Value:
|
|
;
|
|
; None.
|
|
;
|
|
;--
|
|
cPublicProc _HalEnableSystemInterrupt ,3
|
|
cPublicFpo 3, 0
|
|
;
|
|
; --- The base processor controls enabling/disabling of all ints
|
|
;
|
|
movzx ecx, byte ptr [esp+4] ; (ecx) = Vector
|
|
movzx eax, byte ptr PCR[PcHal.PcrNumber]
|
|
cmp al, 0
|
|
jne HalEnableInt999 ; Exit if not base proc
|
|
cPublicFpo 3, 1
|
|
pushfd
|
|
cli
|
|
;
|
|
; --- Enable/Disable does not get called for the interrupt vectors
|
|
; which are used for the 8259 generated interrupts. It only gets
|
|
; called for the the APIC vectors which correspond to the 8259 ints...
|
|
;
|
|
cmp ecx, APIC_DMA_VECTOR ; Is this for the 8259 DMA?
|
|
jne short HalEnableInt10 ; No - branch
|
|
mov ecx, 13 ; EISA DMA IRQ
|
|
jmp HalEnableInt60 ; Enable 8259 Int
|
|
HalEnableInt10:
|
|
cmp ecx, APIC_KBD_VECTOR ; Is this the keyboard vector?
|
|
jne short HalEnableInt20 ; No - branch
|
|
mov ecx, 1 ; Keyboard IRQ
|
|
jmp HalEnableInt60 ; Enable 8259 Int
|
|
HalEnableInt20:
|
|
cmp ecx, APIC_CLOCK_VECTOR ; 8259 clock?
|
|
jne short HalEnableInt30 ; No - branch
|
|
mov ecx, 0 ; Clock IRQ
|
|
jmp HalEnableInt60
|
|
HalEnableInt30:
|
|
cmp ecx, APIC_RTC_VECTOR ; Real-time clock?
|
|
jne short HalEnableInt31 ; No -branch
|
|
mov ecx, 8 ; RTC IRQ
|
|
jmp HalEnableInt60
|
|
HalEnableInt31:
|
|
cmp ecx, APIC_FLOPPY_VECTOR ; Floppy?
|
|
jne short HalEnableInt32 ; No -branch
|
|
mov ecx, 6 ; Floppy IRQ
|
|
jmp HalEnableInt60
|
|
HalEnableInt32:
|
|
cmp ecx, APIC_IDE_VECTOR ; IDE Disk?
|
|
jne short HalEnableInt33 ; No -branch
|
|
mov ecx, 14 ; IDE Disk IRQ
|
|
jmp HalEnableInt60
|
|
HalEnableInt33:
|
|
cmp ecx, APIC_MOUSE_VECTOR ; IRQ12 vector
|
|
jne short HalEnableInt34 ; No -branch
|
|
mov ecx, 12 ; IRQ12
|
|
jmp HalEnableInt60
|
|
HalEnableInt34:
|
|
|
|
|
|
;
|
|
; --- Process APIC vectors
|
|
;
|
|
xor eax,eax
|
|
mov al, _HalpK2Vector2RdirTabEntry[ecx] ; Get EBS RDIR entry
|
|
cmp al, 0FFH ; No RDIR entry..exit
|
|
je HalEnableInt50 ; ..exit
|
|
cmp al, 0 ; Not used vector
|
|
je HalEnableInt50 ; ..exit
|
|
btr eax, 7 ; EBS I/O APIC RDIR??
|
|
jnc HalEnableInt35 ; Yes
|
|
mov edx, _HalpIOunitTwoBase ; Boot processor I/O APIC RDIR
|
|
jmp HalEnableInt40 ; continue
|
|
HalEnableInt35:
|
|
mov edx, _HalpIOunitBase ; Address of EBS I/O APIC
|
|
HalEnableInt40:
|
|
;
|
|
; No need for a lock here since only the base manipulates these registers
|
|
;
|
|
mov [edx+IO_REGISTER_SELECT], eax ; Select register
|
|
and dword ptr [edx+IO_REGISTER_WINDOW], NOT IOMPIC_RT_MASK ; Unmask it
|
|
HalEnableInt50:
|
|
cPublicFpo 3, 0
|
|
popfd
|
|
stdRET _HalEnableSystemInterrupt
|
|
;
|
|
; --- 8259 interrupt enable...
|
|
;
|
|
HalEnableInt60:
|
|
xor eax, eax
|
|
;
|
|
; Get the current interrupt mask register from the 8259
|
|
;
|
|
in al, PIC2_PORT1
|
|
shl eax, 8
|
|
in al, PIC1_PORT1
|
|
;
|
|
; Unmask the interrupt to be enabled
|
|
;
|
|
btr eax, ecx
|
|
btr eax, 2 ; Enable cascaded IRQ2
|
|
|
|
;
|
|
; Write the new interrupt mask register back to the 8259
|
|
;
|
|
out PIC1_PORT1, al
|
|
shr eax, 8
|
|
out PIC2_PORT1, al
|
|
PIC2DELAY
|
|
cPublicFpo 3, 0
|
|
popfd
|
|
HalEnableInt999:
|
|
stdRET _HalEnableSystemInterrupt
|
|
stdENDP _HalEnableSystemInterrupt
|
|
|
|
|
|
; HalpEndSystemInterrupt
|
|
; IN KIRQL NewIrql,
|
|
; IN ULONG Vector
|
|
; )
|
|
;
|
|
; Routine Description:
|
|
;
|
|
; This routine is used to lower IRQL to the specified value just prior
|
|
; to ending interrupt processing.
|
|
;
|
|
; Arguments:
|
|
;
|
|
; NewIrql - the new irql to be set.
|
|
;
|
|
; Vector - Vector number of the interrupt
|
|
;
|
|
; Note that esp+8 is the beginning of interrupt/trap frame and upon
|
|
; entering to this routine.
|
|
;
|
|
; Return Value:
|
|
;
|
|
; None.
|
|
;
|
|
;--
|
|
HeiVector equ [esp+8]
|
|
HeiNewIrql equ [esp+4]
|
|
|
|
cPublicProc _HalEndSystemInterrupt ,2
|
|
cPublicFpo 2, 0
|
|
|
|
mov eax, HeiVector ; Get the current vector
|
|
mov edx, _HalpLocalUnitBase ; Local APIC address
|
|
if DBG
|
|
xor ecx, ecx
|
|
mov cl, byte ptr HeiNewIrql
|
|
cmp cl, PCR[PcHal.ProcIrql]
|
|
jbe short @f
|
|
push dword ptr ecx ; new irql for debugging
|
|
push dword ptr PCR[PcHal.ProcIrql] ; old irql for debugging
|
|
mov dword ptr [edx+LU_TPR], 0FFH
|
|
mov PCR[PcHal.ProcIrql], HIGH_LEVEL ; Set to avoid recursive error
|
|
stdCall _KeBugCheck, <IRQL_NOT_LESS_OR_EQUAL>
|
|
@@:
|
|
endif
|
|
;
|
|
; EOI the APIC on level EISA interrupts
|
|
;
|
|
mov al, _HalpK2Vector2EISA[eax] ; Get EISA IRQ #
|
|
mov cx, _HalpELCRImage ; Get edge/level register value
|
|
bt cx, ax ; test appropriate bit
|
|
jnc short NoEOI ; 1 means level interrupt
|
|
|
|
;
|
|
; Level interrupt so we need to determine if the source
|
|
; is the PIC or APIC. If the PIC, then we need to unmask the
|
|
; source, if the APIC, then we need to do an EOI to the APIC.
|
|
;
|
|
|
|
mov cx, _HalpMASKED ; get PIC level ints
|
|
bt cx, ax ; test appropriate bit
|
|
jnc short @f ; CF=1 means PIC level int
|
|
|
|
lock btr _HalpMASKED, ax ; atomic clear of bit
|
|
|
|
mov cx, ax
|
|
mov ax, 1
|
|
shl ax, cl
|
|
or al, ah
|
|
not al
|
|
mov cl, al
|
|
|
|
in al, PIC2_PORT1 ; unmask bit in PIC
|
|
and al, cl
|
|
out PIC2_PORT1, al
|
|
|
|
jmp short NoEOI
|
|
@@:
|
|
mov [edx+LU_EOI], eax ; EOI APIC
|
|
NoEOI:
|
|
xor eax, eax
|
|
mov al, byte ptr HeiNewIrql
|
|
|
|
;
|
|
; Write new lower priority level into the APIC Task Priority Register
|
|
;
|
|
pushfd
|
|
cli
|
|
mov PCR[PcHal.ProcIrql], al ; set new IRQL
|
|
mov al, _HalpIrql2TPR[eax] ; get new TPR
|
|
mov [edx+LU_TPR], eax ; write new TPR
|
|
mov eax, [edx+LU_TPR] ; Flush CPU write buffer
|
|
popfd
|
|
|
|
mov al, byte ptr HeiNewIrql ; get current irql
|
|
cmp al, DISPATCH_LEVEL ; SW ints possible?
|
|
jb short @f
|
|
stdRET _HalEndSystemInterrupt
|
|
|
|
;
|
|
; Check for any pending software interrupts
|
|
;
|
|
@@:
|
|
mov edx, PCR[PcIRR] ; get current IRR
|
|
and edx, FindHigherIrqlMask[eax*4]
|
|
jnz short @f
|
|
stdRET _HalEndSystemInterrupt
|
|
|
|
;
|
|
; Software interrupt(s) pending, figure out which one(s) and take it
|
|
;
|
|
@@:
|
|
cli
|
|
test dword ptr PCR[PcIRR], (1 SHL DISPATCH_LEVEL)
|
|
jz short @f
|
|
add esp, 12
|
|
jmp HalpDispatchInterrupt2ndEntry
|
|
@@:
|
|
cmp al, APC_LEVEL
|
|
jae short @f
|
|
test dword ptr PCR[PcIRR], (1 SHL APC_LEVEL)
|
|
jz short @f
|
|
add esp, 12
|
|
jmp HalpApcInterrupt2ndEntry
|
|
@@:
|
|
sti
|
|
stdRET _HalEndSystemInterrupt
|
|
|
|
stdENDP _HalEndSystemInterrupt
|
|
|
|
_TEXT ENDS
|
|
|
|
END
|