NT4/private/ntos/nthals/haloli/i386/oliipi.asm
2020-09-30 17:12:29 +02:00

572 lines
12 KiB
NASM

title "Interprocessor Interrupt"
;++
;
;Copyright (c) 1991 Microsoft Corporation
;
;Module Name:
;
; oliipi.asm
;
;Abstract:
;
; SystemPro IPI code.
; Provides the HAL support for Interprocessor Interrupts for hte
; MP SystemPro implementation.
;
;Author:
;
; Ken Reneris (kenr) 13-Jan-1992
;
;Revision History:
;
; Bruno Sartirana (o-obruno) 3-Mar-92
; Added support for the Olivetti LSX5030.
;--
.386p
.xlist
;
; Include LSX5030 detection code
;
include i386\olidtect.asm
;
; Normal includes
;
include hal386.inc
include callconv.inc
include i386\kimacro.inc
include i386\ix8259.inc
;LSX5030 start
include i386\olimp.inc
EXTRNP _HalpInitializeProcessor,1
extrn _IdtIpiVector:DWORD
extrn KiI8259MaskTable:DWORD
;LSX5030 end
EXTRNP _KiCoprocessorError,0,IMPORT
EXTRNP Kei386EoiHelper,0,IMPORT
EXTRNP _HalBeginSystemInterrupt,3
EXTRNP _HalEndSystemInterrupt,2
EXTRNP _KiIpiServiceRoutine,2,IMPORT
EXTRNP _HalEnableSystemInterrupt,3
EXTRNP _HalpInitializePICs,0
EXTRNP _HalDisplayString,1
EXTRNP _HalEnableSystemInterrupt,3
EXTRNP _HalDisableSystemInterrupt,2
extrn _HalpActiveProcessors:DWORD
_DATA SEGMENT DWORD PUBLIC 'DATA'
;LSX5030 start
;ifdef HALOLI_DBG
; for debug only
public DbgDelay
DbgDelay dd 20000000
;endif
; IPI IRQL decoding array
public PcrIpiIrql
PcrIpiIrql db 15
db 11
db 10
db 13
;LSX5030 end
;
; Processor Control Ports
;
public ProcessorControlPort, _HalpProcessorPCR, _HalpInitializedProcessors
ProcessorControlPort dw PCR_P0 ; P0 Processor Control Port
dw PCR_P1 ; P1 Processor Control Port
dw PCR_P2 ; P2 Processor Control Port
dw PCR_P3 ; P3 Processor Control Port
_HalpProcessorPCR dd MAXIMUM_PROCESSORS dup (?) ; PCR pointer for each processor
_HalpInitializedProcessors dd 0
;
;InterruptVectorControl dw 0 ; P0 none for p0
;dw ICP_P1 ; P1 Processor Control Port
;dw ICP_P2 ; P2 Processor Control Port
;dw ICP_P3 ; P3 Processor Control Port
public _HalpFindFirstSetRight
_HalpFindFirstSetRight db 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
public _SystemType
_SystemType dd 0
;LSX5030 start
BadHalString db 'HAL: LSX5030 HAL.DLL cannot be run on non LSX5030', cr, lf
db ' Replace the hal.dll with the correct hal', cr, lf
db ' System is HALTING *********', 0
;LSX5030 end
_DATA 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
; );
;
;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 what kind of system is it,
; . if (NotSysProCompatible) Halt;
; . InitializePICs.
; . if (P1)
; . program VECTOR_PORT to accept IPI at IRQ13.
; . Save ProcesserControlPort (PCR) to PCRegion, per processor.
; . Enable PINTs on CPU.
;
;Arguments:
;
; eax: processor number - Logical processor number of calling processor
;
;Return Value:
;
; None.
;
;--
cPublicProc _HalInitializeProcessor,1
;LSX5030 start
;DBG_DISPLAY 0a0h
; Initialize PcIDR in PCR to enable slave IRQ
mov fs:PcIDR, 0fffffffbh
movzx eax, byte ptr [esp+4] ; get processor number
mov fs:PcHal.PcrNumber, al ; Save processor # in PCR
lock bts _HalpActiveProcessors, eax
lock inc _HalpInitializedProcessors
mov ecx, fs:PcSelfPcr ; Flat address of this PCR
mov _HalpProcessorPCR[eax*4], ecx ; Save it away
or eax, eax
jnz hip20_Any ; jump if not P0
; For P0 only, determine if this is an LSX5030 or not.
lea eax, _SystemType ; this just to honor the
; DetectOlivettiMp call interface
stdCall _DetectOlivettiMp,<eax>
;DBG_DISPLAY 0a1h
mov _SystemType, eax ; Remember system type
or eax, eax
jz _NotAnLSX5030 ; (SystemType == 0): Alien machine
; P0
; Initialized the stall scale factor to something other that 0,
; just in case KeStallExecutionProcessor was called before
; HalpInitializeStallExecution (when a DbgBreakPoint() is used
; before HalpInitializeStallExecution() is called.
;
mov dword ptr fs:PcStallScaleFactor, INITIAL_STALL_COUNT
; load eax with the processor #
movzx eax, byte ptr fs:PcHal.PcrNumber ; get processor # from PCR
hip20_Any:
; Note: at this point eax must contain the processor number
mov dx, word ptr ProcessorControlPort[eax*2]
in al, dx ; get PCR status
and al, not PINT ; clear IPI pending bit
or al, IPI_EN ; enable IPI's
out dx, al ; store the new PCR status
mov fs:PcHal.PcrControlPort, dx ; Save port value
movzx eax, byte ptr [esp+4] ; get processor number
or eax, eax
jz hip30_Any ; jump if P0
; init PICs, interval timer, stall scale factor...
;DBG_DISPLAY 0a2h
stdCall _HalpInitializeProcessor,<eax>
;DBG_DISPLAY 0a3h
hip30_Any:
;LSX5030 end
stdRET _HalInitializeProcessor
;LSX5030 start
_NotAnLSX5030:
stdCall _HalDisplayString,<offset BadHalString>
hlt
;LSX5030 end
stdENDP _HalInitializeProcessor
;++
;
; VOID
; HalRequestIpi(
; IN ULONG Mask
; );
;
;Routine Description:
;
; Requests an interprocessor interrupt
;
;Arguments:
;
; Mask - Supplies a mask of the processors to be interrupted
;
;Return Value:
;
; None.
;
;--
cPublicProc _HalRequestIpi,1
movzx ecx, byte ptr [esp+4] ; (eax) = Processor bitmask
ifdef DBG
or ecx, ecx ; must ipi somebody
jz short ipibad
movzx eax, byte ptr fs:PcHal.PcrNumber
bt ecx, eax ; cannot ipi yourself
jc short ipibad
endif
@@:
movzx eax, _HalpFindFirstSetRight[ecx] ; lookup first processor to ipi
btr ecx, eax
mov dx, ProcessorControlPort[eax*2]
in al, dx ; (al) = original content of PCP
or al, PINT ; generate Ipi on target
out dx, al
or ecx, ecx ; ipi any other processors?
jnz @b ; yes, loop
stdRET _HalRequestIpi
ifdef DBG
ipibad: int 3
stdRET _HalRequestIpi
endif
stdENDP _HalRequestIpi
page ,132
subttl "LSX5030 Inter-Processor Interrupt Handler"
;LSX5030 start
;++
;
; VOID
; HalpIpiHandler (
; );
;
; Routine Description:
;
; This routine is entered as the result of an interrupt generated by inter
; processor communication.
; The interrupt is dismissed.
;
; Arguments:
;
; None.
;
; Return Value:
;
; None.
;
;--
ENTER_DR_ASSIST Hixx_a, Hixx_t
cPublicProc _HalpIpiHandler,0
;
; Save machine state in trap frame
;
ENTER_INTERRUPT Hixx_a, Hixx_t ; (ebp) -> Trap frame
;
; Save previous IRQL
;
mov eax, _IdtIpiVector
push eax ; Vector
sub esp, 4 ; space for OldIrql
;DBG_DISPLAY 90h
; Dismiss interrupt.
;
mov dx, fs:PcHal.PcrControlPort
in al, dx
;
; Dismiss the interprocessor interrupt and call its handler
;
and al, not PINT
out dx, al ; clear PINT
;DBG_DISPLAY 91h
mov eax, _IdtIpiVector
; esp - stack location of OldIrql
; eax - vector
; IPI_LEVEL - Irql
stdCall _HalBeginSystemInterrupt,<IPI_LEVEL,eax,esp>
;DBG_DISPLAY 92h
; Pass Null ExceptionFrame
; Pass TrapFrame to Ipi service rtn
stdCall _KiIpiServiceRoutine ,<ebp,0>
;
; Do interrupt exit processing
;
;DBG_DISPLAY 9fh
INTERRUPT_EXIT ; will return to caller
stdENDP _HalpIpiHandler
ifdef HALOLI_DBG
;++
;
; DbgDisplay (
; IN UCHAR DisplayCode
; )
;
; Description:
;
; This function writes 'DisplayCode' to the parallel port, where a LED
; display can be plugged in to show such a code.
; In order to allow the user to read the code on the LED display,
; after writing, a delay is introduced.
;
; Arguments:
; DisplayCode - Byte to write to the parallel port
;
; Return Value:
; None.
;
;--
public _DbgDisplay
_DbgDisplay proc
push eax
push edx
; signal something on the parallel port
mov dx, 378h
mov eax, [esp+12]
out dx, al
mov eax, DbgDelay
@@:
dec eax
cmp eax, 0
jne @b
pop edx
pop eax
ret
_DbgDisplay endp
endif ; HALOLI_DBG
; ULONG
; HalpGetIpiIrqNumber (
; );
;
; Routine Description:
;
; This routine is entered during the phase 0 initialization of the
; first processor. It determines the IRQ # for IPI's.
; The IPI IRQ is stored in the PCR's by the LSX5030 configuration
; utility.
;
; Arguments:
;
; None.
;
; Return Value:
;
; The IPI IRQ# in eax.
;
;--
cPublicProc _HalpGetIpiIrqNumber,0
mov dx, word ptr ProcessorControlPort ; get 1st CPU slot #
in al, dx ; get PCR content
; determine which IRQ for IPI has been set by the user
shr eax, 2 ; bits 0,1 encode the IPI IRQ
and eax, 3 ; zero all the bits but 0,1
movzx ecx, byte ptr PcrIpiIrql[eax] ; decode the IRQ
push ecx
; edit the 8259 mask table to unmask IPI's from IPI_LEVEL-1 down
mov edx, 1
shl edx, cl
not edx ; mask with IPI IRQ# bit set to
; 0
; mov eax, IPI_LEVEL
; sub eax, ecx
lea eax, KiI8259MaskTable ; start from the beginning
; lea eax, KiI8259MaskTable[eax*4] ; start from
; IPI_LEVEL - IPI_IRQ#
mov ecx, IPI_LEVEL
NextEntry:
and [eax], edx
add eax, 4
dec ecx ; loop for IPI IRQ# times
jnz NextEntry
pop eax ; return IPI IRQ#
stdRET _HalpGetIpiIrqNumber
stdENDP _HalpGetIpiIrqNumber
page ,132
subttl "Irq13 Interrupt Handler"
;++
;
; VOID
; HalpIrq13Handler (
; );
;
; Routine Description:
;
; This routine is entered as the result of an interrupt generated by
; coprocessor error,
; This routine will lower irql to its original level, and finally invoke
; coprocessor error handler. By doing this, the coprocessor
; error will be handled at Irql 0 as it should be.
;
; Arguments:
;
; None.
; Interrupt is dismissed
;
; Return Value:
;
; None.
;
;--
ENTER_DR_ASSIST Hi13_a, Hi13_t
cPublicProc _HalpIrq13Handler,0
;
; Save machine state in trap frame
;
ENTER_INTERRUPT Hi13_a, Hi13_t ; (ebp) -> Trap frame
;
; Save previous IRQL
;
push 13 + PRIMARY_VECTOR_BASE ; Vector
sub esp, 4 ; space for OldIrql
;
; Dismiss interrupt.
; location for OldIrql
; Vector
; Irql
stdCall _HalBeginSystemInterrupt,<IPI_LEVEL,13+PRIMARY_VECTOR_BASE,esp>
stdCall _KiCoprocessorError ; call CoprocessorError handler
;
; Do interrupt exit processing
;
INTERRUPT_EXIT ; will return to caller
stdENDP _HalpIrq13Handler
;LSX5030 end
_TEXT ENDS
END