diff options
Diffstat (limited to 'private/ntos/nthals/halwyse7/i386')
44 files changed, 6396 insertions, 0 deletions
diff --git a/private/ntos/nthals/halwyse7/i386/halnls.h b/private/ntos/nthals/halwyse7/i386/halnls.h new file mode 100644 index 000000000..e829faba8 --- /dev/null +++ b/private/ntos/nthals/halwyse7/i386/halnls.h @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\halnls.h" diff --git a/private/ntos/nthals/halwyse7/i386/halp.h b/private/ntos/nthals/halwyse7/i386/halp.h new file mode 100644 index 000000000..a9dbf1e13 --- /dev/null +++ b/private/ntos/nthals/halwyse7/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/halwyse7/i386/ix8259.inc b/private/ntos/nthals/halwyse7/i386/ix8259.inc new file mode 100644 index 000000000..b9e0a196a --- /dev/null +++ b/private/ntos/nthals/halwyse7/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/halwyse7/i386/ixbeep.asm b/private/ntos/nthals/halwyse7/i386/ixbeep.asm new file mode 100644 index 000000000..f53bd3e58 --- /dev/null +++ b/private/ntos/nthals/halwyse7/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/halwyse7/i386/ixbusdat.c b/private/ntos/nthals/halwyse7/i386/ixbusdat.c new file mode 100644 index 000000000..a42039752 --- /dev/null +++ b/private/ntos/nthals/halwyse7/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/halwyse7/i386/ixcmos.asm b/private/ntos/nthals/halwyse7/i386/ixcmos.asm new file mode 100644 index 000000000..7f4e7393e --- /dev/null +++ b/private/ntos/nthals/halwyse7/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/halwyse7/i386/ixcmos.inc b/private/ntos/nthals/halwyse7/i386/ixcmos.inc new file mode 100644 index 000000000..2fe289fb0 --- /dev/null +++ b/private/ntos/nthals/halwyse7/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/halwyse7/i386/ixdat.c b/private/ntos/nthals/halwyse7/i386/ixdat.c new file mode 100644 index 000000000..f6b0e34de --- /dev/null +++ b/private/ntos/nthals/halwyse7/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/halwyse7/i386/ixenvirv.c b/private/ntos/nthals/halwyse7/i386/ixenvirv.c new file mode 100644 index 000000000..e194820ba --- /dev/null +++ b/private/ntos/nthals/halwyse7/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/halwyse7/i386/ixfirm.c b/private/ntos/nthals/halwyse7/i386/ixfirm.c new file mode 100644 index 000000000..f666e405c --- /dev/null +++ b/private/ntos/nthals/halwyse7/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/halwyse7/i386/ixhwsup.c b/private/ntos/nthals/halwyse7/i386/ixhwsup.c new file mode 100644 index 000000000..ea91dc8d0 --- /dev/null +++ b/private/ntos/nthals/halwyse7/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/halwyse7/i386/ixidle.asm b/private/ntos/nthals/halwyse7/i386/ixidle.asm new file mode 100644 index 000000000..9bdd670f3 --- /dev/null +++ b/private/ntos/nthals/halwyse7/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/halwyse7/i386/ixinfo.c b/private/ntos/nthals/halwyse7/i386/ixinfo.c new file mode 100644 index 000000000..7f211f7a9 --- /dev/null +++ b/private/ntos/nthals/halwyse7/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/halwyse7/i386/ixisa.h b/private/ntos/nthals/halwyse7/i386/ixisa.h new file mode 100644 index 000000000..f67b35f49 --- /dev/null +++ b/private/ntos/nthals/halwyse7/i386/ixisa.h @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\ixisa.h" diff --git a/private/ntos/nthals/halwyse7/i386/ixisabus.c b/private/ntos/nthals/halwyse7/i386/ixisabus.c new file mode 100644 index 000000000..c1edfb067 --- /dev/null +++ b/private/ntos/nthals/halwyse7/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/halwyse7/i386/ixisasup.c b/private/ntos/nthals/halwyse7/i386/ixisasup.c new file mode 100644 index 000000000..58c426544 --- /dev/null +++ b/private/ntos/nthals/halwyse7/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/halwyse7/i386/ixkdcom.c b/private/ntos/nthals/halwyse7/i386/ixkdcom.c new file mode 100644 index 000000000..29bb8308e --- /dev/null +++ b/private/ntos/nthals/halwyse7/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/halwyse7/i386/ixkdcom.h b/private/ntos/nthals/halwyse7/i386/ixkdcom.h new file mode 100644 index 000000000..22f1aac09 --- /dev/null +++ b/private/ntos/nthals/halwyse7/i386/ixkdcom.h @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\ixkdcom.h" diff --git a/private/ntos/nthals/halwyse7/i386/ixphwsup.c b/private/ntos/nthals/halwyse7/i386/ixphwsup.c new file mode 100644 index 000000000..a1cdab598 --- /dev/null +++ b/private/ntos/nthals/halwyse7/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/halwyse7/i386/ixreboot.c b/private/ntos/nthals/halwyse7/i386/ixreboot.c new file mode 100644 index 000000000..15d7bd898 --- /dev/null +++ b/private/ntos/nthals/halwyse7/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/halwyse7/i386/ixthunk.c b/private/ntos/nthals/halwyse7/i386/ixthunk.c new file mode 100644 index 000000000..6f15aad73 --- /dev/null +++ b/private/ntos/nthals/halwyse7/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/halwyse7/i386/ixusage.c b/private/ntos/nthals/halwyse7/i386/ixusage.c new file mode 100644 index 000000000..519ec31f3 --- /dev/null +++ b/private/ntos/nthals/halwyse7/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/halwyse7/i386/wy7000mp.inc b/private/ntos/nthals/halwyse7/i386/wy7000mp.inc new file mode 100644 index 000000000..34222ea50 --- /dev/null +++ b/private/ntos/nthals/halwyse7/i386/wy7000mp.inc @@ -0,0 +1,368 @@ +;++ +; Copyright (c) 1992, 1993 Wyse Technology +; +; Module Name: +; +; wy7000mp.inc +; +; Abstract: +; +; Wyse 7000i MP include file +; +; Author: +; John Nels Fuller (o-johnf) 3-Apr-1992 +;-- + +;***************************** +; Wyse 7000i MP defines +; +WyModel740 Equ 00170335Fh ;EISA id for model 740 system board +WyModel760 Equ 00178335Fh ;EISA id for model 760 system board +WyModel780 Equ 00978335Fh ;EISA id for model 780 system board +; ;(model hasn't been named, but +; ; 780 is as good as anything) + +WyUPcpu Equ 00171335Fh ;EISA id for UP-cpu (can only be + ; read through EISA_ReadId) +WyMPcpu Equ 00179335Fh ;EISA id for MP-cpu (can only be + ; read through EISA_ReadId) +WyIDmask Equ 00FFFFFFFh ;mask out rev/speed for cpu id + +WyShadowArea Equ 0000F0000h ;physical address of BIOS RAM shadow +WyShadowLength Equ 000010000h ;length of BIOS RAM shadow (64Kb) + +WarmResetVector Equ 000000467h ;address of low mem reset variable + +EISA_Functions Equ 00000F859h ;offset into BIOS of EISA Int 15h +EISA_ReadId Equ 00000D884h ;function to read EISA slot ID +MPFW_FuncTable Equ 0FFFE0100h ;physical address of F/W function table + fnICU_Sync_Mstr Equ 25h ;function number of F/W routine to + ; cause specified cpu's to sync and + ; report back (used to verify that + ; installed cpu's are running) + fnICU_Send_Mstr Equ 23h ;function number of F/W routine to + ; send command/data packtets to other + ; cpu's (cpu's must be running in + ; F/W or Diag as at boot time). + fnOS_Diag_Mon Equ 0Dh ;function number of O/S transfer + ; to Diagnostic monitor + fnOS_Panic Equ 0Ch ;function number of O/S transfer + ; to Diagnostic monitor for NMI/crash + ; panic + +; These four reigisters access the bus control unit chip (BCU) for the +; Wyse Wyde Bus(tm) (WWB), CpuIntCmd and CpuPriortyLevel are read only +; except for the local cpu (i.e. My+CpuIntCmt and My+CpuPriortyLevel). + +CpuPtrReg Equ 0800h ;cpu pointer register (add WWB slot*16) +CpuDataReg Equ 0804h ;cpu data register (add WWB slot*16) +CpuIntCmd Equ 0802h ;cpu interrupt cmd reg (add WWB slot*16) +CpuPriortyLevel Equ 0806h ;cpu int priority level (add WWB slot*16) + +; These two registers access the cache control unit chip (CCU) +; (80486 mp-cpu's only) + +CpuCCUptr Equ 0C00h ;CCU pointer register (add WWB slot*16) +CpuCCUdata Equ 0C02h ;CCU data register (add WWB slot*16) + +; These three registers access the three Wyde Bus Interface chips (WBI) +; (80486 mp-cpu's only) + +CpuWBIlow Equ 0C04h ;low WBI register (add WWB slot*16) +CpuWBIhigh Equ 0C06h ;high WBI register (add WWB slot*16) +CpuWBIaddr Equ 0C08h ;addr WBI register (add WWB slot*16) + +; These two registers access the WWB Data Controller chip (WDC) +; (Pentium cpu's only) (DON'T add WWB slot*16 to these addresses) + +MyCpuWDCptr Equ 0CF0h ;WDC pointer register +MyCpuWDCdata Equ 0CF2h ;WDC data register + +; These two registers access the WWB Data Path chip (WDP) +; (Pentium cpu's only) (DON'T add WWB slot*16 to these addresses) + +MyCpuWDPlow Equ 0CF4h ;low WDP register +MyCpuWDPhigh Equ 0CF6h ;high WDP register + +; Each cpu has a 16450 uart connected to the diagnostic serial port +; on the back of the machine, only one cpu's 16450 is enabled (normally +; processor 0) so the WWB slot for that cpu must be used for other +; cpu's to access it. However, not all variations of cpu boards +; support access to this uart from another cpu. + +CpuDiagUart Equ 0808h ;16450 base address (add WWB slot*16) + +; Use these fixed WWB slots numbers for modifing above i/o addresses + +My Equ 00F0h ;WWB slot number specifies local cpu +Sys Equ 0000h ;WWB slot number for system board + ; use for 760/780 system board only + ; and only for BCU/ICU registers +; +; The following registers are accessed by writing the register number +; to CpuPtrReg and then reading or writing the 16-bit data at CpuDataReg +; each 16-bit access to CpuDataReg toggles bit 1 of CpuPtrReg so, for +; example to access both ICU_IMR0 and ICU_IMR1 write ICU_IMR0 to +; CpuPtrReg and do two 16-bit i/o's to CpuDataReg to access first the +; low word and then the high word of the mask register. +; +ICU_SYS_CPU Equ 00h ;system cpu config register +ICU_CPU_MASTER Equ 04h ;system cpu master register +ICU_CPU_SYNC Equ 08h ;cpu synchronization register +BCU_STAT0 Equ 0Ch ;BCU status register 0 + PERR_LOW Equ 02h ;parity error, low 32-bits of data bus + PERR_HIGH Equ 04h ;parity error, high 32-bits of data bus + PERR_ADDR Equ 08h ;parity error, address bus + PERR_CCU Equ 10h ;cache control unit error + PERR_TAG Equ 20h ;snoop tag parity error + NOT_FAIL Equ 80h ;when zero red LED on CPU is on +CPU_STAT Equ 10h ;CPU status register +BCU_ID Equ 14h ;Slot identification (bits 0-3) + WWB_ID_MASK Equ 0Fh ;these bits are WWB slot number +BCU_GPR Equ 18h ;General purpose register +BCU_BCTLR Equ 1Ch ;BCU control register + A20M_WWB Equ 01h ;when set gate A20 comes from 8042 + A20M_CPU Equ 02h ;when set forces A20 to be masked + SLOW_ENB Equ 04h ;when set allows CPUSlowDown from + ; EISA chipset to drive CPU Hold + ; (for 8Mhz emulation) + SNP_ENB Equ 08h ;when set the cache snoops bus cycles + BCU_FWT Equ 10h ;when set two extra clocks are inserted + ; in cache line operations +BCU_ERRCTLR Equ 20h ;BCU error control register + ERR_MODE Equ 03h ;error mode field mask + ERR_MODE0 Equ 00h ;report no errors + ERR_MODE1 Equ 01h ;Local CPU gets NMI (only local CPU + ; can see this) + ERR_MODE2 Equ 02h ;report to WWB NMI line (all CPU's + ; may see this) + ERR_MODE3 Equ 03h ;report on WWB PCHK line (all CPU's + ; and ISP may see this, ISP may assert + ; WWB NMI in response) + NMI_ENB Equ 04h ;enable NMI's to CPU + WWB_NMI Equ 08h ;enable WWB NMI to cause NMI this CPU + WWB_PCHK Equ 10h ;enable WWB PCHK to cause NMI this CPU +BCU_STAT1 Equ 24h ;BCU status register 1 + NMISRC_WWB Equ 01h ;NMI source is WWB NMI + NMISRC_PCHK Equ 02h ;NMI source is WWB PCHK + NMISRC_BTO Equ 04h ;NMI source is WWB bus timeout + NMISRC_EXT Equ 08h ;NMI source is NMI button on CPU + NMISRC_ICU Equ 10h ;NMI source is ICU (send NMI to Slot) +ICU_DATA Equ 40h ;ICU data register +ICU_ICTLR Equ 44h ;ICU control register + WWB_INT Equ 01h ;specifies this ICU to be master + IACK_MODE Equ 02h ;set for MP interrupt mode + ICU_AEOI Equ 04h ;automatic EOI for ICU interrupts + INT_ENB Equ 08h ;enable interrupts from ICU + TMR_TEST Equ 10h ;select timer test mode + IVP_TEST Equ 40h ;select Int Vector Processor test mode + MSK_CPURST Equ 80h ;set to prevent 8042 from reseting cpu +ICU_IMR0 Equ 48h ;ICU int mask register (low 16 bits) +ICU_IMR1 Equ 4Ah ;ICU int mask register (high 16 bits) + IMR_MASK Equ 007FFFFFh ;only bits 0-22 are valid +ICU_MSKPND0 Equ 4Ch ;ICU masked pending register (low) +ICU_MSKPND1 Equ 4Eh ;ICU masked pending register (high) +ICU_VB0 Equ 50h ;vector base register 0 +ICU_VB1 Equ 54h ;vector base register 1 +ICU_VB2 Equ 58h ;vector base register 2 +ICU_STAT Equ 5Ch ;ICU status register + INSERV0 Equ 01h ;int in service bit 0 + INSERV1 Equ 02h ;int in service bit 1 +ICU_PSR0 Equ 60h ;pending status register (low) +ICU_PSR1 Equ 62h ;pending status register (high) +ICU_CNT_VAL Equ 64h ;timer count current value +ICU_CNT_REG Equ 68h ;timer count register +ICU_LIPTR Equ 6Ch ;local interrupt ptr register + ;each field specifies the Local/IPI + ;interrupt level of a local bus intr. + ;with 0 meaning the intr. is disabled + ;Each Local/IPI int level maps to a + ;specific CpuPriorityLevel (CPL)--see + ;chart in WYIRQL.ASM. CPL is also the + ;bit # in ICU_IMR to mask the level. + lipSlot Equ 7000h ;mask for slot IPI interrupt + lipSlotShl Equ 12 ;shift for slot IPI interrupt field + lipSlotVal Equ 1 Shl lipSlotShl ;IPI level used by this Hal + lipSlotCPL Equ 1 ;CPL / IMR bit number + lipGlobal Equ 0700h ;mask for global IPI interrupt + lipGlobalShl Equ 8 ;shift for global IPI interrupt field + lipGlobalVal Equ 3 Shl lipGlobalShl ;IPI level used by this Hal + lipGlobalCPL Equ 3 ;CPL / IMR bit number + lipSerial Equ 0070h ;mask for diagnostic uart interrupt + lipSerialShl Equ 4 ;shift for uart interrupt field + lipSerialVal Equ (lipGlobalVal Shr lipGlobalShl) Shl lipSerialShl + ;use same as Global + lipSerialCPL Equ lipGlobalCPL ;CPL / IMR bit number + lipTimer Equ 0007h ;mask for local timer interrupt + lipTimerShl Equ 0 ;shift for timer interrupt field + lipTimerVal Equ 2 Shl lipTimerShl ;IPI level used by this Hal + lipTimerCPL Equ 2 ;CPL / IMR bit number + lipDefault Equ lipSlotVal+lipTimerVal+lipSerialVal+0 ;Global off +ICU_CNTREC Equ 70h ;recovery count register +ICU_VIN Equ 74h ;vector in register +ICU_VOUT Equ 78h ;vector out register +SYS_WBI_LOW Equ 0F0h ;low WBI register (system board only) +SYS_WBI_HIGH Equ 0F4h ;high WBI register (system board only) +SYS_WBI_ADDR Equ 0F8h ;addr WBI register (system board only) + +; +; The following describes the CpuIntCmd register +; +ICU_CMD_BUSY Equ 0100h ;do not issue command while set +ICU_IPI_SLOT Equ 0060h ;IPI cpu in slot (add WWB slot number) +ICU_CLR_INSERV0 Equ 00E8h ;clear interrupt in service bit 0 +ICU_CLR_INSERV1 Equ 00E9h ;clear interrupt in service bit 1 +ICU_XMT_INT_SND Equ 0020h ;rebroadcast int (add CPL of int) + ;(cannot be used for CLOCK2/IPI) +ICU_XMT_GLB_INT Equ 00E0h ;Send global interrupt + +; +; The following describes each WBI register +; +WBI_SLT_MSK Equ 000Fh ;WWB slot number +WBI_FPAR_ERR Equ 0010h ;force parity error for diagnostics +WBI_IACK_MODE Equ 0020h ;set for MP interrupt acknowlege mode +WBI_FWT Equ 0040h ;force 2 clock cycles on Cpu bus +; Equ 0080h ;reserved +WBI_PE_IN_0 Equ 0100h ;for data WBI's: + ; parity err in 1st inbound data phase + ;for addr WBI: + ; parity err in inbound address +WBI_PE_IN_1 Equ 0200h ;for data WBI's: + ; parity err in 2nd inboud data phase + ;for addr WBI: + ; parity err in inbound address +WBI_PE_OUT_CPU Equ 0400h ;data parity err outbound data from cpu +WBI_PE_OUT_CSH Equ 0800h ;data perr outbound data from cache +WBI_PE_BYTE0 Equ 1000h ;parity error in byte lane 0 +WBI_PE_BYTE1 Equ 2000h ;parity error in byte lane 1 +WBI_PE_BYTE2 Equ 4000h ;parity error in byte lane 2 +WBI_PE_BYTE3 Equ 8000h ;parity error in byte lane 3 + +; The following describes the bits in the WDP register that concern HAL +; +WDP_IACK_MODE Equ 0020h ;set for MP interrupt acknowlege mode +WDP_FPE_EN Equ 0040h ;enable CPU FERR onto WWB (to IRQ13) + +; +; The following registers are accessed by writing the register number +; to CpuCCUptr and then reading or writing the 16-bit data at CpuCCUdata. +; +CCU_CR Equ 00h ;CCU control register + CACHE_EN Equ 0001h ;enable secondary cache + BURST_EN Equ 0002h ;enable CPU burst cycles + WWB_FPE_EN Equ 0004h ;enable CPU FERR onto WWB (to IRQ13) + ;(reset to use int 10h trap for + ; floating point errors, thus + ; preventing IRQ13's for FP err) + TPEN Equ 0008h ;cache tag parity enable + SHADOW_ROM_EN Equ 0010h ;enable BIOS ROM shadow in 1st Mb + AMOD Equ 0020h ;enable local memory mapped I/O to + ; cache data/tags for diagnostics, + ; flash rom write area, diagnostic + ; ROM area. + SRAM_MODE Equ 0040h ;specifies type of SRAM used for + ; cache, standard/~synchronous + SYSCONFIG Equ 0080h ;allows configuration cycles to be + ; run on WWB + PCD_EN Equ 0100h ;enables use of cpu PCD output + RDWT Equ 0200h ;adds one wait cycle to reads + WRWT_MSK Equ 0C00h ;mask for write wait cycle count field + BRWT Equ 1000h ;adds one wiat state on cpu burst reads + FST_ODD Equ 2000h ;force odd parity on cache state bits + ; for diagnostics + FTAG_ODD Equ 4000h ;force odd parity on cache tag bits + ; for diagnostics + CCU_FWT Equ 8000h ;force two clocks for cache-WBI data + ; transfers (cache fill, copy back, + ; intervention, & snoop update) +CCU_ERR0 Equ 18h ;CCU latched error status register 0 + TPAR Equ 0001h ;tag parity bit + SNP_ERR Equ 0002h ;snoop error + TAG_DATA Equ 1FFCh ;tag data bits + CCU_STATE Equ 6000h ;cache line state bits: + ; 0=default, 1=exclusive, 2=shared + ; 3=modified + SPAR Equ 8000h ;state parity bit +CCU_ERR1 Equ 1Ah ;CCU latched error status register 1 + TAGINDEX Equ 3FFFh ;tag index address + CPU_DPE Equ 4000h ;cpu data parity error + VALID_ERROR Equ 8000h ;set when CCU_ERR0,1 have valid info +CCU_ID Equ 1Ch ;CCU has WWB slot number +;***************************** +; end of list + + +; +; The kernel leaves some space (64 byte) 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 +; dependant. +; + + +PcHalData struc +; pchStallCnt dd ? ;per processor stall count + pchCurLiptr dd ? ;per processor current ICU_LIPTR + pchPrNum db ? ;NT's processor number + pchPrSlot db ? ;WWB processor slot + pchPentiumFlag db ? ;non-zero if current cpu is a Pentium + pchHwIrql db ? ;Irql to which CpuPriorityLevel is + ;programmed. Due to lazy Irql's this + ;may be different than PcIrql +PcHalData ends + + +cr equ 0ah +lf equ 0dh + +PIC1_BASE equ PRIMARY_VECTOR_BASE +PIC2_BASE equ PRIMARY_VECTOR_BASE + 8 +IPIv_BASE equ PRIMARY_VECTOR_BASE + 16 + +PIC_SLAVE_IRQ equ 2 + +IFDEF STD_CALL + +enproc macro pn + if DBG + %out enproc pn + ifndef _ProcSub@4 + extrn _ProcSub@4:NEAR + endif ;_ProcSub + push pn ;save routine number + call _ProcSub@4 ;write to BCU_GPR + endif ;DBG + endm + +exproc macro pn + if DBG + %out exproc pn + push (pn) or 80h ;save routine number and exit flag + call _ProcSub@4 ;write to BCU_GPR + endif ;DBG + endm + +ELSE + +enproc macro pn + if DBG + %out enproc pn + ifndef _ProcSub + extrn _ProcSub:NEAR + endif ;_ProcSub + push pn ;save routine number + call _ProcSub ;write to BCU_GPR + lea esp, [esp][4] ;remove parameter w/o altering flags + endif ;DBG + endm + +exproc macro pn + if DBG + %out exproc pn + push (pn) or 80h ;save routine number and exit flag + call _ProcSub ;write to BCU_GPR + lea esp, [esp][4] ;remove parameter w/o altering flags + endif ;DBG + endm +ENDIF diff --git a/private/ntos/nthals/halwyse7/i386/wyclock.asm b/private/ntos/nthals/halwyse7/i386/wyclock.asm new file mode 100644 index 000000000..c2335419b --- /dev/null +++ b/private/ntos/nthals/halwyse7/i386/wyclock.asm @@ -0,0 +1,1292 @@ + title "Interval Clock Interrupt" +;++ +; +; Copyright (c) 1989-1993 Microsoft Corporation +; Copyright (c) 1992, 1993 Wyse Technology +; +; Module Name: +; +; wyclock.asm +; +; Abstract: +; +; This module implements the code necessary to field and process the +; interval clock interrupt. +; +; Author: +; +; Shie-Lin Tzong (shielint) 12-Jan-1990 +; +; Environment: +; +; Kernel mode only. +; +; Revision History: +; +; bryanwi 20-Sep-90 +; +; Add KiSetProfileInterval, KiStartProfileInterrupt, +; KiStopProfileInterrupt procedures. +; KiProfileInterrupt ISR. +; KiProfileList, KiProfileLock are delcared here. +; +; shielint 10-Dec-90 +; Add performance counter support. +; Move system clock to irq8, ie we now use RTC to generate system +; clock. Performance count and Profile use timer 1 counter 0. +; The interval of the irq0 interrupt can be changed by +; KiSetProfileInterval. Performance counter does not care about the +; interval of the interrupt as long as it knows the rollover count. +; Note: Currently I implemented 1 performance counter for the whole +; i386 NT. It works on UP and SystemPro. +; +; John Vert (jvert) 11-Jul-1991 +; Moved from ke\i386 to hal\i386. Removed non-HAL stuff +; +; shie-lin tzong (shielint) 13-March-92 +; Move System clock back to irq0 and use RTC (irq8) to generate +; profile interrupt. Performance counter and system clock use time1 +; counter 0 of 8254. +; +; John Fuller (o-johnf) 1-Apr-92 +; convert to Wyse 7000i MP system, clock goes to cpu's local timer, +; profile interrupt and performance counter use 8254 timer1 counter 0, +; use cpu's local timer to initialize stall execution. +;-- + +.386p + .xlist +include hal386.inc +include callconv.inc ; calling convention macros +include i386\ix8259.inc +include i386\kimacro.inc +include mac386.inc +include i386\wy7000mp.inc + .list + + extrn ReadMyCpuReg:NEAR + extrn WriteMyCpuReg:NEAR + EXTRNP _DbgBreakPoint,0,IMPORT + EXTRNP _KeUpdateSystemTime,0 + EXTRNP _KeUpdateRunTime,1,IMPORT + EXTRNP _KeProfileInterrupt,1,IMPORT + EXTRNP _KeSetTimeIncrement,2,IMPORT + EXTRNP Kei386EoiHelper,0,IMPORT + EXTRNP _HalEndSystemInterrupt,2 + EXTRNP _HalBeginSystemInterrupt,3 + EXTRNP _HalpAcquireCmosSpinLock ,0 + EXTRNP _HalpReleaseCmosSpinLock ,0 + extrn _HalpIRQLtoCPL:BYTE + extrn _HalpIRQLtoVector:BYTE + +; +; 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 1193000 + +; +; Constants used to initialize CMOS/Real Time Clock +; + +D_INT032 EQU 8E00h ; access word for 386 ring 0 interrupt gate + +RTC_OFFSET_SECOND EQU 0 ; second field of RTC memory +RTC_OFFSET_MINUTE EQU 2 ; minute field of RTC memory +RTC_OFFSET_HOUR EQU 4 ; hour field of RTC memory +RTC_OFFSET_DAY_OF_WEEK EQU 6 ; day-of-week field of RTC memory +RTC_OFFSET_DATE_OF_MONTH EQU 7 ; date-of-month field of RTC memory +RTC_OFFSET_MONTH EQU 8 ; month field of RTC memory +RTC_OFFSET_YEAR EQU 9 ; year field of RTC memory +RTC_OFFSET_CENTURY EQU 32h ; Century field of RTC memory + +; +; ==== Values used for System Clock ==== +; + +; Convert the interval to rollover count for ICU local timer (ltimer) device. +; Since ltimer counts down a 16 bit value at a one count every 240ns and the +; interval is in units of 100ns, the computation is: +; RolloverCount = (Interval*10)/24 = (Interval*5)/12 +; Therefore, for an integral RolloverCount, Interval must be a multiple of +; 1.2us. Since RolloverCount is a 16-bit count the maximum Interval is +; (65535*12)/5 or 15.7284ms. +; +; For the convience of HalpInitializeStallExecution the TIME_INCREMENT +; should be chosen to be an integral number of microseconds. Hence +; TIME_INCREMENT should be a multiple of 60 (6us). +; +; The default Interrupt interval is 10.002ms (8335 * 1.2us) +; + +TIME_INCREMENT EQU 100020 ; 10.002ms +ROLLOVER_COUNT EQU (TIME_INCREMENT*5)/12 + +; +; ==== Values used for performance counter +; +; Maximum counter value for timer1 (8254) and its corresponding interrupt +; interval. These values are for profiling and performance counter support. +; +; This value is equivalent to a value of zero (counter is 16-bit). +; So, the rollover rate is approximately 18.2 Hz. +; Note this value will be used if no profiling support. +; +MAXIMUM_ROLLOVER_COUNT Equ 0FFFFh +MAXIMUM_ROLLOVER_INTERVAL Equ 861D2h ; in 100ns units + +_DATA SEGMENT DWORD PUBLIC 'DATA' + +; +; The following array stores the per microsecond loop count for each +; central processor. +; + +; +; 8254 spinlock. This must be acquired before touching the 8254 chip. +; + public _Halp8254Lock + +_Halp8254Lock dd 0 + +; +; Init Stall count must have a spin lock. This lock is held a long time +; but only processors tring to initialize the stall count will wait. +; +iscSpinLock dd 0 + +HalpProfileRolloverCnt dd MAXIMUM_ROLLOVER_COUNT + public HalpPerfCounterLow + public HalpPerfCounterHigh +HalpPerfCounterLow dd 0 +HalpPerfCounterHigh dd 0 +HalpRollOverCount dd 0 +HalpNextRolloverCount dd MAXIMUM_ROLLOVER_COUNT +HalpProfilingStopped dd -1 ;stopped when this is negative +HalpPerfCounterInit dd 0 + public HalpHackEsp +HalpHackEsp dd 0 + +_DATA ends + + +_TEXT 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 the local timer +; to generate an interrupt at every 15ms interval +; +; See the definition of TIME_INCREMENT and ROLLOVER_COUNT if clock rate +; needs to be changed. +; +; Arguments: +; +; None +; +; Return Value: +; +; None. +; +;-- +cPublicProc _HalpInitializeClock ,0 + enproc 4 + +; +; Fill in PCR value with TIME_INCREMENT +; + + mov eax, TIME_INCREMENT + stdCall _KeSetTimeIncrement, <eax, eax> + + pushfd ; save caller's eflag + cli ; make sure interrupts are disabled + +; +; Set clock rate for Wyse local timer +; + mov al, ICU_CNT_REG + mov dx, My+CpuPtrReg + out dx, al + mov dx, My+CpuDataReg + mov ax, ROLLOVER_COUNT + out dx, ax + +; +; Initialize rollover count for performance counter and profiling +; + cmp fs:PcHal.pchPrNum, 0 ;master cpu? + jne short HICexit ;jump if not + +; +; Since this happens only on master cpu before other cpu's are started +; we do not need to aquire Halp8254Lock. +; + stdCall _HalpSetRolloverCount, <MAXIMUM_ROLLOVER_COUNT> + +HICexit: + + exproc 4 + popfd ; restore caller's eflag + stdRET _HalpInitializeClock + +stdENDP _HalpInitializeClock + + 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: +; +; Current implementation assumes that all the processors share +; the same Real Time Clock. So, the dispatcher database lock is +; acquired before entering this routine to guarantee only one +; processor can access the routine. +; +;-- +isc00: sti + SPIN_ON_SPINLOCK eax, <isc01> + +KiseInterruptCount equ [ebp-12] ; local variable + +cPublicProc _HalpInitializeStallExecution ,1 + enproc 7 + + push ebp ; save ebp + mov ebp, esp ; set up 12 bytes for local use + sub esp, 12 + + pushfd ; save caller's eflag + +; +; Initialize Cpu Local Timer to interrupt us for every 15ms at +; PROFILE_LEVEL-19 +; +; +; acquire spin lock to prevent two processors from doing this routine at +; the same time +; +isc01: cli + lea eax, iscSpinLock + ACQUIRE_SPINLOCK eax, isc00 +; +; Get and save current local interrupt pointer register +; + + push ICU_LIPTR + call ReadMyCpuReg + push eax ; save for later + push lipTimer ; set to only timer at PROFILE_LEVEL-19 + ;(must use an otherwise unused level + ; or at least one that won't generate + ; an interrupt until all processors + ; have been started) + push ICU_LIPTR + call WriteMyCpuReg + +; +; Get and save current ICU interrupt masks +; + push ICU_IMR0 + call ReadMyCpuReg ; get local interrupt masks (low) + shl eax, 16 + in ax, dx ; get local interrupt masks (high) + push eax ; save the masks + + movzx ecx, _HalpIRQLtoCPL[PROFILE_LEVEL-19] + mov eax, IMR_MASK ; all ints masked out + btr eax, ecx ; clear bit for local timer + out dx, ax ; set new mask (low) + rol eax, 16 + out dx, ax ; set new mask (high) + +; +; Since RTC interrupt will come from PROFILE_LEVEL-19, we need to +; Save original IDT descriptor and set the descriptor to point to +; our own handler. +; + movzx ecx, _HalpIRQLtoVector[PROFILE_LEVEL-19] + sidt fword ptr [ebp-8] ; get IDT address + mov edx, [ebp-6] ; (edx)->IDT + + push dword ptr [edx+8*ecx] + ; (TOS) = original desc of IRQ 8 + push dword ptr [edx+8*ecx + 4] + ; each descriptor has 8 bytes + push edx ; (TOS) -> IDT + mov eax, offset FLAT:RealTimeClockHandler + mov word ptr [edx+8*ecx], ax + ; Lower half of handler addr + mov word ptr [edx+8*ecx+2], KGDT_R0_CODE + ; set up selector + mov word ptr [edx+8*ecx+4], D_INT032 + ; 386 interrupt gate + shr eax, 16 ; (ax)=higher half of handler addr + mov word ptr [edx+8*ecx+6], ax + mov dword ptr KiseinterruptCount, 0 ; set no interrupt yet + + mov dx, My+CpuPriortyLevel + in ax, dx ;get old CPL + shl eax, 16 + push ICU_CNT_REG + call ReadMyCpuReg ;read old tick count + push eax ;save for later + push ROLLOVER_COUNT + push ICU_CNT_REG + call WriteMyCpuReg + movzx eax, _HalpIRQLtoCPL[PROFILE_LEVEL-19] + inc eax ;allow this level interrupt + mov dx, My+CpuPriortyLevel + out dx, ax + +; +; Now enable the interrupt and start the counter +; (As a matter of fact, only local timer can come through.) +; + + xor eax, eax ; (eax) = 0, initialize loopcount + sti +kise10: + add eax, 1 ; increment the loopcount + jnz short kise10 +; +; Counter overflowed +; + + stdCall _DbgBreakPoint + +; +; Our RealTimeClock interrupt handler. The control comes here through +; irq 8. +; Note: we discard first two real time clock interrupts and compute the +; permicrosecond loopcount on receiving of the third real time +; interrupt. This is because the first interrupt may be already +; pending in which case the second is generated based on the previous +; real time tick interval. +; + +RealTimeClockHandler: + + inc dword ptr KiseInterruptCount ; increment interrupt count + cmp dword ptr KiseInterruptCount, 2 ; Is this 1st or 2nd interrupt? + ja short kise25 ; no, its the third go process it + pop eax ; get rid of original ret addr + push offset FLAT:kise10 ; set new return addr + +; +; dismiss interrupt at ICU +; + mov dx, My+CpuIntCmd +@@: in ax, dx + test eax, ICU_CMD_BUSY + jnz @B + mov al, ICU_CLR_INSERV1 ; clear interrupt in service bit + out dx, ax + + xor eax, eax ; reset loop counter + +cPublicProc _HalpICUSpurious ,0 + iretd +stdENDP _HalpICUSpurious + +kise25: + +; +; ** temporary - check for incorrect KeStallExecutionProcessorLoopCount +; + +if DBG + cmp eax, 0 + jnz short kise30 + stdCall _DbgBreakPoint + +endif + ; never return +; +; ** End temporay code +; + +kise30: + xor edx, edx ; (edx:eax) = divident + mov ecx, TIME_INCREMENT / 10; (ecx) = time spent in the loop + div ecx ; (eax) = loop count per microsecond + cmp edx, 0 ; Is remainder =0? + jz short kise40 ; yes, go kise40 + inc eax ; increment loopcount by 1 +kise40: + movzx ecx, byte ptr [ebp+8] ; Current processor number + mov fs:PcStallScaleFactor, eax ; save in per processor data + +; +; Reset return address to kexit +; + + pop eax ; discard original return address + push offset FLAT:kexit ; return to kexit + + and word ptr [esp+8], NOT 0200H ; Disable interrupt upon return + iretd + +kexit: ; Interrupts are disabled +; push original tick count (already on stack) + push ICU_CNT_REG + call WriteMyCpuReg ; restore original tick count + shr eax, 16 ; original CPL to AX + mov dx, My+CpuPriortyLevel + out dx, ax ; restore original CPL + + pop edx ; (edx)->IDT + movzx ecx, _HalpIRQLtoVector[PROFILE_LEVEL-19] + pop [edx+8*Ecx+4] + ; restore higher half of NMI desc + pop [edx+8*Ecx] + ; restore lower half of NMI desc +; push original interrupt masks (already on stack) + push ICU_IMR1 + call WriteMyCpuReg ; restore original mask (high) + rol eax, 16 + out dx, ax ; restore original mask (low) + +; push original local interrupt pointer (already on stack) + push ICU_LIPTR + call WriteMyCpuReg ; restore original LIPTR + +; +; dismiss interrupt at ICU +; + mov dx, My+CpuIntCmd +@@: in ax, dx + test eax, ICU_CMD_BUSY + jnz @B + mov al, ICU_CLR_INSERV1 ; clear interrupt in service bit + out dx, ax + + lea eax, iscSpinLock + RELEASE_SPINLOCK eax + + exproc 7 + 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 + + + mov ecx, MicroSeconds ; (ecx) = Microseconds + jecxz short kese10 ; return if no loop needed + + + mov eax, fs:PcStallScaleFactor ; get per microsecond + ; loop count for the processor + mul ecx ; (eax) = desired loop count + +if DBG + +; +; Make sure we the loopcount is less than 4G and is not equal to zero +; + + cmp edx, 0 + jz short kese + stdCall _DbgBreakPoint ; stop ... +;; align 4 +kese: cmp eax,0 + jnz short kese0 + stdCall _DbgBreakPoint ; stop ... +endif + +kese0: + sub eax, 1 ; (eax) = (eax) - 1 + jnz short kese0 +kese10: + stdRET _KeStallExecutionProcessor + +stdENDP _KeStallExecutionProcessor + + + +;++ +; +; PROFILING AND PERFORMANCE COUNTER SUPPORT +; +;-- + +;++ +; +; HalStartProfileInterrupt( +; IN ULONG Reserved +; ); +; +; Routine Description: +; +; What we do here is change the interrupt +; rate from the slowest thing we can get away with to the value +; that's been KeSetProfileInterval +; +;-- + +cPublicProc _HalStartProfileInterrupt ,1 + +; +; Prevent races by aquiring Halp8254Lock +; + + pushfd +HStartPI01: + cli + test fs:PcHal.pchCurLiptr, lipGlobal + jnz short HStartPI08 ;jump if already started + lea eax, _Halp8254Lock + ACQUIRE_SPINLOCK eax, HStartPI10 + +; +; Mark profiling as active +; + + inc HalpProfilingStopped ;protected by spinlock + jnz short HStartPI06 ;jump if RollerCount already set + +; +; Set the interrupt rate to what is actually needed +; + + stdCall _HalpSetRolloverCount, <HalpProfileRolloverCnt> + +HStartPI06: + lea eax, _Halp8254Lock + RELEASE_SPINLOCK eax + push lipDefault+lipGlobalVal + push ICU_LIPTR + call WriteMyCpuReg + mov fs:PcHal.pchCurLiptr, eax +HStartPI08: + popfd + stdRET _HalStartProfileInterrupt + +HStartPI10: + sti + SPIN_ON_SPINLOCK eax, HStartPI01 + +stdENDP _HalStartProfileInterrupt + + + +;++ +; +; HalStopProfileInterrupt( +; IN ULONG Reserved +; ); +; +; Routine Description: +; +; What we do here is change the interrupt +; rate from the high profiling rate to the slowest thing we +; can get away with for PerformanceCounter rollover notification. +; +;-- + +cPublicProc _HalStopProfileInterrupt ,1 + +; +; Prevent races +; + pushfd +HStopPI01: + cli + test fs:PcHal.pchCurLiptr, lipGlobal + jz short HStopPI08 ;jump if already stopped + lea eax, _Halp8254Lock + ACQUIRE_SPINLOCK eax, HStopPI10 + + dec HalpProfilingStopped ;protected by spinlock + jns short HStopPI06 ;jump if still someone doing it +; +; Set the interrupt rate to "idle" +; + + stdCall _HalpSetRolloverCount, <MAXIMUM_ROLLOVER_COUNT> + +; +; Turn off profiling hit computation +; + + +HStopPI06: + lea eax, _Halp8254Lock + RELEASE_SPINLOCK eax + push lipDefault + push ICU_LIPTR + call WriteMyCpuReg + mov fs:PcHal.pchCurLiptr, eax +HStopPI08: + popfd + stdRET _HalStopProfileInterrupt + +HStopPI10: + sti + SPIN_ON_SPINLOCK eax, HStopPI01 +stdENDP _HalStopProfileInterrupt + +;++ +; ULONG +; HalSetProfileInterval ( +; ULONG Interval +; ); +; +; Routine Description: +; +; This procedure sets the interrupt rate (and thus the sampling +; interval) for the profiling interrupt. +; +; If profiling is active (KiProfilingStopped == 0) the actual +; hardware interrupt rate will be set. Otherwise, a simple +; rate validation computation is done. +; +; Arguments: +; +; (TOS+4) - Interval in 100ns unit. +; +; Return Value: +; +; Interval actually used by system. +; +;-- + +cPublicProc _HalSetProfileInterval ,1 + + mov edx, [esp+4] ; [edx] = interval in 100ns unit + + pushfd +HSetPI01: + cli + lea eax, _Halp8254Lock + ACQUIRE_SPINLOCK eax, HSetPI10 + + push edx ; [TOS] = interval +; +; Convert the interval to rollover count for Timer1 device. +; Since timer1 counts down a 16 bit value at a rate of 1.193M counts-per- +; sec, the computation is: +; RolloverCount = (Interval * 0.0000001) * (1.193 * 1000000) +; = Interval * 0.1193 +; = Interval * 1193 / 10000 +; + + mov eax, 1193 + mul edx ; [edx:eax] = interval * 1193 + mov ecx, 10000 + div ecx ; [eax] = rollover count + test eax, 0FFFF0000H ; Is high word set? + jz short Kspi80 ; if z, no , go initialize 8254 + pop eax ; else discard original interval + push MAXIMUM_ROLLOVER_INTERVAL ; set real interval + mov eax, MAXIMUM_ROLLOVER_COUNT ; use max. rollover count + +Kspi80: + mov HalpProfileRolloverCnt, eax + test dword ptr HalpProfilingStopped,-1 + js short Kspi90 + + stdCall _HalpSetRolloverCount, <eax> + +Kspi90: + lea eax, _Halp8254Lock + RELEASE_SPINLOCK eax + pop eax ; (eax) = returned Interval + + Popfd + + stdRET _HalSetProfileInterval ; (eax) = cReturn interval + +HSetPI10: + sti + SPIN_ON_SPINLOCK eax, HSetPI01 +stdENDP _HalSetProfileInterval + + page ,132 + subttl "Set Performance Counter Rollover count" +;++ +; +; VOID +; HalpSetRolloverCount ( +; IN ULONG RolloverCount +; ) +; +; Routine Description: +; +; This function initialize 8254 timer chip counter 0 to generate +; timer interrupt at the rate specified by caller. The timer 1 counter0 +; will be initialized to use binary count down, 16-bit counter, and mode +; 2. +; +; Note that 8254 mode 2 will not use the new count immediately. The +; new count will be loaded at the end of current counting cycle. +; +; NOTE: Interrupts must already be disabled and Halp8254Lock must +; already be aquired! +; +; Arguments: +; +; RolloverCount [TOS+4] - Value used to set timer 1 counter 0's +; rollover counter. +; +; Return Value: +; +; None. +; +;-- + +; +; Parameter definitions +; + +KsrcRolloverCount equ [esp+4] + +cPublicProc _HalpSetRolloverCount ,1 + + 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 ecx, KsrcRolloverCount + mov HalpNextRolloverCount, ecx ; set new count + 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 + + mov HalpPerfCounterInit, 1 ; indicate performance counter has + ; been initialized + stdRET _HalpSetRolloverCount + +stdENDP _HalpSetRollOverCount + + 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 + push ebx + push esi + +; +; 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 8254 +; initialization has occured. Reading garbage off the 8254 is not reasonable. +; + cmp HalpPerfCounterInit, 0 + jne Kqpc01 ; ok, perf counter has been initialized + +; +; Initialization hasn't occured yet, so just return zeroes. +; + mov eax, 0 + mov edx, 0 + jmp Kqpc20 + +Kqpc01: +Kqpc11: pushfd + cli + lea eax, _Halp8254Lock + ACQUIRE_SPINLOCK eax, Kqpc198 + +; +; Fetch the base value. Note that interrupts are off. +; +; NOTE: +; Need to watch for Px reading the 'CounterLow', P0 updates both +; then Px finishes reading 'CounterHigh' [getting the wrong value]. +; After reading both, make sure that 'CounterLow' didn't change. +; If it did, read it again. This way, we won't have to use a spinlock. +; + +@@: + 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. + IODelay + movzx ecx,al ;Zero upper bytes of (ECX). + in al, TIMER1_DATA_PORT0 ;Read PIT Ctr 0, MSByte. + mov ch, al ;(CX) = PIT Ctr 0 count. + + lea eax, _Halp8254Lock + RELEASE_SPINLOCK eax + +; +; 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 + + +; +; 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, +; simply returns the new Performance counter. Otherwise, we add the hardware +; count to the performance counter to form the final result. +; + + cmp eax, ebx + jne short Kqpc20 + cmp edx, esi + jne short Kqpc20 + neg ecx ; PIT counts down from 0h + add ecx, HalpRolloverCount + add eax, ecx + adc edx, 0 ; [edx:eax] = Final result + +; +; Return the counter +; + +Kqpc20: + ; return value is in edx:eax + +; +; Return the freq. if caller wants it. +; + + or dword ptr KqpcFrequency, 0 ; is it a NULL variable? + jz short Kqpc99 ; 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 + +Kqpc99: + pop esi ; restore esi and ebx + pop ebx + stdRET _KeQueryPerformanceCounter + +Kqpc198: popfd + SPIN_ON_SPINLOCK eax,<Kqpc11> + +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 + mov eax, [esp+4] ; ponter to Number + 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 a Wyse MP machine. There is only a single + ; 8254 device + ; + + 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 +; + + movzx eax, _HalpIRQLtoVector[CLOCK2_LEVEL] + push eax ; save our interrupt vector number + sub esp, 4 ; allocate space to save OldIrql + + stdCall _HalBeginSystemInterrupt, <CLOCK2_LEVEL,eax,esp> + + or al,al ; check for spurious interrupt + jz Hci100 + +; +; (esp) = OldIrql +; (esp+4) = Vector +; (esp+8) = base of trap frame +; (ebp) = address of trap frame +; + mov eax, TIME_INCREMENT + + cmp fs:PcHal.pchPrNum, 0 ; is this the master cpu? + je _KeUpdateSystemTime@0 ; if it is, update system time + + sti + stdCall _KeUpdateRunTime,<dword ptr [esp]> ; othewise update runtime + + INTERRUPT_EXIT ; lower irql to old value, iret + +Hci100: + add esp, 8 ; spurious, no EndOfInterrupt + SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi + +stdENDP _HalpClockInterrupt + + 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 +; + + movzx eax, _HalpIRQLtoVector[PROFILE_LEVEL] + push eax + sub esp, 4 ; allocate space to save OldIrql + stdCall _HalBeginSystemInterrupt, <PROFILE_LEVEL,eax,esp> + or al,al ; check for spurious interrupt + jz Hpi100 +; +; (esp) = OldIrql +; (esp+4) = H/W vector +; (esp+8) = base of trap frame +; + test fs:PcHal.pchCurLiptr, lipGlobal + je Hpi90 ; if prof disable don't call kernel + + stdCall _KeProfileInterrupt,<ebp> ; (ebp) = trap frame + +Hpi90: INTERRUPT_EXIT + +Hpi100: + add esp, 8 ; spurious, no EndOfInterrupt + SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi + +stdENDP _HalpProfileInterrupt + +;++ +; +; Routine Description: +; +; This routine is entered as the result of a performance counter interrupt. +; Its function is to dismiss the interrupt, raise system Irql to +; PROFILE_LEVEL-1, update the performance counter, and generate the +; profile interrupts if any there are any active profiles. +; +; Arguments: +; +; None +; Interrupt is disabled +; +; Return Value: +; +; none +; +; Sets Irql = PROFILE_LEVEL-1 and dismisses the interrupt +; +;-- + ENTER_DR_ASSIST Hpci_a, Hpci_t + +cPublicProc _HalpPerfCtrInterrupt ,0 + +; +; Save machine state in trap frame +; + + ENTER_INTERRUPT Hpci_a, Hpci_t + +; +; (esp) - base of trap frame +; + + movzx eax, _HalpIRQLtoVector[PROFILE_LEVEL-1] + push eax + sub esp, 4 ; allocate space to save OldIrql + stdCall _HalBeginSystemInterrupt, <PROFILE_LEVEL-1,eax,esp> + or al,al ; check for spurious interrupt + jz Hpci100 +; +; (esp) = OldIrql +; (esp+4) = H/W vector +; (esp+8) = base of trap frame +; + +; +; Update performance counter +; + mov eax, HalpNextRolloverCount + mov ecx, HalpRollOverCount + mov HalpRollOverCount, eax ; next rollover count + add HalpPerfCounterLow, ecx ; update performace counter + adc HalpPerfCounterHigh, 0 + +; +; Now check is any profiling stuff to do. +; + + cmp HalpProfilingStopped, 0 ; Has profiling been stopped? +; je _KeProfileInterrupt@0 ; if prof enabled, jump to kernel + js short Hpci99 ; jump if all stopped + cli + mov dx, My+CpuIntCmd +@@: in ax, dx ;wait til ICU not busy + test eax, ICU_CMD_BUSY + jnz @B + mov ax, ICU_XMT_GLB_INT + out dx, ax ;set profile interrupt to all interested + +Hpci99: + INTERRUPT_EXIT + +Hpci100: + add esp, 8 ; spurious, no EndOfInterrupt + SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi + +stdENDP _HalpPerfCtrInterrupt + +;++ +; +; 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, TIME_INCREMENT + stdRET _HalSetTimeIncrement + +stdENDP _HalSetTimeIncrement +_TEXT ends + end + diff --git a/private/ntos/nthals/halwyse7/i386/wydetect.asm b/private/ntos/nthals/halwyse7/i386/wydetect.asm new file mode 100644 index 000000000..b18e643ee --- /dev/null +++ b/private/ntos/nthals/halwyse7/i386/wydetect.asm @@ -0,0 +1,167 @@ +;++ +; +; Copyright (c) 1991 Microsoft Corporation +; Copyright (c) 1992, 1993 Wyse Technology +; +; Module Name: +; +; wydetect.asm +; +; Abstract: +; +; This modules detects a Wyse7000 or compatible. It is INCLUDED +; by WYIPI and other binaries whom need to know how to detect a +; Wyse7000 type MP machine (ie, setup). It must assemble more or +; less standalone and run in protect mode. +; +; Author: +; +; John Fuller (o-johnf) 3-Apr-1992 Convert to Wyse7000i MP system. +; +;Revision History: +; +; John Fuller (o-johnf) 3-Apr-1992 Convert to Wyse7000i MP system. +;-- + +include callconv.inc ; calling convention macros + +;***************************** +; Wyse 7000i MP defines from wy7000mp.inc +; These are copied into this module to allow it to be build standalone +; by the setup program. +; +WyModel740 Equ 00170335Fh ;EISA id for model 740 system board +WyModel760 Equ 00178335Fh ;EISA id for model 760 system board +WyModel780 Equ 00978335Fh ;EISA id for model 780 system board +; ;(model hasn't been named, but +; ; 780 is as good as anything) + + +My Equ 00F0h ;WWB slot number specifies local cpu +CpuCCUptr Equ 0C00h ;CCU pointer register (add WWB slot*16) + + +_DATA SEGMENT DWORD PUBLIC 'DATA' + +; wySystemType: SystemType is read from 0c80-0c83h. +; 0c80-0c81: 5F33: Compressed WYS (5 bit encoding). +; 0c82-0c83: System Board type. +; +; SystemType: Is it a Wyse7000i? Gets init'd by P0 ONLY ONCE. +; 0: not a Wyse7000i +; 1: 7000i/model 740 +; 2: 7000i/model 760 +; 3: 7000i/model 780 +; +wySystemTypeTable label dword + + dd WyModel740 ;type 1 + +; dd ?????????? add here any other non-ICU type system boards + + public SYSTYPE_NO_ICU +SYSTYPE_NO_ICU equ ($-wySystemTypeTable)/4 ;highest non-ICU type number + + dd WyModel760 ;type 2 + dd WyModel780 ;type 3 + +; dd ?????????? add here any other ICU type system boards + +WYTABLE_SIZE equ ($-wySystemTypeTable)/4 ;highest system type number + +wySystemType dd 0 ;store EISA ID for system board + +_DATA ends + + page ,132 + subttl "Post InterProcessor Interrupt" +_TEXT SEGMENT DWORD PUBLIC 'CODE' + ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING + +;++ +; ULONG +; DetectWyse7 ( +; OUT PBOOLEAN IsConfiguredMp +; ); +; +; Routine Description: +; Determines the type of system (specifically for eisa machines), by reading +; the system board system ID. It compares the 4 bytes of the ID, to +; a predefined table <abSystemTypeTable> 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: +; 0 - if not a Wyse7 +; 1 - if type 1 +; 2 - if type 2 +; etc... +;-- +cPublicProc _DetectWyse7 ,1 + + push edi + push esi + push ebx ; Save C Runtime + + ; 4 byte value is read from 0c80-0c83, and saved in <wySystemType>. + ; The value is compared to table in <abSystemTypeTable>, and + ; the SystemType is updated accordingly. + + lea edi, wySystemType + mov edx, 0c80h + cld ; increment edi + insb ; 0e CPQ + inc edx + insb ; 11 + inc edx + insb ; SystemType + inc edx + insb ; Revision + + mov ebx, wySystemType ;get read EISA ID + mov ecx, WYTABLE_SIZE +@@: cmp ebx, wySystemTypeTable[4*ecx-4] + je short @F ;jump if found + loop @B + jmp short WyNotFound + +@@: + cmp ecx, SYSTYPE_NO_ICU + ja short WyFound ;jump if ICU type system board found +; +; We have found an MP-capable system, now we have to verify that +; we have an actual MP-CPU + + mov eax, 0FFAAh + mov edx, My+CpuCCUptr ;register doesn't exist on UP-CPU + pushfd ;save interrupt flag + cli + out dx, al ;write data pattern to register + xchg ah, al + out 0ECh, al ;precharge bus (non-existant register) + in al, dx ;read data pattern again + popfd + cmp al, ah ;if it's not the data we wrote + jne short WyNotFound ; then it's not an MP-CPU + +WyFound: + mov eax, ecx ; Type found + mov ebx, dword ptr [esp+16] + mov byte ptr [ebx], 1 ; *IsConfiguredMp = TRUE + +WyExit: pop ebx + pop esi + pop edi + + stdRET _DetectWyse7 + +WyNotFound: + xor eax, eax ; No type + jmp short WyExit + +stdENDP _DetectWyse7 + +_TEXT ENDS diff --git a/private/ntos/nthals/halwyse7/i386/wyhal.c b/private/ntos/nthals/halwyse7/i386/wyhal.c new file mode 100644 index 000000000..85b724b14 --- /dev/null +++ b/private/ntos/nthals/halwyse7/i386/wyhal.c @@ -0,0 +1,378 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation +Copyright (c) 1992, 1993 Wyse Technology + +Module Name: + + wyhal.c + +Abstract: + + + This module implements the initialization of the system dependent + functions that define the Hardware Architecture Layer (HAL) for an + Wyse 7000i x86 system. + +Author: + + David N. Cutler (davec) 25-Apr-1991 + +Environment: + + Kernel mode only. + +Revision History: + + John Nels Fuller (o-johnf) 26-Mar-1992 convert for Wyse 7000i +--*/ + +#include "halp.h" + +ADDRESS_USAGE HalpDefaultWyseIoSpace = { + NULL, CmResourceTypePort, InternalUsage, + { + // Standard PC ISA I/O space used... + 0x000, 0x10, // ISA DMA + 0x0C0, 0x10, // ISA DMA + 0x080, 0x10, // DMA + + 0x020, 0x2, // PIC + 0x0A0, 0x2, // Cascaded PIC + + 0x040, 0x4, // Timer1, Referesh, Speaker, Control Word + 0x048, 0x4, // Timer2, Failsafe + + 0x061, 0x1, // NMI (system control port B) + 0x092, 0x1, // system control port A + + 0x070, 0x2, // Cmos/NMI enable + 0x0F0, 0x10, // coprocessor ports + + // Standard PC EISA I/O space used... + 0x0D0, 0x10, // DMA + 0x400, 0x10, // DMA + 0x480, 0x10, // DMA + 0x4C2, 0xE, // DMA + 0x4D4, 0x2C, // DMA + + 0x461, 0x2, // Extended NMI + 0x464, 0x2, // Last Eisa Bus Muster granted + + 0x4D0, 0x2, // edge/level control registers + + 0xC84, 0x1, // System board enable + + // Wyse I/O Space used... + + 0x8F0, 0x8, // BCU/ICU on cpu boards + 0x800, 0x8, // BCU/ICU on system board + 0xCF0, 0x4, // 80486 CCU, Pentium WDC + 0xCF4, 0x6, // 80486 WBI, Pentium WDP + + 0, 0 + + } +}; + + +VOID +HalpICUSpurious( + VOID + ); + +VOID +HalpIPInterrupt( + VOID + ); + +VOID +HalpReInitProcessor( + ULONG ProcessorNumber + ); + +ULONG HalpBusType; + +#ifndef NT_UP +ULONG +HalpInitMP( + IN ULONG Phase, + IN PLOADER_PARAMETER_BLOCK LoaderBlock + ); +#endif + + +extern CCHAR HalpIRQLtoVector[]; + +VOID +HalpPerfCtrInterrupt( + VOID + ); + +KSPIN_LOCK HalpSystemHardwareLock; + +//BOOLEAN +//HalpVerifyMachine ( +// VOID +// ); + +BOOLEAN +HalInitSystem ( + IN ULONG Phase, + IN PLOADER_PARAMETER_BLOCK LoaderBlock + ) + + +/*++ + +Routine Description: + + This function initializes the Hardware Architecture Layer (HAL) for an + x86 system. + +Arguments: + + None. + +Return Value: + + A value of TRUE is returned if the initialization was successfully + completed. Otherwise a value of FALSE is returend. + +--*/ + +{ + PMEMORY_ALLOCATION_DESCRIPTOR Descriptor; + PLIST_ENTRY NextMd; + KIRQL CurrentIrql; + PKPRCB pPRCB; + ULONG BuildType; + + + pPRCB = KeGetCurrentPrcb(); + + if (Phase == 0) { + + HalpBusType = LoaderBlock->u.I386.MachineType & 0x00ff; + + // + // Verify Prcb version and build flags conform to + // this image + // + + BuildType = 0; +#if DBG + BuildType |= PRCB_BUILD_DEBUG; +#endif +#ifdef NT_UP + BuildType |= PRCB_BUILD_UNIPROCESSOR; +#endif + + if (pPRCB->MajorVersion != PRCB_MAJOR_VERSION) { + KeBugCheckEx (MISMATCHED_HAL, + 1, pPRCB->MajorVersion, PRCB_MAJOR_VERSION, 0); + } + + if (pPRCB->BuildType != BuildType) { + KeBugCheckEx (MISMATCHED_HAL, + 2, pPRCB->BuildType, BuildType, 0); + } + + + // + // Phase 0 initialization + // only called by P0 + // + + + // + // Initialize the ICU spurious interrupt vector + // + + KiSetHandlerAddressToIDT( PRIMARY_VECTOR_BASE+16, HalpICUSpurious ); + + HalpInitializePICs(); + + // + // Now that the PICs are initialized, we need to mask them to + // reflect the current Irql + // + + CurrentIrql = KeGetCurrentIrql(); + KfLowerIrql(CurrentIrql); + + // + // Fill in handlers for APIs which this hal supports + // + + HalQuerySystemInformation = HaliQuerySystemInformation; + HalSetSystemInformation = HaliSetSystemInformation; + + // + // Initialize CMOS + // + + HalpInitializeCmos(); + + // + // Register base IO space used by hal + // + + HalpRegisterAddressUsage (&HalpDefaultWyseIoSpace); + + // + // Note that HalpInitializeClock MUST be called after + // HalpInitializeStallExecution, because HalpInitializeStallExecution + // reprograms the timer. + // + + HalpInitializeStallExecution(0); + + HalpInitializeClock(); + + // + // Initialize the clock interrupt vector for the processor that keeps + // the system time. + // + + KiSetHandlerAddressToIDT( HalpIRQLtoVector[CLOCK2_LEVEL], + HalpClockInterrupt ); + + // + // Initialize the IPI vector + // + + KiSetHandlerAddressToIDT( HalpIRQLtoVector[IPI_LEVEL], + HalpIPInterrupt); + + // + // Initialize the profile interrupt vector. + // + + HalStopProfileInterrupt(0); + + KiSetHandlerAddressToIDT( HalpIRQLtoVector[PROFILE_LEVEL], + HalpProfileInterrupt); + + // + // Initialize the performance counter interrupt vector + // + + KiSetHandlerAddressToIDT( HalpIRQLtoVector[PROFILE_LEVEL-1], + HalpPerfCtrInterrupt); + + 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; + } + + } else { + + // + // Phase 1 initialization + // + + if (KeGetPcr()->Prcb->Number == 0) { + HalpRegisterInternalBusHandlers (); + } + + // + // enable PROFILE interrupt + // + HalEnableSystemInterrupt( HalpIRQLtoVector[PROFILE_LEVEL], + PROFILE_LEVEL, Latched); + // + // enable Performance Counter interrupt + // + HalEnableSystemInterrupt( HalpIRQLtoVector[PROFILE_LEVEL-1], + PROFILE_LEVEL-1, Latched); + // + // enable CLOCK2 interrupt + // + HalEnableSystemInterrupt( HalpIRQLtoVector[CLOCK2_LEVEL], + CLOCK2_LEVEL, Latched); + if (KeGetPcr()->Prcb->Number == 0) { + + // + // If P0, then enable IPI, IPI's already enabled on other cpu's + // + HalEnableSystemInterrupt( HalpIRQLtoVector[IPI_LEVEL], + IPI_LEVEL, Latched); + } + + } + + + HalpInitMP (Phase, LoaderBlock); + + return TRUE; +} diff --git a/private/ntos/nthals/halwyse7/i386/wyipi.asm b/private/ntos/nthals/halwyse7/i386/wyipi.asm new file mode 100644 index 000000000..297964749 --- /dev/null +++ b/private/ntos/nthals/halwyse7/i386/wyipi.asm @@ -0,0 +1,775 @@ + title "Interprocessor Interrupt" +;++ +; +;Copyright (c) 1991-1993 Microsoft Corporation +;Copyright (c) 1992, 1993 Wyse Technology +; +;Module Name: +; +; wyipi.asm +; +;Abstract: +; +; Wyse7000i IPI code. +; Provides the HAL support for Interprocessor Interrupts for the +; MP Wyse7000i implementation. +; +;Author: +; +; Ken Reneris (kenr) 13-Jan-1992 +; +;Revision History: +; +; John Fuller (o-johnf) 3-Apr-1992 Convert to Wyse7000i MP system. +; John Fuller (o-johnf) 31-Aug-1993 Mods for Lazy IRQLs +;-- +.386p + .xlist + +; +; Include Wyse7 dection code +; + +include i386\wydetect.asm + +; +; Normal includes +; + +include hal386.inc +include i386\kimacro.inc +include i386\ix8259.inc +include i386\wy7000mp.inc +include callconv.inc + + EXTRNP _HalBeginSystemInterrupt,3 + EXTRNP _HalEndSystemInterrupt,2 + extrn _HalpDefaultInterruptAffinity:DWORD + EXTRNP _KiIpiServiceRoutine,2,IMPORT + EXTRNP Kei386EoiHelper,0,IMPORT + EXTRNP _HalEnableSystemInterrupt,3 + EXTRNP _HalpInitializeClock,0 + EXTRNP _HalDisplayString,1 + EXTRNP _HalpInitializeStallExecution,1 + extrn _HalpIRQLtoVector:BYTE + extrn _ProcessorsPresent:BYTE + extrn _HalpActiveProcessors:DWORD + +_DATA SEGMENT DWORD PUBLIC 'DATA' + + public SystemType +SystemType dd 0 + + public _HalpProcessorSlot +_HalpProcessorSlot db MAXIMUM_PROCESSORS dup (0) + +BadHalString db 'HAL: Wyse EISA/MP HAL cannot run on ' + db 'non-Wyse or non-EISA/MP machine.', cr, lf + db ' Replace the hal.dll with the correct hal', cr, lf + db ' System is HALTING *********', 0 +_DATA ends + + page ,132 + subttl "Post InterProcessor Interrupt" +_TEXT SEGMENT DWORD PUBLIC 'CODE' + ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING + + if DBG + %out _ProcSub +;++ +; +; VOID +; ProcSub( +; UCHAR Number +; ); +; +;Routine Description: +; +; Writes Number to BCU general purpose register, restores all +; registers and flags. +; +;Arguments: +; +; Number - Procedure entry/exit code +; +;Return Value: +; +; None. (restores eax) +; +;-- +cPublicProc _ProcSub ,1 + pushfd + push eax + push edx + mov dx, My+CpuPtrReg + mov al, BCU_GPR + cli + out dx, al + add edx, CpuDataReg-CpuPtrReg + movzx eax, byte ptr [esp][16] + out dx, ax + pop edx + pop eax + popfd + stdRET _ProcSub +stdENDP _ProcSub + + endif ;DBG + +;++ +; +; VOID +; HalInitializeProcessor( +; ULONG Number +; ); +; +;Routine Description: +; +; Initialize hal pcr values for current processor (if any) +; (called shortly after processor reaches kernel, before +; HalInitSystem if P0) +; +; IPI's and KeReadir/LowerIrq's must be available once this function +; returns. (IPI's are only used once two or more processors are +; available) +; +; . PcHal.pchPrNum = processor number +; . PcHal.pchPentiumFlag = processor type (80486=0, Pentium=1) +; . if (P0) +; . determine what kind of system is it, +; . if (Not Wyse7000i) Exit; +; . HalpDefaultInterruptAffinity[Pn] = 1 +; . if (80486) +; . WBI IACK_MODE = 1 (all WBIs) +; . CCU_CR[WWB_FPE_EN, PCD_EN] = 0,1? +; . else (Pentium) +; . WDP[IACK_MODE, FPE_EN] = 1, 0 (both WDP's) +; . CpuDiagUart[MCR] = 7 (DTR, RTS, OUT1, -OUT2, -LOOP) +; . CpuPriortyLevel = 0 +; . PcHal.pchHwIrql = HIGH_LEVEL +; . ICU_CNT_REG = 0 +; . ICU_LIPTR = lipDefault +; . BCU_BCTLR[A20M_WWB, A20M_CPU, SLOW_ENB] = 0,0,0 +; . _HalpProcessorSlot[Pn] = BCU_ID +; . ICU_PSR0,1 = 0 +; . PcIDR = ICU_IMR0,1 = IMR_MASK +; . ICU_VB0 = PIC1_BASE +; . ICU_VB1 = PIC2_BASE +; . ICU_VB2 = IPIv_BASE +; . if (P0) +; . _ProcessorsPresent = ~ICU_SYS_CPU & ~(P0_slot_bit+sys_slot_bit) +; . if (Model760/780) // Init SysBd ICU/BCU/WBI +; . ICU_ICTLR[IACK_MODE, ICU_AEOI, INT_ENB, MSK_CPURST, WWB_INT] = 1,0,1,0,0 +; . clear pending interrupt +; . Sys ICU_CNT_REG = 0 +; . Sys WBI IACK_MODE = 1 (all WBIs) +; . Sys ICU_LIPTR = 0 +; . Sys BCU_BCTLR[A20M_WWB, A20M_CPU, SLOW_ENB] = 0,0,0 +; . Sys ICU_PSR0,1 = 0 +; . Sys ICU_IMR0,1 = IMR_MASK & ~1 +; . Sys ICU_VB0 = PIC1_BASE +; . Sys ICU_VB1 = PIC2_BASE +; . Sys ICU_VB2 = IPIv_BASE +; . Sys ICU_ICTLR[IACK_MODE, ICU_AEOI, INT_ENB, MSK_CPURST, WWB_INT] = 1,1,1,1,1 +; . else +; . ICU_ICTLR[IACK_MODE, ICU_AEOI, INT_ENB, MSK_CPURST, WWB_INT] = 1,0,1,0,1 +; . ICU_ICTLR[WWB_INT] = 1 +; . PcPDR[0] = 0 +; . clear pending interrupt +; . else +; . ICU_ICTLR[IACK_MODE, ICU_AEOI, INT_ENB, MSK_CPURST, WWB_INT] = 1,0,1,1,0 +; . clear pending interrupt +; . initalize stall count +; . initialize clock +; . enable IPI's +; +;Arguments: +; +; Number - Logical processor number of calling processor +; +;Return Value: +; +; None. +; +;-- +cPublicProc _HalInitializeProcessor ,1 + enproc 1 + pushfd + cli + +; . PcHal.pchPrNum = processor number + movzx eax, byte ptr [esp+8] ;get processor number + mov fs:PcHal.pchPrNum, al ;save for future reference + lock bts _HalpActiveProcessors, eax + +; . PcHal.pchPentiumFlag = processor type (80486=0, Pentium=1) + pushfd + pop ecx + xor ecx, 1 shl 21 ;toggle CPUID flag + push ecx + popfd + pushfd + pop edx + cmp ecx, edx + sete Fs:PcHal.pchPentiumFlag + +; . if (P0) + or eax, eax ;test for processor zero + jnz short hipAllCpus ;jump if not + +; . determine what kind of system is it, +; . if (Not Wyse7000i) Exit; + + sub esp, 4 + stdCall _DetectWyse7, <esp> ;doesn't run if not Wyse 7000i + add esp, 4 + or eax, eax + jz NotWyse7 + mov SystemType, eax + + xor eax, eax ;make sure eax is 0 for hipAllCpus + +hipAllCpus: +; . HalpDefaultInterruptAffinity[Pn] = 1 + lock bts _HalpDefaultInterruptAffinity, eax + mov dword ptr fs:PcStallScaleFactor, INITIAL_STALL_COUNT + +; . if (80486) + cmp Fs:PcHal.pchPentiumFlag, 0 + Jne Short hipIsPentium + +; . WBI IACK_MODE = 1 (all WBIs) + mov dx, My+CpuWBIlow ;point to WBI for data bits 0-32 + in ax, dx + or ax, WBI_IACK_MODE ;set MP interrupt mode + out dx, ax + + mov dx, My+CpuWBIhigh ;point to WBI for data bits 33-63 + in ax, dx + or ax, WBI_IACK_MODE ;set MP interrupt mode + out dx, ax + + mov dx, My+CpuWBIaddr ;point to WBI for address bits + in ax, dx + or ax, WBI_IACK_MODE ;set MP interrupt mode + out dx, ax + +; . CCU_CR[WWB_FPE_EN, PCD_EN] = 0,1? + mov al, CCU_CR + mov dx, My+CpuCCUptr + out dx, al + mov dx, My+CpuCCUdata + in ax, dx + and eax, not WWB_FPE_EN + or eax, PCD_EN + out dx, ax + jmp short hipIs80486 + +; . else (Pentium) +hipIsPentium: +; . WDP[IACK_MODE, FPE_EN] = 1, 0 (both WDP's) + mov dx, MyCpuWDPlow + in ax, dx + and eax, not WDP_FPE_EN + or eax, WDP_IACK_MODE + out dx, ax + mov dx, MyCpuWDPhigh + in ax, dx + and eax, not WDP_FPE_EN + or eax, WDP_IACK_MODE + out dx, ax + +hipIs80486: +; . CpuDiagUart[MCR] = 7 (DTR, RTS, OUT1, -OUT2, -LOOP) + mov dx, My+CpuDiagUart+4 + mov al, 7 + out dx, ax ;disable diag port interrupts + +; . CpuPriortyLevel = 0 + xor eax, eax + mov dx, My+CpuPriortyLevel + out dx, ax + +; . PcHal.pchHwIrql = HIGH_LEVEL + mov Fs:PcHal.pchHwIrql, HIGH_LEVEL + + mov dx, My+CpuDataReg ;point to my BCU/ICU + +; . ICU_CNT_REG = 0 + push 0 + push ICU_CNT_REG + call WriteCpuReg ;stop local timer + +; . ICU_LIPTR = lipDefault + push lipDefault + push ICU_LIPTR + call WriteCpuReg + mov fs:PcHal.pchCurLiptr, eax + +; . BCU_BCTLR[A20M_WWB, A20M_CPU, SLOW_ENB] = 0,0,0 + push BCU_BCTLR + call ReadCpuReg + and eax, not (A20M_WWB + A20M_CPU + SLOW_ENB) + push eax + push BCU_BCTLR + call WriteCpuReg + +; . _HalpProcessorSlot[Pn] = BCU_ID + push BCU_ID + call ReadCpuReg + and al, WWB_ID_MASK ;keep only WWB slot number + movzx ecx, byte ptr [esp+8] ;get processor number again + mov _HalpProcessorSlot[ecx], al + mov fs:PcHal.pchPrSlot, al + +; . ICU_PSR0,1 = 0 + push 0 + push ICU_PSR0 + call WriteCpuReg ;clear pending bits in ICU_PSR0 + out dx, ax ;shortcut to clear ICU_PSR1 + +; . PcIDR = ICU_IMR0,1 = IMR_MASK + push IMR_MASK + push ICU_IMR0 + call WriteCpuReg + mov fs:PcIDR, eax + shr eax, 16 + out dx, ax ;shortcut to write ICU_IMR1 + +; . ICU_VB0 = PIC1_BASE + push PIC1_BASE + push ICU_VB0 + call WriteCpuReg + +; . ICU_VB1 = PIC2_BASE + push PIC2_BASE + push ICU_VB1 + call WriteCpuReg + +; . ICU_VB2 = IPIv_BASE + push IPIv_BASE + push ICU_VB2 + call WriteCpuReg + +; . if (P0) + cmp byte ptr [esp+8], 0 + jnz hipNotP0 + +; . _ProcessorsPresent = ~ICU_SYS_CPU & ~(P0_slot_bit+sys_slot_bit) + push ICU_SYS_CPU + call ReadCpuReg + not al ;make positive true cpu bits + and al, not 1 ;clear system board bit + movzx ecx, _HalpProcessorSlot[0] ;get P0 slot number + btr eax, ecx ;clear our own bit + mov _ProcessorsPresent, al ;save for starting others + +; . if (Model760/780) // Init SysBd ICU/BCU/WBI + cmp SystemType, SYSTYPE_NO_ICU + jna hipNotModel760 + +; . ICU_ICTLR[IACK_MODE, ICU_AEOI, INT_ENB, MSK_CPURST, WWB_INT] = 1,0,1,0,0 + push ICU_ICTLR + call ReadCpuReg + and eax, not (WWB_INT + ICU_AEOI + MSK_CPURST) + or eax, IACK_MODE + INT_ENB + push eax + push ICU_ICTLR + call WriteCpuReg + +; . clear pending interrupt + call ClearPendingInt + + mov dx, Sys+CpuDataReg ;point to system board registers + +; . Sys ICU_CNT_REG = 0 + push 0 + push ICU_CNT_REG + call WriteCpuReg ;disable sys board timer + +; . Sys WBI IACK_MODE = 1 (all WBIs) + push SYS_WBI_LOW + call ReadCpuReg + or eax, WBI_IACK_MODE ;set MP interrupt mode + push eax + push SYS_WBI_LOW + call WriteCpuReg + + mov dx, Sys+CpuDataReg ;point to system board registers + push SYS_WBI_HIGH + call ReadCpuReg + or eax, WBI_IACK_MODE ;set MP interrupt mode + push eax + push SYS_WBI_HIGH + call WriteCpuReg + + mov dx, Sys+CpuDataReg ;point to system board registers + push SYS_WBI_ADDR + call ReadCpuReg + or eax, WBI_IACK_MODE ;set MP interrupt mode + push eax + push SYS_WBI_ADDR + call WriteCpuReg + + push 0 + push ICU_LIPTR + call WriteCpuReg + +; . Sys ICU_PSR0,1 = 0 + push 0 + push ICU_PSR0 + call WriteCpuReg ;clear pending bits in ICU_PSR0 + + push 0 + push ICU_PSR1 + call WriteCpuReg ;clear pending bits in ICU_PSR1 + +; . Sys ICU_IMR0,1 = IMR_MASK & ~1 + push IMR_MASK and (not 1) ;allow only level 0 + push ICU_IMR0 + call WriteCpuReg + + shr eax, 16 + push eax + push ICU_IMR1 + call WriteCpuReg ;set ICU_IMR1 + +; . Sys ICU_VB0 = PIC1_BASE + push PIC1_BASE + push ICU_VB0 + call WriteCpuReg + +; . Sys ICU_VB1 = PIC2_BASE + push PIC2_BASE + push ICU_VB1 + call WriteCpuReg + +; . Sys ICU_VB2 = IPIv_BASE + push IPIv_BASE + push ICU_VB2 + call WriteCpuReg + +; . Sys ICU_ICTLR[IACK_MODE, ICU_AEOI, INT_ENB, MSK_CPURST, WWB_INT] = 1,1,1,1,1 + push ICU_ICTLR + call ReadCpuReg + or eax, IACK_MODE + INT_ENB + WWB_INT + MSK_CPURST + ICU_AEOI + push eax + push ICU_ICTLR + call WriteCpuReg + jmp short hipExit + +; . else +hipNotModel760: + +; . ICU_ICTLR[IACK_MODE, ICU_AEOI, INT_ENB, MSK_CPURST, WWB_INT] = 1,0,1,0,1 + push ICU_ICTLR + call ReadCpuReg + and eax, not (ICU_AEOI + MSK_CPURST) + or eax, IACK_MODE + INT_ENB + WWB_INT + push eax + push ICU_ICTLR + call WriteCpuReg + +; . PcPDR[0] = 0 + and fs:dword ptr PcIDR, not 1 ;allow 8259 interrupt + ; distribution, but not until + ; 1st HalEnableSystemInterrupt +; . clear pending interrupt + call ClearPendingInt + jmp short hipExit + +; . else +hipNotP0: + +; . ICU_ICTLR[IACK_MODE, ICU_AEOI, INT_ENB, MSK_CPURST, WWB_INT] = 1,0,1,1,0 + push ICU_ICTLR + call ReadCpuReg + and eax, not (WWB_INT + ICU_AEOI) + or eax, IACK_MODE + INT_ENB + MSK_CPURST + push eax + push ICU_ICTLR + call WriteCpuReg + +; . clear pending interrupt + call ClearPendingInt + +; . initialize stall count + stdCall _HalpInitializeStallExecution, <[esp+8]> + +; . initialize clock + stdCall _HalpInitializeClock + +; . enable IPI's + movzx eax, _HalpIRQLtoVector[IPI_LEVEL] + stdCall _HalEnableSystemInterrupt, <eax,IPI_LEVEL,1> ;latched interrupt + +hipExit: + exproc 1 + popfd + stdRET _HalInitializeProcessor + +NotWyse7: +; on a non-Wyse. Display +; message and HALT system. + stdCall _HalDisplayString, <offset BadHalString> + hlt + +stdENDP _HalInitializeProcessor + + +;++ +; +; VOID +; HalRequestIpi( +; IN ULONG Mask +; ); +; +;Routine Description: +; +; Requests an interprocessor interrupt +; +;Arguments: +; +; Mask - Supplies a mask of the processors to be interrupted +; +;Return Value: +; +; None. +; +;-- +cPublicProc _HalRequestIpi ,1 + enproc 2 + + movzx eax, byte ptr [esp+4] ; (eax) = Processor bitmask +if DBG + or eax, eax ; must ipi somebody + jz short ipibad + + movzx ecx, byte ptr fs:PcHal.pchPrNum + bt eax, ecx ; cannot ipi yourself + jc short ipibad +endif + + xchg eax, ecx ;processor list to ecx + mov edx, My+CpuIntCmd ;point to ICU cmd register +hriNextProcessor: + pushfd + cli +@@: in ax, dx ;get ICU busy status + test eax, ICU_CMD_BUSY + jnz @B ;wait for not busy + bsf eax, ecx + btr ecx, eax + mov al, _HalpProcessorSlot[eax] + or al, ICU_IPI_SLOT + out dx, ax + popfd + or ecx, ecx + jnz hriNextProcessor + exproc 2 + stdRET _HalRequestIpi + +if DBG +ipibad: int 3 + stdRET _HalRequestIpi +endif + +stdENDP _HalRequestIpi + + + page ,132 + subttl "Wyse7000i IPI Handler" +;++ +; +; VOID +; HalpIPInterrupt ( +; ); +; +; Routine Description: +; +; This routine is entered as the result of an interrupt generated by the +; IPI hardware. +; +; Arguments: +; +; None. +; Interrupt is dismissed +; +; Return Value: +; +; None. +; +;-- + + ENTER_DR_ASSIST Hipi_a, Hipi_t + +cPublicProc _HalpIPInterrupt ,0 + +; +; Save machine state in trap frame +; + ENTER_INTERRUPT Hipi_a, Hipi_t ; (ebp) -> Trap frame + enproc 3 +; +; Save previous IRQL +; + movzx eax, _HalpIRQLtoVector[IPI_LEVEL] + push eax ;interrupt vector + sub esp, 4 ;space for OldIrql + +;raise to new Irql + + stdCall _HalBeginSystemInterrupt, <IPI_LEVEL,eax,esp> + or al, al + jz Hipi100 ;jump if spurrious interrupt + +; Pass TrapFrame to Ipi service rtn +; Pass Null ExceptionFrame + + stdCall _KiIpiServiceRoutine, <ebp,0> + + exproc 3 +; +; Do interrupt exit processing +; + INTERRUPT_EXIT ; will return to caller + +Hipi100: + exproc 3 + add esp, 8 ; spurious, no EndOfInterrupt + SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi + +stdENDP _HalpIPInterrupt +;++ +; +; VOID +; HalpIrq13Handler ( +; ); +; +; Routine Description: +; +; This routine is entered as the result of an interrupt generated by the +; EISA DMA buffer chaining interrupt. Currently, NO NT driver uses the DMA +; buffer chaining capability. For now, this routine is simply commented +; out. +; +; Note: IRQ13 could also be used for coprocessor error, but the Wyse7000i +; is a 486 machine so coprocessor error is handled as a processor +; fault and the FERR output of the 486 is masked off the IRQ13 +; input to the 8259 so that the only possible IRQ13 interrupt is for +; DMA chaining. +; +; Arguments: +; +; None. +; Interrupt is dismissed +; +; Return Value: +; +; None. +; +;-- + +; public _HalpIrq13Handler +;_HalpIrq13Handler proc +; +;_HalpIrq13Handler endp + +;++ +; BOOLEAN +; HalpVerifyMachine ( +; VOID +; ); +; +; Routine Description: +; Return TRUE if this is a Wyse7000i +; +;-- +;cPublicProc _HalpVerifyMachine ,0 +; xor eax, eax +; cmp SystemType, eax +; setnz al +; stdRET _HalpVerifyMachine +;stdENDP _HalpVerifyMachine + + + public ReadMyCpuReg +ReadMyCpuReg proc + mov dx, My+CpuDataReg +ReadCpuReg: + add edx, CpuPtrReg - CpuDataReg + mov al, [esp+4] + out dx, al + add edx, CpuDataReg - CpuPtrReg + in ax, dx + ret 4 +ReadMyCpuReg endp + + public WriteMyCpuReg +WriteMyCpuReg proc + Mov dx, My+CpuDataReg +WriteCpuReg: + add edx, CpuPtrReg - CpuDataReg + mov al, [esp+4] + out dx, al + add edx, CpuDataReg - CpuPtrReg + mov eax, [esp+8] + out dx, ax + ret 8 +WriteMyCpuReg endp + +D_INT032 EQU 8E00h ; access word for 386 ring 0 interrupt gate + +ClearPendingInt proc + enter 8,0 ; setup ebp, reserve 8 bytes of stack + + mov dx, My+CpuDataReg + push PIC1_BASE+2 ;set vector out register(unused vector) + push ICU_VOUT ;in case of int pending + call WriteCpuReg + + xchg ecx, eax ;put vector number in ecx + + sidt fword ptr [ebp-8] ; get IDT address + mov edx, [ebp-6] ; (edx)->IDT + + push dword ptr [edx+8*ecx] + ; (TOS) = original desc of IRQ + push dword ptr [edx+8*ecx + 4] + ; each descriptor has 8 bytes + mov eax, offset FLAT:cpiService + 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 + + sti + jmp short $+2 ;allow one pending interrupt + cli + + pop [edx+8*ecx+4] ; restore higher half of NMI desc + pop [edx+8*ecx] ; restore lower half of NMI desc + + leave + ret +ClearPendingInt endp + +cpiService proc + push edx + push eax + mov dx, My+CpuIntCmd +@@: in ax, dx + test eax, ICU_CMD_BUSY + jnz @B + mov al, ICU_CLR_INSERV1 ; clear interrupt in service bit + out dx, ax + pop eax + pop edx + iretd +cpiService endp +_TEXT ENDS + END diff --git a/private/ntos/nthals/halwyse7/i386/wyirql.asm b/private/ntos/nthals/halwyse7/i386/wyirql.asm new file mode 100644 index 000000000..28ef5a777 --- /dev/null +++ b/private/ntos/nthals/halwyse7/i386/wyirql.asm @@ -0,0 +1,667 @@ + title "Irql Processing" +;++ +; +; Copyright (c) 1989-1993 Microsoft Corporation +; Copyright (c) 1992, 1993 Wyse Technology +; +; Module Name: +; +; wyirql.asm +; +; Abstract: +; +; Wyse7000i IRQL +; +; This module implements the code necessary to raise and lower i386 +; Irql and dispatch software interrupts with the Wyse ICU hardware. +; +; Author: +; +; Shie-Lin Tzong (shielint) 8-Jan-1990 +; +; Environment: +; +; Kernel mode only. +; +; Revision History: +; +; John Vert (jvert) 27-Nov-1991 +; Moved from kernel into HAL +; +; John Fuller (o-johnf) 2-Apr-1992 +; Converted to Wyse hardware. +; +; John Fuller (o-johnf) 31-Aug-1993 +; Mods for Lazy IRQLs +;-- + +.386p + .xlist +include hal386.inc +include callconv.inc ; calling convention macros +include i386\ix8259.inc +include i386\kimacro.inc +include i386\wy7000mp.inc + .list + + + EXTRNP _KeBugCheck,1,IMPORT + + extrn _HalpApcInterrupt:near + extrn _HalpDispatchInterrupt:near + extrn _KiUnexpectedInterrupt:near + extrn ReadMyCpuReg:NEAR + extrn WriteMyCpuReg:NEAR + EXTRNP _HalpClockInterrupt,0 + EXTRNP _HalpIPInterrupt,0 + +; +; Initialization control words equates for the PICs +; + +ICW1_ICW4_NEEDED equ 01H +ICW1_CASCADE equ 00H +ICW1_INTERVAL8 equ 00H +ICW1_LEVEL_TRIG equ 08H +ICW1_EDGE_TRIG equ 00H +ICW1_ICW equ 10H + +ICW4_8086_MODE equ 001H +ICW4_NORM_EOI equ 000H +ICW4_NON_BUF_MODE equ 000H +ICW4_SPEC_FULLY_NESTED equ 010H +ICW4_NOT_SPEC_FULLY_NESTED equ 000H + +OCW2_NON_SPECIFIC_EOI equ 020H +OCW2_SPECIFIC_EOI equ 060H +OCW2_SET_PRIORITY equ 0c0H + +; +; Interrupt flag bit maks for EFLAGS +; + +EFLAGS_IF equ 200H +EFLAGS_SHIFT equ 9 + +; + +_DATA SEGMENT DWORD PUBLIC 'DATA' + +; +; PICsInitializationString - Master PIC initialization command string +; + +PICsInitializationString dw PIC1_PORT0 + +; +; Master PIC initialization command +; + + db ICW1_ICW + ICW1_EDGE_TRIG + ICW1_INTERVAL8 +\ + ICW1_CASCADE + ICW1_ICW4_NEEDED + db PIC1_BASE + db 1 SHL PIC_SLAVE_IRQ + db ICW4_NOT_SPEC_FULLY_NESTED + \ + ICW4_NON_BUF_MODE + \ + ICW4_NORM_EOI + \ + ICW4_8086_MODE + db not (1 shl PIC_SLAVE_IRQ) ;OCW1 +; +; Slave PIC initialization command strings +; + + dw PIC2_PORT0 + db ICW1_ICW + ICW1_EDGE_TRIG + ICW1_INTERVAL8 +\ + ICW1_CASCADE + ICW1_ICW4_NEEDED + db PIC2_BASE + db PIC_SLAVE_IRQ + db ICW4_NOT_SPEC_FULLY_NESTED + \ + ICW4_NON_BUF_MODE + \ + ICW4_NORM_EOI + \ + ICW4_8086_MODE + db 0FFh ;OCW1 + dw 0 ; end of string + + + .errnz PROFILE_LEVEL-27 ;error if defines don't match tables + .errnz CLOCK2_LEVEL-28 ;error if defines don't match tables + .errnz IPI_LEVEL-29 ;error if defines don't match tables + .errnz POWER_LEVEL-30 ;error if defines don't match tables + .errnz HIGH_LEVEL-31 ;error if defines don't match tables +;;;;;;;;;;;;;;;; +; +; The following tables are generated from this information: +; +;KIRQL H/W pri CPL Vector Source Common use Name +;----- ------- --- ------ ------ ---------- ---- +; 00 31 +; 01 31 APC_LEVEL +; 02 31 DISPATCH_LEVEL +; 03 31 WAKE_LEVEL +; 04 31 +; 05 31 +; 06 31 +; 07 31 +; 08 22 (lo) 22 VB2+7 Local/IPI level 7 reserved +; 09 21 21 VB2+6 Local/IPI level 6 reserved +; 10 20 20 VB2+5 Local/IPI level 5 reserved +; 11 19 19 VB0+7 EISA IRQ7 LPT1 +; 12 18 18 VB0+6 EISA IRQ6 Flpy +; 13 17 17 VB0+5 EISA IRQ5 LPT2 +; 14 16 16 VB0+4 EISA IRQ4 COM1 +; 15 15 15 VB0+3 EISA IRQ3 COM2 +; 16 14 14 VB1+7 EISA IRQ15 +; 17 13 13 VB1+6 EISA IRQ14 AT disk +; 18 12 12 VB1+5 EISA IRQ13 DMA chaining +; 19 11 11 VB1+4 EISA IRQ12 +; 20 10 10 VB1+3 EISA IRQ11 +; 21 9 9 VB1+2 EISA IRQ10 +; 22 8 8 VB1+1 EISA IRQ9 +; 23 7 7 VB1+0 EISA IRQ8 RTC +; 24 6 6 VB2+4 Local/IPI level 4 reserved +; 25 5 5 VB0+1 EISA IRQ1 Kbd +; 26 4 4 VB0+0 EISA IRQ0 8254 +; 27 3 3 VB2+3 Local/IPI level 3 Global IPI PROFILE_LEVEL +; 28 2 2 VB2+2 Local/IPI level 2 Local Timer CLOCK2_LEVEL +; 29 1 1 VB2+1 Local/IPI level 1 Slot IPI IPI_LEVEL +; 30 1 POWER_LEVEL +; 31 0 (high) 0 VB2+0 Spurious local interrupt HIGH_LEVEL +; +;;;;;;;;;;;;;;;; + +; CCHAR HalpIRQLtoCPL[36]; this array is used to get the value +; for the hardware current priority level +; (CPL) register from the KIRQL. + Public _HalpIRQLtoCPL +_HalpIRQLtoCPL Label Byte ;don't know how to make this symbolic + db 31,31,31,31,31,31,31,31,22 + db 21,20,19,18,17,16,15,14,13 + db 12,11,10, 9, 8, 7, 6, 5, 4 + db 3, 2, 1, 1, 0 + db 0, 0, 0, 0 ;four extra levels for good luck + +; CCHAR HalpIRQLtoVector[36]; this array is used to get the interrupt +; vector used for a given KIRQL, zero +; means no vector is used for the KIRQL + Public _HalpIRQLtoVector +_HalpIRQLtoVector Label Byte + db 0 + db 0 ;APC_LEVEL + db 0 ;DISPATCH_LEVEL + db 0 ;WAKE_LEVEL + db 0 + db 0 + db 0 + db 0 + db PRIMARY_VECTOR_BASE+23 + db PRIMARY_VECTOR_BASE+22 + db PRIMARY_VECTOR_BASE+21 + db PRIMARY_VECTOR_BASE+7 + db PRIMARY_VECTOR_BASE+6 + db PRIMARY_VECTOR_BASE+5 + db PRIMARY_VECTOR_BASE+4 + db PRIMARY_VECTOR_BASE+3 + db PRIMARY_VECTOR_BASE+15 + db PRIMARY_VECTOR_BASE+14 + db PRIMARY_VECTOR_BASE+13 + db PRIMARY_VECTOR_BASE+12 + db PRIMARY_VECTOR_BASE+11 + db PRIMARY_VECTOR_BASE+10 + db PRIMARY_VECTOR_BASE+9 + db PRIMARY_VECTOR_BASE+8 + db PRIMARY_VECTOR_BASE+20 + db PRIMARY_VECTOR_BASE+1 + db PRIMARY_VECTOR_BASE + db PRIMARY_VECTOR_BASE+19 ;PROFILE_LEVEL + db PRIMARY_VECTOR_BASE+18 ;CLOCK2_LEVEL + db PRIMARY_VECTOR_BASE+17 ;IPI_LEVEL + db 0 ;POWER_LEVEL + db 0 ;prevent CPL 0 enable changes ;HIGH_LEVEL + db 0, 0, 0, 0 ;four extra levels for good luck + +; CCHAR HalpVectorToIRQL[24]; this array is used to obtain the +; required IRQL from an interrupt +; vector, it is indexed by +; interrupt vector-PRIMARY_VECTOR_BASE + Public _HalpVectorToIRQL +_HalpVectorToIRQL Label Byte + db PROFILE_LEVEL-1 ;IRQ0 + db PROFILE_LEVEL-2 ;IRQ1 + db HIGH_LEVEL ;IRQ2--cascade + db PROFILE_LEVEL-12 ;IRQ3 + db PROFILE_LEVEL-13 ;IRQ4 + db PROFILE_LEVEL-14 ;IRQ5 + db PROFILE_LEVEL-15 ;IRQ6 + db PROFILE_LEVEL-16 ;IRQ7 + + db PROFILE_LEVEL-4 ;IRQ8 + db PROFILE_LEVEL-5 ;IRQ9 + db PROFILE_LEVEL-6 ;IRQ10 + db PROFILE_LEVEL-7 ;IRQ11 + db PROFILE_LEVEL-8 ;IRQ12 + db PROFILE_LEVEL-9 ;IRQ13 + db PROFILE_LEVEL-10 ;IRQ14 + db PROFILE_LEVEL-11 ;IRQ15 + + db HIGH_LEVEL ;Local/IPI level 0 (spurious) + db IPI_LEVEL ;Local/IPI level 1 + db CLOCK2_LEVEL ;Local/IPI level 2 + db PROFILE_LEVEL ;Local/IPI level 3 + db PROFILE_LEVEL-3 ;Local/IPI level 4 + db PROFILE_LEVEL-17 ;Local/IPI level 5 + db PROFILE_LEVEL-18 ;Local/IPI level 6 + db PROFILE_LEVEL-19 ;Local/IPI level 7 + + align 4 +; +; The following table is a bit map of IRQLs that use ICU local interrpt ptr +; (it must indicate those IRQLs corresponding to levels used in the ICU_LIPTR) +; + public _HalpLocalInts +_HalpLocalInts dd (1 shl CLOCK2_LEVEL)+(1 shl IPI_LEVEL)+(1 shl PROFILE_LEVEL) + +; +; The following tables define the addresses of software interrupt routers +; + +; +; Use this table if there is NO machine state frame on stack already +; + + public SWInterruptHandlerTable +SWInterruptHandlerTable label dword + dd offset FLAT:_KiUnexpectedInterrupt ; irql 0 + dd offset FLAT:_HalpApcInterrupt ; irql 1 + dd offset FLAT:_HalpDispatchInterrupt ; irql 2 + dd offset FLAT:_KiUnexpectedInterrupt ; irql 3 + dd offset FLAT:_KiUnexpectedInterrupt ; irql 4 + dd offset FLAT:_KiUnexpectedInterrupt ; irql 5 + dd offset FLAT:_KiUnexpectedInterrupt ; irql 6 + dd offset FLAT:_KiUnexpectedInterrupt ; irql 7 + dd offset FLAT:_KiUnexpectedInterrupt ; irql 8 + dd offset FLAT:_KiUnexpectedInterrupt ; irql 9 + dd offset FLAT:_KiUnexpectedInterrupt ; irql 10 + dd offset FLAT:_KiUnexpectedInterrupt ; irql 11 + dd offset FLAT:_KiUnexpectedInterrupt ; irql 12 + dd offset FLAT:_KiUnexpectedInterrupt ; irql 13 + dd offset FLAT:_KiUnexpectedInterrupt ; irql 14 + dd offset FLAT:_KiUnexpectedInterrupt ; irql 15 + dd offset FLAT:_KiUnexpectedInterrupt ; irql 16 + dd offset FLAT:_KiUnexpectedInterrupt ; irql 17 + dd offset FLAT:_KiUnexpectedInterrupt ; irql 18 + dd offset FLAT:_KiUnexpectedInterrupt ; irql 19 + dd offset FLAT:_KiUnexpectedInterrupt ; irql 20 + dd offset FLAT:_KiUnexpectedInterrupt ; irql 21 + dd offset FLAT:_KiUnexpectedInterrupt ; irql 22 + dd offset FLAT:_KiUnexpectedInterrupt ; irql 23 + dd offset FLAT:_KiUnexpectedInterrupt ; irql 24 + dd offset FLAT:_KiUnexpectedInterrupt ; irql 25 + dd offset FLAT:_KiUnexpectedInterrupt ; irql 26 + dd offset FLAT:_KiUnexpectedInterrupt ; irql 27 + dd offset FLAT:_KiUnexpectedInterrupt ; irql 28 + dd offset FLAT:_KIUnexpectedInterrupt ; irql 29 +; +; The following table picks up the highest pending software irq level +; from software irr +; + + public SWInterruptLookUpTable +SWInterruptLookUpTable label byte + db 0 ; SWIRR=0, so highest pending SW irql= 0 + db 0 ; SWIRR=1, so highest pending SW irql= 0 + db 1 ; SWIRR=2, so highest pending SW irql= 1 + db 1 ; SWIRR=3, so highest pending SW irql= 1 + db 2 ; SWIRR=4, so highest pending SW irql= 2 + db 2 ; SWIRR=5, so highest pending SW irql= 2 + db 2 ; SWIRR=6, so highest pending SW irql= 2 + db 2 ; SWIRR=7, so highest pending SW irql= 2 + db 3 ; SWIRR=8, so highest pending SW irql= 3 + db 3 ; SWIRR=9, so highest pending SW irql= 3 + db 3 ; SWIRR=A, so highest pending SW irql= 3 + db 3 ; SWIRR=B, so highest pending SW irql= 3 + db 3 ; SWIRR=C, so highest pending SW irql= 3 + db 3 ; SWIRR=D, so highest pending SW irql= 3 + db 3 ; SWIRR=E, so highest pending SW irql= 3 + db 3 ; SWIRR=F, so highest pending SW irql= 3 + + db 4 ; SWIRR=10, so highest pending SW irql= 4 + db 4 ; SWIRR=11, so highest pending SW irql= 4 + db 4 ; SWIRR=12, so highest pending SW irql= 4 + db 4 ; SWIRR=13, so highest pending SW irql= 4 + db 4 ; SWIRR=14, so highest pending SW irql= 4 + db 4 ; SWIRR=15, so highest pending SW irql= 4 + db 4 ; SWIRR=16, so highest pending SW irql= 4 + db 4 ; SWIRR=17, so highest pending SW irql= 4 + db 4 ; SWIRR=18, so highest pending SW irql= 4 + db 4 ; SWIRR=19, so highest pending SW irql= 4 + db 4 ; SWIRR=1A, so highest pending SW irql= 4 + db 4 ; SWIRR=1B, so highest pending SW irql= 4 + db 4 ; SWIRR=1C, so highest pending SW irql= 4 + db 4 ; SWIRR=1D, so highest pending SW irql= 4 + db 4 ; SWIRR=1E, so highest pending SW irql= 4 + db 4 ; SWIRR=1F, so highest pending SW irql= 4 + +_DATA ENDS + + page ,132 + subttl "Raise Irql" + +_TEXT SEGMENT DWORD PUBLIC 'CODE' + ASSUME DS:FLAT, ES:FLAT, SS:FLAT, FS:NOTHING, GS:NOTHING +;++ +; +; KIRQL +; FASTCALL +; KfRaiseIrql ( +; IN KIRQL NewIrql +; ) +; +; Routine Description: +; +; This routine is used to raise IRQL to the specified value. +; The 'lazy irql' algorythm is used, which is to say that the +; hardware interrupt priority level will not be programmed unless +; a lower priority interrupt actually comes in. +; +; Arguments: +; +; (cl) NewIrql - the new irql to be raised to +; +; +; Return Value: +; +; OldIrql +; +;-- + +; equates for accessing arguments + +cPublicFastCall KfRaiseIrql,1 +cPublicFpo 0, 0 +; +; Note it is very important that we set the OldIrql AFTER we raised to +; the new irql. Otherwise, if there is an interrupt comes in between and +; the OldIrql is not a local variable, the caller will get wrong OldIrql. +; The bottom line is the raising irql and returning old irql has to be +; atomic to the caller. +; + mov al, Fs:PcIrql ; (al) = Old Irql + mov Fs:PcIrql, cl ; set new irql + +if DBG + cmp al, cl ; old > new? + ja short Kri99 ; yes, go bugcheck + + fstRET KfRaiseIrql + +cPublicFpo 2, 2 +Kri99: + push ecx ; put new irql where we can find it + push eax ; put old irql where we can find it + mov byte ptr Fs:PcIrql,0 ; avoid recursive error + stdCall _KeBugCheck, <IRQL_NOT_GREATER_OR_EQUAL> ; never return +endif + fstRET KfRaiseIrql + +fstENDP KfRaiseIrql + + page ,132 + subttl "Lower irql" + +;++ +; +; VOID +; FASTCALL +; KfLowerIrql ( +; IN KIRQL NewIrql +; ) +; +; Routine Description: +; +; This routine is used to lower IRQL to the specified value. +; The IRQL and PIRQL will be updated accordingly. Also, this +; routine checks to see if any software interrupt should be +; generated. The following condition will cause software +; interrupt to be simulated: +; any software interrupt which has higher priority than +; current IRQL's is pending. +; +; NOTE: This routine simulates software interrupt as long as +; any pending SW interrupt level is higher than the current +; IRQL, even when interrupts are disabled. +; +; Arguments: +; +; (cl) = NewIrql - the new irql to be set. +; +; Return Value: +; +; None. +; +;-- + +cPublicFastCall KfLowerIrql ,1 +cPublicFpo 0,0 + + mov al, cl ; get new irql value + if DBG + cmp al, Fs:PcIrql + ja short KliBug + endif + pushfd + cli + mov Fs:PcIrql, al ;save new irql + cmp al, Fs:PcHal.pchHwIrql ;does hardware need reprogramming? + jb short @F ;jump if it does + popfd + fstRET KfLowerIrql + +@@: mov Fs:PcHal.pchHwIrql, al + and eax, 0FFh + mov al, _HalpIRQLtoCPL[eax] + mov dx, My+CpuPriortyLevel + out dx, ax ;set hardware level down + +@@: mov eax, Fs:PcIRR ;look for software interrupts + and eax, 1Fh + jz short @F ;jump if none + + mov al, SWInterruptLookUpTable[eax] ;get swint's irql + cmp al, Fs:PcIrql ;high enough to do this int? + jbe short @F ;jump if not + + call SWInterruptHandlerTable[eax*4] + jmp @B + +@@: popfd + fstRET KfLowerIrql + + if DBG +KliBug: + push eax ; new irql for debugging + push Fs:PcIrql ; old irql for debugging + mov byte ptr Fs:PcIrql,HIGH_LEVEL ; avoid recursive error + stdCall _KeBugCheck, <IRQL_NOT_LESS_OR_EQUAL> ; never return + endif + +fstENDP KfLowerIrql + +cPublicProc _HalpEndSoftwareInterrupt,1 +cPublicFpo 1,0 + mov ecx, [esp+4] + fstCall KfLowerIrql + stdRet _HalpEndSoftwareInterrupt +stdENDP _HalpEndSoftwareInterrupt + +;++ +; +; 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 + + + page ,132 + subttl "Get current irql" + +;++ +; +; KIRQL +; KeGetCurrentIrql (VOID) +; +; Routine Description: +; +; This routine returns to current IRQL. +; +; Arguments: +; +; None. +; +; Return Value: +; +; The current IRQL. +; +;-- + +cPublicProc _KeGetCurrentIrql ,0 + movzx eax, byte ptr fs:PcIrql ; Current irql is in the PCR + 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 interrupts for the Wyse HAL + ; + + mov ecx, HIGH_LEVEL + fstCall KfRaiseIrql + mov al, _HalpIRQLtoCPL[HIGH_LEVEL] + mov dx, My+CpuPriortyLevel + out dx, ax + mov Fs:PcHal.pchHwIrql, HIGH_LEVEL + stdRET _HalpDisableAllInterrupts + +stdENDP _HalpDisableAllInterrupts + + page ,132 + subttl "Interrupt Controller Chip Initialization" +;++ +; +; VOID +; HalpInitializePICs ( +; ) +; +; Routine Description: +; +; This routine sends the 8259 PIC initialization commands and +; masks all the interrupts on 8259s. +; +; Arguments: +; +; None +; +; Return Value: +; +; None. +; +;-- +cPublicProc _HalpInitializePICs ,0 + + push esi ; save caller's esi + cli ; disable interrupt + lea esi, PICsInitializationString + +Hip00: + lodsw ; (AX) = PIC port 0 address +Hip10: movzx edx, ax + outsb ; output ICW1 + IODelay + inc edx ; (DX) = PIC port 1 address + outsb ; output ICW2 + IODelay + outsb ; output ICW3 + IODelay + outsb ; output ICW4 + IODelay + outsb ; output OCW1 (interrupt mask) + lodsw + cmp ax, 0 ; end of init string? + jne short Hip10 ; go init next PIC + + pop esi ; restore caller's esi + sti ; enable interrupt + stdRET _HalpInitializePICs +stdENDP _HalpInitializePICs + +_TEXT ends + end diff --git a/private/ntos/nthals/halwyse7/i386/wymapint.c b/private/ntos/nthals/halwyse7/i386/wymapint.c new file mode 100644 index 000000000..6a8d48717 --- /dev/null +++ b/private/ntos/nthals/halwyse7/i386/wymapint.c @@ -0,0 +1,185 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + wymapint.c + +Abstract: + + This module implements the HAL HalGetInterruptVector routine + for an x86 system + +Author: + + John Vert (jvert) 17-Jul-1991 + +Environment: + + Kernel mode + +Revision History: + + John Fuller (o-johnf) 3-Apr-1992 Modifications for Wyse7000i +--*/ +#include "halp.h" +#if DBG +ULONG +ProcSub( + IN UCHAR RoutineNumber + ); + +#define enproc(x) ProcSub(x) +#define exproc(x) ProcSub((x)|0x80) + +#else //DBG + +#define enproc(x) +#define exproc(x) + +#endif //DBG + + +extern CCHAR HalpVectorToIRQL[]; + +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 + ); + + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE,HalpGetSystemInterruptVector) +#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 ); + + 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; + + UNREFERENCED_PARAMETER( BusHandler ); + UNREFERENCED_PARAMETER( BusInterruptVector ); + + enproc(0x0F); + + SystemVector = BusInterruptLevel + PRIMARY_VECTOR_BASE; + if (SystemVector < PRIMARY_VECTOR_BASE || + SystemVector > PRIMARY_VECTOR_BASE + HIGHEST_LEVEL_FOR_8259 || + HalpIDTUsage[SystemVector].Flags & IDTOwned ) { + + // + // This is an illegal BusInterruptVector and cannot be connected. + // + + return(0); + } + + *Irql = (KIRQL) HalpVectorToIRQL[BusInterruptLevel]; + + // + // On most MP systems the interrupt affinity is all processors. + // + *Affinity = HalpDefaultInterruptAffinity; + ASSERT(HalpDefaultInterruptAffinity); + + exproc(0x0F); + return SystemVector; +} + diff --git a/private/ntos/nthals/halwyse7/i386/wynmi.asm b/private/ntos/nthals/halwyse7/i386/wynmi.asm new file mode 100644 index 000000000..1bf044c0f --- /dev/null +++ b/private/ntos/nthals/halwyse7/i386/wynmi.asm @@ -0,0 +1,108 @@ + title "Wyse7000i NMI Handler" +;++ +; +; Copyright (c) 1989 Microsoft Corporation +; +; Module Name: +; +; wynmi.asm +; +; Abstract: +; +; Provides Wyse7000 x86 NMI handler +; +; Author: +; +; Environment: +; +; Kernel mode only. +; +; Revision History: +; +.386p + + .xlist +include hal386.inc +include i386\wy7000mp.inc +include callconv.inc + + extrn ReadMyCpuReg:NEAR + extrn WriteMyCpuReg:NEAR + +_TEXT SEGMENT DWORD PUBLIC 'CODE' + ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING + +;++ +; NTSTATUS +; 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... +; +;Arguments: +; +; NmiInfo - Pointer to NMI information structure (TBD) +; - NULL means no NMI information structure was passed +; +;Return Value: +; +; BugCheck code +; +;-- +cPublicProc _HalHandleNMI,1 + + push BCU_STAT1 + call ReadMyCpuReg + + test al, NMISRC_EXT + jnz short WyseDebugNmiButtonPressed + +; +; Decode other Wyse7000 NMI causes here... +; + mov eax, MPFW_FuncTable ;point to firmware entry points + + call dword ptr [eax][fnOS_Panic * 4] ;display NMI code to user + + mov eax, 0f002h ; SYSTEM_FATAL_TRAP + stdRET _HalHandleNMI + + public WyseDebugNmiButtonPressed +WyseDebugNmiButtonPressed: +; +; Recessed NMI button on back of CPU card was pressed +; Go to the debugger, then allow the system to continue +; + int 3 + + and eax, NOT NMISRC_EXT + push eax + push BCU_STAT1 + call WriteMyCpuReg +; +; Re-enable NMIs +; + push BCU_ERRCTLR + call ReadMyCpuReg + or al, NMI_ENB ;this bit was cleared by the NMI + push eax + push BCU_ERRCTLR + call WriteMyCpuReg + + xor eax, eax ; STATUS_SUCCESS + stdRET _HalHandleNMI + +stdENDP _HalHandleNMI + +_TEXT ends + + end diff --git a/private/ntos/nthals/halwyse7/i386/wyspin.asm b/private/ntos/nthals/halwyse7/i386/wyspin.asm new file mode 100644 index 000000000..b9d320668 --- /dev/null +++ b/private/ntos/nthals/halwyse7/i386/wyspin.asm @@ -0,0 +1,449 @@ +if NT_INST + +else + TITLE "Spin Locks" +;++ +; +; Copyright (c) 1989-1993 Microsoft Corporation +; Copyright (c) 1993 Wyse Technology +; +; Module Name: +; +; wyspin.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 +; John Fuller (o-johnf) 19-Apr-1993 modify for Wyse 7000i +; John Fuller (o-johnf) 31-Aug-1993 modify for Lazy IRQLs +;-- + + PAGE + +.486p + +include callconv.inc ; calling convention macros +include i386\kimacro.inc +include hal386.inc +include mac386.inc +include i386\wy7000mp.inc + + EXTRNP KfRaiseIrql,1,,FASTCALL + EXTRNP KfLowerIrql,1,,FASTCALL + EXTRNP _KeBugCheck,1,IMPORT + EXTRNP _KeSetEventBoostPriority, 2, IMPORT + EXTRNP _KeWaitForSingleObject,5, IMPORT + extrn SWInterruptLookUpTable:byte + extrn SWInterruptHandlerTable:dword + extrn _HalpIRQLtoCPL:byte + +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: +; +; OldIrql +; +;-- + +align 16 +cPublicFastCall KfAcquireSpinLock ,1 + +ifdef NT_UP ; On up build just perform raiseirql + + mov ecx, DISPATCH_LEVEL + jmp @KfRaiseIrql@4 +else +cPublicFpo 0,0 +; +; On a MP build we raise to dispatch_level +; and then acquire the spinlock +; + +; +; Since on the Wyse 7000i the hardware priority of DISPATCH_LEVEL +; is the same as for all levels below DISPATCH_LEVEL we just need +; to update PcIrql to raise the level and don't need to touch the +; hardware. +; + mov al, fs:PcIrql ; get current irql + +if DBG + cmp al, DISPATCH_LEVEL ; old > new? + jbe short @F ; no, we're OK + push DISPATCH_LEVEL ; put new irql where we can find it + push eax ; put old irql where we can find it + mov byte ptr fs:PcIrql,0 ; avoid recursive error + stdCall _KeBugCheck, <IRQL_NOT_GREATER_OR_EQUAL> +@@: +endif + + mov byte ptr fs:PcIrql, DISPATCH_LEVEL + +; +; Attempt to assert the lock +; + +sl10: ACQUIRE_SPINLOCK ecx,<short sl20> + fstRET KfAcquireSpinLock + +; +; 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 + +ifndef NT_UP +cPublicFpo 2,0 + RELEASE_SPINLOCK ecx ; release it +endif +; +; NOTE: The following code for the Wyse 7000i does not assume any knowelege +; of either the current Irql or the new Irql. Therefore, the hardware +; must be programmed. +; + mov al, dl ; get new irql value + if DBG + cmp al, Fs:PcIrql + ja short KrsBug + endif + pushfd + cli + mov Fs:PcIrql, al ;save new irql + cmp al, Fs:PcHal.pchHwIrql ;does hardware need reprogramming? + jb short @F ;jump if it does + popfd + fstRET KfReleaseSpinLock + +@@: mov Fs:PcHal.pchHwIrql, al + and eax, 0FFh + mov dx, My+CpuPriortyLevel + mov al, _HalpIRQLtoCPL[eax] + out dx, ax ;set hardware level down + +@@: mov eax, Fs:PcIRR ;look for software interrupts + and eax, 1Fh + jz short @F ;jump if none + + mov al, SWInterruptLookUpTable[eax] ;get swint's irql + cmp al, Fs:PcIrql ;high enough to do this int? + jbe short @F ;jump if not + + call SWInterruptHandlerTable[eax*4] + jmp @B + +@@: popfd + fstRET KfReleaseSpinLock + + if DBG +KrsBug: + push eax ; new irql for debugging + push Fs:PcIrql ; old irql for debugging + mov byte ptr Fs:PcIrql,HIGH_LEVEL ; avoid recursive error + stdCall _KeBugCheck, <IRQL_NOT_LESS_OR_EQUAL> ; never return + endif + +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/halwyse7/i386/wysproc.c b/private/ntos/nthals/halwyse7/i386/wysproc.c new file mode 100644 index 000000000..3c8d2ff1e --- /dev/null +++ b/private/ntos/nthals/halwyse7/i386/wysproc.c @@ -0,0 +1,465 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation +Copyright (c) 1992, 1993 Wyse Technology + +Module Name: + + spsproc.c + +Abstract: + + Wyse7000i Start Next Processor c code. + + This module implements the initialization of the system dependent + functions that define the Hardware Architecture Layer (HAL) for an + Wyse MP 7000i + +Author: + + Ken Reneris (kenr) 22-Jan-1991 + +Environment: + + Kernel mode only. + +Revision History: + +--*/ +#include "halp.h" + +UCHAR HalName[] = "Wyse7000i MP HAL"; + +#if DBG +ULONG +ProcSub( + IN UCHAR RoutineNumber + ); + +#define enproc(x) ProcSub(x) +#define exproc(x) ProcSub((x)|0x80) + +#else //DBG + +#define enproc(x) +#define exproc(x) + +#endif //DBG + + +PVOID +HalpRemapVirtualAddress( + IN PVOID VirtualAddress, + IN PVOID PhysicalAddress, + IN BOOLEAN WriteThrough + ); + +VOID +HalpMapCR3 ( + IN ULONG VirtAddress, + IN PVOID PhysicalAddress, + IN ULONG Length + ); + +ULONG +HalpBuildTiledCR3 ( + IN PKPROCESSOR_STATE ProcessorState + ); + +VOID +HalpFreeTiledCR3 ( + VOID + ); + +VOID HalpInitOtherBuses (VOID); + +BOOLEAN +HalpInitMP ( + IN ULONG Phase, + IN PLOADER_PARAMETER_BLOCK LoaderBlock + ); + +ULONG __cdecl +icu_sync_master ( + ULONG i_sync, + UCHAR i_exp_cfg, + ULONG i_timeout + ); + + +#define LOW_MEMORY 0x000100000 + +#define MAX_PT 8 + +extern VOID StartPx_PMStub(VOID); + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(INIT,HalpInitMP) +#pragma alloc_text(INIT,HalAllProcessorsStarted) +#pragma alloc_text(INIT,HalReportResourceUsage) +#pragma alloc_text(INIT,HalReportResourceUsage) +#pragma alloc_text(INIT,HalpInitOtherBuses) +#pragma alloc_text(INIT,HalpFreeTiledCR3) +#pragma alloc_text(INIT,HalpMapCR3) +#pragma alloc_text(INIT,HalpBuildTiledCR3) +#endif + +UCHAR ProcessorsPresent; // bitmap by WWB slot of cpu's present +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 + + +BOOLEAN +HalpInitMP ( + IN ULONG Phase, + IN PLOADER_PARAMETER_BLOCK LoaderBlock + ) +/*++ + +Routine Description: + Allows MP initialization from HalInitSystem. + +Arguments: + Same as HalInitSystem + +Return Value: + none. + +--*/ +{ + ULONG paddress; + ULONG adjust; + PKPCR pPCR; + + enproc(0x0B); + + + pPCR = KeGetPcr(); + + if (Phase == 0) { + MppIDT = HalpMapPhysicalMemory (0, 1); + + // + // Map system firmware to last 128Kb of memory + // + + paddress = 0xFFFE0000; // address of last 128Kb of memory + for (adjust = 0x20000 / PAGE_SIZE; adjust; --adjust) { + HalpRemapVirtualAddress((PVOID) paddress, (PVOID) paddress, FALSE); + paddress += PAGE_SIZE; + } + + // + // Are other processors installed and running? + // + + if ( ProcessorsPresent ) { // any other cpu's installed? + adjust = icu_sync_master( 0x80, // SYNC_CONTINUE + ProcessorsPresent,// cpu's installed + 5 ); // 5*15ms timeout + ProcessorsPresent = (UCHAR) (adjust >> 8); // running cpu's + } + + if ( !ProcessorsPresent ) { + exproc(0x0B); + return TRUE; + } + + // + // Allocate some low memory for processor bootup stub + // + + MpLowStubPhysicalAddress = (PVOID)HalpAllocPhysicalMemory (LoaderBlock, + LOW_MEMORY, 1, FALSE); + + if (!MpLowStubPhysicalAddress) { + ProcessorsPresent = 0; // can't start other cpu's + exproc(0x0B); + return TRUE; + } + + MpLowStub = (PCHAR) HalpMapPhysicalMemory (MpLowStubPhysicalAddress, 1); + exproc(0x0B); + return TRUE; + + } else { + + // + // Phase 1 + // + + ; // nothing to do + + } + exproc(0x0B); +} + +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 // Wyse7000 is an Eisa machines + ); + + RtlFreeUnicodeString (&UHalName); +} + + + +VOID +HalpResetAllProcessors ( + VOID + ) +{ + // Just return, that will invoke the standard PC reboot code +} + + +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 + + +--*/ +{ + enproc(0x0C); +#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); + + exproc(0x0C); + 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; + + enproc(0x0D); + + 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; + } + } + exproc(0x0D); +} + + + +VOID +HalpFreeTiledCR3 ( + VOID + ) +/*++ + +Routine Description: + Free's any memory allocated when the tiled page directory was built. + +Arguments: + none + +Return Value: + none +--*/ +{ + ULONG i; + + enproc(0x0E); + + for (i=0; MpFreeCR3[i]; i++) { + ExFreePool (MpFreeCR3[i]); + MpFreeCR3[i] = 0; + } + exproc(0x0E); +} + + + +VOID +HalpInitOtherBuses ( + VOID + ) +{ + // no other buses +} + + + +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/halwyse7/i386/wysproca.asm b/private/ntos/nthals/halwyse7/i386/wysproca.asm new file mode 100644 index 000000000..07ec04831 --- /dev/null +++ b/private/ntos/nthals/halwyse7/i386/wysproca.asm @@ -0,0 +1,436 @@ + title "MP primitives for Wyse 7000i" +;++ +; +;Copyright (c) 1991 Microsoft Corporation +; +;Module Name: +; +; wysproca.asm +; +;Abstract: +; +; Wyse7000i Start Next Processor assemble code +; +; This module along with wysproc.c implement the code to start +; off additional processors on the Wyse 7000i. +; +;Author: +; +; Ken Reneris (kenr) 12-Jan-1992 +; +;Revision History: +; +; John Fuller (o-johnf) 7-Apr-1992 convert to Wyse 7000i +; +;-- + + + +.386p + .xlist +include hal386.inc +include callconv.inc ; calling convention macros +include i386\kimacro.inc +include mac386.inc +include i386\wy7000mp.inc + .list + + EXTRNP _ExAllocatePool,2,IMPORT + EXTRNP _HalpBuildTiledCR3,1 + EXTRNP _HalpFreeTiledCR3,0 + + extrn _MppIDT:DWORD + extrn _MpLowStub:DWORD + extrn _MpLowStubPhysicalAddress:DWORD + extrn _ProcessorsPresent:BYTE + + + +; +; Internal defines and structures +; + +PxParamBlock struc + SPx_flag dd ? + SPx_TiledCR3 dd ? + SPx_P0EBP dd ? + SPx_PB db processorstatelength dup (?) +PxParamBlock ends + +BootPkg struc +bpLength db 08h + 80h ;package length + sync flag +bpDest db ? ;destination bitmap +bpCode db 08h + 40h+ 80h ;boot_cpu_cmd + mpfw_pkg + cmd_pkg + db 0 ;reserved +bpStartAddr dd ? ;start execution physical addr + ;executions starts in flat 32-bit + ;non-paged mode. +BootPkg ends + +_DATA SEGMENT DWORD PUBLIC 'DATA' + + public _CpuBootPkg +_CpuBootPkg BootPkg <> + +_DATA ends + +_TEXT SEGMENT PARA 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] + + +cPublicProc _HalStartNextProcessor ,2 + enproc 8 + + 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.SPx_flag, eax + + cmp _ProcessorsPresent, al ; any processors left to start + je snp_exit ; exit FALSE + + 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.SPx_PB + mov esi, pProcessorState + mov ecx, processorstatelength ; Copy processorstate + rep movsb ; to PxFrame + + stdCall _HalpBuildTiledCR3, <pProcessorState> + + mov PxFrame.SPx_TiledCR3, eax + mov PxFrame.SPx_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.SPx_PB.PsContextFrame.CsSegCs] + mov [eax.SPrxFlatCS], bx ; patch realmode stub with + mov [eax.SPrxPMStub], offset _StartPx_PMStub ; valid long jump + + mov ebx, _MppIDT + add ebx, WarmResetVector + + cli + push dword ptr [ebx] ; Save current vector + push ebx ; save ptr to it + + mov eax, _MpLowStubPhysicalAddress + mov dword ptr [ebx], eax ; copy of PxFrame is here + + add eax, size PxParamBlock ; calc start execution addr + mov _CpuBootPkg.bpStartAddr, eax ; put in start cpu package +@@: movzx eax, _ProcessorsPresent ; get bitmap of processors + bsf ecx, eax ; look for next one + jz snp_exitA ; jump if blew it + btr eax, ecx ; clear its bit + xchg al, _ProcessorsPresent ; save new bitmap + xor al, _ProcessorsPresent ; leave only one bit + mov _CpuBootPkg.bpDest, al ; save as destination of cmd + + mov ebx, eax + mov eax, MPFW_FuncTable + push ebx + push offset _CpuBootPkg + call dword ptr [eax][fnICU_Send_Mstr * 4] + add esp, 8 + ror eax, 16 + cmp al, 1 + jne @B ; try another cpu if error + +@@: + cmp PxFrame.SPx_flag, 0 ; wait for Px to get it's + jz @b ; info + + mov eax, 1 ; return TRUE +snp_exitA: + pop ebx ; get ptr to WarmResetVector + pop dword ptr [ebx] ; restore WarmResetVector + + sti + + push eax ; save true/false return + stdCall _HalpFreeTiledCR3 ; free memory used for tiled +;; if DBG + %out generating stall code + EXTRNP _KeStallExecutionProcessor,1 + push ecx + push edx + + stdCall _KeStallExecutionProcessor, <75000> ; wait 75 milliseconds + + pop edx + pop ecx +;; endif ;DBG + ; CR3 + pop eax ; restore return value + +snp_exit: + pop ebx + pop edi + pop esi + mov esp, ebp + pop ebp + + exproc 8 + + stdRET _HalStartNextProcessor + +stdENDP _HalStartNextProcessor + +;++ +; +; ULONG +; icu_sync_master ( +; ULONG i_sync, +; UCHAR i_exp_cfg, +; ULONG i_timeout +; ); +; +; Routine Description: +; +; This routine is called by HalpInitMP during phase 0 to determine +; if any other processors are running. +; +; This routine is just a stub to access the firmware roms. +; +; Arguments: +; +; i_sync specifies wether to wait or continue??? +; +; i_exp_cfg specifies bitmap of WWB slot to try communicating with +; +; i_timeout specifies maximum time to wait for response +; +; Return Value: +; +; eax[0:7] remaining length of command +; +; eax[8:15] bitmap of WWB slots responding (running) +; +; eax[16:23] return code, 1=Ok, 2=timeout +; +; eax[24:31] reserved +; +;-- +public _icu_sync_master +_icu_sync_master proc + mov eax, MPFW_FuncTable + jmp dword ptr [eax][fnICU_Sync_Mstr * 4] +_icu_sync_master endp +;_TEXT ends ; end 32 bit code + + +;_TEXT16 SEGMENT DWORD PUBLIC USE16 'CODE' ; start 16 bit code + + align 4 +;++ +; +; VOID +; StartPx_RMStub +; +; Routine Description: +; +; When a new processor is started, it starts in 32-bit protected mode +; with paging disabled and is sent to a copy of this function which has +; been copied into low memory. (below 1m). +; +; 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 + cli + + mov edi, WarmResetVector + mov edi, cs:[edi] ; point to processor block + ; load the GDT + lgdt fword ptr cs:[edi].SPx_PB.PsSpecialRegisters.SrGdtr + + ; load the IDT + lidt fword ptr cs:[edi].SPx_PB.PsSpecialRegisters.SrIdtr + + mov eax, cs:[edi].SPx_TiledCR3 + mov cr3, eax + + mov ebp, dword ptr cs:[edi].SPx_P0EBP + mov ecx, dword ptr cs:[edi].SPx_PB.PsContextFrame.CsSegDs + mov ebx, dword ptr cs:[edi].SPx_PB.PsSpecialRegisters.SrCr3 + mov eax, dword ptr cs:[edi].SPx_PB.PsSpecialRegisters.SrCr0 + + mov cr0, eax ; into prot mode + + db 0eah ; reload cs:eip +SPrxPMStub dd 0 +SPrxFlatCS dw 0 + +StartPx_RMStub_Len equ $ - StartPx_RMStub +stdENDP StartPx_RMStub + + +;_TEXT16 ends ; End 16 bit code + +;_TEXT SEGMENT ; 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 +; +;-- + align 16 ; to make sure we don't cross a page boundry + ; before reloading CR3 + +cPublicProc _StartPx_PMStub ,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.SPx_PB.PsSpecialRegisters + + lldt word ptr ds:[esi].SrLdtr ; load ldtr + ltr word ptr ds:[esi].SrTr ; load tss + + lea edi, PxFrame.SPx_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 + + ; eax, ebx, edx are still free + + inc [PxFrame.SPx_flag] ; Signal p0 that we are + ; done with it's data + ; Set remaining registers + pop ebp + pop edi + pop edx + pop ebx + pop eax + exproc 0 + stdRET _StartPx_PMStub ; Set eip + +stdENDP _StartPx_PMStub + +_TEXT ends ; end 32 bit code + end diff --git a/private/ntos/nthals/halwyse7/i386/wyswint.asm b/private/ntos/nthals/halwyse7/i386/wyswint.asm new file mode 100644 index 000000000..2e0fd4201 --- /dev/null +++ b/private/ntos/nthals/halwyse7/i386/wyswint.asm @@ -0,0 +1,336 @@ + title "Software Interrupts" + +;++ +; +; Copyright (c) 1992-1993 Microsoft Corporation +; Copyright (c) 1993 Wyse Technology +; +; Module Name: +; +; wyswint.asm +; +; Abstract: +; +; This module implements the software interrupt handlers +; for x86 machines +; +; Author: +; +; John Vert (jvert) 2-Jan-1992 +; +; Environment: +; +; Kernel mode only. +; +; Revision History: +; John Fuller (o-johnf) 31-Aug-1993 mods to support Wyse Lazy IRQLs +; +;-- + +.386p + .xlist +include hal386.inc +include callconv.inc ; calling convention macros +include i386\ix8259.inc +include i386\kimacro.inc +include i386\wy7000mp.inc + .list + + EXTRNP _KiDeliverApc,3,IMPORT + EXTRNP _KiDispatchInterrupt,0,IMPORT + EXTRNP Kei386EoiHelper,0,IMPORT + EXTRNP _HalEndSystemInterrupt,2 + extrn SWInterruptHandlerTable:dword + extrn SWInterruptLookUpTable:byte +ifdef IRQL_METRICS + extrn HalApcSoftwareIntCount:dword + extrn HalDpcSoftwareIntCount:dword +endif + +_TEXT$02 SEGMENT DWORD PUBLIC 'CODE' + ASSUME DS:FLAT, ES:FLAT, SS:FLAT, FS:NOTHING, GS:NOTHING + + page ,132 + subttl "Request Software Interrupt" + +;++ +; +; VOID +; FASTCALL +; HalRequestSoftwareInterrupt ( +; IN KIRQL RequestIrql +; ) +; +; Routine Description: +; +; This routine is used to request a software interrupt to the +; system. Also, this routine checks to see if any software +; interrupt should be generated. +; The following condition will cause software interrupt to +; be simulated: +; any software interrupt which has higher priority than +; current IRQL's is pending. +; +; NOTE: This routine simulates software interrupt as long as +; any pending SW interrupt level is higher than the current +; IRQL, even when interrupts are disabled. +; +; ASSUMPTIONS: +; 1. This routine is only called for IRQL's 1-4. +; 2. No bits above bit 4 can be set in PcIRR. +; 3. All hardware interrups are above IRQL 4. +; +; Arguments: +; +; (cl) = RequestIrql - Supplies the request IRQL value +; +; Return Value: +; +; None. +; +;-- + +cPublicFastCall HalRequestSoftwareInterrupt ,1 +cPublicFpo 0, 1 + + mov eax,1 + shl eax, cl ; convert to mask + pushfd ; save interrupt mode + cli ; disable interrupt + or PCR[PcIRR], eax ; set the request bit + + mov eax, PCR[PcIRR] ; get SW interrupt request register + and eax, 3 ; mask off pending HW interrupts + jz short KsiExit ; exit is none for now + mov al, SWInterruptLookUpTable[eax] ; get the highest pending + ; software interrupt level + cmp al, PCR[PcIrql] ; Is highest SW int level > irql? + jbe KsiExit ; No, jmp ksiexit + call SWInterruptHandlerTable[eax*4] ; yes, simulate interrupt + ; to the appropriate handler +@@: popfd ; restore original interrupt mode + fstRET HalRequestSoftwareInterrupt + +KsiExit: + cmp cl, PCR[PcHal.pchHwIrql]; compare with Hardware Irql + jbe @B ; jump if hardware already above us + mov PCR[PcHal.pchHwIrql], cl; ensure KeLowerIrql checks PcIRR + popfd ; restore original interrupt mode + 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 + + align dword + public _HalpDispatchInterrupt +_HalpDispatchInterrupt proc +ifdef IRQL_METRICS + lock inc HalDpcSoftwareIntCount +endif +; +; 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 and set new priority level + + push PCR[PcIrql] ; save previous IRQL + mov byte ptr PCR[PcIrql], DISPATCH_LEVEL; set new irql + btr dword ptr PCR[PcIRR], DISPATCH_LEVEL; clear the pending bit in IRR + +; +; 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 + +_HalpDispatchInterrupt endp + + 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 + + align dword + public _HalpApcInterrupt +_HalpApcInterrupt proc +ifdef IRQL_METRICS + lock inc HalApcSoftwareIntCount +endif +; +; Create IRET frame on stack +; + pop eax + pushfd + push cs + push eax + +; +; Save machine state in trap frame +; + ENTER_INTERRUPT hapc_a, hapc_t +.FPO ( FPO_LOCALS+1, 0, 0, 0, 0, FPO_TRAPFRAME ) + + + public _HalpApcInterrupt2ndEntry +_HalpApcInterrupt2ndEntry: + +; +; Save previous IRQL and set new priority level +; + + push PCR[PcIrql] ; save previous Irql + mov byte ptr PCR[PcIrql], APC_LEVEL ; set new Irql + btr dword ptr PCR[PcIRR], APC_LEVEL ; dismiss pending APC +; +; 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 + +_HalpApcInterrupt endp + +_TEXT$02 ends + end diff --git a/private/ntos/nthals/halwyse7/i386/wysysint.asm b/private/ntos/nthals/halwyse7/i386/wysysint.asm new file mode 100644 index 000000000..ebd2feaec --- /dev/null +++ b/private/ntos/nthals/halwyse7/i386/wysysint.asm @@ -0,0 +1,615 @@ +;++ +; +;Copyright (c) 1991-1993 Microsoft Corporation +;Copyright (c) 1992, 1993 Wyse Technology +; +;Module Name: +; +; wysysint.asm +; +;Abstract: +; +; This module implements the HAL routines to enable/disable system +; interrupts, for the MP Wyse7000i implementation +; +;Author: +; +; John Vert (jvert) 22-Jul-1991 +; +;Environment: +; +; Kernel Mode +; +;Revision History: +; +;-- + + +.386p + .xlist +include hal386.inc +include callconv.inc ; calling convention macros +include i386\ix8259.inc +include i386\kimacro.inc +include mac386.inc +include i386\wy7000mp.inc + .list + + EXTRNP _KeBugCheck,1,IMPORT + extrn WriteMyCpuReg:NEAR + EXTRNP _KeLowerIrql,1 + extrn _HalpVectorToIRQL:BYTE + extrn _HalpIRQLtoVector:BYTE + extrn _HalpIRQLtoCPL:BYTE + extrn _HalpLocalInts:DWORD + +; +; Constants used to initialize CMOS/Real Time Clock +; + +CMOS_CONTROL_PORT EQU 70h ; command port for cmos +CMOS_DATA_PORT EQU 71h ; cmos data port + +; +; Macros to Read/Write/Reset CMOS to initialize RTC +; + +; CMOS_READ +; +; Description: This macro read a byte from the CMOS register specified +; in (AL). +; +; Parameter: (AL) = address/register to read +; Return: (AL) = data +; +; NOTE: IODelay's are not needed on EISA machines. + +CMOS_READ MACRO + OUT CMOS_CONTROL_PORT,al ; ADDRESS LOCATION AND DISABLE NMI +; IODelay ; I/O DELAY + IN AL,CMOS_DATA_PORT ; READ IN REQUESTED CMOS DATA +; IODelay ; I/O DELAY +ENDM + +_DATA SEGMENT DWORD PUBLIC 'DATA' + +align dword + + public _HalpICUlock ;spinlock for rebroadcasting timer & global IPI's +_HalpICUlock dd 0 + public _Halp8259Lock ;spinlock for accessing 8259 mask registers +_Halp8259Lock dd 0 + public _i8259_IMR ;global 8259 interrupt mask +_i8259_IMR dd not (1 shl PIC_SLAVE_IRQ) + public _i8259_ISR ;global 8259 interrupts in services +_i8259_ISR dd 0 + public _Halp8259Counts ;count of cpu's attached to each 8259 interrupt +_Halp8259Counts db 16 dup(0) + +; +; HalDismissSystemInterrupt does an indirect jump through this table so it +; can quickly execute specific code for different interrupts. +; + public HalpSpecialDismissTable +HalpSpecialDismissTable label dword + dd offset FLAT:HalpDismissNormal ; irq 0 + dd offset FLAT:HalpDismissNormal ; irq 1 + dd offset FLAT:HalpDismissSpurious ; irq 2 + dd offset FLAT:HalpDismissNormal ; irq 3 + dd offset FLAT:HalpDismissNormal ; irq 4 + dd offset FLAT:HalpDismissNormal ; irq 5 + dd offset FLAT:HalpDismissNormal ; irq 6 + dd offset FLAT:HalpDismissIrq07 ; irq 7 + dd offset FLAT:HalpDismissNormal ; irq 8 + dd offset FLAT:HalpDismissNormal ; irq 9 + dd offset FLAT:HalpDismissNormal ; irq A + dd offset FLAT:HalpDismissNormal ; irq B + dd offset FLAT:HalpDismissNormal ; irq C + dd offset FLAT:HalpDismissNormal ; irq D + dd offset FLAT:HalpDismissNormal ; irq E + dd offset FLAT:HalpDismissIrq0f ; irq F + dd offset FLAT:HalpDismissSpurious ; irq 10 + dd offset FLAT:HalpDismissIPIlevel ; irq 11 + dd offset FLAT:HalpDismissIPIlevel ; irq 12 + dd offset FLAT:HalpDismissIPIlevel ; irq 13 + dd offset FLAT:HalpDismissIPIlevel ; irq 14 + dd offset FLAT:HalpDismissIPIlevel ; irq 15 + dd offset FLAT:HalpDismissIPIlevel ; irq 16 + dd offset FLAT:HalpDismissIPIlevel ; irq 17 + dd offset FLAT:HalpDismissSpurious ; irq 18 + dd offset FLAT:HalpDismissSpurious ; irq 19 + dd offset FLAT:HalpDismissSpurious ; irq 1A + dd offset FLAT:HalpDismissSpurious ; irq 1B + dd offset FLAT:HalpDismissSpurious ; irq 1C + dd offset FLAT:HalpDismissSpurious ; irq 1D + dd offset FLAT:HalpDismissSpurious ; irq 1E + dd offset FLAT:HalpDismissSpurious ; irq 1F + dd offset FLAT:HalpDismissSpurious ; irq 20 + dd offset FLAT:HalpDismissSpurious ; irq 21 + dd offset FLAT:HalpDismissSpurious ; irq 22 + dd offset FLAT:HalpDismissSpurious ; irq 23 + +_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 is used to dismiss the specified vector number. It is called +; before any interrupt service routine code is executed. +; +; N.B. This routine does NOT preserve EAX or EBX +; +;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 - Interrupt successfully dismissed and Irql raised. +; +;-- +align dword +HbsiIrql equ byte ptr [esp+4+8] +HbsiVector equ byte ptr [esp+8+8] +HbsiOldIrql equ dword ptr [esp+12+8] + +cPublicProc _HalBeginSystemInterrupt ,3 + push ecx + push edx + mov ebx, (-PRIMARY_VECTOR_BASE) and 0FFh + add bl, HbsiVector ; (ebx) = 8259 IRQ # +if DBG + cmp ebx, 23h + jbe hbsi00 + int 3 +hbsi00: + +endif + xor ecx, ecx + mov cl, _HalpVectorToIRQL[ebx] ; get h/w Irql of interrupt + cmp cl, Fs:PcIrql ; int after raise Irql? + jbe short HalpIntBelowIRQL ; jump if it is + jmp HalpSpecialDismissTable[ebx*4] + +HalpIntBelowIRQL: + xor eax, eax + mov al, Fs:PcIrql + mov dx, My+CpuPriortyLevel + mov Fs:PcHal.pchHwIrql, al + mov al, _HalpIRQLtoCPL[eax] + out dx, ax + bt _HalpLocalInts, ecx ; EISA or Local interrupt? + jnc short HalpRebroadcastEISAint ; jump if EISA interrupt + + cmp cl, IPI_LEVEL ; IPI's are easy + jne HalpEmulateClockOrGlobal ; jmp if not an IPI + + mov cl, byte ptr fs:PcHal.pchPrSlot ; IPIs get resent to + or cl, ICU_IPI_SLOT ; the current processor + jmp short HalpRebroadcastIPI + +HalpRebroadcastEISAint: + mov cl, _HalpIRQLtoCPL[ecx] ; get hw interrupt level + add cl, ICU_XMT_INT_SND ; make ICU command +HalpRebroadcastIPI: + mov dx, My+CpuIntCmd ; point to ICU command register +@@: in ax, dx + test eax, ICU_CMD_BUSY + jnz short @B ; wait for ICU not busy + xchg eax, ecx ; get ICU command + out dx, ax ; rebroadcast EISA interrupt + jmp HalpDismissSpurious ; clear ICU in service bit + +HalpEmulateClockOrGlobal: +; The following code resends a clock or global interrupt by mapping the +; appropriate ICU_LIPTR value to zero and then broadcasting the level. +; This must be spinlocked since it will not work it two CPUs try it at +; the same time. + + cmp cl, CLOCK2_LEVEL ; is this CLOCK or GLOBAL? + mov cl, _HalpIRQLtoCPL[ecx] ; (get this int's level #) + mov ax, not lipTimer ; (assume timer interrupt) + je short @F ; jump if timer interrupt + mov ax, not (lipGlobal+lipSerial) ; it is global interrupt +@@: and ax, fs:word ptr PcHal.pchCurLiptr + push eax ; save temp LIPTR + + lea eax, _HalpICUlock ; Serialize access to +Hec10: ACQUIRE_SPINLOCK eax, HecSpin ; remappings + + push ICU_LIPTR ; Point global interrupt to + call WriteMyCpuReg ; make it a clock interrupt + + mov dx, My+CpuIntCmd ; wait for ICU not busy +@@: in ax, dx + test eax, ICU_CMD_BUSY + jnz short @B + + xchg eax, ecx ; get int level back + add al, ICU_XMT_INT_SND ; make send level command + out dx, ax ; to make to clock interrupt + +@@: in ax, dx ; wait for ICU not busy + test eax, ICU_CMD_BUSY ; before resetting GlobalIpi + jnz short @B ; value + + push fs:PcHal.pchCurLiptr + push ICU_LIPTR ; Put GlobalIpi back to + call WriteMyCpuReg ; normal setting + + lea eax, _HalpICUlock + RELEASE_SPINLOCK eax + + jmp HalpDismissSpurious + +HecSpin: + SPIN_ON_SPINLOCK eax, Hec10 + + +HalpDismissSpinF: + SPIN_ON_SPINLOCK eax, Hbsi10 + + align dword +HalpDismissIrq0f: +; +; Check to see if this is a spurious interrupt +; + lea eax, _Halp8259Lock +Hbsi10: ACQUIRE_SPINLOCK eax, HalpDismissSpinF + mov al, OCW3_READ_ISR ; tell 8259 we want to read ISR + out PIC2_PORT0, al +; IODelay ; delay + in al, PIC2_PORT0 ; (al) = content of PIC 1 ISR + test al, 10000000B ; Is In-Service register set? + jnz HalpDismissNormal2 ; No, this is NOT a spurious int, + ; go do the normal interrupt stuff + +; +; This is a spurious interrupt. +; Because the slave PIC is cascaded to irq2 of master PIC, we need to +; dismiss the interupt on master PIC's irq2. +; + + mov al, PIC2_EOI ; Specific eoi to master for pic2 eoi + out PIC1_PORT0, al ; send irq2 specific eoi to master + + lea eax, _Halp8259Lock + RELEASE_SPINLOCK eax + +HalpDismissSpurious: + mov dx, My+CpuIntCmd +@@: in ax, dx + test eax, ICU_CMD_BUSY + jnz @B + mov al, ICU_CLR_INSERV1 + out dx, ax + xor eax, eax ; return FALSE +; sti + pop edx + pop ecx + stdRET _HalBeginSystemInterrupt + +HalpDismissSpin: + SPIN_ON_SPINLOCK eax, HalpDismissNormal + +HalpDismissSpin7: + SPIN_ON_SPINLOCK eax, Hbsi20 + + align dword +HalpDismissIrq07: +; +; Check to see if this is a spurious interrupt +; + lea eax, _Halp8259Lock +Hbsi20: ACQUIRE_SPINLOCK eax, HalpDismissSpin7 + mov al, OCW3_READ_ISR ; tell 8259 we want to read ISR + out PIC1_PORT0, al +; IODelay ; delay + in al, PIC1_PORT0 ; (al) = content of PIC 1 ISR + test al, 10000000B ; Is In-Service register set? + jnz short HalpDismissNormal2 ; No, so this is a spurious int + + lea eax, _Halp8259Lock + RELEASE_SPINLOCK eax + jmp HalpDismissSpurious + + align dword +HalpDismissNormal: + lea eax, _Halp8259Lock + ACQUIRE_SPINLOCK eax, HalpDismissSpin + + align dword +HalpDismissNormal2: + mov eax, _i8259_IMR ;get current 8259 masks + bts _i8259_ISR, ebx ;mark this int as in service + or eax, _i8259_ISR ;also mask in service ints + SET_8259_MASK ;tell 8259's the news + lea eax, _Halp8259Lock + RELEASE_SPINLOCK eax + +; +; Dismiss interrupt. Current interrupt is already masked off. +; + mov eax, ebx ; (eax) = IRQ # + cmp eax, 8 ; EOI to master or slave? + + jae short Hbsi100 ; EIO to both master and slave + or al, PIC1_EOI_MASK ; create specific eoi mask for master + out PIC1_PORT0, al ; dismiss the interrupt + jmp short Hbsi200 ; IO delay + +Hbsi100: + mov al, OCW2_NON_SPECIFIC_EOI ; send non specific eoi to slave + out PIC2_PORT0, al + mov al, PIC2_EOI ; specific eoi to master for pic2 eoi + out PIC1_PORT0, al ; send irq2 specific eoi to master +Hbsi200: + PIC1DELAY + +HalpDismissIPIlevel: + + mov bl, HbsiIrql + mov dx, My+CpuPriortyLevel + mov al, _HalpIRQLtoCPL[ebx] + mov cl, Fs:PcIrql ; (cl) = Old Irql + out dx, ax + mov Fs:PcIrql, bl ; set new irql + mov edx, HbsiOldIrql ; get addr to store old irql + mov Fs:PcHal.pchHwIrql, bl + mov [edx], cl ; save old irql in the return variable + +ifdef IRQL_METRICS + lock inc HalRaiseIrqlCount +endif + + mov dx, My+CpuIntCmd +@@: in ax, dx + test eax, ICU_CMD_BUSY + jnz @B + mov al, ICU_CLR_INSERV1 ; clear this processor's in service bit + out dx, ax + + sti + mov eax, 1 ; return TRUE, interrupt dismissed + pop edx + pop ecx + stdRET _HalBeginSystemInterrupt +stdENDP _HalBeginSystemInterrupt + +;++ +;BOOLEAN +;HalEndSystemInterrupt( +; IN KIRQL Irql +; IN CCHAR Vector, +; ) +; +; +; +;Routine Description: +; +; This routine is used to complete any interrupt h/w processing and to +; lower the IRQL to the original value. +; +;Arguments: +; +; Irql - Supplies the IRQL to raise to +; +; Vector - Supplies the vector of the interrupt to be dismissed +; +; +;Return Value: +; +; FALSE - Interrupt is spurious and should be ignored +; +; TRUE - Interrupt successfully dismissed and Irql raised. +; +;-- +align dword + +cPublicProc _HalEndSystemInterrupt ,2 + movzx ecx, byte ptr [esp+8] + + ; change stack to be for KeLowerIrql + pop eax ;(eax) = ret addr + mov edx, [esp] ;(edx) = new irql + mov [esp], eax + mov [esp+4], edx + + sub cl, PRIMARY_VECTOR_BASE + cmp cl, 16 + jnb _KeLowerIrql@4 ;jump if not 8259 interrupt + pushfd + lea eax, _Halp8259Lock +HesiAquireLock: + cli + ACQUIRE_SPINLOCK eax, HesiSpin + mov eax, _i8259_IMR + btr _i8259_ISR, ecx + or eax, _i8259_ISR + SET_8259_MASK + lea eax, _Halp8259Lock + RELEASE_SPINLOCK eax + popfd + jmp _KeLowerIrql@4 + +HesiSpin: + popfd + pushfd + SPIN_ON_SPINLOCK eax, HesiAquireLock +stdENDP _HalEndSystemInterrupt + +;++ +;VOID +;HalDisableSystemInterrupt( +; IN CCHAR Vector, +; IN KIRQL Irql +; ) +; +; +; +;Routine Description: +; +; Disables a system interrupt. +; +;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 + enproc 9 +; + + push ebx + movzx ebx, byte ptr [esp+12] ;get IRQL + movzx ecx, _HalpIRQLtoVector[ebx] + or ecx, ecx + jz DisSysIntExit ;jump if not H/W interrupt + sub cl, PRIMARY_VECTOR_BASE + movzx eax, _HalpIRQLtoCPL[ebx] + cli + bts fs:PcIDR, eax ;disable int locally + jc DisSysIntExit ;jump if already disabled + push fs:PcIDR + push ICU_IMR0 ;write low interrupt masks + call WriteMyCpuReg + shr eax, 16 + out dx, ax ;shortcut to high interrupt masks + cmp cl, 16 ;is this an 8259 interrupt? + jnb DisSysIntExit ;jump if not + lea eax, _Halp8259Lock +DisSysIntAquire: + ACQUIRE_SPINLOCK eax, DisSysIntSpin + dec _Halp8259Counts[ecx] + jnz short DisSysIntRelease + mov eax, _i8259_ISR + bts _i8259_IMR, ecx + or eax, _i8259_IMR + SET_8259_MASK + + lea eax, _Halp8259Lock +DisSysIntRelease: + RELEASE_SPINLOCK eax + +DisSysIntExit: + exproc 9 + sti + pop ebx + stdRET _HalDisableSystemInterrupt + +DisSysIntSpin: + SPIN_ON_SPINLOCK eax, DisSysIntAquire + +stdENDP _HalDisableSystemInterrupt + +;++ +; +;BOOLEAN +;HalEnableSystemInterrupt( +; IN ULONG Vector, +; IN KIRQL Irql, +; IN KINTERRUPT_MODE InterruptMode +; ) +; +; +;Routine Description: +; +; Enables a system interrupt +; +;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 + enproc 0Ah + + push ebx + movzx ebx, byte ptr [esp+12] ;get IRQL + movzx ecx, _HalpIRQLtoVector[ebx] + or ecx, ecx + jz EnbSysIntError ;jump if not H/W interrupt + sub cl, PRIMARY_VECTOR_BASE + movzx eax, _HalpIRQLtoCPL[ebx] + cli + btr fs:PcIDR, eax ;enable int locally + jnc EnbSysIntExit ;jump if already enabled + push fs:PcIDR + push ICU_IMR0 + call WriteMyCpuReg ;write low interrupt masks + shr eax, 16 + out dx, ax ;shortcut to high interrupt masks + cmp cl, 16 ;is this an 8259 interrupt? + jnb EnbSysIntExit ;jump if not + lea eax, _Halp8259Lock +EnbSysIntAquire: + ACQUIRE_SPINLOCK eax, EnbSysIntSpin + inc _Halp8259Counts[ecx] + cmp _Halp8259Counts[ecx], 1 + jnz short EnbSysIntRelease + mov eax, _i8259_ISR + btr _i8259_IMR, ecx + or eax, _i8259_IMR + SET_8259_MASK + + lea eax, _Halp8259Lock +EnbSysIntRelease: + RELEASE_SPINLOCK eax + +EnbSysIntExit: + exproc 0Ah + sti + pop ebx + mov eax, 1 + stdRET _HalEnableSystemInterrupt + +EnbSysIntError: + if DBG + int 3 + endif + exproc 0Ah + sti + pop ebx + xor eax,eax + stdRET _HalEnableSystemInterrupt + +EnbSysIntSpin: + SPIN_ON_SPINLOCK eax, EnbSysIntAquire + +stdENDP _HalEnableSystemInterrupt + + +_TEXT ENDS + END diff --git a/private/ntos/nthals/halwyse7/i386/xxbiosa.asm b/private/ntos/nthals/halwyse7/i386/xxbiosa.asm new file mode 100644 index 000000000..bc0173a17 --- /dev/null +++ b/private/ntos/nthals/halwyse7/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/halwyse7/i386/xxbiosc.c b/private/ntos/nthals/halwyse7/i386/xxbiosc.c new file mode 100644 index 000000000..60cf92748 --- /dev/null +++ b/private/ntos/nthals/halwyse7/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/halwyse7/i386/xxdisp.c b/private/ntos/nthals/halwyse7/i386/xxdisp.c new file mode 100644 index 000000000..d48977df0 --- /dev/null +++ b/private/ntos/nthals/halwyse7/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/halwyse7/i386/xxflshbf.c b/private/ntos/nthals/halwyse7/i386/xxflshbf.c new file mode 100644 index 000000000..b054121cf --- /dev/null +++ b/private/ntos/nthals/halwyse7/i386/xxflshbf.c @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\xxflshbf.c" diff --git a/private/ntos/nthals/halwyse7/i386/xxioacc.asm b/private/ntos/nthals/halwyse7/i386/xxioacc.asm new file mode 100644 index 000000000..8445c3404 --- /dev/null +++ b/private/ntos/nthals/halwyse7/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/halwyse7/i386/xxkdsup.c b/private/ntos/nthals/halwyse7/i386/xxkdsup.c new file mode 100644 index 000000000..6e569b5ac --- /dev/null +++ b/private/ntos/nthals/halwyse7/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/halwyse7/i386/xxmemory.c b/private/ntos/nthals/halwyse7/i386/xxmemory.c new file mode 100644 index 000000000..920714540 --- /dev/null +++ b/private/ntos/nthals/halwyse7/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/halwyse7/i386/xxstubs.c b/private/ntos/nthals/halwyse7/i386/xxstubs.c new file mode 100644 index 000000000..8421fb30a --- /dev/null +++ b/private/ntos/nthals/halwyse7/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/halwyse7/i386/xxtime.c b/private/ntos/nthals/halwyse7/i386/xxtime.c new file mode 100644 index 000000000..92abb2aeb --- /dev/null +++ b/private/ntos/nthals/halwyse7/i386/xxtime.c @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\xxtime.c" |