|
|
title "Interprocessor Interrupt" ;++ ; ;Copyright (c) 1991 Microsoft Corporation ;Copyright (c) 1992 Intel Corporation ;All rights reserved ; ;INTEL CORPORATION PROPRIETARY INFORMATION ; ;This software is supplied to Microsoft under the terms ;of a license agreement with Intel Corporation and may not be ;copied nor disclosed except in accordance with the terms ;of that agreement. ; ; ;Module Name: ; ; mpipi.asm ; ;Abstract: ; ; PC+MP IPI code. ; Provides the HAL support for Interprocessor Interrupts and Processor ; initialization for PC+MP Systems ; ;Author: ; ; Ken Reneris (kenr) 13-Jan-1992 ; ;Revision History: ; ; Ron Mosgrove (Intel) Aug 1993 ; Modified for PC+MP Systems ;-- .486p .xlist
; ; Normal includes ;
include hal386.inc include i386\kimacro.inc include mac386.inc include apic.inc include callconv.inc ; calling convention macros include ntapic.inc
EXTRNP Kei386EoiHelper,0,IMPORT
EXTRNP _HalpMarkProcessorStarted,2
EXTRNP _HalBeginSystemInterrupt,3 EXTRNP _HalEndSystemInterrupt,2 EXTRNP _KiIpiServiceRoutine,2,IMPORT EXTRNP _HalDisplayString,1 EXTRNP HalpAcquireHighLevelLock,1,,FASTCALL EXTRNP HalpReleaseHighLevelLock,2,,FASTCALL EXTRNP HalpSendIpi,2,,FASTCALL ifdef ACPI_HAL EXTRNP _DetectAcpiMP,2 else EXTRNP _DetectMPS,1 endif EXTRNP _HalpRegisterKdSupportFunctions,1 EXTRNP _HalpInitializeLocalUnit,0 EXTRNP _HalpResetThisProcessor,0 if DBG OR DEBUGGING EXTRNP _DbgBreakPoint,0,IMPORT endif extrn _HalpDefaultInterruptAffinity:DWORD extrn _HalpActiveProcessors:DWORD
extrn _HalpGlobal8259Mask:WORD extrn _HalpStaticIntAffinity:BYTE extrn _HalpPICINTToVector:BYTE extrn _rgzBadHal:BYTE
extrn _HalpMaxProcsPerCluster:BYTE extrn _HalpIntDestMap:BYTE
I386_80387_BUSY_PORT equ 0f0h
SEND_IPI macro IpiCommand mov ecx, eax mov edx, IpiCommand fstCall halpSendIpi endm
_DATA SEGMENT DWORD PUBLIC 'DATA'
ALIGN dword
public _HalpProcessorPCR _HalpProcessorPCR dd MAXIMUM_PROCESSORS dup (?) ; PCR pointer for each processor
; ; The following symbols are used by the Local Apic Error handler. ; LogApicErrors equ 1 if LogApicErrors
public _HalpLocalApicErrorLock public _HalpLocalApicErrorCount public _HalpApicErrorLog
APIC_ERROR_LOG_SIZE equ 128 ; Must be 2^n see usage below
ALIGN dword
_HalpApicErrorLog dw APIC_ERROR_LOG_SIZE dup(0) _HalpLocalApicErrorLock dd 0 _HalpLocalApicErrorCount dd 0
; ; Bit: ; ; 0 - Send checksum error ; 1 - Recieve checksum error ; 2 - Send accept error ; 3 - Receive accept error ; 4 - reserved ; 5 - Send illegal vector ; 6 - Receive illegal vector ; 7 - illegal register address ; 8-31 - reserved ;
endif ; LogApicErrors
public HalpBroadcastLock, HalpBroadcastTargets public HalpBroadcastFunction, HalpBroadcastContext HalpBroadcastLock dd 0 HalpBroadcastFunction dd 0 HalpBroadcastContext dd 0 HalpBroadcastTargets dd 0
_DATA ends
_TEXT SEGMENT DWORD PUBLIC 'DATA'
ALIGN dword ; ; The _PicExtintIntiHandlers and the _PicNopIntiHandlers tables are ; used by the enable and disable system interrupt routines to determine ; the EXTINT interrupt handler to install. ; public _PicExtintIntiHandlers _PicExtintIntiHandlers label dword dd PicInterruptHandlerInti0 ; Inti 0 - PIC 1 dd PicInterruptHandlerInti1 ; Inti 1 - PIC 1 dd PicInterruptHandlerInti2 ; Inti 2 - PIC 1 dd PicInterruptHandlerInti3 ; Inti 3 - PIC 1 dd PicInterruptHandlerInti4 ; Inti 4 - PIC 1 dd PicInterruptHandlerInti5 ; Inti 5 - PIC 1 dd PicInterruptHandlerInti6 ; Inti 6 - PIC 1 dd PicInterruptHandlerInti7 ; Inti 7 - PIC 1 dd PicInterruptHandlerInti8 ; Inti 8 - PIC 2 dd PicInterruptHandlerInti9 ; Inti 9 - PIC 2 dd PicInterruptHandlerIntiA ; Inti 10 - PIC 2 dd PicInterruptHandlerIntiB ; Inti 11 - PIC 2 dd PicInterruptHandlerIntiC ; Inti 12 - PIC 2 dd PicInterruptHandlerIntiD ; Inti 13 - PIC 2 dd PicInterruptHandlerIntiE ; Inti 14 - PIC 2 dd PicInterruptHandlerIntiF ; Inti 15 - PIC 2
public _PicNopIntiHandlers _PicNopIntiHandlers label dword dd PicNopHandlerInti0 ; Inti 0 - PIC 1 dd PicNopHandlerInti1 ; Inti 1 - PIC 1 dd PicNopHandlerInti2 ; Inti 2 - PIC 1 dd PicNopHandlerInti3 ; Inti 3 - PIC 1 dd PicNopHandlerInti4 ; Inti 4 - PIC 1 dd PicNopHandlerInti5 ; Inti 5 - PIC 1 dd PicNopHandlerInti6 ; Inti 6 - PIC 1 dd PicNopHandlerInti7 ; Inti 7 - PIC 1 dd CommonPic2NopHandler ; Inti 8 - PIC 2 dd CommonPic2NopHandler ; Inti 9 - PIC 2 dd CommonPic2NopHandler ; Inti 10 - PIC 2 dd CommonPic2NopHandler ; Inti 11 - PIC 2 dd CommonPic2NopHandler ; Inti 12 - PIC 2 dd PicNopHandlerIntiD ; Inti 13 - PIC 2 dd CommonPic2NopHandler ; Inti 14 - PIC 2 dd CommonPic2NopHandler ; Inti 15 - PIC 2
_TEXT ends
page ,132 subttl "Post InterProcessor Interrupt" _TEXT SEGMENT DWORD PUBLIC 'CODE' ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
;++ ; ; VOID ; HalInitializeProcessor( ; ULONG Number ; PVOID LoaderBlock ; ); ; ;Routine Description: ; ; Initialize hal pcr values for current processor (if any) ; (called shortly after processor reaches kernel, before ; HalInitSystem if P0) ; ; IPI's and KeReadir/LowerIrq's must be available once this function ; returns. (IPI's are only used once two or more processors are ; available) ; ; . Enable IPI interrupt (makes sense for P1, P2, ...). ; . Save Processor Number in PCR. ; . if (P0) ; . determine if the system is a PC+MP, ; . if not a PC+MP System Halt; ; . Enable IPI's on CPU. ; ;Arguments: ; ; Number - Logical processor number of calling processor ; ;Return Value: ; ; None. ; ;-- cPublicProc _HalInitializeProcessor ,2
mov PCR[PcIDR], 0FFFFFFFFH ; mark all INTs as disabled
movzx eax, byte ptr [esp+4] mov PCR[PcHal.PcrNumber], al ; Save processor # in PCR
mov ecx, PCR[PcSelfPcr] ; Flat address of this PCR mov _HalpProcessorPCR[eax*4], ecx ; Save it away
mov dword ptr PCR[PcStallScaleFactor], INITIAL_STALL_COUNT
; ; set bit in affinity mask for this active processor ;
lock bts _HalpActiveProcessors, eax
; ; set interrupt affinity to either be most-significant processor or ; a set of all processors ;
mov edx, eax mov eax, _HalpDefaultInterruptAffinity
hip10: cmp _HalpStaticIntAffinity, 1 ; Signle or all? sbb ecx, ecx ; set mask 0 or -1 and ecx, eax ; include existing set or not bts ecx, edx ; include self
cmp ecx, eax ; new mask a better choice? jc short hip20 ; no, done
lock cmpxchg _HalpDefaultInterruptAffinity, ecx ; set new mask jnz short hip10 ; if it didn't take, do it again hip20:
; ; Most of the following code is only needed on P0 ;
or edx, edx jnz PnInitCode ; Not P0 skip a lot
; Run on P0 only
; ; Determine if the system we are on is an PC+MP ; ; DetectMPS has a parameter we don't currently use. It's a boolean ; which is set to TRUE if the system we're on is a MP system. Remember, ; we could have a UP PC+MP system. ; ; The DetectMPS routine also allocates Virtual Addresses for all of ; the APIC's in the system (it needs to access the devices anyway so ...) ;
sub esp, 4 ifdef ACPI_HAL mov eax, esp stdCall _DetectAcpiMP <eax, [esp + 12]> ; Are we running on an ACPI MP else stdCall _DetectMPS <esp> ; Are we running on an PC+MP endif add esp,4
cmp eax, 0 ; Yes (nonZero) or je NotPcMp ; No (Zero)
; stdCall _HalDisplayString, <offset HalSignonString>
; ; This next call has nothing to do with processor init. ; But this is the only function in the HAL that gets ; called before KdInit. ; stdCall _HalpRegisterKdSupportFunctions <[esp + 8]>
mov ax, 0FFFFH ; mask all PIC interrupts mov _HalpGlobal8259Mask, ax ; save the mask SET_8259_MASK
; ; Other P0 initialization would go here ; jmp CommonInitCode
PnInitCode: ; ; Pn initialization goes here ;
mov ecx, PCR[PcPrcb] ; get PRCB movzx eax, byte ptr [ecx].PbHalReserved.PrcbPCMPApicID ; get APIC id movzx ecx, byte ptr [ecx].PbNumber ; get processor number
stdCall _HalpMarkProcessorStarted, <eax, ecx>
CommonInitCode:
stdCall _HalInitApicInterruptHandlers
; ; initialize the APIC local unit for this Processor ;
stdCall _HalpInitializeLocalUnit
stdRET _HalInitializeProcessor
NotPcMp: stdCall _HalDisplayString, <offset _rgzBadHal> hlt
stdENDP _HalInitializeProcessor
D_INT032 EQU 8E00h ; access word for 386 ring 0 interrupt gate
;++ ; ; VOID ; HalInitApicInterruptHandlers( ; ); ; ;Routine Description: ; ; This routine installs the interrupt vector in the IDT for the APIC ; spurious interrupt. ; ;Arguments: ; ; None. ; ;Return Value: ; ; None. ; ;-- cPublicProc _HalInitApicInterruptHandlers ,0 enter 8,0 ; setup ebp, reserve 8 bytes of stack
sidt fword ptr [ebp-8] ; get IDT address mov edx, [ebp-6] ; (edx)->IDT
mov ecx, PIC1_SPURIOUS_VECTOR ; Spurious Vector mov eax, offset FLAT:PicSpuriousService37 mov word ptr [edx+8*ecx], ax ; Lower half of handler addr mov word ptr [edx+8*ecx+2], KGDT_R0_CODE ; set up selector mov word ptr [edx+8*ecx+4], D_INT032 ; 386 interrupt gate shr eax, 16 ; (ax)=higher half of handler addr mov word ptr [edx+8*ecx+6], ax
mov ecx, APIC_SPURIOUS_VECTOR ; Apic Spurious Vector mov eax, offset FLAT:_HalpApicSpuriousService mov word ptr [edx+8*ecx], ax ; Lower half of handler addr mov word ptr [edx+8*ecx+2], KGDT_R0_CODE ; set up selector mov word ptr [edx+8*ecx+4], D_INT032 ; 386 interrupt gate shr eax, 16 ; (ax)=higher half of handler addr mov word ptr [edx+8*ecx+6], ax
leave stdRET _HalInitApicInterruptHandlers stdENDP _HalInitApicInterruptHandlers
cPublicProc PicSpuriousService37 ,0 iretd stdENDP PicSpuriousService37
;++ ; ; VOID ; HalpApicRebootService( ; ); ; ;Routine Description: ; ; This is the ISR that handles Reboot events ; ;--
ENTER_DR_ASSIST HReboot_a, HReboot_t cPublicProc _HalpApicRebootService ,0 ENTER_INTERRUPT_FORCE_STATE HReboot_a, HReboot_t ; (ebp) -> Trap frame
mov eax, APIC_REBOOT_VECTOR
mov ecx, dword ptr APIC[LU_TPR] ; get the old TPR push ecx ; save it mov dword ptr APIC[LU_TPR], eax ; set the TPR APICFIX edx
; ; EOI the local APIC, warm reset does not reset the 82489 APIC ; so if we don't EOI here we'll never see an interrupt after ; the reboot. ;
mov dword ptr APIC[LU_EOI], 0 ; send EOI to APIC local unit
stdCall _HalpResetThisProcessor
; ; We should never get here, but just in case someone is stepping ; through this ;
pop eax mov dword ptr APIC[LU_TPR], eax ; reset the TPR APICFIX edx
; ; Do interrupt exit processing without EOI ;
SPURIOUS_INTERRUPT_EXIT
stdENDP _HalpApicRebootService
;++ ; ; VOID ; HalpGenericCallService( ; ); ; ; Routine Description: ; This is the ISR that handles the GenericCall interrupt ; ;-- ENTER_DR_ASSIST HGeneric_a, HGeneric_t cPublicProc _HalpBroadcastCallService ,0 ENTER_INTERRUPT HGeneric_a, HGeneric_t ; (ebp) -> Trap frame ; ; (esp) - base of trap frame ; ; dismiss interrupt and raise Irql ; push APIC_GENERIC_VECTOR sub esp, 4 ; allocate space to save OldIrql stdCall _HalBeginSystemInterrupt, <CLOCK2_LEVEL-1,APIC_GENERIC_VECTOR,esp>
call _HalpPollForBroadcast
INTERRUPT_EXIT ; lower irql to old value, iret
stdENDP _HalpBroadcastCallService
;++ ; ; VOID ; HalpGenericCall( ; IN VOID (*WorkerFunction)(VOID), ; IN ULONG Context, ; IN KAFFINITY TargetProcessors ; ); ; ; Routine Description: ; Causes the WorkerFunction to be called on the specified target ; processors. The WorkerFunction is called at CLOCK2_LEVEL-1 ; (Must be below IPI_LEVEL in order to prevent system deadlocks). ; ; Enviroment: ; Must be called with interrupts enabled. ; Must be called with IRQL = CLOCK2_LEVEL-1 ;--
cPublicProc _HalpGenericCall,3 cPublicFpo 3, 0
GENERIC_IPI equ (DELIVER_FIXED OR LOGICAL_DESTINATION OR ICR_USE_DEST_FIELD OR APIC_GENERIC_VECTOR)
@@: call _HalpPollForBroadcast test HalpBroadcastLock, 1 ; Is broadcast busy? jnz short @b ; Yes, wait
lock bts HalpBroadcastLock, 0 ; Try to get lock jc short @b ; didn't get it, loop
hgc30: mov ecx, [esp+4] mov edx, [esp+8] mov eax, [esp+12] mov HalpBroadcastFunction, ecx mov HalpBroadcastContext, edx mov HalpBroadcastTargets, eax
or eax, eax ; (eax) = Targets jz gc90
SEND_IPI GENERIC_IPI
; ; Wait for all processors to call broadcast function ;
@@: call _HalpPollForBroadcast cmp HalpBroadcastTargets, 0 jnz short @b
gc90: mov HalpBroadcastLock, 0 ; Release BroadcastLock stdRET _HalpGenericCall
stdENDP _HalpGenericCall
;++ ; ; VOID ; _HalpPollForBroadcast ( ; VOID ; ); ; ; Routine Description: ; ; IRQL = CLOCK2_LEVEL-1 ;-- cPublicProc _HalpPollForBroadcast, 0 cPublicFpo 0, 0 mov eax, PCR[PcSetMember] test HalpBroadcastTargets, eax jz short pb90
mov ecx, HalpBroadcastFunction ; Pickup broadcast function push HalpBroadcastContext
not eax ; Remove our bit from destionations lock and HalpBroadcastTargets, eax
call ecx
pb90: stdRET _HalpPollForBroadcast
stdENDP _HalpPollForBroadcast
;++ ; ; ULONG ; FASTCALL ; HalpWaitForPending ( ; ULONG Count (ecx) ; PULONG LuICR (edx) ; ); ; ; Routine Description: ; ; Waits for DELIVERY_PENDING to clear and returns remaining iteration count ;-- cPublicFastCall HalpWaitForPending, 2 cPublicFpo 0, 0
wfp10: test dword ptr [edx], DELIVERY_PENDING jz short wfp20
dec ecx jnz short wfp10
wfp20: mov eax, ecx fstRet HalpWaitForPending
fstENDP HalpWaitForPending
;++ ; ; VOID ; HalpLocalApicErrorService( ; ); ; ;Routine Description: ; ; This routine fields Local APIC error Events ; ;--
ENTER_DR_ASSIST HApicErr_a, HApicErr_t
cPublicProc _HalpLocalApicErrorService ,0
; ; Save machine state in trap frame ;
ENTER_INTERRUPT HApicErr_a, HApicErr_t ; (ebp) -> Trap frame
if LogApicErrors
lea ecx, _HalpLocalApicErrorLock fstCall HalpAcquireHighLevelLock push eax
mov eax, _HalpLocalApicErrorCount inc _HalpLocalApicErrorCount
lea ecx, _HalpApicErrorLog
and eax, APIC_ERROR_LOG_SIZE-1 shl eax, 1 add ecx, eax
endif ; LogApicErrors
mov dword ptr APIC[LU_EOI], 0 ; local unit EOI APICFIX eax
; ; The Apic EDS (Rev 4.0) says you have to write before you read ; this doesn't work. The write clears the status bits. ; But P6 works as according to the EDS! ;
mov eax, PCR[PcPrcb] cmp byte ptr [eax].PbCpuType, 6 jc short lae10 mov dword ptr APIC[LU_ERROR_STATUS], 0
lae10: mov eax, dword ptr APIC[LU_ERROR_STATUS] ; read error status
; Find out what kind of error it is and update the appropriate count.
if LogApicErrors ; out 80h, al mov byte ptr [ecx], al inc ecx mov al, byte ptr PCR[PcHal.PcrNumber] mov byte ptr [ecx], al
lea ecx, _HalpLocalApicErrorLock pop edx fstCall HalpReleaseHighLevelLock
endif ; LogApicErrors
SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi stdENDP _HalpLocalApicErrorService
page ,132 subttl "PC+MP IPI Interrupt Handler" ;++ ; ; VOID ; HalpIpiHandler ( ; ); ; ; Routine Description: ; ; This routine is entered as the result of an interrupt generated by inter ; processor communication. ; ; Arguments: ; ; None. ; ; Return Value: ; ; None. ; ;--
ENTER_DR_ASSIST Hipi_a, Hipi_t
cPublicProc _HalpIpiHandler ,0
; ; Save machine state in trap frame ;
ENTER_INTERRUPT Hipi_a, Hipi_t ; (ebp) -> Trap frame
; ; Save previous IRQL ; push APIC_IPI_VECTOR ; Vector sub esp, 4 ; space for OldIrql ; ; We now dismiss the interprocessor interrupt and call its handler ;
stdCall _HalBeginSystemInterrupt,<IPI_LEVEL,APIC_IPI_VECTOR,esp>
stdCall _KiIpiServiceRoutine, <ebp,0>
; ; Do interrupt exit processing ;
INTERRUPT_EXIT ; will return to caller
stdENDP _HalpIpiHandler
;++ ; ; VOID ; HalpApicSpuriousService( ; ); ; ;Routine Description: ; ; A place for spurious interrupts to end up. ; ;-- cPublicProc _HalpApicSpuriousService,0 iretd stdENDP _HalpApicSpuriousService
;++ ; ; VOID ; _PicInterruptHandlerIntiXX( ; ); ; ;Routine Description: ; ; These handlers receive interrupts from the PIC and reissues them via ; a vector at the proper priority level. This is used to provide a symetric ; interrupt distribution on a non symetric system. ; ; The PIC interrupts will normally only be received (in the PC+MP Hal) via an ; interrupt input from on either the IO Unit or the Local unit which has been ; programed as EXTINT. EXTINT interrupts are received outside of the APIC ; priority structure (the PIC provides the vector). We use the APIC ICR to ; generate interrupts to the proper handler at the proper priority. ; ; The EXTINT interrupts are directed to a single processor, currently P0. ; There is no good reason why they can't be directed to another processor. ; ; Since one processor must absorb the overhead of redistributing PIC interrupts ; the interrupt handling on a system using EXTINT interrupts is not symetric. ; ;--
ENTER_DR_ASSIST Hcpic_a, Hcpic_t
cPublicProc PicHandler ,0
PicInterruptHandlerInti0: push 0 jmp short CommonPicHandler
PicInterruptHandlerInti1: push 1 jmp short CommonPicHandler
PicInterruptHandlerInti2: push 2 jmp short CommonPicHandler
PicInterruptHandlerInti3: push 3 jmp short CommonPicHandler
PicInterruptHandlerInti4: push 4 jmp short CommonPicHandler
PicInterruptHandlerInti5: push 5 jmp short CommonPicHandler
PicInterruptHandlerInti6: push 6 jmp short CommonPicHandler
PicInterruptHandlerInti7: ; ; Check to see if this is a spurious interrupt ; push eax mov al, OCW3_READ_ISR ; tell 8259 we want to read ISR out PIC1_PORT0, al IODelay ; delay in al, PIC1_PORT0 ; (al) = content of PIC 1 ISR test al, 10000000B ; Is In-Service register set? pop eax jz short pic7_spurious ;
push 7 jmp short CommonPicHandler
picf_spurious: mov al, OCW2_SPECIFIC_EOI OR SlavePicInti ; specific eoi to master for pic2 eoi out PIC1_PORT0, al pop eax pic7_spurious: iretd ; ignore PIC
PicInterruptHandlerInti8: push 8 jmp short CommonPicHandler
PicInterruptHandlerInti9: push 9 jmp short CommonPicHandler
PicInterruptHandlerIntiA: push 10 jmp short CommonPicHandler
PicInterruptHandlerIntiB: push 11 jmp short CommonPicHandler
PicInterruptHandlerIntiC: push 12 jmp short CommonPicHandler
PicInterruptHandlerIntiD: push 13 push eax xor eax, eax out I386_80387_BUSY_PORT, al pop eax jmp short CommonPicHandler
PicInterruptHandlerIntiE: push 14 jmp short CommonPicHandler
PicInterruptHandlerIntiF: push eax mov al, OCW3_READ_ISR ; tell 8259 we want to read ISR out PIC2_PORT0, al IODelay ; delay in al, PIC2_PORT0 ; (al) = content of PIC 1 ISR test al, 10000000B ; Is In-Service register set? jz short picf_spurious ; Go eoi PIC1 & Ignore PIC2
pop eax push 15 jmp short CommonPicHandler
CommonPicHandler: ENTER_INTERRUPT Hcpic_a, Hcpic_t,PassDwordParm ; (ebp) -> Trap frame
; ; Need to determine if we have a level interrupt and if so don't EOI it ; It should be EOI'd by end system interrupt ;
cmp bl, 8 ; Pic or Slave Pic jae short cph20
mov al, bl or al, OCW2_SPECIFIC_EOI ; specific eoi out PIC1_PORT0, al ; dismiss the interrupt jmp short cph30
cph20: mov al, OCW2_NON_SPECIFIC_EOI ; send non specific eoi to slave out PIC2_PORT0, al mov al, OCW2_SPECIFIC_EOI OR SlavePicInti ; specific eoi to master for pic2 eoi out PIC1_PORT0, al ; send irq2 specific eoi to master
cph30: mov al, _HalpPICINTToVector[ebx] ; Get vector for PIC interrupt or al, al ; Is vector known? jz short cph90 ; No, don't dispatch it
; ; Now gain exclusive access to the ICR ;
STALL_WHILE_APIC_BUSY
cmp bl, 8 je short HandleClockInti
; ; Write the IPI Command to the Memory Mapped Register ;
mov dword ptr APIC[LU_INT_CMD_HIGH], DESTINATION_ALL_CPUS APICFIX edx mov dword ptr APIC[LU_INT_CMD_LOW], eax jmp short cph90
HandleClockInti: ; ; Write the IPI Command to the Memory Mapped Register ;
mov dword ptr APIC[LU_INT_CMD_LOW], (DELIVER_FIXED OR ICR_SELF OR APIC_CLOCK_VECTOR)
cph90: APICFIX edx SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi
stdENDP PicHandler
;++ ; ; VOID ; _PicXXNopHandler( ; ); ; ;Routine Description: ; ; These handlers are designed to be installed on a system to field any PIC ; interrupts when there are not supposed to be any delivered. ; ; In the Debug case this routine increments an error count EOI's the PIC and ; returns. Normally the increment is not performed. ;--
cPublicProc PicNopHandler ,0
PicNopHandlerInti0: push eax ; Save Scratch Registers mov al, 0 jmp short CommonPic1NopHandler
PicNopHandlerInti1: push eax ; Save Scratch Registers mov al, 1 jmp short CommonPic1NopHandler
PicNopHandlerInti2: push eax ; Save Scratch Registers mov al, 2 jmp short CommonPic1NopHandler
PicNopHandlerInti3: push eax ; Save Scratch Registers mov al, 3 jmp short CommonPic1NopHandler
PicNopHandlerInti4: push eax ; Save Scratch Registers mov al, 4 jmp short CommonPic1NopHandler
PicNopHandlerInti5: push eax ; Save Scratch Registers mov al, 5 jmp short CommonPic1NopHandler
PicNopHandlerInti6: push eax ; Save Scratch Registers mov al, 6 jmp short CommonPic1NopHandler
PicNopHandlerInti7: push eax ; Save Scratch Registers mov al, 7
CommonPic1NopHandler: ; ; Need to determine if we have a level interrupt and if so don't EOI it ; It should be EOI'd by end system interrupt ;
or al, OCW2_SPECIFIC_EOI ; specific eoi out PIC1_PORT0, al ; dismiss the interrupt pop eax ; Restore Scratch registers iretd
PicNopHandlerIntiD: push eax xor eax, eax out I386_80387_BUSY_PORT, al pop eax
CommonPic2NopHandler: push eax
; ; Need to determine if we have a level interrupt and if so don't EOI it ; It should be EOI'd by end system interrupt ;
mov al, OCW2_NON_SPECIFIC_EOI ; send non specific eoi to slave out PIC2_PORT0, al mov al, OCW2_SPECIFIC_EOI OR SlavePicInti ; specific eoi to master for pic2 eoi out PIC1_PORT0, al ; send irq2 specific eoi to master pop eax iretd
stdENDP PicNopHandler
_TEXT ENDS
END
|