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, ;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, ;DBG_DISPLAY 0a3h hip30_Any: ;LSX5030 end stdRET _HalInitializeProcessor ;LSX5030 start _NotAnLSX5030: stdCall _HalDisplayString, 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, ;DBG_DISPLAY 92h ; Pass Null ExceptionFrame ; Pass TrapFrame to Ipi service rtn stdCall _KiIpiServiceRoutine , ; ; 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, stdCall _KiCoprocessorError ; call CoprocessorError handler ; ; Do interrupt exit processing ; INTERRUPT_EXIT ; will return to caller stdENDP _HalpIrq13Handler ;LSX5030 end _TEXT ENDS END