summaryrefslogtreecommitdiffstats
path: root/private/ntos/nthals/haloli/i386
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/nthals/haloli/i386
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/ntos/nthals/haloli/i386')
-rw-r--r--private/ntos/nthals/haloli/i386/halnls.h5
-rw-r--r--private/ntos/nthals/haloli/i386/halp.h5
-rw-r--r--private/ntos/nthals/haloli/i386/ix8259.inc5
-rw-r--r--private/ntos/nthals/haloli/i386/ixbeep.asm5
-rw-r--r--private/ntos/nthals/haloli/i386/ixbusdat.c5
-rw-r--r--private/ntos/nthals/haloli/i386/ixcmos.asm5
-rw-r--r--private/ntos/nthals/haloli/i386/ixcmos.inc5
-rw-r--r--private/ntos/nthals/haloli/i386/ixdat.c5
-rw-r--r--private/ntos/nthals/haloli/i386/ixenvirv.c5
-rw-r--r--private/ntos/nthals/haloli/i386/ixfirm.c5
-rw-r--r--private/ntos/nthals/haloli/i386/ixhwsup.c5
-rw-r--r--private/ntos/nthals/haloli/i386/ixidle.asm5
-rw-r--r--private/ntos/nthals/haloli/i386/ixinfo.c5
-rw-r--r--private/ntos/nthals/haloli/i386/ixisa.h5
-rw-r--r--private/ntos/nthals/haloli/i386/ixisabus.c5
-rw-r--r--private/ntos/nthals/haloli/i386/ixisasup.c5
-rw-r--r--private/ntos/nthals/haloli/i386/ixkdcom.c5
-rw-r--r--private/ntos/nthals/haloli/i386/ixkdcom.h5
-rw-r--r--private/ntos/nthals/haloli/i386/ixnmi.c5
-rw-r--r--private/ntos/nthals/haloli/i386/ixpcibus.c5
-rw-r--r--private/ntos/nthals/haloli/i386/ixpciint.c5
-rw-r--r--private/ntos/nthals/haloli/i386/ixphwsup.c5
-rw-r--r--private/ntos/nthals/haloli/i386/ixreboot.c5
-rw-r--r--private/ntos/nthals/haloli/i386/ixstall.asm5
-rw-r--r--private/ntos/nthals/haloli/i386/ixswint.asm5
-rw-r--r--private/ntos/nthals/haloli/i386/ixthunk.c5
-rw-r--r--private/ntos/nthals/haloli/i386/ixusage.c5
-rw-r--r--private/ntos/nthals/haloli/i386/oliclock.asm1281
-rw-r--r--private/ntos/nthals/haloli/i386/olidtect.asm98
-rw-r--r--private/ntos/nthals/haloli/i386/oliipi.asm571
-rw-r--r--private/ntos/nthals/haloli/i386/oliirql.asm669
-rw-r--r--private/ntos/nthals/haloli/i386/olimapin.c168
-rw-r--r--private/ntos/nthals/haloli/i386/olimp.inc166
-rw-r--r--private/ntos/nthals/haloli/i386/oliproca.asm478
-rw-r--r--private/ntos/nthals/haloli/i386/olisproc.c581
-rw-r--r--private/ntos/nthals/haloli/i386/olisyint.asm386
-rw-r--r--private/ntos/nthals/haloli/i386/pcip.h5
-rw-r--r--private/ntos/nthals/haloli/i386/spspin.asm5
-rw-r--r--private/ntos/nthals/haloli/i386/xxbiosa.asm5
-rw-r--r--private/ntos/nthals/haloli/i386/xxbiosc.c5
-rw-r--r--private/ntos/nthals/haloli/i386/xxdisp.c5
-rw-r--r--private/ntos/nthals/haloli/i386/xxflshbf.c5
-rw-r--r--private/ntos/nthals/haloli/i386/xxhal.c5
-rw-r--r--private/ntos/nthals/haloli/i386/xxioacc.asm5
-rw-r--r--private/ntos/nthals/haloli/i386/xxkdsup.c5
-rw-r--r--private/ntos/nthals/haloli/i386/xxmemory.c5
-rw-r--r--private/ntos/nthals/haloli/i386/xxstubs.c5
-rw-r--r--private/ntos/nthals/haloli/i386/xxtime.c5
48 files changed, 4593 insertions, 0 deletions
diff --git a/private/ntos/nthals/haloli/i386/halnls.h b/private/ntos/nthals/haloli/i386/halnls.h
new file mode 100644
index 000000000..e829faba8
--- /dev/null
+++ b/private/ntos/nthals/haloli/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/haloli/i386/halp.h b/private/ntos/nthals/haloli/i386/halp.h
new file mode 100644
index 000000000..a9dbf1e13
--- /dev/null
+++ b/private/ntos/nthals/haloli/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/haloli/i386/ix8259.inc b/private/ntos/nthals/haloli/i386/ix8259.inc
new file mode 100644
index 000000000..b9e0a196a
--- /dev/null
+++ b/private/ntos/nthals/haloli/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/haloli/i386/ixbeep.asm b/private/ntos/nthals/haloli/i386/ixbeep.asm
new file mode 100644
index 000000000..f53bd3e58
--- /dev/null
+++ b/private/ntos/nthals/haloli/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/haloli/i386/ixbusdat.c b/private/ntos/nthals/haloli/i386/ixbusdat.c
new file mode 100644
index 000000000..a42039752
--- /dev/null
+++ b/private/ntos/nthals/haloli/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/haloli/i386/ixcmos.asm b/private/ntos/nthals/haloli/i386/ixcmos.asm
new file mode 100644
index 000000000..7f4e7393e
--- /dev/null
+++ b/private/ntos/nthals/haloli/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/haloli/i386/ixcmos.inc b/private/ntos/nthals/haloli/i386/ixcmos.inc
new file mode 100644
index 000000000..2fe289fb0
--- /dev/null
+++ b/private/ntos/nthals/haloli/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/haloli/i386/ixdat.c b/private/ntos/nthals/haloli/i386/ixdat.c
new file mode 100644
index 000000000..f6b0e34de
--- /dev/null
+++ b/private/ntos/nthals/haloli/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/haloli/i386/ixenvirv.c b/private/ntos/nthals/haloli/i386/ixenvirv.c
new file mode 100644
index 000000000..e194820ba
--- /dev/null
+++ b/private/ntos/nthals/haloli/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/haloli/i386/ixfirm.c b/private/ntos/nthals/haloli/i386/ixfirm.c
new file mode 100644
index 000000000..f666e405c
--- /dev/null
+++ b/private/ntos/nthals/haloli/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/haloli/i386/ixhwsup.c b/private/ntos/nthals/haloli/i386/ixhwsup.c
new file mode 100644
index 000000000..ea91dc8d0
--- /dev/null
+++ b/private/ntos/nthals/haloli/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/haloli/i386/ixidle.asm b/private/ntos/nthals/haloli/i386/ixidle.asm
new file mode 100644
index 000000000..9bdd670f3
--- /dev/null
+++ b/private/ntos/nthals/haloli/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/haloli/i386/ixinfo.c b/private/ntos/nthals/haloli/i386/ixinfo.c
new file mode 100644
index 000000000..7f211f7a9
--- /dev/null
+++ b/private/ntos/nthals/haloli/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/haloli/i386/ixisa.h b/private/ntos/nthals/haloli/i386/ixisa.h
new file mode 100644
index 000000000..f67b35f49
--- /dev/null
+++ b/private/ntos/nthals/haloli/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/haloli/i386/ixisabus.c b/private/ntos/nthals/haloli/i386/ixisabus.c
new file mode 100644
index 000000000..c1edfb067
--- /dev/null
+++ b/private/ntos/nthals/haloli/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/haloli/i386/ixisasup.c b/private/ntos/nthals/haloli/i386/ixisasup.c
new file mode 100644
index 000000000..58c426544
--- /dev/null
+++ b/private/ntos/nthals/haloli/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/haloli/i386/ixkdcom.c b/private/ntos/nthals/haloli/i386/ixkdcom.c
new file mode 100644
index 000000000..29bb8308e
--- /dev/null
+++ b/private/ntos/nthals/haloli/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/haloli/i386/ixkdcom.h b/private/ntos/nthals/haloli/i386/ixkdcom.h
new file mode 100644
index 000000000..22f1aac09
--- /dev/null
+++ b/private/ntos/nthals/haloli/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/haloli/i386/ixnmi.c b/private/ntos/nthals/haloli/i386/ixnmi.c
new file mode 100644
index 000000000..2ab99a52b
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/ixnmi.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixnmi.c"
diff --git a/private/ntos/nthals/haloli/i386/ixpcibus.c b/private/ntos/nthals/haloli/i386/ixpcibus.c
new file mode 100644
index 000000000..640cebfba
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/ixpcibus.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixpcibus.c"
diff --git a/private/ntos/nthals/haloli/i386/ixpciint.c b/private/ntos/nthals/haloli/i386/ixpciint.c
new file mode 100644
index 000000000..5243acee5
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/ixpciint.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixpciint.c"
diff --git a/private/ntos/nthals/haloli/i386/ixphwsup.c b/private/ntos/nthals/haloli/i386/ixphwsup.c
new file mode 100644
index 000000000..a1cdab598
--- /dev/null
+++ b/private/ntos/nthals/haloli/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/haloli/i386/ixreboot.c b/private/ntos/nthals/haloli/i386/ixreboot.c
new file mode 100644
index 000000000..15d7bd898
--- /dev/null
+++ b/private/ntos/nthals/haloli/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/haloli/i386/ixstall.asm b/private/ntos/nthals/haloli/i386/ixstall.asm
new file mode 100644
index 000000000..115c6c9c1
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/ixstall.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixstall.asm
diff --git a/private/ntos/nthals/haloli/i386/ixswint.asm b/private/ntos/nthals/haloli/i386/ixswint.asm
new file mode 100644
index 000000000..68b302dfe
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/ixswint.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixswint.asm
diff --git a/private/ntos/nthals/haloli/i386/ixthunk.c b/private/ntos/nthals/haloli/i386/ixthunk.c
new file mode 100644
index 000000000..6f15aad73
--- /dev/null
+++ b/private/ntos/nthals/haloli/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/haloli/i386/ixusage.c b/private/ntos/nthals/haloli/i386/ixusage.c
new file mode 100644
index 000000000..519ec31f3
--- /dev/null
+++ b/private/ntos/nthals/haloli/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/haloli/i386/oliclock.asm b/private/ntos/nthals/haloli/i386/oliclock.asm
new file mode 100644
index 000000000..58ce1a7ea
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/oliclock.asm
@@ -0,0 +1,1281 @@
+ title "Interval Clock Interrupt"
+;++
+;
+; Copyright (c) 1989 Microsoft Corporation
+;
+; Module Name:
+;
+; oliclock.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 LSX5030.
+;
+; John Vert (jvert) 11-Jul-1991
+; Moved from ke\i386 to hal\i386. Removed non-HAL stuff
+;
+; Bruno Sartirana (o-obruno) 3-Mar-92
+; Added support for the Olivetti LSX5030.
+;
+; 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.
+;
+;
+;--
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc
+include i386\ix8259.inc
+include i386\ixcmos.inc
+include i386\kimacro.inc
+include mac386.inc
+;LSX5030 start
+include i386\olimp.inc
+;LSX5030 end
+ .list
+
+ EXTRNP _DbgBreakPoint,0,IMPORT
+ extrn KiI8259MaskTable:DWORD
+ EXTRNP _KeUpdateSystemTime,0
+ EXTRNP _KeUpdateRunTime,1,IMPORT
+ EXTRNP _KeProfileInterrupt,1,IMPORT
+ EXTRNP Kei386EoiHelper,0,IMPORT
+ EXTRNP _HalEndSystemInterrupt,2
+ EXTRNP _HalBeginSystemInterrupt,3
+ EXTRNP _HalRequestIpi,1
+ EXTRNP _HalpAcquireCmosSpinLock ,0
+ EXTRNP _HalpReleaseCmosSpinLock ,0
+ EXTRNP _KeSetTimeIncrement,2,IMPORT
+ extrn _HalpProcessorPCR:DWORD
+ extrn _HalpSystemHardwareLock:DWORD
+ extrn _HalpFindFirstSetRight: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
+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
+;
+
+CMOS_CONTROL_PORT EQU 70h ; command port for cmos
+CMOS_DATA_PORT EQU 71h ; cmos data port
+D_INT032 EQU 8E00h ; access word for 386 ring 0 interrupt gate
+RTCIRQ EQU 8 ; IRQ number for RTC interrupt
+REGISTER_B_ENABLE_PERIODIC_INTERRUPT EQU 01000010B
+ ; RT/CMOS Register 'B' Init byte
+ ; Values for byte shown are
+ ; Bit 7 = Update inhibit
+ ; Bit 6 = Periodic interrupt enable
+ ; Bit 5 = Alarm interrupt disable
+ ; Bit 4 = Update interrupt disable
+ ; Bit 3 = Square wave disable
+ ; Bit 2 = BCD data format
+ ; Bit 1 = 24 hour time mode
+ ; Bit 0 = Daylight Savings disable
+
+REGISTER_B_DISABLE_PERIODIC_INTERRUPT EQU 00000010B
+
+;
+; RegisterAInitByte sets 8Hz clock rate, used during init to set up
+; KeStallExecutionProcessor, etc. (See RegASystemClockByte below.)
+;
+
+RegisterAInitByte EQU 00101101B ; RT/CMOS Register 'A' init byte
+ ; 32.768KHz Base divider rate
+ ; 8Hz int rate, period = 125.0ms
+PeriodInMicroSecond EQU 125000 ;
+
+CMOS_STATUS_BUSY EQU 80H ; Time update in progress
+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 8254 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
+;
+;
+; The default Interrupt interval is Interval = 15ms.
+;
+
+TIME_INCREMENT EQU 150000 ; 15ms
+ROLLOVER_COUNT EQU 15 * 1193
+
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+
+RegisterAProfileValue db 00101000B ; default interval = 3.90625 ms
+
+ProfileIntervalTable dd 1221 ; unit = 100 ns
+ dd 2441
+ dd 4883
+ dd 9766
+ dd 19531
+ dd 39063
+ dd 78125
+ dd 156250
+ dd 312500
+ dd 625000
+ dd 1250000
+ dd 2500000
+ dd 5000000
+ dd 5000000 OR 80000000H
+
+ProfileIntervalInitTable db 00100011B
+ db 00100100B
+ db 00100101B
+ db 00100110B
+ db 00100111B
+ db 00101000B
+ db 00101001B
+ db 00101010B
+ db 00101011B
+ db 00101100B
+ db 00101101B
+ db 00101110B
+ db 00101111B
+ db 00101111B
+
+;
+; The following array stores the per microsecond loop count for each
+; central processor.
+;
+
+ifndef NT_UP
+ public _HalpIpiClock
+_HalpIpiClock dd 0 ; Processors to IPI clock pulse to
+endif
+
+;
+; Holds the value of the eflags register before a cmos spinlock is
+; acquired (used in HalpAcquire/ReleaseCmosSpinLock().
+;
+_HalpHardwareLockFlags dd 0
+
+;
+; 8254 spinlock. This must be acquired before touching the 8254 chip.
+;
+ public _Halp8254Lock
+
+_Halp8254Lock dd 0
+
+;
+; PerfCounter value lock. locks access to the HalpPerfCounterLow/High vars.
+;
+
+_HalpPerfCounterLock dd 0
+
+
+HalpProfileInterval dd -1
+ public HalpPerfCounterLow
+ public HalpPerfCounterHigh
+HalpPerfCounterLow dd 0
+HalpPerfCounterHigh dd 0
+HalpProfilingStopped dd 1
+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 8254 timer1 counter 0
+; to generate an interrupt at every 15ms interval at 8259 irq0
+;
+; See the definition of TIME_INCREMENT and ROLLOVER_COUNT if clock rate
+; needs to be changed.
+;
+; Arguments:
+;
+; None
+;
+; Return Value:
+;
+; None.
+;
+;--
+cPublicProc _HalpInitializeClock,0
+
+ pushfd ; save caller's eflag
+ cli ; make sure interrupts are disabled
+
+;
+; Set clock rate
+;
+
+ mov al,COMMAND_8254_COUNTER0+COMMAND_8254_RW_16BIT+COMMAND_8254_MODE2
+ out TIMER1_CONTROL_PORT0, al ;program count mode of timer 0
+ IoDelay
+ mov ecx, ROLLOVER_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
+
+ popfd ; restore caller's eflag
+
+;
+; Fill in PCR value with TIME_INCREMENT
+;
+ mov edx, TIME_INCREMENT
+ stdCall _KeSetTimeIncrement, <edx, edx>
+
+ mov HalpPerfCounterInit, 1 ; Indicate performance counter
+ ; has been initialized.
+ 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.
+;
+; NOTE:The routine is called for each cpu after the
+; 'KiDispatcherLock' is acquired in ke\kernlini.c!KiInitializeKernel
+; So, global variables used here are safe, but global resources
+; like RTC are not (must be spinlocked).
+;--
+
+KiseInterruptCount equ [ebp-12] ; local variable
+
+cPublicProc _HalpInitializeStallExecution,1
+
+
+; LSX5030 start
+;+++
+;
+; WARNING o-obruno Mar-3-92 This routine can't be used for Px, x>0.
+;
+; Since on the LSX5030 only processor 0 can receive RT clock interrupts,
+; the other processors would hang in this routine. In order to calculate
+; the right per microsecond loop count for each processor, the 8254 timer
+; has to be used (To Be Implemented). The processors can have different
+; clock rates, so such a loop count must be calculated for each processor.
+; Here, temporarily, it is assumed that all the processors run at the same
+; speed, so the loop count of the first processor is used by all the others
+; as well.
+
+
+; LSX5030 end
+
+ movzx ecx, byte ptr [esp+4] ; Current processor number
+ cmp ecx, 0 ; if proc number = 0, ie master
+ jz short kise ; if z, it's master, do regular processing
+ mov ecx, _HalpProcessorPCR[0] ; PCR for P0
+ mov eax, [ecx].PcStallScaleFactor; get P0 scale factor
+ mov fs:PcStallScaleFactor, eax ; Px scale factor.
+ stdRET _HalpInitializeStallExecution
+kise:
+
+;
+; End of Hack
+;
+;---
+
+ push ebp ; save ebp
+ mov ebp, esp ; set up 12 bytes for local use
+ sub esp, 12
+
+ pushfd ; save caller's eflag
+
+;
+; Initialize Real Time Clock to interrupt us for every 125ms at
+; IRQ 8.
+;
+
+ cli ; make sure interrupts are disabled
+
+;
+; Get and save current 8259 masks
+;
+
+ xor eax,eax
+
+;
+; Assume there is no third and fourth PICs
+;
+; Get interrupt Mask on PIC2
+;
+
+ in al,PIC2_PORT1
+ shl eax, 8
+
+;
+; Get interrupt Mask on PIC1
+;
+
+ in al,PIC1_PORT1
+ push eax ; save the masks
+ mov eax, NOT (( 1 SHL PIC_SLAVE_IRQ) + (1 SHL RTCIRQ))
+ ; Mask all the irqs except irq 2 and 8
+ SET_8259_MASK ; Set 8259's int mask register
+
+;
+; Since RTC interrupt will come from IRQ 8, we need to
+; Save original irq 8 descriptor and set the descriptor to point to
+; our own handler.
+;
+
+ sidt fword ptr [ebp-8] ; get IDT address
+ mov edx, [ebp-6] ; (edx)->IDT
+
+ push dword ptr [edx+8*(RTCIRQ+PRIMARY_VECTOR_BASE)]
+ ; (TOS) = original desc of IRQ 8
+ push dword ptr [edx+8*(RTCIRQ+PRIMARY_VECTOR_BASE) + 4]
+ ; each descriptor has 8 bytes
+ push edx ; (TOS) -> IDT
+ mov eax, offset FLAT:RealTimeClockHandler
+ mov word ptr [edx+8*(RTCIRQ+PRIMARY_VECTOR_BASE)], ax
+ ; Lower half of handler addr
+ mov word ptr [edx+8*(RTCIRQ+PRIMARY_VECTOR_BASE)+2], KGDT_R0_CODE
+ ; set up selector
+ mov word ptr [edx+8*(RTCIRQ+PRIMARY_VECTOR_BASE)+4], D_INT032
+ ; 386 interrupt gate
+ shr eax, 16 ; (ax)=higher half of handler addr
+ mov word ptr [edx+8*(RTCIRQ+PRIMARY_VECTOR_BASE)+6], ax
+ mov dword ptr KiseinterruptCount, 0 ; set no interrupt yet
+
+ stdCall _HalpAcquireCmosSpinLock ; intr disabled
+
+ mov ax,(RegisterAInitByte SHL 8) OR 0AH ; Register A
+ CMOS_WRITE ; Initialize it
+ mov ax,(REGISTER_B_ENABLE_PERIODIC_INTERRUPT SHL 8) OR 0BH ; Register B
+ CMOS_WRITE ; Initialize it
+ mov al,0CH ; Register C
+ CMOS_READ ; Read to initialize
+ mov al,0DH ; Register D
+ CMOS_READ ; Read to initialize
+ mov dword ptr [KiseInterruptCount], 0
+
+ stdCall _HalpReleaseCmosSpinLock
+
+;
+; Now enable the interrupt and start the counter
+; (As a matter of fact, only IRQ8 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 real time clock interrupt and compute the
+; permicrosecond loopcount on receiving of the second real time
+; interrupt. This is because the first interrupt is generated
+; based on the previous real time tick interval.
+;
+
+RealTimeClockHandler:
+
+ inc dword ptr KiseInterruptCount ; increment interrupt count
+ cmp dword ptr KiseInterruptCount,1 ; Is this the first interrupt?
+ jnz short kise25 ; no, its the second go process it
+ pop eax ; get rid of original ret addr
+ push offset FLAT:kise10 ; set new return addr
+
+ stdCall _HalpAcquireCmosSpinLock ; intr disabled
+
+ mov ax,(RegisterAInitByte SHL 8) OR 0AH ; Register A
+ CMOS_WRITE ; Initialize it
+ mov ax,(REGISTER_B_ENABLE_PERIODIC_INTERRUPT SHL 8) OR 0BH ; Register B
+ CMOS_WRITE ; Initialize it
+ mov al,0CH ; Register C
+ CMOS_READ ; Read to initialize
+ mov al,0DH ; Register D
+ CMOS_READ ; Read to initialize
+ xor eax, eax ; reset loop counter
+
+ stdCall _HalpReleaseCmosSpinLock
+;
+; Dismiss the interrupt.
+;
+
+ 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
+
+ iretd
+
+kise25:
+
+;
+; ** temporary - check for incorrect KeStallExecutionProcessorLoopCount
+;
+
+ifdef DBG
+ cmp eax, 0
+ jnz short kise30
+ stdCall _DbgBreakPoint
+
+endif
+ ; never return
+;
+; ** End temporay code
+;
+
+kise30:
+ xor edx, edx ; (edx:eax) = divident
+ mov ecx, PeriodInMicroSecond; (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
+;
+; Reset return address to kexit
+;
+
+ pop eax ; discard original return address
+ push offset FLAT:kexit ; return to kexit
+
+ 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
+
+ and word ptr [esp+8], NOT 0200H ; Disable interrupt upon return
+ iretd
+
+kexit: ; Interrupts are disabled
+ pop edx ; (edx)->IDT
+ pop [edx+8*(RTCIRQ+PRIMARY_VECTOR_BASE)+4]
+ ; restore higher half of NMI desc
+ pop [edx+8*(RTCIRQ+PRIMARY_VECTOR_BASE)]
+ ; restore lower half of NMI desc
+
+ pop eax ; (eax) = origianl 8259 int masks
+ SET_8259_MASK
+
+ 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
+
+; DbgWrtP84 57h
+ mov eax, fs:PcStallScaleFactor ; get per microsecond
+
+ mul ecx ; (eax) = desired loop count
+
+ifdef DBG
+
+;
+; Make sure we the loopcount is less than 4G and is not equal to zero
+;
+
+ cmp edx, 0
+ jz short 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
+
+;
+; This function gets called on every processor so the hal can enable
+; a profile interrupt on each processor. The LSX5030 only support
+; profile on P0.
+;
+
+ cmp fs:PcHal.PcrNumber, 0
+ jnz short eip_exit
+
+ stdCall _HalpAcquireCmosSpinLock ; intr disabled
+
+;
+; Mark profiling as active
+;
+
+ mov dword ptr HalpProfilingStopped, 0
+
+;
+; Set the interrupt rate to what is actually needed.
+;
+
+
+ mov al, RegisterAProfileValue
+ shl ax, 8
+ mov al, 0AH ; Register A
+ CMOS_WRITE ; Initialize it
+ mov ax,(REGISTER_B_ENABLE_PERIODIC_INTERRUPT SHL 8) OR 0BH
+ ; Register B
+ CMOS_WRITE ; Initialize it
+ mov al,0CH ; Register C
+ CMOS_READ ; Read to initialize
+ mov al,0DH ; Register D
+ CMOS_READ ; Read to initialize
+
+ stdCall _HalpReleaseCmosSpinLock
+eip_exit:
+ stdRET _HalStartProfileInterrupt
+
+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
+
+ cmp fs:PcHal.PcrNumber, 0
+ jnz short dip_exit
+
+
+;
+; Turn off profiling hit computation and profile interrupt
+;
+
+ stdCall _HalpAcquireCmosSpinLock ; intr disabled
+
+ mov ax,(REGISTER_B_DISABLE_PERIODIC_INTERRUPT SHL 8) OR 0BH
+ ; Register B
+ CMOS_WRITE ; Initialize it
+ mov al,0CH ; Register C
+ CMOS_READ ; dismiss pending profiling interrupt
+ mov dword ptr HalpProfilingStopped, 1
+
+ stdCall _HalpReleaseCmosSpinLock
+dip_exit:
+ stdRET _HalStopProfileInterrupt
+
+stdENDP _HalStopProfileInterrupt
+
+;++
+; ULONG
+; HalSetProfileInterval (
+; ULONG Interval
+; );
+;
+; Routine Description:
+;
+; This procedure sets the interrupt rate (and thus the sampling
+; interval) for the profiling interrupt.
+;
+; 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.
+;
+; WARNING - This is HIGHLY machine specific code. Current code
+; works for UP machines and the LSX5030.
+;--
+
+cPublicProc _HalSetProfileInterval,1
+
+ mov edx, [esp+4] ; [edx] = interval in 100ns unit
+ and edx, 7FFFFFFFh ; Remove highest bit.
+ mov ecx, 0 ; index = 0
+Hspi00:
+ mov eax, ProfileIntervalTable[ecx * 4]
+ cmp edx, eax ; if request interval < suport interval
+ jbe short Hspi10 ; if be, find supported interval
+ inc ecx
+ jmp short Hspi00
+
+Hspi10:
+ and eax, 7FFFFFFFh ; remove highest bit from supported interval
+ push eax ; save interval value
+ mov al, ProfileIntervalInitTable[ecx]
+ mov RegisterAProfileValue, al
+ test dword ptr HalpProfilingStopped,-1
+ jnz Hspi90
+
+ stdCall _HalStartProfileInterrupt,<0> ; Re-start profile interrupt
+ ; with the new interval
+Hspi90: pop eax
+ stdRET _HalSetProfileInterval ; (eax) = return interval
+
+stdENDP _HalSetProfileInterval
+
+ 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
+ifndef NT_UP
+ lea eax, _Halp8254Lock
+ ACQUIRE_SPINLOCK eax, Kqpc198
+endif
+
+
+;
+; 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.
+
+ifndef NT_UP
+ lea eax, _Halp8254Lock
+ RELEASE_SPINLOCK eax
+endif
+
+;
+; Now enable interrupts such that if timer interrupt is pending, it can
+; be serviced and update the PerformanceCounter. Note that there could
+; be a long time between the sti and cli because ANY interrupt could come
+; in in between.
+;
+
+ popfd ; don't re-enable interrupts if
+ nop ; the caller had them off!
+ jmp $+2
+
+
+;
+; 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, ROLLOVER_COUNT
+ 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
+
+ifndef NT_UP
+Kqpc198: popfd
+ SPIN_ON_SPINLOCK eax,<Kqpc11>
+endif
+
+stdENDP _KeQueryPerformanceCounter
+
+
+;++
+;
+; VOID
+; HalCalibratePerformanceCounter (
+; IN volatile PLONG Number
+; )
+;
+; /*++
+;
+; Routine Description:
+;
+; This routine calibrates the performance counter value for a
+; multiprocessor system. The calibration can be done by zeroing
+; the current performance counter, or by calculating a per-processor
+; skewing between each processors counter.
+;
+; Arguments:
+;
+; Number - Supplies a pointer to count of the number of processors in
+; the configuration.
+;
+; Return Value:
+;
+; None.
+;--
+cPublicProc _HalCalibratePerformanceCounter,1
+ 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 OLI 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
+;
+
+Hci10:
+ push CLOCK_VECTOR
+ sub esp, 4 ; allocate space to save OldIrql
+
+; esp - OldIrql
+ stdCall _HalBeginSystemInterrupt,<CLOCK2_LEVEL,CLOCK_VECTOR,esp>
+ or al,al ; check for spurious interrupt
+ jz Hci100
+
+;
+; Update performance counter
+;
+
+ ;add HalpPerfCounterLow, ROLLOVER_COUNT ; update performace counter
+ ;adc HalpPerfCounterHigh, 0
+
+;
+; (esp) = OldIrql
+; (esp+4) = Vector
+; (esp+8) = base of trap frame
+; (ebp) = address of trap frame
+;
+
+; LSX5030 start
+ ;mov eax, _HalpIpiClock ; Emulate clock ticks to any processors?
+ ;or eax, eax
+ ;jz Hci90
+
+;
+; On the SystemPro we know the processor which needs an emulated clock tick.
+; Just set that processors bit and IPI him
+;
+
+;@@:
+ ;movzx ecx, _HalpFindFirstSetRight[eax] ; lookup first processor
+ ;btr eax, ecx
+ ;mov ecx, _HalpProcessorPCR[ecx*4] ; PCR of processor
+ ;mov [ecx].PcHal.PcrIpiClockTick, 1 ; Set internal IPI event
+ ;or eax, eax ; any other processors?
+ ;jnz @b ; yes, loop
+
+ ;push _HalpIpiClock ; Processors to IPI
+ ;call _HalRequestIpi ; IPI the processor
+ ;add esp, 4
+
+;Hci90:
+;
+; On the LSX5030 every processor receives the timer 1 counter 0 interrupts,
+; since such a timer is present on each CPU. Only processor 0 updates the
+; system time. All the processors execute KeUpdateRunTime (which is called
+; by KeUpdateSystemTime) in order to update the runtime of the current
+; thread, update the runtime of the current thread's process, and
+; decrement the current thread's quantum.
+;
+
+ movzx eax, fs:PcHal.PcrNumber ; (eax)= Processor number
+ or eax, eax
+ jnz @f
+;
+; Processor 0 updates the performance counter
+;
+
+ add HalpPerfCounterLow, ROLLOVER_COUNT ; update performace counter
+ adc HalpPerfCounterHigh, 0
+
+ mov eax, TIME_INCREMENT
+ jmp _KeUpdateSystemTime@0 ; if P0, jump to _KeUpdateSystemTime
+
+@@:
+ stdCall _KeUpdateRunTime,<dword ptr [esp]> ; if Px, x>0, call _KeUpdateRunTime
+
+ INTERRUPT_EXIT
+; LSX5030 end
+
+Hci100:
+ add esp, 8 ; spurious, no EndOfInterrupt
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi
+
+_HalpClockInterrupt endp
+
+ 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
+
+
+;
+; This is the RTC interrupt, so we have to clear the
+; interrupt flag on the RTC.
+;
+; clear interrupt flag on RTC by banging on the CMOS. On some systems this
+; doesn't work the first time we do it, so we do it twice. It is rumored that
+; some machines require more than this, but that hasn't been observed with NT.
+;
+; NOTE: THIS IS MACHINE SPECIFIC
+; for MP machines that utilize one global RTC chip, and a subset of
+; the CPUs (here,P0 must be one of them) accept an interrupt from
+; the RTC, only one CPU needs to ACK the RTC (P0 in this scheme).
+;
+
+ifndef NT_UP
+ cmp fs:PcHal.PcrNumber, 0 ; Only P0 ack RTC.
+ jne Hpi10
+endif
+
+Hpil01:
+ cli
+ lea eax, _HalpSystemHardwareLock
+ ACQUIRE_SPINLOCK eax, Hpil90
+
+ mov al,0CH ; Register C
+ CMOS_READ ; Read to initialize
+ mov al,0CH ; Register C
+ CMOS_READ ; Read to initialize
+if DBG
+Hpi00: test al, 80h
+ jz short Hpi05
+ mov al,0CH ; Register C
+ CMOS_READ ; Read to initialize
+ jmp short Hpi00
+Hpi05:
+endif ; DBG
+
+ lea eax, _HalpSystemHardwareLock
+ RELEASE_SPINLOCK eax
+
+Hpi10:
+
+
+;
+; (esp) - base of trap frame
+;
+
+ push PROFILE_VECTOR
+ sub esp, 4 ; allocate space to save OldIrql
+
+; esp - OldIrql
+
+ stdCall _HalBeginSystemInterrupt,<PROFILE_LEVEL,PROFILE_VECTOR,esp>
+ or al,al ; check for spurious interrupt
+ jz Hpi100
+;
+; (esp) = OldIrql
+; (esp+4) = H/W vector
+; (esp+8) = base of trap frame
+;
+
+;
+; Now check is any profiling stuff to do.
+;
+
+ cmp HalpProfilingStopped, dword ptr 1 ; Has profiling been stopped?
+ jz short Hpi90 ; if z, prof disenabled
+
+ stdCall _KeProfileInterrupt,<ebp>
+Hpi90: INTERRUPT_EXIT
+
+
+Hpi100:
+ add esp, 8 ; spurious, no EndOfInterrupt
+ SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi
+
+Hpil90:
+;
+; Even though intr gets enabled here, we shouldn't get another
+; intr on this channel, because we didn't eoi the interrupt yet.
+;
+ sti
+ SPIN_ON_SPINLOCK eax, <Hpil01>
+
+stdENDP _HalpProfileInterrupt
+
+;++
+;
+; 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/haloli/i386/olidtect.asm b/private/ntos/nthals/haloli/i386/olidtect.asm
new file mode 100644
index 000000000..736d71f70
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/olidtect.asm
@@ -0,0 +1,98 @@
+;++
+;
+;Module Name:
+;
+; olidtect.c
+;
+;Abstract:
+;
+; This modules implements the machine type detection.
+;
+;Author:
+;
+;
+;
+;Environment:
+;
+; Kernel mode only.
+;
+;Revision History:
+;
+;--
+.386p
+
+ include callconv.inc
+
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+;++
+; BOOLEAN
+; DetectOlivettiMp (
+; OUT PBOOLEAN IsConfiguredMp
+; );
+;
+; Routine Description:
+; Determines the type of system (specifically for eisa machines), by reading
+; the system board ID.
+;
+; Arguments:
+; IsConfiguredMp - If LSX5030/40/40E is detected, then this value is
+; set to TRUE if more than one CPU is found, else FALSE.
+; The effect is that on returning FALSE, the standard HAL
+; is used, whilst on returning TRUE, the LSX5030 HAL is used.
+;
+; Return Value:
+; TRUE (non-zero in eax): LSX5030/40/40E detected
+; FALSE (zero in eax): non-LSX5030 detected
+;
+;--
+cPublicProc _DetectOlivettiMp,1
+
+ ; 3 byte value is read from 0c80-0c82
+
+ mov edx, 0c80h
+ in al, dx
+ cmp al, 3dh ; Manufacturer Code - 1st byte
+ jne NotAnLSX5030
+ inc edx
+ in al, dx
+ cmp al, 89h ; Manufacturer Code - 2nd byte
+ jne NotAnLSX5030
+ inc edx
+ in al, dx
+ cmp al, 03h ; Product Number part 1
+ jne NotAnLSX5030
+ ;inc edx
+ ;in al, dx
+ ;and al, 0f8h ; 5-bit Product Number part 2
+ ;cmp al, 10h
+ ;jne NotAnLSX5030
+
+;
+; Detect Processor Type reading Product Number part 2
+; Mask out Id's different from Cxh and Dxh
+;
+ mov edx, 0c8bh
+ in al, dx
+ and al, 0e0h
+ cmp al, 0c0h
+ je AnLSX5030
+
+
+NotAnLSX5030:
+ mov eax, 0
+ stdRET _DetectOlivettiMp
+
+AnLSX5030:
+
+ mov edx, dword ptr [esp+4] ; get the address of IsConfiguredMp
+ mov byte ptr [edx], 1 ; *IsConfiguredMp = TRUE
+ mov eax, 1
+
+ stdRET _DetectOlivettiMp
+
+stdENDP _DetectOlivettiMp
+
+
+_TEXT ENDS
diff --git a/private/ntos/nthals/haloli/i386/oliipi.asm b/private/ntos/nthals/haloli/i386/oliipi.asm
new file mode 100644
index 000000000..2c2886242
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/oliipi.asm
@@ -0,0 +1,571 @@
+ title "Interprocessor Interrupt"
+;++
+;
+;Copyright (c) 1991 Microsoft Corporation
+;
+;Module Name:
+;
+; oliipi.asm
+;
+;Abstract:
+;
+; SystemPro IPI code.
+; Provides the HAL support for Interprocessor Interrupts for hte
+; MP SystemPro implementation.
+;
+;Author:
+;
+; Ken Reneris (kenr) 13-Jan-1992
+;
+;Revision History:
+;
+; Bruno Sartirana (o-obruno) 3-Mar-92
+; Added support for the Olivetti LSX5030.
+;--
+.386p
+ .xlist
+
+;
+; Include LSX5030 detection code
+;
+
+include i386\olidtect.asm
+
+;
+; Normal includes
+;
+
+include hal386.inc
+include callconv.inc
+include i386\kimacro.inc
+include i386\ix8259.inc
+;LSX5030 start
+include i386\olimp.inc
+ EXTRNP _HalpInitializeProcessor,1
+ extrn _IdtIpiVector:DWORD
+ extrn KiI8259MaskTable:DWORD
+;LSX5030 end
+
+ EXTRNP _KiCoprocessorError,0,IMPORT
+ EXTRNP Kei386EoiHelper,0,IMPORT
+ EXTRNP _HalBeginSystemInterrupt,3
+ EXTRNP _HalEndSystemInterrupt,2
+ EXTRNP _KiIpiServiceRoutine,2,IMPORT
+ EXTRNP _HalEnableSystemInterrupt,3
+ EXTRNP _HalpInitializePICs,0
+ EXTRNP _HalDisplayString,1
+ EXTRNP _HalEnableSystemInterrupt,3
+ EXTRNP _HalDisableSystemInterrupt,2
+ extrn _HalpActiveProcessors:DWORD
+
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+
+;LSX5030 start
+
+;ifdef HALOLI_DBG
+
+; for debug only
+
+public DbgDelay
+DbgDelay dd 20000000
+
+;endif
+
+; IPI IRQL decoding array
+
+public PcrIpiIrql
+PcrIpiIrql db 15
+ db 11
+ db 10
+ db 13
+
+
+;LSX5030 end
+
+;
+; Processor Control Ports
+;
+
+ public ProcessorControlPort, _HalpProcessorPCR, _HalpInitializedProcessors
+ProcessorControlPort dw PCR_P0 ; P0 Processor Control Port
+ dw PCR_P1 ; P1 Processor Control Port
+ dw PCR_P2 ; P2 Processor Control Port
+ dw PCR_P3 ; P3 Processor Control Port
+
+_HalpProcessorPCR dd MAXIMUM_PROCESSORS dup (?) ; PCR pointer for each processor
+
+_HalpInitializedProcessors dd 0
+
+;
+;InterruptVectorControl dw 0 ; P0 none for p0
+ ;dw ICP_P1 ; P1 Processor Control Port
+ ;dw ICP_P2 ; P2 Processor Control Port
+ ;dw ICP_P3 ; P3 Processor Control Port
+
+ public _HalpFindFirstSetRight
+_HalpFindFirstSetRight db 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
+
+
+ public _SystemType
+_SystemType dd 0
+
+;LSX5030 start
+BadHalString db 'HAL: LSX5030 HAL.DLL cannot be run on non LSX5030', cr, lf
+ db ' Replace the hal.dll with the correct hal', cr, lf
+ db ' System is HALTING *********', 0
+;LSX5030 end
+
+_DATA ends
+
+ page ,132
+ subttl "Post InterProcessor Interrupt"
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+
+;++
+;
+; VOID
+; HalInitializeProcessor(
+; ULONG Number
+; );
+;
+;Routine Description:
+;
+; Initialize hal pcr values for current processor (if any)
+; (called shortly after processor reaches kernel, before
+; HalInitSystem if P0)
+;
+; IPI's and KeReadir/LowerIrq's must be available once this function
+; returns. (IPI's are only used once two or more processors are
+; available)
+;
+; . Enable IPI interrupt (makes sense for P1, P2, ...).
+; . Save Processor Number in PCR.
+; . if (P0)
+; . determine what kind of system is it,
+; . if (NotSysProCompatible) Halt;
+; . InitializePICs.
+; . if (P1)
+; . program VECTOR_PORT to accept IPI at IRQ13.
+; . Save ProcesserControlPort (PCR) to PCRegion, per processor.
+; . Enable PINTs on CPU.
+;
+;Arguments:
+;
+; eax: processor number - Logical processor number of calling processor
+;
+;Return Value:
+;
+; None.
+;
+;--
+cPublicProc _HalInitializeProcessor,1
+
+;LSX5030 start
+
+ ;DBG_DISPLAY 0a0h
+
+ ; Initialize PcIDR in PCR to enable slave IRQ
+
+ mov fs:PcIDR, 0fffffffbh
+
+ movzx eax, byte ptr [esp+4] ; get processor number
+ mov fs:PcHal.PcrNumber, al ; Save processor # in PCR
+ lock bts _HalpActiveProcessors, eax
+ lock inc _HalpInitializedProcessors
+
+ mov ecx, fs:PcSelfPcr ; Flat address of this PCR
+ mov _HalpProcessorPCR[eax*4], ecx ; Save it away
+
+ or eax, eax
+ jnz hip20_Any ; jump if not P0
+
+
+ ; For P0 only, determine if this is an LSX5030 or not.
+
+ lea eax, _SystemType ; this just to honor the
+ ; DetectOlivettiMp call interface
+ stdCall _DetectOlivettiMp,<eax>
+ ;DBG_DISPLAY 0a1h
+ mov _SystemType, eax ; Remember system type
+ or eax, eax
+ jz _NotAnLSX5030 ; (SystemType == 0): Alien machine
+
+ ; P0
+
+ ; Initialized the stall scale factor to something other that 0,
+ ; just in case KeStallExecutionProcessor was called before
+ ; HalpInitializeStallExecution (when a DbgBreakPoint() is used
+ ; before HalpInitializeStallExecution() is called.
+ ;
+
+ mov dword ptr fs:PcStallScaleFactor, INITIAL_STALL_COUNT
+
+ ; load eax with the processor #
+
+ movzx eax, byte ptr fs:PcHal.PcrNumber ; get processor # from PCR
+
+
+hip20_Any:
+
+ ; Note: at this point eax must contain the processor number
+
+ mov dx, word ptr ProcessorControlPort[eax*2]
+ in al, dx ; get PCR status
+ and al, not PINT ; clear IPI pending bit
+ or al, IPI_EN ; enable IPI's
+ out dx, al ; store the new PCR status
+
+ mov fs:PcHal.PcrControlPort, dx ; Save port value
+
+ movzx eax, byte ptr [esp+4] ; get processor number
+ or eax, eax
+ jz hip30_Any ; jump if P0
+
+ ; init PICs, interval timer, stall scale factor...
+
+ ;DBG_DISPLAY 0a2h
+
+ stdCall _HalpInitializeProcessor,<eax>
+
+ ;DBG_DISPLAY 0a3h
+
+hip30_Any:
+
+
+;LSX5030 end
+
+ stdRET _HalInitializeProcessor
+
+;LSX5030 start
+
+_NotAnLSX5030:
+ stdCall _HalDisplayString,<offset BadHalString>
+ hlt
+
+;LSX5030 end
+
+
+stdENDP _HalInitializeProcessor
+
+
+;++
+;
+; VOID
+; HalRequestIpi(
+; IN ULONG Mask
+; );
+;
+;Routine Description:
+;
+; Requests an interprocessor interrupt
+;
+;Arguments:
+;
+; Mask - Supplies a mask of the processors to be interrupted
+;
+;Return Value:
+;
+; None.
+;
+;--
+cPublicProc _HalRequestIpi,1
+
+ movzx ecx, byte ptr [esp+4] ; (eax) = Processor bitmask
+
+ifdef DBG
+ or ecx, ecx ; must ipi somebody
+ jz short ipibad
+
+ movzx eax, byte ptr fs:PcHal.PcrNumber
+ bt ecx, eax ; cannot ipi yourself
+ jc short ipibad
+endif
+
+@@:
+ movzx eax, _HalpFindFirstSetRight[ecx] ; lookup first processor to ipi
+ btr ecx, eax
+ mov dx, ProcessorControlPort[eax*2]
+ in al, dx ; (al) = original content of PCP
+ or al, PINT ; generate Ipi on target
+ out dx, al
+ or ecx, ecx ; ipi any other processors?
+ jnz @b ; yes, loop
+
+ stdRET _HalRequestIpi
+
+ifdef DBG
+ipibad: int 3
+ stdRET _HalRequestIpi
+endif
+
+stdENDP _HalRequestIpi
+
+
+ page ,132
+ subttl "LSX5030 Inter-Processor Interrupt Handler"
+
+;LSX5030 start
+
+;++
+;
+; VOID
+; HalpIpiHandler (
+; );
+;
+; Routine Description:
+;
+; This routine is entered as the result of an interrupt generated by inter
+; processor communication.
+; The interrupt is dismissed.
+;
+; Arguments:
+;
+; None.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+ ENTER_DR_ASSIST Hixx_a, Hixx_t
+
+cPublicProc _HalpIpiHandler,0
+
+;
+; Save machine state in trap frame
+;
+
+ ENTER_INTERRUPT Hixx_a, Hixx_t ; (ebp) -> Trap frame
+
+;
+; Save previous IRQL
+;
+ mov eax, _IdtIpiVector
+ push eax ; Vector
+ sub esp, 4 ; space for OldIrql
+
+ ;DBG_DISPLAY 90h
+
+; Dismiss interrupt.
+;
+ mov dx, fs:PcHal.PcrControlPort
+
+ in al, dx
+
+;
+; Dismiss the interprocessor interrupt and call its handler
+;
+
+ and al, not PINT
+ out dx, al ; clear PINT
+
+
+ ;DBG_DISPLAY 91h
+
+ mov eax, _IdtIpiVector
+
+; esp - stack location of OldIrql
+; eax - vector
+; IPI_LEVEL - Irql
+
+ stdCall _HalBeginSystemInterrupt,<IPI_LEVEL,eax,esp>
+
+ ;DBG_DISPLAY 92h
+
+; Pass Null ExceptionFrame
+; Pass TrapFrame to Ipi service rtn
+ stdCall _KiIpiServiceRoutine ,<ebp,0>
+
+;
+; Do interrupt exit processing
+;
+ ;DBG_DISPLAY 9fh
+
+
+ INTERRUPT_EXIT ; will return to caller
+
+
+stdENDP _HalpIpiHandler
+
+
+ifdef HALOLI_DBG
+
+;++
+;
+; DbgDisplay (
+; IN UCHAR DisplayCode
+; )
+;
+; Description:
+;
+; This function writes 'DisplayCode' to the parallel port, where a LED
+; display can be plugged in to show such a code.
+; In order to allow the user to read the code on the LED display,
+; after writing, a delay is introduced.
+;
+; Arguments:
+; DisplayCode - Byte to write to the parallel port
+;
+; Return Value:
+; None.
+;
+;--
+
+public _DbgDisplay
+_DbgDisplay proc
+
+
+ push eax
+ push edx
+
+ ; signal something on the parallel port
+
+ mov dx, 378h
+ mov eax, [esp+12]
+ out dx, al
+
+ mov eax, DbgDelay
+
+@@:
+ dec eax
+ cmp eax, 0
+ jne @b
+ pop edx
+ pop eax
+
+
+ ret
+ _DbgDisplay endp
+
+endif ; HALOLI_DBG
+
+
+; ULONG
+; HalpGetIpiIrqNumber (
+; );
+;
+; Routine Description:
+;
+; This routine is entered during the phase 0 initialization of the
+; first processor. It determines the IRQ # for IPI's.
+; The IPI IRQ is stored in the PCR's by the LSX5030 configuration
+; utility.
+;
+; Arguments:
+;
+; None.
+;
+; Return Value:
+;
+; The IPI IRQ# in eax.
+;
+;--
+
+cPublicProc _HalpGetIpiIrqNumber,0
+
+
+ mov dx, word ptr ProcessorControlPort ; get 1st CPU slot #
+ in al, dx ; get PCR content
+
+ ; determine which IRQ for IPI has been set by the user
+
+ shr eax, 2 ; bits 0,1 encode the IPI IRQ
+ and eax, 3 ; zero all the bits but 0,1
+ movzx ecx, byte ptr PcrIpiIrql[eax] ; decode the IRQ
+ push ecx
+
+ ; edit the 8259 mask table to unmask IPI's from IPI_LEVEL-1 down
+
+ mov edx, 1
+ shl edx, cl
+ not edx ; mask with IPI IRQ# bit set to
+ ; 0
+; mov eax, IPI_LEVEL
+; sub eax, ecx
+ lea eax, KiI8259MaskTable ; start from the beginning
+; lea eax, KiI8259MaskTable[eax*4] ; start from
+ ; IPI_LEVEL - IPI_IRQ#
+ mov ecx, IPI_LEVEL
+
+NextEntry:
+ and [eax], edx
+ add eax, 4
+ dec ecx ; loop for IPI IRQ# times
+ jnz NextEntry
+
+ pop eax ; return IPI IRQ#
+
+ stdRET _HalpGetIpiIrqNumber
+stdENDP _HalpGetIpiIrqNumber
+
+
+ page ,132
+ subttl "Irq13 Interrupt Handler"
+;++
+;
+; VOID
+; HalpIrq13Handler (
+; );
+;
+; Routine Description:
+;
+; This routine is entered as the result of an interrupt generated by
+; coprocessor error,
+; This routine will lower irql to its original level, and finally invoke
+; coprocessor error handler. By doing this, the coprocessor
+; error will be handled at Irql 0 as it should be.
+;
+; Arguments:
+;
+; None.
+; Interrupt is dismissed
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+ ENTER_DR_ASSIST Hi13_a, Hi13_t
+
+cPublicProc _HalpIrq13Handler,0
+
+
+;
+; Save machine state in trap frame
+;
+
+ ENTER_INTERRUPT Hi13_a, Hi13_t ; (ebp) -> Trap frame
+
+;
+; Save previous IRQL
+;
+ push 13 + PRIMARY_VECTOR_BASE ; Vector
+ sub esp, 4 ; space for OldIrql
+;
+; Dismiss interrupt.
+
+; location for OldIrql
+; Vector
+; Irql
+ stdCall _HalBeginSystemInterrupt,<IPI_LEVEL,13+PRIMARY_VECTOR_BASE,esp>
+
+ stdCall _KiCoprocessorError ; call CoprocessorError handler
+
+;
+; Do interrupt exit processing
+;
+
+ INTERRUPT_EXIT ; will return to caller
+
+
+stdENDP _HalpIrq13Handler
+
+;LSX5030 end
+
+_TEXT ENDS
+ END
diff --git a/private/ntos/nthals/haloli/i386/oliirql.asm b/private/ntos/nthals/haloli/i386/oliirql.asm
new file mode 100644
index 000000000..b18871e22
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/oliirql.asm
@@ -0,0 +1,669 @@
+ title "Irql Processing"
+;++
+;
+; Copyright (c) 1989 Microsoft Corporation
+;
+; Module Name:
+;
+; oliirql.asm
+;
+; Abstract:
+;
+; SystemPro IRQL
+;
+; This module implements the code necessary to raise and lower i386
+; Irql and dispatch software interrupts with the 8259 PIC.
+;
+; 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
+;
+; Bruno Sartirana (o-obruno) 3-Mar-92
+; Added support for the Olivetti LSX5030.
+;--
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc
+include i386\ix8259.inc
+include i386\kimacro.inc
+;LSX5030 start
+include i386\olimp.inc
+;LSX5030 end
+
+ .list
+
+
+ EXTRNP _KeBugCheck,1,IMPORT
+
+ extrn _HalpApcInterrupt:NEAR
+ extrn _HalpDispatchInterrupt:NEAR
+ extrn _HalpApcInterrupt2ndEntry:NEAR
+ extrn _HalpDispatchInterrupt2ndEntry:NEAR
+; extrn _HalpSWNonPrimaryClockTick2ndEntry:NEAR
+ extrn _KiUnexpectedInterrupt:NEAR
+ extrn _HalpBusType:DWORD
+
+;
+; 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
+
+PIC_SLAVE_IRQ equ 2
+PIC1_BASE equ 30H
+PIC2_BASE equ 38H
+
+;
+; 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
+;
+; 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
+ dw 0 ; end of string
+
+PS2PICsInitializationString dw PIC1_PORT0
+
+;
+; Master PIC initialization command
+;
+
+ db ICW1_ICW + ICW1_LEVEL_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
+;
+; Slave PIC initialization command strings
+;
+
+ dw PIC2_PORT0
+ db ICW1_ICW + ICW1_LEVEL_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
+ dw 0 ; end of string
+
+
+ align 4
+
+;LSX5030 start
+
+ public KiI8259MaskTable
+KiI8259MaskTable label dword
+ dd 00000000000000000000000000000000B ; irql 0
+ dd 00000000000000000000000000000000B ; irql 1
+ dd 00000000000000000000000000000000B ; irql 2
+ dd 00000000000000000000000000000000B ; irql 3
+ dd 00000000000000000000000000000000B ; irql 4
+ dd 11111111110000000000000000000000B ; irql 5
+ dd 11111111111000000000000000000000B ; irql 6
+ dd 11111111111100000000000000000000B ; irql 7
+ dd 11111111111110000000000000000000B ; irql 8
+ dd 11111111111111000000000000000000B ; irql 9
+ dd 11111111111111100000000000000000B ; irql 10
+ dd 11111111111111110000000000000000B ; irql 11
+ dd 11111111111111111000000000000000B ; irql 12
+ dd 11111111111111111100000000000000B ; irql 13
+ dd 11111111111111111110000000000000B ; irql 14
+ dd 11111111111111111111000000000000B ; irql 15
+ dd 11111111111111111111100000000000B ; irql 16
+ dd 11111111111111111111110000000000B ; irql 17
+ dd 11111111111111111111111000000000B ; irql 18
+ dd 11111111111111111111111000000000B ; irql 19
+ dd 11111111111111111111111010000000B ; irql 20
+ dd 11111111111111111111111011000000B ; irql 21
+ dd 11111111111111111111111011100000B ; irql 22
+ dd 11111111111111111111111011110000B ; irql 23
+ dd 11111111111111111111111011111000B ; irql 24
+ dd 11111111111111111111111011111000B ; irql 25
+ dd 11111111111111111111111011111010B ; irql 26
+ dd 11111111111111111111111111111010B ; irql 27
+ dd 11111111111111111111111111111011B ; irql 28
+ dd 11111111111111111111111111111011B ; irql 29
+ dd 11111111111111111111111111111011B ; irql 30
+ dd 11111111111111111111111111111011B ; irql 31
+;LSX5030 end
+
+ align 4
+;
+; 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
+
+;
+; Use this table if there is a machine state frame on stack already
+;
+
+ public SWInterruptHandlerTable2
+SWInterruptHandlerTable2 label dword
+ dd offset FLAT:_KiUnexpectedInterrupt ; irql 0
+ dd offset FLAT:_HalpApcInterrupt2ndEntry ; irql 1
+ dd offset FLAT:_HalpDispatchInterrupt2ndEntry ; irql 2
+
+;
+; 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
+
+_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.
+; Also, a mask will be used to mask off all the lower lever 8259
+; interrupts.
+;
+; Arguments:
+;
+; (cl) = NewIrql - the new irql to be raised to
+;
+;
+; Return Value:
+;
+; OldIrql - the addr of a variable which old irql should be stored
+;
+;--
+
+; equates for accessing arguments
+; since eflags and iret addr are pushed into stack, all the arguments
+; offset by 8 bytes
+;
+
+cPublicFastCall KfRaiseIrql,1
+cPublicFpo 0,1
+
+ pushfd ; save caller's eflags
+
+ movzx eax, cl ; (eax) = NewIrql
+ mov cl, fs:PcIrql ; get current irql
+
+if DBG
+ cmp cl,al ; old > new?
+ jbe short Kri99 ; no, we're OK
+ push eax ; put new irql where we can find it
+ push ecx ; put old irql where we can find it
+ mov byte ptr fs:PcIrql,0 ; avoid recursive error
+ stdCall _KeBugCheck,<IRQL_NOT_GREATER_OR_EQUAL>
+Kri99:
+endif
+
+ cmp al,DISPATCH_LEVEL ; software level?
+ cli ; disable interrupt
+ mov fs:PcIrql, al ; set the new irql
+ jbe kri10 ; go skip setting 8259 hardware
+
+ mov eax, KiI8259MaskTable[eax*4]; get pic masks for the new irql
+ or eax, fs:PcIDR ; mask irqs which are disabled
+ SET_8259_MASK ; set 8259 masks
+
+kri10: popfd ; restore flags (including interrupts)
+
+ mov al, cl ; return old irql
+ fstRET KfRaiseIrql
+
+fstENDP KfRaiseIrql
+
+
+;++
+;
+; 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
+
+ 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 "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
+
+ pushfd ; save caller's eflags
+ movzx ecx, cl ; (ecx) = new irql value
+
+if DBG
+ cmp cl,fs:PcIrql
+ jbe short Kli99
+ push ecx ; 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>
+Kli99:
+endif
+
+ cmp byte ptr fs:PcIrql,DISPATCH_LEVEL ; Software level?
+ cli
+ jbe kli02 ; yes, go skip setting 8259 hw
+
+ mov eax, KiI8259MaskTable[ecx*4]; get pic masks for the new irql
+ or eax, fs:PcIDR ; mask irqs which are disabled
+ SET_8259_MASK ; set 8259 masks
+
+kli02: mov fs:PcIrql, cl ; set the new irql
+ mov eax, fs:PcIRR ; get SW interrupt request register
+ mov al, SWInterruptLookUpTable[eax] ; get the highest pending
+ ; software interrupt level
+ cmp al, cl ; Is highest SW int level > irql?
+ ja Kli10 ; yes, go simulate interrupt
+
+ popfd ; restore flags, including ints
+ fstRET KfLowerIrql
+
+; When we come to Kli10, (eax) = soft interrupt index
+
+Kli10:
+ call SWInterruptHandlerTable[eax*4] ; SIMULATE INTERRUPT
+ ; to the appropriate handler
+ popfd
+ fstRET KfLowerIrql
+
+fstENDP KfLowerIrql
+
+;++
+;
+; VOID
+; HalpEndSystemInterrupt
+; IN KIRQL NewIrql,
+; IN ULONG Vector
+; )
+;
+; 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:
+;
+; NewIrql - the new irql to be set.
+;
+; Vector - Vector number of the interrupt
+;
+; Note that esp+8 is the beginning of interrupt/trap frame and upon
+; entering to this routine the interrupts are off.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+HeiNewIrql equ [esp + 4]
+
+cPublicProc _HalEndSystemInterrupt,2
+
+ movzx ecx, byte ptr HeiNewIrql; get new irql value
+
+ cmp byte ptr fs:PcIrql, DISPATCH_LEVEL ; Software level?
+ jbe short Hei02 ; yes, go skip setting 8259 hw
+
+ mov eax, KiI8259MaskTable[ecx*4]; get pic masks for the new irql
+ or eax, fs:PcIDR ; mask irqs which are disabled
+ SET_8259_MASK ; set 8259 masks
+
+;
+; Unlike KeLowerIrql, we don't check if the the irql is lowered to
+; below IPI level and enable interrupt for second processor. This is because
+; the correct interrupt flag is already stored in the TsEflags of Trap frame.
+;
+
+Hei02: mov fs:PcIrql, cl ; set the new irql
+ mov eax, fs:PcIRR ; get SW interrupt request register
+ mov al, SWInterruptLookUpTable[eax] ; get the highest pending
+ ; software interrupt level
+ cmp al, cl ; Is highest SW int level > irql?
+ ja Hei10 ; yes, go simulate interrupt
+
+ stdRET _HalEndSystemInterrupt ; RETURN
+
+; When we come to Kli10, (eax) = soft interrupt index
+
+Hei10: add esp, 12
+ jmp SWInterruptHandlerTable2[eax*4] ; SIMULATE INTERRUPT
+ ; to the appropriate handler
+stdENDP _HalEndSystemInterrupt
+
+;++
+;
+; VOID
+; HalpEndSoftwareInterrupt
+; IN KIRQL NewIrql,
+; )
+;
+; Routine Description:
+;
+; This routine is used to lower IRQL from software interrupt
+; level 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:
+;
+; NewIrql - the new irql to be set.
+;
+; Note that esp+8 is the beginning of interrupt/trap frame and upon
+; entering to this routine the interrupts are off.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicProc _HalpEndSoftwareInterrupt,1
+cPublicFpo 1,0
+ mov ecx, [esp+4]
+ fstCall KfLowerIrql
+ stdRet _HalpEndSoftwareInterrupt
+stdENDP _HalpEndSoftwareInterrupt
+
+ 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 Oli-HAL
+ ;
+
+ mov ecx, HIGH_LEVEL
+ fstCall KfRaiseIrql
+ 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
+ mov al, 0FFH ; mask all 8259 irqs
+ out dx,al ; write mask to PIC
+ 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/haloli/i386/olimapin.c b/private/ntos/nthals/haloli/i386/olimapin.c
new file mode 100644
index 000000000..60d80553f
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/olimapin.c
@@ -0,0 +1,168 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ olimapin.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:
+
+ Bruno Sartirana (o-obruno) 4-Aug-1992
+ Added static interrupts assignement to the CPUs for LSX5030.
+
+--*/
+
+#include "halp.h"
+
+extern ULONG HalpInitializedProcessors;
+BOOLEAN HalpPciLockSettings; // make it build
+
+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 );
+
+ 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)(HIGHEST_LEVEL_FOR_8259 + PRIMARY_VECTOR_BASE - SystemVector);
+
+ //
+ // On LSX5030 any CPU can handle any interrupt.
+ //
+
+ *Affinity = 1 << BusInterruptLevel % HalpInitializedProcessors;
+ return SystemVector;
+}
+
diff --git a/private/ntos/nthals/haloli/i386/olimp.inc b/private/ntos/nthals/haloli/i386/olimp.inc
new file mode 100644
index 000000000..c75d8dca2
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/olimp.inc
@@ -0,0 +1,166 @@
+;++
+;
+; Copyright (c) 1989 Microsoft Corporation
+;
+; Module Name:
+;
+; olimp.inc
+;
+; Abstract:
+;
+; LSX5030 MP include file
+;
+; Author:
+;
+; Bruno Sartirana (o-obruno) 3-Mar-92
+;
+;--
+
+
+
+
+
+;*****************************
+; Olivetti LSX5030 defines
+;
+
+MAX_NUMBER_PROCESSORS_MASK equ 0fh ; Maximum number of processors
+ ; bitmask
+MAX_NUMBER_PROCESSORS equ 4 ; Maximum number of processors
+RESET_WO_EOI equ 00ah ; Reset with out EOI
+WarmResetVector equ 467h ; warm reset vector in ROM data segment
+
+
+; Multi-Processor Control and Configuration Registers I/O Locations:
+
+PCR_Px equ 0c6ah ; control register offset
+;LEV2_CACHE_REG equ 0c94h ; level 2 cache register offset
+
+P0_SLOT equ 00000h
+P1_SLOT equ 0c000h
+P2_SLOT equ 0d000h
+P3_SLOT equ 0e000h
+
+Px_SLOT_MASK equ 0f000h
+
+PCR_P0 equ P0_SLOT + PCR_Px
+PCR_P1 equ P1_SLOT + PCR_Px
+PCR_P2 equ P2_SLOT + PCR_Px
+PCR_P3 equ P3_SLOT + PCR_Px
+
+
+; WHO AM I Register
+
+PROC_ID_PORT equ 0c70h ; who am I
+
+
+; Multi-Processor Control Register Bit Definitions:
+
+IPI_EN equ 080h ; Inter-Processor Interrupt Enable bit
+PINT equ 040h ; Inter-Processor Interrupt bit
+IPI_IRQ10 equ 008h ; Inter-processor-interrupt vectors
+IPI_IRQ11 equ 004h
+IPI_IRQ13 equ 00ch
+IPI_IRQ15 equ 000h
+RESET equ 001h ; RESET processor bit (1-0 transition
+
+; Multi-Processor 2nd Level Cache Policy Registers Bit Definitions
+
+;LEV2_CACHE_ON equ 80h ; 2nd level cache enable bit
+
+
+;
+; 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.
+;
+
+
+PcrE struc
+ PcrControlPort dw 0 ; Processor's control port
+ PcrNumber db 0 ; Processor's number
+PcrE ends
+
+
+cr equ 0ah
+lf equ 0dh
+
+
+
+
+;
+; 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
+
+CMOS_GET_MP_STATUS equ 36h ; offset for MP status
+
+;
+; Macros to Read/Write/Reset CMOS
+;
+
+; CMOS_READ
+;
+; Description: This macro read a byte from the CMOS register specified
+; in (AL).
+;
+; Parameter: (AL) = address/register to read
+; Return: (AL) = data
+;
+
+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
+
+;++
+;
+; DBG_DISPLAY DisplayCode
+;
+; Macro Description:
+;
+; This macro writes 'DisplayCode' to the parallel port, where a LED
+; display can be plugged in to show such a code.
+; In order to allow the user to read the code on the LED display,
+; after writing, a delay is introduced.
+;
+; Arguments:
+; DisplayCode - Byte to write to the parallel port
+;
+;
+;--
+
+DBG_DISPLAY macro DisplayCode
+
+ifdef HALOLI_DBG
+
+ push eax
+ push edx
+
+ ; signal something on the parallel port
+
+ mov dx, 378h
+ mov al, DisplayCode
+ out dx, al
+
+ mov eax, DbgDelay
+
+@@:
+ dec eax
+ cmp eax, 0
+ jne @b
+ pop edx
+ pop eax
+
+endif ; HALOLI_DBG
+
+ endm
+
+
+;*****************************
+; end of list
diff --git a/private/ntos/nthals/haloli/i386/oliproca.asm b/private/ntos/nthals/haloli/i386/oliproca.asm
new file mode 100644
index 000000000..6e72e8efe
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/oliproca.asm
@@ -0,0 +1,478 @@
+ title "MP primitives for Compaq SystemPro"
+;++
+;
+;Copyright (c) 1991 Microsoft Corporation
+;
+;Module Name:
+;
+; oliproca.asm
+;
+;Abstract:
+;
+; SystemPro Start Next Processor assemble code
+;
+; This module along with mpspro.c implement the code to start
+; off the second processor on the Compaq SystemPro.
+;
+;Author:
+;
+; Ken Reneris (kenr) 12-Jan-1992
+;
+; Bruno Sartirana (o-obruno) 3-Mar-92
+; Added support for the Olivetti LSX5030.
+;
+;Revision History:
+;
+;--
+
+
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc
+include i386\kimacro.inc
+include mac386.inc
+;LSX5030 start
+include i386\ix8259.inc
+include i386\olimp.inc
+;LSX5030 end
+ .list
+
+ EXTRNP _HalpBuildTiledCR3,1
+ EXTRNP _HalpFreeTiledCR3,0
+
+ extrn _MppIDT:DWORD
+ extrn _MpLowStub:DWORD
+ extrn _MpLowStubPhysicalAddress:DWORD
+ extrn ProcessorControlPort:WORD
+;LSX5030 start
+ extrn _CpuLeft:DWORD
+ extrn _NextCpuToStart:DWORD
+ extrn DbgDelay:DWORD
+;LSX5030 end
+
+
+;
+; Internal defines and structures
+;
+
+PxParamBlock struc
+ SPx_flag dd ?
+ SPx_TiledCR3 dd ?
+ SPx_P0EBP dd ?
+ SPx_ControlPort dd ?
+ SPx_PB db processorstatelength dup (?)
+PxParamBlock 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
+ push ebp ; save ebp
+ mov ebp, esp ;
+
+ sub esp, size PxParamBlock ; Make room for local vars
+
+ DBG_DISPLAY 0f0h
+
+ push esi
+ push edi
+ push ebx
+
+ xor eax, eax
+ mov PxFrame.SPx_flag, eax
+
+ cmp _CpuLeft, eax
+ 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 eax, pLoaderBlock ; lookup processor # we are
+ mov eax, [eax].LpbPrcb ; starting
+ movzx eax, byte ptr [eax].PbNumber
+ movzx edx, ProcessorControlPort[eax*2] ; Get processor's control port
+ mov PxFrame.SPx_ControlPort, edx ; Pass it along
+
+ 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
+
+ mov eax, _MpLowStubPhysicalAddress
+ shl eax, 12 ; seg:0
+ add eax, size PxParamBlock
+ mov dword ptr [ebx], eax ; start Px here
+
+;LSX5030 start
+ mov eax, _NextCpuToStart
+ mov dx, word ptr ProcessorControlPort[eax*2]
+ in al, dx
+ or al, RESET ; assert RESET
+ out dx, al
+ and al, not RESET ; the 1-0 transition of PCR
+ ; reset bit resets the
+ ; processor
+ out dx, al ; reset processor
+;LSX5030 end
+
+@@:
+ cmp PxFrame.SPx_flag, 0 ; wait for Px to get it's
+ jz @b ; info
+
+ pop dword ptr [ebx] ; restore WarmResetVector
+
+ sti
+
+ stdCall _HalpFreeTiledCR3 ; free memory used for tiled
+ ; CR3
+
+;LSX5030 start
+ DBG_DISPLAY 0ffh
+
+ dec _CpuLeft ; one less
+ inc _NextCpuToStart ; next CPU # to start
+;LSX5030 end
+
+ mov eax, 1 ; return TRUE
+
+snp_exit:
+ DBG_DISPLAY 0feh
+ pop ebx
+ pop edi
+ pop esi
+ mov esp, ebp
+ pop ebp
+ stdRET _HalStartNextProcessor
+
+_HalStartNextProcessor endp
+
+
+_TEXT ends ; end 32 bit code
+
+
+_TEXT16 SEGMENT DWORD PUBLIC USE16 'CODE' ; start 16 bit code
+
+
+;++
+;
+; VOID
+; StartPx_RMStub
+;
+; Routine Description:
+;
+; When a new processor is started, it starts in real-mode and is
+; sent to a copy of this function which has been copied into low memory.
+; (below 1m and accessable from real-mode).
+;
+; Once CR0 has been set, this function jmp's to a StartPx_PMStub
+;
+; Arguments:
+; none
+;
+; Return Value:
+; does not return, jumps to StartPx_PMStub
+;
+;--
+cPublicProc StartPx_RMStub,0
+ cli
+
+ db 066h ; load the GDT
+ lgdt fword ptr cs:[SPx_PB.PsSpecialRegisters.SrGdtr]
+
+ db 066h ; load the IDT
+ lidt fword ptr cs:[SPx_PB.PsSpecialRegisters.SrIdtr]
+
+ mov eax, cs:[SPx_TiledCR3]
+ mov cr3, eax
+
+ mov ebp, dword ptr cs:[SPx_P0EBP]
+ mov ecx, dword ptr cs:[SPx_PB.PsContextFrame.CsSegDs]
+ mov ebx, dword ptr cs:[SPx_PB.PsSpecialRegisters.SrCr3]
+ mov eax, dword ptr cs:[SPx_PB.PsSpecialRegisters.SrCr0]
+
+ mov cr0, eax ; into prot mode
+
+ db 066h
+ 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
+
+ public _StartPx_PMStub
+_StartPx_PMStub proc
+
+ ; 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
+
+;LSX5030 start
+ mov eax, _NextCpuToStart
+ mov dx, word ptr ProcessorControlPort[eax*2]
+ in al, dx ; Get register
+ and al, not IPI_EN ; disable PINTs for now
+ out dx, al
+ ;and dx, Px_SLOT_MASK ; get processor slot (olibus)
+ ;or dx, LEV2_CACHE_REG ; calculate address of the 2nd
+ ; level cache policy register
+ ; for this processor
+ ;in al, dx ; Get register
+ ;and al, not LEV2_CACHE_ON ; turn cache off
+ ;or al, LEV2_CACHE_ON ; turn cache on
+ ;out dx, al
+ ;and dx, Px_SLOT_MASK ; get processor slot (olibus)
+ ;or dx, SLOT_CONFIG_REG_0 ; calculate address of
+ ; configuration register 0 for
+ ; this processor
+ ;in al, dx ; get register
+ ;and al, not INTERNAL_CACHE_ON ; turn internal cache off
+ ;or al, INTERNAL_CACHE_ON ; turn processor's internal
+ ; cache on
+ ;out dx, al
+
+ ;DBG_DISPLAY 0b0h
+
+; sti
+
+ inc [PxFrame.SPx_flag] ; Signal p0 that we are
+ ; done with its data
+ ;DBG_DISPLAY 0bfh
+
+;LSX5030 end
+
+ ; Set remaining registers
+ pop ebp
+ pop edi
+ pop edx
+ pop ebx
+ pop eax
+ ret ; Set eip
+
+_StartPx_PMStub endp
+
+;LSX5030 start
+;++
+;
+; ULONG
+; HalpGetNumberOfProcessors()
+;
+; Routine Description:
+;
+; This routine queries the CMOS to determine the number of processors
+; that can be started.
+; Also, it rearranges the ProcessorControlPort array to make it
+; non-sparse. This means that, eventually, ProcessorControlPort[n]
+; will contain the slot # of the processor n, where n=0,1,2,3.
+; For example, if the machine has two processors, one in slot 0 and
+; the other in slot 3, only the ProcessorControlPort array elements
+; #0 and #1 will be meaningful.
+;
+; Arguments:
+;
+; None.
+;
+; Return Value:
+;
+; The number of available processors in register eax.
+;
+;--
+
+cPublicProc _HalpGetNumberOfProcessors,0
+
+
+ push ebx
+ push ecx
+ push edx
+ mov al, CMOS_GET_MP_STATUS
+ CMOS_READ
+ mov ch, al ; al[7-4] = CPU card present bits
+ ; al[3-0] = CPU diagnostics passed bits
+ shr al, 4 ; al[3-0] = CPU card present bits
+ mov cl, al ; ch[3-0] = CPU card diag passed bits
+ ; cl[3-0] = CPU card present bits
+ and cl, ch ; CPUs actually available (bit mapped)
+
+ mov edx, 1 ; there's always the CPU0, so skip it
+ mov eax, 1 ; logical processor #
+NextCPU:
+ bt ecx, edx
+ jnc IncLoopCounter
+ mov bx, word ptr ProcessorControlPort[edx*2] ; get address of
+ ; PCP #edx
+ mov word ptr ProcessorControlPort[eax*2], bx ; set PCP address
+ ; for processor #eax
+ inc eax
+IncLoopCounter:
+ inc edx
+ cmp edx, MAX_NUMBER_PROCESSORS
+ jl NextCPU
+
+ pop edx
+ pop ecx
+ pop ebx
+
+ stdRET _HalpGetNumberOfProcessors
+
+stdENDP _HalpGetNumberOfProcessors
+
+;LSX5030 end
+
+_TEXT ends ; end 32 bit code
+ end
diff --git a/private/ntos/nthals/haloli/i386/olisproc.c b/private/ntos/nthals/haloli/i386/olisproc.c
new file mode 100644
index 000000000..1de78859f
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/olisproc.c
@@ -0,0 +1,581 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ olisproc.c
+
+Abstract:
+
+ SystemPro Start Next Processor c code.
+
+ This module implements the initialization of the system dependent
+ functions that define the Hardware Architecture Layer (HAL) for an
+ MP Compaq SystemPro
+
+Author:
+
+ Ken Reneris (kenr) 22-Jan-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Bruno Sartirana (o-obruno) 3-Mar-92
+ Added support for the Olivetti LSX5030.
+--*/
+
+#include "halp.h"
+
+UCHAR HalName[] = "Olivetti LSX5030 MP Hal";
+
+
+VOID
+HalpMapCR3 (
+ IN ULONG VirtAddress,
+ IN PVOID PhysicalAddress,
+ IN ULONG Length
+ );
+
+ULONG
+HalpBuildTiledCR3 (
+ IN PKPROCESSOR_STATE ProcessorState
+ );
+
+VOID
+HalpFreeTiledCR3 (
+ VOID
+ );
+
+//LSX5030 start
+
+
+ULONG
+HalpGetIpiIrqNumber();
+
+VOID
+HalpIpiHandler(
+ VOID
+ );
+
+ULONG
+HalpGetNumberOfProcessors();
+
+
+#ifdef HALOLI_DBG
+
+VOID
+DbgDisplay(
+ IN UCHAR Code
+ );
+# define DBG_DISPLAY(x) DbgDisplay(x)
+#else
+# define DBG_DISPLAY(x)
+#endif
+
+
+
+/***
+ * Olivetti LSX5030 varialbles and constants
+ */
+
+
+
+ULONG IpiVector; // Inter-processor interrupt vector
+ULONG IdtIpiVector; // Inter-processor interrupt vector # in
+ // the IDT
+ULONG HalpCpuCount; // total number of CPU's available
+ULONG CpuLeft; // number of CPU's not started yet
+ULONG NextCpuToStart = 1; // next CPU logical # to start
+
+
+// LSX5030 end
+
+
+
+#define LOW_MEMORY 0x000100000
+#define MAX_PT 8
+
+extern VOID __cdecl StartPx_PMStub(VOID);
+
+
+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.
+
+--*/
+{
+ PKPCR pPCR;
+ KIRQL CurrentIrql;
+
+
+ pPCR = KeGetPcr();
+
+ if (Phase == 0) {
+
+ //
+ // Only Processor 0 runs the phase 0 initializtion code
+ //
+
+ //DBG_DISPLAY(0x00);
+ MppIDT = HalpMapPhysicalMemory (0, 1);
+
+//LSX5030 start
+ IpiVector = HalpGetIpiIrqNumber();
+ IdtIpiVector = IpiVector + PRIMARY_VECTOR_BASE;
+
+ HalpCpuCount = HalpGetNumberOfProcessors();
+ CpuLeft = HalpCpuCount - 1;
+
+ if (CpuLeft == 0) {
+
+ //
+ // Only 1 CPU available
+ //
+
+ return TRUE;
+ }
+
+
+ //
+ // Register IPI handler
+ //
+
+ KiSetHandlerAddressToIDT(PRIMARY_VECTOR_BASE + IpiVector,
+ HalpIpiHandler);
+
+ //
+ // Enable inter-processor interrupts on CPU 0
+ //
+
+ HalEnableSystemInterrupt(PRIMARY_VECTOR_BASE + IpiVector,
+ IPI_LEVEL, 0);
+
+//LSX5030 end
+
+ //
+ // Allocate some low memory for processor bootup stub
+ //
+
+ MpLowStubPhysicalAddress = (PVOID)HalpAllocPhysicalMemory (LoaderBlock,
+ LOW_MEMORY, 1, FALSE);
+
+ if (!MpLowStubPhysicalAddress)
+ return TRUE;
+
+ MpLowStub = (PCHAR) HalpMapPhysicalMemory (MpLowStubPhysicalAddress, 1);
+
+ } else {
+
+ //
+ // Phase 1
+ //
+
+ //DBG_DISPLAY(0x10);
+ //
+ // Check to see if this is not processor 0
+ //
+
+ if (pPCR->Prcb->Number != 0) {
+
+ //DBG_DISPLAY(0x11);
+ //
+ // It is not processor 0. Mask the PICs and start the clock.
+ //
+
+ //
+ // Mask the PICs to reflect the current Irql
+ //
+
+ CurrentIrql = KeGetCurrentIrql();
+ CurrentIrql = KfRaiseIrql (CurrentIrql);
+
+
+ //
+ // Initialize the timer 1 counter 0
+ //
+
+ HalpInitializeClock();
+ //DBG_DISPLAY(0x12);
+
+ //
+ // Initialize the clock interrupt vector and enable the
+ // clock interrupt.
+ //
+
+ KiSetHandlerAddressToIDT(CLOCK_VECTOR, HalpClockInterrupt );
+ HalEnableSystemInterrupt(CLOCK_VECTOR, CLOCK2_LEVEL, Latched);
+ //DBG_DISPLAY(0x13);
+ }
+ }
+ 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 // The LSX5030 is an Eisa machine
+ );
+
+ RtlFreeUnicodeString (&UHalName);
+
+}
+
+
+BOOLEAN
+HalAllProcessorsStarted (
+ VOID
+ )
+{
+ return TRUE;
+}
+
+
+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
+
+
+--*/
+{
+#define GetPdeAddress(va) ((PHARDWARE_PTE)((((((ULONG)(va)) >> 22) & 0x3ff) << 2) + (PUCHAR)MpFreeCR3[0]))
+#define GetPteAddress(va) ((PHARDWARE_PTE)((((((ULONG)(va)) >> 12) & 0x3ff) << 2) + (PUCHAR)pPageTable))
+
+// bugbug kenr 27mar92 - fix physical memory usage!
+
+ MpFreeCR3[0] = ExAllocatePool (NonPagedPool, PAGE_SIZE);
+ RtlZeroMemory (MpFreeCR3[0], PAGE_SIZE);
+
+ //
+ // Map page for real mode stub (one page)
+ //
+ HalpMapCR3 ((ULONG) MpLowStubPhysicalAddress,
+ MpLowStubPhysicalAddress,
+ PAGE_SIZE);
+
+ //
+ // Map page for protect mode stub (one page)
+ //
+ HalpMapCR3 ((ULONG) &StartPx_PMStub, NULL, 0x1000);
+
+
+ //
+ // Map page(s) for processors GDT
+ //
+ HalpMapCR3 (ProcessorState->SpecialRegisters.Gdtr.Base, NULL,
+ ProcessorState->SpecialRegisters.Gdtr.Limit);
+
+
+ //
+ // Map page(s) for processors IDT
+ //
+ HalpMapCR3 (ProcessorState->SpecialRegisters.Idtr.Base, NULL,
+ ProcessorState->SpecialRegisters.Idtr.Limit);
+
+ return MmGetPhysicalAddress (MpFreeCR3[0]).LowPart;
+}
+
+
+VOID
+HalpMapCR3 (
+ IN ULONG VirtAddress,
+ IN PVOID PhysicalAddress,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+ Called to build a page table entry for the passed page directory.
+ Used to build a tiled page directory with real-mode & flat mode.
+
+Arguments:
+ VirtAddress - Current virtual address
+ PhysicalAddress - Optional. Physical address to be mapped to, if passed
+ as a NULL then the physical address of the passed
+ virtual address is assumed.
+ Length - number of bytes to map
+
+Return Value:
+ none.
+
+--*/
+{
+ ULONG i;
+ PHARDWARE_PTE PTE;
+ PVOID pPageTable;
+ PHYSICAL_ADDRESS pPhysicalPage;
+
+
+ while (Length) {
+ PTE = GetPdeAddress (VirtAddress);
+ if (!PTE->PageFrameNumber) {
+ pPageTable = ExAllocatePool (NonPagedPool, PAGE_SIZE);
+ RtlZeroMemory (pPageTable, PAGE_SIZE);
+
+ for (i=0; i<MAX_PT; i++) {
+ if (!MpFreeCR3[i]) {
+ MpFreeCR3[i] = pPageTable;
+ break;
+ }
+ }
+ ASSERT (i<MAX_PT);
+
+ pPhysicalPage = MmGetPhysicalAddress (pPageTable);
+ PTE->PageFrameNumber = (pPhysicalPage.LowPart >> PAGE_SHIFT);
+ PTE->Valid = 1;
+ PTE->Write = 1;
+ }
+
+ pPhysicalPage.LowPart = PTE->PageFrameNumber << PAGE_SHIFT;
+ pPhysicalPage.HighPart = 0;
+ pPageTable = MmMapIoSpace (pPhysicalPage, PAGE_SIZE, TRUE);
+
+ PTE = GetPteAddress (VirtAddress);
+
+ if (!PhysicalAddress) {
+ PhysicalAddress = (PVOID)MmGetPhysicalAddress ((PVOID)VirtAddress).LowPart;
+ }
+
+ PTE->PageFrameNumber = ((ULONG) PhysicalAddress >> PAGE_SHIFT);
+ PTE->Valid = 1;
+ PTE->Write = 1;
+
+ MmUnmapIoSpace (pPageTable, PAGE_SIZE);
+
+ PhysicalAddress = 0;
+ VirtAddress += PAGE_SIZE;
+ if (Length > PAGE_SIZE) {
+ Length -= PAGE_SIZE;
+ } else {
+ Length = 0;
+ }
+ }
+}
+
+
+
+VOID
+HalpFreeTiledCR3 (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Free's any memory allocated when the tiled page directory was built.
+
+Arguments:
+ none
+
+Return Value:
+ none
+--*/
+{
+ ULONG i;
+
+ for (i=0; MpFreeCR3[i]; i++) {
+ ExFreePool (MpFreeCR3[i]);
+ MpFreeCR3[i] = 0;
+ }
+}
+
+
+
+VOID
+HalpInitializeProcessor (
+ IN UCHAR ProcessorNumber
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes the current CPU's PIC's and clock.
+
+Arguments:
+
+ ProcessorNumber: current processor
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ KIRQL CurrentIrql;
+
+
+
+
+
+ //DBG_DISPLAY(0x70);
+
+// if (ProcessorNumber != '\0') {
+
+ //
+ // For processor 0 only initialize PICs and stall execution counter.
+ //
+
+ HalpInitializePICs();
+
+ //
+ // Now that the PICs are initialized, we need to mask them to
+ // reflect the current Irql
+ //
+
+ //DBG_DISPLAY(0x71);
+
+ CurrentIrql = KeGetCurrentIrql();
+ //DBG_DISPLAY(0x72);
+
+ KeRaiseIrql(CurrentIrql, &CurrentIrql);
+ //DBG_DISPLAY(0x73);
+
+ //
+ // Note that HalpInitializeClock MUST be called after
+ // HalpInitializeStallExecution, because
+ // HalpInitializeStallExecution reprograms the timer.
+ //
+
+ HalpInitializeStallExecution(ProcessorNumber);
+ //DBG_DISPLAY(0x74);
+
+ // }
+
+ //
+ // Register IPI handler
+ //
+
+ KiSetHandlerAddressToIDT(PRIMARY_VECTOR_BASE + IpiVector , HalpIpiHandler);
+ //DBG_DISPLAY(0x75);
+
+ //
+ // Enable inter-processor interrupts on this CPU
+ //
+
+ HalEnableSystemInterrupt(PRIMARY_VECTOR_BASE + IpiVector,
+ (KIRQL) IPI_LEVEL,
+ (KINTERRUPT_MODE) 0);
+
+ //DBG_DISPLAY(0x76);
+
+
+ return;
+}
+
+VOID
+HalpInitOtherBuses (
+ VOID
+ )
+{
+}
+
+
+
+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/haloli/i386/olisyint.asm b/private/ntos/nthals/haloli/i386/olisyint.asm
new file mode 100644
index 000000000..17476ff92
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/olisyint.asm
@@ -0,0 +1,386 @@
+;++
+;
+;Copyright (c) 1991 Microsoft Corporation
+;
+;Module Name:
+;
+; olisyint.asm
+;
+;Abstract:
+;
+; This module implements the HAL routines to enable/disable system
+; interrupts, for the MP systempro implementation
+;
+;Author:
+;
+; John Vert (jvert) 22-Jul-1991
+;
+;Environment:
+;
+; Kernel Mode
+;
+;Revision History:
+;
+; Bruno Sartirana (o-obruno) 3-Mar-92
+; Added support for the Olivetti LSX5030.
+;
+;--
+
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc
+include i386\ix8259.inc
+include i386\kimacro.inc
+include mac386.inc
+;LSX5030 start
+include i386\olimp.inc
+;LSX5030 end
+ .list
+
+ extrn KiI8259MaskTable:DWORD
+ EXTRNP _KeBugCheck,1,IMPORT
+
+;
+; 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
+;
+
+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
+;
+; 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:HalpDismissNormal ; 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:HalpDismissNormal ; irq 10
+ dd offset FLAT:HalpDismissNormal ; irq 11
+ dd offset FLAT:HalpDismissNormal ; irq 12
+ dd offset FLAT:HalpDismissNormal ; irq 13
+ dd offset FLAT:HalpDismissNormal ; irq 14
+ dd offset FLAT:HalpDismissNormal ; irq 15
+ dd offset FLAT:HalpDismissNormal ; irq 16
+ dd offset FLAT:HalpDismissNormal ; irq 17
+ dd offset FLAT:HalpDismissNormal ; irq 18
+ dd offset FLAT:HalpDismissNormal ; irq 19
+ dd offset FLAT:HalpDismissNormal ; irq 1A
+ dd offset FLAT:HalpDismissNormal ; irq 1B
+ dd offset FLAT:HalpDismissNormal ; irq 1C
+ dd offset FLAT:HalpDismissNormal ; irq 1D
+ dd offset FLAT:HalpDismissNormal ; irq 1E
+ dd offset FLAT:HalpDismissNormal ; irq 1F
+ dd offset FLAT:HalpDismissNormal ; irq 20
+ dd offset FLAT:HalpDismissNormal ; irq 21
+ dd offset FLAT:HalpDismissNormal ; irq 22
+ dd offset FLAT:HalpDismissNormal ; 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]
+HbsiVector equ byte ptr [esp+8]
+HbsiOldIrql equ dword ptr [esp+12]
+
+cPublicProc _HalBeginSystemInterrupt,3
+ movzx ebx,HbsiVector ; (ebx) = System Vector
+ sub ebx, PRIMARY_VECTOR_BASE ; (ebx) = 8259 IRQ #
+
+ cmp ebx, 24h ; Interrupt in table?
+ jnc hbsi00 ; no go handle
+ jmp HalpSpecialDismissTable[ebx*4]
+
+hbsi00:
+;
+; Interrupt is out of range. There's no EOI here since it wouldn't
+; have been out of range if it occured on either interrupt controller
+; which is known about.
+;
+ mov eax,0 ; return FALSE
+ stdRET _HalBeginSystemInterrupt
+
+HalpDismissIrq0f:
+;
+; Check to see if this is a spurious interrupt
+;
+ 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 short HalpDismissNormal ; 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
+ mov eax,0 ; return FALSE
+ stdRET _HalBeginSystemInterrupt
+
+HalpDismissIrq07:
+;
+; Check to see if this is a spurious interrupt
+;
+ 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 HalpDismissNormal ; No, so this is NOT a spurious int
+ mov eax, 0 ; return FALSE
+ stdRET _HalBeginSystemInterrupt
+
+HalpDismissNormal:
+;
+; Store OldIrql
+;
+ mov eax, HbsiOldIrql
+ movzx ecx, byte ptr fs:PcIrql
+ mov byte ptr [eax], cl
+
+;
+; Raise IRQL to requested level
+;
+ movzx eax, HbsiIrql ; (eax) = irql
+ ; (ebx) = IRQ #
+
+ mov fs:PcIrql, al ; set new Irql
+
+
+ mov eax, KiI8259MaskTable[eax*4] ; get 8259's masks
+ or eax, fs:PcIDR ; mask disabled irqs
+ SET_8259_MASK ; send mask to 8259s
+
+;
+; 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
+
+ sti
+ mov eax, 1 ; return TRUE, interrupt dismissed
+ stdRET _HalBeginSystemInterrupt
+stdENDP _HalBeginSystemInterrupt
+
+;++
+;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
+
+;
+
+ movzx ecx, byte ptr [esp+4] ; (ecx) = Vector
+ sub ecx, PRIMARY_VECTOR_BASE ; (ecx) = 8259 irq #
+ mov edx, 1
+ shl edx, cl ; (ebx) = bit in IMR to disable
+ cli
+ or fs:PcIDR, edx
+ xor eax, eax
+
+;
+; Get the current interrupt mask register from the 8259
+;
+ in al, PIC2_PORT1
+ shl eax, 8
+ in al, PIC1_PORT1
+;
+; Mask off the interrupt to be disabled
+;
+ or eax, edx
+;
+; Write the new interrupt mask register back to the 8259
+;
+ out PIC1_PORT1, al
+ shr eax, 8
+ out PIC2_PORT1, al
+ PIC2DELAY
+
+ sti
+ stdRET _HalDisableSystemInterrupt
+
+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
+
+ movzx ecx, byte ptr [esp+4] ; (ecx) = vector
+ sub ecx, PRIMARY_VECTOR_BASE
+ jc hes_error
+ cmp ecx, CLOCK2_LEVEL
+ jnc hes_error
+
+ mov eax, 1
+ shl eax, cl ; (ebx) = bit in IMR to enable
+ not eax
+
+ cli
+ and fs:PcIDR, eax
+
+;
+; Get the PIC masks for the current Irql
+;
+ movzx eax, byte ptr fs:PcIrql
+ mov eax, KiI8259MaskTable[eax*4]
+ or eax, fs:PcIDR
+;
+; Write the new interrupt mask register back to the 8259
+;
+ SET_8259_MASK
+
+ sti
+ mov eax, 1 ; return TRUE
+ stdRET _HalEnableSystemInterrupt
+
+hes_error:
+if DBG
+ int 3
+endif
+ xor eax, eax ; FALSE
+ stdRET _HalEnableSystemInterrupt
+
+stdENDP _HalEnableSystemInterrupt
+
+
+_TEXT ENDS
+ END
diff --git a/private/ntos/nthals/haloli/i386/pcip.h b/private/ntos/nthals/haloli/i386/pcip.h
new file mode 100644
index 000000000..476bab1e4
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/pcip.h
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\pcip.h"
diff --git a/private/ntos/nthals/haloli/i386/spspin.asm b/private/ntos/nthals/haloli/i386/spspin.asm
new file mode 100644
index 000000000..0d70c442f
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/spspin.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halsp
+; This is a cpp style symbolic link
+
+include ..\halsp\i386\spspin.asm
diff --git a/private/ntos/nthals/haloli/i386/xxbiosa.asm b/private/ntos/nthals/haloli/i386/xxbiosa.asm
new file mode 100644
index 000000000..bc0173a17
--- /dev/null
+++ b/private/ntos/nthals/haloli/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/haloli/i386/xxbiosc.c b/private/ntos/nthals/haloli/i386/xxbiosc.c
new file mode 100644
index 000000000..60cf92748
--- /dev/null
+++ b/private/ntos/nthals/haloli/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/haloli/i386/xxdisp.c b/private/ntos/nthals/haloli/i386/xxdisp.c
new file mode 100644
index 000000000..d48977df0
--- /dev/null
+++ b/private/ntos/nthals/haloli/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/haloli/i386/xxflshbf.c b/private/ntos/nthals/haloli/i386/xxflshbf.c
new file mode 100644
index 000000000..b054121cf
--- /dev/null
+++ b/private/ntos/nthals/haloli/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/haloli/i386/xxhal.c b/private/ntos/nthals/haloli/i386/xxhal.c
new file mode 100644
index 000000000..198d08346
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/xxhal.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxhal.c"
diff --git a/private/ntos/nthals/haloli/i386/xxioacc.asm b/private/ntos/nthals/haloli/i386/xxioacc.asm
new file mode 100644
index 000000000..8445c3404
--- /dev/null
+++ b/private/ntos/nthals/haloli/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/haloli/i386/xxkdsup.c b/private/ntos/nthals/haloli/i386/xxkdsup.c
new file mode 100644
index 000000000..6e569b5ac
--- /dev/null
+++ b/private/ntos/nthals/haloli/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/haloli/i386/xxmemory.c b/private/ntos/nthals/haloli/i386/xxmemory.c
new file mode 100644
index 000000000..920714540
--- /dev/null
+++ b/private/ntos/nthals/haloli/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/haloli/i386/xxstubs.c b/private/ntos/nthals/haloli/i386/xxstubs.c
new file mode 100644
index 000000000..8421fb30a
--- /dev/null
+++ b/private/ntos/nthals/haloli/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/haloli/i386/xxtime.c b/private/ntos/nthals/haloli/i386/xxtime.c
new file mode 100644
index 000000000..92abb2aeb
--- /dev/null
+++ b/private/ntos/nthals/haloli/i386/xxtime.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\xxtime.c"