diff options
Diffstat (limited to 'private/ntos/nthals/halws3/i386')
46 files changed, 9288 insertions, 0 deletions
diff --git a/private/ntos/nthals/halws3/i386/apic.inc b/private/ntos/nthals/halws3/i386/apic.inc new file mode 100644 index 000000000..133cb8e8f --- /dev/null +++ b/private/ntos/nthals/halws3/i386/apic.inc @@ -0,0 +1,556 @@ +;/* +;++ +; +; 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: +; +; apic.inc +; +; Abstract: +; +; This module contains the definitions used by HAL to manipulate +; APIC interrupt controller and APIC-specific constants. +; +; WARNING: This file is included by both ASM and C files. +; +; Author: +; +; Hugh Bynum and Ron Mosgrove Aug-1992 +; +;-- +if 0 ; Begin C only code */ + +// +// APIC defines for C code +// BE SURE TO CHANGE THESE VALUES IN BOTH TABLES! +// + +#define IO_BASE_ADDRESS 0xFEC00000 // Physical address +#define IO_REGISTER_SELECT 0x00000000 // offset from IO_BASE_ADDRESS +#define IO_REGISTER_WINDOW 0x00000010 // offset from IO_BASE_ADDRESS + +#define IO_UNIT_0 0x00000000 // adder for IO unit 0 +#define IO_UNIT_1 0x00001000 // adder for IO unit 1 +#define IO_UNIT_2 0x00002000 // adder for IO unit 2 +#define IO_UNIT_3 0x00003000 // adder for IO unit 3 + +#define IO_ID_REGISTER 0x00000000 +#define IO_VERS_REGISTER 0x00000001 +#define IO_ARB_ID_REGISTER 0x00000002 +#define IO_REDIR_00_LOW 0x00000010 +#define IO_REDIR_00_HIGH 0x00000011 + +#define IO_MAX_REDIR_MASK 0x00FF0000 +#define IO_VERSION_MASK 0x000000FF + +#define LU_BASE_ADDRESS 0xFEE00000 // Physical address +#define LU_ID_REGISTER 0x00000020 // offset from LU_BASE_ADDRESS +#define LU_VERS_REGISTER 0x00000030 // offset from LU_BASE_ADDRESS +#define LU_TPR 0x00000080 // offset from LU_BASE_ADDRESS +#define LU_APR 0x00000090 // offset from LU_BASE_ADDRESS +#define LU_PPR 0x000000A0 // offset from LU_BASE_ADDRESS +#define LU_EOI 0x000000B0 // offset from LU_BASE_ADDRESS +#define LU_REMOTE_REGISTER 0x000000C0 // offset from LU_BASE_ADDRESS + +#define LU_LOGICAL_DEST 0x000000D0 // offset from LU_BASE_ADDRESS +#define LU_LOGICAL_DEST_MASK 0xFF000000 + +#define LU_DEST_FORMAT 0x000000E0 // offset from LU_BASE_ADDRESS +#define LU_DEST_FORMAT_MASK 0xF0000000 +#define LU_DEST_FORMAT_FLAT 0xFFFFFFFF + +#define LU_SPURIOUS_VECTOR 0x000000F0 // offset from LU_BASE_ADDRESS +#define LU_UNIT_ENABLED 0x00000100 + +#define LU_ISR_0 0x00000100 // offset from LU_BASE_ADDRESS +#define LU_TMR_0 0x00000180 // offset from LU_BASE_ADDRESS +#define LU_IRR_0 0x00000200 // offset from LU_BASE_ADDRESS +#define LU_ERROR_STATUS 0x00000280 // offset from LU_BASE_ADDRESS +#define LU_INT_CMD_LOW 0x00000300 // offset from LU_BASE_ADDRESS +#define LU_INT_CMD_HIGH 0x00000310 // offset from LU_BASE_ADDRESS +#define LU_TIMER_VECTOR 0x00000320 // offset from LU_BASE_ADDRESS +#define LU_INT_VECTOR_0 0x00000350 // TEMPORARY - do not use +#define LU_INT_VECTOR_1 0x00000360 // TEMPORARY - do not use +#define LU_INITIAL_COUNT 0x00000380 // offset from LU_BASE_ADDRESS +#define LU_CURRENT_COUNT 0x00000390 // offset from LU_BASE_ADDRESS +#define LU_DIVIDER_CONFIG 0x000003E0 // offset from LU_BASE_ADDRESS + +#define APIC_ID_MASK 0x0F000000 +#define APIC_ID_SHIFT 24 + +#define INT_VECTOR_MASK 0x000000FF +#define RESERVED_HIGH_INT 0x000000F8 +#define DELIVERY_MODE_MASK 0x00000700 +#define DELIVER_FIXED 0x00000000 +#define DELIVER_LOW_PRIORITY 0x00000100 +#define DELIVER_SMI 0x00000200 +#define DELIVER_REMOTE_READ 0x00000300 +#define DELIVER_NMI 0x00000400 +#define DELIVER_INIT 0x00000500 +#define DELIVER_EXTINT 0x00000700 +#define LOGICAL_DESTINATION 0x00000800 +#define DELIVERY_PENDING 0x00001000 +#define ACTIVE_LOW 0x00002000 +#define REMOTE_IRR 0x00004000 +#define LEVEL_TRIGGERED 0x00008000 +#define INTERRUPT_MASKED 0x00010000 +#define PERIODIC_TIMER 0x00020000 + +#define ICR_LEVEL_ASSERTED 0x00004000 +#define ICR_RR_STATUS_MASK 0x00030000 +#define ICR_RR_INVALID 0x00000000 +#define ICR_RR_IN_PROGRESS 0x00010000 +#define ICR_RR_VALID 0x00020000 +#define ICR_SHORTHAND_MASK 0x000C0000 +#define ICR_USE_DEST_FIELD 0x00000000 +#define ICR_SELF 0x00040000 +#define ICR_ALL_INCL_SELF 0x00080000 +#define ICR_ALL_EXCL_SELF 0x000C0000 + +#define DESTINATION_MASK 0xFF000000 +#define DESTINATION_SHIFT 24 + +/* +endif + +; APIC defines for assembly code +; BE SURE TO CHANGE THESE VALUES IN BOTH TABLES! +; + +IO_BASE_ADDRESS equ 0FEC00000H ; Physical address +IO_REGISTER_SELECT equ 00000000H ; offset from IO_BASE_ADDRESS +IO_REGISTER_WINDOW equ 00000010H ; offset from IO_BASE_ADDRESS + +IO_UNIT_0 equ 00000000H ; adder for IO unit 0 +IO_UNIT_1 equ 00001000H ; adder for IO unit 1 +IO_UNIT_2 equ 00002000H ; adder for IO unit 2 +IO_UNIT_3 equ 00003000H ; adder for IO unit 3 + +IO_ID_REGISTER equ 00000000H ; +IO_VERS_REGISTER equ 00000001H ; +IO_ARB_ID_REGISTER equ 00000002H ; +IO_REDIR_00_LOW equ 00000010H ; +IO_REDIR_00_HIGH equ 00000011H ; + +IO_MAX_REDIR_MASK equ 00FF0000H ; +IO_VERSION_MASK equ 000000FFH ; + +LU_BASE_ADDRESS equ 0FEE00000H ; +LU_ID_REGISTER equ 00000020H ; offset from LU_BASE_ADDRESS +LU_VERS_REGISTER equ 00000030H ; offset from LU_BASE_ADDRESS +LU_TPR equ 00000080H ; offset from LU_BASE_ADDRESS +LU_APR equ 00000090H ; offset from LU_BASE_ADDRESS +LU_PPR equ 000000A0H ; offset from LU_BASE_ADDRESS +LU_EOI equ 000000B0H ; offset from LU_BASE_ADDRESS +LU_REMOTE_REGISTER equ 000000C0H ; offset from LU_BASE_ADDRESS + +LU_LOGICAL_DEST equ 000000D0H ; offset from LU_BASE_ADDRESS +LU_LOGICAL_DEST_MASK equ 0FF000000H ; + +LU_DEST_FORMAT equ 000000E0H ; offset from LU_BASE_ADDRESS +LU_DEST_FORMAT_MASK equ 0F0000000H ; +LU_DEST_FORMAT_FLAT equ 0FFFFFFFFH ; + +LU_SPURIOUS_VECTOR equ 000000F0H ; offset from LU_BASE_ADDRESS +LU_UNIT_ENABLED equ 00000100H ; + +LU_ISR_0 equ 00000100H ; offset from LU_BASE_ADDRESS +LU_TMR_0 equ 00000180H ; offset from LU_BASE_ADDRESS +LU_IRR_0 equ 00000200H ; offset from LU_BASE_ADDRESS +LU_ERROR_STATUS equ 00000280H ; offset from LU_BASE_ADDRESS +LU_INT_CMD_LOW equ 00000300H ; offset from LU_BASE_ADDRESS +LU_INT_CMD_HIGH equ 00000310H ; offset from LU_BASE_ADDRESS +LU_TIMER_VECTOR equ 00000320H ; offset from LU_BASE_ADDRESS +LU_INT_VECTOR_0 equ 00000350H ; TEMPORARY - do not use +LU_INT_VECTOR_1 equ 00000360H ; TEMPORARY - do not use +LU_INITIAL_COUNT equ 00000380H ; offset from LU_BASE_ADDRESS +LU_CURRENT_COUNT equ 00000390H ; offset from LU_BASE_ADDRESS + +LU_DIVIDER_CONFIG equ 000003E0H ; offset from LU_BASE_ADDRESS +LU_DIVIDE_BY_1 equ 0000000BH ; +LU_DIVIDE_BY_2 equ 00000000H ; +LU_DIVIDE_BY_4 equ 00000001H ; +LU_DIVIDE_BY_8 equ 00000002H ; +LU_DIVIDE_BY_16 equ 00000003H ; +LU_DIVIDE_BY_32 equ 00000008H ; +LU_DIVIDE_BY_64 equ 00000009H ; +LU_DIVIDE_BY_128 equ 0000000AH ; + +APIC_ID_MASK equ 0F000000H ; +APIC_ID_SHIFT equ 24 ; + +INT_VECTOR_MASK equ 000000FFH ; +RESERVED_HIGH_INT equ 000000F8H ; +DELIVERY_MODE_MASK equ 00000700H ; +DELIVER_FIXED equ 00000000H ; +DELIVER_LOW_PRIORITY equ 00000100H ; +DELIVER_SMI equ 00000200H ; +DELIVER_REMOTE_READ equ 00000300H ; +DELIVER_NMI equ 00000400H ; +DELIVER_INIT equ 00000500H ; +DELIVER_EXTINT equ 00000700H ; +PHYSICAL_DESTINATION equ 00000000H ; +LOGICAL_DESTINATION equ 00000800H ; +DELIVERY_PENDING equ 00001000H ; +ACTIVE_LOW equ 00002000H ; +REMOTE_IRR equ 00004000H ; +LEVEL_TRIGGERED equ 00008000H ; +INTERRUPT_MASKED equ 00010000H ; +INTERRUPT_MOT_MASKED equ 00000000H ; +PERIODIC_TIMER equ 00020000H ; + +ICR_LEVEL_ASSERTED equ 00004000H ; +ICR_RR_STATUS_MASK equ 00030000H ; +ICR_RR_INVALID equ 00000000H ; +ICR_RR_IN_PROGRESS equ 00010000H ; +ICR_RR_VALID equ 00020000H ; +ICR_SHORTHAND_MASK equ 000C0000H ; +ICR_USE_DEST_FIELD equ 00000000H ; +ICR_SELF equ 00040000H ; +ICR_ALL_INCL_SELF equ 00080000H ; +ICR_ALL_EXCL_SELF equ 000C0000H ; + +DESTINATION_MASK equ 0FF000000H ; +DESTINATION_SHIFT equ 24 ; shift count for dest. mask + +; +; remaining macro definitions for assembler only +; + +;++ +; +; WRITE_IO_APIC +; +; Macro Description: +; +; This macro writes a value to a register in the I/O Apic. +; +; Arguments: +; +; Register - Register to be written +; +; Value - Value to write +; +;-- +WRITE_IO_APIC MACRO Register , Value + +.errb <Register> +.errb <Value> + + ; Need two scratch registers + push eax ; Save registers + push ecx + + push Value ; Save paramters on the stack + push Register + + pop eax ; Get the Register + mov ecx, _HalpIOunitBase + add ecx, IO_REGISTER_SELECT+IO_UNIT_0 ; Register select on I/O Unit + mov dword ptr [ecx], eax ; Program register + + pop eax ; Get the Value + mov ecx, _HalpIOunitBase + add ecx, IO_REGISTER_WINDOW+IO_UNIT_0 ; Register select on I/O Unit + mov dword ptr [ecx], eax ; Program register + + pop ecx ; Restore scratch registers + pop eax + + ; We're Out'a Here + +endm + +;++ +; +; READ_IO_APIC +; +; Macro Description: +; +; This macro reads a 32 bit register from the I/O Apic. +; +; Arguments: +; +; Register - Register to be read +; +; Return +; +; eax - value read from I/O Apic +; +;-- +READ_IO_APIC MACRO Register + +.errb <Register> + +ifndef _HalpIOunitBase + extrn _HalpIOunitBase:DWORD +endif + + push ecx ; Need one scratch register + push Register + + pop eax ; Get the Register + mov ecx, _HalpIOunitBase + add ecx, IO_REGISTER_SELECT+IO_UNIT_0 ; Register select on I/O Unit + mov dword ptr [ecx], eax ; Program register + + mov ecx, _HalpIOunitBase + add ecx, IO_REGISTER_WINDOW+IO_UNIT_0 ; Register Window on I/O Unit + mov eax, dword ptr [ecx] ; Program register + + pop ecx ; Restore scratch register + + ; We're Out'a Here + +endm + +;++ +; +; GetIOApicRedirTable +; +; Macro Description: +; +; This reads a redirection table entry from the I/O APIC (unit 0). +; +; Arguments: +; +; IoApicInputPin - Interrupt Input (INTI) we're interested in +; The Caller MUST have locked access to the IO Apic prior to +; this call. +; +; Return +; +; 64 Bit redirection table entry in eax [31:0] and edx [63:32] +; +;-- +GetIOApicRedirTable MACRO IoApicInputPin + +.errb <IoApicInputPin> + + push IoApicInputPin ; Save paramter on the stack + + pop eax ; INTI we're looking for + and eax, 0fh ; Make sure we're dealing with + ; defined inputs + shl eax, 1 ; <IoApicInputPin> * 2 + add eax, IO_REDIR_00_LOW+IO_UNIT_0 ; eax == low(redir) of INTI + + push eax ; Save the register address + inc eax ; Points to high(redir) + + READ_IO_APIC eax ; Read the Upper 32 Bits of the Redir + + mov edx, eax ; Save the High 32 Bits to return + pop eax ; Get the low register address + + READ_IO_APIC eax ; Read the Lower 32 Bits of the Redir + + ; + ; edx == bits 32-63 of RedirectionTable[IoApicInputPin] + ; eax == bits 00-31 of RedirectionTable[IoApicInputPin] + ; + +endm + +;++ +; +; PutIOApicRedirTable +; +; Macro Description: +; +; This writes a redirection table entry to the I/O APIC (unit 0).. +; The Caller MUST have locked access to the IO Apic prior to +; this call. +; +; Arguments: +; +; IoApicInputPin - Interrupt Input (INTI) we're interested in +; +; LowWord - Low 32 Bits of redirection Table entry +; +; HighWord - High 32 Bits of redirection Table entry +; +; +;-- +PutIOApicRedirTable MACRO IoApicInputPin , LowWord , HighWord + +.errb <IoApicInputPin> +.errb <LowWord> +.errb <HighWord> + + push LowWord ; Save paramter on the stack + push HighWord + push IoApicInputPin + + pop eax ; INTI we're looking for + and eax, 0fh ; Make sure we're dealing with + ; defined inputs + shl eax, 1 ; <IoApicInputPin> * 2 + add eax, IO_REDIR_00_LOW+IO_UNIT_0 ; eax == low(redir) of INTI + + pop edx ; edx <= Bits 31-63 of redir + + push eax ; Save the register address + inc eax ; Points to high(redir) + + WRITE_IO_APIC eax , edx ; Write the Upper 32 Bits of the Redir + + pop eax ; Get the low register address + pop edx ; edx <= Bits 00-31 of redir + + WRITE_IO_APIC eax , edx ; Write the Lower 32 Bits of the Redir + +endm + +;++ +; +; GrabHalIoApicSpinLock +; +; Macro Description: +; +; This macro is used to prevent multiple CPU's from accessing the IO APIC on a MP +; system. It grabs the IoAPIC Spin lock if available, ifnot then it waits until +; it is available. +; +; The compliment of this macro is ReleaseHalIoApicSpinLock. +; +;-- +GrabHalIoApicSpinLock MACRO +local WaitForRelease, StartSpinLockLoop, Gotit + +ifndef _HalpIOunitLock + extrn _HalpIOunitLock:DWORD ; IoUnit SpinLock +endif ; _HalpIOunitLock + +StartSpinLockLoop: + + pushfd ; Save Flags + cli ; Don't Interrupt us here + + lea eax, _HalpIOunitLock ; The SpinLock we're interested in + ACQUIRE_SPINLOCK eax, WaitForRelease ; Try for the lock, if Not successful + ; Go and wait till the owner frees it. + + ; + ; We now own the spinlock + ; + + jmp Gotit + +WaitForRelease: + sti ; Allow other activity while we wait + SPIN_ON_SPINLOCK eax, StartSpinLockLoop ; Stare at it until it's free + + ; + ; We'll Never get here + ; + +Gotit: + + popfd ; restore Original Flags + +endm + +;++ +; +; ReleaseHalIoApicSpinLock +; +; Macro Description: +; +; This macro is used to prevent multiple CPU's from accessing the IO Apic on a MP +; system. It frees the IoApic Spin lock. +; +; The compliment of this macro is GrabHalIoApicSpinLock. +;-- +ReleaseHalIoApicSpinLock MACRO + +ifndef _HalpIOunitLock + extrn _HalpIOunitLock:DWORD ; IoUnit SpinLock +endif ; _HalpIOunitLock + + lea eax, _HalpIOunitLock + RELEASE_SPINLOCK eax + +endm + +;++ +; +; GrabHal8259SpinLock +; +; Macro Description: +; +; This macro is used to prevent multiple CPU's from accessing the IO APIC on a MP +; system. It grabs the 8259 Spin lock if available, ifnot then it waits until +; it is available. +; +; The compliment of this macro is ReleaseHal8259SpinLock. +; +;-- +GrabHal8259SpinLock MACRO +local WaitForRelease, StartSpinLockLoop, Gotit + +ifndef _Halp8259Lock + extrn _Halp8259Lock:DWORD ; 8259 SpinLock +endif ; _Halp8259Lock + +StartSpinLockLoop: + + pushfd ; Save Flags + cli ; Don't Interrupt us here + + lea eax, _Halp8259Lock ; The SpinLock we're interested in + ACQUIRE_SPINLOCK eax, WaitForRelease ; Try for the lock, if Not successful + ; Go and wait till the owner frees it. + + ; + ; We now own the spinlock + ; + + jmp Gotit + +WaitForRelease: + sti ; Allow other activity while we wait + SPIN_ON_SPINLOCK eax, StartSpinLockLoop ; Stare at it until it's free + + ; + ; We'll Never get here + ; + +Gotit: + + popfd ; restore Original Flags + +endm + +;++ +; +; ReleaseHal8259SpinLock +; +; Macro Description: +; +; This macro is used to prevent multiple CPU's from accessing the IO Apic on a MP +; system. It frees the 8259 Spin lock. +; +; The compliment of this macro is GrabHal8259SpinLock. +;-- +ReleaseHal8259SpinLock MACRO + +ifndef _Halp8259Lock + extrn _Halp8259Lock:DWORD ; 8259 SpinLock +endif ; _Halp8259Lock + + lea eax, _Halp8259Lock + RELEASE_SPINLOCK eax + +endm +;*/ diff --git a/private/ntos/nthals/halws3/i386/halp.h b/private/ntos/nthals/halws3/i386/halp.h new file mode 100644 index 000000000..a9dbf1e13 --- /dev/null +++ b/private/ntos/nthals/halws3/i386/halp.h @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\halp.h" diff --git a/private/ntos/nthals/halws3/i386/halver.h b/private/ntos/nthals/halws3/i386/halver.h new file mode 100644 index 000000000..1c18a5540 --- /dev/null +++ b/private/ntos/nthals/halws3/i386/halver.h @@ -0,0 +1,42 @@ +/*++ + +Module Name: + + halver.h + +Abstract: + + HAL WS3500 version file. + + Update the version number and date in this file before each HAL release. + This file is maintained for the benefit of Microsoft builds of our + HAL source only. Sequent builds use halver.tmp to create halver.h + during the build process. (6/6/94 rlary) + +Author: + + Phil Hochstetler (phil@sequent.com) + +Environment: + + Kernel mode only. + +--*/ + +#if defined(NT_UP) + +#if DBG +UCHAR HalName[] = "Sequent WinServer (TM) 3500 HAL -DNT_UP -DDBG"; +#else +UCHAR HalName[] = "Sequent WinServer (TM) 3500 HAL -DNT_UP"; +#endif + +#else // !defined(NT_UP) + +#if DBG +UCHAR HalName[] = "Sequent WinServer (TM) 3500 HAL -DDBG"; +#else +UCHAR HalName[] = "Sequent WinServer (TM) 3500 HAL"; +#endif + +#endif // defined(NT_UP) diff --git a/private/ntos/nthals/halws3/i386/ix8259.inc b/private/ntos/nthals/halws3/i386/ix8259.inc new file mode 100644 index 000000000..b9e0a196a --- /dev/null +++ b/private/ntos/nthals/halws3/i386/ix8259.inc @@ -0,0 +1,5 @@ +; +; Include code from halx86 +; This is a cpp style symbolic link + +include ..\halx86\i386\ix8259.inc diff --git a/private/ntos/nthals/halws3/i386/ixbeep.asm b/private/ntos/nthals/halws3/i386/ixbeep.asm new file mode 100644 index 000000000..f53bd3e58 --- /dev/null +++ b/private/ntos/nthals/halws3/i386/ixbeep.asm @@ -0,0 +1,5 @@ +; +; Include code from halx86 +; This is a cpp style symbolic link + +include ..\halx86\i386\ixbeep.asm diff --git a/private/ntos/nthals/halws3/i386/ixbusdat.c b/private/ntos/nthals/halws3/i386/ixbusdat.c new file mode 100644 index 000000000..a42039752 --- /dev/null +++ b/private/ntos/nthals/halws3/i386/ixbusdat.c @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\ixbusdat.c" diff --git a/private/ntos/nthals/halws3/i386/ixcmos.asm b/private/ntos/nthals/halws3/i386/ixcmos.asm new file mode 100644 index 000000000..7f4e7393e --- /dev/null +++ b/private/ntos/nthals/halws3/i386/ixcmos.asm @@ -0,0 +1,5 @@ +; +; Include code from halx86 +; This is a cpp style symbolic link + +include ..\halx86\i386\ixcmos.asm diff --git a/private/ntos/nthals/halws3/i386/ixcmos.inc b/private/ntos/nthals/halws3/i386/ixcmos.inc new file mode 100644 index 000000000..2fe289fb0 --- /dev/null +++ b/private/ntos/nthals/halws3/i386/ixcmos.inc @@ -0,0 +1,5 @@ +; +; Include code from halx86 +; This is a cpp style symbolic link + +include ..\halx86\i386\ixcmos.inc diff --git a/private/ntos/nthals/halws3/i386/ixdat.c b/private/ntos/nthals/halws3/i386/ixdat.c new file mode 100644 index 000000000..f6b0e34de --- /dev/null +++ b/private/ntos/nthals/halws3/i386/ixdat.c @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\ixdat.c" diff --git a/private/ntos/nthals/halws3/i386/ixenvirv.c b/private/ntos/nthals/halws3/i386/ixenvirv.c new file mode 100644 index 000000000..e194820ba --- /dev/null +++ b/private/ntos/nthals/halws3/i386/ixenvirv.c @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\ixenvirv.c" diff --git a/private/ntos/nthals/halws3/i386/ixfirm.c b/private/ntos/nthals/halws3/i386/ixfirm.c new file mode 100644 index 000000000..f666e405c --- /dev/null +++ b/private/ntos/nthals/halws3/i386/ixfirm.c @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\ixfirm.c" diff --git a/private/ntos/nthals/halws3/i386/ixhwsup.c b/private/ntos/nthals/halws3/i386/ixhwsup.c new file mode 100644 index 000000000..ea91dc8d0 --- /dev/null +++ b/private/ntos/nthals/halws3/i386/ixhwsup.c @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\ixhwsup.c" diff --git a/private/ntos/nthals/halws3/i386/ixidle.asm b/private/ntos/nthals/halws3/i386/ixidle.asm new file mode 100644 index 000000000..9bdd670f3 --- /dev/null +++ b/private/ntos/nthals/halws3/i386/ixidle.asm @@ -0,0 +1,5 @@ +; +; Include code from halx86 +; This is a cpp style symbolic link + +include ..\halx86\i386\ixidle.asm diff --git a/private/ntos/nthals/halws3/i386/ixinfo.c b/private/ntos/nthals/halws3/i386/ixinfo.c new file mode 100644 index 000000000..7f211f7a9 --- /dev/null +++ b/private/ntos/nthals/halws3/i386/ixinfo.c @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\ixinfo.c" diff --git a/private/ntos/nthals/halws3/i386/ixisabus.c b/private/ntos/nthals/halws3/i386/ixisabus.c new file mode 100644 index 000000000..c1edfb067 --- /dev/null +++ b/private/ntos/nthals/halws3/i386/ixisabus.c @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\ixisabus.c" diff --git a/private/ntos/nthals/halws3/i386/ixisasup.c b/private/ntos/nthals/halws3/i386/ixisasup.c new file mode 100644 index 000000000..58c426544 --- /dev/null +++ b/private/ntos/nthals/halws3/i386/ixisasup.c @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\ixisasup.c" diff --git a/private/ntos/nthals/halws3/i386/ixkdcom.c b/private/ntos/nthals/halws3/i386/ixkdcom.c new file mode 100644 index 000000000..29bb8308e --- /dev/null +++ b/private/ntos/nthals/halws3/i386/ixkdcom.c @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\ixkdcom.c" diff --git a/private/ntos/nthals/halws3/i386/ixphwsup.c b/private/ntos/nthals/halws3/i386/ixphwsup.c new file mode 100644 index 000000000..a1cdab598 --- /dev/null +++ b/private/ntos/nthals/halws3/i386/ixphwsup.c @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\ixphwsup.c" diff --git a/private/ntos/nthals/halws3/i386/ixreboot.c b/private/ntos/nthals/halws3/i386/ixreboot.c new file mode 100644 index 000000000..15d7bd898 --- /dev/null +++ b/private/ntos/nthals/halws3/i386/ixreboot.c @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\ixreboot.c" diff --git a/private/ntos/nthals/halws3/i386/ixthunk.c b/private/ntos/nthals/halws3/i386/ixthunk.c new file mode 100644 index 000000000..6f15aad73 --- /dev/null +++ b/private/ntos/nthals/halws3/i386/ixthunk.c @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\ixthunk.c" diff --git a/private/ntos/nthals/halws3/i386/ixusage.c b/private/ntos/nthals/halws3/i386/ixusage.c new file mode 100644 index 000000000..519ec31f3 --- /dev/null +++ b/private/ntos/nthals/halws3/i386/ixusage.c @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\ixusage.c" diff --git a/private/ntos/nthals/halws3/i386/w3.inc b/private/ntos/nthals/halws3/i386/w3.inc new file mode 100644 index 000000000..5eb27638d --- /dev/null +++ b/private/ntos/nthals/halws3/i386/w3.inc @@ -0,0 +1,341 @@ +;/* +;++ +; +;Copyright (c) 1992 Sequent Computer Systems, Inc. +; +;Module Name: +; +; w3hal.h +; +;Abstract: +; +; This header file contains definitions for the WinServer 3000. +; +;Author: +; +; Phil Hochstetler (phil@sequent.com) +; +;Environment: +; +; Kernel mode only. +; +;Revision History: +; +;-- +if 0 ; Begin C only code */ + +// +// Interrupt vector definitions for C +// + +#define APIC_APC_VECTOR 0x30 +#define APIC_DPC_VECTOR 0x40 + +#define APIC_IRQ16_VECTOR 0x60 +#define APIC_IRQ17_VECTOR 0x61 +#define APIC_IRQ18_VECTOR 0x62 +#define APIC_IRQ19_VECTOR 0x63 +#define APIC_IRQ20_VECTOR 0x64 +#define APIC_IRQ21_VECTOR 0x65 +#define APIC_IRQ22_VECTOR 0x66 +#define APIC_IRQ23_VECTOR 0x67 + +#define APIC_IRQ8_VECTOR 0x70 +#define APIC_IRQ9_VECTOR 0x71 +#define APIC_IRQ10_VECTOR 0x72 +#define APIC_IRQ11_VECTOR 0x73 +#define APIC_IRQ12_VECTOR 0x74 +#define APIC_IRQ13_VECTOR 0x75 +#define APIC_IRQ14_VECTOR 0x76 +#define APIC_IRQ15_VECTOR 0x77 + +#define APIC_IRQ0_VECTOR 0x80 +#define APIC_IRQ1_VECTOR 0x81 +#define APIC_IRQ2_VECTOR 0x82 +#define APIC_IRQ3_VECTOR 0x83 +#define APIC_IRQ4_VECTOR 0x84 +#define APIC_IRQ5_VECTOR 0x85 +#define APIC_IRQ6_VECTOR 0x86 +#define APIC_IRQ7_VECTOR 0x87 + +#define APIC_RTC_VECTOR 0x70 +#define APIC_MOUSE_VECTOR 0x74 +#define APIC_DMA_VECTOR 0x75 +#define APIC_IDE_VECTOR 0x76 +#define APIC_KBD_VECTOR 0x81 +#define APIC_FLOPPY_VECTOR 0x86 + +#define APIC_PROFILE_VECTOR 0x90 +#define APIC_CLOCK_VECTOR 0xA0 +#define APIC_IPI_VECTOR 0xB0 +#define APIC_POWERFAIL_VECTOR 0xC0 +#define EISA_CLOCK_VECTOR 0xD0 +#define EISA_KBD_VECTOR 0xD1 +#define EISA_IRQ2_VECTOR 0xD2 +#define EISA_FLOPPY_VECTOR 0xD6 +#define EISA_PIC1_SPURIOUS_VECTOR 0xD7 +#define EISA_RTC_VECTOR 0xD8 +#define EISA_MOUSE_VECTOR 0xDC +#define EISA_DMA_VECTOR 0xDD +#define EISA_IDE_VECTOR 0xDE +#define EISA_PIC2_SPURIOUS_VECTOR 0xDF +#define APIC_SPURIOUS_VECTOR 0xE0 +#define APIC_SYSINT_VECTOR 0xE1 +#define APIC_HIGH_VECTOR 0xF0 +#define APIC_STALL_VECTOR 0xF8 + + +#define PIC0_BASE_VECTOR EISA_CLOCK_VECTOR +#define PIC1_BASE_VECTOR EISA_RTC_VECTOR + +#define EISA_SHIFT 12 // EISA slot starts at this offset +#define EISA_MASK 0xfff // Low bits of EISA slot address +#define POSTREGISTERPORT 0x80 // BIOS post register +#define OCW2_SPECIFIC_EOI 0x60 +#define OCW2_NON_SPECIFIC_EOI 0x20 +#define PIC1_PORT0 0x20 +#define PIC1_PORT1 0x21 +#define PIC2_PORT0 0xA0 +#define PIC2_PORT1 0xA1 +#define PIC3_PORT0 0xCC0 +#define PIC3_PORT1 0xCC1 +#define EISA_2_MPIC_POLARITY_REG 0x0C0E +#define ELCR_MASK 0xDEF8 +#define PIC1_ELCR_PORT 0x04D0 +#define PIC2_ELCR_PORT 0x04D1 +#define DESTINATION_ALL_CPUS 0xff +#define DESTINATION_CPU_0 0x01 +#define FCR 0x0C84 +#define WarmResetVector 0x467 +#define FCR_RESET_MASK 0x0080 +#define IOMPIC_RT_MASK 0x10000 +#define FIRST_SYSTEM_SLOT 9 +#define LAST_SYSTEM_SLOT 15 +#define SLOT_ID_REG 0x0C80 +#define SLOT_ID_BOARDTYPE 0x00F00000 +#define SLOT_ID_TYPECPU 0x00100000 +#define IOUNIT_APIC_ID 7 +#define IOUNIT2_APIC_ID 8 +#define D_INT032 8E00h +#define PeriodInUsec 200 + + + +#define IRQL_APIC_KBD 25 +#define IRQL_APIC_FLOPPY 21 +#define IRQL_APIC_RTC 19 +#define IRQL_APIC_DMA 14 +#define IRQL_APIC_IDE 13 +#define IRQL_APIC_MOUSE 15 + +// +// Hal private data structures (max 64 bytes in length) +// + +typedef struct _WS3_HAL_PRIVATE { + UCHAR PcrNumber; // Logical Processor Number + UCHAR ProcLightState; // State of Processor light (1=on,0=off) + UCHAR ProcIrql; // Current IRQL + UCHAR ProcPad1; // Reserved (for padding) + USHORT ProcSlotAddr; // (slot << EISA_SHIFT) + USHORT ProcPad2; // Reserved (for padding) +} WS3_HAL_PRIVATE, *PWS3_HAL_PRIVATE; + +/* +endif + +; Start of Assembly only code + +; +; Interrupt vector definitions for ASM +; + +APIC_APC_VECTOR equ 030h +APIC_DPC_VECTOR equ 040h + +APIC_IRQ16_VECTOR equ 060h +APIC_IRQ17_VECTOR equ 061h +APIC_IRQ18_VECTOR equ 062h +APIC_IRQ19_VECTOR equ 063h +APIC_IRQ20_VECTOR equ 064h +APIC_IRQ21_VECTOR equ 065h +APIC_IRQ22_VECTOR equ 066h +APIC_IRQ23_VECTOR equ 067h + +APIC_IRQ8_VECTOR equ 070h +APIC_IRQ9_VECTOR equ 071h +APIC_IRQ10_VECTOR equ 072h +APIC_IRQ11_VECTOR equ 073h +APIC_IRQ12_VECTOR equ 074h +APIC_IRQ13_VECTOR equ 075h +APIC_IRQ14_VECTOR equ 076h +APIC_IRQ15_VECTOR equ 077h + +APIC_IRQ0_VECTOR equ 080h +APIC_IRQ1_VECTOR equ 081h +APIC_IRQ2_VECTOR equ 082h +APIC_IRQ3_VECTOR equ 083h +APIC_IRQ4_VECTOR equ 084h +APIC_IRQ5_VECTOR equ 085h +APIC_IRQ6_VECTOR equ 086h +APIC_IRQ7_VECTOR equ 087h + +APIC_RTC_VECTOR equ 070h +APIC_MOUSE_VECTOR equ 074h +APIC_DMA_VECTOR equ 075h +APIC_IDE_VECTOR equ 076h +APIC_KBD_VECTOR equ 081h +APIC_FLOPPY_VECTOR equ 086h + +APIC_PROFILE_VECTOR equ 090h +APIC_CLOCK_VECTOR equ 0A0h +APIC_IPI_VECTOR equ 0B0h +APIC_POWERFAIL_VECTOR equ 0C0h +EISA_CLOCK_VECTOR equ 0D0h +EISA_KBD_VECTOR equ 0D1h +EISA_IRQ2_VECTOR equ 0D2h +EISA_FLOPPY_VECTOR equ 0D6h +EISA_PIC1_SPURIOUS_VECTOR equ 0D7h +EISA_RTC_VECTOR equ 0D8h +EISA_MOUSE_VECTOR equ 0DCh +EISA_DMA_VECTOR equ 0DDh +EISA_IDE_VECTOR equ 0DEh +EISA_PIC2_SPURIOUS_VECTOR equ 0DFh +APIC_SPURIOUS_VECTOR equ 0E0h +APIC_SYSINT_VECTOR equ 0E1h +APIC_HIGH_VECTOR equ 0F0h +APIC_STALL_VECTOR equ 0F8h + +PIC0_BASE_VECTOR equ EISA_CLOCK_VECTOR +PIC1_BASE_VECTOR equ EISA_RTC_VECTOR + + +EISA_SHIFT equ 12 ; EISA slot starts at this offset +EISA_MASK equ 0fffh ; Low bits of EISA slot address +PostRegisterPort equ 080h ; BIOS post register +OCW2_SPECIFIC_EOI equ 060h +OCW2_NON_SPECIFIC_EOI equ 020h +PIC1_PORT0 equ 020h +PIC1_PORT1 equ 021h +PIC2_PORT0 equ 0A0h +PIC2_PORT1 equ 0A1h +PIC3_PORT0 equ 0CC0h +PIC3_PORT1 equ 0CC1h +EISA_2_MPIC_POLARITY_REG equ 0C0Eh +ELCR_MASK equ 0DEF8h +PIC1_ELCR_PORT equ 04D0h +PIC2_ELCR_PORT equ 04D1h +DESTINATION_ALL_CPUS equ 0ffh +DESTINATION_CPU_0 equ 1 +FCR equ 0C84h +WarmResetVector equ 0467h +FCR_RESET_MASK equ 0080h +IOMPIC_RT_MASK equ 10000h +FIRST_SYSTEM_SLOT equ 9 +LAST_SYSTEM_SLOT equ 15 +SLOT_ID_REG equ 0C80h +SLOT_ID_BOARDTYPE equ 00F00000h +SLOT_ID_TYPECPU equ 00100000h +IOUNIT_APIC_ID equ 7 +IOUNIT2_APIC_ID equ 8 +D_INT032 equ 8E00h ; access word for 386 ring 0 interrupt gate +PeriodInUsec equ 200 + + +IRQL_APIC_KBD equ 25 +IRQL_APIC_FLOPPY equ 21 +IRQL_APIC_RTC equ 19 +IRQL_APIC_DMA equ 14 +IRQL_APIC_IDE equ 13 +IRQL_APIC_MOUSE equ 15 + +; +; The kernel leaves some space (64 bytes) of the PCR for the HAL to use +; as it needs. Currently this space is used for some efficiency in +; some of the MP specific code and is highly implementation-dependent. +; Must match the preceeding C structure. + +PcrE struc + PcrNumber db 0 ; Processor's number + ProcLightState db 0 ; State of Processor light + ProcIrql db 0 ; Current IRQL + ProcPad1 db 0 ; Reserved (for padding) + ProcSlotAddr dw 0 ; Slot (9-15) << 12 + ProcPad2 dw 0 ; Reserved (for padding) +PcrE ends + +CR equ 0dh +LF equ 0ah + +IoDelay macro + push eax + in al, 020h + pop eax +endm + +SET_8259_MASK macro + out PIC1_PORT1, al ; set master 8259 mask + shr eax, 8 ; shift slave 8259 mask to al + out PIC2_PORT1, al ; set slave 8259 mask +endm + +PIC1DELAY macro + in al, PIC1_PORT1 +endm + +PIC2DELAY macro + in al, PIC2_PORT1 +endm + +DISABLE_INTERRUPTS_AT_CPU macro + pushfd ; save interrupt mode + cli ; disable interrupt +endm + +RESTORE_INTERRUPTS_AT_CPU macro + popfd ; restore original interrupt mode +endm + +;++ +; +; SOFT_INTERRUPT_EXIT +; +; Macro Description: +; +; This macro is executed on return from the soft interrupt +; service routine. Its function is to restore privileged processor +; state, and continue thread execution. +; +; Arguments: +; +; (TOS) = previous irql +; (TOS+4 ...) = machine_state frame +; +;-- + +SOFT_INTERRUPT_EXIT macro + + EXTRNP _KeLowerIrql,1 + cli + call _KeLowerIrql@4 ; restore irql + SPURIOUS_INTERRUPT_EXIT ; exit interrupt without EOI +endm + +; Macro for programming IDT entries directly + +IDTEntry macro Vector, Handler + sub esp, 8 ; allocate temp stack space + sidt fword ptr [esp] ; IDT base + limit + mov edx, [esp+2] ; IDT linear base address + mov ecx, Vector ; get Vector + mov eax, offset FLAT:Handler ; Get Handler + 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 + add esp, 8 ; deallocate temp stack space +endm + +; End of Assembly only code +;*/ diff --git a/private/ntos/nthals/halws3/i386/w3clock.asm b/private/ntos/nthals/halws3/i386/w3clock.asm new file mode 100644 index 000000000..b45761307 --- /dev/null +++ b/private/ntos/nthals/halws3/i386/w3clock.asm @@ -0,0 +1,782 @@ + title "Interval Clock Interrupt" +;++ +; +; Copyright (c) 1989 Microsoft Corporation +; Copyright (c) 1993 Sequent Computer Systems, Inc. +; +; Module Name: +; +; w3clock.asm +; +; Abstract: +; +; This module implements the code necessary to field and process the +; interval clock interrupt. +; +; Author: +; +; Phil Hochstetler (phil@sequent.com) +; +; Environment: +; +; Kernel mode only. +; +; Revision History: +; +;-- + +.386p + .xlist +include hal386.inc +include callconv.inc +include i386\kimacro.inc +include mac386.inc +include i386\apic.inc +include i386\ixcmos.inc +include i386\w3.inc + .list + + EXTRNP _DbgBreakPoint,0,IMPORT + EXTRNP _KeUpdateSystemTime,0 + EXTRNP _KeUpdateRunTime,1,IMPORT + EXTRNP _KeProfileInterrupt,1,IMPORT + EXTRNP Kei386EoiHelper,0,IMPORT + EXTRNP _KeSetTimeIncrement,2,IMPORT + EXTRNP _HalEndSystemInterrupt,2 + EXTRNP _HalBeginSystemInterrupt,3 + extrn _HalpLocalUnitBase:DWORD + extrn _HalpW3PostRegisterImage:DWORD + +; +; Constants used to initialize timer 0 +; + +TIMER1_DATA_PORT0 EQU 40H ; Timer1, channel 0 data port +TIMER1_CONTROL_PORT0 EQU 43H ; Timer1, channel 0 control port +TIMER2_DATA_PORT0 EQU 48H ; Timer1, channel 0 data port +TIMER2_CONTROL_PORT0 EQU 4BH ; Timer1, channel 0 control port +TIMER1_IRQ EQU 0 ; Irq 0 for timer1 interrupt + +COMMAND_8254_COUNTER0 EQU 00H ; Select count 0 +COMMAND_8254_RW_16BIT EQU 30H ; Read/Write LSB firt then MSB +COMMAND_8254_MODE2 EQU 4 ; Use mode 2 +COMMAND_8254_BCD EQU 0 ; Binary count down +COMMAND_8254_LATCH_READ EQU 0 ; Latch read command + +PERFORMANCE_FREQUENCY EQU 1193182 + +; +; ==== Values used for System Clock ==== +; + +_DATA SEGMENT DWORD PUBLIC 'DATA' + +; +; 8254 spinlock. This must be acquired before touching the 8254 chip. +; + public _Halp8254Lock +_Halp8254Lock dd 0 + + + public HalpPerfCounterLow, HalpPerfCounterHigh + public HalpLastPerfCounterLow, HalpLastPerfCounterHigh +HalpPerfCounterLow dd 0 +HalpPerfCounterHigh dd 0 +HalpLastPerfCounterLow dd 0 +HalpLastPerfCounterHigh dd 0 + + + public HalpCurrentRollOver, HalpCurrentTimeIncrement +HalpCurrentRollOver dd 0 +HalpCurrentTimeIncrement dd 0 + +; +; Convert the interval to rollover count for 8254 Timer1 device. +; Timer1 counts down a 16 bit value at a rate of 1.193181667M counts-per-sec. +; +; +; The best fit value closest to 10ms is 10.0144012689ms: +; ROLLOVER_COUNT 11949 +; TIME_INCREMENT 100144 +; Calculated error is -.0109472 s/day +; +; +; The following table contains 8254 values timer values to use at +; any given ms setting from 1ms - 15ms. All values work out to the +; same error per day (-.0109472 s/day). +; + + public HalpRollOverTable + + ; RollOver Time + ; Count Increment MS +HalpRollOverTable dd 1197, 10032 ; 1ms + dd 2394, 20064 ; 2 ms + dd 3591, 30096 ; 3 ms + dd 4767, 39952 ; 4 ms + dd 5964, 49984 ; 5 ms + dd 7161, 60016 ; 6 ms + dd 8358, 70048 ; 7 ms + dd 9555, 80080 ; 8 ms + dd 10731, 89936 ; 9 ms + dd 11949, 100144 ; 10 ms + dd 13125, 110000 ; 11 ms + dd 14322, 120032 ; 12 ms + dd 15519, 130064 ; 13 ms + dd 16695, 139920 ; 14 ms + dd 17892, 149952 ; 15 ms + +TimeIncr equ 4 +RollOver equ 0 + + public HalpLargestClockMS, HalpNextMSRate, HalpPendingMSRate +HalpLargestClockMS dd 15 ; Table goes to 15MS +HalpNextMSRate dd 0 +HalpPendingMSRate dd 0 + + +_DATA ends + + +INIT SEGMENT DWORD PUBLIC 'CODE' + ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING + + page ,132 + subttl "Initialize Clock" +;++ +; +; VOID +; HalpInitializeClock ( +; ) +; +; Routine Description: +; +; This routine initialize system time clock using 8254 timer1 counter 0 +; to generate an interrupt at every 10ms interval at EISA_CLOCK_VECTOR +; +; The Eisa clock interrupt handler then IPIs all processors at +; APIC_CLOCK_VECTOR +; +; See the definitions of TIME_INCREMENT and ROLLOVER_COUNT if clock rate +; needs to be changed. +; +; This routine assumes it runs during Phase 0 on P0. +; +; Arguments: +; +; None +; +; Return Value: +; +; None. +; +;-- +cPublicProc _HalpInitializeClock ,0 + + mov eax, PCR[PcPrcb] + cmp byte ptr [eax].PbCpuType, 4 ; 486 or better? + jc short @f ; no, skip + + mov HalpLargestClockMS, 10 ; Limit 486's to 10MS +@@: + mov eax, HalpLargestClockMS + mov ecx, HalpRollOverTable.TimeIncr + mov edx, HalpRollOverTable[eax*8-8].TimeIncr + mov eax, HalpRollOverTable[eax*8-8].RollOver + + mov HalpCurrentTimeIncrement, edx + +; +; (ecx) = Min time_incr +; (edx) = Max time_incr +; (eax) = max roll over count +; + + push eax + stdCall _KeSetTimeIncrement, <edx, ecx> + pop ecx + + pushfd ; save caller's eflag + cli ; make sure interrupts are disabled + +; +; Set clock rate +; (ecx) = RollOverCount +; + + mov al,COMMAND_8254_COUNTER0+COMMAND_8254_RW_16BIT+COMMAND_8254_MODE2 + out TIMER1_CONTROL_PORT0, al ;program count mode of timer 0 + IoDelay + mov al, cl + out TIMER1_DATA_PORT0, al ; program timer 0 LSB count + IoDelay + mov al,ch + out TIMER1_DATA_PORT0, al ; program timer 0 MSB count + + popfd ; restore caller's eflag + mov HalpCurrentRollOver, ecx ; Set RollOverCount & initialized + + stdRET _HalpInitializeClock + +stdENDP _HalpInitializeClock + +INIT ends + +_TEXT$03 SEGMENT DWORD PUBLIC 'CODE' + ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING + + page ,132 + subttl "Query Performance Counter" +;++ +; +; LARGE_INTEGER +; KeQueryPerformanceCounter ( +; OUT PLARGE_INTEGER PerformanceFrequency OPTIONAL +; ) +; +; Routine Description: +; +; This routine returns current 64-bit performance counter and, +; optionally, the Performance Frequency. +; +; Note this routine can NOT be called at Profiling interrupt +; service routine. Because this routine depends on IRR0 to determine +; the actual count. +; +; Also note that the performace counter returned by this routine +; is not necessary the value when this routine is just entered. +; The value returned is actually the counter value at any point +; between the routine is entered and is exited. +; +; Arguments: +; +; PerformanceFrequency [TOS+4] - optionally, supplies the address +; of a variable to receive the performance counter frequency. +; +; Return Value: +; +; Current value of the performance counter will be returned. +; +;-- + +; +; Parameter definitions +; + +KqpcFrequency EQU [esp+12] ; User supplied Performance Frequence + +cPublicProc _KeQueryPerformanceCounter ,1 +cPublicFpo 1, 0 +; +; First check to see if the performance counter has been initialized yet. +; Since the kernel debugger calls KeQueryPerformanceCounter to support the +; !timer command, we need to return something reasonable before Timer +; initialization has occured. Reading garbage off the Timer is not reasonable. +; + cmp HalpCurrentRollOver, 0 + je Kqpc50 + + push ebx + push esi + +Kqpc01: pushfd + cli +Kqpc20: +ifndef NT_UP + lea eax, _Halp8254Lock + ACQUIRE_SPINLOCK eax, Kqpc198 +endif + +; +; Fetch the base value. Note that interrupts are off. +; + +@@: + mov ebx, HalpPerfCounterLow + mov esi, HalpPerfCounterHigh ; [esi:ebx] = Performance counter + + cmp ebx, HalpPerfCounterLow + jne @b + +; +; Fetch the current counter value from the hardware +; + + mov al, COMMAND_8254_LATCH_READ+COMMAND_8254_COUNTER0 + ;Latch PIT Ctr 0 command. + out TIMER1_CONTROL_PORT0, al + IoDelay + in al, TIMER1_DATA_PORT0 ;Read PIT Ctr 0, LSByte. + movzx ecx,al ;Zero upper bytes of (ECX). + IoDelay + in al, TIMER1_DATA_PORT0 ;Read PIT Ctr 0, MSByte. + mov ch, al ;(CX) = PIT Ctr 0 count. + +ifndef NT_UP + lea eax, _Halp8254Lock + RELEASE_SPINLOCK eax +endif + + +; +; Now enable interrupts such that if timer interrupt is pending, it can +; be serviced and update the PerformanceCounter. Note that there could +; be a long time between the sti and cli because ANY interrupt could come +; in in between. +; + + popfd ; don't re-enable interrupts if + nop ; the caller had them off! + + jmp $+2 ; allow interrupt in case counter + ; has wrapped + + pushfd + cli + +; +; Fetch the base value again. +; + +@@: + mov eax, HalpPerfCounterLow + mov edx, HalpPerfCounterHigh ; [edx:eax] = new counter value + + cmp eax, HalpPerfCounterLow + jne @b +; +; Compare the two reads of Performance counter. If they are different, +; start over +; + + cmp eax, ebx + jne Kqpc20 + cmp edx, esi + jne Kqpc20 + + neg ecx ; PIT counts down from 0h + add ecx, HalpCurrentRollOver + jnc short Kqpc60 + +Kqpc30: + add eax, ecx + adc edx, 0 ; [edx:eax] = Final result + + cmp edx, HalpLastPerfCounterHigh + jc short Kqpc70 ; jmp if edx < lastperfcounterhigh + jne short Kqpc35 ; jmp if edx > lastperfcounterhigh + + cmp eax, HalpLastPerfCounterLow + jc short Kqpc70 ; jmp if eax < lastperfcounterlow + +Kqpc35: + mov HalpLastPerfCounterLow, eax + mov HalpLastPerfCounterHigh, edx + + popfd ; restore interrupt flag + + +; +; Return the freq. if caller wants it. +; + cmp dword ptr KqpcFrequency, 0 ; is it a NULL variable? + jz short Kqpc40 ; if z, yes, go exit + + mov ecx, KqpcFrequency ; (ecx)-> Frequency variable + mov DWORD PTR [ecx], PERFORMANCE_FREQUENCY ; Set frequency + mov DWORD PTR [ecx+4], 0 + +Kqpc40: + pop esi ; restore esi and ebx + pop ebx + stdRET _KeQueryPerformanceCounter + +Kqpc50: +; Initialization hasn't occured yet, so just return zeroes. + mov eax, 0 + mov edx, 0 + stdRET _KeQueryPerformanceCounter + +Kqpc60: +; +; The current count is larger then the HalpCurrentRollOver. The only way +; that could happen is if there is an interrupt in route to the processor +; but it was not processed while interrupts were enabled. +; + mov esi, [esp] ; (esi) = flags + mov ecx, HalpCurrentRollOver ; (ecx) = max possible value + popfd ; restore flags + + test esi, EFLAGS_INTERRUPT_MASK + jnz Kqpc01 ; ints are enabled, problem should go away + + pushfd ; fix stack + jmp short Kqpc30 ; ints are disabled, use max count (ecx) + +Kqpc70: +; +; The current count is smaller then the last returned count. The only way +; this should occur is if there is an interrupt in route to the processor +; which was not been processed. +; + + mov ebx, HalpLastPerfCounterLow + mov esi, HalpLastPerfCounterHigh + + mov ecx, ebx + or ecx, esi ; is last returned value 0? + jz short Kqpc35 ; Yes, then just return what we have + + ; sanity check - make sure count is not off by bogus amount + sub ebx, eax + sbb esi, edx + jnz short Kqpc75 ; off by bogus amount + cmp ebx, HalpCurrentRollOver + jg short Kqpc75 ; off by bogus amount + + sub eax, ebx + sbb edx, esi ; (edx:eax) = last returned count + + mov ecx, [esp] ; (ecx) = flags + popfd + + test ecx, EFLAGS_INTERRUPT_MASK + jnz Kqpc01 ; ints enabled, problem should go away + + pushfd ; fix stack + jmp Kqpc35 ; ints disabled, just return last count + +Kqpc75: + popfd + xor eax, eax ; reset bogus values + mov HalpLastPerfCounterLow, eax + mov HalpLastPerfCounterHigh, eax + jmp Kqpc01 ; go try again + +ifndef NT_UP +Kqpc198: popfd + SPIN_ON_SPINLOCK eax,<Kqpc01> +endif + +stdENDP _KeQueryPerformanceCounter + +;++ +; +; VOID +; HalCalibratePerformanceCounter ( +; IN volatile PLONG Number +; ) +; +; /*++ +; +; Routine Description: +; +; This routine calibrates the performance counter value for a +; multiprocessor system. The calibration can be done by zeroing +; the current performance counter, or by calculating a per-processor +; skewing between each processors counter. +; +; Arguments: +; +; Number - Supplies a pointer to count of the number of processors in +; the configuration. +; +; Return Value: +; +; None. +;-- +cPublicProc _HalCalibratePerformanceCounter,1 +cPublicFpo 1, 0 + + mov eax, [esp+4] ; ponter to Number +cPublicFpo 1, 1 + pushfd ; save previous interrupt state + cli ; disable interrupts (go to high_level) + + lock dec dword ptr [eax] ; count down + +@@: cmp dword ptr [eax], 0 ; wait for all processors to signal + jnz short @b + + ; + ; Nothing to calibrate on this apic based MP machine. There is only + ; a single 8254 device in use + ; + +cPublicFpo 1, 0 + popfd ; restore interrupt flag + stdRET _HalCalibratePerformanceCounter + +stdENDP _HalCalibratePerformanceCounter + + + + page ,132 + subttl "System Clock Interrupt" +;++ +; +; Routine Description: +; +; +; This routine is entered as the result of an interrupt generated by CLOCK2. +; Its function is to dismiss the interrupt, raise system Irql to +; CLOCK2_LEVEL, update performance counter and transfer control to the +; standard system routine to update the system time and the execution +; time of the current thread +; and process. +; +; +; Arguments: +; +; None +; Interrupt is disabled +; +; Return Value: +; +; Does not return, jumps directly to KeUpdateSystemTime, which returns +; +; Sets Irql = CLOCK2_LEVEL and dismisses the interrupt +; +;-- + + ENTER_DR_ASSIST Hci_a, Hci_t + +cPublicProc _HalpClockInterrupt ,0 + +; +; Save machine state in trap frame +; + + ENTER_INTERRUPT Hci_a, Hci_t + +; +; (esp) - base of trap frame +; +; dismiss interrupt and raise Irql +; + + push APIC_CLOCK_VECTOR + sub esp, 4 ; allocate space to save OldIrql + stdCall _HalBeginSystemInterrupt, <CLOCK2_LEVEL,APIC_CLOCK_VECTOR,esp> + or al,al ; check for spurious interrupt + jz Hci100 + +; +; Turn off (on) the processor active light to reflect whether +; we are (are not) currently executing the Idle Thread. +; + + mov edi, PCR[PcPrcb] ; (edi) -> Prcb + mov eax, [edi].PbCurrentThread + cmp eax, [edi].PbIdleThread ; running idle thread? + setnz al ; set al to desired light state + cmp al, byte ptr PCR[PcHal.ProcLightState] + jne Hci05 +Hci10: + +ifndef NT_UP + cmp byte ptr PCR[PcHal.PcrNumber], 0 ; Only P0 Will update System Time + je Do_P0Timer + + ; + ; All processors will update RunTime for current thread + ; + + sti + ; TOS const PreviousIrql + stdCall _KeUpdateRunTime,<dword ptr [esp]> + + INTERRUPT_EXIT ; lower irql to old value, iret + + ; + ; We don't return here + ; + + +Do_P0Timer: + +endif + +; +; Update front panel light show +; + mov eax, _HalpW3PostRegisterImage ; get current bits + and al, 01111111b ; clear disk error bit + out PostRegisterPort, al ; write PostCode Reg + +; +; Update performance counter +; + + mov eax, HalpCurrentRollOver + add HalpPerfCounterLow, eax ; update performace counter + adc HalpPerfCounterHigh, dword ptr 0 + + mov eax, HalpCurrentTimeIncrement +Hci30: + +; +; (esp) = OldIrql +; (esp+4) = Vector +; (esp+8) = base of trap frame +; ebp = trap frame +; eax = time increment +; + cmp HalpNextMSRate, 0 ; New clock rate desired? + jz _KeUpdateSystemTime@0 ; No, process tick + +; +; Time of clock frequency is being changed. See if the 8254 was +; was reprogrammed for a new rate during last tick +; + cmp HalpPendingMSRate, 0 ; Was a new rate set durning last + jnz short Hci50 ; tick? Yes, go update globals + +Hci40: +; (eax) = time increment for current tick + +; +; A new clock rate needs to be set. Setting the rate here will +; cause the tick after the next tick to be at the new rate. +; (the next tick is already in progress by the 8254 and will occur +; at the same rate as this tick) +; +Kci01: pushfd + cli +ifndef NT_UP + lea ecx, _Halp8254Lock + ACQUIRE_SPINLOCK ecx, Kci198 +endif + mov ebx, HalpNextMSRate + mov HalpPendingMSRate, ebx ; pending rate + + mov ecx, HalpRollOverTable[ebx*8-8].RollOver + +; +; Set clock rate +; (ecx) = RollOverCount +; + + push eax ; save current tick's rate + + + mov al,COMMAND_8254_COUNTER0+COMMAND_8254_RW_16BIT+COMMAND_8254_MODE2 + out TIMER1_CONTROL_PORT0, al ;program count mode of timer 0 + IoDelay + mov al, cl + out TIMER1_DATA_PORT0, al ; program timer 0 LSB count + IoDelay + mov al,ch + out TIMER1_DATA_PORT0, al ; program timer 0 MSB count + +ifndef NT_UP + lea eax, _Halp8254Lock + RELEASE_SPINLOCK eax +endif + + pop eax + popfd + jmp Hci30 ; dispatch this tick + +Hci50: +; +; The next tick will occur at the rate which was programmed during the last +; tick. Update globals for new rate which starts with the next tick. +; +; (eax) = time increment for current tick +; + mov ebx, HalpPendingMSRate + mov ecx, HalpRollOverTable[ebx*8-8].RollOver + mov edx, HalpRollOverTable[ebx*8-8].TimeIncr + + mov HalpCurrentRollOver, ecx + mov HalpCurrentTimeIncrement, edx ; next tick rate + mov HalpPendingMSRate, 0 ; no longer pending, clear it + + cmp ebx, HalpNextMSRate ; new rate == NextRate? + jne Hci40 ; no, go set new pending rate + + mov HalpNextMSRate, 0 ; we are at this rate, clear it + jmp Hci30 ; process this tick + +Hci100: + add esp, 8 ; spurious, no EndOfInterrupt + SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi + +ifndef NT_UP +Kci198: popfd + SPIN_ON_SPINLOCK ecx,<Kqpc01> +endif + +; +; Update the state of hardware lights and state variable +; +Hci05: + cmp al, 1 ; identify light going + je Hci06 ; on (or going off) + +; Turn light off that was on + + xor eax, eax + mov al, byte ptr PCR[PcHal.PcrNumber] ; get processor number + lock btr _HalpW3PostRegisterImage, eax ; clear the bit + mov byte ptr PCR[PcHal.ProcLightState], 0 ; update flag + jmp hci10 ; return + +; Turn light on that was off +Hci06: + xor eax, eax + mov al, byte ptr PCR[PcHal.PcrNumber] ; get processor number + lock bts _HalpW3PostRegisterImage, eax ; set the bit + mov byte ptr PCR[PcHal.ProcLightState], 1 ; update flag + jmp hci10 ; return + +stdENDP _HalpClockInterrupt + +;++ +; +; ULONG +; HalSetTimeIncrement ( +; IN ULONG DesiredIncrement +; ) +; +; /*++ +; +; Routine Description: +; +; This routine initialize system time clock to generate an +; interrupt at every DesiredIncrement interval. +; +; Arguments: +; +; DesiredIncrement - desired interval between every timer tick (in +; 100ns unit.) +; +; Return Value: +; +; The *REAL* time increment set. +;-- +cPublicProc _HalSetTimeIncrement,1 + + mov eax, [esp+4] ; desired setting + xor edx, edx + mov ecx, 10000 + div ecx ; round to MS + + cmp eax, HalpLargestClockMS ; MS > max? + jc short @f + mov eax, HalpLargestClockMS ; yes, use max +@@: + or eax, eax ; MS < min? + jnz short @f + inc eax ; yes, use min +@@: + mov HalpNextMSRate, eax + + mov eax, HalpRollOverTable[eax*8-8].TimeIncr + stdRET _HalSetTimeIncrement + +stdENDP _HalSetTimeIncrement +_TEXT$03 ends + + end diff --git a/private/ntos/nthals/halws3/i386/w3detect.asm b/private/ntos/nthals/halws3/i386/w3detect.asm new file mode 100644 index 000000000..0a77c4b3b --- /dev/null +++ b/private/ntos/nthals/halws3/i386/w3detect.asm @@ -0,0 +1,106 @@ +;++ +; +; Copyright (c) 1991 Microsoft Corporation +; Copyright (c) 1993,1994 Sequent Computer Systems, Inc. +; +; Module Name: +; +; w3detect.asm +; +; Abstract: +; +; This module detects a Sequent WinServer 3000. It is included +; by w3ipi.asm and the setup program. It must assemble more or less +; standalone and run in protected mode. +; +; Author: +; +; Phil Hochstetler (phil@sequent.com) 3-30-93 +; +; Revision History: +; +;-- + +include callconv.inc + +_DATA SEGMENT DWORD PUBLIC 'DATA' + +; W3SystemType: SystemType is read from 0c80-0c83. +; +; 0c80-0c81: Compressed "TRI" (5 bit encoding). +; 0c82: System Board Type. +; 0c83: System Board Revision Level. + + +W3SystemTypeTable db 052h, 049h, 08h, 00h +W3SystemType db 5 dup(0) + +_DATA ends + + page ,132 +_TEXT SEGMENT DWORD PUBLIC 'CODE' + ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING + +;++ +; ULONG +; DetectWS3000( +; OUT PBOOLEAN IsConfiguredMp +; ); +; +; Routine Description: +; Determines the type of system (specifically for eisa machine), by reading +; the system board system ID. It compares the 4 bytes of the ID, to +; a predefined table <W3SystemTypeTable> and returns the index to the +; found entry. +; +; Arguments: +; IsConfiguredMp - If detected, then this value is +; set to TRUE if it's an MP system, else FALSE. +; +; Return Value: +; +; A value of 1 is returned if a WS3000 machine is detected. +; Otherwise a value of 0 is returned. +;-- +cPublicProc _DetectWS3000 ,1 +cPublicFpo 1, 3 + + push edi + push esi + push ebx ; Save C Runtime + + ; A 4 byte value is read from 0c80-0c83, and saved in <W3SystemType>. + ; This value is compared to the first 3 bytes of the value in + ; <W3SystemTypeTable>. + + cld ; set direction to forward + lea edi, W3SystemType + mov edx, 0c80h + insb ; 52h + inc edx + insb ; 49h + inc edx + insb ; 08h - System Board Type + inc edx + insb ; 00h - Revision Level + + xor eax, eax ; default to return failure + lea edi, W3SystemTypeTable ; Type Table + mov ecx, 3 ; bytes to compare against + lea esi, W3SystemType ; match string against table entry + repe cmpsb ; if (ecx == 0 and ZF set) + jnz @f ; we have a winner + inc al + mov ebx, dword ptr [esp+16] + mov byte ptr [ebx], 1 ; *IsConfiguredMp = TRUE + +@@: + pop ebx + pop esi + pop edi ; Restore C Runtime + + stdRET _DetectWS3000 + +stdENDP _DetectWS3000 + +_TEXT ENDS diff --git a/private/ntos/nthals/halws3/i386/w3hal.c b/private/ntos/nthals/halws3/i386/w3hal.c new file mode 100644 index 000000000..a0476e92b --- /dev/null +++ b/private/ntos/nthals/halws3/i386/w3hal.c @@ -0,0 +1,660 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation +Copyright (c) 1993,1994 Sequent Computer Systems, Inc. + +Module Name: + + w3hal.c + +Abstract: + + + This module implements the initialization of the system dependent + functions that define the Hardware Architecture Layer (HAL) for an + x86 system. + +Author: + + Phil Hochstetler (phil@sequent.com) + +Environment: + + Kernel mode only. + +Revision History: + +--*/ + +#include "halp.h" +#include "w3.inc" + +UCHAR SequentCopyright[] = "\n\n\ +Copyright (c) 1993,1994\n\ +Sequent Computer Systems, Inc. All rights reserved.\n\ + \n\ +This software is furnished under a license and may be used\n\ +only in accordance with the terms of that license and with the\n\ +inclusion of the above copyright notice. This software may not\n\ +be provided or otherwise made available to, or used by, any\n\ +other person. No title to or ownership of the software is\n\ +hereby transferred.\n\n"; + +ULONG HalpBusType; +ULONG ProcessorsPresent; + +extern ADDRESS_USAGE HalpDefaultPcIoSpace; +extern ADDRESS_USAGE HalpEisaIoSpace; + +ADDRESS_USAGE HalpW3IoSpace = { + NULL, CmResourceTypePort, InternalUsage, + { + 0x800, 0x100, // EISA CMOS Page + 0xC00, 0x10, // SBC + 0xC10, 0x10, // EISA Page Select + 0xC20, 0x10, // LCD + 0xC30, 0x10, // Cache Flush + 0xC80, 0x4, // EISA SBID + 0xC84, 0x4, // EISA SBE + 0xCC0, 0x2, // PIC 3 + 0xCC2, 0x3E, // Reserved + 0,0 + } +}; + +#ifdef NT_UP + +UCHAR UPWarn[] = "\ +HAL: Incorrect system configuration.\n\ +HAL: Uniprocessor HAL.DLL and NTOSKRNL.EXE are running\n\ +HAL: on a system that contains more than one processor.\n\ +HAL: Please install multiprocessor HAL.DLL and NTOSKRNL.EXE to correct.\n\ +HAL: Only using 1 processor to allow system boot to continue.\n"; + +#else + +UCHAR MPWarn[] = "\ +HAL: Incorrect system configuration.\n\ +HAL: Multiprocessor HAL.DLL and NTOSKRNL.EXE are running\n\ +HAL: on a system that contains only one processor.\n\ +HAL: Please install uniprocessor HAL.DLL and NTOSKRNL.EXE to correct.\n"; + +#endif + +#ifndef NT_UP +ULONG +HalpInitMP( + IN ULONG Phase, + IN PLOADER_PARAMETER_BLOCK LoaderBlock + ); +#endif + +KSPIN_LOCK HalpSystemHardwareLock; + +VOID +HalpIpiHandler( + VOID + ); + +USHORT +HalpMySlotAddr( + ); + +VOID +HalpSetProcessorsPresent( + ); + +// +// CAUTION!! these local vector definitions must match those in w3.inc +// these are included to avoid conflicts with vectors defined in ix8259.inc +// (which is included by halp.h) +// +#define APIC_PROFILE_VECTOR 0x90 +#define APIC_CLOCK_VECTOR 0xA0 +#define APIC_IPI_VECTOR 0xB0 + +#define KB_STAT 0x64 // keyboard controller status +#define KB_IDAT 0x60 // input buffer data write +#define KB_OUTBF 0x01 // output buffer full + +extern UCHAR HalName[]; +extern PKPCR HalpProcessorPCR[]; + + +VOID +HalpGetUserInput ( + ) + +{ + UCHAR i, j; + UCHAR byte; + UCHAR OldPicMask; + + // + // Mask keyboard interrupt directly at the PIC + // + OldPicMask = READ_PORT_UCHAR((PUCHAR) 0x21); + WRITE_PORT_UCHAR((PUCHAR) 0x21, (UCHAR)(OldPicMask | 1)); + + j = 1; + do { + for (i = 0; i < 50; i++) { + // flush all keyboard input + if (READ_PORT_UCHAR((PUCHAR) KB_STAT) & KB_OUTBF) + byte = READ_PORT_UCHAR((PUCHAR) KB_IDAT); // read scan code + KeStallExecutionProcessor(1000); // delay 1 ms + } + if (j == 1) { + HalDisplayString("HAL: Press any key to continue ..."); + while ((READ_PORT_UCHAR((PUCHAR) KB_STAT) & KB_OUTBF) == 0) + continue; + HalDisplayString("\n"); + } + } while (j-- > 0); + + WRITE_PORT_UCHAR((PUCHAR) 0x21, OldPicMask); // restore mask + return; +} + + +BOOLEAN +HalInitSystem ( + IN ULONG Phase, + IN PLOADER_PARAMETER_BLOCK LoaderBlock + ) + +/*++ + +Routine Description: + + This function initializes the Hardware Architecture Layer (HAL) for + the WINSERVER 3000 x86 SMP system. + +Arguments: + + None. + +Return Value: + + A value of TRUE is returned is the initialization was successfully + complete. Otherwise a value of FALSE is returend. + +--*/ + +{ + PMEMORY_ALLOCATION_DESCRIPTOR Descriptor; + PLIST_ENTRY NextMd; + KIRQL CurrentIrql; + PKPRCB pPRCB; + + pPRCB = KeGetCurrentPrcb(); + + if (Phase == 0) { + + HalpBusType = LoaderBlock->u.I386.MachineType & 0x00ff; + + // + // Verify Prcb version and build flags conform to + // this image + // + +#if DBG + if (!(pPRCB->BuildType & PRCB_BUILD_DEBUG)) { + // This checked hal requires a checked kernel + KeBugCheckEx (MISMATCHED_HAL, + 2, pPRCB->BuildType, PRCB_BUILD_DEBUG, 0); + } +#else + if (pPRCB->BuildType & PRCB_BUILD_DEBUG) { + // This free hal requires a free kernel + KeBugCheckEx (MISMATCHED_HAL, 2, pPRCB->BuildType, 0, 0); + } +#endif +#ifndef NT_UP + if (pPRCB->BuildType & PRCB_BUILD_UNIPROCESSOR) { + // This MP hal requires an MP kernel + KeBugCheckEx (MISMATCHED_HAL, 2, pPRCB->BuildType, 0, 0); + } +#endif + if (pPRCB->MajorVersion != PRCB_MAJOR_VERSION) { + KeBugCheckEx (MISMATCHED_HAL, + 1, pPRCB->MajorVersion, PRCB_MAJOR_VERSION, 0); + } + + HalpSetProcessorsPresent(); + ProcessorsPresent &= ~(1 << (HalpMySlotAddr() >> EISA_SHIFT)); + +#ifdef NT_UP + if (ProcessorsPresent) { + HalDisplayString(UPWarn); // UP HAL/NTOSKRNL on MP HW + ProcessorsPresent = 0; // Hide procs to allow boot + HalpGetUserInput(); + } +#else + if (ProcessorsPresent == 0) { + HalDisplayString(MPWarn); // MP HAL/NTOSKRNL on UP HW + HalpGetUserInput(); + } +#endif + + // + // Phase 0 initialization only called by P0 + // + + HalpInitializePICs(); + + // + // Initialize CMOS + // + + HalpInitializeCmos(); + + // + // Register cascade vector + // + + HalpRegisterVector ( + InternalUsage, EISA_IRQ2_VECTOR, EISA_IRQ2_VECTOR, HIGH_LEVEL ); + + // + // Register PIC vectors + // + + HalpRegisterVector ( + InternalUsage, + EISA_PIC1_SPURIOUS_VECTOR, + EISA_PIC1_SPURIOUS_VECTOR, + HIGH_LEVEL ); + + HalpRegisterVector ( + InternalUsage, + EISA_PIC2_SPURIOUS_VECTOR, + EISA_PIC2_SPURIOUS_VECTOR, + HIGH_LEVEL ); + + HalpRegisterVector ( + DeviceUsage, + EISA_CLOCK_VECTOR, + EISA_CLOCK_VECTOR, + HIGH_LEVEL ); + + HalpRegisterVector ( + DeviceUsage, + EISA_KBD_VECTOR, + EISA_KBD_VECTOR, + HIGH_LEVEL ); + + HalpRegisterVector ( + DeviceUsage, + EISA_FLOPPY_VECTOR, + EISA_FLOPPY_VECTOR, + HIGH_LEVEL ); + + HalpRegisterVector ( + DeviceUsage, + EISA_RTC_VECTOR, + EISA_RTC_VECTOR, + HIGH_LEVEL ); + + HalpRegisterVector ( + DeviceUsage, + EISA_MOUSE_VECTOR, + EISA_MOUSE_VECTOR, + HIGH_LEVEL ); + + HalpRegisterVector ( + DeviceUsage, + EISA_DMA_VECTOR, + EISA_DMA_VECTOR, + HIGH_LEVEL ); + + HalpRegisterVector ( + DeviceUsage, + EISA_IDE_VECTOR, + EISA_IDE_VECTOR, + HIGH_LEVEL ); + + // + // Register APIC spurious vector + // + + HalpRegisterVector ( + InternalUsage, + APIC_SPURIOUS_VECTOR, + APIC_SPURIOUS_VECTOR, + HIGH_LEVEL ); + + // + // Now that the PICs are initialized, we need to mask them to + // reflect the current Irql + // + + CurrentIrql = KeGetCurrentIrql(); + CurrentIrql = KfRaiseIrql(CurrentIrql); + + // + // Fill in handlers for APIs which this hal supports + // + + HalQuerySystemInformation = HaliQuerySystemInformation; + HalSetSystemInformation = HaliSetSystemInformation; + + // + // Register base IO space used by hal + // + + HalpRegisterAddressUsage (&HalpDefaultPcIoSpace); + HalpRegisterAddressUsage (&HalpEisaIoSpace); + HalpRegisterAddressUsage (&HalpW3IoSpace); + + // + // P0's stall execution is initialized here to allow the kernel + // debugger to work properly before initializing all the other + // processors. + // + + HalpInitializeStallExecution(0); + + HalpEnableInterruptHandler ( + DeviceUsage, // Report as device vector + APIC_CLOCK_VECTOR, // Bus interrupt level + APIC_CLOCK_VECTOR, // System IDT + CLOCK2_LEVEL, // System Irql + HalpClockInterrupt, // IRS + Latched ); + + HalpInitializeClock(); + + // + // Initialize the profile interrupt vector. + // + + HalStopProfileInterrupt(0); + + HalpEnableInterruptHandler ( + DeviceUsage, // Report as device vector + APIC_PROFILE_VECTOR, // Bus interrupt level + APIC_PROFILE_VECTOR, // System IDT + PROFILE_LEVEL, // System Irql + HalpProfileInterrupt, // IRS + Latched ); + + // + // Initialize the IPI handler + // + + HalpEnableInterruptHandler ( + DeviceUsage, // Report as device vector + APIC_IPI_VECTOR, // Bus interrupt level + APIC_IPI_VECTOR, // System IDT + IPI_LEVEL, // System Irql + HalpIpiHandler, // IRS + Latched ); + + HalpInitializeDisplay(); + + // + // Initialize spinlock used by HalGetBusData hardware access routines + // + + KeInitializeSpinLock(&HalpSystemHardwareLock); + + // + // Determine if there is physical memory above 16 MB. + // + + LessThan16Mb = TRUE; + + NextMd = LoaderBlock->MemoryDescriptorListHead.Flink; + + while (NextMd != &LoaderBlock->MemoryDescriptorListHead) { + Descriptor = CONTAINING_RECORD( NextMd, + MEMORY_ALLOCATION_DESCRIPTOR, + ListEntry ); + + if (Descriptor->BasePage + Descriptor->PageCount > 0x1000) { + LessThan16Mb = FALSE; + } + + NextMd = Descriptor->ListEntry.Flink; + } + + // + // Determine the size need for map buffers. If this system has + // memory with a physical address of greater than + // MAXIMUM_PHYSICAL_ADDRESS, then allocate a large chunk; otherwise, + // allocate a small chunk. + // + + if (LessThan16Mb) { + + // + // Allocate a small set of map buffers. They are only need for + // slave DMA devices. + // + + HalpMapBufferSize = INITIAL_MAP_BUFFER_SMALL_SIZE; + + } else { + + // + // Allocate a larger set of map buffers. These are used for + // slave DMA controllers and Isa cards. + // + + HalpMapBufferSize = INITIAL_MAP_BUFFER_LARGE_SIZE; + + } + + // + // Allocate map buffers for the adapter objects + // + + HalpMapBufferPhysicalAddress.LowPart = + HalpAllocPhysicalMemory (LoaderBlock, MAXIMUM_PHYSICAL_ADDRESS, + HalpMapBufferSize >> PAGE_SHIFT, TRUE); + HalpMapBufferPhysicalAddress.HighPart = 0; + + + if (!HalpMapBufferPhysicalAddress.LowPart) { + + // + // There was not a satisfactory block. Clear the allocation. + // + + HalpMapBufferSize = 0; + } + + // + // Print copyright notice + // + + HalDisplayString(HalName); + HalDisplayString(SequentCopyright); + + } else { + + // + // Phase 1 initialization + // + + if (pPRCB->Number == 0) { + + HalpRegisterInternalBusHandlers (); + + } else { + + // + // Other processors inherit P0 stall factor. + // This assumes all procs have the same basic speed. + // + + KiPcr()->StallScaleFactor = HalpProcessorPCR[0]->StallScaleFactor; + } + + HalpEnableInterruptHandler ( + DeviceUsage, // Report as device vector + APIC_PROFILE_VECTOR, // Bus interrupt level + APIC_PROFILE_VECTOR, // System IDT + PROFILE_LEVEL, // System Irql + HalpProfileInterrupt, // IRS + Latched ); + + HalpEnableInterruptHandler ( + DeviceUsage, // Report as device vector + APIC_CLOCK_VECTOR, // Bus interrupt level + APIC_CLOCK_VECTOR, // System IDT + CLOCK2_LEVEL, // System Irql + HalpClockInterrupt, // IRS + Latched ); + + HalpEnableInterruptHandler ( + DeviceUsage, // Report as device vector + APIC_IPI_VECTOR, // Bus interrupt level + APIC_IPI_VECTOR, // System IDT + IPI_LEVEL, // System Irql + HalpIpiHandler, // IRS + Latched ); + + } + +#ifndef NT_UP + HalpInitMP (Phase, LoaderBlock); +#endif + + return TRUE; +} + +// +// XXX, hack for now. Need to remove this code. +// + +static UCHAR tmasterline[] = {0, 2, 5, 0}; + +static USHORT cmdport[] /* command port addrs for pics */ + = { PIC1_PORT0, PIC2_PORT0, PIC2_PORT0 }; + +static USHORT imrport[] /* intr mask port addrs for pics */ + = { PIC1_PORT1, PIC2_PORT1, PIC2_PORT1 }; + +VOID +Halptpicinit() +{ + ULONG cmd, imr, pic; + +/* + * --- Initialize the 8259s + */ + +#define PIC_EDGED 0 +#define PIC_ICW1BASE 0x10 +#define PIC_NEEDICW4 1 +#define PIC_86MODE 1 +#define PIC_READISR 0xb +#define PIC_SLAVEBUF 0x8 + /* + * Initialize master ICW1-ICW4 + */ + WRITE_PORT_UCHAR((PUCHAR)cmdport[0], (UCHAR)PIC_EDGED | PIC_ICW1BASE | PIC_NEEDICW4); + WRITE_PORT_UCHAR((PUCHAR)imrport[0], (UCHAR)PIC0_BASE_VECTOR); + WRITE_PORT_UCHAR((PUCHAR)imrport[0], (UCHAR)0x4); /* Cascade IRQ2 */ + WRITE_PORT_UCHAR((PUCHAR)imrport[0], (UCHAR)PIC_86MODE); + + /* OCW1 -- Mask everything for now */ + WRITE_PORT_UCHAR((PUCHAR)imrport[0], (UCHAR)0xFF); + + /* OCW3*/ + WRITE_PORT_UCHAR((PUCHAR)cmdport[0], (UCHAR)PIC_READISR); + + /* + * Initialize slave(s) - We only do 1 slave now.... + */ + for (pic = 1; pic < 2; pic++) + { + cmd = cmdport[pic]; + imr = imrport[pic]; + + /* + * --- Set up ICW1-ICW4 + */ + + WRITE_PORT_UCHAR((PUCHAR)cmd, (UCHAR)(PIC_EDGED | PIC_ICW1BASE | PIC_NEEDICW4)); + WRITE_PORT_UCHAR((PUCHAR)imr, (UCHAR)(PIC0_BASE_VECTOR + (UCHAR)(pic * 8))); + WRITE_PORT_UCHAR((PUCHAR)imr, (UCHAR)tmasterline[pic]); + if (pic == 2) + WRITE_PORT_UCHAR((PUCHAR)imr, (UCHAR)(PIC_SLAVEBUF | PIC_86MODE)); /* Tricord PIC buffered */ + else + WRITE_PORT_UCHAR((PUCHAR)imr, (UCHAR)PIC_86MODE); + + /* OCW1 */ + + WRITE_PORT_UCHAR( (PUCHAR)imr, (UCHAR)0xFF); + + /* OCW3 */ + + WRITE_PORT_UCHAR((PUCHAR)cmd, (UCHAR)PIC_READISR); + } +} + +USHORT +HalpMySlotAddr( + ) +{ + UCHAR slot; + ULONG id; + UCHAR stat; + + for (slot=9; slot <= 15 ; slot++) + { + /* + * --- Insure system bus board is a CPU + */ + id = READ_PORT_ULONG((PULONG)((slot<<12) | 0xC80)); + id = id>>16; + if ((id & 0xf0) == 0x10) + { + stat = READ_PORT_UCHAR((PUCHAR)((slot<<12) | 0xC90)); + + /* + * --- If bus cycle is active it's us! + */ + if ((stat & 0x40) != 0) + break; + } + } + if (slot == 16) + slot = 0; + return (slot << EISA_SHIFT); +} + +VOID +HalpSetProcessorsPresent( + ) + +/*++ + +Routine Description: + + This routine sets a global 32 bit word "ProcessorsPresent" + with a "1" bit for each SYSTEM slot that contains a processor board. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + UCHAR slot; + ULONG cpuid; + + for (slot = FIRST_SYSTEM_SLOT; slot < LAST_SYSTEM_SLOT + 1; slot++) { + cpuid = READ_PORT_ULONG((PULONG)((slot << EISA_SHIFT) | SLOT_ID_REG)); + if ((cpuid & SLOT_ID_BOARDTYPE) == SLOT_ID_TYPECPU) + ProcessorsPresent |= (1 << slot); + } +} 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 diff --git a/private/ntos/nthals/halws3/i386/w3irql.asm b/private/ntos/nthals/halws3/i386/w3irql.asm new file mode 100644 index 000000000..9b830dac6 --- /dev/null +++ b/private/ntos/nthals/halws3/i386/w3irql.asm @@ -0,0 +1,776 @@ + title "Irql Processing" +;++ +; +; Copyright (c) 1989 Microsoft Corporation +; Copyright (c) 1993 Sequent Computer Systems, Inc. +; +; Module Name: +; +; w3irql.asm +; +; Abstract: +; +; WinServer 3000 IRQL implementation. +; +; This module implements the code necessary to raise and lower i386 +; Irql and dispatch software interrupts with the WinServer APIC/PIC system. +; +; Author: +; +; Phil Hochstetler (phil@sequent.com) 3-30-93 +; +; Environment: +; +; Kernel mode only. +; +; Revision History: +; + +.386p + .xlist +include ks386.inc +include callconv.inc ; calling convention macros +include i386\apic.inc +include i386\kimacro.inc +include i386\w3.inc + .list + + EXTRNP _KeBugCheck,1 + EXTRNP _Halptpicinit,0 + EXTRNP _HalpDispatchInterrupt,0 + EXTRNP _HalpApcInterrupt,0 + + extrn _HalpIrql2TPR:byte + extrn _HalpK2Rdir2Irq:byte + extrn _HalpELCRImage:word + extrn _HalpW3BaseIOunitRedirectionTable:dword + extrn _HalpK2EbsIOunitRedirectionTable:dword + extrn _HalpK2EISAIrq2Irql:byte + extrn _HalpK2Irql2Eisa:byte + extrn _HalpActiveProcessors:DWORD + extrn _HalpIrql2IRRMask:dword + extrn ApicSpuriousService@0:near + +_DATA SEGMENT DWORD PUBLIC 'DATA' + +; +; Virtual addresses of the APIC Local and IO units. +; The virtual mapping is done in HalInitializeProcessor. +; + align dword + public _HalpLocalUnitBase, _HalpIOunitBase, _HalpIOunitTwoBase +_HalpLocalUnitBase dd 0 +_HalpIOunitBase dd 0 +_HalpIOunitTwoBase dd 0 + +SyncIdCommand equ DELIVER_INIT + \ + LOGICAL_DESTINATION + \ + LEVEL_TRIGGERED +ResetAllExclSelf equ DELIVER_INIT + \ + LEVEL_TRIGGERED + \ + ICR_LEVEL_ASSERTED + \ + ICR_ALL_EXCL_SELF +UnResetLogical equ DELIVER_INIT + \ + LOGICAL_DESTINATION + \ + LEVEL_TRIGGERED + +; +; This table is used to mask all pending interrupts below a given Irql +; out of the IRR +; + align 4 + + public FindHigherIrqlMask +FindHigherIrqlMask label dword + dd 11111111111111111111111111111110B ; irql 0 + dd 11111111111111111111111111111100B ; irql 1 + dd 11111111111111111111111111111000B ; irql 2 + dd 11111111111111111111111111110000B ; irql 3 + dd 11111111111111111111111111100000B ; irql 4 + dd 11111111111111111111111111000000B ; irql 5 + dd 11111111111111111111111110000000B ; irql 6 + dd 11111111111111111111111100000000B ; irql 7 + dd 11111111111111111111111000000000B ; irql 8 + dd 11111111111111111111110000000000B ; irql 9 + dd 11111111111111111111100000000000B ; irql 10 + dd 11111111111111111111000000000000B ; irql 11 + dd 11111111111111111110000000000000B ; irql 12 + dd 11111111111111111100000000000000B ; irql 13 + dd 11111111111111111000000000000000B ; irql 14 + dd 11111111111111110000000000000000B ; irql 15 + dd 11111111111111100000000000000000B ; irql 16 + dd 11111111111111000000000000000000B ; irql 17 + dd 11111111111110000000000000000000B ; irql 18 + dd 11111111111100000000000000000000B ; irql 19 + dd 11111111111000000000000000000000B ; irql 20 + dd 11111111110000000000000000000000B ; irql 21 + dd 11111111100000000000000000000000B ; irql 22 + dd 11111111000000000000000000000000B ; irql 23 + dd 11111110000000000000000000000000B ; irql 24 + dd 11111100000000000000000000000000B ; irql 25 + dd 11111000000000000000000000000000B ; irql 26 + dd 11110000000000000000000000000000B ; irql 27 + dd 11100000000000000000000000000000B ; irql 28 + dd 11000000000000000000000000000000B ; irql 29 + dd 10000000000000000000000000000000B ; irql 30 + dd 00000000000000000000000000000000B ; irql 31 + +_DATA ENDS + + page ,132 + subttl "RaiseIrql" + +_TEXT$01 SEGMENT PARA PUBLIC 'CODE' + ASSUME DS:FLAT, ES:FLAT, SS:FLAT, FS:NOTHING, GS:NOTHING + +;++ +; +; KIRQL +; KfRaiseIrql ( +; IN KIRQL NewIrql, +; ) +; +; Routine Description: +; +; This routine is used to raise IRQL to the specified value. +; +; *** IMPORTANT IMPLEMENTATION NOTE *** +; Be sure to not write the OldIrql return value until after the +; IRQL has taken effect (due to poor coding practices). +; +; Arguments: +; +; (cl) = NewIrql - the new irql to be raised to +; +; Return Value: +; +; OldIrql - old irql +; +;-- + +cPublicFastCall KfRaiseIrql ,1 +cPublicFpo 0,0 + + mov al, PCR[PcHal.ProcIrql] ; (al) = old irql +if DBG + cmp al, cl ; old > new? + ja short KriErr1 +endif + cmp cl, DISPATCH_LEVEL ; a software level? + ja short @f ; if yes, set the hardware + mov PCR[PcHal.ProcIrql], cl ; Save new irql + fstRET KfRaiseIrql +@@: + mov edx, _HalpLocalUnitBase ; Get address of Local APIC + and ecx, 0ffh ; clear upper 3 bytes + + pushfd ; enter critical region + cli ; + + mov PCR[PcHal.ProcIrql], cl ; Save new irql + mov cl, _HalpIrql2TPR[ecx] ; convert irql to TPR + mov [edx+LU_TPR], ecx ; write new irql + mov ecx, [edx+LU_TPR] ; Flush CPU write buffer + + popfd ; leave critical region + + fstRET KfRaiseIrql +if DBG +cPublicFpo 0, 2 +KriErr1: + movzx eax, al + movzx ecx, cl + push ecx ; put new irql where we can find it + push eax ; put old irql where we can find it + mov byte ptr PCR[PcHal.ProcIrql], 0 ; avoid recursive error + stdCall _KeBugCheck, <IRQL_NOT_GREATER_OR_EQUAL> +endif + +fstENDP KfRaiseIrql + + page ,132 + subttl "LowerIrql" +;++ +; +; VOID +; KfLowerIrql ( +; IN KIRQL NewIrql +; ) +; +; Routine Description: +; +; This routine is used to lower IRQL to the specified value. +; +; Arguments: +; +; (cl) = NewIrql - the new irql to be set. +; +; Return Value: +; +; None. +; +;-- + + +cPublicFastCall KfLowerIrql ,1 +cPublicFpo 0,0 + + movzx ecx, cl ; get new irql value +if DBG + cmp cl, PCR[PcHal.ProcIrql] ; new > old ? + ja KliErr ; panic if so +endif + cmp byte ptr PCR[PcHal.ProcIrql], DISPATCH_LEVEL + ja short KliHW ; if old irql <= 2, software only + mov PCR[PcHal.ProcIrql], cl ; Save new irql +; +; Check for any pending DISPATCH interrupts +; +KliChkSW: + mov edx, PCR[PcIRR] ; get current IRR + and edx, FindHigherIrqlMask[ecx*4] + jnz KliSW +KliEnd: + fstRET KfLowerIrql ; return +KliSW: + pushfd + cli + test dword ptr PCR[PcIRR], (1 SHL DISPATCH_LEVEL) + jz short @f + stdCall _HalpDispatchInterrupt + popfd + xor ecx, ecx + mov cl, PCR[PcHal.ProcIrql] ; restore current irql value + jmp short KliChkSW +@@: + cmp cl, APC_LEVEL + jae short KliPop + test dword ptr PCR[PcIRR], (1 SHL APC_LEVEL) + jz short KliPop + stdCall _HalpApcInterrupt + popfd + xor ecx, ecx + mov cl, PCR[PcHal.ProcIrql] ; restore current irql value + jmp short KliChkSW +KliPop: + popfd + jmp short KliEnd + +; +; Lower APIC Task Priority Register to reflect change in IRQL +; and then check for software interrupts (if below DISPATCH) +; +KliHW: + mov edx, _HalpLocalUnitBase ; get address of Local APIC + pushfd + cli + mov PCR[PcHal.ProcIrql], cl ; Save new irql + mov cl, _HalpIrql2TPR[ecx] ; convert irql to TPR + mov [edx+LU_TPR], ecx ; write new TPR value + mov ecx, [edx+LU_TPR] ; Flush CPU write buffer + popfd + mov cl, byte ptr PCR[PcHal.ProcIrql] ; restore current irql value + cmp cl, DISPATCH_LEVEL + jb KliChkSW + fstRET KfLowerIrql ; return + +if DBG +cPublicFpo 1, 2 +KliErr: + push ecx ; new irql for debugging + mov cl, PCR[PcHal.ProcIrql] ; get old irql + push ecx ; old irql for debugging + mov byte ptr PCR[PcHal.ProcIrql], HIGH_LEVEL ; avoid recursive error + stdCall _KeBugCheck, <IRQL_NOT_LESS_OR_EQUAL> +endif +fstENDP KfLowerIrql + + +;++ +; +; VOID +; KIRQL +; KeRaiseIrqlToDpcLevel ( +; ) +; +; Routine Description: +; +; This routine is used to raise IRQL to DPC level. +; The APIC TPR is used to block all lower-priority HW interrupts. +; +; Arguments: +; +; Return Value: +; +; OldIrql - the addr of a variable which old irql should be stored +; +;-- + +cPublicProc _KeRaiseIrqlToDpcLevel,0 +cPublicFpo 0, 0 + + mov ecx, DISPATCH_LEVEL + jmp @KfRaiseIrql + +stdENDP _KeRaiseIrqlToDpcLevel + + +;++ +; +; VOID +; KIRQL +; KeRaiseIrqlToSynchLevel ( +; ) +; +; Routine Description: +; +; This routine is used to raise IRQL to SYNC level. +; The APIC TPR is used to block all lower-priority HW interrupts. +; +; Arguments: +; +; Return Value: +; +; OldIrql - the addr of a variable which old irql should be stored +; +;-- + +cPublicProc _KeRaiseIrqlToSynchLevel,0 + + mov ecx, SYNCH_LEVEL + jmp @KfRaiseIrql + +stdENDP _KeRaiseIrqlToSynchLevel + + +;++ +; +; KIRQL +; KeGetCurrentIrql (VOID) +; +; Routine Description: +; +; This routine returns to current IRQL. +; +; Arguments: +; +; None. +; +; Return Value: +; +; The current IRQL. +; +;-- + +cPublicProc _KeGetCurrentIrql ,0 + + xor eax, eax + mov al, PCR[PcHal.ProcIrql] ; return 32 bits to cover mistakes + stdRET _KeGetCurrentIrql + +stdENDP _KeGetCurrentIrql + + +;++ +; +; VOID +; _HalpDisableAllInterrupts (VOID) +; +; Routine Description: +; +; This routine is called during a system crash. The hal needs all +; interrupts disabled. +; +; Arguments: +; +; None. +; +; Return Value: +; +; None - all interrupts are masked off +; +;-- + +cPublicProc _HalpDisableAllInterrupts,0 + +; +; Raising to HIGH_LEVEL disables all interrupts +; + + mov ax, 0FFFFh + SET_8259_MASK + mov ecx, HIGH_LEVEL + fstCall KfRaiseIrql + + stdRET _HalpDisableAllInterrupts + +stdENDP _HalpDisableAllInterrupts + +_TEXT$01 ends + + page ,132 + subttl "Interrupt Controller Initialization" + +_TEXT SEGMENT DWORD PUBLIC 'CODE' + ASSUME DS:FLAT, ES:FLAT, SS:FLAT, FS:NOTHING, GS:NOTHING +;++ +; +; VOID +; _HalpInitializePICs ( +; ) +; +; Routine Description: +; +; Call the _Halptpicinit C routine to initialize 8259 and APIC +; +;Arguments: +; +; None +; +; Return Value: +; +; None. +; +;-- +cPublicProc _HalpInitializePICs ,0 + + DISABLE_INTERRUPTS_AT_CPU + + stdCall _HalpInitializeEbsIOunit ; Initialize EBS I/O APIC + stdCall _HalpInitializeBaseIOunit ; Initialize P0 I/O APIC + stdCall _Halptpicinit ; Initialize PICs + + RESTORE_INTERRUPTS_AT_CPU + + stdRET _HalpInitializePICs + +stdENDP _HalpInitializePICs + + page ,132 + subttl "APIC EBS IO Unit Initialization" +;++ +; +; VOID +; HalpInitializeEbsIOUnit ( +; ) +; +; Routine Description: +; +; This routine initializes the interrupt structures for the IO unit of +; the 82489DX APIC. It masks all interrupt inputs in the redirection +; table - these will be unmasked when the interrupts are enabled by +; HalpEnableSystemInterrupt. +; +; HalpInitializeIOunit is called by HalpInitializePics during Phase 0 +; initialization. It is executed by P0 only, and executes AFTER the +; local unit is initialized. This procedure assumes that the APIC virtual +; address space has been mapped. +; +; The I/O unit for external WinServer 3000 interrupts resides on the +; EBS module. +; +; Arguments: +; +; None +; +; Return Value: +; +; None. +; +;-- + +cPublicProc _HalpInitializeEbsIOUnit ,0 + + push esi ; save regs + push ebx ; + +; +; When using the Intel 82350 ISP Chipset the interrupt edge/level definitions +; are readable from the ISP's edge/level control register (ELCR). +; +; Read the ELCR so the input polarity control XOR gates on the APIC interrupt +; inputs can be programmed. This whole thing works because EISA defines edge +; -triggered interrupts as active-high and level interrupts as active-low. +; +; We will use the ELCR later to set the ACTIVE_LOW bit as required in the +; IOunit redirection table. +; + mov dx, PIC2_ELCR_PORT ; read the edge/level control reg + in al, dx + shl ax, 8 + mov dx, PIC1_ELCR_PORT + in al, dx + and ax, ELCR_MASK ; clear reserved IRQs + mov _HalpELCRImage, ax ; save the image for later +; +; load addresses of the register-select register and register-window register +; + mov ecx, _HalpIOunitBase + lea edx, [ecx+IO_REGISTER_SELECT] + lea ecx, [ecx+IO_REGISTER_WINDOW] + +; +; write the I/O unit APIC-ID - Since we are using the Processor +; Numbers for the local unit ID's we need to set the IO unit +; to a high (out of Processor Number range) value. +; + mov dword ptr [edx], IO_ID_REGISTER + mov dword ptr [ecx], (IOUNIT_APIC_ID SHL APIC_ID_SHIFT) + +; +; program the redirection table +; + mov ebx, IO_REDIR_00_LOW ; [EBX] has register select + lea esi, _HalpK2EbsIOunitRedirectionTable ; [ESI] has address of image + +RedirLoop1: + lodsd ; load low dword + or eax, eax ; end of table? + jz RedirLoopExit1 ; yup - we're done + push ebx + push ecx + push eax + sub ebx, IO_REDIR_00_LOW + shr ebx, 1 ; Form RDIR # + xor ecx,ecx + mov cl, _HalpK2Rdir2Irq[ebx] ; Form IRQ # + xor eax, eax ; clear reg. + mov ax, _HalpELCRImage + bt eax, ecx + pop eax + pop ecx +; Note: 0 will result for all K2 IRQs, this is what we want.... + jnc @f ; bit is 0 => active high (default) + ; eax is val + ; ebx in RDIR entry # + or eax, LEVEL_TRIGGERED ; This is a level triggered interrupt +; +; We must tell the hardware to invert the polarity for level triggered +; interrupts because APIC is "active HIGH", EISA is active low for level +; triggered interrupts...so tickle the K2 EISA to APIC Polarity Register.. +; + push eax + push edx + mov dx, EISA_2_MPIC_POLARITY_REG + in al, dx + bts eax, ebx ; + out dx, al + pop edx + pop eax +@@: + pop ebx + mov dword ptr [edx], ebx ; write to select register + mov dword ptr [ecx], eax ; write redirection table entry + inc ebx ; increment to next entry + lodsd ; load high dword + mov dword ptr [edx], ebx ; write to select register + mov dword ptr [ecx], eax ; write redirection table entry + inc ebx ; increment to next entry + jmp RedirLoop1 ; continue... +RedirLoopExit1: + + pop ebx ; restore registers and return + pop esi ; + stdRET _HalpInitializeEbsIOUnit +stdENDP _HalpInitializeEbsIOUnit + page ,132 + subttl "APIC Base IO Unit Initialization" +;++ +; +; VOID +; HalpInitializeBaseIOUnit ( +; ) +; +; Routine Description: +; +; This routine initializes the interrupt structures for the IO unit of +; the 82489DX APIC. It masks all interrupt inputs in the redirection +; table - these will be unmasked when the interrupts are enabled by +; HalpEnableSystemInterrupt. +; +; HalpInitializeIOunit is called by HalpInitializePics during Phase 0 +; initialization. It is executed by CPU0 only, and executes AFTER the +; local unit is initialized. This procedure assumes that the APIC virtual +; address space has been mapped. +; +; The I/O unit for external K2 interrupts resides on the EBS module. +; +; Arguments: +; +; None +; +; Return Value: +; +; None. +; +;-- + +cPublicProc _HalpInitializeBaseIOUnit ,0 + + push esi ; save regs + push ebx ; + +; +; load addresses of the register-select register and register-window register +; + mov ecx, _HalpIOunitTwoBase + lea edx, [ecx+IO_REGISTER_SELECT] + lea ecx, [ecx+IO_REGISTER_WINDOW] +; +; write the I/O unit APIC-ID - Since we are using the Processor +; Numbers for the local unit ID's we need to set the 2nd IO unit +; to a high (out of Processor Number range) value (but != other IO unit). +; + mov dword ptr [edx], IO_ID_REGISTER + mov dword ptr [ecx], (IOUNIT2_APIC_ID SHL APIC_ID_SHIFT) + +; +; re-program the redirection table +; + mov ebx, IO_REDIR_00_LOW ; [EBX] has register select + lea esi, _HalpW3BaseIOunitRedirectionTable ; [ESI] has address of image + +RedirLoop: + lodsd ; load low dword + or eax, eax ; end of table? + jz RedirLoopExit ; yup - we're done + mov dword ptr [edx], ebx ; write to select register + mov dword ptr [ecx], eax ; write redirection table entry + inc ebx ; increment to next entry + lodsd ; load high dword + mov dword ptr [edx], ebx ; write to select register + mov dword ptr [ecx], eax ; write redirection table entry + inc ebx ; increment to next entry + jmp RedirLoop ; continue... +RedirLoopExit: + + pop ebx ; restore registers and return + pop esi ; + stdRET _HalpInitializeBaseIOUnit +stdENDP _HalpInitializeBaseIOUnit + +cPublicProc _HalpUnResetLocalUnit ,1 + + movzx ecx, byte ptr [esp+4] ; get CPU logical number + xor eax, eax + bts eax, ecx ; convert to bit mask of 1 bit + mov ecx, _HalpLocalUnitBase ; pointer to local unit + + DISABLE_INTERRUPTS_AT_CPU + +@@: test dword ptr [ecx+LU_INT_CMD_LOW], DELIVERY_PENDING + jnz short @b + + mov dword ptr [ecx+LU_INT_CMD_HIGH], eax ; destination bit mask + mov dword ptr [ecx+LU_INT_CMD_LOW], UnResetLogical + + RESTORE_INTERRUPTS_AT_CPU + + stdRET _HalpUnResetLocalUnit + +stdENDP _HalpUnResetLocalUnit + +cPublicProc _HalpResetLocalUnits ,0 + + mov ecx, _HalpLocalUnitBase ; pointer to local unit + + DISABLE_INTERRUPTS_AT_CPU + +@@: test dword ptr [ecx+LU_INT_CMD_LOW], DELIVERY_PENDING + jnz short @b + + mov dword ptr [ecx+LU_INT_CMD_LOW], ResetAllExclSelf + + RESTORE_INTERRUPTS_AT_CPU + + stdRET _HalpResetLocalUnits +stdENDP _HalpResetLocalUnits + + page ,132 + subttl "APIC Local Unit Initialization" +;++ +; +; VOID +; HalpInitializeLocalUnit ( +; ) +; +; Routine Description: +; +; This routine initializes the interrupt structures for the local unit +; of the 82489DX APIC. This procedure is called by HalInitializeProcessor +; as it is executed by each CPU. +; +; Arguments: +; +; None +; +; Return Value: +; +; None. +; +;-- + +APIC_ENABLE equ (APIC_SPURIOUS_VECTOR OR LU_UNIT_ENABLED) + +cPublicProc _HalpInitializeLocalUnit ,0 +cPublicFpo 0, 1 + + pushfd + cli + + mov edx, _HalpLocalUnitBase ; base address of local unit + mov dword ptr [edx+LU_TPR], 0FFh ; Disable all interrupts + movzx eax, byte ptr PCR[PcHal.PcrNumber] ; use CPU number for APIC-id + mov dword ptr [edx+LU_DEST_FORMAT], LU_DEST_FORMAT_FLAT + xor ecx, ecx ; zero bitmask + bts ecx, eax ; create logical dest bitmask + mov [edx+LU_LOGICAL_DEST], ecx ; and set it + shl eax, APIC_ID_SHIFT ; ID_REGISTER has ID in MSB + mov dword ptr [edx+LU_ID_REGISTER], eax ; set local unit ID +; +; APIC does not seem to see a hardware reset across a reboot thus an interrupt +; could have been taken but the EOI is never written. The BIOS does not +; recover from this condition so we must do it here. Many days with a logic +; analyzer finally found this one. If there are any ISR bits set, clear +; one by a write to the EOI register and look again. +; +@@: + mov eax, [edx+LU_ISR_0+000h] ; read ISR 0 + or eax, [edx+LU_ISR_0+010h] ; read ISR 1 + or eax, [edx+LU_ISR_0+020h] ; read ISR 2 + or eax, [edx+LU_ISR_0+030h] ; read ISR 3 + or eax, [edx+LU_ISR_0+040h] ; read ISR 4 + or eax, [edx+LU_ISR_0+050h] ; read ISR 5 + or eax, [edx+LU_ISR_0+060h] ; read ISR 6 + or eax, [edx+LU_ISR_0+070h] ; read ISR 7 + jz short @f + mov dword ptr [edx+LU_EOI], eax ; clear highest ISR bit + jmp short @b +@@: + mov dword ptr [edx+LU_SPURIOUS_VECTOR], APIC_ENABLE +; +; Sync all APIC IDs by using Data Sheet recommended procedure +; + xor eax, eax + mov dword ptr [edx+LU_INT_CMD_HIGH], eax + mov dword ptr [edx+LU_INT_CMD_LOW], SyncIdCommand +; +; we're done - set TPR back to zero and return +; + mov PCR[PcHal.ProcIrql], al ; Set CurrentIrql=0 + mov [edx+LU_TPR], eax + +; +; Program in the spurious interrupt vector into the IDT +; + IDTEntry APIC_SPURIOUS_VECTOR, ApicSpuriousService@0 + + popfd + + stdRET _HalpInitializeLocalUnit + +stdENDP _HalpInitializeLocalUnit + +_TEXT ends + + end diff --git a/private/ntos/nthals/halws3/i386/w3nmi.c b/private/ntos/nthals/halws3/i386/w3nmi.c new file mode 100644 index 000000000..a368bf610 --- /dev/null +++ b/private/ntos/nthals/halws3/i386/w3nmi.c @@ -0,0 +1,78 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation +Copyright (c) 1993 Sequent Computer Systems, Inc. + +Module Name: + + ws3nmi.c + +Abstract: + + Provides x86 NMI handler for the WinServer 3000. + +Author: + + Phil Hochstetler (phil@sequent.com) 3-30-93 + +Revision History: + +--*/ +#include "halp.h" +#include "bugcodes.h" +#include "w3.inc" + + +VOID +HalHandleNMI( + IN OUT PVOID NmiInfo + ) +/*++ + +Routine Description: + + Called DURING an NMI. The system will BugCheck when an NMI occurs. + This function can return the proper bugcheck code, bugcheck itself, + or return success which will cause the system to iret from the nmi. + + This function is called during an NMI - no system services are available. + In addition, you don't want to touch any spinlock which is normally + used since we may have been interrupted while owning it, etc, etc... + +Warnings: + + Do NOT: + Make any system calls + Attempt to acquire any spinlock used by any code outside the NMI handler + Change the interrupt state. Do not execute any IRET inside this code + + Passing data to non-NMI code must be done using manual interlocked + functions. (xchg instructions). + +Arguments: + + NmiInfo - Pointer to NMI information structure (TBD) + - NULL means no NMI information structure was passed + +Return Value: + + BugCheck code + +--*/ +{ + // + // We can not look at the hardware to determine the source + // of the error because reads of many error registers clear + // the error and the IMP board is racing with us. + // + // If support for systems without an IMP board is added, we need + // to duplicate all the error reporting of the IMP board here. + // + + HalDisplayString (MSG_HARDWARE_ERROR1); + HalDisplayString (MSG_HARDWARE_ERROR2); + HalDisplayString ("NMI: The system has detected a fatal NMI\n"); + HalDisplayString (MSG_HALT); + + KeEnterKernelDebugger(); +} diff --git a/private/ntos/nthals/halws3/i386/w3profil.asm b/private/ntos/nthals/halws3/i386/w3profil.asm new file mode 100644 index 000000000..8d8c58ff4 --- /dev/null +++ b/private/ntos/nthals/halws3/i386/w3profil.asm @@ -0,0 +1,223 @@ + title "Profile Support" +;++ +; +; Copyright (c) 1989 Microsoft Corporation +; Copyright (c) 1994 Sequent Computer Systems, Inc. +; +; Module Name: +; +; w3profil.asm +; +; Abstract: +; +; This module implements the code necessary to initialize, +; field, and process the profile interrupt. +; +; Author: +; +; Phil Hochstetler (phil@sequent.com) 3-30-93 +; +; Environment: +; +; Kernel mode only. +; +; Revision History: +; +;-- + +.386p + .xlist +include hal386.inc +include callconv.inc +include i386\kimacro.inc +include mac386.inc +include i386\apic.inc +include i386\ixcmos.inc +include i386\w3.inc + .list + + EXTRNP _DbgBreakPoint,0,IMPORT + EXTRNP _KeProfileInterrupt,1,IMPORT + EXTRNP Kei386EoiHelper,0,IMPORT + EXTRNP _HalEndSystemInterrupt,2 + EXTRNP _HalBeginSystemInterrupt,3 + extrn _HalpLocalUnitBase:DWORD + +; +; APIC Timer Constants +; + +APIC_TIMER_DISABLED equ (INTERRUPT_MASKED OR PERIODIC_TIMER OR APIC_PROFILE_VECTOR) +APIC_TIMER_ENABLED equ (PERIODIC_TIMER OR APIC_PROFILE_VECTOR) + +_DATA SEGMENT DWORD PUBLIC 'DATA' + + +ProfileCountDownValue dd (200 * 11) +HalpProfileRunning dd 0 + +_DATA ends + +_TEXT SEGMENT DWORD PUBLIC 'CODE' + ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING +;++ +; +; HalStartProfileInterrupt( +; IN ULONG Reserved +; ); +; +; Routine Description: +; +; What we do here is set the interrupt rate to the value that's been set +; by the KeSetProfileInterval routine. Then enable the APIC Timer interrupt. +; This function gets called on every processor so the hal can enable +; a profile interrupt on each processor. +;-- + +cPublicProc _HalStartProfileInterrupt ,1 +cPublicFpo 1, 0 + + mov ecx, _HalpLocalUnitBase ; load base address of local unit + +; +; Set the interrupt rate to what is actually needed. +; + + mov eax, ProfileCountDownValue + mov [ecx+LU_INITIAL_COUNT], eax + +; +; Set the Local APIC Timer to interrupt Periodically at APIC_PROFILE_VECTOR +; + + mov [ecx+LU_TIMER_VECTOR], APIC_TIMER_ENABLED + + + stdRET _HalStartProfileInterrupt + +stdENDP _HalStartProfileInterrupt + + + +;++ +; +; HalStopProfileInterrupt( +; IN ULONG Reserved +; ); +; +; Routine Description: +; +;-- + +cPublicProc _HalStopProfileInterrupt ,1 +cPublicFpo 1, 0 + + mov ecx, _HalpLocalUnitBase ; load base address of local unit + mov [ecx+LU_TIMER_VECTOR], APIC_TIMER_DISABLED + + stdRET _HalStopProfileInterrupt + +stdENDP _HalStopProfileInterrupt + +;++ +; ULONG +; HalSetProfileInterval ( +; ULONG Interval +; ); +; +; Routine Description: +; +; This procedure sets the interrupt rate (and thus the sampling +; interval) for the profiling interrupt. +; +; Arguments: +; +; (TOS+4) - Interval in 100ns unit. +; +; Return Value: +; +; Interval actually used by system. +;-- + +cPublicProc _HalSetProfileInterval ,1 +cPublicFpo 1, 0 + +; +; --- On the WinServer 3000, the profile timer uses TBASE on the local APIC +; Timer zero. The TMBASE clock runs at 11Mhz so each clock tick is +; equal to 90.9090ns or roughly 91ns. Since this is close to 100ns +; we will use the 100ns units at the timer counter value directly. +; To use an accurate muliple of 100ns units the profiler would have +; to use 1000ns (1usec) intervals, this interval is equal to 11 clock +; ticks. +; + + mov eax, [esp+4] ; ecx = interval in 100ns unit + + mov ProfileCountDownValue, eax ; Save the Computed Count Down + mov ecx, _HalpLocalUnitBase ; load base address of local unit + + ; + ; Set the interrupt rate in the chip. + ; + + mov [ecx+LU_INITIAL_COUNT], eax + + stdRET _HalSetProfileInterval + +stdENDP _HalSetProfileInterval + + page ,132 + subttl "System Profile Interrupt" +;++ +; +; Routine Description: +; +; This routine is entered as the result of a profile interrupt. +; Its function is to dismiss the interrupt, raise system Irql to +; PROFILE_LEVEL and transfer control to +; the standard system routine to process any active profiles. +; +; Arguments: +; +; None +; Interrupt is disabled +; +; Return Value: +; +; Does not return, jumps directly to KeProfileInterrupt, which returns +; +; Sets Irql = PROFILE_LEVEL and dismisses the interrupt +; +;-- + ENTER_DR_ASSIST Hpi_a, Hpi_t + +cPublicProc _HalpProfileInterrupt ,0 +; +; Save machine state in trap frame +; + + ENTER_INTERRUPT Hpi_a, Hpi_t + +; +; (esp) - base of trap frame +; + + push APIC_PROFILE_VECTOR + sub esp, 4 ; allocate space to save OldIrql + stdCall _HalBeginSystemInterrupt, <PROFILE_LEVEL,APIC_PROFILE_VECTOR,esp> + or al,al ; check for spurious interrupt + jz Hpi100 + + stdCall _KeProfileInterrupt,<ebp> ; (ebp) = TrapFrame address + + INTERRUPT_EXIT +Hpi100: + add esp, 8 ; spurious, no EndOfInterrupt + SPURIOUS_INTERRUPT_EXIT + +stdENDP _HalpProfileInterrupt + +_TEXT ends + + end diff --git a/private/ntos/nthals/halws3/i386/w3space.asm b/private/ntos/nthals/halws3/i386/w3space.asm new file mode 100644 index 000000000..ea6a125dc --- /dev/null +++ b/private/ntos/nthals/halws3/i386/w3space.asm @@ -0,0 +1,1346 @@ + title "Global Storage and Tables" +;++ +; +; Copyright (c) 1991 Microsoft Corporation +; Copyright (c) 1993 Sequent Computer Systems, Inc. +; +; Module Name: +; +; w3space.asm +; +; Abstract: +; +; This module contains global storage and tables +; used by the WinServer 3000 HAL implementation. +; +; Author: +; +; Phil Hochstetler (phil@sequent.com) 3-30-93 +; +; Environment: +; +; Kernel Mode +; +; Revision History: +; +;-- + +.386p + .xlist +include ks386.inc +include callconv.inc ; calling convention macros +include i386\kimacro.inc +include mac386.inc +include i386\apic.inc +include i386\w3.inc + .list + + extrn _HalpBeginW3InvalidInterrupt:near + extrn _HalpBeginW3APICInterrupt:near + +_DATA SEGMENT DWORD PUBLIC 'DATA' + +; +; This location is used to store the EISA Edge/Level Register +; contents read once during initialization. +; + align 4 + public _HalpELCRImage +_HalpELCRImage label word + dw 0 + +; +; This location is used to keep state around when a +; level PIC interrupt occurs. +; + align 4 + public _HalpMASKED +_HalpMASKED label word + dw 0 + +; +; The following location is used to keep a software copy +; of the Post Code Register (register is write only). Used +; to run front panel lights on the WinServer 3000. +; + align 4 + public _HalpW3PostRegisterImage +_HalpW3PostRegisterImage label dword + dd 0 + +; +; Table to convert an Irql to a mask that looks for bits to +; be exposed in the software copy of the IRR. +; + align 4 + public _HalpIrql2IRRMask +_HalpIrql2IRRMask label dword + dd 11111111111111111111111111111110B ; irql 0 + dd 11111111111111111111111111111100B ; irql 1 + dd 11111111111111111111111111111000B ; irql 2 + dd 11111111111111111111111111110000B ; irql 3 + dd 11111111111111111111111111100000B ; irql 4 + dd 11111111111111111111111111000000B ; irql 5 + dd 11111111111111111111111110000000B ; irql 6 + dd 11111111111111111111111100000000B ; irql 7 + dd 11111111111111111111111000000000B ; irql 8 + dd 11111111111111111111110000000000B ; irql 9 + dd 11111111111111111111100000000000B ; irql 10 + dd 11111111111111111111000000000000B ; irql 11 + dd 11111111111111111110000000000000B ; irql 12 + dd 11111111111111111100000000000000B ; irql 13 + dd 11111111111111111000000000000000B ; irql 14 + dd 11111111111111110000000000000000B ; irql 15 + dd 11111111111111100000000000000000B ; irql 16 + dd 11111111111111000000000000000000B ; irql 17 + dd 11111111111110000000000000000000B ; irql 18 + dd 11111111111100000000000000000000B ; irql 19 + dd 11111111111000000000000000000000B ; irql 20 + dd 11111111110000000000000000000000B ; irql 21 + dd 11111111100000000000000000000000B ; irql 22 + dd 11111111000000000000000000000000B ; irql 23 + dd 11111110000000000000000000000000B ; irql 24 + dd 11111100000000000000000000000000B ; irql 25 + dd 11111000000000000000000000000000B ; irql 26 + dd 11110000000000000000000000000000B ; irql 27 + dd 11100000000000000000000000000000B ; irql 28 + dd 11000000000000000000000000000000B ; irql 29 + dd 10000000000000000000000000000000B ; irql 30 + dd 00000000000000000000000000000000B ; irql 31 + +; +; +; HalpBeginW3Interrupt does an indirect jump through this table so it +; can quickly execute specific code for different interrupts. Vectors +; are assigned to accomodate NT IRQL requirements and the APIC task +; priority register definition. +; + align 4 + public _HalpBeginW3InterruptTable +_HalpBeginW3InterruptTable label dword + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; Vector 0 + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; 10 + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; 20 + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; 50 - Wake + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3APICInterrupt ; 60 - IRQ16 + dd offset FLAT:_HalpBeginW3APICInterrupt ; 61 - IRQ17 + dd offset FLAT:_HalpBeginW3APICInterrupt ; 62 - IRQ18 + dd offset FLAT:_HalpBeginW3APICInterrupt ; 63 - IRQ19 + dd offset FLAT:_HalpBeginW3APICInterrupt ; 64 - IRQ20 + dd offset FLAT:_HalpBeginW3APICInterrupt ; 65 - IRQ21 + dd offset FLAT:_HalpBeginW3APICInterrupt ; 66 - IRQ22 + dd offset FLAT:_HalpBeginW3APICInterrupt ; 67 - IRQ23 + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3APICInterrupt ; 70 - IRQ8 + dd offset FLAT:_HalpBeginW3APICInterrupt ; 71 - IRQ9 + dd offset FLAT:_HalpBeginW3APICInterrupt ; 72 - IRQ10 + dd offset FLAT:_HalpBeginW3APICInterrupt ; 73 - IRQ11 + dd offset FLAT:_HalpBeginW3APICInterrupt ; 74 - IRQ12 + dd offset FLAT:_HalpBeginW3APICInterrupt ; 75 - IRQ13 + dd offset FLAT:_HalpBeginW3APICInterrupt ; 76 - IRQ14 + dd offset FLAT:_HalpBeginW3APICInterrupt ; 77 - IRQ15 + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; 80 - IRQ0 + dd offset FLAT:_HalpBeginW3APICInterrupt ; 81 - IRQ1 + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; 82 - IRQ2 + dd offset FLAT:_HalpBeginW3APICInterrupt ; 83 - IRQ3 + dd offset FLAT:_HalpBeginW3APICInterrupt ; 84 - IRQ4 + dd offset FLAT:_HalpBeginW3APICInterrupt ; 85 - IRQ5 + dd offset FLAT:_HalpBeginW3APICInterrupt ; 86 - IRQ6 + dd offset FLAT:_HalpBeginW3APICInterrupt ; 87 - IRQ7 + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3APICInterrupt ; 90 - Profile + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3APICInterrupt ; A0 - Clock + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3APICInterrupt ; B0 - IPI + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3APICInterrupt ; C0 - Powerfail + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; D0 - IRQ0 8259 + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; DF - IRQ15 8259 + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; E0 - APIC_SPURIOUS + dd offset FLAT:_HalpBeginW3APICInterrupt ; E1 - APIC_SYSINT + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; F0 + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; .. + dd offset FLAT:_HalpBeginW3InvalidInterrupt ; Vector FF +; +; This table is used by KeRaiseIrql and KeLowerIrql to convert an IRQL +; value to an APIC task priority value. The APIC uses groups of 16 +; interrupt vectors for each task priority. Windows NT has allowed us +; to use vectors 48-255 for external interrupt processing. This means we +; actually have 14 hardware priorities available to work with. We only +; use 11. +; +; To simplify the prioritization of PIC interrupts we decided to only create +; 3 hardware priorities, i.e., 1 for each PIC. This keeps us from using +; up all of the vectors in case we need them in the future and creates +; less confusion about IRQ numbers and priority.. +; +; The hardware priorities, vectors and APIC task priorities for the 32 +; NT IRQLs are established as follows: +; + align 4 + public _HalpIrql2TPR +_HalpIrql2TPR label byte + db 0 SHL 4 ; IRQL = 0, tpr = 0:0 - Low + db 0 SHL 4 ; IRQL = 1, tpr = 0:0 - APC + db 0 SHL 4 ; IRQL = 2, tpr = 0:0 - DPC + db 0 SHL 4 ; IRQL = 3, tpr = 0:0 - Wake +; +; --- Divide the 24 device IRQLs into 3 hardware priority levels +; ...1 for each 8259 PIC grouping....PIC 1 is highest priority +; +; PIC3 + db 6 SHL 4 ; IRQL = 4, tpr = 6:0 - IRQ23 - + db 6 SHL 4 ; IRQL = 5, tpr = 6:0 - IRQ22 - + db 6 SHL 4 ; IRQL = 6, tpr = 6:0 - IRQ21 - + db 6 SHL 4 ; IRQL = 7, tpr = 6:0 - IRQ20 - + db 6 SHL 4 ; IRQL = 8, tpr = 6:0 - IRQ19 - + db 6 SHL 4 ; IRQL = 9, tpr = 6:0 - IRQ18 - + db 6 SHL 4 ; IRQL = 10, tpr = 6:0 - IRQ17 + db 6 SHL 4 ; IRQL = 11, tpr = 6:0 - IRQ16 - +; PIC2 + db 7 SHL 4 ; IRQL = 12, tpr = 7:0 - IRQ15 - + db 7 SHL 4 ; IRQL = 13, tpr = 7:0 - IRQ14 - + db 7 SHL 4 ; IRQL = 14, tpr = 7:0 - IRQ13 - + db 7 SHL 4 ; IRQL = 15, tpr = 7:0 - IRQ12 - + db 7 SHL 4 ; IRQL = 16, tpr = 7:0 - IRQ11 - + db 7 SHL 4 ; IRQL = 17, tpr = 7:0 - IRQ10 - + db 7 SHL 4 ; IRQL = 18, tpr = 7:0 - IRQ9 - + db 7 SHL 4 ; IRQL = 19, tpr = 7:0 - IRQ8 - +; PIC1 + db 8 SHL 4 ; IRQL = 20, tpr = 8:0 - IRQ7 - + db 8 SHL 4 ; IRQL = 21, tpr = 8:0 - IRQ6 - + db 8 SHL 4 ; IRQL = 22, tpr = 8:0 - IRQ5 - + db 8 SHL 4 ; IRQL = 23, tpr = 8:0 - IRQ4 - + db 8 SHL 4 ; IRQL = 24, tpr = 8:0 - IRQ3 - +; IRQ2 is dropped due to being invalid + db 8 SHL 4 ; IRQL = 25, tpr = 8:0 - IRQ1 - + db 8 SHL 4 ; IRQL = 26, tpr = 8:0 - IRQ0 - +; + db 9 SHL 4 ; IRQL = 27, tpr = 9:0 - Profile + db 10 SHL 4 ; IRQL = 28, tpr = 10:0 - Clock - + db 11 SHL 4 ; IRQL = 29, tpr = 11:0 - IPI - + db 12 SHL 4 ; IRQL = 30, tpr = 12:0 - Power + db 13 SHL 4 ; IRQL = 31, tpr = 13:0 - High +; + align 4 +; +; --- The following table is used to convert a given interrupt vector +; to a specific APIC Redirection table entry address. The redirection +; table entries are used to mask/unmask interrupts, target interrupts, +; and specify vectors for APIC interrupts. +; +; The value of each table entry is defined as follows: +; +; 0ybbbbbbb - RDIR window address +; y = 0 - EBS RDIR entry +; y = 1 - Base Processor I/O APIC RDIR entry +; bbbbbbb = I/O Window address of RDIR entry +; 00 - Vector unused/invalid +; FF - Vector used but no RDIR enable mask needed +; + + public _HalpK2Vector2RdirTabEntry +_HalpK2Vector2RdirTabEntry label byte + db 000H ; Vector 0 + db 0ACH ; Vector 2 - SYS_NMI - Base I/O APIC + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; 10 + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; 20 + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 0FFH ; 30 - APC + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 0FFH ; 40 - DPC + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 020H ; 60 - EBS RDIR 8 - IRQ16 + db 02EH ; EBS RDIR 15 - IRQ17 + db 02CH ; EBS RDIR 14 - IRQ18 + db 02AH ; EBS RDIR 13 - IRQ19 + db 028H ; EBS RDIR 12 - IRQ20 + db 026H ; EBS RDIR 11 - IRQ21 + db 024H ; EBS RDIR 10 - IRQ22 + db 022H ; EBS RDIR 9 - IRQ23 + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; 70 + db 018H ; EBS RDIR 4 - IRQ9 + db 01AH ; EBS RDIR 5 - IRQ10 + db 01CH ; EBS RDIR 6 - IRQ11 + db 000H ; + db 000H ; + db 000H ; + db 01EH ; EBS RDIR 7 - IRQ15 + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; 80 + db 000H ; + db 000H ; + db 010H ; EBS RDIR 0 - IRQ3 + db 012H ; EBS RDIR 1 - IRQ4 + db 014H ; EBS RDIR 2 - IRQ5 + db 000H ; + db 016H ; EBS RDIR 3 - IRQ7 + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 0FFH ; 90 - Profile + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; A0 + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 0FFH ; B0 + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 0A0H ; C0 - Power Fail, I/O RDIR 8 + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; D0 - High + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 0FFH ; E0 - APIC Spurious + db 0AAH ; E1 - SYS_INT I/O RDIR 13 + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; F0 + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; FF +; +; +; The following table is used to convert a vector number to an +; EISA IRQ number. It is used by Begin and End System interrupt +; to know when to do an EOI for edge and level interrupt considerations +; + align 4 + public _HalpK2Vector2EISA +_HalpK2Vector2EISA label byte + db 000H ; Vector 0 + db 000H ; Vector 2 - SYS_NMI - Base I/O APIC + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; 16 + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; 32 + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; 48 - APC + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; 64 - DPC + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 16 ; 96 - IRQ16 + db 17 ; - IRQ17 + db 18 ; - IRQ18 + db 19 ; - IRQ19 + db 20 ; - IRQ20 + db 21 ; - IRQ21 + db 22 ; - IRQ22 + db 23 ; - IRQ23 + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 8 ; 112 - IRQ8 + db 9 ; - IRQ9 + db 10 ; - IRQ10 + db 11 ; - IRQ11 + db 12 ; - IRQ12 + db 13 ; - IRQ13 + db 14 ; - IRQ14 + db 15 ; - IRQ15 + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 0 ; 128 - IRQ0 + db 1 ; - IRQ1 + db 2 ; - IRQ2 + db 3 ; - IRQ3 + db 4 ; - IRQ4 + db 5 ; - IRQ5 + db 6 ; - IRQ6 + db 7 ; - IRQ7 + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 8 ; 144 - Profile + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; 160 - IRQ0 , Clock + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; 176 - IPI + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; 192 - Power Fail, I/O RDIR 8 + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; 208 - High + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; 224 - APIC Spurious + db 000H ; 225 - SYS_ATTN I/O RDIR 7 + db 000H ; 226 - SYS_TIMEOUT " " 9 + db 000H ; 227 - SYS_ERROR " " 10 + db 000H ; 228 - SYS_EISA_PERR " 11 + db 000H ; 229 - SYS_IMS_ATTN " 12 + db 000H ; 230 - SYS_INT " " 13 + db 000H ; 231 - LOCAL_RESET " " 15 + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; 240 + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; + db 000H ; 255 +; + align 4 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; This table is used to convert a designated IRQL number to +; a specific interrupt vector. This is used by the generate +; software interrupt mechanism and HalGetInterruptVector... +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + public _HalpIRQLtoTPR +_HalpIRQLtoTPR label byte + db 0 ; IRQL = 0, tpr = 0 - Low + db APIC_APC_VECTOR ; IRQL = 1, tpr = 3 - APC + db APIC_DPC_VECTOR ; IRQL = 2, tpr = 4 - DPC + db 0 ; IRQL = 3, tpr = 5 +; +; --- Divide the 24 device IRQLs into 3 hardware priority levels +; ...1 for each 8259 PIC grouping....PIC 1 is highest priority +; +; PIC3 + db APIC_IRQ23_VECTOR ; IRQL = 4, tpr = 6 - IRQ23 + db APIC_IRQ22_VECTOR ; IRQL = 5, tpr = 6 - IRQ22 + db APIC_IRQ21_VECTOR ; IRQL = 6, tpr = 6 - IRQ21 + db APIC_IRQ20_VECTOR ; IRQL = 7, tpr = 6 - IRQ20 + db APIC_IRQ19_VECTOR ; IRQL = 8, tpr = 6 - IRQ19 + db APIC_IRQ18_VECTOR ; IRQL = 9, tpr = 6 - IRQ18 + db APIC_IRQ17_VECTOR ; IRQL = 10, tpr = 6 - IRQ17 + db APIC_IRQ16_VECTOR ; IRQL = 11, tpr = 6 - IRQ16 +; PIC2 + db APIC_IRQ15_VECTOR ; IRQL = 12, tpr = 7 - IRQ15 + db APIC_IRQ14_VECTOR ; IRQL = 13, tpr = 7 - IRQ14 + db APIC_IRQ13_VECTOR ; IRQL = 14, tpr = 7 - IRQ13 + db APIC_IRQ12_VECTOR ; IRQL = 15, tpr = 7 - IRQ12 + db APIC_IRQ11_VECTOR ; IRQL = 16, tpr = 7 - IRQ11 + db APIC_IRQ10_VECTOR ; IRQL = 17, tpr = 7 - IRQ10 + db APIC_IRQ9_VECTOR ; IRQL = 18, tpr = 7 - IRQ9 + db APIC_IRQ8_VECTOR ; IRQL = 19, tpr = 7 - IRQ8 +; PIC1 + db APIC_IRQ7_VECTOR ; IRQL = 20, tpr = 8 - IRQ7 + db APIC_IRQ6_VECTOR ; IRQL = 21, tpr = 8 - IRQ6 + db APIC_IRQ5_VECTOR ; IRQL = 22, tpr = 8 - IRQ5 + db APIC_IRQ4_VECTOR ; IRQL = 23, tpr = 8 - IRQ4 + db APIC_IRQ3_VECTOR ; IRQL = 24, tpr = 8 - IRQ3 + db APIC_IRQ1_VECTOR ; IRQL = 25, tpr = 8 - IRQ1 + db APIC_IRQ0_VECTOR ; IRQL = 26, tpr = 8 - IRQ0 +; + db APIC_PROFILE_VECTOR ; IRQL = 27, tpr = 9 - Profile + db APIC_CLOCK_VECTOR ; IRQL = 28, tpr = 10 - Clock + db APIC_IPI_VECTOR ; IRQL = 29, tpr = 11 - IPI + db APIC_POWERFAIL_VECTOR ; IRQL = 30, tpr = 12 - Power + db APIC_HIGH_VECTOR ; IRQL = 31, tpr = 13 - High +; +; +; This table is used by HalGetInterruptVector to convert a +; traditional EISA/ISA IRQ to an NT IRQL value. +; + align 4 + public _HalpK2EISAIrq2Irql +_HalpK2EISAIrq2Irql label byte + db CLOCK2_LEVEL ; INTI 0 - system clock + db 25 ; INTI 1 - keyboard + db 24 ; INTI 2 - unused + db 24 ; INTI 3 - COM2 + db 23 ; INTI 4 - COM1 + db 22 ; INTI 5 - LPT2 + db 21 ; INTI 6 - floppy + db 20 ; INTI 7 - LPT1 + db 19 ; INTI 8 - RTC + db 18 ; INTI 9 - EISA IRQ9 + db 17 ; INTI 10 - EISA IRQ10 + db 16 ; INTI 11 - EISA IRQ11 + db 15 ; INTI 12 - Mouse + db 14 ; INTI 13 - DMA + db 13 ; INTI 14 - IDE disk + db 12 ; INTI 15 - EISA IRQ15 + db 11 ; INTI 16 - K2 IRQ 16 + db 10 ; INTI 17 - K2 IRQ 17 + db 9 ; INTI 18 - K2 IRQ 18 + db 8 ; INIT 19 - K2 IRQ 19 + db 7 ; INIT 20 - K2 IRQ 20 + db 6 ; INIT 21 - K2 IRQ 21 + db 5 ; INIT 22 - K2 IRQ 22 + db 4 ; INIT 23 - K2 IRQ 23 +; +; The following table is used to convert an IRQL to a corresponding +; EISA IRQ. This is used to determine in BeginInterrupt and +; EndInterrupt how do do EOI processing for edge/level EISA +; interrupts. IRQ0 is always designated as edge and will not +; change. We use this for all Irqls which do not correspond +; to EISA IRQ numbers +; + align 4 + public _HalpK2Irql2Eisa +_HalpK2Irql2Eisa label byte + db 0 ; IRQL = 0, tpr = 0 - Low + db 0 ; IRQL = 1, tpr = 3 - APC + db 0 ; IRQL = 2, tpr = 4 - DPC + db 0 ; IRQL = 3, tpr = 5 +; +; --- Divide the 24 device IRQLs into 3 hardware priority levels +; ...1 for each 8259 PIC grouping....PIC 1 is highest priority +; +; PIC3 + db 0 ; IRQL = 4, tpr = 6 - IRQ23 + db 0 ; IRQL = 5, tpr = 6 - IRQ22 + db 0 ; IRQL = 6, tpr = 6 - IRQ21 + db 0 ; IRQL = 7, tpr = 6 - IRQ20 + db 0 ; IRQL = 8, tpr = 6 - IRQ19 + db 0 ; IRQL = 9, tpr = 6 - IRQ18 + db 0 ; IRQL = 10, tpr = 6 - IRQ17 + db 0 ; IRQL = 11, tpr = 6 - IRQ16 +; PIC2 + db 15 ; IRQL = 12, tpr = 7 - IRQ15 + db 14 ; IRQL = 13, tpr = 7 - IRQ14 + db 13 ; IRQL = 14, tpr = 7 - IRQ13 + db 12 ; IRQL = 15, tpr = 7 - IRQ12 + db 11 ; IRQL = 16, tpr = 7 - IRQ11 + db 10 ; IRQL = 17, tpr = 7 - IRQ10 + db 9 ; IRQL = 18, tpr = 7 - IRQ9 + db 8 ; IRQL = 19, tpr = 7 - IRQ8 +; PIC1 + db 7 ; IRQL = 20, tpr = 8 - IRQ7 + db 6 ; IRQL = 21, tpr = 8 - IRQ6 + db 5 ; IRQL = 22, tpr = 8 - IRQ5 + db 4 ; IRQL = 23, tpr = 8 - IRQ4 + db 3 ; IRQL = 24, tpr = 8 - IRQ3 + db 1 ; IRQL = 25, tpr = 8 - IRQ1 + db 0 ; IRQL = 26, tpr = 8 - IRQ0 +; + db 0 ; IRQL = 27, tpr = 9 - Profile + db 0 ; IRQL = 28, tpr = 10 - Clock + db 0 ; IRQL = 29, tpr = 11 - IPI + db 0 ; IRQL = 30, tpr = 12 - Power + db 0 ; IRQL = 31, tpr = 13 - High +; + +; +; _HalpK2EbsIOunitRedirectionTable is the memory image of the redirection table to be +; loaded into APIC I/O unit 0 at initialization. there is one 64-bit entry +; per interrupt input to the I/O unit. the edge/level trigger mode bit will +; be set dynamically when the table is actually loaded. the mask bit is set +; initially, and reset by EnableSystemInterrupt. +; + align dword + public _HalpK2EbsIOunitRedirectionTable +_HalpK2EbsIOunitRedirectionTable label dword + + ; INTI0 - EISA IRQ3 + + dd APIC_IRQ3_VECTOR + INTERRUPT_MASKED + \ + DELIVER_LOW_PRIORITY + LOGICAL_DESTINATION + dd DESTINATION_ALL_CPUS + + ; INTI1 - EISA IRQ4 + + dd APIC_IRQ4_VECTOR + INTERRUPT_MASKED + \ + DELIVER_LOW_PRIORITY + LOGICAL_DESTINATION + dd DESTINATION_ALL_CPUS + + ; INTI2 - EISA IRQ5 + + dd APIC_IRQ5_VECTOR + INTERRUPT_MASKED + \ + DELIVER_LOW_PRIORITY + LOGICAL_DESTINATION + dd DESTINATION_ALL_CPUS + + ; INTI3 - EISA IRQ7 + + dd APIC_IRQ7_VECTOR + INTERRUPT_MASKED + \ + DELIVER_LOW_PRIORITY + LOGICAL_DESTINATION + dd DESTINATION_ALL_CPUS + + ; INTI4 - EISA IRQ9 + + dd APIC_IRQ9_VECTOR + INTERRUPT_MASKED + \ + DELIVER_LOW_PRIORITY + LOGICAL_DESTINATION + dd DESTINATION_ALL_CPUS + + ; INTI5 - EISA IRQ10 + + dd APIC_IRQ10_VECTOR + INTERRUPT_MASKED + \ + DELIVER_LOW_PRIORITY + LOGICAL_DESTINATION + dd DESTINATION_ALL_CPUS + + ; INTI6 - EISA IRQ11 + + dd APIC_IRQ11_VECTOR + INTERRUPT_MASKED + \ + DELIVER_LOW_PRIORITY + LOGICAL_DESTINATION + dd DESTINATION_ALL_CPUS + + ; INTI7 - EISA IRQ15 + + dd APIC_IRQ15_VECTOR + INTERRUPT_MASKED + \ + DELIVER_LOW_PRIORITY + LOGICAL_DESTINATION + dd DESTINATION_ALL_CPUS + + ; INTI8 - PowerBus IRQ16 + + dd APIC_IRQ16_VECTOR + INTERRUPT_MASKED + \ + DELIVER_LOW_PRIORITY + LOGICAL_DESTINATION + dd DESTINATION_ALL_CPUS + + ; INTI9 - PowerBus IRQ23 + + dd APIC_IRQ23_VECTOR + INTERRUPT_MASKED + \ + DELIVER_LOW_PRIORITY + LOGICAL_DESTINATION + dd DESTINATION_ALL_CPUS + + ; INTI10 - PowerBus IRQ22 + + dd APIC_IRQ22_VECTOR + INTERRUPT_MASKED + \ + DELIVER_LOW_PRIORITY + LOGICAL_DESTINATION + dd DESTINATION_ALL_CPUS + + ; INTI11 - PowerBus IRQ21 + + dd APIC_IRQ21_VECTOR + INTERRUPT_MASKED + \ + DELIVER_LOW_PRIORITY + LOGICAL_DESTINATION + dd DESTINATION_ALL_CPUS + + ; INTI12 - PowerBus IRQ20 + + dd APIC_IRQ20_VECTOR + INTERRUPT_MASKED + \ + DELIVER_LOW_PRIORITY + LOGICAL_DESTINATION + dd DESTINATION_ALL_CPUS + + ; INTI13 - PowerBus IRQ19 + + dd APIC_IRQ19_VECTOR + INTERRUPT_MASKED + \ + DELIVER_LOW_PRIORITY + LOGICAL_DESTINATION + dd DESTINATION_ALL_CPUS + + ; INTI14 - PowerBus IRQ18 + + dd APIC_IRQ18_VECTOR + INTERRUPT_MASKED + \ + DELIVER_LOW_PRIORITY + LOGICAL_DESTINATION + dd DESTINATION_ALL_CPUS + + ; INTI15 - PowerBus IRQ17 + + dd APIC_IRQ17_VECTOR + INTERRUPT_MASKED + \ + DELIVER_LOW_PRIORITY + LOGICAL_DESTINATION + dd DESTINATION_ALL_CPUS + + ; zero entry indicates end of table + + dd 0 +; +; +; The following table is used to convert a RDIR # on the EBS +; I/O APIC to an EISA IRQ +; + align 4 + public _HalpK2Rdir2Irq +_HalpK2Rdir2Irq label byte + db 3 ; RDIR = 0, IRQ = 3 + db 4 ; RDIR = 1, IRQ = 4 + db 5 ; RDIR = 2, IRQ = 5 + db 7 ; RDIR = 3, IRQ = 7 + db 9 ; RDIR = 4, IRQ = 9 + db 10 ; RDIR = 5, IRQ = 10 + db 11 ; RDIR = 6, IRQ = 11 + db 15 ; RDIR = 7, IRQ = 15 + db 16 ; RDIR = 8, IRQ = 16 + db 23 ; RDIR = 9, IRQ = 23 + db 22 ; RDIR = 10, IRQ = 22 + db 21 ; RDIR = 11, IRQ = 21 + db 20 ; RDIR = 12, IRQ = 20 + db 19 ; RDIR = 13, IRQ = 19 + db 18 ; RDIR = 14, IRQ = 18 + db 17 ; RDIR = 15, IRQ = 17 +; +; _HalpW3BaseIOunitRedirectionTable is the memory image of the +; redirection table to be loaded into APIC I/O unit 1 at initialization. +; there is one 64-bit entry per interrupt input to the I/O unit. +; + align 4 + public _HalpW3BaseIOunitRedirectionTable +_HalpW3BaseIOunitRedirectionTable label dword + + ; INTI0 - Unused + + dd INTERRUPT_MASKED + dd 0 + + ; INTI1 - Unused + + dd INTERRUPT_MASKED + dd 0 + + ; INTI2 - Unused + + dd INTERRUPT_MASKED + dd 0 + + ; INTI3 - Unused + + dd INTERRUPT_MASKED + dd 0 + + + ; INTI4 - Unused + + dd INTERRUPT_MASKED + dd 0 + + + ; INTI5 - Unused + + dd INTERRUPT_MASKED + dd 0 + + ; INTI6 - Unused + + dd INTERRUPT_MASKED + dd 0 + + ; INTI7 - SYS_ATTN_L + + dd INTERRUPT_MASKED + dd 0 + + ; INTI8 - SYS_POWER_FAIL + + dd INTERRUPT_MASKED + dd 0 + + ; INTI9 - SYS_TIMEOUT + + dd INTERRUPT_MASKED + dd 0 + + ; INTI10 - SYS_ERROR + + dd INTERRUPT_MASKED + dd 0 + + ; INTI11 - SYS_EISA_PERR + + dd INTERRUPT_MASKED + dd 0 + + ; INTI12 - SYS_IMS_ATTN + + dd INTERRUPT_MASKED + dd 0 + + ; INTI13 - SYS_INT + + dd APIC_SYSINT_VECTOR + DELIVER_EXTINT + LOGICAL_DESTINATION + dd DESTINATION_CPU_0 + + ; INTI14 - SYS_NMI + + dd DELIVER_NMI + LEVEL_TRIGGERED + LOGICAL_DESTINATION + dd DESTINATION_CPU_0 + + ; INTI15 - LOC_RESET_CPU + + dd DELIVER_NMI + LEVEL_TRIGGERED + LOGICAL_DESTINATION + dd DESTINATION_CPU_0 + + ; zero entry indicates end of table + + dd 0 +_DATA ENDS + +_TEXT SEGMENT DWORD PUBLIC 'CODE' + ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING +_TEXT ENDS + + END diff --git a/private/ntos/nthals/halws3/i386/w3spin.asm b/private/ntos/nthals/halws3/i386/w3spin.asm new file mode 100644 index 000000000..32746cfb6 --- /dev/null +++ b/private/ntos/nthals/halws3/i386/w3spin.asm @@ -0,0 +1,389 @@ +if NT_INST + +else + TITLE "Spin Locks" +;++ +; +; Copyright (c) 1989 Microsoft Corporation +; +; Module Name: +; +; spinlock.asm +; +; Abstract: +; +; This module implements stubbed x86 spinlock functions for +; any HAL. Some HALs may implement these function directly +; to minimize the amount of code required to perform a spinlock. +; (ie, out Raise & Lower irql in the fall through path) +; +; Author: +; +; Bryan Willman (bryanwi) 13 Dec 89 +; +; Environment: +; +; Kernel mode only. +; +; Revision History: +; +; Ken Reneris (kenr) 22-Jan-1991 +;-- + + PAGE + +.486p + +include callconv.inc ; calling convention macros +include i386\kimacro.inc +include hal386.inc +include mac386.inc + + EXTRNP KfRaiseIrql, 1,,FASTCALL + EXTRNP KfLowerIrql, 1,,FASTCALL + EXTRNP _KeBugCheck,1,IMPORT + EXTRNP _KeSetEventBoostPriority, 2, IMPORT + EXTRNP _KeWaitForSingleObject,5, IMPORT + +ifdef NT_UP + LOCK_ADD equ add + LOCK_DEC equ dec +else + LOCK_ADD equ lock add + LOCK_DEC equ lock dec +endif + +_TEXT SEGMENT PARA PUBLIC 'CODE' + ASSUME DS:FLAT, ES:FLAT, SS:FLAT, FS:NOTHING, GS:NOTHING + + PAGE + SUBTTL "Acquire Kernel Spin Lock" +;++ +; +; KIRQL +; FASTCALL +; KfAcquireSpinLock ( +; IN PKSPIN_LOCK SpinLock, +; ) +; +; Routine Description: +; +; This function raises to DISPATCH_LEVEL and then acquires a the +; kernel spin lock. +; +; Arguments: +; +; (ecx) = SpinLock - Supplies a pointer to an kernel spin lock. +; +; Return Value: +; +; (al) = OldIrql - old irql +; +;-- + +align 16 +cPublicFastCall KfAcquireSpinLock ,1 +cPublicFpo 0,0 + + +ifdef NT_UP ; On up build just perform raiseirql + + jmp @KfRaiseIrql@4 ; (al) = oldIrql +else + +; +; On a MP build we raise to dispatch_level +; and then acquire the spinlock +; + + push ecx ; Save address of spin lock + + mov ecx, DISPATCH_LEVEL ; (cl) = newIrql + fstCall KfRaiseIrql ; (al) = oldIrql + + pop ecx ; (ecx) -> spinlock + +; +; Attempt to assert the lock +; + +sl10: ACQUIRE_SPINLOCK ecx,<short sl20> + + fstRET KfAcquireSpinLock ; (al) = oldIrql + +; +; Lock is owned, spin till it looks free, then go get it again. +; + +sl20: SPIN_ON_SPINLOCK ecx,sl10 + +endif + +fstENDP KfAcquireSpinLock + + + PAGE + SUBTTL "Acquire Synch Kernel Spin Lock" +;++ +; +; KIRQL +; FASTCALL +; KeAcquireSpinLockRaiseToSynch ( +; IN PKSPIN_LOCK SpinLock +; ) +; +; Routine Description: +; +; This function acquires the SpinLock at SYNCH_LEVEL. The function +; is optmized for hoter locks (the lock is tested before acquired, +; any spin should occur at OldIrql) +; +; Arguments: +; +; (ecx) = SpinLock - Supplies a pointer to an kernel spin lock. +; +; Return Value: +; +; OldIrql - pointer to place old irql +; +;-- + +align 16 +cPublicFastCall KeAcquireSpinLockRaiseToSynch,1 +cPublicFpo 0,0 + +; +; Disable interrupts +; + +sls10: cli + +; +; Try to obtain spinlock. Use non-lock operation first +; + TEST_SPINLOCK ecx,<short sls20> + ACQUIRE_SPINLOCK ecx,<short sls20> + + +; +; Got the lock, raise to SYNCH_LEVEL +; + + mov ecx, SYNCH_LEVEL + fstCall KfRaiseIrql ; (al) = OldIrql + +; +; Enable interrupts and return +; + + sti + fstRET KeAcquireSpinLockRaiseToSynch + + +; +; Lock is owned, spin till it looks free, then go get it again. +; + +sls20: sti + SPIN_ON_SPINLOCK ecx,sls10 + +fstENDP KeAcquireSpinLockRaiseToSynch + + + PAGE + SUBTTL "Release Kernel Spin Lock" + +;++ +; +; VOID +; FASTCALL +; KfReleaseSpinLock ( +; IN PKSPIN_LOCK SpinLock, +; IN KIRQL NewIrql +; ) +; +; Routine Description: +; +; This function releases a kernel spin lock and lowers to the new irql +; +; Arguments: +; +; (ecx) = SpinLock - Supplies a pointer to an executive spin lock. +; (dl) = NewIrql - New irql value to set +; +; Return Value: +; +; None. +; +;-- + +align 16 +cPublicFastCall KfReleaseSpinLock ,2 +cPublicFpo 0,0 + +ifndef NT_UP +cPublicFpo 2,0 + + RELEASE_SPINLOCK ecx ; release it +endif + mov ecx, edx + jmp @KfLowerIrql@4 ; to KeLowerIrql + +fstENDP KfReleaseSpinLock + +;++ +; +; VOID +; FASTCALL +; ExAcquireFastMutex ( +; IN PFAST_MUTEX FastMutex +; ) +; +; Routine description: +; +; This function acquire ownership of the FastMutex +; +; Arguments: +; +; (ecx) = FastMutex - Supplies a pointer to the fast mutex +; +; Return Value: +; +; None. +; +;-- + +cPublicFastCall ExAcquireFastMutex,1 +cPublicFpo 0,1 + + push ecx ; Push FAST_MUTEX addr + mov ecx, APC_LEVEL + fstCall KfRaiseIrql + + pop ecx ; (ecx) = Fast Mutex + +cPublicFpo 0,0 + LOCK_DEC dword ptr [ecx].FmCount ; Get count + jz short afm_ret ; The owner? Yes, Done + + inc dword ptr [ecx].FmContention + +cPublicFpo 0,1 + push ecx + push eax + add ecx, FmEvent ; Wait on Event + stdCall _KeWaitForSingleObject,<ecx,WrExecutive,0,0,0> + pop eax + pop ecx + +cPublicFpo 0,0 +afm_ret: + mov byte ptr [ecx].FmOldIrql, al + fstRet ExAcquireFastMutex + +fstENDP ExAcquireFastMutex + +;++ +; +; BOOLEAN +; FASTCALL +; ExTryToAcquireFastMutex ( +; IN PFAST_MUTEX FastMutex +; ) +; +; Routine description: +; +; This function acquire ownership of the FastMutex +; +; Arguments: +; +; (ecx) = FastMutex - Supplies a pointer to the fast mutex +; +; Return Value: +; +; Returns TRUE if the FAST_MUTEX was acquired; otherwise false +; +;-- + +cPublicFastCall ExTryToAcquireFastMutex,1 +cPublicFpo 0,0 + +; +; Try to acquire +; + cmp dword ptr [ecx].FmCount, 1 ; Busy? + jne short tam25 ; Yes, abort + +cPublicFpo 0,1 + push ecx ; Push FAST_MUTEX + mov ecx, APC_LEVEL + fstCall KfRaiseIrql ; (al) = OldIrql + + mov ecx, [esp] ; Restore FAST_MUTEX + mov [esp], eax ; Save OldIrql + + mov eax, 1 ; Value to compare against + mov edx, 0 ; Value to set + lock cmpxchg dword ptr [ecx].FmCount, edx ; Attempt to acquire + jnz short tam20 ; got it? + +cPublicFpo 0,0 + pop edx ; (edx) = OldIrql + mov eax, 1 ; return TRUE + mov byte ptr [ecx].FmOldIrql, dl ; Store OldIrql + fstRet ExTryToAcquireFastMutex + +tam20: pop ecx ; (ecx) = OldIrql + fstCall KfLowerIrql ; restore OldIrql +tam25: xor eax, eax ; return FALSE + fstRet ExTryToAcquireFastMutex ; all done + +fstENDP ExTryToAcquireFastMutex + + +;++ +; +; VOID +; FASTCALL +; ExReleaseFastMutex ( +; IN PFAST_MUTEX FastMutex +; ) +; +; Routine description: +; +; This function releases ownership of the FastMutex +; +; Arguments: +; +; (ecx) FastMutex - Supplies a pointer to the fast mutex +; +; Return Value: +; +; None. +; +;-- + +cPublicFastCall ExReleaseFastMutex,1 + +cPublicFpo 0,0 + mov al, byte ptr [ecx].FmOldIrql ; (cl) = OldIrql + + LOCK_ADD dword ptr [ecx].FmCount, 1 ; Remove our count + xchg ecx, eax ; (cl) = OldIrql + js short rfm05 ; if < 0, set event + jnz @KfLowerIrql@4 ; if != 0, don't set event + +rfm05: add eax, FmEvent + push ecx + stdCall _KeSetEventBoostPriority, <eax, 0> + pop ecx + jmp @KfLowerIrql@4 + + +fstENDP ExReleaseFastMutex + +_TEXT ends + +ENDIF ; NT_INST + + end diff --git a/private/ntos/nthals/halws3/i386/w3sproc.c b/private/ntos/nthals/halws3/i386/w3sproc.c new file mode 100644 index 000000000..54a5b5395 --- /dev/null +++ b/private/ntos/nthals/halws3/i386/w3sproc.c @@ -0,0 +1,710 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation +Copyright (c) 1993 Sequent Computer Systems, Inc. + +Module Name: + + w3sproc.c + +Abstract: + + WinServer 3000 Start Next Processor C code. + + This module implements the initialization of the system dependent + functions that define the Hardware Architecture Layer (HAL) for a + WinServer 3000. + +Author: + + Ken Reneris (kenr) 22-Jan-1991 + Phil Hochstetler (phil@sequent.com) 3-30-93 + +Environment: + + Kernel mode only. + +Revision History: + +--*/ + +#include "halp.h" +#include "apic.inc" +#include "w3.inc" +#include "halver.h" + +VOID +HalpMapCR3 ( + IN ULONG VirtAddress, + IN PVOID PhysicalAddress, + IN ULONG Length + ); + +ULONG +HalpBuildTiledCR3 ( + IN PKPROCESSOR_STATE ProcessorState + ); + +VOID +HalpFreeTiledCR3 ( + VOID + ); + +ULONG +HalpGetW3EisaInterruptVector( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN ULONG BusInterruptLevel, + IN ULONG BusInterruptVector, + OUT PKIRQL Irql, + OUT PKAFFINITY Affinity + ); + + +VOID HalpInitOtherBuses (VOID); + +#define LOW_MEMORY 0x000100000 +#define MAX_PT 8 + +extern VOID StartPx_PMStub(VOID); +extern PKPCR HalpProcessorPCR[]; + + +PUCHAR MpLowStub; // pointer to low memory bootup stub +PVOID MpLowStubPhysicalAddress; // pointer to low memory bootup stub +PUCHAR MppIDT; // pointer to physical memory 0:0 +PVOID MpFreeCR3[MAX_PT]; // remember pool memory to free +#ifndef NT_UP + +BOOLEAN +HalpInitMP ( + IN ULONG Phase, + IN PLOADER_PARAMETER_BLOCK LoaderBlock + ) +/*++ + +Routine Description: + Allows MP initialization from HalInitSystem. + +Arguments: + Same as HalInitSystem + +Return Value: + none. + +--*/ +{ + PKPCR pPCR; + + pPCR = KeGetPcr(); + + if (Phase == 0) { + MppIDT = HalpMapPhysicalMemory (0, 1); + + // + // Allocate some low memory for processor bootup stub + // + + MpLowStubPhysicalAddress = (PVOID)HalpAllocPhysicalMemory (LoaderBlock, + LOW_MEMORY, 1, FALSE); + + if (!MpLowStubPhysicalAddress) + return TRUE; + + MpLowStub = (PCHAR) HalpMapPhysicalMemory (MpLowStubPhysicalAddress, 1); + return TRUE; + + } else { + + // + // Phase 1 for another processor + // + + } +} +#endif + +VOID +HalpFatal ( + IN PCHAR ErrorCode + ) + +/*++ + +Routine Description: + + Print the fatal error code and direct end user to + call service representitive for help. + +Arguments: + + ErrorCode - the error code string to print on error. + +Return Value: + + None. + +--*/ + +{ + + HalDisplayString("HAL: FATAL error #"); + HalDisplayString(ErrorCode); + HalDisplayString(" has occured.\n"); + HalDisplayString("HAL: Call your service representitive for help.\n"); + HalDisplayString(MSG_HALT); + KeEnterKernelDebugger(); +} + + +VOID +HalpCheckHw ( + ) + +/*++ + +Routine Description: + + Verify different aspects of the hardware to assure + the current hardware is both a WinServer and running + sufficient level hardware to support Windows NT. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + UNICODE_STRING unicodeValueName; + UNICODE_STRING KeyName; + OBJECT_ATTRIBUTES ObjectAttributes; + PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation; + NTSTATUS NtStatus; + HANDLE SystemHandle; + UCHAR KeyValueBuffer[512]; + ULONG resultLength; + PWSTR s; + ULONG m, d, y; + + KeyValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION)KeyValueBuffer; + + RtlInitUnicodeString( + &unicodeValueName, + L"\\Registry\\Machine\\Hardware\\Description\\System" + ); + + InitializeObjectAttributes( + &ObjectAttributes, + &unicodeValueName, + OBJ_CASE_INSENSITIVE, + (HANDLE) NULL, + (PSECURITY_DESCRIPTOR) NULL + ); + + NtStatus = ZwOpenKey( + &SystemHandle, + KEY_READ, + &ObjectAttributes + ); + + if (!NT_SUCCESS( NtStatus )) + HalpFatal("1015801"); + + RtlInitUnicodeString( &KeyName, L"SystemBiosDate" ); + + NtStatus = ZwQueryValueKey( + SystemHandle, + &KeyName, + KeyValuePartialInformation, + KeyValueInformation, + sizeof(KeyValueBuffer), + &resultLength + ); + + if (!NT_SUCCESS( NtStatus ) + || KeyValueInformation->Type != REG_SZ + || KeyValueInformation->DataLength < 16 + ) + HalpFatal("1015802"); + + // + // Bios date must be greater than or equal to "02/27/93" + // + + s = (PWSTR)KeyValueInformation->Data; + m = (*s++ - L'0') * 10; m += (*s++ - L'0'); *s++; // skip '/' + d = (*s++ - L'0') * 10; d += (*s++ - L'0'); *s++; // skip '/' + y = (*s++ - L'0') * 10; y += (*s++ - L'0'); + + if ((y * 365) + (m * 31) + d < (93 * 365) + (2 * 31) + 27) + HalpFatal("1015803"); + + RtlInitUnicodeString( &KeyName, L"VideoBiosVersion" ); + + NtStatus = ZwQueryValueKey( + SystemHandle, + &KeyName, + KeyValueBasicInformation, + KeyValueInformation, + sizeof(KeyValueBuffer), + &resultLength + ); + + if (!NT_SUCCESS( NtStatus ) + || KeyValueInformation->Type != REG_MULTI_SZ + ) + HalpFatal("1015804"); + + ZwClose(SystemHandle); + + RtlInitUnicodeString( + &unicodeValueName, + L"\\Registry\\Machine\\Hardware\\Description\\System\\EisaAdapter\\0\\DiskController" + ); + + InitializeObjectAttributes( + &ObjectAttributes, + &unicodeValueName, + OBJ_CASE_INSENSITIVE, + (HANDLE) NULL, + (PSECURITY_DESCRIPTOR) NULL + ); + + NtStatus = ZwOpenKey( + &SystemHandle, + KEY_READ, + &ObjectAttributes + ); + + if (!NT_SUCCESS( NtStatus )) + HalpFatal("1015805"); + + ZwClose(SystemHandle); + + RtlInitUnicodeString( + &unicodeValueName, + L"\\Registry\\Machine\\Hardware\\Description\\System\\EisaAdapter\\0\\DisplayController" + ); + + InitializeObjectAttributes( + &ObjectAttributes, + &unicodeValueName, + OBJ_CASE_INSENSITIVE, + (HANDLE) NULL, + (PSECURITY_DESCRIPTOR) NULL + ); + + NtStatus = ZwOpenKey( + &SystemHandle, + KEY_READ, + &ObjectAttributes + ); + + if (!NT_SUCCESS( NtStatus )) + HalpFatal("1015806"); + + ZwClose(SystemHandle); +} + +BOOLEAN +HalAllProcessorsStarted ( + VOID + ) +{ + return TRUE; +} + +VOID +HalReportResourceUsage ( + VOID + ) +/*++ + +Routine Description: + The registery is now enabled - time to report resources which are + used by the HAL. + +Arguments: + +Return Value: + +--*/ +{ + ANSI_STRING AHalName; + UNICODE_STRING UHalName; + + HalInitSystemPhase2 (); + + RtlInitAnsiString (&AHalName, HalName); + RtlAnsiStringToUnicodeString (&UHalName, &AHalName, TRUE); + + HalpReportResourceUsage ( + &UHalName, // descriptive name + Eisa // WinServer 3000 is an EISA machine + ); + + RtlFreeUnicodeString (&UHalName); + + // + // Take advantage of the registry being enabled to check + // it for a WinServer with the proper hardware support. + // + + HalpCheckHw(); + +} + + +VOID +HalpRebootNow( + ) +/*++ +--*/ +{ +#define KEYBPORT (PUCHAR)0x64 +#define RESET 0xfe + +#ifndef NT_UP + PKPCR pPCR; + PWS3_HAL_PRIVATE pPriv; + USHORT FCRAddr; + UCHAR i; + UCHAR Me; + + pPCR = KeGetPcr(); + pPriv = (PWS3_HAL_PRIVATE) &pPCR->HalReserved[0]; + Me = pPriv->PcrNumber; + + // + // Reset each of the slaves and issue the reset command. + // + + for (i = 1; HalpProcessorPCR[i]; i++) { + + // + // Never reset myself + // + + if (i == Me) + continue; + + // + // Put processor into reset by setting the FCR reset bit + // + + pPriv = (PWS3_HAL_PRIVATE) &HalpProcessorPCR[i]->HalReserved[0]; + FCRAddr = pPriv->ProcSlotAddr | FCR; + WRITE_PORT_USHORT((PUSHORT) FCRAddr, + (USHORT)(READ_PORT_USHORT((PUSHORT) FCRAddr) | + ((USHORT) FCR_RESET_MASK))); + } + + // + // Send the reset command to the keyboard controller + // + + for (;;) { + WRITE_PORT_UCHAR(KEYBPORT, RESET); + KeStallExecutionProcessor(30 * 1000000); + } +#else + // + // Send the reset command to the keyboard controller + // + + for (;;) { + WRITE_PORT_UCHAR(KEYBPORT, RESET); + KeStallExecutionProcessor(30 * 1000000); + } +#endif +} + +VOID +HalpResetAllProcessors ( + ) +/*++ + +Routine Description: + Called very late in the process of rebooting the machine + from HalpReboot() to attempt to put the machine in a state + where sending the reset command to the keyboard controller will + actually reboot the machine. + + On a WinServer 3000, only the P0 processor will see the system + reset line so we must attempt to shutdown each of the slaves. + If the P0 processor is not responding, then we make a best attempt. + Also, this has some implication on leaving errors asserted (like + the APIC NMI state) which the BIOS does not handle. + + N.B. Is is critical that we do not put P0 into reset by writing + the feature control register (FCR) because it will not see the + reset and the system will hang. + +Arguments: + None. + +Return Value: + None. + +--*/ +{ +#ifdef NT_UP + HalDisplayString("System Reboot in progress.\n"); + HalDisplayString("Please wait while the system reboots.\n"); + HalpRebootNow(); +#else + PWS3_HAL_PRIVATE pPriv; + PKPCR pPCR; + + pPCR = KeGetPcr(); + pPriv = (PWS3_HAL_PRIVATE) &pPCR->HalReserved[0]; + + HalDisplayString("System Reboot in progress.\n"); + HalDisplayString("Please wait while the system reboots.\n"); + + if (pPriv->PcrNumber == 0) + HalpRebootNow(); + + // + // On P1-PN, so try to signal P0 to reboot the system by + // taking over P0's IPI handler and sending an IPI. + // + + HalpProcessorPCR[0]->IDT[APIC_IPI_VECTOR].ExtendedOffset = HIGHWORD(HalpRebootNow); + HalpProcessorPCR[0]->IDT[APIC_IPI_VECTOR].Offset = LOWWORD(HalpRebootNow); + HalRequestIpi(1); + KeStallExecutionProcessor(30 * 1000000); + + // + // We only reach here if P0 fails to reboot the system. + // Try to reset all the slaves but our self and P0 and + // then try to reboot. This is the last attempt and + // if it fails, we will probably hang the system. + // + + HalpRebootNow(); +#endif +} + +ULONG +HalpBuildTiledCR3 ( + IN PKPROCESSOR_STATE ProcessorState + ) +/*++ + +Routine Description: + When the x86 processor is reset it starts in real-mode. In order to + move the processor from real-mode to protected mode with flat addressing + the segment which loads CR0 needs to have it's linear address mapped + to machine the phyiscal location of the segment for said instruction so + the processor can continue to execute the following instruction. + + This function is called to built such a tiled page directory. In + addition, other flat addresses are tiled to match the current running + flat address for the new state. Once the processor is in flat mode, + we move to a NT tiled page which can then load up the remaining processors + state. + +Arguments: + ProcessorState - The state the new processor should start in. + +Return Value: + Physical address of Tiled page directory + + +--*/ +{ +#define GetPdeAddress(va) ((PHARDWARE_PTE)((((((ULONG)(va)) >> 22) & 0x3ff) << 2) + (PUCHAR)MpFreeCR3[0])) +#define GetPteAddress(va) ((PHARDWARE_PTE)((((((ULONG)(va)) >> 12) & 0x3ff) << 2) + (PUCHAR)pPageTable)) + +// bugbug kenr 27mar92 - fix physical memory usage! + + MpFreeCR3[0] = ExAllocatePool (NonPagedPool, PAGE_SIZE); + RtlZeroMemory (MpFreeCR3[0], PAGE_SIZE); + + // + // Map page for real mode stub (one page) + // + HalpMapCR3 ((ULONG) MpLowStubPhysicalAddress, + MpLowStubPhysicalAddress, + PAGE_SIZE); + + // + // Map page for protect mode stub (one page) + // + HalpMapCR3 ((ULONG) &StartPx_PMStub, NULL, 0x1000); + + + // + // Map page(s) for processors GDT + // + HalpMapCR3 (ProcessorState->SpecialRegisters.Gdtr.Base, NULL, + ProcessorState->SpecialRegisters.Gdtr.Limit); + + + // + // Map page(s) for processors IDT + // + HalpMapCR3 (ProcessorState->SpecialRegisters.Idtr.Base, NULL, + ProcessorState->SpecialRegisters.Idtr.Limit); + + return MmGetPhysicalAddress (MpFreeCR3[0]).LowPart; +} + + +VOID +HalpMapCR3 ( + IN ULONG VirtAddress, + IN PVOID PhysicalAddress, + IN ULONG Length + ) +/*++ + +Routine Description: + Called to build a page table entry for the passed page directory. + Used to build a tiled page directory with real-mode & flat mode. + +Arguments: + VirtAddress - Current virtual address + PhysicalAddress - Optional. Physical address to be mapped to, if passed + as a NULL then the physical address of the passed + virtual address is assumed. + Length - number of bytes to map + +Return Value: + none. + +--*/ +{ + ULONG i; + PHARDWARE_PTE PTE; + PVOID pPageTable; + PHYSICAL_ADDRESS pPhysicalPage; + + + while (Length) { + PTE = GetPdeAddress (VirtAddress); + if (!PTE->PageFrameNumber) { + pPageTable = ExAllocatePool (NonPagedPool, PAGE_SIZE); + RtlZeroMemory (pPageTable, PAGE_SIZE); + + for (i=0; i<MAX_PT; i++) { + if (!MpFreeCR3[i]) { + MpFreeCR3[i] = pPageTable; + break; + } + } + ASSERT (i<MAX_PT); + + pPhysicalPage = MmGetPhysicalAddress (pPageTable); + PTE->PageFrameNumber = (pPhysicalPage.LowPart >> PAGE_SHIFT); + PTE->Valid = 1; + PTE->Write = 1; + } + + pPhysicalPage.LowPart = PTE->PageFrameNumber << PAGE_SHIFT; + pPhysicalPage.HighPart = 0; + pPageTable = MmMapIoSpace (pPhysicalPage, PAGE_SIZE, TRUE); + + PTE = GetPteAddress (VirtAddress); + + if (!PhysicalAddress) { + PhysicalAddress = (PVOID)MmGetPhysicalAddress ((PVOID)VirtAddress).LowPart; + } + + PTE->PageFrameNumber = ((ULONG) PhysicalAddress >> PAGE_SHIFT); + PTE->Valid = 1; + PTE->Write = 1; + + MmUnmapIoSpace (pPageTable, PAGE_SIZE); + + PhysicalAddress = 0; + VirtAddress += PAGE_SIZE; + if (Length > PAGE_SIZE) { + Length -= PAGE_SIZE; + } else { + Length = 0; + } + } +} + + + +VOID +HalpFreeTiledCR3 ( + VOID + ) +/*++ + +Routine Description: + Free's any memory allocated when the tiled page directory was built. + +Arguments: + none + +Return Value: + none +--*/ +{ + ULONG i; + + for (i=0; MpFreeCR3[i]; i++) { + ExFreePool (MpFreeCR3[i]); + MpFreeCR3[i] = 0; + } +} + +VOID +HalpInitOtherBuses ( + VOID + ) +{ + PBUS_HANDLER Bus; + + // + // Change GetInterruptVector handler on Eisa Bus 0 to a + // Winserver specific handler which supports the Winserver's + // Eisa interrupt vectors 16-23. + // + + Bus = HalpHandlerForBus (Eisa, 0); + Bus->GetInterruptVector = HalpGetW3EisaInterruptVector; + + // + // no other internal buses supported + // +} + + +NTSTATUS +HalpGetMcaLog ( + OUT PMCA_EXCEPTION Exception, + OUT PULONG ReturnedLength + ) +{ + return STATUS_NOT_SUPPORTED; +} + +NTSTATUS +HalpMcaRegisterDriver( + IN PMCA_DRIVER_INFO DriverInfo + ) +{ + return STATUS_NOT_SUPPORTED; +} + +ULONG +FASTCALL +HalSystemVectorDispatchEntry ( + IN ULONG Vector, + OUT PKINTERRUPT_ROUTINE **FlatDispatch, + OUT PKINTERRUPT_ROUTINE *NoConnection + ) +{ + return FALSE; +} diff --git a/private/ntos/nthals/halws3/i386/w3sproca.asm b/private/ntos/nthals/halws3/i386/w3sproca.asm new file mode 100644 index 000000000..8c0fe0b37 --- /dev/null +++ b/private/ntos/nthals/halws3/i386/w3sproca.asm @@ -0,0 +1,377 @@ + title "MP primitives for WinServer 3000" +;++ +; +; Copyright (c) 1991 Microsoft Corporation +; Copyright (c) 1993 Sequent Computer Systems, Inc. +; +; Module Name: +; +; w3sproca.asm +; +; Abstract: +; +; WinServer 3000 Start Next Processor assembly code +; +; This module along with w3sproc.c implement the code to start +; off the mulitple processors on the WinServer 3000. +; +; Author: +; +; Phil Hochstetler (phil@sequent.com) 3-30-93 +; +; Revision History: +; +;-- +.386p + .xlist +include ks386.inc +include callconv.inc ; calling convention macros +include i386\kimacro.inc +include mac386.inc +include i386\w3.inc + .list + + EXTRNP _ExAllocatePool,2 + EXTRNP _HalpBuildTiledCR3,1 + EXTRNP _HalpFreeTiledCR3,0 + EXTRNP _HalpUnResetLocalUnit,1 + + extrn _MppIDT:DWORD + extrn _MpLowStub:DWORD + extrn _MpLowStubPhysicalAddress:DWORD + extrn _ProcessorsPresent:DWORD + +; +; Internal defines and structures +; + +PxParamBlock struc + WS3_flag dd ? + WS3_TiledCR3 dd ? + WS3_P0EBP dd ? + WS3_ControlPort dd ? + WS3_PB db ProcessorStateLength dup (?) +PxParamBlock ends + +_TEXT SEGMENT DWORD PUBLIC 'CODE' ; Start 32 bit code + ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING + +;++ +; +; BOOLEAN +; HalStartNextProcessor ( +; IN PLOADER_BLOCK pLoaderBlock, +; IN PKPROCESSOR_STATE pProcessorState +; ) +; +; Routine Description: +; +; This routine is called by the kernel durning kernel initialization +; to obtain more processors. It is called until no more processors +; are available. +; +; If another processor exists this function is to initialize it to +; the passed in processorstate structure, and return TRUE. +; +; If another processor does not exists, then a FALSE is returned. +; +; Also note that the loader block has been setup for the next processor. +; The new processor logical thread number can be obtained from it, if +; required. +; +; Arguments: +; pLoaderBlock, - Loader block which has been intialized for the +; next processor. +; +; pProcessorState - The processor state which is to be loaded into +; the next processor. +; +; +; Return Value: +; +; TRUE - ProcessorNumber was dispatched. +; FALSE - A processor was not dispatched. no other processors exists. +; +;-- + +pLoaderBlock equ dword ptr [ebp+8] ; zero based +pProcessorState equ dword ptr [ebp+12] + +; +; Local variables +; + +PxFrame equ [ebp - size PxParamBlock] +; +; CMOS equates for warm boot +; +CMOS_ADDR EQU 70h +CMOS_DATA EQU 71h +CMOSCTL EQU 0Fh +CMOSWARMBOOT EQU 0Ah +; + +cPublicProc _HalStartNextProcessor ,2 + + push ebp ; save ebp + mov ebp, esp ; + + sub esp, size PxParamBlock ; Make room for local vars + + + push esi + push edi + push ebx + + xor eax, eax + mov PxFrame.WS3_flag, eax + + cmp _ProcessorsPresent, eax ; any processors left to start + je snp_exit ; exit FALSE +; + bsf eax, _ProcessorsPresent ; get slot index + btr _ProcessorsPresent, eax ; clear slot index + shl eax, EISA_SHIFT + or eax,FCR ; Create Control Port Address + mov PxFrame.WS3_ControlPort, eax ; Store in Frame + + mov esi, OFFSET FLAT:StartPx_RMStub + mov ecx, StartPx_RMStub_Len + mov edi, _MpLowStub ; Copy RMStub to low memory + add edi, size PxParamBlock + rep movsb + + lea edi, PxFrame.WS3_PB + mov esi, pProcessorState + mov ecx, ProcessorStateLength ; Copy processorstate + rep movsb ; to PxFrame + + stdCall _HalpBuildTiledCR3, <pProcessorState> + + mov PxFrame.WS3_TiledCR3, eax + mov PxFrame.WS3_P0EBP, ebp + + mov ecx, size PxParamBlock ; copy param block + lea esi, PxFrame ; to low memory stub + mov edi, _MpLowStub + mov eax, edi + rep movsb + + add eax, size PxParamBlock + mov ebx, OFFSET FLAT:StartPx_RMStub + sub eax, ebx ; (eax) = adjusted pointer + mov bx, word ptr [PxFrame.WS3_PB.PsContextFrame.CsSegCs] + mov [eax.W3rxFlatCS], bx ; patch realmode stub with + mov [eax.W3rxPMStub], offset _StartPx_PMStub ; valid long jump + + mov ebx, _MppIDT + add ebx, WarmResetVector + + cli + push dword ptr [ebx] ; Save current vector + + mov eax, _MpLowStubPhysicalAddress + shl eax, 12 ; seg:0 + add eax, size PxParamBlock + mov dword ptr [ebx], eax ; start Px here + + mov eax, pLoaderBlock ; lookup processor # we are + mov eax, [eax].LpbPrcb ; starting + movzx eax, byte ptr [eax].PbNumber + stdCall _HalpUnResetLocalUnit,<eax> + + mov edx, PxFrame.WS3_ControlPort ; Control port of target + mov al,CMOSCTL + out CMOS_ADDR,al ; Tell BIOS its warm BOOT + mov al,CMOSWARMBOOT + out CMOS_DATA,al + in ax, dx ; processor + and ax, NOT FCR_RESET_MASK ; remove Reset bit + out dx, ax ; bring Pn out of reset +@@: + cmp PxFrame.WS3_flag, 0 ; wait for Px to get it's + jz @b ; info + +; REMOVE THIS CODE FRAGMENT WHEN WE FORCE BIOS REV TO BE 4.0 OR GREATER + + mov al,0 ; Re-enable NMI in ISP + out CMOS_ADDR,al ; because pre 4.0 BIOS + ; code executed by + ; Px leaves it disabled. + +; REMOVE THIS CODE FRAGMENT WHEN WE FORCE BIOS REV TO BE 4.0 OR GREATER + + pop dword ptr [ebx] ; restore WarmResetVector + sti + + stdCall _HalpFreeTiledCR3 ; free memory used for tiled + ; CR3 + + mov eax, 1 ; return TRUE + +snp_exit: + + pop ebx + pop edi + pop esi + mov esp, ebp + pop ebp + + stdRET _HalStartNextProcessor + +stdENDP _HalStartNextProcessor + + +_TEXT ends ; end 32 bit code + + +_TEXT16 SEGMENT DWORD PUBLIC USE16 'CODE' ; start 16 bit code + + +;++ +; +; VOID +; StartPx_RMStub +; +; Routine Description: +; +; When a new processor is started, it starts in real-mode and is +; sent to a copy of this function which has been copied into low memory. +; (below 1m and accessable from real-mode). +; +; Once CR0 has been set, this function jmp's to a StartPx_PMStub +; +; Arguments: +; none +; +; Return Value: +; does not return, jumps to StartPx_PMStub +; +;-- +cPublicProc StartPx_RMStub ,0 +cPublicFpo 0, 0 + + cli + + db 066h ; load the GDT + lgdt fword ptr cs:[WS3_PB.PsSpecialRegisters.SrGdtr] + + db 066h ; load the IDT + lidt fword ptr cs:[WS3_PB.PsSpecialRegisters.SrIdtr] + + mov eax, cs:[WS3_TiledCR3] + mov cr3, eax + + mov ebp, dword ptr cs:[WS3_P0EBP] + mov ecx, dword ptr cs:[WS3_PB.PsContextFrame.CsSegDs] + mov ebx, dword ptr cs:[WS3_PB.PsSpecialRegisters.SrCr3] + mov eax, dword ptr cs:[WS3_PB.PsSpecialRegisters.SrCr0] + + mov cr0, eax ; into prot mode + + db 066h + db 0eah ; reload cs:eip +W3rxPMStub dd 0 +W3rxFlatCS dw 0 + +StartPx_RMStub_Len equ $ - StartPx_RMStub +stdENDP StartPx_RMStub + + +_TEXT16 ends ; End 16 bit code + +_TEXT SEGMENT DWORD PUBLIC 'CODE' ; Start 32 bit code + + +;++ +; +; VOID +; StartPx_PMStub +; +; Routine Description: +; +; This function completes the processor's state loading, and signals +; the requesting processor that the state has been loaded. +; +; Arguments: +; ebx - requested CR3 for this processors_state +; cx - requested ds for this processors_state +; ebp - EBP of P0 +; +; Return Value: +; does not return - completes the loading of the processors_state +; +;-- + +cPublicProc _StartPx_PMStub ,0 +cPublicFpo 0, 0 + + + ; process is now in the load image copy of this function. + ; (ie, it's not the low memory copy) + + mov cr3, ebx ; get real CR3 + mov ds, cx ; set real ds + + lea esi, PxFrame.WS3_PB.PsSpecialRegisters + + lldt word ptr ds:[esi].SrLdtr ; load ldtr + ltr word ptr ds:[esi].SrTr ; load tss + + lea edi, PxFrame.WS3_PB.PsContextFrame + mov es, word ptr ds:[edi].CsSegEs ; Set other selectors + mov fs, word ptr ds:[edi].CsSegFs + mov gs, word ptr ds:[edi].CsSegGs + mov ss, word ptr ds:[edi].CsSegSs + + add esi, SrKernelDr0 + .errnz (SrKernelDr1 - SrKernelDr0 - 1 * 4) + .errnz (SrKernelDr2 - SrKernelDr0 - 2 * 4) + .errnz (SrKernelDr3 - SrKernelDr0 - 3 * 4) + .errnz (SrKernelDr6 - SrKernelDr0 - 4 * 4) + .errnz (SrKernelDr7 - SrKernelDr0 - 5 * 4) + lodsd + mov dr0, eax ; load dr0-dr7 + lodsd + mov dr1, eax + lodsd + mov dr2, eax + lodsd + mov dr3, eax + lodsd + mov dr6, eax + lodsd + mov dr7, eax + + mov esp, dword ptr ds:[edi].CsEsp + mov esi, dword ptr ds:[edi].CsEsi + mov ecx, dword ptr ds:[edi].CsEcx + + push dword ptr ds:[edi].CsEflags + popfd ; load eflags + + push dword ptr ds:[edi].CsEip ; make a copy of remaining + push dword ptr ds:[edi].CsEax ; registers which need + push dword ptr ds:[edi].CsEbx ; loaded + push dword ptr ds:[edi].CsEdx + push dword ptr ds:[edi].CsEdi + push dword ptr ds:[edi].CsEbp + +; + inc [PxFrame.WS3_flag] ; Signal p0 that we are + ; done with it's data + ; Set remaining registers + + pop ebp + pop edi + pop edx + pop ebx + pop eax + + stdRET _StartPx_PMStub ; Set eip + +stdENDP _StartPx_PMStub + +_TEXT ends ; end 32 bit code + + end diff --git a/private/ntos/nthals/halws3/i386/w3stall.asm b/private/ntos/nthals/halws3/i386/w3stall.asm new file mode 100644 index 000000000..588878a83 --- /dev/null +++ b/private/ntos/nthals/halws3/i386/w3stall.asm @@ -0,0 +1,382 @@ + + title "Stall Execution Support" +;++ +; +; Copyright (c) 1989 Microsoft Corporation +; Copyright (c) 1993 Sequent Computer Systems, Inc. +; +; Module Name: +; +; w3stall.asm +; +; Abstract: +; +; This module implements the code necessary to stall the processor +; for some specified period of time. +; +; Author: +; +; Phil Hochstetler (phil@sequent.com) +; +; Environment: +; +; Kernel mode only. +; +; Revision History: +; +;-- + +.386p + .xlist +include hal386.inc +include callconv.inc +include i386\kimacro.inc +include mac386.inc +include i386\apic.inc +include i386\ixcmos.inc +include i386\w3.inc + + + EXTRNP _DbgBreakPoint,0,IMPORT + extrn _HalpLocalUnitBase:DWORD + + page ,132 + subttl "Initialize Stall Execution Counter" +;++ +; +; VOID +; HalpInitializeStallExecution ( +; IN CCHAR ProcessorNumber +; ) +; +; Routine Description: +; +; This routine initialize the per Microsecond counter for +; KeStallExecutionProcessor +; +; Arguments: +; +; ProcessorNumber - Processor Number +; +; Return Value: +; +; None. +; +; Note: +; +; This routine is called from the HalInitSystem routine in w3hal.c. +; It is only called during Phase 0 init on P0 +; +;-- + +; +; Local Variables - These are valid even in the Isr because we're the only thing +; running on this processor and no-one else will change the ebp +; register. + +StallIDTPointer equ [ebp-6] +StallIDTArea equ [ebp-8] +StallInterruptCount equ [ebp-12] +StallLVTentry equ dword ptr [ebp-16] +StallDummyentry0 equ dword ptr [ebp-20] +StallDummyentry1 equ [ebp-24] +StallApicTpr equ dword ptr [ebp-28] + + +_TEXT SEGMENT DWORD PUBLIC 'CODE' + ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING + +cPublicProc _HalpInitializeStallExecution,1 + + push ebp ; save ebp + mov ebp, esp ; set up 28 bytes for local use + sub esp, 32 + + pushfd ; save caller's eflag + +; +; --- For an APIC implementaion we use the APIC timer0 and install a +; --- Local Vector Table entry to point to a high priority +; --- vector for the Timer0 Interrupt. Then use the TPR in the local APIC +; --- to mask out every thing below it. To this end we've reserved a vector +; --- in the highest priority group (0F8) to be used here. +; + +; +; Since APIC timer interrupt will come from APIC_STALL_VECTOR, we need to +; Save original APIC_STALL_VECTOR descriptor and set the descriptor +; to point to our own handler. +; + sidt fword ptr StallIDTArea ; get IDT address + mov edx, StallIDTPointer ; (edx)->IDT + +; +; --- Save Original Descriptor on Stack +; + push dword ptr [edx+8*APIC_STALL_VECTOR]; (TOS) = orig. Vector + push dword ptr [edx+8*APIC_STALL_VECTOR + 4] + push edx ; (TOS) -> IDT +; +; --- Install our IDT entry +; + mov eax, offset FLAT:ApicTimer0Handler + mov word ptr [edx+8*APIC_STALL_VECTOR], ax ; Low half handler addr + mov word ptr [edx+8*APIC_STALL_VECTOR+2], KGDT_R0_CODE ; set up selector + mov word ptr [edx+8*APIC_STALL_VECTOR+4], D_INT032 ; 386 interrupt gate + shr eax, 16 ; (ax)=higher half of handler addr + mov word ptr [edx+8*APIC_STALL_VECTOR+6], ax +; +; --- Init. interrupt Flag +; + mov dword ptr StallinterruptCount, 0 ; set no interrupt yet + + ; + ; Get the Local Vector Table Timer Zero entry and save it + ; + mov edx, _HalpLocalUnitBase ; get the current TPR + mov eax, [edx+LU_TIMER_VECTOR] ; get Timer zero LVT + mov StallLVTentry, eax ; Save LVT + + ; + ; --- Set the Inital Timer count + ; --- Note: we will use TMBASE with No Divider + ; --- which runs at 11 Mhz + ; + + mov eax,(PeriodInUsec*11) ; Set the initial TIMER0 count + mov [edx+LU_INITIAL_COUNT], eax + ; + ; Save then set the Local APIC's TPR to mask all interrupts except the + ; highest priority group + ; + + mov eax, [edx+LU_TPR] ; get TPR + mov StallApicTpr, eax ; save TPR for later + + ; + ; Set TPR (Priority of CPU) = TPR (VECTOR - 16). So that all interrupts + ; in VECTOR's priority group will be allowed in. + ; + mov eax, APIC_STALL_VECTOR-10H + mov [edx+LU_TPR], eax ; Write the new TPR + ; + ; + ; --- Create Timer zero entry and store in Local Vector Table + ; --- STARTING the clock + ; + mov eax,(00040000H OR PERIODIC_TIMER) + or eax,(INTERRUPT_MOT_MASKED OR APIC_STALL_VECTOR) +@@: + test [edx+LU_TIMER_VECTOR], DELIVERY_PENDING + jnz @b + + mov [edx+LU_TIMER_VECTOR], eax +; +; --- Now enable the interrupt and start the counter +; + + xor eax, eax ; (eax) = 0, initialize loopcount +; +; --- ENABLE TIMER ZERO INTERRUPT +; + sti +; +; --- BEGIN SPIN Calibration LOOP +; + +Stall10: + add eax, 1 ; increment the loopcount + jnz short Stall10 +; +; Counter overflowed +; + + stdCall _DbgBreakPoint + +;++ +; +; VOID +; ApicTimer0Handler( +; ); +; +;Routine Description: +; +; APIC Timer zero interrupt Handler for Calibrating Spin Loop for +; KeStallExecution(); +; +; Note: we discard first real time clock interrupt and compute the +; permicrosecond loopcount on receiving of the second real time +; interrupt. This is because the first interrupt is generated +; based on the previous real time tick interval. +; +;-- + Public ApicTimer0Handler + +ApicTimer0Handler: + + inc dword ptr StallInterruptCount ; increment interrupt count + cmp dword ptr StallInterruptCount,1 ; Is this the first interrupt? + jnz Stall25 ; no, its the second go process it + + pop eax ; get rid of original ret addr + push offset FLAT:Stall10 ; set new ret addr --> top of loop + + ; + ; EOI the Local Apic, the value written is immaterial + ; + + mov eax, _HalpLocalUnitBase ; write to local unit EOI register + mov dword ptr [eax+LU_EOI], 0 +; + xor eax, eax ; reset loop counter +; + iretd +; +; --- Process EAX for Spin Count +; +; +Stall25: + +ifdef DBG + cmp eax, 0 + jnz short Stall30 + + stdCall _DbgBreakPoint +endif +; +Stall30: + + xor edx, edx ; (edx:eax) = dividend + mov ecx, PeriodInUSec; ; (ecx) = time spent in the loop + div ecx ; (eax) = loop count per microsecond + cmp edx, 0 ; Is remainder =0? + jz short Stall40 ; yes, go Stall40 + inc eax ; increment loopcount by 1 +; +Stall40: + movzx ecx, byte ptr [ebp+8] ; Current processor number + + mov PCR[PcStallScaleFactor], eax +; +; Reset return address to kexit +; + + pop eax ; discard original return address + push offset FLAT:kexit ; return to kexit + + ; + ; EOI the Local Apic, the value written is immaterial + ; + + mov eax, _HalpLocalUnitBase ; write the local unit EOI register + mov dword ptr [eax+LU_EOI], 0 + + and word ptr [esp+8], NOT 0200H ; Disable interrupt upon return +; + iretd +; +; +; --- Calibration is Done Restore all values and exit +; --- Interrupts are disabled +; +kexit: + ; + ; Turn OFF TIMER ZERO + ; + ; + mov edx, _HalpLocalUnitBase + mov eax, StallLVTentry ; get Saved LVT + +@@: + test [edx+LU_TIMER_VECTOR], DELIVERY_PENDING + jnz @b + + mov [edx+LU_TIMER_VECTOR], eax +; +; --- Restore the interrupt vector we used +; + pop edx ; (edx)->IDT + pop [edx+8*APIC_STALL_VECTOR+4] ; higher half of desc + pop [edx+8*APIC_STALL_VECTOR] ; lower half of desc + +; +; --- Restore the Local APIC's TPR +; + + mov eax, StallApicTpr ; get the saved TPR + mov edx, _HalpLocalUnitBase ; write old value to TPR + mov [edx+LU_TPR], eax + + + sub esp, 32 + popfd ; restore caller's eflags + mov esp, ebp + pop ebp ; restore ebp + + stdRET _HalpInitializeStallExecution + +stdENDP _HalpInitializeStallExecution + + page ,132 + subttl "Stall Execution" +;++ +; +; VOID +; KeStallExecutionProcessor ( +; IN ULONG MicroSeconds +; ) +; +; Routine Description: +; +; This function stalls execution for the specified number of microseconds. +; KeStallExecutionProcessor +; +; Arguments: +; +; MicroSeconds - Supplies the number of microseconds that execution is to be +; stalled. +; +; Return Value: +; +; None. +; +;-- + +MicroSeconds equ [esp + 4] + +cPublicProc _KeStallExecutionProcessor ,1 +cPublicFpo 1, 0 + + mov ecx, MicroSeconds ; (ecx) = Microseconds + jecxz short kese10 ; return if no loop needed + + mov eax, PCR[PcStallScaleFactor] ; get per microsecond + + mul ecx ; (eax) = desired loop count + +ifdef DBG +; +; Make sure we the loopcount is less than 4G and is not equal to zero +; + + cmp edx, 0 + jz short @f + int 3 + +@@: cmp eax,0 + jnz short @f + int 3 +endif + +ALIGN 4 +@@: + sub eax, 1 ; (eax) = (eax) - 1 + jnz short @b +kese10: + stdRET _KeStallExecutionProcessor + +stdENDP _KeStallExecutionProcessor + +_TEXT ends + + end diff --git a/private/ntos/nthals/halws3/i386/w3swint.asm b/private/ntos/nthals/halws3/i386/w3swint.asm new file mode 100644 index 000000000..1becece07 --- /dev/null +++ b/private/ntos/nthals/halws3/i386/w3swint.asm @@ -0,0 +1,317 @@ + title "Software Interrupts" +;++ +; +; Copyright (c) 1992 Microsoft Corporation +; Copyright (c) 1992 Sequent Computer Systems, Inc. +; +; Module Name: +; +; w3swint.asm +; +; Abstract: +; +; This module implements the software interrupt handlers for the +; APIC-based WinServer 3000 multiprocessor. +; +; Author: +; +; Phil Hochstetler (phil@sequent.com) 3-30-93 +; +; Environment: +; +; Kernel mode only. +; +; Revision History: +; +;-- + +.386p + .xlist +include hal386.inc +include callconv.inc ; calling convention macros +include i386\kimacro.inc +include i386\apic.inc +include i386\w3.inc + .list + + EXTRNP _KeBugCheck,1 + EXTRNP KfLowerIrql,1,IMPORT,FASTCALL + EXTRNP Kei386EoiHelper,0,IMPORT + EXTRNP _HalEndSystemInterrupt,2 + EXTRNP _KiDeliverApc,3,IMPORT + EXTRNP _KiDispatchInterrupt,0,IMPORT + EXTRNP _HalBeginSystemInterrupt,3 + + extrn _HalpIRQLtoTPR:byte + extrn _HalpLocalUnitBase:dword + extrn _HalpIrql2IRRMask:dword + +_TEXT SEGMENT DWORD PUBLIC 'CODE' + ASSUME DS:FLAT, ES:FLAT, SS:FLAT, FS:NOTHING, GS:NOTHING + + + page ,132 + subttl "Request Software Interrupt" +;++ +; +; VOID +; HalRequestSoftwareInterrupt ( +; IN KIRQL RequestIrql +; ) +; +; Routine Description: +; +; This routine is used to issue a software interrupt to the +; calling processor. Instead of using the hardware to do this, +; we have observed that emulation in software is *much* faster. +; This mostly because it takes 30 clocks or so to do a APIC access. +; The biggest win here is in avoiding having KeRaiseIrql/KeLowerIrql +; write to the APIC for 75% of the traffic (LOW_LEVEL to APC/DPC LEVEL). +; +; Arguments: +; +; (cl) = RequestIrql - Supplies the request IRQL value +; +; Return Value: +; +; None. +; +;-- + +; equates for accessing argument +; + +cPublicFastCall HalRequestSoftwareInterrupt ,1 +cPublicFpo 0, 0 + + mov eax, 1 + shl eax, cl ; create IRR bitmask + + pushfd ; save interrupt mode + cli ; disable interrupt + + or PCR[PcIRR], eax ; request SW interrupt + cmp PCR[PcHal.ProcIrql], cl ; take it now? + jb short @f + + popfd ; restore interrupt mode + + fstRET HalRequestSoftwareInterrupt ; no, just return +; +; Call KfLowerIrql(CurrentIrql) which handles unmasked software interrupts +; +@@: + mov cl, PCR[PcHal.ProcIrql] + + popfd ; restore interrupt mode + + fstCall KfLowerIrql ; (cl) = CurrentIrql + fstRET HalRequestSoftwareInterrupt + +fstENDP HalRequestSoftwareInterrupt + + page ,132 + subttl "Clear Software Interrupt" +;++ +; +; VOID +; HalClearSoftwareInterrupt ( +; IN KIRQL RequestIrql +; ) +; +; Routine Description: +; +; This routine is used to clear a possible pending software interrupt. +; Support for this function is optional, and allows the kernel to +; reduce the number of spurious software interrupts it receives/ +; +; Arguments: +; +; (cl) = RequestIrql - Supplies the request IRQL value +; +; Return Value: +; +; None. +; +;-- + +cPublicFastCall HalClearSoftwareInterrupt ,1 +cPublicFpo 0, 0 + + mov eax,1 + shl eax, cl ; convert to mask + + not eax + and PCR[PcIRR], eax ; clear pending irr bit + + fstRET HalClearSoftwareInterrupt + +fstENDP HalClearSoftwareInterrupt + + + + page ,132 + subttl "Dispatch Interrupt" +;++ +; +; VOID +; HalpDispatchInterrupt( +; VOID +; ); +; +; Routine Description: +; +; This routine is the interrupt handler for a software interrupt generated +; at DISPATCH_LEVEL. Its function is to save the machine state, raise +; Irql to DISPATCH_LEVEL, dismiss the interrupt, and call the DPC +; delivery routine. +; +; Arguments: +; +; None +; Interrupt is disabled +; +; Return Value: +; +; None. +; +;-- + + + ENTER_DR_ASSIST hdpi_a, hdpi_t + +cPublicProc _HalpDispatchInterrupt ,0 + +; +; Create IRET frame on stack +; + pop eax + pushfd + push cs + push eax + +; +; Save machine state on trap frame +; + + ENTER_INTERRUPT hdpi_a, hdpi_t +.FPO ( FPO_LOCALS+1, 0, 0, 0, 0, FPO_TRAPFRAME ) + + public HalpDispatchInterrupt2ndEntry +HalpDispatchInterrupt2ndEntry: + +; +; Save previous IRQL, set new priority level, and clear IRR bit +; + push dword ptr PCR[PcHal.ProcIrql] + mov byte ptr PCR[PcHal.ProcIrql], DISPATCH_LEVEL + and dword ptr PCR[PcIRR], NOT (1 SHL DISPATCH_LEVEL) + +; +; Now it is safe to enable interrupt to allow higher priority interrupt +; to come in. +; + sti + +; +; Go do Dispatch Interrupt processing +; + stdCall _KiDispatchInterrupt + +; +; Do interrupt exit processing +; + SOFT_INTERRUPT_EXIT ; will do an iret + +stdENDP _HalpDispatchInterrupt + + page ,132 + subttl "APC Interrupt" +;++ +; +; HalpApcInterrupt( +; VOID +; ); +; +; Routine Description: +; +; This routine is entered as the result of a software interrupt generated +; at APC_LEVEL. Its function is to save the machine state, raise Irql to +; APC_LEVEL, dismiss the interrupt, and call the APC delivery routine. +; +; Arguments: +; +; None +; Interrupt is Disabled +; +; Return Value: +; +; None. +; +;-- + + ENTER_DR_ASSIST hapc_a, hapc_t + +cPublicProc _HalpApcInterrupt ,0 + +; +; Create IRET frame on stack +; + pop eax ; get caller PC + pushfd ; flags + push cs ; cs + push eax ; ip + +; +; Save machine state on trap frame +; + + ENTER_INTERRUPT hapc_a, hapc_t +.FPO ( FPO_LOCALS+1, 0, 0, 0, 0, FPO_TRAPFRAME ) + + public HalpApcInterrupt2ndEntry +HalpApcInterrupt2ndEntry: + +; +; Save previous IRQL, set new priority level, and clear IRR bit +; + push dword ptr PCR[PcHal.ProcIrql] + mov byte ptr PCR[PcHal.ProcIrql], APC_LEVEL + and dword ptr PCR[PcIRR], NOT (1 SHL APC_LEVEL) + +; +; Now it is safe to enable interrupt to allow higher priority interrupt +; to come in. +; + sti + +; +; call the APC delivery routine. +; + + mov eax, [ebp]+TsSegCs ; get interrupted code's CS + and eax, MODE_MASK ; extract the mode + + test dword ptr [ebp]+TsEFlags, EFLAGS_V86_MASK + jz short @f + + or eax, MODE_MASK ; if v86 frame, then set user_mode +@@: + +; call APC deliver routine +; Previous mode +; Null exception frame +; Trap frame + + stdCall _KiDeliverApc, <eax, 0, ebp> + +; +; Do interrupt exit processing +; + SOFT_INTERRUPT_EXIT ; will do an iret + +stdENDP _HalpApcInterrupt + +_TEXT ends + + end diff --git a/private/ntos/nthals/halws3/i386/w3swint.bak b/private/ntos/nthals/halws3/i386/w3swint.bak new file mode 100644 index 000000000..669085cf5 --- /dev/null +++ b/private/ntos/nthals/halws3/i386/w3swint.bak @@ -0,0 +1,267 @@ + title "Software Interrupts" +;++ +; +; Copyright (c) 1992 Microsoft Corporation +; Copyright (c) 1992 Sequent Computer Systems, Inc. +; +; Module Name: +; +; w3swint.asm +; +; Abstract: +; +; This module implements the software interrupt handlers for the +; APIC-based WinServer 3000 multiprocessor. +; +; Author: +; +; Phil Hochstetler (phil@sequent.com) 3-30-93 +; +; Environment: +; +; Kernel mode only. +; +; Revision History: +; +;-- + +.386p + .xlist +include hal386.inc +include callconv.inc ; calling convention macros +include i386\kimacro.inc +include i386\apic.inc +include i386\w3.inc + .list + + EXTRNP _KeBugCheck,1 + EXTRNP KfLowerIrql,1,IMPORT,FASTCALL + EXTRNP Kei386EoiHelper,0,IMPORT + EXTRNP _HalEndSystemInterrupt,2 + EXTRNP _KiDeliverApc,3,IMPORT + EXTRNP _KiDispatchInterrupt,0,IMPORT + EXTRNP _HalBeginSystemInterrupt,3 + + extrn _HalpIRQLtoTPR:byte + extrn _HalpLocalUnitBase:dword + extrn _HalpIrql2IRRMask:dword + +_TEXT SEGMENT DWORD PUBLIC 'CODE' + ASSUME DS:FLAT, ES:FLAT, SS:FLAT, FS:NOTHING, GS:NOTHING + + + page ,132 + subttl "Request Software Interrupt" +;++ +; +; VOID +; HalRequestSoftwareInterrupt ( +; IN KIRQL RequestIrql +; ) +; +; Routine Description: +; +; This routine is used to issue a software interrupt to the +; calling processor. Instead of using the hardware to do this, +; we have observed that emulation in software is *much* faster. +; This mostly because it takes 30 clocks or so to do a APIC access. +; The biggest win here is in avoiding having KeRaiseIrql/KeLowerIrql +; write to the APIC for 75% of the traffic (LOW_LEVEL to APC/DPC LEVEL). +; +; Arguments: +; +; (cl) = RequestIrql - Supplies the request IRQL value +; +; Return Value: +; +; None. +; +;-- + +; equates for accessing argument +; + +cPublicFastCall HalRequestSoftwareInterrupt ,1 +cPublicFpo 0, 1 + + mov eax, 1 + shl eax, cl ; create IRR bitmask + or PCR[PcIRR], eax ; request SW interrupt + cmp PCR[PcHal.ProcIrql], cl ; take it now? + jb short @f + fstRET HalRequestSoftwareInterrupt ; no, just return +; +; Call KfLowerIrql(CurrentIrql) which handles unmasked software interrupts +; +@@: + mov ecx, dword ptr PCR[PcHal.ProcIrql] + fstCall KfLowerIrql ; (cl) = CurrentIrql + fstRET HalRequestSoftwareInterrupt + +fstENDP HalRequestSoftwareInterrupt + + page ,132 + subttl "Dispatch Interrupt" +;++ +; +; VOID +; HalpDispatchInterrupt( +; VOID +; ); +; +; Routine Description: +; +; This routine is the interrupt handler for a software interrupt generated +; at DISPATCH_LEVEL. Its function is to save the machine state, raise +; Irql to DISPATCH_LEVEL, dismiss the interrupt, and call the DPC +; delivery routine. +; +; Arguments: +; +; None +; Interrupt is disabled +; +; Return Value: +; +; None. +; +;-- + + + ENTER_DR_ASSIST hdpi_a, hdpi_t + +cPublicProc _HalpDispatchInterrupt ,0 + +; +; Create IRET frame on stack +; + pop eax + pushfd + push cs + push eax + +; +; Save machine state on trap frame +; + + ENTER_INTERRUPT hdpi_a, hdpi_t +.FPO ( FPO_LOCALS+1, 0, 0, 0, 0, FPO_TRAPFRAME ) + + public HalpDispatchInterrupt2ndEntry +HalpDispatchInterrupt2ndEntry: + +; +; Save previous IRQL, set new priority level, and clear IRR bit +; + push dword ptr PCR[PcHal.ProcIrql] + mov byte ptr PCR[PcHal.ProcIrql], DISPATCH_LEVEL + and dword ptr PCR[PcIRR], NOT (1 SHL DISPATCH_LEVEL) + +; +; Now it is safe to enable interrupt to allow higher priority interrupt +; to come in. +; + sti + +; +; Go do Dispatch Interrupt processing +; + stdCall _KiDispatchInterrupt + +; +; Do interrupt exit processing +; + SOFT_INTERRUPT_EXIT ; will do an iret + +stdENDP _HalpDispatchInterrupt + + page ,132 + subttl "APC Interrupt" +;++ +; +; HalpApcInterrupt( +; VOID +; ); +; +; Routine Description: +; +; This routine is entered as the result of a software interrupt generated +; at APC_LEVEL. Its function is to save the machine state, raise Irql to +; APC_LEVEL, dismiss the interrupt, and call the APC delivery routine. +; +; Arguments: +; +; None +; Interrupt is Disabled +; +; Return Value: +; +; None. +; +;-- + + ENTER_DR_ASSIST hapc_a, hapc_t + +cPublicProc _HalpApcInterrupt ,0 + +; +; Create IRET frame on stack +; + pop eax ; get caller PC + pushfd ; flags + push cs ; cs + push eax ; ip + +; +; Save machine state on trap frame +; + + ENTER_INTERRUPT hapc_a, hapc_t +.FPO ( FPO_LOCALS+1, 0, 0, 0, 0, FPO_TRAPFRAME ) + + public HalpApcInterrupt2ndEntry +HalpApcInterrupt2ndEntry: + +; +; Save previous IRQL, set new priority level, and clear IRR bit +; + push dword ptr PCR[PcHal.ProcIrql] + mov byte ptr PCR[PcHal.ProcIrql], APC_LEVEL + and dword ptr PCR[PcIRR], NOT (1 SHL APC_LEVEL) + +; +; Now it is safe to enable interrupt to allow higher priority interrupt +; to come in. +; + sti + +; +; call the APC delivery routine. +; + + mov eax, [ebp]+TsSegCs ; get interrupted code's CS + and eax, MODE_MASK ; extract the mode + + test dword ptr [ebp]+TsEFlags, EFLAGS_V86_MASK + jz short @f + + or eax, MODE_MASK ; if v86 frame, then set user_mode +@@: + +; call APC deliver routine +; Previous mode +; Null exception frame +; Trap frame + + stdCall _KiDeliverApc, <eax, 0, ebp> + +; +; Do interrupt exit processing +; + SOFT_INTERRUPT_EXIT ; will do an iret + +stdENDP _HalpApcInterrupt + +_TEXT ends + + end diff --git a/private/ntos/nthals/halws3/i386/w3sysbus.c b/private/ntos/nthals/halws3/i386/w3sysbus.c new file mode 100644 index 000000000..68cd71b7d --- /dev/null +++ b/private/ntos/nthals/halws3/i386/w3sysbus.c @@ -0,0 +1,233 @@ +/*++ + + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + w3sysbus.c + +Abstract: + +Author: + +Environment: + +Revision History: + + +--*/ + +#include "halp.h" + +extern UCHAR HalpIRQLtoTPR[]; +extern UCHAR HalpK2EISAIrq2Irql[]; + +ULONG HalpDefaultInterruptAffinity; + +BOOLEAN +HalpTranslateSystemBusAddress( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PHYSICAL_ADDRESS BusAddress, + IN OUT PULONG AddressSpace, + OUT PPHYSICAL_ADDRESS TranslatedAddress + ); + +ULONG +HalpGetSystemInterruptVector( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN ULONG BusInterruptLevel, + IN ULONG BusInterruptVector, + OUT PKIRQL Irql, + OUT PKAFFINITY Affinity + ); + +ULONG +HalpGetW3EisaInterruptVector( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN ULONG BusInterruptLevel, + IN ULONG BusInterruptVector, + OUT PKIRQL Irql, + OUT PKAFFINITY Affinity + ); + + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE,HalpTranslateSystemBusAddress) +#pragma alloc_text(PAGE,HalpGetSystemInterruptVector) +#pragma alloc_text(PAGE,HalpGetW3EisaInterruptVector) +#endif + + +BOOLEAN +HalpTranslateSystemBusAddress( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PHYSICAL_ADDRESS BusAddress, + IN OUT PULONG AddressSpace, + OUT PPHYSICAL_ADDRESS TranslatedAddress + ) + +/*++ + +Routine Description: + + This function translates a bus-relative address space and address into + a system physical address. + +Arguments: + + BusAddress - Supplies the bus-relative address + + AddressSpace - Supplies the address space number. + Returns the host address space number. + + AddressSpace == 0 => memory space + AddressSpace == 1 => I/O space + + TranslatedAddress - Supplies a pointer to return the translated address + +Return Value: + + A return value of TRUE indicates that a system physical address + corresponding to the supplied bus relative address and bus address + number has been returned in TranslatedAddress. + + A return value of FALSE occurs if the translation for the address was + not possible + +--*/ + +{ + UNREFERENCED_PARAMETER( BusHandler ); + UNREFERENCED_PARAMETER( RootHandler ); + + if (BusAddress.HighPart != 0 || *AddressSpace > 1) { + return (FALSE); + } + + TranslatedAddress->LowPart = BusAddress.LowPart; + TranslatedAddress->HighPart = 0; + + return(TRUE); +} + + +ULONG +HalpGetSystemInterruptVector( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN ULONG BusInterruptLevel, + IN ULONG BusInterruptVector, + OUT PKIRQL Irql, + OUT PKAFFINITY Affinity + ) + +/*++ + +Routine Description: + +Arguments: + + BusInterruptLevel - Supplies the bus specific interrupt level. + + BusInterruptVector - Supplies the bus specific interrupt vector. + + Irql - Returns the system request priority. + + Affinity - Returns the system wide irq affinity. + +Return Value: + + Returns the system interrupt vector corresponding to the specified device. + +--*/ +{ + ULONG SystemVector; + KIRQL lIrql; + + UNREFERENCED_PARAMETER( BusHandler ); + UNREFERENCED_PARAMETER( RootHandler ); + UNREFERENCED_PARAMETER( BusInterruptVector ); + + lIrql = (KIRQL) HalpK2EISAIrq2Irql[BusInterruptLevel]; + SystemVector = HalpIRQLtoTPR[lIrql]; + + if (BusInterruptLevel > 23 || + HalpIDTUsage[SystemVector].Flags & IDTOwned ) { + + // + // This is an illegal BusInterruptVector and cannot be connected. + // + + return(0); + } + + *Irql = lIrql; + *Affinity = HalpDefaultInterruptAffinity; + ASSERT(HalpDefaultInterruptAffinity); + return SystemVector; +} + +ULONG +HalpGetW3EisaInterruptVector( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN ULONG BusInterruptLevel, + IN ULONG BusInterruptVector, + OUT PKIRQL Irql, + OUT PKAFFINITY Affinity + ) + +/*++ + +Routine Description: + + This function returns the system interrupt vector and IRQL level + corresponding to the specified bus interrupt level and/or vector. The + system interrupt vector and IRQL are suitable for use in a subsequent call + to KeInitializeInterrupt. + +Arguments: + + BusHandle - Per bus specific structure + + Irql - Returns the system request priority. + + Affinity - Returns the system wide irq affinity. + +Return Value: + + Returns the system interrupt vector corresponding to the specified device. + +--*/ +{ + UNREFERENCED_PARAMETER( BusInterruptVector ); + + // + // On standard PCs, IRQ 2 is the cascaded interrupt, and it really shows + // up on IRQ 9. + // + if (BusInterruptLevel == 2) { + BusInterruptLevel = 9; + } + + if (BusInterruptLevel > 23) { + return 0; + } + + // + // Get parent's translation from here.. + // + return BusHandler->ParentHandler->GetInterruptVector ( + BusHandler->ParentHandler, + RootHandler, + BusInterruptLevel, + BusInterruptVector, + Irql, + Affinity + ); +} diff --git a/private/ntos/nthals/halws3/i386/w3sysint.asm b/private/ntos/nthals/halws3/i386/w3sysint.asm new file mode 100644 index 000000000..cc2b79af9 --- /dev/null +++ b/private/ntos/nthals/halws3/i386/w3sysint.asm @@ -0,0 +1,613 @@ + title "System Interrupt" +;++ +; +; Copyright (c) 1991 Microsoft Corporation +; Copyright (c) 1993 Sequent Computer Systems, Inc. +; +; Module Name: +; +; w3sysint.asm +; +; Abstract: +; +; This module implements the HAL routines to begin a system interrupt, +; end a system interrupt, and enable/disable system interrupts +; for the WinServer 3000. +; +; Author: +; +; Phil Hochstetler (phil@sequent.com) 3-30-93 +; +; Environment: +; +; Kernel Mode +; +; Revision History: +; +;-- + +.386p + .xlist +include hal386.inc +include callconv.inc ; calling convention macros +include i386\kimacro.inc +include mac386.inc +include i386\apic.inc +include i386\w3.inc + .list + + EXTRNP _KeBugCheck,1 + EXTRNP _KeLowerIrql,1 + extrn _HalpIrql2TPR:byte + extrn _HalpLocalUnitBase:dword + extrn _HalpIOunitTwoBase:dword + extrn _HalpIOunitBase:dword + extrn _HalpK2Rdir2Irq:byte + extrn _HalpELCRImage:word + extrn _HalpK2EbsIOunitRedirectionTable:dword + extrn _HalpBeginW3InterruptTable:dword + extrn _HalpK2Vector2RdirTabEntry:byte + extrn _HalpK2EISAIrq2Irql:byte + extrn _HalpK2Irql2Eisa:byte + extrn _HalpK2Vector2EISA:byte + extrn FindHigherIrqlMask:dword + extrn HalpDispatchInterrupt2ndEntry:NEAR + extrn HalpApcInterrupt2ndEntry:NEAR + extrn _HalpMASKED:WORD + +_DATA SEGMENT DWORD PUBLIC 'DATA' + +_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 handles the initial interrupt sequence for all +; external APIC interrupts for both single processor and multiple +; processor WinServer 3000 systems. On the WinServer 3000 we use +; the APIC to generate all I/O interrupts and their respective +; priorities. We do not abstract the prioritization of interrupts +; from the hardware since the APIC accomodates all Windows NT +; requirements for IRQLs. In addition to I/O interrupts the APIC +; is used to generate software interrupts for APCs and DPCs. +; The APCs and DPCs are generated by a CPU via it's +; local APIC interrupt command register. The interrupts are sent +; as a self directed interrupt. It is required by NT that software +; interrupts are always handled by the CPU which issues them. +; +; Note: Wakeup is included also in the above fashion +; +; This routine does not process an 8259 generated interrupt which +; is not tied to the APIC. This processing is done in the w3ipi.asm +; module. A subset of IRQs 0-15 are not wired through the EBS APIC. +; This is because the APIC on the EBS only accomodates 16 interrupts +; We have a total of 24 on a WS3000. We chose to have all system bus +; generated interrupts 16-23 tied to the EBS APIC. The remaining +; 8 are divided up for EISA cards. TheHalpK2EbsIounitRedirectionTable +; in k2space.asm describes the EISA IRQs chosen for the EBS APIC. +; +; Prioritization of 8259 interrupts is done by generating an APIC +; interrupt with the appropriate APIC vector which corresponds to +; the incoming 8259 IRQ number. Thus, 2 interrupts are always +; generated by an 8259 interrupt. The first is the 8259 interrupt +; and the second is the APIC interrupt. +; +; The APIC interrupt is then appropriately prioritized by the hardware +; and received accordingly via this routine. +; + +;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 - Valid interrupt and Irql raised appropriately. +; +;-- +HbsiOldIrql equ dword ptr [esp+16] +HbsiVector equ byte ptr [esp+12] +HbsiIrql equ byte ptr [esp+8] + + align 4 +cPublicProc _HalBeginSystemInterrupt ,3 + push ebx + movzx ebx, HbsiVector ; (ebx) = System Vector + jmp _HalpBeginW3InterruptTable[ebx*4] +; +; --- Process APIC external interrupt, i.e., generated via EBS I/O APIC +; - simply raise the Irql to the interrupt level of the +; current interrupt, EOI APIC, and return TRUE +; + align 4 + public _HalpBeginW3APICInterrupt + +_HalpBeginW3APICInterrupt: + mov edx, _HalpLocalUnitBase ; Get address of Local APIC + movzx eax, HbsiIrql ; Get New IRQL + mov cl, PCR[PcHal.ProcIrql] ; Get current irql + cli ; Don't trust caller.. +if DBG + cmp al, cl + ja @f ; New IRQL is > Current + push eax ; New IRQL + push ebx ; Vector + push ecx ; Old IRQL + push [edx+LU_TPR] ; + mov dword ptr [edx+LU_TPR], 0FFH + mov PCR[PcHal.ProcIrql], HIGH_LEVEL ; Set to avoid recursive error + stdCall _KeBugCheck, <0Bh> +@@: +endif + +; +; --- Do to the fact that some drivers like the i8042prt driver +; and possibly other foolhardy drivers which don't use the IRQL +; returned by the HalGetInterrupt routine when they do an IoConnectInt +; we have to use the IRQL passed and not use the vector to set the +; TPR...THESE TYPE OF DRIVERS HAVE TO BE EDGE SENSITIVE DEVICES TO +; WORK IF THEY DO THIS CRAP....We allow changes in the IRQL as long +; as it is a higher IRQL than the one returned by the HAL +; + mov PCR[PcHal.ProcIrql], al ; Set new irql + movzx eax, _HalpIrql2TPR[eax] + mov [edx+LU_TPR], eax ; Set task priority register + mov eax, [edx+LU_TPR] ; Read it to make sure write occurs + mov eax, HbsiOldIrql ; get addr to store old irql + mov [eax], cl ; save old irql in the return variable +; +; --- EOI the APIC if the interrupt is not a level sensitive EISA interrupt +; Level sensitive interrupts are EOI'ed in EndSystemInterrupt +; + xor ah, ah + mov al, _HalpK2Vector2EISA[ebx] ; Get EISA IRQ # + mov cx, _HalpELCRImage ; Get edge/level register value + mov bx, _HalpMASKED ; get PIC level interrupts + not bx + and cx, bx ; clear level bits from PIC + bt cx, ax ; test appropriate bit + jc short @f + mov [edx+LU_EOI], eax ; EOI APIC +@@: + mov eax, 1 ; True interrupt + sti ; Let interrupts go + pop ebx + + stdRET _HalBeginSystemInterrupt +; +; --- Invalid or illegal vector +; + align 4 + public _HalpBeginW3InvalidInterrupt +_HalpBeginW3InvalidInterrupt: + mov eax,0 ; return False + pop ebx + + stdRET _HalBeginSystemInterrupt +stdENDP _HalBeginSystemInterrupt + +;++ +;VOID +;HalDisableSystemInterrupt( +; IN CCHAR Vector, +; IN KIRQL Irql +; ) +; +; +; +;Routine Description: +; +; Disables a system interrupt via the EBS APIC Redirection table +; entries or the 8259 Interrupt mask registers +; +;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 +cPublicFpo 2, 0 + +; +; --- Exit if this is not the base processor +; + movzx ecx, byte ptr [esp+4] ; (ecx) = Vector + movzx eax, byte ptr PCR[PcHal.PcrNumber] + cmp al, 0 + jne HalDisableInt999 ; Exit if not base proc +cPublicFpo 2, 1 + pushfd + cli ; Disable interrupts + +; +; --- Enable/Disable does not get called for the interrupt vectors +; which are used for the 8259 generated interrupts. It only gets +; called for the the APIC vectors which correspond to the 8259 ints... +; + cmp ecx, APIC_DMA_VECTOR ; Is this for the 8259 DMA? + jne short HalDisableInt10 ; No - branch + mov ecx, 13 ; EISA DMA IRQ + jmp HalDisableInt60 ; Enable 8259 Int +HalDisableInt10: + cmp ecx, APIC_KBD_VECTOR ; Is this the keyboard vector? + jne short HalDisableInt20 ; Yes - branch + mov ecx, 1 ; Keyboard IRQ + jmp HalDisableInt60 ; Enable 8259 Int +HalDisableInt20: + cmp ecx, APIC_CLOCK_VECTOR ; 8259 clock? + jne short HalDisableInt30 ; Yes - branch + mov ecx, 0 ; Clock IRQ + jmp HalDisableInt60 +HalDisableInt30: + cmp ecx, APIC_RTC_VECTOR ; Real-time clock? + jne short HalDisableInt31 ; No -branch + mov ecx, 8 ; RTC IRQ + jmp HalDisableInt60 +HalDisableInt31: + cmp ecx, APIC_FLOPPY_VECTOR ; Floppy? + jne short HalDisableInt32 ; No -branch + mov ecx, 6 ; Floppy IRQ + jmp HalDisableInt60 +HalDisableInt32: + cmp ecx, APIC_IDE_VECTOR ; IDE Disk? + jne short HalDisableInt33 ; No -branch + mov ecx, 14 ; IDE Disk IRQ + jmp HalDisableInt60 +HalDisableInt33: + cmp ecx, APIC_MOUSE_VECTOR ; IRQ12 vector + jne short HalDisableInt34 ; No -branch + mov ecx, 12 ; IRQ12 + jmp HalDisableInt60 +HalDisableInt34: + +; +; --- Process other APIC vectors +; + xor eax,eax + mov al, _HalpK2Vector2RdirTabEntry[ecx] ; Get EBS RDIR entry + cmp al, 0FFH ; No RDIR entry..exit + je HalDisableInt50 ; ..exit + cmp al, 0 ; Not used vector + je HalDisableInt50 ; ..exit + btr eax, 7 ; EBS I/O APIC RDIR?? + jnc HalDisableInt35 ; Yes + mov edx, _HalpIOunitTwoBase ; Boot processor I/O APIC RDIR + jmp HalDisableInt40 ; continue +HalDisableInt35: + mov edx, _HalpIOunitBase ; Address of EBS I/O APIC +HalDisableInt40: +; +; No need for a lock here since only the base manipulates these registers +; + mov [edx+IO_REGISTER_SELECT], eax ; Select register + or dword ptr [edx+IO_REGISTER_WINDOW], IOMPIC_RT_MASK ; mask it +HalDisableInt50: +cPublicFpo 2, 0 + popfd + stdRET _HalDisableSystemInterrupt +; +; --- 8259 interrupt enable... +; +HalDisableInt60: +; +; --- 8259 interrupt disable... +; + mov edx, 1 + shl edx, cl ; (ebx) = bit in IMR to disable + xor eax, eax +; +; Get the current interrupt mask register from the 8259 +; + in al, PIC2_PORT1 + shl eax, 8 + in al, PIC1_PORT1 +; +; Mask off the interrupt to be disabled +; + or eax, edx +; +; Write the new interrupt mask register back to the 8259 +; + out PIC1_PORT1, al + shr eax, 8 + out PIC2_PORT1, al + PIC2DELAY +cPublicFpo 2, 0 + popfd +HalDisableInt999: + stdRET _HalDisableSystemInterrupt + +stdENDP _HalDisableSystemInterrupt + +;++ +; +;BOOLEAN +;HalEnableSystemInterrupt( +; IN ULONG Vector, +; IN KIRQL Irql, +; IN KINTERRUPT_MODE InterruptMode +; ) +; +; +;Routine Description: +; + ; Enables a system interrupt via PIC or APIC hardware masks +; +;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 +cPublicFpo 3, 0 +; +; --- The base processor controls enabling/disabling of all ints +; + movzx ecx, byte ptr [esp+4] ; (ecx) = Vector + movzx eax, byte ptr PCR[PcHal.PcrNumber] + cmp al, 0 + jne HalEnableInt999 ; Exit if not base proc +cPublicFpo 3, 1 + pushfd + cli +; +; --- Enable/Disable does not get called for the interrupt vectors +; which are used for the 8259 generated interrupts. It only gets +; called for the the APIC vectors which correspond to the 8259 ints... +; + cmp ecx, APIC_DMA_VECTOR ; Is this for the 8259 DMA? + jne short HalEnableInt10 ; No - branch + mov ecx, 13 ; EISA DMA IRQ + jmp HalEnableInt60 ; Enable 8259 Int +HalEnableInt10: + cmp ecx, APIC_KBD_VECTOR ; Is this the keyboard vector? + jne short HalEnableInt20 ; No - branch + mov ecx, 1 ; Keyboard IRQ + jmp HalEnableInt60 ; Enable 8259 Int +HalEnableInt20: + cmp ecx, APIC_CLOCK_VECTOR ; 8259 clock? + jne short HalEnableInt30 ; No - branch + mov ecx, 0 ; Clock IRQ + jmp HalEnableInt60 +HalEnableInt30: + cmp ecx, APIC_RTC_VECTOR ; Real-time clock? + jne short HalEnableInt31 ; No -branch + mov ecx, 8 ; RTC IRQ + jmp HalEnableInt60 +HalEnableInt31: + cmp ecx, APIC_FLOPPY_VECTOR ; Floppy? + jne short HalEnableInt32 ; No -branch + mov ecx, 6 ; Floppy IRQ + jmp HalEnableInt60 +HalEnableInt32: + cmp ecx, APIC_IDE_VECTOR ; IDE Disk? + jne short HalEnableInt33 ; No -branch + mov ecx, 14 ; IDE Disk IRQ + jmp HalEnableInt60 +HalEnableInt33: + cmp ecx, APIC_MOUSE_VECTOR ; IRQ12 vector + jne short HalEnableInt34 ; No -branch + mov ecx, 12 ; IRQ12 + jmp HalEnableInt60 +HalEnableInt34: + + +; +; --- Process APIC vectors +; + xor eax,eax + mov al, _HalpK2Vector2RdirTabEntry[ecx] ; Get EBS RDIR entry + cmp al, 0FFH ; No RDIR entry..exit + je HalEnableInt50 ; ..exit + cmp al, 0 ; Not used vector + je HalEnableInt50 ; ..exit + btr eax, 7 ; EBS I/O APIC RDIR?? + jnc HalEnableInt35 ; Yes + mov edx, _HalpIOunitTwoBase ; Boot processor I/O APIC RDIR + jmp HalEnableInt40 ; continue +HalEnableInt35: + mov edx, _HalpIOunitBase ; Address of EBS I/O APIC +HalEnableInt40: +; +; No need for a lock here since only the base manipulates these registers +; + mov [edx+IO_REGISTER_SELECT], eax ; Select register + and dword ptr [edx+IO_REGISTER_WINDOW], NOT IOMPIC_RT_MASK ; Unmask it +HalEnableInt50: +cPublicFpo 3, 0 + popfd + stdRET _HalEnableSystemInterrupt +; +; --- 8259 interrupt enable... +; +HalEnableInt60: + xor eax, eax +; +; Get the current interrupt mask register from the 8259 +; + in al, PIC2_PORT1 + shl eax, 8 + in al, PIC1_PORT1 +; +; Unmask the interrupt to be enabled +; + btr eax, ecx + btr eax, 2 ; Enable cascaded IRQ2 + +; +; Write the new interrupt mask register back to the 8259 +; + out PIC1_PORT1, al + shr eax, 8 + out PIC2_PORT1, al + PIC2DELAY +cPublicFpo 3, 0 + popfd +HalEnableInt999: + stdRET _HalEnableSystemInterrupt +stdENDP _HalEnableSystemInterrupt + + +; HalpEndSystemInterrupt +; IN KIRQL NewIrql, +; IN ULONG Vector +; ) +; +; Routine Description: +; +; This routine is used to lower IRQL to the specified value just prior +; to ending interrupt processing. +; +; Arguments: +; +; NewIrql - the new irql to be set. +; +; Vector - Vector number of the interrupt +; +; Note that esp+8 is the beginning of interrupt/trap frame and upon +; entering to this routine. +; +; Return Value: +; +; None. +; +;-- +HeiVector equ [esp+8] +HeiNewIrql equ [esp+4] + +cPublicProc _HalEndSystemInterrupt ,2 +cPublicFpo 2, 0 + + mov eax, HeiVector ; Get the current vector + mov edx, _HalpLocalUnitBase ; Local APIC address +if DBG + xor ecx, ecx + mov cl, byte ptr HeiNewIrql + cmp cl, PCR[PcHal.ProcIrql] + jbe short @f + push dword ptr ecx ; new irql for debugging + push dword ptr PCR[PcHal.ProcIrql] ; old irql for debugging + mov dword ptr [edx+LU_TPR], 0FFH + mov PCR[PcHal.ProcIrql], HIGH_LEVEL ; Set to avoid recursive error + stdCall _KeBugCheck, <IRQL_NOT_LESS_OR_EQUAL> +@@: +endif +; +; EOI the APIC on level EISA interrupts +; + mov al, _HalpK2Vector2EISA[eax] ; Get EISA IRQ # + mov cx, _HalpELCRImage ; Get edge/level register value + bt cx, ax ; test appropriate bit + jnc short NoEOI ; 1 means level interrupt + + ; + ; Level interrupt so we need to determine if the source + ; is the PIC or APIC. If the PIC, then we need to unmask the + ; source, if the APIC, then we need to do an EOI to the APIC. + ; + + mov cx, _HalpMASKED ; get PIC level ints + bt cx, ax ; test appropriate bit + jnc short @f ; CF=1 means PIC level int + +lock btr _HalpMASKED, ax ; atomic clear of bit + + mov cx, ax + mov ax, 1 + shl ax, cl + or al, ah + not al + mov cl, al + + in al, PIC2_PORT1 ; unmask bit in PIC + and al, cl + out PIC2_PORT1, al + + jmp short NoEOI +@@: + mov [edx+LU_EOI], eax ; EOI APIC +NoEOI: + xor eax, eax + mov al, byte ptr HeiNewIrql + +; +; Write new lower priority level into the APIC Task Priority Register +; + pushfd + cli + mov PCR[PcHal.ProcIrql], al ; set new IRQL + mov al, _HalpIrql2TPR[eax] ; get new TPR + mov [edx+LU_TPR], eax ; write new TPR + mov eax, [edx+LU_TPR] ; Flush CPU write buffer + popfd + + mov al, byte ptr HeiNewIrql ; get current irql + cmp al, DISPATCH_LEVEL ; SW ints possible? + jb short @f + stdRET _HalEndSystemInterrupt + +; +; Check for any pending software interrupts +; +@@: + mov edx, PCR[PcIRR] ; get current IRR + and edx, FindHigherIrqlMask[eax*4] + jnz short @f + stdRET _HalEndSystemInterrupt + +; +; Software interrupt(s) pending, figure out which one(s) and take it +; +@@: + cli + test dword ptr PCR[PcIRR], (1 SHL DISPATCH_LEVEL) + jz short @f + add esp, 12 + jmp HalpDispatchInterrupt2ndEntry +@@: + cmp al, APC_LEVEL + jae short @f + test dword ptr PCR[PcIRR], (1 SHL APC_LEVEL) + jz short @f + add esp, 12 + jmp HalpApcInterrupt2ndEntry +@@: + sti + stdRET _HalEndSystemInterrupt + +stdENDP _HalEndSystemInterrupt + +_TEXT ENDS + + END diff --git a/private/ntos/nthals/halws3/i386/xxbiosa.asm b/private/ntos/nthals/halws3/i386/xxbiosa.asm new file mode 100644 index 000000000..bc0173a17 --- /dev/null +++ b/private/ntos/nthals/halws3/i386/xxbiosa.asm @@ -0,0 +1,5 @@ +; +; Include code from halx86 +; This is a cpp style symbolic link + +include ..\halx86\i386\xxbiosa.asm diff --git a/private/ntos/nthals/halws3/i386/xxbiosc.c b/private/ntos/nthals/halws3/i386/xxbiosc.c new file mode 100644 index 000000000..60cf92748 --- /dev/null +++ b/private/ntos/nthals/halws3/i386/xxbiosc.c @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\xxbiosc.c" diff --git a/private/ntos/nthals/halws3/i386/xxdisp.c b/private/ntos/nthals/halws3/i386/xxdisp.c new file mode 100644 index 000000000..d48977df0 --- /dev/null +++ b/private/ntos/nthals/halws3/i386/xxdisp.c @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\xxdisp.c" diff --git a/private/ntos/nthals/halws3/i386/xxioacc.asm b/private/ntos/nthals/halws3/i386/xxioacc.asm new file mode 100644 index 000000000..8445c3404 --- /dev/null +++ b/private/ntos/nthals/halws3/i386/xxioacc.asm @@ -0,0 +1,5 @@ +; +; Include code from halx86 +; This is a cpp style symbolic link + +include ..\halx86\i386\xxioacc.asm diff --git a/private/ntos/nthals/halws3/i386/xxkdsup.c b/private/ntos/nthals/halws3/i386/xxkdsup.c new file mode 100644 index 000000000..6e569b5ac --- /dev/null +++ b/private/ntos/nthals/halws3/i386/xxkdsup.c @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\xxkdsup.c" diff --git a/private/ntos/nthals/halws3/i386/xxmemory.c b/private/ntos/nthals/halws3/i386/xxmemory.c new file mode 100644 index 000000000..920714540 --- /dev/null +++ b/private/ntos/nthals/halws3/i386/xxmemory.c @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\xxmemory.c" diff --git a/private/ntos/nthals/halws3/i386/xxstubs.c b/private/ntos/nthals/halws3/i386/xxstubs.c new file mode 100644 index 000000000..8421fb30a --- /dev/null +++ b/private/ntos/nthals/halws3/i386/xxstubs.c @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\xxstubs.c" diff --git a/private/ntos/nthals/halws3/i386/xxtime.c b/private/ntos/nthals/halws3/i386/xxtime.c new file mode 100644 index 000000000..92abb2aeb --- /dev/null +++ b/private/ntos/nthals/halws3/i386/xxtime.c @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\xxtime.c" |