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.
592 lines
17 KiB
592 lines
17 KiB
;++
|
|
;
|
|
;Copyright (c) 1991 Microsoft Corporation
|
|
;Copyright (c) 1992 AST Research Inc.
|
|
;
|
|
;Module Name:
|
|
;
|
|
; astsyint.asm
|
|
;
|
|
;Abstract:
|
|
;
|
|
; This module implements the HAL routines to enable/disable system
|
|
; interrupts, for the AST MP (Manhattan) implementation
|
|
;
|
|
;Author:
|
|
;
|
|
; John Vert (jvert) 22-Jul-1991
|
|
; Quang Phan (v-quangp) 24-Jul-1992
|
|
;
|
|
;Environment:
|
|
;
|
|
; Kernel Mode
|
|
;
|
|
;Revision History:
|
|
;
|
|
; Quang Phan (v-quangp) 15-Dec-1992:
|
|
; Used different display codes for different spurious interrupt status.
|
|
;
|
|
;--
|
|
|
|
|
|
.386p
|
|
.xlist
|
|
include hal386.inc
|
|
include callconv.inc
|
|
include i386\ix8259.inc
|
|
include i386\kimacro.inc
|
|
include mac386.inc
|
|
include i386\astebi2.inc
|
|
include i386\astmp.inc
|
|
.list
|
|
|
|
EXTRNP _KeBugCheck,1,IMPORT
|
|
extrn KiEBI2IntMaskTable:DWORD
|
|
extrn _HalpIRQLtoEBIBitMask:DWORD
|
|
extrn _EBI2_CallTab:DWORD
|
|
extrn _EBI2_MMIOTable:DWORD
|
|
extrn _HalpInitializedProcessors:DWORD
|
|
extrn _HalpIRQLtoVector:BYTE
|
|
EXTRNP _DisplPanel,1
|
|
EXTRNP _KeRaiseIrql,2
|
|
EXTRNP KfRaiseIrql,1,,FASTCALL
|
|
|
|
_DATA SEGMENT DWORD PUBLIC 'DATA'
|
|
|
|
;
|
|
;spinlock for EBI2 access
|
|
;
|
|
align dword
|
|
public _EBI2_Lock
|
|
_EBI2_Lock dd 0 ;for Enable/DisableSystemInterrupt
|
|
EBI2_GlobalIntMask dd 0 ;loc for EBI2GetGlobalIntMask data
|
|
|
|
;HalpInterruptToProc table is used by HAL to figure out which interrupt
|
|
;(irql) will be assigned to which processor. The current implementation
|
|
;assigns interrupts to processors on a round-robin basis.
|
|
;
|
|
public IrqlAssignToProcTable ;InterruptToProcessor assignment table
|
|
IrqlAssigntoProcTable label dword
|
|
dd 32 dup(0FFh) ;irql -> ProcID
|
|
CurrentAssignProcessor dd 0 ; Current proc. assigned to irql
|
|
;
|
|
; HalDismissSystemInterrupt does an indirect jump through this table so it
|
|
; can quickly execute specific code for different interrupts.
|
|
;
|
|
public HalpSpecialDismissTable
|
|
HalpSpecialDismissTable label dword
|
|
dd offset FLAT:HalpDismissNormal ; irql 0
|
|
dd offset FLAT:HalpDismissNormal ; irql 1
|
|
dd offset FLAT:HalpDismissNormal ; irql 2
|
|
dd offset FLAT:HalpDismissNormal ; irql 3
|
|
dd offset FLAT:HalpDismissNormal ; irql 4
|
|
dd offset FLAT:HalpDismissNormal ; irql 5
|
|
dd offset FLAT:HalpDismissNormal ; irql 6
|
|
dd offset FLAT:HalpDismissNormal ; irql 7
|
|
dd offset FLAT:HalpDismissNormal ; irql 8
|
|
dd offset FLAT:HalpDismissNormal ; irql 9
|
|
dd offset FLAT:HalpDismissNormal ; irql 10
|
|
dd offset FLAT:HalpDismissNormal ; irql 11
|
|
dd offset FLAT:HalpDismissIrq07 ; irql 12 (irq7)
|
|
dd offset FLAT:HalpDismissNormal ; irql 13
|
|
dd offset FLAT:HalpDismissNormal ; irql 14
|
|
dd offset FLAT:HalpDismissNormal ; irql 15
|
|
dd offset FLAT:HalpDismissNormal ; irql 16
|
|
dd offset FLAT:HalpDismissIrq0f ; irql 17 (irq15)
|
|
dd offset FLAT:HalpDismissNormal ; irql 18
|
|
dd offset FLAT:HalpDismissNormal ; irql 19
|
|
dd offset FLAT:HalpDismissNormal ; irql 20
|
|
dd offset FLAT:HalpDismissNormal ; irql 21
|
|
dd offset FLAT:HalpDismissNormal ; irql 22
|
|
dd offset FLAT:HalpDismissNormal ; irql 23
|
|
dd offset FLAT:HalpDismissNormal ; irql 24
|
|
dd offset FLAT:HalpDismissNormal ; irql 25
|
|
dd offset FLAT:HalpDismissNormal ; irql 26
|
|
dd offset FLAT:HalpDismissNormal ; irql 27
|
|
dd offset FLAT:HalpDismissNormal ; irql 28
|
|
dd offset FLAT:HalpDismissNormal ; irql 29
|
|
dd offset FLAT:HalpDismissNormal ; irql 30
|
|
dd offset FLAT:HalpDismissNormal ; irql 31
|
|
;
|
|
;Translation table from system IRQL to EBI's IntNum used in MaskableIntEOI.
|
|
;
|
|
Public HalpIRQLtoEBIIntNumber
|
|
align 4
|
|
HalpIRQLtoEBIIntNumber Label Dword
|
|
dd 0 ;IRQL 0 (Unused Mask)
|
|
dd 0 ;IRQL 1
|
|
dd IRQ_25 ;IRQL 2 (EBI IRQ-25)
|
|
dd 0 ;IRQL 3
|
|
dd 0 ;IRQL 4
|
|
dd 0 ;IRQL 5
|
|
dd 0 ;IRQL 6
|
|
dd 0 ;IRQL 7
|
|
dd 0 ;IRQL 8
|
|
dd 0 ;IRQL 9
|
|
dd 0 ;IRQL 10
|
|
dd 0 ;IRQL 11
|
|
dd IRQ_7 ;IRQL 12
|
|
dd IRQ_6 ;IRQL 13
|
|
dd IRQ_5 ;IRQL 14
|
|
dd IRQ_4 ;IRQL 15
|
|
dd IRQ_3 ;IRQL 16
|
|
dd IRQ_15 ;IRQL 17
|
|
dd IRQ_14 ;IRQL 18
|
|
dd IRQ_13 ;IRQL 19
|
|
dd IRQ_12 ;IRQL 20
|
|
dd IRQ_11 ;IRQL 21
|
|
dd IRQ_10 ;IRQL 22
|
|
dd IRQ_9 ;IRQL 23
|
|
dd IRQ_8 ;IRQL 24
|
|
dd IRQ_2 ;IRQL 25
|
|
dd IRQ_1 ;IRQL 26
|
|
dd IRQ_8 ;IRQL 27
|
|
dd IRQ_0 ;IRQL 28
|
|
dd IRQ_26 ;IRQL 29 (IPI)
|
|
dd IRQ_24 ;IRQL 30 (SPI)
|
|
dd 0 ;IRQL 31
|
|
;
|
|
|
|
_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 is used to dismiss the specified vector number. It is called
|
|
; before any interrupt service routine code is executed.
|
|
;
|
|
;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 - Interrupt successfully dismissed and Irql raised.
|
|
;
|
|
;--
|
|
align dword
|
|
HbsiIrql equ byte ptr [esp+4]
|
|
HbsiVector equ byte ptr [esp+8]
|
|
HbsiOldIrql equ dword ptr [esp+12]
|
|
|
|
cPublicProc _HalBeginSystemInterrupt,3
|
|
|
|
movzx eax,HbsiIrql ; (eax) = System Irql
|
|
movzx ecx,byte ptr fs:PcIrql ; (ecx) = Current Irql
|
|
|
|
if DBG
|
|
cmp eax, 31 ; Irql in table?
|
|
ja hbsi00 ; no go handle
|
|
|
|
cmp cl, al
|
|
ja hbsi00 ; Dismiss as spurious
|
|
endif ;DBG
|
|
|
|
jmp HalpSpecialDismissTable[eax*4] ; ck for spurious int's
|
|
|
|
hbsi00:
|
|
;
|
|
; Interrupt is out of range. There's no EOI here since it wouldn't
|
|
; have been out of range if it occured on either interrupt controller
|
|
; which is known about.
|
|
;
|
|
DisplPanel HalSpuriousInterrupt
|
|
int 3
|
|
mov eax,0 ; return FALSE
|
|
stdRET _HalBeginSystemInterrupt
|
|
|
|
;
|
|
;
|
|
;-------------------
|
|
;Normal handler
|
|
;-------------------
|
|
;
|
|
HalpDismissNormal2:
|
|
movzx eax,HbsiIrql ; (eax) = System Irql
|
|
movzx ecx,byte ptr fs:PcIrql ; (ecx) = Current Irql
|
|
HalpDismissNormal:
|
|
mov dl, _HalpIRQLtoVector[eax] ; Does irql match interrupt
|
|
cmp dl, HbsiVector ; vector?
|
|
jne short hbsi10 ; no, (then it's higher) go raise
|
|
|
|
mov edx, HbsiOldIrql ; (edx) = OldIrql address
|
|
mov fs:PcIrql, al ; Set new irql
|
|
mov byte ptr[edx], cl ; return OldIrql
|
|
; mov dword ptr[edx], ecx
|
|
|
|
mov eax, 1 ; set return value to true
|
|
sti
|
|
stdRET _HalBeginSystemInterrupt
|
|
|
|
hbsi10:
|
|
mov edx, HbsiOldIrql ; (edx) = OldIrql address
|
|
stdCall _KeRaiseIrql <eax, edx>
|
|
mov eax, 1 ; set return value to true
|
|
sti
|
|
stdRET _HalBeginSystemInterrupt
|
|
|
|
|
|
|
|
;
|
|
;-------------------
|
|
;Handler for irq0Fh
|
|
;-------------------
|
|
;
|
|
HalpDismissIrq0f:
|
|
;
|
|
; Check to see if this is a spurious interrupt by reading the global IRQ status
|
|
;
|
|
|
|
sub esp, 8 ;alloc room in stack for 2 dword
|
|
mov eax,esp
|
|
add eax,4
|
|
push eax ;ptr to GlobalIRR
|
|
mov eax,esp
|
|
add eax,4
|
|
push eax ;ptr to GlobalISR
|
|
CALL_EBI2 GetGlobalIRQStatus,3
|
|
|
|
if DBG
|
|
or eax,eax
|
|
je BeginSysInt4_OK
|
|
int 3 ;trap for debugging
|
|
BeginSysInt4_OK:
|
|
endif
|
|
|
|
bt dword ptr [esp],IRQ_15 ;chk In-Service for irq15
|
|
pop eax ;dummy pop to adj stack
|
|
pop eax ;..
|
|
jc short HalpDismissNormal2 ; =1: NOT a spurious int
|
|
;
|
|
;Else, is a spurious interrupt. In this case, we have to send EOI to
|
|
;the ADI to dismiss the interrupt.
|
|
;
|
|
DisplPanel HalSpuriousInterrupt2
|
|
push IRQ_15 ;EOI Irq_15
|
|
CALL_EBI2 MaskableIntEOI,2
|
|
|
|
if DBG
|
|
or eax,eax
|
|
je BeginSysInt3_OK
|
|
int 3 ;trap for debugging
|
|
BeginSysInt3_OK:
|
|
endif
|
|
;
|
|
mov eax, 0 ; return FALSE
|
|
stdRET _HalBeginSystemInterrupt
|
|
;
|
|
;-------------------
|
|
;Handler for irq07
|
|
;-------------------
|
|
;
|
|
HalpDismissIrq07:
|
|
;
|
|
; Check to see if this is a spurious interrupt by reading the global IRQ status
|
|
;
|
|
|
|
sub esp, 8 ;alloc room in stack for 2 dword
|
|
mov eax,esp
|
|
add eax, 4
|
|
push eax ;ptr to GlobalIRR
|
|
mov eax,esp
|
|
add eax, 4
|
|
push eax ;ptr to GlobalISR
|
|
CALL_EBI2 GetGlobalIRQStatus,3
|
|
|
|
if DBG
|
|
or eax,eax
|
|
je BeginSysInt2_OK
|
|
int 3 ;trap for debugging
|
|
BeginSysInt2_OK:
|
|
endif
|
|
|
|
bt dword ptr [esp],IRQ_7 ; chk In-Service for irq7
|
|
pop eax ;dummy pop to adj stack
|
|
pop eax ;..
|
|
jc HalpDismissNormal2 ; =1: NOT a spurious int
|
|
;
|
|
;Else, is a spurious interrupt. In this case, we have to send EOI to
|
|
;the ADI to dismiss the interrupt.
|
|
;
|
|
DisplPanel HalSpuriousInterrupt3
|
|
push IRQ_7 ;EOI Irq_7
|
|
CALL_EBI2 MaskableIntEOI,2
|
|
|
|
if DBG
|
|
or eax,eax
|
|
je BeginSysInt1_OK
|
|
int 3 ;trap for debugging
|
|
BeginSysInt1_OK:
|
|
endif
|
|
;
|
|
mov eax, 0 ; return FALSE
|
|
stdRET _HalBeginSystemInterrupt
|
|
|
|
|
|
stdENDP _HalBeginSystemInterrupt
|
|
|
|
;++
|
|
;VOID
|
|
;HalDisableSystemInterrupt(
|
|
; IN CCHAR Vector,
|
|
; IN KIRQL Irql
|
|
; )
|
|
;
|
|
;
|
|
;
|
|
;Routine Description:
|
|
;
|
|
; Disables a system interrupt.
|
|
;
|
|
;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
|
|
|
|
movzx ecx, byte ptr [esp+4] ;get vector
|
|
sub ecx, PRIMARY_VECTOR_BASE
|
|
jc DisSysIntError ;jump if not H/W interrupt
|
|
cmp ecx, CLOCK2_LEVEL
|
|
jnc DisSysIntError
|
|
movzx ecx, byte ptr [esp+8] ;get IRQL (ecx)
|
|
mov ecx, HalpIRQLtoEBIIntNumber[ecx*4] ;get ebi2 int# (edx)
|
|
cli
|
|
bts fs:PcIDR, ecx ;disable int locally
|
|
jc DisSysIntExit ;jump if already disabled
|
|
|
|
lea eax, _EBI2_Lock
|
|
DisSysIntAquire:
|
|
ACQUIRE_SPINLOCK eax, DisSysIntSpin
|
|
;
|
|
;Mark the appropirate entry in the Irql assign table to NOT_ASSIGNED.
|
|
;
|
|
movzx eax, byte ptr [esp+8] ;get IRQL
|
|
mov IrqlAssignToProcTable[eax*4],NOT_ASSIGNED
|
|
;
|
|
;Get the global interrupt mask
|
|
;
|
|
lea eax, EBI2_GlobalIntMask
|
|
push eax
|
|
CALL_EBI2 GetGlobalIntMask,2
|
|
|
|
if DBG
|
|
or eax,eax
|
|
je DisableSysInt4_OK
|
|
int 3 ;trap for debugging
|
|
DisableSysInt4_OK:
|
|
endif
|
|
|
|
;
|
|
;Disable interrupt globally at PIC
|
|
;
|
|
bts EBI2_GlobalIntMask,ecx ;disable int at global mask
|
|
push EBI2_GlobalIntMask
|
|
CALL_EBI2 SetGlobalIntMask,2
|
|
|
|
if DBG
|
|
or eax,eax
|
|
je DisableSysInt1_OK
|
|
int 3 ;trap for debugging
|
|
DisableSysInt1_OK:
|
|
endif
|
|
;
|
|
;Disable interrupt locally
|
|
;
|
|
mov cl, fs:PcIrql
|
|
fstCall KfRaiseIrql
|
|
|
|
lea eax, _EBI2_Lock
|
|
DisSysIntRelease:
|
|
RELEASE_SPINLOCK eax
|
|
|
|
DisSysIntExit:
|
|
;## DisplPanel HalDisableSystemInterruptExit
|
|
sti
|
|
stdRET _HalDisableSystemInterrupt
|
|
|
|
DisSysIntError:
|
|
DisplPanel HalDisableSystemInterruptError
|
|
if DBG
|
|
int 3
|
|
endif
|
|
sti
|
|
xor eax,eax
|
|
ret
|
|
|
|
DisSysIntSpin:
|
|
SPIN_ON_SPINLOCK eax, DisSysIntAquire
|
|
|
|
stdENDP _HalDisableSystemInterrupt
|
|
|
|
;++
|
|
;
|
|
;BOOLEAN
|
|
;HalEnableSystemInterrupt(
|
|
; IN ULONG Vector,
|
|
; IN KIRQL Irql,
|
|
; IN KINTERRUPT_MODE InterruptMode
|
|
; )
|
|
;
|
|
;
|
|
;Routine Description:
|
|
;
|
|
; Enables a system interrupt
|
|
;
|
|
;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
|
|
;## DisplPanel HalEnableSystemInterruptEnter
|
|
; int 3
|
|
movzx eax, byte ptr [esp+4] ;get vector
|
|
sub eax, PRIMARY_VECTOR_BASE
|
|
jc EnbSysIntError ;jump if not H/W interrupt
|
|
; cmp eax, CLOCK2_LEVEL
|
|
; jnc EnbSysIntError
|
|
;
|
|
;Determine if this irq is to be assigned to this processor.
|
|
;Irqs are to be assigned to the available processors on a round-robin
|
|
;basis
|
|
;
|
|
movzx ecx, byte ptr [esp+8] ;get IRQL
|
|
cmp ecx,PROFILE_LEVEL
|
|
jae HESI_010 ;skip for PROFILE irql and above.
|
|
;
|
|
;To have the fpanel switch work properly, irq13 must be assigned to P0.
|
|
;This is because EBI2 clears switch status when asthal eoi SPI interrupt.
|
|
;The current implementation is that switch status will be read and saved
|
|
;by SPI handler.
|
|
;
|
|
cmp eax,13 ;irq13 vector?
|
|
jne HSEI_006
|
|
mov eax,fs:PcHal.PcrEBI2ProcessorID
|
|
or eax,eax
|
|
jne EnbSysIntExit
|
|
mov IrqlAssignToProcTable[ecx*4],eax ;update IrqlAssingnTable
|
|
jmp short HESI_010 ;go assign irq13 to P0
|
|
|
|
HSEI_006:
|
|
cmp IrqlAssignToProcTable[ecx*4],NOT_ASSIGNED
|
|
jne EnbSysIntExit ;skip if irql already assigned
|
|
mov eax,CurrentAssignProcessor
|
|
cmp eax,fs:PcHal.PcrEBI2ProcessorID
|
|
jne EnbSysIntExit
|
|
mov IrqlAssignToProcTable[ecx*4],eax ;update IrqlAssingnTable
|
|
cmp _HalpInitializedProcessors,1
|
|
je HESI_010 ;skip if only one processor
|
|
inc eax ;1-base count
|
|
cmp eax,_HalpInitializedProcessors
|
|
jae HESI_008
|
|
inc CurrentAssignProcessor
|
|
jmp HESI_010
|
|
HESI_008:
|
|
mov CurrentAssignProcessor,0 ;reset to 0
|
|
|
|
HESI_010:
|
|
mov eax, HalpIRQLtoEBIIntNumber[ecx*4] ;get ebi2 int #
|
|
cli
|
|
btr fs:PcIDR, eax ;enable int locally
|
|
jnc EnbSysIntExit ;jump if already enabled
|
|
;
|
|
lea eax, _EBI2_Lock
|
|
EnbSysIntAquire:
|
|
ACQUIRE_SPINLOCK eax, EnbSysIntSpin
|
|
;
|
|
;Enable interrupt locally
|
|
;
|
|
mov cl, fs:PcIrql
|
|
fstCall KfRaiseIrql
|
|
|
|
;
|
|
;Get the global interrupt mask
|
|
;
|
|
lea eax, EBI2_GlobalIntMask
|
|
push eax
|
|
CALL_EBI2 GetGlobalIntMask,2
|
|
|
|
if DBG
|
|
or eax,eax
|
|
je EnableSysInt4_OK
|
|
int 3 ;trap for debugging
|
|
EnableSysInt4_OK:
|
|
endif
|
|
|
|
;
|
|
;Enable interrupt globally at PIC
|
|
;
|
|
mov eax,EBI2_GlobalIntMask ;current Global mask
|
|
and eax,fs:PcIDR ;enable int according PcIDR
|
|
and eax,0FFFFh ;EBI allows only irqs
|
|
push eax
|
|
CALL_EBI2 SetGlobalIntMask,2
|
|
|
|
if DBG
|
|
or eax,eax
|
|
je EnableSysInt3_OK
|
|
int 3 ;trap for debugging
|
|
EnableSysInt3_OK:
|
|
endif
|
|
|
|
EnbSysIntRelease:
|
|
lea eax, _EBI2_Lock
|
|
RELEASE_SPINLOCK eax
|
|
|
|
EnbSysIntExit:
|
|
;## DisplPanel HalEnableSystemInterruptExit
|
|
sti
|
|
mov eax, 1
|
|
stdRET _HalEnableSystemInterrupt
|
|
|
|
EnbSysIntError:
|
|
DisplPanel HalEnableSystemInterruptError
|
|
if DBG
|
|
int 3
|
|
endif
|
|
sti
|
|
xor eax,eax
|
|
stdRET _HalEnableSystemInterrupt
|
|
|
|
EnbSysIntSpin:
|
|
SPIN_ON_SPINLOCK eax, EnbSysIntAquire
|
|
|
|
stdENDP _HalEnableSystemInterrupt
|
|
|
|
|
|
_TEXT ENDS
|
|
END
|