diff options
Diffstat (limited to 'private/ntos/nthals/halws3/i386/w3ipi.asm')
-rw-r--r-- | private/ntos/nthals/halws3/i386/w3ipi.asm | 955 |
1 files changed, 955 insertions, 0 deletions
diff --git a/private/ntos/nthals/halws3/i386/w3ipi.asm b/private/ntos/nthals/halws3/i386/w3ipi.asm new file mode 100644 index 000000000..a7084dc11 --- /dev/null +++ b/private/ntos/nthals/halws3/i386/w3ipi.asm @@ -0,0 +1,955 @@ + title "Interprocessor Interrupt" +;++ +; +; Copyright (c) 1991 Microsoft Corporation +; Copyright (c) 1993 Sequent Computer Systems, Inc. +; +; Module Name: +; +; w3ipi.asm +; +; Abstract: +; +; Provides the HAL support for Interprocessor Interrupts and +; the initial processor initialization. +; +; Author: +; +; Phil Hochstetler (phil@sequent.com) 3-30-93 +; +; Revision History: +; +;-- +.386p + .xlist + +; +; Include WinServer 3000 detection code +; + +include i386\w3detect.asm + +; +; Normal includes +; + +include ks386.inc +include i386\kimacro.inc +include callconv.inc ; calling convention macros +include i386\apic.inc +include i386\w3.inc + +; +; Import/Export +; + EXTRNP _KiCoprocessorError,0,IMPORT + EXTRNP _KeRaiseIrql,2 + EXTRNP Kei386EoiHelper,0,IMPORT + EXTRNP _HalBeginSystemInterrupt,3 + EXTRNP _HalEndSystemInterrupt,2 + EXTRNP _KiIpiServiceRoutine,2,IMPORT + EXTRNP _HalEnableSystemInterrupt,3 + EXTRNP _HalDisplayString,1 + EXTRNP _HalEnableSystemInterrupt,3 + EXTRNP _HalDisableSystemInterrupt,2 + + EXTRNP _HalpInitializeLocalUnit,0 + EXTRNP _DbgBreakPoint,0,IMPORT + + EXTRNP _HalpMapPhysicalMemoryWriteThrough,2 + EXTRNP _HalpMySlotAddr,0 + EXTRNP _HalpResetLocalUnits,0 + + extrn _HalpDefaultInterruptAffinity:DWORD + extrn _HalpActiveProcessors:DWORD + extrn _HalpLocalUnitBase:DWORD + extrn _HalpIOunitBase:DWORD + extrn _HalpIOunitTwoBase:DWORD + extrn _HalpELCRImage:WORD + extrn _HalpMASKED:WORD + + +_DATA SEGMENT DWORD PUBLIC 'DATA' + +HALBadVaddr db 'HAL: No Virtual Address available to map the APIC', CR, LF, 0 +HALMisMatch db 'HAL: This HAL only runs on a WinServer 3000.', CR, LF + db ' Please replace the hal.dll with the correct hal', CR, LF + db ' System is HALTING.', 0 + + ALIGN dword + public _HalpProcessorPCR +_HalpProcessorPCR dd 8 dup (0) ; PCR pointer for each processor + +_DATA ENDS + + page ,132 + subttl "Initialize Processor" +_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 KeRaiseIrql/LowerIrq's must be available once this function +; returns. (IPI's are only used once two or more processors are +; available) +; +; . Save EISA Slot Address in PCR. +; . Save Processor Number in PCR. +; . Set initial StallScaleFactor +; . Set bit in global data structures for each new processor +; . if (P0) +; . determine if the system is a WS3000, +; . if (!WS3000) Halt; +; . Enable IPI's on CPU. +; +;Arguments: +; +; Number - Logical processor number of calling processor +; +;Return Value: +; +; None. +; +;-- +cPublicProc _HalInitializeProcessor ,1 +cPublicFpo 1, 0 + + mov dword ptr PCR[PcStallScaleFactor], INITIAL_STALL_COUNT + + stdCall _HalpMySlotAddr + mov PCR[PcHal.ProcSlotAddr], ax ; Save processor slot + + mov eax, [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 + + lock bts _HalpDefaultInterruptAffinity, eax ; update globals for each + lock bts _HalpActiveProcessors, eax ; online processor + + test eax, eax + jnz ipi_10 + + ; Only Boot Processor executes from here to label ipi_10 + + sub esp, 4 + stdCall _DetectWS3000 <esp> + add esp, 4 + + test eax, eax + jz ipi_notW3 + + ; Initialize PICs and IDT for PICs + + mov ax, 0FFFFh + SET_8259_MASK + stdCall _HalInitPicInterruptHandlers + + ; call HAL memory manager to get a virtual address mapping for the + ; APIC(s); virtual addresses are saved in global variables for indirect + ; addressing later. This assumes that the page tables are built + ; for P0 in Phase 0 are valid for P1. + + stdCall _HalpMapPhysicalMemoryWriteThrough <LU_BASE_ADDRESS,1> + test eax, eax + jz NoHalVaddr + mov _HalpLocalUnitBase, eax + + stdCall _HalpMapPhysicalMemoryWriteThrough <IO_BASE_ADDRESS,1> + test eax, eax + jz NoHalVaddr + mov _HalpIOunitBase, eax + + stdCall _HalpMapPhysicalMemoryWriteThrough <IO_BASE_ADDRESS+020000h,1> + test eax, eax + jz NoHalVaddr + mov _HalpIOunitTwoBase, eax + + ; Reset all other local units to keep them from accepting any + ; interrupts until their processor is out of reset. This is a + ; problem because starting with Beta 2, not all processors may + ; be brought up during install and the WS3000 BIOS enables the + ; APICs even though the corresponding processor is held in reset. + ; This would not be a bug if setting the FCR to put the processor + ; into reset also put the APIC into reset, or if the APIC reset output + ; was wired to the processor and used to reset it instead of the FCR. + + stdCall _HalpResetLocalUnits + +ipi_10: + + ; For P0-Pn, disable the IO unit so it can't suprise us. + ; We have to do this on each CPU on the WS3000 since each CPU can + ; only address the IO unit on its local APIC. Each CPU IO unit + ; has the same address. + + mov edx, _HalpIOunitTwoBase ; get base address of IO unit + mov ecx, IO_REDIR_00_LOW + mov eax, INTERRUPT_MASKED + +ipi_15: + mov [edx+IO_REGISTER_SELECT], ecx ; write mask to redir entry + mov [edx+IO_REGISTER_WINDOW], eax + + add ecx, 2 ; increment to next redir entry + cmp ecx, IO_REDIR_00_LOW + 32 ; go for 16 entries + jb ipi_15 ; more to go + + ; + ; initialize the APIC local unit for this Processor + ; + + stdCall _HalpInitializeLocalUnit + + stdRET _HalInitializeProcessor + +NoHalVaddr: + stdCall _HalDisplayString, <offset HALBadVaddr> + hlt + +ipi_notW3: + stdCall _HalDisplayString, <offset HALMisMatch> + hlt + +stdENDP _HalInitializeProcessor + +;++ +; +; VOID +; HalInitPicInterruptHandlers( +; ); +; +;Routine Description: +; +; initialize the EISA IDT entries for the WinServer 3000. +; This includes installing spurious interrupt handlers for: +; +; PIC1 spurious interrupt vector (EISA_IRQ7_VECTOR) +; PIC2 spurious interrupt vector (EISA_IRQ15_VECTOR) +; +; and handlers for +; +; CLOCK on PIC1 Vector (EISA_IRQ0_VECTOR) +; KEYBOARD on PIC1 Vector (EISA_IRQ1_VECTOR) +; FLOPPY on PIC1 Vector (EISA_IRQ6_VECTOR) +; RTC on PIC2 Vector (EISA_IRQ8_VECTOR) +; MOUSE on PIC2 Vector (EISA_IRQ12_VECTOR) +; DMA on PIC2 Vector (EISA_IRQ13_VECTOR) +; IDE on PIC2 Vector (EISA_IRQ14_VECTOR) +; +; The 82357 ISP on the WinServer 3000 platform does not route the +; clock and DMA interrupts externally. And the Keyboard, Floppy, Rtc, +; Mouse, and Ide are not available to the APIC by design. Instead, we +; must get these interrupts from the integrated PIC (master and +; slave, actually), whose interrupt output drives INTIN<13> of the 82489DX +; APIC. This APIC interrupt input is programmed for ExtINT (external +; interrupt) mode, which causes the integrated PIC to generate the +; interrupt vector instead of the APIC. +; +; Since we want to route all system interrupts through the APIC to take +; advantage of its prioritization mechanism, we install our own interrupt +; handlers for the Clock, Keyboard, Floppy, RTC, , Mouse, DMA, and +; IDE interrupts from the PIC, then redispatch the interrupts through the +; APIC. +; +; Spurious interrupt handlers for the integrated PICs are required because +; the devices can still generate spurious interrupts. +; +;Arguments: +; +; None. +; +;Return Value: +; +; None. +; +;-- + +cPublicProc _HalInitPicInterruptHandlers ,0 + + IDTEntry EISA_PIC1_SPURIOUS_VECTOR, EisaPic1SpuriousService + IDTEntry EISA_PIC2_SPURIOUS_VECTOR, EisaPic2SpuriousService + IDTEntry EISA_CLOCK_VECTOR, EisaClockService + IDTEntry EISA_KBD_VECTOR, EisaKbdService + IDTEntry EISA_FLOPPY_VECTOR, EisaFloppyService + IDTEntry EISA_RTC_VECTOR, EisaRTCService + IDTEntry EISA_DMA_VECTOR, EisaDmaService + IDTEntry EISA_MOUSE_VECTOR, EisaMouseService + IDTEntry EISA_IDE_VECTOR, EisaIDEService + + stdRET _HalInitPicInterruptHandlers + +stdENDP _HalInitPicInterruptHandlers + +;++ +; +; VOID +; ApicSpuriousService( +; ); +; +;Routine Description: +; +; A place for spurious interrupts to end up. +; +;-- +cPublicProc ApicSpuriousService ,0 + iretd +stdENDP ApicSpuriousService + +;++ +; +; VOID +; EisaPic1SpuriousService( +; ); +; +;Routine Description: +; +; A place for spurious EISA PIC one interrupts to end up. +; +;-- +cPublicProc EisaPic1SpuriousService,0 + iretd +stdENDP EisaPic1SpuriousService + +;++ +; +; VOID +; EisaPic2SpuriousService( +; ); +; +;Routine Description: +; +; A place for spurious EISA PIC two interrupts to end up. +; +;-- +cPublicProc EisaPic2SpuriousService,0 + iretd +stdENDP EisaPic2SpuriousService + +;++ +; +; VOID +; EisaClockService( +; ); +; +;Routine Description: +; +; This handler receives interrupts from the EISA PIC and reissues them via +; a vector at the proper priority level. This is needed on the WinServer +; 3000 because we use the PIC interrupts as EXTINT for the 8254 Clock, +; Keyboard, Floppy, RTC, Mouse, DMA, and IDE. Since EXTINT interrupts are +; received outside of the APIC priority structure we use the APIC ICR +; to generate interrupts to the proper handler at the proper priority. +; +; The EXTINT interrupts are programmed via the CCS APIC IO Unit's +; redirection table. They are directed to Processor zero only. +; +;-- + +IPI_CLOCK_ALL equ (DELIVER_FIXED OR ICR_ALL_INCL_SELF OR APIC_CLOCK_VECTOR) + + ENTER_DR_ASSIST H99_a, H99_t + +cPublicProc EisaClockService,0 + + ; + ; Save machine state in trap frame + ; + + ENTER_INTERRUPT H99_a, H99_t ; (esp) - base of trap frame + + ; + ; Just IPI All Processors ( this is done from P0 ) + ; + + mov al, OCW2_SPECIFIC_EOI OR (EISA_CLOCK_VECTOR - PIC0_BASE_VECTOR) + ; specific eoi + out PIC1_PORT0, al ; dismiss the interrupt + ; + ; Make sure the ICR is available + ; + mov ecx, _HalpLocalUnitBase ; load base address of CCS + ; local unit + +@@: + test [ecx+LU_INT_CMD_LOW], DELIVERY_PENDING + jnz @b + + ; + ; Write the Clock IPI Command to the Memory Mapped Register + ; + + mov [ecx+LU_INT_CMD_LOW], IPI_CLOCK_ALL + + SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi + +stdENDP EisaClockService + +;++ +; +; VOID +; EisaKbdService( +; ); +; +;Routine Description: +; +; This handler receives interrupts from the EISA PIC and reissues them via +; a vector at the proper priority level. This is needed on the WinServer +; 3000 because we use the PIC interrupts as EXTINT for the 8254 Clock, +; Keyboard, Floppy, RTC, Mouse, DMA, and IDE. Since EXTINT interrupts are +; received outside of the APIC priority structure we use the APIC ICR +; to generate interrupts to the proper handler at the proper priority. +; +; The EXTINT interrupts are programmed via the CCS APIC IO Unit's +; redirection table. They are directed to Processor zero only. +; +;-- + +IPI_KBD_ALL equ (DELIVER_LOW_PRIORITY OR LOGICAL_DESTINATION OR ICR_ALL_INCL_SELF OR APIC_KBD_VECTOR) + + ENTER_DR_ASSIST H98_a, H98_t + +cPublicProc EisaKbdService ,0 + + ; + ; Save machine state in trap frame + ; + + ENTER_INTERRUPT H98_a, H98_t ; (esp) - base of trap frame + + mov al, OCW2_SPECIFIC_EOI OR (EISA_KBD_VECTOR - PIC0_BASE_VECTOR) + ; specific eoi + out PIC1_PORT0, al ; dismiss the interrupt + + ; + ; Make sure the ICR is available + ; + + mov ecx, _HalpLocalUnitBase ; load base address of CCS + ; local unit + +@@: + test [ecx+LU_INT_CMD_LOW],DELIVERY_PENDING + jnz @b + + ; + ; Write the KEYBOARD IPI Command to the Memory Mapped Register + ; + + mov [ecx+LU_INT_CMD_LOW], IPI_KBD_ALL + + SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi + +stdENDP EisaKbdService + +;++ +; +; VOID +; EisaFloppyService( +; ); +; +;Routine Description: +; +; This handler receives interrupts from the EISA PIC and reissues them via +; a vector at the proper priority level. This is needed on the WinServer +; 3000 because we use the PIC interrupts as EXTINT for the 8254 Clock, +; Keyboard, Floppy, RTC, Mouse, DMA, and IDE. Since EXTINT interrupts are +; received outside of the APIC priority structure we use the APIC ICR +; to generate interrupts to the proper handler at the proper priority. +; +; The EXTINT interrupts are programmed via the CCS APIC IO Unit's +; redirection table. They are directed to Processor zero only. +; +;-- + +IPI_FLOPPY_ALL equ (DELIVER_LOW_PRIORITY OR LOGICAL_DESTINATION OR ICR_ALL_INCL_SELF OR APIC_FLOPPY_VECTOR) + + ENTER_DR_ASSIST H97_a, H97_t + +cPublicProc EisaFloppyService ,0 + + ; + ; Save machine state in trap frame + ; + + ENTER_INTERRUPT H97_a, H97_t ; (esp) - base of trap frame + + mov al, OCW2_SPECIFIC_EOI OR (EISA_FLOPPY_VECTOR - PIC0_BASE_VECTOR) + ; specific eoi + out PIC1_PORT0, al ; dismiss the interrupt + ; + ; Make sure the ICR is available + ; + + mov ecx, _HalpLocalUnitBase ; load base address of CCS + ; local unit + +@@: + test [ecx+LU_INT_CMD_LOW],DELIVERY_PENDING + jnz @b + + ; + ; Write the FLOPPY IPI Command to the Memory Mapped Register + ; + + mov [ecx+LU_INT_CMD_LOW], IPI_FLOPPY_ALL + + SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi + +stdENDP EisaFloppyService + +;++ +; +; VOID +; EisaRTCService( +; ); +; +;Routine Description: +; +; This handler receives interrupts from the EISA PIC and reissues them via +; a vector at the proper priority level. This is needed on the WinServer +; 3000 because we use the PIC interrupts as EXTINT for the 8254 Clock, +; Keyboard, Floppy, RTC, Mouse, DMA, and IDE. Since EXTINT interrupts are +; received outside of the APIC priority structure we use the APIC ICR +; to generate interrupts to the proper handler at the proper priority. +; +; The EXTINT interrupts are programmed via the CCS APIC IO Unit's +; redirection table. They are directed to Processor zero only. +; +;-- + +IPI_RTC_ALL equ (DELIVER_LOW_PRIORITY OR LOGICAL_DESTINATION OR ICR_ALL_INCL_SELF OR APIC_RTC_VECTOR) + + ENTER_DR_ASSIST H96_a, H96_t + +cPublicProc EisaRTCService ,0 + + ; + ; Save machine state in trap frame + ; + + ENTER_INTERRUPT H96_a, H96_t ; (esp) - base of trap frame + + mov al, OCW2_NON_SPECIFIC_EOI ; send non specific eoi to slave + out PIC2_PORT0, al + mov al, OCW2_SPECIFIC_EOI OR (EISA_IRQ2_VECTOR - PIC0_BASE_VECTOR) + ; specific eoi to master for pic2 eoi + out PIC1_PORT0, al ; send irq2 specific eoi to master + ; + ; Make sure the ICR is available + ; + + mov ecx, _HalpLocalUnitBase ; load base address of CCS + ; local unit + +@@: + test [ecx+LU_INT_CMD_LOW],DELIVERY_PENDING + jnz @b + + ; + ; Write the RTC IPI Command to the Memory Mapped Register + ; + + mov [ecx+LU_INT_CMD_LOW], IPI_RTC_ALL + + SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi + +stdENDP EisaRTCService + +;++ +; +; VOID +; EisaDmaService( +; ); +; +;Routine Description: +; +; This handler receives interrupts from the EISA PIC and reissues them via +; a vector at the proper priority level. This is needed on the WinServer +; 3000 because we use the PIC interrupts as EXTINT for the 8254 Clock, +; Keyboard, Floppy, RTC, Mouse, DMA, and IDE. Since EXTINT interrupts are +; received outside of the APIC priority structure we use the APIC ICR +; to generate interrupts to the proper handler at the proper priority. +; +; The EXTINT interrupts are programmed via the CCS APIC IO Unit's +; redirection table. They are directed to Processor zero only. +; +;-- + +IPI_DMA_ALL equ (DELIVER_LOW_PRIORITY OR LOGICAL_DESTINATION OR ICR_ALL_INCL_SELF OR APIC_DMA_VECTOR) + + ENTER_DR_ASSIST H95_a, H95_t + +cPublicProc EisaDmaService ,0 + + ; + ; Save machine state in trap frame + ; + + ENTER_INTERRUPT H95_a, H95_t ; (esp) - base of trap frame + + mov al, OCW2_NON_SPECIFIC_EOI ; send non specific eoi to slave + out PIC2_PORT0, al + mov al, OCW2_SPECIFIC_EOI OR (EISA_IRQ2_VECTOR - PIC0_BASE_VECTOR) + ; specific eoi to master for pic2 eoi + out PIC1_PORT0, al ; send irq2 specific eoi to master + ; + ; Make sure the ICR is available + ; + + mov ecx, _HalpLocalUnitBase ; load base address of CCS + ; local unit + +@@: + test [ecx+LU_INT_CMD_LOW],DELIVERY_PENDING + jnz @b + + ; + ; Write the DMA IPI Command to the Memory Mapped Register + ; + + mov [ecx+LU_INT_CMD_LOW], IPI_DMA_ALL + + SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi + +stdENDP EisaDmaService + +;++ +; +; VOID +; EisaMouseService( +; ); +; +;Routine Description: +; +; This handler receives interrupts from the EISA PIC and reissues them via +; a vector at the proper priority level. This is needed on the WinServer +; 3000 because we use the PIC interrupts as EXTINT for the 8254 Clock, +; Keyboard, Floppy, RTC, DMA, Mouse, and IDE. Since EXTINT interrupts are +; received outside of the APIC priority structure we use the APIC ICR +; to generate interrupts to the proper handler at the proper priority. +; +; The EXTINT interrupts are programmed via the CCS APIC IO Unit's +; redirection table. They are directed to Processor zero only. +; +;-- + +IPI_MOUSE_ALL equ (DELIVER_LOW_PRIORITY OR LOGICAL_DESTINATION OR ICR_ALL_INCL_SELF OR APIC_MOUSE_VECTOR) + + ENTER_DR_ASSIST H94_a, H94_t + +cPublicProc EisaMouseService ,0 + + ; + ; Save machine state in trap frame + ; + + ENTER_INTERRUPT H94_a, H94_t ; (esp) - base of trap frame + + mov al, OCW2_NON_SPECIFIC_EOI ; send non specific eoi to slave + out PIC2_PORT0, al + mov al, OCW2_SPECIFIC_EOI OR (EISA_IRQ2_VECTOR - PIC0_BASE_VECTOR) + ; specific eoi to master for pic2 eoi + out PIC1_PORT0, al ; send irq2 specific eoi to master + ; + ; Make sure the ICR is available + ; + + mov ecx, _HalpLocalUnitBase ; load base address of CCS + ; local unit + +@@: + test [ecx+LU_INT_CMD_LOW],DELIVERY_PENDING + jnz @b + + ; + ; Write the MOUSE IPI Command to the Memory Mapped Register + ; + + mov [ecx+LU_INT_CMD_LOW], IPI_MOUSE_ALL + + SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi + +stdENDP EisaMouseService + + +;++ +; +; VOID +; EisaIDEService( +; ); +; +;Routine Description: +; +; This handler receives interrupts from the EISA PIC and reissues them via +; a vector at the proper priority level. This is needed on the WinServer +; 3000 because we use the PIC interrupts as EXTINT for the 8254 Clock, +; Keyboard, Floppy, RTC, Mouse, DMA, and IDE. Since EXTINT interrupts are +; received outside of the APIC priority structure we use the APIC ICR +; to generate interrupts to the proper handler at the proper priority. +; +; The EXTINT interrupts are programmed via the CCS APIC IO Unit's +; redirection table. They are directed to Processor zero only. +; +;-- + + ENTER_DR_ASSIST H93_a, H93_t + +cPublicProc EisaIDEService ,0 + + ; + ; Save machine state in trap frame + ; + + ENTER_INTERRUPT H93_a, H93_t ; (esp) - base of trap frame + + mov ebx, (DELIVER_LOW_PRIORITY OR LOGICAL_DESTINATION OR ICR_ALL_INCL_SELF OR APIC_IDE_VECTOR) + test _HalpELCRImage, (1 SHL (EISA_IDE_VECTOR - PIC0_BASE_VECTOR)) + jz short @f + + ; If a level PIC interrupt, mask the interrupt at the PIC until + ; the APIC interrupt HalEndSystemInterrupt unmasks it. + ; We also only send it to ourselves since it needs to mess with the + ; pic in the end of interrupt code. + + +lock or _HalpMASKED, (1 SHL (EISA_IDE_VECTOR - PIC0_BASE_VECTOR)) + in al, PIC2_PORT1 + or al, (1 SHL (EISA_IDE_VECTOR - PIC1_BASE_VECTOR)) + out PIC2_PORT1, al + mov ebx, (DELIVER_LOW_PRIORITY OR LOGICAL_DESTINATION OR ICR_SELF OR APIC_IDE_VECTOR) + +@@: + mov al, OCW2_NON_SPECIFIC_EOI ; send non specific eoi to slave + out PIC2_PORT0, al + mov al, OCW2_SPECIFIC_EOI OR (EISA_IRQ2_VECTOR - PIC0_BASE_VECTOR) + ; specific eoi to master for pic2 eoi + out PIC1_PORT0, al ; send irq2 specific eoi to master + ; + ; Make sure the ICR is available + ; + + mov ecx, _HalpLocalUnitBase ; load base address of CCS + ; local unit +@@: test [ecx+LU_INT_CMD_LOW],DELIVERY_PENDING + jnz @b + + ; + ; Write the IDE IPI Command to the Memory Mapped Register + ; + + mov [ecx+LU_INT_CMD_LOW], ebx + + SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi + +stdENDP EisaIDEService + +;++ +; +; VOID +; HalRequestIpi( +; IN KAFFINITY Mask +; ); +; +;Routine Description: +; +; Requests an interprocessor interrupt +; +;Arguments: +; +; Mask - Supplies a mask of the processors to be interrupted +; +;Return Value: +; +; None. +; +;-- +APIC_IPI equ (DELIVER_FIXED OR LOGICAL_DESTINATION OR ICR_USE_DEST_FIELD OR APIC_IPI_VECTOR) + +cPublicProc _HalRequestIpi ,1 +cPublicFpo 1, 0 + + mov eax, dword ptr [esp+4] ; (eax) = Processor bitmask + mov ecx, _HalpLocalUnitBase ; load base address of local unit + + DISABLE_INTERRUPTS_AT_CPU + +if DBG + or eax, eax ; must ipi somebody + jz short ipibad + movzx edx, byte ptr PCR[PcHal.PcrNumber] ; Get Processor Number + bt eax, edx ; cannot ipi yourself + jc short ipibad +endif + + ; + ; With an APIC we'll IPI everyone needed at the same time. + ; This assumes that: + ; (mask passed in) == (APIC logical destination mask) Since we've programmed + ; the APIC Local Units to use the Processor ID as the APIC ID this IS true + ; + ; + ; Make sure the ICR is available + ; + +@@: + test [ecx+LU_INT_CMD_LOW],DELIVERY_PENDING + jnz @b + + ; + ; Set the destination address, (eax) = Processor bitmask + ; + + mov [ecx+LU_INT_CMD_HIGH], eax + + ; + ; Now issue the command by writing to the Memory Mapped Register + ; + + mov [ecx+LU_INT_CMD_LOW], APIC_IPI + + RESTORE_INTERRUPTS_AT_CPU + + stdRET _HalRequestIpi + +if DBG +ipibad: + RESTORE_INTERRUPTS_AT_CPU + stdCall _DbgBreakPoint + stdRET _HalRequestIpi +endif + +stdENDP _HalRequestIpi + +;++ +; +; VOID +; HalIntProcessorAPIC( +; IN ULONG Mask, +; IN ULONG ICRCommand +; ); +; +;Routine Description: +; +; Requests an interprocessor interrupt +; +;Arguments: +; +; Mask - Supplies a mask of the processors to be interrupted +; +; ICRCommand - ICR Command to use +; +;Return Value: +; +; None. +; +;-- +cPublicProc _HalIntProcessorAPIC ,2 + + mov edx, dword ptr [esp+4] ; (edx) = Processor bitmask + mov eax, dword ptr [esp+8] ; (eax) = ICR Command + + mov ecx, _HalpLocalUnitBase ; load base address of local unit + + ; + ; Make sure the ICR is available + ; + + pushfd ; save interrupt mode + cli ; disable interrupt + +@@: + test [ecx+LU_INT_CMD_LOW],DELIVERY_PENDING + jnz @b + + ; (edx) = Processor bitmask + ; (eax) = ICR Command + + mov [ecx+LU_INT_CMD_HIGH], edx + + ; + ; Now issue the command by writing the ICR Command to the Memory Mapped Register + ; + + mov [ecx+LU_INT_CMD_LOW], eax + + popfd + + stdRET _HalIntProcessorAPIC + +stdENDP _HalIntProcessorAPIC + + + page ,132 + subttl "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> + +; Pass Null ExceptionFrame +; Pass TrapFrame to Ipi service rtn +; + stdCall _KiIpiServiceRoutine, <ebp,0> + +; +; Do interrupt exit processing +; + + INTERRUPT_EXIT ; will return to caller + +stdENDP _HalpIpiHandler + +_TEXT ENDS + + END |