From e611b132f9b8abe35b362e5870b74bce94a1e58e Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 16 May 2020 20:51:50 -0700 Subject: initial commit --- private/ntos/nthals/haloli/drivesup.c | 7 + private/ntos/nthals/haloli/hal.rc | 11 + private/ntos/nthals/haloli/hal.src | 7 + private/ntos/nthals/haloli/i386/halnls.h | 5 + private/ntos/nthals/haloli/i386/halp.h | 5 + private/ntos/nthals/haloli/i386/ix8259.inc | 5 + private/ntos/nthals/haloli/i386/ixbeep.asm | 5 + private/ntos/nthals/haloli/i386/ixbusdat.c | 5 + private/ntos/nthals/haloli/i386/ixcmos.asm | 5 + private/ntos/nthals/haloli/i386/ixcmos.inc | 5 + private/ntos/nthals/haloli/i386/ixdat.c | 5 + private/ntos/nthals/haloli/i386/ixenvirv.c | 5 + private/ntos/nthals/haloli/i386/ixfirm.c | 5 + private/ntos/nthals/haloli/i386/ixhwsup.c | 5 + private/ntos/nthals/haloli/i386/ixidle.asm | 5 + private/ntos/nthals/haloli/i386/ixinfo.c | 5 + private/ntos/nthals/haloli/i386/ixisa.h | 5 + private/ntos/nthals/haloli/i386/ixisabus.c | 5 + private/ntos/nthals/haloli/i386/ixisasup.c | 5 + private/ntos/nthals/haloli/i386/ixkdcom.c | 5 + private/ntos/nthals/haloli/i386/ixkdcom.h | 5 + private/ntos/nthals/haloli/i386/ixnmi.c | 5 + private/ntos/nthals/haloli/i386/ixpcibus.c | 5 + private/ntos/nthals/haloli/i386/ixpciint.c | 5 + private/ntos/nthals/haloli/i386/ixphwsup.c | 5 + private/ntos/nthals/haloli/i386/ixreboot.c | 5 + private/ntos/nthals/haloli/i386/ixstall.asm | 5 + private/ntos/nthals/haloli/i386/ixswint.asm | 5 + private/ntos/nthals/haloli/i386/ixthunk.c | 5 + private/ntos/nthals/haloli/i386/ixusage.c | 5 + private/ntos/nthals/haloli/i386/oliclock.asm | 1281 ++++++++++++++++++++++++++ private/ntos/nthals/haloli/i386/olidtect.asm | 98 ++ private/ntos/nthals/haloli/i386/oliipi.asm | 571 ++++++++++++ private/ntos/nthals/haloli/i386/oliirql.asm | 669 ++++++++++++++ private/ntos/nthals/haloli/i386/olimapin.c | 168 ++++ private/ntos/nthals/haloli/i386/olimp.inc | 166 ++++ private/ntos/nthals/haloli/i386/oliproca.asm | 478 ++++++++++ private/ntos/nthals/haloli/i386/olisproc.c | 581 ++++++++++++ private/ntos/nthals/haloli/i386/olisyint.asm | 386 ++++++++ private/ntos/nthals/haloli/i386/pcip.h | 5 + private/ntos/nthals/haloli/i386/spspin.asm | 5 + private/ntos/nthals/haloli/i386/xxbiosa.asm | 5 + private/ntos/nthals/haloli/i386/xxbiosc.c | 5 + private/ntos/nthals/haloli/i386/xxdisp.c | 5 + private/ntos/nthals/haloli/i386/xxflshbf.c | 5 + private/ntos/nthals/haloli/i386/xxhal.c | 5 + private/ntos/nthals/haloli/i386/xxioacc.asm | 5 + private/ntos/nthals/haloli/i386/xxkdsup.c | 5 + private/ntos/nthals/haloli/i386/xxmemory.c | 5 + private/ntos/nthals/haloli/i386/xxstubs.c | 5 + private/ntos/nthals/haloli/i386/xxtime.c | 5 + private/ntos/nthals/haloli/makefile | 6 + private/ntos/nthals/haloli/makefile.inc | 2 + private/ntos/nthals/haloli/sources | 96 ++ 54 files changed, 4722 insertions(+) create mode 100644 private/ntos/nthals/haloli/drivesup.c create mode 100644 private/ntos/nthals/haloli/hal.rc create mode 100644 private/ntos/nthals/haloli/hal.src create mode 100644 private/ntos/nthals/haloli/i386/halnls.h create mode 100644 private/ntos/nthals/haloli/i386/halp.h create mode 100644 private/ntos/nthals/haloli/i386/ix8259.inc create mode 100644 private/ntos/nthals/haloli/i386/ixbeep.asm create mode 100644 private/ntos/nthals/haloli/i386/ixbusdat.c create mode 100644 private/ntos/nthals/haloli/i386/ixcmos.asm create mode 100644 private/ntos/nthals/haloli/i386/ixcmos.inc create mode 100644 private/ntos/nthals/haloli/i386/ixdat.c create mode 100644 private/ntos/nthals/haloli/i386/ixenvirv.c create mode 100644 private/ntos/nthals/haloli/i386/ixfirm.c create mode 100644 private/ntos/nthals/haloli/i386/ixhwsup.c create mode 100644 private/ntos/nthals/haloli/i386/ixidle.asm create mode 100644 private/ntos/nthals/haloli/i386/ixinfo.c create mode 100644 private/ntos/nthals/haloli/i386/ixisa.h create mode 100644 private/ntos/nthals/haloli/i386/ixisabus.c create mode 100644 private/ntos/nthals/haloli/i386/ixisasup.c create mode 100644 private/ntos/nthals/haloli/i386/ixkdcom.c create mode 100644 private/ntos/nthals/haloli/i386/ixkdcom.h create mode 100644 private/ntos/nthals/haloli/i386/ixnmi.c create mode 100644 private/ntos/nthals/haloli/i386/ixpcibus.c create mode 100644 private/ntos/nthals/haloli/i386/ixpciint.c create mode 100644 private/ntos/nthals/haloli/i386/ixphwsup.c create mode 100644 private/ntos/nthals/haloli/i386/ixreboot.c create mode 100644 private/ntos/nthals/haloli/i386/ixstall.asm create mode 100644 private/ntos/nthals/haloli/i386/ixswint.asm create mode 100644 private/ntos/nthals/haloli/i386/ixthunk.c create mode 100644 private/ntos/nthals/haloli/i386/ixusage.c create mode 100644 private/ntos/nthals/haloli/i386/oliclock.asm create mode 100644 private/ntos/nthals/haloli/i386/olidtect.asm create mode 100644 private/ntos/nthals/haloli/i386/oliipi.asm create mode 100644 private/ntos/nthals/haloli/i386/oliirql.asm create mode 100644 private/ntos/nthals/haloli/i386/olimapin.c create mode 100644 private/ntos/nthals/haloli/i386/olimp.inc create mode 100644 private/ntos/nthals/haloli/i386/oliproca.asm create mode 100644 private/ntos/nthals/haloli/i386/olisproc.c create mode 100644 private/ntos/nthals/haloli/i386/olisyint.asm create mode 100644 private/ntos/nthals/haloli/i386/pcip.h create mode 100644 private/ntos/nthals/haloli/i386/spspin.asm create mode 100644 private/ntos/nthals/haloli/i386/xxbiosa.asm create mode 100644 private/ntos/nthals/haloli/i386/xxbiosc.c create mode 100644 private/ntos/nthals/haloli/i386/xxdisp.c create mode 100644 private/ntos/nthals/haloli/i386/xxflshbf.c create mode 100644 private/ntos/nthals/haloli/i386/xxhal.c create mode 100644 private/ntos/nthals/haloli/i386/xxioacc.asm create mode 100644 private/ntos/nthals/haloli/i386/xxkdsup.c create mode 100644 private/ntos/nthals/haloli/i386/xxmemory.c create mode 100644 private/ntos/nthals/haloli/i386/xxstubs.c create mode 100644 private/ntos/nthals/haloli/i386/xxtime.c create mode 100644 private/ntos/nthals/haloli/makefile create mode 100644 private/ntos/nthals/haloli/makefile.inc create mode 100644 private/ntos/nthals/haloli/sources (limited to 'private/ntos/nthals/haloli') diff --git a/private/ntos/nthals/haloli/drivesup.c b/private/ntos/nthals/haloli/drivesup.c new file mode 100644 index 000000000..38259e5f4 --- /dev/null +++ b/private/ntos/nthals/haloli/drivesup.c @@ -0,0 +1,7 @@ +// +// This file simply includes the common sources from the current HAL +// directory. When the structure is finally changed, the real file should +// be in this directory. +// + +#include "..\drivesup.c" diff --git a/private/ntos/nthals/haloli/hal.rc b/private/ntos/nthals/haloli/hal.rc new file mode 100644 index 000000000..3cba4ad89 --- /dev/null +++ b/private/ntos/nthals/haloli/hal.rc @@ -0,0 +1,11 @@ +#include + +#include + +#define VER_FILETYPE VFT_DLL +#define VER_FILESUBTYPE VFT2_UNKNOWN +#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL" +#define VER_INTERNALNAME_STR "hal.dll" + +#include "common.ver" + diff --git a/private/ntos/nthals/haloli/hal.src b/private/ntos/nthals/haloli/hal.src new file mode 100644 index 000000000..da778bb9d --- /dev/null +++ b/private/ntos/nthals/haloli/hal.src @@ -0,0 +1,7 @@ +// +// This file simply includes the common sources from the current HAL +// directory. When the structure is finally changed, the real file should +// be in this directory. +// + +#include "..\hal.src" 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, + + 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, +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, + 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, ; 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, + 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, +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, + +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, + ;DBG_DISPLAY 0a1h + mov _SystemType, eax ; Remember system type + or eax, eax + jz _NotAnLSX5030 ; (SystemType == 0): Alien machine + + ; P0 + + ; Initialized the stall scale factor to something other that 0, + ; just in case KeStallExecutionProcessor was called before + ; HalpInitializeStallExecution (when a DbgBreakPoint() is used + ; before HalpInitializeStallExecution() is called. + ; + + mov dword ptr fs:PcStallScaleFactor, INITIAL_STALL_COUNT + + ; load eax with the processor # + + movzx eax, byte ptr fs:PcHal.PcrNumber ; get processor # from PCR + + +hip20_Any: + + ; Note: at this point eax must contain the processor number + + mov dx, word ptr ProcessorControlPort[eax*2] + in al, dx ; get PCR status + and al, not PINT ; clear IPI pending bit + or al, IPI_EN ; enable IPI's + out dx, al ; store the new PCR status + + mov fs:PcHal.PcrControlPort, dx ; Save port value + + movzx eax, byte ptr [esp+4] ; get processor number + or eax, eax + jz hip30_Any ; jump if P0 + + ; init PICs, interval timer, stall scale factor... + + ;DBG_DISPLAY 0a2h + + stdCall _HalpInitializeProcessor, + + ;DBG_DISPLAY 0a3h + +hip30_Any: + + +;LSX5030 end + + stdRET _HalInitializeProcessor + +;LSX5030 start + +_NotAnLSX5030: + stdCall _HalDisplayString, + hlt + +;LSX5030 end + + +stdENDP _HalInitializeProcessor + + +;++ +; +; VOID +; HalRequestIpi( +; IN ULONG Mask +; ); +; +;Routine Description: +; +; Requests an interprocessor interrupt +; +;Arguments: +; +; Mask - Supplies a mask of the processors to be interrupted +; +;Return Value: +; +; None. +; +;-- +cPublicProc _HalRequestIpi,1 + + movzx ecx, byte ptr [esp+4] ; (eax) = Processor bitmask + +ifdef DBG + or ecx, ecx ; must ipi somebody + jz short ipibad + + movzx eax, byte ptr fs:PcHal.PcrNumber + bt ecx, eax ; cannot ipi yourself + jc short ipibad +endif + +@@: + movzx eax, _HalpFindFirstSetRight[ecx] ; lookup first processor to ipi + btr ecx, eax + mov dx, ProcessorControlPort[eax*2] + in al, dx ; (al) = original content of PCP + or al, PINT ; generate Ipi on target + out dx, al + or ecx, ecx ; ipi any other processors? + jnz @b ; yes, loop + + stdRET _HalRequestIpi + +ifdef DBG +ipibad: int 3 + stdRET _HalRequestIpi +endif + +stdENDP _HalRequestIpi + + + page ,132 + subttl "LSX5030 Inter-Processor Interrupt Handler" + +;LSX5030 start + +;++ +; +; VOID +; HalpIpiHandler ( +; ); +; +; Routine Description: +; +; This routine is entered as the result of an interrupt generated by inter +; processor communication. +; The interrupt is dismissed. +; +; Arguments: +; +; None. +; +; Return Value: +; +; None. +; +;-- + + ENTER_DR_ASSIST Hixx_a, Hixx_t + +cPublicProc _HalpIpiHandler,0 + +; +; Save machine state in trap frame +; + + ENTER_INTERRUPT Hixx_a, Hixx_t ; (ebp) -> Trap frame + +; +; Save previous IRQL +; + mov eax, _IdtIpiVector + push eax ; Vector + sub esp, 4 ; space for OldIrql + + ;DBG_DISPLAY 90h + +; Dismiss interrupt. +; + mov dx, fs:PcHal.PcrControlPort + + in al, dx + +; +; Dismiss the interprocessor interrupt and call its handler +; + + and al, not PINT + out dx, al ; clear PINT + + + ;DBG_DISPLAY 91h + + mov eax, _IdtIpiVector + +; esp - stack location of OldIrql +; eax - vector +; IPI_LEVEL - Irql + + stdCall _HalBeginSystemInterrupt, + + ;DBG_DISPLAY 92h + +; Pass Null ExceptionFrame +; Pass TrapFrame to Ipi service rtn + stdCall _KiIpiServiceRoutine , + +; +; Do interrupt exit processing +; + ;DBG_DISPLAY 9fh + + + INTERRUPT_EXIT ; will return to caller + + +stdENDP _HalpIpiHandler + + +ifdef HALOLI_DBG + +;++ +; +; DbgDisplay ( +; IN UCHAR DisplayCode +; ) +; +; Description: +; +; This function writes 'DisplayCode' to the parallel port, where a LED +; display can be plugged in to show such a code. +; In order to allow the user to read the code on the LED display, +; after writing, a delay is introduced. +; +; Arguments: +; DisplayCode - Byte to write to the parallel port +; +; Return Value: +; None. +; +;-- + +public _DbgDisplay +_DbgDisplay proc + + + push eax + push edx + + ; signal something on the parallel port + + mov dx, 378h + mov eax, [esp+12] + out dx, al + + mov eax, DbgDelay + +@@: + dec eax + cmp eax, 0 + jne @b + pop edx + pop eax + + + ret + _DbgDisplay endp + +endif ; HALOLI_DBG + + +; ULONG +; HalpGetIpiIrqNumber ( +; ); +; +; Routine Description: +; +; This routine is entered during the phase 0 initialization of the +; first processor. It determines the IRQ # for IPI's. +; The IPI IRQ is stored in the PCR's by the LSX5030 configuration +; utility. +; +; Arguments: +; +; None. +; +; Return Value: +; +; The IPI IRQ# in eax. +; +;-- + +cPublicProc _HalpGetIpiIrqNumber,0 + + + mov dx, word ptr ProcessorControlPort ; get 1st CPU slot # + in al, dx ; get PCR content + + ; determine which IRQ for IPI has been set by the user + + shr eax, 2 ; bits 0,1 encode the IPI IRQ + and eax, 3 ; zero all the bits but 0,1 + movzx ecx, byte ptr PcrIpiIrql[eax] ; decode the IRQ + push ecx + + ; edit the 8259 mask table to unmask IPI's from IPI_LEVEL-1 down + + mov edx, 1 + shl edx, cl + not edx ; mask with IPI IRQ# bit set to + ; 0 +; mov eax, IPI_LEVEL +; sub eax, ecx + lea eax, KiI8259MaskTable ; start from the beginning +; lea eax, KiI8259MaskTable[eax*4] ; start from + ; IPI_LEVEL - IPI_IRQ# + mov ecx, IPI_LEVEL + +NextEntry: + and [eax], edx + add eax, 4 + dec ecx ; loop for IPI IRQ# times + jnz NextEntry + + pop eax ; return IPI IRQ# + + stdRET _HalpGetIpiIrqNumber +stdENDP _HalpGetIpiIrqNumber + + + page ,132 + subttl "Irq13 Interrupt Handler" +;++ +; +; VOID +; HalpIrq13Handler ( +; ); +; +; Routine Description: +; +; This routine is entered as the result of an interrupt generated by +; coprocessor error, +; This routine will lower irql to its original level, and finally invoke +; coprocessor error handler. By doing this, the coprocessor +; error will be handled at Irql 0 as it should be. +; +; Arguments: +; +; None. +; Interrupt is dismissed +; +; Return Value: +; +; None. +; +;-- + + ENTER_DR_ASSIST Hi13_a, Hi13_t + +cPublicProc _HalpIrq13Handler,0 + + +; +; Save machine state in trap frame +; + + ENTER_INTERRUPT Hi13_a, Hi13_t ; (ebp) -> Trap frame + +; +; Save previous IRQL +; + push 13 + PRIMARY_VECTOR_BASE ; Vector + sub esp, 4 ; space for OldIrql +; +; Dismiss interrupt. + +; location for OldIrql +; Vector +; Irql + stdCall _HalBeginSystemInterrupt, + + stdCall _KiCoprocessorError ; call CoprocessorError handler + +; +; Do interrupt exit processing +; + + INTERRUPT_EXIT ; will return to caller + + +stdENDP _HalpIrq13Handler + +;LSX5030 end + +_TEXT ENDS + END 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, +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, +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, + + 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; iPageFrameNumber = (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" diff --git a/private/ntos/nthals/haloli/makefile b/private/ntos/nthals/haloli/makefile new file mode 100644 index 000000000..6ee4f43fa --- /dev/null +++ b/private/ntos/nthals/haloli/makefile @@ -0,0 +1,6 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/private/ntos/nthals/haloli/makefile.inc b/private/ntos/nthals/haloli/makefile.inc new file mode 100644 index 000000000..cb912aa51 --- /dev/null +++ b/private/ntos/nthals/haloli/makefile.inc @@ -0,0 +1,2 @@ +obj\i386\hal.def: hal.src + $(TARGET_CPP) /EP -Di386 $(C_DEFINES) hal.src > obj\i386\hal.def diff --git a/private/ntos/nthals/haloli/sources b/private/ntos/nthals/haloli/sources new file mode 100644 index 000000000..30c7ed5cf --- /dev/null +++ b/private/ntos/nthals/haloli/sources @@ -0,0 +1,96 @@ + +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + sources. + +Abstract: + + This file specifies the target component being built and the list of + sources files needed to build that component. Also specifies optional + compiler switches and libraries that are unique for the component being + built. + + +Author: + + Steve Wood (stevewo) 12-Apr-1990 + +NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl + +!ENDIF + +MAJORCOMP=ntos +MINORCOMP=hal + +TARGETNAME=haloli +TARGETPATH=\nt\public\sdk\lib + +!IF $(386) + +TARGETTYPE=HAL +NT_UP=0 + +!ELSE + +TARGETTYPE=DRIVER + +!ENDIF + +INCLUDES=..\..\inc;..\..\ke;..\..\io + +SOURCES= + +i386_SOURCES=hal.rc \ + drivesup.c \ + bushnd.c \ + rangesup.c \ + i386\ixbeep.asm \ + i386\ixbusdat.c \ + i386\ixdat.c \ + i386\ixisabus.c \ + i386\ixcmos.asm \ + i386\ixenvirv.c \ + i386\ixfirm.c \ + i386\ixhwsup.c \ + i386\ixidle.asm \ + i386\ixinfo.c \ + i386\ixisasup.c \ + i386\ixkdcom.c \ + i386\ixnmi.c \ + i386\ixphwsup.c \ + i386\ixswint.asm \ + i386\ixthunk.c \ + i386\ixreboot.c \ + i386\ixusage.c \ + i386\xxbiosa.asm \ + i386\xxbiosc.c \ + i386\xxdisp.c \ + i386\xxhal.c \ + i386\xxioacc.asm \ + i386\xxkdsup.c \ + i386\xxmemory.c \ + i386\xxstubs.c \ + i386\xxtime.c \ + i386\spspin.asm \ + i386\oliclock.asm \ + i386\oliirql.asm \ + i386\oliipi.asm \ + i386\olisyint.asm \ + i386\olimapin.c \ + i386\olisproc.c \ + i386\oliproca.asm + + +DLLDEF=obj\*\hal.def + +MSC_WARNING_LEVEL=/W3 /WX + +!IF $(386) + +NTTARGETFILES=$(TARGETPATH)\i386\haloli.lib + +!ENDIF -- cgit v1.2.3