summaryrefslogtreecommitdiffstats
path: root/private/ntos/nthals/halmca
diff options
context:
space:
mode:
Diffstat (limited to 'private/ntos/nthals/halmca')
-rw-r--r--private/ntos/nthals/halmca/drivesup.c7
-rw-r--r--private/ntos/nthals/halmca/hal.rc11
-rw-r--r--private/ntos/nthals/halmca/hal.src7
-rw-r--r--private/ntos/nthals/halmca/i386/halnls.h5
-rw-r--r--private/ntos/nthals/halmca/i386/halp.h5
-rw-r--r--private/ntos/nthals/halmca/i386/ix8259.inc5
-rw-r--r--private/ntos/nthals/halmca/i386/ixbeep.asm5
-rw-r--r--private/ntos/nthals/halmca/i386/ixbusdat.c5
-rw-r--r--private/ntos/nthals/halmca/i386/ixclock.asm5
-rw-r--r--private/ntos/nthals/halmca/i386/ixcmos.asm5
-rw-r--r--private/ntos/nthals/halmca/i386/ixcmos.inc5
-rw-r--r--private/ntos/nthals/halmca/i386/ixdat.c5
-rw-r--r--private/ntos/nthals/halmca/i386/ixenvirv.c5
-rw-r--r--private/ntos/nthals/halmca/i386/ixfirm.c5
-rw-r--r--private/ntos/nthals/halmca/i386/ixhwsup.c5
-rw-r--r--private/ntos/nthals/halmca/i386/ixidle.asm5
-rw-r--r--private/ntos/nthals/halmca/i386/ixinfo.c5
-rw-r--r--private/ntos/nthals/halmca/i386/ixipi.asm5
-rw-r--r--private/ntos/nthals/halmca/i386/ixisa.h5
-rw-r--r--private/ntos/nthals/halmca/i386/ixisabus.c5
-rw-r--r--private/ntos/nthals/halmca/i386/ixisasup.c5
-rw-r--r--private/ntos/nthals/halmca/i386/ixkdcom.c5
-rw-r--r--private/ntos/nthals/halmca/i386/ixkdcom.h5
-rw-r--r--private/ntos/nthals/halmca/i386/ixmca.h113
-rw-r--r--private/ntos/nthals/halmca/i386/ixmcabus.c117
-rw-r--r--private/ntos/nthals/halmca/i386/ixmcasup.c1344
-rw-r--r--private/ntos/nthals/halmca/i386/ixnmi.c5
-rw-r--r--private/ntos/nthals/halmca/i386/ixpcibrd.c5
-rw-r--r--private/ntos/nthals/halmca/i386/ixpcibus.c5
-rw-r--r--private/ntos/nthals/halmca/i386/ixpciint.c5
-rw-r--r--private/ntos/nthals/halmca/i386/ixphwsup.c5
-rw-r--r--private/ntos/nthals/halmca/i386/ixproc.c163
-rw-r--r--private/ntos/nthals/halmca/i386/ixprofil.asm5
-rw-r--r--private/ntos/nthals/halmca/i386/ixreboot.c5
-rw-r--r--private/ntos/nthals/halmca/i386/ixstall.asm5
-rw-r--r--private/ntos/nthals/halmca/i386/ixswint.asm5
-rw-r--r--private/ntos/nthals/halmca/i386/ixsysbus.c5
-rw-r--r--private/ntos/nthals/halmca/i386/ixthunk.c5
-rw-r--r--private/ntos/nthals/halmca/i386/ixusage.c5
-rw-r--r--private/ntos/nthals/halmca/i386/mcirql.asm1121
-rw-r--r--private/ntos/nthals/halmca/i386/mcsysint.asm385
-rw-r--r--private/ntos/nthals/halmca/i386/pcip.h5
-rw-r--r--private/ntos/nthals/halmca/i386/xxbiosa.asm5
-rw-r--r--private/ntos/nthals/halmca/i386/xxbiosc.c5
-rw-r--r--private/ntos/nthals/halmca/i386/xxdisp.c5
-rw-r--r--private/ntos/nthals/halmca/i386/xxflshbf.c5
-rw-r--r--private/ntos/nthals/halmca/i386/xxhal.c5
-rw-r--r--private/ntos/nthals/halmca/i386/xxioacc.asm5
-rw-r--r--private/ntos/nthals/halmca/i386/xxkdsup.c5
-rw-r--r--private/ntos/nthals/halmca/i386/xxmemory.c5
-rw-r--r--private/ntos/nthals/halmca/i386/xxstubs.c5
-rw-r--r--private/ntos/nthals/halmca/i386/xxtime.c5
-rw-r--r--private/ntos/nthals/halmca/makefile6
-rw-r--r--private/ntos/nthals/halmca/makefile.inc2
-rw-r--r--private/ntos/nthals/halmca/sources100
55 files changed, 3591 insertions, 0 deletions
diff --git a/private/ntos/nthals/halmca/drivesup.c b/private/ntos/nthals/halmca/drivesup.c
new file mode 100644
index 000000000..38259e5f4
--- /dev/null
+++ b/private/ntos/nthals/halmca/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/halmca/hal.rc b/private/ntos/nthals/halmca/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/halmca/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#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/halmca/hal.src b/private/ntos/nthals/halmca/hal.src
new file mode 100644
index 000000000..da778bb9d
--- /dev/null
+++ b/private/ntos/nthals/halmca/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/halmca/i386/halnls.h b/private/ntos/nthals/halmca/i386/halnls.h
new file mode 100644
index 000000000..e829faba8
--- /dev/null
+++ b/private/ntos/nthals/halmca/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/halmca/i386/halp.h b/private/ntos/nthals/halmca/i386/halp.h
new file mode 100644
index 000000000..a9dbf1e13
--- /dev/null
+++ b/private/ntos/nthals/halmca/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/halmca/i386/ix8259.inc b/private/ntos/nthals/halmca/i386/ix8259.inc
new file mode 100644
index 000000000..b9e0a196a
--- /dev/null
+++ b/private/ntos/nthals/halmca/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/halmca/i386/ixbeep.asm b/private/ntos/nthals/halmca/i386/ixbeep.asm
new file mode 100644
index 000000000..f53bd3e58
--- /dev/null
+++ b/private/ntos/nthals/halmca/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/halmca/i386/ixbusdat.c b/private/ntos/nthals/halmca/i386/ixbusdat.c
new file mode 100644
index 000000000..a42039752
--- /dev/null
+++ b/private/ntos/nthals/halmca/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/halmca/i386/ixclock.asm b/private/ntos/nthals/halmca/i386/ixclock.asm
new file mode 100644
index 000000000..fa1155436
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/ixclock.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixclock.asm
diff --git a/private/ntos/nthals/halmca/i386/ixcmos.asm b/private/ntos/nthals/halmca/i386/ixcmos.asm
new file mode 100644
index 000000000..7f4e7393e
--- /dev/null
+++ b/private/ntos/nthals/halmca/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/halmca/i386/ixcmos.inc b/private/ntos/nthals/halmca/i386/ixcmos.inc
new file mode 100644
index 000000000..2fe289fb0
--- /dev/null
+++ b/private/ntos/nthals/halmca/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/halmca/i386/ixdat.c b/private/ntos/nthals/halmca/i386/ixdat.c
new file mode 100644
index 000000000..f6b0e34de
--- /dev/null
+++ b/private/ntos/nthals/halmca/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/halmca/i386/ixenvirv.c b/private/ntos/nthals/halmca/i386/ixenvirv.c
new file mode 100644
index 000000000..e194820ba
--- /dev/null
+++ b/private/ntos/nthals/halmca/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/halmca/i386/ixfirm.c b/private/ntos/nthals/halmca/i386/ixfirm.c
new file mode 100644
index 000000000..f666e405c
--- /dev/null
+++ b/private/ntos/nthals/halmca/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/halmca/i386/ixhwsup.c b/private/ntos/nthals/halmca/i386/ixhwsup.c
new file mode 100644
index 000000000..ea91dc8d0
--- /dev/null
+++ b/private/ntos/nthals/halmca/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/halmca/i386/ixidle.asm b/private/ntos/nthals/halmca/i386/ixidle.asm
new file mode 100644
index 000000000..9bdd670f3
--- /dev/null
+++ b/private/ntos/nthals/halmca/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/halmca/i386/ixinfo.c b/private/ntos/nthals/halmca/i386/ixinfo.c
new file mode 100644
index 000000000..7f211f7a9
--- /dev/null
+++ b/private/ntos/nthals/halmca/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/halmca/i386/ixipi.asm b/private/ntos/nthals/halmca/i386/ixipi.asm
new file mode 100644
index 000000000..17eea3bf1
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/ixipi.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixipi.asm
diff --git a/private/ntos/nthals/halmca/i386/ixisa.h b/private/ntos/nthals/halmca/i386/ixisa.h
new file mode 100644
index 000000000..f67b35f49
--- /dev/null
+++ b/private/ntos/nthals/halmca/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/halmca/i386/ixisabus.c b/private/ntos/nthals/halmca/i386/ixisabus.c
new file mode 100644
index 000000000..c1edfb067
--- /dev/null
+++ b/private/ntos/nthals/halmca/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/halmca/i386/ixisasup.c b/private/ntos/nthals/halmca/i386/ixisasup.c
new file mode 100644
index 000000000..58c426544
--- /dev/null
+++ b/private/ntos/nthals/halmca/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/halmca/i386/ixkdcom.c b/private/ntos/nthals/halmca/i386/ixkdcom.c
new file mode 100644
index 000000000..29bb8308e
--- /dev/null
+++ b/private/ntos/nthals/halmca/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/halmca/i386/ixkdcom.h b/private/ntos/nthals/halmca/i386/ixkdcom.h
new file mode 100644
index 000000000..22f1aac09
--- /dev/null
+++ b/private/ntos/nthals/halmca/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/halmca/i386/ixmca.h b/private/ntos/nthals/halmca/i386/ixmca.h
new file mode 100644
index 000000000..e96b1064e
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/ixmca.h
@@ -0,0 +1,113 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ imhalp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ MCA specific interfaces, defines and structures.
+
+Author:
+
+ Jeff Havens (jhavens) 20-Jun-91
+
+
+Revision History:
+
+--*/
+
+#ifndef _IXMCA_
+#define _IXMCA_
+
+#include "mca.h"
+
+
+//
+// The MAXIMUM_MAP_BUFFER_SIZE defines the maximum map buffers which the system
+// will allocate for devices which require phyically contigous buffers.
+//
+
+#define MAXIMUM_MAP_BUFFER_SIZE 0x40000
+
+//
+// Define the initial buffer allocation size for a map buffers for systems with
+// no memory which has a physical address greater than MAXIMUM_PHYSICAL_ADDRESS.
+//
+
+#define INITIAL_MAP_BUFFER_SMALL_SIZE 0x10000
+
+//
+// Define the initial buffer allocation size for a map buffers for systems with
+// no memory which has a physical address greater than MAXIMUM_PHYSICAL_ADDRESS.
+//
+
+#define INITIAL_MAP_BUFFER_LARGE_SIZE 0x30000
+
+//
+// Define the incremental buffer allocation for a map buffers.
+//
+
+#define INCREMENT_MAP_BUFFER_SIZE 0x10000
+
+//
+// Define the maximum number of map registers that can be requested at one time
+// if actual map registers are required for the transfer.
+//
+
+#define MAXIMUM_MCA_MAP_REGISTER 16
+
+//
+// Define the maximum physical address which can be handled by an Isa card.
+//
+
+#define MAXIMUM_PHYSICAL_ADDRESS 0x01000000
+
+//
+// Define the scatter/gather flag for the Map Register Base.
+//
+
+#define NO_SCATTER_GATHER 0x00000001
+
+//
+// Define the copy buffer flag for the index.
+//
+
+#define COPY_BUFFER 0XFFFFFFFF
+
+//
+// Define adapter object structure.
+//
+
+typedef struct _ADAPTER_OBJECT {
+ CSHORT Type;
+ CSHORT Size;
+ struct _ADAPTER_OBJECT *MasterAdapter;
+ ULONG MapRegistersPerChannel;
+ PVOID AdapterBaseVa;
+ PVOID MapRegisterBase;
+ ULONG NumberOfMapRegisters;
+ ULONG CommittedMapRegisters;
+ struct _WAIT_CONTEXT_BLOCK *CurrentWcb;
+ KDEVICE_QUEUE ChannelWaitQueue;
+ PKDEVICE_QUEUE RegisterWaitQueue;
+ LIST_ENTRY AdapterQueue;
+ KSPIN_LOCK SpinLock;
+ PRTL_BITMAP MapRegisters;
+ UCHAR ChannelNumber;
+ UCHAR AdapterNumber;
+ DMA_EXTENDED_MODE ExtendedModeFlags;
+ USHORT DmaPortAddress;
+ UCHAR AdapterMode;
+ BOOLEAN NeedsMapRegisters;
+ BOOLEAN MasterDevice;
+ BOOLEAN Width16Bits;
+ BOOLEAN ScatterGather;
+ BOOLEAN Dma32BitAddresses;
+} ADAPTER_OBJECT;
+
+
+#endif // _IXMCA_
diff --git a/private/ntos/nthals/halmca/i386/ixmcabus.c b/private/ntos/nthals/halmca/i386/ixmcabus.c
new file mode 100644
index 000000000..82cc981cd
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/ixmcabus.c
@@ -0,0 +1,117 @@
+/*++
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ ixmcabus.c
+
+Abstract:
+
+Author:
+
+Environment:
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+extern KSPIN_LOCK HalpSystemHardwareLock;
+
+ULONG
+HalpGetPosData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG DOffset,
+ IN ULONG Length
+ )
+{
+ ULONG DataLength = 0;
+ ULONG Offset = 0;
+ ULONG Index = 0;
+ PUCHAR DataBuffer = Buffer;
+ PVOID McaRegisterBase = 0;
+ PUCHAR PosBase;
+ KIRQL Irql;
+ PHYSICAL_ADDRESS BusAddress;
+ BOOLEAN Status;
+ ULONG AddressSpace;
+
+
+ if (DOffset != 0) {
+ // bugbug: should support this
+ return 0;
+ }
+
+ //
+ // Translate the Mca Base port for this MCA bus
+ //
+
+ BusAddress.LowPart = (ULONG) McaRegisterBase;
+ BusAddress.HighPart = 0;
+ AddressSpace = 1; // I/O space
+ Status = BusHandler->TranslateBusAddress(
+ BusHandler,
+ RootHandler,
+ BusAddress,
+ &AddressSpace, // I/O Space
+ &BusAddress);
+
+ if (Status == FALSE || AddressSpace != 1) {
+ return 0;
+ }
+
+ McaRegisterBase = (PVOID) BusAddress.LowPart;
+
+ PosBase = (PUCHAR) &((PMCA_CONTROL) McaRegisterBase)->Pos;
+
+ Irql = KfAcquireSpinLock(&HalpSystemHardwareLock);
+
+ //
+ // Place the specified adapter into setup mode.
+ //
+
+ WRITE_PORT_UCHAR((PVOID) &((PMCA_CONTROL) McaRegisterBase)->AdapterSetup,
+ (UCHAR) ( MCA_ADAPTER_SETUP_ON | SlotNumber ));
+
+ while (DataLength < Length && DataLength < 6) {
+ DataBuffer[DataLength] = READ_PORT_UCHAR( PosBase + DataLength );
+ DataLength++;
+ }
+
+ while (DataLength < Length) {
+
+ WRITE_PORT_UCHAR((PVOID) &((PPROGRAMMABLE_OPTION_SELECT)
+ PosBase)->SubaddressExtensionLsb, (UCHAR) Index);
+
+ WRITE_PORT_UCHAR((PVOID) &((PPROGRAMMABLE_OPTION_SELECT)
+ PosBase)->SubaddressExtensionMsb, (UCHAR) (Index >> 8));
+
+ DataBuffer[Index + 6] = READ_PORT_UCHAR(
+ (PVOID) &((PPROGRAMMABLE_OPTION_SELECT)PosBase)->OptionSelectData2);
+
+ DataLength++;
+
+ if (DataLength < Length) {
+ Offset = DataLength + ((Length - DataLength) / 2);
+ DataBuffer[Offset] = READ_PORT_UCHAR(
+ (PVOID) &((PPROGRAMMABLE_OPTION_SELECT)PosBase)->OptionSelectData3);
+ DataLength++;
+ Index++;
+ }
+ }
+
+ //
+ // Disable adapter setup.
+ //
+
+ WRITE_PORT_UCHAR((PVOID) &((PMCA_CONTROL) McaRegisterBase)->AdapterSetup,
+ (UCHAR) ( MCA_ADAPTER_SETUP_OFF ));
+
+
+ KfReleaseSpinLock( &HalpSystemHardwareLock, Irql );
+ return DataLength;
+}
diff --git a/private/ntos/nthals/halmca/i386/ixmcasup.c b/private/ntos/nthals/halmca/i386/ixmcasup.c
new file mode 100644
index 000000000..6e5f3f105
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/ixmcasup.c
@@ -0,0 +1,1344 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ ixmcasup.c
+
+Abstract:
+
+ This module contains the IoXxx routines for the NT I/O system that
+ are hardware dependent. Were these routines not hardware dependent,
+ they would reside in the iosubs.c module.
+
+Author:
+
+ Darryl E. Havens (darrylh) 11-Apr-1990
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Modified for MCA support - Bill Parry (o-billp) 22-Jul-1991
+
+--*/
+
+#define MCA 1
+#include "halp.h"
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalGetAdapter)
+#endif
+
+//
+// The HalpNewAdapter event is used to serialize allocations
+// of new adapter objects, additions to the HalpMCAAdapter
+// array, and some global values (MasterAdapterObject) and some
+// adapter fields modified by HalpGrowMapBuffers.
+// (AdapterObject->NumberOfMapRegisters is assumed not to be
+// growable while this even is held)
+//
+// Note: We don't really need our own an event object for this.
+//
+
+#define HalpNewAdapter HalpBusDatabaseEvent
+extern KEVENT HalpNewAdapter;
+
+
+//
+// Define save area for MCA adapter objects. Allocate 1 extra slot for
+// bus masters (MAX_DMA_CHANNEL_NUMBER is zero-based).
+//
+
+PADAPTER_OBJECT HalpMCAAdapter[MAX_MCA_DMA_CHANNEL_NUMBER + 1 + 1];
+
+VOID
+HalpCopyBufferMap(
+ IN PMDL Mdl,
+ IN PTRANSLATION_ENTRY TranslationEntry,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ );
+
+
+NTSTATUS
+HalAllocateAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PWAIT_CONTEXT_BLOCK Wcb,
+ IN ULONG NumberOfMapRegisters,
+ IN PDRIVER_CONTROL ExecutionRoutine
+ )
+/*++
+
+Routine Description:
+
+ This routine allocates the adapter channel specified by the adapter object.
+ This is accomplished by placing the device object of the driver that wants
+ to allocate the adapter on the adapter's queue. If the queue is already
+ "busy", then the adapter has already been allocated, so the device object
+ is simply placed onto the queue and waits until the adapter becomes free.
+
+ Once the adapter becomes free (or if it already is), then the driver's
+ execution routine is invoked.
+
+ Also, a number of map registers may be allocated to the driver by specifying
+ a non-zero value for NumberOfMapRegisters. Then the map register must be
+ allocated from the master adapter. Once there are a sufficient number of
+ map registers available, then the execution routine is called and the
+ base address of the allocated map registers in the adapter is also passed
+ to the driver's execution routine.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+
+ Wcb - Supplies a wait context block for saving the allocation parameters.
+ The DeviceObject, CurrentIrp and DeviceContext should be initalized.
+
+ NumberOfMapRegisters - The number of map registers that are to be allocated
+ from the channel, if any.
+
+ ExecutionRoutine - The address of the driver's execution routine that is
+ invoked once the adapter channel (and possibly map registers) have been
+ allocated.
+
+Return Value:
+
+ Returns STATUS_SUCESS unless too many map registers are requested.
+
+Notes:
+
+ Note that this routine MUST be invoked at DISPATCH_LEVEL or above.
+
+--*/
+
+{
+
+ PADAPTER_OBJECT MasterAdapter;
+ BOOLEAN Busy = FALSE;
+ IO_ALLOCATION_ACTION Action;
+ KIRQL Irql;
+ LONG MapRegisterNumber;
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ //
+ // Initialize the device object's wait context block in case this device
+ // must wait before being able to allocate the adapter.
+ //
+
+ Wcb->DeviceRoutine = ExecutionRoutine;
+ Wcb->NumberOfMapRegisters = NumberOfMapRegisters;
+
+ //
+ // Allocate the adapter object for this particular device. If the
+ // adapter cannot be allocated because it has already been allocated
+ // to another device, then return to the caller now; otherwise,
+ // continue.
+ //
+
+ if (!KeInsertDeviceQueue( &AdapterObject->ChannelWaitQueue,
+ &Wcb->WaitQueueEntry )) {
+
+ //
+ // Save the parameters in case there are not enough map registers.
+ //
+
+ AdapterObject->NumberOfMapRegisters = NumberOfMapRegisters;
+ AdapterObject->CurrentWcb = Wcb;
+
+ //
+ // The adapter was not busy so it has been allocated. Now check
+ // to see whether this driver wishes to allocate any map registers.
+ // Ensure that this adapter has enough total map registers
+ // to satisfy the request.
+ //
+
+ if (NumberOfMapRegisters != 0 && AdapterObject->NeedsMapRegisters) {
+
+ //
+ // Lock the map register bit map and the adapter queue in the
+ // master adapter object. The channel structure offset is used as
+ // a hint for the register search.
+ //
+
+ if (NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ IoFreeAdapterChannel(AdapterObject);
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ Irql = KfAcquireSpinLock( &MasterAdapter->SpinLock );
+
+ MapRegisterNumber = -1;
+
+ if (IsListEmpty( &MasterAdapter->AdapterQueue)) {
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ NumberOfMapRegisters,
+ 0
+ );
+ }
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the master adapter where is will wait until some registers
+ // are deallocated.
+ //
+
+ InsertTailList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+ Busy = 1;
+
+ } else {
+
+ //
+ // Calculate the map register base from the allocated map
+ // register and base of the master adapter object.
+ //
+
+ AdapterObject->MapRegisterBase = ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }
+ }
+
+ KfReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ } else {
+
+ AdapterObject->MapRegisterBase = NULL;
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+
+ //
+ // If there were either enough map registers available or no map
+ // registers needed to be allocated, invoke the driver's execution
+ // routine now.
+ //
+
+ if (!Busy) {
+
+ AdapterObject->CurrentWcb = Wcb;
+ Action = ExecutionRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the driver would like to have the adapter deallocated,
+ // then release the adapter object.
+ //
+
+ if (Action == DeallocateObject) {
+
+ IoFreeAdapterChannel( AdapterObject );
+
+ } else if (Action == DeallocateObjectKeepRegisters) {
+
+ //
+ // Set the NumberOfMapRegisters = 0 in the adapter object.
+ // This will keep IoFreeAdapterChannel from freeing the
+ // registers. After this it is the driver's responsiblity to
+ // keep track of the number of map registers.
+ //
+
+ AdapterObject->NumberOfMapRegisters = 0;
+ IoFreeAdapterChannel(AdapterObject);
+
+ }
+ }
+ }
+
+ return(STATUS_SUCCESS);
+
+}
+
+PVOID
+HalAllocateCrashDumpRegisters(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ This routine is called during the crash dump disk driver's initialization
+ to allocate a number map registers permanently.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+ NumberOfMapRegisters - Input the number of registers requests and output
+ the number allocated.
+
+Return Value:
+
+ Returns STATUS_SUCESS if map registers allocated.
+
+--*/
+{
+ PADAPTER_OBJECT MasterAdapter;
+ ULONG MapRegisterNumber;
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ //
+ // Check to see whether this driver needs to allocate any map registers.
+ //
+
+ if (AdapterObject->NeedsMapRegisters) {
+
+ //
+ // Ensure that this adapter has enough total map registers to satisfy
+ // the request.
+ //
+
+ if (*NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ return NULL;
+ }
+
+ //
+ // Attempt to allocate the required number of map registers w/o
+ // affecting those registers that were allocated when the system
+ // crashed.
+ //
+
+ MapRegisterNumber = (ULONG)-1;
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ *NumberOfMapRegisters,
+ 0
+ );
+
+ if (MapRegisterNumber == (ULONG)-1) {
+
+ //
+ // Not enough free map registers were found, so they were busy
+ // being used by the system when it crashed. Force the appropriate
+ // number to be "allocated" at the base by simply overjamming the
+ // bits and return the base map register as the start.
+ //
+
+ RtlSetBits(
+ MasterAdapter->MapRegisters,
+ 0,
+ *NumberOfMapRegisters
+ );
+ MapRegisterNumber = 0;
+
+ }
+
+ //
+ // Calculate the map register base from the allocated map
+ // register and base of the master adapter object.
+ //
+
+ AdapterObject->MapRegisterBase = ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+ }
+
+ } else {
+
+ AdapterObject->MapRegisterBase = NULL;
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+
+ return AdapterObject->MapRegisterBase;
+}
+
+PADAPTER_OBJECT
+HalGetAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescriptor,
+ OUT PULONG NumberOfMapRegisters
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the appropriate adapter object for the device defined
+ in the device description structure. This code works for MCA systems.
+
+Arguments:
+
+ DeviceDescriptor - Supplies a description of the deivce.
+
+ NumberOfMapRegisters - Returns the maximum number of map registers which
+ may be allocated by the device driver.
+
+Return Value:
+
+ A pointer to the requested adpater object or NULL if an adapter could not
+ be created.
+
+--*/
+
+{
+ PADAPTER_OBJECT adapterObject;
+ ULONG channelNumber;
+ ULONG numberOfMapRegisters;
+
+ PAGED_CODE();
+
+ //
+ // Determine the number of map registers for this device.
+ //
+
+ if (DeviceDescriptor->ScatterGather && (LessThan16Mb ||
+ DeviceDescriptor->Dma32BitAddresses ||
+ DeviceDescriptor->InterfaceType == PCIBus)) {
+
+ //
+ // Since the device support scatter/Gather then map registers are not
+ // required.
+ //
+
+ numberOfMapRegisters = 0;
+
+ } else {
+
+ //
+ // Determine the number of map registers required based on the maximum
+ // transfer length, up to a maximum number.
+ //
+
+ numberOfMapRegisters = BYTES_TO_PAGES(DeviceDescriptor->MaximumLength)
+ + 1;
+ numberOfMapRegisters = numberOfMapRegisters > MAXIMUM_MCA_MAP_REGISTER ?
+ MAXIMUM_MCA_MAP_REGISTER : numberOfMapRegisters;
+
+ //
+ // If the device is not a master and does scatter/gather then it only
+ // needs one map register.
+ //
+
+ if (DeviceDescriptor->ScatterGather && !DeviceDescriptor->Master) {
+
+ numberOfMapRegisters = 1;
+ }
+ }
+
+ channelNumber = DeviceDescriptor->DmaChannel;
+
+ //
+ // Determine if a new adapter object is necessary. If so then allocate it.
+ //
+
+ if (!DeviceDescriptor->Master && HalpMCAAdapter[channelNumber] != NULL) {
+
+ adapterObject = HalpMCAAdapter[ channelNumber];
+
+ } else {
+
+ //
+ // Serialize before allocating a new adapter
+ //
+
+ KeWaitForSingleObject (
+ &HalpNewAdapter,
+ WrExecutive,
+ KernelMode,
+ FALSE,
+ NULL
+ );
+
+
+ //
+ // Determine if a new adapter object has already been allocated.
+ // If so use it, otherwise allocate a new adapter object
+ //
+
+ if (!DeviceDescriptor->Master && HalpMCAAdapter[channelNumber] != NULL) {
+
+ adapterObject = HalpMCAAdapter[ channelNumber];
+
+ } else {
+
+ //
+ // Allocate an adapter object.
+ //
+
+ //
+ // bugbug- need to pass in MCA base address instead of 0.
+ //
+
+ adapterObject = (PADAPTER_OBJECT) HalpAllocateAdapter(
+ numberOfMapRegisters,
+ (PVOID) 0,
+ NULL
+ );
+
+ if (adapterObject == NULL) {
+ KeSetEvent (&HalpNewAdapter, 0, FALSE);
+ return(NULL);
+ }
+
+ if (!DeviceDescriptor->Master) {
+ HalpMCAAdapter[channelNumber] = adapterObject;
+ }
+
+ //
+ // Set the maximum number of map registers for this channel bus on
+ // the number requested and the type of device.
+ //
+
+ if (numberOfMapRegisters) {
+
+ //
+ // The specified number of registers are actually allowed to be
+ // allocated.
+ //
+
+ adapterObject->MapRegistersPerChannel = numberOfMapRegisters;
+
+ //
+ // Increase the commitment for the map registers.
+ //
+
+ if (DeviceDescriptor->Master) {
+
+ //
+ // Master I/O devices use several sets of map registers double
+ // their commitment.
+ //
+
+ MasterAdapterObject->CommittedMapRegisters +=
+ numberOfMapRegisters * 2;
+
+ } else {
+
+ MasterAdapterObject->CommittedMapRegisters +=
+ numberOfMapRegisters;
+
+ }
+
+ //
+ // If the committed map registers is signicantly greater than the
+ // number allocated then grow the map buffer.
+ //
+
+ if (MasterAdapterObject->CommittedMapRegisters >
+ MasterAdapterObject->NumberOfMapRegisters &&
+ MasterAdapterObject->CommittedMapRegisters -
+ MasterAdapterObject->NumberOfMapRegisters >
+ MAXIMUM_MCA_MAP_REGISTER ) {
+
+ HalpGrowMapBuffers(
+ MasterAdapterObject,
+ INCREMENT_MAP_BUFFER_SIZE
+ );
+ }
+
+ adapterObject->NeedsMapRegisters = TRUE;
+
+ } else {
+
+ //
+ // No real map registers were allocated. If this is a master
+ // device, then the device can have as may registers as it wants.
+ //
+
+ adapterObject->NeedsMapRegisters = FALSE;
+
+ if (DeviceDescriptor->Master) {
+
+ adapterObject->MapRegistersPerChannel = BYTES_TO_PAGES(
+ DeviceDescriptor->MaximumLength
+ )
+ + 1;
+
+ } else {
+
+ //
+ // The device only gets one register. It must call
+ // IoMapTransfer repeatedly to do a large transfer.
+ //
+
+ adapterObject->MapRegistersPerChannel = 1;
+ }
+ }
+ }
+
+ KeSetEvent (&HalpNewAdapter, 0, FALSE);
+
+ }
+
+ adapterObject->Dma32BitAddresses = DeviceDescriptor->Dma32BitAddresses;
+ adapterObject->ScatterGather = DeviceDescriptor->ScatterGather;
+ *NumberOfMapRegisters = adapterObject->MapRegistersPerChannel;
+
+ //
+ // set up channel number.
+ //
+
+ adapterObject->ChannelNumber = (UCHAR) channelNumber;
+
+ //
+ // initialize MCA Extended DMA Mode flags.
+ //
+
+ *((PUCHAR) &adapterObject->ExtendedModeFlags) = 0;
+
+ //
+ // set up auto-initialize if necessary.
+ //
+
+ if ( DeviceDescriptor->AutoInitialize) {
+
+ adapterObject->ExtendedModeFlags.AutoInitialize = 1;
+
+ }
+
+ //
+ // set up PIO address if necessary.
+ //
+
+ if ( DeviceDescriptor->DmaPort) {
+
+ adapterObject->ExtendedModeFlags.ProgrammedIo = DMA_EXT_USE_PIO;
+ adapterObject->DmaPortAddress = (USHORT) DeviceDescriptor->DmaPort;
+
+ } else {
+
+ adapterObject->ExtendedModeFlags.ProgrammedIo = DMA_EXT_NO_PIO;
+ }
+
+ //
+ // indicate data transfer operation for DMA.
+ //
+
+ adapterObject->ExtendedModeFlags.DmaOpcode = DMA_EXT_DATA_XFER;
+
+ switch (DeviceDescriptor->DmaWidth) {
+ case Width8Bits:
+ adapterObject->ExtendedModeFlags.DmaWidth = DMA_EXT_WIDTH_8_BIT;
+ break;
+
+ case Width16Bits:
+ adapterObject->ExtendedModeFlags.DmaWidth = DMA_EXT_WIDTH_16_BIT;
+ break;
+
+ case Width32Bits:
+ //
+ // If it's a master, it doesn't need DmaWidth filled in
+ //
+
+ if (!DeviceDescriptor->Master) {
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+ }
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ } // switch
+
+ if (DeviceDescriptor->Master) {
+
+ adapterObject->MasterDevice = TRUE;
+
+ } else {
+
+ adapterObject->MasterDevice = FALSE;
+ } // if
+
+ return(adapterObject);
+}
+
+
+PHYSICAL_ADDRESS
+IoMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN OUT PULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to set up the map registers in the DMA controller
+ to allow a transfer to or from a device.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel that has been allocated.
+
+ Mdl - Pointer to the MDL that describes the pages of memory that are
+ being read or written.
+
+ MapRegisterBase - The address of the base map register that has been
+ allocated to the device driver for use in mapping the transfer.
+
+ CurrentVa - Current virtual address in the buffer described by the MDL
+ that the transfer is being done to or from.
+
+ Length - Supplies the length of the transfer. This determines the
+ number of map registers that need to be written to map the transfer.
+ Returns the length of the transfer which was actually mapped.
+
+ WriteToDevice - Boolean value that indicates whether this is a write
+ to the device from memory (TRUE), or vice versa.
+
+Return Value:
+
+ Returns the logical address that should be used bus master controllers.
+
+--*/
+
+{
+ BOOLEAN useBuffer;
+ ULONG transferLength;
+ ULONG logicalAddress;
+ PHYSICAL_ADDRESS returnAddress;
+ ULONG index;
+ PULONG pageFrame;
+ PTRANSLATION_ENTRY translationEntry;
+ PMCA_DMA_CONTROLLER dmaControl;
+ UCHAR channelNumber;
+ KIRQL Irql;
+ KIRQL Irql2;
+ ULONG pageOffset;
+
+ pageOffset = BYTE_OFFSET(CurrentVa);
+
+ //
+ // Calculate how must of the transfer is contiguous.
+ //
+
+ transferLength = PAGE_SIZE - pageOffset;
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) / PAGE_SIZE;
+ logicalAddress = (*pageFrame << PAGE_SHIFT) + pageOffset;
+
+ //
+ // If the buffer is contigous then just extend the buffer.
+ //
+
+ while( transferLength < *Length ){
+
+ if (*pageFrame + 1 != *(pageFrame + 1)) {
+ break;
+ }
+
+ transferLength += PAGE_SIZE;
+ pageFrame++;
+
+ }
+
+ transferLength = transferLength > *Length ? *Length : transferLength;
+
+ //
+ // Determine if the data transfer needs to use the map buffer.
+ //
+
+ if (MapRegisterBase != NULL) {
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER
+ && transferLength < *Length) {
+
+ logicalAddress = translationEntry->PhysicalAddress + pageOffset;
+ translationEntry->Index = COPY_BUFFER;
+ index = 0;
+ transferLength = *Length;
+ useBuffer = TRUE;
+
+ } else {
+
+ //
+ // If there are map registers, then update the index to indicate
+ // how many have been used.
+ //
+
+ useBuffer = FALSE;
+ index = translationEntry->Index;
+ translationEntry->Index += ADDRESS_AND_SIZE_TO_SPAN_PAGES(
+ CurrentVa,
+ transferLength
+ );
+ }
+
+ //
+ // It must require memory to be at less than 16 MB. If the
+ // logical address is greater than 16MB then map registers must be used
+ //
+
+ if (logicalAddress+transferLength >= MAXIMUM_PHYSICAL_ADDRESS) {
+
+ logicalAddress = (translationEntry + index)->PhysicalAddress +
+ pageOffset;
+ useBuffer = TRUE;
+
+ if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER) {
+ translationEntry->Index = COPY_BUFFER;
+ index = 0;
+
+ }
+ }
+
+ //
+ // Copy the data if necessary.
+ //
+
+ if (useBuffer && WriteToDevice) {
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry + index,
+ CurrentVa,
+ *Length,
+ WriteToDevice
+ );
+
+ }
+ }
+
+ //
+ // Return the length.
+ //
+
+ *Length = transferLength;
+
+ //
+ // We only support 32 bits, but the return is 64. Just
+ // zero extend
+ //
+
+ returnAddress.LowPart = logicalAddress;
+ returnAddress.HighPart = 0;
+
+ //
+ // If no adapter was specificed, or device is bus master, then there
+ // is no more work to do so return.
+ //
+
+ if (AdapterObject == NULL || AdapterObject->MasterDevice) {
+
+ return(returnAddress);
+ }
+
+ //
+ // grab the spinlock for the Microchannel system DMA controller
+ //
+
+ Irql = KfAcquireSpinLock( &AdapterObject->MasterAdapter->SpinLock );
+
+ //
+ // Raise to high level. On systems with ABIOS disks
+ // the ABIOS can reprogram the DMA from its interrupt. Raising to high
+ // prevents the ABIOS from running while the DMA controller is being
+ // maniulated. Note this will not work on MP systems, however there are
+ // no know MP systems with non-SCSI ABIOS disks.
+ //
+
+ Irql2 = KfRaiseIrql(HIGH_LEVEL);
+
+ //
+ // Set up the Microchannel system DMA controller
+ //
+
+ dmaControl = (PMCA_DMA_CONTROLLER)
+ &( (PMCA_CONTROL) (AdapterObject->AdapterBaseVa))->
+ ExtendedDmaBasePort[0];
+ channelNumber = AdapterObject->ChannelNumber;
+
+ //
+ // set the mask bit
+ //
+
+ WRITE_PORT_UCHAR( &dmaControl->DmaFunctionLsb,
+ (UCHAR) ( SET_MASK_BIT | channelNumber));
+
+ //
+ // set mode register
+ //
+
+ WRITE_PORT_UCHAR( &dmaControl->DmaFunctionLsb,
+ (UCHAR) ( WRITE_MODE | channelNumber));
+
+ //
+ // Set up for read or write, appropriately
+ //
+
+ if ( WriteToDevice) {
+
+ WRITE_PORT_UCHAR( &dmaControl->DmaFunctionData,
+ (UCHAR) (*((PUCHAR) &AdapterObject->
+ ExtendedModeFlags)
+ | (UCHAR) DMA_MODE_READ));
+
+ } else {
+
+ WRITE_PORT_UCHAR( &dmaControl->DmaFunctionData,
+ (UCHAR) ( *((PUCHAR) &AdapterObject->
+ ExtendedModeFlags)
+ | DMA_MODE_WRITE));
+ }
+
+ //
+ // if there is a DMA Programmed I/O address, set it up
+ //
+
+ if ( AdapterObject->ExtendedModeFlags.ProgrammedIo) {
+
+ //
+ // set up I/O base address
+ //
+
+ WRITE_PORT_UCHAR( &dmaControl->DmaFunctionLsb,
+ (UCHAR) ( WRITE_IO_ADDRESS | channelNumber));
+
+ WRITE_PORT_UCHAR( &dmaControl->DmaFunctionData,
+ (UCHAR) AdapterObject->DmaPortAddress);
+
+ WRITE_PORT_UCHAR( &dmaControl->DmaFunctionData,
+ (UCHAR) ( AdapterObject->DmaPortAddress >> 8));
+
+ }
+
+ //
+ // set the DMA transfer count
+ //
+
+ WRITE_PORT_UCHAR( &dmaControl->DmaFunctionLsb,
+ (UCHAR) ( WRITE_TRANSFER_COUNT | channelNumber));
+
+ //
+ // adjust transfer count for 16-bit transfers as required.
+ //
+
+ if ( AdapterObject->ExtendedModeFlags.DmaWidth == DMA_EXT_WIDTH_16_BIT ) {
+
+ //
+ // Round up on odd byte transfers and divide by 2.
+ //
+
+ transferLength++;
+ transferLength >>= 1;
+ }
+
+ WRITE_PORT_UCHAR( &dmaControl->DmaFunctionData,
+ (UCHAR) ( transferLength - 1));
+
+ WRITE_PORT_UCHAR( &dmaControl->DmaFunctionData,
+ (UCHAR) ( ( transferLength - 1) >> 8));
+
+ //
+ // set the DMA transfer start address
+ //
+
+ WRITE_PORT_UCHAR( &dmaControl->DmaFunctionLsb,
+ (UCHAR) ( WRITE_MEMORY_ADDRESS | channelNumber));
+
+ WRITE_PORT_UCHAR( &dmaControl->DmaFunctionData,
+ (UCHAR) logicalAddress);
+
+ WRITE_PORT_UCHAR( &dmaControl->DmaFunctionData,
+ (UCHAR) (logicalAddress >> 8));
+
+ WRITE_PORT_UCHAR( &dmaControl->DmaFunctionData,
+ (UCHAR) (logicalAddress >> 16));
+
+ //
+ // clear the mask bit
+ //
+
+ WRITE_PORT_UCHAR( &dmaControl->DmaFunctionLsb,
+ (UCHAR) ( CLEAR_MASK_BIT | channelNumber));
+
+ KfLowerIrql(Irql2);
+
+ //
+ // release the spinlock for the Microchannel system DMA controller
+ //
+
+ KfReleaseSpinLock( &AdapterObject->MasterAdapter->SpinLock, Irql );
+
+ return(returnAddress);
+}
+
+BOOLEAN
+IoFlushAdapterBuffers(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine flushes the DMA adpater object buffers.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel.
+
+ Mdl - A pointer to a Memory Descriptor List (MDL) that maps the locked-down
+ buffer to/from which the I/O occured.
+
+ MapRegisterBase - A pointer to the base of the map registers in the adapter
+ or DMA controller.
+
+ CurrentVa - The current virtual address in the buffer described the the Mdl
+ where the I/O operation occurred.
+
+ Length - Supplies the length of the transfer.
+
+ WriteToDevice - Supplies a BOOLEAN value that indicates the direction of
+ the data transfer was to the device.
+
+Return Value:
+
+ TRUE - No errors are detected so the transfer must succeed.
+
+--*/
+
+{
+ PMCA_DMA_CONTROLLER dmaControl;
+ KIRQL Irql;
+ KIRQL Irql2;
+ PTRANSLATION_ENTRY translationEntry;
+ PULONG pageFrame;
+ ULONG transferLength;
+ ULONG partialLength;
+ BOOLEAN masterDevice;
+
+ masterDevice = AdapterObject == NULL || AdapterObject->MasterDevice ?
+ TRUE : FALSE;
+
+ //
+ // If this is a slave device then stop the DMA controller be flushing
+ // the data.
+ //
+
+ if (!masterDevice) {
+
+ //
+ // grab the spinlock for the Microchannel system DMA controller
+ //
+
+ Irql = KfAcquireSpinLock( &AdapterObject->MasterAdapter->SpinLock );
+
+ //
+ // Raise to high level. On systems with ABIOS disks
+ // the ABIOS can reprogram the DMA from its interrupt. Raising to high
+ // prevents the ABIOS from running while the DMA controller is being
+ // maniulated. Note this will not work on MP systems, however there are
+ // no know MP systems with non-SCSI ABIOS disks.
+ //
+
+ Irql2 = KfRaiseIrql(HIGH_LEVEL);
+
+ //
+ // Set up the Microchannel system DMA controller
+ //
+
+ dmaControl = (PMCA_DMA_CONTROLLER)
+ &( (PMCA_CONTROL) (AdapterObject->AdapterBaseVa))->
+ ExtendedDmaBasePort[0];
+ //
+ // clear the mask bit
+ //
+
+ WRITE_PORT_UCHAR( &dmaControl->DmaFunctionLsb,
+ (UCHAR) ( SET_MASK_BIT | AdapterObject->ChannelNumber));
+
+ //
+ // release the spinlock for the Microchannel system DMA controller
+ //
+
+ KfLowerIrql(Irql2);
+ KfReleaseSpinLock( &AdapterObject->MasterAdapter->SpinLock, Irql );
+
+ }
+
+ if (MapRegisterBase == NULL) {
+ return(TRUE);
+ }
+
+ //
+ // Determine if the data needs to be copied to the orginal buffer.
+ // This only occurs if the data tranfer is from the device, the
+ // MapReisterBase is not NULL and the transfer spans a page.
+ //
+
+ if (!WriteToDevice) {
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ //
+ // If this is not a master device, then just transfer the buffer.
+ //
+
+ if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER) {
+
+ if (translationEntry->Index == COPY_BUFFER) {
+
+ if (!masterDevice) {
+
+ //
+ // Copy only the bytes that have actually been transfered.
+ //
+
+ Length -= HalReadDmaCounter(AdapterObject);
+ }
+
+ //
+ // The adapter does not support scatter/gather copy the buffer.
+ //
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ Length,
+ WriteToDevice
+ );
+
+ }
+
+ } else {
+
+ //
+ // Cycle through the pages of the transfer to determine if there
+ // are any which need to be copied back.
+ //
+
+ transferLength = PAGE_SIZE - BYTE_OFFSET(CurrentVa);
+ partialLength = transferLength;
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) / PAGE_SIZE;
+
+ while( transferLength <= Length ){
+
+ if (*pageFrame >= BYTES_TO_PAGES(MAXIMUM_PHYSICAL_ADDRESS)) {
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ partialLength,
+ WriteToDevice
+ );
+
+ }
+
+ (PCCHAR) CurrentVa += partialLength;
+ partialLength = PAGE_SIZE;
+
+ //
+ // Note that transferLength indicates the amount which will be
+ // transfered after the next loop; thus, it is updated with the
+ // new partial length.
+ //
+
+ transferLength += partialLength;
+ pageFrame++;
+ translationEntry++;
+ }
+
+ //
+ // Process the any remaining residue.
+ //
+
+ partialLength = Length - transferLength + partialLength;
+ if (partialLength && *pageFrame >= BYTES_TO_PAGES(MAXIMUM_PHYSICAL_ADDRESS)) {
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ partialLength,
+ WriteToDevice
+ );
+
+ }
+
+ }
+
+ }
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ //
+ // Clear the index of used buffers.
+ //
+
+ if (translationEntry) {
+
+ translationEntry->Index = 0;
+ }
+
+ return TRUE;
+}
+
+ULONG
+HalReadDmaCounter(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+/*++
+
+Routine Description:
+
+ This function reads the DMA counter and returns the number of bytes left
+ to be transfered.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object to be read.
+
+Return Value:
+
+ Returns the number of bytes still be be transfered.
+
+--*/
+
+{
+ ULONG count;
+ ULONG high;
+ PMCA_DMA_CONTROLLER dmaControl;
+ UCHAR channelNumber;
+ KIRQL Irql;
+ KIRQL Irql2;
+
+ //
+ // grab the spinlock for the Microchannel system DMA controller
+ //
+
+ Irql = KfAcquireSpinLock( &AdapterObject->MasterAdapter->SpinLock );
+
+ //
+ // Raise to high level. On systems with ABIOS disks
+ // the ABIOS can reprogram the DMA from its interrupt. Raising to high
+ // prevents the ABIOS from running while the DMA controller is being
+ // maniulated. Note this will not work on MP systems, however there are
+ // no know MP systems with non-SCSI ABIOS disks.
+ //
+
+ Irql2 = KfRaiseIrql(HIGH_LEVEL);
+
+ //
+ // Set up the Microchannel system DMA controller
+ //
+
+ dmaControl = (PMCA_DMA_CONTROLLER)
+ &( (PMCA_CONTROL) (AdapterObject->AdapterBaseVa))->
+ ExtendedDmaBasePort[0];
+ channelNumber = AdapterObject->ChannelNumber;
+
+ count = 0XFFFF00;
+
+ //
+ // Loop until the high byte matches.
+ //
+
+ do {
+
+ high = count;
+
+ //
+ // read the DMA transfer count
+ //
+
+ WRITE_PORT_UCHAR( &dmaControl->DmaFunctionLsb,
+ (UCHAR) ( READ_TRANSFER_COUNT | channelNumber));
+
+ count = READ_PORT_UCHAR( &dmaControl->DmaFunctionData);
+
+ count |= READ_PORT_UCHAR( &dmaControl->DmaFunctionData) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+ //
+ // The DMA counter has a bias of one and can only be 16 bit long.
+ //
+
+ count = (count + 1) & 0xFFFF;
+
+ //
+ // adjust transfer count for 16-bit transfers as required.
+ //
+
+ if ( AdapterObject->ExtendedModeFlags.DmaWidth == DMA_EXT_WIDTH_16_BIT ) {
+ count <<= 1;
+ }
+
+
+ KfLowerIrql(Irql2);
+
+ //
+ // release the spinlock for the Microchannel system DMA controller
+ //
+
+ KfReleaseSpinLock( &AdapterObject->MasterAdapter->SpinLock, Irql );
+
+ return(count);
+}
diff --git a/private/ntos/nthals/halmca/i386/ixnmi.c b/private/ntos/nthals/halmca/i386/ixnmi.c
new file mode 100644
index 000000000..2ab99a52b
--- /dev/null
+++ b/private/ntos/nthals/halmca/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/halmca/i386/ixpcibrd.c b/private/ntos/nthals/halmca/i386/ixpcibrd.c
new file mode 100644
index 000000000..02fd82821
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/ixpcibrd.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixpcibrd.c"
diff --git a/private/ntos/nthals/halmca/i386/ixpcibus.c b/private/ntos/nthals/halmca/i386/ixpcibus.c
new file mode 100644
index 000000000..640cebfba
--- /dev/null
+++ b/private/ntos/nthals/halmca/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/halmca/i386/ixpciint.c b/private/ntos/nthals/halmca/i386/ixpciint.c
new file mode 100644
index 000000000..5243acee5
--- /dev/null
+++ b/private/ntos/nthals/halmca/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/halmca/i386/ixphwsup.c b/private/ntos/nthals/halmca/i386/ixphwsup.c
new file mode 100644
index 000000000..a1cdab598
--- /dev/null
+++ b/private/ntos/nthals/halmca/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/halmca/i386/ixproc.c b/private/ntos/nthals/halmca/i386/ixproc.c
new file mode 100644
index 000000000..fdb962b05
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/ixproc.c
@@ -0,0 +1,163 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ ixsproc.c
+
+Abstract:
+
+ Stub functions for UP hals.
+
+Author:
+
+ Ken Reneris (kenr) 22-Jan-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+UCHAR HalName[] = "PC Compatible MicroChannel HAL";
+
+BOOLEAN
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+VOID HalpInitOtherBuses (VOID);
+VOID HalpInitializePciBus (VOID);
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpInitMP)
+#pragma alloc_text(INIT,HalStartNextProcessor)
+#pragma alloc_text(INIT,HalAllProcessorsStarted)
+#pragma alloc_text(INIT,HalReportResourceUsage)
+#pragma alloc_text(INIT,HalpInitOtherBuses)
+#endif
+
+
+
+BOOLEAN
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+{
+ // do nothing
+ return TRUE;
+}
+
+
+VOID
+HalpResetAllProcessors (
+ VOID
+ )
+{
+ // Just return, that will invoke the standard PC reboot code
+}
+
+
+BOOLEAN
+HalStartNextProcessor (
+ IN PLOADER_PARAMETER_BLOCK pLoaderBlock,
+ IN PKPROCESSOR_STATE pProcessorState
+ )
+{
+ // no other processors
+ return FALSE;
+}
+
+BOOLEAN
+HalAllProcessorsStarted (
+ VOID
+ )
+{
+ return TRUE;
+}
+
+
+VOID
+HalReportResourceUsage (
+ VOID
+ )
+{
+ INTERFACE_TYPE interfacetype;
+ ANSI_STRING AHalName;
+ UNICODE_STRING UHalName;
+
+ HalInitSystemPhase2();
+
+ switch (HalpBusType) {
+ case MACHINE_TYPE_ISA: interfacetype = Isa; break;
+ case MACHINE_TYPE_EISA: interfacetype = Eisa; break;
+ case MACHINE_TYPE_MCA: interfacetype = MicroChannel; break;
+ default: interfacetype = Internal; break;
+ }
+
+ RtlInitAnsiString (&AHalName, HalName);
+ RtlAnsiStringToUnicodeString (&UHalName, &AHalName, TRUE);
+ HalpReportResourceUsage (
+ &UHalName, // descriptive name
+ interfacetype // device space interface type
+ );
+
+ RtlFreeUnicodeString (&UHalName);
+
+ //
+ // Registry is now intialized, see if there are any PCI buses
+ //
+
+ HalpInitializePciBus ();
+}
+
+VOID
+HalpInitOtherBuses (
+ VOID
+ )
+{
+ // no other internal buses supported
+}
+
+NTSTATUS
+HalpGetMcaLog (
+ OUT PMCA_EXCEPTION Exception,
+ OUT PULONG ReturnedLength
+ )
+{
+ return STATUS_NOT_SUPPORTED;
+}
+
+NTSTATUS
+HalpMcaRegisterDriver(
+ IN PMCA_DRIVER_INFO DriverInfo
+ )
+{
+ return STATUS_NOT_SUPPORTED;
+}
+
+VOID
+HalpMcaQueueDpc (
+ VOID
+ )
+{
+}
+
+
+ULONG
+FASTCALL
+HalSystemVectorDispatchEntry (
+ IN ULONG Vector,
+ OUT PKINTERRUPT_ROUTINE **FlatDispatch,
+ OUT PKINTERRUPT_ROUTINE *NoConnection
+ )
+{
+ return FALSE;
+}
diff --git a/private/ntos/nthals/halmca/i386/ixprofil.asm b/private/ntos/nthals/halmca/i386/ixprofil.asm
new file mode 100644
index 000000000..c33b273ae
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/ixprofil.asm
@@ -0,0 +1,5 @@
+;
+; Include code from halx86
+; This is a cpp style symbolic link
+
+include ..\halx86\i386\ixprofil.asm
diff --git a/private/ntos/nthals/halmca/i386/ixreboot.c b/private/ntos/nthals/halmca/i386/ixreboot.c
new file mode 100644
index 000000000..15d7bd898
--- /dev/null
+++ b/private/ntos/nthals/halmca/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/halmca/i386/ixstall.asm b/private/ntos/nthals/halmca/i386/ixstall.asm
new file mode 100644
index 000000000..115c6c9c1
--- /dev/null
+++ b/private/ntos/nthals/halmca/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/halmca/i386/ixswint.asm b/private/ntos/nthals/halmca/i386/ixswint.asm
new file mode 100644
index 000000000..68b302dfe
--- /dev/null
+++ b/private/ntos/nthals/halmca/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/halmca/i386/ixsysbus.c b/private/ntos/nthals/halmca/i386/ixsysbus.c
new file mode 100644
index 000000000..b4776da76
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/ixsysbus.c
@@ -0,0 +1,5 @@
+//
+// Include code from halx86
+// This is a cpp style symbolic link
+
+#include "..\halx86\i386\ixsysbus.c"
diff --git a/private/ntos/nthals/halmca/i386/ixthunk.c b/private/ntos/nthals/halmca/i386/ixthunk.c
new file mode 100644
index 000000000..6f15aad73
--- /dev/null
+++ b/private/ntos/nthals/halmca/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/halmca/i386/ixusage.c b/private/ntos/nthals/halmca/i386/ixusage.c
new file mode 100644
index 000000000..519ec31f3
--- /dev/null
+++ b/private/ntos/nthals/halmca/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/halmca/i386/mcirql.asm b/private/ntos/nthals/halmca/i386/mcirql.asm
new file mode 100644
index 000000000..02d355cd4
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/mcirql.asm
@@ -0,0 +1,1121 @@
+ title "Irql Processing"
+;++
+;
+; Copyright (c) 1989 Microsoft Corporation
+;
+; Module Name:
+;
+; ixirql.asm
+;
+; Abstract:
+;
+; 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
+;
+;--
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include i386\ix8259.inc
+include i386\kimacro.inc
+include mac386.inc
+ .list
+
+
+ EXTRNP _KeBugCheck,1,IMPORT
+ EXTRNP _KeSetEventBoostPriority, 2, IMPORT
+ EXTRNP _KeWaitForSingleObject,5, IMPORT
+
+ extrn _HalpApcInterrupt:near
+ extrn _HalpDispatchInterrupt:near
+ extrn _KiUnexpectedInterrupt:near
+ extrn _HalpBusType:DWORD
+ extrn _HalpApcInterrupt2ndEntry:NEAR
+ extrn _HalpDispatchInterrupt2ndEntry:NEAR
+
+ifdef NT_UP
+ LOCK_ADD equ add
+ LOCK_DEC equ dec
+else
+ LOCK_ADD equ lock add
+ LOCK_DEC equ lock dec
+endif
+
+
+;
+; 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
+;
+
+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
+
+
+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
+
+ align 4
+ public KiI8259MaskTable
+KiI8259MaskTable label dword
+ dd 00000000000000000000000000000000B ; irql 0
+ dd 00000000000000000000000000000000B ; irql 1
+ dd 00000000000000000000000000000000B ; irql 2
+ dd 00000000000000000000000000000000B ; irql 3
+ dd 11111111100000000000000000000000B ; 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
+
+ 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 PARA 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
+;
+;--
+
+cPublicFastCall KfRaiseIrql,1
+cPublicFpo 0,0
+
+ movzx ecx, cl ; 32bit extend NewIrql
+ mov al, PCR[PcIrql] ; get current irql
+
+if DBG
+ cmp al,cl ; old > new?
+ jbe short Kri99 ; no, we're OK
+ movzx ecx, cl
+ movzx eax, al
+ push ecx ; put new irql where we can find it
+ push eax ; put old irql where we can find it
+ mov byte ptr PCR[PcIrql],0 ; avoid recursive error
+ stdCall _KeBugCheck, <IRQL_NOT_GREATER_OR_EQUAL > ; never return
+Kri99:
+endif
+ cmp cl,DISPATCH_LEVEL ; software level?
+ jbe short kri10 ; Skip setting 8259 masks
+
+ mov edx, eax ; Save OldIrql
+
+ pushfd
+ cli ; disable interrupt
+ mov PCR[PcIrql], cl ; set the new irql
+ mov eax, KiI8259MaskTable[ecx*4]; get pic masks for the new irql
+ or eax, PCR[PcIDR] ; mask irqs which are disabled
+ SET_8259_MASK ; set 8259 masks
+
+ popfd
+
+ mov eax, edx ; (al) = OldIrql
+ fstRET KfRaiseIrql
+
+align 4
+kri10:
+;
+; Note it is very important that we set the old irql AFTER we raised to
+; the new irql. Otherwise, if there is an interrupt comes in between and
+; the OldIrql is not a local variable, the caller will get wrong OldIrql.
+; The bottom line is the raising irql and returning old irql has to be
+; atomic to the caller.
+;
+ mov PCR[PcIrql], cl
+ fstRET KfRaiseIrql
+
+fstENDP KfRaiseIrql
+
+;++
+;
+; VOID
+; KIRQL
+; KeRaiseIrqlToDpcLevel (
+; )
+;
+; Routine Description:
+;
+; This routine is used to raise IRQL to DPC level.
+;
+; Arguments:
+;
+; Return Value:
+;
+; OldIrql - the addr of a variable which old irql should be stored
+;
+;--
+
+cPublicProc _KeRaiseIrqlToDpcLevel,0
+cPublicFpo 0, 0
+
+ mov al, PCR[PcIrql] ; (al) = Old Irql
+ mov byte ptr PCR[PcIrql], DISPATCH_LEVEL ; set new irql
+
+ifdef IRQL_METRICS
+ inc HalRaiseIrqlCount
+endif
+if DBG
+ cmp al, DISPATCH_LEVEL ; old > new?
+ ja short Krid99 ; yes, go bugcheck
+endif
+
+ stdRET _KeRaiseIrqlToDpcLevel
+
+if DBG
+cPublicFpo 0,1
+Krid99: movzx eax, al
+ push eax ; put old irql where we can find it
+ stdCall _KeBugCheck, <IRQL_NOT_GREATER_OR_EQUAL> ; never return
+ stdRET _KeRaiseIrqlToDpcLevel
+endif
+
+stdENDP _KeRaiseIrqlToDpcLevel
+
+;++
+;
+; VOID
+; KIRQL
+; KeRaiseIrqlToSynchLevel (
+; )
+;
+; Routine Description:
+;
+; This routine is used to raise IRQL to SYNC level.
+;
+; Arguments:
+;
+; Return Value:
+;
+; OldIrql - the addr of a variable which old irql should be stored
+;
+;--
+
+cPublicProc _KeRaiseIrqlToSynchLevel,0
+cPublicFpo 0, 0
+ pushfd
+ cli ; disable interrupt
+ mov eax, KiI8259MaskTable[SYNCH_LEVEL*4]; get pic masks for the new irql
+ or eax, PCR[PcIDR] ; mask irqs which are disabled
+ SET_8259_MASK ; set 8259 masks
+
+ mov al, PCR[PcIrql] ; (al) = Old irql
+ mov byte ptr PCR[PcIrql], SYNCH_LEVEL ; set new irql
+
+ popfd
+
+if DBG
+ cmp al, SYNCH_LEVEL
+ ja short Kris99
+endif
+
+ifdef IRQL_METRICS
+ inc HalRaiseIrqlCount
+endif
+ stdRET _KeRaiseIrqlToSynchLevel
+
+if DBG
+cPublicFpo 0,1
+Kris99: movzx eax, al
+ push eax ; put old irql where we can find it
+ stdCall _KeBugCheck, <IRQL_NOT_GREATER_OR_EQUAL> ; never return
+ stdRET _KeRaiseIrqlToSynchLevel
+endif
+
+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.
+;
+; On a UP system, HalEndSystenInterrupt is treated as a
+; LowerIrql.
+;
+; Arguments:
+;
+; (cl) = NewIrql - the new irql to be set.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+
+cPublicFastCall KfLowerIrql ,1
+cPublicFpo 0,1
+
+ pushfd ; save caller's eflags
+ movzx ecx, cl ; zero extend irql
+
+if DBG
+ cmp cl,PCR[PcIrql]
+ ja short Kli99
+endif
+ cmp byte ptr PCR[PcIrql],DISPATCH_LEVEL ; Software level?
+ cli
+ jbe short kli02 ; no, go set 8259 hw
+
+ mov eax, KiI8259MaskTable[ecx*4]; get pic masks for the new irql
+ or eax, PCR[PcIDR] ; mask irqs which are disabled
+ SET_8259_MASK ; set 8259 masks
+kli02:
+ mov PCR[PcIrql], cl ; set the new irql
+ mov eax, PCR[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
+
+kil03: popfd ; restore flags, including ints
+cPublicFpo 1,0
+ fstRET KfLowerIrql
+
+if DBG
+cPublicFpo 1,3
+Kli99:
+ push ecx ; new irql for debugging
+ push PCR[PcIrql] ; old irql for debugging
+ mov byte ptr PCR[PcIrql],HIGH_LEVEL ; avoid recursive error
+ stdCall _KeBugCheck, <IRQL_NOT_LESS_OR_EQUAL> ; never return
+endif
+
+;
+; When we come to Kli10, (eax) = soft interrupt index
+;
+; Note Do NOT:
+;
+; popfd
+; jmp SWInterruptHandlerTable[eax*4]
+;
+; We want to make sure interrupts are off after entering SWInterrupt
+; Handler.
+;
+
+align 4
+cPublicFpo 1,1
+Kli10: call SWInterruptHandlerTable[eax*4] ; SIMULATE INTERRUPT
+ popfd ; restore flags, including ints
+cPublicFpo 1,0
+ fstRET KfLowerIrql ; cRetURN
+
+fstENDP KfLowerIrql
+
+;++
+;
+; KIRQL
+; FASTCALL
+; KfAcquireSpinLock (
+; IN PKSPIN_LOCK SpinLock,
+; )
+;
+; Routine Description:
+;
+; This function raises to DISPATCH_LEVEL and then acquires a the
+; kernel spin lock.
+;
+; In a UP hal spinlock serialization is accomplished by raising the
+; IRQL to DISPATCH_LEVEL. The SpinLock is not used; however, for
+; debugging purposes if the UP hal is compiled with the NT_UP flag
+; not set (ie, MP) we take the SpinLock.
+;
+; Arguments:
+;
+; (ecx) = SpinLock - Supplies a pointer to an kernel spin lock.
+;
+; Return Value:
+;
+; OldIrql
+;
+;--
+
+cPublicFastCall KfAcquireSpinLock,1
+cPublicFpo 0,0
+
+ mov al, PCR[PcIrql] ; (al) = Old Irql
+ mov byte ptr PCR[PcIrql], DISPATCH_LEVEL ; set new irql
+
+ifndef NT_UP
+asl10: ACQUIRE_SPINLOCK ecx,<short asl20>
+endif
+
+ifdef IRQL_METRICS
+ inc HalRaiseIrqlCount
+endif
+if DBG
+ cmp al, DISPATCH_LEVEL ; old > new?
+ ja short asl99 ; yes, go bugcheck
+endif
+ fstRET KfAcquireSpinLock
+
+ifndef NT_UP
+asl20: SPIN_ON_SPINLOCK ecx,<short asl10>
+endif
+
+if DBG
+cPublicFpo 2, 1
+asl99:
+ push ecx ; put old irql where we can find it
+ stdCall _KeBugCheck, <IRQL_NOT_GREATER_OR_EQUAL> ; never return
+endif
+ fstRET KfAcquireSpinLock
+fstENDP KfAcquireSpinLock
+
+
+;++
+;
+; KIRQL
+; FASTCALL
+; KeAcquireSpinLockRaiseToSynch (
+; IN PKSPIN_LOCK SpinLock,
+; )
+;
+; Routine Description:
+;
+; This function acquires the SpinLock at SYNCH_LEVEL. The function
+; is optmized for hoter locks (the lock is tested before acquired.
+; Any spin should occur at OldIrql; however, since this is a UP hal
+; we don't have the code for it)
+;
+; In a UP hal spinlock serialization is accomplished by raising the
+; IRQL to SYNCH_LEVEL. The SpinLock is not used; however, for
+; debugging purposes if the UP hal is compiled with the NT_UP flag
+; not set (ie, MP) we take the SpinLock.
+;
+; Arguments:
+;
+; (ecx) = SpinLock - Supplies a pointer to an kernel spin lock.
+;
+; Return Value:
+;
+; OldIrql
+;
+;--
+
+cPublicFastCall KeAcquireSpinLockRaiseToSynch,1
+cPublicFpo 0,0
+
+ push ecx
+ mov ecx, SYNCH_LEVEL
+ fstCall KfRaiseIrql ; Raise to SYNCH_LEVEL
+ pop ecx
+
+ifndef NT_UP
+asls10: ACQUIRE_SPINLOCK ecx,<short asls20>
+endif
+
+ifdef IRQL_METRICS
+ inc HalRaiseIrqlCount
+endif
+if DBG
+ cmp al, SYNCH_LEVEL ; old > new?
+ ja short asls99 ; yes, go bugcheck
+endif
+ fstRET KeAcquireSpinLockRaiseToSynch
+
+ifndef NT_UP
+asls20: SPIN_ON_SPINLOCK ecx,<short asls10>
+endif
+
+if DBG
+cPublicFpo 2, 1
+asls99:
+ push ecx ; put old irql where we can find it
+ stdCall _KeBugCheck, <IRQL_NOT_GREATER_OR_EQUAL> ; never return
+endif
+ fstRET KeAcquireSpinLockRaiseToSynch
+fstENDP KeAcquireSpinLockRaiseToSynch
+
+
+ PAGE
+ SUBTTL "Release Kernel Spin Lock"
+;++
+;
+; VOID
+; FASTCALL
+; KfReleaseSpinLock (
+; IN PKSPIN_LOCK SpinLock,
+; IN KIRQL NewIrql
+; )
+;
+; Routine Description:
+;
+; This function releases a kernel spin lock and lowers to the new irql
+;
+; In a UP hal spinlock serialization is accomplished by raising the
+; IRQL to DISPATCH_LEVEL. The SpinLock is not used; however, for
+; debugging purposes if the UP hal is compiled with the NT_UP flag
+; not set (ie, MP) we use the SpinLock.
+;
+;
+; Arguments:
+;
+; (ecx) = SpinLock - Supplies a pointer to an executive spin lock.
+; (dl) = NewIrql - New irql value to set
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+align 16
+cPublicFastCall KfReleaseSpinLock ,2
+cPublicFpo 0,1
+ pushfd
+
+ifndef NT_UP
+ RELEASE_SPINLOCK ecx ; release it
+endif
+ movzx ecx, dl ; (ecx) = NewIrql
+ cmp byte ptr PCR[PcIrql],DISPATCH_LEVEL ; Software level?
+ cli
+ jbe short rsl02 ; no, go set 8259 hw
+
+ mov eax, KiI8259MaskTable[ecx*4]; get pic masks for the new irql
+ or eax, PCR[PcIDR] ; mask irqs which are disabled
+ SET_8259_MASK ; set 8259 masks
+rsl02:
+ mov PCR[PcIrql], cl
+ mov eax, PCR[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 short rsl20 ; yes, go simulate interrupt
+
+ popfd
+ fstRet KfReleaseSpinLock ; all done
+
+align 4
+rsl20: call SWInterruptHandlerTable[eax*4] ; SIMULATE INTERRUPT
+ popfd ; restore flags, including ints
+cPublicFpo 2,0
+ fstRET KfReleaseSpinLock ; all done
+
+fstENDP KfReleaseSpinLock
+
+
+;++
+;
+; VOID
+; FASTCALL
+; ExAcquireFastMutex (
+; IN PFAST_MUTEX FastMutex
+; )
+;
+; Routine description:
+;
+; This function acquire ownership of the FastMutex
+;
+; Arguments:
+;
+; (ecx) = FastMutex - Supplies a pointer to the fast mutex
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicFastCall ExAcquireFastMutex,1
+cPublicFpo 0,1
+
+ push ecx ; Save FastMutex
+ mov ecx, APC_LEVEL
+ fstCall KfRaiseIrql ; Raise to APC_LEVEL
+ pop ecx ; (ecx) = FastMutex
+
+cPublicFpo 0,0
+ LOCK_DEC dword ptr [ecx].FmCount ; Get count
+ jz short afm_ret ; The owner? Yes, Done
+
+ inc dword ptr [ecx].FmContention
+
+cPublicFpo 0,2
+ push ecx ; Save FastMutex
+ push eax ; Save OldIrql
+ add ecx, FmEvent ; Wait on Event
+ stdCall _KeWaitForSingleObject,<ecx,WrExecutive,0,0,0>
+ pop eax
+ pop ecx
+
+afm_ret:
+ mov byte ptr [ecx].FmOldIrql, al ; (al) = OldIrql
+ fstRet ExAcquireFastMutex
+
+fstENDP ExAcquireFastMutex
+
+;++
+;
+; BOOLEAN
+; FASTCALL
+; ExTryToAcquireFastMutex (
+; IN PFAST_MUTEX FastMutex
+; )
+;
+; Routine description:
+;
+; This function acquire ownership of the FastMutex
+;
+; Arguments:
+;
+; (ecx) = FastMutex - Supplies a pointer to the fast mutex
+;
+; Return Value:
+;
+; Returns TRUE if the FAST_MUTEX was acquired; otherwise false
+;
+;--
+
+cPublicFastCall ExTryToAcquireFastMutex,1
+cPublicFpo 0,1
+
+;
+; Try to acquire - but needs to support 386s.
+; *** Warning: This code is NOT MP safe ***
+; But, we know that this hal really only runs on UP machines
+;
+
+ push ecx ; Save FAST_MUTEX
+
+ mov ecx, APC_LEVEL
+ fstCall KfRaiseIrql ; (al) = OldIrql
+
+ pop edx ; (edx) = FAST_MUTEX
+
+cPublicFpo 0,0
+
+ cli
+ cmp dword ptr [edx].FmCount, 1 ; Busy?
+ jne short tam20 ; Yes, abort
+
+ mov dword ptr [edx].FmCount, 0 ; acquire count
+ sti
+
+ mov byte ptr [edx].FmOldIrql, al
+ mov eax, 1 ; return TRUE
+ fstRet ExTryToAcquireFastMutex
+
+tam20: sti
+ mov ecx, eax ; (cl) = OldIrql
+ fstCall KfLowerIrql ; resture OldIrql
+ xor eax, eax ; return FALSE
+ fstRet ExTryToAcquireFastMutex ; all done
+
+fstENDP ExTryToAcquireFastMutex
+
+
+;++
+;
+; VOID
+; FASTCALL
+; ExReleaseFastMutex (
+; IN PFAST_MUTEX FastMutex
+; )
+;
+; Routine description:
+;
+; This function releases ownership of the FastMutex
+;
+; Arguments:
+;
+; (ecx) = FastMutex - Supplies a pointer to the fast mutex
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicFastCall ExReleaseFastMutex,1
+cPublicFpo 0,0
+ mov al, byte ptr [ecx].FmOldIrql ; (cl) = OldIrql
+
+ LOCK_ADD dword ptr [ecx].FmCount, 1 ; Remove our count
+ xchg ecx, eax ; (cl) = OldIrql
+ js short rfm05 ; if < 0, set event
+ jnz @KfLowerIrql@4 ; if != 0, don't set event
+
+rfm05: add eax, FmEvent
+ push ecx
+ stdCall _KeSetEventBoostPriority, <eax, 0>
+ pop ecx
+ jmp @KfLowerIrql@4
+
+fstENDP ExReleaseFastMutex
+
+
+
+
+;++
+;
+; 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+12 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
+cPublicFpo 2, 0
+
+ movzx ecx, byte ptr HeiNewIrql; get new irql value
+ cmp byte ptr PCR[PcIrql],DISPATCH_LEVEL ; Software level?
+ jbe short Hei02 ; no, go set 8259 hw
+
+ mov eax, KiI8259MaskTable[ecx*4]; get pic masks for the new irql
+ or eax, PCR[PcIDR] ; mask irqs which are disabled
+ SET_8259_MASK ; set 8259 masks
+
+Hei02:
+ mov PCR[PcIrql], cl ; set the new irql
+ mov eax, PCR[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 short Hei10 ; yes, go simulate interrupt
+
+ stdRET _HalEndSystemInterrupt ; cRetURN
+
+; When we come to Hei10, (eax) = soft interrupt index
+
+Hei10: add esp, 12 ; esp = trap frame
+ 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.
+;
+;--
+
+HesNewIrql equ [esp + 4]
+
+cPublicProc _HalpEndSoftwareInterrupt ,1
+cPublicFpo 1, 0
+
+ movzx ecx, byte ptr HesNewIrql; get new irql value
+
+ cmp byte ptr PCR[PcIrql],DISPATCH_LEVEL ; Software level?
+ jbe short Hes02 ; no, go set 8259 hw
+
+ mov eax, KiI8259MaskTable[ecx*4]; get pic masks for the new irql
+ or eax, PCR[PcIDR] ; mask irqs which are disabled
+ SET_8259_MASK ; set 8259 masks
+
+Hes02:
+ mov PCR[PcIrql], cl ; set the new irql
+ mov eax, PCR[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 short Hes10 ; yes, go simulate interrupt
+
+ stdRET _HalpEndSoftwareInterrupt ; cRetURN
+
+; When we come to Hes10, (eax) = soft interrupt index
+
+Hes10: add esp, 8
+ jmp SWInterruptHandlerTable2[eax*4] ; SIMULATE INTERRUPT
+
+ ; to the appropriate handler
+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
+cPublicFpo 0, 0
+ movzx eax, word ptr PCR[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
+cPublicFpo 0, 0
+
+ ;
+ ; Raising to HIGH_LEVEL disables interrupts for the microchannel 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
+
+ test _HalpBusType, MACHINE_TYPE_MCA
+ jz short Hip00
+
+; Is this a PS2 or PS700 series machine?
+
+ in al, 07fh ; get PD700 ID byte
+ and al, 0F0h ; Mask high nibble
+ cmp al, 0A0h ; Is the ID Ax?
+ jz short Hip00
+ cmp al, 090h ; Or an 9X?
+ jz short Hip00 ; Yes, it's a 700
+
+ lea esi, PS2PICsInitializationString
+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/halmca/i386/mcsysint.asm b/private/ntos/nthals/halmca/i386/mcsysint.asm
new file mode 100644
index 000000000..f00b5c6e7
--- /dev/null
+++ b/private/ntos/nthals/halmca/i386/mcsysint.asm
@@ -0,0 +1,385 @@
+;++
+;
+;Copyright (c) 1991 Microsoft Corporation
+;
+;Module Name:
+;
+; ixsysint.asm
+;
+;Abstract:
+;
+; This module implements the HAL routines to enable/disable system
+; interrupts.
+;
+;Author:
+;
+; John Vert (jvert) 22-Jul-1991
+;
+;Environment:
+;
+; Kernel Mode
+;
+;Revision History:
+;
+;--
+
+
+.386p
+ .xlist
+include hal386.inc
+include i386\ix8259.inc
+include i386\kimacro.inc
+include mac386.inc
+include callconv.inc
+ .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$01 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
+;
+; On a UP machine the interrupt dismissed at BeginSystemInterrupt time.
+; This is fine since the irql is being raise to mask it off.
+; HalEndSystemInterrupt is simply a LowerIrql request.
+;
+;
+;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
+cPublicFpo 3, 0
+ movzx ebx,HbsiVector ; (ebx) = System Vector
+ sub ebx, PRIMARY_VECTOR_BASE ; (ebx) = 8259 IRQ #
+if DBG
+ cmp ebx, 23h
+ jbe hbsi00
+ int 3
+hbsi00:
+
+endif
+ jmp HalpSpecialDismissTable[ebx*4]
+
+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
+; sti
+ 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
+; sti
+ stdRET _HalBeginSystemInterrupt
+
+HalpDismissNormal:
+;
+; Store OldIrql
+;
+ mov eax, HbsiOldIrql
+ movzx ecx, word ptr PCR[PcIrql]
+ mov byte ptr [eax], cl
+
+;
+; Raise IRQL to requested level
+;
+ movzx eax, HbsiIrql ; (eax) = irql
+ ; (ebx) = IRQ #
+
+ mov PCR[PcIrql], al ; set new Irql
+
+
+ mov eax, KiI8259MaskTable[eax*4] ; get 8259's masks
+ or eax, PCR[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 - This is not enough for 486
+
+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 ; *MUST* wait for 8259 before sti
+ 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
+cPublicFpo 2, 0
+
+;
+
+ 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 PCR[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
+cPublicFpo 3, 0
+
+ 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 PCR[PcIDR], eax
+
+;
+; Get the PIC masks for the current Irql
+;
+ movzx eax, byte ptr PCR[PcIrql]
+ mov eax, KiI8259MaskTable[eax*4]
+ or eax, PCR[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$01 ENDS
+
+ END
diff --git a/private/ntos/nthals/halmca/i386/pcip.h b/private/ntos/nthals/halmca/i386/pcip.h
new file mode 100644
index 000000000..476bab1e4
--- /dev/null
+++ b/private/ntos/nthals/halmca/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/halmca/i386/xxbiosa.asm b/private/ntos/nthals/halmca/i386/xxbiosa.asm
new file mode 100644
index 000000000..bc0173a17
--- /dev/null
+++ b/private/ntos/nthals/halmca/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/halmca/i386/xxbiosc.c b/private/ntos/nthals/halmca/i386/xxbiosc.c
new file mode 100644
index 000000000..60cf92748
--- /dev/null
+++ b/private/ntos/nthals/halmca/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/halmca/i386/xxdisp.c b/private/ntos/nthals/halmca/i386/xxdisp.c
new file mode 100644
index 000000000..d48977df0
--- /dev/null
+++ b/private/ntos/nthals/halmca/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/halmca/i386/xxflshbf.c b/private/ntos/nthals/halmca/i386/xxflshbf.c
new file mode 100644
index 000000000..b054121cf
--- /dev/null
+++ b/private/ntos/nthals/halmca/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/halmca/i386/xxhal.c b/private/ntos/nthals/halmca/i386/xxhal.c
new file mode 100644
index 000000000..198d08346
--- /dev/null
+++ b/private/ntos/nthals/halmca/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/halmca/i386/xxioacc.asm b/private/ntos/nthals/halmca/i386/xxioacc.asm
new file mode 100644
index 000000000..8445c3404
--- /dev/null
+++ b/private/ntos/nthals/halmca/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/halmca/i386/xxkdsup.c b/private/ntos/nthals/halmca/i386/xxkdsup.c
new file mode 100644
index 000000000..6e569b5ac
--- /dev/null
+++ b/private/ntos/nthals/halmca/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/halmca/i386/xxmemory.c b/private/ntos/nthals/halmca/i386/xxmemory.c
new file mode 100644
index 000000000..920714540
--- /dev/null
+++ b/private/ntos/nthals/halmca/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/halmca/i386/xxstubs.c b/private/ntos/nthals/halmca/i386/xxstubs.c
new file mode 100644
index 000000000..8421fb30a
--- /dev/null
+++ b/private/ntos/nthals/halmca/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/halmca/i386/xxtime.c b/private/ntos/nthals/halmca/i386/xxtime.c
new file mode 100644
index 000000000..92abb2aeb
--- /dev/null
+++ b/private/ntos/nthals/halmca/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/halmca/makefile b/private/ntos/nthals/halmca/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halmca/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/halmca/makefile.inc b/private/ntos/nthals/halmca/makefile.inc
new file mode 100644
index 000000000..cb912aa51
--- /dev/null
+++ b/private/ntos/nthals/halmca/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/halmca/sources b/private/ntos/nthals/halmca/sources
new file mode 100644
index 000000000..0760716a7
--- /dev/null
+++ b/private/ntos/nthals/halmca/sources
@@ -0,0 +1,100 @@
+
+!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=halmca
+TARGETPATH=\nt\public\sdk\lib
+
+HALTYPE=MCA
+
+!IF $(386)
+
+TARGETTYPE=HAL
+
+!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\ixinfo.c \
+ i386\ixisabus.c \
+ i386\ixpcibus.c \
+ i386\ixpciint.c \
+ i386\ixpcibrd.c \
+ i386\ixsysbus.c \
+ i386\ixclock.asm \
+ i386\ixcmos.asm \
+ i386\ixenvirv.c \
+ i386\ixfirm.c \
+ i386\ixhwsup.c \
+ i386\ixidle.asm \
+ i386\ixipi.asm \
+ i386\mcirql.asm \
+ i386\ixkdcom.c \
+ i386\ixmcabus.c \
+ i386\ixmcasup.c \
+ i386\ixnmi.c \
+ i386\ixphwsup.c \
+ i386\ixprofil.asm \
+ i386\ixproc.c \
+ i386\ixreboot.c \
+ i386\ixstall.asm \
+ i386\ixswint.asm \
+ i386\mcsysint.asm \
+ i386\ixthunk.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
+
+DLLDEF=obj\*\hal.def
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+!IF $(386)
+
+NTTARGETFILES=$(TARGETPATH)\i386\halmca.lib
+
+!ENDIF