summaryrefslogtreecommitdiffstats
path: root/private/ntos/nthals/halraw
diff options
context:
space:
mode:
Diffstat (limited to 'private/ntos/nthals/halraw')
-rw-r--r--private/ntos/nthals/halraw/alpha/adjust.c7
-rw-r--r--private/ntos/nthals/halraw/alpha/allstart.c7
-rw-r--r--private/ntos/nthals/halraw/alpha/as4000.h62
-rw-r--r--private/ntos/nthals/halraw/alpha/bios.c7
-rw-r--r--private/ntos/nthals/halraw/alpha/bitmap.c3007
-rw-r--r--private/ntos/nthals/halraw/alpha/bitmap.h252
-rw-r--r--private/ntos/nthals/halraw/alpha/busdata.c137
-rw-r--r--private/ntos/nthals/halraw/alpha/cache.c7
-rw-r--r--private/ntos/nthals/halraw/alpha/devintr.s7
-rw-r--r--private/ntos/nthals/halraw/alpha/drivesup.c7
-rw-r--r--private/ntos/nthals/halraw/alpha/ebsgdma.c7
-rw-r--r--private/ntos/nthals/halraw/alpha/eeprom8k.c7
-rw-r--r--private/ntos/nthals/halraw/alpha/eisaprof.c7
-rw-r--r--private/ntos/nthals/halraw/alpha/eisasup.c7
-rw-r--r--private/ntos/nthals/halraw/alpha/ev5cache.c7
-rw-r--r--private/ntos/nthals/halraw/alpha/ev5int.c7
-rw-r--r--private/ntos/nthals/halraw/alpha/ev5ints.s7
-rw-r--r--private/ntos/nthals/halraw/alpha/ev5mchk.c7
-rw-r--r--private/ntos/nthals/halraw/alpha/ev5mem.s7
-rw-r--r--private/ntos/nthals/halraw/alpha/ev5prof.c7
-rw-r--r--private/ntos/nthals/halraw/alpha/fwreturn.c7
-rw-r--r--private/ntos/nthals/halraw/alpha/haldebug.c7
-rw-r--r--private/ntos/nthals/halraw/alpha/halpal.s7
-rw-r--r--private/ntos/nthals/halraw/alpha/haltsup.s7
-rw-r--r--private/ntos/nthals/halraw/alpha/idle.s7
-rw-r--r--private/ntos/nthals/halraw/alpha/info.c7
-rw-r--r--private/ntos/nthals/halraw/alpha/inithal.c1126
-rw-r--r--private/ntos/nthals/halraw/alpha/intsup.s256
-rw-r--r--private/ntos/nthals/halraw/alpha/iod.c1467
-rw-r--r--private/ntos/nthals/halraw/alpha/iod.h1669
-rw-r--r--private/ntos/nthals/halraw/alpha/iodaddr.c731
-rw-r--r--private/ntos/nthals/halraw/alpha/ioderr.c2304
-rw-r--r--private/ntos/nthals/halraw/alpha/iodio.s2997
-rw-r--r--private/ntos/nthals/halraw/alpha/iodmapio.c163
-rw-r--r--private/ntos/nthals/halraw/alpha/ioproc.c75
-rw-r--r--private/ntos/nthals/halraw/alpha/iousage.c647
-rw-r--r--private/ntos/nthals/halraw/alpha/iousage.h107
-rw-r--r--private/ntos/nthals/halraw/alpha/machdep.h42
-rw-r--r--private/ntos/nthals/halraw/alpha/memory.c7
-rw-r--r--private/ntos/nthals/halraw/alpha/nvenv.c7
-rw-r--r--private/ntos/nthals/halraw/alpha/nvram.c7
-rw-r--r--private/ntos/nthals/halraw/alpha/pcibus.c146
-rw-r--r--private/ntos/nthals/halraw/alpha/pciesc.c489
-rw-r--r--private/ntos/nthals/halraw/alpha/pcisup.c7
-rw-r--r--private/ntos/nthals/halraw/alpha/pcrtc.c383
-rw-r--r--private/ntos/nthals/halraw/alpha/pcserial.c7
-rw-r--r--private/ntos/nthals/halraw/alpha/pcspeakr.c7
-rw-r--r--private/ntos/nthals/halraw/alpha/perf8254.c7
-rw-r--r--private/ntos/nthals/halraw/alpha/pintolin.h214
-rw-r--r--private/ntos/nthals/halraw/alpha/rawerr.c154
-rw-r--r--private/ntos/nthals/halraw/alpha/rawerror.h301
-rw-r--r--private/ntos/nthals/halraw/alpha/rawhide.h349
-rw-r--r--private/ntos/nthals/halraw/alpha/rwclock.c308
-rw-r--r--private/ntos/nthals/halraw/alpha/rwinitnt.c1324
-rw-r--r--private/ntos/nthals/halraw/alpha/rwintbal.c1762
-rw-r--r--private/ntos/nthals/halraw/alpha/rwintbal.h200
-rw-r--r--private/ntos/nthals/halraw/alpha/rwintsup.c2364
-rw-r--r--private/ntos/nthals/halraw/alpha/rwref.h109
-rw-r--r--private/ntos/nthals/halraw/alpha/rwsysint.c501
-rw-r--r--private/ntos/nthals/halraw/alpha/vga.c7
-rw-r--r--private/ntos/nthals/halraw/bushnd.c7
-rw-r--r--private/ntos/nthals/halraw/dirs24
-rw-r--r--private/ntos/nthals/halraw/drivesup.c7
-rw-r--r--private/ntos/nthals/halraw/hal.rc11
-rw-r--r--private/ntos/nthals/halraw/hal.src7
-rw-r--r--private/ntos/nthals/halraw/mp/makefile6
-rw-r--r--private/ntos/nthals/halraw/mp/makefile.inc5
-rw-r--r--private/ntos/nthals/halraw/mp/sources109
-rw-r--r--private/ntos/nthals/halraw/up/makefile6
-rw-r--r--private/ntos/nthals/halraw/up/makefile.inc5
-rw-r--r--private/ntos/nthals/halraw/up/sources109
71 files changed, 24152 insertions, 0 deletions
diff --git a/private/ntos/nthals/halraw/alpha/adjust.c b/private/ntos/nthals/halraw/alpha/adjust.c
new file mode 100644
index 000000000..47c267fb8
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/adjust.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\adjust.c"
+
diff --git a/private/ntos/nthals/halraw/alpha/allstart.c b/private/ntos/nthals/halraw/alpha/allstart.c
new file mode 100644
index 000000000..42f70b7ca
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/allstart.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\allstart.c"
+
diff --git a/private/ntos/nthals/halraw/alpha/as4000.h b/private/ntos/nthals/halraw/alpha/as4000.h
new file mode 100644
index 000000000..9e66de6da
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/as4000.h
@@ -0,0 +1,62 @@
+/*++
+
+Copyright (c) 1996 Digital Equipment Corporation
+
+Module Name:
+
+ as4000.h
+
+Abstract:
+
+ This file defines the AS4000 internal bus interrupts for Windows NT 3.51
+
+Author:
+
+ Matthew Buchman 18 March 1996
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#ifndef _AS4000_
+#define _AS4000_
+
+/*++
+
+ Value added drivers for the AS4000 running Windows NT 3.51 can take
+ advantage of interrupts for the Correctable Error and the I2c Bus.
+ These interrupts are made visible to device drivers on the "Internal"
+ bus. A device driver may connect one of these interrupts via a call to
+ HalGetInterruptVector(). The bus interrupt level/vector are defined
+ below for the Correctable Error, I2c Bus, and I2c Controller interrupts.
+
+ For example, to connect the I2c bus interrupt vector:
+
+ HalGetInterruptVector(
+ Internal,
+ 0,
+ AS4000I2cBusInterruptVector,
+ AS4000I2cBusInterruptVector,
+ &Irql,
+ &Affinity
+ );
+
+ See the Windows NT Network Developers CD for more information on
+ the steps necessary to connect an interrupt service routine for
+ kernel mode device drivers.
+
+-*/
+
+enum _AS4000_INTERNAL_BUS_INTERRUPT_LEVEL {
+
+ AS4000SoftErrInterruptLevel, // Correctable Error
+ AS4000I2cCtrlInterruptLevel, // I2C Controller
+ AS4000I2cBusInterruptLevel // I2C Bus
+
+};
+
+#endif // _AS4000_
diff --git a/private/ntos/nthals/halraw/alpha/bios.c b/private/ntos/nthals/halraw/alpha/bios.c
new file mode 100644
index 000000000..3a9d3aa50
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/bios.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\bios.c"
+
diff --git a/private/ntos/nthals/halraw/alpha/bitmap.c b/private/ntos/nthals/halraw/alpha/bitmap.c
new file mode 100644
index 000000000..6f01b6908
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/bitmap.c
@@ -0,0 +1,3007 @@
+/*++
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ BitMap.c
+
+Abstract:
+
+ Implementation of the bit map routines for the NT rtl.
+
+ Bit numbers within the bit map are zero based. The first is numbered
+ zero.
+
+ The bit map routines keep track of the number of bits clear or set by
+ subtracting or adding the number of bits operated on as bit ranges
+ are cleared or set; individual bit states are not tested.
+ This means that if a range of bits is set,
+ it is assumed that the total range is currently clear.
+
+Author:
+
+ Gary Kimura (GaryKi) & Lou Perazzoli (LouP) 29-Jan-1990
+
+Revision History:
+
+ Eric Rehm 9-Nov-1995 - Rename to Rtl to Halp for use in Rawhide HAL
+
+--*/
+
+// #include "ntrtlp.h"
+
+#include "halp.h"
+#include "rawhide.h"
+
+#define RightShiftUlong(E1,E2) ((E2) < 32 ? (E1) >> (E2) : 0)
+#define LeftShiftUlong(E1,E2) ((E2) < 32 ? (E1) << (E2) : 0)
+
+//
+// Macro that tells how many contiguous bits are set (i.e., 1) in
+// a byte
+//
+
+#define HalppBitSetAnywhere( Byte ) HalppBitsClearAnywhere[ (~(Byte) & 0xFF) ]
+
+
+//
+// Macro that tells how many contiguous LOW order bits are set
+// (i.e., 1) in a byte
+//
+
+#define HalppBitsSetLow( Byte ) HalppBitsClearLow[ (~(Byte) & 0xFF) ]
+
+
+//
+// Macro that tells how many contiguous HIGH order bits are set
+// (i.e., 1) in a byte
+//
+
+#define HalppBitsSetHigh( Byte ) HalppBitsClearHigh[ (~(Byte) & 0xFF) ]
+
+
+//
+// Macro that tells how many set bits (i.e., 1) there are in a byte
+//
+
+#define HalppBitsSetTotal( Byte ) HalppBitsClearTotal[ (~(Byte) & 0xFF) ]
+
+
+#if DBG
+VOID
+HalpDumpBitMap (
+ PRTL_BITMAP BitMap
+ )
+{
+ ULONG i;
+ BOOLEAN AllZeros, AllOnes;
+
+ DbgPrint(" BitMap:%08lx", BitMap);
+
+ KdPrint((" (%08x)", BitMap->SizeOfBitMap));
+ KdPrint((" %08lx\n", BitMap->Buffer));
+
+ AllZeros = FALSE;
+ AllOnes = FALSE;
+
+ for (i = 0; i < ((BitMap->SizeOfBitMap + 31) / 32); i += 1) {
+
+ if (BitMap->Buffer[i] == 0) {
+
+ if (AllZeros) {
+
+ NOTHING;
+
+ } else {
+
+ DbgPrint("%4d:", i);
+ DbgPrint(" %08lx\n", BitMap->Buffer[i]);
+ }
+
+ AllZeros = TRUE;
+
+ } else if (BitMap->Buffer[i] == 0xFFFFFFFF) {
+
+ if (AllOnes) {
+
+ NOTHING;
+
+ } else {
+
+ DbgPrint("%4d:", i);
+ DbgPrint(" %08lx\n", BitMap->Buffer[i]);
+ }
+
+ AllOnes = TRUE;
+
+ } else {
+
+ AllZeros = FALSE;
+ AllOnes = FALSE;
+
+ DbgPrint("%4d:", i);
+ DbgPrint(" %08lx\n", BitMap->Buffer[i]);
+ }
+ }
+}
+
+#endif
+
+
+//
+// There are three macros to make reading the bytes in a bitmap easier.
+//
+
+#define GET_BYTE_DECLARATIONS() \
+ PUCHAR _CURRENT_POSITION;
+
+#define GET_BYTE_INITIALIZATION(RTL_BITMAP,BYTE_INDEX) { \
+ _CURRENT_POSITION = &((PUCHAR)((RTL_BITMAP)->Buffer))[BYTE_INDEX]; \
+}
+
+#define GET_BYTE(THIS_BYTE) ( \
+ THIS_BYTE = *(_CURRENT_POSITION++) \
+)
+
+
+//
+// Lookup table that tells how many contiguous bits are clear (i.e., 0) in
+// a byte
+//
+
+CCHAR HalppBitsClearAnywhere[] =
+ { 8,7,6,6,5,5,5,5,4,4,4,4,4,4,4,4,
+ 4,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
+ 5,4,3,3,2,2,2,2,3,2,2,2,2,2,2,2,
+ 4,3,2,2,2,2,2,2,3,2,2,2,2,2,2,2,
+ 6,5,4,4,3,3,3,3,3,2,2,2,2,2,2,2,
+ 4,3,2,2,2,1,1,1,3,2,1,1,2,1,1,1,
+ 5,4,3,3,2,2,2,2,3,2,1,1,2,1,1,1,
+ 4,3,2,2,2,1,1,1,3,2,1,1,2,1,1,1,
+ 7,6,5,5,4,4,4,4,3,3,3,3,3,3,3,3,
+ 4,3,2,2,2,2,2,2,3,2,2,2,2,2,2,2,
+ 5,4,3,3,2,2,2,2,3,2,1,1,2,1,1,1,
+ 4,3,2,2,2,1,1,1,3,2,1,1,2,1,1,1,
+ 6,5,4,4,3,3,3,3,3,2,2,2,2,2,2,2,
+ 4,3,2,2,2,1,1,1,3,2,1,1,2,1,1,1,
+ 5,4,3,3,2,2,2,2,3,2,1,1,2,1,1,1,
+ 4,3,2,2,2,1,1,1,3,2,1,1,2,1,1,0 };
+
+//
+// Lookup table that tells how many contiguous LOW order bits are clear
+// (i.e., 0) in a byte
+//
+
+CCHAR HalppBitsClearLow[] =
+ { 8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 };
+
+//
+// Lookup table that tells how many contiguous HIGH order bits are clear
+// (i.e., 0) in a byte
+//
+
+CCHAR HalppBitsClearHigh[] =
+ { 8,7,6,6,5,5,5,5,4,4,4,4,4,4,4,4,
+ 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
+
+//
+// Lookup table that tells how many clear bits (i.e., 0) there are in a byte
+//
+
+CCHAR HalppBitsClearTotal[] =
+ { 8,7,7,6,7,6,6,5,7,6,6,5,6,5,5,4,
+ 7,6,6,5,6,5,5,4,6,5,5,4,5,4,4,3,
+ 7,6,6,5,6,5,5,4,6,5,5,4,5,4,4,3,
+ 6,5,5,4,5,4,4,3,5,4,4,3,4,3,3,2,
+ 7,6,6,5,6,5,5,4,6,5,5,4,5,4,4,3,
+ 6,5,5,4,5,4,4,3,5,4,4,3,4,3,3,2,
+ 6,5,5,4,5,4,4,3,5,4,4,3,4,3,3,2,
+ 5,4,4,3,4,3,3,2,4,3,3,2,3,2,2,1,
+ 7,6,6,5,6,5,5,4,6,5,5,4,5,4,4,3,
+ 6,5,5,4,5,4,4,3,5,4,4,3,4,3,3,2,
+ 6,5,5,4,5,4,4,3,5,4,4,3,4,3,3,2,
+ 5,4,4,3,4,3,3,2,4,3,3,2,3,2,2,1,
+ 6,5,5,4,5,4,4,3,5,4,4,3,4,3,3,2,
+ 5,4,4,3,4,3,3,2,4,3,3,2,3,2,2,1,
+ 5,4,4,3,4,3,3,2,4,3,3,2,3,2,2,1,
+ 4,3,3,2,3,2,2,1,3,2,2,1,2,1,1,0 };
+
+//
+// Bit Mask for clearing and setting bits within bytes
+//
+
+static UCHAR FillMask[] = { 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF };
+
+static UCHAR ZeroMask[] = { 0xFF, 0xFE, 0xFC, 0xF8, 0xf0, 0xe0, 0xc0, 0x80, 0x00 };
+
+
+VOID
+HalpInitializeBitMap (
+ IN PRTL_BITMAP BitMapHeader,
+ IN PULONG BitMapBuffer,
+ IN ULONG SizeOfBitMap
+ )
+
+/*++
+
+Routine Description:
+
+ This procedure initializes a bit map.
+
+Arguments:
+
+ BitMapHeader - Supplies a pointer to the BitMap Header to initialize
+
+ BitMapBuffer - Supplies a pointer to the buffer that is to serve as the
+ BitMap. This must be an a multiple number of longwords in size.
+
+ SizeOfBitMap - Supplies the number of bits required in the Bit Map.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //RTL_PAGED_CODE();
+
+ //
+ // Initialize the BitMap header.
+ //
+
+ BitMapHeader->SizeOfBitMap = SizeOfBitMap;
+ BitMapHeader->Buffer = BitMapBuffer;
+
+ //
+ // And return to our caller
+ //
+
+ //DbgPrint("InitializeBitMap"); DumpBitMap(BitMapHeader);
+ return;
+}
+
+
+VOID
+HalpClearAllBits (
+ IN PRTL_BITMAP BitMapHeader
+ )
+
+/*++
+
+Routine Description:
+
+ This procedure clears all bits in the specified Bit Map.
+
+Arguments:
+
+ BitMapHeader - Supplies a pointer to the previously initialized BitMap
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Clear all the bits
+ //
+
+ RtlZeroMemory( BitMapHeader->Buffer,
+ ((BitMapHeader->SizeOfBitMap + 31) / 32) * 4
+ );
+
+ //
+ // And return to our caller
+ //
+
+ //DbgPrint("ClearAllBits"); DumpBitMap(BitMapHeader);
+ return;
+}
+
+
+VOID
+HalpSetAllBits (
+ IN PRTL_BITMAP BitMapHeader
+ )
+
+/*++
+
+Routine Description:
+
+ This procedure sets all bits in the specified Bit Map.
+
+Arguments:
+
+ BitMapHeader - Supplies a pointer to the previously initialized BitMap
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Set all the bits
+ //
+
+ RtlFillMemoryUlong( BitMapHeader->Buffer,
+ ((BitMapHeader->SizeOfBitMap + 31) / 32) * 4,
+ 0xffffffff
+ );
+
+ //
+ // And return to our caller
+ //
+
+ //DbgPrint("SetAllBits"); DumpBitMap(BitMapHeader);
+ return;
+}
+
+
+ULONG
+HalpFindClearBits (
+ IN PRTL_BITMAP BitMapHeader,
+ IN ULONG NumberToFind,
+ IN ULONG HintIndex
+ )
+
+/*++
+
+Routine Description:
+
+ This procedure searches the specified bit map for the specified
+ contiguous region of clear bits. If a run is not found from the
+ hint to the end of the bitmap, we will search again from the
+ beginning of the bitmap.
+
+Arguments:
+
+ BitMapHeader - Supplies a pointer to the previously initialized BitMap.
+
+ NumberToFind - Supplies the size of the contiguous region to find.
+
+ HintIndex - Supplies the index (zero based) of where we should start
+ the search from within the bitmap.
+
+Return Value:
+
+ ULONG - Receives the starting index (zero based) of the contiguous
+ region of clear bits found. If not such a region cannot be found
+ a -1 (i.e. 0xffffffff) is returned.
+
+--*/
+
+{
+ ULONG SizeOfBitMap;
+ ULONG SizeInBytes;
+
+ ULONG HintBit;
+ ULONG MainLoopIndex;
+
+ GET_BYTE_DECLARATIONS();
+
+ //
+ // To make the loops in our test run faster we'll extract the
+ // fields from the bitmap header
+ //
+
+ SizeOfBitMap = BitMapHeader->SizeOfBitMap;
+ SizeInBytes = (SizeOfBitMap + 7) / 8;
+
+ //
+ // Set any unused bits in the last byte so we won't count them. We do
+ // this by first checking if there is any odd bits in the last byte.
+ //
+
+ if ((SizeOfBitMap % 8) != 0) {
+
+ //
+ // The last byte has some odd bits so we'll set the high unused
+ // bits in the last byte to 1's
+ //
+
+ ((PUCHAR)BitMapHeader->Buffer)[SizeInBytes - 1] |=
+ ZeroMask[SizeOfBitMap % 8];
+ }
+
+ //
+ // Calculate from the hint index where the hint byte is and set ourselves
+ // up to read the hint on the next call to GET_BYTE. To make the
+ // algorithm run fast we'll only honor hints down to the byte level of
+ // granularity. There is a possibility that we'll need to execute
+ // our main logic twice. Once to test from the hint byte to the end of
+ // the bitmap and the other to test from the start of the bitmap. First
+ // we need to make sure the Hint Index is within range.
+ //
+
+ if (HintIndex >= SizeOfBitMap) {
+
+ HintIndex = 0;
+ }
+
+ HintBit = HintIndex % 8;
+
+ for (MainLoopIndex = 0; MainLoopIndex < 2; MainLoopIndex += 1) {
+
+ ULONG StartByteIndex;
+ ULONG EndByteIndex;
+
+ UCHAR CurrentByte;
+
+ //
+ // Check for the first time through the main loop, which indicates
+ // that we are going to start our search at our hint byte
+ //
+
+ if (MainLoopIndex == 0) {
+
+ StartByteIndex = HintIndex / 8;
+ EndByteIndex = SizeInBytes;
+
+ //
+ // This is the second time through the loop, make sure there is
+ // actually something to check before the hint byte
+ //
+
+ } else if (HintIndex != 0) {
+
+ //
+ // The end index for the second time around is based on the
+ // number of bits we need to find. We need to use this inorder
+ // to take the case where the preceding byte to the hint byte
+ // is the start of our run, and the run includes the hint byte
+ // and some following bytes, based on the number of bits needed
+ // The computation is to take the number of bits needed minus
+ // 2 divided by 8 and then add 2. This will take in to account
+ // the worst possible case where we have one bit hanging off
+ // of each end byte, and all intervening bytes are all zero.
+ //
+
+ if (NumberToFind < 2) {
+
+ EndByteIndex = 0;
+
+ } else {
+
+ EndByteIndex = (HintIndex / 8) + ((NumberToFind - 2) / 8) + 2;
+
+ //
+ // Make sure we don't overrun the end of the bitmap
+ //
+
+ if (EndByteIndex > SizeInBytes) {
+
+ EndByteIndex = SizeInBytes;
+ }
+ }
+
+ HintIndex = 0;
+ HintBit = 0;
+ StartByteIndex = 0;
+
+ //
+ // Otherwise we already did a complete loop through the bitmap
+ // so we should simply return -1 to say nothing was found
+ //
+
+ } else {
+
+ return 0xffffffff;
+ }
+
+ //
+ // Set ourselves up to get the next byte
+ //
+
+ GET_BYTE_INITIALIZATION(BitMapHeader, StartByteIndex);
+
+ //
+ // Get the first byte, and set any bits before the hint bit.
+ //
+
+ GET_BYTE( CurrentByte );
+
+ CurrentByte |= FillMask[HintBit];
+
+ //
+ // If the number of bits can only fit in 1 or 2 bytes (i.e., 9 bits or
+ // less) we do the following test case.
+ //
+
+ if (NumberToFind <= 9) {
+
+ ULONG CurrentBitIndex;
+ UCHAR PreviousByte;
+
+ PreviousByte = 0xff;
+
+ //
+ // Examine all the bytes within our test range searching
+ // for a fit
+ //
+
+ CurrentBitIndex = StartByteIndex * 8;
+
+ while (TRUE) {
+
+ //
+ // If this is the first itteration of the loop, mask Current
+ // byte with the real hint.
+ //
+
+ //
+ // The current byte does not satisfy our requirements so we'll
+ // check the previous and current byte together to see if
+ // we'll fit. To check uses the high part of the previous
+ // byte and low part of the current byte.
+ //
+
+ if (((ULONG)HalppBitsClearHigh[PreviousByte] +
+ (ULONG)HalppBitsClearLow[CurrentByte]) >= NumberToFind) {
+
+ ULONG StartingIndex;
+
+ //
+ // It all fits in these two bytes, so we can compute
+ // the starting index. This is done by taking the
+ // index of the current byte (bit 0) and subtracting the
+ // number of bits its takes to get to the first cleared
+ // high bit.
+ //
+
+ StartingIndex = CurrentBitIndex -
+ (LONG)HalppBitsClearHigh[PreviousByte];
+
+ //
+ // Now make sure the total size isn't beyond the bitmap
+ //
+
+ if ((StartingIndex + NumberToFind) <= SizeOfBitMap) {
+
+ return StartingIndex;
+ }
+ }
+
+ //
+ // Check to see if a single byte will satisfy the requirement
+ //
+
+ if ((ULONG)HalppBitsClearAnywhere[CurrentByte] >= NumberToFind) {
+
+ UCHAR BitMask;
+ ULONG i;
+
+ //
+ // It all fits in a single byte, so calculate the bit
+ // number. We do this by taking a mask of the appropriate
+ // size and shifting it over until it fits. It fits when
+ // we can bitwise-and the current byte with the bitmask
+ // and get a zero back.
+ //
+
+ BitMask = FillMask[ NumberToFind ];
+ for (i = 0; (BitMask & CurrentByte) != 0; i += 1) {
+
+ BitMask <<= 1;
+ }
+
+ //
+ // return to our caller the located bit index, and the
+ // number that we found.
+ //
+
+ return CurrentBitIndex + i;
+ }
+
+ //
+ // For the next iteration through our loop we need to make
+ // the current byte into the previous byte, and go to the
+ // top of the loop again.
+ //
+
+ PreviousByte = CurrentByte;
+
+ //
+ // Increment our Bit Index, and either exit, or get the
+ // next byte.
+ //
+
+ CurrentBitIndex += 8;
+
+ if ( CurrentBitIndex < EndByteIndex * 8 ) {
+
+ GET_BYTE( CurrentByte );
+
+ } else {
+
+ break;
+ }
+
+ } // end loop CurrentBitIndex
+
+ //
+ // The number to find is greater than 9 but if it is less than 15
+ // then we know it can be satisfied with at most 2 bytes, or 3 bytes
+ // if the middle byte (of the 3) is all zeros.
+ //
+
+ } else if (NumberToFind < 15) {
+
+ ULONG CurrentBitIndex;
+
+ UCHAR PreviousPreviousByte;
+ UCHAR PreviousByte;
+
+ PreviousPreviousByte = 0xff;
+ PreviousByte = 0xff;
+
+ //
+ // Examine all the bytes within our test range searching
+ // for a fit
+ //
+
+ CurrentBitIndex = StartByteIndex * 8;
+
+ while (TRUE) {
+
+ //
+ // Check to see if the Previous byte and current byte
+ // together satisfy the request.
+ //
+
+ if (((ULONG)HalppBitsClearHigh[PreviousByte] +
+ (ULONG)HalppBitsClearLow[CurrentByte]) >= NumberToFind) {
+
+ ULONG StartingIndex;
+
+ //
+ // It all fits in these two bytes, so we can compute
+ // the starting index. This is done by taking the
+ // index of the current byte (bit 0) and subtracting the
+ // number of bits its takes to get to the first cleared
+ // high bit.
+ //
+
+ StartingIndex = CurrentBitIndex -
+ (LONG)HalppBitsClearHigh[PreviousByte];
+
+ //
+ // Now make sure the total size isn't beyond the bitmap
+ //
+
+ if ((StartingIndex + NumberToFind) <= SizeOfBitMap) {
+
+ return StartingIndex;
+ }
+ }
+
+ //
+ // if the previous byte is all zeros then maybe the
+ // request can be satisfied using the Previous Previous Byte
+ // Previous Byte, and the Current Byte.
+ //
+
+ if ((PreviousByte == 0)
+
+ &&
+
+ (((ULONG)HalppBitsClearHigh[PreviousPreviousByte] + 8 +
+ (ULONG)HalppBitsClearLow[CurrentByte]) >= NumberToFind)) {
+
+ ULONG StartingIndex;
+
+ //
+ // It all fits in these three bytes, so we can compute
+ // the starting index. This is done by taking the
+ // index of the previous byte (bit 0) and subtracting
+ // the number of bits its takes to get to the first
+ // cleared high bit.
+ //
+
+ StartingIndex = (CurrentBitIndex - 8) -
+ (LONG)HalppBitsClearHigh[PreviousPreviousByte];
+
+ //
+ // Now make sure the total size isn't beyond the bitmap
+ //
+
+ if ((StartingIndex + NumberToFind) <= SizeOfBitMap) {
+
+ return StartingIndex;
+ }
+ }
+
+ //
+ // For the next iteration through our loop we need to make
+ // the current byte into the previous byte, the previous
+ // byte into the previous previous byte, and go to the
+ // top of the loop again.
+ //
+
+ PreviousPreviousByte = PreviousByte;
+ PreviousByte = CurrentByte;
+
+ //
+ // Increment our Bit Index, and either exit, or get the
+ // next byte.
+ //
+
+ CurrentBitIndex += 8;
+
+ if ( CurrentBitIndex < EndByteIndex * 8 ) {
+
+ GET_BYTE( CurrentByte );
+
+ } else {
+
+ break;
+ }
+
+ } // end loop CurrentBitIndex
+
+ //
+ // The number to find is greater than or equal to 15. This request
+ // has to have at least one byte of all zeros to be satisfied
+ //
+
+ } else {
+
+ ULONG CurrentByteIndex;
+
+ ULONG ZeroBytesNeeded;
+ ULONG ZeroBytesFound;
+
+ UCHAR StartOfRunByte;
+ LONG StartOfRunIndex;
+
+ //
+ // First precalculate how many zero bytes we're going to need
+ //
+
+ ZeroBytesNeeded = (NumberToFind - 7) / 8;
+
+ //
+ // Indicate for the first time through our loop that we haven't
+ // found a zero byte yet, and indicate that the start of the
+ // run is the byte just before the start byte index
+ //
+
+ ZeroBytesFound = 0;
+ StartOfRunByte = 0xff;
+ StartOfRunIndex = StartByteIndex - 1;
+
+ //
+ // Examine all the bytes in our test range searching for a fit
+ //
+
+ CurrentByteIndex = StartByteIndex;
+
+ while (TRUE) {
+
+ //
+ // If the number of zero bytes fits our minimum requirements
+ // then we can do the additional test to see if we
+ // actually found a fit
+ //
+
+ if ((ZeroBytesFound >= ZeroBytesNeeded)
+
+ &&
+
+ ((ULONG)HalppBitsClearHigh[StartOfRunByte] + ZeroBytesFound*8 +
+ (ULONG)HalppBitsClearLow[CurrentByte]) >= NumberToFind) {
+
+ ULONG StartingIndex;
+
+ //
+ // It all fits in these bytes, so we can compute
+ // the starting index. This is done by taking the
+ // StartOfRunIndex times 8 and adding the number of bits
+ // it takes to get to the first cleared high bit.
+ //
+
+ StartingIndex = (StartOfRunIndex * 8) +
+ (8 - (LONG)HalppBitsClearHigh[StartOfRunByte]);
+
+ //
+ // Now make sure the total size isn't beyond the bitmap
+ //
+
+ if ((StartingIndex + NumberToFind) <= SizeOfBitMap) {
+
+ return StartingIndex;
+ }
+ }
+
+ //
+ // Check to see if the byte is zero and increment
+ // the number of zero bytes found
+ //
+
+ if (CurrentByte == 0) {
+
+ ZeroBytesFound += 1;
+
+ //
+ // The byte isn't a zero so we need to start over again
+ // looking for zero bytes.
+ //
+
+ } else {
+
+ ZeroBytesFound = 0;
+ StartOfRunByte = CurrentByte;
+ StartOfRunIndex = CurrentByteIndex;
+ }
+
+ //
+ // Increment our Byte Index, and either exit, or get the
+ // next byte.
+ //
+
+ CurrentByteIndex += 1;
+
+ if ( CurrentByteIndex < EndByteIndex ) {
+
+ GET_BYTE( CurrentByte );
+
+ } else {
+
+ break;
+ }
+
+ } // end loop CurrentByteIndex
+ }
+ }
+
+ //
+ // We never found a fit so we'll return -1
+ //
+
+ return 0xffffffff;
+}
+
+
+ULONG
+HalpFindSetBits (
+ IN PRTL_BITMAP BitMapHeader,
+ IN ULONG NumberToFind,
+ IN ULONG HintIndex
+ )
+
+/*++
+
+Routine Description:
+
+ This procedure searches the specified bit map for the specified
+ contiguous region of set bits.
+
+Arguments:
+
+ BitMapHeader - Supplies a pointer to the previously initialized BitMap.
+
+ NumberToFind - Supplies the size of the contiguous region to find.
+
+ HintIndex - Supplies the index (zero based) of where we should start
+ the search from within the bitmap.
+
+Return Value:
+
+ ULONG - Receives the starting index (zero based) of the contiguous
+ region of set bits found. If such a region cannot be found then
+ a -1 (i.e., 0xffffffff) is returned.
+
+--*/
+
+{
+ ULONG SizeOfBitMap;
+ ULONG SizeInBytes;
+
+ ULONG HintByte;
+
+ ULONG MainLoopIndex;
+
+ GET_BYTE_DECLARATIONS();
+
+ //
+ // To make the loops in our test run faster we'll extract the
+ // fields from the bitmap header
+ //
+
+ SizeOfBitMap = BitMapHeader->SizeOfBitMap;
+ SizeInBytes = (SizeOfBitMap + 7) / 8;
+
+ //
+ // Set any unused bits in the last byte so we won't count them. We do
+ // this by first checking if there is any odd bits in the last byte.
+ //
+
+ if ((SizeOfBitMap % 8) != 0) {
+
+ //
+ // The last byte has some odd bits so we'll set the high unused
+ // bits in the last byte to 0's
+ //
+
+ ((PUCHAR)BitMapHeader->Buffer)[SizeInBytes - 1] &=
+ FillMask[SizeOfBitMap % 8];
+ }
+
+ //
+ // Calculate from the hint index where the hint byte is and set ourselves
+ // up to read the hint on the next call to GET_BYTE. To make the
+ // algorithm run fast we'll only honor hints down to the byte level of
+ // granularity. There is a possibility that we'll need to execute
+ // our main logic twice. Once to test from the hint byte to the end of
+ // the bitmap and the other to test from the start of the bitmap. First
+ // we need to make sure the Hint Index is within range.
+ //
+
+ if (HintIndex >= SizeOfBitMap) {
+
+ HintIndex = 0;
+ }
+
+ HintByte = HintIndex / 8;
+
+ for (MainLoopIndex = 0; MainLoopIndex < 2; MainLoopIndex += 1) {
+
+ ULONG StartByteIndex;
+ ULONG EndByteIndex;
+
+ //
+ // Check for the first time through the main loop, which indicates
+ // that we are going to start our search at our hint byte
+ //
+
+ if (MainLoopIndex == 0) {
+
+ StartByteIndex = HintByte;
+ EndByteIndex = SizeInBytes;
+
+ //
+ // This is the second time through the loop, make sure there is
+ // actually something to check before the hint byte
+ //
+
+ } else if (HintByte != 0) {
+
+ StartByteIndex = 0;
+
+ //
+ // The end index for the second time around is based on the
+ // number of bits we need to find. We need to use this inorder
+ // to take the case where the preceding byte to the hint byte
+ // is the start of our run, and the run includes the hint byte
+ // and some following bytes, based on the number of bits needed
+ // The computation is to take the number of bits needed minus
+ // 2 divided by 8 and then add 2. This will take in to account
+ // the worst possible case where we have one bit hanging off
+ // of each end byte, and all intervening bytes are all zero.
+ // We only need to add one in the following equation because
+ // HintByte is already counted.
+ //
+
+ if (NumberToFind < 2) {
+
+ EndByteIndex = HintByte;
+
+ } else {
+
+ EndByteIndex = HintByte + ((NumberToFind - 2) / 8) + 1;
+
+ //
+ // Make sure we don't overrun the end of the bitmap
+ //
+
+ if (EndByteIndex > SizeInBytes) {
+
+ EndByteIndex = SizeInBytes;
+ }
+ }
+
+ //
+ // Otherwise we already did a complete loop through the bitmap
+ // so we should simply return -1 to say nothing was found
+ //
+
+ } else {
+
+ return 0xffffffff;
+
+ }
+
+ //
+ // Set ourselves up to get the next byte
+ //
+
+ GET_BYTE_INITIALIZATION(BitMapHeader, StartByteIndex);
+
+ //
+ // If the number of bits can only fit in 1 or 2 bytes (i.e., 9 bits or
+ // less) we do the following test case.
+ //
+
+ if (NumberToFind <= 9) {
+
+ ULONG CurrentBitIndex;
+
+ UCHAR PreviousByte;
+ UCHAR CurrentByte;
+
+ PreviousByte = 0x00;
+
+ //
+ // Examine all the bytes within our test range searching
+ // for a fit
+ //
+
+ for (CurrentBitIndex = StartByteIndex * 8;
+ CurrentBitIndex < EndByteIndex * 8;
+ CurrentBitIndex += 8) {
+
+ //
+ // Get the current byte
+ //
+
+ GET_BYTE( CurrentByte );
+
+ //
+ // Check to see if a single byte will satisfy the requirement
+ //
+
+ if ((ULONG)HalppBitSetAnywhere(CurrentByte) >= NumberToFind) {
+
+ UCHAR BitMask;
+ ULONG i;
+
+ //
+ // It all fits in a single byte, so calculate the bit
+ // number. We do this by taking a mask of the appropriate
+ // size and shifting it over until it fits. It fits when
+ // we can bitwise-and the current byte with the bit mask
+ // and get back the bit mask.
+ //
+
+ BitMask = FillMask[ NumberToFind ];
+ for (i = 0; (BitMask & CurrentByte) != BitMask; i += 1) {
+
+ BitMask <<= 1;
+ }
+
+ //
+ // return to our caller the located bit index, and the
+ // number that we found.
+ //
+
+ return CurrentBitIndex + i;
+ }
+
+ //
+ // The current byte does not satisfy our requirements so we'll
+ // check the previous and current byte together to see if
+ // we'll fit. To check uses the high part of the previous
+ // byte and low part of the current byte.
+ //
+
+ if (((ULONG)HalppBitsSetHigh(PreviousByte) +
+ (ULONG)HalppBitsSetLow(CurrentByte)) >= NumberToFind) {
+
+ ULONG StartingIndex;
+
+ //
+ // It all fits in these two bytes, so we can compute
+ // the starting index. This is done by taking the
+ // index of the current byte (bit 0) and subtracting the
+ // number of bits its takes to get to the first set
+ // high bit.
+ //
+
+ StartingIndex = CurrentBitIndex -
+ (LONG)HalppBitsSetHigh(PreviousByte);
+
+ //
+ // Now make sure the total size isn't beyond the bitmap
+ //
+
+ if ((StartingIndex + NumberToFind) <= SizeOfBitMap) {
+
+ return StartingIndex;
+ }
+ }
+
+ //
+ // For the next iteration through our loop we need to make
+ // the current byte into the previous byte, and go to the
+ // top of the loop again.
+ //
+
+ PreviousByte = CurrentByte;
+
+ } // end loop CurrentBitIndex
+
+ //
+ // The number to find is greater than 9 but if it is less than 15
+ // then we know it can be satisfied with at most 2 bytes, or 3 bytes
+ // if the middle byte (of the 3) is all ones.
+ //
+
+ } else if (NumberToFind < 15) {
+
+ ULONG CurrentBitIndex;
+
+ UCHAR PreviousPreviousByte;
+ UCHAR PreviousByte;
+ UCHAR CurrentByte;
+
+ PreviousPreviousByte = 0x00;
+ PreviousByte = 0x00;
+
+ //
+ // Examine all the bytes within our test range searching
+ // for a fit
+ //
+
+ for (CurrentBitIndex = StartByteIndex * 8;
+ CurrentBitIndex < EndByteIndex * 8;
+ CurrentBitIndex += 8) {
+
+ //
+ // Get the current byte
+ //
+
+ GET_BYTE( CurrentByte );
+
+ //
+ // Check to see if the Previous byte and current byte
+ // together satisfy the request.
+ //
+
+ if (((ULONG)HalppBitsSetHigh(PreviousByte) +
+ (ULONG)HalppBitsSetLow(CurrentByte)) >= NumberToFind) {
+
+ ULONG StartingIndex;
+
+ //
+ // It all fits in these two bytes, so we can compute
+ // the starting index. This is done by taking the
+ // index of the current byte (bit 0) and subtracting the
+ // number of bits its takes to get to the first set
+ // high bit.
+ //
+
+ StartingIndex = CurrentBitIndex -
+ (LONG)HalppBitsSetHigh(PreviousByte);
+
+ //
+ // Now make sure the total size isn't beyond the bitmap
+ //
+
+ if ((StartingIndex + NumberToFind) <= SizeOfBitMap) {
+
+ return StartingIndex;
+ }
+ }
+
+ //
+ // if the previous byte is all ones then maybe the
+ // request can be satisfied using the Previous Previous Byte
+ // Previous Byte, and the Current Byte.
+ //
+
+ if ((PreviousByte == 0xff)
+
+ &&
+
+ (((ULONG)HalppBitsSetHigh(PreviousPreviousByte) + 8 +
+ (ULONG)HalppBitsSetLow(CurrentByte)) >= NumberToFind)) {
+
+ ULONG StartingIndex;
+
+ //
+ // It all fits in these three bytes, so we can compute
+ // the starting index. This is done by taking the
+ // index of the previous byte (bit 0) and subtracting
+ // the number of bits its takes to get to the first
+ // set high bit.
+ //
+
+ StartingIndex = (CurrentBitIndex - 8) -
+ (LONG)HalppBitsSetHigh(PreviousPreviousByte);
+
+ //
+ // Now make sure the total size isn't beyond the bitmap
+ //
+
+ if ((StartingIndex + NumberToFind) <= SizeOfBitMap) {
+
+ return StartingIndex;
+ }
+ }
+
+ //
+ // For the next iteration through our loop we need to make
+ // the current byte into the previous byte, the previous
+ // byte into the previous previous byte, and go to the
+ // top of the loop again.
+ //
+
+ PreviousPreviousByte = PreviousByte;
+ PreviousByte = CurrentByte;
+
+ } // end loop CurrentBitIndex
+
+ //
+ // The number to find is greater than or equal to 15. This request
+ // has to have at least one byte of all ones to be satisfied
+ //
+
+ } else {
+
+ ULONG CurrentByteIndex;
+
+ UCHAR CurrentByte;
+
+ ULONG OneBytesNeeded;
+ ULONG OneBytesFound;
+
+ UCHAR StartOfRunByte;
+ LONG StartOfRunIndex;
+
+ //
+ // First precalculate how many one bytes we're going to need
+ //
+
+ OneBytesNeeded = (NumberToFind - 7) / 8;
+
+ //
+ // Indicate for the first time through our loop that we haven't
+ // found a one byte yet, and indicate that the start of the
+ // run is the byte just before the start byte index
+ //
+
+ OneBytesFound = 0;
+ StartOfRunByte = 0x00;
+ StartOfRunIndex = StartByteIndex - 1;
+
+ //
+ // Examine all the bytes in our test range searching for a fit
+ //
+
+ for (CurrentByteIndex = StartByteIndex;
+ CurrentByteIndex < EndByteIndex;
+ CurrentByteIndex += 1) {
+
+ //
+ // Get the current byte
+ //
+
+ GET_BYTE( CurrentByte );
+
+ //
+ // If the number of zero bytes fits our minimum requirements
+ // then we can do the additional test to see if we
+ // actually found a fit
+ //
+
+ if ((OneBytesFound >= OneBytesNeeded)
+
+ &&
+
+ ((ULONG)HalppBitsSetHigh(StartOfRunByte) + OneBytesFound*8 +
+ (ULONG)HalppBitsSetLow(CurrentByte)) >= NumberToFind) {
+
+ ULONG StartingIndex;
+
+ //
+ // It all fits in these bytes, so we can compute
+ // the starting index. This is done by taking the
+ // StartOfRunIndex times 8 and adding the number of bits
+ // it takes to get to the first set high bit.
+ //
+
+ StartingIndex = (StartOfRunIndex * 8) +
+ (8 - (LONG)HalppBitsSetHigh(StartOfRunByte));
+
+ //
+ // Now make sure the total size isn't beyond the bitmap
+ //
+
+ if ((StartingIndex + NumberToFind) <= SizeOfBitMap) {
+
+ return StartingIndex;
+ }
+ }
+
+ //
+ // Check to see if the byte is all ones and increment
+ // the number of one bytes found
+ //
+
+ if (CurrentByte == 0xff) {
+
+ OneBytesFound += 1;
+
+ //
+ // The byte isn't all ones so we need to start over again
+ // looking for one bytes.
+ //
+
+ } else {
+
+ OneBytesFound = 0;
+ StartOfRunByte = CurrentByte;
+ StartOfRunIndex = CurrentByteIndex;
+ }
+
+ } // end loop CurrentByteIndex
+ }
+ }
+
+ //
+ // We never found a fit so we'll return -1
+ //
+
+ return 0xffffffff;
+}
+
+
+ULONG
+HalpFindClearBitsAndSet (
+ IN PRTL_BITMAP BitMapHeader,
+ IN ULONG NumberToFind,
+ IN ULONG HintIndex
+ )
+
+/*++
+
+Routine Description:
+
+ This procedure searches the specified bit map for the specified
+ contiguous region of clear bits, sets the bits and returns the
+ number of bits found, and the starting bit number which was clear
+ then set.
+
+Arguments:
+
+ BitMapHeader - Supplies a pointer to the previously initialized BitMap.
+
+ NumberToFind - Supplies the size of the contiguous region to find.
+
+ HintIndex - Supplies the index (zero based) of where we should start
+ the search from within the bitmap.
+
+Return Value:
+
+ ULONG - Receives the starting index (zero based) of the contiguous
+ region found. If such a region cannot be located a -1 (i.e.,
+ 0xffffffff) is returned.
+
+--*/
+
+{
+ ULONG StartingIndex;
+
+ //
+ // First look for a run of clear bits that equals the size requested
+ //
+
+ StartingIndex = HalpFindClearBits( BitMapHeader,
+ NumberToFind,
+ HintIndex );
+
+ //DbgPrint("FindClearBits %08lx, ", NumberToFind);
+ //DbgPrint("%08lx", StartingIndex);
+ //DumpBitMap(BitMapHeader);
+
+ if (StartingIndex != 0xffffffff) {
+
+ //
+ // We found a large enough run of clear bits so now set them
+ //
+
+ HalpSetBits( BitMapHeader, StartingIndex, NumberToFind );
+ }
+
+ //
+ // And return to our caller
+ //
+
+ return StartingIndex;
+
+}
+
+
+ULONG
+HalpFindSetBitsAndClear (
+ IN PRTL_BITMAP BitMapHeader,
+ IN ULONG NumberToFind,
+ IN ULONG HintIndex
+ )
+
+/*++
+
+Routine Description:
+
+ This procedure searches the specified bit map for the specified
+ contiguous region of set bits, clears the bits and returns the
+ number of bits found and the starting bit number which was set then
+ clear.
+
+Arguments:
+
+ BitMapHeader - Supplies a pointer to the previously initialized BitMap.
+
+ NumberToFind - Supplies the size of the contiguous region to find.
+
+ HintIndex - Supplies the index (zero based) of where we should start
+ the search from within the bitmap.
+
+Return Value:
+
+ ULONG - Receives the starting index (zero based) of the contiguous
+ region found. If such a region cannot be located a -1 (i.e.,
+ 0xffffffff) is returned.
+
+
+--*/
+
+{
+ ULONG StartingIndex;
+
+ //
+ // First look for a run of set bits that equals the size requested
+ //
+
+ if ((StartingIndex = HalpFindSetBits( BitMapHeader,
+ NumberToFind,
+ HintIndex )) != 0xffffffff) {
+
+ //
+ // We found a large enough run of set bits so now clear them
+ //
+
+ HalpClearBits( BitMapHeader, StartingIndex, NumberToFind );
+ }
+
+ //
+ // And return to our caller
+ //
+
+ return StartingIndex;
+}
+
+
+VOID
+HalpClearBits (
+ IN PRTL_BITMAP BitMapHeader,
+ IN ULONG StartingIndex,
+ IN ULONG NumberToClear
+ )
+
+/*++
+
+Routine Description:
+
+ This procedure clears the specified range of bits within the
+ specified bit map.
+
+Arguments:
+
+ BitMapHeader - Supplies a pointer to the previously initialized Bit Map.
+
+ StartingIndex - Supplies the index (zero based) of the first bit to clear.
+
+ NumberToClear - Supplies the number of bits to clear.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG BitOffset;
+ PULONG CurrentLong;
+
+ //DbgPrint("ClearBits %08lx, ", NumberToClear);
+ //DbgPrint("%08lx", StartingIndex);
+
+ ASSERT( StartingIndex + NumberToClear <= BitMapHeader->SizeOfBitMap );
+
+ //
+ // Special case the situation where the number of bits to clear is
+ // zero. Turn this into a noop.
+ //
+
+ if (NumberToClear == 0) {
+
+ return;
+ }
+
+ BitOffset = StartingIndex % 32;
+
+ //
+ // Get a pointer to the first longword that needs to be zeroed out
+ //
+
+ CurrentLong = &BitMapHeader->Buffer[ StartingIndex / 32 ];
+
+ //
+ // Check if we can only need to clear out one longword.
+ //
+
+ if ((BitOffset + NumberToClear) <= 32) {
+
+ //
+ // To build a mask of bits to clear we shift left to get the number
+ // of bits we're clearing and then shift right to put it in position.
+ // We'll typecast the right shift to ULONG to make sure it doesn't
+ // do a sign extend.
+ //
+
+ *CurrentLong &= ~LeftShiftUlong(RightShiftUlong(((ULONG)0xFFFFFFFF),(32 - NumberToClear)),
+ BitOffset);
+
+ //
+ // And return to our caller
+ //
+
+ //DumpBitMap(BitMapHeader);
+
+ return;
+ }
+
+ //
+ // We can clear out to the end of the first longword so we'll
+ // do that right now.
+ //
+
+ *CurrentLong &= ~LeftShiftUlong(0xFFFFFFFF, BitOffset);
+
+ //
+ // And indicate what the next longword to clear is and how many
+ // bits are left to clear
+ //
+
+ CurrentLong += 1;
+ NumberToClear -= 32 - BitOffset;
+
+ //
+ // The bit position is now long aligned, so we can continue
+ // clearing longwords until the number to clear is less than 32
+ //
+
+ while (NumberToClear >= 32) {
+
+ *CurrentLong = 0;
+ CurrentLong += 1;
+ NumberToClear -= 32;
+ }
+
+ //
+ // And now we can clear the remaining bits, if there are any, in the
+ // last longword
+ //
+
+ if (NumberToClear > 0) {
+
+ *CurrentLong &= LeftShiftUlong(0xFFFFFFFF, NumberToClear);
+ }
+
+ //
+ // And return to our caller
+ //
+
+ //DumpBitMap(BitMapHeader);
+
+ return;
+}
+
+VOID
+HalpSetBits (
+ IN PRTL_BITMAP BitMapHeader,
+ IN ULONG StartingIndex,
+ IN ULONG NumberToSet
+ )
+
+/*++
+
+Routine Description:
+
+ This procedure sets the specified range of bits within the
+ specified bit map.
+
+Arguments:
+
+ BitMapHeader - Supplies a pointer to the previously initialied BitMap.
+
+ StartingIndex - Supplies the index (zero based) of the first bit to set.
+
+ NumberToSet - Supplies the number of bits to set.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG BitOffset;
+ PULONG CurrentLong;
+
+ //DbgPrint("SetBits %08lx, ", NumberToSet);
+ //DbgPrint("%08lx", StartingIndex);
+
+ ASSERT( StartingIndex + NumberToSet <= BitMapHeader->SizeOfBitMap );
+
+ //
+ // Special case the situation where the number of bits to set is
+ // zero. Turn this into a noop.
+ //
+
+ if (NumberToSet == 0) {
+
+ return;
+ }
+
+ BitOffset = StartingIndex % 32;
+
+ //
+ // Get a pointer to the first longword that needs to be set
+ //
+
+ CurrentLong = &BitMapHeader->Buffer[ StartingIndex / 32 ];
+
+ //
+ // Check if we can only need to set one longword.
+ //
+
+ if ((BitOffset + NumberToSet) <= 32) {
+
+ //
+ // To build a mask of bits to set we shift left to get the number
+ // of bits we're setting and then shift right to put it in position.
+ // We'll typecast the right shift to ULONG to make sure it doesn't
+ // do a sign extend.
+ //
+
+ *CurrentLong |= LeftShiftUlong(RightShiftUlong(((ULONG)0xFFFFFFFF),(32 - NumberToSet)),
+ BitOffset);
+
+ //
+ // And return to our caller
+ //
+
+ //DumpBitMap(BitMapHeader);
+
+ return;
+ }
+
+ //
+ // We can set bits out to the end of the first longword so we'll
+ // do that right now.
+ //
+
+ *CurrentLong |= LeftShiftUlong(0xFFFFFFFF, BitOffset);
+
+ //
+ // And indicate what the next longword to set is and how many
+ // bits are left to set
+ //
+
+ CurrentLong += 1;
+ NumberToSet -= 32 - BitOffset;
+
+ //
+ // The bit position is now long aligned, so we can continue
+ // setting longwords until the number to set is less than 32
+ //
+
+ while (NumberToSet >= 32) {
+
+ *CurrentLong = 0xffffffff;
+ CurrentLong += 1;
+ NumberToSet -= 32;
+ }
+
+ //
+ // And now we can set the remaining bits, if there are any, in the
+ // last longword
+ //
+
+ if (NumberToSet > 0) {
+
+ *CurrentLong |= ~LeftShiftUlong(0xFFFFFFFF, NumberToSet);
+ }
+
+ //
+ // And return to our caller
+ //
+
+ //DumpBitMap(BitMapHeader);
+
+ return;
+}
+
+
+ULONG
+HalpFindLongestRunClear (
+ IN PRTL_BITMAP BitMapHeader,
+ OUT PULONG StartingIndex
+ )
+
+/*++
+
+Routine Description:
+
+ This procedure finds the largest contiguous range of clear bits
+ within the specified bit map.
+
+Arguments:
+
+ BitMapHeader - Supplies a pointer to the previously initialized BitMap.
+
+ StartingIndex - Receives the index (zero based) of the first run
+ equal to the longest run of clear bits in the BitMap.
+
+Return Value:
+
+ ULONG - Receives the number of bits contained in the largest contiguous
+ run of clear bits.
+
+--*/
+
+{
+ ULONG SizeOfBitMap;
+ ULONG SizeInBytes;
+
+ ULONG LongestRunSize;
+ ULONG LongestRunIndex;
+
+ ULONG CurrentRunSize;
+ ULONG CurrentRunIndex;
+ ULONG CurrentByteIndex;
+ UCHAR CurrentByte;
+
+ GET_BYTE_DECLARATIONS();
+
+ //
+ // Reference the bitmap header to make the loop run faster
+ //
+
+ SizeOfBitMap = BitMapHeader->SizeOfBitMap;
+ SizeInBytes = (SizeOfBitMap + 7) / 8;
+
+ //
+ // Set any unused bits in the last byte so we won't count them. We do
+ // this by first checking if there is any odd bits in the last byte.
+ //
+
+ if ((SizeOfBitMap % 8) != 0) {
+
+ //
+ // The last byte has some odd bits so we'll set the high unused
+ // bits in the last byte to 1's
+ //
+
+ ((PUCHAR)BitMapHeader->Buffer)[SizeInBytes - 1] |=
+ ZeroMask[SizeOfBitMap % 8];
+ }
+
+ //
+ // Set it up so we can the use GET_BYTE macro
+ //
+
+ GET_BYTE_INITIALIZATION( BitMapHeader, 0);
+
+ //
+ // Set our longest and current run variables
+ //
+
+ LongestRunSize = 0;
+ LongestRunIndex = 0;
+
+ CurrentRunSize = 0;
+ CurrentRunIndex = 0;
+
+ //
+ // Examine every byte in the BitMap
+ //
+
+ for (CurrentByteIndex = 0;
+ CurrentByteIndex < SizeInBytes;
+ CurrentByteIndex += 1) {
+
+ GET_BYTE( CurrentByte );
+
+ //
+ // If the current byte is not all zeros we need to
+ // (1) check if the current run is big enough to supercede the
+ // longest run, and (2) check if the current byte inside of
+ // itself can supercede the longest run, and (3) start a new
+ // current run
+ //
+
+ if (CurrentByte != 0x00) {
+
+ UCHAR Temp;
+
+ //
+ // Compute the final size of the current run
+ //
+
+ CurrentRunSize += HalppBitsClearLow[CurrentByte];
+
+ //
+ // Check if the current run is larger than the longest run that
+ // we've found so far
+ //
+
+ if (CurrentRunSize > LongestRunSize) {
+
+ LongestRunSize = CurrentRunSize;
+ LongestRunIndex = CurrentRunIndex;
+ }
+
+ //
+ // The next run starts with the remaining clear bits in the
+ // current byte. We set this up before we check inside the
+ // current byte for a longer run, because the latter test
+ // might require extra work.
+ //
+
+ CurrentRunSize = HalppBitsClearHigh[ CurrentByte ];
+ CurrentRunIndex = (CurrentByteIndex * 8) + (8 - CurrentRunSize);
+
+ //
+ // Check if the current byte contains a run inside of it that
+ // is both greater than the longest run size, and the current
+ // run size. But we'll only both with this test if the
+ // longest run size, and current run size are both less than 8.
+ //
+
+ if ((LongestRunSize < 8) && (CurrentRunSize < 8) &&
+ ((ULONG)(Temp = HalppBitsClearAnywhere[CurrentByte]) > LongestRunSize) &&
+ ((ULONG)Temp > CurrentRunSize)) {
+
+ UCHAR BitMask;
+ ULONG i;
+
+ //
+ // Somewhere in the current byte is a run longer than the
+ // longest run, or the current run. All we need to do now
+ // is find the index for this new longest run.
+ //
+
+ BitMask = FillMask[ Temp ];
+
+ for (i = 0; (BitMask & CurrentByte) != 0; i += 1) {
+
+ BitMask <<= 1;
+ }
+
+ LongestRunIndex = (CurrentByteIndex * 8) + i;
+ LongestRunSize = Temp;
+ }
+
+ //
+ // Otherwise the current byte is all zeros and
+ // we simply continue with the current run
+ //
+
+ } else {
+
+ CurrentRunSize += 8;
+ }
+ }
+
+ //
+ // See if we finished looking over the bitmap with an open current
+ // run that is longer than the longest saved run
+ //
+
+ if (CurrentRunSize > LongestRunSize) {
+
+ LongestRunSize = CurrentRunSize;
+ LongestRunIndex = CurrentRunIndex;
+ }
+
+ //
+ // Set our output variables and return to our caller
+ //
+
+ *StartingIndex = LongestRunIndex;
+ return LongestRunSize;
+}
+
+
+ULONG
+HalpFindLongestRunSet (
+ IN PRTL_BITMAP BitMapHeader,
+ OUT PULONG StartingIndex
+ )
+
+/*++
+
+Routine Description:
+
+ This procedure finds the largest contiguous range of set bits
+ within the specified bit map.
+
+Arguments:
+
+ BitMapHeader - Supplies a pointer to the previously initialized BitMap.
+
+ StartingIndex - Receives the index (zero based) of the first run
+ equal to the longest run of set bits in the BitMap.
+
+Return Value:
+
+ ULONG - Receives the number of bits contained in the largest contiguous
+ run of set bits.
+
+--*/
+
+{
+ ULONG SizeOfBitMap;
+ ULONG SizeInBytes;
+
+ ULONG LongestRunSize;
+ ULONG LongestRunIndex;
+
+ ULONG CurrentRunSize;
+ ULONG CurrentRunIndex;
+ ULONG CurrentByteIndex;
+ UCHAR CurrentByte;
+
+ GET_BYTE_DECLARATIONS();
+
+ //
+ // Reference the bitmap header to make the loop run faster
+ //
+
+ SizeOfBitMap = BitMapHeader->SizeOfBitMap;
+ SizeInBytes = (SizeOfBitMap + 7) / 8;
+
+ //
+ // Set any unused bits in the last byte so we won't count them. We do
+ // this by first checking if there is any odd bits in the last byte.
+ //
+
+ if ((SizeOfBitMap % 8) != 0) {
+
+ //
+ // The last byte has some odd bits so we'll set the high unused
+ // bits in the last byte to 0's
+ //
+
+ ((PUCHAR)BitMapHeader->Buffer)[SizeInBytes - 1] &=
+ FillMask[SizeOfBitMap % 8];
+ }
+
+ //
+ // Set it up so we can the use GET_BYTE macro
+ //
+
+ GET_BYTE_INITIALIZATION( BitMapHeader, 0);
+
+ //
+ // Set our longest and current run variables
+ //
+
+ LongestRunSize = 0;
+ LongestRunIndex = 0;
+
+ CurrentRunSize = 0;
+ CurrentRunIndex = 0;
+
+ //
+ // Examine every byte in the BitMap
+ //
+
+ for (CurrentByteIndex = 0;
+ CurrentByteIndex < SizeInBytes;
+ CurrentByteIndex += 1) {
+
+ GET_BYTE( CurrentByte );
+
+ //
+ // If the current byte is not all ones we need to
+ // (1) check if the current run is big enough to supercede the
+ // longest run, and (2) check if the current byte inside of
+ // itself can supercede the longest run, and (3) start a new
+ // current run
+ //
+
+ if (CurrentByte != 0xff) {
+
+ UCHAR Temp;
+
+ //
+ // Compute the final size of the current run
+ //
+
+ CurrentRunSize += HalppBitsSetLow(CurrentByte);
+
+ //
+ // Check if the current run is larger than the longest run that
+ // we've found so far
+ //
+
+ if (CurrentRunSize > LongestRunSize) {
+
+ LongestRunSize = CurrentRunSize;
+ LongestRunIndex = CurrentRunIndex;
+ }
+
+ //
+ // The next run starts with the remaining set bits in the
+ // current byte. We set this up before we check inside the
+ // current byte for a longer run, because the latter test
+ // might require extra work.
+ //
+
+ CurrentRunSize = HalppBitsSetHigh( CurrentByte );
+ CurrentRunIndex = (CurrentByteIndex * 8) + (8 - CurrentRunSize);
+
+ //
+ // Check if the current byte contains a run inside of it that
+ // is both greater than the longest run size, and the current
+ // run size. But we'll only both with this test if the
+ // longest run size, and current run size are both less than 8.
+ //
+
+ if ((LongestRunSize < 8) && (CurrentRunSize < 8) &&
+ ((ULONG)(Temp = HalppBitSetAnywhere(CurrentByte)) > LongestRunSize) &&
+ ((ULONG)Temp > CurrentRunSize)) {
+
+ UCHAR BitMask;
+ ULONG i;
+
+ //
+ // Somewhere in the current byte is a run longer than the
+ // longest run, or the current run. All we need to do now
+ // is find the index for this new longest run.
+ //
+
+ BitMask = FillMask[ Temp ];
+
+ for (i = 0; (BitMask & CurrentByte) != BitMask; i += 1) {
+
+ BitMask <<= 1;
+ }
+
+ LongestRunIndex = (CurrentByteIndex * 8) + i;
+ LongestRunSize = Temp;
+ }
+
+ //
+ // Otherwise the current byte is all ones and
+ // we simply continue with the current run
+ //
+
+ } else {
+
+ CurrentRunSize += 8;
+ }
+ }
+
+ //
+ // See if we finished looking over the bitmap with an open current
+ // run that is longer than the longest saved run
+ //
+
+ if (CurrentRunSize > LongestRunSize) {
+
+ LongestRunSize = CurrentRunSize;
+ LongestRunIndex = CurrentRunIndex;
+ }
+
+ //
+ // Set our output variables and return to our caller
+ //
+
+ *StartingIndex = LongestRunIndex;
+ return LongestRunSize;
+}
+
+
+ULONG
+HalpFindFirstRunClear (
+ IN PRTL_BITMAP BitMapHeader,
+ OUT PULONG StartingIndex
+ )
+
+/*++
+
+Routine Description:
+
+ This procedure finds the first contiguous range of clear bits
+ within the specified bit map.
+
+Arguments:
+
+ BitMapHeader - Supplies a pointer to the previously initialized BitMap.
+
+ StartingIndex - Receives the index (zero based) of the first run
+ equal to the longest run of clear bits in the BitMap.
+
+Return Value:
+
+ ULONG - Receives the number of bits contained in the first contiguous
+ run of clear bits.
+
+--*/
+
+{
+ ULONG SizeOfBitMap;
+ ULONG SizeInBytes;
+
+ ULONG CurrentRunSize;
+ ULONG CurrentRunIndex;
+ ULONG CurrentByteIndex;
+ UCHAR CurrentByte;
+
+ GET_BYTE_DECLARATIONS();
+
+ //
+ // Reference the bitmap header to make the loop run faster
+ //
+
+ SizeOfBitMap = BitMapHeader->SizeOfBitMap;
+ SizeInBytes = (SizeOfBitMap + 7) / 8;
+
+ //
+ // Set any unused bits in the last byte so we won't count them. We do
+ // this by first checking if there is any odd bits in the last byte.
+ //
+
+ if ((SizeOfBitMap % 8) != 0) {
+
+ //
+ // The last byte has some odd bits so we'll set the high unused
+ // bits in the last byte to 1's
+ //
+
+ ((PUCHAR)BitMapHeader->Buffer)[SizeInBytes - 1] |=
+ ZeroMask[SizeOfBitMap % 8];
+
+ }
+
+ //
+ // Set it up so we can the use GET_BYTE macro
+ //
+
+ GET_BYTE_INITIALIZATION( BitMapHeader, 0);
+
+ //
+ // Set our current run variables
+ //
+
+ CurrentRunSize = 0;
+ CurrentRunIndex = 0xffffffff;
+
+ //
+ // Examine every byte in the BitMap. We'll also break out of this
+ // loop if ever we finish off a run.
+ //
+
+ for (CurrentByteIndex = 0;
+ CurrentByteIndex < SizeInBytes;
+ CurrentByteIndex += 1) {
+
+ GET_BYTE( CurrentByte );
+
+ //
+ // If the current byte is all ones and the run size is zero then
+ // skip over this byte because we haven't found the start of a
+ // run yet.
+ //
+
+ if ((CurrentByte == 0xff) && (CurrentRunSize == 0)) {
+
+ NOTHING;
+
+ //
+ // See if the current byte is all zeros, because if it is then
+ // we simply continue with the current run
+ //
+
+ } else if (CurrentByte == 0x00) {
+
+ CurrentRunSize += 8;
+
+ if (CurrentRunIndex == 0xffffffff) {
+
+ CurrentRunIndex = (CurrentByteIndex * 8);
+ }
+
+ //
+ // Otherwise the current byte is not all zeros, so we need to
+ // (1) check if we have a current run, or (2) check if the
+ // current byte inside of itself is a run, or (3) start a
+ // current run.
+ //
+ // Check if we have a current run, we do that by checking
+ // if the low bits are clear.
+ //
+
+ } else if (CurrentRunSize != 0) {
+
+ CurrentRunSize += HalppBitsClearLow[CurrentByte];
+ break;
+
+ //
+ // Check if we have an internal run, we do that by checking
+ // if the high bits are not clear. This check actually cheats
+ // a bit in that the current byte might have an inside run
+ // but we'll skip over it because we can start a run at the
+ // end of the byte.
+ //
+
+ } else if (HalppBitsClearHigh[CurrentByte] == 0) {
+
+ UCHAR BitMask;
+ ULONG i;
+
+ ASSERT( HalppBitsClearAnywhere[CurrentByte] != 0 );
+
+ CurrentRunSize = HalppBitsClearAnywhere[CurrentByte];
+
+ //
+ // Somewhere in the current byte is a run. All we need to do now
+ // is find the index for this new run.
+ //
+
+ BitMask = FillMask[ CurrentRunSize ];
+
+ for (i = 0; (BitMask & CurrentByte) != 0; i += 1) {
+
+ BitMask <<= 1;
+ }
+
+ CurrentRunIndex = (CurrentByteIndex * 8) + i;
+ break;
+
+ //
+ // Otherwise we start a new current run. It starts with the
+ // remaining clear bits in the current byte.
+ //
+
+ } else {
+
+ CurrentRunSize = HalppBitsClearHigh[ CurrentByte ];
+ CurrentRunIndex = (CurrentByteIndex * 8) + (8 - CurrentRunSize);
+ }
+ }
+
+ //
+ // Set our output variables and return to our caller
+ //
+
+ *StartingIndex = CurrentRunIndex;
+ return CurrentRunSize;
+}
+
+
+ULONG
+HalpFindFirstRunSet (
+ IN PRTL_BITMAP BitMapHeader,
+ OUT PULONG StartingIndex
+ )
+
+/*++
+
+Routine Description:
+
+ This procedure finds the first contiguous range of set bits
+ within the specified bit map.
+
+Arguments:
+
+ BitMapHeader - Supplies a pointer to the previously initialized BitMap.
+
+ StartingIndex - Receives the index (zero based) of the first run
+ equal to the longest run of set bits in the BitMap.
+
+Return Value:
+
+ ULONG - Receives the number of bits contained in the largest contiguous
+ run of set bits.
+
+--*/
+
+{
+ ULONG SizeOfBitMap;
+ ULONG SizeInBytes;
+
+ ULONG CurrentRunSize;
+ ULONG CurrentRunIndex;
+ ULONG CurrentByteIndex;
+ UCHAR CurrentByte;
+
+ GET_BYTE_DECLARATIONS();
+
+ //
+ // Reference the bitmap header to make the loop run faster
+ //
+
+ SizeOfBitMap = BitMapHeader->SizeOfBitMap;
+ SizeInBytes = (SizeOfBitMap + 7) / 8;
+
+ //
+ // Set any unused bits in the last byte so we won't count them. We do
+ // this by first checking if there is any odd bits in the last byte.
+ //
+
+ if ((SizeOfBitMap % 8) != 0) {
+
+ //
+ // The last byte has some odd bits so we'll set the high unused
+ // bits in the last byte to 0's
+ //
+
+ ((PUCHAR)BitMapHeader->Buffer)[SizeInBytes - 1] &=
+ FillMask[SizeOfBitMap % 8];
+ }
+
+ //
+ // Set it up so we can the use GET_BYTE macro
+ //
+
+ GET_BYTE_INITIALIZATION( BitMapHeader, 0);
+
+ //
+ // Set our current run variables
+ //
+
+ CurrentRunSize = 0;
+ CurrentRunIndex = 0xffffffff;
+
+ //
+ // Examine every byte in the BitMap. We'll also break out of this
+ // loop if ever we finish off a run.
+ //
+
+ for (CurrentByteIndex = 0;
+ CurrentByteIndex < SizeInBytes;
+ CurrentByteIndex += 1) {
+
+ GET_BYTE( CurrentByte );
+
+ //
+ // If the current byte is all zeros and the run size is zero then
+ // skip over this byte because we haven't found the start of a
+ // run yet.
+ //
+
+ if ((CurrentByte == 0x00) && (CurrentRunSize == 0)) {
+
+ NOTHING;
+
+ //
+ // See if the current byte is all ones, because if it is then
+ // we simply continue with the current run
+ //
+
+ } else if (CurrentByte == 0xff) {
+
+ CurrentRunSize += 8;
+
+ if (CurrentRunIndex == 0xffffffff) {
+
+ CurrentRunIndex = (CurrentByteIndex * 8);
+ }
+
+ //
+ // Otherwise the current byte is not all ones, so we need to
+ // (1) check if we have the current run, or (2) check if the
+ // current byte inside of itself is a run, or (3) start a
+ // current run.
+ //
+ // Check if we have a current run, we do that by checking
+ // if the low bits are set.
+ //
+
+ } else if (CurrentRunSize != 0) {
+
+ CurrentRunSize += HalppBitsSetLow(CurrentByte);
+ break;
+
+ //
+ // Check if we have an internal run, we do that by checking
+ // if the high bits are not set. This check actually cheats
+ // a bit in that the current byte might have an inside run
+ // but we'll skip over it because we can start a run at the
+ // end of the byte.
+ //
+
+ } else if (HalppBitsSetHigh(CurrentByte) == 0) {
+
+ UCHAR BitMask;
+ ULONG i;
+
+ ASSERT( HalppBitSetAnywhere(CurrentByte) != 0 );
+
+ CurrentRunSize = HalppBitSetAnywhere(CurrentByte);
+
+ //
+ // Somewhere in the current byte is a run. All we need to do now
+ // is find the index for this new run.
+ //
+
+ BitMask = FillMask[ CurrentRunSize ];
+
+ for (i = 0; (BitMask & CurrentByte) != BitMask; i += 1) {
+
+ BitMask <<= 1;
+ }
+
+ CurrentRunIndex = (CurrentByteIndex * 8) + i;
+ break;
+
+ //
+ // Otherwise we start a new current run. It starts with the
+ // remaining set bits in the current byte.
+ //
+
+ } else {
+
+ CurrentRunSize = HalppBitsSetHigh( CurrentByte );
+ CurrentRunIndex = (CurrentByteIndex * 8) + (8 - CurrentRunSize);
+ }
+ }
+
+ //
+ // Set our output variables and return to our caller
+ //
+
+ *StartingIndex = CurrentRunIndex;
+ return CurrentRunSize;
+}
+
+
+ULONG
+HalpNumberOfClearBits (
+ IN PRTL_BITMAP BitMapHeader
+ )
+
+/*++
+
+Routine Description:
+
+ This procedure counts and returns the number of clears bits within
+ the specified bitmap.
+
+Arguments:
+
+ BitMapHeader - Supplies a pointer to the previously initialized bitmap.
+
+Return Value:
+
+ ULONG - The total number of clear bits in the bitmap
+
+--*/
+
+{
+ ULONG SizeOfBitMap;
+ ULONG SizeInBytes;
+
+ ULONG i;
+ UCHAR CurrentByte;
+
+ ULONG TotalClear;
+
+ GET_BYTE_DECLARATIONS();
+
+ //
+ // Reference the bitmap header to make the loop run faster
+ //
+
+ SizeOfBitMap = BitMapHeader->SizeOfBitMap;
+ SizeInBytes = (SizeOfBitMap + 7) / 8;
+
+ //
+ // Set any unused bits in the last byte so we don't count them. We
+ // do this by first checking if there are any odd bits in the last byte
+ //
+
+ if ((SizeOfBitMap % 8) != 0) {
+
+ //
+ // The last byte has some odd bits so we'll set the high unused
+ // bits in the last byte to 1's
+ //
+
+ ((PUCHAR)BitMapHeader->Buffer)[SizeInBytes - 1] |=
+ ZeroMask[SizeOfBitMap % 8];
+ }
+
+ //
+ // Set if up so we can use the GET_BYTE macro
+ //
+
+ GET_BYTE_INITIALIZATION( BitMapHeader, 0 );
+
+ //
+ // Examine every byte in the bitmap
+ //
+
+ TotalClear = 0;
+ for (i = 0; i < SizeInBytes; i += 1) {
+
+ GET_BYTE( CurrentByte );
+
+ TotalClear += HalppBitsClearTotal[CurrentByte];
+ }
+
+ return TotalClear;
+}
+
+
+ULONG
+HalpNumberOfSetBits (
+ IN PRTL_BITMAP BitMapHeader
+ )
+
+/*++
+
+Routine Description:
+
+ This procedure counts and returns the number of set bits within
+ the specified bitmap.
+
+Arguments:
+
+ BitMapHeader - Supplies a pointer to the previously initialized bitmap.
+
+Return Value:
+
+ ULONG - The total number of set bits in the bitmap
+
+--*/
+
+{
+ ULONG SizeOfBitMap;
+ ULONG SizeInBytes;
+
+ ULONG i;
+ UCHAR CurrentByte;
+
+ ULONG TotalSet;
+
+ GET_BYTE_DECLARATIONS();
+
+ //
+ // Reference the bitmap header to make the loop run faster
+ //
+
+ SizeOfBitMap = BitMapHeader->SizeOfBitMap;
+ SizeInBytes = (SizeOfBitMap + 7) / 8;
+
+ //
+ // Clear any unused bits in the last byte so we don't count them. We
+ // do this by first checking if there are any odd bits in the last byte
+ //
+
+ if ((SizeOfBitMap % 8) != 0) {
+
+ //
+ // The last byte has some odd bits so we'll set the high unused
+ // bits in the last byte to 0's
+ //
+
+ ((PUCHAR)BitMapHeader->Buffer)[SizeInBytes - 1] &=
+ FillMask[SizeOfBitMap % 8];
+ }
+
+ //
+ // Set if up so we can use the GET_BYTE macro
+ //
+
+ GET_BYTE_INITIALIZATION( BitMapHeader, 0 );
+
+ //
+ // Examine every byte in the bitmap
+ //
+
+ TotalSet = 0;
+ for (i = 0; i < SizeInBytes; i += 1) {
+
+ GET_BYTE( CurrentByte );
+
+ TotalSet += HalppBitsSetTotal(CurrentByte);
+ }
+
+ return TotalSet;
+}
+
+
+BOOLEAN
+HalpAreBitsClear (
+ IN PRTL_BITMAP BitMapHeader,
+ IN ULONG StartingIndex,
+ IN ULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This procedure determines if the range of specified bits are all clear.
+
+Arguments:
+
+ BitMapHeader - Supplies a pointer to the previously initialized bitmap.
+
+ StartingIndex - Supplies the starting bit index to examine
+
+ Length - Supplies the number of bits to examine
+
+Return Value:
+
+ BOOLEAN - TRUE if the specified bits in the bitmap are all clear, and
+ FALSE if any are set or if the range is outside the bitmap or if
+ Length is zero.
+
+--*/
+
+{
+ ULONG SizeOfBitMap;
+ ULONG SizeInBytes;
+
+ ULONG EndingIndex;
+
+ ULONG StartingByte;
+ ULONG EndingByte;
+
+ ULONG StartingOffset;
+ ULONG EndingOffset;
+
+ ULONG i;
+ UCHAR Byte;
+
+ GET_BYTE_DECLARATIONS();
+
+ //
+ // To make the loops in our test run faster we'll extract the fields
+ // from the bitmap header
+ //
+
+ SizeOfBitMap = BitMapHeader->SizeOfBitMap;
+ SizeInBytes = (SizeOfBitMap + 7) / 8;
+
+ //
+ // First make sure that the specified range is contained within the
+ // bitmap, and the length is not zero.
+ //
+
+ if ((StartingIndex + Length > SizeOfBitMap) || (Length == 0)) {
+
+ return FALSE;
+ }
+
+ //
+ // Compute the ending index, starting and ending byte, and the starting
+ // and ending offset within each byte
+ //
+
+ EndingIndex = StartingIndex + Length - 1;
+
+ StartingByte = StartingIndex / 8;
+ EndingByte = EndingIndex / 8;
+
+ StartingOffset = StartingIndex % 8;
+ EndingOffset = EndingIndex % 8;
+
+ //
+ // Set ourselves up to get the next byte
+ //
+
+ GET_BYTE_INITIALIZATION( BitMapHeader, StartingByte );
+
+ //
+ // Special case the situation where the starting byte and ending
+ // byte are one in the same
+ //
+
+ if (StartingByte == EndingByte) {
+
+ //
+ // Get the single byte we are to look at
+ //
+
+ GET_BYTE( Byte );
+
+ //
+ // Now we compute the mask of bits we're after and then AND it with
+ // the byte. If it is zero then the bits in question are all clear
+ // otherwise at least one of them is set.
+ //
+
+ if ((ZeroMask[StartingOffset] & FillMask[EndingOffset+1] & Byte) == 0) {
+
+ return TRUE;
+
+ } else {
+
+ return FALSE;
+ }
+
+ } else {
+
+ //
+ // Get the first byte that we're after, and then
+ // compute the mask of bits we're after for the first byte then
+ // AND it with the byte itself.
+ //
+
+ GET_BYTE( Byte );
+
+ if ((ZeroMask[StartingOffset] & Byte) != 0) {
+
+ return FALSE;
+ }
+
+ //
+ // Now for every whole byte inbetween read in the byte,
+ // and make sure it is all zeros
+ //
+
+ for (i = StartingByte+1; i < EndingByte; i += 1) {
+
+ GET_BYTE( Byte );
+
+ if (Byte != 0) {
+
+ return FALSE;
+ }
+ }
+
+ //
+ // Get the last byte we're after, and then
+ // compute the mask of bits we're after for the last byte then
+ // AND it with the byte itself.
+ //
+
+ GET_BYTE( Byte );
+
+ if ((FillMask[EndingOffset+1] & Byte) != 0) {
+
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+
+BOOLEAN
+HalpAreBitsSet (
+ IN PRTL_BITMAP BitMapHeader,
+ IN ULONG StartingIndex,
+ IN ULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This procedure determines if the range of specified bits are all set.
+
+Arguments:
+
+ BitMapHeader - Supplies a pointer to the previously initialized bitmap.
+
+ StartingIndex - Supplies the starting bit index to examine
+
+ Length - Supplies the number of bits to examine
+
+Return Value:
+
+ BOOLEAN - TRUE if the specified bits in the bitmap are all set, and
+ FALSE if any are clear or if the range is outside the bitmap or if
+ Length is zero.
+
+--*/
+
+{
+ ULONG SizeOfBitMap;
+ ULONG SizeInBytes;
+
+ ULONG EndingIndex;
+
+ ULONG StartingByte;
+ ULONG EndingByte;
+
+ ULONG StartingOffset;
+ ULONG EndingOffset;
+
+ ULONG i;
+ UCHAR Byte;
+
+ GET_BYTE_DECLARATIONS();
+
+ //
+ // To make the loops in our test run faster we'll extract the fields
+ // from the bitmap header
+ //
+
+ SizeOfBitMap = BitMapHeader->SizeOfBitMap;
+ SizeInBytes = (SizeOfBitMap + 7) / 8;
+
+ //
+ // First make sure that the specified range is contained within the
+ // bitmap, and the length is not zero.
+ //
+
+ if ((StartingIndex + Length > SizeOfBitMap) || (Length == 0)) {
+
+ return FALSE;
+ }
+
+ //
+ // Compute the ending index, starting and ending byte, and the starting
+ // and ending offset within each byte
+ //
+
+ EndingIndex = StartingIndex + Length - 1;
+
+ StartingByte = StartingIndex / 8;
+ EndingByte = EndingIndex / 8;
+
+ StartingOffset = StartingIndex % 8;
+ EndingOffset = EndingIndex % 8;
+
+ //
+ // Set ourselves up to get the next byte
+ //
+
+ GET_BYTE_INITIALIZATION( BitMapHeader, StartingByte );
+
+ //
+ // Special case the situation where the starting byte and ending
+ // byte are one in the same
+ //
+
+ if (StartingByte == EndingByte) {
+
+ //
+ // Get the single byte we are to look at
+ //
+
+ GET_BYTE( Byte );
+
+ //
+ // Now we compute the mask of bits we're after and then AND it with
+ // the complement of the byte If it is zero then the bits in question
+ // are all clear otherwise at least one of them is clear.
+ //
+
+ if ((ZeroMask[StartingOffset] & FillMask[EndingOffset+1] & ~Byte) == 0) {
+
+ return TRUE;
+
+ } else {
+
+ return FALSE;
+ }
+
+ } else {
+
+ //
+ // Get the first byte that we're after, and then
+ // compute the mask of bits we're after for the first byte then
+ // AND it with the complement of the byte itself.
+ //
+
+ GET_BYTE( Byte );
+
+ if ((ZeroMask[StartingOffset] & ~Byte) != 0) {
+
+ return FALSE;
+ }
+
+ //
+ // Now for every whole byte inbetween read in the byte,
+ // and make sure it is all ones
+ //
+
+ for (i = StartingByte+1; i < EndingByte; i += 1) {
+
+ GET_BYTE( Byte );
+
+ if (Byte != 0xff) {
+
+ return FALSE;
+ }
+ }
+
+ //
+ // Get the last byte we're after, and then
+ // compute the mask of bits we're after for the last byte then
+ // AND it with the complement of the byte itself.
+ //
+
+ GET_BYTE( Byte );
+
+ if ((FillMask[EndingOffset+1] & ~Byte) != 0) {
+
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+
+//ULONG
+//HalpCheckBit (
+// IN PRTL_BITMAP BitMapHeader,
+// IN ULONG BitPosition
+// )
+//
+///*++
+//
+//Routine Description:
+//
+// This procedure returns the state of the specified bit within the
+// specified bit map.
+//
+//Arguments:
+//
+// BitMapHeader - Supplies a pointer to the previously initialized BitMap.
+//
+// BitPosition - Supplies the bit number of which to return the state.
+//
+//Return Value:
+//
+// ULONG - The state of the specified bit.
+//
+//--*/
+//
+//{
+// ULONG results;
+//
+// results = ((BitMapHeader->Buffer[BitPosition / 32]) >> (BitPosition % 32)) & 0x00000001;
+//
+// //DbgPrint("CheckBit %08lx", BitPosition);
+// //DbgPrint(" %08lx", results);
+// //DumpBitMap(BitMapHeader);
+//
+// return results;
+//}
+
diff --git a/private/ntos/nthals/halraw/alpha/bitmap.h b/private/ntos/nthals/halraw/alpha/bitmap.h
new file mode 100644
index 000000000..744f8544e
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/bitmap.h
@@ -0,0 +1,252 @@
+/*++
+
+Copyright (c) 1989-1993 Microsoft Corporation
+Copyright (c) 1995 Digital Equipment Corporation
+
+Module Name:
+
+ bitmap.h
+
+Abstract:
+
+
+ ecrfix - (non-paged) copy of Rtl bitmap routines in HAL
+
+ Later: only include routines we really use, or come up with
+ a different solution.
+
+ This file defines the structures and definitions registers on a
+ Rawhide I/O Daughter card. These register reside on the CAP chip,
+ MDP chips, and flash ROM.
+
+
+Author:
+
+ Eric Rehm 17-Nov-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#ifndef _BITMAPH_
+#define _BITMAPH_
+
+//
+// The following routine initializes a new bitmap. It does not alter the
+// data currently in the bitmap. This routine must be called before
+// any other bitmap routine/macro.
+//
+
+
+NTSYSAPI
+VOID
+NTAPI
+RtlFillMemoryUlong (
+ PVOID Destination,
+ ULONG Length,
+ ULONG Pattern
+ );
+
+VOID
+HalpInitializeBitMap (
+ PRTL_BITMAP BitMapHeader,
+ PULONG BitMapBuffer,
+ ULONG SizeOfBitMap
+ );
+
+//
+// The following two routines either clear or set all of the bits
+// in a bitmap.
+//
+
+
+VOID
+HalpClearAllBits (
+ PRTL_BITMAP BitMapHeader
+ );
+
+
+VOID
+HalpSetAllBits (
+ PRTL_BITMAP BitMapHeader
+ );
+
+//
+// The following two routines locate a contiguous region of either
+// clear or set bits within the bitmap. The region will be at least
+// as large as the number specified, and the search of the bitmap will
+// begin at the specified hint index (which is a bit index within the
+// bitmap, zero based). The return value is the bit index of the located
+// region (zero based) or -1 (i.e., 0xffffffff) if such a region cannot
+// be located
+//
+
+
+ULONG
+HalpFindClearBits (
+ PRTL_BITMAP BitMapHeader,
+ ULONG NumberToFind,
+ ULONG HintIndex
+ );
+
+
+ULONG
+HalpFindSetBits (
+ PRTL_BITMAP BitMapHeader,
+ ULONG NumberToFind,
+ ULONG HintIndex
+ );
+
+//
+// The following two routines locate a contiguous region of either
+// clear or set bits within the bitmap and either set or clear the bits
+// within the located region. The region will be as large as the number
+// specified, and the search for the region will begin at the specified
+// hint index (which is a bit index within the bitmap, zero based). The
+// return value is the bit index of the located region (zero based) or
+// -1 (i.e., 0xffffffff) if such a region cannot be located. If a region
+// cannot be located then the setting/clearing of the bitmap is not performed.
+//
+
+
+ULONG
+HalpFindClearBitsAndSet (
+ PRTL_BITMAP BitMapHeader,
+ ULONG NumberToFind,
+ ULONG HintIndex
+ );
+
+
+ULONG
+HalpFindSetBitsAndClear (
+ PRTL_BITMAP BitMapHeader,
+ ULONG NumberToFind,
+ ULONG HintIndex
+ );
+
+//
+// The following two routines clear or set bits within a specified region
+// of the bitmap. The starting index is zero based.
+//
+
+
+VOID
+HalpClearBits (
+ PRTL_BITMAP BitMapHeader,
+ ULONG StartingIndex,
+ ULONG NumberToClear
+ );
+
+
+VOID
+HalpSetBits (
+ PRTL_BITMAP BitMapHeader,
+ ULONG StartingIndex,
+ ULONG NumberToSet
+ );
+
+//
+// The following two routines locate the longest contiguous region of
+// clear or set bits within the bitmap. The returned starting index value
+// denotes the first contiguous region located satisfying our requirements
+// The return value is the length (in bits) of the longest region found.
+//
+
+
+ULONG
+HalpFindLongestRunClear (
+ PRTL_BITMAP BitMapHeader,
+ PULONG StartingIndex
+ );
+
+
+ULONG
+HalpFindLongestRunSet (
+ PRTL_BITMAP BitMapHeader,
+ PULONG StartingIndex
+ );
+
+//
+// The following two routines locate the first contiguous region of
+// clear or set bits within the bitmap. The returned starting index value
+// denotes the first contiguous region located satisfying our requirements
+// The return value is the length (in bits) of the region found.
+//
+
+
+ULONG
+HalpFindFirstRunClear (
+ PRTL_BITMAP BitMapHeader,
+ PULONG StartingIndex
+ );
+
+
+ULONG
+HalpFindFirstRunSet (
+ PRTL_BITMAP BitMapHeader,
+ PULONG StartingIndex
+ );
+
+//
+// The following macro returns the value of the bit stored within the
+// bitmap at the specified location. If the bit is set a value of 1 is
+// returned otherwise a value of 0 is returned.
+//
+// ULONG
+// HalpCheckBit (
+// PRTL_BITMAP BitMapHeader,
+// ULONG BitPosition
+// );
+//
+//
+// To implement CheckBit the macro retrieves the longword containing the
+// bit in question, shifts the longword to get the bit in question into the
+// low order bit position and masks out all other bits.
+//
+
+#define HalpCheckBit(BMH,BP) ((((BMH)->Buffer[(BP) / 32]) >> ((BP) % 32)) & 0x1)
+
+//
+// The following two procedures return to the caller the total number of
+// clear or set bits within the specified bitmap.
+//
+
+
+ULONG
+HalpNumberOfClearBits (
+ PRTL_BITMAP BitMapHeader
+ );
+
+
+ULONG
+HalpNumberOfSetBits (
+ PRTL_BITMAP BitMapHeader
+ );
+
+//
+// The following two procedures return to the caller a boolean value
+// indicating if the specified range of bits are all clear or set.
+//
+
+
+BOOLEAN
+HalpAreBitsClear (
+ PRTL_BITMAP BitMapHeader,
+ ULONG StartingIndex,
+ ULONG Length
+ );
+
+
+BOOLEAN
+HalpAreBitsSet (
+ PRTL_BITMAP BitMapHeader,
+ ULONG StartingIndex,
+ ULONG Length
+ );
+
+#endif //_BITMAPH_
diff --git a/private/ntos/nthals/halraw/alpha/busdata.c b/private/ntos/nthals/halraw/alpha/busdata.c
new file mode 100644
index 000000000..2c56e0c0e
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/busdata.c
@@ -0,0 +1,137 @@
+/*++
+
+Copyright (c) 1989 Microsoft Corporation
+Copyright (c) 1995 Digital Equipment Corporation
+
+Module Name:
+
+ busdata.c
+
+Abstract:
+
+ This module contains get/set bus data routines.
+
+Author:
+
+ Darryl E. Havens (darrylh) 11-Apr-1990
+ Eric Rehm 13-Apr-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+//
+// External Function Prototypes
+//
+
+ULONG
+HalpNoBusData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpRegisterInternalBusHandlers)
+#endif
+
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function registers the bushandlers for buses on the system
+ that will always be present on the system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PBUS_HANDLER Bus;
+
+ //
+ // Initalize BusHandler data before registering any handlers
+ //
+
+ HalpInitBusHandler ();
+
+ //
+ // Build the processor internal bus 0
+ //
+
+ HaliRegisterBusHandler (ProcessorInternal, // Bus Type
+ -1, // No config space
+ 0, // Bus Number
+ -1, // No parent bus type
+ 0, // No parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+
+ //
+ // Build internal-bus 0, or system level bus
+ //
+
+ HaliRegisterBusHandler (Internal, // Bus Type
+ -1, // No config space
+ 0, // Bus Number
+ -1, // No parent bus type
+ 0, // No parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+ Bus->TranslateBusAddress = HalpTranslateSystemBusAddress;
+
+ //
+ // Build Isa/Eisa bus #0
+ //
+
+ HaliRegisterBusHandler (Eisa, // Bus Type
+ EisaConfiguration, // Config space type
+ 0, // Internal bus #0
+ Internal, // Parent bus type
+ 0, // Parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetBusData = HalpGetEisaData;
+ Bus->AdjustResourceList = HalpAdjustEisaResourceList;
+
+ HaliRegisterBusHandler (Isa, // Bus Type
+ -1, // No config space
+ 0, // Internal bus #0
+ Eisa, // Parent bus type
+ 0, // Parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler returne
+
+ Bus->GetBusData = HalpNoBusData;
+ Bus->AdjustResourceList = HalpAdjustIsaResourceList;
+
+}
+
diff --git a/private/ntos/nthals/halraw/alpha/cache.c b/private/ntos/nthals/halraw/alpha/cache.c
new file mode 100644
index 000000000..561528477
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/cache.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\cache.c"
+
diff --git a/private/ntos/nthals/halraw/alpha/devintr.s b/private/ntos/nthals/halraw/alpha/devintr.s
new file mode 100644
index 000000000..d861febd2
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/devintr.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\devintr.s"
+
diff --git a/private/ntos/nthals/halraw/alpha/drivesup.c b/private/ntos/nthals/halraw/alpha/drivesup.c
new file mode 100644
index 000000000..38259e5f4
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/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/halraw/alpha/ebsgdma.c b/private/ntos/nthals/halraw/alpha/ebsgdma.c
new file mode 100644
index 000000000..f2f033fad
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/ebsgdma.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ebsgdma.c"
+
diff --git a/private/ntos/nthals/halraw/alpha/eeprom8k.c b/private/ntos/nthals/halraw/alpha/eeprom8k.c
new file mode 100644
index 000000000..c03d04c0d
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/eeprom8k.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\eeprom8k.c"
+
diff --git a/private/ntos/nthals/halraw/alpha/eisaprof.c b/private/ntos/nthals/halraw/alpha/eisaprof.c
new file mode 100644
index 000000000..1fbc6426e
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/eisaprof.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\eisaprof.c"
+
diff --git a/private/ntos/nthals/halraw/alpha/eisasup.c b/private/ntos/nthals/halraw/alpha/eisasup.c
new file mode 100644
index 000000000..0d46ef3e4
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/eisasup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\eisasup.c"
+
diff --git a/private/ntos/nthals/halraw/alpha/ev5cache.c b/private/ntos/nthals/halraw/alpha/ev5cache.c
new file mode 100644
index 000000000..cd83f7451
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/ev5cache.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev5cache.c"
+
diff --git a/private/ntos/nthals/halraw/alpha/ev5int.c b/private/ntos/nthals/halraw/alpha/ev5int.c
new file mode 100644
index 000000000..23727330f
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/ev5int.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev5int.c"
+
diff --git a/private/ntos/nthals/halraw/alpha/ev5ints.s b/private/ntos/nthals/halraw/alpha/ev5ints.s
new file mode 100644
index 000000000..66852f382
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/ev5ints.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev5ints.s"
+
diff --git a/private/ntos/nthals/halraw/alpha/ev5mchk.c b/private/ntos/nthals/halraw/alpha/ev5mchk.c
new file mode 100644
index 000000000..0bedd3dfc
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/ev5mchk.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev5mchk.c"
+
diff --git a/private/ntos/nthals/halraw/alpha/ev5mem.s b/private/ntos/nthals/halraw/alpha/ev5mem.s
new file mode 100644
index 000000000..dcad6563c
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/ev5mem.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev5mem.s"
+
diff --git a/private/ntos/nthals/halraw/alpha/ev5prof.c b/private/ntos/nthals/halraw/alpha/ev5prof.c
new file mode 100644
index 000000000..839438fd9
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/ev5prof.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev5prof.c"
+
diff --git a/private/ntos/nthals/halraw/alpha/fwreturn.c b/private/ntos/nthals/halraw/alpha/fwreturn.c
new file mode 100644
index 000000000..65ae88cb8
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/fwreturn.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\fwreturn.c"
+
diff --git a/private/ntos/nthals/halraw/alpha/haldebug.c b/private/ntos/nthals/halraw/alpha/haldebug.c
new file mode 100644
index 000000000..ce91863ec
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/haldebug.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\haldebug.c"
+
diff --git a/private/ntos/nthals/halraw/alpha/halpal.s b/private/ntos/nthals/halraw/alpha/halpal.s
new file mode 100644
index 000000000..fc89f8370
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/halpal.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\halpal.s"
+
diff --git a/private/ntos/nthals/halraw/alpha/haltsup.s b/private/ntos/nthals/halraw/alpha/haltsup.s
new file mode 100644
index 000000000..b8a697144
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/haltsup.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\haltsup.s"
+
diff --git a/private/ntos/nthals/halraw/alpha/idle.s b/private/ntos/nthals/halraw/alpha/idle.s
new file mode 100644
index 000000000..f517bab2f
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/idle.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\idle.s"
+
diff --git a/private/ntos/nthals/halraw/alpha/info.c b/private/ntos/nthals/halraw/alpha/info.c
new file mode 100644
index 000000000..22aef63a3
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/info.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\info.c"
+
diff --git a/private/ntos/nthals/halraw/alpha/inithal.c b/private/ntos/nthals/halraw/alpha/inithal.c
new file mode 100644
index 000000000..47f0a5b17
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/inithal.c
@@ -0,0 +1,1126 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ inithal.c
+
+Abstract:
+
+
+ This module implements the initialization of the system dependent
+ functions that define the Hardware Architecture Layer (HAL) for an
+ Alpha machine
+
+Author:
+
+ David N. Cutler (davec) 25-Apr-1991
+ Miche Baker-Harvey (miche) 18-May-1992
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ 28-Jul-1992 Jeff McLeman (mcleman)
+ Add code to allocate a mapping buffer for buffered DMA
+
+ 14-Jul-1992 Jeff McLeman (mcleman)
+ Add call to HalpCachePcrValues, which will call the PALcode to
+ cache values of the PCR that need fast access.
+
+ 10-Jul-1992 Jeff McLeman (mcleman)
+ Remove reference to initializing the fixed TB entries, since Alpha
+ does not have fixed TB entries.
+
+ 24-Sep-1993 Joe Notarangelo
+ Restructured to make this module platform-independent.
+
+--*/
+
+#include "halp.h"
+
+//
+// Declare the extern variable UncorrectableError declared in
+// inithal.c.
+//
+
+PERROR_FRAME PUncorrectableError = NULL;
+
+//
+// external
+//
+
+ULONG HalDisablePCIParityChecking = 0xffffffff;
+
+//
+// Define HAL spinlocks.
+//
+
+KSPIN_LOCK HalpBeepLock;
+KSPIN_LOCK HalpDisplayAdapterLock;
+KSPIN_LOCK HalpSystemInterruptLock;
+
+//
+// Mask of all of the processors that are currently active.
+//
+
+KAFFINITY HalpActiveProcessors;
+
+//
+// Mapping of the logical processor numbers to the physical processors.
+//
+
+HALP_PROCESSOR_ID HalpLogicalToPhysicalProcessor[HAL_MAXIMUM_PROCESSOR+1];
+
+ULONG AlreadySet = 0;
+
+//
+// HalpClockFrequency is the processor cycle counter frequency in units
+// of cycles per second (Hertz). It is a large number (e.g., 125,000,000)
+// but will still fit in a ULONG.
+//
+// HalpClockMegaHertz is the processor cycle counter frequency in units
+// of megahertz. It is a small number (e.g., 125) and is also the number
+// of cycles per microsecond. The assumption here is that clock rates will
+// always be an integral number of megahertz.
+//
+// Having the frequency available in both units avoids multiplications, or
+// especially divisions in time critical code.
+//
+
+ULONG HalpClockFrequency;
+ULONG HalpClockMegaHertz = DEFAULT_PROCESSOR_FREQUENCY_MHZ;
+
+ULONGLONG HalpContiguousPhysicalMemorySize;
+
+//
+// Use the square wave mode of the PIT to measure the processor
+// speed. The timer has a frequency of 1.193MHz. We want a
+// square wave with a period of 50ms so we must initialize the
+// pit with a count of:
+// 50ms*1.193MHz = 59650 cycles
+//
+
+#define TIMER_REF_VALUE 59650
+
+VOID
+HalpEarlyInitializeMachineDependent(
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+
+VOID
+HalpVerifyPrcbVersion(
+ VOID
+ );
+
+VOID
+HalpRecurseLoaderBlock(
+ IN PCONFIGURATION_COMPONENT_DATA CurrentEntry
+ );
+
+ULONG
+HalpQuerySystemFrequency(
+ ULONG SampleTime
+ );
+
+VOID
+HalpAllocateUncorrectableFrame(
+ VOID
+ );
+
+BOOLEAN
+HalInitSystem (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes the Hardware Architecture Layer (HAL) for an
+ Alpha system.
+
+Arguments:
+
+ Phase - Supplies the initialization phase (zero or one).
+
+ LoaderBlock - Supplies a pointer to a loader parameter block.
+
+Return Value:
+
+ A value of TRUE is returned is the initialization was successfully
+ complete. Otherwise a value of FALSE is returend.
+
+--*/
+
+{
+ PKPRCB Prcb;
+ ULONG BuildType = 0;
+ MC_DEVICE_ID McDevid;
+ IOD_WHOAMI IodWhoAmI;
+ Prcb = PCR->Prcb;
+
+#if HALDBG
+ DbgPrint( "HAL/HalInitSystem: entered, Processor = %d\n", PCR->Number );
+#endif
+ //
+ // Perform initialization for the primary processor.
+ //
+
+ if( Prcb->Number == HAL_PRIMARY_PROCESSOR ){
+
+ if (Phase == 0) {
+
+#if HALDBG
+ DbgPrint( "HAL/HalInitSystem: Phase = %d\n", Phase );
+ DbgBreakPoint();
+ HalpDumpMemoryDescriptors( LoaderBlock );
+#endif //HALDBG
+
+ //
+ // Get the memory Size.
+ //
+
+ HalpContiguousPhysicalMemorySize =
+ HalpGetContiguousMemorySize( LoaderBlock );
+
+ //
+ // Set second level cache size
+ // NOTE: Although we set the PCR with the right cache size this
+ // could be overridden by setting the Registry key
+ // HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet
+ // \Control\Session Manager
+ // \Memory Management\SecondLevelDataCache.
+ //
+ // If the secondlevel cache size is 0 or 512KB then it is
+ // possible that the firmware is an old one. In which case
+ // we determine the cache size here. If the value is anything
+ // other than these then it is a new firmware and probably
+ // reporting the correct cache size hence use this value.
+ //
+
+ if(LoaderBlock->u.Alpha.SecondLevelDcacheSize == 0 ||
+ LoaderBlock->u.Alpha.SecondLevelDcacheSize == 512*__1K){
+ PCR->SecondLevelCacheSize = HalpGetBCacheSize(
+ HalpContiguousPhysicalMemorySize
+ );
+ } else {
+ PCR->SecondLevelCacheSize =
+ LoaderBlock->u.Alpha.SecondLevelDcacheSize;
+ }
+
+ //
+ // Initialize HAL spinlocks.
+ //
+
+ KeInitializeSpinLock(&HalpBeepLock);
+ KeInitializeSpinLock(&HalpDisplayAdapterLock);
+ KeInitializeSpinLock(&HalpSystemInterruptLock);
+
+ //
+ // Phase 0 initialization.
+ //
+
+#if HALDBG
+ DbgPrint( "HAL/HalInitSystem: Phase = %d Callouts\n", Phase );
+ DbgPrint( "HAL/HalInitSystem: Early Machine Init\n");
+#endif //HALDBG
+ HalpEarlyInitializeMachineDependent( Phase, LoaderBlock );
+
+#if HALDBG
+ DbgPrint( "HAL/HalInitSystem: Set Time Increment\n");
+#endif //HALDBG
+ HalpSetTimeIncrement();
+#if HALDBG
+ DbgPrint( "HAL/HalInitSystem: Map IO Space\n");
+#endif //HALDBG
+ HalpMapIoSpace();
+#if HALDBG
+ DbgPrint( "HAL/HalInitSystem: Create DMA Structures\n");
+#endif //HALDBG
+ HalpCreateDmaStructures(LoaderBlock);
+#if HALDBG
+ DbgPrint( "HAL/HalInitSystem: Establish Error Handler\n");
+#endif //HALDBG
+ HalpEstablishErrorHandler();
+#if HALDBG
+ DbgPrint( "HAL/HalInitSystem: Init Display\n");
+#endif //HALDBG
+ HalpInitializeDisplay(LoaderBlock);
+#if HALDBG
+ DbgPrint( "HAL/HalInitSystem: Init Machine Dependent\n");
+#endif //HALDBG
+ HalpInitializeMachineDependent( Phase, LoaderBlock );
+#if HALDBG
+ DbgPrint( "HAL/HalInitSystem: Init Interrupts\n");
+#endif //HALDBG
+ HalpInitializeInterrupts();
+#if HALDBG
+ DbgPrint( "HAL/HalInitSystem: Verify Prcb Version\n");
+#endif //HALDBG
+ HalpVerifyPrcbVersion();
+
+ //
+ // Set the processor active in the HAL active processor mask.
+ //
+
+ HalpActiveProcessors = 1 << Prcb->Number;
+
+#if HALDBG
+ DbgPrint( "HAL/HalInitSystem: Phase = %d complete\n", Phase );
+#endif //HALDBG
+ return TRUE;
+
+ } else {
+
+#if HALDBG
+
+ DbgPrint( "HAL/HalInitSystem: Phase = %d\n", Phase );
+ DbgBreakPoint();
+
+#endif //HALDBG
+
+ //
+ // Phase 1 initialization.
+ //
+
+#if HALDBG
+ DbgPrint( "HAL/HalInitSystem: Phase = %d Callouts\n", Phase );
+ DbgPrint( "HAL/HalInitSystem: Init Clock Interrupts\n");
+#endif //HALDBG
+ HalpInitializeClockInterrupts();
+
+#if HALDBG
+ DbgPrint( "HAL/HalInitSystem: Init Machine Dependent\n");
+#endif //HALDBG
+ HalpInitializeMachineDependent( Phase, LoaderBlock );
+
+ //
+ // Allocate memory for the uncorrectable frame
+ //
+
+ HalpAllocateUncorrectableFrame();
+
+ //
+ // Initialize the Buffer for Uncorrectable Error.
+ //
+
+ HalpInitializeUncorrectableErrorFrame();
+
+#if HALDBG
+ DbgPrint( "HAL/HalInitSystem: Phase = %d Complete\n", Phase );
+#endif //HALDBG
+ return TRUE;
+
+ }
+ }
+
+ //
+ // Perform necessary processor-specific initialization for
+ // secondary processors. Phase is ignored as this will be called
+ // only once on each secondary processor.
+ //
+
+#if HALDBG
+ DbgPrint( "HAL/HalInitSystem: Map IO Space\n");
+#endif //HALDBG
+
+ HalpMapIoSpace();
+
+#if HALDBG
+ DbgPrint( "HAL/HalInitSystem: Initialize Interrupts\n");
+#endif //HALDBG
+
+ HalpInitializeInterrupts();
+
+#if HALDBG
+ DbgPrint( "HAL/HalInitSystem: Initialize Machine Dependent\n");
+#endif //HALDBG
+
+ HalpInitializeMachineDependent( Phase, LoaderBlock );
+
+#if HALDBG
+ DbgPrint( "HAL/HalInitSystem: Set Active Processor Mask\n");
+#endif //HALDBG
+
+ //
+ // Set the processor active in the HAL active processor mask.
+ //
+
+ HalpActiveProcessors |= 1 << Prcb->Number;
+
+#if HALDBG
+
+ DbgPrint( "Secondary %d is alive\n", Prcb->Number );
+
+#endif //HALDBG
+
+ return TRUE;
+}
+
+VOID
+HalpAllocateUncorrectableFrame(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function is called after the Phase1 Machine Dependent initialization.
+ It must be called only after Phase1 machine-dependent initialization.
+ This function allocates the necessary amountof memory for storing the
+ uncorrectable error frame. This function makes a call to a machine-
+ dependent function 'HalpGetMachineDependentErrorFrameSizes' for
+ getting the size of the Processor Specific and System Specific error
+ frame size. The machine-dependent code will know the size of these
+ frames after the machine-dependent Phase1 initialization.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG RawProcessorFrameSize;
+ ULONG RawSystemFrameSize;
+ ULONG EntireErrorFrameSize;
+
+ //
+ // First get the machine-dependent error frame sizes.
+ //
+ HalpGetMachineDependentErrorFrameSizes(
+ &RawProcessorFrameSize,
+ &RawSystemFrameSize);
+
+ //
+ // Compute the total size of the error frame
+ //
+ EntireErrorFrameSize = sizeof(ERROR_FRAME) + RawProcessorFrameSize +
+ RawSystemFrameSize;
+
+ //
+ // Allocate space to store the error frame.
+ // Not sure if it is OK to use ExAllocatePool at this instant.
+ // We will give this a try if it doesn't work What do we do??!!
+ //
+
+ PUncorrectableError = ExAllocatePool(NonPagedPool,
+ EntireErrorFrameSize);
+ if(PUncorrectableError == NULL) {
+ return;
+ }
+
+ PUncorrectableError->LengthOfEntireErrorFrame = EntireErrorFrameSize;
+
+ //
+ // if the size is not equal to zero then set the RawInformation pointers
+ // to point to the right place. If not set the pointer to NULL and set
+ // size to 0.
+ //
+
+ //
+ // make Raw processor info to point right after the error frame.
+ //
+ if(RawProcessorFrameSize) {
+ PUncorrectableError->UncorrectableFrame.RawProcessorInformation =
+ (PVOID)((PUCHAR)(&PUncorrectableError->UncorrectableFrame) + sizeof(ERROR_FRAME) );
+ PUncorrectableError->UncorrectableFrame.RawProcessorInformationLength =
+ RawProcessorFrameSize;
+ }
+ else{
+ PUncorrectableError->UncorrectableFrame.RawProcessorInformation =
+ NULL;
+ PUncorrectableError->UncorrectableFrame.RawProcessorInformationLength =
+ 0;
+ }
+ if(RawSystemFrameSize){
+ PUncorrectableError->UncorrectableFrame.RawSystemInformation =
+ (PVOID)((PUCHAR)PUncorrectableError->UncorrectableFrame.
+ RawProcessorInformation + RawProcessorFrameSize);
+ PUncorrectableError->UncorrectableFrame.RawSystemInformationLength =
+ RawSystemFrameSize;
+ }
+ else{
+ PUncorrectableError->UncorrectableFrame.RawSystemInformation =
+ NULL;
+ PUncorrectableError->UncorrectableFrame.RawSystemInformationLength =
+ 0;
+ }
+}
+
+VOID
+HalpGetProcessorInfo(
+ PPROCESSOR_INFO pProcessorInfo
+ )
+/*++
+
+Routine Description:
+
+ Collects the Processor Information and fills in the buffer.
+
+Arguments:
+
+ pProcessorInfo - Pointer to the PROCESSOR_INFO structure into which
+ the processor information will be filled in.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PKPRCB Prcb;
+
+ pProcessorInfo->ProcessorType = PCR->ProcessorType;
+ pProcessorInfo->ProcessorRevision = PCR->ProcessorRevision;
+
+ Prcb = PCR->Prcb;
+ pProcessorInfo->LogicalProcessorNumber = Prcb->Number;
+ pProcessorInfo->PhysicalProcessorNumber =
+ (ULONG) (MCDEVID_TO_PHYS_CPU(
+ HalpLogicalToPhysicalProcessor[Prcb->Number].all)
+ );
+ return;
+}
+
+VOID
+HalInitializeProcessor (
+ IN ULONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called early in the initialization of the kernel
+ to perform platform dependent initialization for each processor
+ before the HAL Is fully functional.
+
+ N.B. When this routine is called, the PCR is present but is not
+ fully initialized.
+
+Arguments:
+
+ Number - Supplies the number of the processor to initialize.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return;
+}
+
+BOOLEAN
+HalStartNextProcessor (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN PKPROCESSOR_STATE ProcessorState
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to start the next processor.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+ ProcessorState - Supplies a pointer to the processor state to be
+ used to start the processor.
+
+Return Value:
+
+ If a processor is successfully started, then a value of TRUE is
+ returned. Otherwise a value of FALSE is returned. If a value of
+ TRUE is returned, then the logical processor number is stored
+ in the processor control block specified by the loader block.
+
+--*/
+
+{
+ ULONG LogicalNumber;
+ PRESTART_BLOCK NextRestartBlock;
+ ULONG PhysicalNumber;
+ PKPRCB Prcb;
+
+#if !defined(NT_UP)
+
+#if 0 //HALDBG
+ DbgPrint("HalStartNextProcessor: enter\n");
+#endif
+
+ //
+ // If the address of the first restart parameter block is NULL, then
+ // the host system is a uniprocessor system running with old firmware.
+ // Otherwise, the host system may be a multiprocessor system if more
+ // than one restart block is present.
+ //
+ // N.B. The first restart parameter block must be for the boot master
+ // and must represent logical processor 0.
+ //
+
+ NextRestartBlock = SYSTEM_BLOCK->RestartBlock;
+ if (NextRestartBlock == NULL) {
+ return FALSE;
+ }
+
+ //
+ // Scan the restart parameter blocks for a processor that is ready,
+ // but not running. If a processor is found, then fill in the restart
+ // processor state, set the logical processor number, and set start
+ // in the boot status.
+ //
+
+ LogicalNumber = 0;
+ PhysicalNumber = 0;
+ do {
+
+ if( NextRestartBlock->BootStatus.ProcessorReady == FALSE ){
+
+#if 0 //HALDBG
+ DbgPrint(
+ "HalStartNextProcessor: Processor %d not ready\n",
+ PhysicalNumber
+ );
+#endif
+ PhysicalNumber += 1;
+
+ } else {
+
+
+ //
+ // If the processor is not ready then we assume that it is not
+ // present. We must increment the physical processor number but
+ // the logical processor number does not changed.
+ //
+
+ //
+ // Check if this processor has already been started.
+ // If it has not then start it now.
+ //
+
+ if( NextRestartBlock->BootStatus.ProcessorStart == FALSE ){
+
+ RtlZeroMemory( &NextRestartBlock->u.Alpha,
+ sizeof(ALPHA_RESTART_STATE));
+ NextRestartBlock->u.Alpha.IntA0 =
+ ProcessorState->ContextFrame.IntA0;
+ NextRestartBlock->u.Alpha.IntSp =
+ ProcessorState->ContextFrame.IntSp;
+ NextRestartBlock->u.Alpha.ReiRestartAddress =
+ (ULONG) ProcessorState->ContextFrame.Fir;
+ Prcb = (PKPRCB)(LoaderBlock->Prcb);
+ Prcb->Number = (CCHAR)LogicalNumber;
+ Prcb->RestartBlock = NextRestartBlock;
+ NextRestartBlock->BootStatus.ProcessorStart = 1;
+
+ HalpInitializeProcessorMapping(
+ LogicalNumber,
+ PhysicalNumber,
+ LoaderBlock
+ );
+
+ return TRUE;
+
+ } else {
+
+ //
+ // Ensure that the logical to physical mapping has been
+ // established for this processor.
+ //
+
+ HalpInitializeProcessorMapping(
+ LogicalNumber,
+ PhysicalNumber,
+ LoaderBlock
+ );
+
+ }
+
+ LogicalNumber += 1;
+ PhysicalNumber += 1;
+ }
+
+ NextRestartBlock = NextRestartBlock->NextRestartBlock;
+
+ } while (NextRestartBlock != NULL);
+
+#endif // !defined(NT_UP)
+
+ return FALSE;
+}
+
+VOID
+HalpVerifyPrcbVersion(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function verifies that the HAL matches the kernel. If there
+ is a mismatch the HAL bugchecks the system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ PKPRCB Prcb;
+
+ //
+ // Verify Prcb major version number, and build options are
+ // all conforming to this binary image
+ //
+
+ Prcb = KeGetCurrentPrcb();
+
+#if DBG
+ if (!(Prcb->BuildType & PRCB_BUILD_DEBUG)) {
+ // This checked hal requires a checked kernel
+ KeBugCheckEx (MISMATCHED_HAL, 2, Prcb->BuildType, PRCB_BUILD_DEBUG, 0);
+ }
+#else
+ if (Prcb->BuildType & PRCB_BUILD_DEBUG) {
+ // This free hal requires a free kernel
+ KeBugCheckEx (MISMATCHED_HAL, 2, Prcb->BuildType, 0, 0);
+ }
+#endif
+#ifndef NT_UP
+ if (Prcb->BuildType & PRCB_BUILD_UNIPROCESSOR) {
+ // This MP hal requires an MP kernel
+ KeBugCheckEx (MISMATCHED_HAL, 2, Prcb->BuildType, 0, 0);
+ }
+#endif
+ if (Prcb->MajorVersion != PRCB_MAJOR_VERSION) {
+ KeBugCheckEx (MISMATCHED_HAL,
+ 1, Prcb->MajorVersion, PRCB_MAJOR_VERSION, 0);
+ }
+
+
+}
+
+
+VOID
+HalpParseLoaderBlock(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+{
+
+ if (LoaderBlock == NULL) {
+ return;
+ }
+
+ HalpRecurseLoaderBlock( (PCONFIGURATION_COMPONENT_DATA)
+ LoaderBlock->ConfigurationRoot);
+}
+
+
+
+VOID
+HalpRecurseLoaderBlock(
+ IN PCONFIGURATION_COMPONENT_DATA CurrentEntry
+ )
+/*++
+
+Routine Description:
+
+ This routine parses the loader parameter block looking for the PCI
+ node. Once found, used to determine if PCI parity checking should be
+ enabled or disabled. Set the default to not disable checking.
+
+Arguments:
+
+ CurrentEntry - Supplies a pointer to a loader configuration
+ tree or subtree.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ PCONFIGURATION_COMPONENT Component;
+ PWSTR NameString;
+
+ //
+ // Quick out
+ //
+
+ if (AlreadySet) {
+ return;
+ }
+
+ if (CurrentEntry) {
+ Component = &CurrentEntry->ComponentEntry;
+
+ if (Component->Class == AdapterClass &&
+ Component->Type == MultiFunctionAdapter) {
+
+ if (strcmp(Component->Identifier, "PCI") == 0) {
+ HalDisablePCIParityChecking = Component->Flags.ConsoleOut;
+ AlreadySet = TRUE;
+#if HALDBG
+ DbgPrint("ARC tree sets PCI parity checking to %s\n",
+ HalDisablePCIParityChecking ? "OFF" : "ON");
+#endif
+ return;
+ }
+ }
+
+ //
+ // Process all the Siblings of current entry
+ //
+
+ HalpRecurseLoaderBlock(CurrentEntry->Sibling);
+
+ //
+ // Process all the Childeren of current entry
+ //
+
+ HalpRecurseLoaderBlock(CurrentEntry->Child);
+
+ }
+}
+
+
+ULONG
+HalpQuerySystemFrequency(
+ ULONG SampleTime
+ )
+/*++
+
+Routine Description:
+
+ This routine returns the speed at which the system is running in hertz.
+ The system frequency is calculated by counting the number of processor
+ cycles that occur during 500ms, using the Programmable Interval Timer
+ (PIT) as the reference time. The PIT is used to generate a square
+ wave with a 50ms Period. We use the Speaker counter since we can
+ enable and disable the count from software. The output of the
+ speaker is obtained from the SIO NmiStatus register.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The system frequency in Hertz.
+
+--*/
+{
+ TIMER_CONTROL TimerControlSetup;
+ TIMER_CONTROL TimerControlReadStatus;
+ TIMER_STATUS TimerStatus;
+ NMI_STATUS NmiStatus;
+ PEISA_CONTROL controlBase;
+ ULONGLONG Count1;
+ ULONGLONG Count2;
+ ULONG NumberOfIntervals;
+ ULONG SquareWaveState = 0;
+
+// mdbfix - move this into eisa.h one day
+#define SB_READ_STATUS_ONLY 2
+
+ controlBase = HalpEisaControlBase;
+
+ //
+ // Disable the speaker counter.
+ //
+
+ *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus);
+
+ NmiStatus.SpeakerGate = 0;
+ NmiStatus.SpeakerData = 0;
+
+ // these are MBZ when writing to NMIMISC
+ NmiStatus.RefreshToggle = 0;
+ NmiStatus.SpeakerTimer = 0;
+ NmiStatus.IochkNmi = 0;
+
+ WRITE_PORT_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus));
+
+ //
+ // Number of Square Wave transitions to count.
+ // at 50ms period, count the number of 25ms
+ // square wave transitions for a sample reference
+ // time to against which we measure processor cycle count.
+ //
+
+ NumberOfIntervals = (SampleTime/50) * 2;
+
+ //
+ // Set the timer for counter 0 in binary mode, square wave output
+ //
+
+ TimerControlSetup.BcdMode = 0;
+ TimerControlSetup.Mode = TM_SQUARE_WAVE;
+ TimerControlSetup.SelectByte = SB_LSB_THEN_MSB;
+ TimerControlSetup.SelectCounter = SELECT_COUNTER_2;
+
+ //
+ // Set the counter for a latched read of the status.
+ // We will poll the PIT for the state of the square
+ // wave output.
+ //
+
+ TimerControlReadStatus.BcdMode = 0;
+ TimerControlReadStatus.Mode = (1 << SELECT_COUNTER_2);
+ TimerControlReadStatus.SelectByte = SB_READ_STATUS_ONLY;
+ TimerControlReadStatus.SelectCounter = SELECT_READ_BACK;
+
+
+ //
+ // Write the count value LSB and MSB for a 50ms clock period
+ //
+
+ WRITE_PORT_UCHAR( &controlBase->CommandMode1,
+ *(PUCHAR)&TimerControlSetup );
+
+ WRITE_PORT_UCHAR( &controlBase->SpeakerTone,
+ TIMER_REF_VALUE & 0xff );
+
+ WRITE_PORT_UCHAR( &controlBase->SpeakerTone,
+ (TIMER_REF_VALUE >> 8) & 0xff );
+
+ //
+ // Enable the speaker counter but disable the SPKR output signal.
+ //
+
+ *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus);
+
+ NmiStatus.SpeakerGate = 1;
+ NmiStatus.SpeakerData = 0;
+
+ // these are MBZ when writing to NMIMISC
+ NmiStatus.RefreshToggle = 0;
+ NmiStatus.SpeakerTimer = 0;
+ NmiStatus.IochkNmi = 0;
+
+ WRITE_PORT_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus));
+
+ //
+ // Synchronize with the counter before taking the first
+ // sample of the Processor Cycle Count (PCC). Since we
+ // are using the Square Wave Mode, wait until the next
+ // state change and then observe half a cycle before
+ // sampling.
+ //
+
+ //
+ // observe the low transition of the square wave output.
+ //
+ do {
+
+ *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus);
+
+ } while (NmiStatus.SpeakerTimer != SquareWaveState);
+
+ SquareWaveState ^= 1;
+
+ //
+ // observe the next transition of the square wave output and then
+ // take the first cycle counter sample.
+ //
+ do {
+
+ *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus);
+
+ } while (NmiStatus.SpeakerTimer != SquareWaveState);
+
+ Count1 = __RCC();
+
+ //
+ // Wait for the 500ms time period to pass and then take the
+ // second sample of the PCC. For a 50ms period, we have to
+ // observe eight wave transitions (25ms each).
+ //
+
+ do {
+
+ SquareWaveState ^= 1;
+
+ //
+ // wait for wave transition
+ //
+ do {
+
+ *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus);
+
+ } while (NmiStatus.SpeakerTimer != SquareWaveState);
+
+ } while (--NumberOfIntervals);
+
+ Count2 = __RCC();
+
+ //
+ // Disable the speaker counter.
+ //
+
+ *((PUCHAR) &NmiStatus) = READ_PORT_UCHAR(&controlBase->NmiStatus);
+
+ NmiStatus.SpeakerGate = 0;
+ NmiStatus.SpeakerData = 0;
+
+ WRITE_PORT_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus));
+
+ //
+ // Calculate the Hz by the number of processor cycles
+ // elapsed during 1s.
+ //
+ // Hz = PCC/SampleTime * 1000ms/s
+ // = PCC * (1000/SampleTime)
+ //
+
+ // did the counter wrap? if so add 2^32
+ if (Count1 > Count2) {
+
+ Count2 += (ULONGLONG)(1 << 32);
+
+ }
+
+ return ( ((ULONG) (Count2 - Count1)) *(((ULONG)1000)/SampleTime));
+}
+
+
+VOID
+HalpInitializeProcessorParameters(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine initalize the processor counter parameters
+ HalpClockFrequency and HalpClockMegaHertz based on the
+ estimated CPU speed. A 1s reference time is used for
+ the estimation.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ HalpClockFrequency = HalpQuerySystemFrequency(1000);
+ HalpClockMegaHertz = (HalpClockFrequency + 500000)/ 1000000;
+
+#if HALDBG
+ DbgPrint(
+ "Frequency = %d\nMegaHertz = %d\n",
+ HalpClockFrequency,
+ HalpClockMegaHertz
+ );
+#endif //HALDBG
+
+}
+
+
+
+
+#if 0
+VOID
+HalpGatherPerformanceParameterStats(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gathers statistics on the method for
+ estimating the system frequency.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG Index;
+ ULONG Hertz[32];
+ ULONGLONG Mean = 0;
+ ULONGLONG Variance = 0;
+ ULONGLONG TempHertz;
+
+ //
+ // take 32 samples of estimated CPU speed,
+ // calculating the mean in the process.
+ //
+ DbgPrint("Sample\tFrequency\tMegaHertz\n\n");
+
+ for (Index = 0; Index < 32; Index++) {
+ Hertz[Index] = HalpQuerySystemFrequency(500);
+ Mean += Hertz[Index];
+
+ DbgPrint(
+ "%d\t%d\t%d\n",
+ Index,
+ Hertz[Index],
+ (ULONG)((Hertz[Index] + 500000)/1000000)
+ );
+
+ }
+
+ //
+ // calculate the mean
+ //
+
+ Mean /= 32;
+
+ //
+ // calculate the variance
+ //
+ for (Index = 0; Index < 32; Index++) {
+ TempHertz = (Mean > Hertz[Index])?
+ (Mean - Hertz[Index]) : (Hertz[Index] - Mean);
+ TempHertz = TempHertz*TempHertz;
+ Variance += TempHertz;
+ }
+
+ Variance /= 32;
+
+ DbgPrint("\nResults\n\n");
+ DbgPrint(
+ "Mean = %d\nVariance = %d\nMegaHertz (derived) = %d\n",
+ Mean,
+ Variance,
+ (Mean + 500000)/ 1000000
+ );
+
+}
+#endif
+
diff --git a/private/ntos/nthals/halraw/alpha/intsup.s b/private/ntos/nthals/halraw/alpha/intsup.s
new file mode 100644
index 000000000..fa1669189
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/intsup.s
@@ -0,0 +1,256 @@
+//++
+//
+// Copyright (c) 1993 Digital Equipment Corporation
+//
+// Module Name:
+//
+// intsup.s
+//
+// Abstract:
+//
+// This module implements first level interrupt handlers.
+//
+// Author:
+//
+// Joe Notarangelo 08-Jul-1993
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+// 24-Sep-93 Joe Notarangelo
+// Make this module platform-independent.
+//--
+
+#include "halalpha.h"
+
+ SBTTL("System Clock Interrupt")
+//++
+//
+// VOID
+// HalpClockInterrupt(
+// )
+//
+// Routine Description:
+//
+// This function is executed for each interval timer interrupt on
+// the primary processor. The routine is responsible for acknowledging the
+// interrupt and calling the kernel to update the system time.
+// In addition, this routine checks for breakins from the kernel debugger
+// and maintains the 64 bit performance counter based upon the
+// processor cycle counter.
+//
+// Arguments:
+//
+// TrapFrame (fp/s6) - Supplies a pointer to the trap frame for
+// the interrupt.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+ .space 8 // filler for octaword alignment
+CiRa: .space 8 // space for return address
+CiFrameLength: //
+
+ NESTED_ENTRY(HalpClockInterrupt, CiFrameLength, zero )
+
+ lda sp, -CiFrameLength(sp) // allocate stack frame
+ stq ra, CiRa(sp) // save return address
+
+ PROLOGUE_END
+
+//
+// Acknowledge the clock interrupt.
+//
+
+ bsr ra, HalpAcknowledgeRawhideClockInterrupt // ack the interrupt
+ beq v0, 30f // Roll over? No: return
+
+//
+// Yes: Call the kernel to update the system time.
+//
+
+ ldl a1, HalpCurrentTimeIncrement // Get current time increment
+ bis fp, zero, a0 // a0 = pointer to trap frame
+ ldl t0, __imp_KeUpdateSystemTime
+ jsr ra, (t0) // call kernel
+
+// ldl t0, HalpNextTimeIncrement // Get next time increment
+// stl t0, HalpCurrentTimeIncrement // Set CurrentTimeIncrement to NextTimeIncrement
+
+ ldl a0, HalpNextRateSelect // Get NextIntervalCount. If 0, no change required
+ beq a0, 20f
+
+ stl zero, HalpNextRateSelect // Set NextRateSelect to 0
+ bsr ra, HalpProgramIntervalTimer // Program timer with new rate select
+
+ ldl t0, HalpNewTimeIncrement
+ stl t0, HalpCurrentTimeIncrement // Set HalpNextTimeIncrement to HalpNewTimeIncrement
+// stl t0, HalpNextTimeIncrement // Set HalpNextTimeIncrement to HalpNewTimeIncrement
+
+//
+// Call to handle performance counter wrap.
+//
+20:
+ bsr ra, HalpCheckPerformanceCounter // check for perf. counter wrap
+
+#if DEVL
+
+//
+// Check for a breakin request from the kernel debugger.
+//
+
+ ldl t0, __imp_KdPollBreakIn
+ jsr ra, (t0) // check for breakin requested
+ beq v0, 30f // if eq[false], no breakin
+ BREAK_BREAKIN // execute breakin breakpoint
+
+30:
+
+#endif //DEVL
+
+//
+// Return to the caller.
+//
+30:
+ ldq ra, CiRa(sp) // restore return address
+ lda sp, CiFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // return to caller
+
+ .end HalpClockInterrupt
+
+
+#ifndef NT_UP
+
+ SBTTL("Secondary Processor Clock Interrupt")
+//++
+//
+// VOID
+// HalpSecondaryClockInterrupt(
+// )
+//
+// Routine Description:
+//
+// This function is executed for each interval timer interrupt on
+// the current secondary processor. The routine is responsible for
+// acknowledging the interrupt and calling the kernel to update the
+// run time for the current processor.
+// In addition, this routine checks for breakins from the kernel debugger
+// and maintains the 64 bit performance counter based upon the
+// processor cycle counter.
+//
+// Arguments:
+//
+// TrapFrame (fp/s6) - Supplies a pointer to the trap frame for
+// the interrupt.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+
+ NESTED_ENTRY(HalpSecondaryClockInterrupt, CiFrameLength, zero )
+
+ lda sp, -CiFrameLength(sp) // allocate stack frame
+ stq ra, CiRa(sp) // save return address
+
+ PROLOGUE_END
+
+//
+// Acknowledge the clock interrupt.
+//
+
+ bsr ra, HalpAcknowledgeRawhideClockInterrupt // ack the interrupt
+ beq v0, 40f // Roll over? No: return
+
+//
+// Call the kernel to update the run time.
+//
+10:
+ bis fp, zero, a0 // a0 = pointer to trap frame
+ ldl t0, __imp_KeUpdateRunTime
+ jsr ra, (t0) // call kernel
+
+#if DEVL
+
+//
+// Check for a breakin request from the kernel debugger.
+//
+
+ ldl t0, __imp_KdPollBreakIn
+ jsr ra, (t0) // check for breakin requested
+ beq v0, 30f // if eq[false], no breakin
+ BREAK_BREAKIN // execute breakin breakpoint
+
+30:
+
+#endif //DEVL
+
+//
+// Return to the caller.
+//
+40:
+ ldq ra, CiRa(sp) // restore return address
+ lda sp, CiFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // return to caller
+
+ .end HalpSecondaryClockInterrupt
+
+ SBTTL("Interprocessor Interrupt")
+//++
+//
+// VOID
+// HalpIpiInterruptHandler
+// )
+//
+// Routine Description:
+//
+// This function is executed as the result of an interprocessor
+// interrupt asserted on the current processor. This function is
+// responsible for acknowledging the interrupt and dispatching to
+// the kernel for processing.
+//
+// Arguments:
+//
+// TrapFrame (fp/s6) - Supplies a pointer to the trap frame for
+// the interrupt.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+ .space 8 // filler for octaword alignment
+IpiRa: .space 8 // space for return address
+IpiFrameLength: //
+
+ NESTED_ENTRY(HalpIpiInterruptHandler, IpiFrameLength, zero )
+
+ lda sp, -IpiFrameLength(sp) // allocate stack frame
+ stq ra, IpiRa(sp) // save return address
+
+ PROLOGUE_END
+
+ bsr ra, HalpAcknowledgeIpiInterrupt // acknowledge interrupt
+
+ ldl t0, __imp_KeIpiInterrupt
+ jsr ra, (t0) // call kernel to process
+
+ ldq ra, IpiRa(sp) // restore return address
+ ret zero, (ra) // return
+
+ .end HalpIpiInterruptHandler
+
+
+#endif //NT_UP
+
diff --git a/private/ntos/nthals/halraw/alpha/iod.c b/private/ntos/nthals/halraw/alpha/iod.c
new file mode 100644
index 000000000..c04d46a85
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/iod.c
@@ -0,0 +1,1467 @@
+/*++
+
+Copyright (c) 1995 Digital Equipment Corporation
+
+Module Name:
+
+ iod.c
+
+Abstract:
+
+ This module implements functions that are specific to the IOD ASIC.
+ The IOD ASIC is a control ASIC for PCI on EV5-based Rawhide
+ systems.
+
+Author:
+
+ Eric Rehm 12-Apr-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "rawhide.h"
+
+BOOLEAN IodInitialized = FALSE;
+
+MC_DEVICE_MASK HalpIodMask = 0x0;
+MC_DEVICE_MASK HalpCpuMask = 0x0;
+MC_DEVICE_MASK HalpGcdMask = 0x0;
+
+//
+// Declare the IOD interrupt vector table and global pointer
+// Due to the fact that the MC_DEVICE_ID specifies the 64
+// byte offset into this global table, we must allocate
+// full table for all
+//
+
+
+PIOD_POSTED_INTERRUPT HalpIodPostedInterrupts;
+
+//
+// Declare the PCI logical to physical mapping structure
+//
+
+MC_DEVICE_ID HalpIodLogicalToPhysical[RAWHIDE_MAXIMUM_PCI_BUS];
+
+//
+// The revision of the IOD. Software visible differences may exist between
+// passes of the IOD. The revision is determined once at the start of
+// run-time and used in places where the software must diverge.
+//
+
+IOD_PCI_REVISION HalpIodRevision;
+
+//
+// Declare routines local to this module
+//
+
+
+VOID
+HalpInitializeBitMap (
+ IN PRTL_BITMAP BitMapHeader,
+ IN PULONG BitMapBuffer,
+ IN ULONG SizeOfBitMap
+);
+
+
+
+VOID
+HalpInitializeIodMappingTable(
+ MC_DEVICE_ID McDeviceId,
+ ULONG PciBusNumber,
+ va_list Arguments
+ )
+/*++
+
+Routine Description:
+
+ This enumeration routine initialize the IOD logical to physical
+ mapping table. The Logical IOD number is via a static variable
+ that is incremented for each invokation of this routine.
+
+Arguments:
+
+ McDeviceId - IOD device id to be mapped.
+
+ PciBusNumber - Logical PCI Bus number (unused).
+
+ Arguments - variable arguments. None for this routine.
+
+Return Values:
+
+ None:
+
+--*/
+
+{
+ HalpIodLogicalToPhysical[PciBusNumber].all = 0;
+ HalpIodLogicalToPhysical[PciBusNumber].Gid = McDeviceId.Gid;
+ HalpIodLogicalToPhysical[PciBusNumber].Mid = McDeviceId.Mid;
+
+#if HALDBG
+ DbgPrint("HalpIodLogicalToPhysical[%d] = %x\n",
+ PciBusNumber,
+ HalpIodLogicalToPhysical[PciBusNumber]);
+#endif // HALDBG
+
+}
+
+VOID
+HalpInitializeIodVectorTable(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Initialize the global pointer to the IOD vector table.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // Allocate the Global Iod vector table.
+ //
+
+ // mdbfix - we only need 4K, but require a page aligned
+ // address due to the fact that IOD uses target CPU's
+ // MC_DEVICE_ID as bits <11,6> of the vector table address
+ // in memory. So we allocate a PAGE more to guarantee
+ // a page aligned address.
+ //
+
+ HalpIodPostedInterrupts =
+ ExAllocatePool(
+ NonPagedPool,
+ __4K + __8K
+ );
+
+#if HALDBG
+ DbgPrint("HalpIodPostedInterrupts = 0x%x\n", HalpIodPostedInterrupts);
+#endif
+
+ if (HalpIodPostedInterrupts == NULL) {
+
+ DbgBreakPoint();
+
+ }
+}
+
+
+VOID
+HalpInitializeIod(
+ MC_DEVICE_ID McDeviceId,
+ ULONG PciBusNumber,
+ va_list Arguments
+ )
+/*++
+
+Routine Description:
+
+ This enumeration routine initializes the corresponding IOD.
+
+Arguments:
+
+ McDeviceId - Supplies the MC Bus Device ID of the IOD to be intialized
+
+ PciBusNumber - Logical PCI Bus number (unused).
+
+ Arguments - Variable arguments including:
+
+ 1) LoaderBlock - Supplies a pointer to the loader parameter block.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ IOD_CAP_CONTROL IodCapControl;
+ IOD_CAP_ERR IodCapError;
+ IOD_WBASE Wbase;
+ IOD_TBASE Tbase;
+ IOD_WMASK Wmask;
+ IOD_TBIA Tbia;
+ IOD_MDPA_STAT IodMdpaStat;
+ IOD_MDPB_STAT IodMdpbStat;
+ IOD_MDPA_DIAG IodMdpaDiag;
+ IOD_MDPB_DIAG IodMdpbDiag;
+ PLOADER_PARAMETER_BLOCK LoaderBlock;
+
+ //
+ // Initialize parameters
+ //
+
+// mdbfix - this is not used
+// LoaderBlock = va_arg(Arguments, PLOADER_PARAMETER_BLOCK);
+
+ //
+ // Read the IOD revision.
+ //
+
+ HalpIodRevision.all =
+ READ_IOD_REGISTER_NEW(
+ McDeviceId,
+ &((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->PciRevision );
+
+#if HALDBG
+
+ DbgPrint( "Entry - HalpInitializeIod\n\n");
+
+ DbgPrint( "IOD (%x,%x) Revision: \n", McDeviceId.Gid, McDeviceId.Mid);
+ DbgPrint( "\tCAP = 0x%x\n", HalpIodRevision.CapRev );
+ DbgPrint( "\tHorse = 0x%x\n", HalpIodRevision.HorseRev );
+ DbgPrint( "\tSaddle = 0x%x\n", HalpIodRevision.SaddleRev );
+ DbgPrint( "\tSaddle Type = 0x%x\n", HalpIodRevision.SaddleType );
+ DbgPrint( "\tEISA Present = 0x%x\n", HalpIodRevision.EisaPresent );
+ DbgPrint( "\tPCI Class, Subclass = 0x%0.2x%0.2x\n",
+ HalpIodRevision.BaseClass, HalpIodRevision.SubClass );
+
+#endif //HALDBG
+
+ //
+ // Initialize IOD Control. Currently, take the initial values
+ // set by the Extended SROM.
+ //
+
+ IodCapControl.all =
+ READ_IOD_REGISTER_NEW(
+ McDeviceId,
+ &((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->CapCtrl );
+
+#if HALDBG
+
+ DbgPrint( "Read Iod CAP Control = 0x%0.4x\n", IodCapControl.all );
+
+#endif //HALDBG
+
+
+#ifdef RISP //ecrfix
+
+ //
+ // For RISP, initialized as per Rawhide S/W Programmers Manual
+ //
+
+ IodCapControl.DlyRdEn = 1;
+ IodCapControl.PciMemEn = 1;
+ IodCapControl.PciReq64 = 1;
+ IodCapControl.PciAck64 = 1;
+ IodCapControl.PciAddrPe= 1;
+ IodCapControl.McCmdAddrPe= 1;
+ IodCapControl.McNxmEn = 1;
+ IodCapControl.McBusMonEn= 1;
+ IodCapControl.PendNum = 11; // 12 - [ (0 * 2) + 1 + (0 * 2)]
+ IodCapControl.RdType = 2;
+ IodCapControl.RlType = 2;
+ IodCapControl.RmType = 2;
+ IodCapControl.PartialWrEn = 0;
+ IodCapControl.ArbMode = 0;
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->CapCtrl,
+ IodCapControl.all );
+#if HALDBG
+
+ IodCapControl.all =
+ READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->CapCtrl );
+
+ DbgPrint( "Read Iod CAP Control = 0x%0.4x\n (after sets)", IodCapControl.all );
+
+#endif //HALDBG
+
+#endif //RISP
+
+
+ //
+ // Disable all of the scatter/gather windows.
+ //
+
+ Wbase.all = 0;
+ Wbase.Wen = 0;
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->W0base,
+ Wbase.all );
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->W1base,
+ Wbase.all );
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->W2base,
+ Wbase.all );
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->W3base,
+ Wbase.all );
+
+ //
+ // Invalidate all of the TLB Entries.
+ //
+
+ Tbia.all = 0;
+
+ //
+ // Perform the invalidation.
+ //
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->Tbia,
+ Tbia.all );
+
+ //
+ // Clear any pending error bits in the IOD_CAP_ERR register:
+ //
+
+ IodCapError.all = 0; // Clear all bits
+
+ IodCapError.Perr = 1; // PCI bus perr detected
+ IodCapError.Serr = 1; // PCI bus serr detected
+ IodCapError.Mab = 1; // PCI bus master abort detected
+ IodCapError.PteInv = 1; // Invalid Pte
+ IodCapError.PioOvfl = 1; // Pio Ovfl
+ IodCapError.LostMcErr = 1; // Lost error
+ IodCapError.McAddrPerr = 1; // MC bus comd/addr parity error
+ IodCapError.Nxm = 1; // MC bus Non-existent memory error
+ IodCapError.CrdA = 1; // Correctable ECC error on MDPA
+ IodCapError.CrdB = 1; // Correctable ECC error on MDPB
+ IodCapError.RdsA = 1; // Uncorrectable ECC error on MDPA
+ IodCapError.RdsA = 1; // Uncorrectable ECC error on MDPA
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->CapErr,
+ IodCapError.all );
+
+ //
+ // Clear any ECC error syndrome bits in the IOD_MDPA/B_SYN registers:
+ //
+
+ IodMdpaStat.all = 0;
+ IodMdpaStat.Crd = 1; // Correctable ECC error (also clears Rds bit)
+
+ IodMdpbStat.all = 0;
+ IodMdpbStat.Crd = 1; // Correctable ECC error (also clears Rds bit)
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpaStat,
+ IodMdpaStat.all );
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpbStat,
+ IodMdpbStat.all );
+
+#if 0 // CAP/MDP Bug
+
+ IodMdpaStat.all =
+ READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpaStat );
+
+ DbgPrint( "MDPA (%x,%x) Revision = 0x%x\n",
+ McDeviceId.Gid, McDeviceId.Mid, IodMdpaStat.MdpaRev);
+
+ IodMdpaStat.all =
+ READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpbStat );
+
+ DbgPrint( "MDPB (%x,%x) Revision = 0x%x\n",
+ McDeviceId.Gid, McDeviceId.Mid, IodMdpbStat.MdpbRev);
+
+#endif
+
+
+ //
+ // Initialize MDP Diagnostic Checking. Currently just take the
+ // initial values set by the Extended SROM. Do both Mdpa and Mdpb.
+ //
+
+#if 0 // CAP/MDP Bug
+
+ IodMdpaDiag.all =
+ READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpaDiag );
+
+ DbgPrint( "Read Iod MDPA Diag = 0x%0.4x\n", IodMdpaDiag.all );
+
+ IodMdpbDiag.all =
+ READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpbDiag );
+
+ DbgPrint( "Read Iod MDPB Diag = 0x%0.4x\n", IodMdpbDiag.all );
+
+#endif
+
+#if defined(AXP_FIRMWARE)
+
+ //
+ // Disable MCI bus interrupts
+ //
+
+ WRITE_IOD_REGISTER_NEW(
+ McDeviceId,
+ &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntCtrl,
+ (IOD_INT_CTL_DISABLE_IO_INT | IOD_INT_CTL_DISABLE_VECT_WRITE)
+ );
+
+ //
+ // Clear interrupt request register (New for CAP Rev2.3)
+ //
+
+ WRITE_IOD_REGISTER_NEW(
+ McDeviceId,
+ &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntReq,
+ IodIntMask
+ );
+
+ //
+ // Clear all pending interrupts for this IOD
+ //
+
+ WRITE_IOD_REGISTER_NEW(
+ McDeviceId,
+ &((PIOD_INT_CSRS)IOD_INT_CSRS_QVA)->IntAck0,
+ 0x0
+ );
+
+ //
+ // Clear all pending EISA interrupts for IOD 0
+ //
+
+ if ( (McDeviceId.Gid == GidPrimary) && (McDeviceId.Mid == MidPci0) ) {
+
+ INTERRUPT_ACKNOWLEDGE((PVOID)IOD_PCI0_IACK_QVA);
+
+ }
+
+ //
+ // Write the target register.
+ //
+
+ WRITE_IOD_REGISTER_NEW(
+ McDeviceId,
+ &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntTarg,
+ (GidPrimary << 9)|(MidCpu1 << 6)|
+ (GidPrimary << 3)|(MidCpu0)
+ );
+
+ //
+ // Initialize the mask bits for target 0 and 1
+ //
+
+ WRITE_IOD_REGISTER_NEW(
+ McDeviceId,
+ (PVOID)&((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntMask0,
+ 0
+ );
+
+ WRITE_IOD_REGISTER_NEW(
+ McDeviceId,
+ (PVOID)&((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntMask1,
+ 0
+ );
+
+#endif //if defined(AXP_FIRMWARE)
+
+ IodInitialized = TRUE;
+
+}
+
+VOID
+HalpClearAllIods(
+ IOD_CAP_ERR IodCapErrMask
+)
+/*++
+
+Routine Description:
+
+ Clears specified CapErr bits on all IODs.
+
+Arguments:
+
+ IodCapErrMask - Mask of bits to be cleared in each IOD_CAP_ERR.
+
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ MC_ENUM_CONTEXT mcCtx;
+ ULONG numIods;
+ BOOLEAN bfoundIod;
+ IOD_CAP_ERR IodCapErr;
+
+
+ //
+ // Clear all the error conditions in CAP_ERR on all IODs
+ // (Note - on 2 Mb Cached CPU, LostMcErr may also be set, so
+ // clear everything to be fer-sure, fer-sure.)
+ //
+
+ numIods = HalpMcBusEnumStart ( HalpIodMask, &mcCtx );
+
+ //
+ // Clear all errors on all IODs.
+ //
+
+ while ( bfoundIod = HalpMcBusEnum( &mcCtx ) ) {
+
+ //
+ // Read it
+ //
+
+ IodCapErr.all = READ_IOD_REGISTER_NEW( mcCtx.McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->CapErr );
+
+ //
+ // Mask it.
+ //
+
+ IodCapErr.all &= IodCapErrMask.all;
+
+ //
+ // If there is anything to clear, then do it.
+ //
+
+ if (IodCapErr.all != 0) {
+
+ WRITE_IOD_REGISTER_NEW( mcCtx.McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->CapErr,
+ IodCapErr.all );
+
+
+ }
+ }
+ }
+
+
+VOID
+HalpInitializeIodVectorCSRs(
+ MC_DEVICE_ID McDeviceId,
+ ULONG PciBusNumber,
+ va_list Arguments
+ )
+/*++
+
+Routine Description:
+
+ This enumeration routine initializes Interrupt Vector Table CSRS
+ for the corresponding IOD.
+
+ The address used by an IOD during interrupt vector writes
+ is:
+
+ 39 38 32 31 12 11 6 5 2 1 0
+ | | | | | | | | | | |
+ ===================================================================
+ |0 | INT_ADDR_EXT | INT_ADDR_LO | TARGET ID | PCI BUS OFFSET | 00 |
+ ===================================================================
+
+ Where:
+ INT_ADDR_EXT = 0 since our table resides in KSEG0_BASE.
+ INT_ADDR_LO = upper 20 bits (4K Page Addr) of Table Physical Address
+ TARGET_ID = MC_DEVICE_ID of Target CPU obtained from INT_TARG(0|1)
+ PCI_BUS_OFFSET = Logical PCI bus number used as an offset into vector
+ table by the interrupting IOD.
+
+ The assignment of PCI_BUS_OFFSET is based on the PCI bus number static
+ variable. This number is incremented with each invokation of this routine.
+
+Arguments:
+
+ McDeviceId - Supplies the MC Bus Device ID of the IOD to be intialized
+
+ PciBusNumber - Logical PCI Bus number (unused).
+
+ Arguments - Variable Arguments. None for this routine.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ IOD_INT_ADDR IodIntAddr;
+ IOD_INT_ADDR_EXT IodIntAddrExt;
+ IOD_INT_CONTROL IodIntControl;
+
+ //
+ // Initialize the Interrupt Vector Table Address register
+ // for this IOD.
+ //
+
+ IodIntAddr.all =
+ READ_IOD_REGISTER_NEW(
+ McDeviceId,
+ &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntAddr );
+
+ IodIntAddr.Reserved1 = 0; // MBZ
+ IodIntAddr.PciOffset = PciBusNumber; // Logical IOD #
+ IodIntAddr.Reserved2 = 0; // MBZ
+ IodIntAddr.IntAddrLo = ((ULONG)HalpIodPostedInterrupts / __4K);
+
+ //
+ // Mask off the KSEG0_BASE to convert this to a physical
+ // address.
+ //
+
+ IodIntAddr.all &= ~KSEG0_BASE;
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntAddr,
+ IodIntAddr.all );
+
+ //
+ // Initialize the interrupt vector table Address Extension
+ // register to zero since our address resides in KSEG0_BASE.
+ //
+
+ IodIntAddrExt.all =
+ READ_IOD_REGISTER_NEW(
+ McDeviceId,
+ &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntAddrExt );
+
+ IodIntAddrExt.all = 0;
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntAddrExt,
+ IodIntAddrExt.all );
+}
+
+
+VOID
+HalpIodInitializeSfwWindow(
+// ecrfix MC_DEVICE_ID McDeviceId,
+ PWINDOW_CONTROL_REGISTERS WindowRegisters,
+ IOD_WINDOW_NUMBER WindowNumber
+ )
+/*++
+
+Routine Description:
+
+ Initialize the DMA Control software window registers for the specified
+ DMA Window.
+
+Arguments:
+
+ WindowRegisters - Supplies a pointer to the software window control.
+
+ WindowNumber - Supplies the window number initialized. (0 = Isa Dma
+ Window, 1 = Master Dma Window).
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ switch( WindowNumber ){
+
+ //
+ // The ISA DMA Window.
+ //
+
+ case IodIsaWindow:
+
+ WindowRegisters->WindowBase = (PVOID)ISA_DMA_WINDOW_BASE;
+ WindowRegisters->WindowSize = ISA_DMA_WINDOW_SIZE;
+ WindowRegisters->TranslatedBaseRegister =
+ &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->T1base;
+ WindowRegisters->WindowBaseRegister =
+ &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->W1base;
+ WindowRegisters->WindowMaskRegister =
+ &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->W1mask;
+ WindowRegisters->WindowTbiaRegister =
+ &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->Tbia;
+
+ break;
+
+ case IodMasterWindow:
+
+ WindowRegisters->WindowBase = (PVOID)MASTER_DMA_WINDOW_BASE;
+ WindowRegisters->WindowSize = MASTER_DMA_WINDOW_SIZE;
+ WindowRegisters->TranslatedBaseRegister =
+ &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->T0base;
+ WindowRegisters->WindowBaseRegister =
+ &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->W0base;
+ WindowRegisters->WindowMaskRegister =
+ &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->W0mask;
+ WindowRegisters->WindowTbiaRegister =
+ &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->Tbia;
+
+ break;
+
+ default:
+
+#if HALDBG
+
+ DbgPrint( "IodInitializeSfwWindow: Bad Window Number = %x\n",
+ WindowNumber );
+
+#endif //HALDBG
+
+ break;
+
+ }
+
+ return;
+}
+
+
+VOID
+HalpIodProgramDmaWindow(
+ PWINDOW_CONTROL_REGISTERS WindowRegisters,
+ PVOID MapRegisterBase
+ )
+/*++
+
+Routine Description:
+
+ Program the control windows in the hardware so that DMA can be started
+ to the DMA window.
+
+Arguments:
+
+ WindowRegisters - Supplies a pointer to the software window register
+ control structure.
+
+ MapRegisterBase - Supplies the logical address of the scatter/gather
+ array in system memory.
+
+
+Return Value:
+
+ None.
+
+--*/
+{
+ IOD_WBASE Wbase;
+ IOD_TBASE Tbase;
+ IOD_WMASK Wmask;
+ IOD_TBIA Tbia;
+
+ MC_ENUM_CONTEXT mcCtx;
+ MC_DEVICE_ID McDeviceId;
+
+ //
+ // Program the windows as specified by the caller.
+ //
+
+ Wbase.all = 0;
+ Wbase.Wen = 1;
+ Wbase.SgEn = 1;
+ Wbase.Wbase = (ULONG)(WindowRegisters->WindowBase) >> 20;
+
+ Wmask.all = 0;
+ Wmask.Wmask = (WindowRegisters->WindowSize >> 20) - 1;
+
+ Tbase.all = 0;
+ Tbase.Tbase = (ULONG)MapRegisterBase >> 10;
+
+ Tbia.all = 0;
+
+ //
+ // Dump the IOD registers.
+ //
+
+#if HALDBG
+
+// DumpAllIods( IodScatterGatherRegisters );
+
+#endif //HALDBG
+
+ //
+ // Loop through all of the Iods
+ //
+ // ecrfix - is it OK to do it one at a time this way?
+ //
+
+ HalpMcBusEnumStart( HalpIodMask, &mcCtx );
+
+ while ( HalpMcBusEnum ( &mcCtx ) ) {
+
+ McDeviceId = mcCtx.McDeviceId;
+
+ //
+ // Clear the window base, temporarily disabling transactions to this
+ // DMA window.
+ //
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ WindowRegisters->WindowBaseRegister, 0 );
+
+ //
+ // Now program the window by writing the translated base, then the size
+ // of the window in the mask register and finally the window base,
+ // enabling both the window and scatter gather.
+ //
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ WindowRegisters->TranslatedBaseRegister,
+ Tbase.all );
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ WindowRegisters->WindowMaskRegister,
+ Wmask.all );
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ WindowRegisters->WindowBaseRegister,
+ Wbase.all );
+
+ //
+ // Flush the volatile entries in this IOD's scatter/gather Tlb.
+ //
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ WindowRegisters->WindowTbiaRegister,
+ Tbia.all );
+ }
+
+ // ecrfix - we did it above. HalpIodInvalidateTlb( WindowRegisters );
+
+ //
+ // Dump the IOD registers.
+ //
+
+#if HALDBG
+
+// DumpAllIods( IodScatterGatherRegisters | IodGeneralRegisters );
+
+#endif //HALDBG
+
+ return;
+}
+
+
+ULONG
+HalpMcBusEnumStart(
+ MC_DEVICE_MASK McDeviceMask,
+ PMC_ENUM_CONTEXT McContext
+ )
+/*++
+
+Routine Description:
+
+ Given a particular MC Bus device mask:
+
+ * Set up state so that subsequent MC Bus devices can be enumerated
+ by calling HalpMcBusEnum( McContext ).
+
+ * Return the first MC_DEVICE_ID in that mask via McContext.
+ (ECRFIX: IFDEF out for now!)
+
+ N.B. The search will start with GID = 7, i.e., McDeviceMask<56>
+ because the primary GID is 7.
+
+Arguments:
+
+ McDeviceMask - Supplies a bitfield of MC Bus devices to be enumerated.
+
+ McContext - A structure that contains the MC_DEVICE_ID to be enumerated
+ and associated enumerator state.
+
+
+Return Value:
+
+ Number of MC Bus devices to be enumerated.
+
+--*/
+{
+ ULONG count;
+
+ //
+ // Intialize the bitmap from the McDeviceMask.
+ // (Make a copy so that McDeviceMask is preserved for the caller.)
+ //
+
+ McContext->tempMask = McDeviceMask;
+
+// RtlInitializeBitMap(&McContext->McDeviceBitmap,
+ HalpInitializeBitMap(&McContext->McDeviceBitmap,
+ (PULONG) &McContext->tempMask,
+ sizeof(MC_DEVICE_MASK) * 8);
+
+ //
+ // Count the number of device to be enuerated
+ //
+
+ count = HalpNumberOfSetBits (&McContext->McDeviceBitmap);
+
+ //
+
+ // Start looking at GID = 7.
+ //
+
+ McContext->nextBit = GidPrimary * 8;
+
+#if 0
+ //
+ // Find the first MC Bus device to be enumerated.
+ //
+
+ McContext->nextBit = HalpFindSetBitsAndClear (&McContext->McDeviceBitmap,
+ 1,
+ McContext->nextBit);
+
+ //
+ // Convert first non-zero bit found to MC_DEVICE_ID
+ //
+
+ McContext->McDeviceId.all = 0;
+ McContext->McDeviceId.Gid = McContext->nextBit / 8;
+ McContext->McDeviceId.Mid = McContext->nextBit % 8;
+#endif
+
+ return ( count );
+
+}
+
+BOOLEAN
+HalpMcBusEnum(
+ PMC_ENUM_CONTEXT McContext
+ )
+/*++
+
+Routine Description:
+
+ Enumerate MC Bus devices until none are left
+
+Arguments:
+
+ McContext - A structure that contains the MC_DEVICE_ID to be enumerated
+ and associated enumerator state.
+
+
+Return Value:
+
+ TRUE, unless there were no more MC Bus devices to be enumerated,
+ in which case, returns FALSE.
+
+--*/
+{
+ //
+ // Find the next MC Bus device.
+ //
+
+ McContext->nextBit = HalpFindSetBitsAndClear (&McContext->McDeviceBitmap,
+ 1,
+ McContext->nextBit);
+
+ if ( McContext->nextBit != 0xffffffff) {
+
+ //
+ // Convert the non-zero bit found to MC_DEVICE_ID
+ //
+
+ McContext->McDeviceId.all = 0;
+ McContext->McDeviceId.Gid = McContext->nextBit / 8;
+ McContext->McDeviceId.Mid = McContext->nextBit % 8;
+
+ //
+ // Since we just set nextBit to zero, we can start the
+ // next search one bit higher. This will speed up the
+ // next call to HalpMcBusEnum.
+ //
+
+ McContext->nextBit++;
+
+ return ( TRUE );
+
+ } else {
+
+ return ( FALSE) ;
+
+ }
+
+}
+
+VOID
+HalpMcBusEnumAndCall(
+ MC_DEVICE_MASK McDeviceMask,
+ PMC_ENUM_ROUTINE McBusEnumRoutine,
+ ...
+ )
+/*++
+
+Routine Description:
+
+ Execute the Call routine for all devices in the MC device mask.
+ This routine provides a general method to enumerate an MC_DEVICE_MASK
+ and execute a caller-supplied routine for each device. A logical
+ device number and variable arguments are passed to the routine.
+
+Arguments:
+
+ McDeviceMask - Supplies a bitfield of MC Bus devices to be enumerated.
+
+ McBusEnumRoutine - Routine that is called for each MC Bus device.
+
+ ... - Variable arguments passed by the caller.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ MC_ENUM_CONTEXT mcCtx;
+ ULONG numIods;
+ ULONG LogicalDeviceNumber = 0;
+ va_list Arguments;
+
+ //
+ // Intialize enumerator.
+ //
+
+ numIods = HalpMcBusEnumStart ( McDeviceMask, &mcCtx );
+
+ //
+ // Execute routine for each device.
+ //
+
+ while ( HalpMcBusEnum( &mcCtx ) ) {
+ va_start(Arguments, McBusEnumRoutine);
+ McBusEnumRoutine( mcCtx.McDeviceId, LogicalDeviceNumber++, Arguments );
+ va_end(Arguments);
+ }
+}
+
+
+ULONG
+HalpReadWhoAmI(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Read the WHOAMI register.
+Arguments:
+
+ None.
+Return Value:
+
+ The value of the WHOAMI.
+
+--*/
+{
+
+ MC_DEVICE_ID McDeviceId;
+ IOD_WHOAMI IodWhoAmI;
+
+
+ //
+ // Initialize Id for IOD 0.
+ //
+
+ McDeviceId.all = 0;
+ McDeviceId.Gid = GidPrimary;
+ McDeviceId.Mid = MidPci0;
+
+
+ return (
+ READ_IOD_REGISTER_NEW(
+ McDeviceId,
+ &((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->WhoAmI )
+ );
+
+}
+
+
+VOID
+HalpIodInvalidateTlb(
+ PWINDOW_CONTROL_REGISTERS WindowRegisters
+ )
+/*++
+
+Routine Description:
+
+ Invalidate the DMA Scatter/Gather TLB in all the IODs.
+ The TLB is invalidated whenever the scatter/gather translation
+ entries are modified.
+
+Arguments:
+
+ WindowRegisters - Supplies a pointer to the software window register
+ control structure.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ //
+ // Perform the S/G TLB invalidation
+ //
+
+ IOD_TBIA Tbia;
+ MC_ENUM_CONTEXT mcCtx;
+
+ Tbia.all = 0;
+
+ HalpMcBusEnumStart(HalpIodMask, &mcCtx);
+
+ while ( HalpMcBusEnum( &mcCtx ) ) {
+
+ WRITE_IOD_REGISTER_NEW( mcCtx.McDeviceId,
+ WindowRegisters->WindowTbiaRegister,
+ Tbia.all );
+
+ }
+
+}
+
+
+#if HALDBG || DUMPIODS
+
+IOD_REGISTER_CLASS DumpIodFlag = AllRegisters;
+
+VOID
+DumpAllIods(
+ IOD_REGISTER_CLASS RegistersToDump
+ )
+/*++
+
+Routine Description:
+
+ Read the interesting Iod registers and print them to the debug port.
+
+Arguments:
+
+ McDeviceId - Supplies the MC Bus Device ID of the IOD to be dumped
+
+
+Return Value:
+
+ None.
+
+--*/
+{
+ MC_ENUM_CONTEXT mcCtx;
+ ULONG NumIods;
+
+ DbgPrint( "Dump All IODs: \n" );
+
+ NumIods = HalpMcBusEnumStart(HalpIodMask, &mcCtx);
+
+ DbgPrint( "Dump All IODs: (%d IODs)\n", NumIods );
+
+ while ( HalpMcBusEnum( &mcCtx ) ) {
+
+ DumpIod( mcCtx.McDeviceId,
+ RegistersToDump );
+ }
+
+
+}
+
+VOID
+DumpIod(
+ MC_DEVICE_ID McDeviceId,
+ IOD_REGISTER_CLASS RegistersToDump
+ )
+/*++
+
+Routine Description:
+
+ Read the interesting Iod registers and print them to the debug port.
+
+Arguments:
+
+ McDeviceId - Supplies the MC Bus Device ID of the IOD to be dumped
+
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PVOID RegisterQva;
+ ULONG Value;
+
+ DbgPrint( "IOD (%x, %x) Register Dump: \n", McDeviceId.Gid, McDeviceId.Mid );
+
+ //
+ // Dump the IOD General Control registers.
+ //
+
+ if( (RegistersToDump & IodGeneralRegisters) != 0 ){
+
+ RegisterQva = &((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->PciRevision;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "IodRevision = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->WhoAmI;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "WhoAmI = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->PciLat;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "PciLat = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->CapCtrl;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "IodCtrl = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->HaeMem;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "HaeMem = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->HaeIo;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "HaeIo = 0x%x\n", Value );
+
+#if 0 // ecrfix - don't read this on PCI0 - creates an IACK cycle
+ // on the EISA bus. Don't read this on PCI1,2,3, because
+ // (apparently), it doesn't exist there.
+
+ RegisterQva = &((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->IackSc;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "IackSc = 0x%x\n", Value );
+#endif
+
+ }
+
+ //
+ // Dump the IOD Interrupt registers.
+ //
+
+ if( (RegistersToDump & IodInterruptRegisters) != 0 ){
+
+ RegisterQva = &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntCtrl;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "IntCtrl = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntReq;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "IntReq = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntTarg;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "IntTarg = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntAddr;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "IntAddr = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntAddrExt;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "IntAddrExt = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntMask0;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "IntMask0 = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntMask1;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "IntMask1 = 0x%x\n", Value );
+
+
+ }
+
+ //
+ // Dump the IOD Diagnostic registers.
+ //
+
+ if( (RegistersToDump & IodDiagnosticRegisters) != 0 ){
+
+ RegisterQva = &((PIOD_DIAG_CSRS)(IOD_DIAG_CSRS_QVA))->CapDiag;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "CapDiag = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_DIAG_CSRS)(IOD_DIAG_CSRS_QVA))->Scratch;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "Scratch = 0x%x\n", Value );
+
+ }
+
+ //
+ // Dump the IOD Error registers.
+ //
+
+ if( (RegistersToDump & IodErrorRegisters) != 0 ){
+
+ RegisterQva = &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->McErr0;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "MCErr0 = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->McErr1;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "MCErr1 = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->CapErr;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "CapErr = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->PciErr1;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "PciErr1 = 0x%x\n", Value );
+
+#if 0 // CAP/MDP Bug
+ RegisterQva = &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpaStat;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "MdpaStat = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpaSyn;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "MdpaSyn = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpaDiag;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "MdpaDiag = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpbStat;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "MdpbStat = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpbSyn;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "MdpbSyn = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpbDiag;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "MdpbDiag = 0x%x\n", Value );
+#endif
+ }
+
+ //
+ // Dump the PCI Scatter/Gather registers.
+ //
+
+ if( (RegistersToDump & IodScatterGatherRegisters) != 0 ){
+
+ RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->Tbia;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "Tbia = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->Hbase;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "Hbase = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->W0base;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "W0base = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->W0mask;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "W0mask = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->T0base;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "T0base = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->W1base;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "W1base = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->W1mask;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "W1mask = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->T1base;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "T1base = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->W2base;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "W2base = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->W2mask;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "W2mask = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->T2base;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "T2base = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->W3base;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "W3base = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->W3mask;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "W3mask = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->T3base;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "T3base = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->Wdac;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "Wdac = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->TbTag0;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "TbTag0 = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->TbTag1;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "TbTag1 = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->TbTag2;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "TbTag2 = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->TbTag3;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "TbTag3 = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->TbTag4;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "TbTag4 = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->TbTag5;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "TbTag5 = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->TbTag6;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "TbTag6 = 0x%x\n", Value );
+
+ RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->TbTag7;
+ Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
+ DbgPrint( "TbTag7 = 0x%x\n", Value );
+ }
+
+ //
+ // Dump the IOD Reset register.
+ //
+
+ if( (RegistersToDump & IodResetRegister) != 0 ){
+
+ RegisterQva = (PIOD_ELCR1)((ULONG)HalpEisaControlBase + 27);
+ Value = (ULONG) READ_PORT_UCHAR( (PUCHAR) RegisterQva );
+ DbgPrint( "ELCR2 = 0x%x\n", Value );
+
+ }
+
+
+ DbgPrint( "--end IOD Register dump\n\n" );
+
+ return;
+
+}
+
+#endif //HALDBG || DUMPIODS
+
diff --git a/private/ntos/nthals/halraw/alpha/iod.h b/private/ntos/nthals/halraw/alpha/iod.h
new file mode 100644
index 000000000..6aee89719
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/iod.h
@@ -0,0 +1,1669 @@
+/*++
+
+Copyright (c) 1995 Digital Equipment Corporation
+
+Module Name:
+
+ iod.h
+
+Abstract:
+
+ This file defines the structures and definitions registers on a
+ Rawhide I/O Daughter card. These register reside on the CAP chip,
+ MDP chips, and flash ROM.
+
+
+Author:
+
+ Eric Rehm 16-Feb-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#ifndef _IODH_
+#define _IODH_
+
+
+//
+// IOD Revision definitions.
+//
+
+#define IOD_REVISION_1 (0)
+#define IOD_REVISION_2 (1)
+
+//
+// Define QVA constants.
+//
+
+#if !defined(QVA_ENABLE)
+
+#define QVA_ENABLE (0xA0000000) // Identify VA as a QVA
+
+#endif //QVA_ENABLE
+
+#define QVA_SELECTORS (0xE0000000) // QVA identification mask
+
+#define IO_BIT_SHIFT 0x05 // Bits to shift QVA
+
+#define IO_BYTE_OFFSET 0x20 // Offset to next byte
+#define IO_SHORT_OFFSET 0x40 // Offset to next short
+#define IO_LONG_OFFSET 0x80 // Offset to next long
+
+#define IO_BYTE_LEN 0x00 // Byte length
+#define IO_WORD_LEN 0x08 // Word length
+#define IO_TRIBYTE_LEN 0x10 // TriByte length
+#define IO_LONG_LEN 0x18 // Longword length
+
+#define IOD_SPARSE_SELECTORS (0x18000000) // BusNumber is encoded in QVA<28:27>
+#define IOD_SPARSE_ENABLE (0xB8000000) // QVA_SELECTORS|IOD_SPARSE_SELECTORS
+#define IOD_SPARSE_BUS_SHIFT 0x06 // Bits to shift BusNumber into MID
+
+#define IOD_DENSE_SELECTORS (0xC0000000) // BusNumber is encoded in QVA<31:30>
+#define IOD_DENSE_ENABLE (0xC0000000) // Same as IOD_DENSE_SELECTORS
+#define IOD_DENSE_BUS_SHIFT 0x03 // Bits to shift BusNumber into MID
+
+//
+// Define size of I/O and memory space for the CIA.
+// Assume that the HAE==0.
+//
+
+#define PCI_MAX_IO_ADDRESS (__32MB - 1) // I/O: 0 - 32MB
+#define PCI_MAX_SPARSE_MEMORY_ADDRESS (__128MB - 1) // Mem: 0 - 128MB
+#define PCI_MIN_DENSE_MEMORY_ADDRESS PCI_MAX_SPARSE_MEMORY_ADDRESS + 1
+#define PCI_MAX_DENSE_MEMORY_ADDRESS (__1GB - 1) // Dense: 128 Mb - 1.0 Gb
+
+#if !defined(_LANGUAGE_ASSEMBLY)
+
+#define GID_TO_PHYS_ADDR( GID ) ((ULONGLONG)(((GID & 0x7) << 36))
+#define MCDEVID_FROM_PHYS_ADDR( PA ) ( (ULONG)(((PA) >> 33) & 0x3f) )
+#if 0
+#define MCDEVID_TO_PHYS_ADDR( MCDEVID ) \
+ ((ULONGLONG)((ULONGLONG)(MCDEVID & 0x3F ) << 33 ))
+#else
+#define MCDEVID_TO_PHYS_ADDR( MCDEVID ) \
+ ((ULONGLONG)((ULONGLONG)(MCDEVID & 0x07 ) << 33 ))
+#endif
+#define MCDEVID_TO_PHYS_CPU( MCDEVID ) \
+ ( (((MCDEVID) & 0x07) < 4) ? \
+ (((MCDEVID) & 0x07) - 2) : \
+ (((MCDEVID) & 0x07) - 4) )
+#define PHYS_ADDR_TO_OFFSET( PA ) ( (PA) & ( (ULONGLONG) 0x1FFFFFFFF) )
+#define IOD_QVA_PHYSICAL_BASE ((ULONGLONG)0xf800000000)
+
+
+//
+// QVA
+// HAL_MAKE_QVA(
+// ULONGLONG PhysicalAddress
+// )
+//
+// Routine Description:
+//
+// This macro returns the Qva for a physical address in system space.
+//
+// Arguments:
+//
+// PhysicalAddress - Supplies a 64-bit physical address.
+//
+// Return Value:
+//
+// The Qva associated with the physical address.
+//
+
+#define HAL_MAKE_QVA(PA) \
+ ( (PVOID)( QVA_ENABLE | \
+ (ULONG)( (PA - IOD_QVA_PHYSICAL_BASE) >> IO_BIT_SHIFT) ) )
+
+//
+// QVA
+// HAL_MAKE_IOD_SPARSE_QVA(
+// ULONG BusNumber,
+// ULONG BusAddress
+// )
+//
+// Routine Description:
+//
+// This macro returns the Qva for a physical address in sparse I/O
+// or sparse memory space.
+//
+// Arguments:
+//
+// BusNumber - Supplies a bus number between 0-3.
+// BusAddress - Supplies a 32-bit PCI bus address.
+//
+// Return Value:
+//
+// The Qva associated with bus number and bus address.
+// HAL I/O access routines can use this to constrct the
+// correct physical address for the accesss.
+//
+
+#define HAL_MAKE_IOD_SPARSE_QVA(BUS_NUMBER, BA) \
+ ( (PVOID)( QVA_ENABLE | (BUS_NUMBER << 27) | ((ULONG) BA) ) )
+
+
+//
+// QVA
+// HAL_MAKE_IOD_DENSE_QVA(
+// ULONG BusNumber,
+// ULONG BusAddress
+// )
+//
+// Routine Description:
+//
+// This macro returns the Qva for a physical address in dense
+// memory space space.
+//
+// Arguments:
+//
+// BusNumber - Supplies a bus number between 0-3.
+// BusAddress - Supplies a 32-bit PCI bus address.
+//
+// Return Value:
+//
+// The Qva associated with bus number and bus address.
+// HAL I/O access routines can use this to constrct the
+// correct physical address for the accesss.
+//
+
+#define HAL_MAKE_IOD_DENSE_QVA(BUS_NUMBER, BA) \
+ ( (PVOID)( (BUS_NUMBER << 30) | ((ULONG) BA) ) )
+
+
+
+
+//
+// Define GID/MIDs for IIP and PIO flavors of MC Bus
+//
+
+#define IOD_DODGE_GID 0x7
+#define IOD_DURANGO_GID IOD_DODGE_GID
+
+#define IOD_GCD_MID 0x0
+#define IOD_MEM_MID 0x1
+#define IOD_CPU0_MID 0x2
+#define IOD_CPU1_MID 0x3
+#define IOD_PCI0_MID 0x4
+#define IOD_PCI1_MID 0x5
+#define IOD_CPU2_MID 0x6
+#define IOD_PCI2_MID IOD_CPU2_MID
+#define IOD_CPU3_MID 0x7
+#define IOD PCI3_MID IOD_CPU3_MID
+
+//
+// QVA
+// HAL_MAKE_NEW_QVA(
+// ULONGLONG PhysicalAddress
+// )
+//
+// Routine Description:
+//
+// This macro returns the Qva for a physical address in system space.
+//
+// Arguments:
+//
+// PhysicalAddress - Supplies a 64-bit physical address.
+//
+// Return Value:
+//
+// The Qva associated with the physical address.
+//
+
+#define HAL_MAKE_NEW_QVA(PA) \
+ ( (PVOID)( QVA_ENABLE | (ULONG)( (PA) >> IO_BIT_SHIFT) ) )
+
+//
+// Define IO space offsets for generic rawhide
+//
+
+#define IOD_IO_SPACE_START ((ULONGLONG)0x8000000000)
+
+//
+// These offsets are from IOD_IO_SPACE_START
+//
+
+#define IOD_GCD_CSRS_OFFSET ((ULONGLONG)0x0000000000)
+#define IOD_MEMORY_CSRS_OFFSET ((ULONGLONG)0x0200000000)
+
+#define IOD_CPU_IP_INTR_OFFSET ((ULONGLONG)0x0010000000)
+#define IOD_CPU_NODE_HALT_OFFSET ((ULONGLONG)0x0070000000)
+#define IOD_CPU_INTTIM_ACK_OFFSET ((ULONGLONG)0x0100000000)
+#define IOD_CPU_IO_INTR_OFFSET ((ULONGLONG)0x00f0000000)
+#define IOD_CPU_IP_ACK_OFFSET ((ULONGLONG)0x0110000000)
+#define IOD_CPU_MCHK_ACK_OFFSET ((ULONGLONG)0x0130000000)
+#define IOD_CPU_DTAG_EN_0_OFFSET ((ULONGLONG)0x0140000000)
+#define IOD_CPU_DTAG_EN_1_OFFSET ((ULONGLONG)0x0150000000)
+#define IOD_CPU_HALT_ACK_OFFSET ((ULONGLONG)0x0170000000)
+
+#define IOD_SPARSE_MEM_OFFSET ((ULONGLONG)0x0000000000)
+#define IOD_DENSE_MEM_OFFSET ((ULONGLONG)0x0100000000)
+#define IOD_SPARSE_IO_OFFSET ((ULONGLONG)0x0180000000)
+#define IOD_SPARSE_CONFIG_OFFSET ((ULONGLONG)0x01c0000000)
+#define IOD_SPARSE_CSR_OFFSET ((ULONGLONG)0x01e0000000)
+
+//
+// Generic Rawhide I/O Address Computation macros
+//
+
+#define IOD_GCD_CSRS_QVA \
+ (HAL_MAKE_NEW_QVA(IOD_GCD_CSRS_OFFSET))
+
+#define IOD_MEMORY_CSRS_QVA \
+ (HAL_MAKE_NEW_QVA(IOD_MEMORY_CSRS_OFFSET))
+
+#define IOD_CPU_IP_INTR_QVA \
+ (HAL_MAKE_NEW_QVA(IOD_CPU_IP_INTR_OFFSET))
+
+#define IOD_CPU_NODE_HALT_QVA \
+ (HAL_MAKE_NEW_QVA(IOD_CPU_NODE_HALT_OFFSET))
+
+#define IOD_CPU_IO_INTR_QVA \
+ (HAL_MAKE_NEW_QVA(IOD_CPU_IO_INTR_OFFSET))
+
+#define IOD_CPU_INTTIM_ACK_QVA \
+ (HAL_MAKE_NEW_QVA(IOD_CPU_INTTIM_ACK_OFFSET))
+
+#define IOD_CPU_IP_ACK_QVA \
+ (HAL_MAKE_NEW_QVA(IOD_CPU_IP_ACK_OFFSET))
+
+#define IOD_CPU_MCHK_ACK_QVA \
+ (HAL_MAKE_NEW_QVA(IOD_CPU_MCHK_ACK_OFFSET))
+
+#define IOD_CPU_DTAG_EN_0_QVA \
+ (HAL_MAKE_NEW_QVA(IOD_CPU_DTAG_EN_0_OFFSET))
+
+#define IOD_CPU_DTAG_EN_1_QVA \
+ (HAL_MAKE_NEW_QVA(IOD_CPU_DTAG_EN_1_OFFSET))
+
+#define IOD_CPU_HALT_ACK_QVA \
+ (HAL_MAKE_NEW_QVA(IOD_CPU_HALT_ACK_OFFSET))
+
+#define IOD_SPARSE_MEM_QVA \
+ (HAL_MAKE_NEW_QVA(IOD_SPARSE_MEM_OFFSET ))
+
+#define IOD_DENSE_MEM_QVA \
+ (HAL_MAKE_NEW_QVA(IOD_DENSE_MEM_OFFSET ))
+
+#define IOD_SPARSE_IO_QVA \
+ (HAL_MAKE_NEW_QVA(IOD_SPARSE_IO_OFFSET ))
+
+#define IOD_SPARSE_CONFIG_QVA \
+ (HAL_MAKE_NEW_QVA(IOD_SPARSE_CONFIG_OFFSET ))
+
+#define IOD_SPARSE_CSR_QVA \
+ (HAL_MAKE_NEW_QVA(IOD_SPARSE_CSR_OFFSET ))
+
+#define IOD_GENERAL_CSRS_QVA IOD_SPARSE_CSR_QVA
+
+#define IOD_PCI_IACK_QVA \
+ (HAL_MAKE_NEW_QVA(IOD_SPARSE_CSR_OFFSET + 0x480))
+
+#define IOD_INT_CSRS_QVA \
+ (HAL_MAKE_NEW_QVA(IOD_SPARSE_CSR_OFFSET + 0x500))
+
+#define IOD_DIAG_CSRS_QVA \
+ (HAL_MAKE_NEW_QVA(IOD_SPARSE_CSR_OFFSET + 0x700))
+
+#define IOD_ERROR_CSRS_QVA \
+ (HAL_MAKE_NEW_QVA(IOD_SPARSE_CSR_OFFSET + 0x800))
+
+#define IOD_SG_CSRS_QVA \
+ (HAL_MAKE_NEW_QVA(IOD_SPARSE_CSR_OFFSET + 0x1300))
+
+//
+// Define physical address space for 1 CPU at GID=7, MID=1,
+// and XSone IOD. // ecrfix
+//
+
+#define IOD_GCD_CSRS_PHYSICAL ((ULONGLONG)0xf000000000)
+#define IOD_MEMORY_CSRS_PHYSICAL ((ULONGLONG)0xf200000000)
+
+#define IOD_CPU0_IO_INTR_PHYSICAL ((ULONGLONG)0xf400000000)
+#define IOD_CPU0_IP_INTR_PHYSICAL ((ULONGLONG)0xf510000000)
+#define IOD_CPU0_NODE_HALT_PHYSICAL ((ULONGLONG)0xf520000000)
+
+//
+// PCI Bus 0
+//
+
+// old ecrfix #define IOD_PCI0_DENSE_MEMORY_PHYSICAL ((ULONGLONG)0xf800000000)
+// old ecrfix #define IOD_PCI0_SPARSE_MEMORY_PHYSICAL ((ULONGLONG)0xf900000000)
+#define IOD_PCI0_SPARSE_MEMORY_PHYSICAL ((ULONGLONG)0xf800000000)
+#define IOD_PCI0_DENSE_MEMORY_PHYSICAL ((ULONGLONG)0xf900000000)
+#define IOD_PCI0_SPARSE_IO_PHYSICAL ((ULONGLONG)0xf980000000)
+#define IOD_PCI0_CONFIGURATION_PHYSICAL ((ULONGLONG)0xf9C0000000)
+#define IOD_MAIN0_CSRS_PHYSICAL ((ULONGLONG)0xf9E0000000)
+
+#define IOD_PCI0_CONFIG_BASE_QVA (HAL_MAKE_QVA(IOD_PCI0_CONFIGURATION_PHYSICAL))
+#define IOD_PCI0_SPARSE_IO_QVA (HAL_MAKE_QVA(IOD_PCI0_SPARSE_IO_PHYSICAL))
+#define IOD_PCI0_SPARSE_MEMORY_QVA (HAL_MAKE_QVA(IOD_PCI0_SPARSE_MEMORY_PHYSICAL))
+
+#define IOD_GENERAL0_CSRS_PHYSICAL ((ULONGLONG)IOD_MAIN0_CSRS_PHYSICAL)
+#define IOD_GENERAL0_CSRS_QVA HAL_MAKE_QVA(IOD_GENERAL0_CSRS_PHYSICAL)
+
+#define IOD_PCI0_IACK_PHYSICAL ((ULONGLONG)IOD_MAIN0_CSRS_PHYSICAL+0x480)
+#define IOD_PCI0_IACK_QVA HAL_MAKE_QVA(IOD_PCI0_IACK_PHYSICAL)
+
+#define IOD_INT0_CSRS_PHYSICAL ((ULONGLONG)IOD_MAIN0_CSRS_PHYSICAL+0x500)
+#define IOD_INT0_CSRS_QVA HAL_MAKE_QVA(IOD_INT0_CSRS_PHYSICAL)
+#define IOD_DIAG0_CSRS_PHYSICAL ((ULONGLONG)IOD_MAIN0_CSRS_PHYSICAL+0x700)
+#define IOD_DIAG0_CSRS_QVA HAL_MAKE_QVA(IOD_DIAG0_CSRS_PHYSICAL)
+
+#define IOD_ERROR0_CSRS_PHYSICAL ((ULONGLONG)IOD_MAIN0_CSRS_PHYSICAL+0x800)
+#define IOD_ERROR0_CSRS_QVA HAL_MAKE_QVA(IOD_ERROR0_CSRS_PHYSICAL)
+
+#define IOD_SCATTER_GATHER0_CSRS_PHYSICAL ((ULONGLONG)IOD_MAIN0_CSRS_PHYSICAL+0x1300)
+#define IOD_SG0_CSRS_QVA (HAL_MAKE_QVA(IOD_SCATTER_GATHER0_CSRS_PHYSICAL))
+
+//
+// PCI Bus 1
+//
+
+#define IOD_PCI1_SPARSE_MEMORY_PHYSICAL ((ULONGLONG)0xfa00000000)
+#define IOD_PCI1_DENSE_MEMORY_PHYSICAL ((ULONGLONG)0xfb00000000)
+#define IOD_PCI1_SPARSE_IO_PHYSICAL ((ULONGLONG)0xfb80000000)
+#define IOD_PCI1_CONFIGURATION_PHYSICAL ((ULONGLONG)0xfbC0000000)
+#define IOD_MAIN1_CSRS_PHYSICAL ((ULONGLONG)0xfbE0000000)
+
+#define IOD_PCI1_CONFIG_BASE_QVA (HAL_MAKE_QVA(IOD_PCI1_CONFIGURATION_PHYSICAL))
+#define IOD_PCI1_SPARSE_IO_QVA (HAL_MAKE_QVA(IOD_PCI1_SPARSE_IO_PHYSICAL))
+#define IOD_PCI1_SPARSE_MEMORY_QVA (HAL_MAKE_QVA(IOD_PCI1_SPARSE_MEMORY_PHYSICAL))
+
+#define IOD_GENERAL1_CSRS_PHYSICAL ((ULONGLONG)IOD_MAIN1_CSRS_PHYSICAL)
+#define IOD_GENERAL1_CSRS_QVA HAL_MAKE_QVA(IOD_GENERAL1_CSRS_PHYSICAL)
+
+#define IOD_INT1_CSRS_PHYSICAL ((ULONGLONG)IOD_MAIN1_CSRS_PHYSICAL+0x500)
+#define IOD_INT1_CSRS_QVA HAL_MAKE_QVA(IOD_INT1_CSRS_PHYSICAL)
+
+#define IOD_DIAG1_CSRS_PHYSICAL ((ULONGLONG)IOD_MAIN1_CSRS_PHYSICAL+0x700)
+#define IOD_DIAG1_CSRS_QVA HAL_MAKE_QVA(IOD_DIAG1_CSRS_PHYSICAL)
+
+#define IOD_ERROR1_CSRS_PHYSICAL ((ULONGLONG)IOD_MAIN1_CSRS_PHYSICAL+0x800)
+#define IOD_ERROR1_CSRS_QVA HAL_MAKE_QVA(IOD_ERROR1_CSRS_PHYSICAL)
+
+#define IOD_SCATTER_GATHER1_CSRS_PHYSICAL ((ULONGLONG)IOD_MAIN1_CSRS_PHYSICAL+0x1300)
+#define IOD_SG_CSRS1_QVA (HAL_MAKE_QVA(IOD_SCATTER_GATHER1_CSRS_PHYSICAL))
+
+//
+// Define the classes of IOD registers.
+//
+
+typedef enum _IOD_REGISTER_CLASS{
+ IodGeneralRegisters = 0x1,
+ IodInterruptRegisters = 0x2,
+ IodDiagnosticRegisters = 0x3,
+ IodErrorRegisters = 0x4,
+ IodScatterGatherRegisters = 0x5,
+ IodFlashRomRegisters = 0x6,
+ IodResetRegister = 0x7,
+ AllRegisters = 0xffffffff
+} IOD_REGISTER_CLASS, *PIOD_REGISTER_CLASS;
+
+//
+// Define the MC bus global id's
+//
+
+typedef enum _MC_GLOBAL_ID{
+ GidPrimary = 0x7
+} MC_GLOBAL_ID, *PMC_GLOBAL_ID;
+
+//
+// Define the MC bus module id's
+//
+
+typedef enum _MC_MODULE_ID{
+ MidGcd = 0x0,
+ MidMem = 0x1,
+ MidCpu0 = 0x2,
+ MidCpu1 = 0x3,
+ MidPci0 = 0x4,
+ MidPci1 = 0x5,
+ MidCpu2 = 0x6, // Dodge, IIP Motherboard
+ MidCpu3 = 0x7, // Dodge, IIP Motherboard
+ MidPci2 = 0x6, // Durango, PIO Motherboard
+ MidPci3 = 0x7 // Durango, PIO Motherboard
+} MC_MODULE_ID, *PMC_MODULE_ID;
+
+//
+// Define the MC device id type
+//
+
+typedef union _MC_DEVICE_ID{
+ struct{
+ ULONG Mid: 3; // <2:0> Module Id
+ ULONG Gid: 3; // <5:3> Global Id
+ ULONG Reserved0: 26; //
+ };
+ ULONG all; // <5:0> MC Bus Device Id
+} MC_DEVICE_ID, *PMC_DEVICE_ID;
+
+extern MC_DEVICE_ID HalpIodLogicalToPhysical[];
+
+//
+// Define the MC bus enumeration types
+//
+
+typedef ULONGLONG MC_DEVICE_MASK;
+
+extern MC_DEVICE_MASK HalpIodMask;
+extern MC_DEVICE_MASK HalpCpuMask;
+extern MC_DEVICE_MASK HalpGcdMask;
+
+//
+// Define the number of IOD's and CPU's in the system
+//
+
+extern ULONG HalpNumberOfIods;
+extern ULONG HalpNumberOfCpus;
+
+typedef struct _MC_ENUM_CONTEXT {
+ RTL_BITMAP McDeviceBitmap; // Device mask being enumerated
+ MC_DEVICE_MASK tempMask; // Bitmap storage
+ ULONG nextBit; // Hint to speed up enumeration
+ // N.B. this is the only public member of this structure:
+ MC_DEVICE_ID McDeviceId; // Currently enumerated McDeviceID
+} MC_ENUM_CONTEXT, *PMC_ENUM_CONTEXT;
+
+//
+// The Bus enumeration routine is called from HalpMcBusEnumAndCall()
+// to perform operations on an enumerated device mask.
+//
+
+typedef
+VOID (*PMC_ENUM_ROUTINE) (
+ MC_DEVICE_ID McDeviceId,
+ ULONG PciBusNumber,
+ va_list McEnumBusArgs
+ );
+
+//
+// Define expected machine check data type
+//
+
+typedef struct _IOD_EXPECTED_ERROR {
+ ULONG Number; // Processor Number
+ ULONGLONG Addr; // SuperPage mode address causing Fill_Error
+} IOD_EXPECTED_ERROR, *PIOD_EXPECTED_ERROR;
+
+#define MASTER_ABORT_NOT_EXPECTED 0xffffffff
+
+//
+// Define the format of the posted interrupt written that the
+// bridge writes to system memory.
+//
+
+typedef union _IOD_POSTED_INTERRUPT {
+
+ struct{
+ ULONG Pci: 16; // <15:0> PCI interrupt State
+ ULONG Eisa: 1; // <17> Eisa/NCR810 interrupt state
+ ULONG I2cCtrl: 1; // <17> 8254 I2C Controller (PCI 0 Only)
+ ULONG I2cBus: 1; // <18> 8254 I2C Bus: (PCI 0 Only)
+ ULONG Reserved0: 2; // <20:19>
+ ULONG Nmi: 1; // <21> 8259 Eisa NMI
+ ULONG SoftErr: 1; // <22> Soft (correctable) error interrupt
+ ULONG HardErr: 1; // <23> Hard error interrupt
+ ULONG Target: 1; // <24> Target device number (0,1)
+ ULONG McDevId: 6; // PCI source of interrupt
+ ULONG Valid: 1; // Device interrupt pending/serviced
+ } ;
+ struct{
+ ULONG IntReq: 24; // <23:0> InterruptState
+ } ;
+ ULONG all;
+
+} IOD_POSTED_INTERRUPT, *PIOD_POSTED_INTERRUPT;
+
+extern PIOD_POSTED_INTERRUPT HalpIodPostedInterrupts;
+
+//
+// Address of vector table in memory
+//
+
+typedef union _IOD_POSTED_INTERRUPT_ADDR {
+ struct{
+ ULONG BusVectorOffset: 2; // QuadWord per vector entry
+ ULONG PciBusOffset: 4; // PCI bus offset into CPU area
+ ULONG CpuOffset: 6; // 64K area per CPU
+ ULONG Base4KPage: 20; // 4K page address of table
+ };
+ ULONG all;
+
+} IOD_POSTED_INTERRUPT_ADDR, PIOD_POSTED_INTERRUPT_ADDR;
+
+
+#define Ncr810 Eisa
+
+//
+// Define the structures to access the IOD general CSRs.
+//
+
+typedef struct _IOD_GENERAL_CSRS{
+ UCHAR PciRevision; // (000) PCI Revision
+ UCHAR Filler1; // (020)
+ UCHAR WhoAmI; // (040) WhoAmI
+ UCHAR Filler2; // (060)
+ UCHAR PciLat; // (080) PCI Latency
+ UCHAR Filler3[3]; // (0a0 - 0e0)
+ UCHAR CapCtrl; // (100) CAP control (MC-PCI Bridge Command)
+ UCHAR Filler4[15]; // (120 - 2e0)
+ UCHAR PerfMon; // (300) Performance Monitor Counter
+ UCHAR Filler5; // (320)
+ UCHAR PerfCon; // (340) Peformance Monitor Ctrl Register
+ UCHAR Filler6[5]; // (360 - 3e0)
+ UCHAR HaeMem; // (400) Host address extension, sparse memory
+ UCHAR Filler7; // (420)
+ UCHAR HaeIo; // (440) Host address extension, space i/o
+ UCHAR Filler8; // (460)
+ UCHAR IackSc; // (480) Interrup Acknowledge / Special Cycle
+ UCHAR Filler9; // (4A0)
+ UCHAR HaeDense; // (4C0) Host address extension, dense memory
+} IOD_GENERAL_CSRS, *PIOD_GENERAL_CSRS;
+
+typedef union _IOD_PCI_REVISION{
+ struct{
+ ULONG CapRev: 4; // <3:0> CAP Revision Id
+ ULONG HorseRev: 4; // <7:4> Horse Revision Id
+ ULONG SaddleRev: 4; // <11:8> Saddle Revision Id
+ ULONG SaddleType: 3; // <14:12> Type Id
+ ULONG EisaPresent: 1; // <15> Set if EISA bus present
+ ULONG SubClass: 8; // <23:16> PCI Host bus bridge sub class
+ ULONG BaseClass: 8; // <3:124> PCI Host bus bridge base class
+ };
+ ULONG all;
+} IOD_PCI_REVISION, *PIOD_PCI_REVISION;
+
+extern ULONG HalpIodPciRevision; // global containing IOD PCI revision id
+
+typedef union _IOD_WHOAMI{
+ struct{
+ ULONG Devid: 6; // <5:0> MC Bus Device Id
+ ULONG CpuInfo: 8; // <13:6> Data Bits
+ ULONG Reserved0: 18; // <31:14> MBZ
+ };
+ MC_DEVICE_ID McDevId; // <5:0> MC Bus Device Id
+ ULONG all;
+} IOD_WHOAMI, *PIOD_WHOAMI;
+
+#define CACHED_CPU_FILL_ERROR 0x80 // CpuInfo Data Bits
+#define CACHED_CPU_DTAG_PARITY_ERROR 0x40 // CpuInfo Data Bits
+
+typedef union _IOD_PCI_LAT{
+ struct{
+ ULONG Reserved0: 8; // <7:0>
+ ULONG Latency: 8; // <15:8> PCI Master Latency timer (in PCI clocks)
+ ULONG Reserved1: 16; // <31:16>
+ };
+ ULONG all;
+} IOD_PCI_LAT, *PIOD_PCI_LAT;
+
+typedef union _IOD_CAP_CONTROL{
+ struct{
+ ULONG Led: 1; // <0> Selftest passed LED
+ ULONG Reserved0: 3; // <3:1>
+ ULONG DlyRdEn: 1; // <4> Enables PCI delayed read protocol ( > 16 clks)
+ ULONG PciMemEn: 1; // <5> Enables Bridge response to PCI transactions
+ ULONG PciReq64: 1; // <6> Enables request for 64-bit PCI transactions
+ ULONG PciAck64: 1; // <7> Enables accepting 64-bit PCI transactions
+ ULONG PciAddrPe: 1; // <8> Enables PCI address parity checking & SERR#
+ ULONG McCmdAddrPe: 1; // <9> Enables Check MC bus CMD / Address Parity
+ ULONG McNxmEn: 1; // <10> Enables Check MC bus NXM on IO space reads
+ ULONG McBusMonEn: 1; // <11> Enables Check MC bus errors when a bystander
+ ULONG Reserved1: 4; // <15:12>
+ ULONG PendNum: 4; // <19:16> Write Pend Number Threshold
+ ULONG RdType: 2; // <21:20> Memory Read Prefetch Type
+ ULONG RlType: 2; // <23:22> Memory Read Line Prefetch Type
+ ULONG RmType: 2; // <25:24> Memory Read Multiple Prefetch Type
+ ULONG PartialWrEn: 1; // <26> Partial Write Enable
+ ULONG Reserved3: 3; // <29:27>
+ ULONG ArbMode: 2; // <31:30> PCI Arbitration Mode
+ };
+ ULONG all;
+} IOD_CAP_CONTROL, *PIOD_CAP_CONTROL;
+
+typedef enum _IOD_READ_PREFETCH_TYPE{
+ IodPrefetchShort = 0x00,
+ IodPrefetchMedium = 0x01,
+ IodPrefetchLong = 0x02,
+ IodPrefetchReserved = 0x03
+} IOD_READ_PREFETCH_TYPE, *PIOD_READ_PREFETCH_TYPE;
+
+typedef enum _IOD_PCI_ARB_MODE{
+ IodArbBridgePriority = 0x00,
+ IodArbRoundRobin = 0x01,
+ IodArbModRoundRobin = 0x02,
+ IodArbReserved = 0x03
+} IOD_PCI_ARB_MODE, *PIOD_PCI_ARB_MODE;
+
+typedef union _IOD_PERF_MON{
+ struct{
+ ULONG Counter: 24; // <23:0>
+ ULONG Reserved0: 8; // <31:24> sets HAE for sparse memory space
+ };
+ ULONG all;
+} IOD_PERF_MON, *PIOD_PERF_MON;
+
+typedef union _IOD_PERF_CON{
+ struct{
+ ULONG CntFrame: 1; // <0> 0 = count PCI Frame#, 1 = cnt TLB miss
+ ULONG Reserved0: 31; // <31:1>
+ };
+ ULONG all;
+} IOD_PERF_CON, *PIOD_PERF_CON;
+
+typedef enum _IOD_PERF_COUNTER_MODE{
+ IodPerfMonPciFrame = 0x0,
+ IodPerfMonTlbMiss = 0x1
+} IOD_PERF_COUNTER_MODE, *PIOD_PERF_COUNTER_MODE;
+
+typedef union _IOD_HAE_MEM{
+ struct{
+ ULONG Reserved0: 26; // <25:0>
+ ULONG HaeMem: 6; // <31:26> sets HAE for sparse memory space
+ };
+ ULONG all;
+} IOD_HAE_MEM, *PIOD_HAE_MEM;
+
+typedef union _IOD_HAE_IO{
+ struct{
+ ULONG Reserved0: 25; // <24:0>
+ ULONG HaeIo: 7; // <31:25> sets HAE for sparse i/o space
+ };
+ ULONG all;
+} IOD_HAE_IO, *PIOD_HAE_IO;
+
+typedef union _IOD_IACK_SC{
+ struct{
+ ULONG Message: 16; // <15:0> Encoded Message
+ ULONG MessageEx: 16; // <31:16> Message Dependent
+ };
+ ULONG all;
+} IOD_IACK_SC, *PIOD_IACK_SC;
+
+//
+// Define the structures and definitions for the IOD interrupt registers.
+//
+
+typedef struct _IOD_INT_CSRS{
+ UCHAR IntCtrl; // (500) Interrupt Control
+ UCHAR Filler1; // (520)
+ UCHAR IntReq; // (540) Interrupt Request
+ UCHAR Filler2; // (560)
+ UCHAR IntTarg; // (580) Interrupt Target Devices
+ UCHAR Filler3; // (5a0)
+ UCHAR IntAddr; // (5c0) Interrupt Target Address
+ UCHAR Filler4; // (5e0)
+ UCHAR IntAddrExt; // (600) Interrupt Target Address Extension
+ UCHAR Filler5; // (620)
+ UCHAR IntMask0; // (640) Interrupt Mask 0
+ UCHAR Filler6; // (660)
+ UCHAR IntMask1; // (680) Interrupt Mask 1
+ UCHAR Filler7[0x8001c3]; // (6a0 - 10003ea0)
+ UCHAR IntAck0; // (10003f00) Interrupt Target 0 Acknowledge
+ UCHAR Filler8; // (10003f20)
+ UCHAR IntAck1; // (10003f40) Interrupt Target 1 Acknowledge
+} IOD_INT_CSRS, *PIOD_INT_CSRS;
+
+//
+// 16 PCI vectors per IOD
+//
+
+#define IOD_PCI_VECTORS 0x10
+
+typedef union _IOD_INT_CONTROL{
+ struct{
+ ULONG EnInt: 1; // <0> Enable MC Bus IO interrupt transactions
+ ULONG EnIntNum: 1; // <1> Enable MC Bus interrupt number write
+ ULONG Reserved: 4; // <31:2>
+ };
+ ULONG all;
+} IOD_INT_CONTROL, *PIOD_INT_CONTROL;
+
+#define IOD_INT_CTL_ENABLE_IO_INT 0x1
+#define IOD_INT_CTL_DISABLE_IO_INT 0x0
+#define IOD_INT_CTL_ENABLE_VECT_WRITE 0x2
+#define IOD_INT_CTL_DISABLE_VECT_WRITE 0x0
+
+
+typedef union _IOD_INT_REQUEST{
+ struct{
+ ULONG IntReq: 22; // <21:0> Interrupt State
+ ULONG SoftErr: 1; // <22> Soft (correctable) error interrupt
+ ULONG HardErr: 1; // <23> Hard error interrupt
+ ULONG Reserved: 8; // <31:24>
+ };
+ ULONG all;
+} IOD_INT_REQUEST, *PIOD_INT_REQUEST;
+
+typedef union _IOD_INT_TARGET_DEVICE{
+ struct{
+ ULONG Int0TargDevId: 6; // <5:0> Interrupt Target 0 McDevid
+ ULONG Int1TargDevId: 6; // <11:6> Interrupt Target 1 McDevid
+ ULONG Reserved: 20; // <31:12> MBZ
+ };
+ ULONG all;
+} IOD_INT_TARGET_DEVICE, *PIOD_INT_TARGET_DEVICE;
+
+#define IOD_MAX_INT_TARG 2
+
+typedef union _IOD_INT_ADDR{
+ struct{
+ ULONG Reserved1: 2; // <1:0> MBZ
+ ULONG PciOffset: 4; // <5:2> PCI Offset
+ ULONG Reserved2: 6; // <11:6> MBZ
+ ULONG IntAddrLo: 20; // <31:12> Page address of interrupt target
+ };
+ ULONG all;
+} IOD_INT_ADDR, *PIOD_INT_ADDR;
+
+typedef union _IOD_INT_ADDR_EXT{
+ struct{
+ ULONG IntAddrExt: 7; // <6:0> Upper bits of interrupt target address
+ ULONG Reserved: 25; // <31:7> MBZ
+ };
+ ULONG all;
+} IOD_INT_ADDR_EXT, *PIOD_INT_ADDR_EXT;
+
+
+//
+// IOD_INT_MASK applies to IntMask0 and IntMask1
+//
+
+typedef union _IOD_INT_MASK{
+ struct{
+ ULONG IntMask: 24; // <23:0> Interrupt Mask
+ ULONG Reserved: 8; // <31:24>
+ };
+ struct{
+ ULONG IntA0: 1; // <0> PCI Slot 0
+ ULONG IntB0: 1;
+ ULONG IntC0: 1;
+ ULONG IntD0: 1;
+ ULONG IntA1: 1; // <4> PCI Slot 1
+ ULONG IntB1: 1;
+ ULONG IntC1: 1;
+ ULONG IntD1: 1;
+ ULONG IntA2: 1; // <8> PCI Slot 2
+ ULONG IntB2: 1;
+ ULONG IntC2: 1;
+ ULONG IntD2: 1;
+ ULONG IntA3: 1; // <12> PCI Slot 3
+ ULONG IntB3: 1;
+ ULONG IntC3: 1;
+ ULONG IntD3: 1;
+ ULONG EisaInt: 1; // <16> 8259 Eisa IRQ's (PCI 0), NCR810 SCSI (PCI 1)
+ ULONG I2cCtrl: 1; // <17> 8254 I2C Controller (PCI 0 Only)
+ ULONG I2cBus: 1; // <18> 8254 I2C Bus: Pwr, Fan, etc. (PCI 0 Only)
+ ULONG Reserved0: 2; // <20:19>
+ ULONG Nmi: 1; // <21> 8259 Eisa NMI
+ ULONG SoftErr: 1; // <22> Soft Error from CAP Chip
+ ULONG HardErr: 1; // <23> Hard Error from CAP Chip
+ ULONG Reserved1 :8; // <31:24>
+ };
+ ULONG all;
+} IOD_INT_MASK, *PIOD_INT_MASK;
+
+typedef enum _IOD_MASK_DEFS{
+ IodPci0IntMask = (1 << 0),
+ IodPci1IntMask = (1 << 1),
+ IodPci2IntMask = (1 << 2),
+ IodPci3IntMask = (1 << 3),
+ IodPci4IntMask = (1 << 4),
+ IodPci5IntMask = (1 << 5),
+ IodPci6IntMask = (1 << 6),
+ IodPci7IntMask = (1 << 7),
+ IodPci8IntMask = (1 << 8),
+ IodPci9IntMask = (1 << 9),
+ IodPci10IntMask = (1 << 10),
+ IodPci11IntMask = (1 << 11),
+ IodPci12IntMask = (1 << 12),
+ IodPci13IntMask = (1 << 13),
+ IodPci14IntMask = (1 << 14),
+ IodPci15IntMask = (1 << 15),
+ IodEisaIntMask = (1 << 16),
+ IodScsiIntMask = (1 << 16),
+ IodI2cCtrlIntMask = (1 << 17),
+ IodI2cBusIntMask = (1 << 18),
+ IodEisaNmiIntMask = (1 << 21),
+ IodSoftErrIntMask = (1 << 22),
+ IodHardErrIntMask = (1 << 23),
+
+ IodIntMask = 0x03ffffff,
+ IodPciIntMask = 0x0000ffff,
+ IodIntDisableMask = 0x00000000,
+
+} IOD_MASK_DEFS, *PIOD_MASK_DEFS;
+
+
+//
+// IOD_INT_ACK applies to IntAck0 and IntAck1
+//
+
+typedef union _IOD_INT_ACK{
+ struct{
+ ULONG Reserved: 32; // <31:0> Reserved
+ };
+ ULONG all;
+} IOD_INT_ACK, *PIOD_INT_ACK;
+
+
+
+//
+// Define the structures and definitions for the IOD diagnostic registers.
+//
+
+typedef struct _IOD_DIAG_CSRS{
+ UCHAR CapDiag; // (700) CAP Diagnostic Control register
+ UCHAR Filler1; // (720)
+ UCHAR Scratch; // (740) General Purpose Scratch register
+ UCHAR Filler2; // (760)
+ UCHAR ScratchAlias; // (780) General Purpose Scratch register alias
+ UCHAR Filler3; // (7a0)
+ UCHAR TopOfMem; // (7c0) Top of Memory
+} IOD_DIAG_CSRS, *PIOD_DIAG_CSRS;
+
+typedef union _IOD_CAP_DIAG {
+ struct{
+ ULONG PciReset: 1; // <0> Reset PCI (must be cleared with 100 us)
+ ULONG Reserved0: 30; // <29:1>
+ ULONG ForceMcAddrPe: 1; // <30> Force bad parity to MC bus (one-shot)
+ ULONG ForcePciAddrPe: 1;// <31> Force bad parity to PCI bus (one-shot)
+ };
+ ULONG all;
+} IOD_CAP_DIAG, *PIOD_CAP_DIAG;
+
+
+//
+// Define the structures and definitions for the IOD error symptom registers.
+//
+
+typedef struct _IOD_ERROR_CSRS{
+ UCHAR McErr0; // (800) MC Error Information Register 0
+ UCHAR Filler0; // (820)
+ UCHAR McErr1; // (840) MC Error Information Register 1
+ UCHAR Filler1; // (860)
+ UCHAR CapErr; // (880) CAP Error Register
+ UCHAR Filler2[61]; // (8a0-1020)
+ UCHAR PciErr1; // (1040) PCI error - failing address
+ UCHAR Filler3[381]; // (1060-3fe0)
+ UCHAR MdpaStat; // (4000) MDPA Status Register
+ UCHAR Filler4; // (4020)
+ UCHAR MdpaSyn; // (4040) MDPA Error Syndrome register
+ UCHAR Filler5; // (4060)
+ UCHAR MdpaDiag; // (4080) MDPA Diagnostic Check Register
+ UCHAR Filler6[507]; // (40a0-7fe0)
+ UCHAR MdpbStat; // (8000) MDPB Status Register
+ UCHAR Filler7; // (8020)
+ UCHAR MdpbSyn; // (8040) MDPB Error Syndrome register
+ UCHAR Filler8; // (8060)
+ UCHAR MdpbDiag; // (8080) MDPB Diagnostic Check Register
+} IOD_ERROR_CSRS, *PIOD_ERROR_CSRS;
+
+typedef union _IOD_MC_ERR0{
+ struct{
+ ULONG Addr: 32; // <31:0> address bits 31-4 of current MC bus error
+ };
+ ULONG all;
+} IOD_MC_ERR0, *PIOD_MC_ERR0;
+
+typedef union _IOD_MC_ERR1{
+ struct{
+ ULONG Addr39_32: 8; // <7:0> address bits 39-32 of current MC bus error
+ ULONG McCmd: 6; // <13:8> MC Bus command active at time of error
+ ULONG DevId: 6; // <19:14> Gid,Mid of bus master at time of error
+ ULONG Dirty: 1; // <20> Set if MC Bus Read/Dirty transaction
+ ULONG Reserved0: 10; // <30:21>
+ ULONG Valid: 1; // <31> OR of CAP_ERR<30:23), McErr0 and McErr1 valid
+ };
+ ULONG all;
+} IOD_MC_ERR1, *PIOD_MC_ERR1;
+
+typedef union _IOD_CAP_ERR{
+ struct{
+ ULONG Perr: 1; // <0> PCI bus PERR# observed by bridge
+ ULONG Serr: 1; // <1> PCI bus SERR# observed by bridge
+ ULONG Mab: 1; // <2> PCI target abort observed by bridge
+ ULONG PteInv: 1; // <3> Invalid Pte
+
+ ULONG PciErrValid: 1; // <4> (RO) PCI Error Valid - Logical OR of <3:0>
+ ULONG Reserved0: 18; // <22:5>
+ ULONG PioOvfl: 1; // <23> CAP buffer full, transaction lost
+
+ ULONG LostMcErr: 1; // <24> Lost uncorrectable MC error
+ ULONG McAddrPerr: 1; // <25> MC Bus command/address parity error
+ ULONG Nxm: 1; // <26> Nonexistent MC Bus address error
+ ULONG CrdA: 1; // <27> Correctable ECC error detected by MDPA
+
+ ULONG CrdB: 1; // <28> Correctable ECC error detected by MDPB
+ ULONG RdsA: 1; // <29> Uncorrectable ECC error detected by MDPA
+ ULONG RdsB: 1; // <30> Uncorrectable ECC error detected by MDPB
+ ULONG McErrValid: 1; // <31> (RO) MC Error Valid - Logical OR of <30:23>
+ };
+ ULONG all;
+} IOD_CAP_ERR, *PIOD_CAP_ERR;
+
+typedef struct _IOD_PCI_ERR1{
+ ULONG PciAddress; // (RO) <31:0> PCI Address
+} IOD_PCI_ERR1, *PIOD_PCI_ERR1;
+
+typedef union _IOD_MDPA_STAT{
+ struct{
+ ULONG MdpaRev: 4; // <3:0> MDP chip revision level
+ ULONG Reserved: 26; // <29:4>
+ ULONG Crd: 1; // <30> MdpaSyn contains correctable error syndrome
+ ULONG Rds: 1; // <31> MdpaSyn contains uncorrectable error syndrome
+ };
+ ULONG all;
+} IOD_MDPA_STAT, *PIOD_MDPA_STAT;
+
+typedef union _IOD_MDPB_STAT{
+ struct{
+ ULONG MdpbRev: 4; // <3:0> MDP chip revision level
+ ULONG Reserved: 26; // <29:4>
+ ULONG Crd: 1; // <30> MdpaSyn contains correctable error syndrome
+ ULONG Rds: 1; // <31> MdpaSyn contains uncorrectable error syndrome
+ };
+ ULONG all;
+} IOD_MDPB_STAT, *PIOD_MDPB_STAT;
+
+typedef union _IOD_MDPA_SYN{
+ struct{
+ ULONG EccSyndrome0: 8; // <8:0> Cycle 0 ECC Syndrome
+ ULONG EccSyndrome1: 8; // <15:9> Cycle 1 ECC Syndrome
+ ULONG EccSyndrome2: 8; // <23:16> Cycle 2 ECC Syndrome
+ ULONG EccSyndrome3: 8; // <31:24> Cycle 3 ECC Syndrome
+ };
+ ULONG all;
+} IOD_MDPA_SYN, *PIOD_MDPA_SYN;
+
+typedef union _IOD_MDPB_SYN{
+ struct{
+ ULONG EccSyndrome0: 8; // <8:0> Cycle 0 ECC Syndrome
+ ULONG EccSyndrome1: 8; // <15:9> Cycle 1 ECC Syndrome
+ ULONG EccSyndrome2: 8; // <23:16> Cycle 2 ECC Syndrome
+ ULONG EccSyndrome3: 8; // <31:24> Cycle 3 ECC Syndrome
+ };
+ ULONG all;
+} IOD_MDPB_SYN, *PIOD_MDPB_SYN;
+
+typedef union _IOD_MDPA_DIAG{
+ struct{
+ ULONG DiagCheck: 8; // <7:0> Data for ECC in diag DMA writes
+ ULONG Reserved: 20; // <27:8>
+ ULONG EccCkEn: 1; // <28> Enable ECC check
+ ULONG ParCkEn: 1; // <29> Enable PCI data parity check
+ ULONG FpePciLo: 1; // <30> Force bad PCI parity on low 32 bits of data
+ ULONG UseDiagCheck: 1; // <31> DMA write cycles to mem use DiagCheck as ECC
+ };
+ ULONG all;
+} IOD_MDPA_DIAG, *PIOD_MDPA_DIAG;
+
+typedef union _IOD_MDPB_DIAG{
+ struct{
+ ULONG DiagCheck: 8; // <7:0> Data for ECC in diag DMA writes
+ ULONG Reserved: 20; // <27:8>
+ ULONG EccCkEn: 1; // <28> Enable ECC check
+ ULONG ParCkEn: 1; // <29> Enable PCI data parity check
+ ULONG FpePciHi: 1; // <30> Force bad PCI parity on high 32 bits of data
+ ULONG UseDiagCheck: 1; // <31> DMA write cycles to mem use DiagCheck as ECC
+ };
+ ULONG all;
+} IOD_MDPB_DIAG, *PIOD_MDPB_DIAG;
+
+//
+// Define I/O CSRs specific to the Rawhide IOD
+//
+
+#if 0
+typedef union _IOD_ELCR1{
+ struct{
+ ULONG From0Rdy: 1; // <0> (RO) Primary flash ROM ready to accept cmds
+ ULONG From1Rdy: 1; // <1> (RO) Secondary flash ROM ready to accept cmds
+ ULONG FsafeWrProt: 1; // <2> (RO) Fail Safe Write Protect (if set)
+ ULONG AvpPresent: 1; // <3> (RO) Programming jumper inserted (if set)
+ ULONG From1Sel: 1; // <4> Selects secondary flash ROM
+ ULONG FromAddr: 3; // <7:5> Selects 64Kb flash ROM range
+ };
+ ULONG all;
+} IOD_ELCR1, *PIOD_ELCR1;
+#else
+typedef union _IOD_ELCR1{
+ struct{
+ ULONG From0Rdy: 1; // <0> (RO) Primary flash ROM ready to accept cmds
+ ULONG From1Rdy: 1; // <1> (RO) Secondary flash ROM ready to accept cmds
+ ULONG AvpPresent: 1; // <2> (RO) Programming jumper inserted (if set)
+ ULONG FromSel: 1; // <3> (RW) Selects secondary flash ROM
+ ULONG FromAddr: 4; // <7:4> (RW) Selects 64Kb flash ROM range
+ };
+ ULONG all;
+} IOD_ELCR1, *PIOD_ELCR1;
+#endif
+
+typedef union _IOD_ELCR2{
+ struct{
+ ULONG SfwResetReq: 1; // <0> (WO) System-wide reset to Power Control Module
+ ULONG SfwReset: 1; // <1> (RO) Most recent reset was via SfwResetReq
+ ULONG CapReset: 1; // <2> (RO) Most recent reset was from CAP chip
+ ULONG OcpReset: 1; // <3> (RO) Most recent reset was via OCP reset swtch
+ ULONG RsmReset: 1; // <4> (RO) Most recent reset was via RSM module
+ ULONG Reserved0: 3; // <7:5>
+ };
+ ULONG all;
+} IOD_ELCR2, *PIOD_ELCR2;
+
+
+//
+// Define structures and definitions for Scatter/Gather control registers:
+//
+
+typedef struct _IOD_SG_CSRS{
+ UCHAR Tbia; // (1300) Translation buffer invalidate all
+ UCHAR Filler; // (1320)
+ UCHAR Hbase; // (1340) PC Hole Compatibility Register
+ UCHAR Filler0[5]; // (1360-13e0)
+ UCHAR W0base; // (1400) Base address, DMA window 0
+ UCHAR Filler1; // (1420)
+ UCHAR W0mask; // (1440) Mask Register, DMA window 0
+ UCHAR Filler2; // (1460)
+ UCHAR T0base; // (1480) Translation Base, DMA window 0
+ UCHAR Filler3[3]; // (14a0 - 14e0)
+ UCHAR W1base; // (1500) Base address, DMA window 1
+ UCHAR Filler4; // (1520)
+ UCHAR W1mask; // (1540) Mask Register, DMA window 1
+ UCHAR Filler5; // (1560)
+ UCHAR T1base; // (1580) Translation Base, DMA window 1
+ UCHAR Filler6[3]; // (15a0 - 15e0)
+ UCHAR W2base; // (1600) Base address, DMA window 2
+ UCHAR Filler7; // (1620)
+ UCHAR W2mask; // (1640) Mask Register, DMA window 2
+ UCHAR Filler8; // (1660)
+ UCHAR T2base; // (1680) Translation Base, DMA window 2
+ UCHAR Filler9[3]; // (16a0 - 16e0)
+ UCHAR W3base; // (1700) Base address, DMA window 3
+ UCHAR Filler10; // (1720)
+ UCHAR W3mask; // (1740) Mask Register, DMA window 3
+ UCHAR Filler11; // (1760)
+ UCHAR T3base; // (1780) Translation Base, DMA window 3
+ UCHAR Filler12; // (17a0)
+ UCHAR Wdac; // (17c0) Window DAC Base
+ UCHAR Filler13; // (17e0)
+ UCHAR TbTag0; // (1800) Translation Buffer Tag 0
+ UCHAR Filler14; // (1820)
+ UCHAR TbTag1; // (1840) Translation Buffer Tag 1
+ UCHAR Filler15; // (1860)
+ UCHAR TbTag2; // (1880) Translation Buffer Tag 2
+ UCHAR Filler16; // (18a0)
+ UCHAR TbTag3; // (18c0) Translation Buffer Tag 3
+ UCHAR Filler17; // (18e0)
+ UCHAR TbTag4; // (1900) Translation Buffer Tag 4
+ UCHAR Filler18; // (1920)
+ UCHAR TbTag5; // (1940) Translation Buffer Tag 5
+ UCHAR Filler19; // (1960)
+ UCHAR TbTag6; // (1980) Translation Buffer Tag 6
+ UCHAR Filler20; // (19a0)
+ UCHAR TbTag7; // (19c0) Translation Buffer Tag 7
+ UCHAR Filler21; // (19e0)
+ UCHAR Tb0Page0; // (2000) Translation Buffer 0 Page 0
+ UCHAR Filler22; // (2020)
+ UCHAR Tb0Page1; // (2040) Translation Buffer 0 Page 1
+ UCHAR Filler23; // (2060)
+ UCHAR Tb0Page2; // (2080) Translation Buffer 0 Page 2
+ UCHAR Filler24; // (20a0)
+ UCHAR Tb0Page3; // (20c0) Translation Buffer 0 Page 3
+ UCHAR Filler25; // (20e0)
+ UCHAR Tb1Page0; // (2100) Translation Buffer 1 Page 0
+ UCHAR Filler26; // (2120)
+ UCHAR Tb1Page1; // (2140) Translation Buffer 1 Page 1
+ UCHAR Filler27; // (2160)
+ UCHAR Tb1Page2; // (2180) Translation Buffer 1 Page 2
+ UCHAR Filler28; // (21a0)
+ UCHAR Tb1Page3; // (21c0) Translation Buffer 1 Page 3
+ UCHAR Filler29; // (21e0)
+ UCHAR Tb2Page0; // (2200) Translation Buffer 2 Page 0
+ UCHAR Filler30; // (2220)
+ UCHAR Tb2Page1; // (2240) Translation Buffer 2 Page 1
+ UCHAR Filler31; // (2260)
+ UCHAR Tb2Page2; // (2280) Translation Buffer 2 Page 2
+ UCHAR Filler32; // (22a0)
+ UCHAR Tb2Page3; // (22c0) Translation Buffer 2 Page 3
+ UCHAR Filler33; // (22e0)
+ UCHAR Tb3Page0; // (2300) Translation Buffer 3 Page 0
+ UCHAR Filler34; // (2320)
+ UCHAR Tb3Page1; // (2340) Translation Buffer 3 Page 1
+ UCHAR Filler35; // (2360)
+ UCHAR Tb3Page2; // (2380) Translation Buffer 3 Page 2
+ UCHAR Filler36; // (23a0)
+ UCHAR Tb3Page3; // (23c0) Translation Buffer 3 Page 3
+ UCHAR Filler37; // (23e0)
+ UCHAR Tb4Page0; // (2400) Translation Buffer 4 Page 0
+ UCHAR Filler38; // (2420)
+ UCHAR Tb4Page1; // (2440) Translation Buffer 4 Page 1
+ UCHAR Filler39; // (2460)
+ UCHAR Tb4Page2; // (2480) Translation Buffer 4 Page 2
+ UCHAR Filler40; // (24a0)
+ UCHAR Tb4Page3; // (24c0) Translation Buffer 4 Page 3
+ UCHAR Filler41; // (24e0)
+ UCHAR Tb5Page0; // (2500) Translation Buffer 5 Page 0
+ UCHAR Filler42; // (2520)
+ UCHAR Tb5Page1; // (2540) Translation Buffer 5 Page 1
+ UCHAR Filler43; // (2560)
+ UCHAR Tb5Page2; // (2580) Translation Buffer 5 Page 2
+ UCHAR Filler44; // (25a0)
+ UCHAR Tb5Page3; // (25c0) Translation Buffer 5 Page 3
+ UCHAR Filler45; // (25e0)
+ UCHAR Tb6Page0; // (2600) Translation Buffer 6 Page 0
+ UCHAR Filler46; // (2620)
+ UCHAR Tb6Page1; // (2640) Translation Buffer 6 Page 1
+ UCHAR Filler47; // (2660)
+ UCHAR Tb6Page2; // (2680) Translation Buffer 6 Page 2
+ UCHAR Filler48; // (26a0)
+ UCHAR Tb6Page3; // (26c0) Translation Buffer 6 Page 3
+ UCHAR Filler49; // (26e0)
+ UCHAR Tb7Page0; // (2700) Translation Buffer 7 Page 0
+ UCHAR Filler50; // (2720
+ UCHAR Tb7Page1; // (2740) Translation Buffer 7 Page 1
+ UCHAR Filler51; // (2760)
+ UCHAR Tb7Page2; // (2780) Translation Buffer 7 Page 2
+ UCHAR Filler52; // (27a0)
+ UCHAR Tb7Page3; // (27c0) Translation Buffer 7 Page 3
+
+} IOD_SG_CSRS, *PIOD_SG_CSRS;
+
+
+typedef union _IOD_TBIA{
+ struct{
+ ULONG Reserved0: 32; // <31:0> Don't care
+ };
+ ULONG all;
+} IOD_TBIA, *PIOD_TBIA;
+
+typedef union _IOD_HBASE{
+ struct{
+ ULONG Hbound: 9; // <8:0> PC compatibility hole upper bound
+ ULONG Reserved0: 4; // <12:9>
+ ULONG PcHe1: 1; // <13> Fixed hole (512 Kb - 1 Mb) enable
+ ULONG PcHe2: 1; // <14> Moveable hole (Hbase - Hbound) enable
+ ULONG Hbase: 9; // <23:15> PC compatibility hole lower bound
+ ULONG Reserved1: 8; // <31:24>
+ };
+ ULONG all;
+} IOD_HBASE, *PIOD_HBASE;
+
+typedef union _IOD_WBASE{
+ struct{
+ ULONG Wen: 1; // <0> Window enable
+ ULONG SgEn: 1; // <1> Scatter Gather enable
+ ULONG Reserved: 1; // <2>
+ ULONG DacEn: 1; // <3> DAC Enable (W3base only)
+ ULONG Reserved0: 16; // <19:4>
+ ULONG Wbase: 12; // <31:20> Base address of DMA window, bits <31:20>
+ };
+ ULONG all;
+} IOD_WBASE, *PIOD_WBASE;
+
+typedef union _IOD_WMASK{
+ struct{
+ ULONG Reserved0: 20; // <19:0>
+ ULONG Wmask: 12; // <31:20> Window mask
+ };
+ ULONG all;
+} IOD_WMASK, *PIOD_WMASK;
+
+typedef union _IOD_TBASE{
+ struct{
+ ULONG Reserved0: 2; // <1:0>
+ ULONG Tbase: 30; // <31:2> Translation base address, bits <39:10>
+ };
+ ULONG all;
+} IOD_TBASE, *PIOD_TBASE;
+
+typedef union _IOD_WDAC{
+ struct{
+ ULONG Wdac: 8; // <7:0> Bbase addr of DAC DMA window 3, bits <39:32>
+ ULONG Reserved0: 24; // <31:8>
+ };
+ ULONG all;
+} IOD_WDAC, *PIOD_WDAC;
+
+typedef union _IOD_TB_TAG{
+ struct{
+ ULONG Valid: 1; // <0> SG TB tag is valid
+ ULONG Reserved0: 1; // <1>
+ ULONG Dac: 1; // <2> SG TB tag corresponds to a 64-bit (DAC) addr
+ ULONG Reserved1: 12; // <14:3>
+ ULONG TbTag: 17; // <31:15> SG TB tag itself
+ };
+ ULONG all;
+} IOD_TB_TAG, *PIOD_TB_TAG;
+
+typedef union _IOD_TB_PAGE{
+ struct{
+ ULONG Valid: 1; // <0> SG Page address is valid
+ ULONG PageAddr: 27; // <27:1> SG TB Page address
+ ULONG Reserved1: 12; // <31:28>
+ };
+ ULONG all;
+} IOD_TB_PAGE, *PIOD_TB_PAGE;
+
+
+//
+// DMA Window Values.
+//
+// The IOD will be initialized to allow 2 DMA windows.
+// The first window will be for the use of of ISA devices and DMA slaves
+// and therefore must have logical addresses below 16MB.
+// The second window will be for bus masters (non-ISA) and so may be
+// above 16MB.
+//
+// The arrangement of the windows will be as follows:
+//
+// Window Logical Start Address Window Size
+// ------ --------------------- -----------
+// Isa 8MB 8MB
+// Master 16MB 16MB
+//
+
+#define ISA_DMA_WINDOW_BASE (__8MB)
+#define ISA_DMA_WINDOW_SIZE (__8MB)
+
+#define MASTER_DMA_WINDOW_BASE (__16MB)
+#define MASTER_DMA_WINDOW_SIZE (__16MB)
+
+//
+// Define the software control registers for a DMA window.
+//
+
+typedef struct _WINDOW_CONTROL_REGISTERS{
+ PVOID WindowBase;
+ ULONG WindowSize;
+ PVOID TranslatedBaseRegister;
+ PVOID WindowBaseRegister;
+ PVOID WindowMaskRegister;
+ PVOID WindowTbiaRegister;
+} WINDOW_CONTROL_REGISTERS, *PWINDOW_CONTROL_REGISTERS;
+
+//
+// Define types of windows.
+//
+
+typedef enum _IOD_WINDOW_NUMBER{
+ IodIsaWindow,
+ IodMasterWindow
+} IOD_WINDOW_NUMBER, *PIOD_WINDOW_NUMBER;
+
+//
+// Define IOD Window Control routines.
+//
+
+VOID
+HalpIodInitializeSfwWindow(
+ PWINDOW_CONTROL_REGISTERS WindowRegisters,
+ IOD_WINDOW_NUMBER WindowNumber
+ );
+
+VOID
+HalpIodProgramDmaWindow(
+ PWINDOW_CONTROL_REGISTERS WindowRegisters,
+ PVOID MapRegisterBase
+ );
+
+VOID
+HalpIodInvalidateTlb(
+ PWINDOW_CONTROL_REGISTERS WindowRegisters
+ );
+
+PKPCR
+HalpRdPcr(
+ VOID
+ );
+
+//
+// Define IOD CSR Routines
+//
+
+VOID
+WRITE_IOD_REGISTER(
+ PVOID,
+ ULONG
+ );
+
+ULONG
+READ_IOD_REGISTER(
+ PVOID
+ );
+
+VOID
+WRITE_IOD_REGISTER_NEW(
+ MC_DEVICE_ID,
+ PVOID,
+ ULONG
+ );
+
+ULONG
+READ_IOD_REGISTER_NEW(
+ MC_DEVICE_ID,
+ PVOID
+ );
+
+//
+// Define IOD interrupt request/acknowledge routines
+//
+
+ULONG
+INTERRUPT_ACKNOWLEDGE(
+ PVOID
+ );
+
+VOID
+IOD_INTERRUPT_ACKNOWLEDGE(
+ MC_DEVICE_ID McDeviceId,
+ ULONG Target
+ );
+
+VOID
+CPU_CLOCK_ACKNOWLEDGE(
+ MC_DEVICE_ID McDeviceId
+ );
+
+VOID
+IP_INTERRUPT_REQUEST(
+ MC_DEVICE_ID McDeviceId
+ );
+
+VOID
+IP_INTERRUPT_ACKNOWLEDGE(
+ MC_DEVICE_ID McDeviceId
+ );
+
+//
+// Define MC Bus emumerator routines
+//
+
+
+ULONG
+HalpMcBusEnumStart(
+ MC_DEVICE_MASK McDeviceMask,
+ PMC_ENUM_CONTEXT McContext
+ );
+
+BOOLEAN
+HalpMcBusEnum(
+ PMC_ENUM_CONTEXT McContext
+ );
+
+VOID
+HalpMcBusEnumAndCall(
+ MC_DEVICE_MASK McDeviceMask,
+ PMC_ENUM_ROUTINE McBusEnumRoutine,
+ ...
+ );
+
+//
+// Define other IOD routines
+//
+
+ULONG
+HalpReadWhoAmI(
+ VOID
+ );
+
+VOID
+HalpInitializeIodVectorTable(
+ VOID
+ );
+
+VOID
+HalpInitializeIodMappingTable(
+ MC_DEVICE_ID McDeviceId,
+ ULONG PciBusNumber,
+ va_list Arguments
+ );
+
+BOOLEAN
+HalpIodUncorrectableError(
+ PMC_DEVICE_ID pMcDeviceId
+ );
+
+VOID
+HalpIodReportFatalError(
+ MC_DEVICE_ID McDevid
+ );
+
+BOOLEAN
+HalpIodMachineCheck(
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PKEXCEPTION_FRAME ExceptionFrame,
+ IN PKTRAP_FRAME TrapFrame
+ );
+
+VOID
+HalpInitializeIod(
+ MC_DEVICE_ID McDeviceId,
+ ULONG PciBusNumber,
+ va_list Arguments
+ );
+
+VOID
+HalpInitializeIodVectorCSRs(
+ MC_DEVICE_ID McDeviceId,
+ ULONG PciBusNumber,
+ va_list Arguments
+ );
+
+VOID
+HalpInitializeIodMachineChecks(
+ IN BOOLEAN ReportCorrectableErrors,
+ IN BOOLEAN PciParityChecking
+ );
+
+VOID
+HalpIodSoftErrorInterrupt(
+ VOID
+ );
+
+VOID
+HalpIodHardErrorInterrupt(
+ VOID
+ );
+
+VOID
+HalpClearAllIods(
+ IOD_CAP_ERR IodCapErrMask
+);
+
+#define ALL_CAP_ERRORS 0xffffffff
+
+
+#if HALDBG || defined(DUMPIODS)
+
+VOID
+DumpIod(
+ MC_DEVICE_ID DevId,
+ IOD_REGISTER_CLASS RegistersToDump
+ );
+
+VOID
+DumpAllIods(
+ IOD_REGISTER_CLASS RegistersToDump
+ );
+
+#endif //HALDBG
+
+
+//
+// VOID
+// INITIALIZE_ISA_DMA_CONTROL(
+// PWINDOW_CONTROL_REGISTERS WindowRegisters
+// )
+//
+// Routine Description:
+//
+// Initialize the DMA Control software window registers for the ISA
+// DMA window.
+//
+// Arguments:
+//
+// WindowRegisters - Supplies a pointer to the software window control.
+//
+// Return Value:
+//
+// None.
+//
+
+#define INITIALIZE_ISA_DMA_CONTROL( WR ) \
+ HalpIodInitializeSfwWindow( (WR), IodIsaWindow );
+
+
+//
+// VOID
+// INITIALIZE_MASTER_DMA_CONTROL(
+// PWINDOW_CONTROL_REGISTERS WindowRegisters
+// )
+//
+// Routine Description:
+//
+// Initialize the DMA Control software window registers for the PCI
+// DMA window.
+//
+// Arguments:
+//
+// WindowRegisters - Supplies a pointer to the software window control.
+//
+// Return Value:
+//
+// None.
+//
+
+#define INITIALIZE_MASTER_DMA_CONTROL( WR ) \
+ HalpIodInitializeSfwWindow( (WR), IodMasterWindow );
+
+
+//
+// VOID
+// INITIALIZE_DMA_WINDOW(
+// PWINDOW_CONTROL_REGISTERS WindowRegisters,
+// PTRANSLATION_ENTRY MapRegisterBase
+// )
+//
+// Routine Description:
+//
+// Program the control windows so that DMA can be started to the
+// DMA window.
+//
+// Arguments:
+//
+// WindowRegisters - Supplies a pointer to the software window register
+// control structure.
+//
+// MapRegisterBase - Supplies the logical address of the scatter/gather
+// array in system memory.
+//
+// Return Value:
+//
+// None.
+//
+
+#define INITIALIZE_DMA_WINDOW( WR, MRB ) \
+ HalpIodProgramDmaWindow( (WR), (MRB) );
+
+
+//
+// VOID
+// INVALIDATE_DMA_TRANSLATIONS(
+// PWINDOW_CONTROL_REGISTERS WindowRegisters
+// )
+//
+// Routine Description:
+//
+// Invalidate all of the cached translations for a DMA window.
+//
+//
+// Arguments:
+//
+// WindowRegisters - Supplies a pointer to the software window control
+// registers.
+//
+// Return Value:
+//
+// None.
+//
+
+#define INVALIDATE_DMA_TRANSLATIONS( WR ) \
+ HalpIodInvalidateTlb( (WR) );
+
+
+//
+// Define the format of a translation entry aka a scatter/gather entry
+// or map register.
+//
+
+typedef struct _TRANSLATION_ENTRY{
+ ULONG Valid: 1;
+ ULONG Pfn: 31;
+ ULONG Reserved;
+} TRANSLATION_ENTRY, *PTRANSLATION_ENTRY;
+
+
+
+//
+// VOID
+// HAL_MAKE_VALID_TRANSLATION(
+// PTRANSLATION_ENTRY Entry,
+// ULONG PageFrameNumber
+// )
+//
+// Routine Description:
+//
+// Make the scatter/gather entry pointed to by Entry valid with
+// a translation to the page indicated by PageFrameNumber.
+//
+// Arguments:
+//
+// Entry - Supplies a pointer to the translation entry to make valid.
+//
+// PageFrameNumber - Supplies the page frame of the valid translation.
+//
+// Return Value:
+//
+// None.
+//
+
+#define HAL_MAKE_VALID_TRANSLATION( ENTRY, PFN ) \
+ { \
+ (ENTRY)->Valid = 1; \
+ (ENTRY)->Pfn = PFN; \
+ (ENTRY)->Reserved = 0; \
+ }
+
+
+//
+// VOID
+// HAL_INVALIDATE_TRANSLATION(
+// PTRANSLATION_ENTRY Entry
+// )
+//
+// Routine Description:
+//
+// Invalidate the translation indicated by Entry.
+//
+// Arguments:
+//
+// Entry - Supplies a pointer to the translation to be invalidated.
+//
+// Return Value:
+//
+// None.
+//
+
+#define HAL_INVALIDATE_TRANSLATION( ENTRY ) \
+ (ENTRY)->Valid = 0;
+
+#endif //!_LANGUAGE_ASSEMBLY
+
+#endif //_IODH_
diff --git a/private/ntos/nthals/halraw/alpha/iodaddr.c b/private/ntos/nthals/halraw/alpha/iodaddr.c
new file mode 100644
index 000000000..d0a2958f3
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/iodaddr.c
@@ -0,0 +1,731 @@
+/*++
+
+Copyright (c) 1993-1995 Digital Equipment Corporation
+
+Module Name:
+
+ iodaddr.c
+
+Abstract:
+
+ This module contains the platform dependent code to create bus addreses
+ and QVAs for the Rawhide system.
+
+Author:
+
+ Eric Rehm 10-Apr-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+#include "pci.h"
+#include "pcip.h"
+
+typedef PVOID QUASI_VIRTUAL_ADDRESS;
+
+QUASI_VIRTUAL_ADDRESS
+HalCreateQva(
+ IN PHYSICAL_ADDRESS PA,
+ IN PVOID VA
+ );
+
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system physical address for a specified I/O bus
+ address. The return value is suitable for use in a subsequent call to
+ MmMapIoSpace.
+
+Arguments:
+
+ BusHandler - Registered BUSHANDLER for the target configuration space
+ Supplies the bus handler (bus no, interface type).
+
+ RootHandler - Registered BUSHANDLER for the orginating
+ HalTranslateBusAddress request.
+
+ BusAddress - Supplies the bus relative address.
+
+ AddressSpace - Supplies the address space number for the device: 0 for
+ memory and 1 for I/O space. If the desired access mode is user mode,
+ then bit 1 must be TRUE.
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+
+Notes:
+
+ This is a variation of what began in the MIPS code. The intel code often
+ assumes that if an address is in I/O space, the bottom 32 bits of the
+ physical address can be used "like" a virtual address, and are returned
+ to the user. This doesn't work on Alpha and MIPS machines where physical
+ addresses can be larger than 32 bits.
+
+ Since we are using superpage addresses for I/O on Alpha, we can do
+ almost what is done on intel. If AddressSpace is equal to 0 or 1, then
+ we assume the user is doing kernel I/O and we use the macro
+ HAL_MAKE_IOD_SPARSE_QVA to build a Quasi Virtual address and return
+ that to the caller. We then set AddressSpace to a 1, so that the caller
+ will not call MmMapIoSpace. The Caller will use the low 32 bits of the
+ physical address we return as the VA. (Which we built a QVA in).
+
+ Note that KernelPciDenseMemory *is* mapped via MmMapIoSpace.
+
+ If the caller wants to access EISA I/O or Memory through user mode, then
+ the caller must set bit 1 in AddressSpace to a 1 (AddressSpace=2 or 3,
+ depending on whether EISA I/O or Memory), then the caller is returned the
+ 40 bit Physical address. The caller will then call MmMapIoSpace, or
+ ZwMapViewOfSection which in turn calls HalCreateQva to build a QVA out
+ of a VA mapped through the page tables.
+
+ **** Note ****
+
+ The QVA in user mode can only be used via the user-mode access macros.
+
+Rawhide notes:
+
+ QVA's on Rawhide encode a BusNumber and an offset on that bus, i.e.,
+ the physical address is not directly coded in the QVA. The actual
+ superpage physical address is constructed at the time of access.
+
+ Sparse QVA space from A000.0000 - C000.0000 is separate for I/O
+ and memory space. For example, sparse memory address 0 on BusNumber
+ 0 has QVA = A000.0000 and sparse I/O address 0 on BusNumber 0 also
+ has QVA = A000.0000. The user of a QVA must know what they're
+ doing, and properly call the correct access routine for the
+ address space that they desire.
+
+ Finally, sparse and dense memory QVA's must coexist with the
+ same memory access routines (READ/WRITE_REGISTER_*). Since
+ Rawhide has 4 I/O buses, supporting 4 * 1 Gb dense spaces +
+ 4 * 128 Mb sparse spaces is not possible using a 32 bit QVA.
+ Therefore, we arbitrarily "short sheet" the dense address space
+ of BusNumber 2 to 512 Mb to make room for the sparse space QVAs.
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ INTERFACE_TYPE InterfaceType = BusHandler->InterfaceType;
+ ULONG BusNumber = BusHandler->BusNumber;
+ MC_DEVICE_ID McDeviceId;
+ PPCIPBUSDATA BusData;
+ ULONG HwBusNumber;
+
+
+ PVOID va = 0; // note, this is used for a placeholder
+
+ //
+ // Check InterfaceType:
+ // The only buses available on Rawhide are an EISA bus and a PCI bus.
+ // We support any translations for EISA devices as well, though
+ // if they are true EISA devices they won't even be able to plug into
+ // the connectors!
+ //
+
+ if ( (InterfaceType != Isa) &&
+ (InterfaceType != Eisa) &&
+ (InterfaceType != PCIBus) ) {
+
+ //
+ // Not on this system return nothing.
+ //
+
+#if HALDBG
+ DbgPrint( "HalTBA: Unhandled interface type = %x\n", InterfaceType );
+#endif //HALDBG
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+
+ //
+ // Next, generate the IOD number (HwBusNumber).
+ //
+ // If it's ISA or EISA, BusNumber and HwBusNumber = 0.
+ // If it's PCI, we get HwBusNumber from PCI-specific bus data.
+ //
+
+ HwBusNumber = 0; // Isa, Eisa
+ if (InterfaceType == PCIBus ) {
+
+ //
+ // Get a pointer to the PCIBus-specific data.
+ //
+
+ BusData = (PPCIPBUSDATA)BusHandler->BusData;
+
+ //
+ // In particular, what root PCI bus (IOD) are we on?
+ //
+
+ HwBusNumber = BusData->HwBusNumber;
+ }
+
+ //
+ // Build MC Bus device id for this bus using HwBusNumber.
+ // Currently, only the Primary Global Id (0x7) is supported.
+ //
+
+ McDeviceId.all = 0;
+ McDeviceId.Gid = GidPrimary;
+ McDeviceId.Mid = MidPci0 + HwBusNumber;
+
+ //
+ // Determine the address based on whether the bus address is in I/O space
+ // or bus memory space.
+ //
+
+ switch ( (ADDRESS_SPACE_TYPE)(*AddressSpace) ) {
+
+ case BusMemory: {
+
+ //
+ // The address is in PCI memory space, kernel mode.
+ //
+
+ switch( InterfaceType ) {
+
+ case Isa: {
+
+ //
+ // Can't go above 16MB (24 Bits) for Isa Buses
+ //
+ if( BusAddress.LowPart >= __16MB ){
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+
+ break;
+
+ } // case Isa
+
+ case Eisa:
+
+ //
+ // Eisa is the same as PCI, with respect to kernel mode
+ // sparse and dense space memory support, i.e., its a full 32 bit space,
+ // supports dense memory access.
+ //
+
+ case PCIBus: {
+
+ //
+ // Don't allow accesses to PCI/EISA addresses below
+ // 1 Mb on root buses other than PCI-0.
+ //
+#if 1 // ecrfix - needed for WINT3.51 !!!
+ if ( BusAddress.LowPart < __1MB &&
+ HwBusNumber > 0 ) {
+#if HALDBG
+ DbgPrint ("Unsupported PCI-%d (ISA legacy) address %x:%x\n",
+ HwBusNumber,
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+#endif
+
+ //
+ // Check legal PCI bus address ranges
+ //
+
+ if ( BusAddress.LowPart > PCI_MAX_DENSE_MEMORY_ADDRESS ) {
+
+ //
+ // Unsupported dense PCI bus address.
+ //
+#if HALDBG
+ DbgPrint ("Unsupported PCI address %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+ else if( BusAddress.LowPart >= PCI_MIN_DENSE_MEMORY_ADDRESS &&
+ BusAddress.LowPart <= PCI_MAX_DENSE_MEMORY_ADDRESS ) {
+
+#if HALDBG
+ DbgPrint ("Translating PCI kernel dense address %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif
+ //
+ // Bus Address is in dense PCI memory space
+ //
+
+ //
+ // QVA, as such, is simply PCI bus address offset
+ // from the base dense memory address for that bus.
+ // The bus number is encoded in bits <31:30>.
+ //
+
+ TranslatedAddress->LowPart = (ULONG)
+ HAL_MAKE_IOD_DENSE_QVA(HwBusNumber, BusAddress.LowPart);
+
+ //
+ // clear high longword for QVA
+ //
+
+ TranslatedAddress->HighPart = 0;
+
+ //
+ // dont let the user call MmMapIoSpace
+ //
+
+ *AddressSpace = 1;
+
+ return (TRUE);
+
+
+ }
+
+ //
+ // Bus Address is in sparse PCI memory space
+ //
+
+
+#if HALDBG
+ DbgPrint ("Translating PCI kernel sparse address %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif
+
+ break;
+ } // case PCIBus
+
+ } // switch( InterfaceType )
+
+ //
+ // Now create the QVA from the HwBusNumber and BusAddress.
+ //
+ // Unlike many other Alpha platfroms, the QVA is *not* an
+ // encoding of the physical address. The full physical address
+ // will can be constructed at the time of the I/O access with the
+ // information encoded here in the QVA: HwBusNumber and BusAddress.
+ // (The bus number is encoded in bits <28:27> of the QVA.)
+ //
+
+ TranslatedAddress->LowPart = (ULONG)
+ HAL_MAKE_IOD_SPARSE_QVA(HwBusNumber, BusAddress.LowPart);
+
+ //
+ // clear high longword for QVA
+ //
+
+ TranslatedAddress->HighPart = 0;
+
+ //
+ // don't let the user call MmMapIoSpace
+ //
+
+ *AddressSpace = 1;
+
+ return(TRUE);
+
+ } // case BusMemory
+
+ case BusIo: {
+
+ //
+ // The address is in PCI I/O space, kernel mode.
+ //
+ switch( InterfaceType ) {
+
+ case Eisa:
+
+ //
+ // Eisa is the same as ISA, with respect to kernel mode
+ // sparse I/O space support, i.e., it is a 16 bit sparse
+ // space.
+ //
+
+ case Isa: {
+ //
+ // Can't go above 64KB (16 Bits) for Isa Buses
+ //
+ if( BusAddress.LowPart >= __64K ){
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+ break;
+ } // case Isa
+
+ case PCIBus: {
+
+ //
+ // PCI IO space is always below 32MB (25 Bits) BusAddress
+ // If the address cannot be mapped, just return FALSE.
+ //
+
+ if( BusAddress.LowPart >= __32MB ){
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+ //
+ // if the BusAddress.LowPart is > 64K then we use the HAER2
+ // register.
+ //
+ break;
+ } // case PCIBus
+
+ } // switch( InterfaceType )
+
+ //
+ // Now create the QVA from the HwBusNumber and BusAddress.
+ //
+ // Unlike many other Alpha platfroms, the QVA is *not* an
+ // encoding of the physical address. The full physical address
+ // will can be constructed at the time of the I/O access with the
+ // information encoded here in the QVA: HwBusNumber and BusAddress.
+ // (The bus number is encoded in bits <28:27> of the QVA.)
+ //
+
+ TranslatedAddress->LowPart = (ULONG)
+ HAL_MAKE_IOD_SPARSE_QVA(HwBusNumber, BusAddress.LowPart);
+
+ //
+ // clear high longword for QVA
+ //
+
+ TranslatedAddress->HighPart = 0;
+
+ //
+ // don't let the user call MmMapIoSpace
+ //
+
+ *AddressSpace = 1;
+
+
+ return(TRUE);
+
+ } // case BusIo
+
+ case UserBusMemory: {
+
+ //
+ // The address is in PCI memory space, user mode.
+ //
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = IOD_SPARSE_MEM_OFFSET;
+ TranslatedAddress->QuadPart |= MCDEVID_TO_PHYS_ADDR( McDeviceId.all );
+ TranslatedAddress->QuadPart |= EV5_USER_IO_ADDRESS_SPACE;
+ TranslatedAddress->QuadPart += (((ULONGLONG)BusAddress.LowPart) << IO_BIT_SHIFT);
+
+#if HALDBG
+ DbgPrint ("Translating PCI user mem sparse address %x:%x to %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart,
+ TranslatedAddress->HighPart,
+ TranslatedAddress->LowPart);
+#endif
+
+ *AddressSpace = 0; // Let the user call MmMapIoSpace
+
+ return(TRUE);
+
+ }
+
+ case UserBusIo: {
+
+ //
+ // The address is in PCI I/O space, user mode.
+ //
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = IOD_SPARSE_IO_OFFSET;
+ TranslatedAddress->QuadPart |= MCDEVID_TO_PHYS_ADDR( McDeviceId.all );
+ TranslatedAddress->QuadPart |= EV5_USER_IO_ADDRESS_SPACE;
+ TranslatedAddress->QuadPart += (((ULONGLONG)BusAddress.LowPart) << IO_BIT_SHIFT);
+
+#if HALDBG
+ DbgPrint ("Translating PCI user I/O sparse address %x:%x to %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart,
+ TranslatedAddress->HighPart,
+ TranslatedAddress->LowPart);
+#endif
+
+
+ *AddressSpace = 0; // Make sure user can call
+ // MmMapIoSpace.
+
+ return(TRUE);
+
+ }
+
+ case KernelPciDenseMemory:
+ case UserPciDenseMemory:
+ {
+
+ //
+ // The address is in PCI dense memory space, user mode.
+ //
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart = IOD_DENSE_MEM_OFFSET;
+ TranslatedAddress->QuadPart |= MCDEVID_TO_PHYS_ADDR( McDeviceId.all );
+ TranslatedAddress->QuadPart |= EV5_USER_IO_ADDRESS_SPACE;
+ TranslatedAddress->QuadPart += BusAddress.LowPart;
+
+ *AddressSpace = 0; // Let the user call MmMapIoSpace
+
+#if HALDBG
+ DbgPrint("HTBA: UserPciDenseMemory %x to %x;%x\n",
+ BusAddress.LowPart,
+ TranslatedAddress->HighPart,
+ TranslatedAddress->LowPart);
+#endif // HALDBG
+
+ return(TRUE);
+
+ }
+
+ default: {
+
+ //
+ // Unsupported address space.
+ //
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+ }
+
+
+}
+
+PVOID
+HalCreateQva(
+ IN PHYSICAL_ADDRESS PA,
+ IN PVOID VA
+ )
+
+/*++
+
+Routine Description:
+
+ This function is only available to a caller constructing a QVA
+ as a result of a page table mapping via ZwMapViewOfSection or
+ MmMapIoSpace.
+
+ N.B. HalTranslateBusAddress, or other HAL routines MUST NOT
+ CALL THIS ROUTINE. This is because on Rawhide, a kernel-mode
+ dense or sparse superpage QVA cannot be contructed without
+ knowledge of the BusNumber, which is not passed into this routine.
+
+ If the input parameter VA is zero, then we assume the caller
+ was incorrectly attempting to create a super page and build
+ a QUASI virtual address, and results in an error.
+
+ If the input parameter VA is non-zero, we assume the user has either
+ called MmMapIoSpace or ZwMapViewOfSection and will use the user mode
+ access macros.
+
+ If the PA is not an I/O space address (PCI I/O, PCI Memory),
+ then return the VA as the QVA.
+
+Arguments:
+
+ PA - the physical address generated by HalTranslateBusAddress
+
+ VA - the virtual address returned by MmMapIoSpace
+
+Return Value:
+
+ The returned value is a quasi virtual address in that it can be
+ added to and subtracted from, but it cannot be used to access the
+ bus directly. The top bits are set so that we can trap invalid
+ accesses in the memory management subsystem. All access should be
+ done through the Hal Access Routines in *ioacc.s if it was a superpage
+ kernel mode access. If it is usermode, then the user mode access
+ macros must be used.
+
+--*/
+{
+
+ PHYSICAL_ADDRESS PhysicalOffset;
+ PVOID qva;
+
+ PhysicalOffset.QuadPart = PHYS_ADDR_TO_OFFSET( PA.QuadPart );
+
+#if HALDBG
+ DbgPrint("HalCreateQva: PhysicalOffset = %x;%x\n",
+ PhysicalOffset.HighPart,
+ PhysicalOffset.LowPart);
+#endif
+
+
+ if (VA == 0) {
+
+ //
+ // Error - HalCreateQva should not be called to create
+ // a superpage QVA.
+ //
+
+#if HALDBG
+
+ DbgPrint( "HalCreateQva: Should not be called to create a superpage QVA from %x:%x\n", PA.HighPart, PA.LowPart );
+ DbgBreakPoint();
+
+#endif //HALDBG
+
+ return (VA);
+
+ } else if( (PhysicalOffset.QuadPart >= IOD_DENSE_MEM_OFFSET) &&
+ (PhysicalOffset.QuadPart <= (IOD_DENSE_MEM_OFFSET +
+ PCI_MAX_DENSE_MEMORY_ADDRESS)) ){
+
+ //
+ // Physical dense address, return VA.
+ //
+
+#if HALDBG
+ DbgPrint("HalCreateQva: User Mode Dense QVA = VA = %x\n", VA);
+#endif
+ return(VA);
+
+ } else {
+
+ //
+ // The physical address is within one of the sparse I/O spaces.
+ //
+
+ qva = (PVOID)((ULONG)VA >> IO_BIT_SHIFT);
+
+ qva = (PVOID)((ULONG)qva | QVA_ENABLE);
+
+#if HALDBG
+ DbgPrint("HalCreateQva: User Mode Sparse QVA = %x\n", qva);
+#endif
+ return(qva);
+ }
+}
+
+PVOID
+HalDereferenceQva(
+ PVOID Qva,
+ INTERFACE_TYPE InterfaceType,
+ ULONG BusNumber
+ )
+/*++
+
+Routine Description:
+
+ This function performs the inverse of the HalCreateQva for I/O addresses
+ that are memory-mapped (i.e. the quasi-virtual address was created from
+ a virtual address rather than a physical address).
+
+Arguments:
+
+ Qva - Supplies the quasi-virtual address to be converted back to a
+ virtual address.
+
+ InterfaceType - Supplies the interface type of the bus to which the
+ Qva pertains.
+
+ BusNumber - Supplies the bus number of the bus to which the Qva pertains.
+
+Return Value:
+
+ The Virtual Address from which the quasi-address was originally created
+ is returned.
+
+--*/
+{
+
+
+ //
+ // For Sable we have three supported bus types:
+ //
+ // Isa
+ // Eisa
+ // PCIBus
+ //
+
+ switch (InterfaceType ){
+
+ case Isa:
+ case Eisa:
+ case PCIBus:
+
+ //
+ // Support dense space: check to see if it's really
+ // a sparse space QVA.
+ //
+
+ if ( ((ULONG) Qva & QVA_SELECTORS) == QVA_ENABLE ) {
+ return( (PVOID)( (ULONG)Qva << IO_BIT_SHIFT ) );
+ } else {
+ return (Qva);
+ }
+ break;
+
+ default:
+
+ return NULL;
+
+ }
+
+
+}
+
diff --git a/private/ntos/nthals/halraw/alpha/ioderr.c b/private/ntos/nthals/halraw/alpha/ioderr.c
new file mode 100644
index 000000000..f0038b5e5
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/ioderr.c
@@ -0,0 +1,2304 @@
+/*++
+
+Copyright (c) 1995 Digital Equipment Corporation
+
+Module Name:
+
+ ioderr.c
+
+Abstract:
+
+ This module implements error handling functions for the Rawhide
+ IOD (CAP and MDP ASICs).
+
+Author:
+
+ Eric Rehm 13-Apr-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+//#include "iod.h"
+#include "rawhide.h"
+#include "stdio.h"
+
+//
+// Externals and globals.
+//
+
+extern PERROR_FRAME PUncorrectableError;
+extern ULONG HalDisablePCIParityChecking;
+ULONG IodCorrectedErrors = 0;
+
+//
+// Define the context structure for use by interrupt service routines.
+//
+
+typedef BOOLEAN (*PSECOND_LEVEL_DISPATCH)(
+ PKINTERRUPT InterruptObject,
+ PVOID ServiceContext
+ );
+
+//
+// The Soft Error interrupt is always turned on for Rawhide. When a
+// Soft Error interrupt occurs, HalpIodSoftErrorInterrupt() must
+// be called to reset the error condition on the offending IOD to
+// insure system integrity.
+//
+// A Correctable Error Driver might also connect to the Soft Error interrupt
+// via the Internal Bus interface. When a Soft Error interrupt occurs,
+// we determine if it is also necessary to dispatch an ISR for the
+// Correctable Error Driver via a boolean.
+//
+
+BOOLEAN HalpLogCorrectableErrors = FALSE;
+
+//
+// Keep the first time we read the WhoAmI register
+// since it does not always read the same the second time.
+//
+// Zero value indicates that we haven't read WhoAmI yet and that
+// this global variable is not valid.
+//
+// (On machine checks that we dismiss, we must remember to
+// to reset this to zero.)
+//
+
+IOD_WHOAMI HalpIodWhoAmIOnError = { 0 };
+
+//
+// Function prototypes.
+//
+
+VOID
+HalpSetMachineCheckEnables(
+ IN BOOLEAN DisableMachineChecks,
+ IN BOOLEAN DisableProcessorCorrectables,
+ IN BOOLEAN DisableSystemCorrectables
+ );
+
+VOID
+HalpUpdateMces(
+ IN BOOLEAN ClearMachineCheck,
+ IN BOOLEAN ClearCorrectableError
+ );
+
+//
+// Function prototypes for routines not visible outside this module
+//
+
+VOID
+HalpBuildIodErrorFrame(
+ MC_DEVICE_ID McDeviceId,
+ PIOD_ERROR_FRAME IodErrorFrame
+ );
+
+BOOLEAN
+bFindIodError(
+ PMC_DEVICE_ID pMcDeviceId,
+ PIOD_CAP_ERR pIodCapErr
+);
+
+BOOLEAN
+bHandleFatalIodError(
+ MC_DEVICE_ID McDeviceId,
+ BOOLEAN bMachineCheck
+ );
+
+BOOLEAN
+bHandleIsaError(
+ MC_DEVICE_ID pMcDeviceId,
+ IOD_CAP_ERR IodCapErr
+);
+
+VOID
+HalpErrorFrameString(
+ PUNCORRECTABLE_ERROR uncorr,
+ PUCHAR OutBuffer
+ );
+
+ULONG
+BuildActiveCpus (
+ VOID
+ );
+
+//
+// Allocate a flag that indicates when a PCI Master Abort is expected.
+// PCI Master Aborts are signaled on configuration reads to non-existent
+// PCI slots. A cardinal value (0-128) indicates that a Master Abort is expected.
+// A value of 0xffffffff indicates that a Master Abort is *not* expected.
+//
+
+IOD_EXPECTED_ERROR HalpMasterAbortExpected = {MASTER_ABORT_NOT_EXPECTED, 0x0};
+
+
+VOID
+HalpInitializeIodMachineChecks(
+ IN BOOLEAN ReportCorrectableErrors,
+ IN BOOLEAN PciParityChecking
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes machine check handling for a IOD-based
+ system by clearing all pending errors in the IOD registers and
+ enabling correctable errors according to the callers specification.
+
+Arguments:
+
+ ReportCorrectableErrors - Supplies a boolean value which specifies
+ if correctable error reporting should be
+ enabled.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ IOD_CAP_CONTROL IodCapControl;
+ IOD_CAP_ERR IodCapError;
+ IOD_MDPA_DIAG IodMdpaDiag;
+ IOD_MDPB_DIAG IodMdpbDiag;
+ IOD_INT_MASK IodIntMask;
+
+ MC_DEVICE_ID McDeviceId;
+ MC_ENUM_CONTEXT mcCtx;
+ ULONG numIods;
+ BOOLEAN bfoundIod;
+
+ //
+ // Clear any pending error bits in the IOD_CAP_ERR register:
+ //
+
+ IodCapError.all = 0; // Clear all bits
+
+ IodCapError.Perr = 1; // PCI bus perr detected
+ IodCapError.Serr = 1; // PCI bus serr detected
+ IodCapError.Mab = 1; // PCI bus master abort detected
+ IodCapError.PteInv = 1; // Invalid Pte
+ IodCapError.PioOvfl = 1; // Pio Ovfl
+ IodCapError.LostMcErr = 1; // Lost error
+ IodCapError.McAddrPerr = 1; // MC bus comd/addr parity error
+ IodCapError.Nxm = 1; // Non-existent memory error
+ IodCapError.CrdA = 1; // Correctable ECC error on MDPA
+ IodCapError.CrdB = 1; // Correctable ECC error on MDPB
+ IodCapError.RdsA = 1; // Uncorrectable ECC error on MDPA
+ IodCapError.RdsA = 1; // Uncorrectable ECC error on MDPA
+
+ //
+ // Intialize enumerator.
+ //
+
+ numIods = HalpMcBusEnumStart ( HalpIodMask, &mcCtx );
+
+ //
+ // Intialize each Iod
+ //
+
+ while ( bfoundIod = HalpMcBusEnum( &mcCtx ) ) {
+
+ McDeviceId = mcCtx.McDeviceId;
+
+ //
+ // Initialize IOD_CAP_ERR
+ //
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->CapErr,
+ IodCapError.all );
+
+ //
+ // Set the Iod error enable bits in the IOD_CAP_CTRL and
+ // IOD_MDPA/B_DIAG registers. The configuration bits in the IOD
+ // will be left as set by the Extended SROM, with the few
+ // exceptions documented below.
+ //
+
+ IodCapControl.all = READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->CapCtrl );
+
+#if 0 // CAP/MDP Bug
+ IodMdpaDiag.all =
+ READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpaDiag );
+
+ IodMdpbDiag.all =
+ READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpbDiag );
+#else
+
+ //
+ // Clear Mdp Diagnotic Check Registers....
+ //
+
+ IodMdpaDiag.all = 0;
+ IodMdpbDiag.all = 0;
+
+ //
+ // Enable ECC checking on all MC Bus transactions
+ //
+
+ IodMdpaDiag.EccCkEn = 1;
+ IodMdpbDiag.EccCkEn = 1;
+
+#endif
+
+ //
+ // Disable/enable PCI parity checking as requested
+ //
+
+ if (PciParityChecking == FALSE) {
+
+ IodCapControl.PciAddrPe= 0; // Do *not* check PCI address parity
+ IodMdpaDiag.ParCkEn = 0; // Do *not* check PCI data parity
+ IodMdpbDiag.ParCkEn = 0; // Do *not* check PCI data parity
+
+ } else {
+
+ IodCapControl.PciAddrPe= PciParityChecking;
+ IodMdpaDiag.ParCkEn = PciParityChecking;
+ IodMdpbDiag.ParCkEn = PciParityChecking;
+
+ }
+
+
+ //
+ // Disable McBus NXM's
+ //
+ // (If enabled, accesses to non-existent McBus device will cause an
+ // EV5 fill error. Non existant CSRs will return all 0s most of the time
+ // and not fill error.)
+ //
+
+ IodCapControl.McNxmEn = 0;
+
+ //
+ // Disable monitoring of McBus bystander errors.
+ //
+ // That means the IOD will not capture the failing address in the event of
+ // an MC bus NXM. It has no effect on what the IOD does in the event of a
+ // PCI NXM (which causes a Master Abort).
+ //
+ // Regardless of how McBusMonEn PCI PERR, SERR, MAB, and PTE_INV
+ // will only show up in IOD CAP_ERR of the participant in the transaction.
+ //
+ // If McBusMonEn is set, there can be a difference between the bystander CAP_ERR
+ // state and the participant CAP_ERR state (as per Sam Duncan, 5/3/95)
+ // shows up in an unlikely situation:
+ // "Cache single bit or double bit error: read is dirty in a cache
+ // and the fill has an ecc error, don't want to indite a memory for this
+ // (very unlikely) error."
+ // Thus, we choose not to be able to correctly detect this situation in
+ // order to make machine check and error handling easier, i.e., we
+ // always only need to clear only one IOD's CAP_ERROR.
+ //
+
+ IodCapControl.McBusMonEn= 0;
+
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->CapCtrl,
+ IodCapControl.all );
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpaDiag,
+ IodMdpaDiag.all );
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpbDiag,
+ IodMdpbDiag.all );
+
+
+ //
+ // Soft and Hard Error handling
+ //
+ // ecrfix - IntMask0 on Bus 0 only.
+
+ IodIntMask.all = READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntMask0 );
+
+ IodIntMask.SoftErr = (ReportCorrectableErrors == TRUE);
+ IodIntMask.HardErr = 0; // ecrfix - Mask Hard Errors for now
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntMask0,
+ IodIntMask.all );
+
+ } // while ( HalpMcBusEnum ( &mcCtx ) )
+
+ //
+ // Set the machine check enables within the EV5.
+ //
+
+ if( ReportCorrectableErrors == TRUE ){
+ HalpSetMachineCheckEnables( FALSE, FALSE, FALSE );
+ } else {
+ HalpSetMachineCheckEnables( FALSE, TRUE, TRUE );
+ }
+
+ return;
+
+}
+
+#define MAX_ERROR_STRING 128
+
+
+BOOLEAN
+HalpIodUncorrectableError(
+ PMC_DEVICE_ID pMcDeviceId
+ )
+/*++
+
+Routine Description:
+
+ Read the IOD error register and determine if an uncorrectable error
+ is latched in the error bits.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ TRUE is returned if an uncorrectable error has been detected. FALSE
+ is returned otherwise.
+
+--*/
+{
+ UCHAR OutBuffer[ MAX_ERROR_STRING ];
+ IOD_WHOAMI IodWhoAmI;
+ IOD_CAP_ERR IodCapErr;
+
+ //
+ // Check for a duplicate tag parity error on this (in the Smalltalk
+ // sense) processor.
+ //
+
+ IodWhoAmI.all = HalpReadWhoAmI();
+ HalpIodWhoAmIOnError.all = IodWhoAmI.all;
+
+ if ( IodWhoAmI.CpuInfo & CACHED_CPU_DTAG_PARITY_ERROR ) {
+
+ pMcDeviceId->all = IodWhoAmI.Devid;
+
+ return TRUE;
+
+ } else {
+
+ //
+ // None of the uncorrectable error conditions were detected.
+ //
+
+ return FALSE;
+ }
+
+}
+
+VOID
+HalpBuildIodErrorFrame(
+ MC_DEVICE_ID McDeviceId,
+ PIOD_ERROR_FRAME IodErrorFrame
+ )
+/*++
+
+Routine Description:
+
+ This function reports and interprets a fatal hardware error
+ detected by the IOD chipset. It is assumed that HalGetDisplayOwnership()
+ has been called prior to this function.
+
+Arguments:
+
+ McDevid - Supplies the MC Bus Device ID of the IOD
+ IodErrorFrame - Supplies a pointer to an IOD_ERROR_FRAME
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // Clear it first, since caller may reuse the IodErrorFrame
+ //
+
+ RtlZeroMemory(IodErrorFrame, sizeof(IOD_ERROR_FRAME));
+
+ //
+ // Everything is valid
+ //
+
+ IodErrorFrame->ValidBits.all = 0xffffffff; // all valid
+
+
+ //
+ // Read the General registers
+ //
+
+ IodErrorFrame->BaseAddress = IOD_IO_SPACE_START |
+ IOD_SPARSE_CSR_OFFSET |
+ MCDEVID_TO_PHYS_ADDR(McDeviceId.all);
+
+ IodErrorFrame->WhoAmI = (ULONG)READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->WhoAmI
+ );
+
+ IodErrorFrame->PciRevision = (ULONG)READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->PciRevision
+ );
+
+ IodErrorFrame->CapCtrl = (ULONG)READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->CapCtrl
+ );
+
+ IodErrorFrame->HaeMem = (ULONG)READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->HaeMem
+ );
+
+ IodErrorFrame->HaeIo = (ULONG)READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->HaeIo
+ );
+
+ //
+ // Read Interrupt Control and Status Registers
+ //
+
+ IodErrorFrame->IntCtrl = (ULONG)READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntCtrl
+ );
+
+ IodErrorFrame->IntReq = (ULONG)READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntReq
+ );
+
+ IodErrorFrame->IntMask0 = (ULONG)READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntMask0
+ );
+
+ IodErrorFrame->IntMask1 = (ULONG)READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntMask1
+ );
+
+ //
+ // Read the rest of the error registers and then unlock them by
+ // writing to CAP_ERR
+ //
+
+ IodErrorFrame->CapErr = (ULONG)READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->CapErr
+ );
+
+ IodErrorFrame->PciErr1 = (ULONG)READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->PciErr1
+ );
+
+ IodErrorFrame->McErr0 = (ULONG)READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->McErr0
+ );
+
+ IodErrorFrame->McErr1 = (ULONG)READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->McErr1
+ );
+#if 0 // CAP/MDP Bug
+ IodErrorFrame->MdpaStat = (ULONG)READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpaStat
+ );
+
+ IodErrorFrame->MdpaSyn = (ULONG)READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpaSyn
+ );
+
+ IodErrorFrame->MdpbStat = (ULONG)READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpbStat
+ );
+
+ IodErrorFrame->MdpbSyn = (ULONG)READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpbSyn
+ );
+#else
+
+ //
+ // CAP/MDP Bug - these registers are not valid.
+ //
+
+ IodErrorFrame->ValidBits.MdpaStatValid = 0;
+ IodErrorFrame->ValidBits.MdpbStatValid = 0;
+ IodErrorFrame->ValidBits.MdpaSynValid = 0;
+ IodErrorFrame->ValidBits.MdpbSynValid = 0;
+
+#endif // CAP/MDP Bug
+
+}
+
+VOID
+HalpIodReportFatalError(
+ MC_DEVICE_ID ErrorMcDeviceId
+ )
+/*++
+
+Routine Description:
+
+ This function reports and interprets a fatal hardware error
+ detected by the IOD chipset. It is assumed that HalGetDisplayOwnership()
+ has been called prior to this function.
+
+Arguments:
+
+ ErrorMcDeviceId - Supplies the MC Bus Device ID of the IOD
+ where the error was found
+
+ - In the case of a Duplicate Tag Parity Error, supplies
+ the CPU that took the error. Note, in this case
+ the ErrorMcDeviceId will never match a IOD McDeviceId.
+ No MC Bus snapshot is present in this case.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ UCHAR OutBuffer[ MAX_ERROR_STRING ];
+ IOD_ERROR_FRAME IodErrorFrame, *pCurrentIodErrorFrame;
+ MC_ENUM_CONTEXT mcCtx;
+ MC_DEVICE_ID McDeviceId;
+ ULONG numIods;
+ BOOLEAN bfoundIod;
+
+ PUNCORRECTABLE_ERROR uncorr = NULL;
+ PRAWHIDE_UNCORRECTABLE_FRAME rawerr = NULL;
+ PEXTENDED_ERROR PExtErr;
+
+ //
+ // Do we have an uncorrectable error frame?
+ //
+
+ if (PUncorrectableError) {
+ uncorr = (PUNCORRECTABLE_ERROR)
+ &PUncorrectableError->UncorrectableFrame;
+ rawerr = (PRAWHIDE_UNCORRECTABLE_FRAME)
+ PUncorrectableError->UncorrectableFrame.RawSystemInformation;
+ PExtErr = &PUncorrectableError->UncorrectableFrame.ErrorInformation;
+ }
+
+ //
+ // Validate the ProcessorInfo portion of the Error Frame.
+ //
+
+ if (uncorr) {
+ uncorr->Flags.ProcessorInformationValid = 1;
+ HalpGetProcessorInfo(&uncorr->ReportingProcessor);
+
+ //
+ // Initialize our "error string accumulator"
+ //
+
+ HalpErrorFrameString( uncorr, NULL );
+
+ }
+
+ //
+ // Validate the Rawhide Uncorrectable Frame
+ // (Common RCUD Header was already set up.)
+ //
+
+ if (rawerr) {
+ rawerr->Revision = RAWHIDE_UNCORRECTABLE_FRAME_REVISION;
+ rawerr->WhoAmI = HalpIodWhoAmIOnError.all;
+ rawerr->ErrorSubpacketFlags.all = 0;
+ rawerr->CudHeader.ActiveCpus = BuildActiveCpus();
+
+ }
+
+ //
+ // Handle cached CPU duplicate tag parity error.
+ // (Note that a DTAG parity error implies that we don't
+ // take an MC Bus Snapshot.
+ //
+
+ if ( HalpIodWhoAmIOnError.CpuInfo & CACHED_CPU_DTAG_PARITY_ERROR ) {
+
+ sprintf( OutBuffer, "Duplicate Tag Parity Error on CPU %x\n",
+ MCDEVID_TO_PHYS_CPU(HalpIodWhoAmIOnError.McDevId.all) );
+
+ HalDisplayString( OutBuffer );
+#if HALDBG
+ DbgPrint( "Duplicate Tag Parity Error on CPU (%d, %d)\n",
+ HalpIodWhoAmIOnError.McDevId.Gid, HalpIodWhoAmIOnError.McDevId.Mid);
+#endif
+ HalpErrorFrameString( uncorr, OutBuffer );
+
+ //
+ // OK. This is tedious:
+ // * Error is in memory space and is the system (external) cache.
+ // * And we know this is the L3 cache.
+ // * And we'll subvert the "CacheBoard" to squirrel away the
+ // Cached CPU Revision Info and Cache size.
+ //
+
+ uncorr->Flags.AddressSpace = MEMORY_SPACE;
+ uncorr->Flags.ExtendedErrorValid = 1;
+ uncorr->Flags.MemoryErrorSource = SYSTEM_CACHE;
+ PExtErr->CacheError.Flags.CacheLevelValid = 1;
+ PExtErr->CacheError.Flags.CacheBoardValid = 1;
+ PExtErr->CacheError.Flags.CacheSimmValid = 0;
+ PExtErr->CacheError.CacheLevel = 3;
+ PExtErr->CacheError.CacheBoardNumber = HalpIodWhoAmIOnError.CpuInfo;
+
+ return;
+ }
+
+ //
+ // Handle cached CPU fill error.
+ // Since this could be caused by an MC Bus or PCI error,
+ // we continue to create an MC Bus snapshot.
+ //
+
+ if ( HalpIodWhoAmIOnError.CpuInfo & CACHED_CPU_FILL_ERROR ) {
+
+ sprintf( OutBuffer, "Fill Error on CPU %x\n",
+ MCDEVID_TO_PHYS_CPU(HalpIodWhoAmIOnError.McDevId.all) );
+
+ HalDisplayString( OutBuffer );
+#if HALDBG
+ DbgPrint( "Fill Error on CPU (%d, %d)\n",
+ HalpIodWhoAmIOnError.McDevId.Gid, HalpIodWhoAmIOnError.McDevId.Mid);
+#endif
+ HalpErrorFrameString( uncorr, OutBuffer );
+
+ //
+ // * WhoAmI tells us Addr<38:33> of reference causing error.
+ // * However, PciErr1 and/or McErr0/McErr1 give us more bits,
+ // so the data entered here my get overwritten later.
+ //
+
+ uncorr->Flags.PhysicalAddressValid = 1;
+ uncorr->PhysicalAddress =
+ ( ((ULONGLONG)(HalpIodWhoAmIOnError.CpuInfo & 0x3f)) << 33 );
+
+ }
+
+ //
+ // Validate the MCBusSnapshot header.
+ //
+
+ if (rawerr) {
+ rawerr->ErrorSubpacketFlags.McBusPresent = 1;
+ rawerr->McBusSnapshot.ReportingCpuBaseAddr =
+ IOD_IO_SPACE_START |
+ MCDEVID_TO_PHYS_ADDR( HalpIodWhoAmIOnError.Devid );
+ pCurrentIodErrorFrame = (PIOD_ERROR_FRAME) (rawerr + 1);
+ }
+
+ //
+ // Intialize enumerator.
+ //
+
+ numIods = HalpMcBusEnumStart ( HalpIodMask, &mcCtx );
+ ASSERT( numIods == HalpNumberOfIods);
+
+ //
+ // Gather data from each Iod
+ //
+
+ while ( bfoundIod = HalpMcBusEnum( &mcCtx ) ) {
+
+ McDeviceId.all = mcCtx.McDeviceId.all;
+
+ HalpBuildIodErrorFrame( McDeviceId, &IodErrorFrame );
+
+ //
+ // Fill in IOD_ERROR_FRAME portion of the RAWHIDE_UNCORRECTABLE_FRAME
+ //
+
+ if (rawerr) {
+
+ RtlCopyMemory( pCurrentIodErrorFrame,
+ &IodErrorFrame,
+ sizeof(IOD_ERROR_FRAME));
+
+ pCurrentIodErrorFrame++;
+ }
+
+ //
+ // If this is the IOD where we found the error
+ // a. clear the error
+ // b. complete the uncorrectable error frame processing
+ // c. Display an interpretation of the error to the screen
+ //
+
+ if (ErrorMcDeviceId.all == McDeviceId.all) {
+
+ // ecrfix Put below into HalpInterpretIodError(McDeviceId, IodErrorFrame) ???
+ IOD_WHOAMI IodWhoAmI;
+ IOD_CAP_CONTROL IodCapCtrl;
+ IOD_CAP_ERR IodCapErr;
+ IOD_PCI_ERR1 IodPciErr1;
+ IOD_MC_ERR0 IodMcErr0;
+ IOD_MC_ERR1 IodMcErr1;
+ IOD_MDPA_STAT IodMdpaStat;
+ IOD_MDPB_STAT IodMdpbStat;
+ ULONG HwBusNumber = ErrorMcDeviceId.Mid & 0x3;
+
+ //
+ // Copy error frame variables in locals for bitfield access
+ //
+
+ IodWhoAmI.all = IodErrorFrame.WhoAmI;
+ IodCapCtrl.all = IodErrorFrame.CapCtrl;
+ IodCapErr.all = IodErrorFrame.CapErr;
+ IodPciErr1.PciAddress = IodErrorFrame.PciErr1;
+ IodMcErr0.all = IodErrorFrame.McErr0;
+ IodMcErr1.all = IodErrorFrame.McErr1;
+
+ #if 0 // CAP/MDP Bug
+ IodMdpaStat.all = IodErrorFrame.MdpaStat;
+ IodMdpbStat.all = IodErrorFrame.MdpbStat;
+ IodMdpaSyn.all = IodErrorFrame.MdpaSyn;
+ IodMdpbSyn.all = IodErrorFrame.MdpbSyn;
+ #else
+ IodMdpaStat.all = 0xffffffff;
+ IodMdpbStat.all = 0xffffffff;
+ #endif // CAP/MDP Bug
+
+
+
+ //
+ // Clear state in MDPA and MDPB before clearing CAP_ERR
+ //
+
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpaStat,
+ IodErrorFrame.MdpaStat
+ );
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpbStat,
+ IodErrorFrame.MdpbStat
+ );
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->CapErr,
+ IodErrorFrame.CapErr
+ );
+
+ sprintf( OutBuffer,
+ "IOD MC_DEVICE_ID : (%x, %x) CAP_CTRL : %08x CAP_ERR : %08x\n",
+ McDeviceId.Gid, McDeviceId.Mid,
+ IodCapCtrl.all,
+ IodCapErr.all );
+
+ HalDisplayString( OutBuffer );
+#if HALDBG
+ DbgPrint( OutBuffer );
+#endif
+
+ sprintf( OutBuffer,
+ "PCI_ERR1 %08x MC_ERR0 : %08x MC_ERR1 : %08x\n",
+ IodPciErr1.PciAddress,
+ IodMcErr0.all,
+ IodMcErr1.all );
+
+ HalDisplayString( OutBuffer );
+#if HALDBG
+ DbgPrint( OutBuffer );
+#endif
+
+ #if 0 // CAP/MDP Bug
+ sprintf( OutBuffer,
+ "MDPA_STAT : %08x MDPA_SYN : %08x MDPB_STAT : %08x MDPB_SYN : %08x\n",
+ IodMdpaStat.all,
+ IodMdpaSyn.all,
+ IodMdpbStat.all,
+ IodMdpbSyn.all );
+ HalDisplayString( OutBuffer );
+#if HALDBG
+ DbgPrint( OutBuffer );
+#endif
+ #endif
+
+ //
+ // If no valid error then no interpretation.
+ //
+
+ if (( IodCapErr.PciErrValid == 0 ) && ( IodCapErr.McErrValid == 0 ) ){
+
+ return; // No IOD error detected
+
+ }
+
+ //
+ // Interpret any detected errors:
+ //
+
+ if (IodCapErr.McErrValid == 1) {
+
+ if ( IodMcErr1.Dirty != 1 ) {
+ sprintf( OutBuffer,
+ "MC Bus Error, Bus Master=(%x,%x)\n",
+
+ ( ( IodMcErr1.DevId & 0x38) >> 3 ),
+ ( IodMcErr1.DevId & 0x07)
+ );
+ } else {
+
+ sprintf( OutBuffer,
+ "MC bus error on a read/dirty transaction\n"
+ );
+ }
+
+
+ //
+ // Output the detected error message:
+ //
+
+ HalDisplayString( OutBuffer );
+#if HALDBG
+ DbgPrint( OutBuffer );
+#endif
+ HalpErrorFrameString( uncorr, OutBuffer);
+
+
+ sprintf( OutBuffer,
+ "IOD Addr=%x%x, Cmd=%x\n",
+ IodMcErr1.Addr39_32, // bits 39:32
+ IodMcErr0.Addr, // bits 31:4
+ IodMcErr1.McCmd
+ );
+
+ //
+ // Output the detected error message:
+ //
+
+ HalDisplayString( OutBuffer );
+#if HALDBG
+ DbgPrint( OutBuffer );
+#endif
+ HalpErrorFrameString( uncorr, OutBuffer);
+
+ //
+ // Interpret specific MC bus error
+ //
+
+ uncorr->Flags.PhysicalAddressValid = 1;
+ uncorr->PhysicalAddress = (
+ (((ULONGLONG)IodMcErr1.Addr39_32) << 32) |
+ ((ULONGLONG)IodMcErr0.Addr) );
+
+ //
+ // McAddr<39> indicates whether this was a
+ // memory or I/O transaction.
+ //
+
+ if ( (IodMcErr1.Addr39_32 & 0x80) == 1) {
+ uncorr->Flags.AddressSpace = IO_SPACE;
+ } else {
+ uncorr->Flags.AddressSpace = MEMORY_SPACE;
+ }
+
+ if ( IodCapErr.PioOvfl == 1 ){
+
+ sprintf( OutBuffer,
+ "IOD PIO Overflow, PendNumb=%x\n",
+ IodCapCtrl.PendNum
+ );
+
+ } else if ( IodCapErr.McAddrPerr == 1 ){
+
+ sprintf( OutBuffer,
+ "MC bus parity error\n"
+ );
+
+ } else if ( IodCapErr.Nxm == 1 ){
+
+ sprintf( OutBuffer,
+ "MC bus NXM\n"
+ );
+
+ } else if ( IodCapErr.CrdA == 1 ){
+
+ sprintf( OutBuffer,
+ "IOD Correctable ECC error in MDPA\n"
+ );
+
+ } else if ( IodCapErr.CrdB == 1 ){
+
+ sprintf( OutBuffer,
+ "IOD Correctable ECC error in MDPB\n"
+ );
+
+ } else if ( IodCapErr.RdsA == 1 ){
+
+ sprintf( OutBuffer,
+ "IOD Uncorrectable ECC error in MDPA\n"
+ );
+
+ } else if ( IodCapErr.RdsB == 1 ){
+
+ sprintf( OutBuffer,
+ "IOD Uncorrectable ECC error in MDPB\n"
+ );
+
+ }
+
+ //
+ // Output the detected error message:
+ //
+
+ HalDisplayString( OutBuffer );
+#if HALDBG
+ DbgPrint( OutBuffer );
+#endif
+ HalpErrorFrameString( uncorr, OutBuffer);
+
+ }
+
+ if ( IodCapErr.PciErrValid == 1 ){
+
+ //
+ // Interpret specific PCI bus error
+ //
+
+ uncorr->Flags.AddressSpace = IO_SPACE;
+ uncorr->Flags.PhysicalAddressValid = 1;
+ uncorr->PhysicalAddress = IOD_IO_SPACE_START |
+ MCDEVID_TO_PHYS_ADDR(IodWhoAmI.McDevId.all) |
+ IodPciErr1.PciAddress << IO_BIT_SHIFT;
+
+ uncorr->Flags.ExtendedErrorValid = 1;
+ PExtErr->IoError.Interface = PCIBus;
+ PExtErr->IoError.BusNumber = HwBusNumber;
+ PExtErr->IoError.BusAddress.LowPart = IodPciErr1.PciAddress;
+
+ if ( IodCapErr.Perr == 1 ){
+ sprintf( OutBuffer,
+ "PERR detected on PCI-%d, Addr=%x\n",
+ HwBusNumber,
+ IodPciErr1.PciAddress
+ );
+
+ } else if ( IodCapErr.Serr == 1 ){
+
+ sprintf( OutBuffer,
+ "SERR detected on PCI-%d, Addr=%x\n",
+ HwBusNumber,
+ IodPciErr1.PciAddress
+ );
+
+ } else if ( IodCapErr.Mab == 1 ){
+
+ sprintf( OutBuffer,
+ "Master Abort on PCI-%d, Addr=%x\n",
+ HwBusNumber,
+ IodPciErr1.PciAddress
+ );
+
+ } else if ( IodCapErr.PteInv == 1 ){
+
+ sprintf( OutBuffer,
+ "Invalid Scatter/Gather PTE on PCI-%d, Addr=%x\n",
+ HwBusNumber,
+ IodPciErr1.PciAddress
+ );
+ }
+
+ //
+ // Output the detected error message:
+ //
+
+ HalDisplayString( OutBuffer );
+#if HALDBG
+ DbgPrint( OutBuffer );
+#endif
+ HalpErrorFrameString( uncorr, OutBuffer);
+
+ }
+
+ //
+ // Check for lost errors and output message if any occurred:
+ //
+
+ if ( IodCapErr.LostMcErr == 1 ){
+ HalDisplayString("IOD Lost errors were detected\n");
+#if HALDBG
+ DbgPrint("IOD Lost errors were detected\n");
+#endif
+ HalpErrorFrameString(uncorr, "IOD Lost errors were detected\n");
+ }
+
+ } // if (ErrorMcDeviceID == McDeviceId)
+
+ } // while (bfoundIod = HalpMcBusEnum)
+
+ return; // Fatal error detected
+}
+
+
+BOOLEAN
+HalpIodMachineCheck(
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PKEXCEPTION_FRAME ExceptionFrame,
+ IN PKTRAP_FRAME TrapFrame
+ )
+/*++
+
+Routine Description:
+
+ This routine is given control when an hard error is acknowledged
+ by the IOD chipset. The routine is given the chance to
+ correct and dismiss the error.
+
+Arguments:
+
+ ExceptionRecord - Supplies a pointer to the exception record generated
+ at the point of the exception.
+
+ ExceptionFrame - Supplies a pointer to the exception frame generated
+ at the point of the exception.
+
+ TrapFrame - Supplies a pointer to the trap frame generated
+ at the point of the exception.
+
+Return Value:
+
+ TRUE is returned if the machine check has been handled and dismissed -
+ indicating that execution can continue. FALSE is return otherwise.
+
+--*/
+{
+ IOD_CAP_ERR IodCapErr;
+ IOD_CAP_ERR IodCapErrMask;
+ IOD_MC_ERR1 IodMcErr1;
+ IOD_WHOAMI IodWhoAmI;
+ MC_DEVICE_ID McDeviceId;
+ BOOLEAN ExpectedMchk;
+ BOOLEAN ExpectedMcAddrPerr;
+ BOOLEAN PciMemReadMchk;
+ BOOLEAN bfoundIod;
+
+ //
+ // We don't expect a machine check yet...
+ //
+
+ ExpectedMchk = FALSE;
+ ExpectedMcAddrPerr = FALSE;
+
+ //
+ // Make sure any error due to 2Mb/4Mb Cached CUD bug is latched.
+ //
+ // At this point, WhoAmI may indicate the symptoms of a fill_error
+ // and CUD cache size is not available. We'll read it again when
+ // we need to know the Cache size. However, we save he here so we
+ // can figure out if this was a fill error or not.
+ //
+
+ HalpIodWhoAmIOnError.all = HalpReadWhoAmI();
+
+ //
+ // Where do we look for the error symptoms?
+ //
+ // 1. If we expected this machine check, then we know which
+ // IOD to check.
+ // 2. If we didn't expect this machine check, find the IOD that
+ // generated the error.
+ //
+
+ //
+ // For an expected machine check, HalpMasterAbortExpected will
+ // contain the processor number and address of a PCI config
+ // space read. CAP_ERR will indicate a MasterAbort.
+ //
+
+ if( HalpMasterAbortExpected.Number == (ULONG)KeGetCurrentProcessorNumber() ) {
+
+ //
+ // Determine expected IOD from the address of the PCI config read
+ //
+
+ McDeviceId.all = MCDEVID_FROM_PHYS_ADDR(HalpMasterAbortExpected.Addr);
+
+ //
+ // Now get the Bcache size information.
+ //
+
+ IodWhoAmI.all = READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->WhoAmI);
+
+ //
+ //
+ // Make sure there is a Master abort on this IOD
+ //
+
+ IodCapErr.all = READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->CapErr );
+
+
+ if( IodCapErr.Mab == 1 ) {
+ ExpectedMchk = TRUE;
+
+ //
+ // If 2Mb or 4 Mb cached CUD, and we may get an MCbus address parity
+ // error with MC command signature in MC_ERR1 equal to zero (cached
+ // CPU idle transaction). Also dismiss this error that's the result
+ // of the cached 2Mb/4Mb cached CPU VCTY bug.
+ //
+
+ IodMcErr1.all = READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->McErr1 );
+
+ if ((IodWhoAmI.CpuInfo & 0x7) && // Cached CPU?
+ IodCapErr.McAddrPerr && // McAddrPerr?
+ (IodMcErr1.McCmd == 0) ) { // McCmd is zero?
+
+ ExpectedMcAddrPerr = TRUE; // All yes, then dismiss it!
+ }
+ }
+
+#if HALDBG
+ DbgPrint( "Expected Mchk (Mab) on IOD (%x, %x), Processor number %x\n",
+ McDeviceId.Gid,
+ McDeviceId.Mid,
+ HalpMasterAbortExpected.Number);
+#endif //HALDBG
+ }
+
+ //
+ // If this isn't the machine check we expected, then
+ // we must find the IOD that took the error.
+ //
+
+ if (!ExpectedMchk) {
+
+ bfoundIod = bFindIodError( &McDeviceId, &IodCapErr );
+
+ //
+ // Check that we found an IOD that has a valid PCI or MC error.
+ // If it is not this is a pretty weird (fatal???) condition.
+ // For now, we'll just go return TRUE.
+ //
+ // ecrfix - should we check the error interrupts? probably not...
+ //
+
+ if( !bfoundIod ) {
+
+#if HALDBG
+ DbgPrint( "HalpIodMachineCheck called but no PCI or MC error found\n");
+#endif
+ return (TRUE);
+ }
+
+
+#if 0 // HALDBG
+ DbgPrint( "Unexpected Mchk on IOD (%x, %x)\n",
+ McDeviceId.Gid,
+ McDeviceId.Mid );
+#endif //HALDBG
+
+ //
+ // Case: Uexpected Master Abort, e.g. a PCI memory or I/O space read to
+ // legacy ISA space (0 - 1 Mb) on PCI-1,2,3.
+ //
+
+ if ( bHandleIsaError( McDeviceId, IodCapErr) ) {
+ return TRUE;
+ }
+
+ }
+
+ //
+ // Case: PCI or MC Bus error other than master abort
+ //
+ // At this point we have either:
+ // (a) an expected PCI Master Abort (ExpectedMchk == TRUE), or
+ // (b) an unexpected PCI or MC Bus error.
+ //
+ // However, it's possible that we have *both* (a) AND (b).
+ // So, even if ExpectedMch == TRUE, check for other PCI or MC Bus
+ // errors. Any of these other errors indicate a
+ // fatal condition.
+ //
+
+ if( (IodCapErr.Perr == 1) || // PCI bus perr detected
+ (IodCapErr.Serr == 1) || // PCI bus serr detected
+ (IodCapErr.PteInv == 1) || // Invalid Pte
+ (IodCapErr.PioOvfl == 1) || // Pio Ovfl
+
+ //
+ // Cached CUD with 2 Mb and 4 Mb Cache may also assert an MCAddrPerr
+ // or Nxm upon a config space read. Lost Error bit will also be set.
+ //
+ //
+
+ ( (IodCapErr.LostMcErr == 1) && !ExpectedMcAddrPerr) ||
+ // Lost error
+ ( (IodCapErr.McAddrPerr == 1) && !ExpectedMcAddrPerr ) ||
+ // MC bus comd/addr parity error
+
+
+ ( (IodCapErr.Nxm == 1) && !ExpectedMcAddrPerr ) ||
+ // Non-existent memory error
+ (IodCapErr.CrdA == 1) || // Correctable ECC error on MDPA
+ (IodCapErr.CrdB == 1) || // Correctable ECC error on MDPB
+ (IodCapErr.RdsA == 1) || // Uncorrectable ECC error on MDPA
+ (IodCapErr.RdsA == 1) // Uncorrectable ECC error on MDPA
+
+ ){
+ return ( bHandleFatalIodError(McDeviceId, TRUE) );
+ }
+
+ //
+ // At this point, we have either an expected or unexpected Master
+ // abort. There are three cases:
+ // 1. Expected MAB from a PCI config space read that must be handled
+ // 2. Unexpected MAB from a PCI memory or I/O space read in ISA legacy
+ // space that can be handled.
+ // 3. Unexpected MAB. Don't handle or fix up this error condition.
+ // (Really take the machine check.)
+ //
+
+ //
+ // Case 1: Expected Master Abort, e.g. a PCI configuration read error.
+ //
+
+ if ( (IodCapErr.Mab == 1) && ExpectedMchk ){
+
+ //
+ // Here's how a PCI config space read to an empty slot will transpire:
+ //
+ // READ_CONFIG_Usize indicates the issuing CPU and address in
+ // HalpMasterAbortExpected.Number and HalpMasterAbortExpected.Addr.
+ //
+ // PCI config space read will case a MC Bus FILL_ERROR on the issuing CPU
+ // FILL_ERROR causes a machine check.
+ //
+ // The targeted MC-PCI bus bridge will set CAP_ERR<MasterAbort> bit.
+ //
+ // So far, the error looks like a PCI configuration space read
+ // that accessed a device that does not exist. In order to fix
+ // this up we expect that the original faulting instruction must
+ // be a load with v0 as the destination register. Unfortunately,
+ // machine checks are not precise exceptions so we may have exectued
+ // many instructions since the faulting load. For EV5 a pair of
+ // memory barrier instructions following the load will stall the pipe
+ // waiting for load completion before the second memory barrier can
+ // be issued. Therefore, we expect the exception PC to point to either
+ // the load instruction or one of the two memory barriers. We will
+ // assume that if the exception pc is not an mb that instead it
+ // points to the load that machine checked. We must be careful to
+ // not reexectute the load.
+ //
+
+ ALPHA_INSTRUCTION FaultingInstruction;
+
+
+ FaultingInstruction.Long = *(PULONG)((ULONG)TrapFrame->Fir);
+ if( FaultingInstruction.Memory.Opcode != MEMSPC_OP ){
+
+ //
+ // Exception pc does not point to a memory barrier, return
+ // to the instruction after the exception pc.
+ //
+
+ TrapFrame->Fir += 4;
+
+ }
+
+ //
+ // The error has matched all of our conditions. Fix it up by
+ // writing the value 0xffffffff into the destination of the load.
+ //
+
+ TrapFrame->IntV0 = (ULONGLONG)0xffffffffffffffff;
+
+ //
+ // Clear all error conditions in CAP_ERR.
+ // (McAddrPerr, LostMcErr, Mab)
+ //
+#if 0
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->CapErr,
+ IodCapErr.all );
+#else
+ IodCapErrMask.all = ALL_CAP_ERRORS;
+ HalpClearAllIods( IodCapErrMask );
+#endif
+
+ //
+ // Clear the hard error interrupt.
+ // ecrfix - For now, the Hard error interrupt is masked, so
+ // we don't have to clear it.
+ //
+
+ return TRUE;
+
+ }
+#if 0
+ //
+ // Case 2: Uexpected Master Abort, e.g. a PCI memory or I/O space read to
+ // legacy ISA space (0 - 1 Mb) on PCI-1,2,3.
+ //
+
+ if ( bHandleIsaError( McDeviceId, IodCapErr) ) {
+ return TRUE;
+ }
+#endif
+ //
+ // Case 3: Unexpected Master abort.
+ // (Or anything I might have missed.... )
+ //
+
+#if (DBG) || (HALDBG)
+ DbgPrint( "Unexpected PCI master abort\n" );
+#endif
+
+ return ( bHandleFatalIodError(McDeviceId, TRUE) );
+
+}
+
+
+#define ENTIRE_FRAME_SIZE (sizeof(ERROR_FRAME) + sizeof(RAWHIDE_CORRECTABLE_FRAME))
+VOID
+HalpIodSoftErrorInterrupt(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Handle a IOD soft (correctable) error interrupt.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ BOOLEAN bfoundIod;
+ MC_DEVICE_ID McDeviceId;
+
+ static UCHAR Frame[ENTIRE_FRAME_SIZE];
+ static PERROR_FRAME pFrame;
+ static RAWHIDE_CORRECTABLE_FRAME RawhideFrame;
+ static BOOLEAN RawhideFrameInitialized = FALSE;
+
+ UCHAR TempFrame[ENTIRE_FRAME_SIZE];
+ PERROR_FRAME pTempFrame;
+ PCORRECTABLE_ERROR pCorr;
+ PRAWHIDE_CORRECTABLE_FRAME pRawCorr;
+
+ PBOOLEAN ErrorlogBusy;
+ PULONG DispatchCode;
+ PKINTERRUPT InterruptObject;
+ PKSPIN_LOCK ErrorlogSpinLock;
+ PRAWHIDE_UNCORRECTABLE_FRAME rawerr;
+
+ IOD_CAP_ERR IodCapErr;
+ IOD_MDPA_STAT IodMdpaStat;
+ IOD_MDPA_STAT IodMdpbStat;
+ IOD_MC_ERR0 IodMcErr0;
+ IOD_MC_ERR1 IodMcErr1;
+
+ KIRQL Irql;
+
+#if 0 // CAP/MDP Bug
+ IOD_MDPA_SYN IodMdpaSyn;
+ IOD_MDPB_SYN IodMdpbSyn;
+#endif
+
+
+//ecrfix - later we should log the error, throttle the logging and turn off
+// correctable error reporting if the frequency is too high
+
+ //
+ // The error is expected to be a corrected ECC error on a DMA or
+ // Scatter/Gather TLB read/write. Read the error registers relevant
+ // to this error.
+ //
+
+ //
+ // Find the IOD that latched the error.
+ //
+
+ bfoundIod = bFindIodError( &McDeviceId, &IodCapErr );
+
+#ifdef FORCE_CORRECTABLE_ERROR
+ IodCapErr.all = 0x88000000;
+ bfoundIod = 1;
+#endif // FORCE_CORRECTABLE_ERROR
+
+ //
+ // Check that we found an IOD that has a valid PCI or MC error.
+ // If it is not this is a pretty weird (fatal???) condition.
+ // For now, we'll just go return TRUE.
+ //
+
+ if( !bfoundIod ) {
+
+#if 0 //HALDBG
+ DbgPrint( "HalpIodSoftErrorInterrupt: no PCI or MC error found.\n");
+#endif
+ return;
+ }
+
+ //
+ // Check if an error is latched into the IOD. If not, goodbye.
+ //
+
+ if( IodCapErr.McErrValid == 0 ){
+
+#if HALDBG
+ DbgPrint( "Iod soft error interrupt without valid MC error\n" );
+#endif //HALDBG
+
+ return;
+ }
+
+ //
+ // Check for the correctable error bit.
+ //
+
+ if( (IodCapErr.CrdA == 0) && (IodCapErr.CrdB == 0) ){
+
+#if HALDBG
+ DbgPrint( "Iod soft error interrupt without correctable error indicated in CapErr\n" );
+#endif //HALDBG
+
+ }
+
+
+ //
+ // Increment the number of IOD correctable errors.
+ //
+
+ IodCorrectedErrors += 1;
+
+ //
+ // Read the rest of the error registers
+ //
+
+ IodMcErr0.all = (ULONG)READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR0_CSRS_QVA))->McErr0
+ );
+
+ IodMcErr1.all = (ULONG)READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR0_CSRS_QVA))->McErr1
+ );
+#ifdef FORCE_CORRECTABLE_ERROR
+ IodMcErr0.all = 0x00bebad0;
+ IodMcErr1.all = 0x800f3f00;
+#endif // FORCE_CORRECTABLE_ERROR
+
+#if 0 // CAP/MDP Bug
+ IodMdpaStat.all = (ULONG)READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR0_CSRS_QVA))->MdpaStat
+ );
+
+ IodMdpaSyn.all = (ULONG)READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR0_CSRS_QVA))->MdpaSyn
+ );
+
+ IodMdpbStat.all = (ULONG)READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR0_CSRS_QVA))->MdpbStat
+ );
+
+ IodMdpbSyn.all = (ULONG)READ_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR0_CSRS_QVA))->MdpbSyn
+ );
+#endif
+
+
+#if HALDBG
+
+ //
+ // Print a correctable error message to the debugger.
+ //
+
+ DbgPrint( "IOD Correctable Error Number %d, state follows: \n",
+ IodCorrectedErrors );
+ DbgPrint( "\tIOD_CAP_ERR: 0x%x\n", IodCapErr.all );
+ DbgPrint( "\tIOD_MC_ERR0: 0x%x\n", IodMcErr0.all );
+ DbgPrint( "\tIOD_MC_ERR1: 0x%x\n", IodMcErr1.all );
+// DbgPrint( "\tIOD_MDPA_STAT: 0x%x\n", IodMdpaStat.all );
+// DbgPrint( "\tIOD_MDPA_SYN: 0x%x\n", IodMdpaSyn.all );
+// DbgPrint( "\tIOD_MDPB_STAT: 0x%x\n", IodMdpbStat.all );
+// DbgPrint( "\tIOD_MDPB_SYN: 0x%x\n", IodMdpbSyn.all );
+
+#endif //HALDBG
+
+ //
+ // Fill in the Correctable Error frame only if we've connected
+ // to the Correctable Error interrupt.
+ //
+
+ if (HalpLogCorrectableErrors) {
+
+ //
+ // Real error, get the interrupt object.
+ //
+
+ DispatchCode = (PULONG)PCR->InterruptRoutine[RawhideSoftErrVector];
+ InterruptObject = CONTAINING_RECORD(
+ DispatchCode,
+ KINTERRUPT,
+ DispatchCode
+ );
+
+ //
+ // Set various pointers so we can use them later.
+ //
+
+ pFrame = (PERROR_FRAME) Frame;
+ pTempFrame = (PERROR_FRAME) TempFrame;
+ pCorr = (PCORRECTABLE_ERROR) &pTempFrame->CorrectableFrame;
+ pRawCorr = (PRAWHIDE_CORRECTABLE_FRAME) (TempFrame +
+ sizeof(ERROR_FRAME) );
+
+ ErrorlogBusy = (PBOOLEAN)((PUCHAR)InterruptObject->ServiceContext +
+ sizeof(PERROR_FRAME));
+ ErrorlogSpinLock = (PKSPIN_LOCK)((PUCHAR)ErrorlogBusy + sizeof(PBOOLEAN));
+
+ //
+ // Clear the data structures that we will use.
+ //
+
+ RtlZeroMemory(&TempFrame, ENTIRE_FRAME_SIZE);
+
+ //
+ // Fill in the error frame information.
+ //
+
+ pTempFrame->Signature = ERROR_FRAME_SIGNATURE;
+ pTempFrame->LengthOfEntireErrorFrame = ENTIRE_FRAME_SIZE;
+ pTempFrame->FrameType = CorrectableFrame;
+ pTempFrame->VersionNumber = ERROR_FRAME_VERSION;
+ pTempFrame->SequenceNumber = IodCorrectedErrors;
+ pTempFrame->PerformanceCounterValue =
+ KeQueryPerformanceCounter(NULL).QuadPart;
+
+ //
+ // Check for lost error.
+ //
+
+ if( IodCapErr.LostMcErr ) {
+
+ //
+ // Since the error registers are locked from a previous error,
+ // we do not know where the error came from. Mark everything
+ // as UNIDENTIFIED.
+ //
+
+ pCorr->Flags.LostCorrectable = 1;
+ pCorr->Flags.LostAddressSpace = UNIDENTIFIED;
+ pCorr->Flags.LostMemoryErrorSource = UNIDENTIFIED;
+ }
+
+ pCorr->Flags.ErrorBitMasksValid = 0;
+
+ //
+ // Determine error type.
+ //
+
+ if (IodMcErr1.Addr39_32 & 0x80) {
+
+ //
+ // I/O ECC error occurred.
+ //
+
+ pCorr->Flags.AddressSpace = IO_SPACE;
+ pCorr->Flags.ExtendedErrorValid = 1;
+ pCorr->ErrorInformation.IoError.Interface = PCIBus;
+ pCorr->ErrorInformation.IoError.BusNumber = IodMcErr1.DevId & 0x3;
+
+ // We never alloc PCI address higher than 1 Gb for any PCI
+ // address space (sparse mem, dense mem, sparse I/O), so this
+ // trick works.
+
+ pCorr->ErrorInformation.IoError.BusAddress.LowPart =
+ ((IodMcErr0.Addr & 0x3FFFFFFF) >> IO_BIT_SHIFT);
+
+ // The code below is not strictly correct. Based on the MC Bus
+ // spec, p.32, we can roughly say that McCmd<3> tells us whether
+ // there was a write or read transaction on the bus. If I looked
+ // at the spec harder, I might be able to distinguish a PIO op
+ // from a DMA operation.
+
+ pCorr->ErrorInformation.IoError.TransferType
+ = ((IodMcErr1.McCmd & 0x8) ? BUS_IO_READ : BUS_IO_WRITE);
+
+ } else {
+
+ //
+ // Memory ECC error occurred.
+ //
+
+ pCorr->Flags.AddressSpace = MEMORY_SPACE;
+
+ }
+
+ //
+ // Get the physical address where the error occurred.
+ //
+
+ if (IodMcErr1.Valid) {
+ pCorr->Flags.PhysicalAddressValid = 1;
+ pCorr->PhysicalAddress =
+ ((ULONGLONG) (IodMcErr1.Addr39_32)) << 32;
+ pCorr->PhysicalAddress |= IodMcErr0.all;
+ }
+
+ //
+ // Scrub the error if it's any type of memory error.
+ //
+
+ if ( pCorr->Flags.AddressSpace == MEMORY_SPACE &&
+ pCorr->Flags.PhysicalAddressValid ) {
+ pCorr->Flags.ScrubError = 1;
+ }
+
+ //
+ // Acquire the spinlock.
+ //
+
+ KeAcquireSpinLock(ErrorlogSpinLock, &Irql );
+
+ //
+ // Check to see if an errorlog operation is in progress already.
+ //
+
+ if (!*ErrorlogBusy) {
+
+ //
+ // Set reporting processor information. Disregard at the moment.
+ //
+
+ pCorr->Flags.ProcessorInformationValid = 0;
+
+ //
+ // Copy the SYSTEM_INFORMATION from the uncorrectable frame
+ //
+
+ pCorr->System = PUncorrectableError->UncorrectableFrame.System;
+
+ //
+ //
+ // Set raw system information flag.
+ //
+
+ pCorr->Flags.SystemInformationValid = 1;
+
+ //
+ // Do the Rawhide-specific stuff here
+ //
+
+ pRawCorr->Revision = RAWHIDE_CORRECTABLE_FRAME_REVISION;
+
+ //
+ // Copy the CUD header from the uncorrectable frame
+ //
+
+ rawerr = (PRAWHIDE_UNCORRECTABLE_FRAME)
+ PUncorrectableError->UncorrectableFrame.RawSystemInformation;
+ if (rawerr) {
+ pRawCorr->CudHeader = rawerr->CudHeader;
+ }
+
+ //
+ // Fill in the rest of the dynamic portion of the
+ // correctable frame.
+ //
+
+ pRawCorr->CudHeader.ActiveCpus = BuildActiveCpus();
+ pRawCorr->ErrorSubpacketFlags.all = 0;
+ pRawCorr->ErrorSubpacketFlags.IodSubpacketPresent = 1;
+ pRawCorr->WhoAmI = HalpReadWhoAmI();
+ HalpBuildIodErrorFrame( McDeviceId, &(pRawCorr->IodErrorFrame) );
+
+ //
+ // Copy the information that we need to log.
+ //
+
+ RtlCopyMemory(&Frame,
+ &TempFrame,
+ ENTIRE_FRAME_SIZE);
+
+ pFrame->CorrectableFrame.RawSystemInformation =
+ (PVOID)((PUCHAR)pFrame + sizeof(ERROR_FRAME) );
+
+ pFrame->CorrectableFrame.RawSystemInformationLength =
+ sizeof(RAWHIDE_CORRECTABLE_FRAME);
+
+
+ //
+ // Put frame into ISR service context.
+ //
+
+ *(PERROR_FRAME *)InterruptObject->ServiceContext = pFrame;
+
+ } else {
+
+ //
+ // An errorlog operation is in progress already. We will
+ // set various lost bits and then get out without doing
+ // an actual errorloging call.
+ //
+
+ pFrame->CorrectableFrame.Flags.LostCorrectable = TRUE;
+ pFrame->CorrectableFrame.Flags.LostAddressSpace =
+ pTempFrame->CorrectableFrame.Flags.AddressSpace;
+ pFrame->CorrectableFrame.Flags.LostMemoryErrorSource =
+ pTempFrame->CorrectableFrame.Flags.MemoryErrorSource;
+ }
+
+ //
+ // Release the spinlock.
+ //
+
+ KeReleaseSpinLock(ErrorlogSpinLock, Irql );
+
+ //
+ // Dispatch to the secondary correctable interrupt service routine.
+ // The assumption here is that if this interrupt ever happens, then
+ // some driver enabled it, and the driver should have the ISR connected.
+ //
+
+ ((PSECOND_LEVEL_DISPATCH)InterruptObject->DispatchAddress)(
+ InterruptObject,
+ InterruptObject->ServiceContext
+ );
+
+ }
+
+
+
+ //
+ // Clear state in MDPA and MDPB before clearing CAP_ERR
+ //
+
+ IodCapErr.all = 0;
+ IodCapErr.CrdA = 1;
+ IodCapErr.CrdB = 1;
+ IodMdpaStat.all = 0xffffffff;
+ IodMdpbStat.all = 0xffffffff;
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpaStat,
+ IodMdpaStat.all
+ );
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpaStat,
+ IodMdpbStat.all
+ );
+
+ WRITE_IOD_REGISTER_NEW( McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->CapErr,
+ IodCapErr.all
+ );
+
+ return;
+
+}
+
+VOID
+HalpIodHardErrorInterrupt(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Handle a IOD hard (uncorrectable) error interrupt.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ BOOLEAN bfoundIod;
+ MC_DEVICE_ID McDeviceId;
+ IOD_CAP_ERR IodCapErr;
+ IOD_WHOAMI IodWhoAmI;
+ KIRQL OldIrql;
+
+
+ //
+ // Raise IRQL to the highest level.
+ // Prevents us from taking other hard error interrupts
+ // during this one.
+ //
+ // Also, acquire a spin lock to keep entry
+ // to this code serialized.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+ //
+ // Find the IOD that latched the error.
+ //
+
+ bfoundIod = bFindIodError( &McDeviceId, &IodCapErr );
+
+ //
+ // Check that we found an IOD that has a valid PCI or MC error.
+ // If it is not this is a pretty weird (fatal???) condition.
+ // For now, we'll just return.
+ //
+
+ if( !bfoundIod ) {
+
+#if 0 // HALDBG
+ DbgPrint( "HalpIodHardErrorInterrupt: no PCI or MC error found.\n");
+#endif
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KiReleaseSpinLock(&HalpSystemInterruptLock);
+ KeLowerIrql(OldIrql);
+ return;
+ }
+
+#if 1 // ecrfix
+ //
+ // See if this was an ISA legacy space access
+ // on PCI-1,2,3. If so, dismiss this interrupt.
+ //
+
+ if ( bHandleIsaError( McDeviceId, IodCapErr) ) {
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KiReleaseSpinLock(&HalpSystemInterruptLock);
+ KeLowerIrql(OldIrql);
+ return;
+ }
+#endif
+
+#if HALDBG
+ DbgPrint( "Hard Error Found on IOD (%x, %x)\n",
+ McDeviceId.Gid,
+ McDeviceId.Mid );
+#endif //HALDBG
+
+ //
+ // Save IodWhoAmI
+ //
+
+ IodWhoAmI.all = HalpReadWhoAmI();
+ HalpIodWhoAmIOnError.all = IodWhoAmI.all;
+
+ //
+ // Handle the Fatal Error
+ //
+
+ bHandleFatalIodError( McDeviceId, FALSE );
+
+ KeBugCheckEx( DATA_BUS_ERROR,
+ 0xbeadfeed, //ecrfix - quick error interrupt id
+ McDeviceId.all,
+ 0,
+ (ULONG) PUncorrectableError );
+
+
+}
+
+BOOLEAN
+bHandleFatalIodError(
+ MC_DEVICE_ID McDeviceId,
+ BOOLEAN bMachineCheck
+ )
+/*++
+
+Routine Description:
+
+ Handles the epilogue of a fatal IOD unccorrectable error
+ from either a machine check or IOD hard error interrupt.
+
+Arguments:
+
+ McDeviceId - IOD on which the error was found
+
+ bMachineCheck - TRUE if we're handling a fatal machine check
+ FALSE if we're handling a fatal hard error interrupt
+
+Return Value:
+
+ TRUE is returned if the IOD error has been handled and dismissed -
+ indicating that execution can continue. FALSE is return otherwise.
+
+--*/
+{
+
+#if HALDBG
+ if (bMachineCheck ) {
+ DbgPrint( "Handling fatal error - machine check\n" );
+ } else {
+ DbgPrint( "Handling fatal error - hard error interrupt\n" );
+ }
+#endif
+
+ //
+ // Clear the error condition in the MCES register.
+ //
+ // ecrfix - the way this is written, this will be done on hard
+ // error interrupts too (where there has been *no* machine check).
+ // I hope it will be benign in this case....
+ //
+
+ HalpUpdateMces( TRUE, TRUE );
+
+ //
+ // Proceed to display the error.
+ //
+
+ HalAcquireDisplayOwnership(NULL);
+
+ //
+ // Display the dreaded banner.
+ //
+
+ HalDisplayString( "\nFatal system hardware error.\n" );
+
+#ifdef DUMPIODS
+ DumpAllIods(AllRegisters);
+#endif
+
+
+ HalpIodReportFatalError( McDeviceId );
+
+ return( FALSE );
+
+}
+
+BOOLEAN
+bFindIodError(
+ PMC_DEVICE_ID pMcDeviceId,
+ PIOD_CAP_ERR pIodCapErr
+)
+/*++
+
+Routine Description:
+
+ Determines which IOD has an error latched in it.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ TRUE if an IOD was found with an error latched in CAP_ERR.
+ FALSE otherwise.
+
+--*/
+{
+ MC_ENUM_CONTEXT mcCtx;
+ ULONG numIods;
+ BOOLEAN bfoundIod;
+ IOD_CAP_ERR IodCapErr;
+
+
+ //
+ // Intialize enumerator.
+ //
+
+ numIods = HalpMcBusEnumStart ( HalpIodMask, &mcCtx );
+
+#if 0 // HALDBG
+ DbgPrint( "FindIodError: Searching: %d Iods: ", numIods);
+#endif // HALDBG
+
+ //
+ // Search each Iod and look for a PCI or McBus error.
+ //
+
+ while ( bfoundIod = HalpMcBusEnum( &mcCtx ) ) {
+
+ //
+ // Read the IOD error register to determine the source of the
+ // error.
+ //
+
+#if 0 //HALDBG
+ DbgPrint( "(%d, %d) ", mcCtx.McDeviceId.Gid, mcCtx.McDeviceId.Mid);
+#endif // HALDBG
+
+ IodCapErr.all = READ_IOD_REGISTER_NEW( mcCtx.McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->CapErr );
+
+ if( (IodCapErr.PciErrValid != 0) || (IodCapErr.McErrValid != 0) ){
+ break;
+ }
+ }
+
+#if 0 // HALDBG
+ if (bfoundIod) {
+ DbgPrint( "Found!\n");
+ } else {
+ DbgPrint( "Error Not Found!\n");
+ }
+#endif // HALDBG
+
+ //
+ // Return the McDeviceId and CapErr register contents
+ // of the first IOD that has an error.
+ //
+
+ *pMcDeviceId = mcCtx.McDeviceId;
+ pIodCapErr->all = IodCapErr.all;
+
+ return (bfoundIod);
+}
+
+BOOLEAN
+bHandleIsaError(
+ MC_DEVICE_ID McDeviceId,
+ IOD_CAP_ERR IodCapErrIn
+)
+/*++
+
+Routine Description:
+
+ Gives PCI-1,2,3 ISA legacy semantics for I/O and memory accesses.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ TRUE if the error was handled.
+ FALSE otherwise.
+
+--*/
+{
+
+ MC_ENUM_CONTEXT mcCtx;
+ MC_DEVICE_ID McDeviceIdWithMab;
+ ULONG numIods;
+ BOOLEAN bfoundIod;
+ IOD_CAP_ERR IodCapErr;
+ IOD_CAP_ERR IodCapErrMask;
+
+
+ //
+ // Find an IOD that has Mab set. If we do not find one, then
+ // we don't have this error.
+ //
+
+
+ numIods = HalpMcBusEnumStart ( HalpIodMask, &mcCtx );
+
+ //
+ // Search each Iod and look for a PCI or McBus error.
+ //
+
+ while ( bfoundIod = HalpMcBusEnum( &mcCtx ) ) {
+
+ //
+ // Read the IOD error register to determine who has Mab set
+ //
+
+ IodCapErr.all = READ_IOD_REGISTER_NEW( mcCtx.McDeviceId,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->CapErr );
+
+ if( (IodCapErr.PciErrValid == 1) &&
+ (IodCapErr.Perr == 0) &&
+ (IodCapErr.Serr == 0) &&
+ (IodCapErr.Mab == 1) &&
+ (IodCapErr.PteInv == 0) ) {
+ break;
+ }
+ }
+
+ //
+ // If we didn't find an IOD with Mab set, then do not handle this error.
+ //
+
+ if (!bfoundIod) {
+ return FALSE;
+ }
+
+ //
+ // Save the McDevice Id of the offending IOD
+ //
+
+ McDeviceIdWithMab.all = mcCtx.McDeviceId.all;
+
+ //
+ // This must be on a bus other than PCI0 for us to handle this error
+ // (PCI0 reads to non-existent ISA addresses will be fixed by by the
+ // PCI-EISA bridge. Thus we'll never get here on PCI0 unless there
+ // really is an error.)
+ //
+
+ if ( McDeviceIdWithMab.Mid != MidPci0 ) {
+
+
+ IOD_PCI_ERR1 IodPciErr1;
+
+ //
+ // Get the PCI address of the transaction that caused the MAB
+ //
+
+ IodPciErr1.PciAddress =
+ (ULONG) READ_IOD_REGISTER_NEW( McDeviceIdWithMab,
+ &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->PciErr1 );
+
+
+ //
+ // To be handled as an ISA legacy memory or I/O space read, the
+ // FaultingPciAddress must be in the range 0-1 Mb
+ //
+
+ if( IodPciErr1.PciAddress < __1MB ) {
+
+ //
+ // The error has matched all of our conditions. Assume that
+ // V0 has already been set to 0xffffffff. (This is a contract
+ // with the HAL access routines in iodio.s.)
+ //
+
+ IodCapErrMask.all = ALL_CAP_ERRORS;
+ HalpClearAllIods( IodCapErrMask );
+
+ return TRUE;
+
+ }
+
+#if HALDBG
+ DbgPrint( "Failed checking for legacy ISA read:\n");
+ DbgPrint( "PciErr1 : %08x\n", IodPciErr1.PciAddress );
+#endif //HALDBG
+
+ }
+
+ //
+ // We have a PCI Mab on PCI0. Do not handle this error.
+ //
+
+ return FALSE;
+
+ }
+
+VOID
+HalpErrorFrameString(
+ PUNCORRECTABLE_ERROR uncorr,
+ PUCHAR OutBuffer
+ )
+/*++
+
+Routine Description:
+
+ Append an Error message to the Uncorrectable Error Frame
+ string
+
+Arguments:
+
+ uncorr - Pointer to the UNCORRECTABLE_ERROR frame.
+
+ OutBuffer - message to be appended.
+ (If null, no string is appended, and pCurrentString
+ is reset to NULL).
+
+
+Return Value:
+
+ none.
+
+--*/
+{
+ ULONG len;
+ static PCHAR pCurrentString = NULL;
+
+ //
+ // If OutBuffer is NULL, reset pointer and flag
+ //
+
+ if (OutBuffer == NULL) {
+ pCurrentString = NULL;
+ if (uncorr) uncorr->Flags.ErrorStringValid = 0;
+ return;
+ }
+
+ //
+ // Uncorrectable frame valid?
+ //
+
+ if (uncorr) {
+
+ //
+ // On first error message:
+ // * Init pCurrentString to beginning of ErrorString
+ // * Set valid flag
+ //
+
+ if (pCurrentString == NULL) {
+ pCurrentString = uncorr->ErrorString;
+ uncorr->Flags.ErrorStringValid = 1;
+ }
+
+ //
+ // Append OutBuffer to ErrorString
+ //
+
+ len = strlen(OutBuffer);
+ strncpy(pCurrentString,
+ OutBuffer,
+ len);
+
+ //
+ // Zero-terminate the error string.
+ //
+
+ pCurrentString += len;
+ *pCurrentString = 0;
+
+ }
+}
+
+ULONG
+BuildActiveCpus (
+ VOID
+ )
+{
+ ULONG ActiveLogicalProcessors = HalpActiveProcessors;
+ ULONG ActivePhysicalCpus = 0;
+ ULONG i;
+
+ //
+ // Make a physical processor mask from the logical processor mask
+ //
+
+ for (i = 0; i < HalpNumberOfCpus; i++, ActiveLogicalProcessors >> 1) {
+ if (ActiveLogicalProcessors & 0x1) {
+ ActivePhysicalCpus |= (1 << (ULONG) (MCDEVID_TO_PHYS_CPU(
+ HalpLogicalToPhysicalProcessor[i].all)));
+ }
+ }
+
+ return (ActivePhysicalCpus);
+
+}
diff --git a/private/ntos/nthals/halraw/alpha/iodio.s b/private/ntos/nthals/halraw/alpha/iodio.s
new file mode 100644
index 000000000..6edc5f9d0
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/iodio.s
@@ -0,0 +1,2997 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ iodio.s
+
+Abstract:
+
+ This module implements the I/O access routines for the IOD
+ (CAP/MDP) ASICs.
+
+ The module contains the functions to turn quasi virtual
+ addresses into an Alpha superpage virtual address
+ and then read or write based on the request.
+
+Author:
+
+ Eric Rehm 10-Apr-1995
+
+
+Environment:
+
+ Executes in kernel mode.
+
+Revision History:
+
+
+--*/
+
+#include "halalpha.h"
+#include "iod.h"
+
+
+//
+// Superpage VAs
+//
+// The following constants are used to construct the physical addresses
+// used to access i/o space.
+//
+// assembler BUGBUG:
+//
+// The following values are hacks to get around the intelligent
+// Alpha assemblers. Instead of sign extending 16 bit quantities greater
+// than 32K-1, the assembler generates a ldah/lda pair to load exactly
+// the sixteen bit quantity specified, without sign extending.
+//
+// By specifying the quantity as a negative number, the assembler allows
+// a single lda instruction, with sign extension.
+//
+
+
+//
+// ecrfix - these definitions are good for PCI 0 (GID = 7, MID = 4) ONLY!!!
+//
+
+
+#define IOD_SPARSE_MEM_SVA -0x3080 // negative of 0xcf80
+#define IOD_DENSE_MEM_SVA -0x3070 // negative of 0xcf90
+#define IOD_SPARSE_IO_SVA -0x3068 // negative of 0xcf98
+#define IOD_REGISTER_SVA -0x3062 // negative of 0xcf9E
+
+//
+// These definitions are based on GID=0, MID=0 and can be used
+// to construct an superpage address for any (GID, MID).
+//
+
+#define IOD_PCI0_REGISTER_SVA -0x3062 // negative of 0xcf9E
+#define IOD_REGISTER_NEW_SVA -0x3800 // negative of 0xc800
+#define IOD_IP_INTR_SVA -0x37ff // negative of 0xc801 (to CUD only)
+#define IOD_INTTIM_SVA -0x37f0 // negative of 0xc810 (to CUD only)
+#define IOD_IP_ACK_SVA -0x37ef // negative of 0xc811 (to CUD only)
+#define IOD_MCHK_ACK_SVA -0x37ee // negative of 0xc812 (to CUD only)
+#define IOD_HALT_ACK_SVA -0x37e9 // negative of 0xc817 (to CUD only)
+#define IOD_PCI_CONFIG_SVA -0x37e4 // negative of 0xc81C
+#define IOD_INT_ACK_SVA -0x37e1 // negative of 0xc81F
+
+#define IOD_TARGET0_OFFSET 0x3f00
+#define IOD_TARGET1_OFFSET 0x3f40
+
+#define MabNumber 0 // offset of HalpMasterAbortExpected.Number
+#define MabAddr 8 // offset of HalpMasterAbortExpected.Addr
+#define MASTER_ABORT_NOT_EXPECTED 0xffffffff
+
+#define GET_PROCESSOR_CONTROL_BLOCK_BASE \
+ call_pal rdpcr; \
+ ldl v0, PcPrcb(v0)
+
+
+ SBTTL( "Return PCR address for current processor" )
+//++
+//
+// PVOID
+// HalpRdPcr(
+// )
+//
+// Routine Description:
+//
+// Calls PAL to obtain PCR for current processor
+//
+// Arguments:
+//
+// None
+//
+// Return Value:
+//
+// v0 - Address of PCR
+//
+//--
+
+ LEAF_ENTRY(HalpRdPcr)
+
+
+ call_pal rdpcr; // CallPal to read PCR
+ ret zero, (ra) // return
+
+ .end HalpRdPcr
+
+
+
+ SBTTL( "Read byte from PCI memory" )
+//++
+//
+// UCHAR
+// READ_REGISTER_UCHAR(
+// IN PVOID RegisterQva
+// )
+//
+// Routine Description:
+//
+// Reads a byte location in PCI bus sparse memory space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the I/O byte to read.
+//
+// Return Value:
+//
+// v0 - Returns the value read from I/O space.
+//
+//--
+
+ LEAF_ENTRY(READ_REGISTER_UCHAR)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get byte lane
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 10f // if ne, iff failed
+
+//
+// Sparse space access.
+//
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ and a0, IOD_SPARSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_SPARSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_SPARSE_ENABLE, a0 // clear QVA fields <32:27>
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, IOD_SPARSE_MEM_SVA(zero) // 0xffff ffff ffff cf80
+ sll t4, 28, t4 // 0xffff fcf8 0000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, t4, t0 // superpage mode
+ bis zero, 0xffffffff,v0 // ecrfix
+
+ ldl v0, (t0) // get the longword
+ extbl v0, t3, v0 // get correct byte if eisa
+
+ ret zero, (ra) // return
+
+//
+// Dense space access.
+//
+
+10:
+ zap a0, 0xf0, a0 // clear <63:32>
+ and a0, 3, t3 // capture byte offset
+ bic a0, 3, a0 // clear byte offset
+ and a0, IOD_DENSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_DENSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_DENSE_ENABLE, a0 // clear QVA fields <31:30>
+ lda t0, IOD_DENSE_MEM_SVA(zero) // 0xffff ffff ffff cf90
+ sll t0, 28, t0 // 0xffff fcf9 0000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, a0, t0 // 0xffff fcf9 xxxx xxxx
+ bis zero, 0xffffffff,v0 // ecrfix
+ mb // ensure all writes are visible
+ ldl v0, 0(t0) // read from dense space
+ extbl v0, t3, v0 // extract appropriate byte
+
+ ret zero, (ra) // return
+
+ .end READ_REGISTER_UCHAR
+
+
+
+ SBTTL( "Read byte from PCI sparse i/o" )
+//++
+//
+// UCHAR
+// READ_PORT_UCHAR(
+// IN PVOID RegisterQva
+// )
+//
+// Routine Description:
+//
+// Reads a byte location in PCI bus sparse i/o space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the I/O byte to read.
+//
+// Return Value:
+//
+// v0 - Returns the value read from I/O space.
+//
+//--
+
+ LEAF_ENTRY(READ_PORT_UCHAR)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get byte lane
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 10f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ and a0, IOD_SPARSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_SPARSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_SPARSE_ENABLE, a0 // clear QVA fields <32:27>
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, IOD_SPARSE_IO_SVA(zero) // 0xffff ffff cf98 0000
+ sll t4, 28, t4 // 0xffff fcf9 8000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, t4, t0 // superpage mode
+ bis zero, 0xffffffff,v0 // ecrfix
+
+ mb // ensure all writes are visible
+ ldl v0, (t0) // get the longword
+ extbl v0, t3, v0 // get correct byte if eisa
+
+ ret zero, (ra) // return
+
+//
+// Illegal access, did not use a QVA.
+//
+
+10:
+
+#if DBG
+
+ BREAK_DEBUG_STOP // take a breakpoint
+
+#endif //DBG
+
+ ldil v0, 0xffffffff // return fixed value
+
+ ret zero, (ra) // return to caller
+
+ .end READ_PORT_UCHAR
+
+
+ SBTTL( "Read short from PCI memory" )
+//++
+//
+// UCHAR
+// READ_REGISTER_USHORT(
+// IN PVOID RegisterQva
+// )
+//
+// Routine Description:
+//
+// Reads a short location in PCI bus sparse memory space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the memory short to read.
+//
+// Return Value:
+//
+// v0 - Returns the value read from PCI memory.
+//
+//--
+
+ LEAF_ENTRY(READ_REGISTER_USHORT)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get short lane
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 10f // if ne, iff failed
+
+//
+// Sparse space access.
+//
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ and a0, IOD_SPARSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_SPARSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_SPARSE_ENABLE, a0 // clear QVA fields <32:27>
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, IOD_SPARSE_MEM_SVA(zero) // 0xffff ffff ffff cf80
+ sll t4, 28, t4 // 0xffff fcf8 0000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, t4, t0 // superpage mode
+
+ or t0, IO_WORD_LEN, t0 // set size to short
+ bis zero, 0xffffffff,v0 // ecrfix
+
+ mb // ensure all writes are visible
+ ldl v0, (t0) // get the longword
+ extwl v0, t3, v0 // get correct byte if eisa
+
+ ret zero, (ra) // return
+
+//
+// Dense space access.
+//
+
+10:
+ zap a0, 0xf0, a0 // clear <63:32>
+ and a0, 3, t3 // capture byte offset
+ bic a0, 3, a0 // clear byte offset
+ and a0, IOD_DENSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_DENSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_DENSE_ENABLE, a0 // clear QVA fields <31:30>
+ lda t0, IOD_DENSE_MEM_SVA(zero) // 0xffff ffff ffff cf90
+ sll t0, 28, t0 // 0xffff fcf9 0000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, a0, t0 // 0xffff fcf9 xxxx xxxx
+ bis zero, 0xffffffff,v0 // ecrfix
+ ldl v0, 0(t0) // read from dense space
+ extwl v0, t3, v0 // extract appropriate word
+
+ ret zero, (ra) // return
+
+ .end READ_REGISTER_USHORT
+
+
+ SBTTL( "Read short from PCI sparse I/O" )
+//++
+//
+// UCHAR
+// READ_PORT_USHORT(
+// IN PVOID RegisterQva
+// )
+//
+// Routine Description:
+//
+// Reads a short location in PCI bus sparse i/o space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the i/o short to read.
+//
+// Return Value:
+//
+// v0 - Returns the value read from PCI I/O.
+//
+//--
+
+ LEAF_ENTRY(READ_PORT_USHORT)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get short lane
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 10f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ and a0, IOD_SPARSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_SPARSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_SPARSE_ENABLE, a0 // clear QVA fields <32:27>
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, IOD_SPARSE_IO_SVA(zero) // 0xffff ffff ffff cf98
+ sll t4, 28, t4 // 0xffff fcf9 8000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, t4, t0 // superpage mode
+
+ or t0, IO_WORD_LEN, t0 // set size to short
+ bis zero, 0xffffffff,v0 // ecrfix
+
+ mb // ensure all writes are visible
+ ldl v0, (t0) // get the longword
+ extwl v0, t3, v0 // get correct byte if eisa
+
+ ret zero, (ra) // return
+
+//
+// Illegal access, did not use a QVA.
+//
+
+10:
+
+#if DBG
+
+ BREAK_DEBUG_STOP // take a breakpoint
+
+#endif //DBG
+
+ ldil v0, 0xffffffff // return fixed value
+
+ ret zero, (ra) // return to caller
+
+ .end READ_PORT_USHORT
+
+
+ SBTTL( "Read long from PCI memory" )
+//++
+//
+// UCHAR
+// READ_REGISTER_ULONG(
+// IN PVOID RegisterQva
+// )
+//
+// Routine Description:
+//
+// Reads a long location in PCI bus sparse memory space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the memory long to read.
+//
+// Return Value:
+//
+// v0 - Returns the value read from PCI memory.
+//
+//--
+
+ LEAF_ENTRY(READ_REGISTER_ULONG)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 10f // if ne, iff failed
+
+//
+// Sparse space access.
+//
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ and a0, IOD_SPARSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_SPARSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_SPARSE_ENABLE, a0 // clear QVA fields <32:27>
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, IOD_SPARSE_MEM_SVA(zero) // 0xffff ffff ffff cf80
+ sll t4, 28, t4 // 0xffff fcf8 0000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, t4, t0 // superpage mode
+
+ or t0, IO_LONG_LEN, t0 // set size to long
+
+ mb // ensure all writes are visible
+ bis zero, 0xffffffff,v0 // ecrfix
+ ldl v0, (t0) // get the longword
+#if 0 //mdbfix support Canonical ULONG form
+ extll v0, 0, v0 // if NXM, make exception more precise
+#endif
+
+ ret zero, (ra) // return
+
+//
+// Dense space access.
+//
+
+10:
+ zap a0, 0xf0, a0 // clear <63:32>
+ and a0, IOD_DENSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_DENSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_DENSE_ENABLE, a0 // clear QVA fields <31:30>
+ lda t0, IOD_DENSE_MEM_SVA(zero) // 0xffff ffff ffff cf90
+ sll t0, 28, t0 // 0xffff fcf9 0000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, a0, t0 // 0xffff fcf9 xxxx xxxx
+ bis zero, 0xffffffff,v0 // ecrfix
+ ldl v0, 0(t0) // read from dense space
+#if 0 //mdbfix support Canonical ULONG form
+ extll v0, 0, v0 // if NXM, make exception more precise
+#endif
+
+ ret zero, (ra) // return
+
+ .end READ_REGISTER_ULONG
+
+
+ SBTTL( "Read long from PCI sparse I/O" )
+//++
+//
+// UCHAR
+// READ_PORT_ULONG(
+// IN PVOID RegisterQva
+// )
+//
+// Routine Description:
+//
+// Reads a long location in PCI bus sparse i/o space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the i/o long to read.
+//
+// Return Value:
+//
+// v0 - Returns the value read from PCI I/O.
+//
+//--
+
+ LEAF_ENTRY(READ_PORT_ULONG)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get short lane
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 10f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ and a0, IOD_SPARSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_SPARSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_SPARSE_ENABLE, a0 // clear QVA fields <32:27>
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, IOD_SPARSE_IO_SVA(zero) // 0xffff ffff ffff cf80
+ sll t4, 28, t4 // 0xffff fcf8 0000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, t4, t0 // superpage mode
+
+ or t0, IO_LONG_LEN, t0 // set size to short
+
+ bis zero, 0xffffffff,v0 // ecrfix
+
+ mb // ensure all writes are visible
+ ldl v0, (t0) // get the longword
+
+ ret zero, (ra) // return
+
+//
+// Illegal access, did not use a QVA.
+//
+
+10:
+
+#if DBG
+
+ BREAK_DEBUG_STOP // take a breakpoint
+
+#endif //DBG
+
+ ldil v0, 0xffffffff // return fixed value
+
+ ret zero, (ra) // return to caller
+
+ .end READ_PORT_ULONG
+
+
+ SBTTL( "Write byte to PCI memory" )
+//++
+//
+// VOID
+// WRITE_REGISTER_UCHAR(
+// IN PVOID RegisterQva
+// IN UCHAR Value
+// )
+//
+// Routine Description:
+//
+// Write a byte location to PCI bus sparse memory space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the memory byte to write.
+//
+// Value(a1) - Supplies the value written to I/O space.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_REGISTER_UCHAR)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get byte lane
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 10f // if ne, iff failed
+
+//
+// Sparse space access.
+//
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ and a0, IOD_SPARSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_SPARSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_SPARSE_ENABLE, a0 // clear QVA fields <32:27>
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, IOD_SPARSE_MEM_SVA(zero) // 0xffff ffff ffff cf80
+ sll t4, 28, t4 // 0xffff fcf8 0000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, t4, t0 // superpage mode
+
+ insbl a1, t3, v0 // insert to proper byte lane
+ stl v0, (t0) // store the longword
+ mb // order the write
+
+ ret zero, (ra) // return
+
+//
+// Dense space access.
+//
+
+10:
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, 3, a0 // clear byte offset
+ and a0, IOD_DENSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_DENSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_DENSE_ENABLE, a0 // clear QVA fields <31:30>
+ lda t0, IOD_DENSE_MEM_SVA(zero) // 0xffff ffff ffff cf90
+ sll t0, 28, t0 // 0xffff fcf9 0000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, a0, t0 // 0xffff fcf9 xxxx xxxx
+
+ ldl t1, (t0) // get the long
+ mskbl t1, t3, t1 // mask the proper byte
+
+
+ insbl a1, t3, a1 // insert to appropriate byte lane
+ bis a1, t1, a1 // merge byte in result
+ stl a1, (t0) // write to dense space
+ mb // order subsequent reads/writes
+
+ ret zero, (ra) // return
+
+ .end WRITE_REGISTER_UCHAR
+
+
+ SBTTL( "Write byte to PCI sparse i/o" )
+//++
+//
+// VOID
+// WRITE_PORT_UCHAR(
+// IN PVOID RegisterQva
+// IN UCHAR Value
+// )
+//
+// Routine Description:
+//
+// Write a byte location to PCI bus sparse memory space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the memory byte to write.
+//
+// Value(a1) - Supplies the value written to I/O space.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_PORT_UCHAR)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get byte lane
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 10f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ and a0, IOD_SPARSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_SPARSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_SPARSE_ENABLE, a0 // clear QVA fields <32:27>
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, IOD_SPARSE_IO_SVA(zero) // 0xffff ffff ffff cf98
+ sll t4, 28, t4 // 0xffff fcf9 8000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, t4, t0 // superpage mode
+
+ insbl a1, t3, v0 // insert to proper byte lane
+ stl v0, (t0) // store the longword
+ mb // order the write
+
+ ret zero, (ra) // return
+
+//
+// Illegal access, did not use a QVA.
+//
+
+10:
+
+#if DBG
+
+ BREAK_DEBUG_STOP // take a breakpoint
+
+#endif //DBG
+
+ ret zero, (ra) // return to caller
+
+ .end WRITE_PORT_UCHAR
+
+
+ SBTTL( "Write short to PCI memory" )
+//++
+//
+// VOID
+// WRITE_REGISTER_USHORT(
+// IN PVOID RegisterQva
+// IN UCHAR Value
+// )
+//
+// Routine Description:
+//
+// Write a short to PCI bus sparse memory space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the memory short to write.
+//
+// Value(a1) - Supplies the value written to I/O space.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_REGISTER_USHORT)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get short lane
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 10f // if ne, iff failed
+
+//
+// Sparse space access.
+//
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ and a0, IOD_SPARSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_SPARSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_SPARSE_ENABLE, a0 // clear QVA fields <32:27>
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, IOD_SPARSE_MEM_SVA(zero) // 0xffff ffff ffff cf80
+ sll t4, 28, t4 // 0xffff fcf8 0000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, t4, t0 // superpage mode
+
+ or t0, IO_WORD_LEN, t0 // set size to short
+
+ inswl a1, t3, v0 // insert to proper short lane
+ stl v0, (t0) // store the longword
+ mb // order the write
+
+ ret zero, (ra) // return
+
+//
+// Dense space access.
+//
+
+10:
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, 3, a0 // clear byte offset
+ and a0, IOD_DENSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_DENSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_DENSE_ENABLE, a0 // clear QVA fields <31:30>
+ lda t0, IOD_DENSE_MEM_SVA(zero) // 0xffff ffff ffff cf90
+ sll t0, 28, t0 // 0xffff fcf9 0000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ bis t0, a0, t0 // 0xffff fcf9 xxxx xxxx
+ ldl t1, (t0) // get the long
+ mskwl t1, t3, t1 // mask the proper word
+ inswl a1, t3, a1 // insert to appropriate short lane
+ bis a1, t1, a1 // merge in result
+ stl a1, (t0) // write to dense space
+ mb // order subsequent reads/writes
+
+ ret zero, (ra) // return
+
+ .end WRITE_REGISTER_USHORT
+
+
+ SBTTL( "Write short to PCI sparse i/o" )
+//++
+//
+// VOID
+// WRITE_PORT_USHORT(
+// IN PVOID RegisterQva
+// IN UCHAR Value
+// )
+//
+// Routine Description:
+//
+// Write a byte location to PCI bus sparse memory space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the memory byte to write.
+//
+// Value(a1) - Supplies the value written to I/O space.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_PORT_USHORT)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get short lane
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 10f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ and a0, IOD_SPARSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_SPARSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_SPARSE_ENABLE, a0 // clear QVA fields <32:27>
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, IOD_SPARSE_IO_SVA(zero) // 0xffff ffff ffff cf98
+ sll t4, 28, t4 // 0xffff fcf9 8000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, t4, t0 // superpage mode
+
+ or t0, IO_WORD_LEN, t0 // set size to short
+
+ inswl a1, t3, v0 // insert to proper short lane
+ stl v0, (t0) // store the longword
+ mb // order the write
+
+ ret zero, (ra) // return
+
+//
+// Illegal access, did not use a QVA.
+//
+
+10:
+
+#if DBG
+
+ BREAK_DEBUG_STOP // take a breakpoint
+
+#endif //DBG
+
+ ret zero, (ra) // return to caller
+
+ .end WRITE_PORT_USHORT
+
+
+
+ SBTTL( "Write long to PCI memory" )
+//++
+//
+// VOID
+// WRITE_REGISTER_ULONG(
+// IN PVOID RegisterQva
+// IN UCHAR Value
+// )
+//
+// Routine Description:
+//
+// Write a long to PCI bus sparse memory space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the memory long to write.
+//
+// Value(a1) - Supplies the value written to I/O space.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_REGISTER_ULONG)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 10f // if ne, iff failed
+
+//
+// Sparse space access.
+//
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ and a0, IOD_SPARSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_SPARSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_SPARSE_ENABLE, a0 // clear QVA fields <32:27>
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, IOD_SPARSE_MEM_SVA(zero) // 0xffff ffff ffff cf80
+ sll t4, 28, t4 // 0xffff fcf8 0000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, t4, t0 // superpage mode
+
+ or t0, IO_LONG_LEN, t0 // set size to long
+
+ stl a1, (t0) // store the longword
+ mb // order the write
+
+ ret zero, (ra) // return
+
+//
+// Dense space access.
+//
+
+10:
+ zap a0, 0xf0, a0 // clear <63:32>
+ and a0, IOD_DENSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_DENSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_DENSE_ENABLE, a0 // clear QVA fields <31:30>
+ lda t0, IOD_DENSE_MEM_SVA(zero) // 0xffff ffff ffff cf90
+ sll t0, 28, t0 // 0xffff fcf9 0000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, a0, t0 // 0xffff fcf9 xxxx xxxx
+ stl a1, 0(t0) // write to dense space
+ mb // order subsequent reads/writes
+
+ ret zero, (ra) // return
+
+ .end WRITE_REGISTER_ULONG
+
+
+ SBTTL( "Write long to PCI sparse i/o" )
+//++
+//
+// VOID
+// WRITE_PORT_ULONG(
+// IN PVOID RegisterQva
+// IN UCHAR Value
+// )
+//
+// Routine Description:
+//
+// Write a long to PCI bus sparse memory space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the I/O long to write.
+//
+// Value(a1) - Supplies the value written to I/O space.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_PORT_ULONG)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 10f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ and a0, IOD_SPARSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_SPARSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_SPARSE_ENABLE, a0 // clear QVA fields <32:27>
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, IOD_SPARSE_IO_SVA(zero) // 0xffff ffff ffff cf98
+ sll t4, 28, t4 // 0xffff fcf9 8000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, t4, t0 // superpage mode
+
+ or t0, IO_LONG_LEN, t0 // set size to long
+
+ stl a1, (t0) // store the longword
+ mb // order the write
+
+ ret zero, (ra) // return
+
+//
+// Illegal access, did not use a QVA.
+//
+
+10:
+
+#if DBG
+
+ BREAK_DEBUG_STOP // take a breakpoint
+
+#endif //DBG
+
+ ret zero, (ra) // return to caller
+
+ .end WRITE_PORT_ULONG
+
+
+ SBTTL( "Write IOD Register" )
+//++
+//
+// VOID
+// WRITE_IOD_REGISTER(
+// IN PVOID RegisterQva,
+// IN ULONG Value
+// )
+//
+// Routine Description:
+//
+// Write an IOD control register.
+//
+// Arguments:
+//
+// RegisterQva(a0) - QVA of control register to be written.
+//
+// Value(a1) - Longword value to be written to the control register.
+//
+// Return Value:
+//
+// None.
+//
+// N.B. Since the physical address of the IOD CSRS exceed the 34 bit
+// capacity of the QVAs, the QVA values of the IOD CSRS specify
+// the offset of the QVAs from the IOD CSR base address (89.e000.0000)
+//--
+
+ LEAF_ENTRY(WRITE_IOD_REGISTER)
+
+ ALTERNATE_ENTRY(WRITE_GRU_REGISTER)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 10f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 //
+ lda t4, IOD_REGISTER_SVA(zero) // 0xffff ffff ffff cf9e
+ sll t4, 28, t4 // 0xffff fcf9 e000 0000
+ or t0, t4, t0 // superpage mode
+ stl a1, (t0) // write the longword
+ mb // order the write
+ ret zero, (ra) // return
+
+10:
+ BREAK_DEBUG_STOP // take a breakpoint
+ ret zero, (ra) // return
+
+ .end WRITE_IOD_REGISTER
+
+
+ SBTTL( "Read IOD Register" )
+//++
+//
+// ULONG
+// READ_IOD_REGISTER(
+// IN PVOID RegisterQva
+// )
+//
+// Routine Description:
+//
+// Read an IOD Control register
+//
+// Arguments:
+//
+// RegisterQva(a0) - QVA of control register to be written.
+//
+// Return Value:
+//
+// v0 - Return the value read from the control register.
+//
+//--
+
+ LEAF_ENTRY(READ_IOD_REGISTER)
+
+//
+// Generate the superpage address of the requested IOD register.
+//
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 20f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 //
+ lda t4, IOD_REGISTER_SVA(zero) // 0xffff ffff ffff cf9e
+ sll t4, 28, t4 // 0xffff fcf9 e000 0000
+ or t0, t4, t0 // superpage mode
+
+//
+// Perform the read of the requested IOD register and return.
+//
+
+ ldl v0, (t0) // read the register
+
+ ret zero, (ra) // return
+
+//
+// The requested IOD register address is bogus. Stop in the debugger so
+// we can find the culprit.
+//
+
+20: // flag bad QVAs
+ BREAK_DEBUG_STOP // take a breakpoint
+
+ ret zero, (ra) // return
+
+ .end READ_IOD_REGISTER
+
+
+ SBTTL( "Write IOD Register_New" )
+//++
+//
+// VOID
+// WRITE_IOD_REGISTER_NEW(
+// IN ULONG McDevid
+// IN PVOID RegisterQva,
+// IN ULONG Value
+// )
+//
+// Routine Description:
+//
+// Write a IOD control register.
+//
+// Arguments:
+//
+// McDevid(a0) - MC Bus Device ID of this IOD
+//
+// RegisterQva(a1) - Qva of control register to be written.
+// N.B. RegisterQva *does not* specifiy which IOD to write to.
+// That's why we pass in McDevid
+//
+// Value(a2) - Longword value to be written to the control register.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_IOD_REGISTER_NEW)
+
+//
+// Generate the superpage address of the requested IOD register.
+//
+
+ // Args are actually byte values:
+ and a1, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 10f // if ne, iff failed
+
+ zap a1, 0xf0, a1 // clear <63:32>
+ bic a1, QVA_ENABLE, a1 // clear QVA fields so shift is correct
+ sll a1, IO_BIT_SHIFT, t4 // shift RegisterOffset into position
+
+ extbl a0, zero, a0 // McDevId
+
+ lda t0, IOD_REGISTER_NEW_SVA(zero) // 0xffff ffff ffff c800
+ sll a0, 5, t1 // shift McDevId into position
+ bis t0, t1, t0 // create SVA for this IOD
+ sll t0, 28, t0 // 0xffff fcXX 0000 0000
+
+ or t0, t4, t0 // superpage mode
+ stl a2, (t0) // write the longword
+ mb // order the write
+ ret zero, (ra) // return
+
+//
+// The requested IOD register address is bogus. Stop in the debugger so
+// we can find the culprit.
+//
+
+10:
+ BREAK_DEBUG_STOP // take a breakpoint
+ ret zero, (ra) // return
+
+ .end WRITE_IOD_REGISTER_NEW
+
+
+ SBTTL( "Read IOD Register_NEW" )
+//++
+//
+// ULONG
+// READ_IOD_REGISTER_NEW(
+// IN ULONG McDevid
+// IN ULONG RegisterOffset
+// )
+//
+// Routine Description:
+//
+// Read an IOD Control register
+//
+// Arguments:
+//
+// McDevid(a0) - MC Bus Device ID of this IOD.
+//
+// RegisterQva(a1) - QVA of control register to be read.
+//
+// Return Value:
+//
+// v0 - Return the value read from the control register.
+//
+//--
+
+ LEAF_ENTRY(READ_IOD_REGISTER_NEW)
+
+//
+// Generate the superpage address of the requested IOD register.
+//
+
+ and a1, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 10f // if ne, iff failed
+
+ zap a1, 0xf0, a1 // clear <63:32>
+ bic a1, QVA_ENABLE, a1 // clear QVA fields so shift is correct
+ sll a1, IO_BIT_SHIFT, t4 // shift RegisterQva into position
+
+ extbl a0, zero, a0 // McDevId
+
+ lda t0, IOD_REGISTER_NEW_SVA(zero) // 0xffff ffff ffff c800
+ sll a0, 5, t1 // shift McDevId into position
+ bis t0, t1, t0 // create SVA for this IOD
+ sll t0, 28, t0 // 0xffff fcXX 0000 0000
+
+ or t0, t4, t0 // superpage mode
+
+//
+// Perform the read of the requested IOD register and return.
+//
+
+ ldl v0, (t0) // read the register
+
+ ret zero, (ra) // return
+
+//
+// The requested IOD register address is bogus. Stop in the debugger so
+// we can find the culprit.
+//
+
+10:
+ BREAK_DEBUG_STOP // take a breakpoint
+ ret zero, (ra) // return
+
+ .end READ_IOD_REGISTER_NEW
+
+
+ SBTTL( "Read Buffer from Port Space in Uchars")
+//++
+//
+// VOID
+// READ_PORT_BUFFER_UCHAR(
+// IN PVOID PortQva,
+// IN PUCHAR Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Read multiple bytes from the specified port address into the
+// destination buffer.
+//
+// Arguments:
+//
+// PortQva(a0) - Supplies the QVA of the port to read.
+//
+// Buffer(a1) - Supplies a pointer to the buffer to fill with
+// the data read from the port.
+//
+// Count(a2) - Supplies the number of bytes to read.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(READ_PORT_BUFFER_UCHAR)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 30f // if ne, iff failed
+
+ and a0, 3, t3 // get byte we need if eisa
+ zap a0, 0xf0, a0 // clear <63:32>
+ and a0, IOD_SPARSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_SPARSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_SPARSE_ENABLE, a0 // clear QVA fields <32:27>
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, IOD_SPARSE_IO_SVA(zero) // 0xffff ffff ffff cf98
+ sll t4, 28, t4 // 0xffff fcf9 8000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, t4, t0 // superpage mode
+
+10: beq a2, 20f // while count > 0
+
+ ldl v0, (t0) // get the longword
+ subl a2, 1, a2 // decrement count
+ extbl v0,t3,v0 // get the correct byte
+ stb v0,(a1) // cheat and let the assembler do it
+ addl a1, 1, a1 // next byte in buffer
+ br zero, 10b // end while
+20:
+ ret zero, (ra) // return
+
+//
+// Illegal access, did not use a QVA.
+//
+
+30:
+
+#if DBG
+
+ BREAK_DEBUG_STOP // take a breakpoint
+
+#endif //DBG
+
+ ldil v0, 0xffffffff // return fixed value
+
+ ret zero, (ra) // return to caller
+
+ .end READ_PORT_BUFFER_UCHAR
+
+
+ SBTTL( "Read Buffer from Port Space in Ushorts")
+//++
+//
+// VOID
+// READ_PORT_BUFFER_USHORT(
+// IN PVOID PortQva,
+// IN PUSHORT Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Read multiple words from the specified port address into the
+// destination buffer.
+//
+// Arguments:
+//
+// PortQva(a0) - Supplies the QVA of the port to read.
+//
+// Buffer(a1) - Supplies a pointer to the buffer to fill with
+// the data read from the port.
+//
+// Count(a2) - Supplies the number of words to read.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(READ_PORT_BUFFER_USHORT)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 30f // if ne, iff failed
+
+ and a0, 3, t3 // get word we need
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ and a0, IOD_SPARSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_SPARSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_SPARSE_ENABLE, a0 // clear QVA fields <32:27>
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, IOD_SPARSE_IO_SVA(zero) // 0xffff ffff ffff cf98
+ sll t4, 28, t4 // 0xffff fcf9 8000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, t4, t0 // superpage mode
+ or t0, IO_WORD_LEN, t0 // or in the byte enables
+
+10: beq a2, 20f // while count > 0
+
+ ldl v0, (t0) // get the longword
+ subl a2, 1, a2 // decrement count
+ extwl v0,t3,v0 // get the correct word
+ stw v0,(a1) // cheat and let the assembler do it
+ addl a1, 2, a1 // next word in buffer
+ br zero, 10b // end while
+20:
+ ret zero, (ra) // return
+
+//
+// Illegal access, did not use a QVA.
+//
+
+30:
+
+#if DBG
+
+ BREAK_DEBUG_STOP // take a breakpoint
+
+#endif //DBG
+
+ ldil v0, 0xffffffff // return fixed value
+
+ ret zero, (ra) // return to caller
+
+ .end READ_PORT_BUFFER_USHORT
+
+ SBTTL( "Read Buffer from Port Space in Ulongs")
+//++
+//
+// VOID
+// READ_PORT_BUFFER_ULONG(
+// IN PVOID PortQva,
+// IN PULONG Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Read multiple longwords from the specified port address into the
+// destination buffer.
+//
+// Arguments:
+//
+// PortQva(a0) - Supplies the QVA of the port to read.
+//
+// Buffer(a1) - Supplies a pointer to the buffer to fill with
+// the data read from the port.
+//
+// Count(a2) - Supplies the number of longwords to read.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(READ_PORT_BUFFER_ULONG)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 30f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ and a0, IOD_SPARSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_SPARSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_SPARSE_ENABLE, a0 // clear QVA fields <32:27>
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+
+ lda t4, IOD_SPARSE_IO_SVA(zero) // 0xffff ffff ffff cf98
+ sll t4, 28, t4 // 0xffff fcf9 8000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, t4, t0 // superpage mode
+ or t0, IO_LONG_LEN, t0 // or in the byte enables
+
+10: beq a2, 20f // while count > 0
+
+ ldl v0, (t0) // get the longword
+ subl a2, 1, a2 // decrement count
+ stl v0,(a1) // cheat and let the assembler do it
+ addl a1, 4, a1 // next word in buffer
+ br zero, 10b // end while
+20:
+ ret zero, (ra) // return
+
+//
+// Illegal access, did not use a QVA.
+//
+
+30:
+
+#if DBG
+
+ BREAK_DEBUG_STOP // take a breakpoint
+
+#endif //DBG
+
+ ldil v0, 0xffffffff // return fixed value
+
+ ret zero, (ra) // return to caller
+
+ .end READ_PORT_BUFFER_ULONG
+
+
+ SBTTL( "Write Buffer to Port Space in Uchars")
+//++
+//
+// VOID
+// WRITE_PORT_BUFFER_UCHAR(
+// IN PVOID PortQva,
+// IN PUCHAR Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Write multiple bytes from the source buffer to the specified port
+// address.
+//
+// Arguments:
+//
+// PortQva(a0) - Supplies the QVA of the port to write.
+//
+// Buffer(a1) - Supplies a pointer to the buffer containing the data
+// to write to the port.
+//
+// Count(a2) - Supplies the number of bytes to write.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_PORT_BUFFER_UCHAR)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 30f // if ne, iff failed
+
+ and a0, 3, t3 // get byte we need if eisa
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ and a0, IOD_SPARSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_SPARSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_SPARSE_ENABLE, a0 // clear QVA fields <32:27>
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, IOD_SPARSE_IO_SVA(zero) // 0xffff ffff ffff cf98
+ sll t4, 28, t4 // 0xffff fcf9 8000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, t4, t0 // superpage mode
+
+10: beq a2, 20f // copy while a2 > 0
+
+ ldq_u t1, 0(a1) // get quad surrounding byte
+ subl a2, 1, a2 // decrement count
+ extbl t1, a1, t1 // extract appropriate byte
+ addl a1, 1, a1 // increment buffer pointer
+ insbl t1, t3, t1 // put byte to appropriate lane
+ stl t1, 0(t0) // store to port
+ mb // push writes off chip
+ br zero, 10b // end while
+
+20:
+ ret zero, (ra) // return
+
+//
+// Illegal access, did not use a QVA.
+//
+
+30:
+
+#if DBG
+
+ BREAK_DEBUG_STOP // take a breakpoint
+
+#endif //DBG
+
+ ret zero, (ra) // return to caller
+
+
+ .end WRITE_PORT_BUFFER_UCHAR
+
+ SBTTL( "Write Buffer to Port Space in Ushorts")
+//++
+//
+// VOID
+// WRITE_PORT_BUFFER_USHORT(
+// IN PVOID PortQva,
+// IN PSHORT Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Write multiple words from the source buffer to the specified port
+// address.
+//
+// Arguments:
+//
+// PortQva(a0) - Supplies the QVA of the port to write.
+//
+// Buffer(a1) - Supplies a pointer to the buffer containing the data
+// to write to the port.
+//
+// Count(a2) - Supplies the number of words to write.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_PORT_BUFFER_USHORT)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 30f // if ne, iff failed
+
+ and a0, 3, t3 // get word we need
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ and a0, IOD_SPARSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_SPARSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_SPARSE_ENABLE, a0 // clear QVA fields <32:27>
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, IOD_SPARSE_IO_SVA(zero) // 0xffff ffff ffff cf98
+ sll t4, 28, t4 // 0xffff fcf9 8000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, t4, t0 // superpage mode
+ or t0, IO_WORD_LEN, t0 // or in the byte enables
+
+10: beq a2, 20f // copy while a2 > 0
+
+ ldq_u t1, 0(a1) // get quad surrounding word
+ subl a2, 1, a2 // decrement count
+ extwl t1, a1, t1 // extract appropriate word
+ addl a1, 2, a1 // increment buffer pointer
+ inswl t1, t3, t1 // put word in appropriate lane
+ stl t1, 0(t0) // store to port
+ mb // push the write off the chip
+ br zero, 10b // end while
+
+20:
+ ret zero, (ra) // return
+
+//
+// Illegal access, did not use a QVA.
+//
+
+30:
+
+#if DBG
+
+ BREAK_DEBUG_STOP // take a breakpoint
+
+#endif //DBG
+
+ ret zero, (ra) // return to caller
+
+ .end WRITE_PORT_BUFFER_USHORT
+
+
+ SBTTL( "Write Buffer to Port Space in Ulongs")
+//++
+//
+// VOID
+// WRITE_PORT_BUFFER_ULONG(
+// IN PVOID PortQva,
+// IN PULONG Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Write multiple longwords from the source buffer to the specified port
+// address.
+//
+// Arguments:
+//
+// PortQva(a0) - Supplies the QVA of the port to write.
+//
+// Buffer(a1) - Supplies a pointer to the buffer containing the data
+// to write to the port.
+//
+// Count(a2) - Supplies the number of longwords to write.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_PORT_BUFFER_ULONG)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 30f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ and a0, IOD_SPARSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_SPARSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_SPARSE_ENABLE, a0 // clear QVA fields <32:27>
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, IOD_SPARSE_IO_SVA(zero) // 0xffff ffff ffff cf98
+ sll t4, 28, t4 // 0xffff fcf9 8000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, t4, t0 // superpage mode
+ or t0, IO_LONG_LEN, t0 // or in the byte enables
+
+10: beq a2, 20f // copy while a2 > 0
+
+ ldl t1, 0(a1) // a1 must be longword aligned
+ subl a2, 1, a2 // decrement count
+ stl t1, 0(t0) // store to port
+ mb // push write off the chip
+ addl a1, 4, a1 // increment buffer
+ br zero, 10b // end while
+
+20:
+ ret zero, (ra) // return
+
+//
+// Illegal access, did not use a QVA.
+//
+
+30:
+
+#if DBG
+
+ BREAK_DEBUG_STOP // take a breakpoint
+
+#endif //DBG
+
+ ret zero, (ra) // return to caller
+
+ .end WRITE_PORT_BUFFER_ULONG
+
+
+ SBTTL( "Read Buffer from PCI Memory Space in Uchars")
+//++
+//
+// VOID
+// READ_REGISTER_BUFFER_UXXXXX(
+// IN PVOID RegisterQva,
+// IN PUCHAR Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Copies a buffer from PCI Memory Space to an in-memory buffer.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the starting QVA of the memory space buffer.
+//
+// Buffer(a1) - Supplies a pointer to the in-memory buffer to receive
+// the copied data.
+//
+// Count(a2) - Supplies the number of bytes, words or longwords to write.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(READ_REGISTER_BUFFER_ULONG)
+
+ sll a2, 1, a2 // convert number of longs to words
+
+ ALTERNATE_ENTRY(READ_REGISTER_BUFFER_USHORT)
+
+
+ sll a2, 1, a2 // convert number of words to chars
+
+ ALTERNATE_ENTRY(READ_REGISTER_BUFFER_UCHAR)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ beq t1, 1f // if (eq) go do sparse space
+
+//
+// Dense space access: QVA is an offset into dense space
+// Set IO address in t0
+//
+ zap a0, 0xf0, a0 // clear <63:32>
+ and a0, IOD_DENSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_DENSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_DENSE_ENABLE, a0 // clear QVA fields <31:30>
+ lda t0, IOD_DENSE_MEM_SVA(zero) // 0xffff ffff ffff cf90
+ sll t0, 28, t0 // 0xffff fcf9 0000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or a0, t0, t0 // superpage mode: add offset to base
+
+ ldil a3, 1 // Offset to next byte
+ ldil a4, 4 // Offset to next long
+ ldil a5, 0 // LONG LEN ENABLE
+
+ br zero 2f // go do the actual transfer
+
+//
+// Sparse memory
+// Set IO address in t0
+//
+
+1:
+ zap a0, 0xf0, a0 // clear <63:32>
+ and a0, IOD_SPARSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_SPARSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_SPARSE_ENABLE, a0 // clear QVA fields <32:27>
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, IOD_SPARSE_MEM_SVA(zero) // 0xffff ffff ffff cf80
+ sll t4, 28, t4 // 0xffff fcf8 0000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, t4, t0 // superpage mode
+
+ ldil a3, IO_BYTE_OFFSET // Offset to next byte
+ ldil a4, IO_LONG_OFFSET // Offset to next long
+ ldil a5, IO_LONG_LEN // LONG LEN ENABLE
+
+//
+// Do the ACTUAL TRANSFER
+// a2 = count in characters
+//
+
+2:
+ beq a2, 60f // if count == 0 goto 60f (return)
+
+//
+// Check alignment of src and destn
+//
+
+ and a0, 3, t3 // source alignment = t3
+ and a1, 3, t2 // destination alignment = t2
+ xor t2, t3, t4 // t4 = t2 xor t3
+ bne t4, 70f // if (t4!=0) do unaligned copy
+ // else do byte copies till alignment
+
+ beq t3, 20f // if t3==0 go do long word copies
+ // else do byte copies till alignment
+
+//
+// Src and Destn are not longword aligned but have same alignment
+// (sympathetically aligned) copy till alignment
+//
+
+10:
+ beq a2, 60f // if count == 0 goto 60f (return)
+
+ bis zero, 0xffffffff,v0 // ecrfix
+ ldl v0, 0(t0) // get the longword
+ subl a2, 1, a2 // decrement count
+ extbl v0, t3,v0 // get the correct byte
+ stb v0, (a1) // cheat and let the assembler do it
+ addq t0, a3, t0 // next I/O address
+ addl a1, 1, a1 // next byte in buffer
+ addl t3, 1, t3 // next byte in lane
+ and t3, 3, t3 // longword lanes
+ bne t3, 10b // while unaligned
+
+//
+// Src and Destn have same alignment and are longword aligned
+//
+
+20:
+ srl a2, 2, t3 // t3= #longwords to move
+ beq t3, 40f // if #longwords == 0 goto 40f
+ or t0, a5, t0 // We will now do LONG READS
+
+30:
+ bis zero, 0xffffffff,v0 // ecrfix
+ ldl v0, 0(t0) // get the longword
+ subl t3, 1, t3 // decrement long word count
+ stl v0, (a1) // store the longword at destn
+ addq t0, a4, t0 // next I/O address
+ addl a1, 4, a1 // next longword in buffer
+ bne t3, 30b // while #longwords > 0
+
+//
+// Do byte copies of remaining data uncopied
+//
+ bic t0, a5, t0 // We will now do BYTE READS
+40:
+ and a2, 3, a2 // remaining Bytes to copy
+ beq a2, 60f // if count == 0 goto 60f
+
+50:
+ bis zero, 0xffffffff,v0 // ecrfix
+ ldl v0, 0(t0) // get the longword
+ subl a2, 1, a2 // decrement count
+ extbl v0, t3,v0 // get the correct byte
+ stb v0, (a1) // cheat and let the assembler do it
+ addl a1, 1, a1 // next byte in buffer
+ addq t0, a3, t0 // next I/O address
+ addl t3, 1, t3 // next byte in lane
+ and t3, 3, t3 // longword lanes
+ bne a2, 50b // while count > 0
+
+60:
+ ret zero, (ra) // return
+
+
+//
+// source IO alignment != destination memory alignment
+// move enough bytes to longword align the IO source
+// then move 32bit (longwords) storing unaligned into memory
+// then move residual bytes
+//
+// Align src IO addresses; unaligned destn memory
+//
+
+70:
+ beq t3, 90f // branch if source is long aligned
+//
+// Move bytes until IO src is at a longword boundary or bytes exhausted
+//
+
+80:
+ beq a2, 130f // if count == 0 goto 130f (return)
+
+ bis zero, 0xffffffff,v0 // ecrfix
+ ldl v0, 0(t0) // get the longword
+ subl a2, 1, a2 // decrement count
+ extbl v0, t3,v0 // get the correct byte
+ stb v0, (a1) // cheat and let the assembler do it
+ addl a1, 1, a1 // next byte in buffer
+ addq t0, a3, t0 // next I/O address
+ addl t3, 1, t3 // next byte in lane
+ and t3, 3, t3 // longword lanes
+ bne t3, 80b // while unaligned
+
+//
+// aligned IO source, unaligned memory destination
+//
+
+90:
+ srl a2, 3, t3 // quadwords to move
+ beq t3, 110f // if no quads finish with bytes copies
+
+ or t0, a5, t0 // We will now do LONG READS
+
+100:
+ //
+ // Decoding for Comment:
+ // S= sign, X= overwritten byte, V= Valid byte,assume destn align a1= 2
+ //
+ bis zero, 0xffffffff,t1 // ecrfix
+ ldl t1, 0(t0) // load LW 0 from IO src SSSS 4321
+ ldq_u t4, 0(a1) // load destn merge XXVV VVVV
+ ldq_u t5, 7(a1) // load destn next merge VVXX XXXX
+ subl t3, 1, t3 // decrement quadwords to move
+
+ addq t0, a4, t0 // add LONG OFFSET to t0
+ bis zero, 0xffffffff,t2 // ecrfix
+ ldl t2, 0(t0) // load LW 1 from IO src SSSS 8765
+
+ mskql t4, a1, t4 // mask low LW for merge 00VV VVVV
+ mskqh t5, a1, t5 // mask high LW for merge VV00 0000
+
+ zap t1, 0xf0, t1 // clear high LW for long 0 0000 4321
+ sll t2, 32, t2 // get long 1 to high longword 8765 0000
+ bis t1, t2, t1 // merge read quadword together8765 4321
+
+ addq t0, a4, t0 // increment to next long
+
+ insql t1, a1, t6 // position low QW for merge 2100 0000
+ insqh t1, a1, t7 // position high QW for merge 0087 6543
+
+ bis t4, t6, t4 // merge new data, low QW 21VV VVVV
+ bis t5, t7, t5 // merge new data, high QW VV87 6543
+
+ stq_u t5, 7(a1) // write high quadword
+ stq_u t4, 0(a1) // write low quadword
+
+ lda a1, 8(a1) // increment memory pointer
+ bne t3, 100b // while quadwords to move
+
+//
+// Do byte copies of the remaining data not yet copied
+//
+ bic t0, a5, t0 // We will now do BYTE READS
+110:
+ and a2, 7, a2 // remaining bytes to copy
+ beq a2, 130f // if count == 0 goto 130f (return)
+
+120:
+ bis zero, 0xffffffff,v0 // ecrfix
+ ldl v0, 0(t0) // get the longword
+ subl a2, 1, a2 // decrement count
+ extbl v0, t3,v0 // get the correct byte
+ stb v0, (a1) // cheat and let the assembler do it
+ addl a1, 1, a1 // next byte in buffer
+ addq t0, a3, t0 // next I/O address
+ addl t3, 1, t3 // next byte in lane
+ and t3, 3, t3 // longword lanes
+ bne a2, 120b // while count != 0
+
+130:
+ ret zero, (ra) // return
+
+ .end READ_REGISTER_BUFFER_ULONG // end for UCHAR & USHORT
+
+
+ SBTTL( "Write Buffer to PCI Memory Space in Uchars")
+//++
+//
+// VOID
+// WRITE_REGISTER_BUFFER_UXXXXX(
+// IN PVOID RegisterQva,
+// IN PUCHAR Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Copies an in-memory buffer to a PCI Memory Space buffer.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the starting QVA of the memory space buffer.
+//
+// Buffer(a1) - Supplies a pointer to the in-memory source buffer.
+//
+// Count(a2) - Supplies the number of bytes, words to longwords to write.
+//
+// Return Value:
+//
+// None.
+//
+//--
+ LEAF_ENTRY(WRITE_REGISTER_BUFFER_ULONG)
+
+ sll a2, 1, a2 // convert number of longs to words
+
+ ALTERNATE_ENTRY(WRITE_REGISTER_BUFFER_USHORT)
+
+ sll a2, 1, a2 // convert number of words to chars
+
+ ALTERNATE_ENTRY(WRITE_REGISTER_BUFFER_UCHAR)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ beq t1, 1f // if (eq) go do sparse space
+
+//
+// Dense space access: QVA is an offset into dense space
+// Set IO address in t0
+//
+
+ ldil t7, 1 // DENSE FLAG
+ zap a0, 0xf0, a0 // clear <63:32>
+ and a0, IOD_DENSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_DENSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_DENSE_ENABLE, a0 // clear QVA fields <31:30>
+ lda t0, IOD_DENSE_MEM_SVA(zero) // 0xffff ffff ffff cf90
+ sll t0, 28, t0 // 0xffff fcf9 0000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or a0, t0, t0 // superpage mode: add offset to base
+
+ ldil a3, 1 // Offset to next byte
+ ldil a4, 4 // Offset to next long
+ ldil a5, 0 // LONG LEN ENABLE
+
+ br zero, 2f // go do the actual transfer
+
+//
+// Sparse Space
+// Set IO address in t0
+//
+
+1:
+ ldil t7, 0 // SPARSE FLAG
+ zap a0, 0xf0, a0 // clear <63:32>
+ and a0, IOD_SPARSE_SELECTORS, t2 // get BusNum from QVA
+ sll t2, IOD_SPARSE_BUS_SHIFT, t2 // put BusNum into MID position
+
+ bic a0, IOD_SPARSE_ENABLE, a0 // clear QVA fields <32:27>
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ lda t4, IOD_SPARSE_MEM_SVA(zero) // 0xffff ffff ffff cf80
+ sll t4, 28, t4 // 0xffff fcf8 0000 0000
+ or t0, t2, t0 // add BusNum in MID field
+ or t0, t4, t0 // superpage mode
+
+ ldil a3, IO_BYTE_OFFSET // Offset to next byte
+ ldil a4, IO_LONG_OFFSET // Offset to next long
+ ldil a5, IO_LONG_LEN // LONG LEN ENABLE
+
+//
+// Do the ACTUAL TRANSFER
+// a2 = count in characters
+//
+
+2:
+ beq a2, 60f // if count == 0 goto 60f (return)
+
+//
+// Check alignment of src and destn
+//
+ and a0, 3, t3 // destn alignment = t3
+ and a1, 3, t2 // src alignment = t2
+ xor t2, t3, t4 // t4 = t2 xor t3
+ bne t4, 70f // if (t4!=0) do unaligned copy
+ // else do byte copies till alignment
+
+ beq t3, 20f // if t3==0 go do longword copies
+ // else do byte copies till alignment
+
+//
+// Src and Destn are not longword aligned but have same alignment
+// (sympathetically aligned) copy till alignment
+//
+
+10:
+ beq a2, 60f // if count == 0 goto 60f (return)
+
+ ldq_u t1, 0(a1) // get quad surrounding byte
+ subl a2, 1, a2 // decrement count
+ extbl t1, a1, t1 // extract appropriate byte
+ addl a1, 1, a1 // increment buffer pointer
+ insbl t1, t3, t1 // get proper lane
+
+ beq t7, 11f // if not DENSE goto 11f
+
+//
+// Read\modify\write for DENSE space I/O
+//
+ bic t0, 3, t9 // clear bits <1:0> of dest
+ ldl t10, 0(t9) // read dest long
+ mskbl t10, t3, t10 // poke out the byte we will write
+ bis t10, t1, t1 // merge in our byte
+ stl t1, 0(t9) // commit it
+
+ br zero, 12f
+
+//
+// We're in SPARSE space, so simply perform the write
+//
+11:
+ stl t1, 0(t0) // store byte to buffer (BYTE ENABLED)
+12:
+ addq t0, a3, t0 // increment I/O buffer
+ addl t3, 1, t3 // increment bytelane
+ and t3, 3, t3 // longwords only
+ bne t3, 10b // loop while not long aligned
+
+//
+// Src and Destn have same alignment and are longword aligned
+//
+
+20:
+ srl a2, 2, t3 // t3= #longwords to move
+ beq t3, 40f // if #longwords == 0 goto 40f
+ or t0, a5, t0 // We will now do LONG WRITE
+
+30:
+ ldl t1, 0(a1) // get the longword
+ addl a1, 4, a1 // increment buffer pointer
+ subl t3, 1, t3 // decrement #longwords by 1
+ stl t1, 0(t0) // store long to buffer
+ addq t0, a4, t0 // increment I/O buffer
+ bne t3, 30b // while #longwords > 0
+
+//
+// Do byte copies of remaining data uncopied
+//
+ bic t0, a5, t0 // Stop doing LONG WRITE
+
+40:
+ and a2, 3, a2 // remaining Bytes to copy
+ beq a2, 60f // if count == 0 goto 60f (return)
+
+50:
+ ldq_u t1, 0(a1) // get quad surrounding byte
+ subl a2, 1, a2 // decrement count
+ extbl t1, a1, t1 // extract appropriate byte
+ addl a1, 1, a1 // increment buffer pointer
+ insbl t1, t3, t1 // get proper lane
+
+ beq t7, 51f // if not DENSE goto 51f
+
+//
+// Read\modify\write for DENSE space I/O
+//
+ bic t0, 3, t9 // clear bits <1:0> of dest
+ ldl t10, 0(t9) // read dest long
+ mskbl t10, t3, t10 // poke out the byte we will write
+ bis t10, t1, t1 // merge in our byte
+ stl t1, 0(t9) // commit it
+
+ br zero, 52f
+
+//
+// We're in SPARSE space, so simply perform the write
+//
+51:
+ stl t1, 0(t0) // store to buffer
+52:
+ addq t0, a3, t0 // increment I/O buffer
+ addl t3, 1, t3 // increment bytelane
+ and t3, 3, t3 // longwords only
+ bne a2, 50b // while count != 0
+
+60:
+ mb // push writes off chip
+ ret zero, (ra) // return
+
+//
+// destn IO alignment != Src memory alignment
+// move enough bytes to longword align the IO destn
+// then move 32bit (longwords) reading unaligned data from memory
+// then move residual bytes
+//
+
+70:
+ beq t3, 90f // branch if destn is long aligned
+
+//
+// Move bytes until IO destn is at a longword boundary or bytes exhausted
+//
+
+80:
+ beq a2, 130f // if count == 0 goto 130f (return)
+
+ ldq_u t1, 0(a1) // get quad surrounding byte
+ extbl t1, a1, t1 // extract appropriate byte
+ insbl t1, t3, t1 // get proper lane
+
+ beq t7, 81f // if not DENSE goto 81f
+
+//
+// Read\modify\write for DENSE space I/O
+//
+ bic t0, 3, t9 // clear bits <1:0> of dest
+ ldl t10, 0(t9) // read dest long
+ mskbl t10, t3, t10 // poke out the byte we will write
+ bis t10, t1, t1 // merge in our byte
+ stl t1, 0(t9) // commit it
+
+ br zero, 82f
+
+//
+// We're in SPARSE space, so simply perform the write
+//
+81:
+ stl t1, 0(t0) // store byte to buffer (BYTE ENABLED)
+82:
+ subl a2, 1, a2 // decrement count
+ addl a1, 1, a1 // increment buffer pointer
+ addq t0, a3, t0 // increment I/O buffer
+ addl t3, 1, t3 // increment bytelane
+ and t3, 3, t3 // longwords only
+ bne t3, 80b // loop if not long aligned
+
+//
+// aligned IO destn, unaligned memory src
+//
+
+90:
+ srl a2, 3, t3 // t3 = quadwords to move
+ beq t3, 110f // if no quads finish with bytes copies
+
+ or t0, a5, t0 // We will now do LONG WRITES
+
+100:
+ ldq_u t1, 0(a1) // load low source quadword
+ ldq_u t2, 7(a1) // load high source quadword
+ extql t1, a1, t1 // extract low portion of quadword
+ extqh t2, a1, t2 // extract high portion of quadword
+ or t1, t2, t1 // merge to get the source quadword
+ stl t1, 0(t0) // store the long word (LONG ENABLED)
+
+ lda a1, 8(a1) // next source quadword
+ srl t1, 32, t1 // get high longword into position
+ subl t3, 1, t3 // decrement number of quadwords to move
+ addq t0, a4, t0 // add LONG OFFSET to t0
+ stl t1, (t0) // store the second long word
+
+ addq t0, a4, t0 // increment to next dest. long
+ bne t3, 100b // while quadwords to move
+//
+// Do byte copies of the remaining data not yet copied
+//
+ bic t0, a5, t0 // We will now do BYTE WRITES
+110:
+ and a2, 7, a2 // remaining Bytes to copy
+ beq a2, 130f // if count == 0 goto 130f (return)
+
+120:
+ ldq_u t1, 0(a1) // get quad surrounding byte
+ subl a2, 1, a2 // decrement count
+ extbl t1, a1, t1 // extract appropriate byte
+ addl a1, 1, a1 // increment buffer pointer
+ insbl t1, t3, t1 // get proper lane
+
+ beq t7, 121f // if not DENSE goto 122f
+
+//
+// Read\modify\write for DENSE space I/O
+//
+ bic t0, 3, t9 // clear bits <1:0> of dest
+ ldl t10, 0(t9) // read dest long
+ mskbl t10, t3, t10 // poke out the byte we will write
+ bis t10, t1, t1 // merge in our byte
+ stl t1, 0(t9) // commit it
+
+ br zero, 122f
+
+//
+// We're in SPARSE space, so simply perform the write
+//
+121:
+ stl t1, 0(t0) // store byte to buffer (BYTE ENABLED)
+122:
+ addq t0, a3, t0 // increment I/O buffer
+ addl t3, 1, t3 // increment bytelane
+ and t3, 3, t3 // longwords only
+ bne a2, 120b // while count != 0
+
+130:
+ mb // push writes off chip
+ ret zero, (ra) // return
+
+ .end WRITE_REGISTER_BUFFER_ULONG // end for UCHAR & USHORT
+
+
+#if 0 //ecrfix
+//
+// Values and structures used to access configuration space.
+//
+
+//
+// Define the configuration routines stack frame.
+//
+
+ .struct 0
+CfgRa: .space 8 // return address
+CfgA0: .space 8 // saved McDevid
+CfgA1: .space 8 // saved BusNumber
+CfgA2: .space 8 // saved SlotNumber
+CfgA3: .space 8 // saved Offset
+CfgA4: .space 8 // padding for 16 byte alignment
+CfgFrameLength:
+
+#endif
+
+//++
+//
+// ULONG
+// READ_CONFIG_UCHAR(
+// ULONG ConfigurationAddress,
+// ULONG ConfigurationCycleType
+// )
+//
+// Routine Description:
+//
+// Read an unsigned byte from PCI configuration space.
+//
+// Arguments:
+//
+// ConfigurationAddress(a0) - Supplies the QVA of configuration to be read.
+//
+// ConfigurationCycleType(a1) - Supplies the type of the configuration cycle.
+//
+// Return Value:
+//
+// (v0) Returns the value of configuration space at the specified location.
+//
+// N.B. - This routine follows a protocol for reading from PCI configuration
+// space that allows the HAL or firmware to fixup and continue
+// execution if no device exists at the configuration target address.
+// The protocol requires 2 rules:
+// (1) The configuration space load must use a destination register
+// of v0
+// (2) The instruction immediately following the configuration space
+// load must use v0 as an operand (it must consume the value
+// returned by the load)
+//
+//--
+
+ LEAF_ENTRY( READ_CONFIG_UCHAR )
+
+//
+// Set the flag indicating the number of the processor upon which a PCI master abort
+// may be expected by the machine check handler.
+//
+
+#if !defined(AXP_FIRMWARE)
+ GET_PROCESSOR_CONTROL_BLOCK_BASE // v0 = prcb base address
+ ldl t0, PbNumber(v0) // capture current processor number
+#else
+ bis zero,zero,t0 // Force processor zero in fw
+#endif
+ extbl t0, 0, t0 // PbNumber is of type CCHAR
+ lda t4, HalpMasterAbortExpected // get address of flag
+ stl t0, MabNumber(t4) // save current processor number
+
+//
+// Perform the read from configuration space after restoring the
+// configuration space address.
+//
+
+ lda t7, IOD_PCI_CONFIG_SVA(zero) // 0xffff ffff ffff c81c
+ sll t7, 28, t7 // 0xffff fc81 c000 0000
+
+ extbl a0, 0x3, t0 // Extract McDevId from ConfigAddress
+ sll t0, 33, t0 // shift McDevId into position @ bit 33
+ bis t7, t0, t7 // superpage mode
+
+ and a0, 0x3, t3 // capture byte lane
+ zapnot a0, 0x7, a0 // Clear McDevid from ConfigAddress
+ sll a0, IO_BIT_SHIFT, t1 // Shift the rest into position
+ bis t7, t1, t7 //
+
+ bis t7, IO_BYTE_LEN, t7 // or in the byte enables
+ stq t7, MabAddr(t4) // save current access address
+
+ .set noreorder // cannot reorder these instructions
+
+ mb // order the writes
+ ldl v0, (t7) // read the longword
+ mb // stall the pipe waiting for mchk
+ mb //
+ extbl v0, t3, v0 // return byte from requested lane
+
+ .set reorder // reordering can begin again
+
+ lda t5, MASTER_ABORT_NOT_EXPECTED(zero)
+ stl t5, MabNumber(t4) // "clear" flag
+
+ ret zero, (ra) // return
+
+ .end READ_CONFIG_UCHAR
+
+//++
+//
+// VOID
+// WRITE_CONFIG_UCHAR(
+// ULONG ConfigurationAddress,
+// UCHAR ConfigurationData,
+// ULONG ConfigurationCycleType
+// )
+//
+// Routine Description:
+//
+// Write an unsigned byte to PCI configuration space.
+//
+// Arguments:
+//
+// ConfigurationAddress(a0) - Supplies the QVA of configuration to be read.
+//
+// ConfigurationData(a1) - Supplies the data to be written.
+//
+// ConfigurationCycleType(a2) - Supplies the type of the configuration cycle.
+//
+// Return Value:
+//
+// None.
+//
+// N.B. - The configuration address must exist within the address space
+// allocated to an existing PCI device. Otherwise, the access
+// below will initiate an unrecoverable machine check.
+//
+//--
+
+ LEAF_ENTRY( WRITE_CONFIG_UCHAR )
+
+//
+// Perform the write to configuration space
+//
+
+ lda t7, IOD_PCI_CONFIG_SVA(zero) // 0xffff ffff ffff c81c
+ sll t7, 28, t7 // 0xffff fc81 c000 0000
+
+ extbl a0, 0x3, t0 // Extract McDevId from ConfigAddress
+ sll t0, 33, t0 // shift McDevId into position @ bit 33
+ bis t7, t0, t7 // superpage mode
+
+ and a0, 0x3, t3 // capture byte lane
+ zapnot a0, 0x7, a0 // Clear McDevid from ConfigAddress
+ sll a0, IO_BIT_SHIFT, t1 // Shift the rest into position
+ bis t7, t1, t7 //
+
+ bis t7, IO_BYTE_LEN, t7 // or in the byte enables
+
+ insbl a1, t3, t4 // put byte in the appropriate lane
+ stl t4, (t7) // write the configuration byte
+ mb // synchronize
+
+ ret zero, (ra) // return
+
+ .end WRITE_CONFIG_UCHAR
+
+//++
+//
+// ULONG
+// READ_CONFIG_USHORT(
+// ULONG ConfigurationAddress,
+// ULONG ConfigurationCycleType
+// )
+//
+// Routine Description:
+//
+// Read a short from PCI configuration space.
+//
+// Arguments:
+//
+// ConfigurationAddress(a0) - Supplies the QVA of configuration to be read.
+//
+// ConfigurationCycleType(a1) - Supplies the type of the configuration cycle.
+//
+// Return Value:
+//
+// (v0) Returns the value of configuration space at the specified location.
+//
+// N.B. - This routine follows a protocol for reading from PCI configuration
+// space that allows the HAL or firmware to fixup and continue
+// execution if no device exists at the configuration target address.
+// The protocol requires 2 rules:
+// (1) The configuration space load must use a destination register
+// of v0
+// (2) The instruction immediately following the configuration space
+// load must use v0 as an operand (it must consume the value
+// returned by the load)
+//--
+
+ LEAF_ENTRY( READ_CONFIG_USHORT )
+
+//
+// Set the flag indicating the number of the processor upon which a PCI master abort
+// may be expected by the machine check handler.
+//
+
+#if !defined(AXP_FIRMWARE)
+ GET_PROCESSOR_CONTROL_BLOCK_BASE // v0 = prcb base address
+ ldl t0, PbNumber(v0) // capture current processor number
+#else
+ bis zero,zero,t0 // Force processor zero in fw
+#endif
+ extbl t0, 0, t0 // PbNumber is of type CCHAR
+ lda t4, HalpMasterAbortExpected // get address of flag
+ stl t0, MabNumber(t4) // save current processor number
+
+//
+// Perform the read from configuration space.
+//
+ lda t7, IOD_PCI_CONFIG_SVA(zero) // 0xffff ffff ffff c81c
+ sll t7, 28, t7 // 0xffff fc81 c000 0000
+
+ extbl a0, 0x3, t0 // Extract McDevId from ConfigAddress
+ sll t0, 33, t0 // shift McDevId into position @ bit 33
+ bis t7, t0, t7 // superpage mode
+
+ and a0, 0x3, t3 // capture word offset
+ zapnot a0, 0x7,a0 // Clear McDevid from ConfigAddress
+ sll a0, IO_BIT_SHIFT, t1 // Shift the rest into position
+ bis t7, t1, t7 //
+
+ bis t7, IO_WORD_LEN, t7 // or in the byte enables
+ stq t7, MabAddr(t4) // save current access address
+
+ .set noreorder // cannot reorder these instructions
+
+ mb // order the write
+ ldl v0, (t7) // read the longword
+ mb // stall the pipe waiting for mchk
+ mb //
+ extwl v0, t3, v0 // return word from requested lanes
+
+ .set reorder // reordering can begin again
+
+ lda t5, MASTER_ABORT_NOT_EXPECTED(zero)
+ stl t5, MabNumber(t4) // "clear" flag
+
+ ret zero, (ra) // return
+
+ .end READ_CONFIG_USHORT
+
+//++
+//
+// VOID
+// WRITE_CONFIG_USHORT(
+// ULONG ConfigurationAddress,
+// UCHAR ConfigurationData,
+// ULONG ConfigurationCycleType
+// )
+//
+// Routine Description:
+//
+// Write a short to PCI configuration space.
+//
+// Arguments:
+//
+// ConfigurationAddress(a0) - Supplies the QVA of configuration to be read.
+//
+// ConfigurationData(a1) - Supplies the data to be written.
+//
+// ConfigurationCycleType(a2) - Supplies the type of the configuration cycle.
+//
+// Return Value:
+//
+// (v0) Returns the value of configuration space at the specified location.
+//
+// N.B. - The configuration address must exist within the address space
+// allocated to an existing PCI device. Otherwise, the access
+// below will initiate an unrecoverable machine check.
+//
+//--
+
+ LEAF_ENTRY( WRITE_CONFIG_USHORT )
+
+//
+// Perform the write to configuration space.
+//
+
+ lda t7, IOD_PCI_CONFIG_SVA(zero) // 0xffff ffff ffff c81c
+ sll t7, 28, t7 // 0xffff fc81 c000 0000
+
+ extbl a0, 0x3, t0 // Extract McDevId from ConfigAddress
+ sll t0, 33, t0 // shift McDevId into position @ bit 33
+ bis t7, t0, t7 // superpage mode
+
+ and a0, 0x3, t3 // capture word offset
+ zapnot a0, 0x7,a0 // Clear McDevid from ConfigAddress
+ sll a0, IO_BIT_SHIFT, t1 // Shift the rest into position
+ bis t7, t1, t7 //
+
+ bis t7, IO_WORD_LEN, t7 // or in the byte enables
+
+ inswl a1, t3, t4 // put byte in the appropriate lane
+ stl t4, (t7) // write the configuration byte
+ mb // synchronize
+
+ ret zero, (ra) // return
+
+ .end WRITE_CONFIG_USHORT
+
+//++
+//
+// ULONG
+// READ_CONFIG_ULONG(
+// ULONG ConfigurationAddress,
+// ULONG ConfigurationCycleType
+// )
+//
+// Routine Description:
+//
+// Read a longword from PCI configuration space.
+//
+// Arguments:
+//
+// ConfigurationAddress(a0) - Supplies the QVA of configuration to be read.
+//
+// ConfigurationCycleType(a1) - Supplies the type of the configuration cycle.
+//
+// Return Value:
+//
+// (v0) Returns the value of configuration space at the specified location.
+//
+// N.B. - This routine follows a protocol for reading from PCI configuration
+// space that allows the HAL or firmware to fixup and continue
+// execution if no device exists at the configuration target address.
+// The protocol requires 2 rules:
+// (1) The configuration space load must use a destination register
+// of v0
+// (2) The instruction immediately following the configuration space
+// load must use v0 as an operand (it must consume the value
+// returned by the load)
+//--
+
+ LEAF_ENTRY( READ_CONFIG_ULONG )
+
+//
+// Set the flag indicating the number of the processor upon which a PCI master abort
+// may be expected by the machine check handler.
+//
+
+#if !defined(AXP_FIRMWARE)
+ GET_PROCESSOR_CONTROL_BLOCK_BASE // v0 = prcb base address
+ ldl t0, PbNumber(v0) // capture current processor number
+#else
+ bis zero,zero,t0 // Force processor zero in fw
+#endif
+ extbl t0, 0, t0 // PbNumber is of type CCHAR
+ lda t4, HalpMasterAbortExpected // get address of flag
+ stl t0, MabNumber(t4) // save current processor number
+
+//
+// Perform the read from configuration space.
+//
+ lda t7, IOD_PCI_CONFIG_SVA(zero) // 0xffff ffff ffff c81c
+ sll t7, 28, t7 // 0xffff fc81 c000 0000
+
+ extbl a0, 0x3, t0 // Extract McDevId from ConfigAddress
+ sll t0, 33, t0 // shift McDevId into position @ bit 33
+ bis t7, t0, t7 // superpage mode
+
+ zapnot a0, 0x7, a0 // Clear McDevid from ConfigAddress
+ sll a0, IO_BIT_SHIFT, t1 // Shift the rest into position
+ bis t7, t1, t7 //
+
+ bis t7, IO_LONG_LEN, t7 // or in the byte enables
+ stq t7, MabAddr(t4) // save current access address
+
+ .set noreorder // cannot reorder these instructions
+
+ mb // order the writes
+ ldl v0, (t7) // read the longword
+ mb // stall the pipe waiting for mchk
+ mb //
+
+ .set reorder // reordering can begin again
+
+ lda t5, MASTER_ABORT_NOT_EXPECTED(zero)
+ stl t5, MabNumber(t4) // "clear" flag
+
+ ret zero, (ra) // return
+
+ .end READ_CONFIG_ULONG
+
+
+//++
+//
+// VOID
+// WRITE_CONFIG_ULONG(
+// ULONG ConfigurationAddress,
+// ULONG ConfigurationData,
+// ULONG ConfigurationCycleType
+// )
+//
+// Routine Description:
+//
+// Read a longword from PCI configuration space.
+//
+// Arguments:
+//
+// ConfigurationAddress(a0) - Supplies the QVA of configuration to be read.
+//
+// ConfigurationData(a1) - Supplies the data to be written.
+//
+// ConfigurationCycleType(a2) - Supplies the type of the configuration cycle.
+//
+// Return Value:
+//
+// (v0) Returns the value of configuration space at the specified location.
+//
+// N.B. - The configuration address must exist within the address space
+// allocated to an existing PCI device. Otherwise, the access
+// below will initiate an unrecoverable machine check.
+//
+//--
+
+ LEAF_ENTRY( WRITE_CONFIG_ULONG )
+
+//
+// Perform the write to configuration space.
+//
+
+ lda t7, IOD_PCI_CONFIG_SVA(zero) // 0xffff ffff ffff c81c
+ sll t7, 28, t7 // 0xffff fc81 c000 0000
+
+ extbl a0, 0x3, t0 // Extract McDevId from ConfigAddress
+ sll t0, 33, t0 // shift McDevId into position @ bit 33
+ bis t7, t0, t7 // superpage mode
+
+ zapnot a0, 0x7, a0 // Clear McDevid from ConfigAddress
+ sll a0, IO_BIT_SHIFT, t1 // Shift the rest into position
+ bis t7, t1, t7 //
+
+ bis t7, IO_LONG_LEN, t7 // or in the byte enables
+
+ stl a1, (t7) // write the longword
+ mb // synchronize
+
+ ret zero, (ra) // return
+
+ .end WRITE_CONFIG_ULONG
+
+//++
+//
+// ULONG
+// INTERRUPT_ACKNOWLEDGE(
+// VOID
+// )
+//
+// Routine Description:
+//
+// Perform an interrupt acknowledge cycle on PCI bus 0
+//
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// (v0) Returns the vector returned by the interrupt acknowledge
+// read.
+//
+//--
+
+
+ LEAF_ENTRY( INTERRUPT_ACKNOWLEDGE )
+
+ lda t0, IOD_PCI0_REGISTER_SVA(zero) // 0xffff ffff ffff cf9e
+ sll t0, 28, t0 // 0xffff fcf9 e000 0000
+ lda t0, 0x480(t0) // 0xffff fcf9 e000 0480
+
+ ldl v0, 0(t0) // perform PCI0 IACK, get vector
+
+ ret zero, (ra) // return
+
+ .end INTERRUPT_ACKNOWLEDGE
+
+ SBTTL( "IOD Interrupt Acknowledge" )
+//++
+//
+// VOID
+// IOD_INTERRUPT_ACKNOWEDGE
+// IN ULONG McDeviceId,
+// IN ULONG Target
+// )
+//
+// Routine Description:
+//
+// Perform an IOD interrupt acknowledge to the selected
+// interrupt target.
+//
+// Arguments:
+//
+// McDeviceId(a0) - MC Bus Device ID of the IOD to acknowledge
+//
+// Target(a1) - Which one of two interrupt targets generated
+// the interrupt. Must be 0 or 1.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(IOD_INTERRUPT_ACKNOWLEDGE)
+
+//
+// Generate the superpage address of the requested IOD INT_ACK register
+//
+ mb
+
+ extbl a0, zero, a0 // McDevId
+
+ sll a1, 6, a1 // Which target?
+ lda t4, IOD_TARGET0_OFFSET // If target = 0, offset = 0x3f00
+ bis a1, t4, t4 // If target = 1, offset = 0x3f40
+
+ lda t0, IOD_INT_ACK_SVA(zero) //0xffff ffff ffff c81f
+ sll a0, 5, t1 // 0x0000000mc 0000 0000 McDeviceId
+ bis t0, t1, t0 // 0xffff fc81 f000 0000
+ sll t0, 28, t0 // 0xffff fcXX f000 0000
+
+ or t0, t4, t0 // 0xffff fcXX f000 3f00/3f40
+ stl zero, (t0) // write the longword
+ mb // order the write
+ mb // SPECIAL 2nd MB for Rawhide
+
+ ret zero, (ra) // return
+
+ .end IOD_INTERRUPT_ACKNOWLEDGE
+
+
+ SBTTL( "CPU Clock Interrupt Acknowledge" )
+//++
+//
+// VOID
+// CPU_CLOCK_ACKNOWEDGE
+// IN ULONG McDeviceId
+// )
+//
+// Routine Description:
+//
+// Perform an clock (interval timer) interrupt acknowledge to the
+// selected CPU.
+//
+// Arguments:
+//
+// McDevid(a0) - MC Bus Device ID of the CPU to acknowledge.
+//
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(CPU_CLOCK_ACKNOWLEDGE)
+
+//
+// Generate the superpage address of the requested CUD's INTTIM_ACK register
+//
+
+
+ extbl a0, zero, a0 // McDeviceId
+
+ lda t0, IOD_INTTIM_SVA(zero) //0xffff ffff ffff c810
+ sll a0, 5, t1 // 0x0000000mc 0000 0000 McDeviceId
+ bis t0, t1, t0 // 0xffff fc81 0000 0000
+ sll t0, 28, t0 // 0xffff fcXX 0000 0000
+
+ stl zero, (t0) // write the longword
+ mb // order the write
+ mb // SPECIAL 2nd MB for Rawhide
+
+ ret zero, (ra) // return
+
+ .end CPU_CLOCK_ACKNOWLEDGE
+
+
+
+ SBTTL( "Interprocessor Interrupt Request" )
+//++
+//
+// VOID
+// IP_INTERRUPT_REQUEST
+// IN ULONG McDeviceId
+// )
+//
+// Routine Description:
+//
+// Perform an inteprocessor interrupt request to the
+// selected CPU.
+//
+// Arguments:
+//
+// McDevid(a0) - MC Bus Device ID of the CPU to send an IPI request.
+//
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(IP_INTERRUPT_REQUEST)
+
+//
+// Generate the superpage address of the requested CUD's IP_INTR register
+//
+
+
+ extbl a0, zero, a0 // McDeviceId
+
+ lda t0, IOD_IP_INTR_SVA(zero) // 0xffff ffff ffff c801
+ sll a0, 5, t1 // 0x0000000mc 0000 0000 McDeviceId
+ bis t0, t1, t0 // 0xffff fc80 1000 0000
+ sll t0, 28, t0 // 0xffff fcXX 1000 0000
+
+ stl zero, (t0) // write the longword
+ mb // order the write
+ mb // SPECIAL 2nd MB for Rawhide
+
+ ret zero, (ra) // return
+
+ .end IP_INTERRUPT_REQUEST
+
+
+ SBTTL( "Interprocessor Interrupt Acknowledge" )
+//++
+//
+// VOID
+// IP_INTERRUPT_ACKNOWEDGE
+// IN ULONG McDeviceId
+// )
+//
+// Routine Description:
+//
+// Perform an inteprocessor interrupt acknowledge to the
+// selected CPU.
+//
+// Arguments:
+//
+// McDevid(a0) - MC Bus Device ID of the CPU to send an IPI acknowledge.
+//
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(IP_INTERRUPT_ACKNOWLEDGE)
+
+//
+// Generate the superpage address of the requested CUD's IP_ACK register
+//
+
+
+ extbl a0, zero, a0 // McDeviceId
+
+ lda t0, IOD_IP_ACK_SVA(zero) // 0xffff ffff ffff c811
+ sll a0, 5, t1 // 0x0000000mc 0000 0000 McDeviceId
+ bis t0, t1, t0 // 0xffff fc81 1000 0000
+ sll t0, 28, t0 // 0xffff fcXX 1000 0000
+
+ stl zero, (t0) // write the longword
+ mb // order the write
+ mb // SPECIAL 2nd MB for Rawhide
+
+ ret zero, (ra) // return
+
+ .end IP_INTERRUPT_ACKNOWLEDGE
diff --git a/private/ntos/nthals/halraw/alpha/iodmapio.c b/private/ntos/nthals/halraw/alpha/iodmapio.c
new file mode 100644
index 000000000..2970fb955
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/iodmapio.c
@@ -0,0 +1,163 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ iodmapio.c
+
+Abstract:
+
+ This module contains the functions to map HAL-accessed I/O addresses
+ on IOD-based systems.
+
+Author:
+
+ Eric Rehm 26-Apr-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "isaaddr.h"
+
+//
+// Define global data used to locate the EISA control space.
+//
+
+PVOID HalpEisaControlBase;
+PVOID HalpEisaIntAckBase;
+PVOID HalpPciIrQva;
+PVOID HalpPciImrQva;
+PVOID HalpCMOSRamBase;
+
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL I/O space for an IOD-based system using
+ the Quasi VA mechanism.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ PVOID PciIoSpaceBase;
+
+ //
+ // Map base addresses in QVA space.
+ //
+
+// PciIoSpaceBase = HAL_MAKE_QVA( IOD_PCI0_SPARSE_IO_PHYSICAL );
+
+ //
+ // IoSpace Base for PCI 0 is a bus address 0.
+ //
+
+ PciIoSpaceBase = HAL_MAKE_IOD_SPARSE_QVA( 0, 0 );
+
+ HalpEisaControlBase = PciIoSpaceBase;
+
+// ecrfix - not needed? HalpEisaIntAckBase = HAL_MAKE_IOD_SPARSE_QVA(0, 0);
+
+ //
+ // Map CMOS RAM address.
+ //
+
+ HalpCMOSRamBase = (PVOID)((ULONG)PciIoSpaceBase + CMOS_ISA_PORT_ADDRESS);
+
+ //
+ // Map the real-time clock registers.
+ //
+
+ HalpRtcAddressPort = (PVOID)((ULONG)PciIoSpaceBase + RTC_ISA_ADDRESS_PORT);
+ HalpRtcDataPort = (PVOID)((ULONG)PciIoSpaceBase + RTC_ISA_DATA_PORT);
+
+ return TRUE;
+
+}
+
+ULONG
+HalpMapDebugPort(
+ IN ULONG ComPort,
+ OUT PULONG ReadQva,
+ OUT PULONG WriteQva
+ )
+/*++
+
+Routine Description:
+
+ This routine maps the debug com port so that the kernel debugger
+ may function - if called it is called very earlier in the boot sequence.
+
+Arguments:
+
+ ComPort - Supplies the number of the com port to use as the debug port.
+
+ ReadQva - Receives the QVA used to access the read registers of the debug
+ port.
+
+ WriteQva - Receives the QVA used to access the write registers of the
+ debug port.
+
+Return Value:
+
+ Returns the base bus address of the device used as the debug port.
+
+--*/
+{
+ ULONG ComPortAddress;
+ ULONG PortQva;
+
+ //
+ // Compute the port address, based on the desired com port.
+ //
+
+ switch( ComPort ){
+
+ case 1:
+
+ ComPortAddress = COM1_ISA_PORT_ADDRESS;
+ break;
+
+ case 2:
+ default:
+
+ ComPortAddress = COM2_ISA_PORT_ADDRESS;
+
+ }
+
+ //
+ // COM ports are on PCI bus 0.
+ // Return the QVAs for read and write access.
+ //
+
+ PortQva = (ULONG)HAL_MAKE_IOD_SPARSE_QVA( 0, 0 ) + ComPortAddress;
+
+ *ReadQva = PortQva;
+ *WriteQva = PortQva;
+
+ return ComPortAddress;
+
+}
+
+
diff --git a/private/ntos/nthals/halraw/alpha/ioproc.c b/private/ntos/nthals/halraw/alpha/ioproc.c
new file mode 100644
index 000000000..8789e513c
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/ioproc.c
@@ -0,0 +1,75 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ ioproc.c
+
+Abstract:
+
+ Stub functions for UP hals.
+
+Author:
+
+ Ken Reneris (kenr) 22-Jan-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Added to Avanti Hals (Sameer Dekate) 04-May-1994
+
+--*/
+
+#include "halp.h"
+#include "iousage.h"
+
+UCHAR HalName[] = "Alpha Compatible PCI/Eisa/Isa HAL";
+
+BOOLEAN
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+VOID HalpInitializePciBuses (VOID);
+VOID HalpInitOtherBuses (VOID);
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpInitMP)
+#pragma alloc_text(INIT,HalStartNextProcessor)
+#pragma alloc_text(INIT,HalpInitOtherBuses)
+#endif
+
+
+
+BOOLEAN
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+{
+ return TRUE;
+ // do nothing
+}
+
+
+VOID
+HalpResetAllProcessors (
+ VOID
+ )
+{
+ // Just return, that will invoke the standard PC reboot code
+}
+
+
+VOID
+HalpInitOtherBuses (
+ VOID
+ )
+{
+ // no other internal buses supported
+}
diff --git a/private/ntos/nthals/halraw/alpha/iousage.c b/private/ntos/nthals/halraw/alpha/iousage.c
new file mode 100644
index 000000000..6ac8f6f4e
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/iousage.c
@@ -0,0 +1,647 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ iousage.c
+
+Abstract:
+
+Author:
+
+ Ken Reneris (kenr)
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Chao Chen 1-25-1995
+
+--*/
+
+#include "halp.h"
+#include "iousage.h"
+
+//
+// Externals.
+//
+
+extern KAFFINITY HalpActiveProcessors;
+
+//
+// Private resource list.
+//
+
+static PBUS_USAGE HalpBusUsageList = NULL;
+static PRESOURCE_USAGE HalpResourceUsageList = NULL;
+
+//
+// Default HAL name.
+//
+
+#define MAX_NAME_LENGTH 256
+UCHAR HalRegisteredName[MAX_NAME_LENGTH] = "Alpha Compatible PCI/EISA/ISA HAL";
+
+//
+// Function prototype.
+//
+
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName
+ );
+
+VOID
+HalpGetResourceSortValue (
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
+ OUT PULONG sortscale,
+ OUT PLARGE_INTEGER sortvalue
+ );
+
+//
+// Pragma stuff.
+//
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpRegisterHalName)
+#pragma alloc_text(INIT,HalpRegisterBusUsage)
+#pragma alloc_text(INIT,HalpRegisterResourceUsage)
+#pragma alloc_text(INIT,HalReportResourceUsage)
+#pragma alloc_text(INIT,HalpReportResourceUsage)
+#pragma alloc_text(INIT,HalpGetResourceSortValue)
+#endif
+
+//
+// Function definitions.
+//
+
+
+VOID
+HalpRegisterHalName(
+ IN PUCHAR NewHalName
+ )
+/*++
+
+Routine Description:
+
+ Allow the HAL to register a name string.
+
+Arguments:
+
+ HalName - Supplies a pointer to the HAL name to register.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ strncpy( HalRegisteredName, NewHalName, MAX_NAME_LENGTH );
+ return;
+}
+
+
+
+VOID
+HalpRegisterBusUsage (
+ IN INTERFACE_TYPE BusType
+ )
+/*++
+
+Routine Description:
+
+ Register the different bus types in the system.
+
+Arguments:
+
+ BusType - bus type that requires registering.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PBUS_USAGE Temp;
+
+ //
+ // Allocate the buffer to store the bus information.
+ //
+
+ Temp = (PBUS_USAGE)ExAllocatePool(NonPagedPool, sizeof(BUS_USAGE));
+
+ //
+ // Save the bus type.
+ //
+
+ Temp->BusType = BusType;
+
+ //
+ // Add the bus type to the head of the list.
+ //
+
+ Temp->Next = HalpBusUsageList;
+ HalpBusUsageList = Temp;
+}
+
+
+
+VOID
+HalpRegisterResourceUsage (
+ IN PRESOURCE_USAGE Resource
+ )
+/*++
+
+Routine Description:
+
+ Register the resources used internally by the HAL to the I/O system.
+
+Arguments:
+
+ Resource - resource that requires registering.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PRESOURCE_USAGE Temp;
+
+ //
+ // Allocate the buffer to store the resource information.
+ //
+
+ Temp = (PRESOURCE_USAGE)ExAllocatePool(NonPagedPool, sizeof(RESOURCE_USAGE));
+
+ //
+ // Copy the resource to the buffer we allocated.
+ //
+
+ RtlCopyMemory(Temp, Resource, sizeof(RESOURCE_USAGE));
+
+ //
+ // Add the resource to the head of the resource list.
+ //
+
+ Temp->Next = HalpResourceUsageList;
+ HalpResourceUsageList = Temp;
+}
+
+
+
+VOID
+HalReportResourceUsage (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Report the resources used internally by the HAL to the I/O system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ANSI_STRING AHalName;
+ UNICODE_STRING UHalName;
+
+ //
+ // Convert the string.
+ //
+
+ RtlInitAnsiString (&AHalName, HalRegisteredName);
+ RtlAnsiStringToUnicodeString (&UHalName, &AHalName, TRUE);
+
+ //
+ // Report the resources registered as in use by the HAL.
+ //
+
+ HalpReportResourceUsage(&UHalName);
+
+ RtlFreeUnicodeString(&UHalName);
+}
+
+
+
+VOID
+HalpGetResourceSortValue (
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
+ OUT PULONG sortscale,
+ OUT PLARGE_INTEGER sortvalue
+ )
+/*++
+
+Routine Description:
+
+ Used by HalpReportResourceUsage in order to properly sort
+ partial_resource_descriptors.
+
+Arguments:
+
+ pRCurLoc - resource descriptor
+
+Return Value:
+
+ sortscale - scaling of resource descriptor for sorting
+ sortvalue - value to sort on
+
+
+--*/
+{
+
+ switch (pRCurLoc->Type) {
+ case CmResourceTypeInterrupt:
+ *sortscale = 0;
+ sortvalue->QuadPart = pRCurLoc->u.Interrupt.Level;
+ break;
+
+ case CmResourceTypePort:
+ *sortscale = 1;
+ *sortvalue = pRCurLoc->u.Port.Start;
+ break;
+
+ case CmResourceTypeMemory:
+ *sortscale = 2;
+ *sortvalue = pRCurLoc->u.Memory.Start;
+ break;
+
+ case CmResourceTypeDma:
+ *sortscale = 3;
+ sortvalue->QuadPart = pRCurLoc->u.Dma.Channel;
+ break;
+
+ default:
+ *sortscale = 4;
+ sortvalue->QuadPart = 0;
+ break;
+ }
+}
+
+
+
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName
+ )
+/*++
+
+Routine Description:
+
+ This routine registers the resources for the hal.
+
+Arguments:
+
+ HalName - the name of the hal to be registered.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PCM_RESOURCE_LIST RawResourceList, TranslatedResourceList;
+ PCM_FULL_RESOURCE_DESCRIPTOR pRFullDesc, pTFullDesc;
+ PCM_PARTIAL_RESOURCE_LIST pRPartList, pTPartList;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc, pTCurLoc;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR pRSortLoc, pTSortLoc;
+ CM_PARTIAL_RESOURCE_DESCRIPTOR RPartialDesc, TPartialDesc;
+ ULONG i, j, k, ListSize, Count;
+ ULONG curscale, sortscale;
+ LARGE_INTEGER curvalue, sortvalue;
+ PHYSICAL_ADDRESS PhyAddress;
+ PBUS_USAGE CurrentBus;
+ PRESOURCE_USAGE CurrentResource;
+
+ //
+ // Allocate some space to build the resource structure.
+ //
+
+ RawResourceList=
+ (PCM_RESOURCE_LIST)ExAllocatePool(NonPagedPool, PAGE_SIZE*2);
+ TranslatedResourceList=
+ (PCM_RESOURCE_LIST)ExAllocatePool(NonPagedPool, PAGE_SIZE*2);
+
+ //
+ // This functions assumes unset fields are zero.
+ //
+
+ RtlZeroMemory (RawResourceList, PAGE_SIZE*2);
+ RtlZeroMemory (TranslatedResourceList, PAGE_SIZE*2);
+
+ //
+ // Initialize the lists
+ //
+
+ RawResourceList->List[0].InterfaceType = (INTERFACE_TYPE) -1;
+ pRFullDesc = RawResourceList->List;
+ pRCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) RawResourceList->List;
+ pTCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) TranslatedResourceList->List;
+
+ //
+ // Report all the HAL resources.
+ //
+
+ CurrentBus = HalpBusUsageList;
+
+ while (CurrentBus) {
+
+ //
+ // Start at the head of the resource list for each bus type.
+ //
+
+ CurrentResource = HalpResourceUsageList;
+
+ while (CurrentResource) {
+
+ //
+ // Register the resources for a particular bus.
+ //
+
+ if (CurrentBus->BusType == CurrentResource->BusType) {
+
+ switch (CurrentResource->ResourceType) {
+
+ case CmResourceTypeInterrupt:
+
+ //
+ // Process interrupt resources.
+ //
+
+ RPartialDesc.Type = CmResourceTypeInterrupt;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+
+ if (CurrentResource->u.InterruptMode == Latched)
+ RPartialDesc.Flags = CM_RESOURCE_INTERRUPT_LATCHED;
+ else
+ RPartialDesc.Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+
+ RPartialDesc.u.Interrupt.Vector =
+ CurrentResource->u.BusInterruptVector;
+ RPartialDesc.u.Interrupt.Level =
+ CurrentResource->u.BusInterruptVector;
+ RPartialDesc.u.Interrupt.Affinity = HalpActiveProcessors;
+
+ RtlCopyMemory(&TPartialDesc, &RPartialDesc, sizeof(TPartialDesc));
+ TPartialDesc.u.Interrupt.Vector =
+ CurrentResource->u.SystemInterruptVector;
+ TPartialDesc.u.Interrupt.Level =
+ CurrentResource->u.SystemIrql;
+
+ break;
+
+ case CmResourceTypePort:
+ case CmResourceTypeMemory:
+
+ //
+ // Process port and memory resources.
+ //
+
+ RPartialDesc.Type = CurrentResource->ResourceType;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+
+ if (RPartialDesc.Type == CmResourceTypePort) {
+
+ //
+ // In IO space.
+ //
+
+ i = 1;
+ RPartialDesc.Flags = CM_RESOURCE_PORT_IO;
+
+ } else {
+
+ //
+ // In memory space.
+ //
+
+ i = 0;
+ RPartialDesc.Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ }
+
+ //
+ // Notice: assume u.Memory and u.Port have the same layout.
+ //
+
+ RPartialDesc.u.Memory.Start.HighPart = 0;
+ RPartialDesc.u.Memory.Start.LowPart = CurrentResource->u.Start;
+ RPartialDesc.u.Memory.Length = CurrentResource->u.Length;
+
+ RtlCopyMemory(&TPartialDesc, &RPartialDesc, sizeof(TPartialDesc));
+
+ //
+ // Translate the address.
+ //
+
+ HalTranslateBusAddress(CurrentResource->BusType,
+ CurrentResource->BusNumber,
+ RPartialDesc.u.Memory.Start,
+ &i,
+ &PhyAddress );
+
+ TPartialDesc.u.Memory.Start = PhyAddress;
+
+ if ((RPartialDesc.Type == CmResourceTypePort) && (i == 0))
+ TPartialDesc.Flags = CM_RESOURCE_PORT_MEMORY;
+
+ break;
+
+ case CmResourceTypeDma:
+
+ //
+ // Process dma resources.
+ //
+
+ RPartialDesc.Type = CmResourceTypeDma;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+
+ RPartialDesc.u.Dma.Channel = CurrentResource->u.DmaChannel;
+ RPartialDesc.u.Dma.Port = CurrentResource->u.DmaPort;
+
+ RtlCopyMemory(&TPartialDesc, &RPartialDesc, sizeof(TPartialDesc));
+ TPartialDesc.u.Dma.Channel = CurrentResource->u.DmaChannel;
+ TPartialDesc.u.Dma.Port = CurrentResource->u.DmaPort;
+
+ break;
+
+ default:
+
+ //
+ // Got a resource we don't know. Bail out!
+ //
+
+ goto NextResource;
+ }
+
+ //
+ // Include the current resource in the HAL list.
+ //
+
+ if (pRFullDesc->InterfaceType != CurrentBus->BusType) {
+
+ //
+ // Interface type changed, add another full section
+ //
+
+ RawResourceList->Count++;
+ TranslatedResourceList->Count++;
+
+ pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR)pRCurLoc;
+ pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR)pTCurLoc;
+
+ pRFullDesc->InterfaceType = CurrentBus->BusType;
+ pTFullDesc->InterfaceType = CurrentBus->BusType;
+
+ pRPartList = &pRFullDesc->PartialResourceList;
+ pTPartList = &pTFullDesc->PartialResourceList;
+
+ //
+ // Bump current location pointers up
+ //
+
+ pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
+ pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
+ }
+
+ //
+ // Add current resource in.
+ //
+
+ pRPartList->Count++;
+ pTPartList->Count++;
+ RtlCopyMemory(pRCurLoc, &RPartialDesc, sizeof(RPartialDesc));
+ RtlCopyMemory(pTCurLoc, &TPartialDesc, sizeof(TPartialDesc));
+
+ pRCurLoc++;
+ pTCurLoc++;
+ }
+
+ //
+ // Finished with this resource, move to the next one.
+ //
+
+ NextResource:
+ CurrentResource = CurrentResource->Next;
+ }
+
+ //
+ // Finished with this bus, move to the next one.
+ //
+
+ CurrentBus = CurrentBus->Next;
+ }
+
+ //
+ // Do the actual reporting.
+ //
+
+ ListSize = (ULONG)(((PUCHAR)pRCurLoc) - ((PUCHAR)RawResourceList));
+
+ //
+ // The HAL's resource usage structures have been built
+ // Sort the partial lists based on the Raw resource values.
+ //
+
+ pRFullDesc = RawResourceList->List;
+ pTFullDesc = TranslatedResourceList->List;
+
+ for (i=0; i < RawResourceList->Count; i++) {
+
+ pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
+ pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
+ Count = pRFullDesc->PartialResourceList.Count;
+
+ for (j=0; j < Count; j++) {
+ HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue);
+
+ pRSortLoc = pRCurLoc;
+ pTSortLoc = pTCurLoc;
+
+ for (k=j; k < Count; k++) {
+ HalpGetResourceSortValue (pRSortLoc, &sortscale, &sortvalue);
+
+ if (sortscale < curscale ||
+ (sortscale == curscale &&
+ (sortvalue.QuadPart < curvalue.QuadPart)) ){
+
+ //
+ // Swap the elements.
+ //
+
+ RtlCopyMemory (&RPartialDesc, pRCurLoc, sizeof RPartialDesc);
+ RtlCopyMemory (pRCurLoc, pRSortLoc, sizeof RPartialDesc);
+ RtlCopyMemory (pRSortLoc, &RPartialDesc, sizeof RPartialDesc);
+
+ //
+ // Swap translated descriptor as well.
+ //
+
+ RtlCopyMemory (&TPartialDesc, pTCurLoc, sizeof TPartialDesc);
+ RtlCopyMemory (pTCurLoc, pTSortLoc, sizeof TPartialDesc);
+ RtlCopyMemory (pTSortLoc, &TPartialDesc, sizeof TPartialDesc);
+
+ //
+ // Get new curscale & curvalue.
+ //
+
+ HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue);
+ }
+
+ pRSortLoc++;
+ pTSortLoc++;
+ }
+
+ pRCurLoc++;
+ pTCurLoc++;
+ }
+
+ pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc;
+ pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc;
+ }
+
+ //
+ // Inform the IO system of our resources.
+ //
+
+ IoReportHalResourceUsage(HalName,
+ RawResourceList,
+ TranslatedResourceList,
+ ListSize);
+
+ ExFreePool (RawResourceList);
+ ExFreePool (TranslatedResourceList);
+
+ //
+ // Free all registered buses.
+ //
+
+ while (HalpBusUsageList) {
+
+ CurrentBus = HalpBusUsageList;
+ HalpBusUsageList = HalpBusUsageList->Next;
+ ExFreePool(CurrentBus);
+ }
+
+ //
+ // Free all registered resources.
+ //
+
+ while (HalpResourceUsageList) {
+
+ CurrentResource = HalpResourceUsageList;
+ HalpResourceUsageList = HalpResourceUsageList->Next;
+ ExFreePool(CurrentResource);
+ }
+}
+
diff --git a/private/ntos/nthals/halraw/alpha/iousage.h b/private/ntos/nthals/halraw/alpha/iousage.h
new file mode 100644
index 000000000..b54cd179a
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/iousage.h
@@ -0,0 +1,107 @@
+/*++
+
+Copyright (c) 1993-1995 Microsoft Corporation
+Copyright (c) 1993-1995 Digital Equipment Corporation
+
+Module Name:
+
+ iousage.h
+
+Abstract:
+
+ This header file defines the iousage definitions
+
+Author:
+
+ Sameer Dekate 5-3-1994
+
+
+Revision History:
+
+ Chao Chen 1-25-1995
+
+--*/
+
+//
+// Resource usage information
+//
+
+//
+// Bus usage information.
+//
+
+typedef struct _HalBusUsage{
+ INTERFACE_TYPE BusType;
+ struct _HalBusUsage *Next;
+} BUS_USAGE, *PBUS_USAGE;
+
+//
+// Address usage information.
+//
+
+typedef struct _HalResourceUsage {
+
+ //
+ // Common elements.
+ //
+
+ INTERFACE_TYPE BusType;
+ ULONG BusNumber;
+ CM_RESOURCE_TYPE ResourceType;
+ struct _HalResourceUsage *Next;
+
+ //
+ // Resource type specific.
+ //
+
+ union {
+
+ //
+ // Address usage.
+ //
+
+ struct {
+ ULONG Start;
+ ULONG Length;
+ };
+
+ //
+ // Vector type specific.
+ //
+
+ struct {
+ KINTERRUPT_MODE InterruptMode;
+ ULONG BusInterruptVector;
+ ULONG SystemInterruptVector;
+ KIRQL SystemIrql;
+ };
+
+ //
+ // Dma type specific.
+ //
+
+ struct {
+ ULONG DmaChannel;
+ ULONG DmaPort;
+ };
+ } u;
+} RESOURCE_USAGE, *PRESOURCE_USAGE;
+
+//
+// Functions to report HAL's resource usage.
+//
+
+VOID
+HalpRegisterHalName(
+ IN PUCHAR HalName
+ );
+
+VOID
+HalpRegisterBusUsage (
+ IN INTERFACE_TYPE BusType
+ );
+
+VOID
+HalpRegisterResourceUsage (
+ IN PRESOURCE_USAGE Resource
+ );
diff --git a/private/ntos/nthals/halraw/alpha/machdep.h b/private/ntos/nthals/halraw/alpha/machdep.h
new file mode 100644
index 000000000..d45f00988
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/machdep.h
@@ -0,0 +1,42 @@
+/*++
+
+Copyright (c) 1993,1995 Digital Equipment Corporation
+
+Module Name:
+
+ machdep.h
+
+Abstract:
+
+ This file includes the platform-dependent include files used to
+ build the HAL.
+
+Author:
+
+ Joe Notarangelo 01-Dec-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#ifndef _MACHDEP_
+#define _MACHDEP_
+
+//
+// Include Rawhide platform-specific definitions.
+//
+
+#include "rawhide.h"
+
+//
+// Include scatter/gather definitions.
+//
+
+#include "ebsgdma.h"
+
+#endif //_MACHDEP_
diff --git a/private/ntos/nthals/halraw/alpha/memory.c b/private/ntos/nthals/halraw/alpha/memory.c
new file mode 100644
index 000000000..76b1eb7df
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/memory.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\memory.c"
+
diff --git a/private/ntos/nthals/halraw/alpha/nvenv.c b/private/ntos/nthals/halraw/alpha/nvenv.c
new file mode 100644
index 000000000..8a8dfdeb5
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/nvenv.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\nvenv.c"
+
diff --git a/private/ntos/nthals/halraw/alpha/nvram.c b/private/ntos/nthals/halraw/alpha/nvram.c
new file mode 100644
index 000000000..6fd93ab46
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/nvram.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\nvram.c"
+
diff --git a/private/ntos/nthals/halraw/alpha/pcibus.c b/private/ntos/nthals/halraw/alpha/pcibus.c
new file mode 100644
index 000000000..80a22247b
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/pcibus.c
@@ -0,0 +1,146 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation, Digital Equipment Corporation
+
+
+Module Name:
+
+ pcibus.c
+
+Abstract:
+
+ Platform-specific PCI bus routines
+
+Author:
+
+ Eric Rehm 6-June-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "machdep.h"
+
+
+extern ULONG PCIMaxBus;
+
+
+
+PCI_CONFIGURATION_TYPES
+HalpPCIConfigCycleType (
+ IN PBUS_HANDLER BusHandler
+ )
+{
+ PCI_CONFIGURATION_TYPES ConfigType;
+ ULONG BusNumber = BusHandler->BusNumber;
+ PPCIPBUSDATA BusData;
+ BOOLEAN BusIsAcrossPPB;
+
+ //
+ // Get a pointer to the bus-specific data.
+ //
+
+ BusData = (PPCIPBUSDATA)BusHandler->BusData;
+
+ //
+ // Get the flag that tells use whether this is
+ // a root bus or not.
+ //
+
+ BusIsAcrossPPB = BusData->BusIsAcrossPPB;
+
+ //
+ // Valid Config cycles for Bus # < PCIMaxBus
+ //
+ // Then, Type 1 config cycles only when bus is across
+ // a PPB.
+ //
+
+ if (BusNumber < PCIMaxBus) {
+ ConfigType = PciConfigType0;
+ if (BusIsAcrossPPB == TRUE)
+ {
+ ConfigType = PciConfigType1;
+ }
+ } else {
+ ConfigType = PciConfigTypeInvalid;
+ }
+
+#if HALDBG
+ DbgPrint("BusNumber %d BusIsAcrossPPB %d ConfigType %d\n",
+ BusNumber, BusIsAcrossPPB, ConfigType);
+#endif
+
+ return ConfigType;
+
+}
+
+
+VOID
+HalpPCIConfigAddr (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ PPCI_CFG_CYCLE_BITS pPciAddr
+ )
+{
+ PCI_CONFIGURATION_TYPES ConfigType;
+ MC_DEVICE_ID McDevid;
+ ULONG BusNumber = BusHandler->BusNumber;
+ PPCIPBUSDATA BusData;
+
+ ConfigType = HalpPCIConfigCycleType(BusHandler);
+
+ //
+ // Get a pointer to the bus-specific data.
+ //
+
+ BusData = (PPCIPBUSDATA)BusHandler->BusData;
+
+#if HALDBG
+
+ DbgPrint( "PCI Config Access: Bus = %d, Device = %d, BusIsAcrossPPB %d ConfigType = %d\n",
+ BusNumber, Slot.u.bits.DeviceNumber, BusData->BusIsAcrossPPB, ConfigType );
+
+#endif //HALDBG
+
+ //
+ // From the root bus number (a.k.a. HwBusNumber), get
+ // the MC_DEVICE_ID of the IOD that we're attempting to access.
+ //
+
+ McDevid = HalpIodLogicalToPhysical[BusData->HwBusNumber];
+
+ //
+ // If this is an access to an PCI device on a root bus,
+ // then we want to generate a Type 0 config cycle. To do this
+ // on Rawhide, you must set BusNumber to zero.
+ //
+ // We know that an access is destined to a root bus when
+ // when the bus being accessed is *not* across a PPB.
+ //
+
+ if (BusData->BusIsAcrossPPB == FALSE) {
+ BusNumber = 0;
+ }
+
+
+ //
+ // Initialize PciAddr for a PCI type 1 configuration cycle
+ //
+
+ pPciAddr->u.AsULONG = McDevid.all << 24;
+ pPciAddr->u.bits1.BusNumber = BusNumber;
+ pPciAddr->u.bits1.DeviceNumber = Slot.u.bits.DeviceNumber;
+ pPciAddr->u.bits1.FunctionNumber = Slot.u.bits.FunctionNumber;
+ pPciAddr->u.bits1.Reserved1 = PciConfigType1; // don't care!
+
+
+ return;
+}
diff --git a/private/ntos/nthals/halraw/alpha/pciesc.c b/private/ntos/nthals/halraw/alpha/pciesc.c
new file mode 100644
index 000000000..ef14f3c15
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/pciesc.c
@@ -0,0 +1,489 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1992, 1993, 1994 Digital Equipment Corporation
+
+Module Name:
+
+ pciesc.c
+
+Abstract:
+
+ The module provides the interrupt support for the PCI ESC's
+ cascaded 82c59 programmable interrupt controllers.
+
+Author:
+
+ Eric Rehm (DEC) 4-Feburary-1994
+
+Revision History:
+
+ James Livingston 29-Apr-1994
+ Adapted from pcisio.c module for Intel 82374EB (ESC).
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+//
+// Define the context structure for use by interrupt service routines.
+//
+
+typedef BOOLEAN (*PSECOND_LEVEL_DISPATCH)(
+ PKINTERRUPT InterruptObject
+ );
+
+//
+// Import save area for ESC interrupt mask registers.
+//
+
+UCHAR HalpEisaInterrupt1Mask;
+UCHAR HalpEisaInterrupt2Mask;
+UCHAR HalpEisaInterrupt1Level;
+UCHAR HalpEisaInterrupt2Level;
+
+
+BOOLEAN
+HalpInitializeEisaInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the standard dual 82c59 programmable interrupt
+ controller.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ UCHAR DataByte;
+
+ //
+ // Initialize the ESC interrupt controller. There are two cascaded
+ // interrupt controllers, each of which must be initialized with 4
+ // control words.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ DataByte
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0,
+ DataByte
+ );
+
+ //
+ // The second intitialization control word sets the interrupt vector to
+ // 0-15.
+ //
+
+ DataByte = 0;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = 0x08;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The third initialization control word sets the controls for slave mode.
+ // The master ICW3 uses bit position and the slave ICW3 uses a numeric.
+ //
+
+ DataByte = 1 << SLAVE_IRQL_LEVEL;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = SLAVE_IRQL_LEVEL;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The fourth initialization control word is used to specify normal
+ // end-of-interrupt mode and not special-fully-nested mode.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_4) &DataByte)->I80x86Mode = 1;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+
+ //
+ // Disable all of the interrupts except the slave.
+ //
+
+ HalpEisaInterrupt1Mask = (UCHAR)(~(1 << SLAVE_IRQL_LEVEL));
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+
+ HalpEisaInterrupt2Mask = 0xFF;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+
+ //
+ // Initialize the edge/level register masks to 0, which is the default
+ // edge-sensitive value.
+ //
+
+ HalpEisaInterrupt1Level = 0;
+ HalpEisaInterrupt2Level = 0;
+
+ return (TRUE);
+}
+
+VOID
+HalpDisableEisaInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function Disables the EISA interrupt specified by Vector.
+
+Arguments:
+
+ Vector - Supplies the vector of the ESIA interrupt that is Disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Calculate the EISA interrupt vector.
+ //
+
+ Vector -= EISA_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is for controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt2Mask |= (UCHAR) 1 << Vector;
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ //
+ // never disable IRQL2; it is the slave interrupt
+ //
+
+ if (Vector != SLAVE_IRQL_LEVEL) {
+ HalpEisaInterrupt1Mask |= (ULONG) 1 << Vector;
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+ }
+ }
+}
+
+VOID
+HalpEnableEisaInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the EISA interrupt specified by Vector.
+Arguments:
+
+ Vector - Supplies the vector of the EISA interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Calculate the EISA interrupt vector.
+ //
+
+ Vector -= EISA_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt2Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpEisaInterrupt2Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpEisaInterrupt2Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2EdgeLevel,
+ HalpEisaInterrupt2Level
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt1Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpEisaInterrupt1Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpEisaInterrupt1Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1EdgeLevel,
+ HalpEisaInterrupt1Level
+ );
+ }
+}
+
+BOOLEAN
+HalpEisaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PKTRAP_FRAME TrapFrame
+ )
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt being generated
+ via the vector that is connected to an interrupt object that describes
+ the EISA device interrupts. Its function is to call the second-level
+ interrupt dispatch routine and acknowledge the interrupt at the ESC
+ controller.
+
+ This service routine could be connected as follows:
+
+ KeInitializeInterrupt(&Interrupt, HalpDispatch,
+ EISA_VIRTUAL_BASE,
+ (PKSPIN_LOCK)NULL, ISA_LEVEL, ISA_LEVEL, ISA_LEVEL,
+ LevelSensitive, TRUE, 0, FALSE);
+ KeConnectInterrupt(&Interrupt);
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the EISA interrupt acknowledge
+ register.
+
+ TrapFrame - Supplies a pointer to the trap frame for this interrupt.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+{
+ UCHAR EISAVector;
+ PKPRCB Prcb;
+ BOOLEAN returnValue;
+ USHORT PCRInOffset;
+ UCHAR Int1Isr;
+ UCHAR Int2Isr;
+ PULONG DispatchCode;
+ PKINTERRUPT InterruptObject;
+
+ //
+ // Acknowledge the Interrupt controller and receive the returned
+ // interrupt vector.
+ //
+
+ EISAVector = HalpAcknowledgeEisaInterrupt(ServiceContext);
+
+
+ if ((EISAVector & 0x07) == 0x07) {
+
+ //
+ // Check for a passive release by looking at the inservice register.
+ // If there is a real IRQL7 interrupt, just go along normally. If there
+ // is not, then it is a passive release. So just dismiss it.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ 0x0B
+ );
+
+ Int1Isr = READ_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0);
+
+ //
+ // do second controller
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0,
+ 0x0B
+ );
+
+ Int2Isr = READ_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0);
+
+
+ if (!(Int2Isr & 0x80) && !(Int1Isr & 0x80)) {
+
+ //
+ // Clear the master controller to clear situation
+ //
+
+ if (!(Int2Isr & 0x80)) {
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ }
+
+ return FALSE; // ecrfix - now returns a value
+
+ }
+ }
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ PCRInOffset = EISAVector + EISA_VECTORS;
+ DispatchCode = (PULONG)PCR->InterruptRoutine[PCRInOffset];
+ InterruptObject = CONTAINING_RECORD(DispatchCode,
+ KINTERRUPT,
+ DispatchCode);
+
+ returnValue = ((PSECOND_LEVEL_DISPATCH)
+ InterruptObject->DispatchAddress)(InterruptObject);
+
+ //
+ // Dismiss the interrupt in the ESC interrupt controllers.
+ //
+
+ //
+ // If this is a cascaded interrupt then the interrupt must be dismissed in
+ // both controlles.
+ //
+
+ if (EISAVector & 0x08) {
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+ }
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ return(returnValue);
+}
diff --git a/private/ntos/nthals/halraw/alpha/pcisup.c b/private/ntos/nthals/halraw/alpha/pcisup.c
new file mode 100644
index 000000000..360919f42
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/pcisup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcisup.c"
+
diff --git a/private/ntos/nthals/halraw/alpha/pcrtc.c b/private/ntos/nthals/halraw/alpha/pcrtc.c
new file mode 100644
index 000000000..b5006ddf7
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/pcrtc.c
@@ -0,0 +1,383 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ pcrtc.c
+
+Abstract:
+
+ This module implements the HAL set/query realtime clock routines for
+ the standard pc-compatible real time clock use on Alpha AXP systems.
+
+Author:
+
+ David N. Cutler (davec) 5-May-1991
+ Jeff McLeman (mcleman) 3-Jun-1992
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ 13-Jul-1992 Jeff McLeman
+ use VTI access routines to access clock
+
+ 3-June-1992 Jeff McLeman
+ Adapt this module into a Jensen specific module
+
+--*/
+
+#include "halp.h"
+#include "pcrtc.h"
+
+//
+// Local function prototypes.
+//
+
+BOOLEAN
+HalQueryRealTimeClock (
+ OUT PTIME_FIELDS TimeFields
+ );
+
+BOOLEAN
+HalSetRealTimeClock (
+ IN PTIME_FIELDS TimeFields
+ );
+
+UCHAR
+HalpReadClockRegister (
+ UCHAR Register
+ );
+
+VOID
+HalpWriteClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ );
+
+#ifdef AXP_FIRMWARE
+
+//
+// Put these functions in the discardable text section.
+//
+
+#pragma alloc_text(DISTEXT, HalQueryRealTimeClock )
+#pragma alloc_text(DISTEXT, HalSetRealTimeClock )
+#pragma alloc_text(DISTEXT, HalpReadClockRegister )
+#pragma alloc_text(DISTEXT, HalpWriteClockRegister )
+
+#endif // AXP_FIRMWARE
+
+//
+// Define globals used to map the realtime clock address and data ports.
+//
+
+PVOID HalpRtcAddressPort = NULL;
+PVOID HalpRtcDataPort = NULL;
+
+
+BOOLEAN
+HalQueryRealTimeClock (
+ OUT PTIME_FIELDS TimeFields
+ )
+
+/*++
+
+Routine Description:
+
+ This routine queries the realtime clock.
+
+ N.B. This routine assumes that the caller has provided any required
+ synchronization to query the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that receives
+ the realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are read from the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ BOOLEAN Status;
+ KIRQL OldIrql;
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // If the realtime clock battery is still functioning, then read
+ // the realtime clock values, and return a function value of TRUE.
+ // Otherwise, return a function value of FALSE.
+ //
+
+ DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERD);
+ if (((PRTC_CONTROL_REGISTER_D)(&DataByte))->ValidTime == 1) {
+
+ //
+ // Wait until the realtime clock is not being updated.
+ //
+
+ do {
+ DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERA);
+ } while (((PRTC_CONTROL_REGISTER_A)(&DataByte))->UpdateInProgress == 1);
+
+ //
+ // Read the realtime clock values.
+ //
+
+ TimeFields->Year = 1980 + (CSHORT)HalpReadClockRegister(RTC_YEAR);
+ TimeFields->Month = (CSHORT)HalpReadClockRegister(RTC_MONTH);
+ TimeFields->Day = (CSHORT)HalpReadClockRegister(RTC_DAY_OF_MONTH);
+ TimeFields->Weekday = (CSHORT)HalpReadClockRegister(RTC_DAY_OF_WEEK) - 1;
+ TimeFields->Hour = (CSHORT)HalpReadClockRegister(RTC_HOUR);
+ TimeFields->Minute = (CSHORT)HalpReadClockRegister(RTC_MINUTE);
+ TimeFields->Second = (CSHORT)HalpReadClockRegister(RTC_SECOND);
+ TimeFields->Milliseconds = 0;
+ Status = TRUE;
+
+ } else {
+ Status = FALSE;
+ }
+
+ KeLowerIrql(OldIrql);
+ return(Status);
+}
+
+BOOLEAN
+HalSetRealTimeClock (
+ IN PTIME_FIELDS TimeFields
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the realtime clock.
+
+ N.B. This routine is required to provide any synchronization necessary
+ to set the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that specifies the
+ realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are written to the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ KIRQL OldIrql;
+
+ UCHAR DataByte;
+
+ //
+ // If the realtime clock battery is still functioning, then write
+ // the realtime clock values, and return a function value of TRUE.
+ // Otherwise, return a function value of FALSE.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERD);
+ if (((PRTC_CONTROL_REGISTER_D)(&DataByte))->ValidTime == 1) {
+
+ //
+ // Set the realtime clock control to set the time.
+ //
+
+ DataByte = 0;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->HoursFormat = 1;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->DataMode = 1;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SetTime = 1;
+
+#ifdef RTC_SQE
+
+ //
+ // If the platform requires it, make sure that the Square
+ // Wave output of the RTC is turned on.
+ //
+
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SquareWaveEnable = 1;
+
+#endif //RTC_SQE
+
+ HalpWriteClockRegister(RTC_CONTROL_REGISTERB, DataByte);
+
+ //
+ // Write the realtime clock values.
+ //
+
+ HalpWriteClockRegister(RTC_YEAR, (UCHAR)(TimeFields->Year - 1980));
+ HalpWriteClockRegister(RTC_MONTH, (UCHAR)TimeFields->Month);
+ HalpWriteClockRegister(RTC_DAY_OF_MONTH, (UCHAR)TimeFields->Day);
+ HalpWriteClockRegister(RTC_DAY_OF_WEEK, (UCHAR)(TimeFields->Weekday + 1));
+ HalpWriteClockRegister(RTC_HOUR, (UCHAR)TimeFields->Hour);
+ HalpWriteClockRegister(RTC_MINUTE, (UCHAR)TimeFields->Minute);
+ HalpWriteClockRegister(RTC_SECOND, (UCHAR)TimeFields->Second);
+
+ //
+ // Set the realtime clock control to update the time.
+ // (Make sure periodic interrupt is enabled)
+ //
+
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SetTime = 0;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->TimerInterruptEnable = 1;
+ HalpWriteClockRegister(RTC_CONTROL_REGISTERB, DataByte);
+ KeLowerIrql(OldIrql);
+ return TRUE;
+
+ } else {
+ KeLowerIrql(OldIrql);
+ return FALSE;
+ }
+}
+
+
+UCHAR
+HalpReadClockRegister (
+ UCHAR Register
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads the specified realtime clock register.
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is read.
+
+Return Value:
+
+ The value of the register is returned as the function value.
+
+--*/
+
+{
+ //
+ // Read the realtime clock register value.
+ //
+
+ WRITE_PORT_UCHAR( HalpRtcAddressPort, Register );
+
+ return READ_PORT_UCHAR( HalpRtcDataPort );
+}
+
+VOID
+HalpWriteClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This routine writes the specified value to the specified realtime
+ clock register.
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is written.
+
+ Value - Supplies the value that is written to the specified register.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ //
+ // Write the realtime clock register value.
+ //
+
+ WRITE_PORT_UCHAR( HalpRtcAddressPort, Register );
+
+ WRITE_PORT_UCHAR( HalpRtcDataPort, Value );
+
+ return;
+}
+
+
+#if 0 // ecrfix - should not be in this common routine!!!!
+VOID
+HalpProgramIntervalTimer(
+ IN ULONG RateSelect
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to program the interval timer. It is used during
+ Phase 1 initialization to start the heartbeat timer. It also used by
+ the clock interrupt interrupt routine to change the hearbeat timer rate
+ when a call to HalSetTimeIncrement has been made in the previous time slice.
+
+ On Sable the periodic interrupt comes from the square ware output of
+ the Dallas 1489A RTC on the Standard I/O board. Each processor
+ receives this clock phase shifted by at least 90 degrees from all
+ other processors. The periodic interrupt from the RTC is not used and
+ thus doesn't need to be enabled or acknowledged. Each processor has
+ its own clock interrupt latch that is cleared locally. This routine is
+ not used for Sable platforms.
+
+ Because of the phase shifting among the processors, the clock is
+ half the rate given to the RTC. So, the RTC is programmed twice
+ as fast as on a system that takes the RTC periodic interrupt in
+ directly.
+
+Arguments:
+
+ RateSelect - Supplies rate select to be placed in the clock.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UCHAR DataByte;
+
+ //
+ // Set the new rate
+ //
+ DataByte = 0;
+ ((PRTC_CONTROL_REGISTER_A)(&DataByte))->RateSelect = (UCHAR)RateSelect;
+ ((PRTC_CONTROL_REGISTER_A)(&DataByte))->TimebaseDivisor = RTC_TIMEBASE_DIVISOR;
+ HalpWriteClockRegister( RTC_CONTROL_REGISTERA, DataByte );
+
+ //
+ // Set the correct mode
+ //
+ DataByte = 0;
+#if defined(RTC_SQE)
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SquareWaveEnable = 1;
+#else
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->TimerInterruptEnable = 1;
+#endif
+
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->HoursFormat = 1;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->DataMode = 1;
+ HalpWriteClockRegister( RTC_CONTROL_REGISTERB, DataByte );
+}
+#endif
diff --git a/private/ntos/nthals/halraw/alpha/pcserial.c b/private/ntos/nthals/halraw/alpha/pcserial.c
new file mode 100644
index 000000000..a2f159c48
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/pcserial.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcserial.c"
+
diff --git a/private/ntos/nthals/halraw/alpha/pcspeakr.c b/private/ntos/nthals/halraw/alpha/pcspeakr.c
new file mode 100644
index 000000000..807b6f324
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/pcspeakr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcspeakr.c"
+
diff --git a/private/ntos/nthals/halraw/alpha/perf8254.c b/private/ntos/nthals/halraw/alpha/perf8254.c
new file mode 100644
index 000000000..5fade7e42
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/perf8254.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\perf8254.c"
+
diff --git a/private/ntos/nthals/halraw/alpha/pintolin.h b/private/ntos/nthals/halraw/alpha/pintolin.h
new file mode 100644
index 000000000..44cc02593
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/pintolin.h
@@ -0,0 +1,214 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ pintolin.h
+
+Abstract:
+
+ This file includes the platform-dependent Pin To Line Tables
+
+Author:
+
+ Steve Brooks 6-July 1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+//
+// These tables represent the mapping from slot number and interrupt pin
+// into a PCI Interrupt Vector.
+//
+// Formally, these mappings can be expressed as:
+//
+// PCIPinToLine:
+// SlotNumber.DeviceNumber x InterruptPin -> InterruptLine
+//
+// LineToVector:
+// InterruptLine -> InterruptVector
+//
+// VectorToIRRBit:
+// InterruptVector -> InterruptRequestRegisterBit
+//
+// VectorToIMRBit:
+// InterruptVector -> InterruptMaskRegisterBit
+//
+// SlotNumberToIDSEL:
+// SlotNumber.DeviceNumber -> IDSEL
+//
+// subject to following invariants (predicates must always be true):
+//
+// Slot.DeviceNumber in {0,...,15}
+//
+// InterruptPin in {1, 2, 3, 4}
+//
+// InterruptRequestRegisterBit in {0,...,15}
+//
+// InterruptMaskRegisterBit in {0,...,15}
+//
+// PCIPinToLine(SlotNumber.DeviceNumber, InterruptPin) =
+// PCIPinToLineTable[SlotNumber.DeviceNumber, InterruptPin]
+// (Table-lookup function initialized below)
+//
+// LineToVector(InterruptLine) = PCI_VECTORS + InterruptLine
+//
+// VectorToIRRBit(InterruptVector) = InterruptVector - 1
+//
+// VectorToIMRBit(InterruptVector) [see below]
+//
+// SlotNumberToIDSEL(SlotNumber.DeviceNumber) = (1 << (Slot.DeviceNumber+11))
+//
+// where:
+//
+// SlotNumber.DeviceNumber:
+// Alpha AXP Platforms receive interrupts on local PCI buses only, which
+// are limited to 16 devices (PCI AD[11]-AD[26]). (We loose AD[27]-AD[31]
+// since PCI Config space is a sparse space, requiring a five-bit shift.)
+//
+// InterruptPin:
+// Each virtual slot has up to four interrupt pins INTA#, INTB#, INTC#, INTD#,
+// as per the PCI Spec. V2.0, Section 2.2.6. (FYI, only multifunction devices
+// use INTB#, INTC#, INTD#.)
+//
+// PCI configuration space indicates which interrupt pin a device will use
+// in the InterruptPin register, which has the values:
+//
+// INTA# = 1, INTB#=2, INTC#=3, INTD# = 4
+//
+// Note that there may be up to 8 functions/device on a PCI multifunction
+// device plugged into the option slots, e.g., Slot #0.
+// Each function has it's own PCI configuration space, addressed
+// by the SlotNumber.FunctionNumber field, and will identify which
+// interrput pin of the four it will use in it's own InterruptPin register.
+//
+// If the option is a PCI-PCI bridge, interrupts across the bridge will
+// somehow be combined to appear on some combination of the four
+// interrupt pins that the bridge plugs into.
+//
+// InterruptLine:
+// This PCI Configuration register, unlike x86 PC's, is maintained by
+// software and represents offset into PCI interrupt vectors.
+// Whenever HalGetBusData or HalGetBusDataByOffset is called,
+// HalpPCIPinToLine() computes the correct InterruptLine register value
+// by using the HalpPCIPinToLineTable mapping.
+//
+// InterruptRequestRegisterBit:
+// 0xff is used to mark an invalid IRR bit, hence an invalid request
+// for a vector. Also, note that the 16 bits of the EB66 IRR must
+// be access as two 8-bit reads.
+//
+// InterruptMaskRegisterBit:
+// On EB66, the PinToLine table may also be find the to write the
+// InterruptMaskRegister. Formally, we can express this invariant as
+//
+// VectorToIMRBit(InterrruptVector) = InterruptVector - 1
+//
+//
+// IDSEL:
+// For accessing PCI configuration space on a local PCI bus (as opposed
+// to over a PCI-PCI bridge), type 0 configuration cycles must be generated.
+// In this case, the IDSEL pin of the device to be accessed is tied to one
+// of the PCI Address lines AD[11] - AD[26]. (The function field in the
+// PCI address is used should we be accessing a multifunction device.)
+// Anyway, virtual slot 0 represents the device with IDSEL = AD[11], and
+// so on.
+//
+
+//
+// Interrupt Vector Table Mapping for Rawhide.
+//
+// Alcor PCI interrupts are mapped to arbitrary interrupt numbers
+// in the table below. The values are a 1-1 map of the bit numbers
+// in the Alcor PCI interrupt register that are connected to PCI
+// devices. N.B.: there are two other interrupts in this register,
+// but they are not connected to I/O devices, so they're not
+// represented in the table.
+//
+// Limit init table to 5 entries, which is the
+// MAX_PCI_LOCAL_DEVICE.
+//
+// We won't ever try to set an InterruptLine register of a slot
+// greater than Virtual slot 5 = PCI_AD[16].
+//
+// ecrfix - I don't do this, but I might....
+// N.B. - Have biased the bus interrupt vectors/levels for PCI to start
+// at 0x11 so they are disjoint from EISA levels
+//
+
+//
+// Offset the pin-to-line entries by an offset of 0x20 so interrupt
+// vectors reported by WinXXX will be unique.
+//
+
+enum _RAWHIDE_PIN_TO_LINE {
+ RawhideNcr810PinToLine = (RawhidePinToLineOffset + 0x11)
+};
+
+ULONG *HalpPCIPinToLineTable;
+
+ULONG RawhidePCIPinToLineTable[][4]=
+{
+ //
+ // Virtual Slot 0 = PCI_AD[11]
+ //
+
+ { 0xff, // Pin 1
+ 0xff, // Pin 2
+ 0xff, // Pin 3
+ 0xff }, // Pin 4
+
+ //
+ // Virtual Slot 1 = PCI_AD[12] EISA/NCR810
+ //
+
+ { RawhidePinToLineOffset + 0x11, // Pin 1
+ 0xff, // Pin 2
+ 0xff, // Pin 3
+ 0xff }, // Pin 4
+
+ //
+ // Virtual Slot 2 = PCI_AD[13] Slot #0
+ //
+
+ { RawhidePinToLineOffset + 0x01, // Pin 1
+ RawhidePinToLineOffset + 0x02, // Pin 2
+ RawhidePinToLineOffset + 0x03, // Pin 3
+ RawhidePinToLineOffset + 0x04 },// Pin 4
+
+ //
+ // Virtual Slot 3 = PCI_AD[14] Slot #1
+ //
+
+ { RawhidePinToLineOffset + 0x05, // Pin 1
+ RawhidePinToLineOffset + 0x06, // Pin 2
+ RawhidePinToLineOffset + 0x07, // Pin 3
+ RawhidePinToLineOffset + 0x08 },// Pin 4
+
+ //
+ // Virtual Slot 4 = PCI_AD[15] Slot #2
+ //
+
+ { RawhidePinToLineOffset + 0x09, // Pin 1
+ RawhidePinToLineOffset + 0x0a, // Pin 2
+ RawhidePinToLineOffset + 0x0b, // Pin 3
+ RawhidePinToLineOffset + 0x0c },// Pin 4
+
+ //
+ // Virtual Slot 5 = PCI_AD[16] Slot #3
+ //
+
+ { RawhidePinToLineOffset + 0x0d, // Pin 1
+ RawhidePinToLineOffset + 0x0e, // Pin 2
+ RawhidePinToLineOffset + 0x0f, // Pin 3
+ RawhidePinToLineOffset + 0x10 } // Pin 4
+};
+
diff --git a/private/ntos/nthals/halraw/alpha/rawerr.c b/private/ntos/nthals/halraw/alpha/rawerr.c
new file mode 100644
index 000000000..b30d9b19e
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/rawerr.c
@@ -0,0 +1,154 @@
+/*++
+
+Copyright (c) 1995 Digital Equipment Corporation
+
+Module Name:
+
+ rawerr.c
+
+Abstract:
+
+ This module implements error handling (machine checks and error
+ interrupts) for the Rawhide platform.
+
+Author:
+
+ Eric Rehm 13-Apr-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "rawhide.h"
+
+//
+// Declare the extern variables.
+//
+
+extern PERROR_FRAME PUncorrectableError;
+
+//
+// Function prototypes.
+//
+
+VOID
+HalpSetMachineCheckEnables(
+ IN BOOLEAN DisableMachineChecks,
+ IN BOOLEAN DisableProcessorCorrectables,
+ IN BOOLEAN DisableSystemCorrectables
+ );
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+
+VOID
+HalpCacheErrorInterrupt(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is the interrupt handler for a Rawhide machine check interrupt
+ The function calls HalpIodReportFatalError()
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None. If a Fatal Error is detected the system is crashed.
+
+--*/
+{
+ MC_DEVICE_ID McDeviceId;
+
+ HalAcquireDisplayOwnership(NULL);
+
+ //
+ // Display the dreaded banner.
+ //
+
+ HalDisplayString( "\nFatal system hardware error.\n\n" );
+
+ //
+ // If this is a IOD uncorrectable error then report the error and
+ // crash the system.
+ //
+
+ if( HalpIodUncorrectableError( &McDeviceId ) == TRUE ){
+
+ HalpIodReportFatalError( McDeviceId);
+
+ KeBugCheckEx( DATA_BUS_ERROR,
+ 0xfacefeed, //jnfix - quick error interrupt id
+ McDeviceId.all,
+ 0,
+ (ULONG) PUncorrectableError );
+
+ }
+
+ //
+ // It was not a IOD uncorrectable error, therefore this must be an
+ // NMI interrupt.
+ //
+
+ HalHandleNMI( NULL, NULL );
+
+ return; // never
+
+}
+
+
+BOOLEAN
+HalpPlatformMachineCheck(
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PKEXCEPTION_FRAME ExceptionFrame,
+ IN PKTRAP_FRAME TrapFrame
+ )
+/*++
+
+Routine Description:
+
+ This routine is given control when an hard error is acknowledged
+ by the IOD chipset. The routine is given the chance to
+ correct and dismiss the error.
+
+Arguments:
+
+ ExceptionRecord - Supplies a pointer to the exception record generated
+ at the point of the exception.
+
+ ExceptionFrame - Supplies a pointer to the exception frame generated
+ at the point of the exception.
+
+ TrapFrame - Supplies a pointer to the trap frame generated
+ at the point of the exception.
+
+Return Value:
+
+ TRUE is returned if the machine check has been handled and dismissed -
+ indicating that execution can continue. FALSE is return otherwise.
+
+--*/
+{
+
+ //
+ // All machine check handling on Rawhide is determined by the IOD.
+ //
+
+ return( HalpIodMachineCheck( ExceptionRecord,
+ ExceptionFrame,
+ TrapFrame ) );
+
+}
diff --git a/private/ntos/nthals/halraw/alpha/rawerror.h b/private/ntos/nthals/halraw/alpha/rawerror.h
new file mode 100644
index 000000000..dd2d38787
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/rawerror.h
@@ -0,0 +1,301 @@
+/*++
+
+Copyright (c) 1995 Digital Equipment Corporation
+
+Module Name:
+
+ rawerror.h
+
+Abstract:
+
+ This file defines the structures and definitions of correctable and
+ uncorrectable Rawhide error frames, as well as various optional
+ subpackets, snapshots, and frames.
+
+Author:
+
+ Eric Rehm 20-June-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#ifndef _RAWERRORH_
+#define _RAWERRORH_
+
+//
+// Error Frame Revision definitions.
+//
+
+#define UNCORRECTABLE_REVISION_1 (0)
+#define UNCORRECTABLE_REVISION_2 (1)
+#define CORRECTABLE_FRAME_REVISION_1 (0)
+#define CORRECTABLE_FRAME_REVISION_2 (1)
+
+
+//
+// CPU Daughter Card (CUD) Header
+//
+
+// #pragma pack(1)
+typedef struct _CUD_HEADER { // As Per Rawhide SPM
+ ULONG Reserved0[4]; // (0x00-0x0c)
+ ULONG ActiveCpus; // (0x10)
+ ULONG Reserved1; // (0x14)
+ UCHAR SystemSN[10]; // (0x18-0x21) Same as FRU System Serial Number
+ UCHAR Reserved2[6]; // (0x22-0x27)
+ UCHAR ProcessorSN[10]; // (0x28-0x31) Module (processor) S/N, if available
+ USHORT ModType; // (0x32)
+ ULONG Reserved3; // (0x34)
+ ULONG DisabledResources; // (0x38)
+ ULONG SystemRev; // (0x3c) Same as FRY System Revision Level?
+} CUD_HEADER, *PCUD_HEADER;
+
+
+
+//
+// IOD Error Frame
+//
+// N.B. Used in Uncorrectable *and* correctable error frames for
+// information on the IOD that recevied the machine check.
+// It is uses as well in MC Bus snapshot (for each IOD) and Iod Register
+// Subpacket.
+// As far as I'm concerned, they IOD information is the same in each case.
+// We can use the ValidBits field to optionally disable irrelevant
+// fields.
+//
+
+typedef struct _IOD_ERROR_FRAME {
+ ULONGLONG IodBaseAddr; // (0x00)
+ ULONG WhoAmI; // (0x08) - (Reserved in Rawhide SPM)
+ ULONG ValidBits; // (0x0c)
+ ULONG PciRev; // (0x10)
+ ULONG CapCtrl; // (0x14)
+ ULONG HaeMem; // (0x18)
+ ULONG HaeIo; // (0x1c)
+ ULONG IntCtrl; // (0x20)
+ ULONG IntReq; // (0x24)
+ ULONG IntMask0; // (0x28)
+ ULONG IntMask1; // (0x2c)
+ ULONG McErr0; // (0x30)
+ ULONG McErr1; // (0x34)
+ ULONG CapErr; // (0x38)
+ ULONG Reserved0; // (0x3c)
+ ULONG PciErr1; // (0x40)
+ ULONG MdpaStat; // (0x44)
+ ULONG MdpaSyn; // (0x48)
+ ULONG MdpbStat; // (0x4c)
+ ULONG MdpbSyn; // (0x50)
+ ULONG Reserved1[3]; // (0x54-0x5f)
+} IOD_ERROR_FRAME, *PIOD_ERROR_FRAME;
+
+//
+// IOD Error Frame Valid Bits
+//
+// Corresponds to bitfields of ValidBits in the Iod Error Frame
+//
+
+typedef union _IOD_ERROR_FRAME_VALID_BITS {
+ struct {
+ ULONG IodBaseAddrValid: 1; // <0>
+ ULONG WhoAmIValid: 1; // <1>
+ ULONG PciRevValid: 1; // <2>
+ ULONG CapCtrlValid: 1; // <3>
+ ULONG HaeMemValid: 1; // <4>
+ ULONG HaeIoValid: 1; // <5>
+ ULONG IntCtrlValid: 1; // <6>
+ ULONG IntReqValid: 1; // <7>
+ ULONG IntMask0Valid: 1; // <8>
+ ULONG IntMask1Valid: 1; // <9>
+ ULONG McErr0Valid: 1; // <10>
+ ULONG McErr1Valid: 1; // <11>
+ ULONG CapErrValid: 1; // <12>
+ ULONG PciErr1Valid: 1; // <13>
+ ULONG MdpaStatValid: 1; // <14>
+ ULONG MdpaSynValid: 1; // <15>
+ ULONG MdpbStatValid: 1; // <16>
+ ULONG MdpbSynValid: 1; // <17>
+ };
+ ULONG all;
+} IOD_ERROR_FRAME_VALID_BITS, *PIOD_ERROR_FRAME_VALID_BITS;
+
+//
+// Optional Snapshots for which headers or frames are defined below:
+// PCI Bus Snapshot
+// MC Bus Snapshot
+// Memory Size Frame
+// System Managment Frame
+// ESC Frame
+//
+
+//
+// Flags indicating which of the optional snapshots or frames are present
+// in a correctable or uncorrectable error frame
+//
+
+typedef union _ERROR_SUBPACKET_FLAGS {
+ struct {
+ ULONGLONG Reserved0: 10; // <0:9> Reserved
+ ULONGLONG SysEnvPresent : 1; // <10>
+ ULONGLONG MemSizePreset : 1; // <11>
+ ULONGLONG Reserved1: 8; // <12:19> Reserved
+ ULONGLONG McBusPresent: 1; // <20>
+ ULONGLONG GcdBusPresent: 1; // <21>
+ ULONGLONG Reserved2: 8; // <22:29> Reserved
+ ULONGLONG IodSubpacketPresent: 1; // <30>
+ ULONGLONG PciSnapshotPresent: 1; // <31>
+ ULONGLONG EscSubpacketPresent: 1; // <32>
+ ULONGLONG Reserved3: 7; // <33:39> Reserved
+ ULONGLONG Iod2SubpacketPresent: 1; // <40> ???
+ ULONGLONG Pci2SnapshotPresent: 1; // <41> ???
+ };
+ ULONGLONG all;
+} ERROR_SUBPACKET_FLAGS, *PERROR_SUBPACKET_FLAGS;
+
+
+//
+// PCI Bus Snapshot Header
+//
+// Header is followed PCI_COMMON_CONFIG packets (256 bytes each) for each PCI
+// device present in the system. Therefore,
+// Length = sizeof (PCI_BUS_SNAPSHOT) + NumberOfNodes*sizeof(PCI_COMMON_CONFIG)
+//
+// N.B. PCI_COMMON_CONFIG is defined \nt\private\ntos\inc\pci.h
+//
+
+
+typedef struct _PCI_BUS_SNAPSHOT {
+ ULONG Length; // (0x00)
+ USHORT BusNumber; // (0x04)
+ USHORT NumberOfNodes; // (0x06)
+ //
+ // NumberOfNodes packets follow (0x08)
+ //
+} PCI_BUS_SNAPSHOT, *PPCI_BUS_SNAPSHOT;
+
+
+
+//
+// MC Bus Snapshot Header
+//
+// Header is followed a IOD_ERROR_FRAME for each IOD on the system;
+// Therefore,
+// Length = sizeof (MC_BUS_SNAPSHOT) + NumberOfIods*sizeof(IOD_ERROR_FRAME)
+//
+
+typedef struct _MC_BUS_SNAPSHOT {
+ ULONG Length; // (0x00)
+ ULONG NumberOfIods; // (0x04)
+ ULONGLONG ReportingCpuBaseAddr; // (0x08)
+ //
+ // NumberOfIods packets follow (0x10)
+ //
+} MC_BUS_SNAPSHOT, *PMC_BUS_SNAPSHOT;
+
+
+//
+// Memory Size Frame
+//
+
+typedef struct _MEMORY_SIZE_FRAME {
+ ULONGLONG MemorySize; // (0x00)
+} MEMORY_SIZE_FRAME, *PMEMORY_SIZE_FRAME;
+
+typedef union _MEMORY_SIZE {
+ struct {
+ ULONGLONG MemorySize0: 8; // <0:7>
+ ULONGLONG MemorySize1: 8; // <8:15>
+ ULONGLONG MemorySize2: 8; // <16:23>
+ ULONGLONG MemorySize3: 8; // <24:31>
+ ULONGLONG Reserved: 24; // <32:55>
+ ULONGLONG MemorySize0Valid: 1; // <56>
+ ULONGLONG MemorySize1Valid: 1; // <57>
+ ULONGLONG MemorySize2Valid: 1; // <58>
+ ULONGLONG MemorySize3Valid: 1; // <59>
+ };
+ ULONGLONG all;
+} MEMORY_SIZE, *PMEMORY_SIZE;
+
+
+//
+// System Managment Frame
+//
+
+typedef struct _SYSTEM_MANAGEMENT_FRAME {
+ ULONGLONG SystemEnvironment; // (0x00)
+ ULONG Elcr2; // (0x08) (see IOD_ELCR2 in iod.h)
+ ULONG Reserved0; // (0x0c)
+} SYSTEM_MANAGEMENT_FRAME, *PSYSTEM_MANAGEMENT_FRAME;
+
+typedef union _SYSTEM_ENVIRONMENT {
+ struct {
+ ULONGLONG FanFailReg: 8; // <0:7> I2C Fain Fail Register
+ ULONGLONG SensorReg1: 8; // <8:15> I2C Sensor Register 1
+ ULONGLONG OpcControl: 8; // <16:23> I2C OPC Control
+ ULONGLONG SensorReg2: 8; // <24:31> I2C Sensor Register 2
+ ULONGLONG Reserved: 24; // <32:55> I2C Sensor Register 1
+ ULONGLONG FanFailValid: 1; // <56>
+ ULONGLONG SensorReg1Valid: 1; // <57>
+ ULONGLONG OpcControlValid: 1; // <58>
+ ULONGLONG SensorReg2Valid: 1; // <59>
+ };
+ ULONGLONG all;
+} SYSTEM_ENVIRONMENT, *PSYSTEM_ENVIRONMENT;
+
+
+//
+// ESC Frame
+//
+// This isn't just and ESC frame. EISA Id information is also contained herein.
+//
+// N.B. "index" refers to an indexed config ESC register accessed at index/data
+// ports 0x22/0x23.
+//
+
+
+typedef struct _ESC_FRAME {
+ UCHAR Id[4]; // (0x00) "ESC\0"
+ ULONG ByteCount; // (0x04) ???
+ UCHAR EscId; // (0x08) ESC ID Register (index 0x02)
+ UCHAR Filler0[7]; // (0x09-0x0f)
+ UCHAR Rid; // (0x0c) Revision Id (index 0x08)
+ UCHAR Filler1[3]; // (0x0d-0x0f)
+ UCHAR ModeSel; // (0x10) Mode Select Reg (index 0x40)
+ UCHAR Filler2[3]; // (0x11-0x13)
+ UCHAR EisaId[4]; // (0x14-0x17) EisaId of devices in EISA Slots
+ UCHAR SgRba; // (0x18) S-G Reloate Base Addr Reg (index 57)
+ UCHAR Filler3[3]; // (0x19-0x1b)
+ UCHAR Pirq[4]; // (0x1c-0x1f) PIRQ Route Ctrl (index 0x60-0x63)
+ UCHAR NmiSc; // (0x20) NMI Status & Ctrl (port 0x61)
+ UCHAR Filler4[3]; // (0x21-0x23)
+ UCHAR NmiEsc; // (0x24) NMI Ext. Status & Ctrl (port 0x461)
+ UCHAR Filler5[3]; // (0x25-0x27)
+ UCHAR LEisaMg; // (0x28) Last EISA Master Granted (port 0x464)
+ UCHAR Filler6[3]; // (0x29-0x2b)
+} ESC_FRAME, *PESC_FRAME;
+
+
+//
+// Rawhide Uncorrectable (Hard) Error Frame
+// Rawhide Correctable (Soft) Error Frame
+//
+
+typedef union _RAWHIDE_CORRECTABLE_FRAME {
+ ULONG Revision; // (0x00)
+ ULONG Reserved0; // (0x04)
+ ULONGLONG ErrorSubpacketFlags; // (0x08)
+ CUD_HEADER CudHeader; // (0x10-0x4f)
+ IOD_ERROR_FRAME IodErrorFrame; // (0x50-0xaf)
+ //
+ // Optional Error Subpackets // (0xb0)
+ // as per ErrorSubpackFlags
+ //
+} RAWHIDE_CORRECTABLE_FRAME, *PRAWHIDE_CORRECTABLE_FRAME,
+ RAWHIDE_UNCORRECTABLE_FRAME, *PRAWHIDE_UNCORRECTABLE_FRAME;
+
+#endif // _RAWERRORH_
diff --git a/private/ntos/nthals/halraw/alpha/rawhide.h b/private/ntos/nthals/halraw/alpha/rawhide.h
new file mode 100644
index 000000000..9d237a01e
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/rawhide.h
@@ -0,0 +1,349 @@
+/*++
+
+Copyright (c) 1995 Digital Equipment Corporation
+
+Module Name:
+
+ rawhide.h
+
+Abstract:
+
+ This file contains definitions specific to the Rawhide platform
+
+Author:
+
+ Eric Rehm 16-Feb-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#ifndef _RAWHIDEH_
+#define _RAWHIDEH_
+
+//
+// Include definitions for the components that make up Alcor.
+//
+
+#include "axp21164.h" // 21164 (EV5) microprocessor definitions
+#include "stdarg.h" // VarArgs support
+#include "iod.h" // CAP/MDP controller definitions
+#include "rwintbal.h" // Interrupt Balancing definitions
+#include "rwref.h" // Interrupt Vector Layout
+#include "bitmap.h" // Local copy of RTL bitmap routines
+
+#define CACHE_BLOCK_SIZE 0x40 // 64 byte cache line size
+
+//
+// Define number of PCI, EISA, and combo slots
+//
+// ecrfix - this is only good for PCI0
+//
+
+#define NUMBER_EISA_SLOTS 3
+#define NUMBER_PCI_SLOTS 4
+#define NUMBER_COMBO_SLOTS 1
+
+//
+// Define the data and csr ports for the I2C bus and OCP.
+//
+
+#define I2C_INTERFACE_DATA_PORT 0x530
+#define I2C_INTERFACE_CSR_PORT 0x531
+#define I2C_INTERFACE_LENGTH 0x2
+#define I2C_INTERFACE_MASK 0x1
+
+//
+// Define the index and data ports for the NS Super IO chip.
+//
+
+#define SUPERIO_INDEX_PORT 0x398
+#define SUPERIO_DATA_PORT 0x399
+#define SUPERIO_PORT_LENGTH 0x2
+
+//
+// Define the csr ports for Rawhide-specific Reset and Flash control
+//
+
+#define RAWHIDE_RESET_PORT 0x26
+#define RAWHIDE_FLASH_CONTROL_PORT 0x27
+
+//
+// PCI bus address values:
+//
+
+#define PCI_MAX_LOCAL_DEVICE 5
+#define PCI_MAX_INTERRUPT_VECTOR (MAXIMUM_PCI_VECTOR - PCI_VECTORS)
+
+//
+// PCI bus interrupt vector base value
+//
+
+#define RawhidePinToLineOffset 0x20
+
+//
+// Define the platform processor id type
+//
+
+typedef MC_DEVICE_ID HALP_PROCESSOR_ID, *PHALP_PROCESSOR_ID;
+
+extern HALP_PROCESSOR_ID HalpLogicalToPhysicalProcessor[];
+
+//
+// Define numbers and names of cpus.
+//
+
+#define RAWHIDE_PRIMARY_PROCESSOR ((ULONG) 0x0)
+#define RAWHIDE_MAXIMUM_PROCESSOR ((ULONG) 0x3)
+
+#define HAL_PRIMARY_PROCESSOR (RAWHIDE_PRIMARY_PROCESSOR)
+#define HAL_MAXIMUM_PROCESSOR (RAWHIDE_MAXIMUM_PROCESSOR)
+
+//
+// Define maximum number of MC-PCI bus bridges
+//
+
+#define RAWHIDE_MAXIMUM_PCI_BUS ((ULONG) 0x10)
+
+//
+// NCR810 SCSI device on PCI bus 1
+//
+
+#define RAWHIDE_SCSI_PCI_BUS ((ULONG) 0x01)
+
+//
+// Define default processor frequency.
+//
+
+#define DEFAULT_PROCESSOR_FREQUENCY_MHZ (250)
+
+//
+// Define Rawhide-specific routines that are really macros for performance.
+//
+
+#define HalpAcknowledgeEisaInterrupt(x) (UCHAR) (INTERRUPT_ACKNOWLEDGE(x))
+
+#if !defined (_LANGUAGE_ASSEMBLY)
+//
+// Define the per-processor data structures allocated in the PCR.
+//
+
+typedef struct _RAWHIDE_PCR{
+ ULONGLONG HalpCycleCount; // 64-bit per-processor cycle count
+ ULONGLONG IpirSva; // Superpage VA of per-perocessor IPIR CSR
+ PVOID CpuCsrsQva; // Qva of per-cpu csrs
+ EV5ProfileCount ProfileCount; // Profile counter state
+ PIOD_POSTED_INTERRUPT PostedInterrupts; // per-cpu area in vector table
+ } RAWHIDE_PCR, *PRAWHIDE_PCR;
+
+#define HAL_PCR ( (PRAWHIDE_PCR)(&(PCR->HalReserved)) )
+
+//
+// Rawhide Memory information.
+//
+
+typedef enum _RAWHIDE_MEMORY_TYPE {
+ RawhideMemoryFree, // Good memory
+ RawhideMemoryHole, // Hole memory
+ RawhideMemoryBad, // Bad memory
+ RawhideMemoryMaximum
+} RAWHIDE_MEMORY_TYPE;
+
+
+typedef struct _RAWHIDE_MEMORY_DESCRIPTOR {
+ RAWHIDE_MEMORY_TYPE MemoryType; // From above
+ ULONG BasePage; // Base page number
+ ULONG PageCount; // Number of pages in this descriptor
+ ULONG bTested; // TRUE if memory has been tested
+} RAWHIDE_MEMORY_DESCRIPTOR, *PRAWHIDE_MEMORY_DESCRIPTOR;
+
+
+//
+// Rawhide Resource Configuration Subpackets
+//
+// N.B. Only the System Platform Configuration Subpacket is defined
+//
+
+//
+// Echo data structure constructed for SRM FRU table
+//
+// N.B. Minimum value length is 4.
+//
+
+#define TAG_INVALID 0
+#define TAG_ISO_LATIN1 1
+#define TAG_QUOTED 2
+#define TAG_BINARY 3
+#define TAG_UNICODE 4
+#define TAG_RESERVED 5
+
+typedef struct _TLV {
+ USHORT Tag; // Code describing data type of field
+ USHORT Length; // Length of Value field in bytes (>=4)
+ ULONG Value; // Beginning of data
+} TLV, *PTLV;
+
+//
+// System Platform Configuration Subpacket
+//
+
+#define SYSTEM_CONFIGURATION_SUBPACKET_CLASS 1
+#define SYSTEM_PLATFORM_SUBPACKET_TYPE 1
+
+//
+// System Platform Configuration Subpacket
+// (As per Russ McManus Config & FRU Table doc, but no Environement Variables.)
+//
+// N.B., the length of this subpacket is variable due to TLV type fields.
+// Total length of the subpacket is available in the Length field.
+//
+// Any field that is invalid will have TLV.Tag = 0.
+//
+
+#if 0
+typedef struct _RAWHIDE_SYSTEM_CONFIGURATION {
+ USHORT Length; // (0x00) Total length of subpacket
+ USHORT Class; // (0x02) Subpacket class
+ USHORT Type; // (0x04) Subpacket type
+ USHORT Reserved; // (0x06)
+ TLV SystemManufacturer; // (0x08) System Manufacturer (string)
+ TLV SystemModel; // (....) Model Name (string)
+ TLV SystemSerialNumber; // (....) SystemSerialNumber (string)
+ TLV SystemRevisionLevel; // (....) SystemRevisionLevel (string)
+ TLV SystemVariation; // (....) SystemVariation
+ TLV ConsoleTypeRev; // (....) SRM Console Rev (string)
+} RAWHIDE_SYSTEM_CONFIGURATION, *PRAWHIDE_SYSTEM_CONFIGURATION;
+#endif
+
+//
+// System Platform Configuration Subpacket
+//
+// (If you prefer something simpler....)
+
+typedef struct _RAWHIDE_SYSTEM_CONFIGURATION {
+ ULONG ValidBits; // (0x00) Valid fields below
+ UCHAR SystemManufacturer[80]; // (0x04) System Manufacturer (string)
+ UCHAR SystemModel[80]; // (0x54) Model Name (string)
+ UCHAR SystemSerialNumber[16]; // (0xA4) SystemSerialNumber (string)
+ UCHAR SystemRevisionLevel[4]; // (0xB4) SystemRevisionLevel (string)
+ UCHAR SystemVariation[80]; // (0xB8) SystemVariation
+ UCHAR ConsoleTypeRev[80]; // (0x108) SRM Console Rev (string)
+} RAWHIDE_SYSTEM_CONFIGURATION, *PRAWHIDE_SYSTEM_CONFIGURATION;
+
+typedef union _RAWHIDE_SYSTEM_CONFIG_VALID_BITS {
+ struct {
+ ULONG SystemManufacturerValid: 1; // <0>
+ ULONG SystemModelValid: 1; // <1>
+ ULONG SystemSerialNumberValid: 1; // <2>
+ ULONG SystemRevisionLevel: 1; // <3>
+ ULONG SystemVariationValid: 1; // <4>
+ ULONG ConsoleTypeRevValid: 1; // <5>
+ };
+ ULONG all;
+} RAWHIDE_SYSTEM_CONFIG_VALID_BITS, *PRAWHIDE_SYSTEM_CONFIG_VALID_BITS;
+
+
+//
+// Define up to 64 Rawhide flags.
+//
+
+typedef union _RAWHIDE_FLAGS {
+ struct {
+ ULONGLONG CpuMaskValid: 1; // <0>
+ ULONGLONG GcdMaskValid: 1; // <1>
+ ULONGLONG IodMaskValid: 1; // <2>
+ ULONGLONG SystemConfigValid: 1; // <3>
+ ULONGLONG MemoryDescriptorValid: 1; // <4>
+ };
+ ULONGLONG all;
+} RAWHIDE_FLAGS, *PRAWHIDE_FLAGS;
+
+//
+// Define data structure for Rawhide machine dependent data
+//
+
+typedef struct _RAWHIDE_SYSTEM_CLASS_DATA {
+ ULONG Length; // (0x00) Length of Rawhide spec. data
+ ULONG Version; // (0x04) Initially 0x1
+ RAWHIDE_FLAGS Flags; // (0x08)
+ ULONGLONG CpuMask; // (0x10) <GID*8+MID> set if CPU presnt
+ ULONGLONG GcdMask; // (0x18) <GID*8+MID> set if GCD presnt
+ ULONGLONG IodMask; // (0x20) <GID*8+MID> set if IOD presnt
+ RAWHIDE_SYSTEM_CONFIGURATION SystemConfig; // (0x28) System config info
+ ULONG MemoryDescriptorCount; // (...)Number of memory descriptors
+ RAWHIDE_MEMORY_DESCRIPTOR MemoryDescriptor[1]; // (...) Array of descriptors
+} RAWHIDE_SYSTEM_CLASS_DATA, *PRAWHIDE_SYSTEM_CLASS_DATA;
+
+//
+// Rawhide interval timer data structure
+//
+
+typedef struct _CLOCK_TABLE {
+ ULONG RollOver;
+ ULONG TimeIncr;
+} CLOCK_TABLE, *PCLOCK_TABLE;
+
+#define NUM_CLOCK_RATES 4
+#define MAXIMUM_CLOCK_INCREMENT (NUM_CLOCK_RATES)
+#define MINIMUM_CLOCK_INCREMENT 1
+
+//
+// Rawhide interrupt routine prototypes.
+//
+
+BOOLEAN
+HalpAcknowledgeRawhideClockInterrupt(
+ VOID
+ );
+
+ULONG
+HalpGetRawhidePciInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+ULONG
+HalpGetRawhideEisaInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+ULONG
+HalpGetRawhideInternalInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+VOID
+HalpInitializeProcessorMapping(
+ IN ULONG LogicalProcessor,
+ IN ULONG PhysicalProcessor,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+VOID
+HalpInitializeSystemClassData(
+ ULONG Phase,
+ PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+#endif // !defined (_LANGUAGE_ASSEMBLY)
+
+#endif //_RAWHIDEH_
diff --git a/private/ntos/nthals/halraw/alpha/rwclock.c b/private/ntos/nthals/halraw/alpha/rwclock.c
new file mode 100644
index 000000000..69a27aa27
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/rwclock.c
@@ -0,0 +1,308 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ rwclock.c
+
+Abstract:
+
+ This module implements the code necessary to field and process the
+ interval clock interrupt.
+
+
+Author:
+
+ Eric Rehm 1-Dec-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "rawhide.h"
+
+//
+// Define global data used to communicate new clock rates to the clock
+// interrupt service routine.
+//
+
+ULONG HalpCurrentTimeIncrement;
+ULONG HalpNewTimeIncrement;
+
+ULONG HalpNextRateSelect;
+
+ULONG HalpCurrentRollOver[RAWHIDE_MAXIMUM_PROCESSOR+1];
+ULONG HalpNextRollOver;
+
+//
+// The Rawhide Interval Timer has an accuracy of 100 ppm:
+// Nominal: 833.3333 us
+// Min: 833.41668 us
+// Max: 833.25001 us
+//
+// The following clock table values indicated the number of actual
+// clock interrupts we should take before we tell the system the time
+// has changed (a.k.a "RollOver count"). Each RollOver count has
+// and associated time increment = INT(RollOver * 833.3333 * 10)
+// that is in units of 100 us.
+//
+// RollOver Time Nominal Error
+// Count Increment MS (ms/day)
+
+CLOCK_TABLE
+HalpRollOverTable[NUM_CLOCK_RATES] =
+ { {2, 16667}, // 1.667 ms
+ {3, 25000}, // 2.5 ms +0.864
+ {6, 50000}, // 5.0 ms +1.728
+ {9, 75000} // 7.5 ms +2.592
+
+// {12, 100000}, // 10.0 ms +3.456
+// {15, 125000}, // 12.5 ms +4.320
+// {18, 150000} // 15.0 ms +5.184
+// debug {1, 8334} // .8333 ms +287.7
+
+ };
+
+BOOLEAN
+HalpAcknowledgeRawhideClockInterrupt(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Acknowledge the clock interrupt from the interval timer. The interval
+ timer for Rawhide comes from an onboard oscillator, divided down
+ by the processor.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ MC_DEVICE_ID McDeviceId;
+ PKPRCB Prcb;
+
+
+ //
+ // Avoid a WhoAmI register read by using the PCR
+ //
+
+ Prcb = PCR->Prcb;
+ McDeviceId.all = HalpLogicalToPhysicalProcessor[Prcb->Number].all;
+
+ //
+ // Acknownledge the clock interrupt by writing to our own
+ // clock interrupt acknowledge.
+ //
+
+ CPU_CLOCK_ACKNOWLEDGE( McDeviceId );
+
+ //
+ // Has the roll-over counter expired for this processor's clock?
+ //
+
+ if ( (--HalpCurrentRollOver[Prcb->Number]) == 0 ) {
+
+ //
+ // Yes. Reset count to latest RollOver count and
+ // tell caller to do something.
+ //
+
+ HalpCurrentRollOver[Prcb->Number] = HalpNextRollOver;
+ return TRUE;
+ }
+
+ //
+ // No. Tell caller to do nothing.
+ //
+
+ return FALSE;
+
+
+}
+
+
+VOID
+HalpProgramIntervalTimer(
+ IN ULONG RateSelect
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to program the interval timer. It is used during
+ Phase 1 initialization to start the heartbeat timer. It also used by
+ the clock interrupt routine to change the hearbeat timer rate when a call
+ to HalSetTimeIncrement has been made in the previous time slice.
+
+Arguments:
+
+ RateSelect - Supplies rate select to be placed in the clock.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG i;
+
+ //
+ // Set the new rate via the global "next" roll-over count.
+ //
+ // When each processor's private roll-over counter
+ // (HalpCurrentRollOver[i]) expires, it will be reset to the
+ // this global "next" roll-over count;
+ //
+
+#if HALDBG
+ DbgPrint( "HalpProgramIntervalTimer: Set to new rate %d, RollOver %d\n",
+ RateSelect,
+ HalpRollOverTable[RateSelect-1].RollOver );
+#endif // HALDBG
+
+ HalpNextRollOver = HalpRollOverTable[RateSelect-1].RollOver;
+}
+
+
+VOID
+HalpSetTimeIncrement(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is responsible for setting the time increment for an EV5
+ based machine via a call into the kernel. This routine is
+ only called by the primary processor.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG i;
+
+ //
+ // Set the time increment value.
+ //
+
+
+ HalpCurrentTimeIncrement
+ = HalpRollOverTable[MAXIMUM_CLOCK_INCREMENT-1].TimeIncr;
+
+
+ for (i = 0; i <= RAWHIDE_MAXIMUM_PROCESSOR; i++) {
+ HalpCurrentRollOver[i] =
+ HalpRollOverTable[MAXIMUM_CLOCK_INCREMENT-1].RollOver;
+ }
+
+ HalpNextRollOver =
+ HalpRollOverTable[MAXIMUM_CLOCK_INCREMENT-1].RollOver;
+
+ HalpNextRateSelect = 0;
+
+ KeSetTimeIncrement( HalpRollOverTable[MAXIMUM_CLOCK_INCREMENT-1].TimeIncr,
+ HalpRollOverTable[MINIMUM_CLOCK_INCREMENT-1].TimeIncr);
+
+}
+
+ULONG
+HalSetTimeIncrement (
+ IN ULONG DesiredIncrement
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to set the clock interrupt rate to the frequency
+ required by the specified time increment value.
+
+Arguments:
+
+ DesiredIncrement - Supplies desired number of 100ns units between clock
+ interrupts.
+
+Return Value:
+
+ The actual time increment in 100ns units.
+
+--*/
+
+{
+ KIRQL OldIrql;
+ ULONG rate;
+ ULONG BestIndex;
+
+ //
+ // Raise IRQL to the highest level, set the new clock interrupt
+ // parameters, lower IRQl, and return the new time increment value.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // Find the allowed increment that is less than or equal to
+ // the desired increment.
+ //
+
+ for (rate = 1; rate < NUM_CLOCK_RATES; rate++) {
+ if (DesiredIncrement < HalpRollOverTable[rate].TimeIncr) {
+ break;
+ }
+ }
+
+ BestIndex = rate - 1;
+
+#if HALDBG
+ DbgPrint(
+ "HalSetTimeIncrement: Desired %d, BestIndex: %d TimeIncr %d RollOver %d \n",
+ DesiredIncrement,
+ BestIndex,
+ HalpRollOverTable[BestIndex].TimeIncr,
+ HalpRollOverTable[BestIndex].RollOver
+ );
+#endif // HALDBG
+
+ //
+ // Set the new time increment and the rate select (RollOverTable index)
+ // that will be used on the next tick of each processor's "soft"
+ // clock counter (HalpCurrentRollOver[i]).
+ //
+
+ HalpNewTimeIncrement = HalpRollOverTable[BestIndex].TimeIncr;
+ HalpNextRateSelect = BestIndex + 1;
+
+
+ KeLowerIrql(OldIrql);
+
+ return HalpNewTimeIncrement;
+
+}
+
+
+
+
diff --git a/private/ntos/nthals/halraw/alpha/rwinitnt.c b/private/ntos/nthals/halraw/alpha/rwinitnt.c
new file mode 100644
index 000000000..3ea569e93
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/rwinitnt.c
@@ -0,0 +1,1324 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ rwinitnt.c
+
+Abstract:
+
+
+ This module implements the platform-specific initialization for
+ a Rawhide system.
+
+Author:
+
+ Eric Rehm 4-May-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "rawhide.h"
+#include "iousage.h"
+#include "stdio.h"
+
+// Includes for Error Logging
+
+#include "fwcallbk.h" // To get firmware revisions
+#include <ntverp.h> // To O/S build number
+#include "errframe.h" // Error Frame Definitions
+
+//
+// Define extern global buffer for the Uncorrectable Error Frame.
+//
+
+extern PERROR_FRAME PUncorrectableError;
+
+extern IOD_REGISTER_CLASS DumpIodFlag;
+
+
+//
+// Define the Product Naming data.
+//
+
+PCHAR HalpFamilyName = "AlphaServer";
+PCHAR HalpProductName = "4000";
+ULONG HalpProcessorNumber = 5;
+
+#define MAX_INIT_MSG (80)
+
+PRAWHIDE_SYSTEM_CLASS_DATA HalpSystemClassData;
+ULONG HalpNumberOfIods;
+ULONG HalpNumberOfCpus;
+
+
+//
+// Define the bus type, this value allows us to distinguish between
+// EISA and ISA systems. We're only interested in distinguishing
+// between just those two buses.
+//
+
+ULONG HalpBusType = MACHINE_TYPE_EISA;
+
+//
+// Define external references.
+//
+
+extern ULONG HalDisablePCIParityChecking;
+
+//
+// Function prototypes.
+//
+
+VOID
+HalpInitializeProcessorParameters(
+ VOID
+ );
+
+BOOLEAN
+HalpInitializeRawhideInterrupts (
+ VOID
+ );
+
+VOID
+HalpParseLoaderBlock(
+ PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+VOID
+HalpRegisterPlatformResources(
+ PUCHAR HalName
+ );
+
+#if HALDBG
+VOID
+HalpDumpSystemClassData(
+ PRAWHIDE_SYSTEM_CLASS_DATA SystemClassData
+);
+#endif // HALDBG
+
+
+//
+// Irql mask and tables
+//
+// irql 0 - passive
+// irql 1 - sfw apc level
+// irql 2 - sfw dispatch level
+// irql 3 - device low
+// irql 4 - device high
+// irql 5 - interval clock
+// irql 6 - not used
+// irql 7 - error, mchk, nmi, performance counters
+//
+//
+
+//
+// The hardware interrupt pins are used as follows for Rawhide
+//
+// IRQ0 = Reserved (unused)
+// IRQ1 = IOD Interrupts (PCI, ESC, and CAP interrupts)
+// IRQ2 = Interval Clock
+// IRQ3 = IP Interrupt
+// SYS_MCH_CHK_IRQ = Duplicate TAG parity error (cached CUD only)
+// MCH_HLT_IRQ = Halt button or CPU halt
+//
+
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes interrupts for an Alcor system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the initialization is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+ extern ULONG Halp21164CorrectedErrorInterrupt();
+ extern VOID HalpCacheErrorInterrupt();
+ extern ULONG HalpDeviceInterrupt();
+#if !defined(NT_UP)
+ extern VOID HalpIpiInterruptHandler();
+#endif //NT_UP
+ extern ULONG HalpHaltInterrupt();
+ PKPRCB Prcb;
+ ULONG Vector;
+
+ Prcb = PCR->Prcb;
+
+ //
+ // Initialize interrupt handling for the primary processor and
+ // any system-wide interrupt initialization.
+ //
+
+ if( Prcb->Number == HAL_PRIMARY_PROCESSOR ){
+
+#if HALDBG
+ DbgPrint("HalpInitializeInterrupts: Primary Processor\n");
+#endif // HALDBG
+ //
+ // Initialize HAL processor parameters based on estimated CPU speed.
+ // This must be done before HalpStallExecution is called. Compute integral
+ // megahertz first to avoid rounding errors due to imprecise cycle clock
+ // period values.
+ //
+
+#if HALDBG
+ DbgPrint("HalpInitializeInterrupts: Init Processor Params\n");
+#endif // HALDBG
+ HalpInitializeProcessorParameters();
+
+ //
+ // Start the periodic interrupt from the RTC
+ //
+
+#if HALDBG
+ DbgPrint("HalpInitializeInterrupts: Program Interval Timer\n");
+#endif // HALDBG
+ HalpProgramIntervalTimer(MAXIMUM_CLOCK_INCREMENT);
+
+ //
+ // Initialize Rawhide interrupts.
+ //
+
+#if HALDBG
+ DbgPrint("HalpInitializeInterrupts: Init Rawhide Interrupts\n");
+#endif // HALDBG
+ HalpInitializeRawhideInterrupts();
+
+ //
+ // Initialize the EV5 (21164) interrupts.
+ //
+
+#if HALDBG
+ DbgPrint("HalpInitializeInterrupts: Init 21164 Interrupts\n");
+#endif // HALDBG
+ HalpInitialize21164Interrupts();
+
+#if HALDBG
+ DbgPrint("HalpInitializeInterrupts: Init IDT entries\n");
+#endif // HALDBG
+#if 0
+ PCR->InterruptRoutine[EV5_IRQ0_VECTOR] = // IRQ0 is unused on Rawhide
+ (PKINTERRUPT_ROUTINE) NULL;
+#endif
+
+ PCR->InterruptRoutine[EV5_IRQ1_VECTOR] = // IOD Interrupt
+ (PKINTERRUPT_ROUTINE)HalpDeviceInterrupt;
+
+ PCR->InterruptRoutine[EV5_IRQ2_VECTOR] = // Interval Timer Interrupt
+ (PKINTERRUPT_ROUTINE)HalpClockInterrupt;
+
+#if !defined(NT_UP)
+ PCR->InterruptRoutine[EV5_IRQ3_VECTOR] = // IP Interrupt
+ (PKINTERRUPT_ROUTINE)HalpIpiInterruptHandler;
+#endif //NT_UP
+
+ PCR->InterruptRoutine[EV5_HALT_VECTOR] = // Halt button, CPU halt
+ (PKINTERRUPT_ROUTINE)HalpHaltInterrupt;
+
+ PCR->InterruptRoutine[EV5_MCHK_VECTOR] = // Duplicate TAG Parity Error
+ (PKINTERRUPT_ROUTINE)HalpCacheErrorInterrupt; // (cached CUD only).
+
+#if HALDBG
+ DbgPrint("HalpInitializeInterrupts: Start 21164 Interrupts\n");
+#endif // HALDBG
+ HalpStart21164Interrupts();
+
+#if HALDBG
+ DumpAllIods(DumpIodFlag & IodInterruptRegisters);
+
+ DbgPrint("HalpInitializeInterrupts: Primary Processor Complete\n");
+#endif // HALDBG
+
+ } else {
+
+#if !defined(NT_UP)
+#if HALDBG
+ DbgPrint("HalpInitializeInterrupts: Secondary Processor\n");
+#endif // HALDBG
+
+ //
+
+ //
+ // Initialize the EV5 (21164) interrupts.
+ //
+
+ HalpInitialize21164Interrupts();
+
+#if 0
+ PCR->InterruptRoutine[EV5_IRQ0_VECTOR] = // IRQ0 is unused on Rawhide
+ (PKINTERRUPT_ROUTINE) NULL;
+#endif
+
+ PCR->InterruptRoutine[EV5_IRQ1_VECTOR] = // IOD Interrupt
+ (PKINTERRUPT_ROUTINE)HalpDeviceInterrupt;
+
+ PCR->InterruptRoutine[EV5_IRQ2_VECTOR] = // Interval Timer Interrupt
+ (PKINTERRUPT_ROUTINE)HalpSecondaryClockInterrupt;
+
+ PCR->InterruptRoutine[EV5_IRQ3_VECTOR] = // IP Interrupt
+ (PKINTERRUPT_ROUTINE)HalpIpiInterruptHandler;
+
+ PCR->InterruptRoutine[EV5_HALT_VECTOR] = // Halt button, CPU halt
+ (PKINTERRUPT_ROUTINE)HalpHaltInterrupt;
+
+ PCR->InterruptRoutine[EV5_MCHK_VECTOR] = // Duplicate TAG Parity Error
+ (PKINTERRUPT_ROUTINE)HalpCacheErrorInterrupt; // (cached CUD only).
+
+ HalpStart21164Interrupts();
+#endif //NT_UP
+ }
+
+ return TRUE;
+
+}
+
+
+
+
+VOID
+HalpInitializeClockInterrupts(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called during phase 1 initialization to complete
+ the initialization of clock interrupts. For EV4, this function
+ connects the true clock interrupt handler and initializes the values
+ required to handle profile interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+#if 0
+// mdbfix - who references this?
+ //
+ // Compute the profile interrupt rate.
+ //
+
+ HalpProfileCountRate = ((1000 * 1000 * 10) / KeQueryTimeIncrement());
+#endif
+
+ //
+ // Set the time increment value and connect the real clock interrupt
+ // routine.
+ //
+
+ PCR->InterruptRoutine[EV5_IRQ2_VECTOR] = HalpClockInterrupt;
+
+ return;
+}
+
+
+VOID
+HalpEstablishErrorHandler(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine performs the initialization necessary for the HAL to
+ begin servicing machine checks.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ BOOLEAN PciParityChecking;
+ BOOLEAN ReportCorrectables;
+
+ //
+ // Connect the machine check handler via the PCR.
+ //
+
+ PCR->MachineCheckError = HalMachineCheck;
+
+ HalpInitializeIodMachineChecks( ReportCorrectables = FALSE,
+ PciParityChecking = FALSE );
+
+ return;
+}
+
+
+VOID
+HalpInitializeSystemClassData(
+ ULONG Phase,
+ PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+
+ Initialize the Rawhide configuration masks passed in the ARC tree.
+ For phase 0, only initialize the hardware masks. Wait until phase 1,
+ (after memory manager started) to allocate and save.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PCONFIGURATION_COMPONENT_DATA ConfigComponent;
+ PRAWHIDE_SYSTEM_CLASS_DATA SystemClassData;
+ MC_ENUM_CONTEXT mcCtx;
+
+ ConfigComponent = KeFindConfigurationEntry(
+ LoaderBlock->ConfigurationRoot,
+ SystemClass, // Class
+ ArcSystem, // Type
+ 0
+ );
+
+ //
+ // Check for errors
+ //
+
+ if ( (ConfigComponent == NULL) ||
+ (ConfigComponent->ConfigurationData == NULL) ) {
+
+#if HALDBG
+ DbgPrint ("HalpInitializeSystemClassData: Configuration Data Missing\n");
+ DbgBreakPoint ();
+#endif // HALDBG
+ }
+
+
+ SystemClassData = (PRAWHIDE_SYSTEM_CLASS_DATA)
+ ConfigComponent->ConfigurationData;
+
+ if (Phase == 0) {
+
+#if HALDBG
+ HalpDumpSystemClassData(SystemClassData);
+#endif
+
+ //
+ // Initialize the rawhide configuration masks
+ //
+
+ HalpIodMask = SystemClassData->IodMask;
+ HalpCpuMask = SystemClassData->CpuMask;
+ HalpGcdMask = SystemClassData->GcdMask;
+
+ HalpNumberOfIods = HalpMcBusEnumStart(HalpIodMask, &mcCtx);
+ HalpNumberOfCpus = HalpMcBusEnumStart(HalpCpuMask, &mcCtx);
+
+ } else {
+
+ //
+ // Allocate memory and save
+ //
+
+ HalpSystemClassData = (PRAWHIDE_SYSTEM_CLASS_DATA)
+ ExAllocatePool(NonPagedPool, SystemClassData->Length);
+
+ RtlMoveMemory(
+ HalpSystemClassData,
+ ConfigComponent->ConfigurationData,
+ SystemClassData->Length
+ );
+ }
+
+}
+
+#if HALDBG
+VOID
+HalpDumpSystemClassData(
+ PRAWHIDE_SYSTEM_CLASS_DATA SystemClassData
+ )
+{
+
+#define ONE_MB 1024
+
+ ULONG entry;
+ ULONGLONG TotalMemorySize;
+ ULONGLONG FreeMemorySize;
+ ULONGLONG BadMemorySize;
+ ULONGLONG EntrySizeInBytes;
+
+ //
+ // Print out machine dependent data for debug
+ //
+
+ DbgPrint("System Class Data:\r\n");
+ DbgPrint("Length: %x\n", SystemClassData->Length);
+ DbgPrint("Version: %x\n", SystemClassData->Version);
+ DbgPrint("Flags: %8.8x %8.8x\n", SystemClassData->Flags.all >> 32,
+ SystemClassData->Flags);
+ DbgPrint("CpuMask: %8.8x %8.8x\n", SystemClassData->CpuMask >> 32,
+ SystemClassData->CpuMask);
+ DbgPrint("GcdMask: %8.8x %8.8x\n", SystemClassData->GcdMask >> 32,
+ SystemClassData->GcdMask);
+ DbgPrint("IodMask: %8.8x %8.8x\n", SystemClassData->IodMask >> 32,
+ SystemClassData->IodMask);
+ DbgPrint("System Configuration:\n");
+ DbgPrint("\tValidBits: %x\n", SystemClassData->SystemConfig.ValidBits);
+
+ DbgPrint("\tSystemManufacturer: %s\r\n",
+ SystemClassData->SystemConfig.SystemManufacturer);
+
+ DbgPrint("\tSystemModel: %s\r\n",
+ SystemClassData->SystemConfig.SystemModel);
+
+ DbgPrint("\tSystemSerialNumber: %s\r\n",
+ SystemClassData->SystemConfig.SystemSerialNumber);
+
+ DbgPrint("\tSystemRevisionLevel: %s\r\n",
+ SystemClassData->SystemConfig.SystemRevisionLevel);
+
+ DbgPrint("\tSystemVariation: %s\r\n",
+ SystemClassData->SystemConfig.SystemVariation);
+
+ DbgPrint("\tSystemConsoleTypeRev: %s\r\n",
+ SystemClassData->SystemConfig.ConsoleTypeRev);
+
+ DbgPrint("MemoryDescriptor is: %s\r\n",
+ (SystemClassData->Flags.MemoryDescriptorValid ?
+ "Valid" : "Invalid"));
+ DbgPrint("MemoryDescriptorCount: %d\r\n",
+ SystemClassData->MemoryDescriptorCount);
+
+ DbgPrint("MemoryDescriptor is: %s\n",
+ (SystemClassData->Flags.MemoryDescriptorValid ?
+ "Valid" : "Invalid"));
+ DbgPrint("MemoryDescriptorCount: %d\n", SystemClassData->MemoryDescriptorCount);
+
+ DbgPrint("Descriptor\tMemoryType\tBasePage\tPageCount\tSize\tTested?\n");
+
+ TotalMemorySize = 0;
+ FreeMemorySize = 0;
+ BadMemorySize = 0;
+
+ for (entry = 0; entry < SystemClassData->MemoryDescriptorCount; entry++) {
+
+ EntrySizeInBytes =
+ (SystemClassData->MemoryDescriptor[entry].PageCount) << PAGE_SHIFT;
+
+ DbgPrint("[%d]\t\t%d\t\t%x\t\t%8x\t%4d Mb %x\n",
+ entry,
+ SystemClassData->MemoryDescriptor[entry].MemoryType,
+ SystemClassData->MemoryDescriptor[entry].BasePage,
+ SystemClassData->MemoryDescriptor[entry].PageCount,
+ (EntrySizeInBytes / ONE_MB),
+ SystemClassData->MemoryDescriptor[entry].bTested
+ );
+
+ //
+ // Total up free (good memory) entries
+ //
+
+ if (SystemClassData->MemoryDescriptor[entry].MemoryType
+ == RawhideMemoryFree) {
+ FreeMemorySize += EntrySizeInBytes;
+ }
+
+ //
+ // Total up hole (bad memory) entries
+ // Remember them so that they can be removed later.
+ //
+
+ if (SystemClassData->MemoryDescriptor[entry].MemoryType
+ == RawhideMemoryBad) {
+
+ //
+ // N.B. If this is the last descriptor, and it's a hole
+ // (bad memory), then ignore it.
+ //
+
+ if (entry == (SystemClassData->MemoryDescriptorCount - 1)) {
+ break;
+ }
+
+ BadMemorySize += EntrySizeInBytes;
+
+ }
+
+ //
+ // Total up all entries, except a trailing hole
+ //
+
+ TotalMemorySize += EntrySizeInBytes;
+
+
+ }
+
+ DbgPrint("Total Size:\t\t\t\t\t%8x\t%4d Mb\n\n",
+ (TotalMemorySize >> PAGE_SHIFT),
+ (TotalMemorySize / ONE_MB));
+ DbgPrint("Free Memory Size:\t\t\t\t%8x\t%4d Mb\n",
+ (FreeMemorySize >> PAGE_SHIFT),
+ (FreeMemorySize / ONE_MB));
+ DbgPrint("Bad Memory Size:\t\t\t\t%8x\t%4d Mb\n",
+ (BadMemorySize >> PAGE_SHIFT),
+ (BadMemorySize / ONE_MB));
+
+}
+#endif // HALDBG
+
+
+VOID
+HalpEarlyInitializeMachineDependent(
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+
+ This function performs any critical Platform-specific initialization based on
+ the current phase on initialization.
+
+Arguments:
+
+ Phase - Supplies an indicator for phase of initialization, phase 0 or
+ phase 1.
+
+ LoaderBlock - supplies a pointer to the loader block.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ if( Phase == 0 ){
+
+ //
+ // Phase 0 Initialization.
+ //
+
+ //
+ // Initialize the Rawhide hardware configuration masks from the
+ // SRM Machine Dependent Data passed in the Configuration Tree.
+ //
+
+ HalpInitializeSystemClassData(Phase, LoaderBlock);
+
+ } else {
+
+ //
+ // Phase 1 Initialization.
+ //
+
+ }
+
+ return;
+
+}
+
+
+VOID
+HalpInitializeMachineDependent(
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+
+ This function performs any Platform-specific initialization based on
+ the current phase on initialization.
+
+Arguments:
+
+ Phase - Supplies an indicator for phase of initialization, phase 0 or
+ phase 1.
+
+ LoaderBlock - supplies a pointer to the loader block.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG BusIrql;
+ ULONG BusNumber;
+ UCHAR MsgBuffer[MAX_INIT_MSG];
+ BOOLEAN ReportCorrectables;
+ BOOLEAN PciParityChecking;
+ PKPRCB Prcb;
+ PRAWHIDE_PCR pRawhidePcr;
+ IOD_POSTED_INTERRUPT_ADDR PostingTable;
+ IOD_WHOAMI IodWhoAmI;
+
+ Prcb = PCR->Prcb;
+
+#if HALDBG
+ DbgPrint("HalpInitializeMachineDependent: Phase = %d\n", Phase);
+#endif // HALDBG
+
+ if( Prcb->Number == HAL_PRIMARY_PROCESSOR) {
+
+ if( Phase == 0 ){
+
+
+ //
+ // Phase 0 Initialization.
+ //
+
+ //
+ // Parse the Loader Parameter block looking for PCI entry to determine
+ // if PCI parity should be disabled
+ //
+
+#if HALDBG
+ DbgPrint("HalpInitializeMachineDependent: Parse Loader Block\n");
+#endif // HALDBG
+ HalpParseLoaderBlock( LoaderBlock );
+
+ //
+ // Establish the error handler, to reflect the PCI parity checking.
+ //
+
+#if HALDBG
+ DbgPrint("HalpInitializeMachineDependent: \n");
+#endif // HALDBG
+ if( HalDisablePCIParityChecking != 0 ){
+ PciParityChecking = FALSE;
+ } else {
+ PciParityChecking = TRUE;
+ }
+
+#if HALDBG
+ DbgPrint("HalpInitializeMachineDependent: Init Iod Machine Checks\n");
+#endif // HALDBG
+ HalpInitializeIodMachineChecks( ReportCorrectables = TRUE,
+ PciParityChecking );
+
+ //
+ // Initialize the IOD mapping table, assigning logical
+ // numbers to all IOD's. This logical number cooresponds
+ // to the HwBusNumber found in PCIPBUSDATA.
+ //
+
+#if HALDBG
+ DbgPrint("HalpInitializeMachineDependent: Init Iod Mapping Table\n");
+#endif // HALDBG
+ HalpMcBusEnumAndCall(HalpIodMask, HalpInitializeIodMappingTable);
+
+ //
+ // Initialize the logical to physical processor mapping
+ // for the primary processor.
+ //
+
+#if HALDBG
+ DbgPrint("HalpInitializeMachineDependent: Init HalpLogicalToPhysicalProcesor\n");
+#endif // HALDBG
+
+ HalpInitializeProcessorMapping(
+ HAL_PRIMARY_PROCESSOR,
+ HAL_PRIMARY_PROCESSOR,
+ LoaderBlock
+ );
+
+#if HALDBG
+ DbgPrint("HalpInitializeMachineDependent: Phase %d complete\n", Phase);
+#endif // HALDBG
+ } else {
+
+ //
+ // Phase 1 Initialization.
+ //
+
+ //
+ // Save the Machine Dependent Data now that Memory Manager started.
+ //
+
+#if HALDBG
+ DbgPrint("HalpInitializeMachineDependent: Init System Class Data\n");
+#endif // HALDBG
+ HalpInitializeSystemClassData(Phase, LoaderBlock);
+
+ //
+ // Initialize the existing bus handlers.
+ //
+
+#if HALDBG
+ DbgPrint("HalpInitializeMachineDependent: Register Internal Bus Handlers\n");
+#endif // HALDBG
+ HalpRegisterInternalBusHandlers();
+
+ //
+ // Initialize PCI Bus.
+ //
+
+#if HALDBG
+ DbgPrint("HalpInitializeMachineDependent: Init PCI Bus\n");
+#endif // HALDBG
+ HalpInitializePCIBus(LoaderBlock);
+
+ //
+ // Initialize the IOD vector table
+ //
+
+#if HALDBG
+ DbgPrint("HalpInitializeMachineDependent: Init Iod Vector Table\n");
+#endif // HALDBG
+ HalpInitializeIodVectorTable();
+
+ //
+ // Initialize the IOD interrupt vector table CSR's
+ //
+
+#if HALDBG
+ DbgPrint("HalpInitializeMachineDependent: Init Iod Vector CSRs\n");
+#endif // HALDBG
+ HalpMcBusEnumAndCall(HalpIodMask, HalpInitializeIodVectorCSRs);
+
+ //
+ // Generate pointer to the CPU's area in the IOD vector table
+ //
+
+ PostingTable.all = 0;
+ PostingTable.Base4KPage = ((ULONG)HalpIodPostedInterrupts / __4K);
+ PostingTable.CpuOffset =
+ HalpLogicalToPhysicalProcessor[PCR->Number].all;
+
+ HAL_PCR->PostedInterrupts =
+ (PIOD_POSTED_INTERRUPT)PostingTable.all;
+
+ //
+ // Initialize the IOD and CPU interrupt Vector table
+ //
+
+ HalpInitializeVectorBalanceData();
+
+ //
+ // Initialize the CPU vector entry for this processor
+ //
+
+ HalpInitializeCpuVectorData(PCR->Number);
+
+ //
+ // Assign the primary processors vectors
+ //
+
+ HalpAssignPrimaryProcessorVectors(&HalpIodVectorDataHead);
+
+ //
+ // Initialize profiler.
+ //
+
+#if HALDBG
+ DbgPrint("HalpInitializeMachineDependent: Init Profiler\n");
+#endif // HALDBG
+ HalpInitializeProfiler();
+
+#if HALDBG
+ DbgPrint("HalpInitializeMachineDependent: Print Version Message\n");
+#endif // HALDBG
+ //
+ // Print a message with version number.
+ //
+
+ sprintf( MsgBuffer,
+ "Digital Equipment Corporation %s %s %d/%d\n",
+ HalpFamilyName,
+ HalpProductName,
+ HalpProcessorNumber,
+ HalpClockMegaHertz );
+
+ HalDisplayString( MsgBuffer );
+
+ //
+ // Register the name of the HAL.
+ //
+
+ sprintf( MsgBuffer,
+ "%s %s %d/%d PCI/EISA HAL",
+ HalpFamilyName,
+ HalpProductName,
+ HalpProcessorNumber,
+ HalpClockMegaHertz );
+
+#if HALDBG
+ DbgPrint("HalpInitializeMachineDependent: Register Platform Resources\n");
+#endif // HALDBG
+ HalpRegisterPlatformResources( MsgBuffer );
+
+#if HALDBG
+ DbgPrint("HalpInitializeMachineDependent: Phase %d Complete\n", Phase);
+#endif // HALDBG
+ }
+
+ } else {
+
+ //
+ // Connect the machine check handler via the PCR. The machine check
+ // handler for Rawhide is the default EV4 parity-mode handler. Note
+ // that this was done in HalpEstablishErrorHandler() for the
+ // primary processor.
+ //
+
+ PCR->MachineCheckError = HalMachineCheck;
+
+ //
+ // Generate pointer to the CPU's area in the IOD vector table
+ //
+
+ PostingTable.all = 0;
+ PostingTable.Base4KPage = ((ULONG)HalpIodPostedInterrupts / __4K);
+ PostingTable.CpuOffset = HalpLogicalToPhysicalProcessor[PCR->Number].all;
+
+ HAL_PCR->PostedInterrupts = (PIOD_POSTED_INTERRUPT)PostingTable.all;
+
+ //
+ // Initialize profiler on this secondary processor.
+ //
+
+ HalpInitializeProfiler();
+
+ //
+ // Initialize the CPU vector entry for this processor
+ //
+
+ HalpInitializeCpuVectorData(PCR->Number);
+
+ }
+
+ return;
+
+}
+
+
+VOID
+HalpInitializeProcessorMapping(
+ IN ULONG LogicalProcessor,
+ IN ULONG PhysicalProcessor,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+
+ This function initializes the logical to physical processor mapping
+ entry in the processor mapping table. The physical mapping is passed
+ by ARC FW via the configuration tree.
+
+Arguments:
+
+ LogicalProcessor - logical processor number.
+
+ PhysicalProcessor - restart block number.
+
+ LoaderBlock - supplies a pointer to the loader block.
+
+Return Value:
+
+ None.
+
+--*/
+
+
+{
+ PCONFIGURATION_COMPONENT_DATA CpuConfigComponent;
+ PHALP_PROCESSOR_ID HalpProcessorId;
+
+ //
+ // If the processor is not ready then we assume that it is not
+ // present. We must increment the physical processor number but
+ // the logical processor number does not changed.
+ //
+
+ //
+ // Get a pointer to the configuration entry for this processor.
+ // The configuration data will contain the processors MC device ID.
+ //
+
+ CpuConfigComponent = KeFindConfigurationEntry(
+ LoaderBlock->ConfigurationRoot,
+ ProcessorClass,
+ CentralProcessor,
+ &PhysicalProcessor
+ );
+
+ //
+ // Check for errors.
+ //
+
+ if ( (CpuConfigComponent == NULL) ||
+ (CpuConfigComponent->ConfigurationData == NULL) ) {
+
+#if 0 //HALDBG
+ DbgPrint ("HalStartNextProcessor: Configuration Data Missing\n");
+#endif //HALDBG
+ // What to do now?
+ DbgBreakPoint ();
+ }
+
+ //
+ // Obtain a pointer to the processor Id from the configuration data.
+ //
+
+ HalpProcessorId =
+ ((PHALP_PROCESSOR_ID)CpuConfigComponent->ConfigurationData);
+
+ //
+ // Initialize the table entry for this processor.
+ //
+
+ HalpLogicalToPhysicalProcessor[LogicalProcessor].all = HalpProcessorId->all;
+
+}
+
+VOID
+HalpRegisterPlatformResources(
+ PUCHAR HalName
+ )
+/*++
+
+Routine Description:
+
+ Register I/O resources used by the HAL.
+
+Arguments:
+
+ HalName - Supplies a pointer to the name for the HAL.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ RESOURCE_USAGE Resource;
+
+ //
+ // Register the buses.
+ //
+
+ HalpRegisterBusUsage(Internal);
+ HalpRegisterBusUsage(Eisa);
+ HalpRegisterBusUsage(Isa);
+ HalpRegisterBusUsage(PCIBus);
+
+ //
+ // Register the name of the HAL.
+ //
+
+ HalpRegisterHalName( HalName );
+
+ //
+ // Register the interrupt vector used for the cascaded interrupt
+ // on the 8254s.
+ //
+
+ Resource.BusType = Isa;
+ Resource.BusNumber = 0;
+ Resource.ResourceType = CmResourceTypeInterrupt;
+ Resource.u.InterruptMode = Latched;
+ Resource.u.BusInterruptVector = 2;
+ Resource.u.SystemInterruptVector = 2;
+ Resource.u.SystemIrql = 2;
+ HalpRegisterResourceUsage(&Resource);
+
+ //
+ // Register machine specific io/memory addresses.
+ //
+
+ Resource.BusType = Isa;
+ Resource.BusNumber = 0;
+ Resource.ResourceType = CmResourceTypePort;
+
+#if 0
+ Resource.u.Start = I2C_INTERFACE_DATA_PORT;
+ Resource.u.Length = I2C_INTERFACE_LENGTH;
+ HalpRegisterResourceUsage(&Resource);
+#endif
+
+ Resource.u.Start = SUPERIO_INDEX_PORT;
+ Resource.u.Length = SUPERIO_PORT_LENGTH;
+ HalpRegisterResourceUsage(&Resource);
+
+ //
+ // Register the DMA channel used for the cascade.
+ //
+
+ Resource.BusType = Isa;
+ Resource.BusNumber = 0;
+ Resource.ResourceType = CmResourceTypeDma;
+ Resource.u.DmaChannel = 0x4;
+ Resource.u.DmaPort = 0x0;
+ HalpRegisterResourceUsage(&Resource);
+}
+
+
+//
+//jnfix
+//
+// This routine is bogus and does not apply to Alcor and the call should be
+// ripped out of fwreturn (or at least changed to something that is more
+// abstract).
+//
+
+VOID
+HalpResetHAERegisters(
+ VOID
+ )
+{
+ return;
+}
+
+VOID
+HalpGetMachineDependentErrorFrameSizes(
+ PULONG RawProcessorSize,
+ PULONG RawSystemInfoSize
+ )
+/*++
+
+Routine Description:
+
+ This function returns the size of the system specific structures.
+
+
+Arguments:
+
+ RawProcessorSize - Pointer to a buffer that will receive the
+ size of the processor specific error information buffer.
+
+ RawSystemInfoSize - Pointer to a buffer that will receive the
+ size of the system specific error information buffer.
+
+Return Value:
+
+ none
+
+--*/
+{
+ *RawProcessorSize = sizeof(PROCESSOR_EV5_UNCORRECTABLE);
+ *RawSystemInfoSize = sizeof(RAWHIDE_UNCORRECTABLE_FRAME)
+ + HalpNumberOfIods * sizeof(IOD_ERROR_FRAME);
+
+ //
+ // ecrfix - will have to figure out something else for
+ // PCI, ESC snapshots and System Mgmt Frame.
+ //
+
+ return;
+}
+
+VOID
+HalpGetSystemInfo(SYSTEM_INFORMATION *SystemInfo)
+/*++
+
+Routine Description:
+
+ This function fills in the System information.
+
+
+Arguments:
+
+ SystemInfo - Pointer to the SYSTEM_INFORMATION buffer that needs
+ to be filled in.
+
+Return Value:
+
+ none
+
+--*/
+{
+ char systemtype[] = "Rawhide";
+ EXTENDED_SYSTEM_INFORMATION FwExtSysInfo;
+
+
+ VenReturnExtendedSystemInformation(&FwExtSysInfo);
+
+ RtlCopyMemory(SystemInfo->FirmwareRevisionId,
+ FwExtSysInfo.FirmwareVersion,
+ 16);
+
+
+ RtlCopyMemory(SystemInfo->SystemType, systemtype, 8);
+
+ SystemInfo->ClockSpeed =
+ ((1000 * 1000) + (PCR->CycleClockPeriod >> 1)) / PCR->CycleClockPeriod;
+
+ SystemInfo->SystemRevision = PCR->SystemRevision;
+
+// RtlCopyMemory(SystemInfo->SystemSerialNumber,
+// PCR->SystemSerialNumber,
+// 16);
+
+ SystemInfo->SystemVariant = PCR->SystemVariant;
+
+
+ SystemInfo->PalMajorVersion = PCR->PalMajorVersion;
+ SystemInfo->PalMinorVersion = PCR->PalMinorVersion;
+
+ SystemInfo->OsRevisionId = VER_PRODUCTBUILD;
+
+ //
+ // For now fill in dummy values.
+ //
+ SystemInfo->ModuleVariant = 1UL;
+ SystemInfo->ModuleRevision = 1UL;
+ SystemInfo->ModuleSerialNumber = 0;
+
+ return;
+}
+
+
+VOID
+HalpInitializeUncorrectableErrorFrame (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function Allocates an Uncorrectable Error frame for this
+ system and initializes the frame with certain constant/global
+ values.
+
+ This is routine called during machine dependent system
+ Initialization.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ none
+
+--*/
+{
+ PRAWHIDE_UNCORRECTABLE_FRAME rawerr;
+
+ //
+ // If the Uncorrectable error buffer is not set then simply return
+ //
+
+ if(PUncorrectableError == NULL)
+ return;
+
+ PUncorrectableError->Signature = ERROR_FRAME_SIGNATURE;
+
+ PUncorrectableError->FrameType = UncorrectableFrame;
+
+ //
+ // ERROR_FRAME_VERSION is define in errframe.h and will
+ // change as and when there is a change in the errframe.h.
+ // This Version number helps the service, that reads this
+ // information from the dumpfile, to check if it knows about
+ // this frmae version type to decode. If it doesn't know, it
+ // will dump the entire frame to the EventLog with a message
+ // "Error Frame Version Mismatch".
+ //
+
+ PUncorrectableError->VersionNumber = ERROR_FRAME_VERSION;
+
+ //
+ // The sequence number will always be 1 for Uncorrectable errors.
+ //
+
+ PUncorrectableError->SequenceNumber = 1;
+
+ //
+ // The PerformanceCounterValue field is not used for Uncorrectable
+ // errors.
+ //
+
+ PUncorrectableError->PerformanceCounterValue = 0;
+
+ //
+ // We will fill in the UncorrectableFrame.SystemInfo here.
+ //
+ HalpGetSystemInfo(&PUncorrectableError->UncorrectableFrame.System);
+
+ PUncorrectableError->UncorrectableFrame.Flags.SystemInformationValid = 1;
+
+ //
+ // Fill in Common RCUD Header
+ //
+
+ rawerr = (PRAWHIDE_UNCORRECTABLE_FRAME)
+ PUncorrectableError->UncorrectableFrame.RawSystemInformation;
+
+ strncpy( PUncorrectableError->UncorrectableFrame.System.SystemSerialNumber,
+ HalpSystemClassData->SystemConfig.SystemSerialNumber, 10);
+
+ strncpy( rawerr->CudHeader.SystemSN,
+ HalpSystemClassData->SystemConfig.SystemSerialNumber, 10);
+
+ strncpy( rawerr->CudHeader.SystemRev,
+ HalpSystemClassData->SystemConfig.SystemRevisionLevel, 4);
+
+ // Jam the SRM console revision in the Module SN
+
+ strncpy( rawerr->CudHeader.ModuleSN,
+ HalpSystemClassData->SystemConfig.ConsoleTypeRev, 9);
+ rawerr->CudHeader.ModuleSN[9] = '\0';
+
+ // Jam the first 5 chars of System Model (4x00, etc.) in a reserved field
+
+ strncpy( rawerr->CudHeader.Reserved2,
+ HalpSystemClassData->SystemConfig.SystemModel, 5);
+ rawerr->CudHeader.Reserved2[5] = '\0';
+
+ //
+ // The following RCUD header data is not valid for Windows NT.
+ //
+
+ rawerr->CudHeader.HwRevision = 0;
+ rawerr->CudHeader.ModType = 0;
+ rawerr->CudHeader.DisabledResources = 0;
+
+ //
+ // Fill in MC Bus Snapshot header
+ //
+
+ rawerr->McBusSnapshot.Length = sizeof(MC_BUS_SNAPSHOT)
+ + HalpNumberOfIods * sizeof(IOD_ERROR_FRAME);
+
+ rawerr->McBusSnapshot.NumberOfIods = HalpNumberOfIods;
+
+ return;
+}
diff --git a/private/ntos/nthals/halraw/alpha/rwintbal.c b/private/ntos/nthals/halraw/alpha/rwintbal.c
new file mode 100644
index 000000000..f32f533b1
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/rwintbal.c
@@ -0,0 +1,1762 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ rwintbal.c
+
+Abstract:
+
+ The module provides support for distributing interrupt load among
+ processors for Rawhide systems.
+
+Author:
+
+ Matthew Buchman (DEC) 29-November-1995
+
+Revision History:
+
+--*/
+
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "rawhide.h"
+#include "pcrtc.h"
+
+//
+// The enable mask for all interrupts sourced from the IOD (all device
+// interrupts, and all from PCI). A "1" indicates the interrupt is enabled.
+//
+
+extern PULONG *HalpIodInterruptMask;
+
+//
+// Declare IOD and CPU affinity tables
+//
+
+LIST_ENTRY HalpIodVectorDataHead;
+LIST_ENTRY HalpCpuVectorDataHead;
+
+PIOD_VECTOR_DATA HalpIodVectorData;
+PCPU_VECTOR_DATA HalpCpuVectorData;
+
+
+//
+// The number of target CPUS, mainly for performance comparison of
+// one processor vs. distributed interrupt load
+//
+
+#if 1
+ULONG HalpNumberOfTargetCpus = IOD_MAX_INT_TARG;
+#else
+ULONG HalpNumberOfTargetCpus = 1;
+#endif
+
+
+
+PVOID
+HalpFindWeightedEntry(
+ PLIST_ENTRY ListHead,
+ WEIGHTED_SEARCH_CRITERIA SearchCriteria
+ )
+/*++
+
+Routine Description:
+
+ This routine searches a WEIGHTED list searching for the maximum
+ or minimum weight, depending on the SearchCriteria. A WEIGHTED
+ list entry overlays the generic LIST_ENTRY provided by NT. This
+ allows us to use the generic LIST_ENTRY routines for list
+ manipulation. To treat this as an ordered list, we must traverse
+ this list by hand to find the maximum element.
+
+ The entry matching the search criteria is removed from the list
+ as a side effect.
+
+Arguments:
+
+ ListHead - a pointer the list head.
+
+ SearchCriteria - either FindMaxEntry or FindMinEntry
+
+Return Value:
+
+ Return a pointer to the maximum element or NULL for
+ an empty list.
+
+--*/
+{
+ PLIST_ENTRY NextEntry;
+ PLIST_ENTRY CurrentMaxMinEntry;
+ PWEIGHTED_LIST_ENTRY WeightedEntry;
+ LONG CurrentMaxMinWeight;
+
+
+ //
+ // Handle the empty list case
+ //
+
+ if (IsListEmpty(ListHead)) {
+ return (NULL);
+ }
+
+ //
+ // Traverse this list looking for the maximum weight
+ //
+
+ for (
+ NextEntry = ListHead->Flink,
+ CurrentMaxMinEntry = NULL;
+
+ NextEntry != ListHead;
+
+ NextEntry = NextEntry->Flink
+
+ ) {
+
+ //
+ // The WEIGHTED_LIST_ENTRY overlays the LIST_ENTRY
+ //
+
+ WeightedEntry = (PWEIGHTED_LIST_ENTRY)NextEntry;
+
+ if (CurrentMaxMinEntry == NULL) {
+
+ CurrentMaxMinEntry = NextEntry;
+ CurrentMaxMinWeight = WeightedEntry->Weight;
+
+ } else {
+
+ if (SearchCriteria == FindMaxWeight) {
+
+ if (WeightedEntry->Weight > CurrentMaxMinWeight) {
+ CurrentMaxMinEntry = NextEntry;
+ CurrentMaxMinWeight = WeightedEntry->Weight;
+ }
+
+ } else {
+
+ if (WeightedEntry->Weight < CurrentMaxMinWeight) {
+ CurrentMaxMinEntry = NextEntry;
+ CurrentMaxMinWeight = WeightedEntry->Weight;
+ }
+
+ }
+ }
+ }
+
+ //
+ // Remove the maximum from the list
+ //
+
+ RemoveEntryList(CurrentMaxMinEntry);
+
+ return ((PVOID)CurrentMaxMinEntry);
+}
+
+// mdbfix - delete these routines later!
+#if 0
+
+//
+// Declare the lower-level routine used to read PCI config space
+//
+
+VOID
+HalpReadPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+
+VOID
+HalpFindPciBusVectors(
+ IN PCONFIGURATION_COMPONENT Component,
+ IN PVOID ConfigurationData
+ )
+
+/*++
+
+Routine Description:
+
+ This routine finds all device interrupt vectors for the PCI bus
+ handler obtained from the configuration tree and sets the
+ corresponding bits in the VectorPresent bitmap for the IOD.
+
+Arguments:
+
+ Component - The ARC configuration component for this bus.
+
+ ConfigurationData - The configuration data payload (or NULL).
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ARC_PCI_CONFIGURATION ArcPciConfiguration;
+ ULONG BusNumber;
+ ULONG HwBusNumber;
+ BOOLEAN BusIsAcrossPPB;
+ PBUS_HANDLER BusHandler;
+ PPCIPBUSDATA BusData;
+ PCIPBUSDATA BusContext;
+ RTL_BITMAP DevicePresent;
+ PCI_SLOT_NUMBER SlotNumber;
+ PIOD_VECTOR_DATA IodIoVectors;
+ ULONG DeviceNumber;
+ ULONG NextDevice;
+ ULONG FunctionNumber;
+ ULONG InterruptLine;
+ PCI_COMMON_CONFIG CommonConfig;
+
+ //
+ // Copy the configuration data from the component.
+ //
+
+ RtlCopyMemory(
+ &ArcPciConfiguration,
+ ConfigurationData,
+ sizeof (ARC_PCI_CONFIGURATION)
+ );
+
+ //
+ // Use the values provided.
+ //
+
+ BusNumber = ArcPciConfiguration.BusNumber;
+ HwBusNumber = ArcPciConfiguration.HwBusNumber;
+ BusIsAcrossPPB = ArcPciConfiguration.BusIsAcrossPPB;
+ IodIoVectors = HalpIodVectorData + HwBusNumber;
+
+ //
+ // Initialize the BusNumber for this IOD now.
+ // We might want to use it later to obtain the bus handler
+ //
+
+ IodIoVectors->BusNumber = BusNumber;
+
+ //
+ // Allocate and initialize the handler for this bus. N.B. device-present
+ // checking is disabled at this point. We will enable it below.
+ //
+
+ BusHandler = HaliHandlerForBus(
+ PCIBus,
+ BusNumber
+ );
+
+ //
+ // Get a pointer to the bus-specific data.
+ //
+
+ BusData = (PPCIPBUSDATA)BusHandler->BusData;
+
+ //
+ // Use the device-present bitmap for this bus to query configuration
+ // Space for InterruptLine values.
+ //
+
+ //
+ // Initialize the device-present bitmap for this bus.
+ //
+
+ HalpInitializeBitMap(
+ &BusContext.DevicePresent,
+ BusContext.DevicePresentBits,
+ PCI_MAX_DEVICES * PCI_MAX_FUNCTION
+ );
+
+ //
+ // Copy the bitmap from the bus handler.
+ //
+
+ RtlCopyMemory(
+ &BusContext.DevicePresentBits,
+ &BusData->DevicePresentBits,
+ sizeof (BusData->DevicePresentBits)
+ );
+
+
+ //
+ // Starting with device 0, scan the device present
+ // bitmap.
+ //
+
+ DeviceNumber = 0;
+
+ while ( (DeviceNumber =
+ HalpFindSetBitsAndClear(
+ &BusContext.DevicePresent,
+ 1,
+ DeviceNumber
+ ) ) != -1 ) {
+
+ //
+ // Initialize the slot number.
+ //
+
+ SlotNumber.u.AsULONG = 0;
+ SlotNumber.u.bits.DeviceNumber = DeviceNumber;
+
+ //
+ // Loop through each function number.
+ //
+
+ for (FunctionNumber = 0;
+ FunctionNumber < PCI_MAX_FUNCTION;
+ FunctionNumber++) {
+
+ SlotNumber.u.bits.FunctionNumber = FunctionNumber;
+
+ //
+ // Read the common configuration header.
+ //
+
+ HalpReadPCIConfig(
+ BusHandler,
+ SlotNumber,
+ &CommonConfig,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ //
+ // If the Vendor ID is invalid, then no device is present
+ // at this device/function number.
+ //
+
+ if (CommonConfig.VendorID == PCI_INVALID_VENDORID) {
+ if (FunctionNumber == 0) {
+ break;
+ }
+ continue;
+ }
+
+ //
+ // Obtain the vector assigned to this Device:Function
+ // during PCI configuration.
+ //
+
+ if (CommonConfig.u.type0.InterruptLine) {
+
+ //
+ // Obtain vector and normalize
+ //
+
+ InterruptLine =CommonConfig.u.type0.InterruptLine;
+ InterruptLine -= (RawhidePinToLineOffset + 1);
+
+ //
+ // Determine if this is a shared vector
+ //
+
+ if ( HalpAreBitsSet(
+ &IodIoVectors->VectorPresent[0],
+ InterruptLine,
+ 1
+ ) == TRUE ) {
+
+ //
+ // Indicate vector is shared in bitmap
+ //
+
+ HalpSetBits(
+ &IodIoVectors->SharedVector[0],
+ InterruptLine,
+ 1
+ );
+
+ HalpDumpBitMap(&IodIoVectors->SharedVector[0]);
+
+ } else {
+
+ //
+ // Indicate device is present in bitmap
+ //
+
+ HalpSetBits(
+ &IodIoVectors->VectorPresent[0],
+ InterruptLine,
+ 1
+ );
+
+ HalpDumpBitMap(&IodIoVectors->VectorPresent[0]);
+
+ }
+
+ //
+ // Increment the weight
+ //
+
+ IodIoVectors->ListEntry.Weight++;
+
+ } // if (CommonConfig.InterruptLine)
+
+ //
+ // If this is not a multi-function device, then terminate
+ // the function number loop.
+ //
+
+ if ((CommonConfig.HeaderType & PCI_MULTIFUNCTION) == 0) {
+ break;
+ }
+
+ } // for (FunctionNumber...)
+
+ } // while (DeviceNumber != -1)
+}
+
+
+VOID
+HalpFindAllPciVectors(
+ IN PCONFIGURATION_COMPONENT_DATA Root
+ )
+/*++
+
+Routine Description:
+
+ This function loops through each multi-function adapter component
+ in the ARC configuration tree and calls HalpFindPciBusVectors()
+ searching for device vectors.
+
+Arguments:
+
+ Root - The root of the ARC configuration tree.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG Key;
+ PCONFIGURATION_COMPONENT_DATA Adapter;
+
+ //
+ // Loop through each multi-function adapter component in the ARC
+ // configuration tree.
+ //
+
+ for (Key = 0; TRUE; Key++) {
+
+ //
+ // Get a pointer to the component data.
+ //
+
+ Adapter = KeFindConfigurationEntry(
+ Root,
+ AdapterClass,
+ MultiFunctionAdapter,
+ &Key
+ );
+
+ //
+ // If there are no more multi-function adapters in the ARC
+ // configuration tree, then we're done.
+ //
+
+ if (Adapter == NULL) {
+ break;
+ }
+
+ //
+ // Ascertain whether this is a PCI multi-function adapter component.
+ // If so, find the device vectors.
+ //
+
+ if (stricmp(Adapter->ComponentEntry.Identifier, "PCI") == 0) {
+ HalpFindPciBusVectors(
+ &Adapter->ComponentEntry,
+ Adapter->ConfigurationData
+ );
+ }
+ }
+}
+
+
+VOID
+HalpBalanceVectorLoadForIod(
+ PIOD_VECTOR_DATA IodVectorData
+ )
+/*++
+
+Routine Description:
+
+ Balance the vector load for the given IOD among the
+ CPU pair. The basic algorithm is:
+
+ 1. Find a device present from the bitmap.
+ 2. Choose the CPUwith the minimum vector load.
+ 3. Assign the device vector from (1) to this CPU
+ and update the CPU's vector load (weight) by 1.
+ 4. If the vector is shared (multiple devices
+ connect), update the CPU's vector load by 1.
+ While this does not accurately reflect the
+ actual vector's sharing the device, it will
+ due for algorithmic simplicity.
+ 5. Update the CPU's IOD service mask.
+ 6. repeat for all vectors.
+
+
+Arguments:
+
+ IodListHead - head of temporary IOD vector info list.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ RTL_BITMAP VectorPresent;
+ ULONG VectorPresentBits;
+ ULONG IRRBitNumber;
+ ULONG InterruptBit;
+
+ HalpInitializeBitMap(
+ &VectorPresent,
+ (PULONG)&VectorPresentBits,
+ 32
+ );
+
+ //
+ // Copy the device present bitmap from the IOD information.
+ //
+
+ RtlCopyMemory(
+ &VectorPresentBits,
+ &IodVectorData->VectorPresentBits[0],
+ sizeof (IodVectorData->VectorPresentBits[0])
+ );
+
+ //
+ // Now that we have a copy of all device vectors for this
+ // IOD, clear the device present bitmap for target 0.
+ // This was only being used as temporary storage.
+ //
+
+ HalpClearAllBits(&IodVectorData->VectorPresent[0]);
+
+ //
+ // Start with the first IRR bit.
+ //
+
+ IRRBitNumber = 0;
+
+ //
+ // Find the next Device present.
+ // Remember that this bitmap actually represents
+ // the interrupt vector assigned to devices.
+ //
+
+ while (( IRRBitNumber =
+ HalpFindSetBitsAndClear(
+ &VectorPresent,
+ 1,
+ IRRBitNumber) ) != -1 ) {
+
+ InterruptBit = (1 << IRRBitNumber);
+
+ //
+ // Assign the vector for this IOD
+ //
+
+ HalpAssignInterruptForIod(IodVectorData, InterruptBit);
+
+ }
+
+}
+
+
+VOID
+HalpBalanceIoVectorLoad(
+ PLIST_ENTRY IodListHead
+ )
+/*++
+
+Routine Description:
+
+ Balance the vector load among the set of processors.
+ The basic algorithm is:
+
+ 1. Find an IOD to process:
+
+ From the IOD set, find the IOD with the maximum
+ number of vectors, and permanantly remove this
+ IOD from the set.
+
+ 2. Find a CPU pair that will act as targets for
+ the selected IOD interrupts:
+
+ a. From the CPU set, find the first CPU with the
+ minimum number of vectors assigned and temporarily
+ remove this CPU from the CPU set.
+
+ b. From the CPU set, find the second CPU with the
+ minimum number of vectors assigned and temporarily
+ remove this CPU from the CPU set.
+
+ 3. Call HalpBalanceIodVectorLoad to divide the IOD
+ vectors among the two CPU's.
+
+ 5. Add the CPU's back the the CPU set. This makes them
+ available for selection during the next iteration.
+
+ 6. Repeat until the IOD set is empty.
+
+Arguments:
+
+ IodListHead - head of temporary IOD vector info list.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PIOD_VECTOR_DATA IodVectorData;
+
+ //
+ // Balance the vector load for each IOD,
+ // assigning vector affinity in the process
+ //
+
+ while (!IsListEmpty(IodListHead)) {
+
+ //
+ // Find the IOD with the maximum number of
+ // vectors. It is removed from the list as
+ // a side effect.
+ //
+
+ IodVectorData = (PIOD_VECTOR_DATA)
+ HalpFindWeightedEntry(IodListHead, FindMaxWeight);
+
+ //
+ // Assign the interrupt vector affinity for this IOD
+ //
+
+ HalpBalanceVectorLoadForIod(
+ IodVectorData
+ );
+
+ //
+ // Add this to the global list of IOD's.
+ // Use shortcut to obtain LIST_ENTRY.
+ //
+
+ InsertHeadList(
+ &HalpIodVectorDataHead,
+ &IodVectorData->ListEntry.ListEntry
+ );
+
+ }
+
+}
+
+
+VOID
+HalpInitializeIoVectorAffinity(
+ PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+
+ The IOD and CPU vector information tables are used balance the
+ interrupt load from all IOD's among the set of available CPU's.
+
+ Allocate and initialize the IOD and CPU vector information tables,
+ pre-assign vectors for EISA, I2c, SoftErr, and HardErr, and
+ call HalpIoVectorLoad() to assign IOD vectors to CPU's.
+
+Arguments:
+
+ LoaderParameterBlock - supplies a pointer to the loader block.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ MC_DEVICE_MASK IodMask = HalpIodMask;
+ MC_DEVICE_MASK CpuMask = HalpCpuMask;
+ PIOD_VECTOR_DATA IodVectorData;
+ PCPU_VECTOR_DATA CpuVectorData;
+ LIST_ENTRY IodListHead;
+ ULONG LogicalNumber;
+ ULONG Target;
+
+ //
+ // Allocate the IOD device affinity table.
+ //
+
+ HalpIodVectorData = (PIOD_VECTOR_DATA)
+ ExAllocatePool(
+ NonPagedPool,
+ sizeof(IOD_VECTOR_DATA)* HalpNumberOfIods
+ );
+
+ RtlZeroMemory(
+ HalpIodVectorData,
+ sizeof(IOD_VECTOR_DATA)*HalpNumberOfIods
+ );
+
+ //
+ // Initialize the IOD vector affinity list.
+ //
+
+ InitializeListHead(&HalpIodVectorDataHead);
+ InitializeListHead(&IodListHead);
+
+ for ( LogicalNumber = 0, IodVectorData = HalpIodVectorData;
+ LogicalNumber < HalpNumberOfIods;
+ LogicalNumber++, IodVectorData++ ) {
+
+
+ //
+ // Initialize bitmaps for each target.
+
+ for (Target = 0; Target < IOD_MAX_INT_TARG; Target++) {
+
+ //
+ // The VectorBitmap represents the devices on this IOD
+ // that been assigned vectors and to which target the
+ // vectors have been assigned.
+ //
+
+
+ HalpInitializeBitMap(
+ &IodVectorData->VectorPresent[Target] ,
+ (PULONG)&IodVectorData->VectorPresentBits[Target],
+ 32
+ );
+
+ //
+ // The SharedBitmap represents vectors that are shared
+ // by devices on this IOD. It is used to make decisions
+ // on which target to assign vectors.
+ //
+
+ HalpInitializeBitMap(
+ &IodVectorData->SharedVector[Target],
+ (PULONG)&IodVectorData->SharedVectorBits[Target],
+ 32
+ );
+
+ }
+
+ //
+ // Assign the device number. This cooresponds to the logical
+ // IOD number.
+ //
+
+ IodVectorData->HwBusNumber = LogicalNumber;
+
+ //
+ // Add this IOD to temporary list. The IOD will be added
+ // to permanent list after it is processed.
+ //
+
+ InsertTailList(
+ &IodListHead,
+ &IodVectorData->ListEntry.ListEntry
+ );
+
+ }
+
+ //
+ // Allocate the CPU IO device affinity table.
+ //
+
+ HalpCpuVectorData = (PCPU_VECTOR_DATA)
+ ExAllocatePool(
+ NonPagedPool,
+ sizeof(CPU_VECTOR_DATA) * HalpNumberOfCpus
+ );
+
+ RtlZeroMemory(
+ HalpCpuVectorData,
+ sizeof(CPU_VECTOR_DATA)*HalpNumberOfCpus
+ );
+
+ //
+ // Initialize the CPU vector affinity list.
+ //
+
+ InitializeListHead(&HalpCpuVectorDataHead);
+
+ for ( LogicalNumber = 0, CpuVectorData = HalpCpuVectorData;
+ LogicalNumber < HalpNumberOfCpus;
+ LogicalNumber++, CpuVectorData++ ) {
+
+ //
+ // Assign the device number. This cooresponds to the logical
+ // CPU number.
+ //
+
+ CpuVectorData->LogicalNumber = LogicalNumber;
+ CpuVectorData->McDeviceId.Gid = GidPrimary;
+
+ switch (LogicalNumber) {
+
+ case 0:
+
+ CpuVectorData->McDeviceId.Mid = MidCpu1;
+ break;
+
+ case 1:
+
+ CpuVectorData->McDeviceId.Mid = MidCpu1;
+ break;
+
+ case 2:
+
+ CpuVectorData->McDeviceId.Mid = MidCpu2;
+ break;
+
+ case 3:
+
+ CpuVectorData->McDeviceId.Mid = MidCpu3;
+ break;
+
+ }
+ //
+ // Insert this CPU into the list
+ //
+
+ InsertTailList(
+ &HalpCpuVectorDataHead,
+ &CpuVectorData->ListEntry.ListEntry
+ );
+
+ }
+
+ //
+ // Find all PCI Iod Vectors.
+ //
+
+ HalpFindAllPciVectors(LoaderBlock->ConfigurationRoot);
+
+ //
+ // Preassign error vectors for all IOD's as well as EISA, EISANMI
+ // and I2c vectors to the primary processor.
+ //
+
+ HalpAssignPrimaryProcessorVectors(&IodListHead);
+
+ //
+ // Balance the IO vector load among the CPU's
+ //
+
+ HalpBalanceIoVectorLoad(&IodListHead);
+
+#if HALDBG
+
+ HalpDumpIoVectorAffinity();
+
+#endif
+
+}
+
+
+VOID
+HalpAssignIodInterrupts(
+ MC_DEVICE_ID McDeviceId,
+ ULONG PciBusNumber,
+ va_list Arguments
+ )
+
+/*++
+
+Routine Description:
+
+ This enumeration routine assigns the Rawhide interrupts for the
+ corresponding IOD and sets up the target CPU's. The interrupts
+ are initialized with the values determined by
+ HalpInitializeIoVectorAffinity()
+
+ Interrupts were previously routed to the primary processor
+ by HalpInitializeIodInterrupts. Now that All processors are
+ started, we must reassign HardErr, Eisa, and EisaNMI interrupts.
+
+ The logical bus is assigned from the static variable PciBusNumber, which is
+ incremented with each invokation.
+
+Arguments:
+
+ McDeviceId - Supplies the MC Bus Device ID of the IOD to be intialized
+
+ PciBusNumber - Logical (Hardware) bus number.
+
+ Arguments - Variable Arguments. None for this routine.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PIOD_VECTOR_DATA IodVectorData;
+ IOD_INT_MASK IntMask;
+ IOD_INT_TARGET_DEVICE IntTarg;
+ PVOID IntMaskQva;
+ ULONG Target;
+
+ IodVectorData = HalpIodVectorData + PciBusNumber;
+
+ //
+ // Disable MCI bus interrupts
+ //
+
+ WRITE_IOD_REGISTER_NEW(
+ McDeviceId,
+ &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntCtrl,
+ (IOD_INT_CTL_DISABLE_IO_INT | IOD_INT_CTL_DISABLE_VECT_WRITE)
+ );
+
+ //
+ // Initialize the target register base on assigned values
+ //
+
+ IntTarg.Int0TargDevId = (ULONG)IodVectorData->IntTarg[0].all;
+ IntTarg.Int1TargDevId = (ULONG)IodVectorData->IntTarg[1].all;
+
+ //
+ // Write the target register.
+ //
+
+ WRITE_IOD_REGISTER_NEW(
+ McDeviceId,
+ &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntTarg,
+ IntTarg.all
+ );
+
+ //
+ // Write the mask bits for target 0 and 1
+ //
+
+ for (Target = 0; Target < IOD_MAX_INT_TARG; Target++) {
+
+ //
+ // Obtain the target IRR QVA
+ //
+
+ if (Target) {
+
+ IntMaskQva = (PVOID)&((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntMask1;
+
+ } else {
+
+ IntMaskQva = (PVOID)&((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntMask0;
+
+ }
+ IntMask.all = IodVectorData->IntMask[Target].all;
+
+ WRITE_IOD_REGISTER_NEW(
+ McDeviceId,
+ IntMaskQva,
+ IntMask.all
+ );
+
+ }
+
+ //
+ // Enable Interrupts.
+ //
+
+ WRITE_IOD_REGISTER_NEW(
+ McDeviceId,
+ &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntCtrl,
+ IOD_INT_CTL_ENABLE_IO_INT
+ );
+
+}
+
+#endif // STATIC BALANCE
+
+
+VOID
+HalpInitializeVectorBalanceData(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ The IOD and CPU vector information tables are used balance the
+ interrupt load from all IOD's among the set of available CPU's.
+
+ Allocate and initialize the IOD and CPU vector information tables,
+ pre-assign vectors for EISA, I2c, SoftErr, and HardErr, and
+ call HalpIoVectorLoad() to assign IOD vectors to CPU's.
+
+Arguments:
+
+ LoaderParameterBlock - supplies a pointer to the loader block.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ MC_DEVICE_MASK IodMask = HalpIodMask;
+ MC_DEVICE_MASK CpuMask = HalpCpuMask;
+ PIOD_VECTOR_DATA IodVectorData;
+ ULONG LogicalNumber;
+ ULONG Target;
+
+ //
+ // Allocate the IOD device affinity table.
+ //
+
+ HalpIodVectorData = (PIOD_VECTOR_DATA)
+ ExAllocatePool(
+ NonPagedPool,
+ sizeof(IOD_VECTOR_DATA)* HalpNumberOfIods
+ );
+
+ RtlZeroMemory(
+ HalpIodVectorData,
+ sizeof(IOD_VECTOR_DATA)*HalpNumberOfIods
+ );
+
+ //
+ // Initialize the IOD vector affinity list.
+ //
+
+ InitializeListHead(&HalpIodVectorDataHead);
+
+ for ( LogicalNumber = 0, IodVectorData = HalpIodVectorData;
+ LogicalNumber < HalpNumberOfIods;
+ LogicalNumber++, IodVectorData++ ) {
+
+ //
+ // Assign the device number. This cooresponds to the logical
+ // IOD number.
+ //
+
+ IodVectorData->HwBusNumber = LogicalNumber;
+
+ //
+ // Add this IOD to temporary list. The IOD will be added
+ // to permanent list after it is processed.
+ //
+
+ InsertTailList(
+ &HalpIodVectorDataHead,
+ &IodVectorData->ListEntry.ListEntry
+ );
+
+ }
+
+ //
+ // Allocate the CPU vector data table for the maximum
+ // processor configuration.
+ //
+
+ HalpCpuVectorData = (PCPU_VECTOR_DATA)
+ ExAllocatePool(
+ NonPagedPool,
+ sizeof(CPU_VECTOR_DATA)*HalpNumberOfCpus
+ );
+
+ RtlZeroMemory(
+ HalpCpuVectorData,
+ sizeof(CPU_VECTOR_DATA)*HalpNumberOfCpus
+ );
+
+ //
+ // Initialize the CPU vector affinity list.
+ // CPU's will add their entry later.
+ //
+
+ InitializeListHead(&HalpCpuVectorDataHead);
+
+}
+
+
+VOID
+HalpInitializeCpuVectorData(
+ ULONG LogicalCpu
+ )
+/*++
+
+Routine Description:
+
+ Allocate and initialize the CPU vector entry for this logical
+ CPU and add it to the global list,
+
+Arguments:
+
+ LogicalCpu - Logical CPU number assigned by HalStartNextProcessor().
+
+Return Value:
+
+ None.
+
+--*/
+{
+ MC_DEVICE_MASK CpuMask = HalpCpuMask;
+ PCPU_VECTOR_DATA CpuVectorData;
+ ULONG Target;
+
+ //
+ // Use the logical processor number to offset into in the
+ // global CPU table.
+ //
+
+ CpuVectorData = HalpCpuVectorData + LogicalCpu;
+
+ //
+ // Initalize CPU vector data fields
+ //
+
+ CpuVectorData->LogicalNumber = LogicalCpu;
+
+ //
+ // Insert into global list
+ //
+
+ InsertTailList(
+ &HalpCpuVectorDataHead,
+ &CpuVectorData->ListEntry.ListEntry
+ );
+
+#if HALDBG
+ DbgPrint(
+ "Initialized vector data for CPU %d (%d, %d)\n",
+ CpuVectorData->LogicalNumber,
+ HalpLogicalToPhysicalProcessor[LogicalCpu].Gid,
+ HalpLogicalToPhysicalProcessor[LogicalCpu].Mid
+ );
+#endif
+
+}
+
+
+VOID
+HalpAssignPrimaryProcessorVectors(
+ PLIST_ENTRY IodListHead
+ )
+/*++
+
+Routine Description:
+
+ Assign primary processor vectors. This includes the following:
+
+ HardErr
+ SoftErr
+ Eisa
+ EisaNMI
+ I2cBus
+ I2cCtrl
+
+ By having the primary processor handle the error vectors, we
+ prevent hard errors from being serviced by multiple
+ processors.
+
+Arguments:
+
+ IodListHead - head of temporary IOD vector info list.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PLIST_ENTRY ListEntry;
+ PIOD_VECTOR_DATA IodVectorData;
+ PCPU_VECTOR_DATA PrimaryCpuVectorData;
+ MC_DEVICE_ID McDeviceId;
+ ULONG Target;
+
+ //
+ // Obtain the vector data structure for the primary processor
+ //
+
+ PrimaryCpuVectorData = HalpCpuVectorData;
+
+ //
+ // Assign the hard and soft error interrupt for each IOD
+ // to the primary processor
+ //
+
+ for ( ListEntry = IodListHead->Flink;
+ ListEntry != IodListHead;
+ ListEntry = ListEntry->Flink ) {
+
+ //
+ // Obtain the IOD vector data.
+ //
+
+ IodVectorData = (PIOD_VECTOR_DATA)ListEntry;
+
+ McDeviceId = HalpIodLogicalToPhysical[IodVectorData->HwBusNumber];
+
+#if HALDBG
+ DbgPrint(
+ "Assign IOD (%d, %d) Target 0 to Primary Processor\n",
+ McDeviceId.Gid,
+ McDeviceId.Mid
+ );
+#endif
+
+ //
+ // Assign the Target 0 CPU for this IOD
+ //
+
+ IodVectorData->TargetCpu[0] = PrimaryCpuVectorData;
+
+ //
+ // Assign the SoftErr and HardErr interrupts to each IOD
+ //
+
+ IodVectorData->IntMask[0].all |= (1 << IodHardErrIrrBit);
+ IodVectorData->IntMask[0].all |= (1 << IodSoftErrIrrBit);
+
+
+#if HALDBG
+ DbgPrint(
+ "Assign IOD (%d, %d) HardError to Target 0, CPU 0\n",
+ McDeviceId.Gid,
+ McDeviceId.Mid
+ );
+#endif
+
+ //
+ // Assign the Eisa, EisaNMI, and I2C interrupts for PCI bus 0
+ // to the primary processor.
+ //
+
+ if (IodVectorData->HwBusNumber == 0) {
+
+ IodVectorData->IntMask[0].all |= (1 << IodEisaIrrBit);
+// mdbfix - I2c not enabled
+// IodVectorData->IntMask[0].all |= (1 << IodI2cBusIrrBit);
+// IodVectorData->IntMask[0].all |= (1 << IodI2cCtrlIrrBit);
+ IodVectorData->IntMask[0].all |= (1 << IodEisaNmiIrrBit);
+
+#if HALDBG
+ DbgPrint(
+ "Assign IOD (%d, %d) EISA & EISANMI to Target 0, CPU 0\n",
+ McDeviceId.Gid,
+ McDeviceId.Mid
+ );
+#endif
+
+// mdbfix -
+#if 0
+ //
+ // Weight this Processor for EISA vectors KBD, MOUSE, etc.
+ //
+
+ PrimaryCpuVectorData->ListEntry.Weight++;
+#endif
+ }
+
+ //
+ // Initialize the affinity mask, target, and CPU vector link
+ //
+
+ IodVectorData->Affinity[0] |= 1;
+
+ IodVectorData->IntTarg[0] =
+ HalpLogicalToPhysicalProcessor[HAL_PRIMARY_PROCESSOR];
+
+ IodVectorData->TargetCpu[0] = PrimaryCpuVectorData;
+
+ }
+
+}
+
+
+ULONG
+HalpAssignInterruptForIod(
+ PIOD_VECTOR_DATA IodVectorData,
+ ULONG InterruptBit
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+ IodVectorData - IOD to assign interrupt
+
+ InterruptBit - Interrupt bit in the IRR to set
+
+Return Value:
+
+ Return the logical CPU number assigned the interrupt
+
+--*/
+
+{
+ PCPU_VECTOR_DATA TargetCpu;
+ MC_DEVICE_ID McDeviceId;
+ IOD_INT_TARGET_DEVICE IntTarg;
+ ULONG Target;
+ ULONG LogicalCpu;
+
+ McDeviceId = HalpIodLogicalToPhysical[IodVectorData->HwBusNumber];
+
+#if HALDBG
+
+ DbgPrint(
+ "Assigning IOD (%d, %d) Interrupt 0x%x\n",
+ McDeviceId.Gid,
+ McDeviceId.Mid,
+ InterruptBit
+ );
+#endif
+
+ //
+ // If both of the target CPU's have not been assigned,
+ // assign them now.
+ //
+
+ if ( !IodVectorData->TargetCpu[0] || !IodVectorData->TargetCpu[1] ) {
+
+
+ for (Target = 0; Target < HalpNumberOfTargetCpus; Target++) {
+
+ if ((TargetCpu = IodVectorData->TargetCpu[Target]) == NULL) {
+
+ TargetCpu = (PCPU_VECTOR_DATA)
+ HalpFindWeightedEntry(
+ &HalpCpuVectorDataHead,
+ FindMinWeight
+ );
+
+ //
+ // Handle for UP and second target not assigned
+ //
+
+ if (TargetCpu == NULL) {
+
+ break;
+
+ }
+
+#if HALDBG
+ DbgPrint(
+ "IOD (%d, %d) Target %d assigned to CPU %d\n",
+ McDeviceId.Gid,
+ McDeviceId.Mid,
+ Target,
+ TargetCpu->LogicalNumber
+ );
+#endif
+
+ LogicalCpu = TargetCpu->LogicalNumber;
+
+ //
+ // Initialize the affinity mask, target, and CPU vector link
+ //
+
+ IodVectorData->Affinity[Target] |= (1 << LogicalCpu);
+ IodVectorData->IntTarg[Target] =
+ HalpLogicalToPhysicalProcessor[LogicalCpu];
+ IodVectorData->TargetCpu[Target] = TargetCpu;
+
+ //
+ // Initialize the MC_DEVICE_ID for this target.
+ //
+
+
+ //
+ // Read the target register.
+ //
+
+ IntTarg.all = READ_IOD_REGISTER_NEW(
+ McDeviceId,
+ &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntTarg
+ );
+
+
+ //
+ // Obtain the Target assigned by Vector Balancing
+ //
+
+ if (Target) {
+
+ IntTarg.Int1TargDevId = (ULONG)
+ IodVectorData->IntTarg[Target].all;
+
+ } else {
+
+ IntTarg.Int1TargDevId = (ULONG)
+ IodVectorData->IntTarg[Target].all;
+
+ }
+
+ //
+ // Write the target register.
+ //
+
+ WRITE_IOD_REGISTER_NEW(
+ McDeviceId,
+ &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntTarg,
+ IntTarg.all
+ );
+
+ } else {
+
+ //
+ // Remove this entry from the list before assigning
+ // the next CPU
+ //
+
+ RemoveEntryList(&TargetCpu->ListEntry.ListEntry);
+
+ }
+ }
+
+ //
+ // Add the CPU's back to the global list.
+ //
+
+ for (Target = 0; Target < HalpNumberOfTargetCpus; Target++) {
+
+ if (IodVectorData->TargetCpu[Target]) {
+
+ InsertTailList(
+ &HalpCpuVectorDataHead,
+ &IodVectorData->TargetCpu[Target]->ListEntry.ListEntry
+ );
+
+ }
+ }
+
+ }
+
+ //
+ // Determine if the vector has already been assigned a target.
+ // If so, return the target cpu that is was assigned to.
+ // If not Choose the CPU with the minimum weight. The weight
+ // is an indication of how many PCI vectors have already been
+ // assigned to a CPU.
+ //
+
+ if ( (IodVectorData->TargetCpu[0] != NULL) &&
+ (IodVectorData->IntMask[0].all & InterruptBit) ) {
+
+ Target = 0;
+
+ } else if ( (IodVectorData->TargetCpu[1] != NULL) &&
+ (IodVectorData->IntMask[1].all & InterruptBit) ) {
+
+ Target = 1;
+
+ } else if ( !IodVectorData->TargetCpu[1] ) {
+
+ //
+ // If the second target CPU was not assigned,
+ // this is a UP system so choose target 0.
+ //
+
+ Target = 0;
+
+ } else if ( IodVectorData->TargetCpu[0]->ListEntry.Weight <
+ IodVectorData->TargetCpu[1]->ListEntry.Weight ) {
+
+ //
+ // Target 0 currently has a lower interrupt load
+ //
+
+ Target = 0;
+
+ } else {
+
+ //
+ // Target 1 currently has a lower interrupt load
+ //
+
+ Target = 1;
+
+ }
+
+ TargetCpu = IodVectorData->TargetCpu[Target];
+ LogicalCpu = TargetCpu->LogicalNumber;
+
+#if HALDBG
+ DbgPrint(
+ "Assign IOD (%d, %d) Interrupt 0x%x to Target %d, CPU %d\n",
+ McDeviceId.Gid,
+ McDeviceId.Mid,
+ InterruptBit,
+ Target,
+ TargetCpu->LogicalNumber
+ );
+
+#endif
+
+ //
+ // Enable this vector in the IOD Interrupt Mask
+ // This value is written later to the IntReq register
+ //
+
+ IodVectorData->IntMask[Target].all |= InterruptBit;
+
+ //
+ // Update the weight of the target CPU.
+ //
+
+ TargetCpu->ListEntry.Weight++;
+
+ return (LogicalCpu);
+
+}
+
+#if HALDBG
+//
+// Declare the lower-level routine used to read PCI config space
+//
+
+VOID
+HalpReadPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+
+VOID
+HalpDumpIoVectorAffinity(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Dump IO vector Affinity Assignment
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+
+ PIOD_VECTOR_DATA IodVectorData;
+ PCPU_VECTOR_DATA CpuVectorData;
+ MC_DEVICE_ID McDeviceId;
+ MC_ENUM_CONTEXT mcCtx;
+ PCI_COMMON_CONFIG CommonConfig;
+ PBUS_HANDLER BusHandler;
+ PPCIPBUSDATA BusData;
+ PCIPBUSDATA BusContext;
+ RTL_BITMAP DevicePresent;
+ PCI_SLOT_NUMBER SlotNumber;
+ PLIST_ENTRY NextEntry;
+ ULONG HwBusNumber;
+ ULONG BusNumber;
+ ULONG DeviceNumber;
+ ULONG FunctionNumber;
+ ULONG Target;
+
+
+ DbgPrint("Dump IOD VECTOR DATA\n\n");
+
+ //
+ // Traverse Iod Vector Data List
+ //
+
+ for (
+ NextEntry = HalpIodVectorDataHead.Flink;
+ NextEntry != &HalpIodVectorDataHead;
+ NextEntry = NextEntry->Flink
+ ) {
+
+
+ IodVectorData = (PIOD_VECTOR_DATA) NextEntry;
+ HwBusNumber = IodVectorData->HwBusNumber;
+ BusNumber = IodVectorData->BusNumber;
+ McDeviceId = HalpIodLogicalToPhysical[HwBusNumber];
+
+ DbgPrint(
+ "\n\nIod: Logical %d, Physical (%d, %d)\n\n",
+ HwBusNumber,
+ McDeviceId.Gid,
+ McDeviceId.Mid
+ );
+
+
+ BusHandler = HaliHandlerForBus(PCIBus,BusNumber);
+
+ //
+ // Get a pointer to the bus-specific data.
+ //
+
+ BusData = (PPCIPBUSDATA)BusHandler->BusData;
+
+ //
+ // Use the device-present bitmap for this bus to query configuration
+ // Space for InterruptLine values.
+ //
+
+ //
+ // Initialize the device-present bitmap for this bus.
+ //
+
+ HalpInitializeBitMap(
+ &BusContext.DevicePresent,
+ BusContext.DevicePresentBits,
+ PCI_MAX_DEVICES * PCI_MAX_FUNCTION
+ );
+
+ //
+ // Copy the bitmap from the bus handler.
+ //
+
+ RtlCopyMemory(
+ &BusContext.DevicePresentBits,
+ &BusData->DevicePresentBits,
+ sizeof (BusData->DevicePresentBits)
+ );
+
+
+ //
+ // Starting with device 0, scan the device present
+ // bitmap.
+ //
+
+ DeviceNumber = 0;
+
+ DbgPrint("Devices Present on Bus:\n\n");
+
+ while ( (DeviceNumber =
+ HalpFindSetBitsAndClear(
+ &BusContext.DevicePresent,
+ 1,
+ DeviceNumber
+ ) ) != -1 ) {
+
+ DbgPrint("Device Number %d\n", DeviceNumber);
+
+ //
+ // Initialize the slot number.
+ //
+
+ SlotNumber.u.AsULONG = 0;
+ SlotNumber.u.bits.DeviceNumber = DeviceNumber;
+
+ //
+ // Loop through each function number.
+ //
+
+ for (FunctionNumber = 0;
+ FunctionNumber < PCI_MAX_FUNCTION;
+ FunctionNumber++) {
+
+ SlotNumber.u.bits.FunctionNumber = FunctionNumber;
+
+ //
+ // Read the common configuration header.
+ //
+
+ HalpReadPCIConfig(
+ BusHandler,
+ SlotNumber,
+ &CommonConfig,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ //
+ // If the Vendor ID is invalid, then no device is present
+ // at this device/function number.
+ //
+
+ if (CommonConfig.VendorID == PCI_INVALID_VENDORID) {
+ if (FunctionNumber == 0) {
+ break;
+ }
+ continue;
+ }
+
+ DbgPrint(
+ "Device %d, Function %d\n",
+ DeviceNumber,
+ FunctionNumber
+ );
+
+ DbgPrint(
+ "VendorId 0x%x, InterruptLine 0x%x\n",
+ CommonConfig.VendorID,
+ CommonConfig.u.type0.InterruptLine
+ );
+
+ //
+ // If this is not a multi-function device, then terminate
+ // the function number loop.
+ //
+
+ if ((CommonConfig.HeaderType & PCI_MULTIFUNCTION) == 0) {
+ break;
+ }
+
+ } // for (FunctionNumber...)
+
+ } // while (DeviceNumber)
+
+
+ DbgPrint("\nIOD Targets:\n\n");
+
+ for (Target = 0; Target < IOD_MAX_INT_TARG; Target++) {
+
+ DbgPrint(
+ "DevId: (%d, %d), Mask: 0x%x\n",
+ IodVectorData->IntTarg[Target].Gid,
+ IodVectorData->IntTarg[Target].Mid,
+ IodVectorData->IntMask[Target].all
+ );
+
+ }
+
+ } //for (IodVectorData)
+
+ DbgPrint("\nDump CPU VECTOR DATA\n\n");
+
+ for (
+ NextEntry = HalpCpuVectorDataHead.Flink;
+ NextEntry != &HalpCpuVectorDataHead;
+ NextEntry = NextEntry->Flink
+ ) {
+
+
+ CpuVectorData = (PCPU_VECTOR_DATA) NextEntry;
+ McDeviceId =
+ HalpLogicalToPhysicalProcessor[CpuVectorData->LogicalNumber];
+
+ DbgPrint(
+ "Cpu: Logical %d Physical (%d,%d)\n",
+ CpuVectorData->LogicalNumber,
+ McDeviceId.Gid,
+ McDeviceId.Mid
+ );
+
+ }
+
+}
+
+#endif // HALDBG
diff --git a/private/ntos/nthals/halraw/alpha/rwintbal.h b/private/ntos/nthals/halraw/alpha/rwintbal.h
new file mode 100644
index 000000000..ba3d5fb0a
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/rwintbal.h
@@ -0,0 +1,200 @@
+/*++
+
+Copyright (c) 1995 Digital Equipment Corporation
+
+Module Name:
+
+ rwintbal.h
+
+Abstract:
+
+ This file contains definitions specific to the Rawhide platform
+
+Author:
+
+ Matthew Buchman 29-Nov-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#ifndef _RWINTBALH_
+#define _RWINTBALH_
+
+#if !defined (_LANGUAGE_ASSEMBLY)
+
+//
+// Define the structures for assigning vector affinity
+//
+
+//
+// Generic weighted list. The weight field is used by the
+// affinity assignment algorithm when selecting IOD and CPU's
+//
+
+typedef struct _WEIGHTED_LIST_ENTRY {
+ LIST_ENTRY ListEntry;
+ LONG Weight;
+} WEIGHTED_LIST_ENTRY, *PWEIGHTED_LIST_ENTRY;
+
+//
+// Search Criteria enum for MAX/MIN search
+//
+
+typedef enum _WEIGHTED_SEARCH_CRITERIA {
+ FindMaxWeight,
+ FindMinWeight
+} WEIGHTED_SEARCH_CRITERIA, *PWEIGHTED_SEARC_CRITERIA;
+
+//
+// Define CPU vector information structure.
+//
+
+typedef struct _CPU_VECTOR_DATA {
+
+ WEIGHTED_LIST_ENTRY ListEntry; // Generic list
+ ULONG LogicalNumber; // Logical Id for this CPU
+
+} CPU_VECTOR_DATA, *PCPU_VECTOR_DATA;
+
+//
+// Define IOD vector data structure. This structure
+// contains information on devices present on an IOD, their
+// vectors, and shadow registers for IntReq and IntTarg
+//
+
+typedef struct _IOD_VECTOR_DATA {
+
+ WEIGHTED_LIST_ENTRY ListEntry; // Generic list
+
+ PCPU_VECTOR_DATA TargetCpu[2]; // Target CPU vector data
+
+ RTL_BITMAP VectorPresent[2]; // IOD device vectors present
+ RTL_BITMAP SharedVector[2]; // IOD device vectors shared
+ ULONG VectorPresentBits[2]; // bitmap storage
+ ULONG SharedVectorBits[2]; // bitmap storage
+ ULONG BusNumber; // Logical bus number for this IOD
+ ULONG HwBusNumber; // Physical bus number for this IOD
+ ULONG Affinity[2]; // Vector AFFINITY for targets 0/1
+ IOD_INT_MASK IntMask[2]; // Shadow of IOD IntMaskX
+ MC_DEVICE_ID IntTarg[2]; // Shadow of IOD IntTargX
+
+} IOD_VECTOR_DATA, *PIOD_VECTOR_DATA;
+
+
+typedef enum _IOD_IRR_BITS{
+
+ IodPci0IrrBit = 0,
+ IodPci1IrrBit = 1,
+ IodPci2IrrBit = 2,
+ IodPci3IrrBit = 3,
+ IodPci4IrrBit = 4,
+ IodPci5IrrBit = 5,
+ IodPci6IrrBit = 6,
+ IodPci7IrrBit = 7,
+ IodPci8IrrBit = 8,
+ IodPci9IrrBit = 9,
+ IodPci10IrrBit = 10,
+ IodPci11IrrBit = 11,
+ IodPci12IrrBit = 12,
+ IodPci13IrrBit = 13,
+ IodPci14IrrBit = 14,
+ IodPci15IrrBit = 15,
+ IodEisaIrrBit = 16,
+ IodScsiIrrBit = 16,
+ IodI2cCtrlIrrBit = 17,
+ IodI2cBusIrrBit = 18,
+ IodEisaNmiIrrBit = 21,
+ IodSoftErrIrrBit = 22,
+ IodHardErrIrrBit = 23
+
+} IOD_IRR_BITS, *PIOD_IRR_BITS;
+
+extern PIOD_VECTOR_DATA HalpIodVectorData;
+extern PCPU_VECTOR_DATA HalpCpuVectorData;
+
+extern MC_DEVICE_ID HalpProcessorMcDeviceId[];
+
+extern LIST_ENTRY HalpIodVectorDataHead;
+extern LIST_ENTRY HalpCpuVectorDataHead;
+
+//
+// Weighted list manipulation routines
+//
+
+PWEIGHTED_LIST_ENTRY
+HalpFindWeightedList(
+ PLIST_ENTRY ListHead,
+ WEIGHTED_SEARCH_CRITERIA SearchCriteria
+ );
+
+
+//
+// Rawhide interrupt routine prototypes.
+//
+
+#if 0
+VOID
+HalpFindAllPciVectors(
+ IN PCONFIGURATION_COMPONENT_DATA Root
+ );
+
+VOID
+HalpFindPciBusVectors(
+ IN PCONFIGURATION_COMPONENT Component,
+ IN PVOID ConfigurationData
+ );
+
+VOID
+HalpInitializeIoVectorAffinity(
+ PLOADER_PARAMETER_BLOCK AFFINITYerBlock
+ );
+
+VOID
+HalpBalanceIoVectorLoad(
+ PLIST_ENTRY pIodListHead
+ );
+
+VOID
+HalpBalanceVectorLoadForIod(
+ PIOD_VECTOR_DATA IodVectorData
+ );
+
+#endif
+
+VOID
+HalpInitializeVectorBalanceData(
+ VOID
+ );
+
+VOID
+HalpInitializeCpuVectorData(
+ ULONG LogicalCpu
+ );
+
+VOID
+HalpAssignPrimaryProcessorVectors(
+ PLIST_ENTRY
+ );
+
+ULONG
+HalpAssignInterruptForIod(
+ PIOD_VECTOR_DATA IodVectorData,
+ ULONG InterruptVector
+ );
+
+#ifdef HALDBG
+VOID
+HalpDumpIoVectorAffinity(
+ VOID
+ );
+#endif
+
+#endif // !defined (_LANGUAGE_ASSEMBLY)
+
+#endif //_RWINTBALH_
diff --git a/private/ntos/nthals/halraw/alpha/rwintsup.c b/private/ntos/nthals/halraw/alpha/rwintsup.c
new file mode 100644
index 000000000..53f546dc3
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/rwintsup.c
@@ -0,0 +1,2364 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ rwintsup.c
+
+Abstract:
+
+ The module provides the interrupt support for Rawhide systems.
+
+Author:
+
+ Eric Rehm (DEC) 29-December-1993
+
+Revision History:
+
+ Eric Rehm (DEC) 26-July-1994
+ Adapted from Alcor module for Rawhide.
+
+--*/
+
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "eisa.h"
+#include "ebsgdma.h"
+#include "rawhide.h"
+#include "pintolin.h"
+
+extern IOD_REGISTER_CLASS DumpIodFlag;
+
+//
+// Declare the interrupt structures and spinlocks for the intermediate
+// interrupt dispatchers.
+//
+
+KINTERRUPT HalpPciInterrupt;
+KINTERRUPT HalpEisaInterrupt;
+
+extern BOOLEAN HalpLogCorrectableErrors;
+
+//
+// The enable mask for all interrupts sourced from the IOD (all device
+// interrupts, and all from PCI). A "1" indicates the interrupt is enabled.
+//
+
+ULONG HalpIodInterruptMask[RAWHIDE_MAXIMUM_PCI_BUS][2] = {0};
+
+//
+// Define the context structure for use by interrupt service routines.
+//
+
+typedef BOOLEAN (*PSECOND_LEVEL_DISPATCH)(
+ PKINTERRUPT InterruptObject,
+ PVOID ServiceContext,
+ PKTRAP_FRAME TrapFrame
+ );
+
+//
+// Declare the interrupt handler for the EISA bus. The interrupt dispatch
+// routine, HalpEisaDispatch, is called from this handler.
+//
+
+BOOLEAN
+HalpEisaInterruptHandler(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+//
+// The following is the interrupt object used for DMA controller interrupts.
+// DMA controller interrupts occur when a memory parity error occurs or a
+// programming error occurs to the DMA controller.
+//
+
+KINTERRUPT HalpEisaNmiInterrupt;
+
+//
+// The following function initializes NMI handling.
+//
+
+VOID
+HalpInitializeNMI(
+ VOID
+ );
+
+//
+// The following function is called when an EISA NMI occurs.
+//
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+//
+// The following functions handle the PCI interrupts.
+//
+
+VOID
+HalpInitializeIodInterrupts(
+ MC_DEVICE_ID McDeviceId,
+ ULONG PciBusNumber,
+ va_list Arguments
+ );
+
+VOID
+HalpDisablePciInterrupt(
+ IN ULONG Vector
+ );
+
+VOID
+HalpEnablePciInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+BOOLEAN
+HalpDeviceDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PKTRAP_FRAME TrapFrame
+ );
+
+//
+// Private prototypes
+
+VOID
+HalpRawhideDecodePciVector(
+ IN ULONG PciVector,
+ OUT PULONG PciBusNumber,
+ OUT PULONG InterruptLine
+ );
+
+
+ULONG
+HalpGetRawhidePciInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified PCI bus interrupt level and/or vector.
+ PCI vectors for rawhide are allocated starting with vector 0x40.
+ Vectors are assigned using the BusInterruptVector and the HwBusNumber.
+ One execption to this is NCR810 SCSI on PCI bus 1, which is always
+ allocated vector 0x32.
+
+ The HwBusNumber is encoded in the PCI vector by allocating vectors
+ in blocks of 16 (each IOD supports 16 PCI vectors) as shown below.
+
+ RawhidePciVectors:
+ 0x40 |-------------------|
+ | PCI 0 vectors |
+ |-------------------|
+ 0x50 | PCI 1 vectors |
+ |-------------------|
+ .
+ .
+ PCI interrupt routines may use the vector assigned to obtain the
+ PCI bus number and IRR bit as follows.
+
+ PciBus = (Vector - RawhidePciVectors) / 0x10
+ IrrBitShift = (Vector - RawhidePciVectors) % 0x10
+
+Arguments:
+
+ BusHandler - Supplies a pointer to the bus handler of the bus that
+ needs a system interrupt vector.
+
+ RootHandler - Supplies a pointer to the bus handler of the root
+ bus for the bus represented by BusHandler.
+
+ BusInterruptLevel - Supplies the bus-specific interrupt level.
+
+ BusInterruptVector - Supplies the bus-specific interrupt vector
+ assigned to the device during PCI configuration
+ using the Pin-to-line table.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the affinity for the requested vector
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the PCI device.
+
+--*/
+
+{
+ MC_DEVICE_ID McDeviceId;
+ IOD_INT_MASK IntMask;
+ IOD_INT_TARGET_DEVICE IntTarg;
+ PIOD_VECTOR_DATA IodVectorData;
+ PPCIPBUSDATA BusData = (PPCIPBUSDATA)BusHandler->BusData;
+ ULONG LogicalProcessor;
+ ULONG TargetCpu;
+ ULONG MaskBit;
+ ULONG PciVector;
+ ULONG PciBusNumber;
+ ULONG InterruptLine;
+
+ //
+ // NCR 810 on Bus 1 is a special case
+ //
+
+ if ( (BusInterruptVector == RawhideNcr810PinToLine) &&
+ (BusData->HwBusNumber == 1) ) {
+
+ PciVector = RawhideScsiVector;
+
+ } else {
+
+#if HALDBG
+ DbgPrint(
+ "HalpGetRawhidePciInterruptVector: Bus %d\n",
+ BusData->HwBusNumber
+ );
+#endif
+ //
+ // Build the rawhide vector.
+ //
+
+ PciVector = RawhidePciVectors;
+ PciVector += (BusData->HwBusNumber << 4);
+
+ //
+ // BusInterruptVectors are numbered 1-16, so
+ // subtract one to convert to table offset.
+ //
+
+ PciVector += (BusInterruptVector - 1);
+
+ //
+ // Rawhide Pin2Line table entries contain an arbitrary offset
+ // so that PCI InterruptLine values don't appear to conflict
+ // with EISA/ISA vectors reported by WINMSD.
+ //
+
+ PciVector -= RawhidePinToLineOffset;
+
+ }
+
+ //
+ // Decode the PCI bus number and interrupt line from the Vector
+ //
+
+ HalpRawhideDecodePciVector(PciVector, &PciBusNumber, &InterruptLine);
+
+#if HALDBG
+ DbgPrint(
+ "Vector 0x%x maps to PCI %d, InterruptLine %d\n",
+ PciVector,
+ PciBusNumber,
+ InterruptLine
+ );
+#endif
+
+ //
+ // Determine which IOD this interrupt is assigned to
+ // and obtain the IOD's geographic address.
+ //
+
+ McDeviceId = HalpIodLogicalToPhysical[PciBusNumber];
+
+ //
+ // Determine the IRR bit
+ //
+
+ MaskBit = (ULONG) 1<< InterruptLine;
+
+ //
+ // Obtain the IOD vector table entry
+ //
+
+ IodVectorData = HalpIodVectorData + PciBusNumber;
+
+ //
+ // Assign this vector to a CPU. This will update the target
+ // mask for this IOD as a side effect.
+ //
+
+ TargetCpu = HalpAssignInterruptForIod(IodVectorData, MaskBit);
+
+#if HALDBG
+ DbgPrint("HalpGetRawhidePCIVector: CPU %d\n", TargetCpu);
+#endif
+
+ //
+ // Assign affinity for all processors. This will cause
+ // the kernel to add an IDT entry for all processors.
+ // This is necessary if we are going to dynamically
+ // reassign the interrupt to a different processor at
+ // a later time.
+ //
+
+ *Irql = DEVICE_HIGH_LEVEL;
+ *Affinity = (1 << TargetCpu);
+
+#if HALDBG
+ DbgPrint(
+ "HalpGetRawhidePCIVector: vector 0x%x, Iqrl 0x%x, Affinity 0x%x\n",
+ PciVector,
+ *Irql,
+ *Affinity
+ );
+#endif
+
+ return ( PciVector );
+
+}
+
+
+ULONG
+HalpGetRawhideEisaInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified Eisa/Isa interrupt level and/or vector.
+ Eisa vectors for rawhide are allocated starting at vector 0x20.
+ Vectors are assigned using the BusInterruptLevel.
+
+Arguments:
+
+ BusHandler - Supplies a pointer to the bus handler of the bus that
+ needs a system interrupt vector.
+
+ RootHandler - Supplies a pointer to the bus handler of the root
+ bus for the bus represented by BusHandler.
+
+ BusInterruptLevel - Supplies the bus-specific interrupt level.
+
+ BusInterruptVector - Supplies the bus-specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the affinity for the requested vector
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+{
+ ULONG EisaVector;
+ PPCIPBUSDATA BusData = (PPCIPBUSDATA)BusHandler->BusData;
+
+ //
+ // Build the Eisa/Isa vector
+ //
+
+ EisaVector = RawhideEisaVectors;
+ EisaVector += BusInterruptLevel;
+
+ //
+ // Assign affinity for all processors. This will cause
+ // the kernel to add an IDT entry for all processors.
+ // This is necessary if we are going to dynamically
+ // reassign the interrupt to a different processor at
+ // a later time.
+ //
+
+ *Irql = DEVICE_HIGH_LEVEL;
+ *Affinity = (1 << HAL_PRIMARY_PROCESSOR);
+
+ return ( EisaVector );
+}
+
+
+ULONG
+HalpGetRawhideInternalInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified Internal Bus interrupt level.
+ Vectors are assigned using the BusInterruptLevel.
+
+Arguments:
+
+ BusHandler - Supplies a pointer to the bus handler of the bus that
+ needs a system interrupt vector.
+
+ RootHandler - Supplies a pointer to the bus handler of the root
+ bus for the bus represented by BusHandler.
+
+ BusInterruptLevel - Supplies the bus-specific interrupt level.
+
+ BusInterruptVector - Supplies the bus-specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the affinity for the requested vector
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+{
+ PPCIPBUSDATA BusData = (PPCIPBUSDATA)BusHandler->BusData;
+ PIOD_VECTOR_DATA IodVectorData;
+ ULONG InternalVector;
+ ULONG TargetCpu;
+ ULONG MaskBit;
+
+ //
+ // Build the Eisa/Isa vector
+ //
+
+ InternalVector = RawhideInternalBusVectors;
+ InternalVector += BusInterruptLevel;
+
+ //
+ // The Soft Error has already been assigned
+ // to the primary processor.
+ //
+
+ if (InternalVector == RawhideSoftErrVector) {
+
+ TargetCpu = HAL_PRIMARY_PROCESSOR;
+
+ }
+
+ //
+ // The only other Internal device support by
+ // Rawhide is the I2c bus. This reside on PCI0.
+ //
+
+ else {
+
+ //
+ // Map the vector to an interrupt line.
+ //
+
+ switch (InternalVector) {
+
+ case RawhideI2cCtrlVector:
+
+ MaskBit = IodI2cCtrlIntMask;
+ break;
+
+ case RawhideI2cBusVector:
+
+ MaskBit = IodI2cBusIntMask;
+ break;
+
+ }
+
+ //
+ // Obtain PCI0 vector data
+ //
+
+ IodVectorData = HalpIodVectorData;
+
+ //
+ // Assign this vector to a CPU. This will update the target
+ // mask for this IOD as a side effect.
+ //
+
+ TargetCpu = HalpAssignInterruptForIod(IodVectorData, MaskBit);
+
+#if HALDBG
+ DbgPrint("HalpGetRawhideInternalVector: CPU %d\n", TargetCpu);
+#endif
+
+ }
+
+ //
+ // Assign the vector affinity.
+ //
+
+ *Irql = DEVICE_HIGH_LEVEL;
+ *Affinity = (1 << TargetCpu);
+
+#if HALDBG
+ DbgPrint(
+ "HalpGetRawhideInternalVector: vector 0x%x, Iqrl 0x%x, Affinity 0x%x\n",
+ InternalVector,
+ *Irql,
+ *Affinity
+ );
+#endif
+
+ return ( InternalVector );
+}
+
+
+BOOLEAN
+HalpInitializeRawhideInterrupts (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for EISA & PCI operations
+ and connects the intermediate interrupt dispatchers. It also initializes
+ the EISA interrupt controller; the Rawhide ESC's interrupt controller is
+ compatible with the EISA interrupt contoller used on Jensen.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatchers are connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ KIRQL oldIrql;
+
+ //
+ // Initialize the EISA NMI interrupt.
+ //
+
+ HalpInitializeNMI();
+
+ (PVOID) HalpPCIPinToLineTable = (PVOID) RawhidePCIPinToLineTable;
+
+ //
+ // Intitialize interrupt controller
+ //
+
+ KeRaiseIrql(DEVICE_HIGH_LEVEL, &oldIrql);
+
+ //
+ // Initialize the ESC's PICs for EISA interrupts.
+ //
+
+ HalpInitializeEisaInterrupts();
+
+ //
+ // Initialize the interrupt request masks for all IOD's
+ //
+
+ HalpMcBusEnumAndCall(HalpIodMask, HalpInitializeIodInterrupts);
+
+
+#if HALDBG
+ DumpAllIods(DumpIodFlag);
+#endif
+ //
+ // Restore the IRQL.
+ //
+
+ KeLowerIrql(oldIrql);
+
+ //
+ // Initialize the EISA DMA mode registers to a default value.
+ // Disable all of the DMA channels except channel 4 which is the
+ // cascade of channels 0-3.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort.AllMask,
+ 0x0F
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort.AllMask,
+ 0x0E
+ );
+
+ return(TRUE);
+}
+
+
+VOID
+HalpInitializeNMI(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function is called to intialize ESC NMI interrupts.
+ Rawhide uses the Axp legacy ESC NMI vector.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+--*/
+{
+ UCHAR DataByte;
+ MC_DEVICE_ID McDeviceId;
+ IOD_INT_MASK IodIntMask;
+
+ //
+ // Initialize the ESC NMI interrupt.
+ //
+
+ KeInitializeInterrupt( &HalpEisaNmiInterrupt,
+ HalHandleNMI,
+ NULL,
+ NULL,
+ EISA_NMI_VECTOR,
+ EISA_NMI_LEVEL,
+ EISA_NMI_LEVEL,
+ LevelSensitive,
+ FALSE,
+ 0,
+ FALSE
+ );
+
+ //
+ // Don't fail if the interrupt cannot be connected.
+ //
+
+ KeConnectInterrupt( &HalpEisaNmiInterrupt );
+
+ //
+ // Clear the Eisa NMI disable bit. This bit is the high order of the
+ // NMI enable register.
+ //
+
+ DataByte = 0;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable,
+ DataByte
+ );
+
+}
+
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ This function is called when an EISA NMI occurs. It prints the
+ appropriate status information and bugchecks.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object
+
+ ServiceContext - Bug number to call bugcheck with.
+
+Return Value:
+
+ Returns TRUE.
+
+--*/
+{
+ UCHAR StatusByte;
+
+ StatusByte =
+ READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus);
+
+ if (StatusByte & 0x80) {
+ HalDisplayString ("NMI: Parity Check / Parity Error\n");
+ }
+
+ if (StatusByte & 0x40) {
+ HalDisplayString ("NMI: Channel Check / IOCHK\n");
+ }
+
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+ return(TRUE);
+}
+
+
+VOID
+HalpInitializeIodInterrupts(
+ MC_DEVICE_ID McDeviceId,
+ ULONG PciBusNumber,
+ va_list Arguments
+ )
+
+/*++
+
+Routine Description:
+
+ This enumeration routine is called during Phase 0 to assign the
+ Rawhide Error interrupts for the corresponding IOD to the Primary CPU.
+ The interrupts
+ are initialized as follows:
+
+ PCI - disabled
+ HardErr - DISABLED!!! //ecrfix enabled
+ SoftErr - disabled
+ Eisa - enabled (Bus 0 only)
+ EisaNmi - enabled (Bus 0 only)
+ I2c - disabled (Bus 0 only)
+
+ The logical bus is assigned from the static variable PciBusNumber, which is
+ incremented with each invokation.
+
+Arguments:
+
+ McDeviceId - Supplies the MC Bus Device ID of the IOD to be intialized
+
+ PciBusNumber - Logical (Hardware) PCI Bus number.
+
+ Arguments - Variable Arguments. None for this routine.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ IOD_INT_MASK IntMask;
+ PVOID IntMaskQva;
+ ULONG Target;
+
+ //
+ // Disable MCI bus interrupts
+ //
+
+ WRITE_IOD_REGISTER_NEW(
+ McDeviceId,
+ &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntCtrl,
+ (IOD_INT_CTL_DISABLE_IO_INT | IOD_INT_CTL_DISABLE_VECT_WRITE)
+ );
+
+
+ //
+ // Clear all pending interrupts for this IOD
+ //
+
+ WRITE_IOD_REGISTER_NEW(
+ McDeviceId,
+ &((PIOD_INT_CSRS)IOD_INT_CSRS_QVA)->IntAck0,
+ 0x0
+ );
+
+ //
+ // Clear interrupt request register (New for CAP Rev2.3)
+ //
+
+ WRITE_IOD_REGISTER_NEW(
+ McDeviceId,
+ &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntReq,
+ IodIntMask
+ );
+
+ //
+ // Clear all pending EISA interrupts for IOD 0
+ //
+
+ if (PciBusNumber == 0) {
+
+ INTERRUPT_ACKNOWLEDGE((PVOID)IOD_PCI0_IACK_QVA);
+
+ }
+
+
+ // mdbfix - For now, target0 = CPU0, target1 = CPU1
+ //
+ // Write the target register.
+ //
+
+ WRITE_IOD_REGISTER_NEW(
+ McDeviceId,
+ &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntTarg,
+ HalpLogicalToPhysicalProcessor[0].all
+ );
+
+ //
+ // Write the mask bits for target 0 and 1
+ //
+
+ for (Target = 0; Target < 2; Target++) {
+
+ //
+ // Obtain the target IRR QVA
+ //
+
+ if (Target) {
+
+ IntMaskQva = (PVOID)&((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntMask1;
+
+ } else {
+
+ IntMaskQva = (PVOID)&((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntMask0;
+
+ }
+
+ IntMask.all = READ_IOD_REGISTER_NEW(
+ McDeviceId,
+ IntMaskQva
+ );
+
+ //
+ // Initialize HardErr for all buses, but Eisa and EisaNmi
+ // only for Bus 0
+ //
+
+ if (PciBusNumber == 0) {
+
+ IntMask.all =
+ IodHardErrIntMask | IodSoftErrIntMask |
+ IodEisaIntMask |IodEisaNmiIntMask;
+
+ } else {
+
+ IntMask.all = IodHardErrIntMask | IodSoftErrIntMask;
+
+ }
+
+ if (Target ) {
+
+ IntMask.all = 0;
+
+ }
+
+ WRITE_IOD_REGISTER_NEW(
+ McDeviceId,
+ IntMaskQva,
+ IntMask.all
+ );
+
+ HalpIodInterruptMask[PciBusNumber][Target] = IntMask.all;
+ }
+
+ //
+ // Enable Interrupts.
+ //
+
+ WRITE_IOD_REGISTER_NEW(
+ McDeviceId,
+ &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntCtrl,
+ (IOD_INT_CTL_ENABLE_IO_INT | IOD_INT_CTL_ENABLE_VECT_WRITE)
+ );
+}
+
+
+VOID
+HalpRawhideDecodePciVector(
+ IN ULONG PciVector,
+ OUT PULONG PciBusNumber,
+ OUT PULONG InterruptLine
+ )
+
+/*++
+
+Routine Description:
+
+ This decodes a PCI vector to obtain the PCI hardware bus number
+ and the InterruptLine.
+
+Arguments:
+
+ PciVector - Supplies the vector of the PCI interrupt that is disabled.
+
+ PciBusNumber - IOD number encoded in vector
+
+ InterruptLine - IRR interrupt bit number encoded in vector
+
+Return Value:
+
+ The PCI bus number and interrupt line are returned.
+
+--*/
+
+{
+ //
+ // Special case for NCR810 vector
+ //
+
+ if (PciVector == RawhideScsiVector) {
+
+ *PciBusNumber = RAWHIDE_SCSI_PCI_BUS;
+ *InterruptLine = IodScsiIrrBit;
+
+ } else {
+
+ //
+ // Extract the Pci bus number and Interrupt line from the vector
+ //
+
+ PciVector -= RawhidePciVectors;
+ *PciBusNumber = PciVector / IOD_PCI_VECTORS;
+ *InterruptLine = PciVector % IOD_PCI_VECTORS;
+
+ }
+}
+
+
+VOID
+HalpDisablePciInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function disables the PCI interrupt specified by Vector.
+
+Arguments:
+
+ Vector - Supplies the vector of the PCI interrupt that is disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ MC_DEVICE_ID McDeviceId;
+ IOD_INT_MASK IntMask;
+ PIOD_VECTOR_DATA IodVectorData;
+ PVOID IntMaskQva;
+ ULONG PciBusNumber;
+ ULONG InterruptLine;
+ ULONG MaskBit;
+ ULONG Target = 0;
+
+ //
+ // Decode the PCI bus number and interrupt line from the vector
+ //
+
+ HalpRawhideDecodePciVector(Vector, &PciBusNumber, &InterruptLine);
+
+ //
+ // Determine which IOD this interrupt is assigned to
+ // and obtain the IOD's geographic address.
+ //
+
+ McDeviceId = HalpIodLogicalToPhysical[PciBusNumber];
+
+ //
+ // Determine the IRR bit
+ //
+
+ MaskBit = ~(1 << InterruptLine);
+
+ //
+ // Obtain the IOD vector table entry
+ //
+
+ IodVectorData = HalpIodVectorData + PciBusNumber;
+
+ //
+ // Determine the target CPU for this vector and
+ // obtain the cooresponding IntMask QVA
+ //
+
+ if (IodVectorData->IntMask[0].all & MaskBit) {
+
+ Target = 0;
+ IntMaskQva = (PVOID)&((PIOD_INT_CSRS)IOD_INT_CSRS_QVA)->IntMask0;
+
+ } else if (IodVectorData->IntMask[1].all & MaskBit) {
+
+ Target = 1;
+ IntMaskQva = (PVOID)&((PIOD_INT_CSRS)IOD_INT_CSRS_QVA)->IntMask1;
+
+ } else {
+
+#if HALDBG
+ DbgPrint("HalpDisablePciInterrupt: Vector not assigned target\n");
+#endif
+ return;
+
+ }
+
+#if HALDBG
+ DbgPrint("HalpDisablePciInterrupt: Target %d\n", Target);
+#endif
+
+ //
+ // Unassign this vector in the IOD vector data
+ //
+
+ IodVectorData->IntMask[Target].all &= MaskBit;
+
+ //
+ // Decrement CPU vector weight
+ //
+
+ IodVectorData->TargetCpu[Target]->ListEntry.Weight--;
+
+ //
+ // Get the current state of the interrupt mask register, then clear
+ // the bit corresponding to the adjusted value of Vector to zero,
+ // to disable that PCI interrupt.
+ //
+
+ IntMask.all = READ_IOD_REGISTER_NEW(
+ McDeviceId,
+ IntMaskQva
+ );
+
+#if HALDBG
+ DbgPrint("HalpDisablePCIVector: IntMask(before) 0x%x\n", IntMask);
+#endif
+
+ IntMask.all &= MaskBit;
+
+ WRITE_IOD_REGISTER_NEW(
+ McDeviceId,
+ IntMaskQva,
+ IntMask.all
+ );
+
+#if HALDBG
+ IntMask.all = READ_IOD_REGISTER_NEW(
+ McDeviceId,
+ IntMaskQva
+ );
+
+ DbgPrint("HalpDisablePCIVector: IntMask(after) 0x%x\n", IntMask);
+#endif
+
+ //
+ // Turn off this interrupt in the software mask
+ //
+
+ HalpIodInterruptMask[PciBusNumber][Target] &= MaskBit;
+
+}
+
+
+VOID
+HalpEnablePciInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the PCI interrupt specified by Vector.
+Arguments:
+
+ Vector - Supplies the vector of the PCI interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched (ignored for Rawhide PCI interrupts; they're always levels).
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ MC_DEVICE_ID McDeviceId;
+ IOD_INT_MASK IntMask;
+ IOD_INT_TARGET_DEVICE IntTarg;
+ PIOD_VECTOR_DATA IodVectorData;
+ PVOID IntMaskQva;
+ ULONG PciBusNumber;
+ ULONG InterruptLine;
+ ULONG MaskBit;
+ ULONG Affinity;
+ ULONG Target = 0;
+
+
+#if HALDBG
+ DbgPrint(
+ "HalpEnablePciInterrupt: Vector 0x%x, Mode 0x%x\n",
+ Vector,
+ InterruptMode
+ );
+#endif
+
+ //
+ // The kernel will call this routine on the processor
+ // who will receive the interrupt
+ //
+
+ Affinity = ( 1 << PCR->Prcb->Number);
+
+ //
+ // Decode the PCI bus number and interrupt line from the Vector
+ //
+
+ HalpRawhideDecodePciVector(Vector, &PciBusNumber, &InterruptLine);
+
+#if HALDBG
+ DbgPrint(
+ "Vector 0x%x maps to PCI %d, InterruptLine %d\n",
+ Vector,
+ PciBusNumber,
+ InterruptLine
+ );
+#endif
+
+ //
+ // Determine which IOD this interrupt is assigned to
+ // and obtain the IOD's geographic address.
+ //
+
+ McDeviceId = HalpIodLogicalToPhysical[PciBusNumber];
+
+ //
+ // Determine the IRR bit
+ //
+
+ MaskBit = (ULONG) 1<< InterruptLine;
+
+ //
+ // Obtain the IOD vector table entry
+ //
+
+ IodVectorData = HalpIodVectorData + PciBusNumber;
+
+ //
+ // Obtain the Target CPU
+ //
+
+
+ if (IodVectorData->Affinity[0] == Affinity) {
+
+ Target = 0;
+ IntMaskQva = (PVOID)&((PIOD_INT_CSRS)IOD_INT_CSRS_QVA)->IntMask0;
+
+ } else {
+
+ Target = 1;
+ IntMaskQva = (PVOID)&((PIOD_INT_CSRS)IOD_INT_CSRS_QVA)->IntMask1;
+
+ }
+
+ //
+ // Handle the case where another device shares this interrupt line.
+ //
+
+ if ( HalpIodInterruptMask[PciBusNumber][Target] & MaskBit) {
+
+#if HALDBG
+ DbgPrint("Vector 0x%x already assigned\n", Vector);
+#endif
+
+ return;
+
+ }
+
+ //
+ // Get the current state of the interrupt mask register, then set
+ // the bit corresponding to the adjusted value of Vector to zero,
+ // to enable that PCI interrupt.
+ //
+
+ IntMask.all = READ_IOD_REGISTER_NEW(
+ McDeviceId,
+ IntMaskQva
+ );
+
+#if HALDBG
+ DbgPrint("HalpEnablePCIVector: IntMask(before) 0x%x\n", IntMask);
+#endif
+
+ IntMask.all |= MaskBit;
+
+ WRITE_IOD_REGISTER_NEW(
+ McDeviceId,
+ IntMaskQva,
+ IntMask.all
+ );
+
+#if HALDBG
+ IntMask.all = READ_IOD_REGISTER_NEW(
+ McDeviceId,
+ IntMaskQva
+ );
+
+ DbgPrint("HalpEnablePCIVector: IntMask(after) 0x%x\n", IntMask);
+#endif
+
+#if HALDBG
+ DumpAllIods(DumpIodFlag & IodInterruptRegisters);
+#endif
+
+ HalpIodInterruptMask[PciBusNumber][Target] |= MaskBit;
+
+#if HALDBG
+ DbgPrint(
+ "HalpEnablePCIVector: Software Mask 0x%x\n",
+ HalpIodInterruptMask[PciBusNumber][Target]
+ );
+#endif
+}
+
+
+VOID
+HalpDisableInternalInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function disables the Internal Bus interrupt specified by Vector.
+
+Arguments:
+
+ Vector - Supplies the vector of the Internal Bus interrupt to disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ MC_DEVICE_ID McDeviceId;
+ IOD_INT_MASK IntMask;
+ PIOD_VECTOR_DATA IodVectorData;
+ PVOID IntMaskQva;
+ ULONG PciBusNumber;
+ ULONG InterruptLine;
+ ULONG MaskBit;
+ ULONG Target = 0;
+
+ //
+ // Do not physically disable the Soft Error Vector because
+ // the HAL Correctable Error Handler must execute when
+ // a Soft Error occurs for system integrity.
+ //
+
+ if (Vector == RawhideSoftErrVector) {
+
+ HalpLogCorrectableErrors = FALSE;
+ return;
+
+ }
+
+ //
+ // Map the vector to an interrupt line.
+ //
+
+ switch (Vector) {
+
+ case RawhideI2cCtrlVector:
+
+ //
+ // I2C ctrl interrupt on PCI0
+ //
+
+ PciBusNumber = 0;
+
+ MaskBit = IodI2cCtrlIntMask;
+
+ break;
+
+
+ case RawhideI2cBusVector:
+
+ //
+ // I2C bus interrupt on PCI0
+ //
+
+ PciBusNumber = 0;
+
+ MaskBit = IodI2cBusIntMask;
+ break;
+
+
+ default:
+ return;
+
+ }
+
+ //
+ // Obtain the IOD geographic address for the PCI bus.
+ //
+
+ McDeviceId = HalpIodLogicalToPhysical[PciBusNumber];
+
+ //
+ // Obtain the IOD vector data for the PCI bus.
+ //
+
+ IodVectorData = HalpIodVectorData + PciBusNumber;
+
+ //
+ // Determine the target CPU for this vector and
+ // obtain the cooresponding IntMask QVA
+ //
+
+ if (IodVectorData->IntMask[0].all & MaskBit) {
+
+ Target = 0;
+ IntMaskQva = (PVOID)&((PIOD_INT_CSRS)IOD_INT_CSRS_QVA)->IntMask0;
+
+ } else if (IodVectorData->IntMask[1].all & MaskBit) {
+
+ Target = 1;
+ IntMaskQva = (PVOID)&((PIOD_INT_CSRS)IOD_INT_CSRS_QVA)->IntMask1;
+
+ } else {
+
+#if HALDBG
+ DbgPrint("HalpDisablePciInterrupt: Vector not assigned target\n");
+#endif
+ return;
+
+ }
+
+#if HALDBG
+ DbgPrint("HalpDisableInteralInterrupt: Target %d\n", Target);
+#endif
+
+ //
+ // Unassign this vector in the IOD vector data
+ //
+
+ IodVectorData->IntMask[Target].all &= ~MaskBit;
+
+ //
+ // Decrement CPU vector weight
+ //
+
+ IodVectorData->TargetCpu[Target]->ListEntry.Weight--;
+
+ //
+ // Get the current state of the interrupt mask register, then clear
+ // the bit corresponding to the adjusted value of Vector to zero,
+ // to disable that PCI interrupt.
+ //
+
+ IntMask.all = READ_IOD_REGISTER_NEW(
+ McDeviceId,
+ IntMaskQva
+ );
+
+#if HALDBG
+ DbgPrint("HalpEnablePCIVector: IntMask(before) 0x%x\n", IntMask);
+#endif
+
+ IntMask.all &= ~MaskBit;
+
+ WRITE_IOD_REGISTER_NEW(
+ McDeviceId,
+ IntMaskQva,
+ IntMask.all
+ );
+
+#if HALDBG
+ IntMask.all = READ_IOD_REGISTER_NEW(
+ McDeviceId,
+ IntMaskQva
+ );
+
+ DbgPrint("HalpEnablePCIVector: IntMask(after) 0x%x\n", IntMask);
+#endif
+
+ //
+ // Turn off this interrupt in the software mask
+ //
+
+ HalpIodInterruptMask[PciBusNumber][Target] &= ~MaskBit;
+
+}
+
+
+VOID
+HalpEnableInternalInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the Internal Bus interrupt specified by Vector.
+Arguments:
+
+ Vector - Supplies the vector of the Internal Bus interrupt that is enabled.
+
+ InterruptMode - Ignored. Rawhide device interrupts level sensitive.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ MC_DEVICE_ID McDeviceId;
+ IOD_INT_MASK IntMask;
+ IOD_INT_TARGET_DEVICE IntTarg;
+ PIOD_VECTOR_DATA IodVectorData;
+ PVOID IntMaskQva;
+ ULONG PciBusNumber;
+ ULONG InterruptLine;
+ ULONG MaskBit;
+ ULONG Affinity;
+ ULONG Target = 0;
+
+
+ //
+ // Do not physically disable the Soft Error Vector because
+ // the HAL Correctable Error Handler must execute when
+ // a Soft Error occurs for system integrity.
+ //
+
+ if (Vector == RawhideSoftErrVector) {
+
+ HalpLogCorrectableErrors = TRUE;
+ return;
+
+ }
+
+ //
+ // The kernel will call this routine on the processor
+ // who will receive the interrupt
+ //
+
+ Affinity = ( 1 << PCR->Prcb->Number);
+
+ //
+ // Map the vector to an interrupt line.
+ //
+
+ switch (Vector) {
+
+ case RawhideI2cCtrlVector:
+
+ //
+ // I2C ctrl interrupt on PCI0
+ //
+
+ PciBusNumber = 0;
+
+ MaskBit = IodI2cCtrlIntMask;
+
+ break;
+
+ case RawhideI2cBusVector:
+
+ //
+ // I2C ctrl interrupt on PCI0
+ //
+
+ PciBusNumber = 0;
+
+ MaskBit = IodI2cBusIntMask;
+
+ break;
+
+
+ default:
+ return;
+
+ }
+
+#if HALDBG
+ DbgPrint(
+ "HalpEnableInternalInterrupt: Vector 0x%x, Mode 0x%x\n",
+ Vector,
+ InterruptMode
+ );
+#endif
+
+
+#if HALDBG
+ DbgPrint(
+ "Vector 0x%x maps to PCI %d, InterruptLine %d\n",
+ Vector,
+ 0,
+ MaskBit
+ );
+#endif
+
+ //
+ // Obtain the IOD geographic address for the PCI bus.
+ //
+
+ McDeviceId = HalpIodLogicalToPhysical[PciBusNumber];
+
+ //
+ // Obtain the IOD vector table entry for the PCI bus.
+ //
+
+ IodVectorData = HalpIodVectorData + PciBusNumber;
+
+ //
+ // Determine the target CPU for this vector and
+ // obtain the cooresponding IntMask QVA
+ //
+
+ if (IodVectorData->Affinity[0] == Affinity) {
+
+ Target = 0;
+ IntMaskQva = (PVOID)&((PIOD_INT_CSRS)IOD_INT_CSRS_QVA)->IntMask0;
+
+ } else {
+
+ Target = 1;
+ IntMaskQva = (PVOID)&((PIOD_INT_CSRS)IOD_INT_CSRS_QVA)->IntMask1;
+
+ }
+
+ //
+ // Get the current state of the interrupt mask register, then set
+ // the bit corresponding to the adjusted value of Vector to zero,
+ // to enable that PCI interrupt.
+ //
+
+ IntMask.all = READ_IOD_REGISTER_NEW(
+ McDeviceId,
+ IntMaskQva
+ );
+
+#if HALDBG
+ DbgPrint("HalpEnableInternalVector: IntMask(before) 0x%x\n", IntMask);
+#endif
+
+ IntMask.all |= MaskBit;
+
+ WRITE_IOD_REGISTER_NEW(
+ McDeviceId,
+ IntMaskQva,
+ IntMask.all
+ );
+
+#if HALDBG
+ IntMask.all = READ_IOD_REGISTER_NEW(
+ McDeviceId,
+ IntMaskQva
+ );
+
+ DbgPrint("HalpEnableInternalVector: IntMask(after) 0x%x\n", IntMask);
+#endif
+
+#if HALDBG
+ DumpAllIods(DumpIodFlag & IodInterruptRegisters);
+#endif
+
+ HalpIodInterruptMask[PciBusNumber][Target] |= MaskBit;
+
+#if HALDBG
+ DbgPrint(
+ "HalpEnableInternalVector: Software Mask 0x%x\n",
+ HalpIodInterruptMask[PciBusNumber][Target]
+ );
+#endif
+}
+
+
+#if HALDBG
+ULONG DeviceDispatchFlag = 0;
+
+#define DispatchPrint(_X_)\
+{ \
+ if (DeviceDispatchFlag) DbgPrint _X_; \
+} \
+
+#else
+
+#define DispatchPrint(_X_)
+
+#endif
+
+#ifdef FORCE_CORRECTABLE_ERROR
+ULONG DispatchSoftError = 0;
+#endif // FORCE_CORRECTABLE_ERROR
+
+
+#ifndef POSTED
+
+
+BOOLEAN
+HalpDeviceDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PKTRAP_FRAME TrapFrame
+ )
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt being generated
+ via the vector that is connected to an interrupt object associated with
+ the PCI device interrupts. Its function is to call the second-level
+ interrupt dispatch routine.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the PCI interrupt register.
+
+ TrapFrame - Supplies a pointer to the trap frame for this interrupt.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+{
+ PULONG DispatchCode;
+ PKINTERRUPT InterruptObject;
+ IOD_POSTED_INTERRUPT IntReq;
+ MC_ENUM_CONTEXT mcCtx;
+ ULONG PciIdtIndex;
+ ULONG VectorShift;
+ ULONG PciBusNumber;
+ ULONG Target = 0;
+ volatile IOD_PCI_REVISION IodRevision;
+
+ DispatchPrint(("HalpDeviceDispatch: enter\n"));
+
+ //
+ // Intialize enumerator.
+ //
+
+ HalpMcBusEnumStart ( HalpIodMask, &mcCtx );
+
+ //
+ // Handle interrupts for each IOD as follows.
+ //
+ // 1. read interrupt request register for IOD
+ // 2. process pending EISA interrupt.
+ // 3. process all pending PCI interrupts.
+ // 4. acknowledge the interrupts serviced.
+ // 5. start over with next IOD.
+ //
+
+ PciBusNumber = 0;
+
+ while ( HalpMcBusEnum( &mcCtx ) ) {
+
+ //
+ // Read in the interrupt register.
+ //
+
+ IntReq.all = READ_IOD_REGISTER_NEW(
+ mcCtx.McDeviceId,
+ &((PIOD_INT_CSRS)IOD_INT_CSRS_QVA)->IntReq);
+
+ DispatchPrint((
+ "HalpDeviceDispatch: IOD 0x%x, IRR 0x%x\n",
+ mcCtx.McDeviceId.all,
+ IntReq.all
+ ));
+
+ // mdbfix - is this really necessary?
+ //
+ // Consider only those interrupts which are currently enabled.
+ //
+
+#if HALDBG
+ if ( IntReq.all !=
+ (IntReq.all & HalpIodInterruptMask[PciBusNumber][Target]) ) {
+
+ DispatchPrint((
+ "HalpDeviceDispatch: IOD (%d, %d), IRR Unmasked 0x%x != IRR Masked 0x%x\n",
+ mcCtx.McDeviceId.Gid,
+ mcCtx.McDeviceId.Mid,
+ IntReq.all,
+ (IntReq.all & HalpIodInterruptMask[PciBusNumber][Target])
+ ));
+ }
+#endif
+
+ IntReq.all &= HalpIodInterruptMask[PciBusNumber][Target];
+
+ DispatchPrint((
+ "HalpDeviceDispatch: IRR masked 0x%x\n",
+ IntReq.all
+ ));
+
+ //
+ // If no interrupts pending, do not
+ // send INT ACK and skip to next bus.
+ //
+
+ if (IntReq.all == 0) {
+ PciBusNumber++;
+ continue;
+ }
+
+ //
+ // Handle Error Interrupts
+ //
+
+ if (IntReq.HardErr ) {
+
+ //
+ // Handle hard error interrupt
+ //
+#if HALDBG
+ DispatchPrint((
+ "Hard Error Interrupt on IOD (%d, %d)\n",
+ mcCtx.McDeviceId.Gid,
+ mcCtx.McDeviceId.Mid
+ ));
+#endif // HALDBG
+
+ HalpIodHardErrorInterrupt();
+
+ }
+
+ if ( IntReq.SoftErr ) {
+
+ //
+ // Dispatch Event logging interrupt.
+ //
+
+#if HALDBG
+ DispatchPrint((
+ "Soft Error Interrupt on IOD (%d, %d)\n",
+ mcCtx.McDeviceId.Gid,
+ mcCtx.McDeviceId.Mid
+ ));
+#endif // HALDBG
+
+#if 1
+// mdbfix - until an error log driver exists to connect the
+// soft error interrupt, explicitly call the ISR.
+
+ HalpIodSoftErrorInterrupt();
+
+#else
+ DispatchCode =
+ (PULONG)PCR->InterruptRoutine[RawhideSoftErrVector];
+
+ InterruptObject = CONTAINING_RECORD(
+ DispatchCode,
+ KINTERRUPT,
+ DispatchCode
+ );
+
+ ((PSECOND_LEVEL_DISPATCH)
+ InterruptObject->DispatchAddress)(
+ InterruptObject,
+ InterruptObject->ServiceContext,
+ TrapFrame
+ );
+#endif
+ }
+
+ //
+ // Process PCI interrupts.
+ //
+
+ if ( IntReq.Pci ) {
+
+ DispatchPrint((
+ "HalpDeviceDispatch: PCI interrupt\n", IntReq.all
+ ));
+
+ //
+ // Initialize IDT offset to PCI vectors and obtain
+ // the vector table section for this PCI bus
+ //
+
+ PciIdtIndex = RawhidePciVectors + (PciBusNumber << 4);
+
+ VectorShift = IntReq.Pci;
+
+ while (VectorShift) {
+
+ if ( VectorShift & 0x1 ) {
+
+ DispatchPrint((
+ "HalpDeviceDispatch: Dispatch PCI IDT Index %d\n",
+ PciIdtIndex
+ ));
+
+
+ //
+ // Map the Interrupt Request Register bit to a vector
+ //
+
+
+ DispatchCode = (PULONG)PCR->InterruptRoutine[PciIdtIndex];
+ InterruptObject = CONTAINING_RECORD(
+ DispatchCode,
+ KINTERRUPT,
+ DispatchCode
+ );
+
+ ((PSECOND_LEVEL_DISPATCH)InterruptObject->DispatchAddress)(
+ InterruptObject,
+ InterruptObject->ServiceContext,
+ TrapFrame
+ );
+
+ }
+
+ //
+ // Try next vector
+ //
+
+ PciIdtIndex++;
+ VectorShift = VectorShift >> 1;
+
+ } //end while(VectorShift);
+
+ } //end if(IntReq.Pci);
+
+ //
+ // Handle bus 0 specific interrupts
+ //
+
+ if ( PciBusNumber == 0 ) {
+
+ if ( IntReq.Eisa ) {
+
+ //
+ // EISA interrupt. Call HalpEisaDispatch.
+ //
+
+ HalpEisaDispatch(
+ Interrupt,
+ (PVOID)IOD_PCI0_IACK_QVA,
+ TrapFrame
+ );
+
+ }
+
+ if (IntReq.I2cBus) {
+
+ //
+ // I2c Bus Vector
+ //
+
+ DispatchCode =
+ (PULONG)PCR->InterruptRoutine[RawhideI2cBusVector] ;
+ InterruptObject = CONTAINING_RECORD(
+ DispatchCode,
+ KINTERRUPT,
+ DispatchCode
+ );
+
+ ((PSECOND_LEVEL_DISPATCH)
+ InterruptObject->DispatchAddress)(
+ InterruptObject,
+ InterruptObject->ServiceContext,
+ TrapFrame
+ );
+ }
+
+ if (IntReq.I2cCtrl) {
+
+ //
+ // I2c Controller Vector
+ //
+
+ DispatchCode =
+ (PULONG)PCR->InterruptRoutine[RawhideI2cCtrlVector] ;
+ InterruptObject = CONTAINING_RECORD(
+ DispatchCode,
+ KINTERRUPT,
+ DispatchCode
+ );
+
+ ((PSECOND_LEVEL_DISPATCH)
+ InterruptObject->DispatchAddress)(
+ InterruptObject,
+ InterruptObject->ServiceContext,
+ TrapFrame
+ );
+ }
+
+ }
+
+ //
+ // Handle NCR810 for PCI bus 1
+ //
+
+ if ( ( PciBusNumber == 1 ) && ( IntReq.Ncr810 ) ) {
+
+
+ DispatchCode = (PULONG)PCR->InterruptRoutine[RawhideScsiVector];
+ InterruptObject = CONTAINING_RECORD( DispatchCode,
+ KINTERRUPT,
+ DispatchCode );
+
+ ((PSECOND_LEVEL_DISPATCH)InterruptObject->DispatchAddress)(
+ InterruptObject,
+ InterruptObject->ServiceContext,
+ TrapFrame );
+ }
+
+
+ //
+ // Acknowledge after All pending interrupts serviced for this IOD
+ // for UP interrupt scheme, all Interrupts routed to targe 0.
+ //
+
+ WRITE_IOD_REGISTER_NEW(
+ mcCtx.McDeviceId,
+ &((PIOD_INT_CSRS)IOD_INT_CSRS_QVA)->IntAck0,
+ 0x0
+ );
+
+ //
+ // ecrfix - Read the IOD revision to force the write.
+ //
+
+ IodRevision.all =
+ READ_IOD_REGISTER_NEW(
+ mcCtx.McDeviceId,
+ &((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->PciRevision );
+
+
+ //
+ // Next PCI bus number
+ //
+
+ PciBusNumber++;
+
+ } //end while (HalpMcBusEnum())
+
+ return TRUE;
+
+}
+
+#else // POSTED
+
+
+BOOLEAN
+HalpDeviceDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PKTRAP_FRAME TrapFrame
+ )
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt being generated
+ via the vector that is connected to an interrupt object associated with
+ the PCI device interrupts. Its function is to call the second-level
+ interrupt dispatch routine.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the PCI interrupt register.
+
+ TrapFrame - Supplies a pointer to the trap frame for this interrupt.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+{
+ PULONG DispatchCode;
+ PKINTERRUPT InterruptObject;
+ PIOD_POSTED_INTERRUPT PostedInterrupts;
+ IOD_POSTED_INTERRUPT IntReq;
+ MC_DEVICE_ID McDeviceId;
+ PKPRCB Prcb;
+ PVOID IodAckQva;
+ ULONG PciIdtIndex;
+ ULONG VectorShift;
+ ULONG PciBusNumber;
+ ULONG Target = 0;
+ volatile IOD_PCI_REVISION IodRevision;
+
+ Prcb = PCR->Prcb;
+ PciIdtIndex = RawhidePciVectors;
+
+
+ //
+ // Obtain the processor area in IOD vector table
+ // and the IOD service mask.
+ //
+
+ PostedInterrupts = (PIOD_POSTED_INTERRUPT) HAL_PCR->PostedInterrupts;
+
+ DispatchPrint((
+ "DeviceDispatch: enter, IodVectorTable 0x%x\n",
+ PostedInterrupts
+ ));
+
+
+ //
+ // Handle interrupts for each IOD as follows.
+ //
+ // 1. read the interrupt vector table entry.
+ // 2. process pending EISA interrupt.
+ // 3. process all pending PCI interrupts.
+ // 4. acknowledge the interrupts serviced.
+ // 5. start over with next IOD.
+ //
+
+
+ for ( PciBusNumber = 0;
+ PciBusNumber < HalpNumberOfIods;
+ PciBusNumber++, PostedInterrupts++) {
+
+ DispatchPrint((
+ "DeviceDispatch: IntReq: 0x%x\n\tTarget: %d\n\tDevice: (%d, %d)",
+ PostedInterrupts->IntReq,
+ PostedInterrupts->Target,
+ (PostedInterrupts->McDevId >> 0x3) & 0x7,
+ PostedInterrupts->McDevId & 0x7
+ ));
+
+ //
+ // Perform a passive release.
+ //
+
+ if (PostedInterrupts->Valid && (PostedInterrupts->IntReq == 0) ) {
+
+ IntReq.all = PostedInterrupts->IntReq;
+ McDeviceId.all = PostedInterrupts->McDevId;
+
+ Target = PostedInterrupts->Target;
+
+ //
+ // Invalidate this entry to prevent the next device interrupt
+ // dispatch from using stale information. We must do this
+ // before the ACK, which allows the IOD to post.
+ //
+
+ PostedInterrupts->all = 0;
+
+ IOD_INTERRUPT_ACKNOWLEDGE(McDeviceId, Target);
+
+ //
+ // Skip to check next vector
+ //
+
+ continue;
+
+ }
+
+ if (PostedInterrupts->Valid && PostedInterrupts->IntReq) {
+
+ DispatchPrint((
+ "DeviceDispatch: Interrupt(s) Pending on PCI bus %d\n",
+ PciBusNumber
+ ));
+
+
+ IntReq.all = PostedInterrupts->IntReq;
+ McDeviceId.all = PostedInterrupts->McDevId;
+
+ Target = PostedInterrupts->Target;
+
+ DispatchPrint((
+ "DeviceDispatch: IodVectorTable\n\tIntReq: 0x%x\n\tTarget: %d\n\tDevice: (%d, %d)",
+ PostedInterrupts->IntReq,
+ PostedInterrupts->Target,
+ McDeviceId.Gid,
+ McDeviceId.Mid
+ ));
+
+ //
+ // Consider only those interrupts which are currently enabled.
+ //
+
+ IntReq.all &= HalpIodInterruptMask[PciBusNumber][Target];
+
+ DispatchPrint((
+ "DeviceDispatch: IntReq (masked) 0x%x\n",
+ IntReq.all
+ ));
+
+ //
+ // Handle Error Interrupts
+ //
+
+ if (IntReq.HardErr ) {
+
+ //
+ // Handle hard error interrupt
+ //
+
+ DispatchPrint((
+ "Hard Error Interrupt on IOD (%d, %d)\n",
+ McDeviceId.Gid,
+ McDeviceId.Mid
+ ));
+
+ HalpIodHardErrorInterrupt();
+
+ }
+
+ if ( IntReq.SoftErr ) {
+
+ //
+ // Dispatch Event logging interrupt.
+ //
+
+ DispatchPrint((
+ "Soft Error Interrupt on IOD (%d, %d)\n",
+ McDeviceId.Gid,
+ McDeviceId.Mid
+ ));
+
+ HalpIodSoftErrorInterrupt();
+
+ }
+
+#ifdef FORCE_CORRECTABLE_ERROR
+ if ( (PCR->Number == HAL_PRIMARY_PROCESSOR) &&
+ DispatchSoftError ) {
+ DispatchSoftError = 0;
+ HalpIodSoftErrorInterrupt();
+ }
+#endif // FORCE_CORRECTABLE_ERROR
+
+ //
+ // Process PCI interrupts.
+ //
+
+ if ( IntReq.Pci ) {
+
+ DispatchPrint((
+ "HalpDeviceDispatch: PCI interrupt\n", IntReq.all
+ ));
+
+ //
+ // Initialize IDT offset to PCI vectors and obtain
+ // the vector table section for this PCI bus
+ //
+
+ PciIdtIndex = RawhidePciVectors + (PciBusNumber << 4);
+
+ VectorShift = IntReq.Pci;
+
+ while (VectorShift) {
+
+ if ( VectorShift & 0x1 ) {
+
+ DispatchPrint((
+ "HalpDeviceDispatch: Dispatch PCI IDT Index %d\n",
+ PciIdtIndex
+ ));
+
+
+ //
+ // Map the Interrupt Request Register bit to a vector
+ //
+
+
+ DispatchCode = (PULONG)PCR->InterruptRoutine[PciIdtIndex];
+ InterruptObject = CONTAINING_RECORD(
+ DispatchCode,
+ KINTERRUPT,
+ DispatchCode
+ );
+
+ ((PSECOND_LEVEL_DISPATCH)InterruptObject->DispatchAddress)(
+ InterruptObject,
+ InterruptObject->ServiceContext,
+ TrapFrame
+ );
+
+ }
+
+ //
+ // Try next vector
+ //
+
+ PciIdtIndex++;
+ VectorShift = VectorShift >> 1;
+
+ } //end while(VectorShift);
+
+ } //end if(IntReq.Pci);
+
+ //
+ // Handle bus 0 specific interrupts
+ //
+
+ if ( PciBusNumber == 0 ) {
+
+ if ( IntReq.Eisa ) {
+
+ //
+ // EISA interrupt. Call HalpEisaDispatch.
+ //
+
+ HalpEisaDispatch(
+ Interrupt,
+ (PVOID)IOD_PCI0_IACK_QVA,
+ TrapFrame
+ );
+
+ }
+
+ //
+ // Handle I2c Bus Vector
+ //
+
+ if (IntReq.I2cBus) {
+
+
+ DispatchCode =
+ (PULONG)PCR->InterruptRoutine[RawhideI2cBusVector] ;
+ InterruptObject = CONTAINING_RECORD(
+ DispatchCode,
+ KINTERRUPT,
+ DispatchCode
+ );
+
+ ((PSECOND_LEVEL_DISPATCH)
+ InterruptObject->DispatchAddress)(
+ InterruptObject,
+ InterruptObject->ServiceContext,
+ TrapFrame
+ );
+ }
+
+ //
+ // Handle I2c Controller Vector
+ //
+
+ if (IntReq.I2cCtrl) {
+
+ DispatchCode =
+ (PULONG)PCR->InterruptRoutine[RawhideI2cCtrlVector] ;
+ InterruptObject = CONTAINING_RECORD(
+ DispatchCode,
+ KINTERRUPT,
+ DispatchCode
+ );
+
+ ((PSECOND_LEVEL_DISPATCH)
+ InterruptObject->DispatchAddress)(
+ InterruptObject,
+ InterruptObject->ServiceContext,
+ TrapFrame
+ );
+ }
+
+ }
+
+ //
+ // Handle NCR810 for PCI bus 1
+ //
+
+ if ( ( PciBusNumber == 1 ) && ( IntReq.Ncr810 ) ) {
+
+
+ DispatchCode = (PULONG)PCR->InterruptRoutine[RawhideScsiVector];
+ InterruptObject = CONTAINING_RECORD( DispatchCode,
+ KINTERRUPT,
+ DispatchCode );
+
+ ((PSECOND_LEVEL_DISPATCH)InterruptObject->DispatchAddress)(
+ InterruptObject,
+ InterruptObject->ServiceContext,
+ TrapFrame );
+ }
+
+ //
+ // Invalidate this entry to prevent the next device interrupt
+ // dispatch from using stale information. We must do this
+ // before the ACK, which allows the IOD to post.
+ //
+
+ PostedInterrupts->all = 0;
+
+ //
+ // Acknowledge the interrupt
+ //
+
+ IOD_INTERRUPT_ACKNOWLEDGE(McDeviceId, Target);
+
+ } //end if (PostedInterrupts.Valid && PostedInterrupts.IntReq)
+
+
+ } //end for
+
+ return TRUE;
+
+}
+
+#endif //POSTED
+
+
+VOID
+HalpAcknowledgeIpiInterrupt(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Acknowledge the interprocessor interrupt on the current processor.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PIOD_GENERAL_CSRS IodGeneralCsrs;
+ IOD_WHOAMI IodWhoAmI;
+ MC_ENUM_CONTEXT mcCtx;
+ MC_DEVICE_ID McDeviceId;
+ volatile IOD_PCI_REVISION IodRevision;
+
+ PKPRCB Prcb;
+
+
+ //
+ // Avoid a WhoAmI register read by using the PCR
+ //
+
+ Prcb = PCR->Prcb;
+ McDeviceId.all = HalpLogicalToPhysicalProcessor[Prcb->Number].all;
+
+ //
+ // Acknownledge the ip interrupt by writing to our own
+ // ip interrupt acknowledge.
+ //
+
+ IP_INTERRUPT_ACKNOWLEDGE( McDeviceId );
+
+ return;
+
+}
diff --git a/private/ntos/nthals/halraw/alpha/rwref.h b/private/ntos/nthals/halraw/alpha/rwref.h
new file mode 100644
index 000000000..1b691e0e0
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/rwref.h
@@ -0,0 +1,109 @@
+/*++
+
+Copyright (c) 1995 Digital Equipment Corporation
+
+Module Name:
+
+ rwref.h
+
+Abstract:
+
+ This file defines the structures and definitions of the Rawhide
+ interrupt architecture.
+
+Author:
+
+ Matthew Buchman 18 Sept 1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#ifndef _RAWREFH_
+#define _RAWREFH_
+
+#if !defined(_LANGUAGE_ASSEMBLY)
+
+//
+// Layout of platform usable portion of vector table
+//
+
+enum _RAWHIDE_INTERRUPT_VECTORS {
+
+ //
+ // 16 Eisa/Isa vectors starting at vector 32.
+ //
+
+ RawhideEisaVectors = EISA_VECTORS, // Eisa base vector
+ RawhideIsaVectors = ISA_VECTORS, // Isa base vector
+
+ RawhideMaxEisaVector = MAXIMUM_EISA_VECTOR, // Maximum Eisa/Isa vector
+
+ //
+ // All buses, except bus 1, have 16 PCI vectors
+ // PciVector = 16*BusNumber + PinToLine(Slot, Interrupt)
+ //
+
+ RawhidePciVectors = PCI_VECTORS,
+
+ RawhidePci0Vectors = PCI_VECTORS, // PCI bus 0
+ RawhidePci1Vectors = (PCI_VECTORS + 0x10), // PCI bus 1
+ RawhidePci2Vectors = (PCI_VECTORS + 0x20), // PCI bus 2
+ RawhidePci3Vectors = (PCI_VECTORS + 0x30), // PCI bus 3
+
+ // One special case for PCI vectors is NCR810 Scsi on bus 1
+ // whereas MAXIMUM_PCI_VECTOR is unused on other platforms,
+ // we use it for this special case.
+
+ RawhideScsiVector = MAXIMUM_PCI_VECTOR, // NCR810 SCSI, bus 1
+
+ RawhideMaxPciVector = MAXIMUM_PCI_VECTOR, // Max Rawhide PCI vector
+
+ //
+ // Miscellaneous
+ //
+
+
+ RawhideHardErrVector, // IOD Hard Error
+
+ //
+ // Internal Bus Vectors
+ //
+
+ RawhideInternalBusVectors,
+
+ RawhideSoftErrVector = RawhideInternalBusVectors, // IOD Soft Error
+
+ RawhideI2cCtrlVector, // I^2C Controller, bus 0
+ RawhideI2cBusVector, // I^2C vector, bus 0
+
+ RawhideMaxInternalBusVector
+
+};
+
+#define IOD_PCI_VECTORS 0x10
+
+//
+// Internal Bus interrupt line values
+//
+// These line values allow device drivers to connect
+// to interrupts for the Correctable, I2C Bus, and I2C
+// controller interrupts. These interrupts are connected
+// via the internal bus for NT 3.51
+//
+
+enum _RAWHIDE_INTERNAL_BUS_INTERRUPT_LINE {
+
+ RawhideSoftErrInterruptLine, // IOD Soft Error
+ RawhideI2cCtrlInterruptLine, // I^2C Controller, bus 0
+ RawhideI2cBusInterruptLine // I^2C vector, bus 0
+
+};
+
+#endif // _LANGUAGE_ASSEMBLY
+
+#endif // _RAWREFH_
diff --git a/private/ntos/nthals/halraw/alpha/rwsysint.c b/private/ntos/nthals/halraw/alpha/rwsysint.c
new file mode 100644
index 000000000..f3450c747
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/rwsysint.c
@@ -0,0 +1,501 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ alsysint.c
+
+Abstract:
+
+ This module implements the HAL enable/disable system interrupt, and
+ request interprocessor interrupt routines for the Alcor system.
+
+Author:
+
+ Joe Notarangelo 20-Jul-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "rawhide.h"
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpGetSystemInterruptVector)
+#endif
+
+
+//
+// Function prototype
+//
+
+VOID
+HalpDisablePciInterrupt(
+ IN ULONG Vector
+ );
+
+VOID
+HalpEnablePciInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+VOID
+HalpDisableInternalInterrupt(
+ IN ULONG Vector
+ );
+
+VOID
+HalpEnableInternalInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+
+VOID
+HalDisableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This routine disables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is disabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // disable the EISA interrrupt.
+ //
+
+ if (Vector >= EISA_VECTORS &&
+ Vector < MAXIMUM_EISA_VECTOR &&
+ Irql == DEVICE_HIGH_LEVEL) {
+ HalpDisableEisaInterrupt(Vector);
+ }
+
+ //
+ // If the vector number is within the range of the PCI interrupts, then
+ // disable the PCI interrrupt. Remember that, unlike other platforms,
+ // MAXIMUM_PCI_VECTOR is assigned rather than used as a place holder.
+ //
+
+ if (Vector >= RawhidePciVectors &&
+ Vector < RawhideMaxPciVector &&
+ Irql == DEVICE_HIGH_LEVEL) {
+ HalpDisablePciInterrupt(Vector);
+ }
+
+ //
+ // If the vector number is within the range of the Intenal bus
+ // interrupts, then disable the interrupt.
+ //
+
+ if (Vector >= RawhideInternalBusVectors &&
+ Vector <= RawhideMaxInternalBusVector &&
+ Irql == DEVICE_HIGH_LEVEL ) {
+ HalpDisableInternalInterrupt(Vector);
+ }
+
+ //
+ // If the vector is a performance counter vector we will ignore
+ // the enable - the performance counters are enabled directly by
+ // the wrperfmon callpal. Wrperfmon must be controlled directly
+ // by the driver.
+ //
+
+ switch (Vector) {
+
+ case PC0_VECTOR:
+ case PC1_VECTOR:
+ case PC2_VECTOR:
+
+ break;
+
+ } //end switch Vector
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+
+BOOLEAN
+HalEnableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is enabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ TRUE if the system interrupt was enabled
+
+--*/
+
+{
+ BOOLEAN Enabled = FALSE;
+ KIRQL OldIrql;
+
+#if 0 // ecrfix
+ DbgPrint(
+ "HalEnableSystemInterrupt: Vector 0x%x, Irql 0x%x, InterruptMode 0x%x\n",
+ Vector,
+ Irql,
+ InterruptMode
+ );
+#endif
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // enable the EISA interrrupt and set the Level/Edge register.
+ //
+
+ if (Vector >= EISA_VECTORS &&
+ Vector < MAXIMUM_EISA_VECTOR &&
+ Irql == DEVICE_HIGH_LEVEL) {
+
+#if 0 // ecrfix
+ DbgPrint("HalEnableSystemInterrupt: Eisa Vector\n");
+#endif
+ HalpEnableEisaInterrupt( Vector, InterruptMode );
+ Enabled = TRUE;
+ }
+
+ //
+ // If the vector number is within the range of the PCI interrupts, then
+ // enable the PCI interrrupt. Remember, unlike other platforms,
+ // MAXIMUM_PCI_VECTOR is assigned rather than used as a place holder.
+ //
+
+ else if (Vector >= RawhidePciVectors &&
+ Vector <= RawhideMaxPciVector &&
+ Irql == DEVICE_HIGH_LEVEL) {
+
+#if 0 // ecrfix
+ DbgPrint("HalEnableSystemInterrupt: Pci Vector\n");
+#endif
+ HalpEnablePciInterrupt( Vector, InterruptMode );
+ Enabled = TRUE;
+ }
+
+ //
+ // If the vector number is within the range of the Intenal bus
+ // interrupts.
+ //
+
+ if (Vector >= RawhideInternalBusVectors &&
+ Vector < RawhideMaxInternalBusVector &&
+ Irql == DEVICE_HIGH_LEVEL ) {
+
+#if 0 // ecrfix
+ DbgPrint("HalEnableSystemInterrupt: Internal Vector\n");
+#endif
+ HalpEnableInternalInterrupt( Vector, InterruptMode );
+ Enabled = TRUE;
+ }
+
+ //
+ // If the vector is a performance counter vector we will ignore
+ // the enable - the performance counters are enabled directly by
+ // the wrperfmon callpal. Wrperfmon must be controlled directly
+ // by the driver.
+ //
+
+ switch (Vector) {
+
+ case PC0_VECTOR:
+ case PC1_VECTOR:
+ case PC2_VECTOR:
+
+ Enabled = TRUE;
+ break;
+
+ } //end switch Vector
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+#if 0 // ecrfix
+ DbgPrint("HalEnableSystemInterrupt: Enabled = %s\n", Enabled?"TRUE":"FALSE");
+#endif
+
+ return Enabled;
+
+}
+
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified bus interrupt level and/or vector. The
+ system interrupt vector and IRQL are suitable for use in a subsequent
+ call to KeInitializeInterrupt.
+
+ We only use InterfaceType and BusInterruptLevel. BusInterruptVector
+ for EISA and ISA are the same as the InterruptLevel, so ignore.
+
+Arguments:
+
+ BusHandler - Supplies a pointer to the bus handler of the bus that
+ needs a system interrupt vector.
+
+ RootHandler - Supplies a pointer to the bus handler of the root
+ bus for the bus represented by BusHandler.
+
+ BusInterruptLevel - Supplies the bus-specific interrupt level.
+
+ BusInterruptVector - Supplies the bus-specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the affinity for the requested vector
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+
+{
+ INTERFACE_TYPE InterfaceType = BusHandler->InterfaceType;
+ ULONG BusNumber = BusHandler->BusNumber;
+ ULONG Vector;
+
+#if HALDBG
+ DbgPrint("HalpGetSystemInterruptVector: Vector 0x%x\n", BusInterruptVector);
+#endif
+
+ //
+ // Handle the special internal bus defined for the processor itself
+ // and used to control the performance counters in the 21064.
+ //
+
+ if( InterfaceType == ProcessorInternal ) {
+
+ Vector = HalpGet21164PerformanceVector( BusInterruptLevel, Irql );
+
+ if( Vector != 0 ){
+
+ //
+ // Success
+ //
+
+ *Affinity = HalpActiveProcessors;
+ return Vector;
+
+ } else {
+
+ //
+ // Unrecognized processor interrupt.
+ //
+
+ *Irql = 0;
+ *Affinity = 0;
+ return 0;
+
+ }
+
+ }
+
+ //
+ // Rawhide uses the Internal bus to make system management interupts
+ // visible to device drivers. The devices defined for the internal
+ // bus for Rawhide are the Correctable Error and the I2C Bus.
+ //
+
+ if( (InterfaceType == Internal) ) {
+
+
+#if HALDBG
+ DbgPrint("HalpGetSystemInterruptVector: Internal Vector\n");
+#endif
+
+ return HalpGetRawhideInternalInterruptVector(
+ BusHandler,
+ RootHandler,
+ BusInterruptLevel,
+ BusInterruptVector,
+ Irql,
+ Affinity
+ );
+
+ }
+
+ //
+ // Handle Isa/Eisa bus devices.
+ //
+ // N.B. The bus interrupt level is the actual E/ISA signal name for
+ // option boards while the bus interrupt level is the actual
+ // interrupt vector number for internal devices.
+ //
+
+ if( (InterfaceType == Isa) ||
+ (InterfaceType == Eisa) ){
+
+#if HALDBG
+ DbgPrint("HalpGetSystemInterruptVector: Eisa Vector\n");
+#endif
+
+ return HalpGetRawhideEisaInterruptVector(
+ BusHandler,
+ RootHandler,
+ BusInterruptLevel,
+ BusInterruptVector,
+ Irql,
+ Affinity
+ );
+
+ }
+
+ if( (InterfaceType == PCIBus) ) {
+#if HALDBG
+ DbgPrint(
+ "HalpGetSystemInterruptVector: PCIBUS, level 0x%x, vector 0x%x\n",
+ BusInterruptLevel,
+ BusInterruptVector
+ );
+#endif
+
+ return HalpGetRawhidePciInterruptVector(
+ BusHandler,
+ RootHandler,
+ BusInterruptLevel,
+ BusInterruptVector,
+ Irql,
+ Affinity
+ );
+ }
+
+
+ //
+ // Not an interface supported on Alpha systems
+ //
+
+ *Irql = 0;
+ *Affinity = 0;
+ return(0);
+}
+
+
+VOID
+HalRequestIpi (
+ IN ULONG Mask
+ )
+/*++
+
+Routine Description:
+
+ This routine requests an interprocessor interrupt on a set of processors.
+
+Arguments:
+
+ Mask - Supplies the set of processors that are sent an interprocessor
+ interrupt.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ MC_DEVICE_ID McDeviceId;
+ ULONG LogicalCpu;
+
+ //
+ // Scan the mask for logical CPU numbers
+ //
+
+ for (LogicalCpu=0; LogicalCpu< (HAL_MAXIMUM_PROCESSOR+1); LogicalCpu++) {
+
+ //
+ // The Logical to Geographic ID was saved
+ // in HalStartNextProcessor
+ //
+
+ if (Mask & 0x1) {
+
+ McDeviceId.all = HalpLogicalToPhysicalProcessor[LogicalCpu].all;
+
+ //
+ // Send the IP interrupt by writing to the
+ // IP interrupt for the Device Id.
+ //
+
+ IP_INTERRUPT_REQUEST( McDeviceId );
+ }
+
+ Mask = Mask >> 1;
+ }
+
+ return;
+}
diff --git a/private/ntos/nthals/halraw/alpha/vga.c b/private/ntos/nthals/halraw/alpha/vga.c
new file mode 100644
index 000000000..764c585af
--- /dev/null
+++ b/private/ntos/nthals/halraw/alpha/vga.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\vga.c"
+
diff --git a/private/ntos/nthals/halraw/bushnd.c b/private/ntos/nthals/halraw/bushnd.c
new file mode 100644
index 000000000..a1e648dc1
--- /dev/null
+++ b/private/ntos/nthals/halraw/bushnd.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 "..\bushnd.c"
diff --git a/private/ntos/nthals/halraw/dirs b/private/ntos/nthals/halraw/dirs
new file mode 100644
index 000000000..a2a38f0fd
--- /dev/null
+++ b/private/ntos/nthals/halraw/dirs
@@ -0,0 +1,24 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+
+NOTE: Commented description of this file is in \nt\bak\bin\dirs.tpl
+
+!ENDIF
+
+DIRS=up
+
+OPTIONAL_DIRS=mp
diff --git a/private/ntos/nthals/halraw/drivesup.c b/private/ntos/nthals/halraw/drivesup.c
new file mode 100644
index 000000000..38259e5f4
--- /dev/null
+++ b/private/ntos/nthals/halraw/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/halraw/hal.rc b/private/ntos/nthals/halraw/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/halraw/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/halraw/hal.src b/private/ntos/nthals/halraw/hal.src
new file mode 100644
index 000000000..da778bb9d
--- /dev/null
+++ b/private/ntos/nthals/halraw/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/halraw/mp/makefile b/private/ntos/nthals/halraw/mp/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halraw/mp/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/halraw/mp/makefile.inc b/private/ntos/nthals/halraw/mp/makefile.inc
new file mode 100644
index 000000000..a434415d9
--- /dev/null
+++ b/private/ntos/nthals/halraw/mp/makefile.inc
@@ -0,0 +1,5 @@
+obj\alpha\hal.def: ..\..\hal.src
+ rcpp -P -f ..\..\hal.src -DALPHA=1 $(C_DEFINES) -g obj\alpha\hal.def
+
+$(TARGETPATH)\alpha\hal.lib: $(TARGETPATH)\alpha\halrawmp.lib
+ copy $** $@
diff --git a/private/ntos/nthals/halraw/mp/sources b/private/ntos/nthals/halraw/mp/sources
new file mode 100644
index 000000000..18f050720
--- /dev/null
+++ b/private/ntos/nthals/halraw/mp/sources
@@ -0,0 +1,109 @@
+!IF 0
+
+Copyright (c) 1993 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:
+
+ David N. Cutler (davec) 12-Apr-1993
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halrawmp
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+
+ALPHA_WARNING_LEVEL=-W3 -WX
+C_DEFINES=-DEV5 -DAXPRAW -DEISA_PLATFORM -DTAGGED_NVRAM -DPOSTED
+
+NT_UP=0
+
+!IF $(ALPHA)
+
+TARGETTYPE=HAL
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+INCLUDES=..\alpha;..\..\..\inc;..\..\..\ke;..\..\..\io;..\..\..\fw\alpha;..\..\..\fastfat;..\..\halalpha;..\..\halraw\alpha
+
+SOURCES=
+
+ALPHA_SOURCES=..\hal.rc \
+ ..\alpha\bushnd.c \
+ ..\drivesup.c \
+ ..\alpha\adjust.c \
+ ..\alpha\allstart.c \
+ ..\alpha\bios.c \
+ ..\alpha\bitmap.c \
+ ..\alpha\cache.c \
+ ..\alpha\devintr.s \
+ ..\alpha\ebsgdma.c \
+ ..\alpha\eeprom8k.c \
+ ..\alpha\eisasup.c \
+ ..\alpha\ev5cache.c \
+ ..\alpha\ev5int.c \
+ ..\alpha\ev5mchk.c \
+ ..\alpha\ev5mem.s \
+ ..\alpha\ev5prof.c \
+ ..\alpha\ev5ints.s \
+ ..\alpha\fwreturn.c \
+ ..\alpha\haldebug.c \
+ ..\alpha\halpal.s \
+ ..\alpha\haltsup.s \
+ ..\alpha\idle.s \
+ ..\alpha\info.c \
+ ..\alpha\inithal.c \
+ ..\alpha\intsup.s \
+ ..\alpha\iousage.c \
+ ..\alpha\ioproc.c \
+ ..\alpha\memory.c \
+ ..\alpha\nvenv.c \
+ ..\alpha\nvram.c \
+ ..\alpha\pciesc.c \
+ ..\alpha\pcisup.c \
+ ..\alpha\pcrtc.c \
+ ..\alpha\pcserial.c \
+ ..\alpha\pcspeakr.c \
+ ..\alpha\perf8254.c \
+ ..\alpha\vga.c \
+ ..\alpha\busdata.c \
+ ..\alpha\pcibus.c \
+ ..\alpha\iod.c \
+ ..\alpha\iodaddr.c \
+ ..\alpha\ioderr.c \
+ ..\alpha\iodio.s \
+ ..\alpha\iodmapio.c \
+ ..\alpha\rawerr.c \
+ ..\alpha\rwclock.c \
+ ..\alpha\rwinitnt.c \
+ ..\alpha\rwintbal.c \
+ ..\alpha\rwintsup.c \
+ ..\alpha\rwsysint.c
+
+DLLDEF=obj\*\hal.def
+
+!IF $(ALPHA)
+
+NTTARGETFILES=$(TARGETPATH)\alpha\hal.lib \
+ $(TARGETPATH)\alpha\hal.dll
+
+!ENDIF
diff --git a/private/ntos/nthals/halraw/up/makefile b/private/ntos/nthals/halraw/up/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halraw/up/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/halraw/up/makefile.inc b/private/ntos/nthals/halraw/up/makefile.inc
new file mode 100644
index 000000000..e06ce5247
--- /dev/null
+++ b/private/ntos/nthals/halraw/up/makefile.inc
@@ -0,0 +1,5 @@
+obj\alpha\hal.def: ..\..\hal.src
+ rcpp -P -f ..\..\hal.src -DALPHA=1 $(C_DEFINES) -g obj\alpha\hal.def
+
+$(TARGETPATH)\alpha\hal.lib: $(TARGETPATH)\alpha\halrawup.lib
+ copy $** $@
diff --git a/private/ntos/nthals/halraw/up/sources b/private/ntos/nthals/halraw/up/sources
new file mode 100644
index 000000000..0caeb41eb
--- /dev/null
+++ b/private/ntos/nthals/halraw/up/sources
@@ -0,0 +1,109 @@
+!IF 0
+
+Copyright (c) 1993 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:
+
+ David N. Cutler (davec) 12-Apr-1993
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halrawup
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+
+ALPHA_WARNING_LEVEL=-W3 -WX
+C_DEFINES=-DEV5 -DAXPRAW -DEISA_PLATFORM -DTAGGED_NVRAM -DPOSTED
+
+NT_UP=1
+
+!IF $(ALPHA)
+
+TARGETTYPE=HAL
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+INCLUDES=..\alpha;..\..\..\inc;..\..\..\ke;..\..\..\io;..\..\..\fw\alpha;..\..\..\fastfat;..\..\halalpha;..\..\halraw\alpha
+
+SOURCES=
+
+ALPHA_SOURCES=..\hal.rc \
+ ..\alpha\bushnd.c \
+ ..\drivesup.c \
+ ..\alpha\adjust.c \
+ ..\alpha\allstart.c \
+ ..\alpha\bios.c \
+ ..\alpha\bitmap.c \
+ ..\alpha\cache.c \
+ ..\alpha\devintr.s \
+ ..\alpha\ebsgdma.c \
+ ..\alpha\eeprom8k.c \
+ ..\alpha\eisasup.c \
+ ..\alpha\ev5cache.c \
+ ..\alpha\ev5int.c \
+ ..\alpha\ev5mchk.c \
+ ..\alpha\ev5mem.s \
+ ..\alpha\ev5prof.c \
+ ..\alpha\ev5ints.s \
+ ..\alpha\fwreturn.c \
+ ..\alpha\haldebug.c \
+ ..\alpha\halpal.s \
+ ..\alpha\haltsup.s \
+ ..\alpha\idle.s \
+ ..\alpha\info.c \
+ ..\alpha\inithal.c \
+ ..\alpha\intsup.s \
+ ..\alpha\iousage.c \
+ ..\alpha\ioproc.c \
+ ..\alpha\memory.c \
+ ..\alpha\nvenv.c \
+ ..\alpha\nvram.c \
+ ..\alpha\pciesc.c \
+ ..\alpha\pcisup.c \
+ ..\alpha\pcrtc.c \
+ ..\alpha\pcserial.c \
+ ..\alpha\pcspeakr.c \
+ ..\alpha\perf8254.c \
+ ..\alpha\vga.c \
+ ..\alpha\busdata.c \
+ ..\alpha\pcibus.c \
+ ..\alpha\iod.c \
+ ..\alpha\iodaddr.c \
+ ..\alpha\ioderr.c \
+ ..\alpha\iodio.s \
+ ..\alpha\iodmapio.c \
+ ..\alpha\rawerr.c \
+ ..\alpha\rwclock.c \
+ ..\alpha\rwinitnt.c \
+ ..\alpha\rwintbal.c \
+ ..\alpha\rwintsup.c \
+ ..\alpha\rwsysint.c
+
+DLLDEF=obj\*\hal.def
+
+!IF $(ALPHA)
+
+NTTARGETFILES=$(TARGETPATH)\alpha\hal.lib \
+ $(TARGETPATH)\alpha\hal.dll
+
+!ENDIF