summaryrefslogtreecommitdiffstats
path: root/private/ntos/nthals/halflex
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/nthals/halflex
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/ntos/nthals/halflex')
-rw-r--r--private/ntos/nthals/halflex/adjust.c185
-rw-r--r--private/ntos/nthals/halflex/allstart.c56
-rw-r--r--private/ntos/nthals/halflex/alpha/addrsup.c820
-rw-r--r--private/ntos/nthals/halflex/alpha/alphaio.s1482
-rw-r--r--private/ntos/nthals/halflex/alpha/apoc.h167
-rw-r--r--private/ntos/nthals/halflex/alpha/arcssup.c87
-rw-r--r--private/ntos/nthals/halflex/alpha/dtidef.h149
-rw-r--r--private/ntos/nthals/halflex/alpha/ev4int.c955
-rw-r--r--private/ntos/nthals/halflex/alpha/ev4ints.s300
-rw-r--r--private/ntos/nthals/halflex/alpha/ev4prof.c585
-rw-r--r--private/ntos/nthals/halflex/alpha/ev5ints.s397
-rw-r--r--private/ntos/nthals/halflex/alpha/ev5prof.c747
-rw-r--r--private/ntos/nthals/halflex/alpha/evclock.s119
-rw-r--r--private/ntos/nthals/halflex/alpha/evxcache.c823
-rw-r--r--private/ntos/nthals/halflex/alpha/evxmem.s231
-rw-r--r--private/ntos/nthals/halflex/alpha/evxprof.c342
-rw-r--r--private/ntos/nthals/halflex/alpha/halpal.s276
-rw-r--r--private/ntos/nthals/halflex/alpha/info.c128
-rw-r--r--private/ntos/nthals/halflex/alpha/initsys.c579
-rw-r--r--private/ntos/nthals/halflex/alpha/intsup.c393
-rw-r--r--private/ntos/nthals/halflex/alpha/jxhalp.h404
-rw-r--r--private/ntos/nthals/halflex/alpha/jxmapio.c103
-rw-r--r--private/ntos/nthals/halflex/alpha/minitlb.c221
-rw-r--r--private/ntos/nthals/halflex/alpha/pcisup.c897
-rw-r--r--private/ntos/nthals/halflex/alpha/perfcntr.c262
-rw-r--r--private/ntos/nthals/halflex/alpha/portsup.c93
-rw-r--r--private/ntos/nthals/halflex/alpha/xxidle.s62
-rw-r--r--private/ntos/nthals/halflex/alpha/xxinitnt.c194
-rw-r--r--private/ntos/nthals/halflex/busdata.c175
-rw-r--r--private/ntos/nthals/halflex/bushnd.c7
-rw-r--r--private/ntos/nthals/halflex/drivesup.c7
-rw-r--r--private/ntos/nthals/halflex/hal.rc11
-rw-r--r--private/ntos/nthals/halflex/hal.src7
-rw-r--r--private/ntos/nthals/halflex/halp.h453
-rw-r--r--private/ntos/nthals/halflex/ioproc.c112
-rw-r--r--private/ntos/nthals/halflex/iousage.c515
-rw-r--r--private/ntos/nthals/halflex/iousage.h77
-rw-r--r--private/ntos/nthals/halflex/makefile6
-rw-r--r--private/ntos/nthals/halflex/makefile.inc5
-rw-r--r--private/ntos/nthals/halflex/mips/addrsup.c204
-rw-r--r--private/ntos/nthals/halflex/mips/arcssup.c144
-rw-r--r--private/ntos/nthals/halflex/mips/dtidef.h150
-rw-r--r--private/ntos/nthals/halflex/mips/flushio.c282
-rw-r--r--private/ntos/nthals/halflex/mips/gambit.h54
-rw-r--r--private/ntos/nthals/halflex/mips/info.c116
-rw-r--r--private/ntos/nthals/halflex/mips/initsys.c405
-rw-r--r--private/ntos/nthals/halflex/mips/intsup.c240
-rw-r--r--private/ntos/nthals/halflex/mips/j4cache.s1091
-rw-r--r--private/ntos/nthals/halflex/mips/j4flshbf.s61
-rw-r--r--private/ntos/nthals/halflex/mips/j4prof.c290
-rw-r--r--private/ntos/nthals/halflex/mips/jxhalp.h122
-rw-r--r--private/ntos/nthals/halflex/mips/jxmapio.c192
-rw-r--r--private/ntos/nthals/halflex/mips/pcisup.c1008
-rw-r--r--private/ntos/nthals/halflex/mips/portsup.c137
-rw-r--r--private/ntos/nthals/halflex/mips/x4clock.s210
-rw-r--r--private/ntos/nthals/halflex/mips/x4tb.s109
-rw-r--r--private/ntos/nthals/halflex/mips/xxcalstl.c253
-rw-r--r--private/ntos/nthals/halflex/mips/xxidle.s79
-rw-r--r--private/ntos/nthals/halflex/mips/xxinitnt.c159
-rw-r--r--private/ntos/nthals/halflex/pcip.h138
-rw-r--r--private/ntos/nthals/halflex/platform.h194
-rw-r--r--private/ntos/nthals/halflex/sources141
-rw-r--r--private/ntos/nthals/halflex/uniflex.h108
-rw-r--r--private/ntos/nthals/halflex/x86bios.c599
-rw-r--r--private/ntos/nthals/halflex/xxbeep.c125
-rw-r--r--private/ntos/nthals/halflex/xxclock.c174
-rw-r--r--private/ntos/nthals/halflex/xxdisp.c293
-rw-r--r--private/ntos/nthals/halflex/xxebsup.c2375
-rw-r--r--private/ntos/nthals/halflex/xxenvirv.c106
-rw-r--r--private/ntos/nthals/halflex/xxhwsup.c1250
-rw-r--r--private/ntos/nthals/halflex/xxinithl.c286
-rw-r--r--private/ntos/nthals/halflex/xxpcisup.c2391
-rw-r--r--private/ntos/nthals/halflex/xxport.c769
-rw-r--r--private/ntos/nthals/halflex/xxreturn.c101
-rw-r--r--private/ntos/nthals/halflex/xxsysint.c217
-rw-r--r--private/ntos/nthals/halflex/xxtime.c285
76 files changed, 27290 insertions, 0 deletions
diff --git a/private/ntos/nthals/halflex/adjust.c b/private/ntos/nthals/halflex/adjust.c
new file mode 100644
index 000000000..c42bacc93
--- /dev/null
+++ b/private/ntos/nthals/halflex/adjust.c
@@ -0,0 +1,185 @@
+/*++
+
+
+Copyright (C) 1989-1995 Microsoft Corporation
+Copyright (c) 1994,1995 Digital Equipment Corporation
+
+Module Name:
+
+ adjust.c
+
+Abstract:
+
+ This module contains platform-independent slot resource adjust routines.
+
+Environment:
+
+ Kernel mode
+
+
+--*/
+
+#include "halp.h"
+
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpAdjustResourceListUpperLimits)
+#endif
+
+VOID
+HalpAdjustResourceListUpperLimits (
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList,
+ IN LARGE_INTEGER MaximumPortAddress,
+ IN LARGE_INTEGER MaximumMemoryAddress,
+ IN ULONG MaximumInterruptVector,
+ IN ULONG MaximumDmaChannel
+ )
+/*++
+
+Routine Description:
+
+ Adjust a pResource list with respect to the upper bounds supplied.
+ (A resource is changed only if it execceds the maximum.)
+
+Arguments:
+
+ pResouceList - Resource list to be checked.
+
+ MaximumPortAddress - Maximum I/O port allowed.
+
+ MaximumMemoryAddress - Maximum I/O memory address allowed.
+
+ MaximumInterruptVector - Maximum interrupt vector allowed.
+
+ MaximumDmaChannel - Maximum dma channel allowed.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PIO_RESOURCE_REQUIREMENTS_LIST CompleteList;
+ PIO_RESOURCE_LIST ResourceList;
+ PIO_RESOURCE_DESCRIPTOR Descriptor;
+ ULONG alt, cnt;
+
+
+ //
+ // Walk each ResourceList and shrink any values to system limits
+ //
+
+ CompleteList = *pResourceList;
+ ResourceList = CompleteList->List;
+
+ for (alt=0; alt < CompleteList->AlternativeLists; alt++) {
+ Descriptor = ResourceList->Descriptors;
+ for (cnt = ResourceList->Count; cnt; cnt--) {
+
+ //
+ // Make sure descriptor limits fall within the
+ // CompleteList->InterfaceType & CompleteList->BusNumber.
+ //
+ //
+
+ switch (Descriptor->Type) {
+ case CmResourceTypePort:
+ if (Descriptor->u.Port.MaximumAddress.QuadPart >
+ MaximumPortAddress.QuadPart) {
+
+ Descriptor->u.Port.MaximumAddress = MaximumPortAddress;
+ }
+
+ break;
+
+ case CmResourceTypeInterrupt:
+ if (Descriptor->u.Interrupt.MaximumVector >
+ MaximumInterruptVector ) {
+
+ Descriptor->u.Interrupt.MaximumVector =
+ MaximumInterruptVector;
+ }
+ break;
+
+ case CmResourceTypeMemory:
+ if (Descriptor->u.Memory.MaximumAddress.QuadPart >
+ MaximumMemoryAddress.QuadPart) {
+
+ Descriptor->u.Memory.MaximumAddress =
+ MaximumMemoryAddress;
+ }
+ break;
+
+ case CmResourceTypeDma:
+ if (Descriptor->u.Dma.MaximumChannel >
+ MaximumDmaChannel ) {
+
+ Descriptor->u.Dma.MaximumChannel =
+ MaximumDmaChannel;
+ }
+ break;
+
+#if DBG
+ default:
+ DbgPrint ("HalAdjustResourceList: Unkown resource type\n");
+ break;
+#endif
+ }
+
+ //
+ // Next descriptor
+ //
+ Descriptor++;
+ }
+
+ //
+ // Next Resource List
+ //
+ ResourceList = (PIO_RESOURCE_LIST) Descriptor;
+ }
+
+}
+
+NTSTATUS
+HalpAdjustIsaResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ )
+/*++
+
+Routine Description:
+
+ The function adjusts pResourceList to keep it in the bounds of ISA bus
+ resources.
+
+Arguments:
+
+ BusHandler - Registered BUSHANDLER for the target configuration space
+
+ RootHandler - Register BUSHANDLER for the orginating HalAdjustResourceList request.
+
+ pResourceList - Supplies the PIO_RESOURCE_REQUIREMENTS_LIST to be checked.
+
+Return Value:
+
+ STATUS_SUCCESS
+
+--*/
+{
+ LARGE_INTEGER li64k, limem;
+
+ li64k.QuadPart = 0xffff;
+ limem.QuadPart = 0xffffff;
+
+ HalpAdjustResourceListUpperLimits (
+ pResourceList,
+ li64k, // Bus supports up to I/O port 0xFFFF
+ limem, // Bus supports up to memory 0xFFFFFF
+ 15, // Bus supports up to 15 IRQs
+ 7 // Bus supports up to Dma channel 7
+ );
+
+ return STATUS_SUCCESS;
+}
diff --git a/private/ntos/nthals/halflex/allstart.c b/private/ntos/nthals/halflex/allstart.c
new file mode 100644
index 000000000..8d81b6eb8
--- /dev/null
+++ b/private/ntos/nthals/halflex/allstart.c
@@ -0,0 +1,56 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ allstart.c
+
+Abstract:
+
+
+ This module implements the platform specific operations that must be
+ performed after all processors have been started.
+
+Author:
+
+ David N. Cutler (davec) 19-Jun-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+BOOLEAN
+HalAllProcessorsStarted (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function executes platform specific operations that must be
+ performed after all processors have been started. It is called
+ for each processor in the host configuration.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If platform specific operations are successful, then return TRUE.
+ Otherwise, return FALSE.
+
+--*/
+
+{
+
+ return TRUE;
+}
diff --git a/private/ntos/nthals/halflex/alpha/addrsup.c b/private/ntos/nthals/halflex/alpha/addrsup.c
new file mode 100644
index 000000000..08174ae45
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/addrsup.c
@@ -0,0 +1,820 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ addrsup.c
+
+Abstract:
+
+ This module contains the platform dependent code to create bus addreses
+ and QVAs for the EB64+ system.
+
+Author:
+
+ Joe Notarangelo 22-Oct-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Dick Bissen (Digital) 30-Jun-1994
+ Added code to check the new PCI Memory MAp address range which is
+ impacted by the EPEC HAXR1.
+
+ Eric Rehm (Digital) 03-Jan-1994
+ Added PCIBus(0) and dense space support to all routines.
+
+--*/
+
+#include "halp.h"
+
+typedef PVOID QUASI_VIRTUAL_ADDRESS;
+
+#define HAL_MAKE_LQVA(PA) (LONGLONG)HAL_MAKE_QVA(PA)
+#define HAL_MAKE_TA(PA,ByteOffset) (LONGLONG)(PA) + (LONGLONG)((ByteOffset) << IO_BIT_SHIFT)
+
+#define KERNEL_PCI_VGA_VIDEO_ROM (LONGLONG)(0x8000000000000000)
+#define USER_PCI_VGA_VIDEO_ROM (LONGLONG)(0x4000000000000000)
+
+PLATFORM_RANGE_LIST Apoc10Trebbia13RangeList[] = {
+ { Isa , 0, BusIo, 1, HAL_MAKE_LQVA(TREB1_APOC1_ISA_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Isa , 0, BusMemory, 1, HAL_MAKE_LQVA(TREB1_APOC1_ISA_MEMORY_BASE_PHYSICAL) , 0x00000000, 0x00ffffff },
+
+ { Isa , 0, UserBusIo, 0, TREB1_APOC1_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Isa , 0, UserBusMemory, 0, TREB1_APOC1_ISA_MEMORY_BASE_PHYSICAL , 0x00000000, 0x00ffffff },
+
+ { Isa , 1, BusIo, 1, HAL_MAKE_LQVA(TREB1_APOC1_ISA1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Isa , 1, BusMemory, 1, HAL_MAKE_LQVA(TREB1_APOC1_ISA1_MEMORY_BASE_PHYSICAL)+0xa0000, 0x000a0000, 0x000bffff },
+ { Isa , 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+
+ { Isa , 1, UserBusIo, 0, TREB1_APOC1_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Isa , 1, UserBusMemory, 0, HAL_MAKE_TA(TREB1_APOC1_ISA1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { Isa , 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB1_APOC1_ISA1_MEMORY_BASE_PHYSICAL, 0x000c0000, 0x000c7fff },
+
+ { Eisa , 0, BusIo, 1, HAL_MAKE_LQVA(TREB1_APOC1_ISA_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Eisa , 0, BusMemory, 1, HAL_MAKE_LQVA(TREB1_APOC1_ISA_MEMORY_BASE_PHYSICAL) , 0x00000000, 0x07ffffff },
+
+ { Eisa , 0, UserBusIo, 0, TREB1_APOC1_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Eisa , 0, UserBusMemory, 0, TREB1_APOC1_ISA_MEMORY_BASE_PHYSICAL , 0x00000000, 0x07ffffff },
+
+ { Eisa , 1, BusIo, 1, HAL_MAKE_LQVA(TREB1_APOC1_ISA1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Eisa , 1, BusMemory, 1, HAL_MAKE_LQVA(TREB1_APOC1_ISA1_MEMORY_BASE_PHYSICAL)+0xa0000, 0x000a0000, 0x000bffff },
+ { Eisa , 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+
+ { Eisa , 1, UserBusIo, 0, TREB1_APOC1_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Eisa , 1, UserBusMemory, 0, HAL_MAKE_TA(TREB1_APOC1_ISA1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { Eisa , 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB1_APOC1_ISA1_MEMORY_BASE_PHYSICAL, 0x000c0000, 0x000c7fff },
+
+ { PCIBus, 0, BusIo, 1, HAL_MAKE_LQVA(TREB1_APOC1_PCI_IO_BASE_PHYSICAL) , 0x00000000, 0x07ffffff },
+ { PCIBus, 0, BusMemory, 1, HAL_MAKE_LQVA(TREB1_APOC1_PCI_HIGH_MEMORY_BASE_PHYSICAL) , 0x40000000, 0x47ffffff },
+
+ { PCIBus, 0, UserBusIo, 0, TREB1_APOC1_PCI_IO_BASE_PHYSICAL , 0x00000000, 0x07ffffff },
+ { PCIBus, 0, UserBusMemory, 0, TREB1_APOC1_PCI_HIGH_MEMORY_BASE_PHYSICAL , 0x40000000, 0x47ffffff },
+
+ { PCIBus, 1, BusIo, 1, HAL_MAKE_LQVA(TREB1_APOC1_PCI_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { PCIBus, 1, BusMemory, 1, HAL_MAKE_LQVA(TREB1_APOC1_PCI_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { PCIBus, 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+ { PCIBus, 1, BusMemory, 1, HAL_MAKE_LQVA(TREB1_APOC1_PCI_HIGH_MEMORY_BASE_PHYSICAL) , 0x40000000, 0x47ffffff },
+
+ { PCIBus, 1, UserBusIo, 0, TREB1_APOC1_PCI_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { PCIBus, 1, UserBusMemory, 0, HAL_MAKE_TA(TREB1_APOC1_PCI_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { PCIBus, 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB1_APOC1_PCI_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+ { PCIBus, 1, UserBusMemory, 0, TREB1_APOC1_PCI_HIGH_MEMORY_BASE_PHYSICAL , 0x40000000, 0x47ffffff },
+
+ { MaximumInterfaceType, 0, 0, 0, 0 , 0 , 0 }
+};
+
+PLATFORM_RANGE_LIST Apoc20Trebbia13RangeList[] = {
+ { Isa , 0, BusIo, 1, HAL_MAKE_LQVA(TREB1_APOC2_ISA_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Isa , 0, BusMemory, 1, HAL_MAKE_LQVA(TREB1_APOC2_ISA_MEMORY_BASE_PHYSICAL) , 0x00000000, 0x00ffffff },
+
+ { Isa , 0, UserBusIo, 0, TREB1_APOC2_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Isa , 0, UserBusMemory, 0, TREB1_APOC2_ISA_MEMORY_BASE_PHYSICAL , 0x00000000, 0x00ffffff },
+
+ { Isa , 1, BusIo, 1, HAL_MAKE_LQVA(TREB1_APOC2_ISA1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Isa , 1, BusMemory, 1, HAL_MAKE_LQVA(TREB1_APOC2_ISA1_MEMORY_BASE_PHYSICAL)+0xa0000, 0x000a0000, 0x000bffff },
+ { Isa , 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM|HAL_MAKE_LQVA(APOC2_TRANSLATED_MEMORY_BASE_PHYSICAL) , 0x000c0000, 0x000c7fff },
+
+ { Isa , 1, UserBusIo, 0, TREB1_APOC2_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Isa , 1, UserBusMemory, 0, HAL_MAKE_TA(TREB1_APOC2_ISA1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { Isa , 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB1_APOC2_ISA1_MEMORY_BASE_PHYSICAL, 0x000c0000, 0x000c7fff },
+
+ { Eisa , 0, BusIo, 1, HAL_MAKE_LQVA(TREB1_APOC2_ISA_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Eisa , 0, BusMemory, 1, HAL_MAKE_LQVA(TREB1_APOC2_ISA_MEMORY_BASE_PHYSICAL) , 0x00000000, 0x07ffffff },
+
+ { Eisa , 0, UserBusIo, 0, TREB1_APOC2_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Eisa , 0, UserBusMemory, 0, TREB1_APOC2_ISA_MEMORY_BASE_PHYSICAL , 0x00000000, 0x07ffffff },
+
+ { Eisa , 1, BusIo, 1, HAL_MAKE_LQVA(TREB1_APOC2_ISA1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Eisa , 1, BusMemory, 1, HAL_MAKE_LQVA(TREB1_APOC2_ISA1_MEMORY_BASE_PHYSICAL)+0xa0000, 0x000a0000, 0x000bffff },
+ { Eisa , 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM|HAL_MAKE_LQVA(APOC2_TRANSLATED_MEMORY_BASE_PHYSICAL) , 0x000c0000, 0x000c7fff },
+
+ { Eisa , 1, UserBusIo, 0, TREB1_APOC2_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Eisa , 1, UserBusMemory, 0, HAL_MAKE_TA(TREB1_APOC2_ISA1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { Eisa , 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB1_APOC2_ISA1_MEMORY_BASE_PHYSICAL, 0x000c0000, 0x000c7fff },
+
+ { PCIBus, 0, BusIo, 1, HAL_MAKE_LQVA(TREB1_APOC2_PCI_IO_BASE_PHYSICAL) , 0x00000000, 0x07ffffff },
+ { PCIBus, 0, BusMemory, 1, HAL_MAKE_LQVA(TREB1_APOC2_PCI_HIGH_MEMORY_BASE_PHYSICAL) , 0x40000000, 0x47ffffff },
+
+ { PCIBus, 0, UserBusIo, 0, TREB1_APOC2_PCI_IO_BASE_PHYSICAL , 0x00000000, 0x07ffffff },
+ { PCIBus, 0, UserBusMemory, 0, TREB1_APOC2_PCI_HIGH_MEMORY_BASE_PHYSICAL , 0x40000000, 0x47ffffff },
+
+ { PCIBus, 1, BusIo, 1, HAL_MAKE_LQVA(TREB1_APOC2_PCI_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { PCIBus, 1, BusMemory, 1, HAL_MAKE_LQVA(TREB1_APOC2_PCI_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { PCIBus, 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM|HAL_MAKE_LQVA(APOC2_TRANSLATED_MEMORY_BASE_PHYSICAL) , 0x000c0000, 0x000c7fff },
+ { PCIBus, 1, BusMemory, 1, HAL_MAKE_LQVA(TREB1_APOC2_PCI_HIGH_MEMORY_BASE_PHYSICAL) , 0x40000000, 0x47ffffff },
+
+ { PCIBus, 1, UserBusIo, 0, TREB1_APOC2_PCI_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { PCIBus, 1, UserBusMemory, 0, HAL_MAKE_TA(TREB1_APOC2_PCI_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { PCIBus, 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB1_APOC2_PCI_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+ { PCIBus, 1, UserBusMemory, 0, TREB1_APOC2_PCI_HIGH_MEMORY_BASE_PHYSICAL , 0x40000000, 0x47ffffff },
+
+ { MaximumInterfaceType, 0, 0, 0, 0 , 0 , 0 }
+};
+
+PLATFORM_RANGE_LIST Rogue0Trebbia13RangeList[] = {
+ { Isa , 0, BusIo, 1, HAL_MAKE_LQVA(TREB1_ROGUE_ISA_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Isa , 0, BusMemory, 1, HAL_MAKE_LQVA(TREB1_ROGUE_ISA_MEMORY_BASE_PHYSICAL) , 0x00000000, 0x00ffffff },
+
+ { Isa , 0, UserBusIo, 0, TREB1_ROGUE_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Isa , 0, UserBusMemory, 0, TREB1_ROGUE_ISA_MEMORY_BASE_PHYSICAL , 0x00000000, 0x00ffffff },
+
+ { Isa , 1, BusIo, 1, HAL_MAKE_LQVA(TREB1_ROGUE_ISA1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Isa , 1, BusMemory, 1, HAL_MAKE_LQVA(TREB1_ROGUE_ISA1_MEMORY_BASE_PHYSICAL)+0xa0000, 0x000a0000, 0x000bffff },
+ { Isa , 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+
+ { Isa , 1, UserBusIo, 0, TREB1_ROGUE_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Isa , 1, UserBusMemory, 0, HAL_MAKE_TA(TREB1_ROGUE_ISA1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { Isa , 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB1_ROGUE_ISA1_MEMORY_BASE_PHYSICAL, 0x000c0000, 0x000c7fff },
+
+ { Eisa , 0, BusIo, 1, HAL_MAKE_LQVA(TREB1_ROGUE_ISA_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Eisa , 0, BusMemory, 1, HAL_MAKE_LQVA(TREB1_ROGUE_ISA_MEMORY_BASE_PHYSICAL) , 0x00000000, 0x07ffffff },
+
+ { Eisa , 0, UserBusIo, 0, TREB1_ROGUE_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Eisa , 0, UserBusMemory, 0, TREB1_ROGUE_ISA_MEMORY_BASE_PHYSICAL , 0x00000000, 0x07ffffff },
+
+ { Eisa , 1, BusIo, 1, HAL_MAKE_LQVA(TREB1_ROGUE_ISA1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Eisa , 1, BusMemory, 1, HAL_MAKE_LQVA(TREB1_ROGUE_ISA1_MEMORY_BASE_PHYSICAL)+0xa0000, 0x000a0000, 0x000bffff },
+ { Eisa , 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+
+ { Eisa , 1, UserBusIo, 0, TREB1_ROGUE_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Eisa , 1, UserBusMemory, 0, HAL_MAKE_TA(TREB1_ROGUE_ISA1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { Eisa , 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB1_ROGUE_ISA1_MEMORY_BASE_PHYSICAL, 0x000c0000, 0x000c7fff },
+
+ { PCIBus, 0, BusIo, 1, HAL_MAKE_LQVA(TREB1_ROGUE_PCI_IO_BASE_PHYSICAL) , 0x00000000, 0x07ffffff },
+ { PCIBus, 0, BusMemory, 1, HAL_MAKE_LQVA(TREB1_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL) , 0x40000000, 0x47ffffff },
+
+ { PCIBus, 0, UserBusIo, 0, TREB1_ROGUE_PCI_IO_BASE_PHYSICAL , 0x00000000, 0x07ffffff },
+ { PCIBus, 0, UserBusMemory, 0, TREB1_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL , 0x40000000, 0x47ffffff },
+
+ { PCIBus, 1, BusIo, 1, HAL_MAKE_LQVA(TREB1_ROGUE_PCI_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { PCIBus, 1, BusMemory, 1, HAL_MAKE_LQVA(TREB1_ROGUE_PCI_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { PCIBus, 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+ { PCIBus, 1, BusMemory, 1, HAL_MAKE_LQVA(TREB1_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL) , 0x40000000, 0x47ffffff },
+
+ { PCIBus, 1, UserBusIo, 0, TREB1_ROGUE_PCI_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { PCIBus, 1, UserBusMemory, 0, HAL_MAKE_TA(TREB1_ROGUE_PCI_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { PCIBus, 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB1_ROGUE_PCI_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+ { PCIBus, 1, UserBusMemory, 0, TREB1_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL , 0x40000000, 0x47ffffff },
+
+ { MaximumInterfaceType, 0, 0, 0, 0 , 0 , 0 }
+};
+
+PLATFORM_RANGE_LIST Rogue1Trebbia13RangeList[] = {
+ { Isa , 0, BusIo, 1, HAL_MAKE_LQVA(TREB1_ROGUE_ISA_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Isa , 0, BusMemory, 1, HAL_MAKE_LQVA(TREB1_ROGUE_ISA_MEMORY_BASE_PHYSICAL) , 0x00000000, 0x00ffffff },
+
+ { Isa , 0, UserBusIo, 0, TREB1_ROGUE_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Isa , 0, UserBusMemory, 0, TREB1_ROGUE_ISA_MEMORY_BASE_PHYSICAL , 0x00000000, 0x00ffffff },
+
+ { Isa , 1, BusIo, 1, HAL_MAKE_LQVA(TREB1_ROGUE_ISA1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Isa , 1, BusMemory, 1, HAL_MAKE_LQVA(TREB1_ROGUE_ISA1_MEMORY_BASE_PHYSICAL)+0xa0000, 0x000a0000, 0x000bffff },
+ { Isa , 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+
+ { Isa , 1, UserBusIo, 0, TREB1_ROGUE_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Isa , 1, UserBusMemory, 0, HAL_MAKE_TA(TREB1_ROGUE_ISA1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { Isa , 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB1_ROGUE_ISA1_MEMORY_BASE_PHYSICAL, 0x000c0000, 0x000c7fff },
+
+ { Eisa , 0, BusIo, 1, HAL_MAKE_LQVA(TREB1_ROGUE_ISA_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Eisa , 0, BusMemory, 1, HAL_MAKE_LQVA(TREB1_ROGUE_ISA_MEMORY_BASE_PHYSICAL) , 0x00000000, 0x07ffffff },
+
+ { Eisa , 0, UserBusIo, 0, TREB1_ROGUE_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Eisa , 0, UserBusMemory, 0, TREB1_ROGUE_ISA_MEMORY_BASE_PHYSICAL , 0x00000000, 0x07ffffff },
+
+ { Eisa , 1, BusIo, 1, HAL_MAKE_LQVA(TREB1_ROGUE_ISA1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Eisa , 1, BusMemory, 1, HAL_MAKE_LQVA(TREB1_ROGUE_ISA1_MEMORY_BASE_PHYSICAL)+0xa0000, 0x000a0000, 0x000bffff },
+ { Eisa , 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+
+ { Eisa , 1, UserBusIo, 0, TREB1_ROGUE_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Eisa , 1, UserBusMemory, 0, HAL_MAKE_TA(TREB1_ROGUE_ISA1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { Eisa , 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB1_ROGUE_ISA1_MEMORY_BASE_PHYSICAL, 0x000c0000, 0x000c7fff },
+
+ { PCIBus, 0, BusIo, 1, HAL_MAKE_LQVA(TREB1_ROGUE_PCI_IO_BASE_PHYSICAL) , 0x00000000, 0x07ffffff },
+ { PCIBus, 0, BusMemory, 1, HAL_MAKE_LQVA(TREB1_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL) , 0x40000000, 0x47ffffff },
+
+ { PCIBus, 0, UserBusIo, 0, TREB1_ROGUE_PCI_IO_BASE_PHYSICAL , 0x00000000, 0x07ffffff },
+ { PCIBus, 0, UserBusMemory, 0, TREB1_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL , 0x40000000, 0x47ffffff },
+
+ { PCIBus, 1, BusIo, 1, HAL_MAKE_LQVA(TREB1_ROGUE_PCI_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { PCIBus, 1, BusMemory, 1, HAL_MAKE_LQVA(TREB1_ROGUE_PCI_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { PCIBus, 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+ { PCIBus, 1, BusMemory, 1, HAL_MAKE_LQVA(TREB1_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL) , 0x40000000, 0x47ffffff },
+
+ { PCIBus, 1, UserBusIo, 0, TREB1_ROGUE_PCI_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { PCIBus, 1, UserBusMemory, 0, HAL_MAKE_TA(TREB1_ROGUE_PCI_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { PCIBus, 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB1_ROGUE_PCI_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+ { PCIBus, 1, UserBusMemory, 0, TREB1_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL , 0x40000000, 0x47ffffff },
+
+ { MaximumInterfaceType, 0, 0, 0, 0 , 0 , 0 }
+};
+
+PLATFORM_RANGE_LIST Apoc10Trebbia20RangeList[] = {
+ { Isa , 0, BusIo, 1, HAL_MAKE_LQVA(TREB2_APOC1_ISA_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Isa , 0, BusMemory, 1, HAL_MAKE_LQVA(TREB2_APOC1_ISA_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { Isa , 0, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+
+ { Isa , 0, UserBusIo, 0, TREB2_APOC1_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Isa , 0, UserBusMemory, 0, HAL_MAKE_TA(TREB2_APOC1_ISA_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { Isa , 0, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_APOC1_ISA_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+
+ { Isa , 1, BusIo, 1, HAL_MAKE_LQVA(TREB2_APOC1_ISA1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Isa , 1, BusMemory, 1, HAL_MAKE_LQVA(TREB2_APOC1_ISA1_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { Isa , 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+
+ { Isa , 1, UserBusIo, 0, TREB2_APOC1_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Isa , 1, UserBusMemory, 0, HAL_MAKE_TA(TREB2_APOC1_ISA1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { Isa , 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_APOC1_ISA1_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+
+ { Eisa , 0, BusIo, 1, HAL_MAKE_LQVA(TREB2_APOC1_ISA_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Eisa , 0, BusMemory, 1, HAL_MAKE_LQVA(TREB2_APOC1_ISA_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { Eisa , 0, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+
+ { Eisa , 0, UserBusIo, 0, TREB2_APOC1_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Eisa , 0, UserBusMemory, 0, HAL_MAKE_TA(TREB2_APOC1_ISA_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { Eisa , 0, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_APOC1_ISA_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+
+ { Eisa , 1, BusIo, 1, HAL_MAKE_LQVA(TREB2_APOC1_ISA1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Eisa , 1, BusMemory, 1, HAL_MAKE_LQVA(TREB2_APOC1_ISA1_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { Eisa , 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+
+ { Eisa , 1, UserBusIo, 0, TREB2_APOC1_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Eisa , 1, UserBusMemory, 0, HAL_MAKE_TA(TREB2_APOC1_ISA1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { Eisa , 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_APOC1_ISA1_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+
+ { PCIBus, 0, BusIo, 1, HAL_MAKE_LQVA(TREB2_APOC1_PCI_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { PCIBus, 0, BusMemory, 1, HAL_MAKE_LQVA(TREB2_APOC1_PCI_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { PCIBus, 0, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+ { PCIBus, 0, BusMemory, 1, HAL_MAKE_LQVA(TREB2_APOC1_PCI_HIGH_MEMORY_BASE_PHYSICAL) , 0x40000000, 0x47ffffff },
+
+ { PCIBus, 0, UserBusIo, 0, TREB2_APOC1_PCI_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { PCIBus, 0, UserBusMemory, 0, HAL_MAKE_TA(TREB2_APOC1_PCI_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { PCIBus, 0, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_APOC1_PCI_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+ { PCIBus, 0, UserBusMemory, 0, TREB2_APOC1_PCI_HIGH_MEMORY_BASE_PHYSICAL , 0x40000000, 0x47ffffff },
+
+ { PCIBus, 1, BusIo, 1, HAL_MAKE_LQVA(TREB2_APOC1_PCI1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { PCIBus, 1, BusMemory, 1, HAL_MAKE_LQVA(TREB2_APOC1_PCI1_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { PCIBus, 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+ { PCIBus, 1, BusMemory, 1, HAL_MAKE_LQVA(TREB2_APOC1_PCI_HIGH_MEMORY_BASE_PHYSICAL) , 0x40000000, 0x47ffffff },
+
+ { PCIBus, 1, UserBusIo, 0, TREB2_APOC1_PCI1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { PCIBus, 1, UserBusMemory, 0, HAL_MAKE_TA(TREB2_APOC1_PCI1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { PCIBus, 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_APOC1_PCI1_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+ { PCIBus, 1, UserBusMemory, 0, TREB2_APOC1_PCI_HIGH_MEMORY_BASE_PHYSICAL , 0x40000000, 0x47ffffff },
+
+ { MaximumInterfaceType, 0, 0, 0, 0 , 0 , 0 }
+};
+
+PLATFORM_RANGE_LIST Apoc20Trebbia20RangeList[] = {
+ { Isa , 0, BusIo, 1, HAL_MAKE_LQVA(TREB2_APOC2_ISA_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Isa , 0, BusMemory, 1, HAL_MAKE_LQVA(TREB2_APOC2_ISA_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { Isa , 0, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM|HAL_MAKE_LQVA(APOC2_TRANSLATED_MEMORY_BASE_PHYSICAL) , 0x000c0000, 0x000c7fff },
+ { Isa , 0, KernelPciDenseMemory, 2, APOC2_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff },
+
+ { Isa , 0, UserBusIo, 0, TREB2_APOC2_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Isa , 0, UserBusMemory, 0, HAL_MAKE_TA(TREB2_APOC2_ISA_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { Isa , 0, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_APOC2_ISA_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+ { Isa , 0, UserPciDenseMemory, 2, APOC2_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff },
+
+ { Isa , 1, BusIo, 1, HAL_MAKE_LQVA(TREB2_APOC2_ISA1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Isa , 1, BusMemory, 1, HAL_MAKE_LQVA(TREB2_APOC2_ISA1_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { Isa , 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM|HAL_MAKE_LQVA(APOC2_TRANSLATED_MEMORY_BASE_PHYSICAL) , 0x000c0000, 0x000c7fff },
+ { Isa , 1, KernelPciDenseMemory, 2, APOC2_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff },
+
+ { Isa , 1, UserBusIo, 0, TREB2_APOC2_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Isa , 1, UserBusMemory, 0, HAL_MAKE_TA(TREB2_APOC2_ISA1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { Isa , 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_APOC2_ISA1_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+ { Isa , 1, UserPciDenseMemory, 2, APOC2_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff },
+
+ { Eisa , 0, BusIo, 1, HAL_MAKE_LQVA(TREB2_APOC2_ISA_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Eisa , 0, BusMemory, 1, HAL_MAKE_LQVA(TREB2_APOC2_ISA_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { Eisa , 0, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM|HAL_MAKE_LQVA(APOC2_TRANSLATED_MEMORY_BASE_PHYSICAL) , 0x000c0000, 0x000c7fff },
+ { Eisa , 0, KernelPciDenseMemory, 2, APOC2_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff },
+
+ { Eisa , 0, UserBusIo, 0, TREB2_APOC2_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Eisa , 0, UserBusMemory, 0, HAL_MAKE_TA(TREB2_APOC2_ISA_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { Eisa , 0, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_APOC2_ISA_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+ { Eisa , 0, UserPciDenseMemory, 2, APOC2_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff },
+
+ { Eisa , 1, BusIo, 1, HAL_MAKE_LQVA(TREB2_APOC2_ISA1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Eisa , 1, BusMemory, 1, HAL_MAKE_LQVA(TREB2_APOC2_ISA1_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { Eisa , 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM|HAL_MAKE_LQVA(APOC2_TRANSLATED_MEMORY_BASE_PHYSICAL) , 0x000c0000, 0x000c7fff },
+ { Eisa , 1, KernelPciDenseMemory, 2, APOC2_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff },
+
+ { Eisa , 1, UserBusIo, 0, TREB2_APOC2_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Eisa , 1, UserBusMemory, 0, HAL_MAKE_TA(TREB2_APOC2_ISA1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { Eisa , 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_APOC2_ISA1_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+ { Eisa , 1, UserPciDenseMemory, 2, APOC2_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff },
+
+ { PCIBus, 0, BusIo, 1, HAL_MAKE_LQVA(TREB2_APOC2_PCI_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { PCIBus, 0, BusMemory, 1, HAL_MAKE_LQVA(TREB2_APOC2_PCI_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { PCIBus, 0, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM|HAL_MAKE_LQVA(APOC2_TRANSLATED_MEMORY_BASE_PHYSICAL) , 0x000c0000, 0x000c7fff },
+ { PCIBus, 0, BusMemory, 1, HAL_MAKE_LQVA(TREB2_APOC2_PCI_HIGH_MEMORY_BASE_PHYSICAL) , 0x40000000, 0x47ffffff },
+ { PCIBus, 0, KernelPciDenseMemory, 2, APOC2_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff },
+ { PCIBus, 0, KernelPciDenseMemory, 2, APOC2_PCI_DENSE_BASE_PHYSICAL+0x40000000 , 0x40000000, 0x7fffffff },
+
+ { PCIBus, 0, UserBusIo, 0, TREB2_APOC2_PCI_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { PCIBus, 0, UserBusMemory, 0, HAL_MAKE_TA(TREB2_APOC2_PCI_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { PCIBus, 0, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_APOC2_PCI_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+ { PCIBus, 0, UserBusMemory, 0, TREB2_APOC2_PCI_HIGH_MEMORY_BASE_PHYSICAL , 0x40000000, 0x47ffffff },
+ { PCIBus, 0, UserPciDenseMemory, 2, APOC2_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff },
+ { PCIBus, 0, UserPciDenseMemory, 2, APOC2_PCI_DENSE_BASE_PHYSICAL+0x40000000 , 0x40000000, 0x7fffffff },
+
+ { PCIBus, 1, BusIo, 1, HAL_MAKE_LQVA(TREB2_APOC2_PCI1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { PCIBus, 1, BusMemory, 1, HAL_MAKE_LQVA(TREB2_APOC2_PCI1_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { PCIBus, 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM|HAL_MAKE_LQVA(APOC2_TRANSLATED_MEMORY_BASE_PHYSICAL) , 0x000c0000, 0x000c7fff },
+ { PCIBus, 1, BusMemory, 1, HAL_MAKE_LQVA(TREB2_APOC2_PCI_HIGH_MEMORY_BASE_PHYSICAL) , 0x40000000, 0x47ffffff },
+ { PCIBus, 1, KernelPciDenseMemory, 2, APOC2_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff },
+ { PCIBus, 1, KernelPciDenseMemory, 2, APOC2_PCI_DENSE_BASE_PHYSICAL+0x40000000 , 0x40000000, 0x7fffffff },
+
+ { PCIBus, 1, UserBusIo, 0, TREB2_APOC2_PCI1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { PCIBus, 1, UserBusMemory, 0, HAL_MAKE_TA(TREB2_APOC2_PCI1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { PCIBus, 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_APOC2_PCI1_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+ { PCIBus, 1, UserBusMemory, 0, TREB2_APOC2_PCI_HIGH_MEMORY_BASE_PHYSICAL , 0x40000000, 0x47ffffff },
+ { PCIBus, 1, UserPciDenseMemory, 2, APOC2_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff },
+ { PCIBus, 1, UserPciDenseMemory, 2, APOC2_PCI_DENSE_BASE_PHYSICAL+0x40000000 , 0x40000000, 0x7fffffff },
+
+ { MaximumInterfaceType, 0, 0, 0, 0 , 0 , 0 }
+};
+
+PLATFORM_RANGE_LIST Rogue0Trebbia20RangeList[] = {
+ { Isa , 0, BusIo, 1, HAL_MAKE_LQVA(TREB2_ROGUE_ISA_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Isa , 0, BusMemory, 1, HAL_MAKE_LQVA(TREB2_ROGUE_ISA_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { Isa , 0, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+
+ { Isa , 0, UserBusIo, 0, TREB2_ROGUE_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Isa , 0, UserBusMemory, 0, HAL_MAKE_TA(TREB2_ROGUE_ISA_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { Isa , 0, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_ROGUE_ISA_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+
+ { Isa , 1, BusIo, 1, HAL_MAKE_LQVA(TREB2_ROGUE_ISA1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Isa , 1, BusMemory, 1, HAL_MAKE_LQVA(TREB2_ROGUE_ISA1_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { Isa , 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+
+ { Isa , 1, UserBusIo, 0, TREB2_ROGUE_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Isa , 1, UserBusMemory, 0, HAL_MAKE_TA(TREB2_ROGUE_ISA1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { Isa , 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_ROGUE_ISA1_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+
+ { Eisa , 0, BusIo, 1, HAL_MAKE_LQVA(TREB2_ROGUE_ISA_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Eisa , 0, BusMemory, 1, HAL_MAKE_LQVA(TREB2_ROGUE_ISA_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { Eisa , 0, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+
+ { Eisa , 0, UserBusIo, 0, TREB2_ROGUE_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Eisa , 0, UserBusMemory, 0, HAL_MAKE_TA(TREB2_ROGUE_ISA_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { Eisa , 0, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_ROGUE_ISA_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+
+ { Eisa , 1, BusIo, 1, HAL_MAKE_LQVA(TREB2_ROGUE_ISA1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Eisa , 1, BusMemory, 1, HAL_MAKE_LQVA(TREB2_ROGUE_ISA1_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { Eisa , 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+
+ { Eisa , 1, UserBusIo, 0, TREB2_ROGUE_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Eisa , 1, UserBusMemory, 0, HAL_MAKE_TA(TREB2_ROGUE_ISA1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { Eisa , 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_ROGUE_ISA1_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+
+ { PCIBus, 0, BusIo, 1, HAL_MAKE_LQVA(TREB2_ROGUE_PCI_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { PCIBus, 0, BusMemory, 1, HAL_MAKE_LQVA(TREB2_ROGUE_PCI_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { PCIBus, 0, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+ { PCIBus, 0, BusMemory, 1, HAL_MAKE_LQVA(TREB2_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL) , 0x40000000, 0x47ffffff },
+
+ { PCIBus, 0, UserBusIo, 0, TREB2_ROGUE_PCI_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { PCIBus, 0, UserBusMemory, 0, HAL_MAKE_TA(TREB2_ROGUE_PCI_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { PCIBus, 0, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_ROGUE_PCI_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+ { PCIBus, 0, UserBusMemory, 0, TREB2_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL , 0x40000000, 0x47ffffff },
+
+ { PCIBus, 1, BusIo, 1, HAL_MAKE_LQVA(TREB2_ROGUE_PCI1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { PCIBus, 1, BusMemory, 1, HAL_MAKE_LQVA(TREB2_ROGUE_PCI1_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { PCIBus, 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+ { PCIBus, 1, BusMemory, 1, HAL_MAKE_LQVA(TREB2_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL) , 0x40000000, 0x47ffffff },
+
+ { PCIBus, 1, UserBusIo, 0, TREB2_ROGUE_PCI1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { PCIBus, 1, UserBusMemory, 0, HAL_MAKE_TA(TREB2_ROGUE_PCI1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { PCIBus, 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_ROGUE_PCI1_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+ { PCIBus, 1, UserBusMemory, 0, TREB2_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL , 0x40000000, 0x47ffffff },
+
+ { MaximumInterfaceType, 0, 0, 0, 0 , 0 , 0 }
+};
+
+PLATFORM_RANGE_LIST Rogue1Trebbia20RangeList[] = {
+ { Isa , 0, BusIo, 1, HAL_MAKE_LQVA(TREB2_ROGUE_ISA_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Isa , 0, BusMemory, 1, HAL_MAKE_LQVA(TREB2_ROGUE_ISA_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { Isa , 0, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+ { Isa , 0, KernelPciDenseMemory, 2, ROGUE_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff },
+
+ { Isa , 0, UserBusIo, 0, TREB2_ROGUE_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Isa , 0, UserBusMemory, 0, HAL_MAKE_TA(TREB2_ROGUE_ISA_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { Isa , 0, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_ROGUE_ISA_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+ { Isa , 0, UserPciDenseMemory, 2, ROGUE_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff },
+
+ { Isa , 1, BusIo, 1, HAL_MAKE_LQVA(TREB2_ROGUE_ISA1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Isa , 1, BusMemory, 1, HAL_MAKE_LQVA(TREB2_ROGUE_ISA1_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { Isa , 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+ { Isa , 1, KernelPciDenseMemory, 2, ROGUE_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff },
+
+ { Isa , 1, UserBusIo, 0, TREB2_ROGUE_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Isa , 1, UserBusMemory, 0, HAL_MAKE_TA(TREB2_ROGUE_ISA1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { Isa , 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_ROGUE_ISA1_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+ { Isa , 1, UserPciDenseMemory, 2, ROGUE_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff },
+
+ { Eisa , 0, BusIo, 1, HAL_MAKE_LQVA(TREB2_ROGUE_ISA_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Eisa , 0, BusMemory, 1, HAL_MAKE_LQVA(TREB2_ROGUE_ISA_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { Eisa , 0, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+ { Eisa , 0, KernelPciDenseMemory, 2, ROGUE_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff },
+
+ { Eisa , 0, UserBusIo, 0, TREB2_ROGUE_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Eisa , 0, UserBusMemory, 0, HAL_MAKE_TA(TREB2_ROGUE_ISA_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { Eisa , 0, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_ROGUE_ISA_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+ { Eisa , 0, UserPciDenseMemory, 2, ROGUE_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff },
+
+ { Eisa , 1, BusIo, 1, HAL_MAKE_LQVA(TREB2_ROGUE_ISA1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { Eisa , 1, BusMemory, 1, HAL_MAKE_LQVA(TREB2_ROGUE_ISA1_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { Eisa , 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+ { Eisa , 1, KernelPciDenseMemory, 2, ROGUE_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff },
+
+ { Eisa , 1, UserBusIo, 0, TREB2_ROGUE_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Eisa , 1, UserBusMemory, 0, HAL_MAKE_TA(TREB2_ROGUE_ISA1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { Eisa , 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_ROGUE_ISA1_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+ { Eisa , 1, UserPciDenseMemory, 2, ROGUE_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff },
+
+ { PCIBus, 0, BusIo, 1, HAL_MAKE_LQVA(TREB2_ROGUE_PCI_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { PCIBus, 0, BusMemory, 1, HAL_MAKE_LQVA(TREB2_ROGUE_PCI_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { PCIBus, 0, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+ { PCIBus, 0, BusMemory, 1, HAL_MAKE_LQVA(TREB2_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL) , 0x40000000, 0x47ffffff },
+ { PCIBus, 0, KernelPciDenseMemory, 2, ROGUE_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff },
+ { PCIBus, 0, KernelPciDenseMemory, 2, ROGUE_PCI_DENSE_BASE_PHYSICAL+0x40000000 , 0x40000000, 0x7fffffff },
+
+ { PCIBus, 0, UserBusIo, 0, TREB2_ROGUE_PCI_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { PCIBus, 0, UserBusMemory, 0, HAL_MAKE_TA(TREB2_ROGUE_PCI_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { PCIBus, 0, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_ROGUE_PCI_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+ { PCIBus, 0, UserBusMemory, 0, TREB2_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL , 0x40000000, 0x47ffffff },
+ { PCIBus, 0, UserPciDenseMemory, 2, ROGUE_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff },
+ { PCIBus, 0, UserPciDenseMemory, 2, ROGUE_PCI_DENSE_BASE_PHYSICAL+0x40000000 , 0x40000000, 0x7fffffff },
+
+ { PCIBus, 1, BusIo, 1, HAL_MAKE_LQVA(TREB2_ROGUE_PCI1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff },
+ { PCIBus, 1, BusMemory, 1, HAL_MAKE_LQVA(TREB2_ROGUE_PCI1_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff },
+ { PCIBus, 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+ { PCIBus, 1, BusMemory, 1, HAL_MAKE_LQVA(TREB2_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL) , 0x40000000, 0x47ffffff },
+ { PCIBus, 1, KernelPciDenseMemory, 2, ROGUE_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff },
+ { PCIBus, 1, KernelPciDenseMemory, 2, ROGUE_PCI_DENSE_BASE_PHYSICAL+0x40000000 , 0x40000000, 0x7fffffff },
+
+ { PCIBus, 1, UserBusIo, 0, TREB2_ROGUE_PCI1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { PCIBus, 1, UserBusMemory, 0, HAL_MAKE_TA(TREB2_ROGUE_PCI1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff },
+ { PCIBus, 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_ROGUE_PCI1_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff },
+ { PCIBus, 1, UserBusMemory, 0, TREB2_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL , 0x40000000, 0x47ffffff },
+ { PCIBus, 1, UserPciDenseMemory, 2, ROGUE_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff },
+ { PCIBus, 1, UserPciDenseMemory, 2, ROGUE_PCI_DENSE_BASE_PHYSICAL+0x40000000 , 0x40000000, 0x7fffffff },
+
+ { MaximumInterfaceType, 0, 0, 0, 0 , 0 , 0 }
+};
+
+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
+ )
+
+{
+ ULONG i;
+ INTERFACE_TYPE InterfaceType = BusHandler->InterfaceType;
+ ULONG BusNumber = BusHandler->BusNumber;
+ LONGLONG Offset;
+ PVOID va = 0; // note, this is used for a placeholder
+
+//BusAddress.HighPart = 0;
+//DbgPrint("HalTranslateBusAddress(IT=%d,BN=%d,BA=%08x %08x,AS=%d)\n\r",InterfaceType,BusNumber,BusAddress.HighPart,BusAddress.LowPart,*AddressSpace);
+
+ //
+ // PCI Bus 0 is different than PCI Bus 1, but all other PCI busses are the same a PCI Bus 1
+ //
+
+ if (InterfaceType == PCIBus) {
+
+ switch (HalpMotherboardType) {
+ case TREBBIA13 :
+ if (BusNumber > 1) {
+ BusNumber = 1;
+ }
+ break;
+
+ case TREBBIA20 :
+ if (BusNumber == 0) {
+
+ //
+ // There are no resources in PCI Bus #0. It only contains the memory system and bridges.
+ //
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+
+ if (BusNumber >= HalpSecondPciBridgeBusNumber) {
+ BusNumber = 1;
+ } else {
+ BusNumber = 0;
+ }
+ break;
+
+ default :
+
+//DbgPrint(" Invalid Motherboard Type\n\r");
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+ }
+
+ //
+ // If the VGA decodes are not enabled on the DEC PCI-PCI bridge associated with this
+ // memory range, then fail the translation.
+ //
+
+ if (!(HalpVgaDecodeBusNumber & (1<<BusNumber)) &&
+ BusAddress.QuadPart < (LONGLONG)0x0000000000100000 &&
+ (((ADDRESS_SPACE_TYPE)(*AddressSpace) == BusMemory) ||
+ ((ADDRESS_SPACE_TYPE)(*AddressSpace) == UserBusMemory) ||
+ ((ADDRESS_SPACE_TYPE)(*AddressSpace) == KernelPciDenseMemory) ||
+ ((ADDRESS_SPACE_TYPE)(*AddressSpace) == UserPciDenseMemory) )) {
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+
+ //
+ // Search the table for a valid mapping.
+ //
+
+ for(i=0;HalpRangeList[i].InterfaceType!=MaximumInterfaceType;i++) {
+
+ if (HalpRangeList[i].InterfaceType == InterfaceType &&
+ HalpRangeList[i].BusNumber == BusNumber &&
+ HalpRangeList[i].AddressType == (ADDRESS_SPACE_TYPE)(*AddressSpace) &&
+ BusAddress.QuadPart >= HalpRangeList[i].Base &&
+ BusAddress.QuadPart <= HalpRangeList[i].Limit ) {
+
+ TranslatedAddress->QuadPart = HalpRangeList[i].SystemBase;
+ *AddressSpace = HalpRangeList[i].SystemAddressSpace;
+
+ if (TranslatedAddress->QuadPart & KERNEL_PCI_VGA_VIDEO_ROM) {
+ TranslatedAddress->QuadPart &= ~KERNEL_PCI_VGA_VIDEO_ROM;
+ TranslatedAddress->QuadPart += (LONGLONG)HalpPlatformSpecificExtension->PciVideoExpansionRomAddress;
+ }
+
+ if (TranslatedAddress->QuadPart & USER_PCI_VGA_VIDEO_ROM) {
+ TranslatedAddress->QuadPart &= ~USER_PCI_VGA_VIDEO_ROM;
+ TranslatedAddress->QuadPart += (LONGLONG)(HalpPlatformSpecificExtension->PciVideoExpansionRomAddress << IO_BIT_SHIFT);
+ }
+
+ Offset = BusAddress.QuadPart - HalpRangeList[i].Base;
+ if (*AddressSpace == 0) {
+ Offset = Offset << IO_BIT_SHIFT;
+ }
+
+ TranslatedAddress->QuadPart += Offset;
+
+ if (*AddressSpace == 0) {
+ if (HalpIoArchitectureType != EV5_PROCESSOR_MODULE) {
+ if (!HalpMiniTlbAllocateEntry(HalCreateQva(*TranslatedAddress,va),TranslatedAddress)) {
+
+//DbgPrint("HalTranslateBusAddress(IT=%d,BN=%d,BA=%08x %08x,AS=%d)\n\r",InterfaceType,BusNumber,BusAddress.HighPart,BusAddress.LowPart,*AddressSpace);
+//DbgPrint(" Failed to allocate MiniTlb\n\r");
+
+ //
+ // A valid mapping was found, but the resources needed for the mapping could not be allocated.
+ //
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+ }
+ }
+
+ //
+ // If this is a UserPciDenseMemory mapping then let user call MmMapIoSpace()
+ //
+
+ if (*AddressSpace == 2) {
+ *AddressSpace = 0;
+ }
+
+//DbgPrint(" TranslatedAddress = %08x %08x AS=%d\n\r",TranslatedAddress->HighPart,TranslatedAddress->LowPart,*AddressSpace);
+
+ return(TRUE);
+ }
+ }
+
+//DbgPrint("HalTranslateBusAddress(IT=%d,BN=%d,BA=%08x %08x,AS=%d)\n\r",InterfaceType,BusNumber,BusAddress.HighPart,BusAddress.LowPart,*AddressSpace);
+//DbgPrint(" Failed\n\r");
+
+ //
+ // A valid mapping was not found.
+ //
+
+ *AddressSpace = 0;
+ TranslatedAddress->QuadPart = 0;
+ return(FALSE);
+}
+
+PVOID
+HalCreateQva(
+ IN PHYSICAL_ADDRESS PA,
+ IN PVOID VA
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called two ways. First, from HalTranslateBusAddress,
+ if the caller is going to run in kernel mode and use superpages.
+ The second way is if the user is going to access in user mode.
+ MmMapIoSpace or ZwViewMapOfSection will call this.
+
+ If the input parameter VA is zero, then we assume super page and build
+ a QUASI virtual address that is only usable by calling the hal I/O
+ access routines.
+
+ 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 a sparse 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.
+
+--*/
+{
+ PVOID qva;
+ ULONG AddressSpace;
+
+ if (VA != 0) {
+
+ AddressSpace = PA.HighPart & 0x0f;
+
+ //
+ // See if the physical address is in cached memory space.
+ //
+
+ if (AddressSpace == 0 && PA.LowPart < 0x40000000) {
+
+ return(VA);
+ }
+
+ //
+ // See if the physical address is in PCI dense memory.
+ //
+
+ if (AddressSpace == ((HalpPciDenseBasePhysicalSuperPage >> 32) & 0x0f)) {
+
+ return(VA);
+ }
+
+ //
+ // See if the physical address is in non cached memory.
+ //
+
+ if (AddressSpace == ((HalpNoncachedDenseBasePhysicalSuperPage >> 32) & 0x0f) && PA.LowPart < 0x40000000) {
+
+ return(VA);
+ }
+ }
+
+ //
+ // Otherwise, the physical address is within one of the sparse I/O spaces.
+ //
+
+ if (VA == 0) {
+
+ qva = (PVOID)(RtlLargeIntegerShiftRight(PA, IO_BIT_SHIFT).LowPart & ~(DTI_QVA_SELECTORS));
+ qva = (PVOID)((ULONG)qva | DTI_QVA_ENABLE);
+
+
+ } else {
+
+ qva = (PVOID)((ULONG)VA >> IO_BIT_SHIFT);
+ qva = (PVOID)((ULONG)qva | QVA_ENABLE);
+
+ }
+
+ 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 EB64+ we have only 2 bus types:
+ //
+ // Isa
+ // PCIBus
+ //
+ // We will allow Eisa as an alias for Isa. All other values not named
+ // above will be considered bogus.
+ //
+
+ 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 & DTI_QVA_SELECTORS) == DTI_QVA_ENABLE )
+ {
+ return( (PVOID)( (ULONG)Qva << IO_BIT_SHIFT ) );
+ }
+ else
+ {
+ return (Qva);
+ }
+ break;
+
+
+ default:
+
+ return NULL;
+
+ }
+}
+
diff --git a/private/ntos/nthals/halflex/alpha/alphaio.s b/private/ntos/nthals/halflex/alpha/alphaio.s
new file mode 100644
index 000000000..f9d7471c6
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/alphaio.s
@@ -0,0 +1,1482 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ alphaio.s
+
+
+Abstract:
+
+ 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.
+ (We are using EV4 64-bit superpage mode.)
+
+Author:
+
+ Joe Notarangelo 25-Oct-1993
+
+Environment:
+
+ Executes in kernel mode.
+
+Revision History:
+
+ 12-Jul-1994 - Eric Rehm - Added dense space I/O
+
+ 27-July-1994 - Sameer Dekate
+
+ Make a common file for all machines and optimize Read/Write
+ register buffer routines. Made a common routine with different
+ entry points for READ & WRITE_REGISTER_BUFFER routines
+
+--*/
+
+#include "halalpha.h"
+#include "apoc.h"
+
+
+
+////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////
+
+ .struct 0
+ .space 8 // filler for octaword alignment
+IoRa: .space 8 // space for return address
+IoS0: .space 8 // space for S0
+IoS1: .space 8 // space for S1
+IoS2: .space 8 // space for S2
+IoIrql: .space 8 // space for local variable
+IoFrameLength: //
+
+////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////
+
+#define EV4_IO(FastIoRoutine) \
+ ldq t0, HalpPciDenseBasePhysicalSuperPage; \
+ ldl t1, HalpIoArchitectureType; \
+ beq t1, FastIoRoutine; \
+ and a0, DTI_QVA_SELECTORS, t1; \
+ xor t1, DTI_QVA_ENABLE, t1; \
+ bne t1, FastIoRoutine; \
+ lda sp, -IoFrameLength(sp); \
+ stq ra, IoRa(sp); \
+ stq s0, IoS0(sp); \
+ stq s1, IoS1(sp); \
+ stq s2, IoS2(sp); \
+ or a0, a0, s0; \
+ or a1, a1, s1; \
+ or a2, a2, s2; \
+ or zero, HIGH_LEVEL, a0; \
+ addq sp, IoIrql, a1; \
+ bsr ra, KeRaiseIrql; \
+ or s0, s0, a0; \
+ bsr ra, HalpMiniTlbResolve; \
+ or v0, v0, a0; \
+ or s1, s1, a1; \
+ or s2, s2, a2; \
+ ldq t0, HalpPciDenseBasePhysicalSuperPage; \
+ bsr ra, FastIoRoutine; \
+ or v0, v0, s0; \
+ ldq a0, IoIrql(sp); \
+ and a0, 0xff, a0; \
+ bsr ra, KeLowerIrql; \
+ or s0, s0, v0; \
+ ldq s2, IoS2(sp); \
+ ldq s1, IoS1(sp); \
+ ldq s0, IoS0(sp); \
+ ldq ra, IoRa(sp); \
+ lda sp, IoFrameLength(sp); \
+ ret zero, (ra)
+
+////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////
+
+ LEAF_ENTRY(READ_REGISTER_UCHAR)
+ ALTERNATE_ENTRY(READ_PORT_UCHAR)
+ EV4_IO(EV5_READ_PORT_UCHAR)
+ .end READ_REGISTER_UCHAR
+
+ LEAF_ENTRY(READ_REGISTER_USHORT)
+ ALTERNATE_ENTRY(READ_PORT_USHORT)
+ EV4_IO(EV5_READ_PORT_USHORT)
+ .end READ_REGISTER_USHORT
+
+ LEAF_ENTRY(READ_REGISTER_ULONG)
+ ALTERNATE_ENTRY(READ_PORT_ULONG)
+ EV4_IO(EV5_READ_PORT_ULONG)
+ .end READ_REGISTER_ULONG
+
+ LEAF_ENTRY(WRITE_REGISTER_UCHAR)
+ ALTERNATE_ENTRY(WRITE_PORT_UCHAR)
+ EV4_IO(EV5_WRITE_PORT_UCHAR)
+ .end WRITE_REGISTER_UCHAR
+
+ LEAF_ENTRY(WRITE_REGISTER_USHORT)
+ ALTERNATE_ENTRY(WRITE_PORT_USHORT)
+ EV4_IO(EV5_WRITE_PORT_USHORT)
+ .end WRITE_REGISTER_USHORT
+
+ LEAF_ENTRY(WRITE_REGISTER_ULONG)
+ ALTERNATE_ENTRY(WRITE_PORT_ULONG)
+ EV4_IO(EV5_WRITE_PORT_ULONG)
+ .end WRITE_REGISTER_ULONG
+
+ LEAF_ENTRY(READ_PORT_BUFFER_UCHAR)
+ EV4_IO(EV5_READ_PORT_BUFFER_UCHAR)
+ .end READ_PORT_BUFFER_UCHAR
+
+ LEAF_ENTRY(READ_PORT_BUFFER_USHORT)
+ EV4_IO(EV5_READ_PORT_BUFFER_USHORT)
+ .end READ_PORT_BUFFER_USHORT
+
+ LEAF_ENTRY(READ_PORT_BUFFER_ULONG)
+ EV4_IO(EV5_READ_PORT_BUFFER_ULONG)
+ .end READ_PORT_BUFFER_ULONG
+
+ LEAF_ENTRY(WRITE_PORT_BUFFER_UCHAR)
+ EV4_IO(EV5_WRITE_PORT_BUFFER_UCHAR)
+ .end WRITE_PORT_BUFFER_UCHAR
+
+ LEAF_ENTRY(WRITE_PORT_BUFFER_USHORT)
+ EV4_IO(EV5_WRITE_PORT_BUFFER_USHORT)
+ .end WRITE_PORT_BUFFER_USHORT
+
+ LEAF_ENTRY(WRITE_PORT_BUFFER_ULONG)
+ EV4_IO(EV5_WRITE_PORT_BUFFER_ULONG)
+ .end WRITE_PORT_BUFFER_ULONG
+
+ LEAF_ENTRY(READ_REGISTER_BUFFER_UCHAR)
+ EV4_IO(EV5_READ_REGISTER_BUFFER_UCHAR)
+ .end READ_REGISTER_BUFFER_UCHAR
+
+ LEAF_ENTRY(READ_REGISTER_BUFFER_USHORT)
+ EV4_IO(EV5_READ_REGISTER_BUFFER_USHORT)
+ .end READ_REGISTER_BUFFER_USHORT
+
+ LEAF_ENTRY(READ_REGISTER_BUFFER_ULONG)
+ EV4_IO(EV5_READ_REGISTER_BUFFER_ULONG)
+ .end READ_REGISTER_BUFFER_ULONG
+
+ LEAF_ENTRY(WRITE_REGISTER_BUFFER_UCHAR)
+ EV4_IO(EV5_WRITE_REGISTER_BUFFER_UCHAR)
+ .end WRITE_REGISTER_BUFFER_UCHAR
+
+ LEAF_ENTRY(WRITE_REGISTER_BUFFER_USHORT)
+ EV4_IO(EV5_WRITE_REGISTER_BUFFER_USHORT)
+ .end WRITE_REGISTER_BUFFER_USHORT
+
+ LEAF_ENTRY(WRITE_REGISTER_BUFFER_ULONG)
+ EV4_IO(EV5_WRITE_REGISTER_BUFFER_ULONG)
+ .end WRITE_REGISTER_BUFFER_ULONG
+
+////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////
+
+ SBTTL( "Read I/O byte" )
+//++
+//
+// UCHAR
+// READ_REGISTER_UCHAR(
+// IN PVOID RegisterQva
+// )
+//
+// Routine Description:
+//
+// Reads a byte location in PCI bus memory or 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(EV5_READ_REGISTER_UCHAR)
+
+ ALTERNATE_ENTRY(EV5_READ_PORT_UCHAR)
+
+ and a0, DTI_QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get byte we need if eisa
+ xor t1, DTI_QVA_ENABLE, t1 // ok iff DTI_QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, DTI_QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, -0x3080 // 0xffff ffff ffff cf80
+ sll t4, 28, t4 // 0xffff fcf8 0000 0000
+ or t0, t4, t0 // superpage mode
+
+ mb
+ ldl v0, (t0) // get the longword
+ extbl v0, t3, v0 // get correct byte if eisa
+
+ ret zero, (ra) // return
+
+//
+// Dense space access: QVA is an offset into dense space
+//
+
+2:
+ and a0, 3, t3 // get byte we need
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, 3, a0 // clear <1:0> to get aligned longword
+
+// ldiq t0, PCI_DENSE_BASE_PHYSICAL_SUPERPAGE
+ or a0, t0, a0 // superpage mode: add offset to base
+
+ ldl v0, (a0) // get the longword
+ extbl v0, t3, v0 // get correct byte
+
+ ret zero, (ra) // return
+
+ .end EV5_READ_REGISTER_UCHAR
+
+
+ SBTTL( "Read I/O word(16 bits)" )
+//++
+//
+// USHORT
+// READ_REGISTER_USHORT(
+// IN PVOID RegisterQva
+// )
+//
+// Routine Description:
+//
+// Reads a word location in PCI bus memory or I/O space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the I/O word to read.
+//
+// Return Value:
+//
+// v0 - Returns the value read from I/O space.
+//
+//--
+
+ LEAF_ENTRY(EV5_READ_REGISTER_USHORT)
+
+ ALTERNATE_ENTRY(EV5_READ_PORT_USHORT)
+
+ and a0, DTI_QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get word
+ xor t1, DTI_QVA_ENABLE, t1 // ok iff DTI_QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, DTI_QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, -0x3080 //
+ sll t4, 28, t4 //
+ or t0, t4, t0 // superpage mode
+
+ or t0, IO_WORD_LEN, t0 // or in the byte enables
+
+ mb
+ ldl v0, (t0) // get the longword
+ extwl v0,t3,v0 // get the correct word
+
+ ret zero, (ra) // return
+
+//
+// Dense space access: QVA is an offset into dense space
+//
+
+2:
+ and a0, 3, t3 // get word we need
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, 3, a0 // clear <1:0> to get aligned longword
+
+// ldiq t0, PCI_DENSE_BASE_PHYSICAL_SUPERPAGE
+ or a0,t0, a0 // superpage mode: add offset to base
+
+ ldl v0, (a0) // get the longword
+ extwl v0, t3, v0 // get correct word
+
+ ret zero, (ra) // return
+
+ .end EV5_READ_REGISTER_USHORT
+
+
+ SBTTL( "Read I/O longword(32 bits)" )
+//++
+//
+// ULONG
+// READ_REGISTER_ULONG(
+// IN PVOID RegisterQva
+// )
+//
+// Routine Description:
+//
+// Reads a longword location in PCI bus memory or I/O space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the I/O longword to read.
+//
+// Return Value:
+//
+// v0 - Returns the value read from I/O space.
+//
+//--
+
+ LEAF_ENTRY(EV5_READ_REGISTER_ULONG)
+
+ ALTERNATE_ENTRY(EV5_READ_PORT_ULONG)
+
+ and a0, DTI_QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, DTI_QVA_ENABLE, t1 // ok iff DTI_QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, DTI_QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, -0x3080 //
+ sll t4, 28, t4 //
+ or t0, t4, t0 // superpage mode
+
+ or t0, IO_LONG_LEN, t0 // or in the byte enables
+
+ mb
+ ldl v0, (t0) // read the longword
+
+ ret zero, (ra) // return
+
+//
+// Dense space access: QVA is an offset into dense space
+//
+
+2:
+ zap a0, 0xf0, a0 // clear <63:32>
+
+// ldiq t0, PCI_DENSE_BASE_PHYSICAL_SUPERPAGE
+ or a0, t0, a0 // superpage mode: add offset to base
+
+ ldl v0, (a0) // get the longword
+
+ ret zero, (ra) // return
+
+ .end EV5_READ_REGISTER_ULONG
+
+ SBTTL( "Write I/O byte" )
+//++
+//
+// VOID
+// WRITE_REGISTER_UCHAR(
+// IN PVOID RegisterQva,
+// IN UCHAR Value
+// )
+//
+// Routine Description:
+//
+// Writes a byte location in PCI bus memory or I/O space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the I/O byte to write.
+//
+// Value(a1) - Supplies the value written to I/O space.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(EV5_WRITE_REGISTER_UCHAR)
+
+ ALTERNATE_ENTRY(EV5_WRITE_PORT_UCHAR)
+
+ and a0, DTI_QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get byte we need if eisa
+ xor t1, DTI_QVA_ENABLE, t1 // ok iff DTI_QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, DTI_QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, -0x3080 //
+ sll t4, 28, t4 //
+ or t0, t4, t0 // superpage mode
+
+ insbl a1,t3,t4 // put the byte in the correct position
+ stl t4, (t0) // write the byte
+ mb // order the write
+
+ ret zero, (ra) // return
+
+//
+// Dense space access: QVA is an offset into dense space
+//
+
+2:
+ and a0, 3, t3 // get byte we need if eisa
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, 3, a0 // clear <1:0> to get aligned longword
+
+// ldiq t0, PCI_DENSE_BASE_PHYSICAL_SUPERPAGE
+ or a0, t0, a0 // superpage mode: add offset to base
+
+ ldl t1, (a0) // get the long
+ mskbl t1, t3, t1 // mask the proper byte
+ insbl a1, t3, t2 // put byte into position
+ bis t1, t2, t1 // merge byte in result
+ stl t1, (a0) // store the result
+ mb // order the write
+
+ ret zero, (ra) // return
+
+ .end EV5_WRITE_REGISTER_UCHAR
+
+
+ SBTTL( "Write I/O word (16 bits)" )
+//++
+//
+// VOID
+// WRITE_REGISTER_USHORT(
+// IN PVOID RegisterQva,
+// IN USHORT Value
+// )
+//
+// Routine Description:
+//
+// Writes a word location in PCI bus memory or I/O space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the I/O word to write.
+//
+// Value(a1) - Supplies the value written to I/O space.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(EV5_WRITE_REGISTER_USHORT)
+
+ ALTERNATE_ENTRY(EV5_WRITE_PORT_USHORT)
+
+ and a0, DTI_QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get word
+ xor t1, DTI_QVA_ENABLE, t1 // ok iff DTI_QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, DTI_QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, -0x3080 //
+ sll t4, 28, t4 //
+ or t0, t4, t0 // superpage mode
+
+ or t0, IO_WORD_LEN, t0 // or in the byte enables
+
+ inswl a1,t3,t2 // put the word in the correct place
+ stl t2, (t0) // write the word
+ mb // order the write
+
+ ret zero, (ra) // return
+
+//
+// Dense space access: QVA is an offset into dense space
+//
+
+2:
+ and a0, 3, t3 // get byte we need if eisa
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, 3, a0 // clear <1:0> to get aligned longword
+
+// ldiq t0, PCI_DENSE_BASE_PHYSICAL_SUPERPAGE
+ or a0, t0, a0 // superpage mode: add offset to base
+
+ ldl t1, (a0) // get the long
+ mskwl t1, t3, t1 // mask the proper word
+ inswl a1, t3, t2 // put word into position
+ bis t1, t2, t1 // merge in result
+ stl t1, (a0) // store the result
+ mb // order the write
+
+ ret zero, (ra) // return
+
+ .end EV5_WRITE_REGISTER_USHORT
+
+
+ SBTTL( "Write I/O longword (32 bits)" )
+//++
+//
+// VOID
+// WRITE_REGISTER_ULONG(
+// IN PVOID RegisterQva,
+// IN ULONG Value
+// )
+//
+// Routine Description:
+//
+// Writes a longword location in PCI bus memory or I/O space.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the QVA of the I/O longword to write.
+//
+// Value(a1) - Supplies the value written to I/O space.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(EV5_WRITE_REGISTER_ULONG)
+
+ ALTERNATE_ENTRY(EV5_WRITE_PORT_ULONG)
+
+ and a0, DTI_QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, DTI_QVA_ENABLE, t1 // ok iff DTI_QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, DTI_QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, -0x3080 //
+ sll t4, 28, t4 //
+ or t0, t4, t0 // superpage mode
+
+ or t0, IO_LONG_LEN, t0 // or in the byte enables
+
+ stl a1, (t0) // write the longword
+ mb // order the write
+
+ ret zero, (ra) // return
+
+//
+// Dense space access: QVA is an offset into dense space
+//
+
+2:
+ zap a0, 0xf0, a0 // clear <63:32>
+// ldiq t0, PCI_DENSE_BASE_PHYSICAL_SUPERPAGE
+ or a0, t0, a0 // superpage mode: add offset to base
+
+ stl a1, (a0) // store the longword
+ mb // order the write
+
+ ret zero, (ra) // return
+
+ .end EV5_WRITE_REGISTER_ULONG
+
+
+//++
+//
+// 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(EV5_READ_PORT_BUFFER_UCHAR)
+
+ and a0, 3, t3 // get byte we need if eisa
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ bic a0, DTI_QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, -0x3080 // t4=ffff ffff ffff c000
+ sll t4, 28, t4 // t4=ffff fc00 0000 0000
+ or t0, t4, t0 // superpage mode
+
+ beq a2, 3f // if count==0 return
+2:
+ 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
+ bne a2, 2b // while count != 0
+3:
+
+ ret zero, (ra) // return
+
+ .end EV5_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(EV5_READ_PORT_BUFFER_USHORT)
+
+ and a0, 3, t3 // get word we need
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ bic a0, DTI_QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, -0x3080 // t4=ffff ffff ffff c000
+ sll t4, 28, t4 // t4=ffff fc00 0000 0000
+ or t0, t4, t0 // superpage mode
+ or t0, IO_WORD_LEN, t0 // or in the byte enables
+
+ beq a2, 3f // if count==0 return
+2:
+ 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
+ bne a2, 2b // while count != 0
+3:
+
+ ret zero, (ra) // return
+
+ .end EV5_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(EV5_READ_PORT_BUFFER_ULONG)
+
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ bic a0, DTI_QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+
+ ldiq t4, -0x3080 // t4=ffff ffff ffff c000
+ sll t4, 28, t4 // t4=ffff fc00 0000 0000
+ or t0, t4, t0 // superpage mode
+ or t0, IO_LONG_LEN, t0 // or in the byte enables
+
+ beq a2, 3f // if count==0 return
+2:
+ 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
+ bne a2, 2b // while count != 0
+3:
+
+ ret zero, (ra) // return
+
+ .end EV5_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(EV5_WRITE_PORT_BUFFER_UCHAR)
+
+ and a0, 3, t3 // get byte we need if eisa
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ bic a0, DTI_QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, -0x3080 // t4=ffff ffff ffff c000
+ sll t4, 28, t4 // t4=ffff fc00 0000 0000
+ or t0, t4, t0 // superpage mode
+
+ beq a2, 3f // if count==0 return
+2:
+ 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
+ bne a2, 2b // while count != 0
+
+3:
+
+ ret zero, (ra) // return
+
+ .end EV5_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(EV5_WRITE_PORT_BUFFER_USHORT)
+
+ and a0, 3, t3 // get word we need
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ bic a0, DTI_QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, -0x3080 // t4=ffff ffff ffff c000
+ sll t4, 28, t4 // t4=ffff fc00 0000 0000
+ or t0, t4, t0 // superpage mode
+ or t0, IO_WORD_LEN, t0 // or in the byte enables
+
+ beq a2, 3f // if count==0 return
+2:
+ 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 writes off chip
+ bne a2, 2b // while count != 0
+
+3:
+
+ ret zero, (ra) // return
+
+ .end EV5_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(EV5_WRITE_PORT_BUFFER_ULONG)
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, DTI_QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, -0x3080 // t4=ffff ffff ffff c000
+ sll t4, 28, t4 // t4=ffff fc00 0000 0000
+ or t0, t4, t0 // superpage mode
+ or t0, IO_LONG_LEN, t0 // or in the byte enables
+
+ beq a2, 3f // if count==0 return
+2:
+ ldl t1, 0(a1) // a1 must be longword aligned
+ subl a2, 1, a2 // decrement count
+ stl t1, 0(t0) // store to port
+ mb // push writes off chip
+ addl a1, 4, a1 // increment buffer
+ bne a2, 2b // while count != 0
+
+3:
+
+ ret zero, (ra) // return
+
+ .end EV5_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(EV5_READ_REGISTER_BUFFER_ULONG)
+
+ sll a2, 1, a2 // convert number of longs to words
+
+ ALTERNATE_ENTRY(EV5_READ_REGISTER_BUFFER_USHORT)
+
+
+ sll a2, 1, a2 // convert number of words to chars
+
+ ALTERNATE_ENTRY(EV5_READ_REGISTER_BUFFER_UCHAR)
+
+ and a0, DTI_QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, DTI_QVA_ENABLE, t1 // ok iff DTI_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>
+// ldiq t0, PCI_DENSE_BASE_PHYSICAL_SUPERPAGE
+ 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>
+ bic a0, DTI_QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, -0x3080 // 0xffff ffff ffff c000
+ sll t4, 28, t4 // 0xffff fc00 0000 0000
+ 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)
+
+ 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:
+ 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:
+ 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)
+
+ 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
+ //
+ 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
+ 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:
+ 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 EV5_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(EV5_WRITE_REGISTER_BUFFER_ULONG)
+
+ sll a2, 1, a2 // convert number of longs to words
+
+ ALTERNATE_ENTRY(EV5_WRITE_REGISTER_BUFFER_USHORT)
+
+ sll a2, 1, a2 // convert number of words to chars
+
+ ALTERNATE_ENTRY(EV5_WRITE_REGISTER_BUFFER_UCHAR)
+
+ and a0, DTI_QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, DTI_QVA_ENABLE, t1 // ok iff DTI_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>
+// ldiq t0, PCI_DENSE_BASE_PHYSICAL_SUPERPAGE
+ 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:
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, DTI_QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, -0x3080 // 0xffff ffff ffff c000
+ sll t4, 28, t4 // 0xffff fc00 0000 0000
+ 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
+ stl t1, 0(t0) // store byte to buffer (BYTE ENABLED)
+ 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
+ stl t1, 0(t0) // store to buffer
+ 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
+ stl t1, 0(t0) // store byte to buffer (BYTE ENABLED)
+ 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
+ stl t1, 0(t0) // store byte to buffer (BYTE ENABLED)
+ 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 EV5_WRITE_REGISTER_BUFFER_ULONG // end for UCHAR & USHORT
+
+
+//++
+//
+// VOID
+// HalpWriteAbsoluteUlong(
+// IN ULONG HighPart,
+// IN ULONG LowPart,
+// IN ULONG Value
+// )
+//
+// Routine Description:
+//
+// Writes Value to the processor address given in HighPart and LowPart.
+//
+// Arguments:
+//
+// HighPart(a0) - Upper 32 bits of address
+//
+// LowPart(a1) - Lower 32 bits of address
+//
+// Value(a2) - Value to write
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpWriteAbsoluteUlong)
+ sll a0, 32, t0 // Shift Upper 32 bits of address into position
+ zap t0, 0x0f, t0 // Clear lower 32 bits of shifted address
+ zap a1, 0xf0, a1 // Clear upper 32 of lower part of address
+ or a1, t0, t0 // Build 64 bit address
+ stl a2, 0x0(t0) // Write value to address
+ mb // Memory Barrier
+ ret zero, (ra) // return
+ .end HalpWriteAbsoluteUlong
+
+//++
+//
+// ULONG
+// HalpReadAbsoluteUlong(
+// IN ULONG HighPart,
+// IN ULONG LowPart
+// )
+//
+// Routine Description:
+//
+// Reads a value from the processor address given in HighPart and LowPart.
+//
+// Arguments:
+//
+// HighPart(a0) - Upper 32 bits of address
+//
+// LowPart(a1) - Lower 32 bits of address
+//
+// Return Value:
+//
+// 32 bit value read from the processor address.
+//
+//--
+
+ LEAF_ENTRY(HalpReadAbsoluteUlong)
+ sll a0, 32, t0 // Shift Upper 32 bits of address into position
+ zap t0, 0x0f, t0 // Clear lower 32 bits of shifted address
+ zap a1, 0xf0, a1 // Clear upper 32 of lower part of address
+ or a1, t0, t0 // Build 64 bit address
+ mb // Memory Barrier
+ ldl v0, 0x0(t0) // Read value from address
+ ret zero, (ra) // return
+ .end HalpReadAbsoluteUlong
+
+
diff --git a/private/ntos/nthals/halflex/alpha/apoc.h b/private/ntos/nthals/halflex/alpha/apoc.h
new file mode 100644
index 000000000..85e3a8dc2
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/apoc.h
@@ -0,0 +1,167 @@
+/*++
+
+Copyright (c) 1995 DeskStation Technology
+
+Module Name:
+
+ apoc.h
+
+Abstract:
+
+ This file contains definitions specific to the Apocalypse (ALPHA EV5)
+ and Rogue (ALPHA EV4) processor modules.
+
+Author:
+
+ Michael D. Kinney 1-May-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#define DTI_QVA_ENABLE (0x80000000) // Identify VA as a QVA
+#define DTI_QVA_SELECTORS (0xc0000000) // 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
+
+//
+// Constant used by dense space I/O routines
+//
+
+#define APOC1_PCI_DENSE_BASE_PHYSICAL_SUPERPAGE ((ULONGLONG)0xfffffcfb00000000)
+#define APOC2_PCI_DENSE_BASE_PHYSICAL_SUPERPAGE ((ULONGLONG)0xfffffcfe00000000)
+#define ROGUE_PCI_DENSE_BASE_PHYSICAL_SUPERPAGE ((ULONGLONG)0xfffffc0100000000)
+
+//
+// Noncached Dense Memory address spaces.
+//
+
+#define APOC1_NONCACHED_DENSE_BASE_PHYSICAL_SUPERPAGE ((ULONGLONG)0xfffffcfb00000000)
+#define APOC2_NONCACHED_DENSE_BASE_PHYSICAL_SUPERPAGE ((ULONGLONG)0xfffffcfb00000000)
+#define ROGUE_NONCACHED_DENSE_BASE_PHYSICAL_SUPERPAGE ((ULONGLONG)0xfffffc0100000000)
+
+//
+// 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)( DTI_QVA_ENABLE | (ULONG)((PA) >> IO_BIT_SHIFT) & ~(DTI_QVA_SELECTORS) ) )
+
+
+
+//
+// Define physical address spaces for Apocalypse
+//
+
+#define TREB1_APOC1_ISA_IO_BASE_PHYSICAL ((ULONGLONG)0x0c00000000)
+#define TREB1_APOC1_ISA_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0a00000000)
+#define TREB1_APOC1_ISA1_IO_BASE_PHYSICAL ((ULONGLONG)0x0d00000000)
+#define TREB1_APOC1_ISA1_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0900000000)
+#define TREB1_APOC1_PCI_IO_BASE_PHYSICAL ((ULONGLONG)0x0d00000000)
+#define TREB1_APOC1_PCI_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0900000000)
+#define TREB1_APOC1_PCI_HIGH_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0800000000)
+
+#define TREB1_APOC2_ISA_IO_BASE_PHYSICAL ((ULONGLONG)0x0c00000000)
+#define TREB1_APOC2_ISA_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0a00000000)
+#define TREB1_APOC2_ISA1_IO_BASE_PHYSICAL ((ULONGLONG)0x0d00000000)
+#define TREB1_APOC2_ISA1_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0900000000)
+#define TREB1_APOC2_PCI_IO_BASE_PHYSICAL ((ULONGLONG)0x0d00000000)
+#define TREB1_APOC2_PCI_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0900000000)
+#define TREB1_APOC2_PCI_HIGH_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0800000000)
+
+#define TREB2_APOC1_ISA_IO_BASE_PHYSICAL ((ULONGLONG)0x0d00000000)
+#define TREB2_APOC1_ISA_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0900000000)
+#define TREB2_APOC1_ISA1_IO_BASE_PHYSICAL ((ULONGLONG)0x0c00000000)
+#define TREB2_APOC1_ISA1_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0a00000000)
+#define TREB2_APOC1_PCI_IO_BASE_PHYSICAL ((ULONGLONG)0x0d00000000)
+#define TREB2_APOC1_PCI_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0900000000)
+#define TREB2_APOC1_PCI1_IO_BASE_PHYSICAL ((ULONGLONG)0x0c00000000)
+#define TREB2_APOC1_PCI1_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0a00000000)
+#define TREB2_APOC1_PCI_HIGH_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0800000000)
+
+#define TREB2_APOC2_ISA_IO_BASE_PHYSICAL ((ULONGLONG)0x0d00000000)
+#define TREB2_APOC2_ISA_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0900000000)
+#define TREB2_APOC2_ISA1_IO_BASE_PHYSICAL ((ULONGLONG)0x0c00000000)
+#define TREB2_APOC2_ISA1_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0a00000000)
+#define TREB2_APOC2_PCI_IO_BASE_PHYSICAL ((ULONGLONG)0x0d00000000)
+#define TREB2_APOC2_PCI_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0900000000)
+#define TREB2_APOC2_PCI1_IO_BASE_PHYSICAL ((ULONGLONG)0x0c00000000)
+#define TREB2_APOC2_PCI1_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0a00000000)
+#define TREB2_APOC2_PCI_HIGH_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0800000000)
+
+#define APOC1_PCI_CONFIG_BASE_PHYSICAL ((ULONGLONG)0xfffffcfe00000000)
+#define APOC1_PCI_CONFIG0_BASE_PHYSICAL ((ULONGLONG)0xfffffcfe00000000)
+#define APOC1_PCI_CONFIG1_BASE_PHYSICAL ((ULONGLONG)0xfffffcff00000000)
+#define APOC1_PCI_DENSE_BASE_PHYSICAL ((ULONGLONG)0x0b00000000)
+
+#define APOC2_PCI_CONFIG_BASE_PHYSICAL ((ULONGLONG)0xfffffcb800000000)
+#define APOC2_PCI_CONFIG0_BASE_PHYSICAL ((ULONGLONG)0xfffffcb800000000)
+#define APOC2_PCI_CONFIG1_BASE_PHYSICAL ((ULONGLONG)0xfffffcd800000000)
+#define APOC2_PCI_DENSE_BASE_PHYSICAL ((ULONGLONG)0x0e00000000)
+#define APOC2_TRANSLATED_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0f00000000)
+
+#define APOC_DMA_CACHE_BASE_PHYSICAL ((ULONGLONG)0x0b007c0000)
+#define APOC_CACHE_FLUSH_BASE_PHYSICAL ((ULONGLONG)0x003fe00000)
+#define APOC_DMA_CACHE_SIZE 0x00040000
+#define APOC_CACHE_FLUSH_SIZE 0x00200000
+
+//
+// Define physical address spaces for Rogue
+//
+
+#define ROGUE_TRANSLATED_BASE_PHYSICAL ((ULONGLONG)0x0a00000000)
+
+#define TREB1_ROGUE_ISA_IO_BASE_PHYSICAL ((ULONGLONG)0x0000000000)
+#define TREB1_ROGUE_ISA_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0040000000)
+#define TREB1_ROGUE_ISA1_IO_BASE_PHYSICAL ((ULONGLONG)0x0080000000)
+#define TREB1_ROGUE_ISA1_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x00c0000000)
+#define TREB1_ROGUE_PCI_IO_BASE_PHYSICAL ((ULONGLONG)0x0080000000)
+#define TREB1_ROGUE_PCI_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x00c0000000)
+#define TREB1_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0100000000)
+
+#define TREB2_ROGUE_ISA_IO_BASE_PHYSICAL ((ULONGLONG)0x0080000000)
+#define TREB2_ROGUE_ISA_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x00c0000000)
+#define TREB2_ROGUE_ISA1_IO_BASE_PHYSICAL ((ULONGLONG)0x0000000000)
+#define TREB2_ROGUE_ISA1_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0040000000)
+#define TREB2_ROGUE_PCI_IO_BASE_PHYSICAL ((ULONGLONG)0x0080000000)
+#define TREB2_ROGUE_PCI_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x00c0000000)
+#define TREB2_ROGUE_PCI1_IO_BASE_PHYSICAL ((ULONGLONG)0x0000000000)
+#define TREB2_ROGUE_PCI1_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0040000000)
+#define TREB2_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0100000000)
+
+#define ROGUE_PCI_CONFIG0_BASE_PHYSICAL ((ULONGLONG)0x0200000000)
+#define ROGUE_PCI_CONFIG1_BASE_PHYSICAL ((ULONGLONG)0x03c0000000)
+#define ROGUE_PCI_DENSE_BASE_PHYSICAL ((ULONGLONG)0x0100000000)
+#define ROGUE_DMA_CACHE_BASE_PHYSICAL ((ULONGLONG)0x01007c0000)
+#define ROGUE_CACHE_FLUSH_BASE_PHYSICAL ((ULONGLONG)0x003fc00000)
+#define ROGUE_DMA_CACHE_SIZE 0x00040000
+#define ROGUE_CACHE_FLUSH_SIZE 0x00400000
diff --git a/private/ntos/nthals/halflex/alpha/arcssup.c b/private/ntos/nthals/halflex/alpha/arcssup.c
new file mode 100644
index 000000000..6169f9c3b
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/arcssup.c
@@ -0,0 +1,87 @@
+/*++
+
+Copyright (c) 1995 DeskStation Technology
+
+Module Name:
+
+ arcssup.c
+
+Abstract:
+
+ This module allocates resources before a call to the ARCS Firmware, and
+ frees those reources after the call returns.
+
+Author:
+
+ Michael D. Kinney 30-Apr-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+static KIRQL HalpArcsIrql;
+
+VOID
+HalpAllocateArcsResources (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allocated resources required before an ARCS Firmware call is made.
+ On an ALPHA system, this is a NULL function.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+
+{
+ if (HalpIoArchitectureType != EV5_PROCESSOR_MODULE) {
+ KeRaiseIrql(HIGH_LEVEL, &HalpArcsIrql);
+ HalpMiniTlbSaveState();
+ }
+}
+
+VOID
+HalpFreeArcsResources (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine frees the TLB entry that was reserved for the ARCS
+ Firmware call. On an ALPHA system, this is a NULL function.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ if (HalpIoArchitectureType != EV5_PROCESSOR_MODULE) {
+ HalpMiniTlbRestoreState();
+ KeLowerIrql(HalpArcsIrql);
+ }
+}
diff --git a/private/ntos/nthals/halflex/alpha/dtidef.h b/private/ntos/nthals/halflex/alpha/dtidef.h
new file mode 100644
index 000000000..2301a1556
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/dtidef.h
@@ -0,0 +1,149 @@
+/*++ BUILD Version: 0005 // Increment this if a change has global effects
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ dtidef.h
+
+Abstract:
+
+ This module is the header file that describes hardware addresses
+ for the Jazz system.
+
+Author:
+
+ David N. Cutler (davec) 26-Nov-1990
+
+Revision History:
+
+--*/
+
+#ifndef _DTIDEF_
+#define _DTIDEF_
+
+#include "uniflex.h"
+#include "apoc.h"
+#include "platform.h"
+
+//
+// Define the data structure returned by a private vector firmware function
+// that contains a set of system parameters.
+//
+
+typedef struct PLATFORM_SPECIFIC_EXTENSION {
+ UCHAR PciInterruptToIsaIrq[12];
+ ULONG PciVideoExpansionRomAddress;
+ PVOID AdvancedSetupInfo;
+} PLATFORM_SPECIFIC_EXTENSION;
+
+typedef struct TREB13SETUPINFO {
+ ULONG Reserved1:16;
+ ULONG Drive0Type:4;
+ ULONG Drive1Type:4;
+ ULONG PciInterruptToIsaIrq0:4;
+ ULONG PciInterruptToIsaIrq8:4;
+ ULONG PciInterruptToIsaIrq1:4;
+ ULONG PciInterruptToIsaIrq9:4;
+ ULONG PciInterruptToIsaIrq2:4;
+ ULONG PciInterruptToIsaIrq10:4;
+ ULONG PciInterruptToIsaIrq3:4;
+ ULONG PciInterruptToIsaIrq11:4;
+ ULONG Lpt1Irq:8;
+ ULONG Lpt2Irq:8;
+ ULONG Lpt3Irq:8;
+ ULONG SerialMousePort:8;
+ ULONG EnableAmd1:1;
+ ULONG EnableAmd2:1;
+ ULONG EnableX86Emulator:1;
+ ULONG Reserved2:5;
+ ULONG LoadEmbeddedScsiDrivers:1;
+ ULONG Reserved3:7;
+ ULONG LoadSoftScsiDrivers:1;
+ ULONG LoadFlashScsiDrivers:1;
+ ULONG Reserved4:6;
+ ULONG EnableDelays:1;
+ ULONG Reserved5:7;
+ ULONG ResetDelay:8;
+ ULONG DetectDelay:8;
+ ULONG EnableIdeDriver:1;
+ ULONG Reserved6:7;
+} TREB13SETUPINFO;
+
+typedef struct TREB20SETUPINFO {
+ ULONG Isa0Drive0Type:4;
+ ULONG Isa0Drive1Type:4;
+ ULONG Isa1Drive0Type:4;
+ ULONG Isa1Drive1Type:4;
+ ULONG SerialMousePort:8;
+ ULONG Isa0Lpt1Irq:8;
+ ULONG Isa0Lpt2Irq:8;
+ ULONG Isa0Lpt3Irq:8;
+ ULONG Isa1Lpt1Irq:8;
+ ULONG Isa1Lpt2Irq:8;
+ ULONG Isa1Lpt3Irq:8;
+ ULONG EnableNcr:1;
+ ULONG EnableX86Emulator:1;
+ ULONG LoadEmbeddedScsiDrivers:1;
+ ULONG LoadSoftScsiDrivers:1;
+ ULONG LoadFlashScsiDrivers:1;
+ ULONG EnableDelays:1;
+ ULONG EnableIdeDriver:1;
+ ULONG Reserved1:1;
+ ULONG ResetDelay:8;
+ ULONG DetectDelay:8;
+ ULONG PciInterruptToIsaIrq0:4;
+ ULONG PciInterruptToIsaIrq1:4;
+ ULONG PciInterruptToIsaIrq2:4;
+ ULONG PciInterruptToIsaIrq3:4;
+ ULONG PciInterruptToIsaIrq4:4;
+ ULONG PciInterruptToIsaIrq5:4;
+ ULONG PciInterruptToIsaIrq6:4;
+ ULONG PciInterruptToIsaIrq7:4;
+ ULONG PciInterruptToIsaIrq8:4;
+ ULONG PciInterruptToIsaIrq9:4;
+ ULONG NcrTermLow:1;
+ ULONG NcrTermHigh:1;
+ ULONG Reserved2:6;
+} TREB20SETUPINFO;
+
+//
+// Define the data structure used to describe all bus translations.
+//
+
+typedef struct PLATFORM_RANGE_LIST {
+ INTERFACE_TYPE InterfaceType;
+ ULONG BusNumber;
+ ADDRESS_SPACE_TYPE AddressType;
+ ULONG SystemAddressSpace;
+ LONGLONG SystemBase;
+ LONGLONG Base;
+ LONGLONG Limit;
+} PLATFORM_RANGE_LIST, *PPLATFORM_RANGE_LIST;
+
+//
+// Define clock constants and clock levels.
+//
+
+#define UNIFLEX_CLOCK_LEVEL UNIFLEX_EISA_VECTORS+0 // Interval clock level is on ISA IRQ 0
+#define UNIFLEX_ISA_DEVICE_LEVEL 5 // ISA bus interrupt level
+#define UNIFLEX_EISA_DEVICE_LEVEL 5 // EISA bus interrupt level
+#define UNIFLEX_PCI_DEVICE_LEVEL 5 // PCI bus interrupt level
+#define UNIFLEX_CLOCK2_LEVEL UNIFLEX_CLOCK_LEVEL
+
+//
+// Define EISA device interrupt vectors.
+//
+
+#define UNIFLEX_ISA_VECTORS 48
+#define UNIFLEX_MAXIMUM_ISA_VECTOR (15 + UNIFLEX_ISA_VECTORS)
+#define UNIFLEX_EISA_VECTORS 48
+#define UNIFLEX_MAXIMUM_EISA_VECTOR (15 + UNIFLEX_EISA_VECTORS)
+#define UNIFLEX_ISA1_VECTORS 64
+#define UNIFLEX_MAXIMUM_ISA1_VECTOR (15 + UNIFLEX_ISA1_VECTORS)
+#define UNIFLEX_EISA1_VECTORS 64
+#define UNIFLEX_MAXIMUM_EISA1_VECTOR (15 + UNIFLEX_EISA1_VECTORS)
+#define UNIFLEX_PCI_VECTORS 100
+#define UNIFLEX_MAXIMUM_PCI_VECTOR (15 + UNIFLEX_PCI_VECTORS)
+
+#endif // _DTIDEF_
diff --git a/private/ntos/nthals/halflex/alpha/ev4int.c b/private/ntos/nthals/halflex/alpha/ev4int.c
new file mode 100644
index 000000000..7b64b42c8
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/ev4int.c
@@ -0,0 +1,955 @@
+/*++
+
+Copyright (C) 1993-1995 Digital Equipment Corporation
+
+Module Name:
+
+ ev4int.c
+
+Abstract:
+
+ This module implements the support routines to enable/disable DECchip
+ 21064-specific interrupts.
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+#include "halp.h"
+#include "axp21064.h"
+
+VOID
+HalpUpdate21064PriorityTable(
+ VOID
+ );
+
+VOID
+HalpCachePcrValues(
+ VOID
+ );
+
+
+
+VOID
+HalpInitialize21064Interrupts(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes the data structures for the 21064
+ interrupt enable/disable routines.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG Index;
+ EV4Irq Irq;
+
+ //
+ // Initialize each entry in the Irq Status Table.
+ //
+
+ for( Irq=Irq0; Irq<MaximumIrq; Irq++ ){
+ HAL_21064_PCR->IrqStatusTable[Irq].Enabled = FALSE;
+ HAL_21064_PCR->IrqStatusTable[Irq].Irql = PASSIVE_LEVEL;
+ HAL_21064_PCR->IrqStatusTable[Irq].Vector = PASSIVE_VECTOR;
+ HAL_21064_PCR->IrqStatusTable[Irq].Priority = 0;
+ }
+
+ HalpUpdate21064PriorityTable();
+
+ //
+ // Write IrqlMask table entries for the Software Subtable.
+ //
+
+ Index = IRQLMASK_SFW_SUBTABLE_21064;
+
+ PCR->IrqlMask[Index].IrqlTableIndex = PASSIVE_LEVEL;
+ PCR->IrqlMask[Index].IDTIndex = PASSIVE_VECTOR;
+ Index += 1;
+
+ PCR->IrqlMask[Index].IrqlTableIndex = APC_LEVEL;
+ PCR->IrqlMask[Index].IDTIndex = APC_VECTOR;
+ Index += 1;
+
+ PCR->IrqlMask[Index].IrqlTableIndex = DISPATCH_LEVEL;
+ PCR->IrqlMask[Index].IDTIndex = DISPATCH_VECTOR;
+ Index += 1;
+
+ PCR->IrqlMask[Index].IrqlTableIndex = DISPATCH_LEVEL;
+ PCR->IrqlMask[Index].IDTIndex = DISPATCH_VECTOR;
+
+ //
+ // Write the IrqlMask table entries for the Performance Counter Subtable.
+ //
+
+ Index = IRQLMASK_PC_SUBTABLE_21064;
+
+ PCR->IrqlMask[Index].IrqlTableIndex = PASSIVE_LEVEL;
+ PCR->IrqlMask[Index].IDTIndex = PASSIVE_VECTOR;
+ Index += 1;
+
+ PCR->IrqlMask[Index].IrqlTableIndex = PROFILE_LEVEL;
+ PCR->IrqlMask[Index].IDTIndex = PC0_VECTOR;
+ Index += 1;
+
+ PCR->IrqlMask[Index].IrqlTableIndex = PROFILE_LEVEL;
+ PCR->IrqlMask[Index].IDTIndex = PC1_VECTOR;
+ Index += 1;
+
+ PCR->IrqlMask[Index].IrqlTableIndex = PROFILE_LEVEL;
+ PCR->IrqlMask[Index].IDTIndex = PC1_VECTOR;
+
+ return;
+
+}
+
+VOID
+HalpUpdate21064PriorityTable(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function updates the Irql Mask Table in the PCR of the current
+ processor. It is called whenever an interrupt is enabled or disabled.
+ The source of the data used to update the table is the global
+ IrqStatusTable.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG InterruptMask;
+ EV4Irq Irq;
+ KIRQL Irql;
+ ULONG IrqlMaskIndex;
+ UCHAR Priority;
+ ULONG Vector;
+
+ //
+ // Cycle through each entry of the interrupt mask table for the
+ // hardware entries. For each entry, compute the highest priority
+ // entry that could be asserted for the mask entry and is enabled.
+ // The priority is determined first by Irql level, higher Irql
+ // indicates higher priority, and then, if there are multiple
+ // enabled, asserted interrupts of the same Irql, by a relative
+ // priority that was assigned by the caller when the interrupt
+ // was enabled.
+ //
+
+ for( InterruptMask=0;
+ InterruptMask < IRQLMASK_HDW_SUBTABLE_21064_ENTRIES;
+ InterruptMask++ ){
+
+ Vector = PASSIVE_VECTOR;
+ Irql = PASSIVE_LEVEL;
+ Priority = 0;
+
+ //
+ // Check if each Irq is asserted and enabled for this interrupt
+ // mask.
+ //
+
+ for( Irq=Irq0; Irq<MaximumIrq; Irq++ ){
+ ULONG IrqMask = 1 << Irq;
+
+ if( (IrqMask & InterruptMask) &&
+ (HAL_21064_PCR->IrqStatusTable[Irq].Enabled == TRUE) &&
+ (HAL_21064_PCR->IrqStatusTable[Irq].Irql >= Irql) ){
+
+ //
+ // If the new Irq has a higher Irql than the highest
+ // currently selected or has a higher relative priority
+ // then this is the Irq to be selected if this mask
+ // pattern is selected.
+ //
+
+ if( (HAL_21064_PCR->IrqStatusTable[Irq].Irql > Irql) ||
+ (HAL_21064_PCR->IrqStatusTable[Irq].Priority > Priority) ){
+
+ Irql = HAL_21064_PCR->IrqStatusTable[Irq].Irql;
+ Priority = HAL_21064_PCR->IrqStatusTable[Irq].Priority;
+ Vector = HAL_21064_PCR->IrqStatusTable[Irq].Vector;
+
+ }
+
+ }
+ }
+
+ IrqlMaskIndex = IRQLMASK_HDW_SUBTABLE_21064 + InterruptMask;
+ PCR->IrqlMask[IrqlMaskIndex].IrqlTableIndex = Irql;
+ PCR->IrqlMask[IrqlMaskIndex].IDTIndex = (USHORT)Vector;
+ }
+}
+
+VOID
+HalpDisable21064HardwareInterrupt(
+ IN ULONG Irq
+ )
+/*++
+
+Routine Description:
+
+ This routine disables the interrupt connected to the specified Irq
+ pin on the 21064.
+
+Arguments:
+
+ Irq - Supplies the number of the Irq pin for the interrupt that is disabled.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ KIRQL IrqlIndex;
+ PIETEntry_21064 IetEntry;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ IetEntry = (PIETEntry_21064)(&PCR->IrqlTable);
+ IrqlIndex = PASSIVE_LEVEL;
+
+ //
+ // Update the enable table for all the Irqls such that the interrupt
+ // is disabled.
+ //
+
+ while( IrqlIndex <= HIGH_LEVEL ){
+
+ switch( Irq ){
+
+ case Irq0:
+
+ IetEntry[IrqlIndex].Irq0Enable = 0;
+ break;
+
+ case Irq1:
+
+ IetEntry[IrqlIndex].Irq1Enable = 0;
+ break;
+
+ case Irq2:
+
+ IetEntry[IrqlIndex].Irq2Enable = 0;
+ break;
+
+ case Irq3:
+
+ IetEntry[IrqlIndex].Irq3Enable = 0;
+ break;
+
+ case Irq4:
+
+ IetEntry[IrqlIndex].Irq4Enable = 0;
+ break;
+
+ case Irq5:
+
+ IetEntry[IrqlIndex].Irq5Enable = 0;
+ break;
+
+
+ } //end switch( Irq )
+
+ IrqlIndex++;
+
+ } //end while IrqlIndex <= HIGH_LEVEL
+
+ //
+ // Update the Irq status table and reflect the changes in the
+ // PCR IrqlMask table.
+ //
+
+ HAL_21064_PCR->IrqStatusTable[Irq].Enabled = FALSE;
+
+ //
+ // Alert the PAL that the enable table has changed so that it can
+ // reload the new values.
+ //
+
+ HalpCachePcrValues();
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+
+}
+
+
+VOID
+HalpDisable21064SoftwareInterrupt(
+ IN KIRQL Irql
+ )
+/*++
+
+Routine Description:
+
+ This routine disables the indicated software interrupt level.
+
+Arguments:
+
+ Irql - Supplies the software interrupt level to disable (APC_LEVEL or
+ DISPATCH_LEVEL).
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ PIETEntry_21064 IetEntry;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ IetEntry = (PIETEntry_21064)(&PCR->IrqlTable);
+
+ switch( Irql ){
+
+ //
+ // APC Interrupt level.
+ //
+
+ case APC_LEVEL:
+
+ IetEntry[PASSIVE_LEVEL].ApcEnable = 0;
+ break;
+
+ //
+ // DPC Interrupt level.
+ //
+
+ case DISPATCH_LEVEL:
+
+ IetEntry[PASSIVE_LEVEL].DispatchEnable = 0;
+ IetEntry[APC_LEVEL].DispatchEnable = 0;
+ break;
+
+ //
+ // Unrecognized software interrupt level.
+ //
+
+ default:
+
+ NOTHING;
+
+#if HALDBG
+
+ DbgPrint( "HalpDisable21064SoftwareInterrupt, Bad software level= %x\n",
+ Irql );
+
+#endif //HALDBG
+
+ }
+
+ //
+ // Alert the PAL that the enable table has changed so that it can
+ // reload the new values.
+ //
+
+ HalpCachePcrValues();
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+
+VOID
+HalpDisable21064PerformanceInterrupt(
+ IN ULONG Vector
+ )
+/*++
+
+Routine Description:
+
+ This routine disables the specified performance counter interrupt.
+
+Arguments:
+
+ Vector - Supplies the interrupt vector number of the performance counter
+ interrupt which is disabled.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ KIRQL IrqlIndex;
+ PIETEntry_21064 IetEntry;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ IetEntry = (PIETEntry_21064)(&PCR->IrqlTable);
+ IrqlIndex = PASSIVE_LEVEL;
+
+ //
+ // Update the enable table for all the Irqls such that the interrupt
+ // is disabled.
+ //
+
+ while( IrqlIndex <= HIGH_LEVEL ){
+
+ switch( Vector ){
+
+ case PC0_VECTOR:
+ case PC0_SECONDARY_VECTOR:
+
+ IetEntry[IrqlIndex].PerformanceCounter0Enable = 0;
+ break;
+
+ case PC1_VECTOR:
+ case PC1_SECONDARY_VECTOR:
+
+ IetEntry[IrqlIndex].PerformanceCounter1Enable = 0;
+ break;
+
+
+ } //end switch( Vector )
+
+ IrqlIndex++;
+
+ } //end while IrqlIndex <= HIGH_LEVEL
+
+ //
+ // Alert the PAL that the enable table has changed so that it can
+ // reload the new values.
+ //
+
+ HalpCachePcrValues();
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+VOID
+HalpDisable21064CorrectableInterrupt(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine disables the correctable read error interrupt.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ KIRQL IrqlIndex;
+ PIETEntry_21064 IetEntry;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ IetEntry = (PIETEntry_21064)(&PCR->IrqlTable);
+ IrqlIndex = PASSIVE_LEVEL;
+
+ //
+ // Update the enable table for all the Irqls such that the interrupt
+ // is disabled.
+ //
+
+ while( IrqlIndex <= HIGH_LEVEL ){
+
+ IetEntry[IrqlIndex].CorrectableReadEnable = 0;
+
+ IrqlIndex++;
+
+ } //end while IrqlIndex <= HIGH_LEVEL
+
+ //
+ // Alert the PAL that the enable table has changed so that it can
+ // reload the new values.
+ //
+
+ HalpCachePcrValues();
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+VOID
+HalpEnable21064HardwareInterrupt (
+ IN ULONG Irq,
+ IN KIRQL Irql,
+ IN ULONG Vector,
+ IN UCHAR Priority
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the specified system interrupt.
+
+Arguments:
+
+ Irq - Supplies the IRQ pin number of the interrupt that is enabled.
+
+ Irql - Supplies the Irql of the interrupting source.
+
+ Vector - Supplies the interrupt vector for the enabled interrupt.
+
+ Priority - Supplies the relative priority of the interrupt in comparison
+ with other Irqs of the same Irql.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL IrqlIndex;
+ PIETEntry_21064 IetEntry;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+
+ IetEntry = (PIETEntry_21064)(&PCR->IrqlTable);
+ IrqlIndex = PASSIVE_LEVEL;
+
+ //
+ // Update the enable table for each Irql that the interrupt should
+ // be enabled.
+ //
+
+ while( IrqlIndex < Irql ){
+
+ switch( Irq ){
+
+ case Irq0:
+
+ IetEntry[IrqlIndex].Irq0Enable = 1;
+ break;
+
+ case Irq1:
+
+ IetEntry[IrqlIndex].Irq1Enable = 1;
+ break;
+
+ case Irq2:
+
+ IetEntry[IrqlIndex].Irq2Enable = 1;
+ break;
+
+ case Irq3:
+
+ IetEntry[IrqlIndex].Irq3Enable = 1;
+ break;
+
+ case Irq4:
+
+ IetEntry[IrqlIndex].Irq4Enable = 1;
+ break;
+
+ case Irq5:
+
+ IetEntry[IrqlIndex].Irq5Enable = 1;
+ break;
+
+ } // end switch( Vector )
+
+ IrqlIndex++;
+
+ } //end while IrqlIndex < Irql
+
+ //
+ // Populate the interrupt status table and then update the Irql Mask
+ // table.
+ //
+
+ HAL_21064_PCR->IrqStatusTable[Irq].Enabled = TRUE;
+ HAL_21064_PCR->IrqStatusTable[Irq].Vector = Vector;
+ HAL_21064_PCR->IrqStatusTable[Irq].Irql = Irql;
+ HAL_21064_PCR->IrqStatusTable[Irq].Priority = Priority;
+
+ HalpUpdate21064PriorityTable();
+
+ //
+ // Alert the PAL that the enable table has changed so that it can
+ // reload the new values.
+ //
+
+ HalpCachePcrValues();
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+
+VOID
+HalpEnable21064SoftwareInterrupt(
+ IN KIRQL Irql
+ )
+/*++
+
+Routine Description:
+
+ This routine enables the indicated software interrupt level.
+
+Arguments:
+
+ Irql - Supplies the software interrupt level to enable (APC_LEVEL or
+ DISPATCH_LEVEL).
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ PIETEntry_21064 IetEntry;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ IetEntry = (PIETEntry_21064)(&PCR->IrqlTable);
+
+ switch( Irql ){
+
+ //
+ // APC Interrupt level.
+ //
+
+ case APC_LEVEL:
+
+ IetEntry[PASSIVE_LEVEL].ApcEnable = 1;
+ break;
+
+ //
+ // DPC Interrupt level.
+ //
+
+ case DISPATCH_LEVEL:
+
+ IetEntry[PASSIVE_LEVEL].DispatchEnable = 1;
+ IetEntry[APC_LEVEL].DispatchEnable = 1;
+ break;
+
+ //
+ // Unrecognized software interrupt level.
+ //
+
+ default:
+
+ NOTHING;
+
+#if HALDBG
+
+ DbgPrint( "HalpEnable21064SoftwareInterrupt, Bad software level= %x\n",
+ Irql );
+
+#endif //HALDBG
+
+ }
+
+ //
+ // Alert the PAL that the enable table has changed so that it can
+ // reload the new values.
+ //
+
+ HalpCachePcrValues();
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+
+}
+
+
+VOID
+HalpEnable21064PerformanceInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the specified performance counter interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the performance counter interrupt that is
+ enabled.
+
+ Irql - Supplies the Irql of the performance counter interrupt.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL IrqlIndex;
+ PIETEntry_21064 IetEntry;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+
+ IetEntry = (PIETEntry_21064)(&PCR->IrqlTable);
+ IrqlIndex = PASSIVE_LEVEL;
+
+ //
+ // Update the enable table for each Irql that the interrupt should
+ // be enabled.
+ //
+
+ while( IrqlIndex < Irql ){
+
+ switch( Vector ){
+
+ case PC0_VECTOR:
+ case PC0_SECONDARY_VECTOR:
+
+ IetEntry[IrqlIndex].PerformanceCounter0Enable = 1;
+ break;
+
+ case PC1_VECTOR:
+ case PC1_SECONDARY_VECTOR:
+
+ IetEntry[IrqlIndex].PerformanceCounter1Enable = 1;
+ break;
+
+ } // end switch( Vector )
+
+ IrqlIndex++;
+
+ } //end while IrqlIndex < Irql
+
+ //
+ // Alert the PAL that the enable table has changed so that it can
+ // reload the new values.
+ //
+
+ HalpCachePcrValues();
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+VOID
+HalpEnable21064CorrectableInterrupt (
+ IN KIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the correctable read error interrupt.
+
+Arguments:
+
+ Irql - Supplies the Irql of the correctable read error interrupt.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL IrqlIndex;
+ PIETEntry_21064 IetEntry;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+
+ IetEntry = (PIETEntry_21064)(&PCR->IrqlTable);
+ IrqlIndex = PASSIVE_LEVEL;
+
+ //
+ // Update the enable table for each Irql that the interrupt should
+ // be enabled.
+ //
+
+ while( IrqlIndex < Irql ){
+
+ IetEntry[IrqlIndex].CorrectableReadEnable = 1;
+
+ IrqlIndex++;
+
+ } //end while IrqlIndex < Irql
+
+ //
+ // Alert the PAL that the enable table has changed so that it can
+ // reload the new values.
+ //
+
+ HalpCachePcrValues();
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+
+ULONG
+HalpGet21064PerformanceVector(
+ IN ULONG BusInterruptLevel,
+ OUT PKIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified performance counter interrupt.
+
+Arguments:
+
+ BusInterruptLevel - Supplies the performance counter number.
+
+ Irql - Returns the system request priority.
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+
+{
+
+ //
+ // Handle the special internal bus defined for the processor itself
+ // and used to control the performance counters in the 21064.
+ //
+
+ *Irql = PROFILE_LEVEL;
+
+ switch( BusInterruptLevel ){
+
+ //
+ // Performance Counter 0
+ //
+
+ case 0:
+
+ return PC0_SECONDARY_VECTOR;
+
+ //
+ // Performance Counter 1
+ //
+
+ case 1:
+
+ return PC1_SECONDARY_VECTOR;
+
+ } //end switch( BusInterruptLevel )
+
+ //
+ // Unrecognized.
+ //
+
+ *Irql = 0;
+ return 0;
+
+}
+
diff --git a/private/ntos/nthals/halflex/alpha/ev4ints.s b/private/ntos/nthals/halflex/alpha/ev4ints.s
new file mode 100644
index 000000000..08fdaadc0
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/ev4ints.s
@@ -0,0 +1,300 @@
+//++
+//
+// Copyright (C) 1994,1995 Microsoft Corporation
+//
+// Module Name:
+//
+// ev4ints.s
+//
+// Abstract:
+//
+// This module implements EV4-specific interrupt handlers.
+// (the performance counters)
+//
+//
+// Environment:
+//
+// Kernel mode only.
+//
+//
+//--
+#include "halalpha.h"
+
+#define PC0_SECONDARY_VECTOR 11
+#define PC1_SECONDARY_VECTOR 13
+#define PcProfileCount0 PcHalReserved+8
+#define PcProfileCount1 PcProfileCount0+4
+#define PcProfileCountReload0 PcProfileCount1+4
+#define PcProfileCountReload1 PcProfileCountReload0+4
+
+ .struct 0
+ .space 8 // reserved for alignment
+PrRa: .space 8 // space for return address
+PrFrameLength: //
+
+ SBTTL("Performance Counter 0 Interrupt")
+//++
+//
+// VOID
+// Halp21064PerformanceCounter0Interrupt
+// )
+//
+// Routine Description:
+//
+// This function is executed as the result of an interrupt from the
+// internal microprocessor performance counter 0. The interrupt
+// may be used to signal the completion of a profile event.
+// If profiling is current active, the function determines if the
+// profile interval has expired and if so dispatches to the standard
+// system routine to update the system profile time. If profiling
+// is not active then the function performs a secondary dispatch for
+// performance counter 0.
+//
+// Arguments:
+//
+// TrapFrame (fp/s6) - Supplies a pointer to the trap frame for
+// the interrupt.
+//
+// Return Value:
+//
+// TRUE is returned.
+//
+//--
+
+ NESTED_ENTRY(Halp21064PerformanceCounter0Interrupt, PrFrameLength, zero )
+
+ lda sp, -PrFrameLength(sp) // allocate a stack frame
+ stq ra, PrRa(sp) // save the return address
+
+ PROLOGUE_END //
+
+ call_pal rdpcr // v0 = pcr base address
+
+ ldl t0, PcProfileCount0(v0) // capture the current profile count
+ beq t0, 20f // if eq, profiling not active
+
+//
+// Profiling is active. Decrement the interval count and if it has
+// reached zero then call the kernel profile routine.
+//
+
+ subl t0, 1, t0 // decrement the interval count
+ bne t0, 10f // if ne, interval has not expired
+
+//
+// The profile interval has expired. Reset the profile interval count
+// and process the profile interrupt.
+//
+
+ ldl t0, PcProfileCountReload0(v0) // get the new tick count
+ stl t0, PcProfileCount0(v0) // reset the profile interval count
+
+ ldl a1, Halp21064ProfileSource0
+ bis fp, zero, a0 // pass trap frame pointer
+ ldl t1, __imp_KeProfileInterruptWithSource
+ jsr ra, (t1) // process the profile interrupt
+
+ br zero, 40f // common return
+
+//
+// The profile interval has not expired. Update the decremented count.
+//
+
+10:
+ stl t0, PcProfileCount0(v0) // update profile interval count
+ br zero, 40f // common return
+
+//
+// Profiling is not active. Therefore, this interrupt was caused by
+// a performance counter driver. Deliver a secondary dispatch.
+//
+
+20:
+
+ ldil a0, PC0_SECONDARY_VECTOR // get IDT vector for secondary
+ s4addl a0, v0, a0 // a0 = PCR + IDT index
+ ldl a0, PcInterruptRoutine(a0) // get service routine address
+ jsr ra, (a0) // call interrupt service routine
+
+//
+// Setup for return.
+//
+
+40:
+ ldil v0, TRUE // set return value = TRUE
+ ldq ra, PrRa(sp) // restore return address
+ lda sp, PrFrameLength(sp) // deallocate the stack frame
+ ret zero, (ra) // return
+
+ .end Halp21064PerformanceCounter0Interrupt
+
+
+ SBTTL("Performance Counter 1 Interrupt")
+//++
+//
+// VOID
+// Halp21064PerformanceCounter1Interrupt
+// )
+//
+// Routine Description:
+//
+// This function is executed as the result of an interrupt from the
+// internal microprocessor performance counter 1. The interrupt
+// may be used to signal the completion of a profile event.
+// If profiling is current active, the function determines if the
+// profile interval has expired and if so dispatches to the standard
+// system routine to update the system profile time. If profiling
+// is not active then the function performs a secondary dispatch for
+// performance counter 1.
+//
+// Arguments:
+//
+// TrapFrame (fp/s6) - Supplies a pointer to the trap frame for
+// the interrupt.
+//
+// Return Value:
+//
+// TRUE is returned.
+//
+//--
+
+ NESTED_ENTRY(Halp21064PerformanceCounter1Interrupt, PrFrameLength, zero )
+
+ lda sp, -PrFrameLength(sp) // allocate a stack frame
+ stq ra, PrRa(sp) // save the return address
+
+ PROLOGUE_END //
+
+ call_pal rdpcr // v0 = pcr base address
+
+ ldl t0, PcProfileCount1(v0) // capture the current profile count
+ beq t0, 20f // if eq, profiling not active
+
+//
+// Profiling is active. Decrement the interval count and if it has
+// reached zero then call the kernel profile routine.
+//
+
+ subl t0, 1, t0 // decrement the interval count
+ bne t0, 10f // if ne, interval has not expired
+
+//
+// The profile interval has expired. Reset the profile interval count
+// and process the profile interrupt.
+//
+
+ ldl t0, PcProfileCountReload1(v0) // get the new tick count
+ stl t0, PcProfileCount1(v0) // reset the profile interval count
+
+ ldl a1, Halp21064ProfileSource1
+ bis fp, zero, a0 // pass trap frame pointer
+ ldl t1, __imp_KeProfileInterruptWithSource
+ jsr ra, (t1) // process the profile interrupt
+
+ br zero, 40f // common return
+
+//
+// The profile interval has not expired. Update the decremented count.
+//
+
+10:
+ stl t0, PcProfileCount1(v0) // update profile interval count
+ br zero, 40f // common return
+
+//
+// Profiling is not active. Therefore, this interrupt was caused by
+// a performance counter driver. Deliver a secondary dispatch.
+//
+
+20:
+
+ ldil a0, PC1_SECONDARY_VECTOR // get IDT vector for secondary
+ s4addl a0, v0, a0 // a0 = PCR + IDT index
+ ldl a0, PcInterruptRoutine(a0) // get service routine address
+ jsr ra, (a0) // call interrupt service routine
+
+//
+// Setup for return.
+//
+
+40:
+ ldil v0, TRUE // set return value = TRUE
+ ldq ra, PrRa(sp) // restore return address
+ lda sp, PrFrameLength(sp) // deallocate the stack frame
+ ret zero, (ra) // return
+
+ .end Halp21064PerformanceCounter1Interrupt
+
+//++
+//
+// VOID
+// Halp21064WritePerformanceCounter(
+// IN ULONG PerformanceCounter,
+// IN BOOLEAN Enable,
+// IN ULONG MuxControl OPTIONAL,
+// IN ULONG EventCount OPTIONAL
+// )
+//
+// Routine Description:
+//
+// Write the specified microprocessor internal performance counter.
+//
+// Arguments:
+//
+// PerformanceCounter(a0) - Supplies the number of the performance counter
+// to write.
+//
+// Enable(a1) - Supplies a boolean that indicates if the performance
+// counter should be enabled or disabled.
+//
+// MuxControl(a2) - Supplies the mux control value which selects which
+// type of event to count when the counter is enabled.
+//
+// EventCount(a3) - Supplies the event interval when the counter is
+// enabled.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(Halp21064WritePerformanceCounter)
+
+ call_pal wrperfmon // write the counter
+
+ ret zero, (ra) // return
+
+ .end Halp21064WritePerformanceCounter
+
+//++
+//
+// VOID
+// Halp21064ClearLockRegister(
+// PVOID LockAddress
+// )
+//
+// Routine Description:
+//
+// This function is called on every interrupt to clear the lock bit.
+//
+// Arguments:
+//
+// ClearLockAddress(a0) - Address in which to perform the conditional store.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(Halp21064ClearLockRegister)
+
+ mb // Force all previous write off chip
+ stl_c zero, 0x0(a0) // Clear the lock register
+ mb // Force the write to clear the lock register off chip
+ ret zero, (ra) // return
+
+ .end Halp21064ClearLockRegister
+
+
diff --git a/private/ntos/nthals/halflex/alpha/ev4prof.c b/private/ntos/nthals/halflex/alpha/ev4prof.c
new file mode 100644
index 000000000..53dc896c6
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/ev4prof.c
@@ -0,0 +1,585 @@
+/*++
+
+Copyright (C) 1994,1995 Digital Equipment Corporation
+
+Module Name:
+
+ ev4prof.c
+
+Abstract:
+
+ This module implements the Profile Counter using the performance
+ counters within the EV4 core. This module is appropriate for all
+ machines based on microprocessors using the EV4 core.
+
+ N.B. - This module assumes that all processors in a multiprocessor
+ system are running the microprocessor at the same clock speed.
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+#include "halp.h"
+#include "axp21064.h"
+
+
+//
+// Define space in the HAL-reserved part of the PCR structure for each
+// performance counter's interval count
+//
+// Note that ev4ints.s depends on these positions in the PCR.
+//
+#define PCRProfileCount ((PULONG)(HAL_21064_PCR->ProfileCount.ProfileCount))
+#define PCRProfileCountReload ((PULONG)(&HAL_21064_PCR->ProfileCount.ProfileCountReload))
+
+
+//
+// Define the currently selected profile source for each counter
+//
+KPROFILE_SOURCE Halp21064ProfileSource0;
+KPROFILE_SOURCE Halp21064ProfileSource1;
+
+#define INTERVAL_DELTA (10)
+
+//
+// Define the mapping between possible profile sources and the
+// CPU-specific settings.
+//
+typedef struct _HALP_PROFILE_MAPPING {
+ BOOLEAN Supported;
+ ULONG MuxControl;
+ ULONG Counter;
+ ULONG EventCount;
+ ULONG NumberOfTicks;
+} HALP_PROFILE_MAPPING, *PHALP_PROFILE_MAPPING;
+
+HALP_PROFILE_MAPPING Halp21064ProfileMapping[ProfileMaximum] =
+ {
+ {TRUE, Ev4TotalCycles, Ev4PerformanceCounter0, Ev4CountEvents2xx12, 10},
+ {FALSE, 0, 0, 0, 0},
+ {TRUE, Ev4TotalIssues, Ev4PerformanceCounter0, Ev4CountEvents2xx16, 10},
+ {TRUE, Ev4PipelineDry, Ev4PerformanceCounter0, Ev4CountEvents2xx16, 10},
+ {TRUE, Ev4LoadInstruction, Ev4PerformanceCounter0, Ev4CountEvents2xx12, 10},
+ {TRUE, Ev4PipelineFrozen, Ev4PerformanceCounter0, Ev4CountEvents2xx16, 10},
+ {TRUE, Ev4BranchInstructions, Ev4PerformanceCounter0, Ev4CountEvents2xx12, 10},
+ {TRUE, Ev4TotalNonIssues, Ev4PerformanceCounter0, Ev4CountEvents2xx16, 10},
+ {TRUE, Ev4DcacheMiss, Ev4PerformanceCounter1, Ev4CountEvents2xx12, 10},
+ {TRUE, Ev4IcacheMiss, Ev4PerformanceCounter1, Ev4CountEvents2xx12, 10},
+ {FALSE, 0, 0, 0, 0},
+ {TRUE, Ev4BranchMispredicts, Ev4PerformanceCounter1, Ev4CountEvents2xx12, 10},
+ {TRUE, Ev4StoreInstructions, Ev4PerformanceCounter1, Ev4CountEvents2xx12, 10},
+ {TRUE, Ev4FPInstructions, Ev4PerformanceCounter1, Ev4CountEvents2xx12, 10},
+ {TRUE, Ev4IntegerOperate, Ev4PerformanceCounter1, Ev4CountEvents2xx12, 10},
+ {TRUE, Ev4DualIssues, Ev4PerformanceCounter1, Ev4CountEvents2xx12, 10},
+ {FALSE, 0, 0, 0, 0},
+ {FALSE, 0, 0, 0, 0},
+ {TRUE, Ev4PalMode, Ev4PerformanceCounter0, Ev4CountEvents2xx16, 10},
+ {TRUE, Ev4TotalCycles, Ev4PerformanceCounter0, Ev4CountEvents2xx16, 10},
+ {FALSE, 0, 0, 0, 0},
+ {FALSE, 0, 0, 0, 0}
+ };
+
+BOOLEAN
+HalQueryProfileInterval(
+ IN KPROFILE_SOURCE Source
+ );
+
+NTSTATUS
+HalSetProfileSourceInterval(
+ IN KPROFILE_SOURCE ProfileSource,
+ IN OUT ULONG *Interval
+ );
+
+
+
+NTSTATUS
+Halp21064ProfileSourceInformation (
+ OUT PVOID Buffer,
+ IN ULONG BufferLength,
+ OUT PULONG ReturnedLength
+ )
+/*++
+
+Routine Description:
+
+ Returns the HAL_PROFILE_SOURCE_INFORMATION for this processor.
+
+Arguments:
+
+ Buffer - output buffer
+ BufferLength - length of buffer on input
+ ReturnedLength - The length of data returned
+
+Return Value:
+
+ STATUS_SUCCESS
+ STATUS_BUFFER_TOO_SMALL - The ReturnedLength contains the buffersize
+ currently needed.
+
+--*/
+{
+ PHAL_PROFILE_SOURCE_INFORMATION SourceInfo;
+ NTSTATUS Status;
+
+
+ if (BufferLength != sizeof(HAL_PROFILE_SOURCE_INFORMATION)) {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ return Status;
+ }
+
+ SourceInfo = (PHAL_PROFILE_SOURCE_INFORMATION)Buffer;
+ SourceInfo->Supported = HalQueryProfileInterval(SourceInfo->Source);
+
+ if (SourceInfo->Supported) {
+ SourceInfo->Interval =
+ Halp21064ProfileMapping[SourceInfo->Source].EventCount *
+ Halp21064ProfileMapping[SourceInfo->Source].NumberOfTicks;
+ if (SourceInfo->Source == ProfileTotalIssues) {
+ //
+ // Convert total issues/2 back into total issues
+ //
+ SourceInfo->Interval = SourceInfo->Interval * 2;
+ }
+ }
+
+ Status = STATUS_SUCCESS;
+ return Status;
+}
+
+NTSTATUS
+Halp21064ProfileSourceInterval (
+ OUT PVOID Buffer,
+ IN ULONG BufferLength
+ )
+/*++
+
+Routine Description:
+
+ Returns the HAL_PROFILE_SOURCE_INTERVAL for this processor.
+
+Arguments:
+
+ Buffer - output buffer
+ BufferLength - length of buffer on input
+
+Return Value:
+
+ STATUS_SUCCESS
+ STATUS_BUFFER_TOO_SMALL - The ReturnedLength contains the buffersize
+ currently needed.
+
+--*/
+{
+ PHAL_PROFILE_SOURCE_INTERVAL Interval;
+ NTSTATUS Status;
+
+
+ if (BufferLength != sizeof(HAL_PROFILE_SOURCE_INTERVAL)) {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ return Status;
+ }
+
+ Interval = (PHAL_PROFILE_SOURCE_INTERVAL)Buffer;
+ Status = HalSetProfileSourceInterval(Interval->Source,
+ &Interval->Interval);
+ return Status;
+}
+
+VOID
+Halp21064InitializeProfiler(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is called during initialization to initialize profiling
+ for each processor in the system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PKINTERRUPT InterruptObject;
+ KIRQL Irql;
+ PKPRCB Prcb = PCR->Prcb;
+ ULONG Vector;
+
+ //
+ // Establish the profile interrupt as the interrupt handler for
+ // all performance counter interrupts.
+ //
+
+ PCR->InterruptRoutine[PC0_VECTOR] = Halp21064PerformanceCounter0Interrupt;
+ PCR->InterruptRoutine[PC1_VECTOR] = Halp21064PerformanceCounter1Interrupt;
+
+ return;
+
+}
+
+
+BOOLEAN
+Hal21064QueryProfileInterval(
+ IN KPROFILE_SOURCE Source
+ )
+
+/*++
+
+Routine Description:
+
+ Given a profile source, returns whether or not that source is
+ supported.
+
+Arguments:
+
+ Source - Supplies the profile source
+
+Return Value:
+
+ TRUE - Profile source is supported
+
+ FALSE - Profile source is not supported
+
+--*/
+
+{
+ if (Source > (sizeof(Halp21064ProfileMapping)/sizeof(HALP_PROFILE_MAPPING))) {
+ return(FALSE);
+ }
+
+ return(Halp21064ProfileMapping[Source].Supported);
+}
+
+
+NTSTATUS
+Hal21064SetProfileSourceInterval(
+ IN KPROFILE_SOURCE ProfileSource,
+ IN OUT ULONG *Interval
+ )
+
+/*++
+
+Routine Description:
+
+ Sets the profile interval for a specified profile source
+
+Arguments:
+
+ ProfileSource - Supplies the profile source
+
+ Interval - Supplies the specified profile interval
+ Returns the actual profile interval
+
+Return Value:
+
+ NTSTATUS
+
+--*/
+
+{
+ ULONG FastTickPeriod;
+ ULONG SlowTickPeriod;
+ ULONG TickPeriod;
+ ULONGLONG CountEvents;
+ ULONG FastCountEvents;
+ ULONG SlowCountEvents;
+ ULONGLONG TempInterval;
+
+ if (!HalQueryProfileInterval(ProfileSource)) {
+ return(STATUS_NOT_IMPLEMENTED);
+ }
+
+ if (ProfileSource == ProfileTime) {
+
+ //
+ // Convert the clock tick period (in 100ns units ) into
+ // a cycle count period
+ //
+
+ CountEvents = ((ULONGLONG)(*Interval) * 100000) / PCR->CycleClockPeriod;
+ } else if (ProfileSource == ProfileTotalIssues) {
+
+ //
+ // Convert the total issue events into the wonky
+ // total issues/2 form implemented by EV4.
+ //
+
+ CountEvents = (ULONGLONG)(*Interval / 2);
+ } else {
+ CountEvents = (ULONGLONG)*Interval;
+ }
+
+ if (Halp21064ProfileMapping[ProfileSource].Counter == Ev4PerformanceCounter1) {
+ FastCountEvents = Ev4CountEvents2xx8;
+ SlowCountEvents = Ev4CountEvents2xx12;
+ } else {
+ FastCountEvents = Ev4CountEvents2xx12;
+ SlowCountEvents = Ev4CountEvents2xx16;
+ }
+
+ //
+ // Limit the interval to the smallest interval we can time.
+ //
+ if (CountEvents < FastCountEvents) {
+ CountEvents = (ULONGLONG)FastCountEvents;
+ }
+
+ //
+ // Assume we will use the fast event count
+ //
+ Halp21064ProfileMapping[ProfileSource].EventCount = FastCountEvents;
+ Halp21064ProfileMapping[ProfileSource].NumberOfTicks =
+ (ULONG)((CountEvents + FastCountEvents - 1) / FastCountEvents);
+
+ //
+ // See if we can successfully use the slower period. If the requested
+ // interval is greater than the slower tick period and the difference
+ // between the requested interval and the interval that we can deliver
+ // with the slower clock is acceptable, then use the slower clock.
+ // We define an acceptable difference as a difference of less than
+ // INTERVAL_DELTA of the requested interval.
+ //
+ if (CountEvents > SlowCountEvents) {
+ ULONG NewInterval;
+
+ NewInterval = (ULONG)(((CountEvents + SlowCountEvents-1) /
+ SlowCountEvents) * SlowCountEvents);
+ if (((NewInterval - CountEvents) * 100 / CountEvents) < INTERVAL_DELTA) {
+ Halp21064ProfileMapping[ProfileSource].EventCount = SlowCountEvents;
+ Halp21064ProfileMapping[ProfileSource].NumberOfTicks = NewInterval / SlowCountEvents;
+ }
+ }
+
+ *Interval = Halp21064ProfileMapping[ProfileSource].EventCount *
+ Halp21064ProfileMapping[ProfileSource].NumberOfTicks;
+
+ if (ProfileSource == ProfileTime) {
+ //
+ // Convert cycle count back into 100ns clock ticks
+ //
+ // Use 64-bit integer to prevent overflow.
+ //
+ TempInterval = (ULONGLONG)(*Interval) * (ULONGLONG)(PCR->CycleClockPeriod);
+ *Interval = (ULONG)(TempInterval / 100000);
+ } else if (ProfileSource == ProfileTotalIssues) {
+ //
+ // Convert issues/2 count back into issues
+ //
+ TempInterval = (ULONGLONG)(*Interval) * 2;
+ *Interval = (ULONG)TempInterval;
+ }
+ return(STATUS_SUCCESS);
+}
+
+
+ULONG
+Hal21064SetProfileInterval (
+ IN ULONG Interval
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the profile interrupt interval.
+
+Arguments:
+
+ Interval - Supplies the desired profile interval in 100ns units.
+
+Return Value:
+
+ The actual profile interval.
+
+--*/
+
+{
+ ULONG NewInterval;
+
+ NewInterval = Interval;
+ HalSetProfileSourceInterval(ProfileTime, &NewInterval);
+ return(NewInterval);
+}
+
+
+
+VOID
+Hal21064StartProfileInterrupt (
+ KPROFILE_SOURCE ProfileSource
+ )
+
+/*++
+
+Routine Description:
+
+ This routine turns on the profile interrupt.
+
+ N.B. This routine must be called at PROCLK_LEVEL while holding the
+ profile lock.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG PerformanceCounter;
+ ULONG MuxControl;
+ ULONG EventCount;
+
+ //
+ // Check input to see if we are turning on a source that is
+ // supported. If it is unsupported, just return.
+ //
+
+ if ((ProfileSource > (sizeof(Halp21064ProfileMapping)/sizeof(HALP_PROFILE_MAPPING))) ||
+ (!Halp21064ProfileMapping[ProfileSource].Supported)) {
+ return;
+ }
+
+ //
+ // Set the performance counter within the processor to begin
+ // counting total cycles.
+ //
+ PerformanceCounter = Halp21064ProfileMapping[ProfileSource].Counter;
+ MuxControl = Halp21064ProfileMapping[ProfileSource].MuxControl;
+
+ if (PerformanceCounter == Ev4PerformanceCounter0) {
+
+ Halp21064ProfileSource0 = ProfileSource;
+ EventCount = (Halp21064ProfileMapping[ProfileSource].EventCount == Ev4CountEvents2xx12) ?
+ Ev4EventCountHigh :
+ Ev4EventCountLow;
+ Halp21064WritePerformanceCounter( PerformanceCounter,
+ TRUE,
+ MuxControl,
+ EventCount );
+
+ PCRProfileCountReload[0] = Halp21064ProfileMapping[ProfileSource].NumberOfTicks;
+ PCRProfileCount[0] = Halp21064ProfileMapping[ProfileSource].NumberOfTicks;
+
+ //
+ // Enable the performance counter interrupt.
+ //
+
+ HalEnableSystemInterrupt ( PC0_VECTOR,
+ PROFILE_LEVEL,
+ LevelSensitive );
+
+
+ } else {
+
+ Halp21064ProfileSource1 = ProfileSource;
+ EventCount = (Halp21064ProfileMapping[ProfileSource].EventCount == Ev4CountEvents2xx12) ?
+ Ev4EventCountLow :
+ Ev4EventCountHigh;
+ Halp21064WritePerformanceCounter( PerformanceCounter,
+ TRUE,
+ MuxControl,
+ EventCount );
+
+ PCRProfileCountReload[1] = Halp21064ProfileMapping[ProfileSource].NumberOfTicks;
+ PCRProfileCount[1] = Halp21064ProfileMapping[ProfileSource].NumberOfTicks;
+
+ //
+ // Enable the performance counter interrupt.
+ //
+
+ HalEnableSystemInterrupt ( PC1_VECTOR,
+ PROFILE_LEVEL,
+ LevelSensitive );
+ }
+
+ return;
+}
+
+
+VOID
+Hal21064StopProfileInterrupt (
+ KPROFILE_SOURCE ProfileSource
+ )
+
+/*++
+
+Routine Description:
+
+ This routine turns off the profile interrupt.
+
+ N.B. This routine must be called at PROCLK_LEVEL while holding the
+ profile lock.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG PerformanceCounter;
+ ULONG Vector;
+
+ //
+ // Check input to see if we are turning off a source that is
+ // supported. If it is unsupported, just return.
+ //
+
+ if ((ProfileSource > (sizeof(Halp21064ProfileMapping)/sizeof(HALP_PROFILE_MAPPING))) ||
+ (!Halp21064ProfileMapping[ProfileSource].Supported)) {
+ return;
+ }
+
+ //
+ // Stop the performance counter from interrupting.
+ //
+
+ PerformanceCounter = Halp21064ProfileMapping[ProfileSource].Counter;
+ Halp21064WritePerformanceCounter( PerformanceCounter,
+ FALSE,
+ 0,
+ 0 );
+
+ //
+ // Disable the performance counter interrupt.
+ //
+ if (PerformanceCounter == Ev4PerformanceCounter0) {
+ HalDisableSystemInterrupt( PC0_VECTOR, PROFILE_LEVEL );
+
+ //
+ // Clear the current profile count. Can't clear value in PCR
+ // since a profile interrupt could be pending or in progress
+ // so clear the reload counter.
+ //
+
+ PCRProfileCountReload[0] = 0;
+ } else {
+ HalDisableSystemInterrupt( PC1_VECTOR, PROFILE_LEVEL );
+
+ //
+ // Clear the current profile count. Can't clear value in PCR
+ // since a profile interrupt could be pending or in progress
+ // so clear the reload counter.
+ //
+
+ PCRProfileCountReload[0] = 0;
+ }
+
+ return;
+}
+
diff --git a/private/ntos/nthals/halflex/alpha/ev5ints.s b/private/ntos/nthals/halflex/alpha/ev5ints.s
new file mode 100644
index 000000000..71319eb58
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/ev5ints.s
@@ -0,0 +1,397 @@
+//++
+//
+// Copyright (c) 1994 Microsoft Corporation
+//
+// Module Name:
+//
+// ev5ints.s
+//
+// Abstract:
+//
+// This module implements EV5-specific interrupt handlers.
+// (the performance counters)
+//
+// Author:
+//
+// John Vert (jvert) 15-Nov-1994
+// Steve Brooks 14-Feb-1994 (modified from ev4ints.s)
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+#include "halalpha.h"
+
+#define PC0_SECONDARY_VECTOR 11
+#define PC1_SECONDARY_VECTOR 13
+#define PC2_SECONDARY_VECTOR 16 // SjBfix. This is actually PC3_VECTOR
+#define PcProfileCount0 PcHalReserved+20
+#define PcProfileCount1 PcProfileCount0+4
+#define PcProfileCount2 PcProfileCount1+4
+#define PcProfileCountReload0 PcProfileCount2+4
+#define PcProfileCountReload1 PcProfileCountReload0+4
+#define PcProfileCountReload2 PcProfileCountReload1+4
+
+ .struct 0
+ .space 8 // reserved for alignment
+PrRa: .space 8 // space for return address
+PrFrameLength: //
+
+ SBTTL("Performance Counter 0 Interrupt")
+//++
+//
+// VOID
+// Halp21164PerformanceCounter0Interrupt
+// )
+//
+// Routine Description:
+//
+// This function is executed as the result of an interrupt from the
+// internal microprocessor performance counter 0. The interrupt
+// may be used to signal the completion of a profile event.
+// If profiling is current active, the function determines if the
+// profile interval has expired and if so dispatches to the standard
+// system routine to update the system profile time. If profiling
+// is not active then the function performs a secondary dispatch for
+// performance counter 0.
+//
+// Arguments:
+//
+// TrapFrame (fp/s6) - Supplies a pointer to the trap frame for
+// the interrupt.
+//
+// Return Value:
+//
+// TRUE is returned.
+//
+//--
+
+ NESTED_ENTRY(Halp21164PerformanceCounter0Interrupt, PrFrameLength, zero )
+
+ lda sp, -PrFrameLength(sp) // allocate a stack frame
+ stq ra, PrRa(sp) // save the return address
+
+ PROLOGUE_END //
+
+ call_pal rdpcr // v0 = pcr base address
+
+ ldl t0, PcProfileCount0(v0) // capture the current profile count
+ beq t0, 20f // if eq, profiling not active
+
+//
+// Profiling is active. Decrement the interval count and if it has
+// reached zero then call the kernel profile routine.
+//
+
+ subl t0, 1, t0 // decrement the interval count
+ bne t0, 10f // if ne, interval has not expired
+
+//
+// The profile interval has expired. Reset the profile interval count
+// and process the profile interrupt.
+//
+
+ ldl t0, PcProfileCountReload0(v0) // get the new tick count
+ stl t0, PcProfileCount0(v0) // reset the profile interval count
+
+ ldl a1, Halp21164ProfileSource0
+ bis fp, zero, a0 // pass trap frame pointer
+ ldl t1, __imp_KeProfileInterruptWithSource
+ jsr ra, (t1) // process the profile interrupt
+
+ br zero, 40f // common return
+
+//
+// The profile interval has not expired. Update the decremented count.
+//
+
+10:
+ stl t0, PcProfileCount0(v0) // update profile interval count
+ br zero, 40f // common return
+
+//
+// Profiling is not active. Therefore, this interrupt was caused by
+// a performance counter driver. Deliver a secondary dispatch.
+//
+
+20:
+
+ ldil a0, PC0_SECONDARY_VECTOR // get IDT vector for secondary
+ s4addl a0, v0, a0 // a0 = PCR + IDT index
+ ldl a0, PcInterruptRoutine(a0) // get service routine address
+ jsr ra, (a0) // call interrupt service routine
+
+//
+// Setup for return.
+//
+
+40:
+ ldil v0, TRUE // set return value = TRUE
+ ldq ra, PrRa(sp) // restore return address
+ lda sp, PrFrameLength(sp) // deallocate the stack frame
+ ret zero, (ra) // return
+
+ .end Halp21164PerformanceCounter0Interrupt
+
+
+ SBTTL("Performance Counter 1 Interrupt")
+//++
+//
+// VOID
+// Halp21164PerformanceCounter1Interrupt
+// )
+//
+// Routine Description:
+//
+// This function is executed as the result of an interrupt from the
+// internal microprocessor performance counter 1. The interrupt
+// may be used to signal the completion of a profile event.
+// If profiling is current active, the function determines if the
+// profile interval has expired and if so dispatches to the standard
+// system routine to update the system profile time. If profiling
+// is not active then the function performs a secondary dispatch for
+// performance counter 1.
+//
+// Arguments:
+//
+// TrapFrame (fp/s6) - Supplies a pointer to the trap frame for
+// the interrupt.
+//
+// Return Value:
+//
+// TRUE is returned.
+//
+//--
+
+ NESTED_ENTRY(Halp21164PerformanceCounter1Interrupt, PrFrameLength, zero )
+
+ lda sp, -PrFrameLength(sp) // allocate a stack frame
+ stq ra, PrRa(sp) // save the return address
+
+ PROLOGUE_END //
+
+ call_pal rdpcr // v0 = pcr base address
+
+ ldl t0, PcProfileCount1(v0) // capture the current profile count
+ beq t0, 20f // if eq, profiling not active
+
+//
+// Profiling is active. Decrement the interval count and if it has
+// reached zero then call the kernel profile routine.
+//
+
+ subl t0, 1, t0 // decrement the interval count
+ bne t0, 10f // if ne, interval has not expired
+
+//
+// The profile interval has expired. Reset the profile interval count
+// and process the profile interrupt.
+//
+
+ ldl t0, PcProfileCountReload1(v0) // get the new tick count
+ stl t0, PcProfileCount1(v0) // reset the profile interval count
+
+ ldl a1, Halp21164ProfileSource1
+ bis fp, zero, a0 // pass trap frame pointer
+ ldl t1, __imp_KeProfileInterruptWithSource
+ jsr ra, (t1) // process the profile interrupt
+
+ br zero, 40f // common return
+
+//
+// The profile interval has not expired. Update the decremented count.
+//
+
+10:
+ stl t0, PcProfileCount1(v0) // update profile interval count
+ br zero, 40f // common return
+
+//
+// Profiling is not active. Therefore, this interrupt was caused by
+// a performance counter driver. Deliver a secondary dispatch.
+//
+
+20:
+
+ ldil a0, PC1_SECONDARY_VECTOR // get IDT vector for secondary
+ s4addl a0, v0, a0 // a0 = PCR + IDT index
+ ldl a0, PcInterruptRoutine(a0) // get service routine address
+ jsr ra, (a0) // call interrupt service routine
+
+//
+// Setup for return.
+//
+
+40:
+ ldil v0, TRUE // set return value = TRUE
+ ldq ra, PrRa(sp) // restore return address
+ lda sp, PrFrameLength(sp) // deallocate the stack frame
+ ret zero, (ra) // return
+
+ .end Halp21164PerformanceCounter1Interrupt
+
+ SBTTL("Performance Counter 2 Interrupt")
+//++
+//
+// VOID
+// Halp21164PerformanceCounter2Interrupt
+// )
+//
+// Routine Description:
+//
+// This function is executed as the result of an interrupt from the
+// internal microprocessor performance counter 2. The interrupt
+// may be used to signal the completion of a profile event.
+// If profiling is current active, the function determines if the
+// profile interval has expired and if so dispatches to the standard
+// system routine to update the system profile time. If profiling
+// is not active then the function performs a secondary dispatch for
+// performance counter 2.
+//
+// Arguments:
+//
+// TrapFrame (fp/s6) - Supplies a pointer to the trap frame for
+// the interrupt.
+//
+// Return Value:
+//
+// TRUE is returned.
+//
+//--
+
+ NESTED_ENTRY(Halp21164PerformanceCounter2Interrupt, PrFrameLength, zero )
+
+ lda sp, -PrFrameLength(sp) // allocate a stack frame
+ stq ra, PrRa(sp) // save the return address
+
+ PROLOGUE_END //
+
+ call_pal rdpcr // v0 = pcr base address
+
+ ldl t0, PcProfileCount2(v0) // capture the current profile count
+ beq t0, 20f // if eq, profiling not active
+
+//
+// Profiling is active. Decrement the interval count and if it has
+// reached zero then call the kernel profile routine.
+//
+
+ subl t0, 1, t0 // decrement the interval count
+ bne t0, 10f // if ne, interval has not expired
+
+//
+// The profile interval has expired. Reset the profile interval count
+// and process the profile interrupt.
+//
+
+ ldl t0, PcProfileCountReload2(v0) // get the new tick count
+ stl t0, PcProfileCount2(v0) // reset the profile interval count
+
+ ldl a1, Halp21164ProfileSource2
+ bis fp, zero, a0 // pass trap frame pointer
+ ldl t1, __imp_KeProfileInterruptWithSource
+ jsr ra, (t1) // process the profile interrupt
+
+ br zero, 40f // common return
+
+//
+// The profile interval has not expired. Update the decremented count.
+//
+
+10:
+ stl t0, PcProfileCount2(v0) // update profile interval count
+ br zero, 40f // common return
+
+//
+// Profiling is not active. Therefore, this interrupt was caused by
+// a performance counter driver. Deliver a secondary dispatch.
+//
+
+20:
+
+ ldil a0, PC2_SECONDARY_VECTOR // get IDT vector for secondary
+ s4addl a0, v0, a0 // a0 = PCR + IDT index
+ ldl a0, PcInterruptRoutine(a0) // get service routine address
+ jsr ra, (a0) // call interrupt service routine
+
+//
+// Setup for return.
+//
+
+40:
+ ldil v0, TRUE // set return value = TRUE
+ ldq ra, PrRa(sp) // restore return address
+ lda sp, PrFrameLength(sp) // deallocate the stack frame
+ ret zero, (ra) // return
+
+ .end Halp21164PerformanceCounter2Interrupt
+
+//++
+//
+// ULONGLONG
+// HalpRead21164PerformanceCounter(
+// VOID
+// )
+//
+// Routine Description:
+//
+// Read the processor performance counter register
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// The current value of the performance counter register.
+//
+//--
+
+ LEAF_ENTRY(HalpRead21164PerformanceCounter)
+
+ bis zero, 1, a1 // indicate read operation
+ call_pal wrperfmon // read the performance counter
+
+ ret zero, (ra) // return to caller
+
+ .end HalpRead21164PerformanceCounter
+
+
+//++
+//
+// VOID
+// HalpWrite21164PerformanceCounter(
+// ULONGLONG PmCtr
+// ULONG CboxMux1
+// ULONG CboxMux2
+// )
+//
+// Routine Description:
+//
+// Write the processor performance counter register
+//
+// Arguments:
+//
+// PmCtr(a0) - value to be written to the performance counter
+// CboxMux1(a1) - value to be written to Cbox mux 1 select (optional)
+// CboxMux2(a2) - value to be written to Cbox mux 2 select (optional)
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpWrite21164PerformanceCounter)
+
+ bis zero, a2, a3 // move arguments up
+ bis zero, a1, a2 //
+ bis zero, zero, a1 // indicate write operation
+ call_pal wrperfmon // write the performance counter
+
+ ret zero, (ra)
+
+ .end HalpWrite21164PerformanceCounter
diff --git a/private/ntos/nthals/halflex/alpha/ev5prof.c b/private/ntos/nthals/halflex/alpha/ev5prof.c
new file mode 100644
index 000000000..625fba304
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/ev5prof.c
@@ -0,0 +1,747 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ ev5prof.c
+
+Abstract:
+
+ This module implements the Profile Counter using the performance
+ counters within the EV5 core. This module is appropriate for all
+ machines based on microprocessors using the EV5 core.
+
+ N.B. - This module assumes that all processors in a multiprocessor
+ system are running the microprocessor at the same clock speed.
+
+Author:
+
+ Steve Brooks 14-Feb-1995 (adapted from ev4prof.c)
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "axp21164.h"
+
+//
+// Default Number of Profile Clock Ticks per sample
+//
+
+ULONG Halp21164NumberOfTicks = 1;
+ULONG Halp21164NumberOfTicksReload;
+
+//
+// Define space in the HAL-reserved part of the PCR structure for each
+// performance counter's interval count
+//
+// Note that ev5ints.s depends on these positions in the PCR.
+//
+#define PCRProfileCount ((PULONG)(HAL_21164_PCR->ProfileCount.ProfileCount))
+#define PCRProfileCountReload ((PULONG)(&HAL_21164_PCR->ProfileCount.ProfileCountReload))
+
+
+//
+// Define the currently selected profile source for each counter
+//
+KPROFILE_SOURCE Halp21164ProfileSource0;
+KPROFILE_SOURCE Halp21164ProfileSource1;
+KPROFILE_SOURCE Halp21164ProfileSource2;
+
+#define INTERVAL_DELTA (10)
+
+//
+// Define the mapping between possible profile sources and the
+// CPU-specific settings.
+//
+typedef struct _HALP_PROFILE_MAPPING {
+ BOOLEAN Supported;
+ ULONG MuxControl;
+ ULONG Counter;
+ ULONG EventCount;
+ ULONG NumberOfTicks;
+} HALP_PROFILE_MAPPING, *PHALP_PROFILE_MAPPING;
+
+HALP_PROFILE_MAPPING Halp21164ProfileMapping[ProfileMaximum] =
+{
+ {TRUE, Ev5Cycles, Ev5PerformanceCounter0, Ev5CountEvents2xx16, 10},
+ {FALSE, 0,0,0,0},
+ {TRUE, Ev5Instructions, Ev5PerformanceCounter0, Ev5CountEvents2xx16, 10},
+ {TRUE, Ev5PipeDry, Ev5PerformanceCounter1, Ev5CountEvents2xx16, 10},
+ {TRUE, Ev5LoadsIssued, Ev5PerformanceCounter1, Ev5CountEvents2xx16, 10},
+ {FALSE, 0,0,0,0},
+ {TRUE, Ev5AllFlowIssued, Ev5PerformanceCounter1, Ev5CountEvents2xx16, 10},
+ {TRUE, Ev5NonIssue, Ev5PerformanceCounter1, Ev5CountEvents2xx16, 10},
+ {TRUE, Ev5DcacheLDMisses, Ev5PerformanceCounter2, Ev5CountEvents2xx14, 10},
+ {TRUE, Ev5IcacheRFBMisses, Ev5PerformanceCounter2, Ev5CountEvents2xx14, 10},
+ {FALSE, 0,0,0,0},
+ {TRUE, Ev5BRMispredicts, Ev5PerformanceCounter2, Ev5CountEvents2xx14, 10},
+ {TRUE, Ev5StoresIssued, Ev5PerformanceCounter1, Ev5CountEvents2xx16, 10},
+ {TRUE, Ev5FPOpsIssued, Ev5PerformanceCounter1, Ev5CountEvents2xx16, 10},
+ {TRUE, Ev5IntOpsIssued, Ev5PerformanceCounter1, Ev5CountEvents2xx16, 10},
+ {TRUE, Ev5DualIssue, Ev5PerformanceCounter1, Ev5CountEvents2xx16, 10},
+ {TRUE, Ev5TripleIssue, Ev5PerformanceCounter1, Ev5CountEvents2xx16, 10},
+ {TRUE, Ev5QuadIssue, Ev5PerformanceCounter1, Ev5CountEvents2xx16, 10},
+ {FALSE, 0,0,0,0},
+ {TRUE, Ev5Cycles, Ev5PerformanceCounter0, Ev5CountEvents2xx16, 10},
+ {TRUE, Ev5IcacheIssued, Ev5PerformanceCounter1, Ev5CountEvents2xx16, 10},
+ {TRUE, Ev5DcacheAccesses,Ev5PerformanceCounter1, Ev5CountEvents2xx16, 10},
+ {TRUE, Ev5MBStallCycles, Ev5PerformanceCounter2, Ev5CountEvents2xx14, 10},
+ {TRUE, Ev5LDxLInstIssued,Ev5PerformanceCounter2, Ev5CountEvents2xx14, 10}
+};
+
+BOOLEAN
+HalQueryProfileInterval(
+ IN KPROFILE_SOURCE Source
+ );
+
+NTSTATUS
+HalSetProfileSourceInterval(
+ IN KPROFILE_SOURCE ProfileSource,
+ IN OUT ULONG *Interval
+ );
+
+VOID
+Halp21164UpdatePerformanceCounter(
+ IN ULONG PerformanceCounter,
+ IN ULONG MuxControl,
+ IN ULONG EventCount
+ );
+
+
+NTSTATUS
+Halp21164ProfileSourceInformation (
+ OUT PVOID Buffer,
+ IN ULONG BufferLength,
+ OUT PULONG ReturnedLength
+ )
+/*++
+
+Routine Description:
+
+ Returns the HAL_PROFILE_SOURCE_INFORMATION for this processor.
+
+Arguments:
+
+ Buffer - output buffer
+ BufferLength - length of buffer on input
+ ReturnedLength - The length of data returned
+
+Return Value:
+
+ STATUS_SUCCESS
+ STATUS_BUFFER_TOO_SMALL - The ReturnedLength contains the buffersize
+ currently needed.
+
+--*/
+{
+ PHAL_PROFILE_SOURCE_INFORMATION SourceInfo;
+ NTSTATUS Status;
+
+
+ if (BufferLength != sizeof(HAL_PROFILE_SOURCE_INFORMATION)) {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ return Status;
+ }
+
+ SourceInfo = (PHAL_PROFILE_SOURCE_INFORMATION)Buffer;
+ SourceInfo->Supported = HalQueryProfileInterval(SourceInfo->Source);
+
+ if (SourceInfo->Supported) {
+ SourceInfo->Interval =
+ Halp21164ProfileMapping[SourceInfo->Source].EventCount *
+ Halp21164ProfileMapping[SourceInfo->Source].NumberOfTicks;
+ }
+
+ Status = STATUS_SUCCESS;
+ return Status;
+}
+
+NTSTATUS
+Halp21164ProfileSourceInterval (
+ OUT PVOID Buffer,
+ IN ULONG BufferLength
+ )
+/*++
+
+Routine Description:
+
+ Returns the HAL_PROFILE_SOURCE_INTERVAL for this processor.
+
+Arguments:
+
+ Buffer - output buffer
+ BufferLength - length of buffer on input
+
+Return Value:
+
+ STATUS_SUCCESS
+ STATUS_BUFFER_TOO_SMALL - The ReturnedLength contains the buffersize
+ currently needed.
+
+--*/
+{
+ PHAL_PROFILE_SOURCE_INTERVAL Interval;
+ NTSTATUS Status;
+
+
+ if (BufferLength != sizeof(HAL_PROFILE_SOURCE_INTERVAL)) {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ return Status;
+ }
+
+ Interval = (PHAL_PROFILE_SOURCE_INTERVAL)Buffer;
+ Status = HalSetProfileSourceInterval(Interval->Source,
+ &Interval->Interval);
+ return Status;
+}
+
+VOID
+Halp21164InitializeProfiler(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is called during initialization to initialize profiling
+ for each processor in the system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ //
+ // Establish the profile interrupt as the interrupt handler for
+ // all performance counter interrupts.
+ //
+
+ PCR->InterruptRoutine[PC0_VECTOR] = Halp21164PerformanceCounter0Interrupt;
+ PCR->InterruptRoutine[PC1_VECTOR] = Halp21164PerformanceCounter1Interrupt;
+ PCR->InterruptRoutine[PC2_VECTOR] = Halp21164PerformanceCounter2Interrupt;
+
+ return;
+
+}
+
+
+BOOLEAN
+Hal21164QueryProfileInterval(
+ IN KPROFILE_SOURCE Source
+ )
+
+/*++
+
+Routine Description:
+
+ Given a profile source, returns whether or not that source is
+ supported.
+
+Arguments:
+
+ Source - Supplies the profile source
+
+Return Value:
+
+ TRUE - Profile source is supported
+
+ FALSE - Profile source is not supported
+
+--*/
+
+{
+ if (Source > (sizeof(Halp21164ProfileMapping)/sizeof(HALP_PROFILE_MAPPING))) {
+ return(FALSE);
+ }
+
+ return(Halp21164ProfileMapping[Source].Supported);
+}
+
+
+NTSTATUS
+Hal21164SetProfileSourceInterval(
+ IN KPROFILE_SOURCE ProfileSource,
+ IN OUT ULONG *Interval
+ )
+
+/*++
+
+Routine Description:
+
+ Sets the profile interval for a specified profile source
+
+Arguments:
+
+ ProfileSource - Supplies the profile source
+
+ Interval - Supplies the specified profile interval
+ Returns the actual profile interval
+
+Return Value:
+
+ NTSTATUS
+
+--*/
+
+{
+ ULONG FastTickPeriod;
+ ULONG SlowTickPeriod;
+ ULONG TickPeriod;
+ ULONG FastCountEvents;
+ ULONG SlowCountEvents;
+ ULONGLONG CountEvents;
+ ULONGLONG TempInterval;
+
+ if (!HalQueryProfileInterval(ProfileSource)) {
+ return(STATUS_NOT_IMPLEMENTED);
+ }
+
+ if (ProfileSource == ProfileTime) {
+
+ //
+ // Convert the clock tick period (in 100ns units ) into
+ // a cycle count period
+ //
+
+ CountEvents = ((ULONGLONG)(*Interval) * 100000) / PCR->CycleClockPeriod;
+ } else {
+ CountEvents = (ULONGLONG)*Interval;
+ }
+
+ FastCountEvents = Ev5CountEvents2xx8;
+ SlowCountEvents = Ev5CountEvents2xx16;
+
+ if (Halp21164ProfileMapping[ProfileSource].Counter == Ev5PerformanceCounter0) {
+ FastCountEvents = Ev5CountEvents2xx16;
+ }
+ else if (Halp21164ProfileMapping[ProfileSource].Counter == Ev5PerformanceCounter2) {
+ SlowCountEvents = Ev5CountEvents2xx14;
+ }
+
+ //
+ // Limit the interval to the smallest interval we can time.
+ //
+ if (CountEvents < FastCountEvents) {
+ CountEvents = (ULONGLONG)FastCountEvents;
+ }
+
+ //
+ // Assume we will use the fast event count
+ //
+ Halp21164ProfileMapping[ProfileSource].EventCount = FastCountEvents;
+ Halp21164ProfileMapping[ProfileSource].NumberOfTicks =
+ (ULONG)((CountEvents + FastCountEvents - 1) / FastCountEvents);
+
+ //
+ // See if we can successfully use the slower period. If the requested
+ // interval is greater than the slower tick period and the difference
+ // between the requested interval and the interval that we can deliver
+ // with the slower clock is acceptable, then use the slower clock.
+ // We define an acceptable difference as a difference of less than
+ // INTERVAL_DELTA of the requested interval.
+ //
+ if (CountEvents > SlowCountEvents) {
+ ULONG NewInterval;
+
+ NewInterval = (ULONG)(((CountEvents + SlowCountEvents-1) /
+ SlowCountEvents) * SlowCountEvents);
+ if (((NewInterval - CountEvents) * 100 / CountEvents) < INTERVAL_DELTA) {
+ Halp21164ProfileMapping[ProfileSource].EventCount = SlowCountEvents;
+ Halp21164ProfileMapping[ProfileSource].NumberOfTicks = NewInterval / SlowCountEvents;
+ }
+ }
+
+ *Interval = Halp21164ProfileMapping[ProfileSource].EventCount *
+ Halp21164ProfileMapping[ProfileSource].NumberOfTicks;
+
+ if (ProfileSource == ProfileTime) {
+ //
+ // Convert cycle count back into 100ns clock ticks
+ //
+ // Use 64-bit integer to prevent overflow.
+ //
+ TempInterval = (ULONGLONG)(*Interval) * (ULONGLONG)(PCR->CycleClockPeriod);
+ *Interval = (ULONG)(TempInterval / 100000);
+ }
+ return(STATUS_SUCCESS);
+}
+
+
+ULONG
+Hal21164SetProfileInterval (
+ IN ULONG Interval
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the profile interrupt interval.
+
+Arguments:
+
+ Interval - Supplies the desired profile interval in 100ns units.
+
+Return Value:
+
+ The actual profile interval.
+
+--*/
+
+{
+ ULONG NewInterval;
+
+ NewInterval = Interval;
+ HalSetProfileSourceInterval(ProfileTime, &NewInterval);
+ return(NewInterval);
+}
+
+
+
+VOID
+Hal21164StartProfileInterrupt (
+ KPROFILE_SOURCE ProfileSource
+ )
+
+/*++
+
+Routine Description:
+
+ This routine turns on the profile interrupt.
+
+ N.B. This routine must be called at PROCLK_LEVEL while holding the
+ profile lock.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG PerformanceCounter;
+ ULONG MuxControl;
+ ULONG EventCount;
+
+ //
+ // Check input to see if we are turning on a source that is
+ // supported. If it is unsupported, just return.
+ //
+
+ if ((ProfileSource > (sizeof(Halp21164ProfileMapping)/sizeof(HALP_PROFILE_MAPPING))) ||
+ (!Halp21164ProfileMapping[ProfileSource].Supported)) {
+ return;
+ }
+
+ //
+ // Set the performance counter within the processor to begin
+ // counting total cycles.
+ //
+ PerformanceCounter = Halp21164ProfileMapping[ProfileSource].Counter;
+ MuxControl = Halp21164ProfileMapping[ProfileSource].MuxControl;
+
+ if (PerformanceCounter == Ev5PerformanceCounter0) {
+
+ EventCount = (Halp21164ProfileMapping[ProfileSource].EventCount ==
+ Ev5CountEvents2xx16) ? Ev5EventCountLow
+ : Ev5EventCountHigh;
+
+ Halp21164ProfileSource0 = ProfileSource;
+ Halp21164UpdatePerformanceCounter( PerformanceCounter,
+ MuxControl,
+ EventCount );
+
+ PCRProfileCountReload[0] = Halp21164ProfileMapping[ProfileSource].NumberOfTicks;
+ PCRProfileCount[0] = Halp21164ProfileMapping[ProfileSource].NumberOfTicks;
+
+ //
+ // Enable the performance counter interrupt.
+ //
+
+ HalEnableSystemInterrupt ( PC0_VECTOR,
+ PROFILE_LEVEL,
+ LevelSensitive );
+
+
+ } else if (PerformanceCounter == Ev5PerformanceCounter1) {
+
+ EventCount = (Halp21164ProfileMapping[ProfileSource].EventCount ==
+ Ev5CountEvents2xx16) ? Ev5EventCountLow
+ : Ev5EventCountHigh;
+
+ Halp21164ProfileSource1 = ProfileSource;
+ Halp21164UpdatePerformanceCounter( PerformanceCounter,
+ MuxControl,
+ EventCount );
+
+ PCRProfileCountReload[1] = Halp21164ProfileMapping[ProfileSource].NumberOfTicks;
+ PCRProfileCount[1] = Halp21164ProfileMapping[ProfileSource].NumberOfTicks;
+
+ //
+ // Enable the performance counter interrupt.
+ //
+
+ HalEnableSystemInterrupt ( PC1_VECTOR,
+ PROFILE_LEVEL,
+ LevelSensitive );
+
+ } else if (PerformanceCounter == Ev5PerformanceCounter2) {
+
+ EventCount = (Halp21164ProfileMapping[ProfileSource].EventCount ==
+ Ev5CountEvents2xx14) ? Ev5EventCountLow
+ : Ev5EventCountHigh;
+
+ Halp21164ProfileSource2 = ProfileSource;
+ Halp21164UpdatePerformanceCounter( PerformanceCounter,
+ MuxControl,
+ EventCount );
+
+ PCRProfileCountReload[2] = Halp21164ProfileMapping[ProfileSource].NumberOfTicks;
+ PCRProfileCount[2] = Halp21164ProfileMapping[ProfileSource].NumberOfTicks;
+
+ //
+ // Enable the performance counter interrupt.
+ //
+
+ HalEnableSystemInterrupt ( PC2_VECTOR,
+ PROFILE_LEVEL,
+ LevelSensitive );
+ }
+
+ return;
+}
+
+
+VOID
+Hal21164StopProfileInterrupt (
+ KPROFILE_SOURCE ProfileSource
+ )
+
+/*++
+
+Routine Description:
+
+ This routine turns off the profile interrupt.
+
+ N.B. This routine must be called at PROCLK_LEVEL while holding the
+ profile lock.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG PerformanceCounter;
+ ULONG Vector;
+
+ //
+ // Check input to see if we are turning off a source that is
+ // supported. If it is unsupported, just return.
+ //
+
+ if ((ProfileSource > (sizeof(Halp21164ProfileMapping)/sizeof(HALP_PROFILE_MAPPING))) ||
+ (!Halp21164ProfileMapping[ProfileSource].Supported)) {
+ return;
+ }
+
+ //
+ // Stop the performance counter from interrupting.
+ //
+
+ PerformanceCounter = Halp21164ProfileMapping[ProfileSource].Counter;
+ Halp21164UpdatePerformanceCounter( PerformanceCounter,
+ 0,
+ Ev5CounterDisable );
+
+ //
+ // Disable the performance counter interrupt.
+ //
+ if (PerformanceCounter == Ev5PerformanceCounter0) {
+
+ HalDisableSystemInterrupt( PC0_VECTOR, PROFILE_LEVEL );
+
+ //
+ // Clear the current profile count. Can't clear value in PCR
+ // since a profile interrupt could be pending or in progress
+ // so clear the reload counter.
+ //
+
+ PCRProfileCountReload[0] = 0;
+
+ } else if (PerformanceCounter == Ev5PerformanceCounter1) {
+
+ HalDisableSystemInterrupt( PC1_VECTOR, PROFILE_LEVEL );
+
+ //
+ // Clear the current profile count. Can't clear value in PCR
+ // since a profile interrupt could be pending or in progress
+ // so clear the reload counter.
+ //
+
+ PCRProfileCountReload[1] = 0;
+
+ } else if (PerformanceCounter == Ev5PerformanceCounter2) {
+
+ HalDisableSystemInterrupt( PC2_VECTOR, PROFILE_LEVEL );
+
+ //
+ // Clear the current profile count. Can't clear value in PCR
+ // since a profile interrupt could be pending or in progress
+ // so clear the reload counter.
+ //
+
+ PCRProfileCountReload[2] = 0;
+ }
+
+ return;
+}
+
+
+VOID
+Halp21164UpdatePerformanceCounter(
+ IN ULONG PerformanceCounter,
+ IN ULONG MuxControl,
+ IN ULONG EventCount
+ )
+//++
+//
+// Routine Description:
+//
+// Write the specified microprocessor internal performance counter.
+//
+// Arguments:
+//
+// PerformanceCounter(a0) - Supplies the number of the performance counter
+// to write.
+//
+// MuxControl(a2) - Supplies the mux control value which selects which
+// type of event to count when the counter is enabled.
+//
+// EventCount(a3) - Supplies the event interval when the counter is
+// enabled.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+{
+ PMCTR_21164 PmCtr; // the performance counter register
+ ULONG CboxMux1 = 0; // CBOX select 1 mux value
+ ULONG CboxMux2 = 0; // CBOX select 2 mux value
+
+ PmCtr.all = HalpRead21164PerformanceCounter();
+
+ //
+ // Check for special values first:
+ //
+
+ if ( MuxControl >= Ev5PcSpecial ) {
+
+ switch( MuxControl ) {
+
+ //
+ // Count JsrRet Issued
+ //
+
+ case Ev5JsrRetIssued:
+
+ PmCtr.Ctl1 = EventCount;
+ PmCtr.Sel1 = Ev5FlowChangeInst;
+ PmCtr.Sel2 = Ev5PCMispredicts;
+ break;
+
+ //
+ // Count CondBr Issued
+ //
+
+ case Ev5CondBrIssued:
+
+ PmCtr.Ctl1 = EventCount;
+ PmCtr.Sel1 = Ev5FlowChangeInst;
+ PmCtr.Sel2 = Ev5BRMispredicts;
+ break;
+
+ //
+ // Count all flow change inst Issued
+ //
+
+ case Ev5AllFlowIssued:
+
+ PmCtr.Ctl1 = EventCount;
+ PmCtr.Sel1 = Ev5FlowChangeInst;
+
+ if ( (PmCtr.Sel2 == Ev5PCMispredicts) ||
+ (PmCtr.Sel2 == Ev5BRMispredicts)) {
+
+ PmCtr.Sel2 = Ev5LongStalls;
+
+ }
+ break;
+
+ //
+ // Must be an Scache counter. Select the appropriate counter
+ // in Sel1 or Sel2, and pass the CBOX mux value to WritePerfCounter
+ //
+
+ default:
+
+ if ( MuxControl <= Ev5ScSystemCmdReq ) {
+
+ PmCtr.Ctl1 = EventCount;
+ PmCtr.Sel1 = Ev5CBOXInput1;
+ CboxMux1 = MuxControl - Ev5ScMux1;
+
+ } else if ( MuxControl <= Ev5ScSysReadReq ) {
+
+ PmCtr.Ctl2 = EventCount;
+ PmCtr.Sel2 = Ev5CBOXInput2;
+ CboxMux2 = MuxControl - Ev5ScMux2;
+
+ }
+
+ } // switch
+
+ } else if ( PerformanceCounter == Ev5PerformanceCounter0 ) {
+
+ PmCtr.Ctl0 = EventCount;
+ PmCtr.Sel0 = MuxControl;
+
+ } else if ( PerformanceCounter == Ev5PerformanceCounter1 ) {
+
+ PmCtr.Ctl1 = EventCount;
+ PmCtr.Sel1 = MuxControl;
+
+ } else if ( PerformanceCounter == Ev5PerformanceCounter2 ) {
+
+ PmCtr.Ctl2 = EventCount;
+ PmCtr.Sel2 = MuxControl;
+
+ }
+
+ HalpWrite21164PerformanceCounter(PmCtr.all, CboxMux1, CboxMux2);
+}
diff --git a/private/ntos/nthals/halflex/alpha/evclock.s b/private/ntos/nthals/halflex/alpha/evclock.s
new file mode 100644
index 000000000..aaaf6cd27
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/evclock.s
@@ -0,0 +1,119 @@
+//++
+//
+// 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
+
+//
+// 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, HalpNextIntervalCount // Get next interval count. If 0, then no change required.
+ beq a0, 10f // See if time increment is to be changed
+ bsr ra, HalpProgramIntervalTimer // Program timer with new rate select
+ ldl t0, HalpNewTimeIncrement // Get HalpNewTimeIncrement
+ stl t0, HalpNextTimeIncrement // Set HalpNextTimeIncrement to HalpNewTimeIncrement
+ stl zero, HalpNextIntervalCount // Set HalpNextIntervalCount to 0
+
+//
+// Call to handle performance counter wrap.
+//
+10:
+ 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
+ ldl t0, __imp_DbgBreakPointWithStatus
+ lda a0, DBG_STATUS_CONTROL_C
+ jsr ra, (t0) // send status to debugger
+
+30:
+
+#endif //DEVL
+
+//
+// Return to the caller.
+//
+
+ ldq ra, CiRa(sp) // restore return address
+ lda sp, CiFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // return to caller
+
+ .end HalpClockInterrupt
+
+
+
diff --git a/private/ntos/nthals/halflex/alpha/evxcache.c b/private/ntos/nthals/halflex/alpha/evxcache.c
new file mode 100644
index 000000000..12237a517
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/evxcache.c
@@ -0,0 +1,823 @@
+/*++
+
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ ev4cache.c
+
+Abstract:
+
+ This file contains the routines for managing the caches on machines
+ based on the DECchip 21064 microprocessor.
+
+ EV4 has primary I and D caches of 8KB each, both write-through.
+ Any systems based on EV4 are expected to have an external backup cache
+ which is write-back, but it is also coherent with all DMA operations. The
+ primary caches are shadowed by the backup, and on a write hit, the
+ primary data (but not instruction) cache is invalidated.
+ Consequently, the routines to flush,sweep,purge,etc the data
+ stream are nops on EV4, but the corresponding routines for the
+ Istream must ensure that we cannot hit in the primary I cache
+ after a DMA operation.
+
+ EV4 has a write buffer which contains 4 32-byte entries, which
+ must be flushable before DMA operations. The MB instruction is
+ used to accomplish this.
+
+ There is no coloring support on EV4, so Color operations are
+ null. Zero page is unsupported because it has no users. Copy
+ page is not special because we lack coloring.
+
+ We had to make a philosophical decision about what interfaces to
+ support in this file. (Almost) none of the interfaces defined in
+ the HAL spec are actually supported in either the i386 or MIPS
+ code. The i386 stream has almost no cache support at all. The
+ Mips stream has cache support, but most routines also refer to
+ coloring. Should we use the Spec'ed interfaces, or the Mips
+ interfaces? I have elected the Mips interfaces because they are
+ in use, and we are stealing much of the Mips code which expects
+ these interfaces. Besides, the only change we might make is to
+ remove the coloring arguments, but they may be used on Alpha
+ machines at some future date.
+
+Author:
+
+ Miche Baker-Harvey (miche) 29-May-1992
+
+Revision History:
+
+
+ 13-Jul-1992 Jeff McLeman (mcleman)
+ use HalpMb to do a memory barrier. Also, alter code and use super
+ pages to pass to rtl memory routines.
+
+ 10-Jul-1992 Jeff McLeman (mcleman)
+ use HalpImb to call pal.
+
+ 06-Jul-1992 Jeff McLeman (mcleman)
+ Move routine KeFlushDcache into this module.
+ Use only one memory barrier in the KeFlushWriteBuffer
+ routine. This is because the PAL for the EVx will
+ make sure the proper write ordering is done in PAL mode.
+
+--*/
+ // Include files
+
+#include "halp.h"
+
+
+
+VOID
+HalFlushDcache (
+ IN BOOLEAN AllProcessors
+ );
+
+//
+// Cache and write buffer flush functions.
+//
+
+
+VOID
+HalChangeColorPage (
+ IN PVOID NewColor,
+ IN PVOID OldColor,
+ IN ULONG PageFrame
+ )
+/*++
+
+Routine Description:
+
+ This function changes the color of a page if the old and new colors
+ do not match. DECchip 21064-based machines do not have page coloring, and
+ therefore, this function performs no operation.
+
+Arguments:
+
+ NewColor - Supplies the page aligned virtual address of the
+ new color of the page to change.
+
+ OldColor - Supplies the page aligned virtual address of the
+ old color of the page to change.
+
+ pageFrame - Supplies the page frame number of the page that
+ is changed.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ return;
+}
+
+VOID
+HalFlushDcachePage (
+ IN PVOID Color,
+ IN ULONG PageFrame,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ This function flushes (invalidates) up to a page of data from the
+ data cache.
+
+Arguments:
+
+ Color - Supplies the starting virtual address and color of the
+ data that is flushed.
+ PageFrame - Supplies the page frame number of the page that
+ is flushed.
+
+ Length - Supplies the length of the region in the page that is
+ flushed.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ return;
+}
+
+VOID
+HalFlushIoBuffers (
+ IN PMDL Mdl,
+ IN BOOLEAN ReadOperation,
+ IN BOOLEAN DmaOperation
+ )
+/*++
+Routine Description:
+
+ This function flushes the I/O buffer specified by the memory descriptor
+ list from the data cache on the current processor.
+
+Arguments:
+
+ Mdl - Supplies a pointer to a memory descriptor list that describes the
+ I/O buffer location.
+
+ ReadOperation - Supplies a boolean value that determines whether the I/O
+ operation is a read into memory.
+
+ DmaOperation - Supplies a boolean value that determines whether the I/O
+ operation is a DMA operation.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG CacheSegment;
+ ULONG Length;
+ ULONG Offset;
+ PULONG PageFrame;
+ ULONG Address;
+ volatile ULONG i;
+ volatile ULONG j;
+
+ if (DmaOperation!=FALSE) {
+
+ HalpMb(); // force all previous writes off chip
+
+ Offset = Mdl->ByteOffset;
+ Length = Mdl->ByteCount;
+ PageFrame = (PULONG)(Mdl + 1);
+
+ //
+ // Export or purge the specified page segments from the data and
+ // instruction caches as appropriate.
+ //
+
+ do {
+ if (Length >= (PAGE_SIZE - Offset)) {
+ CacheSegment = PAGE_SIZE - Offset;
+ } else {
+ CacheSegment = Length;
+ }
+
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+
+ if (HalpModuleHardwareFlushing) {
+
+ Address = *PageFrame << PAGE_SHIFT;
+ if (Address & 0x2000) {
+ HalpWriteAbsoluteUlong(0xfffffce9,0x00000010,(Address >> 14) & 0xffff);
+ } else {
+ HalpWriteAbsoluteUlong(0xfffffce8,0x00000010,(Address >> 14) & 0xffff);
+ }
+
+ } else {
+
+ Address = (*PageFrame << PAGE_SHIFT) & 0x001fffff;
+ for(i=0;i<PAGE_SIZE;i+=0x40) {
+ j = *(volatile ULONG *)((ULONG)HalpCacheFlushBase+Address+i);
+ }
+ }
+
+ } else {
+
+ if (HalpModuleHardwareFlushing) {
+
+ Address = *PageFrame << PAGE_SHIFT;
+ HalpWriteAbsoluteUlong(0xfffffc03,0x40000004,((Address>>21)&0x1ff)<<8);
+ HalpWriteAbsoluteUlong(0xfffffc03,0x00000004,((Address>>13)&0xff)<<9);
+ HalpReadAbsoluteUlong(0xfffffc03,0x00000000);
+
+ } else {
+
+ Address = (*PageFrame << PAGE_SHIFT) & 0x0007ffff;
+ for(i=0;i<PAGE_SIZE;i+=0x20) {
+ j = *(volatile ULONG *)((ULONG)HalpCacheFlushBase+Address+i);
+ }
+
+ for(i=0;i<PAGE_SIZE;i+=0x20) {
+ j = *(volatile ULONG *)((ULONG)HalpCacheFlushBase+0x200000+Address+i);
+ }
+
+ }
+ }
+
+ PageFrame += 1;
+ Length -= CacheSegment;
+ Offset = 0;
+ } while(Length != 0);
+ }
+
+ //
+ // The Dcache coherency is maintained in hardware. The Icache coherency
+ // is maintained by invalidating the istream on page read operations.
+ //
+ HalpMb(); // synchronize this processors view of memory
+ if (ReadOperation) {
+ HalpMb(); // not issued until previous mb completes
+
+ //
+ // If this is an EV4 or an EV45, then do an IMB
+ //
+
+ if (HalpIoArchitectureType != EV5_PROCESSOR_MODULE) {
+ if (Mdl->MdlFlags & MDL_IO_PAGE_READ) {
+
+ //
+ // The operation is a page read, thus the istream must
+ // be flushed.
+ //
+ HalpImb();
+ }
+ }
+ }
+}
+
+VOID
+HalpCleanIoBuffers (
+ IN PMDL Mdl,
+ IN BOOLEAN ReadOperation,
+ IN BOOLEAN DmaOperation
+ )
+/*++
+Routine Description:
+
+ This function flushes the I/O buffer specified by the memory descriptor
+ list from the data cache on the current processor.
+
+Arguments:
+
+ Mdl - Supplies a pointer to a memory descriptor list that describes the
+ I/O buffer location.
+
+ ReadOperation - Supplies a boolean value that determines whether the I/O
+ operation is a read into memory.
+
+ DmaOperation - Supplies a boolean value that determines whether the I/O
+ operation is a DMA operation.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG CacheSegment;
+ ULONG Length;
+ ULONG Offset;
+ PULONG PageFrame;
+ ULONG Address;
+ volatile ULONG i;
+ volatile ULONG j;
+
+// //
+// // If this is an EV4 or an EV45, then do nothing on the backend of DMA operations
+// //
+//
+// if (HalpIoArchitectureType != EV5_PROCESSOR_MODULE) {
+// return;
+// }
+
+ if (DmaOperation!=FALSE) {
+
+ HalpMb(); // force all previous writes off chip
+
+ Offset = Mdl->ByteOffset;
+ Length = Mdl->ByteCount;
+ PageFrame = (PULONG)(Mdl + 1);
+
+ //
+ // Export or purge the specified page segments from the data and
+ // instruction caches as appropriate.
+ //
+
+ do {
+ if (Length >= (PAGE_SIZE - Offset)) {
+ CacheSegment = PAGE_SIZE - Offset;
+ } else {
+ CacheSegment = Length;
+ }
+
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+
+ if (HalpModuleHardwareFlushing) {
+
+ Address = *PageFrame << PAGE_SHIFT;
+ if (Address & 0x2000) {
+ HalpWriteAbsoluteUlong(0xfffffce9,0x00000010,(Address >> 14) & 0xffff);
+ } else {
+ HalpWriteAbsoluteUlong(0xfffffce8,0x00000010,(Address >> 14) & 0xffff);
+ }
+
+ } else {
+
+ Address = (*PageFrame << PAGE_SHIFT) & 0x001fffff;
+ for(i=0;i<PAGE_SIZE;i+=0x40) {
+ j = *(volatile ULONG *)((ULONG)HalpCacheFlushBase+Address+i);
+ }
+ }
+
+ } else {
+
+ if (HalpModuleHardwareFlushing) {
+
+ Address = *PageFrame << PAGE_SHIFT;
+ HalpWriteAbsoluteUlong(0xfffffc03,0x40000004,((Address>>21)&0x1ff)<<8);
+ HalpWriteAbsoluteUlong(0xfffffc03,0x00000004,((Address>>13)&0xff)<<9);
+ HalpReadAbsoluteUlong(0xfffffc03,0x00000000);
+
+ } else {
+
+ Address = (*PageFrame << PAGE_SHIFT) & 0x0007ffff;
+ for(i=0;i<PAGE_SIZE;i+=0x20) {
+ j = *(volatile ULONG *)((ULONG)HalpCacheFlushBase+Address+i);
+ }
+
+ for(i=0;i<PAGE_SIZE;i+=0x20) {
+ j = *(volatile ULONG *)((ULONG)HalpCacheFlushBase+0x200000+Address+i);
+ }
+
+ }
+ }
+
+ PageFrame += 1;
+ Length -= CacheSegment;
+ Offset = 0;
+ } while(Length != 0);
+ }
+
+ //
+ // The Dcache coherency is maintained in hardware. The Icache coherency
+ // is maintained by invalidating the istream on page read operations.
+ //
+ HalpMb(); // synchronize this processors view of memory
+ if (ReadOperation) {
+ HalpMb(); // not issued until previous mb completes
+ if (Mdl->MdlFlags & MDL_IO_PAGE_READ) {
+
+ //
+ // The operation is a page read, thus the istream must
+ // be flushed.
+ //
+ HalpImb();
+ }
+ }
+}
+
+
+VOID
+HalpGoodCleanIoBuffers (
+ IN PMDL Mdl,
+ IN BOOLEAN ReadOperation,
+ IN BOOLEAN DmaOperation
+ )
+/*++
+Routine Description:
+
+ This function flushes the I/O buffer specified by the memory descriptor
+ list from the data cache on the current processor.
+
+Arguments:
+
+ Mdl - Supplies a pointer to a memory descriptor list that describes the
+ I/O buffer location.
+
+ ReadOperation - Supplies a boolean value that determines whether the I/O
+ operation is a read into memory.
+
+ DmaOperation - Supplies a boolean value that determines whether the I/O
+ operation is a DMA operation.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG CacheSegment;
+ ULONG Length;
+ ULONG Offset;
+ PULONG PageFrame;
+ ULONG Address;
+ volatile ULONG i;
+ volatile ULONG j;
+
+ if (DmaOperation!=FALSE) {
+
+ HalpMb(); // force all previous writes off chip
+
+ Offset = Mdl->ByteOffset;
+ Length = Mdl->ByteCount;
+ PageFrame = (PULONG)(Mdl + 1);
+
+ //
+ // Export or purge the specified page segments from the data and
+ // instruction caches as appropriate.
+ //
+
+ do {
+ if (Length >= (PAGE_SIZE - Offset)) {
+ CacheSegment = PAGE_SIZE - Offset;
+ } else {
+ CacheSegment = Length;
+ }
+
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+
+ Address = ((*PageFrame << PAGE_SHIFT) + Offset) & 0x001fffc0;
+ j = *(volatile ULONG *)((ULONG)HalpCacheFlushBase+Address);
+ Address = ((*PageFrame << PAGE_SHIFT) + Offset + 0x40) & 0x001fffc0;
+ j = *(volatile ULONG *)((ULONG)HalpCacheFlushBase+Address);
+ Address = ((*PageFrame << PAGE_SHIFT) + CacheSegment - 1) & 0x001fffc0;
+ j = *(volatile ULONG *)((ULONG)HalpCacheFlushBase+Address);
+
+ } else {
+
+ Address = ((*PageFrame << PAGE_SHIFT) + Offset) & 0x000fffe0;
+ j = *(volatile ULONG *)((ULONG)HalpCacheFlushBase+Address);
+ Address = ((*PageFrame << PAGE_SHIFT) + CacheSegment - 1) & 0x000fffe0;
+ j = *(volatile ULONG *)((ULONG)HalpCacheFlushBase+Address);
+ }
+
+ PageFrame += 1;
+ Length -= CacheSegment;
+ Offset = 0;
+ } while(Length != 0);
+ }
+
+ //
+ // The Dcache coherency is maintained in hardware. The Icache coherency
+ // is maintained by invalidating the istream on page read operations.
+ //
+ HalpMb(); // synchronize this processors view of memory
+ if (ReadOperation) {
+ HalpMb(); // not issued until previous mb completes
+ if (Mdl->MdlFlags & MDL_IO_PAGE_READ) {
+
+ //
+ // The operation is a page read, thus the istream must
+ // be flushed.
+ //
+ HalpImb();
+ }
+ }
+}
+
+
+
+VOID
+HalPurgeDcachePage (
+ IN PVOID Color,
+ IN ULONG PageFrame,
+ IN ULONG Length
+ )
+/*++
+Routine Description:
+
+ This function purges (invalidates) up to a page of data from the
+ data cache.
+
+Arguments:
+
+ Color - Supplies the starting virtual address and color of the
+ data that is purged.
+
+ PageFrame - Supplies the page frame number of the page that
+ is purged.
+
+ Length - Supplies the length of the region in the page that is
+ purged.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ return;
+}
+
+
+VOID
+HalPurgeIcachePage (
+ IN PVOID Color,
+ IN ULONG PageFrame,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ This function purges (invalidates) up to a page fo data from the
+ instruction cache.
+
+Arguments:
+
+ Color - Supplies the starting virtual address and color of the
+ data that is purged.
+
+ PageFrame - Supplies the page frame number of the page that
+ is purged.
+
+ Length - Supplies the length of the region in the page that is
+ purged.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // The call to HalpImb calls PAL to flush the Icache, which ensures that
+ // any stale hits will be invalidated
+ //
+ HalpImb;
+}
+
+VOID
+HalSweepDcache (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function sweeps (invalidates) the entire data cache.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ return;
+}
+
+VOID
+HalSweepDcacheRange (
+ IN PVOID BaseAddress,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ This function flushes the specified range of addresses from the data
+ cache on the current processor.
+
+Arguments:
+
+ BaseAddress - Supplies the starting physical address of a range of
+ physical addresses that are to be flushed from the data cache.
+
+ Length - Supplies the length of the range of physical addresses
+ that are to be flushed from the data cache.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ return;
+}
+
+VOID
+HalSweepIcache (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function sweeps (invalidates) the entire instruction cache.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // The call to HalpImb calls PAL to flush the Icache, which ensures that
+ // any stale hits will be invalidated
+ //
+ HalpImb;
+ return;
+}
+
+VOID
+HalSweepIcacheRange (
+ IN PVOID BaseAddress,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ This function flushes the specified range of addresses from the
+ instruction cache on the current processor.
+
+Arguments:
+
+ BaseAddress - Supplies the starting physical address of a range of
+ physical addresses that are to be flushed from the instruction cache.
+
+ Length - Supplies the length of the range of physical addresses
+ that are to be flushed from the instruction cache.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // The call to HalpImb calls PAL to flush the Icache, which ensures that
+ // any stale hits will be invalidated
+ //
+ HalpImb;
+
+}
+
+VOID
+KeFlushWriteBuffer (
+ VOID
+ )
+
+{
+ //
+ // We flush the write buffer by doing a series of memory
+ // barrier operations. It still isn't clear if we need
+ // to do two/four of them to flush the buffer, or if one
+ // to order the writes is suffcient
+ //
+
+ HalpMb;
+ return;
+}
+
+VOID
+KeFlushDcache (
+ IN BOOLEAN AllProcessors,
+ IN PVOID BaseAddress OPTIONAL,
+ IN ULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This function flushes the data cache on all processors that are currently
+ running threads which are children of the current process or flushes the
+ data cache on all processors in the host configuration.
+
+Arguments:
+
+ AllProcessors - Supplies a boolean value that determines which data
+ caches are flushed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UNREFERENCED_PARAMETER(BaseAddress);
+ UNREFERENCED_PARAMETER(Length);
+
+ HalFlushDcache(AllProcessors);
+ return;
+}
+
+VOID
+HalFlushDcache (
+ IN BOOLEAN AllProcessors
+ )
+
+/*++
+
+Routine Description:
+
+ This function flushes the data cache on all processors that are currently
+ running threads which are children of the current process or flushes the
+ data cache on all processors in the host configuration.
+
+Arguments:
+
+ AllProcessors - Supplies a boolean value that determines which data
+ caches are flushed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Sweep (index/writeback/invalidate) the data cache.
+ //
+
+ HalSweepDcache();
+ return;
+}
+
+ULONG
+HalGetDmaAlignmentRequirement (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the alignment requirements for DMA transfers on
+ host system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The DMA alignment requirement is returned as the fucntion value.
+
+--*/
+
+{
+// if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+// return 0x40;
+// } else {
+// return 0x20;
+// }
+
+ //
+ // Checked builds will not run with an alignment other than 0x08. It generated assertions
+ // when buffers are not aligned correctly and this sometimes happens on the ALPHA builds.
+ // However, SCSI Tape device will not work unless the alignment value is correct. So,
+ // for right now SCSI Tape devices can not be used with a checked build.
+ //
+ // Free builds do not have the assertions for unaligned buffers, so we can set the
+ // alignment value to the systems actual cache line size. This means that SCSI Tape
+ // devices will work with a free build and a free HAL.
+ //
+
+#ifdef DEBUG
+ return 0x08;
+#else
+ return 0x40;
+#endif
+}
diff --git a/private/ntos/nthals/halflex/alpha/evxmem.s b/private/ntos/nthals/halflex/alpha/evxmem.s
new file mode 100644
index 000000000..532a67b6a
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/evxmem.s
@@ -0,0 +1,231 @@
+// TITLE("EV4 Memory Operations")
+//++
+//
+// Copyright (C) 1994,1995 Digital Equipment Corporation
+//
+// Module Name:
+//
+// ev4mem.s
+//
+// Abstract:
+//
+// This module implements EV4 memory operations that require assembly
+// language.
+//
+// Environment:
+//
+// HAL, Kernel mode only.
+//
+//
+//
+//--
+
+#include "ksalpha.h"
+
+#define ZERO_BLOCK_SIZE (256)
+#define ZERO_LOOPS (PAGE_SIZE/ZERO_BLOCK_SIZE)
+
+//++
+//
+// VOID
+// HalEV4ZeroPage (
+// IN PVOID NewColor,
+// IN PVOID OldColor,
+// IN ULONG PageFrame
+// )
+//
+// Routine Description:
+//
+// This function zeros a page of memory.
+//
+// Arguments:
+//
+// NewColor (a0) - Supplies the page aligned virtual address of the
+// new color of the page that is zeroed.
+//
+// OldColor (a1) - Supplies the page aligned virtual address of the
+// old color of the page that is zeroed.
+//
+// PageFrame (a2) - Supplies the page frame number of the page that
+// is zeroed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalZeroPage)
+
+ ldl t0, HalpIoArchitectureType
+ beq t0, HalpEV5ZeroPage
+
+HalpEV4ZeroPage:
+
+ .set noreorder // hand scheduled
+
+//
+// Map the page via the 43-bit super-page on EV4.
+//
+
+ ldiq t0, -0x4000 // 0xffff ffff ffff c000
+ sll a2, PAGE_SHIFT, t1 // physical address of page
+
+ sll t0, 28, t0 // 0xffff fc00 0000 0000
+ ldil t2, ZERO_LOOPS // set count of loops to run
+
+ bis t0, t1, t0 // set super-page enable + physical
+ bis zero, zero, zero // for branch alignment
+
+//
+// Zero the page in a loop, zeroing 256 bytes per iteration. This number
+// was chosen to tradeoff loop overhead versus the overhead of fetching
+// Icache blocks.
+//
+
+10:
+ stq zero, 0x00(t0) //
+ subl t2, 1, t2 // decrement the loop count
+
+ stq zero, 0x08(t0) //
+ stt f31, 0x10(t0) //
+
+ stq zero, 0x18(t0) //
+ stt f31, 0x20(t0) //
+
+ stq zero, 0x28(t0) //
+ stt f31, 0x30(t0) //
+
+ stq zero, 0x38(t0) //
+ stt f31, 0x40(t0) //
+
+ stq zero, 0x48(t0) //
+ stt f31, 0x50(t0) //
+
+ stq zero, 0x58(t0) //
+ stt f31, 0x60(t0) //
+
+ stq zero, 0x68(t0) //
+ stt f31, 0x70(t0) //
+
+ stq zero, 0x78(t0) //
+ stt f31, 0x80(t0) //
+
+ stq zero, 0x88(t0) //
+ stt f31, 0x90(t0) //
+
+ stq zero, 0x98(t0) //
+ stt f31, 0xa0(t0) //
+
+ stq zero, 0xa8(t0) //
+ stt f31, 0xb0(t0) //
+
+ bis t0, zero, t1 // copy base register
+ stq zero, 0xb8(t0) //
+
+ stq zero, 0xc0(t0) //
+ stt f31, 0xc8(t0) //
+
+ stq zero, 0xd0(t0) //
+ stt f31, 0xd8(t0) //
+
+ stq zero, 0xe0(t0) //
+ lda t0, 0x100(t0) // increment to next block
+
+ stq zero, 0xe8(t1) //
+ stt f31, 0xf0(t1) //
+
+ stt f31, 0xf8(t1) // use stt for dual issue with bne
+ bne t2, 10b // while count > 0
+
+ ret zero, (ra) // return
+
+
+ .set reorder //
+
+HalpEV5ZeroPage:
+
+ .set noreorder // hand scheduled
+
+//
+// Map the page via the 43-bit super-page on EV5.
+//
+
+ ldiq t0, -0x4000 // 0xffff ffff ffff c000
+ sll a2, PAGE_SHIFT, t1 // physical address of page
+
+ sll t0, 28, t0 // 0xffff fc00 0000 0000
+ ldil t2, ZERO_LOOPS // set count of loops to run
+
+ bis t0, t1, t0 // set super-page enable + physical
+ br zero, 10f // start the zeroing
+
+//
+// Zero the page in a loop, zeroing 256 bytes per iteration. This number
+// was chosen to tradeoff loop overhead versus the overhead of fetching
+// Icache blocks.
+//
+
+ .align 4 // align as branch target
+10:
+ stq zero, 0x00(t0) //
+ subl t2, 1, t2 // decrement the loop count
+
+ stq zero, 0x08(t0) //
+ stq zero, 0x10(t0) //
+
+ stq zero, 0x18(t0) //
+ stq zero, 0x20(t0) //
+
+ stq zero, 0x28(t0) //
+ stq zero, 0x30(t0) //
+
+ stq zero, 0x38(t0) //
+ stq zero, 0x40(t0) //
+
+ stq zero, 0x48(t0) //
+ stq zero, 0x50(t0) //
+
+ stq zero, 0x58(t0) //
+ stq zero, 0x60(t0) //
+
+ stq zero, 0x68(t0) //
+ stq zero, 0x70(t0) //
+
+ stq zero, 0x78(t0) //
+ stq zero, 0x80(t0) //
+
+ stq zero, 0x88(t0) //
+ stq zero, 0x90(t0) //
+
+ stq zero, 0x98(t0) //
+ stq zero, 0xa0(t0) //
+
+ stq zero, 0xa8(t0) //
+ stq zero, 0xb0(t0) //
+
+ stq zero, 0xb8(t0) //
+ bis t0, zero, t1 // copy base register
+
+ stq zero, 0xc0(t0) //
+ stq zero, 0xc8(t0) //
+
+ stq zero, 0xd0(t0) //
+ stq zero, 0xd8(t0) //
+
+ stq zero, 0xe0(t0) //
+ lda t0, 0x100(t0) // increment to next block
+
+ stq zero, 0xe8(t1) //
+ stq zero, 0xf0(t1) //
+
+ stq zero, 0xf8(t1) // use stt for dual issue with bne
+ bne t2, 10b // while count > 0
+
+ ret zero, (ra) // return
+
+
+ .set reorder //
+
+ .end HalZeroPage
+
diff --git a/private/ntos/nthals/halflex/alpha/evxprof.c b/private/ntos/nthals/halflex/alpha/evxprof.c
new file mode 100644
index 000000000..4e296e5fc
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/evxprof.c
@@ -0,0 +1,342 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ evxprof.c
+
+Abstract:
+
+ This module implements the Profile Counter using the performance
+ counters within the EV5 core. This module is appropriate for all
+ machines based on microprocessors using the EV5 core.
+
+ N.B. - This module assumes that all processors in a multiprocessor
+ system are running the microprocessor at the same clock speed.
+
+Author:
+
+ Michael D. Kinney 14-Aug-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+BOOLEAN
+Hal21064QueryProfileInterval(
+ IN KPROFILE_SOURCE Source
+ );
+
+BOOLEAN
+Hal21164QueryProfileInterval(
+ IN KPROFILE_SOURCE Source
+ );
+
+NTSTATUS
+Hal21064SetProfileSourceInterval(
+ IN KPROFILE_SOURCE ProfileSource,
+ IN OUT ULONG *Interval
+ );
+
+NTSTATUS
+Hal21164SetProfileSourceInterval(
+ IN KPROFILE_SOURCE ProfileSource,
+ IN OUT ULONG *Interval
+ );
+
+ULONG
+Hal21064SetProfileInterval (
+ IN ULONG Interval
+ );
+
+ULONG
+Hal21164SetProfileInterval (
+ IN ULONG Interval
+ );
+
+VOID
+Hal21064StartProfileInterrupt (
+ KPROFILE_SOURCE ProfileSource
+ );
+
+VOID
+Hal21164StartProfileInterrupt (
+ KPROFILE_SOURCE ProfileSource
+ );
+
+VOID
+Hal21064StopProfileInterrupt (
+ KPROFILE_SOURCE ProfileSource
+ );
+
+VOID
+Hal21164StopProfileInterrupt (
+ KPROFILE_SOURCE ProfileSource
+ );
+
+
+BOOLEAN
+HalQueryProfileInterval(
+ IN KPROFILE_SOURCE Source
+ )
+
+/*++
+
+Routine Description:
+
+ Given a profile source, returns whether or not that source is
+ supported.
+
+Arguments:
+
+ Source - Supplies the profile source
+
+Return Value:
+
+ TRUE - Profile source is supported
+
+ FALSE - Profile source is not supported
+
+--*/
+
+{
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+ return(Hal21164QueryProfileInterval(Source));
+ } else {
+ return(Hal21064QueryProfileInterval(Source));
+ }
+}
+
+
+NTSTATUS
+HalSetProfileSourceInterval(
+ IN KPROFILE_SOURCE ProfileSource,
+ IN OUT ULONG *Interval
+ )
+
+/*++
+
+Routine Description:
+
+ Sets the profile interval for a specified profile source
+
+Arguments:
+
+ ProfileSource - Supplies the profile source
+
+ Interval - Supplies the specified profile interval
+ Returns the actual profile interval
+
+Return Value:
+
+ NTSTATUS
+
+--*/
+
+{
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+ return(Hal21164SetProfileSourceInterval(ProfileSource,Interval));
+ } else {
+ return(Hal21064SetProfileSourceInterval(ProfileSource,Interval));
+ }
+}
+
+
+ULONG
+HalSetProfileInterval (
+ IN ULONG Interval
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the profile interrupt interval.
+
+Arguments:
+
+ Interval - Supplies the desired profile interval in 100ns units.
+
+Return Value:
+
+ The actual profile interval.
+
+--*/
+
+{
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+ return(Hal21164SetProfileInterval(Interval));
+ } else {
+ return(Hal21064SetProfileInterval(Interval));
+ }
+}
+
+
+
+VOID
+HalStartProfileInterrupt (
+ KPROFILE_SOURCE ProfileSource
+ )
+
+/*++
+
+Routine Description:
+
+ This routine turns on the profile interrupt.
+
+ N.B. This routine must be called at PROCLK_LEVEL while holding the
+ profile lock.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+ Hal21164StartProfileInterrupt(ProfileSource);
+ } else {
+ Hal21064StartProfileInterrupt(ProfileSource);
+ }
+}
+
+
+VOID
+HalStopProfileInterrupt (
+ KPROFILE_SOURCE ProfileSource
+ )
+
+/*++
+
+Routine Description:
+
+ This routine turns off the profile interrupt.
+
+ N.B. This routine must be called at PROCLK_LEVEL while holding the
+ profile lock.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+ Hal21164StopProfileInterrupt(ProfileSource);
+ } else {
+ Hal21064StopProfileInterrupt(ProfileSource);
+ }
+}
+
+
+VOID
+HalpInitializeProfiler(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is called during initialization to initialize profiling
+ for each processor in the system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+ Halp21164InitializeProfiler();
+ } else {
+ Halp21064InitializeProfiler();
+ }
+}
+
+NTSTATUS
+HalpProfileSourceInformation (
+ OUT PVOID Buffer,
+ IN ULONG BufferLength,
+ OUT PULONG ReturnedLength
+ )
+/*++
+
+Routine Description:
+
+ Returns the HAL_PROFILE_SOURCE_INFORMATION for this processor.
+
+Arguments:
+
+ Buffer - output buffer
+ BufferLength - length of buffer on input
+ ReturnedLength - The length of data returned
+
+Return Value:
+
+ STATUS_SUCCESS
+ STATUS_BUFFER_TOO_SMALL - The ReturnedLength contains the buffersize
+ currently needed.
+
+--*/
+
+{
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+ return(Halp21164ProfileSourceInformation(Buffer,BufferLength,ReturnedLength));
+ } else {
+ return(Halp21064ProfileSourceInformation(Buffer,BufferLength,ReturnedLength));
+ }
+}
+
+NTSTATUS
+HalpProfileSourceInterval (
+ OUT PVOID Buffer,
+ IN ULONG BufferLength
+ )
+/*++
+
+Routine Description:
+
+ Returns the HAL_PROFILE_SOURCE_INTERVAL for this processor.
+
+Arguments:
+
+ Buffer - output buffer
+ BufferLength - length of buffer on input
+
+Return Value:
+
+ STATUS_SUCCESS
+ STATUS_BUFFER_TOO_SMALL - The ReturnedLength contains the buffersize
+ currently needed.
+
+--*/
+
+{
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+ return(Halp21164ProfileSourceInterval(Buffer,BufferLength));
+ } else {
+ return(Halp21064ProfileSourceInterval(Buffer,BufferLength));
+ }
+}
diff --git a/private/ntos/nthals/halflex/alpha/halpal.s b/private/ntos/nthals/halflex/alpha/halpal.s
new file mode 100644
index 000000000..d34a29084
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/halpal.s
@@ -0,0 +1,276 @@
+// TITLE("Alpha PAL funtions for HAL")
+//++
+//
+// Copyright (c) 1992 Digital Equipment Corporation
+// Copyright (c) 1993 Digital Equipment Corporation
+//
+// Module Name:
+//
+// halpal.s
+//
+// Abstract:
+//
+// This module implements routines to call PAL functions
+// from the Hal.
+//
+//
+// Author:
+//
+// Jeff McLeman (mcleman) 09-Jul-1992
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+// 13-Jul-1992 Jeff McLeman (mcleman)
+// add HalpMb to functions.
+//
+// 14-Dec-1993 Joe Notarangelo
+// use new encoding to return to firmware: HalpReboot instead of
+// HalpHalt
+//--
+
+#include "halalpha.h"
+
+//++
+//
+// VOID
+// HalpReboot(
+// )
+//
+// Routine Description:
+//
+// This function merely calls the PAL to reboot the Alpha processor.
+// This is used to restart the console firmware. (Note, MIPS does
+// not have a HALT instruction, so there had to be a mechanism to
+// restart the firware. Alpha merely reboots, which causes a jump
+// to firmware PAL, which restarts the firmware.)
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpReboot)
+
+ REBOOT // call the PAL to reboot
+
+ .end HalpReboot
+
+//++
+//
+// VOID
+// HalpSwppal(
+// )
+//
+// Routine Description:
+//
+// This function merely calls the PAL to issue a SWPPAL
+// on the Alpha processor...
+//
+// Arguments:
+//
+// a0 The physical address to do the Swappal to.
+// a1 -- a5 Any other arguments to the PALcode.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSwppal)
+
+ SWPPAL // call the PAL to do a swap_pal
+
+ ret zero,(ra)
+
+ .end HalpSwppal
+
+
+//++
+//
+// VOID
+// HalpImb(
+// )
+//
+// Routine Description:
+//
+// This function merely calls the PAL to issue an Instruction
+// Memory Barrier on the Alpha processor..
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpImb)
+
+ IMB // call the PAL to do an IMB
+
+ ret zero,(ra)
+
+ .end HalpImb
+
+
+//++
+//
+// VOID
+// HalpMb(
+// )
+//
+// Routine Description:
+//
+// This function merely calls the PAL to issue a general
+// Memory Barrier on the Alpha processor..
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpMb)
+
+ mb // memory barrier
+
+ ret zero, (ra)
+
+ .end HalpMb
+
+//++
+//
+// VOID
+// HalpCachePcrValues(
+// )
+//
+// Routine Description:
+//
+// This function merely calls the PAL to cache values in the
+// PCR for faster access.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpCachePcrValues)
+
+ CACHE_PCR_VALUES // call the palcode
+
+ ret zero,(ra)
+
+ .end HalpCachePcrValues
+//++
+//
+// ULONG
+// HalpRpcc(
+// )
+//
+// Routine Description:
+//
+// This function executes the RPCC (read processor cycle counter)
+// instruction.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// The low-order 32 bits of the processor cycle counter is returned
+// as the function value.
+// N.B. At 125 MHz this counter wraps about every 30 seconds. It is
+// the caller's responsibility to deal with overflow or wraparound.
+//
+//--
+
+ LEAF_ENTRY(HalpRpcc)
+
+ rpcc v0 // get rpcc value
+ addl v0, zero, v0 // extend
+
+ ret zero, (ra) // return
+
+ .end HalpRpcc
+
+
+//++
+//
+// MCES
+// HalpReadMces(
+// VOID
+// )
+//
+// Routine Description:
+//
+// Read the state of the MCES (Machine Check Error Summary)
+// internal processor register.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// v0 - Current MCES value.
+//--
+
+ LEAF_ENTRY(HalpReadMces)
+
+ GET_MACHINE_CHECK_ERROR_SUMMARY // v0 = current value
+
+ ret zero, (ra) // return
+
+ .end HalpReadMces
+
+
+//++
+//
+// MCES
+// HalpWriteMces(
+// IN MCES Mces
+// )
+//
+// Routine Description:
+//
+// Update the current value of the MCES internal processor register.
+//
+// Arguments:
+//
+// Mces(a0) - Supplies the new value for the MCES register.
+//
+// Return Value:
+//
+// v0 - Previous MCES value.
+//
+//--
+
+ LEAF_ENTRY(HalpWriteMces)
+
+ WRITE_MACHINE_CHECK_ERROR_SUMMARY // v0 = previous value
+
+ ret zero, (ra) // return
+
+ .end HalpWriteMces
diff --git a/private/ntos/nthals/halflex/alpha/info.c b/private/ntos/nthals/halflex/alpha/info.c
new file mode 100644
index 000000000..02e46848b
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/info.c
@@ -0,0 +1,128 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ info.c
+
+Abstract:
+
+Author:
+
+ Ken Reneris (kenr) 08-Aug-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+
+#include "halp.h"
+
+#ifdef _PNP_POWER_
+HAL_CALLBACKS HalCallback;
+#endif // _PNP_POWER_
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HaliQuerySystemInformation)
+#pragma alloc_text(PAGE,HaliSetSystemInformation)
+#endif
+
+
+NTSTATUS
+HaliQuerySystemInformation(
+ IN HAL_QUERY_INFORMATION_CLASS InformationClass,
+ IN ULONG BufferSize,
+ OUT PVOID Buffer,
+ OUT PULONG ReturnedLength
+ )
+/*++
+
+Routine Description:
+
+ The function returns system-wide information controlled by the HAL for a
+ variety of classes.
+
+Arguments:
+
+ InformationClass - Information class of the request.
+
+ BufferSize - Size of buffer supplied by the caller.
+
+ Buffer - Supplies the space to store the data.
+
+ ReturnedLength - Supplies a count in bytes of the amount of data returned.
+
+Return Value:
+
+ STATUS_SUCCESS or error.
+
+--*/
+{
+ NTSTATUS Status;
+
+ switch (InformationClass) {
+ case HalProfileSourceInformation:
+ Status = HalpProfileSourceInformation (
+ Buffer,
+ BufferSize,
+ ReturnedLength);
+ break;
+
+ default:
+ Status = STATUS_INVALID_LEVEL;
+ break;
+ }
+
+ return(Status);
+}
+
+NTSTATUS
+HaliSetSystemInformation (
+ IN HAL_SET_INFORMATION_CLASS InformationClass,
+ IN ULONG BufferSize,
+ IN PVOID Buffer
+ )
+/*++
+
+Routine Description:
+
+ The function allows setting of various fields return by
+ HalQuerySystemInformation.
+
+Arguments:
+
+ InformationClass - Information class of the request.
+
+ BufferSize - Size of buffer supplied by the caller.
+
+ Buffer - Supplies the data to be set.
+
+Return Value:
+
+ STATUS_SUCCESS or error.
+
+--*/
+{
+ NTSTATUS Status;
+
+ switch (InformationClass) {
+
+ case HalProfileSourceInterval:
+ Status = HalpProfileSourceInterval (
+ Buffer,
+ BufferSize);
+ break;
+
+ default:
+ Status = STATUS_INVALID_LEVEL;
+ break;
+ }
+
+ return Status;
+}
diff --git a/private/ntos/nthals/halflex/alpha/initsys.c b/private/ntos/nthals/halflex/alpha/initsys.c
new file mode 100644
index 000000000..de6d38930
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/initsys.c
@@ -0,0 +1,579 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ initsys.c
+
+Abstract:
+
+ This module implements the platform specific portions of the
+ HAL initialization.
+
+Author:
+
+ Michael D. Kinney 3-May-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+
+//
+// Type Declarations
+//
+
+typedef
+VOID
+(*POPERATING_SYSTEM_STARTED) (
+ VOID
+ );
+
+//
+// Define global data used to determine the type of system I/O architecture to use.
+//
+
+ULONG HalpIoArchitectureType = UNKNOWN_PROCESSOR_MODULE;
+
+//
+// Define global data used to calibrate and stall processor execution.
+//
+
+ULONG HalpProfileCountRate;
+
+ULONG IoSpaceAlreadyMapped = FALSE;
+ULONG HalpModuleChipSetRevision = MODULE_CHIP_SET_REVISION_UNKNOWN;
+BOOLEAN HalpModuleHardwareFlushing;
+UCHAR HalpSecondPciBridgeBusNumber = 2;
+ULONG HalpMotherboardType = MOTHERBOARD_UNKNOWN;
+UCHAR *HalpInterruptLineToBit;
+UCHAR *HalpBitToInterruptLine;
+UCHAR *HalpInterruptLineToVirtualIsa;
+UCHAR *HalpVirtualIsaToInterruptLine;
+ULONGLONG HalpNoncachedDenseBasePhysicalSuperPage;
+ULONGLONG HalpPciDenseBasePhysicalSuperPage;
+ULONGLONG HalpPciConfig0BasePhysical;
+ULONGLONG HalpPciConfig1BasePhysical;
+ULONGLONG HalpIsaIoBasePhysical;
+ULONGLONG HalpIsa1IoBasePhysical;
+ULONGLONG HalpIsaMemoryBasePhysical;
+ULONGLONG HalpIsa1MemoryBasePhysical;
+ULONGLONG HalpPciIoBasePhysical;
+ULONGLONG HalpPci1IoBasePhysical;
+ULONGLONG HalpPciMemoryBasePhysical;
+ULONGLONG HalpPci1MemoryBasePhysical;
+PPLATFORM_RANGE_LIST HalpRangeList = NULL;
+ULONG HalpIntel82378BusNumber = 0;
+ULONG HalpIntel82378DeviceNumber = 0;
+ULONG HalpSecondIntel82378DeviceNumber = 0;
+ULONG HalpNonExistentPciDeviceMask = ~TREB20_MOTHERBOARD_PCI_DEVICE_MASK;
+ULONG HalpNonExistentPci1DeviceMask = 0;
+ULONG HalpNonExistentPci2DeviceMask = 0;
+ULONG HalpNumberOfIsaBusses;
+ULONG HalpVgaDecodeBusNumber;
+
+//
+// Function prototypes.
+//
+
+VOID
+HalpGetPlatformParameterBlock(
+ VOID
+ );
+
+ULONG FindIntel82378(ULONG Dec2105xBusNumber,ULONG Dec2105xDeviceNumber,ULONG BusNumber,ULONG IsaBusNumber)
+
+{
+ ULONG i;
+ ULONG MaxDevice;
+
+ if (BusNumber == 0) {
+ MaxDevice = PCI_MAX_LOCAL_DEVICE;
+ } else {
+ MaxDevice = 31;
+ }
+ for(i=0;i<=MaxDevice;i++) {
+
+ if (HalpPciLowLevelConfigRead(BusNumber,i,0,0) == 0x04848086) {
+ return(i);
+ }
+ }
+ return(0);
+ }
+
+VOID
+HalpGetIoArchitectureType(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function gets the I/O Architecture Type from the Platform Parameter Block
+ retrieved from the firmware.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG Device16;
+ ULONG Device17;
+
+ //
+ // If the I/O Architecture Type is already known, then just return.
+ //
+
+ if (HalpIoArchitectureType != UNKNOWN_PROCESSOR_MODULE) {
+ return;
+ }
+
+ //
+ // If the Platform Parameter Block has not been retrieved from the firmware,
+ // then do it now.
+ //
+
+ if (HalpPlatformParameterBlock == NULL) {
+ HalpGetPlatformParameterBlock();
+ }
+
+ //
+ // Check for the 21164(EV5) Apocolypse Module Type.
+ //
+
+ if (strcmp(HalpPlatformParameterBlock->ModuleName,"APOCALYPSE1.0")==0) {
+ HalpIoArchitectureType = EV5_PROCESSOR_MODULE;
+ }
+
+ //
+ // Check for the 21064(EV4) Rogue Module Type.
+ //
+
+ if (strcmp(HalpPlatformParameterBlock->ModuleName,"ROGUE2.0")==0) {
+ HalpIoArchitectureType = EV4_PROCESSOR_MODULE;
+ }
+
+ //
+ // If the I/O Architecture Type is still unknown then HALT.
+ //
+
+ if (HalpIoArchitectureType == UNKNOWN_PROCESSOR_MODULE) {
+ for(;;);
+ }
+
+ //
+ // Get the processor module's chip set revision.
+ //
+
+ HalpModuleChipSetRevision = HalpGetModuleChipSetRevision();
+
+ //
+ // Limit the chip set revision to the highest one allowed by this HAL.
+ //
+
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE && HalpModuleChipSetRevision > EV5_MAX_CHIP_SET_REVISION) {
+ HalpModuleChipSetRevision = EV5_MAX_CHIP_SET_REVISION;
+ }
+
+ if (HalpIoArchitectureType == EV4_PROCESSOR_MODULE && HalpModuleChipSetRevision > EV4_MAX_CHIP_SET_REVISION) {
+ HalpModuleChipSetRevision = EV4_MAX_CHIP_SET_REVISION;
+ }
+
+ //
+ // See if the module chip set supports hardware flushing.
+ //
+
+ HalpModuleHardwareFlushing = TRUE;
+
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+ switch (HalpModuleChipSetRevision) {
+ case 0 : HalpModuleHardwareFlushing = FALSE;
+ break;
+ }
+ }
+
+ //
+ // Determine base physical address of Dense PCI Space and the PCI Configuration Spaces
+ //
+
+ if (HalpIoArchitectureType == EV4_PROCESSOR_MODULE) {
+ HalpNoncachedDenseBasePhysicalSuperPage = ROGUE_NONCACHED_DENSE_BASE_PHYSICAL_SUPERPAGE;
+ HalpPciDenseBasePhysicalSuperPage = ROGUE_PCI_DENSE_BASE_PHYSICAL_SUPERPAGE;
+ HalpPciConfig0BasePhysical = ROGUE_PCI_CONFIG0_BASE_PHYSICAL;
+ HalpPciConfig1BasePhysical = ROGUE_PCI_CONFIG1_BASE_PHYSICAL;
+ }
+
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE && (HalpModuleChipSetRevision==0 || HalpModuleChipSetRevision==1)) {
+ HalpNoncachedDenseBasePhysicalSuperPage = APOC1_NONCACHED_DENSE_BASE_PHYSICAL_SUPERPAGE;
+ HalpPciDenseBasePhysicalSuperPage = APOC1_PCI_DENSE_BASE_PHYSICAL_SUPERPAGE;
+ HalpPciConfig0BasePhysical = APOC1_PCI_CONFIG0_BASE_PHYSICAL;
+ HalpPciConfig1BasePhysical = APOC1_PCI_CONFIG1_BASE_PHYSICAL;
+ }
+
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE && HalpModuleChipSetRevision==2) {
+ HalpNoncachedDenseBasePhysicalSuperPage = APOC2_NONCACHED_DENSE_BASE_PHYSICAL_SUPERPAGE;
+ HalpPciDenseBasePhysicalSuperPage = APOC2_PCI_DENSE_BASE_PHYSICAL_SUPERPAGE;
+ HalpPciConfig0BasePhysical = APOC2_PCI_CONFIG0_BASE_PHYSICAL;
+ HalpPciConfig1BasePhysical = APOC2_PCI_CONFIG1_BASE_PHYSICAL;
+ }
+
+ //
+ // Determine the motherboard type. Assume TREBBIA20 so we can do some config cycles.
+ //
+
+ HalpMotherboardType = TREBBIA20;
+
+ Device16 = HalpPciLowLevelConfigRead(0,0x10,0,0);
+ Device17 = HalpPciLowLevelConfigRead(0,0x11,0,0);
+
+ //
+ // Now assume motherboard type is unknown and check out values returned from config cycles.
+ //
+
+ HalpMotherboardType = MOTHERBOARD_UNKNOWN;
+
+ if (Device16 == 0x00211011 && Device17 == 0x00211011) {
+ HalpMotherboardType = TREBBIA20;
+
+ //
+ // Find and initialize up to two Jubilee adapters.
+ //
+
+ HalpNumberOfIsaBusses = 1;
+ HalpIntel82378BusNumber = 1;
+ HalpIntel82378DeviceNumber = FindIntel82378(0,0x11,1,0);
+ HalpSecondPciBridgeBusNumber = (UCHAR)((HalpPciLowLevelConfigRead(0,0x10,0,0x18) >> 8) & 0xff);
+ HalpSecondIntel82378DeviceNumber = FindIntel82378(0,0x10,HalpSecondPciBridgeBusNumber,1);
+ if (HalpSecondIntel82378DeviceNumber != 0) {
+ HalpNumberOfIsaBusses = 2;
+ }
+ HalpVgaDecodeBusNumber = 0x00;
+ if (HalpPciLowLevelConfigRead(0,0x11,0,0x3c) & 0x00080000) {
+ HalpVgaDecodeBusNumber |= 0x01;
+ }
+ if (HalpPciLowLevelConfigRead(0,0x10,0,0x3c) & 0x00080000) {
+ HalpVgaDecodeBusNumber |= 0x02;
+ }
+ }
+
+ if (Device16 == 0x04848086 && Device17 == 0x00011011) {
+ HalpMotherboardType = TREBBIA13;
+ HalpNumberOfIsaBusses = 1;
+ HalpIntel82378BusNumber = 0;
+ HalpIntel82378DeviceNumber = 0x10;
+ HalpVgaDecodeBusNumber = 0x01;
+ if (HalpPciLowLevelConfigRead(0,0x11,0,0x3c) & 0x00080000) {
+ HalpVgaDecodeBusNumber |= 0x02;
+ }
+ }
+
+ //
+ // If the Motherboard Type is unknown then HALT.
+ //
+
+ if (HalpMotherboardType == MOTHERBOARD_UNKNOWN) {
+ for(;;);
+ }
+
+ //
+ // Determine the PCI interrupt translation tables.
+ //
+
+ if (HalpMotherboardType == TREBBIA13) {
+ HalpNonExistentPciDeviceMask = ~TREB13_MOTHERBOARD_PCI_DEVICE_MASK;
+ HalpNonExistentPci1DeviceMask = 0;
+ HalpNonExistentPci2DeviceMask = 0;
+ HalpInterruptLineToBit = Treb13InterruptLineToBit;
+ HalpBitToInterruptLine = Treb13BitToInterruptLine;
+ HalpInterruptLineToVirtualIsa = Treb13InterruptLineToVirtualIsa;
+ HalpVirtualIsaToInterruptLine = Treb13VirtualIsaToInterruptLine;
+ if (HalpPlatformParameterBlock->FirmwareRevision >= 50) {
+ if (!((TREB13SETUPINFO *)(HalpPlatformSpecificExtension->AdvancedSetupInfo))->EnableAmd1) {
+ HalpNonExistentPciDeviceMask |= (1 << 0x0d);
+ }
+ if (!((TREB13SETUPINFO *)(HalpPlatformSpecificExtension->AdvancedSetupInfo))->EnableAmd2) {
+ HalpNonExistentPciDeviceMask |= (1 << 0x0f);
+ }
+ }
+ }
+ if (HalpMotherboardType == TREBBIA20) {
+ HalpNonExistentPciDeviceMask = ~TREB20_MOTHERBOARD_PCI_DEVICE_MASK;
+ HalpNonExistentPci1DeviceMask = 0;
+ HalpNonExistentPci2DeviceMask = 0;
+ HalpInterruptLineToBit = Treb20InterruptLineToBit;
+ HalpBitToInterruptLine = Treb20BitToInterruptLine;
+ HalpInterruptLineToVirtualIsa = Treb20InterruptLineToVirtualIsa;
+ HalpVirtualIsaToInterruptLine = Treb20VirtualIsaToInterruptLine;
+ if (HalpPlatformParameterBlock->FirmwareRevision >= 50) {
+ if (!((TREB20SETUPINFO *)(HalpPlatformSpecificExtension->AdvancedSetupInfo))->EnableNcr) {
+ HalpNonExistentPci2DeviceMask |= (1 << 0x07);
+ }
+ }
+ }
+
+ //
+ // Determine base physical address of thr ISA IO Address Space and the address translation table.
+ //
+
+ if (HalpIoArchitectureType == EV4_PROCESSOR_MODULE) {
+ if (HalpMotherboardType == TREBBIA13) {
+ HalpIsaIoBasePhysical = TREB1_ROGUE_ISA_IO_BASE_PHYSICAL;
+ HalpIsa1IoBasePhysical = (ULONGLONG)(0);
+ HalpIsaMemoryBasePhysical = TREB1_ROGUE_ISA_MEMORY_BASE_PHYSICAL;
+ HalpIsa1MemoryBasePhysical = (ULONGLONG)(0);
+ HalpPciIoBasePhysical = TREB1_ROGUE_PCI_IO_BASE_PHYSICAL;
+ HalpPci1IoBasePhysical = (ULONGLONG)(0);
+ HalpPciMemoryBasePhysical = TREB1_ROGUE_PCI_MEMORY_BASE_PHYSICAL;
+ HalpPci1MemoryBasePhysical = (ULONGLONG)(0);
+ if (HalpModuleChipSetRevision == 0) {
+ HalpRangeList = Rogue0Trebbia13RangeList;
+ }
+ if (HalpModuleChipSetRevision == 1) {
+ HalpRangeList = Rogue1Trebbia13RangeList;
+ }
+ }
+ if (HalpMotherboardType == TREBBIA20) {
+ HalpIsaIoBasePhysical = TREB2_ROGUE_ISA_IO_BASE_PHYSICAL;
+ HalpIsa1IoBasePhysical = TREB2_ROGUE_ISA1_IO_BASE_PHYSICAL;
+ HalpIsaMemoryBasePhysical = TREB2_ROGUE_ISA_MEMORY_BASE_PHYSICAL;
+ HalpIsa1MemoryBasePhysical = TREB2_ROGUE_ISA1_MEMORY_BASE_PHYSICAL;
+ HalpPciIoBasePhysical = TREB2_ROGUE_PCI_IO_BASE_PHYSICAL;
+ HalpPci1IoBasePhysical = TREB2_ROGUE_PCI1_IO_BASE_PHYSICAL;
+ HalpPciMemoryBasePhysical = TREB2_ROGUE_PCI_MEMORY_BASE_PHYSICAL;
+ HalpPci1MemoryBasePhysical = TREB2_ROGUE_PCI1_MEMORY_BASE_PHYSICAL;
+ if (HalpModuleChipSetRevision == 0) {
+ HalpRangeList = Rogue0Trebbia20RangeList;
+ }
+ if (HalpModuleChipSetRevision == 1) {
+ HalpRangeList = Rogue1Trebbia20RangeList;
+ }
+ }
+ }
+
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE && (HalpModuleChipSetRevision==0 || HalpModuleChipSetRevision==1)) {
+ if (HalpMotherboardType == TREBBIA13) {
+ HalpIsaIoBasePhysical = TREB1_APOC1_ISA_IO_BASE_PHYSICAL;
+ HalpIsa1IoBasePhysical = (ULONGLONG)(0);
+ HalpIsaMemoryBasePhysical = TREB1_APOC1_ISA_MEMORY_BASE_PHYSICAL;
+ HalpIsa1MemoryBasePhysical = (ULONGLONG)(0);
+ HalpPciIoBasePhysical = TREB1_APOC1_PCI_IO_BASE_PHYSICAL;
+ HalpPci1IoBasePhysical = (ULONGLONG)(0);
+ HalpPciMemoryBasePhysical = TREB1_APOC1_PCI_MEMORY_BASE_PHYSICAL;
+ HalpPci1MemoryBasePhysical = (ULONGLONG)(0);
+ HalpRangeList = Apoc10Trebbia13RangeList;
+ }
+ if (HalpMotherboardType == TREBBIA20) {
+ HalpIsaIoBasePhysical = TREB2_APOC1_ISA_IO_BASE_PHYSICAL;
+ HalpIsa1IoBasePhysical = TREB2_APOC1_ISA1_IO_BASE_PHYSICAL;
+ HalpIsaMemoryBasePhysical = TREB2_APOC1_ISA_MEMORY_BASE_PHYSICAL;
+ HalpIsa1MemoryBasePhysical = TREB2_APOC1_ISA1_MEMORY_BASE_PHYSICAL;
+ HalpPciIoBasePhysical = TREB2_APOC1_PCI_IO_BASE_PHYSICAL;
+ HalpPci1IoBasePhysical = TREB2_APOC1_PCI1_IO_BASE_PHYSICAL;
+ HalpPciMemoryBasePhysical = TREB2_APOC1_PCI_MEMORY_BASE_PHYSICAL;
+ HalpPci1MemoryBasePhysical = TREB2_APOC1_PCI1_MEMORY_BASE_PHYSICAL;
+ HalpRangeList = Apoc10Trebbia20RangeList;
+ }
+ }
+
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE && HalpModuleChipSetRevision==2) {
+ if (HalpMotherboardType == TREBBIA13) {
+ HalpIsaIoBasePhysical = TREB1_APOC2_ISA_IO_BASE_PHYSICAL;
+ HalpIsa1IoBasePhysical = (ULONGLONG)(0);
+ HalpIsaMemoryBasePhysical = TREB1_APOC2_ISA_MEMORY_BASE_PHYSICAL;
+ HalpIsa1MemoryBasePhysical = (ULONGLONG)(0);
+ HalpPciIoBasePhysical = TREB1_APOC2_PCI_IO_BASE_PHYSICAL;
+ HalpPci1IoBasePhysical = (ULONGLONG)(0);
+ HalpPciMemoryBasePhysical = TREB1_APOC2_PCI_MEMORY_BASE_PHYSICAL;
+ HalpPci1MemoryBasePhysical = (ULONGLONG)(0);
+ HalpRangeList = Apoc20Trebbia13RangeList;
+ }
+ if (HalpMotherboardType == TREBBIA20) {
+ HalpIsaIoBasePhysical = TREB2_APOC2_ISA_IO_BASE_PHYSICAL;
+ HalpIsa1IoBasePhysical = TREB2_APOC2_ISA1_IO_BASE_PHYSICAL;
+ HalpIsaMemoryBasePhysical = TREB2_APOC2_ISA_MEMORY_BASE_PHYSICAL;
+ HalpIsa1MemoryBasePhysical = TREB2_APOC2_ISA1_MEMORY_BASE_PHYSICAL;
+ HalpPciIoBasePhysical = TREB2_APOC2_PCI_IO_BASE_PHYSICAL;
+ HalpPci1IoBasePhysical = TREB2_APOC2_PCI1_IO_BASE_PHYSICAL;
+ HalpPciMemoryBasePhysical = TREB2_APOC2_PCI_MEMORY_BASE_PHYSICAL;
+ HalpPci1MemoryBasePhysical = TREB2_APOC2_PCI1_MEMORY_BASE_PHYSICAL;
+ HalpRangeList = Apoc20Trebbia20RangeList;
+ }
+ }
+
+
+ //
+ // If the address translation table is still NULL then HALT.
+ //
+
+ if (HalpRangeList == NULL) {
+ for(;;);
+ }
+}
+
+BOOLEAN
+HalpInitSystem (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes the Hardware Architecture Layer (HAL).
+
+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.
+
+--*/
+
+
+{
+ POPERATING_SYSTEM_STARTED PrivateOperatingSystemStarted;
+ PSYSTEM_PARAMETER_BLOCK SystemParameterBlock = SYSTEM_BLOCK;
+ PHYSICAL_ADDRESS CacheFlushPhysicalAddress;
+
+ if (Phase == 0) {
+
+ //
+ // Phase 0 initialization.
+ //
+
+ HalpGetIoArchitectureType();
+
+ if (HalpIoArchitectureType != EV5_PROCESSOR_MODULE) {
+
+ //
+ // Inform the firmware that an operating system has taken control of the system.
+ //
+
+ if ((SystemParameterBlock->VendorVectorLength / 4) >= 50) {
+ PrivateOperatingSystemStarted = *(POPERATING_SYSTEM_STARTED *)((ULONG)(SystemParameterBlock->VendorVector) + 50*4);
+ if (PrivateOperatingSystemStarted != NULL) {
+ PrivateOperatingSystemStarted();
+ }
+ }
+ }
+
+ //
+ // Map all I/O Spaces used by the HAL
+ //
+
+ HalpMapIoSpace();
+ IoSpaceAlreadyMapped = TRUE;
+
+ HalpInitializeX86DisplayAdapter();
+
+ //
+ // Initialize Dma Cache Parameters
+ //
+
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+ HalpMapBufferSize = APOC_DMA_CACHE_SIZE;
+ HalpMapBufferPhysicalAddress.QuadPart = APOC_DMA_CACHE_BASE_PHYSICAL;
+ } else {
+ HalpMapBufferSize = ROGUE_DMA_CACHE_SIZE;
+ HalpMapBufferPhysicalAddress.QuadPart = ROGUE_DMA_CACHE_BASE_PHYSICAL;
+ }
+
+ return TRUE;
+
+ } else {
+
+ UCHAR Message[80];
+
+ //
+ // Phase 1 initialization.
+ //
+
+ if (HalpMotherboardType == TREBBIA13) {
+ HalDisplayString("DeskStation Technology UniFlex/Raptor 3 Motherboard Rev. 1\n\r");
+ }
+
+ if (HalpMotherboardType == TREBBIA20) {
+ HalDisplayString("DeskStation Technology Raptor ReFlex Motherboard Rev. 2\n\r");
+ }
+
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+ sprintf(Message,"DeskStation Technology ALPHA 21164 Processor Module Rev. %d\n\r",HalpModuleChipSetRevision);
+ } else {
+ sprintf(Message,"DeskStation Technology ALPHA 21064A Processor Module Rev. %d\n\r",HalpModuleChipSetRevision);
+ }
+ HalDisplayString(Message);
+
+ if (HalpModuleHardwareFlushing == TRUE) {
+ HalDisplayString("Hardware Flushing is Enabled\n\r");
+ } else {
+ HalDisplayString("Hardware Flushing is Disabled\n\r");
+ }
+
+ //
+ // Compute the profile interrupt rate.
+ //
+
+ HalpProfileCountRate = ((1000 * 1000 * 10) / KeQueryTimeIncrement());
+
+ //
+ // Map Cache Flush Region.
+ //
+
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+ CacheFlushPhysicalAddress.QuadPart = APOC_CACHE_FLUSH_BASE_PHYSICAL;
+ HalpCacheFlushBase = MmMapIoSpace(CacheFlushPhysicalAddress,APOC_CACHE_FLUSH_SIZE,TRUE);
+ } else {
+ CacheFlushPhysicalAddress.QuadPart = ROGUE_CACHE_FLUSH_BASE_PHYSICAL;
+ HalpCacheFlushBase = MmMapIoSpace(CacheFlushPhysicalAddress,ROGUE_CACHE_FLUSH_SIZE,TRUE);
+ }
+
+ //
+ // Set the time increment value and connect the real clock interrupt
+ // routine.
+ //
+
+ PCR->InterruptRoutine[UNIFLEX_CLOCK2_LEVEL] = HalpClockInterrupt;
+
+ HalpEnableEisaInterrupt(UNIFLEX_CLOCK2_LEVEL,Latched);
+
+ //
+ // Initialize profiler.
+ //
+
+ HalpInitializeProfiler();
+
+ //
+ // Initialize the existing bus handlers.
+ //
+
+ HalpRegisterInternalBusHandlers();
+
+ //
+ // Initialize the PCI bus.
+ //
+
+ HalpInitializePCIBus ();
+ }
+}
+
diff --git a/private/ntos/nthals/halflex/alpha/intsup.c b/private/ntos/nthals/halflex/alpha/intsup.c
new file mode 100644
index 000000000..7f5fa0f36
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/intsup.c
@@ -0,0 +1,393 @@
+/*++
+
+Copyright (c) 1995 DeskStation Technology
+
+Module Name:
+
+ intsup.c
+
+Abstract:
+
+ This module implements the HAL enable/disable system interrupt for
+ platform specific vectors.
+
+Author:
+
+ Michael D. Kinney 14-May-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+VOID
+HalpDisablePlatformInterrupt (
+ 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.
+
+--*/
+
+{
+ //
+ // 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
+
+ return;
+}
+
+
+BOOLEAN
+HalpEnablePlatformInterrupt (
+ 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;
+
+ //
+ // 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
+
+ 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 ISA and EISA are the same as the InterruptLevel, so ignore.
+
+Arguments:
+
+ BusHandler - Registered BUSHANDLER for the target configuration space
+
+ RootHandler - Registered BUSHANDLER for the orginating HalGetBusData
+ request.
+
+ 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;
+
+ *Affinity = 1;
+
+ if (InterfaceType == ProcessorInternal) {
+
+ //
+ // Handle the internal defined for the processor itself
+ // and used to control the performance counters in the 21064.
+ //
+
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+ if( (Vector = HalpGet21164PerformanceVector( BusInterruptLevel,
+ Irql)) != 0 ){
+
+ //
+ // Performance counter was successfully recognized.
+ //
+
+ return Vector;
+
+ } else {
+
+ //
+ // Unrecognized processor interrupt.
+ //
+
+ *Irql = 0;
+ *Affinity = 0;
+ return 0;
+
+ } //end if Vector
+ } else {
+ if( (Vector = HalpGet21064PerformanceVector( BusInterruptLevel,
+ Irql)) != 0 ){
+
+ //
+ // Performance counter was successfully recognized.
+ //
+
+ return Vector;
+
+ } else {
+
+ //
+ // Unrecognized processor interrupt.
+ //
+
+ *Irql = 0;
+ *Affinity = 0;
+ return 0;
+
+ } //end if Vector
+ }
+
+ } else if ( (InterfaceType==PCI_BUS && BusInterruptLevel>=0x0 && BusInterruptLevel<=0x0f) ||
+ (HalpMotherboardType==TREBBIA13 && InterfaceType==Isa && BusNumber==1) ) {
+
+ ULONG i;
+
+ for(i=0;i<12;i++) {
+ if (BusInterruptLevel == HalpPlatformSpecificExtension->PciInterruptToIsaIrq[i]) {
+
+ *Irql = UNIFLEX_PCI_DEVICE_LEVEL;
+
+ BusInterruptLevel = HalpVirtualIsaInterruptToInterruptLine(i) - 0x10;
+
+ return(BusInterruptLevel + UNIFLEX_PCI_VECTORS);
+ }
+ }
+
+ //
+ // Unrecognized interrupt
+ //
+
+ *Irql = 0;
+ *Affinity = 0;
+ return(0);
+
+ } else if (InterfaceType == PCIBus && BusInterruptLevel >= 0x10) {
+
+ //
+ // Assumes all PCI devices coming in on same pin
+ //
+
+ *Irql = UNIFLEX_PCI_DEVICE_LEVEL;
+
+ BusInterruptLevel -= 0x10;
+
+ //
+ // The vector is equal to the specified bus level plus the PCI_VECTOR.
+ //
+
+ return(BusInterruptLevel + UNIFLEX_PCI_VECTORS);
+
+ } else if (InterfaceType == Isa) {
+
+ //
+ // Assumes all ISA devices coming in on same pin
+ //
+
+ *Irql = UNIFLEX_ISA_DEVICE_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level plus the ISA_VECTOR.
+ // This is assuming that the ISA levels not assigned Interrupt Levels
+ // in the Beta programming guide are unused in the LCA system.
+ // Otherwise, need a different encoding scheme.
+ //
+ // Not all interrupt levels are actually supported on Beta;
+ // Should we make some of them illegal here?
+
+ if (BusNumber == 0) {
+ return(BusInterruptLevel + UNIFLEX_ISA_VECTORS);
+ }
+ if (BusNumber == 1) {
+ return(BusInterruptLevel + UNIFLEX_ISA1_VECTORS);
+ }
+ } else if (InterfaceType == Eisa) {
+
+ //
+ // Assumes all EISA devices coming in on same pin
+ //
+
+ *Irql = UNIFLEX_EISA_DEVICE_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level plus the EISA_VECTOR.
+ //
+
+ if (BusNumber == 0) {
+ return(BusInterruptLevel + UNIFLEX_EISA_VECTORS);
+ }
+ if (BusNumber == 1) {
+ return(BusInterruptLevel + UNIFLEX_EISA1_VECTORS);
+ }
+
+ } else {
+
+ //
+ // Not an interface supported on EB64P systems
+ //
+
+ *Irql = 0;
+ *Affinity = 0;
+ return(0);
+ }
+}
+
+ULONG
+HalpGet21164PerformanceVector(
+ IN ULONG BusInterruptLevel,
+ OUT PKIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified performance counter interrupt.
+
+Arguments:
+
+ BusInterruptLevel - Supplies the performance counter number.
+
+ Irql - Returns the system request priority.
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+
+{
+
+ //
+ // Handle the special internal bus defined for the processor itself
+ // and used to control the performance counters in the 21164.
+ //
+
+ *Irql = PROFILE_LEVEL;
+
+ switch( BusInterruptLevel ){
+
+ //
+ // Performance Counter 0
+ //
+
+ case 0:
+
+ return PC0_SECONDARY_VECTOR;
+
+ //
+ // Performance Counter 1
+ //
+
+ case 1:
+
+ return PC1_SECONDARY_VECTOR;
+
+ //
+ // Performance Counter 2
+ //
+
+ case 2:
+
+ return PC2_SECONDARY_VECTOR;
+
+ } //end switch( BusInterruptLevel )
+
+ //
+ // Unrecognized.
+ //
+
+ *Irql = 0;
+ return 0;
+
+}
+
diff --git a/private/ntos/nthals/halflex/alpha/jxhalp.h b/private/ntos/nthals/halflex/alpha/jxhalp.h
new file mode 100644
index 000000000..84a06ca18
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/jxhalp.h
@@ -0,0 +1,404 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxhalp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ Jazz specific interfaces, defines and structures.
+
+Author:
+
+ Jeff Havens (jhavens) 20-Jun-91
+
+
+Revision History:
+
+--*/
+
+#ifndef _JXHALP_
+#define _JXHALP_
+
+
+typedef enum _ADDRESS_SPACE_TYPE{
+ BusMemory=0,
+ BusIo = 1,
+ UserBusMemory = 2,
+ UserBusIo = 3,
+ KernelPciDenseMemory = 4,
+ UserPciDenseMemory = 6,
+} ADDRESS_SPACE_TYPE, *PADDRESS_SPACE_TYPE;
+
+
+//
+// Define microprocessor-specific function prototypes and structures.
+//
+
+//
+// 21164 (EV4) processor family.
+//
+
+typedef struct _EV5ProfileCount {
+ ULONG ProfileCount[3];
+ ULONG ProfileCountReload[3];
+} EV5ProfileCount, *PEV5ProfileCount;
+
+//
+// 21064 (EV4) processor family.
+//
+
+typedef enum _EV4Irq{
+ Irq0 = 0,
+ Irq1 = 1,
+ Irq2 = 2,
+ Irq3 = 3,
+ Irq4 = 4,
+ Irq5 = 5,
+ MaximumIrq
+} EV4Irq, *PEV4Irq;
+
+typedef struct _EV4IrqStatus{
+ ULONG Vector;
+ BOOLEAN Enabled;
+ KIRQL Irql;
+ UCHAR Priority;
+} EV4IrqStatus, *PEV4IrqStatus;
+
+typedef struct _EV4ProfileCount {
+ ULONG ProfileCount[2];
+ ULONG ProfileCountReload[2];
+} EV4ProfileCount, *PEV4ProfileCount;
+
+VOID
+HalpInitialize21064Interrupts(
+ VOID
+ );
+
+VOID
+HalpDisable21064HardwareInterrupt(
+ IN ULONG Irq
+ );
+
+VOID
+HalpDisable21064SoftwareInterrupt(
+ IN KIRQL Irql
+ );
+
+VOID
+HalpDisable21064PerformanceInterrupt(
+ IN ULONG Vector
+ );
+
+VOID
+HalpEnable21064HardwareInterrupt(
+ IN ULONG Irq,
+ IN KIRQL Irql,
+ IN ULONG Vector,
+ IN UCHAR Priority
+ );
+
+VOID
+HalpEnable21064SoftwareInterrupt(
+ IN KIRQL Irql
+ );
+
+VOID
+HalpInitialize21064Interrupts(
+ VOID
+ );
+
+VOID
+HalpEnable21064PerformanceInterrupt(
+ IN ULONG Vector,
+ IN KIRQL Irql
+ );
+
+ULONG
+HalpGet21064PerformanceVector(
+ IN ULONG BusInterruptLevel,
+ OUT PKIRQL Irql
+ );
+
+//
+// 21164 (EV5) processor family.
+//
+
+typedef struct _EB164_PCR{
+ ULONGLONG HalpCycleCount; // 64-bit per-processor cycle count
+ ULONG Reserved[3]; // Pad ProfileCount to offset 20
+ EV5ProfileCount ProfileCount; // Profile counter state
+ } EB164_PCR, *PEB164_PCR;
+
+#define HAL_21164_PCR ( (PEB164_PCR)(&(PCR->HalReserved)) )
+
+//
+// 21064 (EV4) processor family.
+//
+
+typedef struct _EB64P_PCR {
+ ULONGLONG HalpCycleCount; // 64-bit per-processor cycle count
+ EV4ProfileCount ProfileCount; // Profile counter state, do not move
+ EV4IrqStatus IrqStatusTable[MaximumIrq]; // Irq status table
+} EB64P_PCR, *PEB64P_PCR;
+
+#define HAL_21064_PCR ( (PEB64P_PCR)(&(PCR->HalReserved)) )
+
+//
+// Define used to determine if a page is within the DMA Cache range.
+//
+
+#define HALP_PAGE_IN_DMA_CACHE(Page) \
+ (Page >= (0x40000/2))
+
+//
+// Define global data used to locate the EISA control space and the realtime
+// clock registers.
+//
+
+
+
+extern PVOID HalpCacheFlushBase;
+extern ULONG HalpClockFrequency;
+extern ULONG HalpClockMegaHertz;
+extern ULONG HalpIoArchitectureType;
+extern ULONG HalpModuleChipSetRevision;
+extern ULONG HalpMotherboardType;
+extern BOOLEAN HalpModuleHardwareFlushing;
+extern UCHAR *HalpInterruptLineToBit;
+extern UCHAR *HalpBitToInterruptLine;
+extern UCHAR *HalpInterruptLineToVirtualIsa;
+extern UCHAR *HalpVirtualIsaToInterruptLine;
+extern ULONGLONG HalpNoncachedDenseBasePhysicalSuperPage;
+extern ULONGLONG HalpPciDenseBasePhysicalSuperPage;
+extern ULONGLONG HalpPciConfig0BasePhysical;
+extern ULONGLONG HalpPciConfig1BasePhysical;
+extern ULONGLONG HalpIsaIoBasePhysical;
+extern ULONGLONG HalpIsa1IoBasePhysical;
+extern ULONGLONG HalpIsaMemoryBasePhysical;
+extern ULONGLONG HalpIsa1MemoryBasePhysical;
+extern ULONGLONG HalpPciIoBasePhysical;
+extern ULONGLONG HalpPci1IoBasePhysical;
+extern ULONGLONG HalpPciMemoryBasePhysical;
+extern ULONGLONG HalpPci1MemoryBasePhysical;
+extern PPLATFORM_RANGE_LIST HalpRangeList;
+extern UCHAR HalpSecondPciBridgeBusNumber;
+extern ULONG PCIMaxBus;
+extern ULONG HalpIntel82378BusNumber;
+extern ULONG HalpIntel82378DeviceNumber;
+extern ULONG HalpSecondIntel82378DeviceNumber;
+extern ULONG HalpNonExistentPciDeviceMask;
+extern ULONG HalpNonExistentPci1DeviceMask;
+extern ULONG HalpNonExistentPci2DeviceMask;
+
+extern PLATFORM_RANGE_LIST Apoc10Trebbia13RangeList[];
+extern PLATFORM_RANGE_LIST Apoc10Trebbia20RangeList[];
+extern PLATFORM_RANGE_LIST Apoc20Trebbia13RangeList[];
+extern PLATFORM_RANGE_LIST Apoc20Trebbia20RangeList[];
+extern PLATFORM_RANGE_LIST Rogue0Trebbia13RangeList[];
+extern PLATFORM_RANGE_LIST Rogue1Trebbia13RangeList[];
+extern PLATFORM_RANGE_LIST Rogue0Trebbia20RangeList[];
+extern PLATFORM_RANGE_LIST Rogue1Trebbia20RangeList[];
+
+extern UCHAR Treb13InterruptLineToBit[];
+extern UCHAR Treb13BitToInterruptLine[];
+extern UCHAR Treb13InterruptLineToVirtualIsa[];
+extern UCHAR Treb13VirtualIsaToInterruptLine[];
+extern UCHAR Treb20InterruptLineToBit[];
+extern UCHAR Treb20BitToInterruptLine[];
+extern UCHAR Treb20InterruptLineToVirtualIsa[];
+extern UCHAR Treb20VirtualIsaToInterruptLine[];
+extern ULONG HalpNumberOfIsaBusses;
+extern ULONG HalpVgaDecodeBusNumber;
+
+VOID
+HalpMb (
+ );
+
+VOID
+HalpImb (
+ );
+
+VOID
+HalpCachePcrValues (
+ );
+
+ULONG
+HalpRpcc (
+ );
+
+ULONG
+HalpReadAbsoluteUlong (
+ IN ULONG HighPart,
+ IN ULONG LowPart
+ );
+
+VOID
+HalpWriteAbsoluteUlong (
+ IN ULONG HighPart,
+ IN ULONG LowPart,
+ IN ULONG Value
+ );
+
+ULONG
+HalpGetModuleChipSetRevision(
+ VOID
+ );
+
+VOID
+HalpInitialize21164Interrupts(
+ VOID
+ );
+
+VOID
+HalpStart21164Interrupts(
+ VOID
+ );
+
+VOID
+HalpInitializeProfiler(
+ VOID
+ );
+
+NTSTATUS
+HalpProfileSourceInformation (
+ OUT PVOID Buffer,
+ IN ULONG BufferLength,
+ OUT PULONG ReturnedLength
+ );
+
+NTSTATUS
+HalpProfileSourceInterval (
+ OUT PVOID Buffer,
+ IN ULONG BufferLength
+ );
+
+
+VOID
+Halp21064InitializeProfiler(
+ VOID
+ );
+
+NTSTATUS
+Halp21064ProfileSourceInformation (
+ OUT PVOID Buffer,
+ IN ULONG BufferLength,
+ OUT PULONG ReturnedLength
+ );
+
+NTSTATUS
+Halp21064ProfileSourceInterval (
+ OUT PVOID Buffer,
+ IN ULONG BufferLength
+ );
+
+
+VOID
+Halp21164InitializeProfiler(
+ VOID
+ );
+
+NTSTATUS
+Halp21164ProfileSourceInformation (
+ OUT PVOID Buffer,
+ IN ULONG BufferLength,
+ OUT PULONG ReturnedLength
+ );
+
+NTSTATUS
+Halp21164ProfileSourceInterval (
+ OUT PVOID Buffer,
+ IN ULONG BufferLength
+ );
+
+
+ULONG
+HalpGet21164PerformanceVector(
+ IN ULONG BusInterruptLevel,
+ OUT PKIRQL Irql
+ );
+
+ULONGLONG
+HalpRead21164PerformanceCounter(
+ VOID
+ );
+
+VOID
+HalpWrite21164PerformanceCounter(
+ ULONGLONG PmCtr,
+ ULONG CBOXMux1,
+ ULONG CBOXMux2
+ );
+
+VOID
+Halp21064PerformanceCounter0Interrupt (
+ VOID
+ );
+
+VOID
+Halp21064PerformanceCounter1Interrupt (
+ VOID
+ );
+
+VOID
+Halp21164PerformanceCounter0Interrupt (
+ VOID
+ );
+
+VOID
+Halp21164PerformanceCounter1Interrupt (
+ VOID
+ );
+
+VOID
+Halp21164PerformanceCounter2Interrupt (
+ VOID
+ );
+
+VOID
+Halp21064WritePerformanceCounter(
+ IN ULONG PerformanceCounter,
+ IN BOOLEAN Enable,
+ IN ULONG MuxControl OPTIONAL,
+ IN ULONG EventCount OPTIONAL
+ );
+
+VOID
+Halp21064ClearLockRegister(
+ PVOID LockAddress
+ );
+
+VOID
+HalpMiniTlbSaveState(
+ VOID
+ );
+
+VOID
+HalpMiniTlbRestoreState(
+ VOID
+ );
+
+ULONG
+HalpMiniTlbAllocateEntry(
+ PVOID Qva,
+ PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+VOID
+HalpCleanIoBuffers(
+ IN PMDL Mdl,
+ IN BOOLEAN ReadOperation,
+ IN BOOLEAN DmaOperation
+ );
+
+ULONG HalpPciLowLevelConfigRead(
+ ULONG BusNumber,
+ ULONG DeviceNumber,
+ ULONG FunctionNumber,
+ ULONG Register
+ );
+
+#endif // _JXHALP_
diff --git a/private/ntos/nthals/halflex/alpha/jxmapio.c b/private/ntos/nthals/halflex/alpha/jxmapio.c
new file mode 100644
index 000000000..c46ebb8ee
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/jxmapio.c
@@ -0,0 +1,103 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxmapio.c
+
+Abstract:
+
+ This module implements the mapping of HAL I/O space a MIPS R3000
+ or R4000 Jazz system.
+
+Author:
+
+ David N. Cutler (davec) 28-Apr-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+
+//
+// Define global data used to locate the EISA control space and the realtime
+// clock registers.
+//
+
+PVOID HalpEisaControlBase[MAX_EISA_BUSSES];
+PVOID HalpEisaMemoryBase[MAX_EISA_BUSSES];
+PVOID HalpPciControlBase[MAX_PCI_BUSSES];
+PVOID HalpPciMemoryBase[MAX_PCI_BUSSES];
+PVOID HalpRealTimeClockBase;
+PVOID HalpCacheFlushBase;
+
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL I/O space for a MIPS R3000 or R4000 Jazz
+ system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ //
+ // Map EISA control space. Map all 16 slots. This is done so the NMI
+ // code can probe the cards.
+ //
+
+ HalpEisaControlBase[0] = HAL_MAKE_QVA(HalpIsaIoBasePhysical);
+ HalpEisaControlBase[1] = HAL_MAKE_QVA(HalpIsa1IoBasePhysical);
+
+ //
+ // Map realtime clock registers.
+ //
+
+ HalpRealTimeClockBase = (PVOID)((ULONG)(HAL_MAKE_QVA(HalpIsaIoBasePhysical)) + 0x71);
+
+ //
+ // Map ISA Memory Space.
+ //
+
+ HalpEisaMemoryBase[0] = HAL_MAKE_QVA(HalpIsaMemoryBasePhysical);
+ HalpEisaMemoryBase[1] = HAL_MAKE_QVA(HalpIsa1MemoryBasePhysical);
+
+ //
+ // Map PCI control space. Map all 16 slots. This is done so the NMI
+ // code can probe the cards.
+ //
+
+ HalpPciControlBase[0] = HAL_MAKE_QVA(HalpPciIoBasePhysical);
+ HalpPciControlBase[1] = HAL_MAKE_QVA(HalpPci1IoBasePhysical);
+
+ //
+ // Map PCI Memory Space.
+ //
+
+ HalpPciMemoryBase[0] = HAL_MAKE_QVA(HalpPciMemoryBasePhysical);
+ HalpPciMemoryBase[1] = HAL_MAKE_QVA(HalpPci1MemoryBasePhysical);
+
+ return TRUE;
+}
diff --git a/private/ntos/nthals/halflex/alpha/minitlb.c b/private/ntos/nthals/halflex/alpha/minitlb.c
new file mode 100644
index 000000000..0b29f5cd8
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/minitlb.c
@@ -0,0 +1,221 @@
+/*++
+
+Copyright (c) 1995 DeskStation Technology
+
+Module Name:
+
+ minitlb.c
+
+Abstract:
+
+ This module contains the support functions for the TLB that allows
+ access to the sparse address spaces.
+
+Author:
+
+ Michael D. Kinney 8-Aug-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+#define MINI_TLB_ATTRIBUTES_HIGH 0xfffffc03
+#define MINI_TLB_ATTRIBUTES_LOW 0xc0000004
+#define MINI_TLB_ENTRY_HIGH 0xfffffc03
+
+UCHAR HalpMiniTlbAttributesLookupTable[16] = {
+ 0, // ISA I/O Space 0x00000000 - 0x01ffffff
+ 0, // ISA Memory Space 0x00000000 - 0x01ffffff
+ 1, // PCI I/O Space 0x00000000 - 0x01ffffff
+ 1, // PCI Memory Space 0x00000000 - 0x01ffffff
+ 1, // PCI High Memory Space 0x40000000 - 0x41ffffff
+ 1, // PCI High Memory Space 0x42000000 - 0x43ffffff
+ 1, // PCI High Memory Space 0x44000000 - 0x45ffffff
+ 1, // PCI High Memory Space 0x46000000 - 0x47ffffff
+ 3, // PCI Config Type 0 Space Devices 0-13 0x00000000 - 0x01ffffff
+ 3, // PCI Config Type 0 Space Device 14 0x02000000 - 0x03ffffff
+ 3, // PCI Config Type 0 Space Device 15 0x04000000 - 0x05ffffff
+ 3, // PCI Config Type 0 Space Device 16 0x08000000 - 0x09ffffff
+ 3, // PCI Config Type 0 Space Device 17 0x10000000 - 0x11ffffff
+ 3, // PCI Config Type 0 Space Device 18 0x20000000 - 0x21ffffff
+ 3, // PCI Config Type 0 Space Device 19 0x40000000 - 0x41ffffff
+ 3 // PCI Config Type 1 Space 0x00000000 - 0x01ffffff
+ };
+
+UCHAR HalpMiniTlbEntryLookupTable[16] = {
+ 0x80, // ISA I/O Space 0x00000000 - 0x01ffffff
+ 0x00, // ISA Memory Space 0x00000000 - 0x01ffffff
+ 0x80, // PCI I/O Space 0x00000000 - 0x01ffffff
+ 0x00, // PCI Memory Space 0x00000000 - 0x01ffffff
+ 0x20, // PCI High Memory Space 0x40000000 - 0x41ffffff
+ 0x21, // PCI High Memory Space 0x42000000 - 0x43ffffff
+ 0x22, // PCI High Memory Space 0x44000000 - 0x45ffffff
+ 0x23, // PCI High Memory Space 0x46000000 - 0x47ffffff
+ 0x00, // PCI Config Type 0 Space Devices 0-13 0x00000000 - 0x01ffffff
+ 0x01, // PCI Config Type 0 Space Device 14 0x02000000 - 0x03ffffff
+ 0x02, // PCI Config Type 0 Space Device 15 0x04000000 - 0x05ffffff
+ 0x04, // PCI Config Type 0 Space Device 16 0x08000000 - 0x09ffffff
+ 0x08, // PCI Config Type 0 Space Device 17 0x10000000 - 0x11ffffff
+ 0x10, // PCI Config Type 0 Space Device 18 0x20000000 - 0x21ffffff
+ 0x20, // PCI Config Type 0 Space Device 19 0x40000000 - 0x41ffffff
+ 0x80 // PCI Config Type 1 Space 0x00000000 - 0x01ffffff
+ };
+
+ULONG HalpMiniTlbEntryAddressLow[4] = {
+ 0x1000000c, // Mini TLB Entry 0
+ 0x5000000c, // Mini TLB Entry 1
+ 0x9000000c, // Mini TLB Entry 2
+ 0xd000000c // Mini TLB Entry 3
+ };
+
+UCHAR HalpMiniTlbAttributes = 0x00;
+UCHAR HalpMiniTlbEntry[4] = {0x00,0x00,0x00,0x00};
+
+UCHAR HalpMiniTlbTag[4] = {0xff, 0xff, 0xff, 0xff};
+ULONG HalpMiniTlbIndex = 0;
+ULONG HalpMiniTlbEntries = 4;
+
+VOID
+HalpMiniTlbProgramEntry(
+ ULONG Index
+ )
+
+{
+ HalpMiniTlbAttributes &= (~(0x03 << (Index * 2)));
+ HalpMiniTlbAttributes |= (HalpMiniTlbAttributesLookupTable[HalpMiniTlbTag[Index]] << (Index * 2));
+ HalpMiniTlbEntry[Index] = HalpMiniTlbEntryLookupTable[HalpMiniTlbTag[Index]];
+ HalpWriteAbsoluteUlong(MINI_TLB_ATTRIBUTES_HIGH,MINI_TLB_ATTRIBUTES_LOW,((ULONG)HalpMiniTlbAttributes)<<8);
+ HalpWriteAbsoluteUlong(MINI_TLB_ENTRY_HIGH,HalpMiniTlbEntryAddressLow[Index],((ULONG)HalpMiniTlbEntry[Index])<<8);
+}
+
+VOID
+HalpMiniTlbSaveState(
+ VOID
+ )
+
+{
+}
+
+VOID
+HalpMiniTlbRestoreState(
+ VOID
+ )
+
+{
+ ULONG i;
+
+ for(i=0;i<4;i++) {
+ if (HalpMiniTlbTag[i]!=0xff) {
+ HalpMiniTlbProgramEntry(i);
+ }
+ }
+}
+
+ULONG
+HalpMiniTlbMatch(
+ PVOID Qva,
+ ULONG StartIndex
+ )
+
+{
+ ULONG Tag;
+ ULONG i;
+
+ Tag = ((ULONG)(Qva) >> 25) & 0x0f;
+ for(i=StartIndex;i<4 && HalpMiniTlbTag[i]!=Tag;i++);
+ return(i);
+}
+
+ULONG
+HalpMiniTlbAllocateEntry(
+ PVOID Qva,
+ PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+{
+ ULONG Index;
+
+ //
+ // Check for a tag match among the fixed TLB entries.
+ //
+
+ Index = HalpMiniTlbMatch(Qva,HalpMiniTlbEntries);
+
+ if (Index==4) {
+
+ //
+ // There was no match, so check for an available TLB entry.
+ //
+
+ if (HalpMiniTlbEntries<=1) {
+
+ //
+ // No TLB entries were available. Return NULL
+ //
+
+ return(FALSE);
+ }
+
+ //
+ // A TLB entry was available. Fill it in.
+ //
+
+ HalpMiniTlbEntries--;
+ Index = HalpMiniTlbEntries;
+ HalpMiniTlbTag[Index] = (UCHAR)(((ULONG)(Qva) >> 25) & 0x0f);
+ HalpMiniTlbProgramEntry(Index);
+
+ //
+ // Reset the random replacement index
+ //
+
+ HalpMiniTlbIndex = 0;
+ }
+
+ TranslatedAddress->QuadPart = ROGUE_TRANSLATED_BASE_PHYSICAL;
+ TranslatedAddress->QuadPart += (Index << 30) | (((ULONG)(Qva) & 0x01ffffff) << IO_BIT_SHIFT);
+ return(TRUE);
+}
+
+
+PVOID
+HalpMiniTlbResolve(
+ PVOID Qva
+ )
+
+{
+ ULONG Index;
+
+ //
+ // Check for a tag match among all the TLB entries
+ //
+
+ Index = HalpMiniTlbMatch(Qva,0);
+
+ if (Index==4) {
+
+ //
+ // There was no match, so replace one of the TLB entries
+ //
+
+ Index = HalpMiniTlbIndex;
+ HalpMiniTlbTag[Index] = (UCHAR)(((ULONG)(Qva) >> 25) & 0x0f);
+ HalpMiniTlbProgramEntry(Index);
+
+ //
+ // Point random replacement index at next available entry.
+ //
+
+ HalpMiniTlbIndex++;
+ if (HalpMiniTlbIndex >= HalpMiniTlbEntries) {
+ HalpMiniTlbIndex = 0;
+ }
+ }
+ return( (PVOID)(DTI_QVA_ENABLE | ((0x08 | Index) << 25) | ((ULONG)(Qva) & 0x01ffffff)) );
+}
diff --git a/private/ntos/nthals/halflex/alpha/pcisup.c b/private/ntos/nthals/halflex/alpha/pcisup.c
new file mode 100644
index 000000000..6d708835e
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/pcisup.c
@@ -0,0 +1,897 @@
+/*++
+
+Copyright (c) 1995 DeskStation Technology
+
+Module Name:
+
+ pcisup.c
+
+Abstract:
+
+ This module contains the routines that support PCI configuration cycles
+ and PCI interrupts.
+
+Author:
+
+ Michael D. Kinney 30-Apr-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+
+#define INVALID_PCI_CONFIGURATION_ADDRESS (0xffffff00)
+#define NO_PCI_DEVSEL_DATA_VALUE (0xffffffff)
+
+//
+// The following tables are used to map between PCI interrupt pins, PCI interrupt lines,
+// and virtual ISA interrupt indexes. The Uniflex architecture uses a 16 bit interrupt
+// controller for ISA interrupts and all PCI interrupts. An InterruptLine value of 0x20
+// is reserved for the ISA PIC. InterruptLine values between 0x10 and 0x20 are reserved
+// for PCI devices. InterruptLine values between 0x00 and 0x0f are reserved for ISA IRQs.
+//
+
+UCHAR Treb13InterruptLineToBit[0x11] = {7,2,3,1,4,5,6,9,10,11,16,16,16,16,15,14,0};
+UCHAR Treb13BitToInterruptLine[0x10] = {0x10,0x03,0x01,0x02,0x04,0x05,0x06,0x00,0x00,0x07,0x08,0x09,0x00,0x00,0x0f,0x0e};
+UCHAR Treb13InterruptLineToVirtualIsa[0x10] = {0,1,2,3,8,9,10,11,4,5,0,0,0,0,0,0};
+UCHAR Treb13VirtualIsaToInterruptLine[0x10] = {0x10,0x11,0x12,0x13,0x18,0x19,0,0,0x14,0x15,0x16,0x17,0,0,0,0};
+
+UCHAR Treb20InterruptLineToBit[0x11] = {1,2,3,4,5,6,7,8,9,16,16,16,16,16,16,16,0};
+UCHAR Treb20BitToInterruptLine[0x10] = {0x10,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00};
+UCHAR Treb20InterruptLineToVirtualIsa[0x11] = {0,1,2,3,4,5,6,7,8,0,0,0,0,0,0,0,9};
+UCHAR Treb20VirtualIsaToInterruptLine[0x10] = {0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x20,0,0,0,0,0,0};
+
+//
+// Interrupt mask for all active PCI interrupts including ISA Bus PICs
+//
+
+static volatile ULONG HalpPciInterruptMask;
+
+//
+// Interrupt mask for PCI interrupts that have been connected through device drivers.
+//
+
+static volatile ULONG HalpPciDeviceInterruptMask;
+
+//
+// Interrupt mask showing which bit cooresponds to ISA Bus #0 PIC
+//
+
+static volatile ULONG HalpEisaInterruptMask;
+
+//
+// Interrupt mask showing which bit cooresponds to ISA Bus #1 PIC
+//
+
+static volatile ULONG HalpEisa1InterruptMask;
+
+VOID
+HalpWritePciInterruptRegister(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function writes the interrupt mask register for PCI interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+ {
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+ HalpWriteAbsoluteUlong(0xfffffca8,0x00000010, (HalpPciInterruptMask & 0xff) << 8);
+ HalpWriteAbsoluteUlong(0xfffffc88,0x00000010, HalpPciInterruptMask & 0xff00);
+ } else {
+ HalpWriteAbsoluteUlong(0xfffffc03,0x2000000c, HalpPciInterruptMask & 0xff);
+ HalpWriteAbsoluteUlong(0xfffffc03,0x6000000c, HalpPciInterruptMask >> 8);
+ }
+ }
+
+ULONG
+HalpReadPciInterruptRegister(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function reads the interrupt status register for PCI interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The lower 16 bits contains the status of each interrupt line going to the PCI
+ interrupt controller.
+
+--*/
+
+ {
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+ return ( ((HalpReadAbsoluteUlong(0xfffffca8,0x00000000)>>8)&0xff) |
+ (HalpReadAbsoluteUlong(0xfffffc88,0x00000000) & 0xff00) );
+ } else {
+ return ( (HalpReadAbsoluteUlong(0xfffffc03,0x2000000c) &0xff) |
+ ((HalpReadAbsoluteUlong(0xfffffc03,0x6000000c)<<8) & 0xff00) );
+ }
+ }
+
+ULONG
+HalpGetModuleChipSetRevision(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function identifies the chip set revision of the processor module installed in the
+ system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The chip set revision.
+
+--*/
+
+{
+ ULONG Temp;
+ ULONG ReturnValue;
+
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+ Temp = HalpPciInterruptMask;
+ HalpPciInterruptMask = 0;
+ HalpWritePciInterruptRegister();
+ ReturnValue = (HalpReadPciInterruptRegister() >> 4) & 0x0f;
+ HalpPciInterruptMask = Temp;
+ HalpWritePciInterruptRegister();
+ }
+ if (HalpIoArchitectureType == EV4_PROCESSOR_MODULE) {
+ ReturnValue = HalpReadAbsoluteUlong(0xfffffc03,0xe000000c);
+ ReturnValue = (ReturnValue & 0x0f) ^ ((ReturnValue >> 4) & 0x0f);
+ }
+ return(ReturnValue);
+}
+
+VOID
+HalpSetPciInterruptBit (
+ ULONG Bit
+ )
+
+/*++
+
+Routine Description:
+
+ This function sets a bit in the PCI interrupt mask and writes the new mask
+ to the interrupt controller.
+
+Arguments:
+
+ Bit - The bit number to set in the PCI interrupt mask.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ HalpPciDeviceInterruptMask = HalpPciDeviceInterruptMask | (1<<Bit);
+ HalpPciInterruptMask = HalpPciInterruptMask | (1<<Bit);
+ HalpWritePciInterruptRegister();
+}
+
+VOID
+HalpClearPciInterruptBit (
+ ULONG Bit
+ )
+
+/*++
+
+Routine Description:
+
+ This function clears a bit in the PCI interrupt mask and writes the new mask
+ to the interrupt controller.
+
+Arguments:
+
+ Bit - The bit number to clear from the PCI interrupt mask.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ HalpPciDeviceInterruptMask = HalpPciDeviceInterruptMask & ~(1<<Bit);
+ HalpPciInterruptMask = HalpPciInterruptMask & ~(1<<Bit);
+ HalpWritePciInterruptRegister();
+}
+
+VOID
+HalpEnablePciInterrupt (
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables a PCI interrupt.
+
+Arguments:
+
+ Vector - Specifies the interrupt to enable.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ if (Vector >= UNIFLEX_PCI_VECTORS && Vector <= UNIFLEX_MAXIMUM_PCI_VECTOR) {
+ HalpSetPciInterruptBit(HalpInterruptLineToBit[Vector-UNIFLEX_PCI_VECTORS]);
+ }
+}
+
+VOID
+HalpDisablePciInterrupt (
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function disables a PCI interrupt.
+
+Arguments:
+
+ Vector - Specifies the interrupt to disable.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ if (Vector >= UNIFLEX_PCI_VECTORS && Vector <= UNIFLEX_MAXIMUM_PCI_VECTOR) {
+ HalpClearPciInterruptBit(HalpInterruptLineToBit[Vector-UNIFLEX_PCI_VECTORS]);
+ }
+}
+
+ULONG
+HalpVirtualIsaInterruptToInterruptLine (
+ IN ULONG Index
+ )
+
+/*++
+
+Routine Description:
+
+ This function maps a virtual ISA interrupt to a PCI interrupt line value.
+ This provides the ability to use an ISA device driver on a PCI device.
+
+Arguments:
+
+ Index - Index into a platform specific table that maps PCI interrupts to
+ virtual ISA interrupts.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return(HalpVirtualIsaToInterruptLine[Index]);
+}
+
+
+ULONG HalpClearLockCacheLineAddress[32];
+
+BOOLEAN
+HalpPciDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+
+/*++
+
+Routine Description:
+
+ This is the interrupt dispatcher for all PCI interrupts.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - not used.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+
+{
+ ULONG PciInterruptStatus;
+ PULONG dispatchCode;
+ PKINTERRUPT interruptObject;
+ USHORT PCRInOffset;
+ BOOLEAN returnValue = FALSE;
+ ULONG i;
+
+ if (HalpIoArchitectureType != EV5_PROCESSOR_MODULE) {
+ Halp21064ClearLockRegister(&(HalpClearLockCacheLineAddress[16]));
+ }
+
+ //
+ // Get the active interrupt bits
+ //
+
+ PciInterruptStatus = HalpReadPciInterruptRegister();
+
+ //
+ // See if this is the interrupt for ISA Bus #0 PIC
+ //
+
+ if (PciInterruptStatus & HalpEisaInterruptMask) {
+
+ returnValue = HalpEisaDispatch(Interrupt,ServiceContext,0);
+
+ //
+ // If there really was an interrupt on ISA Bus #0, then return now.
+ //
+
+ if (returnValue) {
+ return(returnValue);
+ }
+ }
+
+ //
+ // See if this is the interrupt for ISA Bus #1 PIC
+ //
+
+ if (PciInterruptStatus & HalpEisa1InterruptMask) {
+
+ returnValue = HalpEisaDispatch(Interrupt,ServiceContext,1);
+
+ //
+ // If there really was an interrupt on ISA Bus #1, then return now.
+ //
+
+ if (returnValue) {
+ return(returnValue);
+ }
+ }
+
+ //
+ // Only keep interrupt bits that have been connected by device drivers.
+ //
+
+ PciInterruptStatus &= HalpPciDeviceInterruptMask;
+
+ //
+ // Dispatch to the ISRs of interrupts that have been connected by device drivers.
+ //
+
+ for(i=0;i<16;i++) {
+ if (PciInterruptStatus & (1<<i)) {
+
+ PCRInOffset = UNIFLEX_PCI_VECTORS + HalpBitToInterruptLine[i];
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ dispatchCode = (PULONG)(PCR->InterruptRoutine[PCRInOffset]);
+ interruptObject = CONTAINING_RECORD(dispatchCode,
+ KINTERRUPT,
+ DispatchCode);
+
+ returnValue =
+ ((PSECONDARY_DISPATCH)interruptObject->DispatchAddress)
+ (interruptObject);
+ }
+ }
+
+ return(returnValue);
+}
+
+UCHAR HalpGetInterruptLine(ULONG BusNumber,ULONG DeviceNumber,ULONG InterruptPin)
+
+/*++
+
+Routine Description:
+
+ This routine maps a PCI interrupt described by the device's bus number, device number, and
+ interrupt pin into the interrupt line value that is stored in the PCI config header.
+
+Arguments:
+
+ BusNumber - PCI bus number of the device.
+
+ DeviceNumber - PCI device number of the device.
+
+ InterruptPin - PCI interrupt pin of the device (A=1,B=2,C=3,D=4).
+
+Return Value:
+
+ Returns the PCI Interrupt Line value for the PCI device.
+
+--*/
+
+{
+ UCHAR InterruptLine;
+
+ if (HalpMotherboardType == TREBBIA13) {
+
+ if (BusNumber > 1)
+ {
+ BusNumber = 1;
+ }
+
+ switch (BusNumber<<16 | DeviceNumber<<8 | InterruptPin) {
+ case 0x010401 : InterruptLine = 0x10; break; // Bus 1, Device 4, Int A
+ case 0x010601 : InterruptLine = 0x11; break; // Bus 1, Device 6, Int A
+ case 0x010501 : InterruptLine = 0x12; break; // Bus 1, Device 5, Int A
+ case 0x010701 : InterruptLine = 0x13; break; // Bus 1, Device 7, Int A
+ case 0x010402 : InterruptLine = 0x17; break; // Bus 1, Device 4, Int B
+ case 0x010602 : InterruptLine = 0x14; break; // Bus 1, Device 6, Int B
+ case 0x010502 : InterruptLine = 0x14; break; // Bus 1, Device 5, Int B
+ case 0x010702 : InterruptLine = 0x17; break; // Bus 1, Device 7, Int B
+ case 0x010403 : InterruptLine = 0x18; break; // Bus 1, Device 4, Int C
+ case 0x010603 : InterruptLine = 0x15; break; // Bus 1, Device 6, Int C
+ case 0x010503 : InterruptLine = 0x15; break; // Bus 1, Device 5, Int C
+ case 0x010703 : InterruptLine = 0x18; break; // Bus 1, Device 7, Int C
+ case 0x010404 : InterruptLine = 0x19; break; // Bus 1, Device 4, Int D
+ case 0x010604 : InterruptLine = 0x16; break; // Bus 1, Device 6, Int D
+ case 0x010504 : InterruptLine = 0x16; break; // Bus 1, Device 5, Int D
+ case 0x010704 : InterruptLine = 0x19; break; // Bus 1, Device 7, Int D
+ case 0x000d01 : InterruptLine = 0x1e; break; // Bus 0, Device 13, Int A
+ case 0x000f01 : InterruptLine = 0x1f; break; // Bus 0, Device 15, Int A
+ case 0x001001 : InterruptLine = 0x20; break; // Bus 0, Device 16, Int A
+ default : InterruptLine = 0xff; break;
+ }
+ }
+
+ if (HalpMotherboardType == TREBBIA20) {
+
+ if (BusNumber == 0) {
+ return(0xff);
+ }
+
+ if (BusNumber >= HalpSecondPciBridgeBusNumber) {
+ BusNumber = 1;
+ } else {
+ BusNumber = 0;
+ }
+
+ switch (BusNumber<<16 | DeviceNumber<<8 | InterruptPin) {
+ case 0x000401 : InterruptLine = 0x20; break;
+
+ case 0x000501 :
+ case 0x000603 :
+ case 0x000704 : InterruptLine = 0x10; break;
+
+ case 0x000502 :
+ case 0x000604 :
+ case 0x000701 : InterruptLine = 0x11; break;
+
+ case 0x000503 :
+ case 0x000601 :
+ case 0x000702 : InterruptLine = 0x12; break;
+
+ case 0x000504 :
+ case 0x000602 :
+ case 0x000703 : InterruptLine = 0x13; break;
+
+ case 0x010401 :
+ case 0x010504 :
+ case 0x010603 : InterruptLine = 0x14; break;
+
+ case 0x010402 :
+ case 0x010501 :
+ case 0x010604 : InterruptLine = 0x15; break;
+
+ case 0x010403 :
+ case 0x010502 :
+ case 0x010601 : InterruptLine = 0x16; break;
+
+ case 0x010404 :
+ case 0x010503 :
+ case 0x010602 : InterruptLine = 0x17; break;
+
+ case 0x010701 : InterruptLine = 0x18; break;
+
+ default : InterruptLine = 0xff; break;
+ }
+ }
+
+ return(InterruptLine);
+}
+
+
+VOID
+HalpConnectInterruptDispatchers(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function connects the PCI interrupt dispatch routine and enables
+ ISA interrupts so they will generate processor interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UCHAR InterruptLine;
+
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+ PCR->InterruptRoutine[22] = (PKINTERRUPT_ROUTINE)HalpPciDispatch;
+ } else {
+ PCR->InterruptRoutine[14] = (PKINTERRUPT_ROUTINE)HalpPciDispatch;
+ }
+
+//DbgPrint("Intel82378 : Bus=%d Device=%d\n\r",HalpIntel82378BusNumber,HalpIntel82378DeviceNumber);
+//DbgPrint("SecondIntel82378 : Bus=%d Device=%d\n\r",HalpSecondPciBridgeBusNumber,HalpSecondIntel82378DeviceNumber);
+
+ InterruptLine = HalpGetInterruptLine(HalpIntel82378BusNumber,HalpIntel82378DeviceNumber,1);
+ HalpEisaInterruptMask = 0x0000;
+ if (InterruptLine != 0xff) {
+ HalpEisaInterruptMask = (1 << HalpInterruptLineToBit[InterruptLine-0x10]) & 0xffff;
+ }
+
+ InterruptLine = HalpGetInterruptLine(HalpSecondPciBridgeBusNumber,HalpSecondIntel82378DeviceNumber,1);
+ HalpEisa1InterruptMask = 0x0000;
+ if (InterruptLine != 0xff) {
+ HalpEisa1InterruptMask = (1 << HalpInterruptLineToBit[InterruptLine-0x10]) & 0xffff;
+ }
+
+//DbgPrint("HalpEisaInterruptMask = %08x\n\r",HalpEisaInterruptMask);
+//DbgPrint("HalpEisa1InterruptMask = %08x\n\r",HalpEisa1InterruptMask);
+
+ //
+ // Enable ISA Interrupts on Apocolypse's PIC
+ //
+
+ HalpPciDeviceInterruptMask = 0x0000;
+ HalpPciInterruptMask = HalpEisaInterruptMask | HalpEisa1InterruptMask;
+ HalpWritePciInterruptRegister();
+}
+
+
+VOID
+HalpDisableAllInterrupts(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function disables all external interrupt sources.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG i;
+
+ //
+ // Mask off all ISA Interrupts
+ //
+
+ for(i=0;i<HalpNumberOfIsaBusses;i++) {
+ WRITE_REGISTER_UCHAR((PUCHAR)((ULONG)HalpEisaControlBase[i]+0x21),0xff);
+ WRITE_REGISTER_UCHAR((PUCHAR)((ULONG)HalpEisaControlBase[i]+0xa1),0xff);
+ }
+
+ //
+ // Mask off all PCI Interrupts
+ //
+
+ HalpPciDeviceInterruptMask = 0x0000;
+ HalpPciInterruptMask = 0x0000;
+ HalpWritePciInterruptRegister();
+}
+
+PCI_CONFIGURATION_TYPES
+HalpPCIConfigCycleType (IN ULONG BusNumber)
+{
+ if (BusNumber == 0) {
+ return PciConfigType0;
+ } else if (BusNumber < PCIMaxBus) {
+ return PciConfigType1;
+ } else {
+ return PciConfigTypeInvalid;
+ }
+}
+
+VOID
+HalpPCIConfigAddr (
+ IN ULONG BusNumber,
+ IN PCI_SLOT_NUMBER Slot,
+ PPCI_CFG_CYCLE_BITS pPciAddr
+ )
+{
+
+ PCI_CONFIGURATION_TYPES ConfigType;
+
+ ConfigType = HalpPCIConfigCycleType(BusNumber);
+
+ if (ConfigType == PciConfigType0) {
+
+ //
+ // Initialize PciAddr for a type 0 configuration cycle
+ //
+
+ //
+ // See if this is a nonexistant device on PCI Bus 0
+ //
+
+ if ( (1 << Slot.u.bits.DeviceNumber) & HalpNonExistentPciDeviceMask ) {
+ pPciAddr->u.AsULONG = INVALID_PCI_CONFIGURATION_ADDRESS;
+ return;
+ }
+
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+ pPciAddr->u.AsULONG = 1 << (3 + Slot.u.bits.DeviceNumber);
+ } else {
+ pPciAddr->u.AsULONG = 1 << (11 + Slot.u.bits.DeviceNumber);
+ }
+ pPciAddr->u.bits0.FunctionNumber = Slot.u.bits.FunctionNumber;
+ pPciAddr->u.bits0.Reserved1 = PciConfigType0;
+ if (HalpIoArchitectureType == EV4_PROCESSOR_MODULE) {
+ pPciAddr->u.AsULONG &= 0x01ffffff;
+ pPciAddr->u.AsULONG += (ULONG)HAL_MAKE_QVA(HalpPciConfig0BasePhysical);
+ if (Slot.u.bits.DeviceNumber >= 14 && Slot.u.bits.DeviceNumber <= 19) {
+ pPciAddr->u.AsULONG += (Slot.u.bits.DeviceNumber-13) << 25;
+ }
+ }
+ } else {
+
+ //
+ // See if this is a nonexistant PCI device on the otherside of the First PCI-PCI Bridge
+ //
+
+ if (BusNumber == 1 && (1 << Slot.u.bits.DeviceNumber) & HalpNonExistentPci1DeviceMask) {
+ pPciAddr->u.AsULONG = INVALID_PCI_CONFIGURATION_ADDRESS;
+ return;
+ }
+
+ //
+ // See if this is a nonexistant PCI device on the otherside of the Second PCI-PCI Bridge
+ //
+
+ if (BusNumber == HalpSecondPciBridgeBusNumber && (1 << Slot.u.bits.DeviceNumber) & HalpNonExistentPci2DeviceMask) {
+ pPciAddr->u.AsULONG = INVALID_PCI_CONFIGURATION_ADDRESS;
+ return;
+ }
+
+ //
+ // Initialize PciAddr for a type 1 configuration cycle
+ //
+
+ pPciAddr->u.AsULONG = 0;
+ if (HalpIoArchitectureType == EV4_PROCESSOR_MODULE) {
+ pPciAddr->u.AsULONG = (ULONG)HAL_MAKE_QVA(HalpPciConfig1BasePhysical);
+ }
+ pPciAddr->u.bits1.BusNumber = BusNumber;
+ pPciAddr->u.bits1.FunctionNumber = Slot.u.bits.FunctionNumber;
+ pPciAddr->u.bits1.DeviceNumber = Slot.u.bits.DeviceNumber;
+ pPciAddr->u.bits1.Reserved1 = PciConfigType1;
+ }
+
+ return;
+}
+
+ULONG READ_CONFIG_Ux(
+ IN PVOID ConfigurationAddress,
+ IN ULONG ConfigurationType,
+ IN ULONG Offset
+ )
+
+{
+ switch(ConfigurationType) {
+ case PciConfigType0 :
+ return(HalpReadAbsoluteUlong((ULONG)(HalpPciConfig0BasePhysical >> 32),
+ (ULONG)HalpPciConfig0BasePhysical + ((ULONG)ConfigurationAddress << IO_BIT_SHIFT) + Offset));
+ case PciConfigType1 :
+ return(HalpReadAbsoluteUlong((ULONG)(HalpPciConfig1BasePhysical >> 32),
+ (ULONG)HalpPciConfig1BasePhysical + ((ULONG)ConfigurationAddress << IO_BIT_SHIFT) + Offset));
+ }
+ return(NO_PCI_DEVSEL_DATA_VALUE);
+}
+
+VOID WRITE_CONFIG_Ux(
+ IN PVOID ConfigurationAddress,
+ IN ULONG ConfigurationType,
+ IN ULONG Offset,
+ IN ULONG Value
+ )
+
+{
+ switch(ConfigurationType) {
+ case PciConfigType0 :
+ HalpWriteAbsoluteUlong((ULONG)(HalpPciConfig0BasePhysical >> 32),
+ (ULONG)HalpPciConfig0BasePhysical + ((ULONG)ConfigurationAddress << IO_BIT_SHIFT) + Offset,
+ Value);
+ break;
+ case PciConfigType1 :
+ HalpWriteAbsoluteUlong((ULONG)(HalpPciConfig1BasePhysical >> 32),
+ (ULONG)HalpPciConfig1BasePhysical + ((ULONG)ConfigurationAddress << IO_BIT_SHIFT) + Offset,
+ Value);
+ break;
+ }
+}
+
+UCHAR
+READ_CONFIG_UCHAR(
+ IN PVOID ConfigurationAddress,
+ IN ULONG ConfigurationType
+ )
+
+{
+ if (((ULONG)ConfigurationAddress & 0xffffff00) == INVALID_PCI_CONFIGURATION_ADDRESS) {
+ return((UCHAR)NO_PCI_DEVSEL_DATA_VALUE);
+ }
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+ return((UCHAR)(READ_CONFIG_Ux(ConfigurationAddress,ConfigurationType,IO_BYTE_LEN) >> (8*((ULONG)ConfigurationAddress & 0x03))));
+ } else {
+ return(READ_REGISTER_UCHAR(ConfigurationAddress));
+ }
+}
+
+USHORT
+READ_CONFIG_USHORT(
+ IN PVOID ConfigurationAddress,
+ IN ULONG ConfigurationType
+ )
+
+{
+ if (((ULONG)ConfigurationAddress & 0xffffff00) == INVALID_PCI_CONFIGURATION_ADDRESS) {
+ return((USHORT)NO_PCI_DEVSEL_DATA_VALUE);
+ }
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+ return((USHORT)(READ_CONFIG_Ux(ConfigurationAddress,ConfigurationType,IO_WORD_LEN) >> (8*((ULONG)ConfigurationAddress & 0x03))));
+ } else {
+ return(READ_REGISTER_USHORT(ConfigurationAddress));
+ }
+}
+
+ULONG
+READ_CONFIG_ULONG(
+ IN PVOID ConfigurationAddress,
+ IN ULONG ConfigurationType
+ )
+
+{
+ if (((ULONG)ConfigurationAddress & 0xffffff00) == INVALID_PCI_CONFIGURATION_ADDRESS) {
+ return((ULONG)NO_PCI_DEVSEL_DATA_VALUE);
+ }
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+ return(READ_CONFIG_Ux(ConfigurationAddress,ConfigurationType,IO_LONG_LEN) >> (8*((ULONG)ConfigurationAddress & 0x03)));
+ } else {
+ return(READ_REGISTER_ULONG(ConfigurationAddress));
+ }
+}
+
+VOID
+WRITE_CONFIG_UCHAR(
+ IN PVOID ConfigurationAddress,
+ IN UCHAR ConfigurationData,
+ IN ULONG ConfigurationType
+ )
+
+{
+ if (((ULONG)ConfigurationAddress & 0xffffff00) != INVALID_PCI_CONFIGURATION_ADDRESS) {
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+ WRITE_CONFIG_Ux(ConfigurationAddress,ConfigurationType,IO_BYTE_LEN,(ULONG)ConfigurationData << (8*((ULONG)ConfigurationAddress & 0x03)));
+ } else {
+ WRITE_REGISTER_UCHAR(ConfigurationAddress,ConfigurationData);
+ }
+ }
+}
+
+VOID
+WRITE_CONFIG_USHORT(
+ IN PVOID ConfigurationAddress,
+ IN USHORT ConfigurationData,
+ IN ULONG ConfigurationType
+ )
+
+{
+ if (((ULONG)ConfigurationAddress & 0xffffff00) != INVALID_PCI_CONFIGURATION_ADDRESS) {
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+ WRITE_CONFIG_Ux(ConfigurationAddress,ConfigurationType,IO_WORD_LEN,(ULONG)ConfigurationData << (8*((ULONG)ConfigurationAddress & 0x03)));
+ } else {
+ WRITE_REGISTER_USHORT(ConfigurationAddress,ConfigurationData);
+ }
+ }
+}
+
+VOID
+WRITE_CONFIG_ULONG(
+ IN PVOID ConfigurationAddress,
+ IN ULONG ConfigurationData,
+ IN ULONG ConfigurationType
+ )
+
+{
+ if (((ULONG)ConfigurationAddress & 0xffffff00) != INVALID_PCI_CONFIGURATION_ADDRESS) {
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+ WRITE_CONFIG_Ux(ConfigurationAddress,ConfigurationType,IO_LONG_LEN,ConfigurationData << (8*((ULONG)ConfigurationAddress & 0x03)));
+ } else {
+ WRITE_REGISTER_ULONG(ConfigurationAddress,ConfigurationData);
+ }
+ }
+}
+
+ULONG HalpPciLowLevelConfigRead(
+ ULONG BusNumber,
+ ULONG DeviceNumber,
+ ULONG FunctionNumber,
+ ULONG Register
+ )
+
+{
+ PCI_SLOT_NUMBER SlotNumber;
+ PCI_CFG_CYCLE_BITS PciCfg;
+ ULONG ConfigurationCycleType;
+
+ SlotNumber.u.AsULONG = 0;
+ SlotNumber.u.bits.DeviceNumber = DeviceNumber;
+ SlotNumber.u.bits.FunctionNumber = FunctionNumber;
+
+ HalpPCIConfigAddr(BusNumber,SlotNumber,&PciCfg);
+ ConfigurationCycleType = PciCfg.u.bits.Reserved1;
+ PciCfg.u.bits.Reserved1 = 0;
+ PciCfg.u.bits0.RegisterNumber = Register>>2;
+ return(READ_CONFIG_ULONG((PVOID)PciCfg.u.AsULONG,ConfigurationCycleType));
+}
diff --git a/private/ntos/nthals/halflex/alpha/perfcntr.c b/private/ntos/nthals/halflex/alpha/perfcntr.c
new file mode 100644
index 000000000..d9a0c4975
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/perfcntr.c
@@ -0,0 +1,262 @@
+/*++
+
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ perfcntr.c
+
+Abstract:
+
+ This module implements the interfaces that access the system
+ performance counter and the calibrated stall. The functions implemented
+ in this module are suitable for uniprocessor systems only.
+
+Author:
+
+ Jeff McLeman (mcleman) 05-June-1992
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+ Rod Gamache [DEC] 9-Mar-1993
+ Fix profile clock.
+
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+//
+// Define and initialize the 64-bit count of total system cycles used
+// as the performance counter.
+//
+
+ULONGLONG HalpCycleCount = 0;
+
+
+LARGE_INTEGER
+KeQueryPerformanceCounter (
+ OUT PLARGE_INTEGER Frequency OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ This routine returns the current performance counter value and the
+ performance counter frequency.
+
+Arguments:
+
+ Frequency - Supplies an optional pointer to a variable which receives
+ the performance counter frequency in Hertz.
+
+Return Value:
+
+ The current performance counter value is returned as the function
+ value.
+
+--*/
+
+{
+
+ LARGE_INTEGER LocalRpccTime;
+ ULONG RpccValue;
+
+ //
+ // Obtain the current value of the processor cycle counter and adjust
+ // the upper 32 bits if a roll-over occurred since the last time the
+ // Rpcc value was checked (at least oncce per clock interrupt). This
+ // code may be interrupted so we must fetch HalpRpccTimec atomically.
+ //
+
+ *(PULONGLONG)&LocalRpccTime = HalpCycleCount;
+ RpccValue = HalpRpcc();
+ if (RpccValue < LocalRpccTime.LowPart) {
+ LocalRpccTime.HighPart += 1;
+ }
+ LocalRpccTime.LowPart = RpccValue;
+
+
+ //
+ // If the frequency parameter is specified, then return the performance
+ // counter frequency as the current system time frequency.
+ //
+
+ if (ARGUMENT_PRESENT(Frequency) != FALSE) {
+ Frequency->LowPart = HalpClockFrequency;
+ Frequency->HighPart = 0;
+ }
+
+ //
+ // Return the current processor cycle counter as the function value.
+ //
+
+ return LocalRpccTime;
+}
+
+
+VOID
+HalCalibratePerformanceCounter (
+ IN volatile PLONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This routine resets the performance counter value for the current
+ processor to zero. The reset is done such that the resulting value
+ is closely synchronized with other processors in the configuration.
+
+Arguments:
+
+ Number - Supplies a pointer to count of the number of processors in
+ the configuration.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+//HalDisplayString("HalCalibratePerformanceCounter()\n\r");
+
+ //
+ // ****** Warning ******
+ //
+ // This is a stub routine. It should clear the current value of the
+ // performance counter. It is really only needed in an MP system where,
+ // close, but not exact synchronization of the performance counters
+ // are needed. See MIPS code in halfxs\mips\j4prof.c for a method of
+ // synchronizing.
+ //
+
+ return;
+}
+
+
+VOID
+HalpCheckPerformanceCounter(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function is called every system clock interrupt in order to
+ check for wrap of the performance counter. The function must handle
+ a wrap if it is detected.
+
+ N.B. - This function must be called at CLOCK_LEVEL.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ LARGE_INTEGER LocalRpccTime;
+ ULONG RpccValue;
+
+ //
+ // Update the low part of the performance counter directly from the
+ // rpcc count. Check for wrap of the rpcc count, if wrap has occurred
+ // then increment the high part of the performance counter.
+ //
+
+ LocalRpccTime.QuadPart = HalpCycleCount;
+ RpccValue = HalpRpcc();
+
+ if (RpccValue < LocalRpccTime.LowPart) {
+ LocalRpccTime.HighPart += 1;
+ }
+
+ LocalRpccTime.LowPart = RpccValue;
+
+ HalpCycleCount = LocalRpccTime.QuadPart;
+
+ return;
+
+}
+
+
+VOID
+KeStallExecutionProcessor (
+ IN ULONG Microseconds
+ )
+
+/*++
+
+Routine Description:
+
+ This function stalll execution of the current processor for the specified
+ number of microseconds.
+
+Arguments:
+
+ Microseconds - Supplies the number of microseconds to stall.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ LONG StallCyclesRemaining; // signed value
+ ULONG PreviousRpcc, CurrentRpcc;
+
+ //
+ // Get the value of the RPCC as soon as we enter
+ //
+
+ PreviousRpcc = HalpRpcc();
+
+ //
+ // Compute the number of cycles to stall
+ //
+
+ StallCyclesRemaining = Microseconds * HalpClockMegaHertz;
+
+ //
+ // Wait while there are stall cycles remaining.
+ // The accuracy of this routine is limited by the
+ // length of this while loop.
+ //
+
+ while (StallCyclesRemaining > 0) {
+
+ CurrentRpcc = HalpRpcc();
+
+ //
+ // The subtraction always works because the Rpcc
+ // is a wrapping long-word. If it wraps, we still
+ // get the positive number we want.
+ //
+
+ StallCyclesRemaining -= (CurrentRpcc - PreviousRpcc);
+
+ //
+ // remember this RPCC value
+ //
+
+ PreviousRpcc = CurrentRpcc;
+ }
+
+}
+
diff --git a/private/ntos/nthals/halflex/alpha/portsup.c b/private/ntos/nthals/halflex/alpha/portsup.c
new file mode 100644
index 000000000..ec96fcebd
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/portsup.c
@@ -0,0 +1,93 @@
+/*++
+
+Copyright (c) 1995 DeskStation Technology
+
+Module Name:
+
+ portsup.c
+
+Abstract:
+
+ This module implements the code that provides the resources required to
+ access the serial port that is used for the kernel debugger.
+
+Author:
+
+ Michael D. Kinney 30-Apr-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+#define SERIAL_PORT_COM1 0x3F8
+
+VOID
+HalpGetIoArchitectureType(
+ VOID
+ );
+
+PUCHAR HalpAllocateKdPortResources(
+ OUT PVOID *SP_READ,
+ OUT PVOID *SP_WRITE
+ )
+
+/*++
+
+Routine Description:
+
+ This function allocates the resources needed by the kernel debugger to
+ access a serial port. For an ALPHA processor, all I/O ports can be
+ accessed through super page addresses, so this function just maps the
+ serial port into the super page address range.
+
+Arguments:
+
+ SP_READ - Quasi virtual address to use for I/O read operations.
+
+ SP_WRITE - Quasi virtual address to use for I/O write operations.
+
+Return Value:
+
+ The bus relative address of the COM port being used as a kernel debugger.
+
+--*/
+
+{
+ HalpGetIoArchitectureType();
+
+ *SP_READ = (PVOID)((ULONG)(HAL_MAKE_QVA(HalpIsaIoBasePhysical)) + SERIAL_PORT_COM1);
+ *SP_WRITE = (PVOID)((ULONG)(HAL_MAKE_QVA(HalpIsaIoBasePhysical)) + SERIAL_PORT_COM1);
+
+ return((PUCHAR)(SERIAL_PORT_COM1));
+}
+
+VOID HalpFreeKdPortResources(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function deallocates the resources needed by the kernel debugger to
+ access a serial port. For an ALPHA processor, no resources were actually
+ allocated, so this is a NULL function.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+}
diff --git a/private/ntos/nthals/halflex/alpha/xxidle.s b/private/ntos/nthals/halflex/alpha/xxidle.s
new file mode 100644
index 000000000..0d53d7aed
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/xxidle.s
@@ -0,0 +1,62 @@
+// TITLE("Processor Idle Support")
+//++
+//
+// Copyright (c) 1992 Digital Equipment Corporation
+// Copyright (c) 1993 Digital Equipment Corporation
+//
+// Module Name:
+//
+// idle.s
+//
+// Abstract:
+//
+// This module implements the HalProcessorIdle interface
+//
+// Author:
+//
+// John Vert (jvert) 11-May-1994
+//
+// Environment:
+//
+// Revision History:
+//
+//--
+#include "halalpha.h"
+
+
+ SBTTL("Processor Idle")
+//++
+//
+// VOID
+// HalProcessorIdle(
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function is called when the current processor is idle with
+// interrupts disabled. There is no thread active and there are no
+// DPCs to process. Therefore, power can be switched to a standby
+// mode until the the next interrupt occurs on the current processor.
+//
+// N.B. This routine is entered with interrupts disabled. This routine
+// must do any power management enabling necessary, enable interrupts,
+// then either return or wait for an interrupt.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalProcessorIdle)
+
+ ENABLE_INTERRUPTS // no power management, just
+ // enable interrupts and return
+ ret zero, (ra)
+
+ .end HalProcessorIdle
diff --git a/private/ntos/nthals/halflex/alpha/xxinitnt.c b/private/ntos/nthals/halflex/alpha/xxinitnt.c
new file mode 100644
index 000000000..45e0cb356
--- /dev/null
+++ b/private/ntos/nthals/halflex/alpha/xxinitnt.c
@@ -0,0 +1,194 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ xxinitnt.c
+
+Abstract:
+
+
+ This module implements the interrupt initialization for a MIPS R3000
+ or R4000 system.
+
+Author:
+
+ David N. Cutler (davec) 26-Apr-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+
+UCHAR Halp21164IrqlTable[] = {00, // Irql 0
+ 01, // Irql 1
+ 02, // Irql 2
+ 20, // Irql 3
+ 21, // Irql 4
+ 22, // Irql 5
+ 23, // Irql 6
+ 31}; // Irql 7
+
+//
+// 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.
+//
+
+#define DEFAULT_21164_PROCESSOR_FREQUENCY_MHZ 300;
+#define DEFAULT_21064_PROCESSOR_FREQUENCY_MHZ 275;
+
+ULONG HalpClockFrequency;
+ULONG HalpClockMegaHertz = DEFAULT_21064_PROCESSOR_FREQUENCY_MHZ;
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes interrupts for a MIPS R3000 or R4000 system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the initialization is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+ ULONG Index;
+ ULONG Irq;
+ KIRQL Irql;
+ UCHAR Priority;
+ ULONG Vector;
+
+ //
+ // Mask sure that all processor interrupts are inactive by masking off all device
+ // interrupts in the system's Programable Interrupt Controllers.
+ //
+
+ HalpDisableAllInterrupts();
+
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+
+ //
+ // Initialize the IRQL translation tables in the PCR. These tables are
+ // used by the interrupt dispatcher to determine the new IRQL. They are
+ // also used by the routines that raise and lower IRQL.
+ //
+
+ for (Index = 0; Index < sizeof(Halp21164IrqlTable); Index++) {
+ PCR->IrqlTable[Index] = Halp21164IrqlTable[Index];
+ }
+ }
+
+ //
+ // Initialize HAL private data from the PCR. This must be done before
+ // HalpStallExecution is called. Compute integral megahertz first to
+ // avoid rounding errors due to imprecise cycle clock period values.
+ //
+
+ HalpClockMegaHertz = ((1000 * 1000) + (PCR->CycleClockPeriod >> 1)) / PCR->CycleClockPeriod;
+ HalpClockFrequency = HalpClockMegaHertz * (1000 * 1000);
+
+ //
+ // Connect the Stall interrupt vector to the clock. When the
+ // profile count is calculated, we then connect the normal
+ // clock.
+
+
+ PCR->InterruptRoutine[UNIFLEX_CLOCK2_LEVEL] = HalpStallInterrupt;
+
+ //
+ // Start the heartbeat timer
+ //
+
+ HalSetTimeIncrement(MAXIMUM_INCREMENT);
+ HalpProgramIntervalTimer(HalpNextIntervalCount);
+
+ //
+ // Initialize the PCI/ISA interrupt controller.
+ //
+
+ HalpCreateDmaStructures();
+
+ if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) {
+
+ //
+ // Initialize the 21164 interrupts.
+ //
+
+ HalpCachePcrValues(0); // Enable all HW INTS on 21164
+
+ } else {
+
+ //
+ // Initialize the 21064 interrupts.
+ //
+
+ HalpInitialize21064Interrupts();
+
+ HalpEnable21064SoftwareInterrupt( Irql = APC_LEVEL );
+ HalpEnable21064SoftwareInterrupt( Irql = DISPATCH_LEVEL );
+
+ HalpEnable21064HardwareInterrupt(Irq = 2,
+// Irql = DEVICE_LEVEL,
+ Irql = UNIFLEX_PCI_DEVICE_LEVEL,
+// Vector = PIC_VECTOR,
+ Vector = 14,
+ Priority = 0 );
+
+ }
+
+ return TRUE;
+}
+
+VOID
+HalpStallInterrupt (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function serves as the stall calibration interrupt service
+ routine. It is executed in response to system clock interrupts
+ during the initialization of the HAL layer.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return;
+}
diff --git a/private/ntos/nthals/halflex/busdata.c b/private/ntos/nthals/halflex/busdata.c
new file mode 100644
index 000000000..7ae3a7987
--- /dev/null
+++ b/private/ntos/nthals/halflex/busdata.c
@@ -0,0 +1,175 @@
+/*++
+
+
+Copyright (C) 1989-1995 Microsoft Corporation
+Copyright (C) 1994,1995 Digital Equipment Corporation
+
+Module Name:
+
+ busdata.c
+
+Abstract:
+
+ This module contains get/set bus data routines.
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+#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
+ );
+
+NTSTATUS
+HalpIsaInstallHandler(
+ IN PBUS_HANDLER Bus
+ );
+
+#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 bus #0
+ //
+
+ HaliRegisterBusHandler (Isa, // Bus Type
+ -1, // No config space
+ 0, // Internal bus #0
+ Internal, // Parent bus type
+ 0, // Parent bus number
+ 0, // No extension data
+ HalpIsaInstallHandler, // Install handler
+ &Bus); // Bushandler return
+
+ //
+ // Build Isa bus #1
+ //
+
+ HaliRegisterBusHandler (Isa, // Bus Type
+ -1, // No config space
+ 1, // Internal bus #1
+ Internal, // Parent bus type
+ 0, // Parent bus number
+ 0, // No extension data
+ HalpIsaInstallHandler, // Install handler
+ &Bus); // Bushandler return
+
+ //
+ // Build Eisa bus #0
+ //
+
+ HaliRegisterBusHandler (Eisa, // Bus Type
+ -1, // No config space
+ 0, // Internal bus #0
+ Internal, // Parent bus type
+ 0, // Parent bus number
+ 0, // No extension data
+ HalpIsaInstallHandler, // Install handler
+ &Bus); // Bushandler return
+
+ //
+ // Build Eisa bus #1
+ //
+
+ HaliRegisterBusHandler (Eisa, // Bus Type
+ -1, // No config space
+ 1, // Internal bus #0
+ Internal, // Parent bus type
+ 0, // Parent bus number
+ 0, // No extension data
+ HalpIsaInstallHandler, // Install handler
+ &Bus); // Bushandler return
+
+}
+
+NTSTATUS
+HalpIsaInstallHandler(
+ IN PBUS_HANDLER Bus
+ )
+
+{
+ //
+ // Fill in ISA handlers
+ //
+
+ Bus->GetBusData = HalpNoBusData;
+ Bus->AdjustResourceList = HalpAdjustIsaResourceList;
+
+ return STATUS_SUCCESS;
+}
diff --git a/private/ntos/nthals/halflex/bushnd.c b/private/ntos/nthals/halflex/bushnd.c
new file mode 100644
index 000000000..a1e648dc1
--- /dev/null
+++ b/private/ntos/nthals/halflex/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/halflex/drivesup.c b/private/ntos/nthals/halflex/drivesup.c
new file mode 100644
index 000000000..38259e5f4
--- /dev/null
+++ b/private/ntos/nthals/halflex/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/halflex/hal.rc b/private/ntos/nthals/halflex/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/halflex/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/halflex/hal.src b/private/ntos/nthals/halflex/hal.src
new file mode 100644
index 000000000..da778bb9d
--- /dev/null
+++ b/private/ntos/nthals/halflex/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/halflex/halp.h b/private/ntos/nthals/halflex/halp.h
new file mode 100644
index 000000000..b6cc7cfdd
--- /dev/null
+++ b/private/ntos/nthals/halflex/halp.h
@@ -0,0 +1,453 @@
+/*++ BUILD Version: 0003 // Increment this if a change has global effects
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ halp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ interfaces.
+
+Author:
+
+ David N. Cutler (davec) 25-Apr-1991
+
+
+Revision History:
+
+--*/
+
+#ifndef _HALP_
+#define _HALP_
+#include "nthal.h"
+#include "hal.h"
+#include "hali.h"
+#include "dtidef.h"
+#include "jxhalp.h"
+#include "string.h"
+
+
+#define __0K (ULONG)(0x0)
+#define __0MB (ULONG)(0x0)
+#define __0GB (ULONG)(0x0)
+#define __2K (ULONG)(0x800)
+#define __4K (ULONG)(0x1000)
+#define __8K (ULONG)(0x2000)
+#define __16K (ULONG)(0x4000)
+#define __32K (ULONG)(0x8000)
+#define __64K (ULONG)(0x10000)
+#define __128K (ULONG)(0x20000)
+#define __256K (ULONG)(0x40000)
+#define __512K (ULONG)(0x80000)
+#define __1MB (ULONG)(0x100000)
+#define __2MB (ULONG)(0x200000)
+#define __4MB (ULONG)(0x400000)
+#define __8MB (ULONG)(0x800000)
+#define __16MB (ULONG)(0x1000000)
+#define __32MB (ULONG)(0x2000000)
+#define __64MB (ULONG)(0x4000000)
+#define __128MB (ULONG)(0x8000000)
+#define __256MB (ULONG)(0x10000000)
+#define __512MB (ULONG)(0x20000000)
+#define __1GB (ULONG)(0x40000000)
+#define __2GB (ULONG)(0x80000000)
+
+//
+// Define the context structure for use by the interrupt routine.
+//
+
+typedef BOOLEAN (*PSECONDARY_DISPATCH)(
+ PVOID InterruptRoutine
+ );
+
+//
+// Define adapter object structure.
+//
+
+typedef struct _ADAPTER_OBJECT {
+ CSHORT Type;
+ CSHORT Size;
+ struct _ADAPTER_OBJECT *MasterAdapter;
+ ULONG MapRegistersPerChannel;
+ ULONG BusNumber;
+ PVOID AdapterBaseVa;
+ PVOID MapRegisterBase;
+ ULONG NumberOfMapRegisters;
+ ULONG CommittedMapRegisters;
+ struct _WAIT_CONTEXT_BLOCK *CurrentWcb;
+ KDEVICE_QUEUE ChannelWaitQueue;
+ PKDEVICE_QUEUE RegisterWaitQueue;
+ LIST_ENTRY AdapterQueue;
+ KSPIN_LOCK SpinLock;
+ PRTL_BITMAP MapRegisters;
+ PUCHAR PagePort;
+ UCHAR ChannelNumber;
+ UCHAR AdapterNumber;
+ USHORT DmaPortAddress;
+ UCHAR AdapterMode;
+ BOOLEAN NeedsMapRegisters;
+ BOOLEAN MasterDevice;
+ BOOLEAN Width16Bits;
+ BOOLEAN ScatterGather;
+} ADAPTER_OBJECT;
+
+//
+// Define function prototypes.
+//
+
+BOOLEAN
+HalpInitSystem (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+VOID
+HalpDisablePlatformInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ );
+
+BOOLEAN
+HalpEnablePlatformInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+BOOLEAN
+HalpCreateEisaStructures(
+ ULONG BusNumber
+ );
+
+VOID
+HalpDisableEisaInterrupt(
+ IN ULONG Vector
+ );
+
+BOOLEAN
+HalpEisaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN ULONG BusNumber
+ );
+
+BOOLEAN
+HalpPciDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+VOID
+HalpEnableEisaInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+ULONG
+HalpAllocateTbEntry (
+ VOID
+ );
+
+VOID
+HalpFreeTbEntry (
+ VOID
+ );
+
+BOOLEAN
+HalpCalibrateStall (
+ VOID
+ );
+
+VOID
+HalpClockInterrupt (
+ VOID
+ );
+
+BOOLEAN
+HalpCreateDmaStructures (
+ VOID
+ );
+
+BOOLEAN
+HalpInitializeDisplay (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ );
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ );
+
+VOID
+HalpProfileInterrupt (
+ VOID
+ );
+
+VOID
+HalpStallInterrupt (
+ VOID
+ );
+
+VOID
+HalpInitializeX86DisplayAdapter (
+ VOID
+ );
+
+VOID
+HalpResetX86DisplayAdapter (
+ VOID
+ );
+
+VOID
+HalpProgramIntervalTimer (
+ IN ULONG IntervalCount
+ );
+
+VOID
+HalpConnectInterruptDispatchers(
+ VOID
+ );
+
+VOID
+HalpEnablePciInterrupt(
+ IN ULONG Vector
+ );
+
+VOID
+HalpDisablePciInterrupt(
+ IN ULONG Vector
+ );
+
+VOID
+HalpDisableAllInterrupts (
+ );
+
+ULONG
+HalpVirtualIsaInterruptToInterruptLine (
+ IN ULONG Index
+ );
+
+ULONG
+HalpReadPciData (
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ OUT PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG
+HalpWritePciData (
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+VOID
+HalpAllocateArcsResources (
+ VOID
+ );
+
+VOID
+HalpFreeArcsResources (
+ VOID
+ );
+
+PUCHAR
+HalpAllocateKdPortResources(
+ PVOID *SP_READ,
+ PVOID *SP_WRITE
+ );
+
+VOID
+HalpFreeKdPortResources(
+ VOID
+ );
+
+//
+// Define Bus Handler support function prototypes.
+//
+
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ );
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+
+VOID
+HalpAdjustResourceListUpperLimits (
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList,
+ IN LARGE_INTEGER MaximumPortAddress,
+ IN LARGE_INTEGER MaximumMemoryAddress,
+ IN ULONG MaximumInterruptVector,
+ IN ULONG MaximumDmaChannel
+ );
+
+//
+//
+//
+
+NTSTATUS
+HalpAdjustIsaResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+//
+// Define PCI support function prototypes.
+//
+
+VOID
+HalpInitializePCIBus (
+ VOID
+ );
+
+PBUS_HANDLER
+HalpAllocateAndInitPCIBusHandler (
+ IN ULONG BusNo
+ );
+
+VOID
+HalpRegisterPCIInstallHandler(
+ IN PINSTALL_BUS_HANDLER MachineSpecificPCIInstallHandler
+);
+
+NTSTATUS
+HalpDefaultPCIInstallHandler(
+ IN PBUS_HANDLER Bus
+ );
+
+VOID
+HalpDeterminePCIDevicesPresent(
+ IN PBUS_HANDLER Bus
+);
+
+BOOLEAN
+HalpInitializePCIInterrupts(
+ VOID
+ );
+
+VOID
+HalpEnablePCIInterrupt(
+ IN ULONG Vector
+ );
+
+VOID
+HalpDisablePCIInterrupt(
+ IN ULONG Vector
+ );
+
+BOOLEAN
+HalpPCIInterruptHandler(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+UCHAR
+READ_CONFIG_UCHAR(
+ IN PVOID ConfigurationAddress,
+ IN ULONG ConfigurationType
+ );
+
+USHORT
+READ_CONFIG_USHORT(
+ IN PVOID ConfigurationAddress,
+ IN ULONG ConfigurationType
+ );
+
+ULONG
+READ_CONFIG_ULONG(
+ IN PVOID ConfigurationAddress,
+ IN ULONG ConfigurationType
+ );
+
+VOID
+WRITE_CONFIG_UCHAR(
+ IN PVOID ConfigurationAddress,
+ IN UCHAR ConfigurationData,
+ IN ULONG ConfigurationType
+ );
+
+VOID
+WRITE_CONFIG_USHORT(
+ IN PVOID ConfigurationAddress,
+ IN USHORT ConfigurationData,
+ IN ULONG ConfigurationType
+ );
+
+VOID
+WRITE_CONFIG_ULONG(
+ IN PVOID ConfigurationAddress,
+ IN ULONG ConfigurationData,
+ IN ULONG ConfigurationType
+ );
+
+NTSTATUS
+HalpMachineSpecificPCIInstallHandler(
+ IN PBUS_HANDLER Bus
+ );
+
+//
+// Define external references.
+//
+
+extern PVOID HalpEisaControlBase[MAX_EISA_BUSSES];
+extern PVOID HalpEisaMemoryBase[MAX_EISA_BUSSES];
+extern PVOID HalpPciControlBase[MAX_PCI_BUSSES];
+extern PVOID HalpPciMemoryBase[MAX_PCI_BUSSES];
+extern PVOID HalpRealTimeClockBase;
+extern PLATFORM_PARAMETER_BLOCK *HalpPlatformParameterBlock;
+extern PLATFORM_SPECIFIC_EXTENSION *HalpPlatformSpecificExtension;
+
+extern PHAL_RESET_DISPLAY_PARAMETERS HalpResetDisplayParameters;
+
+extern ULONG HalpCurrentTimeIncrement;
+extern ULONG HalpNextIntervalCount;
+extern ULONG HalpNextTimeIncrement;
+extern ULONG HalpNewTimeIncrement;
+extern ULONG HalpProfileCountRate;
+
+extern PADAPTER_OBJECT MasterAdapterObject;
+
+//
+// Map buffer prameters. These are initialized in HalInitSystem
+//
+
+extern PHYSICAL_ADDRESS HalpMapBufferPhysicalAddress;
+
+extern ULONG HalpMapBufferSize;
+
+extern ULONG HalpBusType;
+
+#endif // _HALP_
diff --git a/private/ntos/nthals/halflex/ioproc.c b/private/ntos/nthals/halflex/ioproc.c
new file mode 100644
index 000000000..450f8e46d
--- /dev/null
+++ b/private/ntos/nthals/halflex/ioproc.c
@@ -0,0 +1,112 @@
+/*++
+
+Copyright (C) 1991-1995 Microsoft Corporation
+
+Module Name:
+
+ ioproc.c
+
+Abstract:
+
+ Stub functions for UP hals.
+
+Environment:
+
+ Kernel mode only.
+
+
+--*/
+
+#include "halp.h"
+#include "iousage.h"
+
+UCHAR HalName[] = "DeskStation Technology UniFlex PCI/Eisa/Isa HAL";
+
+VOID
+HalpInitializePCIBus (
+ VOID
+ );
+
+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,HalReportResourceUsage)
+#pragma alloc_text(INIT,HalReportResourceUsage)
+#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
+}
+
+
+BOOLEAN
+HalStartNextProcessor (
+ IN PLOADER_PARAMETER_BLOCK pLoaderBlock,
+ IN PKPROCESSOR_STATE pProcessorState
+ )
+{
+ // no other processors
+ return FALSE;
+}
+
+
+VOID
+HalReportResourceUsage (
+ VOID
+ )
+{
+ INTERFACE_TYPE interfacetype;
+ ANSI_STRING AHalName;
+ UNICODE_STRING UHalName;
+
+ switch (HalpBusType) {
+ case UNIFLEX_MACHINE_TYPE_ISA:
+ case UNIFLEX_MACHINE_TYPE_EISA: interfacetype = Isa; break;
+ default: interfacetype = Internal; break;
+ }
+
+ RtlInitAnsiString (&AHalName, HalName);
+ RtlAnsiStringToUnicodeString (&UHalName, &AHalName, TRUE);
+ HalpReportResourceUsage (
+ &UHalName, // descriptive name
+ interfacetype // device space interface type
+ );
+
+ RtlFreeUnicodeString (&UHalName);
+}
+
+
+VOID
+HalpInitOtherBuses (
+ VOID
+ )
+{
+ // no other internal buses supported
+}
diff --git a/private/ntos/nthals/halflex/iousage.c b/private/ntos/nthals/halflex/iousage.c
new file mode 100644
index 000000000..9b30da08e
--- /dev/null
+++ b/private/ntos/nthals/halflex/iousage.c
@@ -0,0 +1,515 @@
+/*++
+
+Copyright (C) 1991-1995 Microsoft Corporation
+
+Module Name:
+
+ iousage.c
+
+Abstract:
+
+Environment:
+
+ Kernel mode only.
+
+--*/
+
+#include "halp.h"
+#include "iousage.h"
+
+//
+// Define constants for system IDTs
+//
+
+#define MAXIMUM_IDTVECTOR 0xff
+#define MAXIMUM_PRIMARY_VECTOR 0xff
+#define PRIMARY_VECTOR_BASE 0x30 // 0-2f are x86 trap vectors
+
+//
+// From usage.c
+//
+
+extern KAFFINITY HalpActiveProcessors;
+
+ADDRESS_USAGE *HalpAddressUsageList;
+
+//
+// IDT vector usage info
+//
+
+IDTUsage HalpIDTUsage[MAXIMUM_IDTVECTOR];
+
+VOID
+HalpGetResourceSortValue (
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
+ OUT PULONG sortscale,
+ OUT PLARGE_INTEGER sortvalue
+ );
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpEnableInterruptHandler)
+#pragma alloc_text(INIT,HalpRegisterVector)
+#pragma alloc_text(INIT,HalpGetResourceSortValue)
+#pragma alloc_text(INIT,HalpReportResourceUsage)
+#endif
+
+
+VOID
+HalpEnableInterruptHandler (
+ IN UCHAR ReportFlags,
+ IN ULONG BusInterruptVector,
+ IN ULONG SystemInterruptVector,
+ IN KIRQL SystemIrql,
+ IN VOID (*HalInterruptServiceRoutine)(VOID),
+ IN KINTERRUPT_MODE InterruptMode
+ )
+/*++
+
+Routine Description:
+
+ This function connects & registers an IDT vectors usage by the HAL.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ //
+ // Remember which vector the hal is connecting so it can be reported
+ // later on
+ //
+ HalpRegisterVector (ReportFlags, BusInterruptVector, SystemInterruptVector, SystemIrql);
+
+
+ //
+ // Connect the IDT and enable the vector now
+ //
+
+#if 0
+ KiSetHandlerAddressToIDT(SystemInterruptVector, HalInterruptServiceRoutine);
+#endif //0
+ HalEnableSystemInterrupt(SystemInterruptVector, SystemIrql, InterruptMode);
+}
+
+
+VOID
+HalpRegisterVector (
+ IN UCHAR ReportFlags,
+ IN ULONG BusInterruptVector,
+ IN ULONG SystemInterruptVector,
+ IN KIRQL SystemIrql
+ )
+/*++
+
+Routine Description:
+
+ This registers an IDT vectors usage by the HAL.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+#if DBG
+ // There are only 0ff IDT entries...
+ ASSERT (SystemInterruptVector <= MAXIMUM_IDTVECTOR &&
+ BusInterruptVector <= MAXIMUM_IDTVECTOR);
+#endif
+
+ //
+ // Remember which vector the hal is connecting so it can be reported
+ // later on
+ //
+
+ HalpIDTUsage[SystemInterruptVector].Flags = ReportFlags;
+ HalpIDTUsage[SystemInterruptVector].Irql = SystemIrql;
+ HalpIDTUsage[SystemInterruptVector].BusReleativeVector = (UCHAR) BusInterruptVector;
+}
+
+
+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;
+
+ default:
+ *sortscale = 4;
+ sortvalue->QuadPart = 0;
+ break;
+ }
+}
+
+
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName,
+ IN INTERFACE_TYPE DeviceInterfaceToUse
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ 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;
+ UCHAR pass, reporton;
+ INTERFACE_TYPE interfacetype;
+ ULONG CurrentIDT, CurrentElement;
+ ADDRESS_USAGE *CurrentAddress;
+ LARGE_INTEGER curvalue, sortvalue;
+ PHYSICAL_ADDRESS TempAddress;
+
+ //
+ // 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;
+
+ //
+ // Make sure all vectors 00-2f are reserved
+ // 00-1E reserved by Intel
+ // 1F reserved by Intel for APIC (apc priority level)
+ // 20-2e reserved by Microsoft
+ // 2f reserved by Microsoft for APIC (dpc priority level)
+ //
+
+ for(i=0; i < PRIMARY_VECTOR_BASE; i++) {
+ if (!(HalpIDTUsage[i].Flags & IDTOwned)) {
+ HalpIDTUsage[i].Flags = InternalUsage;
+ HalpIDTUsage[i].BusReleativeVector = (UCHAR) i;
+ }
+ }
+
+ for(pass=0; pass < 3; pass++) {
+
+ switch(pass) {
+
+ case 0: {
+#if DBG
+DbgPrint("Device LIST...\n");
+#endif // DBG
+ //
+ // First pass - build resource lists for resources reported
+ // reported against device usage.
+ //
+
+ reporton = DeviceUsage & ~IDTOwned;
+ interfacetype = DeviceInterfaceToUse;
+ break;
+ }
+
+ case 1: {
+#if DBG
+DbgPrint("Internal LIST...\n");
+#endif // DBG
+ //
+ // Second pass = build reousce lists for resources reported
+ // as internal usage.
+ //
+
+ reporton = InternalUsage & ~IDTOwned;
+ interfacetype = Internal;
+ break;
+ }
+
+ case 2: {
+#if DBG
+DbgPrint("PCI LIST...\n");
+#endif // DBG
+ //
+ // Third pass = build reousce lists for resources reported
+ // as PCI usage.
+ //
+
+ reporton = PCIUsage & ~IDTOwned;
+ interfacetype = PCIBus;
+ break;
+ }
+ }
+
+ CurrentIDT = 0;
+ CurrentElement = 0;
+ CurrentAddress = HalpAddressUsageList;
+
+ for (; ;) {
+ if (CurrentIDT <= MAXIMUM_IDTVECTOR) {
+ //
+ // Check to see if CurrentIDT needs to be reported
+ //
+
+ if (!(HalpIDTUsage[CurrentIDT].Flags & reporton)) {
+ // Don't report on this one
+ CurrentIDT++;
+ continue;
+ }
+
+ //
+ // Report CurrentIDT resource
+ //
+
+ RPartialDesc.Type = CmResourceTypeInterrupt;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+ RPartialDesc.Flags =
+ HalpIDTUsage[CurrentIDT].Flags & InterruptLatched ?
+ CM_RESOURCE_INTERRUPT_LATCHED :
+ CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+ RPartialDesc.u.Interrupt.Vector = HalpIDTUsage[CurrentIDT].BusReleativeVector;
+ RPartialDesc.u.Interrupt.Level = HalpIDTUsage[CurrentIDT].BusReleativeVector;
+ RPartialDesc.u.Interrupt.Affinity = HalpActiveProcessors;
+
+ RtlCopyMemory (&TPartialDesc, &RPartialDesc, sizeof TPartialDesc);
+ TPartialDesc.u.Interrupt.Vector = CurrentIDT;
+ TPartialDesc.u.Interrupt.Level = HalpIDTUsage[CurrentIDT].Irql;
+
+ CurrentIDT++;
+
+ } else {
+
+ //
+ // Check to see if CurrentAddress needs to be reported
+ //
+
+ if (!CurrentAddress) {
+ break; // No addresses left
+ }
+
+ if (!(CurrentAddress->Flags & reporton)) {
+ // Don't report on this list
+ CurrentElement = 0;
+ CurrentAddress = CurrentAddress->Next;
+ continue;
+ }
+
+ if (!CurrentAddress->Element[CurrentElement].Length) {
+ // End of current list, go to next list
+ CurrentElement = 0;
+ CurrentAddress = CurrentAddress->Next;
+ continue;
+ }
+
+ //
+ // Report CurrentAddress
+ //
+
+ RPartialDesc.Type = (UCHAR) CurrentAddress->Type;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+
+ if (RPartialDesc.Type == CmResourceTypePort) {
+ i = 1; // address space port
+ RPartialDesc.Flags = CM_RESOURCE_PORT_IO;
+ } else {
+ i = 0; // address space memory
+ RPartialDesc.Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ }
+
+ // Notice: assuming u.Memory and u.Port have the same layout
+ RPartialDesc.u.Memory.Start.HighPart = 0;
+ RPartialDesc.u.Memory.Start.LowPart =
+ CurrentAddress->Element[CurrentElement].Start;
+
+ RPartialDesc.u.Memory.Length =
+ CurrentAddress->Element[CurrentElement].Length;
+
+#if DBG
+DbgPrint("Start=0x%x Lenght=0x%x\n", RPartialDesc.u.Memory.Start.LowPart, RPartialDesc.u.Memory.Length);
+#endif // DBG
+
+ // translated address = Raw address
+ RtlCopyMemory (&TPartialDesc, &RPartialDesc, sizeof TPartialDesc);
+ HalTranslateBusAddress (
+ interfacetype, // device bus or internal
+ 0, // bus number
+ RPartialDesc.u.Memory.Start, // source address
+ &i, // address space
+ &TempAddress ); // aligned translated address
+
+ TPartialDesc.u.Memory.Start = TempAddress; // TPartialDesc is pack(4)
+
+#if DBG
+DbgPrint("TRANSLATED ADDRESS Start=0x%x Lenght=0x%x\n", TPartialDesc.u.Memory.Start.LowPart, TPartialDesc.u.Memory.Length);
+#endif // DBG
+
+ if (RPartialDesc.Type == CmResourceTypePort && i == 0) {
+ TPartialDesc.Flags = CM_RESOURCE_PORT_MEMORY;
+ }
+
+ CurrentElement++;
+ }
+
+ //
+ // Include the current resource in the HALs list
+ //
+
+ if (pRFullDesc->InterfaceType != interfacetype) {
+ //
+ // 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 = interfacetype;
+ pTFullDesc->InterfaceType = interfacetype;
+
+ pRPartList = &pRFullDesc->PartialResourceList;
+ pTPartList = &pTFullDesc->PartialResourceList;
+
+ //
+ // Bump current location pointers up
+ //
+ pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
+ pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
+ }
+
+
+ pRPartList->Count++;
+ pTPartList->Count++;
+ RtlCopyMemory (pRCurLoc, &RPartialDesc, sizeof RPartialDesc);
+ RtlCopyMemory (pTCurLoc, &TPartialDesc, sizeof TPartialDesc);
+
+ pRCurLoc++;
+ pTCurLoc++;
+ }
+ }
+
+ 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);
+}
diff --git a/private/ntos/nthals/halflex/iousage.h b/private/ntos/nthals/halflex/iousage.h
new file mode 100644
index 000000000..a9153a982
--- /dev/null
+++ b/private/ntos/nthals/halflex/iousage.h
@@ -0,0 +1,77 @@
+/*++
+
+Copyright (C) 1991-1995 Microsoft Corporation
+Copyright (c) 1992-1995 Digital Equipment Corporation
+
+Module Name:
+
+ iousage.h
+
+Abstract:
+
+ This header file defines the iousage definitions
+
+
+--*/
+
+//
+// External Function Prototypes
+//
+
+VOID
+HalpEnableInterruptHandler (
+ IN UCHAR ReportFlags,
+ IN ULONG BusInterruptVector,
+ IN ULONG SystemInterruptVector,
+ IN KIRQL SystemIrql,
+ IN VOID (*HalInterruptServiceRoutine)(VOID),
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+VOID
+HalpRegisterVector (
+ IN UCHAR ReportFlags,
+ IN ULONG BusInterruptVector,
+ IN ULONG SystemInterruptVector,
+ IN KIRQL SystemIrql
+ );
+
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName,
+ IN INTERFACE_TYPE DeviceInterfaceToUse
+ );
+//
+// Resource usage information
+//
+
+#pragma pack(1)
+typedef struct {
+ UCHAR Flags;
+ KIRQL Irql;
+ UCHAR BusReleativeVector;
+} IDTUsage;
+
+typedef struct _HalAddressUsage{
+ struct _HalAddressUsage *Next;
+ CM_RESOURCE_TYPE Type; // Port or Memory
+ UCHAR Flags; // same as IDTUsage.Flags
+ struct {
+ ULONG Start;
+ ULONG Length;
+ } Element[];
+} ADDRESS_USAGE;
+#pragma pack()
+
+#define IDTOwned 0x01 // IDT is not available for others
+#define InterruptLatched 0x02 // Level or Latched
+#define InternalUsage 0x11 // Report usage on internal bus
+#define DeviceUsage 0x21 // Report usage on device bus
+#define PCIUsage 0x41 // Report usage on PCI bus
+
+extern IDTUsage HalpIDTUsage[];
+extern ADDRESS_USAGE *HalpAddressUsageList;
+
+#define HalpRegisterAddressUsage(a) \
+ (a)->Next = HalpAddressUsageList, HalpAddressUsageList = (a);
+
diff --git a/private/ntos/nthals/halflex/makefile b/private/ntos/nthals/halflex/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halflex/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/halflex/makefile.inc b/private/ntos/nthals/halflex/makefile.inc
new file mode 100644
index 000000000..ad15f5255
--- /dev/null
+++ b/private/ntos/nthals/halflex/makefile.inc
@@ -0,0 +1,5 @@
+obj\*\hal.def: hal.src
+ cl /EP hal.src -D$(PROCESSOR_ARCHITECTIRE)=1 $(C_DEFINES) > obj\*\hal.def
+
+$(TARGETPATH)\*\$(DDKBUILDENV)\hal.lib: $(TARGETPATH)\*\$(DDKBUILDENV)\halflex.lib
+ copy $** $@
diff --git a/private/ntos/nthals/halflex/mips/addrsup.c b/private/ntos/nthals/halflex/mips/addrsup.c
new file mode 100644
index 000000000..795e529a5
--- /dev/null
+++ b/private/ntos/nthals/halflex/mips/addrsup.c
@@ -0,0 +1,204 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ ixphwsup.c
+
+Abstract:
+
+ This module contains the HalpXxx routines for the NT I/O system that
+ are hardware dependent. Were these routines not hardware dependent,
+ they would normally reside in the internal.c module.
+
+Author:
+
+ Michael D. Kinney 30-Apr-1995
+
+Environment:
+
+ Kernel mode, local to I/O system
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+
+#define KERNEL_PCI_VGA_VIDEO_ROM (LONGLONG)(0x8000000000000000)
+
+PLATFORM_RANGE_LIST Gambit20Trebbia13RangeList[] = {
+ { Isa , 0, BusIo, 0, TREB1_GAMBIT_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Isa , 0, BusMemory, 0, TREB1_GAMBIT_ISA_MEMORY_BASE_PHYSICAL , 0x00000000, 0x00ffffff },
+
+ { Isa , 1, BusIo, 0, TREB1_GAMBIT_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Isa , 1, BusMemory, 0, TREB1_GAMBIT_ISA1_MEMORY_BASE_PHYSICAL+0xa0000 , 0x000a0000, 0x000bffff },
+ { Isa , 1, BusMemory, 0, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+
+ { Eisa , 0, BusIo, 0, TREB1_GAMBIT_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Eisa , 0, BusMemory, 0, TREB1_GAMBIT_ISA_MEMORY_BASE_PHYSICAL , 0x00000000, 0xffffffff },
+
+ { Eisa , 1, BusIo, 0, TREB1_GAMBIT_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Eisa , 1, BusMemory, 0, TREB1_GAMBIT_ISA1_MEMORY_BASE_PHYSICAL+0xa0000 , 0x000a0000, 0x000bffff },
+ { Eisa , 1, BusMemory, 0, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+
+ { PCIBus, 0, BusIo, 0, TREB1_GAMBIT_PCI_IO_BASE_PHYSICAL , 0x00000000, 0xffffffff },
+ { PCIBus, 0, BusMemory, 0, TREB1_GAMBIT_PCI_MEMORY_BASE_PHYSICAL+0x40000000 , 0x40000000, 0xffffffff },
+
+ { PCIBus, 1, BusIo, 0, TREB1_GAMBIT_PCI_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { PCIBus, 1, BusMemory, 0, TREB1_GAMBIT_PCI_MEMORY_BASE_PHYSICAL+0xa0000 , 0x000a0000, 0x000bffff },
+ { PCIBus, 1, BusMemory, 0, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+ { PCIBus, 1, BusMemory, 0, TREB1_GAMBIT_PCI_MEMORY_BASE_PHYSICAL+0x40000000 , 0x40000000, 0xffffffff },
+
+ { MaximumInterfaceType, 0, 0, 0, 0 , 0 , 0 }
+};
+
+PLATFORM_RANGE_LIST Gambit20Trebbia20RangeList[] = {
+ { Isa , 0, BusIo, 0, TREB2_GAMBIT_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Isa , 0, BusMemory, 0, TREB2_GAMBIT_ISA_MEMORY_BASE_PHYSICAL+0xa0000 , 0x000a0000, 0x000bffff },
+ { Isa , 0, BusMemory, 0, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+
+ { Isa , 1, BusIo, 0, TREB2_GAMBIT_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Isa , 1, BusMemory, 0, TREB2_GAMBIT_ISA1_MEMORY_BASE_PHYSICAL+0xa0000 , 0x000a0000, 0x000bffff },
+ { Isa , 1, BusMemory, 0, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+
+ { Eisa , 0, BusIo, 0, TREB2_GAMBIT_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Eisa , 0, BusMemory, 0, TREB2_GAMBIT_ISA_MEMORY_BASE_PHYSICAL+0xa0000 , 0x000a0000, 0x000bffff },
+ { Eisa , 0, BusMemory, 0, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+
+ { Eisa , 1, BusIo, 0, TREB2_GAMBIT_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { Eisa , 1, BusMemory, 0, TREB2_GAMBIT_ISA1_MEMORY_BASE_PHYSICAL+0xa0000 , 0x000a0000, 0x000bffff },
+ { Eisa , 1, BusMemory, 0, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+
+ { PCIBus, 0, BusIo, 0, TREB2_GAMBIT_PCI_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { PCIBus, 0, BusMemory, 0, TREB2_GAMBIT_PCI_MEMORY_BASE_PHYSICAL+0xa0000 , 0x000a0000, 0x000bffff },
+ { PCIBus, 0, BusMemory, 0, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+ { PCIBus, 0, BusMemory, 0, TREB2_GAMBIT_PCI_MEMORY_BASE_PHYSICAL+0x40000000 , 0x40000000, 0xffffffff },
+
+ { PCIBus, 1, BusIo, 0, TREB2_GAMBIT_PCI1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff },
+ { PCIBus, 1, BusMemory, 0, TREB2_GAMBIT_PCI1_MEMORY_BASE_PHYSICAL+0xa0000 , 0x000a0000, 0x000bffff },
+ { PCIBus, 1, BusMemory, 0, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff },
+ { PCIBus, 1, BusMemory, 0, TREB2_GAMBIT_PCI1_MEMORY_BASE_PHYSICAL+0x40000000 , 0x40000000, 0xffffffff },
+
+ { MaximumInterfaceType, 0, 0, 0, 0 , 0 , 0 }
+};
+
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+{
+ ULONG i;
+ INTERFACE_TYPE InterfaceType = BusHandler->InterfaceType;
+ ULONG BusNumber = BusHandler->BusNumber;
+ LONGLONG Offset;
+ PVOID va = 0; // note, this is used for a placeholder
+
+//BusAddress.HighPart = 0;
+//DbgPrint("HalTranslateBusAddress(IT=%d,BN=%d,BA=%08x %08x,AS=%d)\n\r",InterfaceType,BusNumber,BusAddress.HighPart,BusAddress.LowPart,*AddressSpace);
+
+ //
+ // PCI Bus 0 is different than PCI Bus 1, but all other PCI busses are the same a PCI Bus 1
+ //
+
+ if (InterfaceType == PCIBus) {
+
+ switch (HalpMotherboardType) {
+ case TREBBIA13 :
+ if (BusNumber > 1) {
+ BusNumber = 1;
+ }
+ break;
+
+ case TREBBIA20 :
+ if (BusNumber == 0) {
+
+ //
+ // There are no resources in PCI Bus #0. It only contains the memory system and bridges.
+ //
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+
+ if (BusNumber >= HalpSecondPciBridgeBusNumber) {
+ BusNumber = 1;
+ } else {
+ BusNumber = 0;
+ }
+ break;
+
+ default :
+
+//DbgPrint(" Invalid Motherboard Type\n\r");
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+ }
+
+ //
+ // If the VGA decodes are not enabled on the DEC PCI-PCI bridge associated with this
+ // memory range, then fail the translation.
+ //
+
+ if (!(HalpVgaDecodeBusNumber & (1<<BusNumber)) &&
+ BusAddress.QuadPart < (LONGLONG)0x0000000000100000 &&
+ (((ADDRESS_SPACE_TYPE)(*AddressSpace) == BusMemory) ||
+ ((ADDRESS_SPACE_TYPE)(*AddressSpace) == UserBusMemory) ||
+ ((ADDRESS_SPACE_TYPE)(*AddressSpace) == KernelPciDenseMemory) ||
+ ((ADDRESS_SPACE_TYPE)(*AddressSpace) == UserPciDenseMemory) )) {
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+
+ //
+ // Search the table for a valid mapping.
+ //
+
+ for(i=0;HalpRangeList[i].InterfaceType!=MaximumInterfaceType;i++) {
+
+ if (HalpRangeList[i].InterfaceType == InterfaceType &&
+ HalpRangeList[i].BusNumber == BusNumber &&
+ HalpRangeList[i].AddressType == (ADDRESS_SPACE_TYPE)(*AddressSpace) &&
+ BusAddress.QuadPart >= HalpRangeList[i].Base &&
+ BusAddress.QuadPart <= HalpRangeList[i].Limit ) {
+
+ TranslatedAddress->QuadPart = HalpRangeList[i].SystemBase;
+ *AddressSpace = HalpRangeList[i].SystemAddressSpace;
+
+ if (TranslatedAddress->QuadPart & KERNEL_PCI_VGA_VIDEO_ROM) {
+ TranslatedAddress->QuadPart &= ~KERNEL_PCI_VGA_VIDEO_ROM;
+ if (HalpPlatformParameterBlock->FirmwareRevision >= 50) {
+ TranslatedAddress->QuadPart += (LONGLONG)HalpPlatformSpecificExtension->PciVideoExpansionRomAddress;
+ } else {
+ TranslatedAddress->QuadPart += (TREB1_GAMBIT_ISA_MEMORY_BASE_PHYSICAL + (LONGLONG)0xc0000);
+ }
+ }
+
+ Offset = BusAddress.QuadPart - HalpRangeList[i].Base;
+ TranslatedAddress->QuadPart += Offset;
+ return(TRUE);
+ }
+ }
+
+ //
+ // A valid mapping was not found.
+ //
+
+ *AddressSpace = 0;
+ TranslatedAddress->QuadPart = 0;
+ return(FALSE);
+}
diff --git a/private/ntos/nthals/halflex/mips/arcssup.c b/private/ntos/nthals/halflex/mips/arcssup.c
new file mode 100644
index 000000000..44d37edd3
--- /dev/null
+++ b/private/ntos/nthals/halflex/mips/arcssup.c
@@ -0,0 +1,144 @@
+/*++
+
+Copyright (c) 1995 DeskStation Technology
+
+Module Name:
+
+ arcssup.c
+
+Abstract:
+
+ This module allocates resources before a call to the ARCS Firmware, and
+ frees those reources after the call returns.
+
+Author:
+
+ Michael D. Kinney 30-Apr-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+typedef
+VOID
+(*PSET_VIRTUAL_BASE) (
+ IN ULONG Number,
+ IN PVOID Base
+ );
+
+
+VOID
+HalpArcsSetVirtualBase (
+ IN ULONG Number,
+ IN PVOID Base
+ )
+
+/*++
+
+Routine Description:
+
+ This routine makes a private call into the ARCS Firmware to provide the
+ firmware with parameters is need to perform I/O operations while NT is
+ active.
+
+Arguments:
+
+ Number : Address space type
+
+ Base : Kernel Virtual Address for the given address space type.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PSYSTEM_PARAMETER_BLOCK SystemParameterBlock = SYSTEM_BLOCK;
+ PSET_VIRTUAL_BASE PrivateSetVirtualBase;
+
+
+ //
+ // Call private vector function SetVirtualBase so that the firmware functions
+ // can perform I/O operations while NT is active. If SetVirtualBase does
+ // not exist, then print an error message out the debug port and halt the system.
+ //
+
+ if ((SystemParameterBlock->VendorVectorLength / 4) >= 28) {
+
+ PrivateSetVirtualBase = *(PSET_VIRTUAL_BASE *)((ULONG)(SystemParameterBlock->VendorVector) + 28*4);
+ PrivateSetVirtualBase(Number,Base);
+
+ } else {
+
+ KdPrint(("HAL : SetVirtualBase does not exist. Halting\n"));
+ for(;;);
+
+ }
+
+}
+
+
+VOID
+HalpAllocateArcsResources (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allocated resources required before an ARCS Firmware call is made.
+ On a MIPS system, if any I/O operations are going to be performed by the
+ firmware routine, a TLB entry needs to be reserved for these I/O operations.
+ This routine reserves a single TLB entry and a 4 KB page out of the kernel
+ virtual address space. These parameters are passed to the firmware through
+ a private vector call.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+
+{
+ HalpArcsSetVirtualBase(6,(PVOID)(HalpAllocateTbEntry()));
+ HalpArcsSetVirtualBase(7,HalpFirmwareVirtualBase);
+}
+
+VOID
+HalpFreeArcsResources (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine frees the TLB entry that was reserved for the ARCS
+ Firmware call.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ HalpFreeTbEntry();
+}
diff --git a/private/ntos/nthals/halflex/mips/dtidef.h b/private/ntos/nthals/halflex/mips/dtidef.h
new file mode 100644
index 000000000..5dcbd65c8
--- /dev/null
+++ b/private/ntos/nthals/halflex/mips/dtidef.h
@@ -0,0 +1,150 @@
+/*++ BUILD Version: 0005 // Increment this if a change has global effects
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ dtidef.h
+
+Abstract:
+
+ This module is the header file that describes hardware addresses
+ for the Jazz system.
+
+Author:
+
+ David N. Cutler (davec) 26-Nov-1990
+
+Revision History:
+
+--*/
+
+#ifndef _DTIDEF_
+#define _DTIDEF_
+
+#include "uniflex.h"
+#include "gambit.h"
+#include "platform.h"
+
+//
+// Define the data structure returned by a private vector firmware function
+// that contains a set of system parameters.
+//
+
+typedef struct PLATFORM_SPECIFIC_EXTENSION {
+ UCHAR PciInterruptToIsaIrq[12];
+ ULONG PciVideoExpansionRomAddress;
+ PVOID AdvancedSetupInfo;
+} PLATFORM_SPECIFIC_EXTENSION;
+
+typedef struct TREB13SETUPINFO {
+ ULONG Reserved1:16;
+ ULONG Drive0Type:4;
+ ULONG Drive1Type:4;
+ ULONG PciInterruptToIsaIrq0:4;
+ ULONG PciInterruptToIsaIrq8:4;
+ ULONG PciInterruptToIsaIrq1:4;
+ ULONG PciInterruptToIsaIrq9:4;
+ ULONG PciInterruptToIsaIrq2:4;
+ ULONG PciInterruptToIsaIrq10:4;
+ ULONG PciInterruptToIsaIrq3:4;
+ ULONG PciInterruptToIsaIrq11:4;
+ ULONG Lpt1Irq:8;
+ ULONG Lpt2Irq:8;
+ ULONG Lpt3Irq:8;
+ ULONG SerialMousePort:8;
+ ULONG EnableAmd1:1;
+ ULONG EnableAmd2:1;
+ ULONG EnableX86Emulator:1;
+ ULONG Reserved2:5;
+ ULONG LoadEmbeddedScsiDrivers:1;
+ ULONG Reserved3:7;
+ ULONG LoadSoftScsiDrivers:1;
+ ULONG LoadFlashScsiDrivers:1;
+ ULONG Reserved4:6;
+ ULONG EnableDelays:1;
+ ULONG Reserved5:7;
+ ULONG ResetDelay:8;
+ ULONG DetectDelay:8;
+ ULONG EnableIdeDriver:1;
+ ULONG Reserved6:7;
+} TREB13SETUPINFO;
+
+typedef struct TREB20SETUPINFO {
+ ULONG Isa0Drive0Type:4;
+ ULONG Isa0Drive1Type:4;
+ ULONG Isa1Drive0Type:4;
+ ULONG Isa1Drive1Type:4;
+ ULONG SerialMousePort:8;
+ ULONG Isa0Lpt1Irq:8;
+ ULONG Isa0Lpt2Irq:8;
+ ULONG Isa0Lpt3Irq:8;
+ ULONG Isa1Lpt1Irq:8;
+ ULONG Isa1Lpt2Irq:8;
+ ULONG Isa1Lpt3Irq:8;
+ ULONG EnableNcr:1;
+ ULONG EnableX86Emulator:1;
+ ULONG LoadEmbeddedScsiDrivers:1;
+ ULONG LoadSoftScsiDrivers:1;
+ ULONG LoadFlashScsiDrivers:1;
+ ULONG EnableDelays:1;
+ ULONG EnableIdeDriver:1;
+ ULONG Reserved1:1;
+ ULONG ResetDelay:8;
+ ULONG DetectDelay:8;
+ ULONG PciInterruptToIsaIrq0:4;
+ ULONG PciInterruptToIsaIrq1:4;
+ ULONG PciInterruptToIsaIrq2:4;
+ ULONG PciInterruptToIsaIrq3:4;
+ ULONG PciInterruptToIsaIrq4:4;
+ ULONG PciInterruptToIsaIrq5:4;
+ ULONG PciInterruptToIsaIrq6:4;
+ ULONG PciInterruptToIsaIrq7:4;
+ ULONG PciInterruptToIsaIrq8:4;
+ ULONG PciInterruptToIsaIrq9:4;
+ ULONG NcrTermLow:1;
+ ULONG NcrTermHigh:1;
+ ULONG Reserved2:6;
+} TREB20SETUPINFO;
+
+//
+// Define the data structure used to describe all bus translations.
+//
+
+typedef struct PLATFORM_RANGE_LIST {
+ INTERFACE_TYPE InterfaceType;
+ ULONG BusNumber;
+ ADDRESS_SPACE_TYPE AddressType;
+ ULONG SystemAddressSpace;
+ LONGLONG SystemBase;
+ LONGLONG Base;
+ LONGLONG Limit;
+} PLATFORM_RANGE_LIST, *PPLATFORM_RANGE_LIST;
+
+//
+// Define clock constants and clock levels.
+//
+
+#define UNIFLEX_CLOCK_LEVEL UNIFLEX_EISA_VECTORS + 0 // Interval clock level is on ISA IRQ 0
+#define UNIFLEX_ISA_DEVICE_LEVEL 4 // ISA bus interrupt level
+#define UNIFLEX_EISA_DEVICE_LEVEL 4 // EISA bus interrupt level
+#define UNIFLEX_PCI_DEVICE_LEVEL 3 // PCI bus interrupt level
+#define UNIFLEX_CLOCK2_LEVEL UNIFLEX_CLOCK_LEVEL
+
+//
+// Define ISA, EISA and PCI device interrupt vectors.
+//
+
+#define UNIFLEX_ISA_VECTORS 48
+#define UNIFLEX_MAXIMUM_ISA_VECTOR (15 + UNIFLEX_ISA_VECTORS)
+#define UNIFLEX_EISA_VECTORS 48
+#define UNIFLEX_MAXIMUM_EISA_VECTOR (15 + UNIFLEX_EISA_VECTORS)
+#define UNIFLEX_ISA1_VECTORS 64
+#define UNIFLEX_MAXIMUM_ISA1_VECTOR (15 + UNIFLEX_ISA1_VECTORS)
+#define UNIFLEX_EISA1_VECTORS 64
+#define UNIFLEX_MAXIMUM_EISA1_VECTOR (15 + UNIFLEX_EISA1_VECTORS)
+#define UNIFLEX_PCI_VECTORS 100
+#define UNIFLEX_MAXIMUM_PCI_VECTOR (15 + UNIFLEX_PCI_VECTORS)
+
+
+#endif // _DTIDEF_
diff --git a/private/ntos/nthals/halflex/mips/flushio.c b/private/ntos/nthals/halflex/mips/flushio.c
new file mode 100644
index 000000000..985601ccc
--- /dev/null
+++ b/private/ntos/nthals/halflex/mips/flushio.c
@@ -0,0 +1,282 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1995 DeskStation Technology
+
+Module Name:
+
+ flushio.c
+
+Abstract:
+
+ This module implements the system dependent kernel function to flush
+ the data cache for I/O transfers on a MIPS R4000 Jazz system.
+
+Author:
+
+ David N. Cutler (davec) 24-Apr-1991
+ Michael D. Kinney 30-Apr-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+
+VOID
+HalpSweepSecondaryCache(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function invalidate all lines from all sets of the secondary write-through cache.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Force read to invalidate entire secondary cache
+ //
+
+ READ_REGISTER_ULONG(HalpSecondaryCacheResetBase);
+}
+
+VOID
+HalFlushIoBuffers (
+ IN PMDL Mdl,
+ IN BOOLEAN ReadOperation,
+ IN BOOLEAN DmaOperation
+ )
+
+/*++
+
+Routine Description:
+
+ This function flushes the I/O buffer specified by the memory descriptor
+ list from the data cache on the current processor.
+
+Arguments:
+
+ Mdl - Supplies a pointer to a memory descriptor list that describes the
+ I/O buffer location.
+
+ ReadOperation - Supplies a boolean value that determines whether the I/O
+ operation is a read into memory.
+
+ DmaOperation - Supplies a boolean value that determines whether the I/O
+ operation is a DMA operation.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG CacheSegment;
+ ULONG Length;
+ ULONG Offset;
+ PULONG PageFrame;
+ ULONG Source;
+
+ //
+ // The Jazz R4000 uses a write back data cache and, therefore, must be
+ // flushed on reads and writes.
+ //
+ // If the length of the I/O operation is greater than the size of the
+ // data cache, then sweep the entire data cache. Otherwise, export or
+ // purge individual pages from the data cache as appropriate.
+ //
+
+ Offset = Mdl->ByteOffset & PCR->DcacheAlignment;
+ Length = (Mdl->ByteCount +
+ PCR->DcacheAlignment + Offset) & ~PCR->DcacheAlignment;
+
+ if (Length > PCR->FirstLevelDcacheSize) {
+
+ //
+ // If the I/O operation is a DMA operation, or the I/O operation is
+ // not a DMA operation and the I/O operation is a page read operation,
+ // then sweep (index/writeback/invalidate) the entire data cache.
+ //
+
+ if ((DmaOperation != FALSE) ||
+ ((DmaOperation == FALSE) &&
+ (ReadOperation != FALSE) &&
+ ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0))) {
+ HalSweepDcache();
+ }
+
+ //
+ // If the I/O operation is a page read, then sweep (index/invalidate)
+ // the entire instruction cache.
+ //
+
+ if ((ReadOperation != FALSE) &&
+ ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0)) {
+ HalSweepIcache();
+ }
+
+ //
+ // Maintain Secondary Caches only on DMA Read Operations
+ //
+
+ if (HalpPlatformParameterBlock->External.UnifiedCache.Size>0 &&
+ ReadOperation!=FALSE &&
+ DmaOperation!=FALSE) {
+
+ //
+ // See if the transfer length is larger than the size of the secondary cache
+ //
+
+ if (Length > HalpPlatformParameterBlock->External.UnifiedCache.Size) {
+ //
+ // Do a fast invalidate of all tags in all sets of the secondary cache
+ //
+
+ HalpSweepSecondaryCache();
+ } else {
+
+ //
+ // Walk MDL and do hit/invalidate cycles on the secondary cache
+ //
+
+ Offset = Mdl->ByteOffset & ~PCR->DcacheAlignment;
+ PageFrame = (PULONG)(Mdl + 1);
+ Source = ((ULONG)(Mdl->StartVa) & 0xfffff000) | Offset;
+
+ do {
+ if (Length >= (PAGE_SIZE - Offset)) {
+ CacheSegment = PAGE_SIZE - Offset;
+ } else {
+ CacheSegment = Length;
+ }
+
+ HalpInvalidateSecondaryCachePage((PVOID)Source, *PageFrame, CacheSegment);
+
+ PageFrame += 1;
+ Length -= CacheSegment;
+ Offset = 0;
+ Source += CacheSegment;
+ } while(Length != 0);
+ }
+ }
+
+ } else {
+
+ //
+ // Export or purge the specified pages from the data cache and
+ // instruction caches as appropriate.
+ //
+ // Compute the number of pages to flush and the starting MDL page
+ // frame address.
+ //
+
+ Offset = Mdl->ByteOffset & ~PCR->DcacheAlignment;
+ PageFrame = (PULONG)(Mdl + 1);
+ Source = ((ULONG)(Mdl->StartVa) & 0xfffff000) | Offset;
+
+ //
+ // Export or purge the specified page segments from the data and
+ // instruction caches as appropriate.
+ //
+
+ do {
+
+ if (Length >= (PAGE_SIZE - Offset)) {
+ CacheSegment = PAGE_SIZE - Offset;
+ } else {
+ CacheSegment = Length;
+ }
+
+ if (ReadOperation == FALSE) {
+
+ //
+ // The I/O operation is a write and the data only needs to
+ // to be copied back into memory if the operation is also
+ // a DMA operation.
+ //
+
+ if (DmaOperation != FALSE) {
+ HalFlushDcachePage((PVOID)Source, *PageFrame, CacheSegment);
+ }
+
+ } else {
+
+ //
+ // If the I/O operation is a DMA operation, then purge the
+ // data cache. Otherwise, is the I/O operation is a page read
+ // operation, then export the data cache.
+ //
+
+ if (DmaOperation != FALSE) {
+ HalPurgeDcachePage((PVOID)Source, *PageFrame, CacheSegment);
+ if (HalpPlatformParameterBlock->External.UnifiedCache.Size>0) {
+ HalpInvalidateSecondaryCachePage((PVOID)Source, *PageFrame, CacheSegment);
+ }
+ } else if ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0) {
+ HalFlushDcachePage((PVOID)Source, *PageFrame, CacheSegment);
+ }
+
+ //
+ // If the I/O operation is a page read, then the instruction
+ // cache must be purged.
+ //
+
+ if ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0) {
+ HalPurgeIcachePage((PVOID)Source, *PageFrame, CacheSegment);
+ }
+ }
+
+ PageFrame += 1;
+ Length -= CacheSegment;
+ Offset = 0;
+ Source += CacheSegment;
+
+ } while(Length != 0);
+ }
+ return;
+}
+
+ULONG
+HalGetDmaAlignmentRequirement (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the alignment requirements for DMA transfers on
+ host system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The DMA alignment requirement is returned as the fucntion value.
+
+--*/
+
+{
+ return PCR->DcacheFillSize;
+}
diff --git a/private/ntos/nthals/halflex/mips/gambit.h b/private/ntos/nthals/halflex/mips/gambit.h
new file mode 100644
index 000000000..7356d16cd
--- /dev/null
+++ b/private/ntos/nthals/halflex/mips/gambit.h
@@ -0,0 +1,54 @@
+/*++
+
+Copyright (c) 1995 DeskStation Technology
+
+Module Name:
+
+ gambit.h
+
+Abstract:
+
+ This file contains definitions specific to the Gambit (MIPS R4600)
+ processor module.
+
+Author:
+
+ Michael D. Kinney 31-Aug-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+//
+// Define physical base addresses for system mapping.
+//
+
+#define TREB1_GAMBIT_ISA_IO_BASE_PHYSICAL (LONGLONG)0x200000000 // ISA I/O Base Address
+#define TREB1_GAMBIT_ISA_MEMORY_BASE_PHYSICAL (LONGLONG)0x000000000 // ISA Memory Base Address
+#define TREB1_GAMBIT_ISA1_IO_BASE_PHYSICAL (LONGLONG)0xa00000000 // ISA I/O Base Address
+#define TREB1_GAMBIT_ISA1_MEMORY_BASE_PHYSICAL (LONGLONG)0x800000000 // ISA Memory Base Address
+#define TREB1_GAMBIT_PCI_IO_BASE_PHYSICAL (LONGLONG)0xa00000000 // PCI I/O Base Address
+#define TREB1_GAMBIT_PCI_MEMORY_BASE_PHYSICAL (LONGLONG)0x800000000 // PCI Memory Base Address
+
+#define TREB2_GAMBIT_ISA_IO_BASE_PHYSICAL (LONGLONG)0xa00000000 // ISA I/O Base Address
+#define TREB2_GAMBIT_ISA_MEMORY_BASE_PHYSICAL (LONGLONG)0x800000000 // ISA Memory Base Address
+#define TREB2_GAMBIT_ISA1_IO_BASE_PHYSICAL (LONGLONG)0x200000000 // ISA I/O Base Address
+#define TREB2_GAMBIT_ISA1_MEMORY_BASE_PHYSICAL (LONGLONG)0x000000000 // ISA Memory Base Address
+#define TREB2_GAMBIT_PCI_IO_BASE_PHYSICAL (LONGLONG)0xa00000000 // PCI I/O Base Address
+#define TREB2_GAMBIT_PCI_MEMORY_BASE_PHYSICAL (LONGLONG)0x800000000 // PCI Memory Base Address
+#define TREB2_GAMBIT_PCI1_IO_BASE_PHYSICAL (LONGLONG)0x200000000 // PCI I/O Base Address
+#define TREB2_GAMBIT_PCI1_MEMORY_BASE_PHYSICAL (LONGLONG)0x000000000 // PCI Memory Base Address
+
+#define GAMBIT_PCI_CONFIG0_BASE_PHYSICAL (LONGLONG)0xb00000000 // PCI Config Type 0 Base Address
+#define GAMBIT_PCI_CONFIG1_BASE_PHYSICAL (LONGLONG)0xc00000000 // PCI Config Type 1 Base Address
+#define GAMBIT_PCI_INTERRUPT_BASE_PHYSICAL (LONGLONG)0x500000000 // PCI Interrupt Register Base Address
+#define GAMBIT_SECONDARY_CACHE_RESET_BASE_PHYSICAL (LONGLONG)0x700000000 // Secondary Cache Reset Register Base Address
+#define GAMBIT_SECONDARY_CACHE_INVALIDATE_PHYSICAL_BASE (LONGLONG)0x600000000 // Secondary Cache Invalidate Base Address
+#define GAMBIT_PFN_SECONDARY_CACHE_INVALIDATE_PHYSICAL_BASE 0x00600000 // PFN version of Secondary Cache Invalidate Base Address
+#define GAMBIT_DMA_CACHE_BASE_PHYSICAL (LONGLONG)0x001c0000 // DMA Cache Base Address
+#define GAMBIT_DMA_CACHE_SIZE 0x00040000 // Size of DMA Cache in bytes - 256 KB
diff --git a/private/ntos/nthals/halflex/mips/info.c b/private/ntos/nthals/halflex/mips/info.c
new file mode 100644
index 000000000..f9abd9d6d
--- /dev/null
+++ b/private/ntos/nthals/halflex/mips/info.c
@@ -0,0 +1,116 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ info.c
+
+Abstract:
+
+Author:
+
+ Ken Reneris (kenr) 08-Aug-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+
+#include "halp.h"
+
+#ifdef _PNP_POWER_
+HAL_CALLBACKS HalCallback;
+#endif // _PNP_POWER_
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HaliQuerySystemInformation)
+#pragma alloc_text(PAGE,HaliSetSystemInformation)
+#endif
+
+
+NTSTATUS
+HaliQuerySystemInformation(
+ IN HAL_QUERY_INFORMATION_CLASS InformationClass,
+ IN ULONG BufferSize,
+ OUT PVOID Buffer,
+ OUT PULONG ReturnedLength
+ )
+/*++
+
+Routine Description:
+
+ The function returns system-wide information controlled by the HAL for a
+ variety of classes.
+
+Arguments:
+
+ InformationClass - Information class of the request.
+
+ BufferSize - Size of buffer supplied by the caller.
+
+ Buffer - Supplies the space to store the data.
+
+ ReturnedLength - Supplies a count in bytes of the amount of data returned.
+
+Return Value:
+
+ STATUS_SUCCESS or error.
+
+--*/
+{
+ NTSTATUS Status;
+
+ switch (InformationClass) {
+
+ default:
+ Status = STATUS_INVALID_LEVEL;
+ break;
+ }
+
+ return(Status);
+}
+
+NTSTATUS
+HaliSetSystemInformation (
+ IN HAL_SET_INFORMATION_CLASS InformationClass,
+ IN ULONG BufferSize,
+ IN PVOID Buffer
+ )
+/*++
+
+Routine Description:
+
+ The function allows setting of various fields return by
+ HalQuerySystemInformation.
+
+Arguments:
+
+ InformationClass - Information class of the request.
+
+ BufferSize - Size of buffer supplied by the caller.
+
+ Buffer - Supplies the data to be set.
+
+Return Value:
+
+ STATUS_SUCCESS or error.
+
+--*/
+{
+ NTSTATUS Status;
+
+ switch (InformationClass) {
+
+ default:
+ Status = STATUS_INVALID_LEVEL;
+ break;
+ }
+
+ return Status;
+}
diff --git a/private/ntos/nthals/halflex/mips/initsys.c b/private/ntos/nthals/halflex/mips/initsys.c
new file mode 100644
index 000000000..e23d422c6
--- /dev/null
+++ b/private/ntos/nthals/halflex/mips/initsys.c
@@ -0,0 +1,405 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ initsys.c
+
+Abstract:
+
+ This module implements the platform specific potions of the
+ HAL initialization.
+
+Author:
+
+ Michael D. Kinney 3-May-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+
+//
+// The WINNT350 define is used to remove memory from the MDL passed in
+// from the loader block. This is required because Windows NT 3.50 had
+// some problems with holes in the MDL. This problem was fixed for
+// Windows NT 3.51.
+//
+
+//#define WINNT350
+
+ULONG HalpIoArchitectureType = UNKNOWN_PROCESSOR_MODULE;
+
+ULONG IoSpaceAlreadyMapped = FALSE;
+UCHAR HalpSecondPciBridgeBusNumber = 2;
+ULONG HalpMotherboardType = MOTHERBOARD_UNKNOWN;
+UCHAR *HalpInterruptLineToBit;
+UCHAR *HalpBitToInterruptLine;
+UCHAR *HalpInterruptLineToVirtualIsa;
+UCHAR *HalpVirtualIsaToInterruptLine;
+ULONGLONG HalpPciConfig0BasePhysical;
+ULONGLONG HalpPciConfig1BasePhysical;
+ULONGLONG HalpIsaIoBasePhysical;
+ULONGLONG HalpIsa1IoBasePhysical;
+ULONGLONG HalpIsaMemoryBasePhysical;
+ULONGLONG HalpIsa1MemoryBasePhysical;
+ULONGLONG HalpPciIoBasePhysical;
+ULONGLONG HalpPci1IoBasePhysical;
+ULONGLONG HalpPciMemoryBasePhysical;
+ULONGLONG HalpPci1MemoryBasePhysical;
+PPLATFORM_RANGE_LIST HalpRangeList = NULL;
+ULONG HalpIntel82378BusNumber = 0;
+ULONG HalpIntel82378DeviceNumber = 0;
+ULONG HalpSecondIntel82378DeviceNumber = 0;
+ULONG HalpNonExistentPciDeviceMask = ~TREB20_MOTHERBOARD_PCI_DEVICE_MASK;
+ULONG HalpNonExistentPci1DeviceMask = 0;
+ULONG HalpNonExistentPci2DeviceMask = 0;
+ULONG HalpNumberOfIsaBusses;
+ULONG HalpVgaDecodeBusNumber;
+
+//
+// Function prototypes.
+//
+
+VOID
+HalpGetPlatformParameterBlock(
+ VOID
+ );
+
+ULONG FindIntel82378(ULONG Dec2105xBusNumber,ULONG Dec2105xDeviceNumber,ULONG BusNumber,ULONG IsaBusNumber)
+
+{
+ ULONG i;
+ ULONG MaxDevice;
+
+ if (BusNumber == 0) {
+ MaxDevice = PCI_MAX_LOCAL_DEVICE;
+ } else {
+ MaxDevice = 31;
+ }
+ for(i=0;i<=MaxDevice;i++) {
+ if (HalpPciLowLevelConfigRead(BusNumber,i,0,0) == 0x04848086) {
+ return(i);
+ }
+ }
+ return(0);
+ }
+
+VOID
+HalpGetIoArchitectureType(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function gets the I/O Architecture Type from the Platform Parameter Block
+ retrieved from the firmware.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG Device16;
+ ULONG Device17;
+
+ //
+ // If the I/O Architecture Type is already known, then just return.
+ //
+
+ if (HalpIoArchitectureType != UNKNOWN_PROCESSOR_MODULE) {
+ return;
+ }
+
+ //
+ // If the Platform Parameter Block has not been retrieved from the firmware,
+ // then do it now.
+ //
+
+ if (HalpPlatformParameterBlock == NULL) {
+ HalpGetPlatformParameterBlock();
+ }
+
+ //
+ // Check for the R4600 Gambit Module Type.
+ //
+
+ if (strcmp(HalpPlatformParameterBlock->ModuleName,"GAMBIT2.0")==0) {
+ HalpIoArchitectureType = R4600_PROCESSOR_MODULE;
+ }
+
+ //
+ // If the I/O Architecture Type is still unknown then HALT.
+ //
+
+ if (HalpIoArchitectureType == UNKNOWN_PROCESSOR_MODULE) {
+ for(;;);
+ }
+
+ HalpPciConfig0BasePhysical = GAMBIT_PCI_CONFIG0_BASE_PHYSICAL;
+ HalpPciConfig1BasePhysical = GAMBIT_PCI_CONFIG1_BASE_PHYSICAL;
+
+ //
+ // Determine the motherboard type. Assume TREBBIA20 so we can do some config cycles.
+ //
+
+ HalpMotherboardType = TREBBIA20;
+
+ Device16 = HalpPciLowLevelConfigRead(0,0x10,0,0);
+ Device17 = HalpPciLowLevelConfigRead(0,0x11,0,0);
+
+ //
+ // Now assume motherboard type is unknown and check out values returned from config cycles.
+ //
+
+ HalpMotherboardType = MOTHERBOARD_UNKNOWN;
+
+ if (Device16 == 0x00211011 && Device17 == 0x00211011) {
+ HalpMotherboardType = TREBBIA20;
+
+ //
+ // Find and initialize up to two Jubilee adapters.
+ //
+
+ HalpNumberOfIsaBusses = 1;
+ HalpIntel82378BusNumber = 1;
+ HalpIntel82378DeviceNumber = FindIntel82378(0,0x11,1,0);
+ HalpSecondPciBridgeBusNumber = (UCHAR)((HalpPciLowLevelConfigRead(0,0x10,0,0x18) >> 8) & 0xff);
+ HalpSecondIntel82378DeviceNumber = FindIntel82378(0,0x10,HalpSecondPciBridgeBusNumber,1);
+ if (HalpSecondIntel82378DeviceNumber != 0) {
+ HalpNumberOfIsaBusses = 2;
+ }
+ HalpVgaDecodeBusNumber = 0x00;
+ if (HalpPciLowLevelConfigRead(0,0x11,0,0x3c) & 0x00080000) {
+ HalpVgaDecodeBusNumber |= 0x01;
+ }
+ if (HalpPciLowLevelConfigRead(0,0x10,0,0x3c) & 0x00080000) {
+ HalpVgaDecodeBusNumber |= 0x02;
+ }
+ }
+
+ if (Device16 == 0x04848086 && Device17 == 0x00011011) {
+ HalpMotherboardType = TREBBIA13;
+ HalpNumberOfIsaBusses = 1;
+ HalpIntel82378BusNumber = 0;
+ HalpIntel82378DeviceNumber = 0x10;
+ HalpVgaDecodeBusNumber = 0x01;
+ if (HalpPciLowLevelConfigRead(0,0x11,0,0x3c) & 0x00080000) {
+ HalpVgaDecodeBusNumber |= 0x02;
+ }
+ }
+
+ //
+ // If the Motherboard Type is unknown then HALT.
+ //
+
+ if (HalpMotherboardType == MOTHERBOARD_UNKNOWN) {
+ for(;;);
+ }
+
+ //
+ // Determine the base physical addresses and PCI interrupt translation tables.
+ //
+
+ if (HalpMotherboardType == TREBBIA13) {
+ HalpIsaIoBasePhysical = TREB1_GAMBIT_ISA_IO_BASE_PHYSICAL;
+ HalpIsa1IoBasePhysical = (ULONGLONG)(0);
+ HalpIsaMemoryBasePhysical = TREB1_GAMBIT_ISA_MEMORY_BASE_PHYSICAL;
+ HalpIsa1MemoryBasePhysical = (ULONGLONG)(0);
+ HalpPciIoBasePhysical = TREB1_GAMBIT_PCI_IO_BASE_PHYSICAL;
+ HalpPci1IoBasePhysical = (ULONGLONG)(0);
+ HalpPciMemoryBasePhysical = TREB1_GAMBIT_PCI_MEMORY_BASE_PHYSICAL;
+ HalpPci1MemoryBasePhysical = (ULONGLONG)(0);
+ HalpRangeList = Gambit20Trebbia13RangeList;
+ HalpNonExistentPciDeviceMask = ~TREB13_MOTHERBOARD_PCI_DEVICE_MASK;
+ HalpNonExistentPci1DeviceMask = 0;
+ HalpNonExistentPci2DeviceMask = 0;
+ HalpInterruptLineToBit = Treb13InterruptLineToBit;
+ HalpBitToInterruptLine = Treb13BitToInterruptLine;
+ HalpInterruptLineToVirtualIsa = Treb13InterruptLineToVirtualIsa;
+ HalpVirtualIsaToInterruptLine = Treb13VirtualIsaToInterruptLine;
+ if (HalpPlatformParameterBlock->FirmwareRevision >= 50) {
+ if (!((TREB13SETUPINFO *)(HalpPlatformSpecificExtension->AdvancedSetupInfo))->EnableAmd1) {
+ HalpNonExistentPciDeviceMask |= (1 << 0x0d);
+ }
+ if (!((TREB13SETUPINFO *)(HalpPlatformSpecificExtension->AdvancedSetupInfo))->EnableAmd2) {
+ HalpNonExistentPciDeviceMask |= (1 << 0x0f);
+ }
+ }
+ }
+ if (HalpMotherboardType == TREBBIA20) {
+ HalpIsaIoBasePhysical = TREB2_GAMBIT_ISA_IO_BASE_PHYSICAL;
+ HalpIsa1IoBasePhysical = TREB2_GAMBIT_ISA1_IO_BASE_PHYSICAL;
+ HalpIsaMemoryBasePhysical = TREB2_GAMBIT_ISA_MEMORY_BASE_PHYSICAL;
+ HalpIsa1MemoryBasePhysical = TREB2_GAMBIT_ISA1_MEMORY_BASE_PHYSICAL;
+ HalpPciIoBasePhysical = TREB2_GAMBIT_PCI_IO_BASE_PHYSICAL;
+ HalpPci1IoBasePhysical = TREB2_GAMBIT_PCI1_IO_BASE_PHYSICAL;
+ HalpPciMemoryBasePhysical = TREB2_GAMBIT_PCI_MEMORY_BASE_PHYSICAL;
+ HalpPci1MemoryBasePhysical = TREB2_GAMBIT_PCI1_MEMORY_BASE_PHYSICAL;
+ HalpRangeList = Gambit20Trebbia20RangeList;
+ HalpNonExistentPciDeviceMask = ~TREB20_MOTHERBOARD_PCI_DEVICE_MASK;
+ HalpNonExistentPci1DeviceMask = 0;
+ HalpNonExistentPci2DeviceMask = 0;
+ HalpInterruptLineToBit = Treb20InterruptLineToBit;
+ HalpBitToInterruptLine = Treb20BitToInterruptLine;
+ HalpInterruptLineToVirtualIsa = Treb20InterruptLineToVirtualIsa;
+ HalpVirtualIsaToInterruptLine = Treb20VirtualIsaToInterruptLine;
+ if (HalpPlatformParameterBlock->FirmwareRevision >= 50) {
+ if (!((TREB20SETUPINFO *)(HalpPlatformSpecificExtension->AdvancedSetupInfo))->EnableNcr) {
+ HalpNonExistentPci2DeviceMask |= (1 << 0x07);
+ }
+ }
+ }
+
+ //
+ // If the address translation table is still NULL then HALT.
+ //
+
+ if (HalpRangeList == NULL) {
+ for(;;);
+ }
+}
+
+BOOLEAN
+HalpInitSystem (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes the Hardware Architecture Layer (HAL).
+
+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.
+
+--*/
+
+{
+#ifdef WINNT350
+ PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
+ PLIST_ENTRY NextMd;
+ PLIST_ENTRY DeleteMd;
+#endif
+
+ if (Phase == 0) {
+
+ //
+ // Phase 0 initialization.
+ //
+
+ HalpGetIoArchitectureType();
+
+ //
+ // Set the number of process id's and TB entries.
+ //
+
+ **((PULONG *)(&KeNumberProcessIds)) = 256;
+ **((PULONG *)(&KeNumberTbEntries)) = 48;
+
+#ifdef WINNT350
+ NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
+ while (NextMd != &LoaderBlock->MemoryDescriptorListHead) {
+ Descriptor = CONTAINING_RECORD( NextMd,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry );
+ //
+ // If Descriptor is >256 MB then remove it for NT 3.5.
+ // This problem was fixed in NT 3.51.
+ //
+
+ DeleteMd = NextMd;
+ NextMd = Descriptor->ListEntry.Flink;
+ if ((Descriptor->BasePage + Descriptor->PageCount) >= ((256*1024*1024)/4096)) {
+
+ //
+ // Delete Descriptor
+ //
+
+ RemoveEntryList(DeleteMd);
+ }
+
+ }
+#endif
+
+ //
+ // Initialize Dma Cache Parameters
+ //
+
+ HalpMapBufferSize = GAMBIT_DMA_CACHE_SIZE;
+ HalpMapBufferPhysicalAddress.QuadPart = GAMBIT_DMA_CACHE_BASE_PHYSICAL;
+
+ return TRUE;
+
+ } else {
+
+ UCHAR Message[80];
+
+ //
+ // Phase 1 initialization.
+ //
+
+ HalpMapIoSpace();
+
+ //
+ // Initialize the existing bus handlers.
+ //
+
+ HalpRegisterInternalBusHandlers();
+
+ //
+ // Initialize the PCI bus.
+ //
+
+ HalpInitializePCIBus ();
+
+ //
+ // Initialize the display adapter.
+ //
+
+ if (IoSpaceAlreadyMapped == FALSE) {
+ HalpInitializeX86DisplayAdapter();
+ IoSpaceAlreadyMapped = TRUE;
+ }
+
+ if (HalpMotherboardType == TREBBIA13) {
+ HalDisplayString("DeskStation Technology UniFlex/Raptor 3 Motherboard Rev. 1\n\r");
+ } else {
+ HalDisplayString("DeskStation Technology Raptor ReFlex Motherboard Rev. 2\n\r");
+ }
+
+ HalDisplayString("DeskStation Technology MIPS R4600 Processor Module\n\r");
+
+ HalpCreateDmaStructures();
+
+ HalpCalibrateStall();
+
+ return TRUE;
+ }
+}
diff --git a/private/ntos/nthals/halflex/mips/intsup.c b/private/ntos/nthals/halflex/mips/intsup.c
new file mode 100644
index 000000000..9ef7a4e98
--- /dev/null
+++ b/private/ntos/nthals/halflex/mips/intsup.c
@@ -0,0 +1,240 @@
+/*++
+
+Copyright (c) 1995 DeskStation Technology
+
+Module Name:
+
+ intsup.c
+
+Abstract:
+
+ This module implements the HAL enable/disable system interrupt for
+ platform specific vectors.
+
+Author:
+
+ Michael D. Kinney 14-May-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+VOID
+HalpDisablePlatformInterrupt (
+ 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.
+
+--*/
+
+{
+ //
+ // There are no additional interrupts for MIPS processors
+ //
+
+ return;
+}
+
+
+BOOLEAN
+HalpEnablePlatformInterrupt (
+ 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
+
+--*/
+
+{
+ //
+ // There are no additional interrupts for MIPS processors
+ //
+
+ return FALSE;
+}
+
+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 ISA and EISA are the same as the InterruptLevel, so ignore.
+
+Arguments:
+
+ BusHandler - Registered BUSHANDLER for the target configuration space
+
+ RootHandler - Registered BUSHANDLER for the orginating HalGetBusData
+ request.
+
+ 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;
+
+ *Affinity = 1;
+
+ if ( (InterfaceType==PCI_BUS && BusInterruptLevel>=0x0 && BusInterruptLevel<=0x0f) ||
+ (HalpMotherboardType==TREBBIA13 && InterfaceType==Isa && BusNumber==1) ) {
+
+ ULONG i;
+
+ for(i=0;i<12;i++) {
+ if (BusInterruptLevel == HalpPlatformSpecificExtension->PciInterruptToIsaIrq[i]) {
+
+ *Irql = UNIFLEX_PCI_DEVICE_LEVEL;
+
+ BusInterruptLevel = HalpVirtualIsaInterruptToInterruptLine(i) - 0x10;
+
+ return(BusInterruptLevel + UNIFLEX_PCI_VECTORS);
+ }
+ }
+
+ //
+ // Unrecognized interrupt
+ //
+
+ *Irql = 0;
+ *Affinity = 0;
+ return(0);
+
+ } else if (InterfaceType == PCIBus && BusInterruptLevel >= 0x10) {
+
+ //
+ // Assumes all PCI devices coming in on same pin
+ //
+
+ *Irql = UNIFLEX_PCI_DEVICE_LEVEL;
+
+ BusInterruptLevel -= 0x10;
+
+ //
+ // The vector is equal to the specified bus level plus the PCI_VECTOR.
+ //
+
+ return(BusInterruptLevel + UNIFLEX_PCI_VECTORS);
+
+ } else if (InterfaceType == Isa) {
+
+ //
+ // Assumes all ISA devices coming in on same pin
+ //
+
+ *Irql = UNIFLEX_ISA_DEVICE_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level plus the ISA_VECTOR.
+ // This is assuming that the ISA levels not assigned Interrupt Levels
+ // in the Beta programming guide are unused in the LCA system.
+ // Otherwise, need a different encoding scheme.
+ //
+ // Not all interrupt levels are actually supported on Beta;
+ // Should we make some of them illegal here?
+
+ if (BusNumber == 0) {
+ return(BusInterruptLevel + UNIFLEX_ISA_VECTORS);
+ }
+ if (BusNumber == 1) {
+ return(BusInterruptLevel + UNIFLEX_ISA1_VECTORS);
+ }
+ } else if (InterfaceType == Eisa) {
+
+ //
+ // Assumes all EISA devices coming in on same pin
+ //
+
+ *Irql = UNIFLEX_EISA_DEVICE_LEVEL;
+
+ //
+ // The vector is equal to the specified bus level plus the EISA_VECTOR.
+ //
+
+ if (BusNumber == 0) {
+ return(BusInterruptLevel + UNIFLEX_EISA_VECTORS);
+ }
+ if (BusNumber == 1) {
+ return(BusInterruptLevel + UNIFLEX_EISA1_VECTORS);
+ }
+
+ } else {
+
+ //
+ // Not an interface supported on EB64P systems
+ //
+
+ *Irql = 0;
+ *Affinity = 0;
+ return(0);
+ }
+}
diff --git a/private/ntos/nthals/halflex/mips/j4cache.s b/private/ntos/nthals/halflex/mips/j4cache.s
new file mode 100644
index 000000000..d50bd2ba5
--- /dev/null
+++ b/private/ntos/nthals/halflex/mips/j4cache.s
@@ -0,0 +1,1091 @@
+#if defined(R4000)
+
+// TITLE("Cache Flush")
+//++
+//
+// Copyright (c) 1991 Microsoft Corporation
+//
+// Module Name:
+//
+// j4cache.s
+//
+// Abstract:
+//
+// This module implements the code necessary for cache operations on
+// a MIPS R4000.
+//
+// Author:
+//
+// David N. Cutler (davec) 19-Dec-1991
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+#include "gambit.h"
+
+
+//
+// Define cache operations constants.
+//
+
+#define COLOR_BITS (7 << PAGE_SHIFT) // color bit (R4000 - 8kb cache)
+#define COLOR_MASK (0x7fff) // color mask (R4000 - 8kb cache)
+#define FLUSH_BASE 0xfffe0000 // flush base address
+#define PROTECTION_BITS ((1 << ENTRYLO_V) | (1 << ENTRYLO_D)) //
+
+ SBTTL("Change Color Page")
+//++
+//
+// VOID
+// HalChangeColorPage (
+// IN PVOID NewColor,
+// IN PVOID OldColor,
+// IN ULONG PageFrame
+// )
+//
+// Routine Description:
+//
+// This function changes the color of a page if the old and new colors
+// do not match.
+//
+// The algorithm used to change colors for a page is as follows:
+//
+// 1. Purge (hit/invalidate) the page from the instruction cache
+// using the old color.
+//
+// 2. Purge (hit/invalidate) the page from the data cache using
+// the old color.
+//
+// Arguments:
+//
+// NewColor (a0) - Supplies the page aligned virtual address of the
+// new color of the page to change.
+//
+// OldColor (a1) - Supplies the page aligned virtual address of the
+// old color of the page to change.
+//
+// PageFrame (a2) - Supplies the page frame number of the page that
+// is changed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+ .space 3 * 4 // fill
+CpRa: .space 4 // saved return address
+CpFrameLength: // length of stack frame
+CpA0: .space 4 // (a0)
+CpA1: .space 4 // (a1)
+CpA2: .space 4 // (a2)
+CpA3: .space 4 // (a3)
+
+ NESTED_ENTRY(HalChangeColorPage, CpFrameLength, zero)
+
+ subu sp,sp,CpFrameLength // allocate stack frame
+ sw ra,CpRa(sp) // save return address
+
+ PROLOGUE_END
+
+ and a0,a0,COLOR_BITS // isolate new color bits
+ and a1,a1,COLOR_BITS // isolate old color bits
+ beq a0,a1,10f // if eq, colors match
+ sw a1,CpA1(sp) // save old color bits
+ sw a2,CpA2(sp) // save page frame
+
+//
+// Purge the instruction cache using the old page color.
+//
+
+ move a0,a1 // set color value
+ move a1,a2 // set page frame number
+ li a2,PAGE_SIZE // set length of purge
+ jal HalPurgeIcachePage // purge instruction cache page
+
+//
+// Flush the data cache using the old page color.
+//
+
+ lw a0,CpA1(sp) // get old color bits
+ lw a1,CpA2(sp) // get page frame number
+ li a2,PAGE_SIZE // set length of purge
+ jal HalFlushDcachePage // purge data cache page
+10: lw ra,CpRa(sp) // get return address
+ addu sp,sp,CpFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalChangeColorPage
+
+ SBTTL("Flush Data Cache Page")
+//++
+//
+// VOID
+// HalFlushDcachePage (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function flushes (hit/writeback/invalidate) up to a page of data
+// from the data cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is flushed.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is flushed.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// flushed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalFlushDcachePage)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ and a0,a0,COLOR_MASK // isolate color and offset bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10: mfc0 t3,wired // get TB entry index
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,15f // if ne, second level cache present
+ move t4,v0 // set flush block size
+ .set at
+ .set reorder
+
+//
+// Flush a page from the data cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,30f // if eq, no blocks to flush
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ bne zero,v0,40f // if ne, second level cache present
+ subu t9,t9,t4 // compute ending loop address
+
+//
+// Flush the primary data cache only.
+//
+
+20: cache HIT_WRITEBACK_INVALIDATE_D,0(t8) // invalidate cache block
+ bne t8,t9,20b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+30: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+//
+// Flush the primary and secondary data caches.
+//
+
+ .set noreorder
+ .set noat
+40: cache HIT_WRITEBACK_INVALIDATE_SD,0(t8) // invalidate cache block
+ bne t8,t9,40b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalFlushDcachePage
+
+ SBTTL("Purge Data Cache Page")
+//++
+//
+// VOID
+// HalPurgeDcachePage (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function purges (hit/invalidate) up to a page of data from the
+// data cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is purged.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is purged.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// purged.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalPurgeDcachePage)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ and a0,a0,COLOR_MASK // isolate color bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10: mfc0 t3,wired // get TB entry index
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,15f // if ne, second level cache present
+ move t4,v0 // set purge block size
+ .set at
+ .set reorder
+
+//
+// Purge data from the data cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,30f // if eq, no blocks to purge
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ bne zero,v0,40f // if ne, second level cache present
+ subu t9,t9,t4 // compute ending loop address
+
+//
+// Purge the primary data cache only.
+//
+
+20: cache HIT_INVALIDATE_D,0(t8) // invalidate cache block
+ bne t8,t9,20b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+30: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+//
+// Purge the primary and secondary data caches.
+//
+
+ .set noreorder
+ .set noat
+40: cache HIT_INVALIDATE_SD,0(t8) // invalidate cache block
+ bne t8,t9,40b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalPurgeDcachePage
+
+ SBTTL("Purge Instruction Cache Page")
+//++
+//
+// VOID
+// HalPurgeIcachePage (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function purges (hit/invalidate) up to a page fo data from the
+// instruction cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is purged.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is purged.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// purged.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalPurgeIcachePage)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ and a0,a0,COLOR_MASK // isolate color bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10: mfc0 t3,wired // get TB entry index
+ lw v0,KiPcr + PcSecondLevelIcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelIcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,15f // if ne, second level cache present
+ move t4,v0 // set purge block size
+ .set at
+ .set reorder
+
+//
+// Purge data from the instruction cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,30f // if eq, no blocks to purge
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ bne zero,v0,40f // if ne, second level cache present
+ subu t9,t9,t4 // compute ending loop address
+
+//
+// Purge the primary instruction cache only.
+//
+
+20: cache HIT_INVALIDATE_I,0(t8) // invalidate cache block
+ bne t8,t9,20b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+30: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+//
+// Purge the primary and secondary instruction caches.
+//
+
+ .set noreorder
+ .set noat
+40: cache HIT_INVALIDATE_SI,0(t8) // invalidate cache block
+ bne t8,t9,40b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalPurgeIcachePage
+
+ SBTTL("Sweep Data Cache")
+//++
+//
+// VOID
+// HalSweepDcache (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/writeback/invalidate) the entire data cache.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepDcache)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ lw t0,KiPcr + PcFirstLevelDcacheSize(zero) // get data cache size
+ lw t1,KiPcr + PcFirstLevelDcacheFillSize(zero) // get block size
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the primary data cache.
+//
+
+ .set noreorder
+ .set noat
+10: cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index
+ cache INDEX_WRITEBACK_INVALIDATE_D,0x2000(a0) // writeback/invalidate on index ORION
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+ lw t0,KiPcr + PcSecondLevelDcacheSize(zero) // get data cache size
+ lw t1,KiPcr + PcSecondLevelDcacheFillSize(zero) // get block size
+ beq zero,t1,30f // if eq, no second level cache
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the secondary data cache.
+//
+
+ .set noreorder
+ .set noat
+20: cache INDEX_WRITEBACK_INVALIDATE_SD,0(a0) // writeback/invalidate on index
+ bne a0,a1,20b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+30:
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalSweepDcache
+
+ SBTTL("Sweep Data Cache Range")
+//++
+//
+// VOID
+// HalSweepDcacheRange (
+// IN PVOID BaseAddress,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/writeback/invalidate) the specified range
+// of virtual addresses from the primary data cache.
+//
+// Arguments:
+//
+// BaseAddress (a0) - Supplies the base address of the range that is swept
+// from the data cache.
+//
+// Length (a1) - Supplies the length of the range that is swept from the
+// data cache.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepDcacheRange)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result conditionally
+
+#endif
+
+ DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ and a0,a0,COLOR_MASK // isolate color and offset bits
+ or a0,a0,KSEG0_BASE // convert to physical address
+ lw t0,KiPcr + PcFirstLevelDcacheFillSize(zero) // get block size
+ addu a1,a0,a1 // compute ending cache address
+ subu a1,a1,t0 // compute ending block address
+
+//
+// Sweep the primary data cache.
+//
+
+ .set noreorder
+ .set noat
+10: cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index
+ cache INDEX_WRITEBACK_INVALIDATE_D,0x2000(a0) // writeback/invalidate on index ORION
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t0 // compute address of next block
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalSweepDcacheRange
+
+ SBTTL("Sweep Instruction Cache")
+//++
+//
+// VOID
+// HalSweepIcache (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/invalidate) the entire instruction cache.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepIcache)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ lw t0,KiPcr + PcSecondLevelIcacheSize(zero) // get instruction cache size
+ lw t1,KiPcr + PcSecondLevelIcacheFillSize(zero) // get fill size
+ beq zero,t1,20f // if eq, no second level cache
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the secondary instruction cache.
+//
+
+ .set noreorder
+ .set noat
+10: cache INDEX_INVALIDATE_SI,0(a0) // invalidate cache line
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+20: lw t0,KiPcr + PcFirstLevelIcacheSize(zero) // get instruction cache size
+ lw t1,KiPcr + PcFirstLevelIcacheFillSize(zero) // get fill size
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the primary instruction cache.
+//
+
+ .set noreorder
+ .set noat
+30: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line
+ cache INDEX_INVALIDATE_I,0x2000(a0) // invalidate cache line ORION
+ bne a0,a1,30b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalSweepIcache
+
+ SBTTL("Sweep Instruction Cache Range")
+//++
+//
+// VOID
+// HalSweepIcacheRange (
+// IN PVOID BaseAddress,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/invalidate) the specified range of addresses
+// from the instruction cache.
+//
+// Arguments:
+//
+// BaseAddress (a0) - Supplies the base address of the range that is swept
+// from the instruction cache.
+//
+// Length (a1) - Supplies the length of the range that is swept from the
+// instruction cache.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepIcacheRange)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ and a0,a0,COLOR_MASK // isolate color and offset bits
+ or a0,a0,KSEG0_BASE // convert to physical address
+ lw t0,KiPcr + PcFirstLevelIcacheFillSize(zero) // get fill size
+ addu a1,a0,a1 // compute ending cache address
+ subu a1,a1,t0 // compute ending block address
+
+//
+// Sweep the primary instruction cache.
+//
+
+ .set noreorder
+ .set noat
+10: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line
+ cache INDEX_INVALIDATE_I,0x2000(a0) // invalidate cache line ORION
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t0 // compute address of next block
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalSweepIcacheRange
+
+ SBTTL("Zero Page")
+//++
+//
+// VOID
+// HalZeroPage (
+// IN PVOID NewColor,
+// IN PVOID OldColor,
+// IN ULONG PageFrame
+// )
+//
+// Routine Description:
+//
+// This function zeros a page of memory.
+//
+// The algorithm used to zero a page is as follows:
+//
+// 1. Purge (hit/invalidate) the page from the instruction cache
+// using the old color iff the old color is not the same as
+// the new color.
+//
+// 2. Purge (hit/invalidate) the page from the data cache using
+// the old color iff the old color is not the same as the new
+// color.
+//
+// 3. Create (create/dirty/exclusive) the page in the data cache
+// using the new color.
+//
+// 4. Write zeros to the page using the new color.
+//
+// Arguments:
+//
+// NewColor (a0) - Supplies the page aligned virtual address of the
+// new color of the page that is zeroed.
+//
+// OldColor (a1) - Supplies the page aligned virtual address of the
+// old color of the page that is zeroed.
+//
+// PageFrame (a2) - Supplies the page frame number of the page that
+// is zeroed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+ .space 3 * 4 // fill
+ZpRa: .space 4 // saved return address
+ZpFrameLength: // length of stack frame
+ZpA0: .space 4 // (a0)
+ZpA1: .space 4 // (a1)
+ZpA2: .space 4 // (a2)
+ZpA3: .space 4 // (a3)
+
+ NESTED_ENTRY(HalZeroPage, ZpFrameLength, zero)
+
+ subu sp,sp,ZpFrameLength // allocate stack frame
+ sw ra,ZpRa(sp) // save return address
+
+ PROLOGUE_END
+
+ and a0,a0,COLOR_BITS // isolate new color bits
+ and a1,a1,COLOR_BITS // isolate old color bits
+ sw a0,ZpA0(sp) // save new color bits
+ sw a1,ZpA1(sp) // save old color bits
+ sw a2,ZpA2(sp) // save page frame
+
+//
+// Purge the instruction cache using the old page color iff the old page
+// color is not equal to the new page color.
+//
+
+ beq a0,a1,10f // if eq, colors match
+ move a0,a1 // set old color value
+ move a1,a2 // set page frame number
+ li a2,PAGE_SIZE // set length of purge
+ jal HalPurgeIcachePage // purge instruction cache page
+
+//
+// Purge the data cache using the old page color iff the old page color is
+// not equal to the new page color.
+//
+
+ lw a0,ZpA1(sp) // get old color value
+ lw a1,ZpA2(sp) // get page frame number
+ li a2,PAGE_SIZE // set length of purge
+ jal HalPurgeDcachePage // purge data cache page
+
+//
+// Create dirty exclusive cache blocks and zero the data.
+//
+
+10: lw a3,ZpA0(sp) // get new color bits
+ lw a1,ZpA2(sp) // get page frame number
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache polciy
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a3 // compute new color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a3,a3,0x1000 // isolate TB entry index
+ beql zero,a3,20f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+20: mfc0 t3,wired // get TB entry index
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ .set at
+ .set reorder
+
+ DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ addu t9,t0,PAGE_SIZE // compute ending address of block
+ dmtc1 zero,f0 // set write pattern
+ bne zero,v0,50f // if ne, second level cache present
+ and t8,t4,0x10 // test if 16-byte cache block
+
+//
+// Zero page in primary data cache only.
+//
+
+30: cache CREATE_DIRTY_EXCLUSIVE_D,0(t0) // create cache block
+ addu t0,t0,t4 // compute next block address
+ bne zero,t8,40f // if ne, 16-byte cache line
+ sdc1 f0,-16(t0) //
+ sdc1 f0,-24(t0) // zero 16 bytes
+ sdc1 f0,-32(t0) //
+40: bne t0,t9,30b // if ne, more blocks to zero
+ sdc1 f0,-8(t0) // zero 16 bytes
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ lw ra,ZpRa(sp) // get return address
+ addu sp,sp,ZpFrameLength // deallocate stack frame
+ j ra // return
+
+//
+// Zero page in primary and secondary data caches.
+//
+
+ .set noreorder
+ .set noat
+50: cache CREATE_DIRTY_EXCLUSIVE_SD,0(t0) // create secondary cache block
+ addu v1,v0,t0 // compute ending primary block address
+60: addu t0,t0,t4 // compute next block address
+ bne zero,t8,70f // if ne, 16-byte primary cache line
+ sdc1 f0,-16(t0) //
+ sdc1 f0,-24(t0) // zero 16 bytes
+ sdc1 f0,-32(t0) //
+70: bne t0,v1,60b // if ne, more primary blocks to zero
+ sdc1 f0,-8(t0) // zero 16 bytes
+ bne t0,t9,50b // if ne, more secondary blocks to zero
+ nop // fill
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ lw ra,ZpRa(sp) // get return address
+ addu sp,sp,ZpFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalZeroPage
+
+ SBTTL("Invalidate Secondary Cache Page")
+//++
+//
+// VOID
+// HalpInvalidateSecondaryCachePage (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function purges (hit/invalidate) up to a page fo data from the
+// instruction cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is purged.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is purged.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// purged.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpInvalidateSecondaryCachePage)
+
+ .set noreorder
+ .set noat
+
+ li t0,GAMBIT_PFN_SECONDARY_CACHE_INVALIDATE_PHYSICAL_BASE
+ or a1,a1,t0
+
+// lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ li v0,0x10 // uncached cache policy
+
+ and a0,a0,COLOR_MASK // isolate color bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10: mfc0 t3,wired // get TB entry index
+ lw t4,KiPcr + PcFirstLevelIcacheFillSize(zero) // get 1st fill size
+ .set at
+ .set reorder
+
+//
+// Purge data from the instruction cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,30f // if eq, no blocks to purge
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ subu t9,t9,t4 // compute ending loop address
+
+//
+// Purge the primary instruction cache only.
+//
+
+20: sw zero,0(t8) // invalidate cache block
+ bne t8,t9,20b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+30: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalpInvalidateSecondaryCachePage
+
+#endif
diff --git a/private/ntos/nthals/halflex/mips/j4flshbf.s b/private/ntos/nthals/halflex/mips/j4flshbf.s
new file mode 100644
index 000000000..ff3a32f78
--- /dev/null
+++ b/private/ntos/nthals/halflex/mips/j4flshbf.s
@@ -0,0 +1,61 @@
+#if defined(R4000)
+
+// TITLE("Miscellaneous Kernel Functions")
+//++
+//
+// Copyright (c) 1991 Microsoft Corporation
+//
+// Module Name:
+//
+// j3flshbf.s
+//
+// Abstract:
+//
+// This module implements the system dependent kernel function to flush
+// the write buffer or otherwise synchronize writes on a MIPS R4000 Jazz
+// system.
+//
+// Author:
+//
+// David N. Cutler (davec) 24-Apr-1991
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+
+ SBTTL("Flush Write Buffer")
+//++
+//
+// NTSTATUS
+// KeFlushWriteBuffer (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function flushes the write buffer on the current processor.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(KeFlushWriteBuffer)
+
+ sync // synchronize writes
+ j ra // return
+
+ .end KeFlushWritebuffer
+
+#endif
diff --git a/private/ntos/nthals/halflex/mips/j4prof.c b/private/ntos/nthals/halflex/mips/j4prof.c
new file mode 100644
index 000000000..14f92a196
--- /dev/null
+++ b/private/ntos/nthals/halflex/mips/j4prof.c
@@ -0,0 +1,290 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ j4prof.c
+
+Abstract:
+
+ This module contains the code to start and stop the profiling interrupt
+ and to compute the profiling interval for a MIPS R4000 Jazz system.
+
+Author:
+
+ David N. Cutler (davec) 21-Feb-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+//
+// Define one second and round values.
+//
+
+#define ONE_SECOND (10 * 1000 * 1000) // 1 second in 100ns units
+#define ROUND_VALUE ((ONE_SECOND) - 1) // 1 second minus 100ns
+
+//
+// Define static data.
+//
+
+LARGE_INTEGER HalpPerformanceCounter;
+ULONG HalpProfileInterval = DEFAULT_PROFILE_INTERVAL;
+
+LARGE_INTEGER
+KeQueryPerformanceCounter (
+ OUT PLARGE_INTEGER Frequency OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ This routine returns the current performance counter value and the
+ performance counter frequency.
+
+Arguments:
+
+ Frequency - Supplies an optional pointer to a variable which receives
+ the performance counter frequency in Hertz.
+
+Return Value:
+
+ The current performance counter value is returned as the function
+ value.
+
+--*/
+
+{
+
+ ULONG CurrentCount;
+ KIRQL OldIrql;
+ LARGE_INTEGER PerformanceCounter;
+
+ //
+ // Raise IRQL to PROFILE_LEVEL, read the current value of the count
+ // register, read the performance counter, and lower IRQL to its
+ // previous value.
+ //
+ // N.B. The minimum, maximum, and default values for the profile
+ // count are chosen such that count register only overflows
+ // after about 20 seconds at 50mhz. Therefore, there is never
+ // a problem with the counter wrapping in the following code.
+ //
+
+ KeRaiseIrql(PROFILE_LEVEL, &OldIrql);
+ CurrentCount = HalpReadCountRegister();
+ PerformanceCounter = HalpPerformanceCounter;
+ KeLowerIrql(OldIrql);
+
+ //
+ // If the frequency parameter is specified, then return the performance
+ // counter frequency as the current system time frequency.
+ //
+
+ if (ARGUMENT_PRESENT(Frequency) != FALSE) {
+ Frequency->QuadPart = HalpProfileCountRate;
+ }
+
+ //
+ // Return the value of the performance counter.
+ //
+
+ PerformanceCounter.QuadPart += CurrentCount;
+ return PerformanceCounter;
+}
+
+VOID
+HalCalibratePerformanceCounter (
+ IN volatile PLONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This routine resets the performance counter value for the current
+ processor to zero. The reset is done such that the resulting value
+ is closely synchronized with other processors in the configuration.
+
+Arguments:
+
+ Number - Supplies a pointer to count of the number of processors in
+ the configuration.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Write the compare register, clear the count register, and zero the
+ // performance counter for the current processor.
+ //
+
+ HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
+ HalpPerformanceCounter.QuadPart = 0;
+ return;
+}
+
+ULONG
+HalSetProfileInterval (
+ IN ULONG Interval
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the profile interrupt interval.
+
+Arguments:
+
+ Interval - Supplies the desired profile interval in 100ns units.
+
+Return Value:
+
+ The actual profile interval.
+
+--*/
+
+{
+
+ LARGE_INTEGER TempValue;
+
+ //
+ // If the specified profile interval is less that the minimum profile
+ // interval or greater than the maximum profile interval, then set the
+ // profile interval to the minimum or maximum as appropriate.
+ //
+
+ if (Interval < MINIMUM_PROFILE_INTERVAL) {
+ Interval = MINIMUM_PROFILE_INTERVAL;
+
+ } else if (Interval > MAXIMUM_PROFILE_INTERVAL) {
+ Interval = MAXIMUM_PROFILE_INTERVAL;
+ }
+
+ //
+ // First compute the profile count value and then back calculate the
+ // actual profile interval.
+ //
+
+ TempValue.QuadPart = Int32x32To64(HalpProfileCountRate, Interval);
+ TempValue.QuadPart += ROUND_VALUE;
+ TempValue = RtlExtendedLargeIntegerDivide(TempValue, ONE_SECOND, NULL);
+ TempValue.QuadPart = Int32x32To64(TempValue.LowPart, ONE_SECOND);
+ TempValue = RtlExtendedLargeIntegerDivide(TempValue, HalpProfileCountRate, NULL);
+ HalpProfileInterval = TempValue.LowPart;
+ return HalpProfileInterval;
+}
+
+VOID
+HalStartProfileInterrupt (
+ KPROFILE_SOURCE Source
+ )
+
+/*++
+
+Routine Description:
+
+ This routine computes the profile count value, writes the compare
+ register, clears the count register, and updates the performance
+ counter.
+
+ N.B. This routine must be called at PROFILE_LEVEL while holding the
+ profile lock.
+
+Arguments:
+
+ Source - Supplies the profile source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG PreviousCount;
+ LARGE_INTEGER TempValue;
+
+ //
+ // Compute the profile count from the current profile interval.
+ //
+
+ TempValue.QuadPart = Int32x32To64(HalpProfileCountRate,
+ HalpProfileInterval);
+
+ TempValue.QuadPart += ROUND_VALUE;
+ TempValue = RtlExtendedLargeIntegerDivide(TempValue, ONE_SECOND, NULL);
+
+ //
+ // Write the compare register and clear the count register.
+ //
+
+ PreviousCount = HalpWriteCompareRegisterAndClear(TempValue.LowPart);
+
+ //
+ // Update the performance counter by adding in the previous count value.
+ //
+
+ HalpPerformanceCounter.QuadPart += PreviousCount;
+ return;
+}
+
+VOID
+HalStopProfileInterrupt (
+ KPROFILE_SOURCE Source
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the default count value, writes the compare
+ register, clears the count register, and updates the performance
+ counter.
+
+ N.B. This routine must be called at PROFILE_LEVEL while holding the
+ profile lock.
+
+Arguments:
+
+ Source - Supplies the profile source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG PreviousCount;
+
+ //
+ // Write the compare register and clear the count register.
+ //
+
+ PreviousCount = HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
+
+ //
+ // Update the performance counter by adding in the previous count value.
+ //
+
+ HalpPerformanceCounter.QuadPart += PreviousCount;
+ return;
+}
diff --git a/private/ntos/nthals/halflex/mips/jxhalp.h b/private/ntos/nthals/halflex/mips/jxhalp.h
new file mode 100644
index 000000000..83bcf38bd
--- /dev/null
+++ b/private/ntos/nthals/halflex/mips/jxhalp.h
@@ -0,0 +1,122 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxhalp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ Jazz specific interfaces, defines and structures.
+
+Author:
+
+ Jeff Havens (jhavens) 20-Jun-91
+
+
+Revision History:
+
+--*/
+
+#ifndef _JXHALP_
+#define _JXHALP_
+
+typedef enum _ADDRESS_SPACE_TYPE{
+ BusMemory=0,
+ BusIo = 1,
+ UserBusMemory = 2,
+ UserBusIo = 3,
+ KernelPciDenseMemory = 4,
+ UserPciDenseMemory = 6,
+} ADDRESS_SPACE_TYPE, *PADDRESS_SPACE_TYPE;
+
+extern PVOID HalpSecondaryCacheResetBase;
+extern PVOID HalpFirmwareVirtualBase;
+extern PVOID PciInterruptRegisterBase;
+
+extern ULONG HalpIoArchitectureType;
+extern ULONG HalpMotherboardType;
+extern UCHAR *HalpInterruptLineToBit;
+extern UCHAR *HalpBitToInterruptLine;
+extern UCHAR *HalpInterruptLineToVirtualIsa;
+extern UCHAR *HalpVirtualIsaToInterruptLine;
+extern ULONGLONG HalpPciConfig0BasePhysical;
+extern ULONGLONG HalpPciConfig1BasePhysical;
+extern ULONGLONG HalpIsaIoBasePhysical;
+extern ULONGLONG HalpIsa1IoBasePhysical;
+extern ULONGLONG HalpIsaMemoryBasePhysical;
+extern ULONGLONG HalpIsa1MemoryBasePhysical;
+extern ULONGLONG HalpPciIoBasePhysical;
+extern ULONGLONG HalpPci1IoBasePhysical;
+extern ULONGLONG HalpPciMemoryBasePhysical;
+extern ULONGLONG HalpPci1MemoryBasePhysical;
+extern PPLATFORM_RANGE_LIST HalpRangeList;
+extern UCHAR HalpSecondPciBridgeBusNumber;
+extern ULONG PCIMaxBus;
+extern ULONG HalpIntel82378BusNumber;
+extern ULONG HalpIntel82378DeviceNumber;
+extern ULONG HalpSecondIntel82378DeviceNumber;
+extern ULONG HalpNonExistentPciDeviceMask;
+extern ULONG HalpNonExistentPci1DeviceMask;
+extern ULONG HalpNonExistentPci2DeviceMask;
+
+extern PLATFORM_RANGE_LIST Gambit20Trebbia13RangeList[];
+extern PLATFORM_RANGE_LIST Gambit20Trebbia20RangeList[];
+
+extern UCHAR Treb13InterruptLineToBit[];
+extern UCHAR Treb13BitToInterruptLine[];
+extern UCHAR Treb13InterruptLineToVirtualIsa[];
+extern UCHAR Treb13VirtualIsaToInterruptLine[];
+extern UCHAR Treb20InterruptLineToBit[];
+extern UCHAR Treb20BitToInterruptLine[];
+extern UCHAR Treb20InterruptLineToVirtualIsa[];
+extern UCHAR Treb20VirtualIsaToInterruptLine[];
+extern ULONG HalpNumberOfIsaBusses;
+extern ULONG HalpVgaDecodeBusNumber;
+
+ULONG
+HalpReadCountRegister (
+ VOID
+ );
+
+ULONG
+HalpWriteCompareRegisterAndClear (
+ IN ULONG Value
+ );
+
+VOID
+HalpInvalidateSecondaryCachePage (
+ IN PVOID Color,
+ IN ULONG PageFrame,
+ IN ULONG Length
+ );
+
+VOID
+HalpArcsSetVirtualBase (
+ IN ULONG Number,
+ IN PVOID Base
+ );
+
+ULONG HalpPciLowLevelConfigRead(
+ IN ULONG BusNumber,
+ IN ULONG DeviceNumber,
+ IN ULONG FunctionNumber,
+ IN ULONG Register
+ );
+
+//
+// There is not need for Memory Barriers on MIPS, so just define them away.
+//
+
+#define HalpMb()
+
+//
+// Define used to determine if a page is within the DMA Cache range.
+//
+
+#define HALP_PAGE_IN_DMA_CACHE(Page) \
+ (Page>=0x0001c0 && Page<0x000200)
+
+#endif // _JXHALP_
diff --git a/private/ntos/nthals/halflex/mips/jxmapio.c b/private/ntos/nthals/halflex/mips/jxmapio.c
new file mode 100644
index 000000000..f7c277ec4
--- /dev/null
+++ b/private/ntos/nthals/halflex/mips/jxmapio.c
@@ -0,0 +1,192 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxmapio.c
+
+Abstract:
+
+ This module implements the mapping of HAL I/O space a MIPS R3000
+ or R4000 Jazz system.
+
+Author:
+
+ David N. Cutler (davec) 28-Apr-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+//
+// Define global data used to locate the EISA control space and the realtime
+// clock registers.
+//
+
+PVOID HalpEisaControlBase[MAX_EISA_BUSSES];
+PVOID HalpEisaMemoryBase[MAX_EISA_BUSSES];
+PVOID HalpPciControlBase[MAX_PCI_BUSSES];
+PVOID HalpPciMemoryBase[MAX_PCI_BUSSES];
+PVOID HalpRealTimeClockBase;
+PVOID HalpFirmwareVirtualBase;
+PVOID PciInterruptRegisterBase;
+PVOID HalpSecondaryCacheResetBase;
+
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL I/O space for a MIPS R3000 or R4000 Jazz
+ system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ PHYSICAL_ADDRESS physicalAddress;
+
+ //
+ // Map EISA control space. Map all 16 slots. This is done so the NMI
+ // code can probe the cards.
+ //
+
+ physicalAddress.QuadPart = HalpIsaIoBasePhysical;
+ HalpEisaControlBase[0] = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE * 16,
+ FALSE);
+
+ if (HalpMotherboardType == TREBBIA20) {
+ physicalAddress.QuadPart = HalpIsa1IoBasePhysical;
+ HalpEisaControlBase[1] = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE * 16,
+ FALSE);
+ }
+
+ //
+ // Map realtime clock registers.
+ //
+
+ physicalAddress.QuadPart = HalpIsaIoBasePhysical + 0x71;
+ HalpRealTimeClockBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE,
+ FALSE);
+
+ //
+ // Map ISA Memory Space.
+ //
+
+ physicalAddress.QuadPart = HalpIsaMemoryBasePhysical;
+ HalpEisaMemoryBase[0] = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE*256,
+ FALSE);
+
+ if (HalpMotherboardType == TREBBIA20) {
+ physicalAddress.QuadPart = HalpIsa1MemoryBasePhysical;
+ HalpEisaMemoryBase[1] = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE*256,
+ FALSE);
+ }
+
+ //
+ // Map PCI control space. Map all 16 slots. This is done so the NMI
+ // code can probe the cards.
+ //
+
+ physicalAddress.QuadPart = HalpPciIoBasePhysical;
+ HalpPciControlBase[0] = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE * 16,
+ FALSE);
+
+ //
+ // Map PCI Memory Space.
+ //
+
+ physicalAddress.QuadPart = HalpPciMemoryBasePhysical;
+ HalpPciMemoryBase[0] = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE*256,
+ FALSE);
+
+ if (HalpMotherboardType == TREBBIA20) {
+ physicalAddress.QuadPart = HalpPci1IoBasePhysical;
+ HalpPciControlBase[1] = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE * 16,
+ FALSE);
+
+ physicalAddress.QuadPart = HalpPci1MemoryBasePhysical;
+ HalpPciMemoryBase[1] = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE*256,
+ FALSE);
+ }
+
+ //
+ // Map PCI interrupt space.
+ //
+
+ physicalAddress.QuadPart = GAMBIT_PCI_INTERRUPT_BASE_PHYSICAL;
+ PciInterruptRegisterBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE,
+ FALSE);
+
+ //
+ // Map Secondary Cache Reset space.
+ //
+
+ physicalAddress.QuadPart = GAMBIT_SECONDARY_CACHE_RESET_BASE_PHYSICAL;
+ HalpSecondaryCacheResetBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE,
+ FALSE);
+
+
+ //
+ // If either mapped address is NULL, then return FALSE as the function
+ // value. Otherwise, return TRUE.
+ //
+
+ if ((HalpEisaControlBase[0] == NULL) ||
+ (HalpRealTimeClockBase == NULL) ||
+ (HalpEisaMemoryBase[0] == NULL) ||
+ (HalpPciControlBase[0] == NULL) ||
+ (HalpPciMemoryBase[0] == NULL) ||
+ (HalpSecondaryCacheResetBase == NULL)) {
+ return FALSE;
+ }
+
+ //
+ // Map 1 page of EISA control space to generate a virtual address that the firmware can use.
+ //
+
+ physicalAddress.QuadPart = HalpIsaIoBasePhysical;
+ HalpFirmwareVirtualBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE,
+ FALSE);
+
+// HalpArcsSetVirtualBase(0,HalpEisaControlBase[0]);
+// HalpArcsSetVirtualBase(1,HalpEisaMemoryBase[0]);
+// HalpArcsSetVirtualBase(4,HalpPciControlBase);
+// HalpArcsSetVirtualBase(5,HalpPciMemoryBase);
+
+ HalpArcsSetVirtualBase(7,HalpFirmwareVirtualBase);
+
+ return TRUE;
+}
diff --git a/private/ntos/nthals/halflex/mips/pcisup.c b/private/ntos/nthals/halflex/mips/pcisup.c
new file mode 100644
index 000000000..117a85228
--- /dev/null
+++ b/private/ntos/nthals/halflex/mips/pcisup.c
@@ -0,0 +1,1008 @@
+/*++
+
+Copyright (c) 1995 DeskStation Technology
+
+Module Name:
+
+ pcisup.c
+
+Abstract:
+
+ This module contains the routines that support PCI configuration cycles and
+ PCI interrupts.
+
+Author:
+
+ Michael D. Kinney 2-May-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+
+#define SP_VIRTUAL_BASE 0xffffa000
+
+#define INVALID_PCI_CONFIGURATION_ADDRESS (0x00000000)
+#define NO_PCI_DEVSEL_DATA_VALUE (0xffffffff)
+
+//
+// The following tables are used to map between PCI interrupt pins, PCI interrupt lines,
+// and virtual ISA interrupt indexes. The Uniflex architecture uses a 16 bit interrupt
+// controller for ISA interrupts and all PCI interrupts.
+// InterruptLine values between 0x10 and 0x20 are reserved
+// for PCI devices. InterruptLine values between 0x00 and 0x10 are reserved for ISA IRQs.
+//
+
+UCHAR Treb13InterruptLineToBit[0x11] = {0,1,2,3,8,9,10,11,12,12,12,12,12,12,4,5,12};
+UCHAR Treb13BitToInterruptLine[12] = {0x00,0x01,0x02,0x03,0x0e,0x0f,0x00,0x00,0x04,0x05,0x06,0x07};
+UCHAR Treb13InterruptLineToVirtualIsa[0x11] = {0,1,2,3,8,9,10,11,0,0,0,0,0,0,0,0,0};
+UCHAR Treb13VirtualIsaToInterruptLine[0x10] = {0x10,0x11,0x12,0x13,0,0,0,0,0x14,0x15,0x16,0x17,0,0,0,0};
+
+UCHAR Treb20InterruptLineToBit[0x11] = {3,1,2,8,9,10,0,5,11,12,12,12,12,12,12,12,12};
+UCHAR Treb20BitToInterruptLine[12] = {0x06,0x01,0x02,0x00,0x00,0x07,0x00,0x00,0x03,0x04,0x05,0x08};
+UCHAR Treb20InterruptLineToVirtualIsa[0x11] = {0,1,2,3,8,9,10,11,0,0,0,0,0,0,0,0,0};
+UCHAR Treb20VirtualIsaToInterruptLine[0x10] = {0x10,0x11,0x12,0x13,0,0,0,0,0x14,0x15,0x16,0x17,0,0,0,0};
+
+//
+// Interrupt mask for all active PCI interrupts including ISA Bus PICs
+//
+
+static volatile ULONG HalpPciInterruptMask;
+
+//
+// Interrupt mask for PCI interrupts that have been connected through device drivers.
+//
+
+static volatile ULONG HalpPciDeviceInterruptMask;
+
+//
+// Interrupt mask showing which bit cooresponds to ISA Bus #0 PIC
+//
+
+static volatile ULONG HalpEisaInterruptMask;
+
+//
+// Interrupt mask showing which bit cooresponds to ISA Bus #1 PIC
+//
+
+static volatile ULONG HalpEisa1InterruptMask;
+
+PVOID HalpAllocateIoMapping(
+ LONGLONG BaseAddress
+ )
+
+{
+ ENTRYLO HalpPte[2];
+ ULONG KdPortEntry;
+
+ //
+ // Map the PCI Configuration register into the system virtual address space by loading
+ // a TB entry.
+ //
+
+ HalpPte[0].PFN = (ULONG)(BaseAddress >> 12);
+ HalpPte[0].G = 1;
+ HalpPte[0].V = 1;
+ HalpPte[0].D = 1;
+
+ //
+ // Allocate a TB entry, set the uncached policy in the PTE that will
+ // map the serial controller, and initialize the second PTE.
+ //
+
+ KdPortEntry = HalpAllocateTbEntry();
+ HalpPte[0].C = UNCACHED_POLICY;
+
+ HalpPte[1].PFN = 0;
+ HalpPte[1].G = 1;
+ HalpPte[1].V = 0;
+ HalpPte[1].D = 0;
+ HalpPte[1].C = 0;
+
+ //
+ // Map the PCI Configuration register through a fixed TB entry.
+ //
+
+ KeFillFixedEntryTb((PHARDWARE_PTE)&HalpPte[0],
+ (PVOID)SP_VIRTUAL_BASE,
+ KdPortEntry);
+
+
+ return((PVOID)(SP_VIRTUAL_BASE + (ULONG)(BaseAddress & 0xfff)));
+}
+
+VOID HalpFreeIoMapping(
+ VOID
+ )
+
+{
+ HalpFreeTbEntry();
+}
+
+VOID
+HalpWritePciInterruptMask (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function writes the interrupt mask register for PCI interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ WRITE_REGISTER_ULONG((ULONG)PciInterruptRegisterBase+0x00,HalpPciInterruptMask&0x0f);
+ WRITE_REGISTER_ULONG((ULONG)PciInterruptRegisterBase+0x08,(HalpPciInterruptMask>>4)&0x0f);
+ WRITE_REGISTER_ULONG((ULONG)PciInterruptRegisterBase+0x10,(HalpPciInterruptMask>>8)&0x0f);
+}
+
+ULONG
+HalpReadPciInterruptStatus (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function reads the interrupt status register for PCI interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The lower 12 bits contain the status of each interrupt line going to the PCI
+ interrupt controller.
+
+--*/
+
+{
+ return( (READ_REGISTER_ULONG((ULONG)PciInterruptRegisterBase+0x00)<<0) & 0x00f |
+ (READ_REGISTER_ULONG((ULONG)PciInterruptRegisterBase+0x08)<<4) & 0x030 |
+ (READ_REGISTER_ULONG((ULONG)PciInterruptRegisterBase+0x10)<<8) & 0xf00 );
+}
+
+ULONG
+HalpGetMemoryMode (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the status of the MemoryMode bit that is embedded within
+ the PCI interrupt controller. The status of this bit must be preserved on all
+ writes to the PCI interrupt mask register.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return( (READ_REGISTER_ULONG((ULONG)PciInterruptRegisterBase+0x08) & 0x08) << 4 );
+}
+
+VOID
+HalpSetPciInterruptBit (
+ ULONG Bit
+ )
+
+/*++
+
+Routine Description:
+
+ This function sets a bit in the PCI interrupt mask and writes the new mask
+ to the interrupt controller.
+
+Arguments:
+
+ Bit - The bit number to set in the PCI interrupt mask.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ if (Bit==6 || Bit==7 || Bit>=12) {
+ return;
+ }
+ HalpPciDeviceInterruptMask = HalpPciDeviceInterruptMask | (1<<Bit);
+ HalpPciInterruptMask = HalpPciInterruptMask | (1<<Bit);
+ HalpWritePciInterruptMask();
+}
+
+VOID
+HalpClearPciInterruptBit (
+ ULONG Bit
+ )
+
+/*++
+
+Routine Description:
+
+ This function clears a bit in the PCI interrupt mask and writes the new mask
+ to the interrupt controller.
+
+Arguments:
+
+ Bit - The bit number to clear from the PCI interrupt mask.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ if (Bit==6 || Bit==7 || Bit>=12) {
+ return;
+ }
+ HalpPciDeviceInterruptMask = HalpPciDeviceInterruptMask & ~(1<<Bit);
+ HalpPciInterruptMask = HalpPciInterruptMask & ~(1<<Bit);
+ HalpWritePciInterruptMask();
+}
+
+VOID
+HalpEnablePciInterrupt (
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables a PCI interrupt.
+
+Arguments:
+
+ Vector - Specifies the interrupt to enable.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ if (Vector >= UNIFLEX_PCI_VECTORS && Vector <= UNIFLEX_MAXIMUM_PCI_VECTOR) {
+ HalpSetPciInterruptBit(HalpInterruptLineToBit[Vector-UNIFLEX_PCI_VECTORS]);
+ }
+}
+
+VOID
+HalpDisablePciInterrupt (
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function disables a PCI interrupt.
+
+Arguments:
+
+ Vector - Specifies the interrupt to disable.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ if (Vector >= UNIFLEX_PCI_VECTORS && Vector <= UNIFLEX_MAXIMUM_PCI_VECTOR) {
+ HalpClearPciInterruptBit(HalpInterruptLineToBit[Vector-UNIFLEX_PCI_VECTORS]);
+ }
+}
+
+ULONG
+HalpVirtualIsaInterruptToInterruptLine (
+ IN ULONG Index
+ )
+
+/*++
+
+Routine Description:
+
+ This function maps a virtual ISA interrupt to a PCI interrupt line value.
+ This provides the ability to use an ISA device driver on a PCI device.
+
+Arguments:
+
+ Index - Index into a platform specific table that maps PCI interrupts to
+ virtual ISA interrupts.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return(HalpVirtualIsaToInterruptLine[Index]);
+}
+
+BOOLEAN
+HalpEisa0Dispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+
+/*++
+
+Routine Description:
+
+ This is the interrupt dispatcher for all ISA Bus #0 interrupts.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - not used.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+
+{
+ return(HalpEisaDispatch(Interrupt,ServiceContext,0));
+}
+
+BOOLEAN
+HalpPciDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+
+/*++
+
+Routine Description:
+
+ This is the interrupt dispatcher for all PCI interrupts.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - not used.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+
+{
+ ULONG PciInterruptStatus;
+ PULONG dispatchCode;
+ PKINTERRUPT interruptObject;
+ USHORT PCRInOffset;
+ BOOLEAN returnValue = FALSE;
+ ULONG i;
+
+ //
+ // Get the active interrupt bits
+ //
+
+ PciInterruptStatus = HalpReadPciInterruptStatus();
+
+ //
+ // See if this is the interrupt for ISA Bus #0 PIC
+ //
+
+ if (PciInterruptStatus & HalpEisaInterruptMask) {
+
+ returnValue = HalpEisaDispatch(Interrupt,ServiceContext,0);
+
+ //
+ // If there really was an interrupt on ISA Bus #0, then return now.
+ //
+
+ if (returnValue) {
+ return(returnValue);
+ }
+ }
+
+ //
+ // See if this is the interrupt for ISA Bus #1 PIC
+ //
+
+ if (PciInterruptStatus & HalpEisa1InterruptMask) {
+
+ returnValue = HalpEisaDispatch(Interrupt,ServiceContext,1);
+
+ //
+ // If there really was an interrupt on ISA Bus #1, then return now.
+ //
+
+ if (returnValue) {
+ return(returnValue);
+ }
+ }
+
+ //
+ // Only keep interrupt bits that have been connected by device drivers.
+ //
+
+ PciInterruptStatus &= HalpPciDeviceInterruptMask;
+
+ //
+ // Dispatch to the ISRs of interrupts that have been connected by device drivers.
+ //
+
+ for(i=0;i<12;i++) {
+ if (PciInterruptStatus & (1<<i)) {
+
+ PCRInOffset = UNIFLEX_PCI_VECTORS + HalpBitToInterruptLine[i];
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ dispatchCode = (PULONG)(PCR->InterruptRoutine[PCRInOffset]);
+ interruptObject = CONTAINING_RECORD(dispatchCode,
+ KINTERRUPT,
+ DispatchCode);
+
+ returnValue =
+ ((PSECONDARY_DISPATCH)interruptObject->DispatchAddress)
+ (interruptObject);
+ }
+ }
+
+ return(returnValue);
+}
+
+UCHAR HalpGetInterruptLine(ULONG BusNumber,ULONG DeviceNumber,ULONG InterruptPin)
+
+/*++
+
+Routine Description:
+
+ This routine maps a PCI interrupt described by the device's bus number, device number, and
+ interrupt pin into the interrupt line value that is stored in the PCI config header.
+
+Arguments:
+
+ BusNumber - PCI bus number of the device.
+
+ DeviceNumber - PCI device number of the device.
+
+ InterruptPin - PCI interrupt pin of the device (A=1,B=2,C=3,D=4).
+
+Return Value:
+
+ Returns the PCI Interrupt Line value for the PCI device.
+
+--*/
+
+{
+ UCHAR InterruptLine;
+
+ if (HalpMotherboardType == TREBBIA13) {
+
+ if (BusNumber > 1)
+ {
+ BusNumber = 1;
+ }
+
+ switch (BusNumber<<16 | DeviceNumber<<8 | InterruptPin) {
+ case 0x010401 : InterruptLine = 0x10; break; // Bus 1, Device 4, Int A
+ case 0x010601 : InterruptLine = 0x11; break; // Bus 1, Device 6, Int A
+ case 0x010501 : InterruptLine = 0x12; break; // Bus 1, Device 5, Int A
+ case 0x010701 : InterruptLine = 0x13; break; // Bus 1, Device 7, Int A
+ case 0x010402 : InterruptLine = 0x17; break; // Bus 1, Device 4, Int B
+ case 0x010602 : InterruptLine = 0x14; break; // Bus 1, Device 6, Int B
+ case 0x010502 : InterruptLine = 0x14; break; // Bus 1, Device 5, Int B
+ case 0x010702 : InterruptLine = 0x17; break; // Bus 1, Device 7, Int B
+ case 0x010403 : InterruptLine = 0x15; break; // Bus 1, Device 4, Int C
+ case 0x010603 : InterruptLine = 0x15; break; // Bus 1, Device 6, Int C
+ case 0x010503 : InterruptLine = 0x15; break; // Bus 1, Device 5, Int C
+ case 0x010703 : InterruptLine = 0x15; break; // Bus 1, Device 7, Int C
+ case 0x010404 : InterruptLine = 0x16; break; // Bus 1, Device 4, Int D
+ case 0x010604 : InterruptLine = 0x16; break; // Bus 1, Device 6, Int D
+ case 0x010504 : InterruptLine = 0x16; break; // Bus 1, Device 5, Int D
+ case 0x010704 : InterruptLine = 0x16; break; // Bus 1, Device 7, Int D
+ case 0x000d01 : InterruptLine = 0x1e; break; // Bus 0, Device 13, Int A
+ case 0x000f01 : InterruptLine = 0x1f; break; // Bus 0, Device 15, Int A
+ case 0x001001 : InterruptLine = 0x20; break; // Bus 0, Device 16, Int A
+ default : InterruptLine = 0xff; break;
+ }
+ }
+
+ if (HalpMotherboardType == TREBBIA20) {
+
+ if (BusNumber == 0) {
+ return(0xff);
+ }
+
+ if (BusNumber >= HalpSecondPciBridgeBusNumber) {
+ BusNumber = 1;
+ } else {
+ BusNumber = 0;
+ }
+
+ switch (BusNumber<<16 | DeviceNumber<<8 | InterruptPin) {
+ case 0x000401 : InterruptLine = 0x20; break;
+
+ case 0x000501 :
+ case 0x000603 :
+ case 0x000704 : InterruptLine = 0x10; break;
+
+ case 0x000502 :
+ case 0x000604 :
+ case 0x000701 : InterruptLine = 0x11; break;
+
+ case 0x000503 :
+ case 0x000601 :
+ case 0x000702 : InterruptLine = 0x12; break;
+
+ case 0x000504 :
+ case 0x000602 :
+ case 0x000703 : InterruptLine = 0x13; break;
+
+ case 0x010401 :
+ case 0x010504 :
+ case 0x010603 : InterruptLine = 0x14; break;
+
+ case 0x010402 :
+ case 0x010501 :
+ case 0x010604 : InterruptLine = 0x15; break;
+
+ case 0x010403 :
+ case 0x010502 :
+ case 0x010601 : InterruptLine = 0x16; break;
+
+ case 0x010404 :
+ case 0x010503 :
+ case 0x010602 : InterruptLine = 0x17; break;
+
+ case 0x010701 : InterruptLine = 0x18; break;
+
+ default : InterruptLine = 0xff; break;
+ }
+ }
+
+ return(InterruptLine);
+}
+
+VOID
+HalpConnectInterruptDispatchers (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function connects the PCI interrupt dispatch routine and enables
+ ISA interrupts so they will generate processor interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UCHAR InterruptLine;
+
+ //
+ // Initialize the EISA interrupt dispatcher and the PCI interrupt dispatcher
+ //
+
+ PCR->InterruptRoutine[UNIFLEX_PCI_DEVICE_LEVEL] = (PKINTERRUPT_ROUTINE)HalpPciDispatch;
+ PCR->InterruptRoutine[UNIFLEX_EISA_DEVICE_LEVEL] = (PKINTERRUPT_ROUTINE)HalpEisa0Dispatch;
+
+DbgPrint("Intel82378 : Bus=%d Device=%d\n\r",HalpIntel82378BusNumber,HalpIntel82378DeviceNumber);
+DbgPrint("SecondIntel82378 : Bus=%d Device=%d\n\r",HalpSecondPciBridgeBusNumber,HalpSecondIntel82378DeviceNumber);
+
+ InterruptLine = HalpGetInterruptLine(HalpIntel82378BusNumber,HalpIntel82378DeviceNumber,1);
+ HalpEisaInterruptMask = 0x0000;
+ if (InterruptLine != 0xff) {
+ HalpEisaInterruptMask = (1 << HalpInterruptLineToBit[InterruptLine-0x10]) & 0xffff;
+ }
+
+ InterruptLine = HalpGetInterruptLine(HalpSecondPciBridgeBusNumber,HalpSecondIntel82378DeviceNumber,1);
+ HalpEisa1InterruptMask = 0x0000;
+ if (InterruptLine != 0xff) {
+ HalpEisa1InterruptMask = (1 << HalpInterruptLineToBit[InterruptLine-0x10]) & 0xffff;
+ }
+
+DbgPrint("HalpEisaInterruptMask = %08x\n\r",HalpEisaInterruptMask);
+DbgPrint("HalpEisa1InterruptMask = %08x\n\r",HalpEisa1InterruptMask);
+
+ //
+ // Enable ISA Interrupts on Gambit's PIC
+ //
+
+ HalpPciInterruptMask = HalpGetMemoryMode();
+ HalpPciInterruptMask |= (HalpEisaInterruptMask | HalpEisa1InterruptMask);
+ HalpWritePciInterruptMask();
+}
+
+VOID
+HalpDisableAllInterrupts(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function disables all external interrupt sources.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG VirtualAddress;
+
+ VirtualAddress = (ULONG)HalpAllocateIoMapping(HalpIsaIoBasePhysical);
+ WRITE_REGISTER_UCHAR(VirtualAddress+0x21,0xff);
+ WRITE_REGISTER_UCHAR(VirtualAddress+0xa1,0xff);
+ HalpFreeIoMapping();
+
+ if (HalpNumberOfIsaBusses > 1) {
+ VirtualAddress = (ULONG)HalpAllocateIoMapping(HalpIsa1IoBasePhysical);
+ WRITE_REGISTER_UCHAR(VirtualAddress+0x21,0xff);
+ WRITE_REGISTER_UCHAR(VirtualAddress+0xa1,0xff);
+ HalpFreeIoMapping();
+ }
+
+ VirtualAddress = (ULONG)HalpAllocateIoMapping(GAMBIT_PCI_INTERRUPT_BASE_PHYSICAL);
+
+ HalpPciInterruptMask = ((READ_REGISTER_ULONG(VirtualAddress+0x08) & 0x08) << 4);
+ WRITE_REGISTER_ULONG(VirtualAddress+0x00,HalpPciInterruptMask&0x0f);
+ WRITE_REGISTER_ULONG(VirtualAddress+0x08,(HalpPciInterruptMask>>4)&0x0f);
+ WRITE_REGISTER_ULONG(VirtualAddress+0x10,(HalpPciInterruptMask>>8)&0x0f);
+ HalpFreeIoMapping();
+
+ HalpPciDeviceInterruptMask = 0x0000;
+}
+
+ULONG HalpPciConfigStructuresInitialized = FALSE;
+PVOID HalpPciConfig0BaseAddress[0x20];
+PVOID HalpPciConfig1BaseAddress[0x100];
+
+PCI_CONFIGURATION_TYPES
+HalpPCIConfigCycleType (IN ULONG BusNumber)
+{
+ if (BusNumber == 0) {
+ return PciConfigType0;
+ } else if (BusNumber < PCIMaxBus) {
+ return PciConfigType1;
+ } else {
+ return PciConfigTypeInvalid;
+ }
+}
+
+VOID
+HalpPCIConfigAddr (
+ IN ULONG BusNumber,
+ IN PCI_SLOT_NUMBER Slot,
+ PPCI_CFG_CYCLE_BITS pPciAddr
+ )
+{
+
+ PCI_CONFIGURATION_TYPES ConfigType;
+
+ //
+ // If the Configuration Base Address tables have not been initialized, then
+ // initialize them to NULL.
+ //
+
+ if (HalpPciConfigStructuresInitialized == FALSE) {
+
+ ULONG i;
+
+ for(i=0;i<0x20;HalpPciConfig0BaseAddress[i++]=NULL);
+ for(i=0;i<0xff;HalpPciConfig1BaseAddress[i++]=NULL);
+ HalpPciConfigStructuresInitialized = TRUE;
+ }
+
+ ConfigType = HalpPCIConfigCycleType(BusNumber);
+
+ if (ConfigType == PciConfigType0) {
+
+ //
+ // Initialize PciAddr for a type 0 configuration cycle
+ //
+
+ //
+ // See if this is a nonexistant device on PCI Bus 0
+ //
+
+ if ( (1 << Slot.u.bits.DeviceNumber) & HalpNonExistentPciDeviceMask ) {
+ pPciAddr->u.AsULONG = INVALID_PCI_CONFIGURATION_ADDRESS;
+ return;
+ }
+
+ if (HalpPciConfig0BaseAddress[Slot.u.bits.DeviceNumber] == NULL) {
+
+ PHYSICAL_ADDRESS physicalAddress;
+
+ physicalAddress.QuadPart = HalpPciConfig0BasePhysical;
+ physicalAddress.QuadPart += (1 << (11 + Slot.u.bits.DeviceNumber));
+ HalpPciConfig0BaseAddress[Slot.u.bits.DeviceNumber] = MmMapIoSpace(physicalAddress,0x800,FALSE);
+
+ //
+ // If the mapping failed, then the return value is INVALID_PCI_CONFIGURATION_ADDRESS.
+ // This will cause Config Reads to return 0xffffffff, and Config Writes to do nothing.
+ //
+
+ if (HalpPciConfig0BaseAddress[Slot.u.bits.DeviceNumber] == NULL) {
+ pPciAddr->u.AsULONG = INVALID_PCI_CONFIGURATION_ADDRESS;
+ return;
+ }
+
+ }
+ pPciAddr->u.AsULONG = (ULONG)HalpPciConfig0BaseAddress[Slot.u.bits.DeviceNumber];
+ pPciAddr->u.AsULONG += ((Slot.u.bits.FunctionNumber & 0x07) << 8);
+ pPciAddr->u.bits0.Reserved1 = PciConfigType0;
+
+#if DBG
+ DbgPrint("HalpPCIConfigAddr: Type 0 PCI Config Access @ %x\n", pPciAddr->u.AsULONG);
+#endif // DBG
+
+ } else {
+
+ //
+ // See if this is a nonexistant PCI device on the otherside of the First PCI-PCI Bridge
+ //
+
+ if (BusNumber == 1 && (1 << Slot.u.bits.DeviceNumber) & HalpNonExistentPci1DeviceMask) {
+ pPciAddr->u.AsULONG = INVALID_PCI_CONFIGURATION_ADDRESS;
+ return;
+ }
+
+ //
+ // See if this is a nonexistant PCI device on the otherside of the Second PCI-PCI Bridge
+ //
+
+ if (BusNumber == HalpSecondPciBridgeBusNumber && (1 << Slot.u.bits.DeviceNumber) & HalpNonExistentPci2DeviceMask) {
+ pPciAddr->u.AsULONG = INVALID_PCI_CONFIGURATION_ADDRESS;
+ return;
+ }
+
+ //
+ // Initialize PciAddr for a type 1 configuration cycle
+ //
+
+ if (HalpPciConfig1BaseAddress[BusNumber] == NULL) {
+
+ PHYSICAL_ADDRESS physicalAddress;
+
+ physicalAddress.QuadPart = HalpPciConfig1BasePhysical;
+ physicalAddress.QuadPart += ((BusNumber & 0xff) << 16);
+ HalpPciConfig1BaseAddress[BusNumber] = MmMapIoSpace(physicalAddress,0x10000,FALSE);
+
+ //
+ // If the mapping failed, then the return value is INVALID_PCI_CONFIGURATION_ADDRESS.
+ // This will cause Config Reads to return 0xffffffff, and Config Writes to do nothing.
+ //
+
+ if (HalpPciConfig1BaseAddress[BusNumber] == NULL) {
+ pPciAddr->u.AsULONG = INVALID_PCI_CONFIGURATION_ADDRESS;
+ return;
+ }
+
+ }
+ pPciAddr->u.AsULONG = (ULONG)HalpPciConfig1BaseAddress[BusNumber];
+ pPciAddr->u.AsULONG += ((Slot.u.bits.DeviceNumber & 0x1f) << 11);
+ pPciAddr->u.AsULONG += ((Slot.u.bits.FunctionNumber & 0x07) << 8);
+ pPciAddr->u.bits0.Reserved1 = PciConfigType1;
+
+#if DBG
+ DbgPrint("Type 1 PCI Config Access @ %x\n", pPciAddr->u.AsULONG);
+#endif // DBG
+
+ }
+
+ return;
+}
+
+UCHAR
+READ_CONFIG_UCHAR(
+ IN PVOID ConfigurationAddress,
+ IN ULONG ConfigurationType
+ )
+
+{
+ if (((ULONG)ConfigurationAddress & 0xffffff00) == INVALID_PCI_CONFIGURATION_ADDRESS) {
+ return((UCHAR)NO_PCI_DEVSEL_DATA_VALUE);
+ }
+ return(READ_REGISTER_UCHAR(ConfigurationAddress));
+}
+
+USHORT
+READ_CONFIG_USHORT(
+ IN PVOID ConfigurationAddress,
+ IN ULONG ConfigurationType
+ )
+
+{
+ if (((ULONG)ConfigurationAddress & 0xffffff00) == INVALID_PCI_CONFIGURATION_ADDRESS) {
+ return((USHORT)NO_PCI_DEVSEL_DATA_VALUE);
+ }
+ return(READ_REGISTER_USHORT(ConfigurationAddress));
+}
+
+ULONG
+READ_CONFIG_ULONG(
+ IN PVOID ConfigurationAddress,
+ IN ULONG ConfigurationType
+ )
+
+{
+ if (((ULONG)ConfigurationAddress & 0xffffff00) == INVALID_PCI_CONFIGURATION_ADDRESS) {
+ return((ULONG)NO_PCI_DEVSEL_DATA_VALUE);
+ }
+ return(READ_REGISTER_ULONG(ConfigurationAddress));
+}
+
+VOID
+WRITE_CONFIG_UCHAR(
+ IN PVOID ConfigurationAddress,
+ IN UCHAR ConfigurationData,
+ IN ULONG ConfigurationType
+ )
+
+{
+ if (((ULONG)ConfigurationAddress & 0xffffff00) != INVALID_PCI_CONFIGURATION_ADDRESS) {
+ WRITE_REGISTER_UCHAR(ConfigurationAddress,ConfigurationData);
+ }
+}
+
+VOID
+WRITE_CONFIG_USHORT(
+ IN PVOID ConfigurationAddress,
+ IN USHORT ConfigurationData,
+ IN ULONG ConfigurationType
+ )
+
+{
+ if (((ULONG)ConfigurationAddress & 0xffffff00) != INVALID_PCI_CONFIGURATION_ADDRESS) {
+ WRITE_REGISTER_USHORT(ConfigurationAddress,ConfigurationData);
+ }
+}
+
+VOID
+WRITE_CONFIG_ULONG(
+ IN PVOID ConfigurationAddress,
+ IN ULONG ConfigurationData,
+ IN ULONG ConfigurationType
+ )
+
+{
+ if (((ULONG)ConfigurationAddress & 0xffffff00) != INVALID_PCI_CONFIGURATION_ADDRESS) {
+ WRITE_REGISTER_ULONG(ConfigurationAddress,ConfigurationData);
+ }
+}
+
+LONGLONG HalpMapPciConfigBaseAddress(
+ IN ULONG BusNumber,
+ IN ULONG DeviceNumber,
+ IN ULONG FunctionNumber,
+ IN ULONG Register
+ )
+
+{
+ LONGLONG BaseAddress;
+
+ if (BusNumber == 0) {
+ BaseAddress = HalpPciConfig0BasePhysical +
+ (1 << (11+(DeviceNumber & 0x1f))) +
+ ((FunctionNumber & 0x07) << 8) +
+ Register;
+ } else {
+ BaseAddress = HalpPciConfig1BasePhysical +
+ ((BusNumber & 0xff) << 16) +
+ ((DeviceNumber & 0x1f) << 11) +
+ ((FunctionNumber & 0x07) << 8) +
+ Register;
+ }
+ return(BaseAddress);
+}
+
+ULONG HalpPciLowLevelConfigRead(
+ IN ULONG BusNumber,
+ IN ULONG DeviceNumber,
+ IN ULONG FunctionNumber,
+ IN ULONG Register
+ )
+
+/*++
+
+Routine Description:
+
+ This function allocates the resources needed to perform a single PCI
+ configuration read cycle. The read data is returned. For a MIPS processor,
+ a single TLB entry is borrowed so that I/O reads and writes can be performed
+ to PCI configuration space.
+
+Return Value:
+
+ Data retuned by the PCI config cycle.
+
+--*/
+
+{
+ LONGLONG BaseAddress;
+ PVOID VirtualAddress;
+ ULONG ReturnValue;
+
+ BaseAddress = HalpMapPciConfigBaseAddress(BusNumber,DeviceNumber,FunctionNumber,Register&0xfc);
+ VirtualAddress = HalpAllocateIoMapping(BaseAddress);
+ ReturnValue = READ_REGISTER_ULONG(VirtualAddress);
+ HalpFreeIoMapping();
+ return(ReturnValue);
+}
+
+VOID HalpPostCard(UCHAR Value)
+
+{
+ LONGLONG BaseAddress;
+ PVOID VirtualAddress;
+
+ BaseAddress = HalpMapPciConfigBaseAddress(HalpIntel82378BusNumber,HalpIntel82378DeviceNumber,0,0x4f);
+ VirtualAddress = HalpAllocateIoMapping(BaseAddress);
+ WRITE_REGISTER_UCHAR(VirtualAddress,0xcf);
+ HalpFreeIoMapping();
+
+ VirtualAddress = HalpAllocateIoMapping(HalpIsaIoBasePhysical + 0x420);
+ Value = (Value & 0x7f) | (READ_REGISTER_UCHAR(VirtualAddress) & 0x80);
+ HalpFreeIoMapping();
+
+ VirtualAddress = HalpAllocateIoMapping(HalpIsaIoBasePhysical + 0xc00);
+ WRITE_REGISTER_UCHAR(VirtualAddress,Value);
+ HalpFreeIoMapping();
+
+ BaseAddress = HalpMapPciConfigBaseAddress(HalpIntel82378BusNumber,HalpIntel82378DeviceNumber,0,0x4f);
+ VirtualAddress = HalpAllocateIoMapping(BaseAddress);
+ WRITE_REGISTER_UCHAR(VirtualAddress,0x4f);
+ HalpFreeIoMapping();
+}
diff --git a/private/ntos/nthals/halflex/mips/portsup.c b/private/ntos/nthals/halflex/mips/portsup.c
new file mode 100644
index 000000000..9e0171440
--- /dev/null
+++ b/private/ntos/nthals/halflex/mips/portsup.c
@@ -0,0 +1,137 @@
+/*++
+
+Copyright (c) 1995 DeskStation Technology
+
+Module Name:
+
+ portsup.c
+
+Abstract:
+
+ This module implements the code that provides the resources required to
+ access the serial port that is used for the kernel debugger.
+
+Author:
+
+ Michael D. Kinney 30-Apr-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+#define HEADER_FILE
+#include "kxmips.h"
+
+#define SP_VIRTUAL_BASE 0xffffa000
+#define SERIAL_PORT_COM1 0x3F8
+
+VOID
+HalpGetIoArchitectureType(
+ VOID
+ );
+
+//
+// Define hardware PTE's that map the serial port used by the debugger.
+//
+
+ENTRYLO HalpPte[2];
+
+PUCHAR HalpAllocateKdPortResources(
+ OUT PVOID *SP_READ,
+ OUT PVOID *SP_WRITE
+ )
+
+/*++
+
+Routine Description:
+
+ This function allocates the resources needed by the kernel debugger to
+ access a serial port. For a MIPS processor, a single TLB entry is borrowed
+ so that I/O reads and writes can be performed to the serial port.
+
+Arguments:
+
+ SP_READ - Kernel virtual address to use for I/O read operations.
+
+ SP_WRITE - Kernel virtual address to use for I/O write operations.
+
+Return Value:
+
+ The bus relative address of the COM port being used as a kernel debugger.
+
+--*/
+
+{
+ ULONG KdPortEntry;
+
+ HalpGetIoArchitectureType();
+
+ //
+ // Map the serial port into the system virtual address space by loading
+ // a TB entry.
+ //
+
+ HalpPte[0].PFN = (ULONG)(HalpIsaIoBasePhysical >> 12);
+ HalpPte[0].G = 1;
+ HalpPte[0].V = 1;
+ HalpPte[0].D = 1;
+
+ //
+ // Allocate a TB entry, set the uncached policy in the PTE that will
+ // map the serial controller, and initialize the second PTE.
+ //
+
+ KdPortEntry = HalpAllocateTbEntry();
+ HalpPte[0].C = UNCACHED_POLICY;
+
+ HalpPte[1].PFN = 0;
+ HalpPte[1].G = 1;
+ HalpPte[1].V = 0;
+ HalpPte[1].D = 0;
+ HalpPte[1].C = 0;
+
+ //
+ // Map the serial controller through a fixed TB entry.
+ //
+
+ KeFillFixedEntryTb((PHARDWARE_PTE)&HalpPte[0],
+ (PVOID)SP_VIRTUAL_BASE,
+ KdPortEntry);
+
+ *SP_READ = (PVOID)(SP_VIRTUAL_BASE + SERIAL_PORT_COM1);
+ *SP_WRITE = (PVOID)(SP_VIRTUAL_BASE + SERIAL_PORT_COM1);
+
+ return((PUCHAR)(SERIAL_PORT_COM1));
+}
+
+VOID HalpFreeKdPortResources(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function deallocates the resources needed by the kernel debugger to
+ access a serial port. For a MIPS processor, this simply frees the TLB entry
+ that was borrowed.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ HalpFreeTbEntry();
+}
diff --git a/private/ntos/nthals/halflex/mips/x4clock.s b/private/ntos/nthals/halflex/mips/x4clock.s
new file mode 100644
index 000000000..0e8475007
--- /dev/null
+++ b/private/ntos/nthals/halflex/mips/x4clock.s
@@ -0,0 +1,210 @@
+#if defined(R4000)
+
+// TITLE("Interval and Profile Clock Interrupts")
+//++
+//
+// Copyright (c) 1991 Microsoft Corporation
+//
+// Module Name:
+//
+// x4clock.s
+//
+// Abstract:
+//
+// This module implements the code necessary to field and process the
+// interval and profile clock interrupts on a MIPS R4000 system.
+//
+// Author:
+//
+// David N. Cutler (davec) 26-Apr-1991
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+
+ SBTTL("System Clock Interrupt")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interrupt generated by
+// the interval timer. Its function is to acknowledge the interrupt and
+// transfer control to the standard system routine to update the system
+// time and the execution time of the current thread and process.
+//
+// Arguments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+CiArgs: .space 4 * 4 // saved arguments
+ .space 3 * 4 // fill
+CiRa: .space 4 // saved return address
+CiFrameLength: //
+
+ NESTED_ENTRY(HalpClockInterrupt, CiFrameLength, zero)
+
+ subu sp,sp,CiFrameLength // allocate stack frame
+ sw ra,CiRa(sp) // save return address
+
+ PROLOGUE_END
+
+ move a0,s8 // set address of trap frame
+ lw a1,HalpCurrentTimeIncrement // Get current time increment
+ jal KeUpdateSystemTime // update system time
+ lw t0,HalpNextTimeIncrement // Get NextTimeIncrement
+ sw t0,HalpCurrentTimeIncrement // Set CurrentTimeIncrement to NextTimeIncrement
+ lw a0,HalpNextIntervalCount // Get Next Interval Count. If 0, then no change required
+ beq zero,a0,5f // See if time increment is to be changed
+ jal HalpProgramIntervalTimer // Program timer with new interval count value
+ lw t0,HalpNewTimeIncrement // Get HalpNewTimeIncrement
+ sw t0,HalpNextTimeIncrement // Set HalpNextTimeIncrement to HalpNewTimeIncrement
+ sw zero,HalpNextIntervalCount // Set HalpNextIntervalCount to 0
+5:
+ lw t0,KdDebuggerEnabled // check if debugger enabled
+ lbu t0,0(t0) //
+ beq zero,t0,10f // if eq, debugger not enabled
+ jal KdPollBreakIn // check if breakin is requested
+ beq zero,v0,10f // if eq, no breakin requested
+ li a0, DBG_STATUS_CONTROL_C // break in and send
+ jal DbgBreakPointWithStatus // status to debugger
+10: lw ra,CiRa(sp) // restore return address
+ addu sp,sp,CiFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalpClockInterrupt
+
+ SBTTL("Profile Clock Interrupt")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interrupt generated by the
+// profile clock. Its function is to acknowledge the profile interrupt,
+// compute the next compare value, update the performance counter, and
+// transfer control to the standard system routine to process any active
+// profiles.
+//
+// Arguments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpProfileInterrupt)
+
+ .set noreorder
+ .set noat
+ mfc0 t1,count // get current count value
+ mfc0 t0,compare // get current comparison value
+ addu t1,t1,8 // factor in lost cycles
+ subu t1,t1,t0 // compute initial count value
+ mtc0 t0,compare // dismiss interrupt
+ mtc0 t1,count // set new count register value
+ .set at
+ .set reorder
+
+ la t1,HalpPerformanceCounter // get performance counter address
+ lw t2,LiLowPart(t1) // get low part of performance count
+ lw t3,LiHighPart(t1) // get high part of performance count
+ addu t2,t2,t0 // update low part of performance count
+ sw t2,LiLowPart(t1) // store low part of performance count
+ sltu t4,t2,t0 // generate carry into high part
+ addu t3,t3,t4 // update high part of performance count
+ sw t3,LiHighPart(t1) // store high part of performance count
+ move a0,s8 // set address of trap frame
+ j KeProfileInterrupt // process profile entries
+
+ .end HalpProfileInterrupt
+
+ SBTTL("Read Count Register")
+//++
+//
+// ULONG
+// HalpReadCountRegister (
+// VOID
+// );
+//
+// Routine Description:
+//
+// This routine reads the current value of the count register and
+// returns the value.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// Current value of the count register.
+//
+//--
+
+ LEAF_ENTRY(HalpReadCountRegister)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,count // get count register value
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpReadCountRegister
+
+ SBTTL("Write Compare Register And Clear")
+//++
+//
+// ULONG
+// HalpWriteCompareRegisterAndClear (
+// IN ULONG Value
+// );
+//
+// Routine Description:
+//
+// This routine reads the current value of the count register, writes
+// the value of the compare register, clears the count register, and
+// returns the previous value of the count register.
+//
+// Arguments:
+//
+// Value - Supplies the value written to the compare register.
+//
+// Return Value:
+//
+// Previous value of the count register.
+//
+//--
+
+ LEAF_ENTRY(HalpWriteCompareRegisterAndClear)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,count // get count register value
+ mtc0 a0,compare // set compare register value
+ li t0,7 // set lost cycle count
+ mtc0 t0,count // set count register to zero
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpWriteCompareRegisterAndClear
+
+#endif
diff --git a/private/ntos/nthals/halflex/mips/x4tb.s b/private/ntos/nthals/halflex/mips/x4tb.s
new file mode 100644
index 000000000..d399da2ac
--- /dev/null
+++ b/private/ntos/nthals/halflex/mips/x4tb.s
@@ -0,0 +1,109 @@
+#if defined(R4000)
+
+// TITLE("AllocateFree TB Entry")
+//++
+//
+// Copyright (c) 1992-1993 Microsoft Corporation
+//
+// Module Name:
+//
+// x4tb.s
+//
+// Abstract:
+//
+// This module implements allocates and frees fixed TB entries using the
+// wired register.
+//
+// Environment:
+//
+// Kernel mode only.
+//
+//--
+
+#include "halmips.h"
+
+ SBTTL("Allocate Tb Entry")
+//++
+//
+// ULONG
+// HalpAllocateTbEntry (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function allocates the TB entry specified by the wired register
+// and increments the wired register.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// The index of the allocated TB entry.
+//
+//--
+
+ LEAF_ENTRY(HalpAllocateTbEntry)
+
+ DISABLE_INTERRUPTS(t0) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 v0,wired // get contents of wired register
+ nop // fill
+ addu v1,v0,1 // allocate TB entry
+ mtc0 v1,wired //
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t0) // enable interrupts
+
+ j ra // return
+
+ .end HalpAllocateTbEntry
+
+ SBTTL("Free Tb Entry")
+//++
+//
+// VOID
+// HalpAllocateTbEntry (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function frees the TB entry specified by the wired register
+// and decrements the wired register.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpFreeTbEntry)
+
+ DISABLE_INTERRUPTS(t0) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 v0,wired // get contents of wired register
+ nop // fill
+ subu v1,v0,1 // free TB entry
+ mtc0 v1,wired //
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t0) // enable interrupts
+
+ j ra // return
+
+ .end HalpFreeTbEntry
+
+#endif
diff --git a/private/ntos/nthals/halflex/mips/xxcalstl.c b/private/ntos/nthals/halflex/mips/xxcalstl.c
new file mode 100644
index 000000000..e1ce0b6b0
--- /dev/null
+++ b/private/ntos/nthals/halflex/mips/xxcalstl.c
@@ -0,0 +1,253 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ xxcalstl.c
+
+Abstract:
+
+
+ This module implements the calibration of the stall execution HAL
+ service, computes the count rate for the profile clock, and connects
+ the clock and profile interrupts for a MIPS R3000 or R4000 system.
+
+Author:
+
+ David N. Cutler (davec) 26-Apr-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+//
+// Define global data used to calibrate and stall processor execution.
+//
+
+ULONG HalpProfileCountRate;
+ULONG volatile HalpStallEnd;
+ULONG volatile HalpStallStart;
+
+BOOLEAN
+HalpCalibrateStall (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function calibrates the stall execution HAL service and connects
+ the clock and profile interrupts to the appropriate NT service routines.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the calibration is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+
+ ULONG Index;
+ KIRQL OldIrql;
+ PKPRCB Prcb;
+
+ //
+ // Start the system clock to interrupt at MAXIMUM_INCREMENT intervals.
+ //
+ // N.B. MAXIMUM_INCREMENT is in 100ns units.
+ //
+
+ HalSetTimeIncrement(MAXIMUM_INCREMENT);
+ HalpProgramIntervalTimer(HalpNextIntervalCount);
+ HalpEnableEisaInterrupt(UNIFLEX_CLOCK2_LEVEL,Latched); /* Enable Timer1,Counter0 interrupt */
+
+ //
+ // Use a range of scale factors from 50ns down to 10ns assuming a
+ // five instruction stall loop.
+ //
+
+ for (Index = 50; Index > 0; Index -= 10) {
+
+ //
+ // Disable all interrupts and establish calibration parameters.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // Set the scale factor, stall count, starting stall count, and
+ // ending stall count values.
+ //
+
+ PCR->StallScaleFactor = 1000 / (Index * 5);
+ PCR->StallExecutionCount = 0;
+ HalpStallStart = 0;
+ HalpStallEnd = 0;
+
+ //
+ // Enable interrupts and stall execution.
+ //
+
+ KeLowerIrql(OldIrql);
+
+ //
+ // Stall execution for (MAXIMUM_INCREMENT / 10) * 4 us.
+ //
+
+ KeStallExecutionProcessor((MAXIMUM_INCREMENT / 10) * 4);
+
+ //
+ // If both the starting and ending stall counts have been captured,
+ // then break out of loop.
+ //
+
+ if ((HalpStallStart != 0) && (HalpStallEnd != 0)) {
+ break;
+ }
+
+ }
+
+ //
+ // Compute the profile interrupt rate.
+ //
+
+ HalpProfileCountRate =
+ HalpProfileCountRate * ((1000 * 1000 * 10) / MAXIMUM_INCREMENT);
+
+ //
+ // Compute the stall execution scale factor.
+ //
+
+ PCR->StallScaleFactor = (HalpStallEnd - HalpStallStart +
+ ((MAXIMUM_INCREMENT / 10) - 1)) / (MAXIMUM_INCREMENT / 10);
+
+ if (PCR->StallScaleFactor <= 0) {
+ PCR->StallScaleFactor = 1;
+ }
+
+ //
+ // Get the address of the processor control block for the current
+ // processor.
+ //
+
+ Prcb = PCR->Prcb;
+
+ //
+ // Connect the real clock interrupt routine.
+ //
+
+ PCR->InterruptRoutine[UNIFLEX_CLOCK2_LEVEL] = HalpClockInterrupt;
+
+ //
+ // Write the compare register and clear the count register, and
+ // connect the profile interrupt.
+ //
+
+ HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
+ PCR->InterruptRoutine[PROFILE_LEVEL] = HalpProfileInterrupt;
+
+ return TRUE;
+}
+
+VOID
+KeStallExecutionProcessor (
+ IN ULONG MicroSeconds
+ )
+
+/*++
+
+Routine Description:
+
+ This function stalls execution of the current processor for the specified
+ number of microseconds.
+
+Arguments:
+
+ MicroSeconds - Supplies the number of microseconds that execution is to
+ be stalled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Index;
+
+ //
+ // Use the stall scale factor to determine the number of iterations
+ // the wait loop must be executed to stall the processor for the
+ // specified number of microseconds.
+ //
+
+ Index = MicroSeconds * PCR->StallScaleFactor;
+ do {
+ PCR->StallExecutionCount += 1;
+ Index -= 1;
+ } while (Index > 0);
+
+ return;
+}
+
+VOID
+HalpStallInterrupt (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function serves as the stall calibration interrupt service
+ routine. It is executed in response to system clock interrupts
+ during the initialization of the HAL layer.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // If this is the very first interrupt, then wait for the second
+ // interrupt before starting the timing interval. Else, if this
+ // the second interrupt, then capture the starting stall count
+ // and clear the count register on R4000 processors. Else, if this
+ // is the third interrupt, then capture the ending stall count and
+ // the ending count register on R4000 processors. Else, if this is
+ // the fourth or subsequent interrupt, then simply dismiss it.
+ //
+
+ if ((HalpStallStart == 0) && (HalpStallEnd == 0)) {
+ HalpStallEnd = 1;
+
+ } else if ((HalpStallStart == 0) && (HalpStallEnd != 0)) {
+ HalpStallStart = PCR->StallExecutionCount;
+ HalpStallEnd = 0;
+ HalpWriteCompareRegisterAndClear(0);
+ } else if ((HalpStallStart != 0) && (HalpStallEnd == 0)) {
+ HalpStallEnd = PCR->StallExecutionCount;
+ HalpProfileCountRate = HalpWriteCompareRegisterAndClear(0);
+ }
+ return;
+}
diff --git a/private/ntos/nthals/halflex/mips/xxidle.s b/private/ntos/nthals/halflex/mips/xxidle.s
new file mode 100644
index 000000000..d0cd9c78b
--- /dev/null
+++ b/private/ntos/nthals/halflex/mips/xxidle.s
@@ -0,0 +1,79 @@
+// TITLE("Processor Idle")
+//++
+//
+// Copyright (c) 1994 Microsoft Corporation
+//
+// Module Name:
+//
+// xxidle.s
+//
+// Abstract:
+//
+// This module implements system platform dependent power management
+// support.
+//
+// Author:
+//
+// David N. Cutler (davec) 5-Mar-1994
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+
+ SBTTL("Processor Idle")
+//++
+//
+// VOID
+// HalProcessorIdle(
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function is called when the current processor is idle with
+// interrupts disabled. There is no thread active and there are no
+// DPCs to process. Therefore, power can be switched to a standby
+// mode until the the next interrupt occurs on the current processor.
+//
+// N.B. This routine is entered with IE in PSR clear. This routine
+// must do any power management enabling necessary, set the IE
+// bit in PSR, then either return or wait for an interrupt.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalProcessorIdle)
+
+//
+// Perform power management enabling.
+//
+
+ .set noreorder
+ .set noat
+ mfc0 v0,psr // get current PSR
+ nop // fill
+ or v0,v0,1 << PSR_IE // set interrupt enable.
+ mtc0 v0,psr // enable interrupts
+ .set at
+ .set reorder
+
+//
+// Wait for an interrupt if supported.
+//
+
+ j ra // return
+
+ .end HalProcessorIdle
diff --git a/private/ntos/nthals/halflex/mips/xxinitnt.c b/private/ntos/nthals/halflex/mips/xxinitnt.c
new file mode 100644
index 000000000..b8b757141
--- /dev/null
+++ b/private/ntos/nthals/halflex/mips/xxinitnt.c
@@ -0,0 +1,159 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ xxinitnt.c
+
+Abstract:
+
+
+ This module implements the interrupt initialization for a MIPS R3000
+ or R4000 system.
+
+Author:
+
+ David N. Cutler (davec) 26-Apr-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+//
+// Define the IRQL mask and level mapping table.
+//
+// These tables are transfered to the PCR and determine the priority of
+// interrupts.
+//
+// N.B. The two software interrupt levels MUST be the lowest levels.
+//
+
+UCHAR HalpIrqlMask[] = {4, 3, 3, 3, 3, 3, 3, 3, // 0000 - 0111 high 4-bits
+ 8, 8, 8, 8, 8, 8, 8, 8, // 1000 - 1111 high 4-bits
+ 0, 1, 2, 2, 3, 3, 3, 3, // 0000 - 0111 low 4-bits
+ 4, 4, 4, 4, 4, 4, 4, 4}; // 1000 - 1111 low 4-bits
+
+UCHAR HalpIrqlTable[] = {0x8f, // IRQL 0
+ 0x8e, // IRQL 1
+ 0x8c, // IRQL 2
+ 0x88, // IRQL 3
+ 0x80, // IRQL 4
+ 0x80, // IRQL 5
+ 0x80, // IRQL 6
+ 0x80, // IRQL 7
+ 0x00}; // IRQL 8
+
+
+VOID
+HalpCountInterrupt (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function serves as the R4000 count/compare interrupt service
+ routine early in the system initialization. Its only function is
+ to field and acknowledge count/compare interrupts during the system
+ boot process.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Acknowledge the R4000 count/compare interrupt.
+ //
+
+ HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
+ return;
+}
+
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes interrupts for a MIPS R3000 or R4000 system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the initialization is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+ ULONG Index;
+ PKPRCB Prcb;
+
+ //
+ // Mask sure that all processor interrupts are inactive by masking off all device
+ // interrupts in the system's Programable Interrupt Controllers.
+ //
+
+ HalpDisableAllInterrupts();
+
+ //
+ // Get the address of the processor control block for the current
+ // processor.
+ //
+
+ Prcb = PCR->Prcb;
+
+ //
+ // Initialize the IRQL translation tables in the PCR. These tables are
+ // used by the interrupt dispatcher to determine the new IRQL and the
+ // mask value that is to be loaded into the PSR. They are also used by
+ // the routines that raise and lower IRQL to load a new mask value into
+ // the PSR.
+ //
+
+ for (Index = 0; Index < sizeof(HalpIrqlMask); Index += 1) {
+ PCR->IrqlMask[Index] = HalpIrqlMask[Index];
+ }
+
+ for (Index = 0; Index < sizeof(HalpIrqlTable); Index += 1) {
+ PCR->IrqlTable[Index] = HalpIrqlTable[Index];
+ }
+
+ //
+ // Connect the clock interrupt to the stall interrupt routine.
+ //
+
+ PCR->InterruptRoutine[UNIFLEX_CLOCK2_LEVEL] = HalpStallInterrupt;
+
+ //
+ // Connect the R4000 count/compare interrupt to the early interrupt
+ // routine.
+ //
+
+ PCR->InterruptRoutine[PROFILE_LEVEL] = HalpCountInterrupt;
+
+ return TRUE;
+}
diff --git a/private/ntos/nthals/halflex/pcip.h b/private/ntos/nthals/halflex/pcip.h
new file mode 100644
index 000000000..2d8527914
--- /dev/null
+++ b/private/ntos/nthals/halflex/pcip.h
@@ -0,0 +1,138 @@
+/*++ BUILD Version: 0000 Increment this if a change has global effects
+
+Copyright (C) 1994,1995 Microsoft Corporation
+Copyright (C) 1994,1995 Digital Equipment Corporation
+
+Module Name:
+
+ pcip.h
+
+Abstract:
+
+ This header file defines the private PCI bus HAL interfaces and
+ data types.
+
+--*/
+//
+// Hal specific PCI bus structures
+//
+
+#define PCI_CONFIG_TYPE(PciData) ((PciData)->HeaderType & ~PCI_MULTIFUNCTION)
+
+#define PCI_MAX_BUSSES 256
+
+#define PciBitIndex(Dev,Fnc) (Fnc*32 + Dev)
+
+//
+// Define PCI configuration cycle types.
+//
+typedef enum _PCI_CONFIGURATION_TYPES {
+ PciConfigTypeInvalid = -1,
+ PciConfigType0 = 0,
+ PciConfigType1 = 1
+} PCI_CONFIGURATION_TYPES, *PPCI_CONFIGURATION_TYPES;
+
+typedef struct _PCI_CFG_CYCLE_BITS {
+ union {
+ struct {
+ ULONG Reserved1:2;
+ ULONG Reserved2:30;
+ } bits; // Generic Config Cycle
+
+ struct {
+ ULONG Reserved1:2;
+ ULONG RegisterNumber:6;
+ ULONG FunctionNumber:3;
+ ULONG Idsel:21;
+ } bits0; // Type0 Config Cycle
+
+ struct {
+ ULONG Reserved1:2;
+ ULONG RegisterNumber:6;
+ ULONG FunctionNumber:3;
+ ULONG DeviceNumber:5;
+ ULONG BusNumber:8;
+ ULONG Reserved2:7;
+ ULONG Enable:1;
+ } bits1; // Type 1 Config Cycle
+
+ ULONG AsULONG;
+ } u;
+} PCI_CFG_CYCLE_BITS, *PPCI_CFG_CYCLE_BITS;
+
+//
+// Define PCI cycle/command types.
+//
+
+typedef enum _PCI_COMMAND_TYPES{
+ PciCommandInterruptAcknowledge = 0x0,
+ PciCommandSpecialCycle = 0x1,
+ PciCommandIoRead = 0x2,
+ PciCommandIoWrite = 0x3,
+ PciCommandMemoryRead = 0x6,
+ PciCommandMemoryWrite = 0x7,
+ PciCommandConfigurationRead = 0xa,
+ PciCommandConfigurationWrite = 0xb,
+ PciCommandMemoryReadMultiple = 0xc,
+ PciCommandDualAddressCycle = 0xd,
+ PciCommandMemoryReadLine = 0xe,
+ PciCommandMemoryWriteAndInvalidate = 0xf,
+ MaximumPciCommand
+} PCI_COMMAND_TYPES, *PPCI_COMMAND_TYPES;
+
+//
+// PCI platform-specific functions
+//
+
+
+PCI_CONFIGURATION_TYPES
+HalpPCIConfigCycleType (
+ IN ULONG BusNumber
+ );
+
+VOID
+HalpPCIConfigAddr (
+ IN ULONG BusNumber,
+ IN PCI_SLOT_NUMBER Slot,
+ PPCI_CFG_CYCLE_BITS pPciAddr
+ );
+
+
+//
+// Define PCI configuration cycle types.
+//
+
+typedef enum _PCI_TYPE0_CONFIG_TYPE {
+ PciConfigType0AsIdsel,
+ PciConfigType0AsDeviceNumber
+} PCI_TYPE0_CONFIG_TYPE, *PPCI_TYPE0_CONFIG_TYPE;
+
+
+typedef struct tagPCIPBUSDATA {
+
+ //
+ // NT Defined PCI data
+ //
+
+ PCIBUSDATA CommonData;
+
+ //
+ // Common alpha hal specific data
+ //
+
+ PVOID ConfigBaseQva;
+ PCI_TYPE0_CONFIG_TYPE PciType0ConfigType;
+ BOOLEAN BusIsAcrossPPB;
+
+ RTL_BITMAP DevicePresent;
+ ULONG DevicePresentBits[PCI_MAX_DEVICES * PCI_MAX_FUNCTION / 32];
+
+ ULONG MaxDevice;
+
+ //
+ // Platform-specific storage
+ //
+
+ PVOID PlatformSpecificData;
+
+} PCIPBUSDATA, *PPCIPBUSDATA;
diff --git a/private/ntos/nthals/halflex/platform.h b/private/ntos/nthals/halflex/platform.h
new file mode 100644
index 000000000..b679d15a6
--- /dev/null
+++ b/private/ntos/nthals/halflex/platform.h
@@ -0,0 +1,194 @@
+/*++
+
+Copyright (c) 1995 DeskStation Technology
+
+Module Name:
+
+ platform.h
+
+Abstract:
+
+ This file contains definitions specific to private vector calls into
+ the ARCSBIOS firmware.
+
+Author:
+
+ Michael D. Kinney 1-May-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#define MAX_PROCESSORS 32
+#define MAX_SYSTEM_INTERRUPTS 256
+#define MAX_SYSTEM_EXCEPTIONS 64
+#define MAX_INTERRUPTS_PER_BUS 32
+#define ARC_NAME_LENGTH 128
+#define IDENTIFIER_LENGTH 64
+#define MAX_SIMM_SOCKETS 32
+#define MAX_BUSSES 16
+#define NUMBEROFNVRAMSECTIONS 5
+
+typedef enum { ISA_BUS, EISA_BUS, VESA_BUS, PCI_BUS, PROCESSOR_BUS, MAXIMUM_BUS } BUS_TYPE;
+
+typedef enum { IO_SPACE, MEMORY_SPACE, CONFIGURATION_TYPE_0_SPACE, CONFIGURATION_TYPE_1_SPACE, MAX_ADDRESS_SPACE_TYPE } ADDRESS_SPACE_TYPE;
+
+typedef enum { EDGE, LEVEL} INTERRUPT_MODE;
+
+typedef enum {UnifiedCache,SplitCache,NoCache} CACHE_TYPE;
+
+typedef struct {
+ CHAR VendorId[8];
+ CHAR ProductId[8];
+ }
+ SYSTEMID;
+
+typedef struct CACHE_DESCRIPTION
+ {
+ ULONG NumberOfSets; // Number of associative sets
+ ULONG RefillSize; // Number of lines read per refill
+ ULONG LineSize; // Size of refill in bytes
+ ULONG Size; // Size of cache set in bytes
+ }
+ CACHE_DESCRIPTION;
+
+typedef struct SPLIT_CACHE_DESCRIPTION
+ {
+ CACHE_DESCRIPTION Instruction; // Configuration information on the insruction cache of a split cache
+ CACHE_DESCRIPTION Data; // Configuration information on the data cache of a split cache
+ }
+ SPLIT_CACHE_DESCRIPTION;
+
+typedef struct PROCESSOR_CACHE_DESCRIPTION
+ {
+ CACHE_TYPE CacheType; // Cache type(i.e. Split or Unified)
+ ULONG CoherentWithDma; // TRUE if cache is coherent with DMA reads and writes
+ union
+ {
+ CACHE_DESCRIPTION UnifiedCache; // Configuration information on a unified cache
+ SPLIT_CACHE_DESCRIPTION SplitCache; // Configuration information on a split cache
+ };
+ }
+ PROCESSOR_CACHE_DESCRIPTION;
+
+typedef struct PROCESSOR
+ {
+ UCHAR *CpuIdentifier; // Pointer to the CPU's identifier
+ UCHAR *FpuIdentifier; // Pointer to the FPU's identifier
+ UCHAR *CpuName; // Pointer to the CPU's print name
+ UCHAR RevisionName[IDENTIFIER_LENGTH]; // CPU's revision print name
+ ULONG InternalClockSpeed; // Internal clock speed in MHz
+ ULONG ExternalClockSpeed; // External clock speed in MHz
+ ULONG StallExecutionDelay; // Count used in calibrated 1 us delay loop
+ PROCESSOR_CACHE_DESCRIPTION FirstLevel; // Primary cache configuration information
+ PROCESSOR_CACHE_DESCRIPTION SecondLevel; // Secondary cache configuration information
+ PROCESSOR_CACHE_DESCRIPTION ThirdLevel; // Third level cache configuration information
+ }
+ PROCESSOR;
+
+typedef struct SIMM_SOCKET
+ {
+ UCHAR Name[IDENTIFIER_LENGTH]; // Print string for the socket's name
+ UCHAR Size[IDENTIFIER_LENGTH]; // Print string for the socket's size
+ }
+ SIMM_SOCKET;
+
+typedef struct SYSTEM_IO_BUS
+ {
+ BUS_TYPE BusType; // Type of bus(i.e. ISA, EISA, VESA, PCI)
+ ULONG BusNumber; // Bus number starting from 0
+ ULONG BusConfigurationError; // TRUE if the bus is not configured correctly
+ ULONG AlliasedBus; // TRUE if this bus is an allias of another bus
+ ULONG DmaCacheOffset; // Bus Physical Offset of Dma Cache
+ PHYSICAL_ADDRESS AddressSpace[MAX_ADDRESS_SPACE_TYPE]; // Processor physical address for each address space type
+ PVOID VirtualAddress[MAX_ADDRESS_SPACE_TYPE]; // Processor virtual address for each address space type
+ ULONG NumberOfPhysicalSlots; // Number of physical slots in bus
+ ULONG NumberOfVirtualSlots; // Number of virtual slots in bus
+ }
+ SYSTEM_IO_BUS;
+
+typedef struct PLATFORM_DEVICE_INFO
+ {
+ UCHAR FloppyDriveATypeInformation;
+ UCHAR FloppyDriveBTypeInformation;
+ UCHAR Lpt1IrqInformation;
+ UCHAR Lpt2IrqInformation;
+ UCHAR Lpt3IrqInformation;
+ UCHAR SerialMouseInformation;
+ UCHAR CheckEisaSlots;
+ UCHAR LoadEmbeddedScsiDrivers;
+ UCHAR LoadFlashScsiDrivers;
+ UCHAR LoadSoftScsiDrivers;
+ UCHAR EnableDelays;
+ UCHAR ResetDelay;
+ UCHAR DetectDelay;
+ UCHAR EnableIDEDriver;
+ UCHAR EnableX86Emulator;
+ }
+ PLATFORM_DEVICE_INFO;
+
+typedef struct {
+ ULONG StartOffset;
+ ULONG EndOffset;
+ ULONG CheckSumOffset;
+ }
+ NVRAMDETAILS;
+
+typedef struct PLATFORM_PARAMETER_BLOCK
+ {
+ SYSTEMID SystemId; // VendorID and ProductID for this platform
+ UCHAR ArchitectureName[16]; // String for the processor architecture(MIPS,ALPHA,X86,PPC)
+ UCHAR ModuleName[16]; // String used to identify the module(MOLDAU,TYNE,GAMBIT,ROGUE,COBRA)
+
+ USHORT ArcVersion; // Major Version of ARC Specification
+ USHORT ArcRevision; // Minor Revision of ARC Specification
+ ULONG FirmwareRevision; // ARCS BIOS Firmware Revision
+
+ ULONG MultiProcessorSystem; // TRUE if system is an MP system
+ ULONG NumberOfCpus; // Total number of CPUs in the system
+ PROCESSOR Processor[MAX_PROCESSORS]; // Configuration information on each processor
+ PROCESSOR_CACHE_DESCRIPTION External; // Configuration information on a shared external cache
+
+ ULONG MemorySize; // Main memory size in bytes
+ ULONG SimmConfigurationError; // TRUE if the SIMMs are not correctly configured
+ SIMM_SOCKET SimmSocket[MAX_SIMM_SOCKETS]; // Configuration information on SIMMs
+
+ ULONG DmaCacheError; // TRUE if the DMA cache did not pass the memory test
+ ULONG DmaCacheVirtualAddress; // Processor virtual address of the DMA cache
+ PHYSICAL_ADDRESS DmaCachePhysicalAddress; // Processor physical address of the DMA cache
+ ULONG DmaCacheSize; // Size of the DMA Cache in bytes
+ ULONG DmaAlignmentRequirement; // DMA Buffer Alignment requirement in bytes
+
+ SYSTEM_IO_BUS SystemIoBus[MAX_BUSSES]; // Configuration information on system busses
+
+ ULONG InterruptDispatchTable[MAX_SYSTEM_INTERRUPTS]; // Dispatch table for processor and bus interrupts
+ ULONG ExceptionDispatchTable[MAX_SYSTEM_EXCEPTIONS]; // Dispatch table for processor exceptions
+
+ ULONG FirmwareBaseAddress; // Memory address for the start of the firmware code/data
+ ULONG FirmwareSize; // Size of the firmware code/data section in bytes
+ ULONG HeapStart; // Memory address for the start of the firmware heap
+ ULONG HeapEnd; // Memory address for the end of the firmware heap
+ ULONG StackBaseAddress; // Memory address for the start of the firmware stack
+ ULONG StackSize; // Size of the firmware stack section in bytes
+ ULONG ImageLibraryBaseAddress; // Memory address for the start of the image library
+ ULONG ImageLibrarySize; // Size of the image library in bytes
+
+ UCHAR ConsoleOutAdapterName[ARC_NAME_LENGTH]; // ARC name for the console out device's adapter
+ UCHAR ConsoleOutName[ARC_NAME_LENGTH]; // ARC name for the console out device
+ UCHAR ProductIdentifier[IDENTIFIER_LENGTH]; // Product identifier string
+ UCHAR ProductName[IDENTIFIER_LENGTH]; // Product name string
+ UCHAR HelpAboutBoxString[IDENTIFIER_LENGTH]; // Help about box string
+
+ PLATFORM_DEVICE_INFO PlatformDeviceInfo; // System info on how to detect I/O devices
+
+ NVRAMDETAILS NVRAMDetails[NUMBEROFNVRAMSECTIONS]; // Describes organization of NVRAM.
+
+ PVOID PlatformSpecificExtension; // Platform Specific Extension
+ }
+ PLATFORM_PARAMETER_BLOCK;
+
diff --git a/private/ntos/nthals/halflex/sources b/private/ntos/nthals/halflex/sources
new file mode 100644
index 000000000..26c244e5d
--- /dev/null
+++ b/private/ntos/nthals/halflex/sources
@@ -0,0 +1,141 @@
+!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) 8-Apr-1993
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halflex
+TARGETPATH=\nt\public\sdk\lib
+
+TARGETTYPE=HAL
+
+INCLUDES=..\x86new;..\inc;..\..\inc
+
+!IF $(MIPS)
+TARGETLIBS=\nt\private\ntos\nthals\x86new\obj\*\x86new.lib \
+ \nt\public\sdk\lib\*\libcntpr.lib
+
+MIPS_ENABLE_MIPS3=1
+MSC_WARNING_LEVEL=/W3
+
+!ENDIF
+
+!IF $(ALPHA)
+TARGETLIBS=\nt\public\sdk\lib\*\libcntpr.lib
+
+ALPHA_WARNING_LEVEL=-W3
+C_DEFINES=-DEV5 -DTAGGED_NVRAM
+NT_UP=1
+
+!ENDIF
+
+SOURCES=
+
+ALPHA_SOURCES=hal.rc \
+ adjust.c \
+ bushnd.c \
+ drivesup.c \
+ allstart.c \
+ busdata.c \
+ ioproc.c \
+ iousage.c \
+ xxbeep.c \
+ xxclock.c \
+ xxdisp.c \
+ xxebsup.c \
+ xxenvirv.c \
+ xxhwsup.c \
+ xxinithl.c \
+ xxpcisup.c \
+ xxport.c \
+ xxreturn.c \
+ xxsysint.c \
+ xxtime.c \
+ x86bios.c \
+ alpha\addrsup.c \
+ alpha\arcssup.c \
+ alpha\evxcache.c \
+ alpha\ev4prof.c \
+ alpha\ev5prof.c \
+ alpha\evxprof.c \
+ alpha\initsys.c \
+ alpha\intsup.c \
+ alpha\jxmapio.c \
+ alpha\minitlb.c \
+ alpha\pcisup.c \
+ alpha\perfcntr.c \
+ alpha\portsup.c \
+ alpha\xxinitnt.c \
+ alpha\alphaio.s \
+ alpha\ev4int.c \
+ alpha\ev4ints.s \
+ alpha\ev5ints.s \
+ alpha\evxmem.s \
+ alpha\halpal.s \
+ alpha\evclock.s \
+ alpha\info.c \
+ alpha\xxidle.s
+
+MIPS_SOURCES=hal.rc \
+ adjust.c \
+ bushnd.c \
+ drivesup.c \
+ allstart.c \
+ busdata.c \
+ ioproc.c \
+ iousage.c \
+ xxbeep.c \
+ xxclock.c \
+ xxdisp.c \
+ xxebsup.c \
+ xxenvirv.c \
+ xxhwsup.c \
+ xxinithl.c \
+ xxpcisup.c \
+ xxport.c \
+ xxreturn.c \
+ xxsysint.c \
+ xxtime.c \
+ x86bios.c \
+ mips\addrsup.c \
+ mips\arcssup.c \
+ mips\flushio.c \
+ mips\info.c \
+ mips\initsys.c \
+ mips\jxmapio.c \
+ mips\intsup.c \
+ mips\j4prof.c \
+ mips\pcisup.c \
+ mips\portsup.c \
+ mips\xxcalstl.c \
+ mips\xxinitnt.c \
+ mips\xxidle.s \
+ mips\x4tb.s \
+ mips\j4flshbf.s \
+ mips\j4cache.s \
+ mips\x4clock.s
+
+DLLDEF=obj\*\hal.def
+
+NTTARGETFILES=$(TARGETPATH)\*\hal.lib
diff --git a/private/ntos/nthals/halflex/uniflex.h b/private/ntos/nthals/halflex/uniflex.h
new file mode 100644
index 000000000..6a239d454
--- /dev/null
+++ b/private/ntos/nthals/halflex/uniflex.h
@@ -0,0 +1,108 @@
+/*++
+
+Copyright (c) 1995 DeskStation Technology
+
+Module Name:
+
+ platform.h
+
+Abstract:
+
+ This file contains definitions specific to the UNIFLEX motherboard.
+
+Author:
+
+ Michael D. Kinney 1-May-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+//
+// Define the motherboard types
+//
+
+#define MOTHERBOARD_UNKNOWN 0
+#define TREBBIA13 1
+#define TREBBIA20 2
+
+//
+// Define the processor module types
+//
+
+#define EV5_PROCESSOR_MODULE 0
+#define EV4_PROCESSOR_MODULE 1
+#define R4600_PROCESSOR_MODULE 2
+#define UNKNOWN_PROCESSOR_MODULE 0xffffffff
+
+//
+// Define the module chip set revision constants
+//
+
+#define EV4_MAX_CHIP_SET_REVISION 1
+#define EV5_MAX_CHIP_SET_REVISION 2
+#define MODULE_CHIP_SET_REVISION_UNKNOWN 0xffffffff
+
+//
+// Define the bus types
+//
+
+#define UNIFLEX_MACHINE_TYPE_ISA 0
+#define UNIFLEX_MACHINE_TYPE_EISA 1
+
+#define MAX_EISA_BUSSES 2
+#define MAX_PCI_BUSSES 2
+#define MAX_DMA_CHANNELS_PER_EISA_BUS 8
+
+//
+// Define the maximum number of map registers that can be requested at one time
+// if actual map registers are required for the transfer.
+//
+
+#define MAXIMUM_ISA_MAP_REGISTER (0x10000/PAGE_SIZE)
+
+#define COPY_BUFFER 0xFFFFFFFF
+
+#define NO_SCATTER_GATHER 0x00000001
+
+#define NULL_MAP_REGISTER_BASE (PVOID)(0xfffffffe)
+
+typedef volatile struct _TRANSLATION_ENTRY {
+ PVOID VirtualAddress;
+ ULONG PhysicalAddress;
+ ULONG Index;
+} TRANSLATION_ENTRY, *PTRANSLATION_ENTRY;
+
+//
+// Define the maximum and minimum time increment values in 100ns units.
+//
+// N.B. these values are as close to exact values as possible given the input
+// clock of 1.19318167 hz (14.31818 / 12)
+//
+
+#define MAXIMUM_INCREMENT (99968) // Time increment in 100ns units - Approx 10 ms
+#define MINIMUM_INCREMENT (10032) // Time increment in 100ns units - Approx 1 ms
+
+//
+// Define clock constants.
+//
+
+#define AT_BUS_OSC 14318180 // 14.31818 MHz Crystal
+
+//
+// Define UniFlex PCI Bus #0 motherboard device mask.
+//
+
+#define TREB13_MOTHERBOARD_PCI_DEVICE_MASK (ULONG)((1<<0x0d) | (1<<0x0f) | (1<<0x10) | (1<<0x11))
+#define TREB20_MOTHERBOARD_PCI_DEVICE_MASK (ULONG)((1<<0x10) | (1<<0x11))
+
+//
+// Highest Virtual local PCI Slot is 20 == IDSEL PCI_AD[31]
+//
+
+#define PCI_MAX_LOCAL_DEVICE 20
diff --git a/private/ntos/nthals/halflex/x86bios.c b/private/ntos/nthals/halflex/x86bios.c
new file mode 100644
index 000000000..7968bca21
--- /dev/null
+++ b/private/ntos/nthals/halflex/x86bios.c
@@ -0,0 +1,599 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ x86bios.c
+
+Abstract:
+
+
+ This module implements the platform specific interface between a device
+ driver and the execution of x86 ROM bios code for the device.
+
+Author:
+
+ David N. Cutler (davec) 17-Jun-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "xm86.h"
+#include "x86new.h"
+
+//
+// The X86 Emulator built into the HAL is suported on MIPS and PPC,
+// but not ALPHA. If this is an ALPHA system, then don't include the
+// code that uses the X86 emulator in the HAL. Instead, use the X86
+// emulator built in the Firmware if one is available.
+//
+
+#ifndef ALPHA
+#define ENABLE_HAL_X86_EMULATOR
+#endif
+
+typedef struct FIRMWARE_INT_ARGUMENTS {
+ ULONG pEAX;
+ ULONG pEBX;
+ ULONG pECX;
+ ULONG pEDX;
+ ULONG pESI;
+ ULONG pEDI;
+ ULONG pEBP;
+ USHORT pES;
+ USHORT pDS;
+ USHORT pFlags;
+} FIRMWARE_INT_ARGUMENTS, *PFIRMWARE_INT_ARGUMENTS;
+
+#ifdef ENABLE_HAL_X86_EMULATOR
+
+extern ULONG x86BiosIoSpace;
+ULONG HalpPciConfigAddress;
+
+#endif
+
+ULONG HalpX86BiosInitialized = FALSE;
+ULONG HalpEnableInt10Calls = FALSE;
+ULONG HalpUseFirmwareX86Emulator = FALSE;
+
+typedef
+VOID
+(*PVENDOR_EXECUTE_INT) (
+ IN USHORT Type,
+ IN PFIRMWARE_INT_ARGUMENTS Context
+ );
+
+PVENDOR_EXECUTE_INT VendorX86ExecuteInt;
+
+VOID HalpInitializeX86DisplayAdapter()
+
+/*++
+
+Routine Description:
+
+ This function performs the initialization required to use an X86 emulator.
+ If a firmware level X86 emulator is available, then that emulator will be used.
+ Otherwise, we will default to using the emulator built into the HAL if it is
+ available.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ XM86_CONTEXT Context;
+ PSYSTEM_PARAMETER_BLOCK SystemParameterBlock = SYSTEM_BLOCK;
+ PCI_SLOT_NUMBER SlotNumber;
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR buffer[PCI_COMMON_HDR_LENGTH];
+ ULONG PciLength;
+ ULONG PciBus;
+ ULONG PciDevice;
+ ULONG PciFunction;
+ ULONG PciVideoAdapterFound;
+
+ //
+ // If EISA I/O Ports or EISA Memory could not be mapped, then leave the
+ // X86 BIOS Emulator disabled.
+ //
+
+ if (HalpEisaControlBase[0] == NULL || HalpEisaMemoryBase[0] == NULL) {
+ return;
+ }
+
+ //
+ // If Firmware level X86 Bios Emulator exists, then use that instead of the
+ // one built into the HAL.
+ //
+
+ if ((SystemParameterBlock->VendorVectorLength/4) >= 34) {
+
+ VendorX86ExecuteInt =
+ *(PVENDOR_EXECUTE_INT *)((ULONG)(SystemParameterBlock->VendorVector) + 34*4);
+
+ if (VendorX86ExecuteInt != NULL) {
+ HalpX86BiosInitialized = TRUE;
+ HalpUseFirmwareX86Emulator = TRUE;
+ HalpEnableInt10Calls = TRUE;
+ return;
+ }
+ }
+
+#ifdef ENABLE_HAL_X86_EMULATOR
+
+ //
+ // Attempt to initialize the Display Adapter by executing the Display Adapters
+ // initialization code in its BIOS. The standard for PC video adapters is for
+ // the BIOS to reside at 0xC000:0000 on the ISA bus.
+ //
+
+ PciVideoAdapterFound = FALSE;
+ PciData = (PPCI_COMMON_CONFIG) buffer;
+ PciBus = 0;
+ do {
+ for(PciDevice=0;PciDevice < PCI_MAX_DEVICES;PciDevice++) {
+ PciFunction = 0;
+ do {
+ SlotNumber.u.AsULONG = 0;
+ SlotNumber.u.bits.DeviceNumber = PciDevice;
+ SlotNumber.u.bits.FunctionNumber = PciFunction;
+
+ PciLength = HalGetBusData (
+ PCIConfiguration,
+ PciBus,
+ SlotNumber.u.AsULONG,
+ PciData,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (PciLength==0) {
+ break;
+ }
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ break;
+ }
+
+ if ( (PciData->BaseClass == 0x00 && PciData->SubClass == 0x01) ||
+ (PciData->BaseClass == 0x03 && PciData->SubClass == 0x00) ) {
+ PciVideoAdapterFound = TRUE;
+ break;
+ }
+ if (PciFunction == 0 && ((PciData->HeaderType & 0x80)==0)) {
+ break;
+ }
+ PciFunction++;
+ } while (PciFunction < PCI_MAX_FUNCTION);
+ if (PciLength==0 || PciVideoAdapterFound) {
+ break;
+ }
+ }
+ if (PciLength==0 || PciVideoAdapterFound) {
+ break;
+ }
+ PciBus++;
+ } while (PciLength!=0);
+
+ if (PciVideoAdapterFound) {
+ if (PciBus < HalpSecondPciBridgeBusNumber) {
+ x86BiosInitializeBios(HalpPciControlBase[0], HalpPciMemoryBase[0]);
+ } else {
+ x86BiosInitializeBios(HalpPciControlBase[1], HalpPciMemoryBase[1]);
+ }
+ Context.Eax = (PciBus<<8) | (PciDevice<<3) | PciFunction;
+ } else {
+ x86BiosInitializeBios(HalpEisaControlBase[0], HalpEisaMemoryBase[0]);
+ Context.Eax = 0;
+ }
+ HalpX86BiosInitialized = TRUE;
+
+ Context.Ecx = 0;
+ Context.Edx = 0;
+ Context.Ebx = 0;
+ Context.Ebp = 0;
+ Context.Esi = 0;
+ Context.Edi = 0;
+
+ if (x86BiosInitializeAdapter(0xc0000, &Context, NULL, NULL) != XM_SUCCESS) {
+ HalpEnableInt10Calls = FALSE;
+ return;
+ }
+
+ HalpEnableInt10Calls = TRUE;
+
+#endif
+}
+
+VOID HalpResetX86DisplayAdapter()
+
+/*++
+
+Routine Description:
+
+ This function invokes the X86 emulator to initialize a text mode 80x25 display.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ XM86_CONTEXT Context;
+
+ //
+ // Make INT 10 call to initialize 80x25 color text mode.
+ //
+
+ Context.Eax = 0x0003; // Function 0, Mode 3
+ Context.Ebx = 0;
+ Context.Ecx = 0;
+ Context.Edx = 0;
+ Context.Esi = 0;
+ Context.Edi = 0;
+ Context.Ebp = 0;
+
+ HalCallBios(0x10,
+ &Context.Eax,
+ &Context.Ebx,
+ &Context.Ecx,
+ &Context.Edx,
+ &Context.Esi,
+ &Context.Edi,
+ &Context.Ebp);
+}
+
+
+BOOLEAN
+HalCallBios (
+ IN ULONG BiosCommand,
+ IN OUT PULONG Eax,
+ IN OUT PULONG Ebx,
+ IN OUT PULONG Ecx,
+ IN OUT PULONG Edx,
+ IN OUT PULONG Esi,
+ IN OUT PULONG Edi,
+ IN OUT PULONG Ebp
+ )
+
+/*++
+
+Routine Description:
+
+ This function provides the platform specific interface between a device
+ driver and the execution of the x86 ROM bios code for the specified ROM
+ bios command.
+
+Arguments:
+
+ BiosCommand - Supplies the ROM bios command to be emulated.
+
+ Eax to Ebp - Supplies the x86 emulation context.
+
+Return Value:
+
+ A value of TRUE is returned if the specified function is executed.
+ Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ FIRMWARE_INT_ARGUMENTS Arguments;
+ XM86_CONTEXT Context;
+
+ //
+ // If the X86 BIOS Emulator has not been initialized then fail all INT calls.
+ //
+
+ if (HalpX86BiosInitialized == FALSE) {
+ return(FALSE);
+ }
+
+ //
+ // If the Video Adapter initialization failed, then we can not make INT 10 calls.
+ //
+
+ if (BiosCommand == 0x10 && HalpEnableInt10Calls == FALSE) {
+ return(FALSE);
+ }
+
+ if (HalpUseFirmwareX86Emulator == TRUE) {
+
+ //
+ // Make private vector call to the emulator in the firmware.
+ //
+
+ Arguments.pEAX = *Eax;
+ Arguments.pEBX = *Ebx;
+ Arguments.pECX = *Ecx;
+ Arguments.pEDX = *Edx;
+ Arguments.pESI = *Esi;
+ Arguments.pEDI = *Edi;
+ Arguments.pEBP = *Ebp;
+ Arguments.pES = 0;
+ Arguments.pDS = 0;
+ Arguments.pFlags = 0;
+
+ HalpAllocateArcsResources();
+
+ VendorX86ExecuteInt((USHORT)BiosCommand,&Arguments);
+
+ HalpFreeArcsResources();
+
+ *Eax = Arguments.pEAX;
+ *Ebx = Arguments.pEBX;
+ *Ecx = Arguments.pECX;
+ *Edx = Arguments.pEDX;
+ *Esi = Arguments.pESI;
+ *Edi = Arguments.pEDI;
+ *Ebp = Arguments.pEBP;
+
+ }
+ else {
+
+#ifdef ENABLE_HAL_X86_EMULATOR
+
+ //
+ // Make call to emulator build into HAL
+ //
+
+ Context.Eax = *Eax;
+ Context.Ebx = *Ebx;
+ Context.Ecx = *Ecx;
+ Context.Edx = *Edx;
+ Context.Esi = *Esi;
+ Context.Edi = *Edi;
+ Context.Ebp = *Ebp;
+
+ if (x86BiosExecuteInterrupt((UCHAR)BiosCommand, &Context, NULL, NULL) != XM_SUCCESS) {
+ return FALSE;
+ }
+
+ *Eax = Context.Eax;
+ *Ebx = Context.Ebx;
+ *Ecx = Context.Ecx;
+ *Edx = Context.Edx;
+ *Esi = Context.Esi;
+ *Edi = Context.Edi;
+ *Ebp = Context.Ebp;
+
+#endif
+
+ }
+
+ return TRUE;
+}
+
+#ifdef ENABLE_HAL_X86_EMULATOR
+
+ULONG
+x86BiosReadIoSpace (
+ IN XM_OPERATION_DATATYPE DataType,
+ IN USHORT PortNumber
+ )
+
+/*++
+
+Routine Description:
+
+ This function reads from emulated I/O space.
+
+Arguments:
+
+ DataType - Supplies the datatype for the read operation.
+
+ PortNumber - Supplies the port number in I/O space to read from.
+
+Return Value:
+
+ The value read from I/O space is returned as the function value.
+
+ N.B. If an aligned operation is specified, then the individual
+ bytes are read from the specified port one at a time and
+ assembled into the specified datatype.
+
+--*/
+
+{
+
+ ULONG Result;
+ ULONG PciBusNumber;
+ PCI_SLOT_NUMBER SlotNumber;
+
+ union {
+ PUCHAR Byte;
+ PUSHORT Word;
+ PULONG Long;
+ } u;
+
+ //
+ // Compute port address and read port.
+ //
+
+ //
+ // If PortNumber is in ISA Motherboard space, then overide the base address of
+ // the IO space with ISA space, otherwise, use the base address passed in on
+ // initialization.
+ //
+
+ if (PortNumber < 0x1000 && ((PortNumber & 0x3ff) < 0x100)) {
+ u.Long = (PULONG)((ULONG)HalpEisaControlBase[0] + PortNumber);
+ } else {
+ u.Long = (PULONG)(x86BiosIoSpace + PortNumber);
+ }
+
+ if (DataType == BYTE_DATA) {
+ Result = READ_REGISTER_UCHAR(u.Byte);
+
+ } else if (DataType == LONG_DATA) {
+
+ //
+ // If PortNumber is attempting to access the PCI config registers defined for X86 systems,
+ // intercept them, and make the appropriate HAL call to get the PCI confoguration data.
+ //
+
+ if (PortNumber == 0xcf8) {
+ Result = HalpPciConfigAddress;
+ } else if (PortNumber == 0xcfc && (HalpPciConfigAddress & 0x80000000)) {
+ PciBusNumber = (HalpPciConfigAddress >> 16) & 0xff;
+ SlotNumber.u.AsULONG = 0;
+ SlotNumber.u.bits.DeviceNumber = (HalpPciConfigAddress >> 11) & 0x1f;
+ SlotNumber.u.bits.FunctionNumber = (HalpPciConfigAddress >> 8) & 0x07;
+ HalGetBusDataByOffset (PCIConfiguration,
+ PciBusNumber,
+ SlotNumber.u.AsULONG,
+ &Result,
+ HalpPciConfigAddress & 0xfc,
+ 4
+ );
+
+ } else {
+ if (((ULONG)u.Long & 0x3) != 0) {
+ Result = (READ_REGISTER_UCHAR(u.Byte + 0)) |
+ (READ_REGISTER_UCHAR(u.Byte + 1) << 8) |
+ (READ_REGISTER_UCHAR(u.Byte + 2) << 16) |
+ (READ_REGISTER_UCHAR(u.Byte + 3) << 24);
+
+ } else {
+ Result = READ_REGISTER_ULONG(u.Long);
+ }
+ }
+
+ } else {
+ if (((ULONG)u.Word & 0x1) != 0) {
+ Result = (READ_REGISTER_UCHAR(u.Byte + 0)) |
+ (READ_REGISTER_UCHAR(u.Byte + 1) << 8);
+
+ } else {
+ Result = READ_REGISTER_USHORT(u.Word);
+ }
+ }
+
+ return Result;
+}
+
+VOID
+x86BiosWriteIoSpace (
+ IN XM_OPERATION_DATATYPE DataType,
+ IN USHORT PortNumber,
+ IN ULONG Value
+ )
+
+/*++
+
+Routine Description:
+
+ This function write to emulated I/O space.
+
+ N.B. If an aligned operation is specified, then the individual
+ bytes are written to the specified port one at a time.
+
+Arguments:
+
+ DataType - Supplies the datatype for the write operation.
+
+ PortNumber - Supplies the port number in I/O space to write to.
+
+ Value - Supplies the value to write.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG PciBusNumber;
+ PCI_SLOT_NUMBER SlotNumber;
+
+ union {
+ PUCHAR Byte;
+ PUSHORT Word;
+ PULONG Long;
+ } u;
+
+ //
+ // Compute port address and read port.
+ //
+
+ //
+ // If PortNumber is in ISA Motherboard space, then overide the base address of
+ // the IO space with ISA space, otherwise, use the base address passed in on
+ // initialization.
+ //
+
+ if (PortNumber < 0x1000 && ((PortNumber & 0x3ff) < 0x100)) {
+ u.Long = (PULONG)((ULONG)HalpEisaControlBase[0] + PortNumber);
+ } else {
+ u.Long = (PULONG)(x86BiosIoSpace + PortNumber);
+ }
+
+ if (DataType == BYTE_DATA) {
+ WRITE_REGISTER_UCHAR(u.Byte, (UCHAR)Value);
+
+ } else if (DataType == LONG_DATA) {
+
+ //
+ // If PortNumber is attempting to access the PCI config registers defined for X86 systems,
+ // intercept them, and make the appropriate HAL call to get the PCI confoguration data.
+ //
+
+ if (PortNumber == 0xcf8) {
+ HalpPciConfigAddress = Value;
+ } else if (PortNumber == 0xcfc) {
+ PciBusNumber = (HalpPciConfigAddress >> 16) & 0xff;
+ SlotNumber.u.AsULONG = 0;
+ SlotNumber.u.bits.DeviceNumber = (HalpPciConfigAddress >> 11) & 0x1f;
+ SlotNumber.u.bits.FunctionNumber = (HalpPciConfigAddress >> 8) & 0x07;
+ HalSetBusDataByOffset (PCIConfiguration,
+ PciBusNumber,
+ SlotNumber.u.AsULONG,
+ &Value,
+ HalpPciConfigAddress & 0xfc,
+ 4
+ );
+
+ } else {
+ if (((ULONG)u.Long & 0x3) != 0) {
+ WRITE_REGISTER_UCHAR(u.Byte + 0, (UCHAR)(Value));
+ WRITE_REGISTER_UCHAR(u.Byte + 1, (UCHAR)(Value >> 8));
+ WRITE_REGISTER_UCHAR(u.Byte + 2, (UCHAR)(Value >> 16));
+ WRITE_REGISTER_UCHAR(u.Byte + 3, (UCHAR)(Value >> 24));
+
+ } else {
+ WRITE_REGISTER_ULONG(u.Long, Value);
+ }
+ }
+
+ } else {
+ if (((ULONG)u.Word & 0x1) != 0) {
+ WRITE_REGISTER_UCHAR(u.Byte + 0, (UCHAR)(Value));
+ WRITE_REGISTER_UCHAR(u.Byte + 1, (UCHAR)(Value >> 8));
+
+ } else {
+ WRITE_REGISTER_USHORT(u.Word, (USHORT)Value);
+ }
+ }
+
+ return;
+}
+
+#endif
diff --git a/private/ntos/nthals/halflex/xxbeep.c b/private/ntos/nthals/halflex/xxbeep.c
new file mode 100644
index 000000000..b3beef50e
--- /dev/null
+++ b/private/ntos/nthals/halflex/xxbeep.c
@@ -0,0 +1,125 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxbeep.c
+
+Abstract:
+
+ This module implements the HAL speaker "beep" routines for a MIPS
+ system.
+
+Author:
+
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+
+BOOLEAN
+HalMakeBeep(
+ IN ULONG Frequency
+ )
+
+/*++
+
+Routine Description:
+
+ This function sets the frequency of the speaker, causing it to sound a
+ tone. The tone will sound until the speaker is explicitly turned off,
+ so the driver is responsible for controlling the duration of the tone.
+
+Arguments:
+
+ Frequency - Supplies the frequency of the desired tone. A frequency of
+ 0 means the speaker should be shut off.
+
+Return Value:
+
+ TRUE - Operation was successful (frequency within range or zero).
+ FALSE - Operation was unsuccessful (frequency was out of range).
+ Current tone (if any) is unchanged.
+
+--*/
+
+{
+ KIRQL oldIrql;
+ NMI_STATUS NmiStatus;
+ PEISA_CONTROL controlBase;
+ TIMER_CONTROL timerControl;
+ ULONG newCount;
+
+ controlBase = HalpEisaControlBase[0];
+
+ KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
+
+ //
+ // Stop the speaker.
+ //
+
+ *((PUCHAR) &NmiStatus) = READ_REGISTER_UCHAR(&controlBase->NmiStatus);
+
+ NmiStatus.SpeakerGate = 0;
+ NmiStatus.SpeakerData = 0;
+
+ WRITE_REGISTER_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus));
+
+ if (Frequency == 0) {
+ KeLowerIrql(oldIrql);
+ return(TRUE);
+ }
+
+ //
+ // Calculate the new counter value.
+ //
+
+ newCount = (AT_BUS_OSC/12) / Frequency;
+
+ //
+ // The new count must be less than 16 bits in value.
+ //
+
+ if (newCount >= 0x10000) {
+ KeLowerIrql(oldIrql);
+ return(FALSE);
+ }
+
+ //
+ // Set the speaker timer to the correct mode.
+ //
+
+ timerControl.BcdMode = 0;
+ timerControl.Mode = TM_SQUARE_WAVE;
+ timerControl.SelectByte = SB_LSB_THEN_MSB;
+ timerControl.SelectCounter = SELECT_COUNTER_2;
+
+ WRITE_REGISTER_UCHAR(&controlBase->CommandMode1, *((PUCHAR) &timerControl));
+
+ //
+ // Set the speaker timer to the correct mode.
+ //
+
+ WRITE_REGISTER_UCHAR(&controlBase->SpeakerTone, (UCHAR)(newCount & 0xff));
+ WRITE_REGISTER_UCHAR(&controlBase->SpeakerTone, (UCHAR)(newCount >> 8));
+
+ //
+ // Start the speaker.
+ //
+
+ NmiStatus.SpeakerGate = 1;
+ NmiStatus.SpeakerData = 1;
+
+ WRITE_REGISTER_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus));
+ KeLowerIrql(oldIrql);
+ return(TRUE);
+}
diff --git a/private/ntos/nthals/halflex/xxclock.c b/private/ntos/nthals/halflex/xxclock.c
new file mode 100644
index 000000000..3a05b3ac1
--- /dev/null
+++ b/private/ntos/nthals/halflex/xxclock.c
@@ -0,0 +1,174 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ xxclock.c
+
+Abstract:
+
+
+ This module implements the function necesssary to change the clock
+ interrupt rate.
+
+Author:
+
+ David N. Cutler (davec) 7-Feb-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+//
+// Define clock count and time table.
+//
+
+typedef struct _COUNT_ENTRY {
+ ULONG Count;
+ ULONG Time;
+} COUNT_ENTRY, *PCOUNT_ENTRY;
+
+COUNT_ENTRY TimeTable[] = {
+ {1197, 10032},
+ {2394, 20064},
+ {3591, 30096},
+ {4767, 39952},
+ {5964, 49984},
+ {7161, 60016},
+ {8358, 70048},
+ {9555, 80080},
+ {10731, 89936},
+ {11928, 99968}
+ };
+
+//
+// Define global data used to communicate new clock rates to the clock
+// interrupt service routine.
+//
+
+ULONG HalpCurrentTimeIncrement;
+ULONG HalpNextIntervalCount;
+ULONG HalpNextTimeIncrement;
+ULONG HalpNewTimeIncrement;
+
+VOID
+HalpProgramIntervalTimer(
+ IN ULONG IntervalCount
+ )
+
+/*++
+
+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.
+
+Arguments:
+
+ IntervalCount - Supplies cound value to be placed in the timer/counter.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+
+ PEISA_CONTROL controlBase;
+ TIMER_CONTROL timerControl;
+
+ //
+ // Set the system clock timer to the correct mode.
+ //
+
+ timerControl.BcdMode = 0;
+ timerControl.Mode = TM_SQUARE_WAVE;
+ timerControl.SelectByte = SB_LSB_THEN_MSB;
+ timerControl.SelectCounter = SELECT_COUNTER_0;
+
+ controlBase = HalpEisaControlBase[0];
+
+ WRITE_REGISTER_UCHAR(&controlBase->CommandMode1, *((PUCHAR) &timerControl));
+
+ //
+ // Set the system clock timer to the correct frequency.
+ //
+
+ WRITE_REGISTER_UCHAR(&controlBase->Timer1, (UCHAR)IntervalCount);
+ WRITE_REGISTER_UCHAR(&controlBase->Timer1, (UCHAR)(IntervalCount >> 8));
+}
+
+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.
+
+ N.B. This function is only executed on the processor that keeps the
+ system time.
+
+Arguments:
+
+ DesiredIncrement - Supplies desired number of 100ns units between clock
+ interrupts.
+
+Return Value:
+
+ The actual time increment in 100ns units.
+
+--*/
+
+{
+
+ ULONG Index;
+ KIRQL OldIrql;
+
+ //
+ // 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);
+
+ //
+ // The new clock count value is selected from a precomputed table of
+ // count/time pairs. The values in the table were selected for their
+ // accuracy and closeness to the values of 1ms, 2ms, 3ms, etc. to 10ms.
+ //
+ // N.B. The NT executive guarantees that this function will never
+ // be called with the desired incrment less than the minimum
+ // increment or greater than the maximum increment.
+ //
+
+ for (Index = 0; Index < sizeof(TimeTable) / sizeof(COUNT_ENTRY); Index += 1) {
+ if (DesiredIncrement <= TimeTable[Index].Time) {
+ break;
+ }
+ }
+
+ if (DesiredIncrement < TimeTable[Index].Time) {
+ Index -= 1;
+ }
+
+ HalpNextIntervalCount = TimeTable[Index].Count;
+ HalpNewTimeIncrement = TimeTable[Index].Time;
+ KeLowerIrql(OldIrql);
+ return HalpNewTimeIncrement;
+}
diff --git a/private/ntos/nthals/halflex/xxdisp.c b/private/ntos/nthals/halflex/xxdisp.c
new file mode 100644
index 000000000..2722c3223
--- /dev/null
+++ b/private/ntos/nthals/halflex/xxdisp.c
@@ -0,0 +1,293 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxdisp.c
+
+Abstract:
+
+ This module implements the HAL display initialization and output routines
+ for a MIPS R3000 or R4000 Jazz system.
+
+Author:
+
+ Andre Vachon (andreva) 09-May-1992
+ David N. Cutler (davec) 27-Apr-1991
+ Michael D. Kinney 30-Apr-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+#define CSI 0x9b
+#define MAX_DISPLAY_BUFFER 256
+
+int sprintf();
+
+extern ULONG IoSpaceAlreadyMapped;
+
+static UCHAR DisplayInitializationString[] = {CSI,'3','7',';','4','4','m',CSI,'2','J',0};
+static UCHAR CarriageReturnString[] = {10,13,0};
+
+static ULONG HalOwnsDisplay = FALSE;
+static ULONG DisplayFile;
+
+static UCHAR DisplayBuffer[MAX_DISPLAY_BUFFER];
+static ULONG DisplayBufferInitialized = FALSE;
+
+PHAL_RESET_DISPLAY_PARAMETERS HalpResetDisplayParameters;
+
+
+VOID
+HalAcquireDisplayOwnership (
+ IN PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters
+ )
+
+/*++
+
+Routine Description:
+
+ This routine switches ownership of the display away from the HAL to
+ the system display driver. It is called when the system has reached
+ a point during bootstrap where it is self supporting and can output
+ its own messages. Once ownership has passed to the system display
+ driver any attempts to output messages using HalDisplayString must
+ result in ownership of the display reverting to the HAL and the
+ display hardware reinitialized for use by the HAL.
+
+Arguments:
+
+ ResetDisplayParameters - if non-NULL the address of a function
+ the hal can call to reset the video card. The function returns
+ TRUE if the display was reset.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ HalpAllocateArcsResources();
+ ArcClose(DisplayFile);
+ HalpFreeArcsResources();
+ HalOwnsDisplay = FALSE;
+ HalpResetDisplayParameters = ResetDisplayParameters;
+ return;
+}
+
+
+VOID
+HalDisplayString (
+ PUCHAR String
+ )
+
+/*++
+
+Routine Description:
+
+ This routine displays a character string on the display screen.
+
+Arguments:
+
+ String - Supplies a pointer to the characters that are to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG Count;
+ ULONG i;
+
+ if (DisplayBufferInitialized==FALSE) {
+ DisplayBufferInitialized = TRUE;
+ strcpy(DisplayBuffer,"");
+ }
+
+ if (IoSpaceAlreadyMapped == FALSE) {
+ if ((strlen(DisplayBuffer)+strlen(String)) < MAX_DISPLAY_BUFFER) {
+ strcat(DisplayBuffer,String);
+ }
+ return;
+ }
+
+ if (HalOwnsDisplay==FALSE) {
+
+ if (HalpResetDisplayParameters != NULL) {
+ (HalpResetDisplayParameters)(80,25);
+ }
+
+ HalpResetX86DisplayAdapter();
+
+ HalpAllocateArcsResources();
+
+ ArcOpen(ArcGetEnvironmentVariable("ConsoleOut"),ArcOpenWriteOnly,&DisplayFile);
+ ArcWrite(DisplayFile,DisplayInitializationString,strlen(DisplayInitializationString),&Count);
+ if (strlen(DisplayBuffer)!=0) {
+
+ for(i=0;i<strlen(DisplayBuffer);i++) {
+ switch (DisplayBuffer[i]) {
+ case '\n' : ArcWrite(DisplayFile,CarriageReturnString,strlen(CarriageReturnString),&Count);
+ break;
+ default : ArcWrite(DisplayFile,&(DisplayBuffer[i]),1,&Count);
+ break;
+ }
+ }
+
+ strcpy(DisplayBuffer,"");
+ }
+
+ HalpFreeArcsResources();
+
+ HalOwnsDisplay=TRUE;
+
+ }
+
+ HalpAllocateArcsResources();
+
+ for(i=0;i<strlen(String);i++) {
+ switch (String[i]) {
+ case '\n' : ArcWrite(DisplayFile,CarriageReturnString,strlen(CarriageReturnString),&Count);
+ break;
+ default : ArcWrite(DisplayFile,&(String[i]),1,&Count);
+ break;
+ }
+ }
+
+ HalpFreeArcsResources();
+
+ return;
+}
+
+
+VOID
+HalQueryDisplayParameters (
+ OUT PULONG WidthInCharacters,
+ OUT PULONG HeightInLines,
+ OUT PULONG CursorColumn,
+ OUT PULONG CursorRow
+ )
+
+/*++
+
+Routine Description:
+
+ This routine return information about the display area and current
+ cursor position.
+
+Arguments:
+
+ WidthInCharacter - Supplies a pointer to a varible that receives
+ the width of the display area in characters.
+
+ HeightInLines - Supplies a pointer to a variable that receives the
+ height of the display area in lines.
+
+ CursorColumn - Supplies a pointer to a variable that receives the
+ current display column position.
+
+ CursorRow - Supplies a pointer to a variable that receives the
+ current display row position.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ARC_DISPLAY_STATUS *DisplayStatus;
+
+ //
+ // Get the display parameter values and return.
+ //
+
+ //
+ // If the HAL does not already own the display, then print an empty string.
+ // This guarantees that the file descriptor DisplayFile is valid.
+ //
+
+ if (!HalOwnsDisplay) {
+ HalDisplayString("");
+ }
+
+ //
+ // Make firmware call to get the display's current status
+ //
+
+ HalpAllocateArcsResources();
+
+ DisplayStatus = ArcGetDisplayStatus(DisplayFile);
+
+ HalpFreeArcsResources();
+
+ *WidthInCharacters = DisplayStatus->CursorMaxXPosition;
+ *HeightInLines = DisplayStatus->CursorMaxYPosition;
+ *CursorColumn = DisplayStatus->CursorXPosition;
+ *CursorRow = DisplayStatus->CursorYPosition;
+
+ return;
+}
+
+VOID
+HalSetDisplayParameters (
+ IN ULONG CursorColumn,
+ IN ULONG CursorRow
+ )
+
+/*++
+
+Routine Description:
+
+ This routine set the current cursor position on the display area.
+
+Arguments:
+
+ CursorColumn - Supplies the new display column position.
+
+ CursorRow - Supplies a the new display row position.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ CHAR SetCursorPositionString[20];
+ ULONG Count;
+
+ //
+ // If the HAL does not already own the display, then print an empty string.
+ // This guarantees that the file descriptor DisplayFile is valid.
+ //
+
+ if (!HalOwnsDisplay) {
+ HalDisplayString("");
+ }
+
+ //
+ // Build ANSI sequence to set the cursor position.
+ //
+
+ sprintf(SetCursorPositionString,"%c%d;%dH",CSI,CursorRow,CursorColumn);
+
+ HalpAllocateArcsResources();
+
+ ArcWrite(DisplayFile,SetCursorPositionString,strlen(SetCursorPositionString),&Count);
+
+ HalpFreeArcsResources();
+
+ return;
+}
diff --git a/private/ntos/nthals/halflex/xxebsup.c b/private/ntos/nthals/halflex/xxebsup.c
new file mode 100644
index 000000000..203c21720
--- /dev/null
+++ b/private/ntos/nthals/halflex/xxebsup.c
@@ -0,0 +1,2375 @@
+/*++
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ ixhwsup.c
+
+Abstract:
+
+ This module contains the IoXxx routines for the NT I/O system that
+ are hardware dependent. Were these routines not hardware dependent,
+ they would reside in the iosubs.c module.
+
+Author:
+
+ Darryl E. Havens (darrylh) 11-Apr-1990
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+//
+// Define save area for EISA adapter objects.
+//
+
+PADAPTER_OBJECT HalpEisaAdapter[MAX_EISA_BUSSES][MAX_DMA_CHANNELS_PER_EISA_BUS];
+
+UCHAR HalpEisaInterrupt1Mask[MAX_EISA_BUSSES];
+UCHAR HalpEisaInterrupt2Mask[MAX_EISA_BUSSES];
+UCHAR HalpEisaInterrupt1Level[MAX_EISA_BUSSES];
+UCHAR HalpEisaInterrupt2Level[MAX_EISA_BUSSES];
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN PVOID AdapterBaseVa,
+ IN PVOID ChannelNumber
+ );
+
+
+VOID
+HalpCopyBufferMap(
+ IN PMDL Mdl,
+ IN PTRANSLATION_ENTRY translationEntry,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine copies the specified data between the user buffer and the
+ map register buffer. First, the user buffer is mapped, if need be then
+ the data is copied. Finally, the user buffer will be unmapped, if need be.
+
+Arguments:
+
+ Mdl - Pointer to the Mdl that describes the pages of memory that are
+ being read or written.
+
+ translationEntry - The address of the base map register that has been
+ allocated to the device driver for use in mapping the xfer.
+
+ CurrentVa - Current Virtual Address in the buffer described by the Mdl
+ that the transfer is being done to or from.
+
+ Length - The length of the transfer. This determines the number of map
+ registers that need to be written to map the transfer.
+
+ WriteToDevice - A Boolean value that indicates whether this is a write
+ to the device from memory of vise-versa.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+
+ PCCHAR bufferAddress;
+ PCCHAR mapAddress;
+
+ //
+ // Get the system address of the MDL.
+ //
+
+ bufferAddress = MmGetSystemAddressForMdl(Mdl);
+
+ //
+ // Calculate the actual start of the buffer based on the system VA and
+ // the current VA.
+ //
+
+ bufferAddress += (PCCHAR) CurrentVa - (PCCHAR) MmGetMdlVirtualAddress(Mdl);
+
+ mapAddress = (PCCHAR) translationEntry->VirtualAddress +
+ BYTE_OFFSET(CurrentVa);
+
+ //
+ // Flush all writes off chip
+ //
+
+ HalpMb();
+ HalpMb();
+
+ //
+ // Copy the data between the user buffer and the map buffer.
+ //
+
+ if (WriteToDevice) {
+
+ RtlMoveMemory( mapAddress, bufferAddress, Length);
+
+ } else {
+
+ RtlMoveMemory ( bufferAddress, mapAddress, Length);
+
+ }
+
+ //
+ // Flush all writes off chip
+ //
+
+ HalpMb();
+ HalpMb();
+}
+
+
+NTSTATUS
+HalAllocateAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PWAIT_CONTEXT_BLOCK Wcb,
+ IN ULONG NumberOfMapRegisters,
+ IN PDRIVER_CONTROL ExecutionRoutine
+ )
+/*++
+
+Routine Description:
+
+ This routine allocates the adapter channel specified by the adapter object.
+ This is accomplished by placing the device object of the driver that wants
+ to allocate the adapter on the adapter's queue. If the queue is already
+ "busy", then the adapter has already been allocated, so the device object
+ is simply placed onto the queue and waits until the adapter becomes free.
+
+ Once the adapter becomes free (or if it already is), then the driver's
+ execution routine is invoked.
+
+ Also, a number of map registers may be allocated to the driver by specifying
+ a non-zero value for NumberOfMapRegisters. Then the map register must be
+ allocated from the master adapter. Once there are a sufficient number of
+ map registers available, then the execution routine is called and the
+ base address of the allocated map registers in the adapter is also passed
+ to the driver's execution routine.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+
+ Wcb - Supplies a wait context block for saving the allocation parameters.
+ The DeviceObject, CurrentIrp and DeviceContext should be initalized.
+
+ NumberOfMapRegisters - The number of map registers that are to be allocated
+ from the channel, if any.
+
+ ExecutionRoutine - The address of the driver's execution routine that is
+ invoked once the adapter channel (and possibly map registers) have been
+ allocated.
+
+Return Value:
+
+ Returns STATUS_SUCESS unless too many map registers are requested.
+
+Notes:
+
+ Note that this routine MUST be invoked at DISPATCH_LEVEL or above.
+
+--*/
+{
+
+ PADAPTER_OBJECT MasterAdapter;
+ BOOLEAN Busy = FALSE;
+ IO_ALLOCATION_ACTION Action;
+ KIRQL Irql;
+ LONG MapRegisterNumber;
+ BOOLEAN MappingRequired;
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ //
+ // Initialize the device object's wait context block in case this device
+ // must wait before being able to allocate the adapter.
+ //
+
+ Wcb->DeviceRoutine = ExecutionRoutine;
+ Wcb->NumberOfMapRegisters = NumberOfMapRegisters;
+
+ //
+ // Allocate the adapter object for this particular device. If the
+ // adapter cannot be allocated because it has already been allocated
+ // to another device, then return to the caller now; otherwise,
+ // continue.
+ //
+
+ if (!KeInsertDeviceQueue( &AdapterObject->ChannelWaitQueue,
+ &Wcb->WaitQueueEntry )) {
+
+ //
+ // Save the parameters in case there are not enough map registers.
+ //
+
+ AdapterObject->NumberOfMapRegisters = NumberOfMapRegisters;
+ AdapterObject->CurrentWcb = Wcb;
+
+ //
+ // The adapter was not busy so it has been allocated. Now check
+ // to see whether this driver wishes to allocate any map registers.
+ // Ensure that this adapter has enough total map registers
+ // to satisfy the request.
+ //
+
+ MappingRequired = FALSE;
+
+ if (NumberOfMapRegisters != 0 && AdapterObject->NeedsMapRegisters) {
+ MappingRequired = TRUE;
+ }
+
+ if (MappingRequired) {
+
+ //
+ // Lock the map register bit map and the adapter queue in the
+ // master adapter object. The channel structure offset is used as
+ // a hint for the register search.
+ //
+
+ if (NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ IoFreeAdapterChannel(AdapterObject);
+
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ MapRegisterNumber = -1;
+
+ if (IsListEmpty( &MasterAdapter->AdapterQueue)) {
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ NumberOfMapRegisters,
+ 0
+ );
+ }
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the master adapter where is will wait until some registers
+ // are deallocated.
+ //
+
+ InsertTailList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+ Busy = 1;
+
+ } else {
+
+ //
+ // Calculate the map register base from the allocated map
+ // register and base of the master adapter object.
+ //
+
+ AdapterObject->MapRegisterBase = (PVOID)((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ } else {
+
+ AdapterObject->MapRegisterBase = NULL_MAP_REGISTER_BASE;
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+
+ //
+ // If there were either enough map registers available or no map
+ // registers needed to be allocated, invoke the driver's execution
+ // routine now.
+ //
+
+ if (!Busy) {
+
+ AdapterObject->CurrentWcb = Wcb;
+ Action = ExecutionRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the driver would like to have the adapter deallocated,
+ // then release the adapter object.
+ //
+
+ if (Action == DeallocateObject) {
+
+ IoFreeAdapterChannel( AdapterObject );
+
+ } else if (Action == DeallocateObjectKeepRegisters) {
+
+ //
+ // Set the NumberOfMapRegisters = 0 in the adapter object.
+ // This will keep IoFreeAdapterChannel from freeing the
+ // registers. After this it is the driver's responsiblity to
+ // keep track of the number of map registers.
+ //
+
+ AdapterObject->NumberOfMapRegisters = 0;
+ IoFreeAdapterChannel(AdapterObject);
+
+ }
+ }
+ }
+ return(STATUS_SUCCESS);
+}
+
+PVOID
+HalAllocateCrashDumpRegisters(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ This routine is called during the crash dump disk driver's initialization
+ to allocate a number map registers permanently.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+ NumberOfMapRegisters - Number of map registers requested. This field is
+ updated with the number of registers allocated in the event that less
+ were available than requested.
+
+Return Value:
+
+ Returns STATUS_SUCESS if map registers allocated.
+
+--*/
+{
+ PADAPTER_OBJECT MasterAdapter;
+ ULONG MapRegisterNumber;
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ //
+ // Check to see whether this driver needs to allocate any map registers.
+ //
+
+ if (AdapterObject->NeedsMapRegisters) {
+
+ //
+ // Ensure that this adapter has enough total map registers to satisfy
+ // the request.
+ //
+
+ if (*NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ return NULL;
+ }
+
+ //
+ // Attempt to allocate the required number of map registers w/o
+ // affecting those registers that were allocated when the system
+ // crashed.
+ //
+
+ MapRegisterNumber = (ULONG)-1;
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ *NumberOfMapRegisters,
+ 0
+ );
+
+ if (MapRegisterNumber == (ULONG)-1) {
+
+ //
+ // Not enough free map registers were found, so they were busy
+ // being used by the system when it crashed. Force the appropriate
+ // number to be "allocated" at the base by simply overjamming the
+ // bits and return the base map register as the start.
+ //
+
+ RtlSetBits(
+ MasterAdapter->MapRegisters,
+ 0,
+ *NumberOfMapRegisters
+ );
+ MapRegisterNumber = 0;
+
+ }
+
+ //
+ // Calculate the map register base from the allocated map
+ // register and base of the master adapter object.
+ //
+
+ AdapterObject->MapRegisterBase = (PVOID)((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+ }
+
+ } else {
+
+ AdapterObject->MapRegisterBase = NULL_MAP_REGISTER_BASE;
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+
+ return AdapterObject->MapRegisterBase;
+}
+
+PADAPTER_OBJECT
+HalGetAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescriptor,
+ OUT PULONG NumberOfMapRegisters
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the appropriate adapter object for the device defined
+ in the device description structure. This code works for Isa and Eisa
+ systems.
+
+Arguments:
+
+ DeviceDescriptor - Supplies a description of the deivce.
+
+ NumberOfMapRegisters - Returns the maximum number of map registers which
+ may be allocated by the device driver.
+
+Return Value:
+
+ A pointer to the requested adapter object or NULL if an adapter could not
+ be created.
+
+--*/
+
+{
+ PADAPTER_OBJECT adapterObject;
+ PVOID adapterBaseVa;
+ UCHAR channelNumber;
+ ULONG controllerNumber;
+ DMA_EXTENDED_MODE extendedMode;
+ UCHAR adapterMode;
+ ULONG numberOfMapRegisters;
+ BOOLEAN useChannel;
+ BOOLEAN eisaSystem;
+ ULONG maximumLength;
+
+ eisaSystem = HalpBusType == UNIFLEX_MACHINE_TYPE_EISA ? TRUE : FALSE;
+
+ //
+ // Determine if the the channel number is important. Master cards on
+ // Eisa and Mca do not use a channel number.
+ //
+
+ if (DeviceDescriptor->InterfaceType != Isa &&
+ DeviceDescriptor->Master) {
+
+ useChannel = FALSE;
+ } else {
+
+ useChannel = TRUE;
+ }
+
+ //
+ // Limit the maximum length to 2 GB this is done so that the BYTES_TO_PAGES
+ // macro works correctly.
+ //
+
+ maximumLength = DeviceDescriptor->MaximumLength & 0x7fffffff;
+
+ //
+ // Channel 4 cannot be used since it is used for chaining. Return null if
+ // it is requested.
+ //
+
+ if (DeviceDescriptor->DmaChannel == 4 && useChannel) {
+
+ return(NULL);
+ }
+
+ //
+ // Determine the number of map registers required based on the maximum
+ // transfer length, up to a maximum number.
+ //
+
+ numberOfMapRegisters = BYTES_TO_PAGES(maximumLength)
+ + 1;
+
+ //
+ // If the device is an ISA device, then limit the number of map registers.
+ //
+
+ if (DeviceDescriptor->InterfaceType == Isa) {
+ numberOfMapRegisters = numberOfMapRegisters > MAXIMUM_ISA_MAP_REGISTER ?
+ MAXIMUM_ISA_MAP_REGISTER : numberOfMapRegisters;
+ }
+
+ //
+ // Make sure there where enough registers allocated initalize to support
+ // this size relaibly. This implies there must be to chunks equal to
+ // the allocatd size. This is only a problem on Isa systems where the
+ // map buffers cannot cross 64KB boundtires.
+ //
+
+ if (!eisaSystem &&
+ numberOfMapRegisters > HalpMapBufferSize / (PAGE_SIZE * 2)) {
+
+ numberOfMapRegisters = (HalpMapBufferSize / (PAGE_SIZE * 2));
+ }
+
+ //
+ // If the device is not a master then it only needs one map register
+ // and does scatter/Gather.
+ //
+
+ if (DeviceDescriptor->ScatterGather && !DeviceDescriptor->Master) {
+
+ numberOfMapRegisters = 1;
+ }
+
+ //
+ // Set the channel number number.
+ //
+
+ channelNumber = (UCHAR)(DeviceDescriptor->DmaChannel & 0x03);
+
+ //
+ // Set the adapter base address to the Base address register and controller
+ // number.
+ //
+
+ if (!(DeviceDescriptor->DmaChannel & 0x04)) {
+
+ controllerNumber = 1;
+ adapterBaseVa = (PVOID) &((PEISA_CONTROL) HalpEisaControlBase[DeviceDescriptor->BusNumber])->Dma1BasePort;
+
+ } else {
+
+ controllerNumber = 2;
+ adapterBaseVa = &((PEISA_CONTROL) HalpEisaControlBase[DeviceDescriptor->BusNumber])->Dma2BasePort;
+
+ }
+
+ //
+ // Determine if a new adapter object is necessary. If so then allocate it.
+ //
+
+ if (useChannel && HalpEisaAdapter[DeviceDescriptor->BusNumber][DeviceDescriptor->DmaChannel] != NULL) {
+
+ adapterObject = HalpEisaAdapter[DeviceDescriptor->BusNumber][DeviceDescriptor->DmaChannel];
+
+ if (adapterObject->NeedsMapRegisters) {
+
+ if (numberOfMapRegisters > adapterObject->MapRegistersPerChannel) {
+
+ adapterObject->MapRegistersPerChannel = numberOfMapRegisters;
+ }
+ }
+
+ } else {
+
+ //
+ // Allocate an adapter object.
+ //
+
+ adapterObject = (PADAPTER_OBJECT) HalpAllocateAdapter(
+ numberOfMapRegisters,
+ adapterBaseVa,
+ NULL
+ );
+
+ if (adapterObject == NULL) {
+
+ return(NULL);
+
+ }
+
+ if (useChannel) {
+
+ HalpEisaAdapter[DeviceDescriptor->BusNumber][DeviceDescriptor->DmaChannel] = adapterObject;
+
+ }
+
+ //
+ // Set the maximum number of map registers for this channel bus on
+ // the number requested and the type of device.
+ //
+
+ if (numberOfMapRegisters) {
+
+ //
+ // The speicified number of registers are actually allowed to be
+ // allocated.
+ //
+
+ adapterObject->MapRegistersPerChannel = numberOfMapRegisters;
+
+ //
+ // Increase the commitment for the map registers.
+ //
+
+ if (DeviceDescriptor->Master) {
+
+ //
+ // Master I/O devices use several sets of map registers double
+ // their commitment.
+ //
+
+ MasterAdapterObject->CommittedMapRegisters +=
+ numberOfMapRegisters * 2;
+
+ } else {
+
+ MasterAdapterObject->CommittedMapRegisters +=
+ numberOfMapRegisters;
+
+ }
+
+ adapterObject->NeedsMapRegisters = TRUE;
+
+ } else {
+
+ //
+ // No real map registers were allocated. If this is a master
+ // device, then the device can have as may registers as it wants.
+ //
+
+ adapterObject->NeedsMapRegisters = FALSE;
+
+ if (DeviceDescriptor->Master) {
+
+ adapterObject->MapRegistersPerChannel = BYTES_TO_PAGES(
+ maximumLength
+ )
+ + 1;
+
+ } else {
+
+ //
+ // The device only gets one register. It must call
+ // IoMapTransfer repeatedly to do a large transfer.
+ //
+
+ adapterObject->MapRegistersPerChannel = 1;
+ }
+ }
+ }
+
+ adapterObject->ScatterGather = DeviceDescriptor->ScatterGather;
+ *NumberOfMapRegisters = adapterObject->MapRegistersPerChannel;
+
+ //
+ // If the device is a 32 bit bus mastering device, then set field in AdapterObject.
+ //
+
+ if (DeviceDescriptor->InterfaceType == PCIBus && DeviceDescriptor->Master) {
+ adapterObject->NeedsMapRegisters = FALSE;
+ }
+
+ //
+ // If the channel number is not used then we are finished. The rest of
+ // the work deals with channels.
+ //
+
+ if (!useChannel) {
+ return(adapterObject);
+ }
+
+ //
+ // Setup the pointers to all the random registers.
+ //
+
+ adapterObject->BusNumber = DeviceDescriptor->BusNumber;
+
+ adapterObject->ChannelNumber = channelNumber;
+
+ if (controllerNumber == 1) {
+
+ switch (channelNumber) {
+
+ case 0:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel0;
+ break;
+
+ case 1:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel1;
+ break;
+
+ case 2:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel2;
+ break;
+
+ case 3:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel3;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 1;
+
+ //
+ // Save the extended mode register address.
+ //
+
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpEisaControlBase[DeviceDescriptor->BusNumber])->Dma1ExtendedModePort;
+
+ } else {
+
+ switch (channelNumber) {
+ case 1:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel5;
+ break;
+
+ case 2:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel6;
+ break;
+
+ case 3:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel7;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 2;
+
+ //
+ // Save the extended mode register address.
+ //
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpEisaControlBase[DeviceDescriptor->BusNumber])->Dma2ExtendedModePort;
+
+ }
+
+
+ adapterObject->Width16Bits = FALSE;
+
+ if (eisaSystem) {
+
+ //
+ // Initialzie the extended mode port.
+ //
+
+ *((PUCHAR) &extendedMode) = 0;
+ extendedMode.ChannelNumber = channelNumber;
+
+ switch (DeviceDescriptor->DmaSpeed) {
+ case Compatible:
+ extendedMode.TimingMode = COMPATIBLITY_TIMING;
+ break;
+
+ case TypeA:
+ extendedMode.TimingMode = TYPE_A_TIMING;
+ break;
+
+ case TypeB:
+ extendedMode.TimingMode = TYPE_B_TIMING;
+ break;
+
+ case TypeC:
+ extendedMode.TimingMode = BURST_TIMING;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+
+ return(NULL);
+
+ }
+
+ switch (DeviceDescriptor->DmaWidth) {
+ case Width8Bits:
+ extendedMode.TransferSize = BY_BYTE_8_BITS;
+ break;
+
+ case Width16Bits:
+ extendedMode.TransferSize = BY_BYTE_16_BITS;
+
+ //
+ // Note Width16bits should not be set here because there is no need
+ // to shift the address and the transfer count.
+ //
+
+ break;
+
+ case Width32Bits:
+ extendedMode.TransferSize = BY_BYTE_32_BITS;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+
+ return(NULL);
+
+ }
+
+ WRITE_REGISTER_UCHAR( adapterBaseVa, *((PUCHAR) &extendedMode));
+
+ } else if (!DeviceDescriptor->Master) {
+
+ switch (DeviceDescriptor->DmaWidth) {
+ case Width8Bits:
+
+ //
+ // The channel must use controller 1.
+ //
+
+ if (controllerNumber != 1) {
+ ObDereferenceObject( adapterObject );
+
+ return(NULL);
+ }
+
+ break;
+
+ case Width16Bits:
+
+ //
+ // The channel must use controller 2.
+ //
+
+ if (controllerNumber != 2) {
+ ObDereferenceObject( adapterObject );
+
+ return(NULL);
+ }
+
+ adapterObject->Width16Bits = TRUE;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+
+ return(NULL);
+
+ }
+ }
+
+ //
+ // Initialize the adapter mode register value to the correct parameters,
+ // and save them in the adapter object.
+ //
+
+ adapterMode = 0;
+ ((PDMA_EISA_MODE) &adapterMode)->Channel = adapterObject->ChannelNumber;
+
+ adapterObject->MasterDevice = FALSE;
+
+ if (DeviceDescriptor->Master) {
+
+ adapterObject->MasterDevice = TRUE;
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE;
+
+ //
+ // Set the mode, and enable the request.
+ //
+
+ if (adapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ }
+
+ } else if (DeviceDescriptor->DemandMode) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = DEMAND_REQUEST_MODE;
+
+ } else {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = SINGLE_REQUEST_MODE;
+
+ }
+
+ if (DeviceDescriptor->AutoInitialize) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->AutoInitialize = 1;
+
+ }
+
+ adapterObject->AdapterMode = adapterMode;
+
+ return(adapterObject);
+}
+
+VOID
+HalpMapTransferHelper(
+ IN PMDL Mdl,
+ IN PVOID CurrentVa,
+ IN ULONG TransferLength,
+ IN PULONG PageFrame,
+ IN OUT PULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ Helper routine for bus master transfers that cross a page
+ boundary. This routine is separated out from the IoMapTransfer
+ fast path in order to minimize the total instruction path
+ length taken for the common network case where the entire
+ buffer being mapped is contained within one page.
+
+Arguments:
+
+ Mdl - Pointer to the MDL that describes the pages of memory that are
+ being read or written.
+
+ CurrentVa - Current virtual address in the buffer described by the MDL
+ that the transfer is being done to or from.
+
+ TransferLength = Supplies the current transferLength
+
+ PageFrame - Supplies a pointer to the starting page frame of the transfer
+
+ Length - Supplies the length of the transfer. This determines the
+ number of map registers that need to be written to map the transfer.
+ Returns the length of the transfer which was actually mapped.
+
+Return Value:
+
+ None. *Length will be updated
+
+--*/
+
+{
+ do {
+ if (*PageFrame + 1 != *(PageFrame + 1)) {
+ break;
+ }
+ TransferLength += PAGE_SIZE;
+ PageFrame++;
+
+ } while ( TransferLength < *Length );
+
+
+ //
+ // Limit the Length to the maximum TransferLength.
+ //
+
+ if (TransferLength < *Length) {
+ *Length = TransferLength;
+ }
+}
+
+PHYSICAL_ADDRESS
+IoMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN OUT PULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to set up the map registers in the DMA controller
+ to allow a transfer to or from a device.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel that has been allocated.
+
+ Mdl - Pointer to the MDL that describes the pages of memory that are
+ being read or written.
+
+ MapRegisterBase - The address of the base map register that has been
+ allocated to the device driver for use in mapping the transfer.
+
+ CurrentVa - Current virtual address in the buffer described by the MDL
+ that the transfer is being done to or from.
+
+ Length - Supplies the length of the transfer. This determines the
+ number of map registers that need to be written to map the transfer.
+ Returns the length of the transfer which was actually mapped.
+
+ WriteToDevice - Boolean value that indicates whether this is a write
+ to the device from memory (TRUE), or vice versa.
+
+Return Value:
+
+ Returns the logical address that should be used bus master controllers.
+
+--*/
+
+{
+ BOOLEAN useBuffer;
+ ULONG transferLength;
+ ULONG logicalAddress;
+ PHYSICAL_ADDRESS returnAddress;
+ ULONG index;
+ PULONG pageFrame;
+ PUCHAR bytePointer;
+ UCHAR adapterMode;
+ UCHAR dataByte;
+ PTRANSLATION_ENTRY translationEntry;
+ ULONG pageOffset;
+ KIRQL Irql;
+
+ pageOffset = BYTE_OFFSET(CurrentVa);
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT;
+ logicalAddress = ((*pageFrame << PAGE_SHIFT) + pageOffset);
+
+ if (MapRegisterBase==NULL_MAP_REGISTER_BASE) {
+
+ pageOffset = BYTE_OFFSET(CurrentVa);
+
+ //
+ // Calculate how much of the transfer is contiguous
+ //
+ transferLength = PAGE_SIZE - pageOffset;
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT;
+
+ //
+ // Compute the starting address of the transfer
+ //
+
+ returnAddress.LowPart = logicalAddress;
+ returnAddress.HighPart = 0;
+
+ //
+ // If the transfer is not completely contained within
+ // a page, call the helper to compute the appropriate
+ // length.
+ //
+ if (transferLength < *Length) {
+ HalpMapTransferHelper(Mdl, CurrentVa, transferLength, pageFrame, Length);
+ }
+
+ return(returnAddress);
+ }
+
+ transferLength = *Length;
+
+ //
+ // Determine if the data transfer needs to use the map buffer.
+ //
+
+ //
+ // If *pageFrame is in the DMA Cache, then it was allocated by HalAllocateCommonBuffer(),
+ // and should not be mapped.
+ //
+
+ if (MapRegisterBase != NULL_MAP_REGISTER_BASE && !HALP_PAGE_IN_DMA_CACHE(*pageFrame)) {
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ //
+ // If there are map registers, then update the index to indicate
+ // how many have been used.
+ //
+
+ index = translationEntry->Index;
+ translationEntry->Index += ADDRESS_AND_SIZE_TO_SPAN_PAGES(
+ CurrentVa,
+ transferLength
+ );
+
+ //
+ // Force IoMapTransfer() to use the map buffer.
+ //
+
+ logicalAddress = (translationEntry + index)->PhysicalAddress + pageOffset;
+ useBuffer = TRUE;
+
+ if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER) {
+
+ translationEntry->Index = COPY_BUFFER;
+ index = 0;
+
+ }
+
+ //
+ // Copy the data if necessary.
+ //
+
+ if (useBuffer && WriteToDevice) {
+
+ HalpCopyBufferMap(Mdl,
+ translationEntry,
+ CurrentVa,
+ transferLength,
+ WriteToDevice);
+ }
+ }
+
+ //
+ // Return the length.
+ //
+
+ *Length = transferLength;
+
+ //
+ // We only support 32 bits, but the return is 64. Just
+ // zero extend
+ //
+
+ returnAddress.LowPart = logicalAddress;
+ returnAddress.HighPart = 0;
+
+ //
+ // If no adapter was specificed then there is no more work to do so
+ // return.
+ //
+
+ if (AdapterObject == NULL || AdapterObject->MasterDevice) {
+
+ return(returnAddress);
+ }
+
+ //
+ // Determine the mode based on the transfer direction.
+ //
+
+ adapterMode = AdapterObject->AdapterMode;
+ ((PDMA_EISA_MODE) &adapterMode)->TransferType = (UCHAR) (WriteToDevice ?
+ WRITE_TRANSFER : READ_TRANSFER);
+
+ bytePointer = (PUCHAR) &logicalAddress;
+
+ if (AdapterObject->Width16Bits) {
+
+ //
+ // If this is a 16 bit transfer then adjust the length and the address
+ // for the 16 bit DMA mode.
+ //
+
+ transferLength >>= 1;
+
+ //
+ // In 16 bit DMA mode the low 16 bits are shifted right one and the
+ // page register value is unchanged. So save the page register value
+ // and shift the logical address then restore the page value.
+ //
+
+ dataByte = bytePointer[2];
+ logicalAddress >>= 1;
+ bytePointer[2] = dataByte;
+
+ }
+
+
+ //
+ // grab the spinlock for the system DMA controller
+ //
+
+ KeAcquireSpinLock( &AdapterObject->MasterAdapter->SpinLock, &Irql );
+
+ //
+ // Determine the controller number based on the Adapter number.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ bytePointer[0]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ bytePointer[1]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase[AdapterObject->BusNumber])->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ bytePointer[2]
+ );
+
+ if (HalpBusType == UNIFLEX_MACHINE_TYPE_EISA) {
+
+ //
+ // Write the high page register with zero value. This enable a special mode
+ // which allows ties the page register and base count into a single 24 bit
+ // address register.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase[AdapterObject->BusNumber])->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ 0
+ );
+ }
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((transferLength - 1) & 0xff)
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((transferLength - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ bytePointer[0]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ bytePointer[1]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase[AdapterObject->BusNumber])->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ bytePointer[2]
+ );
+
+ if (HalpBusType == UNIFLEX_MACHINE_TYPE_EISA) {
+
+ //
+ // Write the high page register with zero value. This enable a special mode
+ // which allows ties the page register and base count into a single 24 bit
+ // address register.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase[AdapterObject->BusNumber])->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ 0
+ );
+ }
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((transferLength - 1) & 0xff)
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((transferLength - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+ KeReleaseSpinLock (&AdapterObject->MasterAdapter->SpinLock, Irql);
+
+ return(returnAddress);
+}
+
+BOOLEAN
+IoFlushAdapterBuffers(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine flushes the DMA adapter object buffers. For the Jazz system
+ its clears the enable flag which aborts the dma.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel.
+
+ Mdl - A pointer to a Memory Descriptor List (MDL) that maps the locked-down
+ buffer to/from which the I/O occured.
+
+ MapRegisterBase - A pointer to the base of the map registers in the adapter
+ or DMA controller.
+
+ CurrentVa - The current virtual address in the buffer described the the Mdl
+ where the I/O operation occurred.
+
+ Length - Supplies the length of the transfer.
+
+ WriteToDevice - Supplies a BOOLEAN value that indicates the direction of
+ the data transfer was to the device.
+
+Return Value:
+
+ TRUE - No errors are detected so the transfer must succeed.
+
+--*/
+
+{
+ PTRANSLATION_ENTRY translationEntry;
+ PULONG pageFrame;
+ BOOLEAN masterDevice;
+ PVOID OriginalCurrentVa;
+
+ OriginalCurrentVa = CurrentVa;
+
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT;
+
+ masterDevice = AdapterObject == NULL || AdapterObject->MasterDevice ?
+ TRUE : FALSE;
+
+#if defined(_ALPHA_)
+
+ HalpCleanIoBuffers(Mdl,!WriteToDevice,TRUE);
+// HalFlushIoBuffers(Mdl,!WriteToDevice,TRUE);
+
+#endif
+
+ if (MapRegisterBase==NULL_MAP_REGISTER_BASE) {
+ return(TRUE);
+ }
+
+ //
+ // If this is a slave device, then stop the DMA controller.
+ //
+
+ if (!masterDevice) {
+
+ //
+ // Mask the DMA request line so that DMA requests cannot occur.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+
+ }
+
+ //
+ // If there are no map registers being used then just return TRUE.
+ // If *pageFrame is in the DMA Cache, then it was allocated by HalAllocateCommonBuffer(),
+ // and was not be mapped. So, just return TRUE.
+ //
+
+ if (MapRegisterBase == NULL_MAP_REGISTER_BASE || HALP_PAGE_IN_DMA_CACHE(*pageFrame)) {
+ return(TRUE);
+ }
+
+ //
+ // Determine if the data needs to be copied to the orginal buffer.
+ // This only occurs if the data tranfer is from the device, the
+ // MapReisterBase is not NULL and the transfer spans a page.
+ //
+
+ if (!WriteToDevice) {
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ //
+ // If this is not a master device, then just transfer the buffer.
+ //
+
+ if (!masterDevice) {
+
+ //
+ // Copy only the bytes that have actually been transfered.
+ //
+
+ Length -= HalReadDmaCounter(AdapterObject);
+
+ }
+
+ //
+ // The adapter does not support scatter/gather copy the buffer.
+ //
+
+ HalpCopyBufferMap(Mdl,
+ translationEntry,
+ CurrentVa,
+ Length,
+ WriteToDevice);
+
+#if defined(_MIPS_)
+
+ //
+ // If this is a page read then flush the buffer from the primary data cache so
+ // it can be potentially read into the primary instruction cache.
+ //
+
+ if ( (Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0) {
+
+ ULONG transferLength;
+ ULONG partialLength;
+
+ if (Length > PCR->FirstLevelDcacheSize) {
+ HalSweepDcache();
+ } else {
+
+ CurrentVa = OriginalCurrentVa;
+
+ transferLength = PAGE_SIZE - BYTE_OFFSET(CurrentVa);
+ partialLength = transferLength;
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT;
+
+ while( transferLength <= Length ){
+
+ HalFlushDcachePage(CurrentVa,*pageFrame,partialLength);
+
+ (PCCHAR) CurrentVa += partialLength;
+ partialLength = PAGE_SIZE;
+
+ transferLength += partialLength;
+ pageFrame++;
+ }
+
+ partialLength = Length - transferLength + partialLength;
+
+ if (partialLength) {
+
+ HalFlushDcachePage(CurrentVa,*pageFrame,partialLength);
+ }
+ }
+ }
+
+#endif
+
+ }
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ //
+ // Clear index in map register.
+ //
+
+ translationEntry->Index = 0;
+
+ return TRUE;
+}
+
+ULONG
+HalReadDmaCounter(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+/*++
+
+Routine Description:
+
+ This function reads the DMA counter and returns the number of bytes left
+ to be transfered.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object to be read.
+
+Return Value:
+
+ Returns the number of bytes still be be transfered.
+
+--*/
+
+{
+ ULONG count;
+ ULONG high;
+
+ if (AdapterObject->PagePort) {
+
+ //
+ // Determine the controller number based on the Adapter number.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ ) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ ) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+ }
+
+ //
+ // The DMA counter has a bias of one and can only be 16 bit long.
+ //
+
+ count = (count + 1) & 0xFFFF;
+
+ }
+
+ return(count);
+}
+
+VOID
+HalpEnableEisaInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the EISA bus specified EISA bus interrupt and sets
+ the level/edge register to the requested value.
+
+Arguments:
+
+ Vector - Supplies the vector of the ESIA interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG BusNumber;
+
+ if (Vector >= UNIFLEX_EISA_VECTORS && Vector <= UNIFLEX_MAXIMUM_EISA_VECTOR) {
+
+ BusNumber = 0;
+
+ //
+ // Calculate the EISA interrupt vector.
+ //
+
+ Vector -= UNIFLEX_EISA_VECTORS;
+ }
+
+ if (Vector >= UNIFLEX_EISA1_VECTORS && Vector <= UNIFLEX_MAXIMUM_EISA1_VECTOR) {
+
+ BusNumber = 1;
+
+ //
+ // Calculate the EISA interrupt vector.
+ //
+
+ Vector -= UNIFLEX_EISA1_VECTORS;
+ }
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt2Mask[BusNumber] &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask[BusNumber]
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpEisaInterrupt2Level[BusNumber] |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpEisaInterrupt2Level[BusNumber] &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt2EdgeLevel,
+ HalpEisaInterrupt2Level[BusNumber]
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt1Mask[BusNumber] &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask[BusNumber]
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpEisaInterrupt1Level[BusNumber] |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpEisaInterrupt1Level[BusNumber] &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt1EdgeLevel,
+ HalpEisaInterrupt1Level[BusNumber]
+ );
+ }
+
+}
+
+VOID
+HalpDisableEisaInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function Disables the EISA bus specified EISA bus interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the ESIA interrupt that is Disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG BusNumber;
+
+ if (Vector >= UNIFLEX_EISA_VECTORS && Vector <= UNIFLEX_MAXIMUM_EISA_VECTOR) {
+
+ BusNumber = 0;
+
+ //
+ // Calculate the EISA interrupt vector.
+ //
+
+ Vector -= UNIFLEX_EISA_VECTORS;
+ }
+
+ if (Vector >= UNIFLEX_EISA1_VECTORS && Vector <= UNIFLEX_MAXIMUM_EISA1_VECTOR) {
+
+ BusNumber = 1;
+
+ //
+ // Calculate the EISA interrupt vector.
+ //
+
+ Vector -= UNIFLEX_EISA1_VECTORS;
+ }
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt2Mask[BusNumber] |= (UCHAR) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask[BusNumber]
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt1Mask[BusNumber] |= (ULONG) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask[BusNumber]
+ );
+
+ }
+
+}
+
+BOOLEAN
+HalpCreateEisaStructures (
+ ULONG BusNumber
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for EISA operations
+ and connects the intermediate interrupt dispatcher. It also initializes the
+ EISA interrupt controller.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher is connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ UCHAR DataByte;
+
+ //
+ // Initialize the EISA interrupt controller. There are two cascaded
+ // interrupt controllers, each of which must initialized with 4 initialize
+ // control words.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt1ControlPort0,
+ DataByte
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt2ControlPort0,
+ DataByte
+ );
+
+ //
+ // The second intitialization control word sets the iterrupt vector to
+ // 0-15.
+ //
+
+ DataByte = 0;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = 0x08;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The thrid initialization control word set the controls for slave mode.
+ // The master ICW3 uses bit position and the slave ICW3 uses a numberic.
+ //
+
+ DataByte = 1 << SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->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_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt2ControlPort1,
+ DataByte
+ );
+
+
+ //
+ // Disable all of the interrupts except the slave.
+ //
+
+ HalpEisaInterrupt1Mask[BusNumber] = (UCHAR)(~(1 << SLAVE_IRQL_LEVEL));
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask[BusNumber]
+ );
+
+ HalpEisaInterrupt2Mask[BusNumber] = 0xFF;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask[BusNumber]
+ );
+
+ //
+ // Initialize the edge/level register masks to 0 which is the default
+ // edge sensitive value.
+ //
+
+ HalpEisaInterrupt1Level[BusNumber] = 0;
+ HalpEisaInterrupt2Level[BusNumber] = 0;
+
+ //
+ // Initialize the DMA mode registers to a default value.
+ // Disable all of the DMA channels except channel 4 which is that
+ // cascade of channels 0-3.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Dma1BasePort.AllMask,
+ 0x0F
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Dma2BasePort.AllMask,
+ 0x0E
+ );
+
+ HalpConnectInterruptDispatchers();
+
+ return(TRUE);
+}
+
+BOOLEAN
+HalpEisaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN ULONG BusNumber
+ )
+
+{
+ volatile UCHAR LowerVector;
+ volatile UCHAR UpperVector;
+ volatile UCHAR UpperVector1;
+ volatile PULONG dispatchCode;
+ volatile PKINTERRUPT interruptObject;
+ volatile USHORT PCRInOffset;
+ volatile BOOLEAN returnValue = FALSE;
+
+ //
+ // Send a POLL Command to Interrupt Controller 2
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL)HalpEisaControlBase[BusNumber])->Interrupt2ControlPort0,
+ 0x0c
+ );
+
+ //
+ // Read the interrupt vector
+ //
+
+ UpperVector = READ_REGISTER_UCHAR(&((PEISA_CONTROL)HalpEisaControlBase[BusNumber])->Interrupt2ControlPort0);
+
+ //
+ // See if there is a real interrupt on Interrupt Controller 2
+ //
+
+ if (UpperVector & 0x80) {
+
+ UpperVector = UpperVector & 0x07;
+
+ if (BusNumber == 0) {
+ PCRInOffset = UpperVector + 8 + UNIFLEX_EISA_VECTORS;
+ }
+ if (BusNumber == 1) {
+ PCRInOffset = UpperVector + 8 + UNIFLEX_EISA1_VECTORS;
+ }
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ dispatchCode = (PULONG)(PCR->InterruptRoutine[PCRInOffset]);
+ interruptObject = CONTAINING_RECORD(dispatchCode,
+ KINTERRUPT,
+ DispatchCode);
+
+ returnValue =
+ ((PSECONDARY_DISPATCH)interruptObject->DispatchAddress)
+ (interruptObject);
+
+ //
+ // Clear the interrupt from Interrupt Controller 2
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL)HalpEisaControlBase[BusNumber])->Interrupt2ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ //
+ // Send a POLL Command to Interrupt Controller 2
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL)HalpEisaControlBase[BusNumber])->Interrupt2ControlPort0,
+ 0x0c
+ );
+
+ //
+ // Read the interrupt vector
+ //
+
+ UpperVector1 = READ_REGISTER_UCHAR(&((PEISA_CONTROL)HalpEisaControlBase[BusNumber])->Interrupt2ControlPort0);
+
+ if ((UpperVector1 & 0x80) && (UpperVector1 & 0x07) == UpperVector) {
+
+ UCHAR DataByte;
+
+//DbgPrint("ERROR : Interrupt controller 2 stuck on ISA bus %d : UpperVector1 = %02x\n\r",BusNumber,UpperVector1);
+
+ //
+ // Initialize the EISA interrupt controller. There are two cascaded
+ // interrupt controllers, each of which must initialized with 4 initialize
+ // control words.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt2ControlPort0,
+ DataByte
+ );
+
+ //
+ // The second intitialization control word sets the iterrupt vector to
+ // 0-15.
+ //
+
+ DataByte = 0x70;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The thrid initialization control word set the controls for slave mode.
+ // The master ICW3 uses bit position and the slave ICW3 uses a numberic.
+ //
+
+ DataByte = SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->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_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // Program the interrupt mask register for the upper PIC
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask[BusNumber]
+ );
+
+ //
+ // Program the interrupt edge/level register for the upper PIC
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt2EdgeLevel,
+ HalpEisaInterrupt2Level[BusNumber]
+ );
+ }
+
+ return(returnValue);
+ }
+
+ //
+ // Send a POLL Command to Interrupt Controller 1
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt1ControlPort0,
+ 0x0c
+ );
+
+ //
+ // Read the interrupt vector
+ //
+
+ LowerVector = READ_REGISTER_UCHAR(&((PEISA_CONTROL)HalpEisaControlBase[BusNumber])->Interrupt1ControlPort0);
+
+ //
+ // See if there is a real interrupt on Interrupt Controller 1
+ //
+
+ if (LowerVector & 0x80) {
+
+ LowerVector = LowerVector & 0x07;
+
+ if (LowerVector!=0x02) {
+
+ //
+ // This interrupt is on the first interrupt controller
+ //
+
+ if (BusNumber == 0) {
+ PCRInOffset = LowerVector + UNIFLEX_EISA_VECTORS;
+ }
+ if (BusNumber == 1) {
+ PCRInOffset = LowerVector + UNIFLEX_EISA1_VECTORS;
+ }
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ //
+ // The interrupt vector for CLOCK2_LEVEL is directly connected by the HAL.
+ // If the interrupt is on CLOCK2_LEVEL then vector to the address stored
+ // in the PCR. Otherwise, bypass the thunk code in the interrupt object
+ // whose address is stored in the PCR.
+ //
+
+ if (PCRInOffset == UNIFLEX_CLOCK2_LEVEL) {
+
+ returnValue =
+ ((PSECONDARY_DISPATCH)PCR->InterruptRoutine[PCRInOffset])
+ (PCR->InterruptRoutine[PCRInOffset]);
+
+ } else {
+
+ dispatchCode = (PULONG)(PCR->InterruptRoutine[PCRInOffset]);
+ interruptObject = CONTAINING_RECORD(dispatchCode,
+ KINTERRUPT,
+ DispatchCode);
+
+ returnValue =
+ ((PSECONDARY_DISPATCH)interruptObject->DispatchAddress)
+ (interruptObject);
+
+ }
+ }
+
+ //
+ // Clear the interrupt from Interrupt Controller 1
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL)HalpEisaControlBase[BusNumber])->Interrupt1ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ return(returnValue);
+ }
+
+ //
+ // Spurrious Interrupt. Return FALSE
+ //
+
+ return(returnValue);
+}
diff --git a/private/ntos/nthals/halflex/xxenvirv.c b/private/ntos/nthals/halflex/xxenvirv.c
new file mode 100644
index 000000000..1b81d4cad
--- /dev/null
+++ b/private/ntos/nthals/halflex/xxenvirv.c
@@ -0,0 +1,106 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxenvirv.c
+
+Abstract:
+
+ This module implements the HAL get and set environment variable routines
+ for a MIPS system.
+
+Author:
+
+ Michael D. Kinney 30-Apr-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "arccodes.h"
+
+ARC_STATUS
+HalGetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN USHORT Length,
+ OUT PCHAR Buffer
+ )
+
+/*++
+
+Routine Description:
+
+ This function locates an environment variable and returns its value.
+
+Arguments:
+
+ Variable - Supplies a pointer to a zero terminated environment variable
+ name.
+
+ Length - Supplies the length of the value buffer in bytes.
+
+ Buffer - Supplies a pointer to a buffer that receives the variable value.
+
+Return Value:
+
+ ESUCCESS is returned if the enviroment variable is located. Otherwise,
+ ENOENT is returned.
+
+--*/
+
+{
+ CHAR *Value;
+
+ HalpAllocateArcsResources();
+ Value = ArcGetEnvironmentVariable(Variable);
+ HalpFreeArcsResources();
+
+ if (Value==NULL)
+ return(ENOENT);
+ if (strlen(Value)>Length)
+ return(ENOENT);
+ strcpy(Buffer,Value);
+ return ESUCCESS;
+}
+
+
+ARC_STATUS
+HalSetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN PCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This function creates an environment variable with the specified value.
+
+Arguments:
+
+ Variable - Supplies a pointer to an environment variable name.
+
+ Value - Supplies a pointer to the environment variable value.
+
+Return Value:
+
+ ESUCCESS is returned if the environment variable is created. Otherwise,
+ ENOMEM is returned.
+
+--*/
+
+{
+ ARC_STATUS ReturnValue;
+
+ HalpAllocateArcsResources();
+ ReturnValue = ArcSetEnvironmentVariable(Variable,Value);
+ HalpFreeArcsResources();
+ return(ReturnValue);
+}
diff --git a/private/ntos/nthals/halflex/xxhwsup.c b/private/ntos/nthals/halflex/xxhwsup.c
new file mode 100644
index 000000000..06f2d77d3
--- /dev/null
+++ b/private/ntos/nthals/halflex/xxhwsup.c
@@ -0,0 +1,1250 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ ixphwsup.c
+
+Abstract:
+
+ This module contains the HalpXxx routines for the NT I/O system that
+ are hardware dependent. Were these routines not hardware dependent,
+ they would normally reside in the internal.c module.
+
+Author:
+
+ Darryl E. Havens (darrylh) 11-Apr-1990
+
+Environment:
+
+ Kernel mode, local to I/O system
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+
+
+//
+// Some devices require a phyicially contiguous data buffers for DMA transfers.
+// Map registers are used give the appearance that all data buffers are
+// contiguous. In order to pool all of the map registers a master
+// adapter object is used. This object is allocated and saved internal to this
+// file. It contains a bit map for allocation of the registers and a queue
+// for requests which are waiting for more map registers. This object is
+// allocated during the first request to allocate an adapter which requires
+// map registers.
+//
+
+extern POBJECT_TYPE IoAdapterObjectType;
+
+PADAPTER_OBJECT MasterAdapterObject;
+
+//
+// Map buffer prameters. These are initialized in HalInitSystem
+//
+
+extern PHYSICAL_ADDRESS HalpMapBufferPhysicalAddress;
+extern ULONG HalpMapBufferSize;
+
+
+BOOLEAN
+HalpGrowMapBuffers(
+ PADAPTER_OBJECT AdapterObject,
+ ULONG Amount
+ )
+/*++
+
+Routine Description:
+
+ This function attempts to allocate additional map buffers for use by I/O
+ devices. The map register table is updated to indicate the additional
+ buffers.
+
+Arguments:
+
+ AdapterObject - Supplies the adapter object for which the buffers are to be
+ allocated.
+
+ Amount - Indicates the size of the map buffers which should be allocated.
+
+Return Value:
+
+ TRUE is returned if the memory could be allocated.
+
+ FALSE is returned if the memory could not be allocated.
+
+--*/
+{
+ ULONG MapBufferPhysicalAddress;
+ PVOID MapBufferVirtualAddress;
+ PTRANSLATION_ENTRY TranslationEntry;
+ LONG NumberOfPages;
+ LONG i;
+ KIRQL Irql;
+ BOOLEAN eisaSystem;
+ PMDL MapBufferMdl;
+
+ eisaSystem = HalpBusType == UNIFLEX_MACHINE_TYPE_EISA ? TRUE : FALSE;
+
+ KeAcquireSpinLock( &AdapterObject->SpinLock, &Irql );
+
+ NumberOfPages = BYTES_TO_PAGES(Amount);
+
+ //
+ // Make sure there is room for the addition pages. The maximum number of
+ // slots needed is equal to NumberOfPages + Amount / 64K + 1.
+ //
+
+ i = BYTES_TO_PAGES(HalpMapBufferSize) - (NumberOfPages +
+ (NumberOfPages * PAGE_SIZE) / 0x10000 + 1 +
+ AdapterObject->NumberOfMapRegisters);
+
+ if (i < 0) {
+
+ //
+ // Reduce the allocatation amount to so it will fit.
+ //
+
+ NumberOfPages += i;
+ }
+
+ if (NumberOfPages <= 0) {
+ //
+ // No more memory can be allocated.
+ //
+
+ KeReleaseSpinLock( &AdapterObject->SpinLock, Irql );
+ return(FALSE);
+
+ }
+
+
+ if (AdapterObject->NumberOfMapRegisters == 0 && HalpMapBufferSize) {
+
+ NumberOfPages = BYTES_TO_PAGES(HalpMapBufferSize);
+
+ //
+ // Since this is the initial allocation, use the buffer allocated by
+ // HalInitSystem rather than allocationg a new one.
+ //
+
+ MapBufferPhysicalAddress = HalpMapBufferPhysicalAddress.LowPart;
+
+ //
+ // Map the buffer for access.
+ //
+
+
+ // On an R4000 system, this space should be mapped with caches
+ // disabled to avoid having to perform page exports on IO writes
+ // and page purges on IO reads.
+
+ MapBufferVirtualAddress = MmMapIoSpace(
+ HalpMapBufferPhysicalAddress,
+ HalpMapBufferSize,
+ FALSE // Cache disabled.
+ );
+
+ if (MapBufferVirtualAddress == NULL) {
+
+ //
+ // The buffer could not be mapped.
+ //
+
+ HalpMapBufferSize = 0;
+
+ KeReleaseSpinLock( &AdapterObject->SpinLock, Irql );
+ return(FALSE);
+ }
+
+ //
+ // Flush all references to the map buffer from the caches.
+ //
+
+ MapBufferMdl = MmCreateMdl(NULL,MapBufferVirtualAddress,HalpMapBufferSize);
+ MmBuildMdlForNonPagedPool(MapBufferMdl);
+ HalFlushIoBuffers(MapBufferMdl,TRUE,TRUE);
+ IoFreeMdl(MapBufferMdl);
+ }
+
+ //
+ // Initailize the map registers where memory has been allocated.
+ //
+
+ TranslationEntry = ((PTRANSLATION_ENTRY) AdapterObject->MapRegisterBase) +
+ AdapterObject->NumberOfMapRegisters;
+
+ for (i = 0; i < NumberOfPages; i++) {
+
+ //
+ // Make sure the perivous entry is physically contiguous with the next
+ // entry and that a 64K physical bountry is not crossed unless this
+ // is an Eisa system.
+ //
+
+ if (TranslationEntry != AdapterObject->MapRegisterBase &&
+ (((TranslationEntry - 1)->PhysicalAddress + PAGE_SIZE) !=
+ MapBufferPhysicalAddress || (!eisaSystem &&
+ ((TranslationEntry - 1)->PhysicalAddress & ~0x0ffff) !=
+ (MapBufferPhysicalAddress & ~0x0ffff)))) {
+
+ //
+ // An entry needs to be skipped in the table. This entry will
+ // remain marked as allocated so that no allocation of map
+ // registers will cross this bountry.
+ //
+
+ TranslationEntry++;
+ AdapterObject->NumberOfMapRegisters++;
+
+ }
+
+ //
+ // Clear the bits where the memory has been allocated.
+ //
+
+ RtlClearBits(
+ AdapterObject->MapRegisters,
+ TranslationEntry - (PTRANSLATION_ENTRY)
+ AdapterObject->MapRegisterBase,
+ 1
+ );
+
+ TranslationEntry->VirtualAddress = MapBufferVirtualAddress;
+ TranslationEntry->PhysicalAddress = MapBufferPhysicalAddress;
+ TranslationEntry++;
+ (PCCHAR) MapBufferVirtualAddress += PAGE_SIZE;
+ MapBufferPhysicalAddress += PAGE_SIZE;
+
+ }
+
+ //
+ // Remember the number of pages that where allocated.
+ //
+
+ AdapterObject->NumberOfMapRegisters += NumberOfPages;
+
+ KeReleaseSpinLock( &AdapterObject->SpinLock, Irql );
+ return(TRUE);
+}
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN PVOID AdapterBaseVa,
+ IN PVOID ChannelNumber
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allocates and initializes an adapter object to represent an
+ adapter or a DMA controller on the system. If no map registers are required
+ then a standalone adapter object is allocated with no master adapter.
+
+ If map registers are required, then a master adapter object is used to
+ allocate the map registers. For Isa systems these registers are really
+ phyically contiguous memory pages.
+
+Arguments:
+
+ MapRegistersPerChannel - Specifies the number of map registers that each
+ channel provides for I/O memory mapping.
+
+ AdapterBaseVa - Address of the the DMA controller.
+
+ ChannelNumber - Unused.
+
+Return Value:
+
+ The function value is a pointer to the allocate adapter object.
+
+--*/
+
+{
+
+ PADAPTER_OBJECT AdapterObject;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ ULONG Size;
+ ULONG BitmapSize;
+ HANDLE Handle;
+ NTSTATUS Status;
+
+ UNREFERENCED_PARAMETER(ChannelNumber);
+
+ //
+ // Initalize the master adapter if necessary.
+ //
+
+ if (MasterAdapterObject == NULL && AdapterBaseVa != (PVOID) -1) {
+
+ MasterAdapterObject = HalpAllocateAdapter(
+ MapRegistersPerChannel,
+ (PVOID) -1,
+ NULL
+ );
+
+ //
+ // If we could not allocate the master adapter then give up.
+ //
+ if (MasterAdapterObject == NULL) {
+
+ return(NULL);
+ }
+ }
+
+ //
+ // Begin by initializing the object attributes structure to be used when
+ // creating the adapter object.
+ //
+
+ InitializeObjectAttributes( &ObjectAttributes,
+ NULL,
+ OBJ_PERMANENT,
+ (HANDLE) NULL,
+ (PSECURITY_DESCRIPTOR) NULL
+ );
+
+ //
+ // Determine the size of the adapter object. If this is the master object
+ // then allocate space for the register bit map; otherwise, just allocate
+ // an adapter object.
+ //
+ if (AdapterBaseVa == (PVOID) -1) {
+
+ //
+ // Allocate a bit map large enough HalpMapBufferSize / PAGE_SIZE
+ // of map register buffers.
+ //
+
+ BitmapSize = (((sizeof( RTL_BITMAP ) +
+ (( (HalpMapBufferSize/PAGE_SIZE) + (HalpMapBufferSize/0x10000) + 1 ) + 7 >> 3)) + 3) & ~3);
+
+ Size = sizeof( ADAPTER_OBJECT ) + BitmapSize;
+
+ } else {
+
+ Size = sizeof( ADAPTER_OBJECT );
+
+ }
+
+ //
+ // Now create the adapter object.
+ //
+
+ Status = ObCreateObject( KernelMode,
+ *((POBJECT_TYPE *)IoAdapterObjectType),
+ &ObjectAttributes,
+ KernelMode,
+ (PVOID) NULL,
+ Size,
+ 0,
+ 0,
+ (PVOID *)&AdapterObject );
+
+ //
+ // Reference the object.
+ //
+
+ if (NT_SUCCESS(Status)) {
+
+ Status = ObReferenceObjectByPointer(
+ AdapterObject,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ *((POBJECT_TYPE *)IoAdapterObjectType),
+ KernelMode
+ );
+
+ }
+
+ //
+ // If the adapter object was successfully created, then attempt to insert
+ // it into the the object table.
+ //
+
+ if (NT_SUCCESS( Status )) {
+
+ Status = ObInsertObject( AdapterObject,
+ NULL,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ 0,
+ (PVOID *) NULL,
+ &Handle );
+
+ if (NT_SUCCESS( Status )) {
+
+ ZwClose( Handle );
+
+ //
+ // Initialize the adapter object itself.
+ //
+
+ AdapterObject->Type = IO_TYPE_ADAPTER;
+ AdapterObject->Size = (USHORT) Size;
+ AdapterObject->MapRegistersPerChannel = 1;
+ AdapterObject->AdapterBaseVa = AdapterBaseVa;
+
+ if (MapRegistersPerChannel) {
+
+ AdapterObject->MasterAdapter = MasterAdapterObject;
+
+ } else {
+
+ AdapterObject->MasterAdapter = NULL;
+
+ }
+
+ //
+ // Initialize the channel wait queue for this
+ // adapter.
+ //
+
+ KeInitializeDeviceQueue( &AdapterObject->ChannelWaitQueue );
+
+ //
+ // If this is the MasterAdatper then initialize the register bit map,
+ // AdapterQueue and the spin lock.
+ //
+
+ if ( AdapterBaseVa == (PVOID) -1 ) {
+
+ KeInitializeSpinLock( &AdapterObject->SpinLock );
+
+ InitializeListHead( &AdapterObject->AdapterQueue );
+
+ AdapterObject->MapRegisters = (PVOID) ( AdapterObject + 1);
+
+ RtlInitializeBitMap( AdapterObject->MapRegisters,
+ (PULONG) (((PCHAR) (AdapterObject->MapRegisters)) + sizeof( RTL_BITMAP )),
+ ( (HalpMapBufferSize/PAGE_SIZE) + (HalpMapBufferSize/0x10000) + 1 )
+ );
+ //
+ // Set all the bits in the memory to indicate that memory
+ // has not been allocated for the map buffers
+ //
+
+ RtlSetAllBits( AdapterObject->MapRegisters );
+ AdapterObject->NumberOfMapRegisters = 0;
+ AdapterObject->CommittedMapRegisters = 0;
+
+ //
+ // ALlocate the memory map registers.
+ //
+
+ AdapterObject->MapRegisterBase = ExAllocatePool(
+ NonPagedPool,
+ ((HalpMapBufferSize/PAGE_SIZE) + (HalpMapBufferSize/0x10000) + 1 ) *
+ sizeof(TRANSLATION_ENTRY)
+ );
+
+ if (AdapterObject->MapRegisterBase == NULL) {
+
+ ObDereferenceObject( AdapterObject );
+ AdapterObject = NULL;
+ return(NULL);
+
+ }
+
+ //
+ // Zero the map registers.
+ //
+
+ RtlZeroMemory(
+ AdapterObject->MapRegisterBase,
+ ((HalpMapBufferSize/PAGE_SIZE) + (HalpMapBufferSize/0x10000) + 1 ) *
+ sizeof(TRANSLATION_ENTRY)
+ );
+
+ if (!HalpGrowMapBuffers(AdapterObject,HalpMapBufferSize))
+ {
+
+ //
+ // If no map registers could be allocated then free the
+ // object.
+ //
+
+ ObDereferenceObject( AdapterObject );
+ AdapterObject = NULL;
+ return(NULL);
+
+ }
+ }
+
+ } else {
+
+ //
+ // An error was incurred for some reason. Set the return value
+ // to NULL.
+ //
+
+ AdapterObject = (PADAPTER_OBJECT) NULL;
+ }
+ } else {
+
+ AdapterObject = (PADAPTER_OBJECT) NULL;
+
+ }
+
+
+ return AdapterObject;
+
+}
+
+IO_ALLOCATION_ACTION
+HalpAllocationRoutine (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID MapRegisterBase,
+ IN PVOID Context
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called by HalAllocateAdapterChannel when sufficent resources
+ are available to the driver. This routine saves the MapRegisterBase,
+ and set the event pointed to by the context parameter.
+
+Arguments:
+
+ DeviceObject - Supplies a pointer where the map register base should be
+ stored.
+
+ Irp - Unused.
+
+ MapRegisterBase - Supplied by the Io subsystem for use in IoMapTransfer.
+
+ Context - Supplies a pointer to an event which is set to indicate the
+ AdapterObject has been allocated.
+
+Return Value:
+
+ DeallocateObjectKeepRegisters - Indicates the adapter should be freed
+ and mapregisters should remain allocated after return.
+
+--*/
+
+{
+
+ UNREFERENCED_PARAMETER(Irp);
+
+ *((PVOID *) DeviceObject) = MapRegisterBase;
+
+ (VOID) KeSetEvent( (PKEVENT) Context, 0L, FALSE );
+
+ return(DeallocateObjectKeepRegisters);
+}
+
+PVOID
+HalAllocateCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ OUT PPHYSICAL_ADDRESS LogicalAddress,
+ IN BOOLEAN CacheEnabled
+ )
+/*++
+
+Routine Description:
+
+ This function allocates the memory for a common buffer and maps so that it
+ can be accessed by a master device and the CPU.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer to be allocated.
+
+ LogicalAddress - Returns the logical address of the common buffer.
+
+ CacheEnable - Indicates whether the memeory is cached or not.
+
+Return Value:
+
+ Returns the virtual address of the common buffer. If the buffer cannot be
+ allocated then NULL is returned.
+
+--*/
+
+{
+ PVOID virtualAddress;
+ PVOID mapRegisterBase;
+ ULONG numberOfMapRegisters;
+ WAIT_CONTEXT_BLOCK wcb;
+ KEVENT allocationEvent;
+ NTSTATUS status;
+ KIRQL irql;
+ PTRANSLATION_ENTRY translationEntry;
+ UCHAR SavedNeedsMapRegisters;
+ ULONG SavedMapRegistersPerChannel;
+ PADAPTER_OBJECT SavedMasterAdapter;
+
+ numberOfMapRegisters = BYTES_TO_PAGES(Length);
+
+ SavedNeedsMapRegisters = AdapterObject->NeedsMapRegisters;
+ SavedMapRegistersPerChannel = AdapterObject->MapRegistersPerChannel;
+ SavedMasterAdapter = AdapterObject->MasterAdapter;
+ AdapterObject->NeedsMapRegisters = TRUE;
+ AdapterObject->MapRegistersPerChannel = numberOfMapRegisters;
+ AdapterObject->MasterAdapter = MasterAdapterObject;
+
+ //
+ // Initialize an event.
+ //
+
+ KeInitializeEvent( &allocationEvent, NotificationEvent, FALSE);
+
+ //
+ // Initialize the wait context block. Use the device object to indicate
+ // where the map register base should be stored.
+ //
+
+ wcb.DeviceObject = &mapRegisterBase;
+ wcb.CurrentIrp = NULL;
+ wcb.DeviceContext = &allocationEvent;
+
+ //
+ // Allocate the adapter and the map registers.
+ //
+
+ KeRaiseIrql(DISPATCH_LEVEL, &irql);
+
+ status = HalAllocateAdapterChannel(
+ AdapterObject,
+ &wcb,
+ numberOfMapRegisters,
+ HalpAllocationRoutine
+ );
+
+ KeLowerIrql(irql);
+
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // Cleanup and return NULL.
+ //
+
+ AdapterObject->NeedsMapRegisters = SavedNeedsMapRegisters;
+ AdapterObject->MapRegistersPerChannel = SavedMapRegistersPerChannel;
+ AdapterObject->MasterAdapter = SavedMasterAdapter;
+ return(NULL);
+
+ }
+
+ //
+ // Wait for the map registers to be allocated.
+ //
+
+ status = KeWaitForSingleObject(
+ &allocationEvent,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL
+ );
+
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // Cleanup and return NULL.
+ //
+
+ AdapterObject->NeedsMapRegisters = SavedNeedsMapRegisters;
+ AdapterObject->MapRegistersPerChannel = SavedMapRegistersPerChannel;
+ AdapterObject->MasterAdapter = SavedMasterAdapter;
+ return(NULL);
+
+ }
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG)mapRegisterBase & ~NO_SCATTER_GATHER);
+ LogicalAddress->HighPart = 0;
+ LogicalAddress->LowPart = translationEntry->PhysicalAddress;
+
+ if (CacheEnabled) {
+ virtualAddress = (PVOID)(KSEG0_BASE | LogicalAddress->LowPart);
+ } else {
+ virtualAddress = translationEntry->VirtualAddress;
+ }
+
+ AdapterObject->NeedsMapRegisters = SavedNeedsMapRegisters;
+ AdapterObject->MapRegistersPerChannel = SavedMapRegistersPerChannel;
+ AdapterObject->MasterAdapter = SavedMasterAdapter;
+ return(virtualAddress);
+}
+
+BOOLEAN
+HalFlushCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress
+ )
+/*++
+
+Routine Description:
+
+ This function is called to flush any hardware adapter buffers when the
+ driver needs to read data written by an I/O master device to a common
+ buffer.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer. This should be the same
+ value used for the allocation of the buffer.
+
+ LogicalAddress - Supplies the logical address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ VirtualAddress - Supplies the virtual address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+Return Value:
+
+ Returns TRUE if no errors were detected; otherwise, FALSE is return.
+
+--*/
+
+{
+ return(TRUE);
+}
+
+VOID
+HalFreeCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress,
+ IN BOOLEAN CacheEnabled
+ )
+/*++
+
+Routine Description:
+
+ This function frees a common buffer and all of the resouces it uses.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer. This should be the same
+ value used for the allocation of the buffer.
+
+ LogicalAddress - Supplies the logical address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ VirtualAddress - Supplies the virtual address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ CacheEnable - Indicates whether the memeory is cached or not.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ PTRANSLATION_ENTRY mapRegisterBase;
+ ULONG numberOfMapRegisters;
+ ULONG mapRegisterNumber;
+ UCHAR SavedNeedsMapRegisters;
+ PADAPTER_OBJECT SavedMasterAdapter;
+
+ if (MasterAdapterObject != NULL) {
+
+ SavedNeedsMapRegisters = AdapterObject->NeedsMapRegisters;
+ SavedMasterAdapter = AdapterObject->MasterAdapter;
+ AdapterObject->NeedsMapRegisters = TRUE;
+ AdapterObject->MasterAdapter = MasterAdapterObject;
+
+ //
+ // Calculate the number of map registers, the map register number and
+ // the map register base.
+ //
+
+ numberOfMapRegisters = ADDRESS_AND_SIZE_TO_SPAN_PAGES(VirtualAddress, Length);
+ mapRegisterNumber = (LogicalAddress.LowPart - HalpMapBufferPhysicalAddress.LowPart) >> PAGE_SHIFT;
+
+ mapRegisterBase = (PTRANSLATION_ENTRY) MasterAdapterObject->MapRegisterBase
+ + mapRegisterNumber;
+
+ //
+ // Free the map registers.
+ //
+
+ IoFreeMapRegisters(
+ AdapterObject,
+ (PVOID) mapRegisterBase,
+ numberOfMapRegisters
+ );
+
+ AdapterObject->NeedsMapRegisters = SavedNeedsMapRegisters;
+ AdapterObject->MasterAdapter = SavedMasterAdapter;
+
+ }
+
+ return;
+
+}
+
+VOID
+IoFreeAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to deallocate the specified adapter object.
+ Any map registers that were allocated are also automatically deallocated.
+ No checks are made to ensure that the adapter is really allocated to
+ a device object. However, if it is not, then kernel will bugcheck.
+
+ If another device is waiting in the queue to allocate the adapter object
+ it will be pulled from the queue and its execution routine will be
+ invoked.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object to be deallocated.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PKDEVICE_QUEUE_ENTRY Packet;
+ PWAIT_CONTEXT_BLOCK Wcb;
+ PADAPTER_OBJECT MasterAdapter;
+ BOOLEAN Busy = FALSE;
+ IO_ALLOCATION_ACTION Action;
+ KIRQL Irql;
+ LONG MapRegisterNumber;
+
+ //
+ // Begin by getting the address of the master adapter.
+ //
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ //
+ // Pull requests of the adapter's device wait queue as long as the
+ // adapter is free and there are sufficient map registers available.
+ //
+
+ while( TRUE ) {
+
+ //
+ // Begin by checking to see whether there are any map registers that
+ // need to be deallocated. If so, then deallocate them now.
+ //
+
+ if (AdapterObject->NumberOfMapRegisters != 0) {
+ IoFreeMapRegisters( AdapterObject,
+ AdapterObject->MapRegisterBase,
+ AdapterObject->NumberOfMapRegisters
+ );
+ }
+
+ //
+ // Simply remove the next entry from the adapter's device wait queue.
+ // If one was successfully removed, allocate any map registers that it
+ // requires and invoke its execution routine.
+ //
+
+ Packet = KeRemoveDeviceQueue( &AdapterObject->ChannelWaitQueue );
+ if (Packet == NULL) {
+
+ //
+ // There are no more requests break out of the loop.
+ //
+
+ break;
+ }
+
+ Wcb = CONTAINING_RECORD( Packet,
+ WAIT_CONTEXT_BLOCK,
+ WaitQueueEntry );
+
+ AdapterObject->CurrentWcb = Wcb;
+ AdapterObject->NumberOfMapRegisters = Wcb->NumberOfMapRegisters;
+
+ //
+ // Check to see whether this driver wishes to allocate any map
+ // registers. If so, then queue the device object to the master
+ // adapter queue to wait for them to become available. If the driver
+ // wants map registers, ensure that this adapter has enough total
+ // map registers to satisfy the request.
+ //
+
+ if (Wcb->NumberOfMapRegisters != 0 &&
+ AdapterObject->MasterAdapter != NULL) {
+
+ //
+ // Lock the map register bit map and the adapter queue in the
+ // master adapter object. The channel structure offset is used as
+ // a hint for the register search.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ MapRegisterNumber = -1;
+
+ if (IsListEmpty( &MasterAdapter->AdapterQueue)) {
+ MapRegisterNumber = RtlFindClearBitsAndSet( MasterAdapter->MapRegisters,
+ Wcb->NumberOfMapRegisters,
+ 0
+ );
+ }
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the master adapter where is will wait until some registers
+ // are deallocated.
+ //
+
+ InsertTailList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+ Busy = 1;
+
+ } else {
+
+ AdapterObject->MapRegisterBase = (PVOID)((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ } else {
+
+ AdapterObject->MapRegisterBase = NULL_MAP_REGISTER_BASE;
+ AdapterObject->NumberOfMapRegisters = 0;
+
+ }
+
+ //
+ // If there were either enough map registers available or no map
+ // registers needed to be allocated, invoke the driver's execution
+ // routine now.
+ //
+
+ if (!Busy) {
+ AdapterObject->CurrentWcb = Wcb;
+ Action = Wcb->DeviceRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the execution routine would like to have the adapter
+ // deallocated, then release the adapter object.
+ //
+
+ if (Action == KeepObject) {
+
+ //
+ // This request wants to keep the channel a while so break
+ // out of the loop.
+ //
+
+ break;
+
+ }
+
+ //
+ // If the driver wants to keep the map registers then set the
+ // number allocated to 0. This keeps the deallocation routine
+ // from deallocating them.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+
+ } else {
+
+ //
+ // This request did not get the requested number of map registers so
+ // out of the loop.
+ //
+
+ break;
+ }
+ }
+}
+
+VOID
+IoFreeMapRegisters(
+ PADAPTER_OBJECT AdapterObject,
+ PVOID MapRegisterBase,
+ ULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ This routine deallocates the map registers for the adapter. If there are
+ any queued adapter waiting for an attempt is made to allocate the next
+ entry.
+
+Arguments:
+
+ AdapterObject - The adapter object to where the map register should be
+ returned.
+
+ MapRegisterBase - The map register base of the registers to be deallocated.
+
+ NumberOfMapRegisters - The number of registers to be deallocated.
+
+Return Value:
+
+ None
+
+--+*/
+{
+ PADAPTER_OBJECT MasterAdapter;
+ LONG MapRegisterNumber;
+ PWAIT_CONTEXT_BLOCK Wcb;
+ PLIST_ENTRY Packet;
+ IO_ALLOCATION_ACTION Action;
+ KIRQL Irql;
+
+
+ //
+ // Begin by getting the address of the master adapter.
+ //
+
+ if (AdapterObject->MasterAdapter != NULL && MapRegisterBase != NULL_MAP_REGISTER_BASE) {
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ } else {
+
+ //
+ // There are no map registers to return.
+ //
+
+ return;
+ }
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ MapRegisterBase = (PVOID) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ MapRegisterNumber = (PTRANSLATION_ENTRY) MapRegisterBase -
+ (PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase;
+
+ //
+ // Acquire the master adapter spinlock which locks the adapter queue and the
+ // bit map for the map registers.
+ //
+
+ KeAcquireSpinLock(&MasterAdapter->SpinLock, &Irql);
+
+ //
+ // Return the registers to the bit map.
+ //
+
+ RtlClearBits( MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ NumberOfMapRegisters
+ );
+
+ //
+ // Process any requests waiting for map registers in the adapter queue.
+ // Requests are processed until a request cannot be satisfied or until
+ // there are no more requests in the queue.
+ //
+
+ while(TRUE) {
+
+ if ( IsListEmpty(&MasterAdapter->AdapterQueue) ){
+ break;
+ }
+
+ Packet = RemoveHeadList( &MasterAdapter->AdapterQueue );
+ AdapterObject = CONTAINING_RECORD( Packet,
+ ADAPTER_OBJECT,
+ AdapterQueue
+ );
+ Wcb = AdapterObject->CurrentWcb;
+
+ //
+ // Attempt to allocate map registers for this request. Use the previous
+ // register base as a hint.
+ //
+
+ MapRegisterNumber = RtlFindClearBitsAndSet( MasterAdapter->MapRegisters,
+ AdapterObject->NumberOfMapRegisters,
+ MasterAdapter->NumberOfMapRegisters
+ );
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Put this request back on
+ // the adapter queue where is came from.
+ //
+
+ InsertHeadList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+
+ break;
+
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }
+
+ //
+ // Invoke the driver's execution routine now.
+ //
+
+ Action = Wcb->DeviceRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the driver wishes to keep the map registers then set the number
+ // allocated to zero and set the action to deallocate object.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ Action = DeallocateObject;
+ }
+
+ //
+ // If the driver would like to have the adapter deallocated,
+ // then deallocate any map registers allocated and then release
+ // the adapter object.
+ //
+
+ if (Action == DeallocateObject) {
+
+ //
+ // The map registers registers are deallocated here rather than in
+ // IoFreeAdapterChannel. This limits the number of times
+ // this routine can be called recursively possibly overflowing
+ // the stack. The worst case occurs if there is a pending
+ // request for the adapter that uses map registers and whos
+ // excution routine decallocates the adapter. In that case if there
+ // are no requests in the master adapter queue, then IoFreeMapRegisters
+ // will get called again.
+ //
+
+ if (AdapterObject->NumberOfMapRegisters != 0) {
+
+ //
+ // Deallocate the map registers and clear the count so that
+ // IoFreeAdapterChannel will not deallocate them again.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ RtlClearBits( MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ AdapterObject->NumberOfMapRegisters
+ );
+
+ AdapterObject->NumberOfMapRegisters = 0;
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+ }
+
+ IoFreeAdapterChannel( AdapterObject );
+ }
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+}
+
+BOOLEAN
+HalpCreateDmaStructures (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for DMA operations
+ and connects the intermediate interrupt dispatcher. It also connects
+ an interrupt handler to the DMA channel interrupt.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher is connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ ULONG i;
+ BOOLEAN ReturnValue;
+
+ //
+ // Initialize EISA bus interrupts.
+ //
+
+ for(i=0;i<HalpNumberOfIsaBusses;i++) {
+ ReturnValue = HalpCreateEisaStructures(i);
+ }
+
+ return(ReturnValue);
+}
+
diff --git a/private/ntos/nthals/halflex/xxinithl.c b/private/ntos/nthals/halflex/xxinithl.c
new file mode 100644
index 000000000..4c91ae959
--- /dev/null
+++ b/private/ntos/nthals/halflex/xxinithl.c
@@ -0,0 +1,286 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ xxinithl.c
+
+Abstract:
+
+
+ This module implements the initialization of the system dependent
+ functions that define the Hardware Architecture Layer (HAL) for a
+ MIPS R3000 or R4000 system.
+
+Author:
+
+ David N. Cutler (davec) 25-Apr-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "iousage.h"
+
+//
+// Constants
+//
+
+ADDRESS_USAGE
+UniFlexPCIMainMemorySpace = {
+ NULL, CmResourceTypeMemory, PCIUsage,
+ {
+ __0MB, __1GB, // Start=0MB; Length=1GB
+ 0,0
+ }
+};
+
+//ADDRESS_USAGE
+//UniFlexPCIReservedMemorySpace = {
+// NULL, CmResourceTypeMemory, PCIUsage,
+// {
+// __1GB + __128MB, __2GB + __1GB - __128MB, // Start=0MB; Length=1GB
+// 0,0
+// }
+//};
+
+//ADDRESS_USAGE
+//UniFlexPCIReservedIoSpace = {
+// NULL, CmResourceTypePort, PCIUsage,
+// {
+// __32MB, ~(__32MB) + 1, // Start=32MB; Length= 4GB - 32MB
+// 0,0
+// }
+//};
+
+//
+// Type Declarations
+//
+
+typedef
+VOID
+(*PGET_PLATFORM_PARAMETER_BLOCK) (
+ OUT PLATFORM_PARAMETER_BLOCK **PlatformParameterBlock
+ );
+
+//
+// Global Veriables
+//
+
+KAFFINITY HalpActiveProcessors;
+ULONG HalpBusType = UNIFLEX_MACHINE_TYPE_EISA;
+ULONG HalpMapBufferSize;
+PHYSICAL_ADDRESS HalpMapBufferPhysicalAddress;
+PLATFORM_PARAMETER_BLOCK *HalpPlatformParameterBlock = NULL;
+PLATFORM_SPECIFIC_EXTENSION *HalpPlatformSpecificExtension = NULL;
+
+
+VOID HalpGetPlatformParameterBlock(VOID)
+
+/*++
+
+Routine Description:
+
+ This function gets the PlatformParameterBlock data structure from the
+ firmware. If the PlatformParameterBlock is not available, then the
+ system is halted.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PSYSTEM_PARAMETER_BLOCK SystemParameterBlock = SYSTEM_BLOCK;
+ PGET_PLATFORM_PARAMETER_BLOCK PrivateGetPlatformParameterBlock;
+
+ //
+ // Get Platform Parameter Block from Firmware
+ //
+
+ if ((SystemParameterBlock->VendorVectorLength / 4) >= 37) {
+ PrivateGetPlatformParameterBlock = *(PGET_PLATFORM_PARAMETER_BLOCK *)((ULONG)(SystemParameterBlock->VendorVector) + 37*4);
+ PrivateGetPlatformParameterBlock(&HalpPlatformParameterBlock);
+ HalpPlatformSpecificExtension = (PLATFORM_SPECIFIC_EXTENSION *)(HalpPlatformParameterBlock->PlatformSpecificExtension);
+ } else {
+
+ //
+ // HALT system. No platform parameter block available.
+ //
+
+ for(;;);
+ }
+}
+
+BOOLEAN
+HalInitSystem (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes the Hardware Architecture Layer (HAL) for a
+ MIPS R3000 or R4000 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;
+
+ Prcb = KeGetCurrentPrcb();
+ if (Phase == 0) {
+
+ //
+ // Phase 0 initialization.
+ //
+
+ //
+ // Verify that the processor block major version number conform
+ // to the system that is being loaded.
+ //
+
+ if (Prcb->MajorVersion != PRCB_MAJOR_VERSION) {
+ KeBugCheck(MISMATCHED_HAL);
+ }
+
+ //
+ // Set the active processor affinity mask.
+ //
+
+ HalpActiveProcessors = 1 << Prcb->Number;
+
+ //
+ // Set the DMA I/O Coherency to not coherent. This means that the instruction
+ // cache is not coherent with DMA, and the data cache is not coherent with DMA
+ // on either reads or writes.
+ //
+
+ KeSetDmaIoCoherency(0);
+
+ //
+ // Set the time increment value.
+ //
+
+ HalpCurrentTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextIntervalCount = 0;
+ KeSetTimeIncrement(MAXIMUM_INCREMENT, MINIMUM_INCREMENT);
+
+ //
+ // Fill in handlers for APIs which this HAL supports
+ //
+
+ HalQuerySystemInformation = HaliQuerySystemInformation;
+ HalSetSystemInformation = HaliSetSystemInformation;
+ HalRegisterBusHandler = HaliRegisterBusHandler;
+ HalHandlerForBus = HaliHandlerForBus;
+ HalHandlerForConfigSpace = HaliHandlerForConfigSpace;
+
+ //
+ // Get Platform Parameter Block from Firmware
+ //
+
+ HalpGetPlatformParameterBlock();
+
+ //
+ // Do platform specific initialization.
+ //
+
+ HalpInitSystem(Phase,LoaderBlock);
+
+ //
+ // Initialize interrupts.
+ //
+
+ HalpInitializeInterrupts();
+
+ //
+ // Register HAL Reserved Address Spaces
+ //
+
+// HalpRegisterAddressUsage (&UniFlexPCIMainMemorySpace);
+// HalpRegisterAddressUsage (&UniFlexPCIReservedMemorySpace);
+// HalpRegisterAddressUsage (&UniFlexPCIReservedIoSpace);
+
+ return TRUE;
+
+ } else {
+
+ //
+ // Phase 1 initialization.
+ //
+
+ //
+ // Do platform specific initialization.
+ //
+
+ HalpInitSystem(Phase,LoaderBlock);
+
+ return TRUE;
+ }
+}
+
+
+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;
+}
+
+VOID
+HalpVerifyPrcbVersion ()
+{
+
+}
+
+
+
diff --git a/private/ntos/nthals/halflex/xxpcisup.c b/private/ntos/nthals/halflex/xxpcisup.c
new file mode 100644
index 000000000..ebe41bd0d
--- /dev/null
+++ b/private/ntos/nthals/halflex/xxpcisup.c
@@ -0,0 +1,2391 @@
+/*++
+
+
+Copyright (C) 1989-1995 Microsoft Corporation
+Copyright (C) 1994,1995 Digital Equipment Corporation
+
+Module Name:
+
+ pcisup.c
+
+Abstract:
+
+ Platform-independent PCI bus routines
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+
+typedef ULONG (*FncConfigIO) (
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+typedef struct {
+ FncConfigIO ConfigRead[3];
+ FncConfigIO ConfigWrite[3];
+} CONFIG_HANDLER, *PCONFIG_HANDLER;
+
+
+//
+// Define PCI slot validity
+//
+typedef enum _VALID_SLOT {
+ InvalidBus = 0,
+ InvalidSlot,
+ ValidSlot
+} VALID_SLOT;
+
+//
+// Local prototypes for routines supporting PCI bus handler routines
+//
+
+ULONG
+HalpGetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG
+HalpSetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+
+NTSTATUS
+HalpAdjustPCIResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+
+NTSTATUS
+HalpAssignPCISlotResources (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN ULONG Slot,
+ IN OUT PCM_RESOURCE_LIST *pAllocatedResources
+ );
+
+VOID
+HalpReadPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+VOID
+HalpWritePCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+VALID_SLOT
+HalpValidPCISlot (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ );
+
+VOID
+HalpPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN FncConfigIO *ConfigIO
+ );
+
+ULONG HalpPCIReadUlong (
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUchar (
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUshort (
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUlong (
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUchar (
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUshort (
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+VOID
+HalpPCILine2PinNop (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciNewData,
+ IN PPCI_COMMON_CONFIG PciOldData
+ );
+
+VOID
+HalpPCIPin2LineNop (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ );
+
+#if DBG
+BOOLEAN
+HalpValidPCIAddr(
+ IN PBUS_HANDLER BusHandler,
+ IN PHYSICAL_ADDRESS BAddr,
+ IN ULONG Length,
+ IN ULONG AddressSpace
+ );
+#endif
+
+//
+// Local prototypes of functions that are not built for Alpha AXP firmware
+//
+
+NTSTATUS
+HalpAssignPCISlotResources (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN ULONG Slot,
+ IN OUT PCM_RESOURCE_LIST *pAllocatedResources
+ );
+
+#if DBG
+VOID
+HalpTestPci (
+ ULONG
+ );
+#endif
+
+//
+// Pragmas to assign functions to different kinds of pages.
+//
+
+#if !defined(AXP_FIRMWARE)
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpInitializePCIBus)
+#pragma alloc_text(INIT,HalpAllocateAndInitPCIBusHandler)
+#pragma alloc_text(INIT,HalpRegisterPCIInstallHandler )
+#pragma alloc_text(INIT,HalpDefaultPCIInstallHandler )
+#pragma alloc_text(INIT,HalpDeterminePCIDevicesPresent )
+#pragma alloc_text(PAGE,HalpAssignPCISlotResources)
+#pragma alloc_text(PAGE,HalpAdjustPCIResourceList)
+#endif // ALLOC_PRAGMA
+#endif // !defined(AXP_FIRMWARE)
+
+#ifdef AXP_FIRMWARE
+
+#define ExFreePool(PoolData)
+
+#pragma alloc_text(DISTEXT, HalpInitializePCIBus )
+#pragma alloc_text(DISTEXT, HalpAllocateAndInitPCIBusHandler)
+#pragma alloc_text(DISTEXT, HalpRegisterPCIInstallHandler )
+#pragma alloc_text(DISTEXT, HalpDefaultPCIInstallHandler )
+#pragma alloc_text(DISTEXT, HalpDeterminePCIDevicesPresent )
+#pragma alloc_text(DISTEXT, HalpGetPCIData )
+#pragma alloc_text(DISTEXT, HalpSetPCIData )
+#pragma alloc_text(DISTEXT, HalpReadPCIConfig )
+#pragma alloc_text(DISTEXT, HalpWritePCIConfig )
+#pragma alloc_text(DISTEXT, HalpValidPCISlot )
+#if DBG
+#pragma alloc_text(DISTEXT, HalpValidPCIAddr )
+#endif
+#pragma alloc_text(DISTEXT, HalpPCIConfig )
+#pragma alloc_text(DISTEXT, HalpPCIReadUchar )
+#pragma alloc_text(DISTEXT, HalpPCIReadUshort )
+#pragma alloc_text(DISTEXT, HalpPCIReadUlong )
+#pragma alloc_text(DISTEXT, HalpPCIWriteUchar )
+#pragma alloc_text(DISTEXT, HalpPCIWriteUshort )
+#pragma alloc_text(DISTEXT, HalpPCIWriteUlong )
+#pragma alloc_text(DISTEXT, HalpAssignPCISlotResources)
+#pragma alloc_text(DISTEXT, HalpAdjustPCIResourceList)
+
+#endif // AXP_FIRMWARE
+
+
+//
+// Globals
+//
+
+KSPIN_LOCK HalpPCIConfigLock;
+BOOLEAN PCIInitialized = FALSE;
+ULONG PCIMaxLocalDevice;
+ULONG PCIMaxDevice;
+ULONG PCIMaxBus;
+PINSTALL_BUS_HANDLER PCIInstallHandler = HalpDefaultPCIInstallHandler;
+
+CONFIG_HANDLER PCIConfigHandlers = {
+ {
+ HalpPCIReadUlong, // 0
+ HalpPCIReadUchar, // 1
+ HalpPCIReadUshort // 2
+ },
+ {
+ HalpPCIWriteUlong, // 0
+ HalpPCIWriteUchar, // 1
+ HalpPCIWriteUshort // 2
+ }
+};
+UCHAR PCIDeref[4][4] = { {0,1,2,2},{1,1,1,1},{2,1,2,2},{1,1,1,1} };
+
+WCHAR rgzMultiFunctionAdapter[] = L"\\Registry\\Machine\\Hardware\\Description\\System\\MultifunctionAdapter";
+WCHAR rgzConfigurationData[] = L"Configuration Data";
+WCHAR rgzIdentifier[] = L"Identifier";
+WCHAR rgzPCIIndetifier[] = L"PCI";
+
+#define Is64BitBaseAddress(a) \
+ (((a & PCI_ADDRESS_IO_SPACE) == 0) && \
+ ((a & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_64BIT))
+
+
+VOID
+HalpInitializePCIBus (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ The function intializes global PCI bus state from the registry.
+
+ The Arc firmware is responsible for building configuration information
+ about the number of PCI buses on the system and nature (local vs. secondary
+ - across a PCI-PCI bridge) of the each bus. This state is held in
+ PCIRegInfo.
+
+ The maximum virtual slot number on the local (type 0 config cycle)
+ PCI bus is registered here, based on the machine dependent define
+ PCI_MAX_LOCAL_DEVICE. This state is carried in PCIMaxLocalDevice.
+
+ The maximum number of virtual slots on a secondary bus is fixed by the
+ PCI Specification and is represented by PCI_MAX_DEVICES. This
+ state is held in PCIMaxDevice.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+
+--*/
+{
+
+#if !defined(AXP_FIRMWARE)
+
+ //
+ // x86 Hal's can query the registry, while on Alpha pltforms we cannot.
+ // So we let the ARC firmware actually configure the bus/bridges.
+ //
+
+ PCI_SLOT_NUMBER SlotNumber;
+ ULONG DeviceNumber;
+ ULONG FunctionNumber;
+ PCI_COMMON_CONFIG CommonConfig;
+ ULONG BusNumber;
+ ULONG ibus;
+ PBUS_HANDLER Bus0;
+
+ //
+ // Has the PCI bus already been initialized?
+ //
+
+ if (PCIInitialized) {
+ return;
+ }
+
+ //
+ // Intialize PCI configuration to the maximum configuration for starters.
+ //
+
+ PCIMaxLocalDevice = PCI_MAX_LOCAL_DEVICE;
+ PCIMaxDevice = PCI_MAX_DEVICES - 1;
+
+ //
+ // Unless there exists any PCI-to-PCI bridges, there will only be 1
+ // bus.
+ //
+
+ PCIMaxBus = 1;
+
+ //
+ // For each "local" PCI bus present, allocate a handler structure and
+ // fill in the dispatch functions
+ //
+ // After we determine how many "remote" PCI buses are present, we will
+ // add them.
+ //
+
+ for (ibus = 0; ibus < PCIMaxBus; ibus++) {
+
+ //
+ // If handler not already built, do it now
+ //
+
+ if (!HaliHandlerForBus (PCIBus, ibus)) {
+ HalpAllocateAndInitPCIBusHandler (ibus);
+ }
+ }
+ //
+ // Initialize the slot number struct.
+ //
+
+ SlotNumber.u.AsULONG = 0;
+
+ //
+ // Loop through each device.
+ //
+
+ Bus0 = HaliHandlerForBus(PCIBus, 0);
+
+ for (DeviceNumber = 0; DeviceNumber < PCI_MAX_DEVICES; DeviceNumber++) {
+
+ SlotNumber.u.bits.DeviceNumber = DeviceNumber;
+
+ //
+ // Loop through each function.
+ //
+
+ for (FunctionNumber = 0; FunctionNumber < PCI_MAX_FUNCTION; FunctionNumber++) {
+ SlotNumber.u.bits.FunctionNumber = FunctionNumber;
+
+ //
+ // Read the device's configuration space.
+ //
+
+ HalpReadPCIConfig(Bus0,
+ SlotNumber,
+ &CommonConfig,
+ 0,
+ PCI_COMMON_HDR_LENGTH);
+
+ //
+ // No device exists at this device/function number.
+ //
+
+ if (CommonConfig.VendorID == PCI_INVALID_VENDORID) {
+
+ //
+ // If this is the first function number, then break, because
+ // we know a priori there will not be any devices on the
+ // other function numbers.
+ //
+
+ if (FunctionNumber == 0) {
+ break;
+ }
+
+ //
+ // Check the next function number.
+ //
+
+ continue;
+ }
+
+ //
+ // A PCI-to-PCI bridge has been discovered.
+ //
+
+ if (CommonConfig.BaseClass == 0x06 &&
+ CommonConfig.SubClass == 0x04 &&
+ CommonConfig.ProgIf == 0x00) {
+
+ //
+ // Get the subordinate bus number (which is the highest
+ // numbered bus this bridge will forward to) and add 1.
+ //
+
+ BusNumber = CommonConfig.u.type1.SubordinateBus + 1;
+
+ //
+ // The maximum subordinate across the local bus is the
+ // maximum number of busses.
+ //
+
+ if (PCIMaxBus < BusNumber) {
+ PCIMaxBus = BusNumber;
+ }
+ }
+
+ //
+ // If this is not a multi-function device then break out now.
+ //
+
+ if ((CommonConfig.HeaderType & PCI_MULTIFUNCTION) == 0) {
+ break;
+ }
+ }
+ }
+
+ //
+ // For each additional PCI bus present, allocate a handler structure and
+ // fill in the dispatch functions. If there are no additional
+ // PCI buses, (i.e., no PCI-PCI bridges were found), this loop
+ // will exit before a single iteration.
+ //
+
+ for (ibus = 1; ibus < PCIMaxBus; ibus++) {
+
+ //
+ // If handler not already built, do it now
+ //
+
+ if (!HaliHandlerForBus (PCIBus, ibus)) {
+ HalpAllocateAndInitPCIBusHandler (ibus);
+ }
+ }
+
+ KeInitializeSpinLock (&HalpPCIConfigLock);
+ PCIInitialized = TRUE;
+
+#if DBG
+ HalpTestPci (0);
+#endif
+
+#else
+
+ PCIMaxLocalDevice = PCI_MAX_LOCAL_DEVICE;
+ PCIMaxDevice = PCI_MAX_DEVICES - 1;
+ PCIMaxBus = PCI_MAX_BUSSES;
+
+ //
+ // Note:
+ // Firmware will allocate bus handlers during
+ // PCI configuration.
+ //
+
+ KeInitializeSpinLock (&HalpPCIConfigLock);
+ PCIInitialized = TRUE;
+
+#endif // !AXP_FIRMWARE
+
+}
+
+PBUS_HANDLER
+HalpAllocateAndInitPCIBusHandler (
+ IN ULONG BusNo
+ )
+{
+ PBUS_HANDLER Bus;
+
+ HaliRegisterBusHandler (
+ PCIBus, // Interface type
+ PCIConfiguration, // Has this configuration space
+ BusNo, // Bus Number
+ Internal, // child of this bus
+ 0, // and number
+ sizeof (PCIPBUSDATA), // sizeof bus specific buffer
+ PCIInstallHandler, // PCI install handler
+ &Bus); // Bushandler return
+
+ return Bus;
+}
+
+NTSTATUS
+HalpDefaultPCIInstallHandler(
+ IN PBUS_HANDLER Bus
+ )
+{
+ PPCIPBUSDATA BusData;
+
+ //
+ // Fill in PCI handlers
+ //
+
+ Bus->GetBusData = (PGETSETBUSDATA) HalpGetPCIData;
+ Bus->SetBusData = (PGETSETBUSDATA) HalpSetPCIData;
+ Bus->AdjustResourceList = (PADJUSTRESOURCELIST) HalpAdjustPCIResourceList;
+ Bus->AssignSlotResources = (PASSIGNSLOTRESOURCES) HalpAssignPCISlotResources;
+
+ BusData = (PPCIPBUSDATA) Bus->BusData;
+
+ //
+ // Fill in common PCI data
+ //
+
+ BusData->CommonData.Tag = PCI_DATA_TAG;
+ BusData->CommonData.Version = PCI_DATA_VERSION;
+ BusData->CommonData.ReadConfig = (PciReadWriteConfig)HalpReadPCIConfig;
+ BusData->CommonData.WriteConfig = (PciReadWriteConfig)HalpWritePCIConfig;
+ BusData->CommonData.Pin2Line = (PciPin2Line)HalpPCIPin2LineNop;
+ BusData->CommonData.Line2Pin = (PciLine2Pin)HalpPCILine2PinNop;
+
+
+ // set defaults
+ //
+ // ecrfix - if we knew more about the PCI bus at this
+ // point (e.g., local vs. across bridge, PCI config
+ // space base QVA, APECS vs. Sable T2/T4 vs. LCA4 vs. ??? config
+ // cycle type 0 mechanism), we could put this info into
+ // the "BusData" structure. The nice thing about this is
+ // that we could eliminate the platform-dependent module
+ // PCIBUS.C.
+ //
+
+ BusData->MaxDevice = PCI_MAX_DEVICES - 1; // not currently used anywhere
+
+#if !defined(AXP_FIRMWARE)
+ //
+ // Perform DevicePresent scan for this bus.
+ //
+
+ HalpDeterminePCIDevicesPresent(Bus);
+#endif // !AXP_FIRMWARE
+
+ return STATUS_SUCCESS;
+}
+
+VOID
+HalpRegisterPCIInstallHandler(
+ IN PINSTALL_BUS_HANDLER MachineSpecificPCIInstallHandler
+)
+/*++
+
+Routine Description:
+
+ The function register's a machine-specific PCI Install Handler.
+ This allows a specific platform to override the default PCI install
+ handler, DefaultPCIInstallHandler().
+
+Arguments:
+
+ MachineSpecificPCIInstallHandler - Function that provides machine
+ specific PCI Bus Handler setup.
+
+Return Value:
+
+ None.
+
+
+--*/
+{
+ PCIInstallHandler = MachineSpecificPCIInstallHandler;
+
+ return;
+}
+
+VOID
+HalpDeterminePCIDevicesPresent(
+ IN PBUS_HANDLER Bus
+)
+/*++
+
+Routine Description:
+
+ The function determines which PCI devices and functions are
+ present on a given PCI bus. An RTL_BITMAP vector in the bus handler's
+ PCI-specific BusData is updated to reflect the devices that actually
+ exist on this bus.
+
+ THIS COULD BE DONE IN FIRMWARE!
+
+Arguments:
+
+ Bus - BusHandler for the bus to be searched. This bus handler must
+ have already been allocated and initialized.
+
+Return Value:
+
+ None.
+
+
+--*/
+{
+ PCI_COMMON_CONFIG CommonConfig;
+ PCI_SLOT_NUMBER Slot;
+ ULONG DeviceNumber;
+ ULONG FunctionNumber;
+ ULONG cnt;
+ RTL_BITMAP DevicePresent;
+ PPCIPBUSDATA BusData;
+
+ //
+ // Formally disable DevicePresent checking for this bus.
+ //
+
+ BusData = (PPCIPBUSDATA) Bus->BusData;
+ BusData->DevicePresent.Buffer = NULL;
+
+ //
+ // Initialize local copy of device present bitmap
+ // (Can't update bus handler data because we need to probe
+ // the bus in question.)
+ //
+
+ RtlInitializeBitMap (&DevicePresent,
+ BusData->DevicePresentBits, 256);
+
+ //
+ // For this bus, probe each possible slot. If no device
+ // is present than indicate that in the DevicePresent structure.
+ //
+
+ Slot.u.AsULONG = 0;
+
+ for( DeviceNumber=0; DeviceNumber < PCI_MAX_DEVICES; DeviceNumber++ ){
+
+ Slot.u.bits.DeviceNumber = DeviceNumber;
+
+ for (FunctionNumber = 0; FunctionNumber < PCI_MAX_FUNCTION; FunctionNumber++)
+ {
+
+ Slot.u.bits.FunctionNumber = FunctionNumber;
+
+ //
+ // Read only first ULONG of PCI config space, which
+ // contains the Vendor ID.
+ //
+ // (DevicePresent checking is *not* in effect yet
+ // for this bus.)
+ //
+
+ HalpReadPCIConfig(Bus,
+ Slot,
+ &CommonConfig,
+ 0,
+ sizeof(ULONG));
+
+ //
+ // See if a device & function is present. If so, set a bit.
+ //
+
+ if (CommonConfig.VendorID != PCI_INVALID_VENDORID) {
+ cnt = PciBitIndex(Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber);
+ RtlSetBits (&DevicePresent, cnt, 1);
+ }
+
+ } // end for( FunctionNumber=0; ...
+
+ } // end for( DeviceNumber=0; ...
+
+ //
+ // Update bus data now that we know what's present on the bus.
+ // (DevicePresent checking is now in effect yet for this bus.)
+ //
+
+ BusData->DevicePresent = DevicePresent;
+
+ return;
+
+}
+
+
+ULONG
+HalpGetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the PCI bus data for a device.
+
+Arguments:
+
+ BusHandler - Registered BUSHANDLER for the target configuration space
+
+ RootHandler - Register BUSHANDLER for the orginating HalGetBusData request.
+
+ VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word)
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+ If this PCI slot has never been set, then the configuration information
+ returned is zeroed.
+
+
+--*/
+{
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ ULONG Len;
+ PCI_SLOT_NUMBER PciSlot;
+
+ if (Length > sizeof (PCI_COMMON_CONFIG)) {
+ Length = sizeof (PCI_COMMON_CONFIG);
+ }
+
+ Len = 0;
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+ PciSlot = *((PPCI_SLOT_NUMBER) &Slot);
+
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The user did not request any data from the common
+ // header. Verify the PCI device exists, then continue
+ // in the device specific area.
+ //
+
+ HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, sizeof(ULONG));
+
+ //
+ // Check for invalid slot
+ //
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ return 0;
+ }
+
+ } else {
+
+ //
+ // Caller requested at least some data within the
+ // common header. Read the whole header, effect the
+ // fields we need to and then copy the user's requested
+ // bytes from the header
+ //
+
+ //
+ // Read this PCI devices slot data
+ //
+
+ Len = PCI_COMMON_HDR_LENGTH;
+ HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, Len);
+
+ //
+ // Check for invalid slot
+ //
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != 0) {
+ PciData->VendorID = PCI_INVALID_VENDORID;
+ Len = 2; // only return invalid id
+ }
+
+ //
+ // Copy whatever data overlaps into the callers buffer
+ //
+
+ if (Len < Offset) {
+ // no data at caller's buffer
+ return 0;
+ }
+
+ Len -= Offset;
+ if (Len > Length) {
+ Len = Length;
+ }
+
+ RtlMoveMemory(Buffer, iBuffer + Offset, Len);
+
+ Offset += Len;
+ Buffer += Len;
+ Length -= Len;
+ }
+
+ if (Length) {
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The remaining Buffer comes from the Device Specific
+ // area - put on the kitten gloves and read from it.
+ //
+ // Specific read/writes to the PCI device specific area
+ // are guarenteed:
+ //
+ // Not to read/write any byte outside the area specified
+ // by the caller. (this may cause WORD or BYTE references
+ // to the area in order to read the non-dword aligned
+ // ends of the request)
+ //
+ // To use a WORD access if the requested length is exactly
+ // a WORD long.
+ //
+ // To use a BYTE access if the requested length is exactly
+ // a BYTE long.
+ //
+
+ HalpReadPCIConfig (BusHandler, PciSlot, Buffer, Offset, Length);
+
+
+ Len += Length;
+ }
+ }
+
+ return Len;
+}
+
+ULONG
+HalpSetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Pci bus data for a device.
+
+Arguments:
+
+ BusHandler - Registered BUSHANDLER for the target configuration space
+
+ RootHandler - Register BUSHANDLER for the orginating HalSetBusData request.
+
+ VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word)
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+{
+ PPCI_COMMON_CONFIG PciData, PciData2;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ UCHAR iBuffer2[PCI_COMMON_HDR_LENGTH];
+ ULONG Len;
+ PCI_SLOT_NUMBER PciSlot;
+
+ if (Length > sizeof (PCI_COMMON_CONFIG)) {
+ Length = sizeof (PCI_COMMON_CONFIG);
+ }
+
+
+ Len = 0;
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+ PciData2 = (PPCI_COMMON_CONFIG) iBuffer2;
+ PciSlot = *((PPCI_SLOT_NUMBER) &Slot);
+
+
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The user did not request any data from the common
+ // header. Verify the PCI device exists, then continue in
+ // the device specific area.
+ //
+
+ HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, sizeof(ULONG));
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PciData->VendorID == 0x00) {
+ return 0;
+ }
+
+ } else {
+
+ //
+ // Caller requested to set at least some data within the
+ // common header.
+ //
+
+ Len = PCI_COMMON_HDR_LENGTH;
+ HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, Len);
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PciData->VendorID == 0x00 ||
+ PCI_CONFIG_TYPE (PciData) != 0) {
+
+ // no device, or header type unkown
+ return 0;
+ }
+
+ //
+ // Copy COMMON_HDR values to buffer2, then overlay callers changes.
+ //
+
+ RtlMoveMemory (iBuffer2, iBuffer, Len);
+
+ Len -= Offset;
+ if (Len > Length) {
+ Len = Length;
+ }
+
+ RtlMoveMemory (iBuffer2+Offset, Buffer, Len);
+
+#if DBG
+ //
+ // Verify R/O fields haven't changed
+ //
+ if (PciData2->VendorID != PciData->VendorID ||
+ PciData2->DeviceID != PciData->DeviceID ||
+ PciData2->RevisionID != PciData->RevisionID ||
+ PciData2->ProgIf != PciData->ProgIf ||
+ PciData2->SubClass != PciData->SubClass ||
+ PciData2->BaseClass != PciData->BaseClass ||
+ PciData2->HeaderType != PciData->HeaderType ||
+ PciData2->BaseClass != PciData->BaseClass ||
+ PciData2->u.type0.MinimumGrant != PciData->u.type0.MinimumGrant ||
+ PciData2->u.type0.MaximumLatency != PciData->u.type0.MaximumLatency) {
+ DbgPrint ("PCI SetBusData: Read-Only configation value changed\n");
+ DbgBreakPoint ();
+ }
+#endif // DBG
+ //
+ // Set new PCI configuration
+ //
+
+ HalpWritePCIConfig (BusHandler, PciSlot, iBuffer2+Offset, Offset, Len);
+
+ Offset += Len;
+ Buffer += Len;
+ Length -= Len;
+ }
+
+ if (Length) {
+
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The remaining Buffer comes from the Device Specific
+ // area - put on the kitten gloves and write it
+ //
+ // Specific read/writes to the PCI device specific area
+ // are guarenteed:
+ //
+ // Not to read/write any byte outside the area specified
+ // by the caller. (this may cause WORD or BYTE references
+ // to the area in order to read the non-dword aligned
+ // ends of the request)
+ //
+ // To use a WORD access if the requested length is exactly
+ // a WORD long.
+ //
+ // To use a BYTE access if the requested length is exactly
+ // a BYTE long.
+ //
+
+ HalpWritePCIConfig (BusHandler, PciSlot, Buffer, Offset, Length);
+
+ Len += Length;
+ }
+ }
+
+ return Len;
+}
+
+VOID
+HalpPCILine2PinNop (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciNewData,
+ IN PPCI_COMMON_CONFIG PciOldData
+ )
+{
+ // line-pin mappings not needed on alpha machines
+ return ;
+}
+
+VOID
+HalpPCIPin2LineNop (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ )
+{
+ // line-pin mappings not needed on alpha machines
+ return ;
+}
+
+VOID
+HalpReadPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+#if 0
+ if (!HalpValidPCISlot (BusHandler, Slot)) {
+ //
+ // Invalid SlotID return no data
+ //
+
+ RtlFillMemory (Buffer, Length, (UCHAR) -1);
+ return ;
+ }
+
+ HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length,
+ PCIConfigHandlers.ConfigRead);
+#endif // 0
+
+ //
+ // Read the slot, if it's valid.
+ // Otherwise, return an Invalid VendorId for a invalid slot on an existing bus
+ // or a null (zero) buffer if we have a non-existant bus.
+ //
+
+ switch (HalpValidPCISlot (BusHandler, Slot))
+ {
+
+ case ValidSlot:
+
+ HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length,
+ PCIConfigHandlers.ConfigRead);
+ break;
+
+ case InvalidSlot:
+
+ //
+ // Invalid SlotID return no data (Invalid Slot ID = 0xFFFF)
+ //
+
+ RtlFillMemory (Buffer, Length, (UCHAR) -1);
+ break ;
+
+ case InvalidBus:
+
+ //
+ // Invalid Bus, return return no data
+ //
+
+ RtlFillMemory (Buffer, Length, (UCHAR) 0);
+ break ;
+ }
+
+ return;
+
+}
+
+VOID
+HalpWritePCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+
+ if (HalpValidPCISlot (BusHandler, Slot) != ValidSlot) {
+ //
+ // Invalid SlotID do nothing
+ //
+ return ;
+ }
+
+ HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length,
+ PCIConfigHandlers.ConfigWrite);
+}
+
+VALID_SLOT
+HalpValidPCISlot (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ )
+{
+ ULONG BusNumber;
+ PPCIPBUSDATA BusData;
+ PCI_SLOT_NUMBER Slot2;
+ PCI_CONFIGURATION_TYPES PciConfigType;
+ UCHAR HeaderType;
+ ULONG i, bit;
+
+ BusNumber = BusHandler->BusNumber;
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ if (Slot.u.bits.Reserved != 0) {
+ return FALSE;
+ }
+
+ //
+ // If the initial device probe has been completed and no device
+ // is present for this slot then simply return invalid slot.
+ //
+
+ bit = PciBitIndex(Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber);
+
+ if( ( (BusData->DevicePresent).Buffer != NULL) &&
+ !RtlCheckBit(&BusData->DevicePresent, bit) ) {
+
+#if HALDBG
+
+ DbgPrint( "Config access supressed for bus = %d, device = %d, function = %d\n",
+ BusNumber,
+ Slot.u.bits.DeviceNumber,
+ Slot.u.bits.FunctionNumber );
+
+#endif // HALDBG
+
+ return InvalidSlot;
+ }
+
+
+ //
+ // Get the config cycle type for the proposed bus.
+ // (PciConfigTypeInvalid indicates a non-existent bus.)
+ //
+
+ PciConfigType = HalpPCIConfigCycleType(BusNumber);
+
+ //
+ // The number of devices allowed on a local PCI bus may be different
+ // than that across a PCI-PCI bridge.
+ //
+
+ switch(PciConfigType) {
+ case PciConfigType0:
+
+ if (Slot.u.bits.DeviceNumber > PCIMaxLocalDevice) {
+#if HALDBG
+ DbgPrint("Invalid local PCI Slot %x\n", Slot.u.bits.DeviceNumber);
+#endif
+ return InvalidSlot;
+ }
+ break;
+
+ case PciConfigType1:
+
+ if (Slot.u.bits.DeviceNumber > PCIMaxDevice) {
+#if HALDBG
+ DbgPrint("Invalid remote PCI Slot %x\n", Slot.u.bits.DeviceNumber);
+#endif
+ return InvalidSlot;
+ }
+ break;
+
+ case PciConfigTypeInvalid:
+
+#if HALDBG
+ DbgPrint("Invalid PCI Bus %x\n", BusNumber);
+#endif
+ return InvalidBus;
+ break;
+
+ }
+
+ //
+ // Check function number
+ //
+
+ if (Slot.u.bits.FunctionNumber == 0) {
+ return ValidSlot;
+ }
+
+ //
+ // Non zero function numbers are only supported if the
+ // device has the PCI_MULTIFUNCTION bit set in it's header
+ //
+
+ i = Slot.u.bits.DeviceNumber;
+
+ //
+ // Read DeviceNumber, Function zero, to determine if the
+ // PCI supports multifunction devices
+ //
+
+ Slot2 = Slot;
+ Slot2.u.bits.FunctionNumber = 0;
+
+ HalpReadPCIConfig (
+ BusHandler,
+ Slot2,
+ &HeaderType,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, HeaderType),
+ sizeof (UCHAR)
+ );
+
+ if (!(HeaderType & PCI_MULTIFUNCTION) || (HeaderType == 0xFF)) {
+ // this device doesn't exists or doesn't support MULTIFUNCTION types
+ return InvalidSlot;
+ }
+
+ return ValidSlot;
+}
+
+VOID
+HalpPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN FncConfigIO *ConfigIO
+ )
+{
+ KIRQL OldIrql;
+ ULONG i;
+ PCI_CFG_CYCLE_BITS PciAddr;
+ ULONG BusNumber;
+
+ BusNumber = BusHandler->BusNumber;
+
+ //
+ // Setup platform-dependent state for configuration space access
+ //
+
+ HalpPCIConfigAddr(BusNumber, Slot, &PciAddr);
+
+ //
+ // Synchronize with PCI config space
+ //
+
+ KeAcquireSpinLock (&HalpPCIConfigLock, &OldIrql);
+
+ //
+ // Do the I/O to PCI configuration space
+ //
+
+ while (Length) {
+ i = PCIDeref[Offset % sizeof(ULONG)][Length % sizeof(ULONG)];
+ i = ConfigIO[i] (&PciAddr, Buffer, Offset);
+
+ Offset += i;
+ Buffer += i;
+ Length -= i;
+ }
+
+ //
+ // Release spinlock
+ //
+
+ KeReleaseSpinLock (&HalpPCIConfigLock, OldIrql);
+
+ return;
+}
+
+ULONG
+HalpPCIReadUchar (
+ IN PPCI_CFG_CYCLE_BITS PciCfg,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG ConfigurationCycleType;
+
+ //
+ // The configuration cycle type is extracted from bits[1:0] of PciCfg.
+ //
+ // Since an LCA4 register generates the configuration cycle type
+ // on the PCI bus, and because Offset bits[1:0] are used to
+ // generate the PCI byte enables (C/BE[3:0]), clear PciCfg bits [1:0]
+ // out before adding in Offset.
+ //
+
+ ConfigurationCycleType = PciCfg->u.bits.Reserved1;
+ PciCfg->u.bits.Reserved1 = 0;
+
+ *Buffer = READ_CONFIG_UCHAR ((PUCHAR) (PciCfg->u.AsULONG + Offset),
+ ConfigurationCycleType);
+
+ //
+ // Reset state to preserve config cycle type across calls
+ //
+
+ PciCfg->u.bits.Reserved1 = ConfigurationCycleType;
+
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIReadUshort (
+ IN PPCI_CFG_CYCLE_BITS PciCfg,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG ConfigurationCycleType;
+
+ ConfigurationCycleType = PciCfg->u.bits.Reserved1;
+ PciCfg->u.bits.Reserved1 = 0;
+
+ *((PUSHORT) Buffer) = READ_CONFIG_USHORT ((PUSHORT) (PciCfg->u.AsULONG + Offset),
+ ConfigurationCycleType);
+ //
+ // Reset state to preserve config cycle type across calls
+ //
+
+ PciCfg->u.bits.Reserved1 = ConfigurationCycleType;
+
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIReadUlong (
+ IN PPCI_CFG_CYCLE_BITS PciCfg,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG ConfigurationCycleType;
+
+ ConfigurationCycleType = PciCfg->u.bits.Reserved1;
+ PciCfg->u.bits.Reserved1 = 0;
+
+ *((PULONG) Buffer) = READ_CONFIG_ULONG ((PULONG) (PciCfg->u.AsULONG + Offset),
+ ConfigurationCycleType);
+ //
+ // Reset state to preserve config cycle type across calls
+ //
+
+ PciCfg->u.bits.Reserved1 = ConfigurationCycleType;
+
+ return sizeof (ULONG);
+}
+
+
+ULONG
+HalpPCIWriteUchar (
+ IN PPCI_CFG_CYCLE_BITS PciCfg,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG ConfigurationCycleType;
+
+ ConfigurationCycleType = PciCfg->u.bits.Reserved1;
+ PciCfg->u.bits.Reserved1 = 0;
+
+ WRITE_CONFIG_UCHAR ((PUCHAR) (PciCfg->u.AsULONG + Offset), *Buffer,
+ ConfigurationCycleType);
+ //
+ // Reset state to preserve config cycle type across calls
+ //
+
+ PciCfg->u.bits.Reserved1 = ConfigurationCycleType;
+
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIWriteUshort (
+ IN PPCI_CFG_CYCLE_BITS PciCfg,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG ConfigurationCycleType;
+
+ ConfigurationCycleType = PciCfg->u.bits.Reserved1;
+ PciCfg->u.bits.Reserved1 = 0;
+
+ WRITE_CONFIG_USHORT ((PUSHORT) (PciCfg->u.AsULONG + Offset), *((PUSHORT) Buffer),
+ ConfigurationCycleType);
+ //
+ // Reset state to preserve config cycle type across calls
+ //
+
+ PciCfg->u.bits.Reserved1 = ConfigurationCycleType;
+
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIWriteUlong (
+ IN PPCI_CFG_CYCLE_BITS PciCfg,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG ConfigurationCycleType;
+
+ ConfigurationCycleType = PciCfg->u.bits.Reserved1;
+ PciCfg->u.bits.Reserved1 = 0;
+
+ WRITE_CONFIG_ULONG ((PULONG) (PciCfg->u.AsULONG + Offset), *((PULONG) Buffer),
+ ConfigurationCycleType);
+ //
+ // Reset state to preserve config cycle type across calls
+ //
+
+ PciCfg->u.bits.Reserved1 = ConfigurationCycleType;
+
+ return sizeof (ULONG);
+}
+
+#if DBG
+
+BOOLEAN
+HalpValidPCIAddr(
+ IN PBUS_HANDLER BusHandler,
+ IN PHYSICAL_ADDRESS BAddr,
+ IN ULONG Length,
+ IN ULONG AddressSpace)
+/*++
+
+Routine Description:
+
+ Checks to see that the begining and ending 64 bit PCI bus addresses
+ of the 32 bit range of length Length are supported on the system.
+
+Arguments:
+
+ BAddr - the 64 bit starting address
+
+ Length - a 32 bit length
+
+ AddressSpace - is this I/O (1) or memory space (0)
+
+Return Value:
+
+ TRUE or FALSE
+
+--*/
+{
+ PHYSICAL_ADDRESS EAddr, TBAddr, TEAddr;
+ LARGE_INTEGER LiILen;
+ ULONG inIoSpace, inIoSpace2;
+ BOOLEAN flag, flag2;
+ ULONG BusNumber;
+
+ BusNumber = BusHandler->BusNumber;
+
+ //
+ // Translated address to system global setting and verify
+ // resource is available.
+ //
+ // Note that this code will need to be changed to support
+ // 64 bit PCI bus addresses.
+ //
+
+ LiILen.QuadPart = (ULONG)(Length - 1); // Inclusive length
+ EAddr.QuadPart = BAddr.QuadPart + LiILen.QuadPart;
+
+ inIoSpace = inIoSpace2 = AddressSpace;
+
+ flag = HalTranslateBusAddress ( PCIBus,
+ BusNumber,
+ BAddr,
+ &inIoSpace,
+ &TBAddr
+ );
+
+ flag2 = HalTranslateBusAddress (PCIBus,
+ BusNumber,
+ EAddr,
+ &inIoSpace2,
+ &TEAddr
+ );
+
+ if (flag == FALSE || flag2 == FALSE || inIoSpace != inIoSpace2) {
+
+ //
+ // HalAdjustResourceList should ensure that the returned range
+ // for the bus is within the bus limits and no translation
+ // within those limits should ever fail
+ //
+
+ DbgPrint ("HalpValidPCIAddr: Error return for HalTranslateBusAddress %x.%x:%x %x.%x:%x\n",
+ BAddr.HighPart, BAddr.LowPart, flag,
+ EAddr.HighPart, EAddr.LowPart, flag2);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+#endif
+
+
+NTSTATUS
+HalpAssignPCISlotResources (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN ULONG Slot,
+ IN OUT PCM_RESOURCE_LIST *pAllocatedResources
+ )
+/*++
+
+Routine Description:
+
+ Reads the targeted device to determine the firmwaire-assigned resources.
+ Calls IoReportResources to report/confirm them.
+ Returns the assignments to the caller.
+
+Arguments:
+
+Return Value:
+
+ STATUS_SUCCESS or error
+
+--*/
+{
+ NTSTATUS status;
+ PUCHAR WorkingPool;
+ PPCI_COMMON_CONFIG PciData, PciOrigData;
+ PCI_SLOT_NUMBER PciSlot;
+
+ PCM_RESOURCE_LIST CmRes;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc;
+ PHYSICAL_ADDRESS BAddr;
+ ULONG addr;
+ ULONG Command;
+ ULONG cnt, len;
+ BOOLEAN conflict;
+
+ ULONG i, j, m, length, holdvalue;
+ ULONG BusNumber;
+
+ BusNumber = BusHandler->BusNumber;
+
+ *pAllocatedResources = NULL;
+ PciSlot = *((PPCI_SLOT_NUMBER) &Slot);
+
+ //
+ // Allocate some pool for working space
+ //
+
+ i = sizeof (CM_RESOURCE_LIST) +
+ sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR) * (PCI_TYPE0_ADDRESSES + 2) +
+ PCI_COMMON_HDR_LENGTH * 2;
+
+ WorkingPool = (PUCHAR) ExAllocatePool (PagedPool, i);
+ if (!WorkingPool) {
+ return STATUS_NO_MEMORY;
+ }
+
+ //
+ // Zero initialize pool, and get pointers into memory - here we allocate
+ // a single chunk of memory and partition it into three pieces, pointed
+ // to by three separate pointers.
+ //
+
+ RtlZeroMemory (WorkingPool, i);
+ CmRes = (PCM_RESOURCE_LIST) WorkingPool;
+ PciData = (PPCI_COMMON_CONFIG)(WorkingPool + i - PCI_COMMON_HDR_LENGTH * 2);
+ PciOrigData = (PPCI_COMMON_CONFIG)(WorkingPool + i - PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Read the PCI device configuration
+ //
+
+ HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+ if (PciData->VendorID == PCI_INVALID_VENDORID || // empty slot
+ PciData->VendorID == 0x00) { // non-existant bus
+ ExFreePool (WorkingPool);
+ return STATUS_NO_SUCH_DEVICE;
+ }
+
+ //
+ // Make a copy of the devices current settings
+ //
+
+ RtlMoveMemory (PciOrigData, PciData, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Set resources to all bits on to see what type of resources
+ // are required.
+ //
+
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ PciData->u.type0.BaseAddresses[j] = 0xFFFFFFFF;
+ }
+
+ PciData->u.type0.ROMBaseAddress = 0xFFFFFFFF;
+
+ PciData->Command &= ~(PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE);
+ PciData->u.type0.ROMBaseAddress &= ~PCI_ROMADDRESS_ENABLED;
+ HalpWritePCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+ HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Build an CM_RESOURCE_LIST for the PCI device to report resources
+ // to IoReportResourceUsage.
+ //
+ // This code does *not* use IoAssignoResources, as the PCI
+ // address space resources have been previously assigned by the ARC firmware
+ //
+
+ CmRes->Count = 1;
+ CmRes->List[0].InterfaceType = PCIBus;
+ CmRes->List[0].BusNumber = BusNumber;
+
+ CmRes->List[0].PartialResourceList.Count = 0;
+
+ //
+ // Set current CM_RESOURCE_LIST version and revision
+ //
+
+ CmRes->List[0].PartialResourceList.Version = 0;
+ CmRes->List[0].PartialResourceList.Revision = 0;
+
+ CmDesc = CmRes->List[0].PartialResourceList.PartialDescriptors;
+
+#if DBG
+ DbgPrint ("HalAssignSlotResources: Resource List V%d.%d for slot %x:\n",
+ CmRes->List[0].PartialResourceList.Version,
+ CmRes->List[0].PartialResourceList.Revision,
+ Slot);
+
+#endif
+
+ //
+ // Interrupt resource
+ //
+
+ if (PciData->u.type0.InterruptPin) {
+
+ CmDesc->Type = CmResourceTypeInterrupt;
+ CmDesc->ShareDisposition = CmResourceShareShared;
+ CmDesc->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+
+ CmDesc->u.Interrupt.Level = PciData->u.type0.InterruptLine;
+ CmDesc->u.Interrupt.Vector = PciData->u.type0.InterruptLine;
+
+#if DBG
+ DbgPrint (" INT Level %x, Vector %x\n",
+ CmDesc->u.Interrupt.Level, CmDesc->u.Interrupt.Vector );
+#endif
+
+ CmRes->List[0].PartialResourceList.Count++;
+ CmDesc++;
+ }
+
+ //
+ // Add a memory or port resoruce for each PCI resource
+ // (Compute the ROM address as well. Just append it to the Base
+ // Address table.)
+ //
+
+ holdvalue = PciData->u.type0.BaseAddresses[PCI_TYPE0_ADDRESSES];
+ PciData->u.type0.BaseAddresses[PCI_TYPE0_ADDRESSES] =
+ PciData->u.type0.ROMBaseAddress & ~PCI_ADDRESS_IO_SPACE;
+
+ Command = PciOrigData->Command;
+ for (j=0; j < PCI_TYPE0_ADDRESSES + 1; j++) {
+ if (PciData->u.type0.BaseAddresses[j]) {
+ addr = i = PciData->u.type0.BaseAddresses[j];
+
+ //
+ // calculate the length necessary - note there is more complicated
+ // code in the x86 HAL that probably isn't necessary
+ //
+
+ length = ~(i & ~((i & 1) ? 3 : 15)) + 1;
+
+ //
+ // I/O space resource
+ //
+
+ if (addr & PCI_ADDRESS_IO_SPACE) {
+
+ CmDesc->Type = CmResourceTypePort;
+ CmDesc->ShareDisposition = CmResourceShareDeviceExclusive;
+ CmDesc->Flags = CM_RESOURCE_PORT_IO;
+
+ BAddr.LowPart = PciOrigData->u.type0.BaseAddresses[j] & ~3;
+ BAddr.HighPart = 0;
+
+#if DBG
+ HalpValidPCIAddr(BusHandler, BAddr, length, 1); // I/O space
+#endif
+
+ CmDesc->u.Port.Start = BAddr;
+ CmDesc->u.Port.Length = length;
+ Command |= PCI_ENABLE_IO_SPACE;
+#if DBG
+ DbgPrint (" IO Start %x:%08x, Len %x\n",
+ CmDesc->u.Port.Start.HighPart, CmDesc->u.Port.Start.LowPart,
+ CmDesc->u.Port.Length );
+#endif
+ //
+ // Memory space resource
+ //
+
+ } else {
+
+ CmDesc->Type = CmResourceTypeMemory;
+ CmDesc->ShareDisposition = CmResourceShareDeviceExclusive;
+
+ if (j == PCI_TYPE0_ADDRESSES) {
+ // this is a ROM address
+ if ((PciOrigData->u.type0.ROMBaseAddress & PCI_ROMADDRESS_ENABLED) == 0) {
+ //
+ // Ignore expansion ROMs which are not enabled by
+ // the firmware/ROM BIOS.
+ //
+
+ continue;
+ }
+ CmDesc->Flags = CM_RESOURCE_MEMORY_READ_ONLY;
+ BAddr.LowPart = PciOrigData->u.type0.ROMBaseAddress &
+ ~PCI_ROMADDRESS_ENABLED;
+ BAddr.HighPart = 0;
+ } else {
+ // this is a memory space base address
+ CmDesc->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ BAddr.LowPart = PciOrigData->u.type0.BaseAddresses[j] & ~15;
+ BAddr.HighPart = 0;
+ }
+
+#if DBG
+ HalpValidPCIAddr(BusHandler, BAddr, length, 0); // Memory space
+#endif
+
+ CmDesc->u.Memory.Start = BAddr;
+ CmDesc->u.Memory.Length = length;
+ Command |= PCI_ENABLE_MEMORY_SPACE;
+#if DBG
+ DbgPrint (" MEM Start %x:%08x, Len %x\n",
+ CmDesc->u.Memory.Start.HighPart, CmDesc->u.Memory.Start.LowPart,
+ CmDesc->u.Memory.Length );
+#endif
+ }
+
+ CmRes->List[0].PartialResourceList.Count++;
+ CmDesc++;
+
+ if (Is64BitBaseAddress(addr)) {
+ // skip upper half of 64 bit address since we
+ // only supports 32 bits PCI addresses for now.
+ j++;
+ }
+ }
+ }
+
+ //
+ // Setup the resource list.
+ // Count only the acquired resources.
+ //
+
+ *pAllocatedResources = CmRes;
+ cnt = CmRes->List[0].PartialResourceList.Count;
+ len = sizeof (CM_RESOURCE_LIST) +
+ cnt * sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR);
+
+#if DBG
+ DbgPrint("HalAssignSlotResources: Acq. Resourses = %d (len %x list %x\n)",
+ cnt, len, *pAllocatedResources);
+#endif
+
+ //
+ // Report the IO resource assignments
+ //
+
+ if (!DeviceObject) {
+ status = IoReportResourceUsage (
+ DriverClassName,
+ DriverObject, // DriverObject
+ *pAllocatedResources, // DriverList
+ len, // DriverListSize
+ DeviceObject, // DeviceObject
+ NULL, // DeviceList
+ 0, // DeviceListSize
+ FALSE, // override conflict
+ &conflict // conflicted detected
+ );
+ } else {
+ status = IoReportResourceUsage (
+ DriverClassName,
+ DriverObject, // DriverObject
+ NULL, // DriverList
+ 0, // DriverListSize
+ DeviceObject,
+ *pAllocatedResources, // DeviceList
+ len, // DeviceListSize
+ FALSE, // override conflict
+ &conflict // conflicted detected
+ );
+ }
+
+ if (NT_SUCCESS(status) && conflict) {
+
+ //
+ // IopReportResourceUsage saw a conflict?
+ //
+
+#if DBG
+ DbgPrint("HalAssignSlotResources: IoAssignResources detected a conflict: %x\n",
+ status);
+#endif
+ status = STATUS_CONFLICTING_ADDRESSES;
+ goto CleanUp;
+ }
+
+ if (!NT_SUCCESS(status)) {
+#if DBG
+ DbgPrint("HalAssignSlotResources: IoAssignResources failed: %x\n", status);
+#endif
+ goto CleanUp;
+ }
+
+ //
+ // Restore orginial data, turning on the appropiate decodes
+ //
+
+#if DBG
+ DbgPrint ("HalAssignSlotResources: IoReportResourseUsage succeeded\n");
+#endif
+
+ // enable IO & Memory decodes
+
+ PciOrigData->Command |= (USHORT) Command;
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ PciOrigData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+#if DBG
+ DbgPrint ("HalAssignSlotResources: PCI Config Space updated with Command = %x\n",
+ Command);
+#endif
+
+CleanUp:
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // Failure, if there are any allocated resources free them
+ //
+
+ i = 0;
+ if (*pAllocatedResources) {
+
+ if (!DeviceObject) {
+ status = IoReportResourceUsage (
+ DriverClassName,
+ DriverObject, // DriverObject
+ (PCM_RESOURCE_LIST) &i, // DriverList
+ sizeof (i), // DriverListSize
+ DeviceObject,
+ NULL, // DeviceList
+ 0, // DeviceListSize
+ FALSE, // override conflict
+ &conflict // conflicted detected
+ );
+ } else {
+ status = IoReportResourceUsage (
+ DriverClassName,
+ DriverObject, // DriverObject
+ NULL, // DriverList
+ 0, // DriverListSize
+ DeviceObject,
+ (PCM_RESOURCE_LIST) &i, // DeviceList
+ sizeof (i), // DeviceListSize
+ FALSE, // override conflict
+ &conflict // conflicted detected
+ );
+ }
+
+ ExFreePool (*pAllocatedResources);
+ *pAllocatedResources = NULL;
+ }
+
+ //
+ // Restore the device settings as we found them, enable memory
+ // and io decode after setting base addresses
+ //
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ PciOrigData,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status),
+ PCI_COMMON_HDR_LENGTH - FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ PciOrigData,
+ 0,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+ }
+
+ return status;
+}
+
+
+NTSTATUS
+HalpAdjustPCIResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ )
+/*++
+
+Routine Description:
+
+ The function adjusts a PCI pResourceList and forces it to match the
+ pre-configured values in PCI configuration space for this device.
+
+Arguments:
+
+ BusHandler - Registered BUSHANDLER for the target configuration space
+
+ RootHandler - Register BUSHANDLER for the orginating HalAdjustResourceList request.
+
+ pResourceList - Supplies the PIO_RESOURCE_REQUIREMENTS_LIST to be checked.
+
+Return Value:
+
+ STATUS_SUCCESS
+
+--*/
+{
+ UCHAR buffer[PCI_COMMON_HDR_LENGTH];
+ PCI_SLOT_NUMBER PciSlot;
+ PPCI_COMMON_CONFIG PciData;
+ PIO_RESOURCE_REQUIREMENTS_LIST CompleteList;
+ PIO_RESOURCE_LIST ResourceList;
+ PIO_RESOURCE_DESCRIPTOR Descriptor;
+ ULONG alt, cnt, bcnt;
+ ULONG MemoryBaseAddress, RomIndex;
+ PULONG BaseAddress[PCI_TYPE0_ADDRESSES + 1];
+
+ //
+ // Fix any requested resources for this device to be the
+ // value set in PCI configuration space for this device.
+ //
+
+ //
+ // Get PCI common configuration space for this slot
+ //
+
+ PciSlot = *((PPCI_SLOT_NUMBER) &(*pResourceList)->SlotNumber),
+ PciData = (PPCI_COMMON_CONFIG) buffer;
+
+ HalGetBusData (
+ PCIConfiguration,
+ BusHandler->BusNumber,
+ PciSlot.u.AsULONG,
+ PciData,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != 0) {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ //
+ // Copy base addresses based on configuration data type
+ //
+
+ switch (PCI_CONFIG_TYPE(PciData)) {
+ case 0 :
+ for (bcnt=0; bcnt < PCI_TYPE0_ADDRESSES; bcnt++) {
+ BaseAddress[bcnt] = &PciData->u.type0.BaseAddresses[bcnt];
+ }
+ BaseAddress[bcnt] = &PciData->u.type0.ROMBaseAddress;
+ RomIndex = bcnt;
+ break;
+ case 1:
+ for (bcnt=0; bcnt < PCI_TYPE1_ADDRESSES; bcnt++) {
+ BaseAddress[bcnt] = &PciData->u.type1.BaseAddresses[bcnt];
+ }
+ BaseAddress[bcnt] = &PciData->u.type0.ROMBaseAddress;
+ RomIndex = bcnt;
+ break;
+
+ default:
+ return STATUS_NO_SUCH_DEVICE;
+ }
+
+ //
+ // Walk each ResourceList and confine resources
+ // to preconfigured settings.
+ //
+
+ CompleteList = *pResourceList;
+ ResourceList = CompleteList->List;
+ ResourceList->Version = 1;
+ ResourceList->Revision = 1;
+
+ for (alt=0; alt < CompleteList->AlternativeLists; alt++) {
+ Descriptor = ResourceList->Descriptors;
+
+ //
+ // For each alternative list, reset to review entire
+ // set of Base Address registers
+ //
+ // We assume that the order of resource descriptors for
+ // each alternative list matches the order of the
+ // PCI configuration space base address registers
+ //
+
+ bcnt = 0;
+
+ for (cnt = ResourceList->Count; cnt; cnt--) {
+
+ //
+ // Limit desctiptor to to preconfigured setting
+ // held in the InterruptLine register.
+ //
+
+ switch (Descriptor->Type) {
+ case CmResourceTypeInterrupt:
+
+ //
+ // Confine interrupt vector to preconfigured setting.
+ //
+
+ Descriptor->u.Interrupt.MinimumVector = PciData->u.type0.InterruptLine;
+ Descriptor->u.Interrupt.MaximumVector = PciData->u.type0.InterruptLine;
+ break;
+
+ case CmResourceTypePort:
+
+ //
+ // Assure that requested descriptor is valid
+ //
+
+ if (bcnt > RomIndex) {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ //
+ // Confine to preconfigured setting.
+ //
+
+ Descriptor->u.Port.MinimumAddress.QuadPart =
+ *BaseAddress[bcnt++] & ~0x3;
+
+ Descriptor->u.Port.MaximumAddress.QuadPart =
+ Descriptor->u.Port.MinimumAddress.QuadPart +
+ Descriptor->u.Port.Length - 1;
+
+#if HALDBG
+ DbgPrint("AdjustPCIResourceList\nPort: MinimumAddress set to %x\n",
+ Descriptor->u.Port.MinimumAddress.QuadPart);
+
+ DbgPrint(" MaximumAddress set to %x\n",
+ Descriptor->u.Port.MaximumAddress.QuadPart);
+#endif
+
+ break;
+
+ case CmResourceTypeMemory:
+
+ //
+ // Assure that requested descriptor is valid
+ //
+
+ if (bcnt > RomIndex) {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ //
+ // Confine to preconfigured setting.
+ //
+
+ MemoryBaseAddress = *BaseAddress[bcnt];
+
+ if (bcnt == RomIndex) {
+ Descriptor->u.Memory.MinimumAddress.QuadPart =
+ *BaseAddress[bcnt++] & ~PCI_ROMADDRESS_ENABLED;
+ } else {
+ Descriptor->u.Memory.MinimumAddress.QuadPart =
+ *BaseAddress[bcnt++] & ~0xF;
+ }
+
+ Descriptor->u.Memory.MaximumAddress.QuadPart =
+ Descriptor->u.Memory.MinimumAddress.QuadPart +
+ Descriptor->u.Memory.Length - 1;
+
+ if (Is64BitBaseAddress(MemoryBaseAddress)) {
+ // skip upper half of 64 bit address since we
+ // only supports 32 bits PCI addresses for now.
+ bcnt++;
+ }
+
+
+#if HALDBG
+ DbgPrint("AdjustPCIResourceList\nMemory: MinimumAddress set to %x\n",
+ Descriptor->u.Memory.MinimumAddress.QuadPart);
+
+ DbgPrint(" MaximumAddress set to %x\n",
+ Descriptor->u.Memory.MaximumAddress.QuadPart);
+#endif
+ break;
+
+ case CmResourceTypeDma:
+ break;
+
+ default:
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ //
+ // Next descriptor
+ //
+ Descriptor++;
+ }
+
+ //
+ // Next Resource List
+ //
+ ResourceList = (PIO_RESOURCE_LIST) Descriptor;
+ }
+ return STATUS_SUCCESS;
+}
+
+#define TEST_PCI 1
+
+#if DBG && TEST_PCI
+
+VOID HalpTestPci (ULONG flag2)
+{
+ PCI_SLOT_NUMBER SlotNumber;
+ PCI_COMMON_CONFIG PciData, OrigData;
+ ULONG i, f, j, k, bus;
+ BOOLEAN flag;
+
+ if (!flag2) {
+ return ;
+ }
+
+ DbgBreakPoint ();
+ SlotNumber.u.bits.Reserved = 0;
+
+ //
+ // Read every possible PCI Device/Function and display it's
+ // default info.
+ //
+ // (note this destories it's current settings)
+ //
+
+ flag = TRUE;
+ for (bus = 0; flag; bus++) {
+
+ for (i = 0; i < 32; i++) {
+ SlotNumber.u.bits.DeviceNumber = i;
+
+ for (f = 0; f < 8; f++) {
+ SlotNumber.u.bits.FunctionNumber = f;
+
+
+ j = HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ if (j == 0) {
+ // out of buses
+ flag = FALSE;
+ break;
+ }
+
+ if (j < PCI_COMMON_HDR_LENGTH) {
+ continue;
+ }
+
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ 1
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ memcpy (&OrigData, &PciData, sizeof PciData);
+
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ PciData.u.type0.BaseAddresses[j] = 0xFFFFFFFF;
+ }
+
+ PciData.u.type0.ROMBaseAddress = 0xFFFFFFFF;
+
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ DbgPrint ("PCI Bus %d Slot %2d %2d ID:%04lx-%04lx Rev:%04lx",
+ bus, i, f, PciData.VendorID, PciData.DeviceID,
+ PciData.RevisionID);
+
+ if (PciData.u.type0.InterruptPin) {
+ DbgPrint (" IntPin:%x", PciData.u.type0.InterruptPin);
+ }
+
+ if (PciData.u.type0.InterruptLine) {
+ DbgPrint (" IntLine:%x", PciData.u.type0.InterruptLine);
+ }
+
+ if (PciData.u.type0.ROMBaseAddress) {
+ DbgPrint (" ROM:%08lx", PciData.u.type0.ROMBaseAddress);
+ }
+
+ DbgPrint ("\n ProgIf:%04x SubClass:%04x BaseClass:%04lx\n",
+ PciData.ProgIf, PciData.SubClass, PciData.BaseClass);
+
+ k = 0;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (PciData.u.type0.BaseAddresses[j]) {
+ DbgPrint (" Ad%d:%08lx", j, PciData.u.type0.BaseAddresses[j]);
+ k = 1;
+ }
+ }
+
+ if (PciData.u.type0.ROMBaseAddress == 0xC08001) {
+
+ PciData.u.type0.ROMBaseAddress = 0xC00001;
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ DbgPrint ("\n Bogus rom address, edit yields:%08lx",
+ PciData.u.type0.ROMBaseAddress);
+ }
+ if (k) {
+ DbgPrint ("\n");
+ }
+
+ if (PciData.VendorID == 0x8086) {
+ // dump complete buffer
+ DbgPrint ("Command %x, Status %x, BIST %x\n",
+ PciData.Command, PciData.Status,
+ PciData.BIST
+ );
+
+ DbgPrint ("CacheLineSz %x, LatencyTimer %x",
+ PciData.CacheLineSize, PciData.LatencyTimer
+ );
+
+ for (j=0; j < 192; j++) {
+ if ((j & 0xf) == 0) {
+ DbgPrint ("\n%02x: ", j + 0x40);
+ }
+ DbgPrint ("%02x ", PciData.DeviceSpecific[j]);
+ }
+ DbgPrint ("\n");
+ }
+
+ //
+ // now print original data
+ //
+
+ if (OrigData.u.type0.ROMBaseAddress) {
+ DbgPrint (" oROM:%08lx", OrigData.u.type0.ROMBaseAddress);
+ }
+
+ DbgPrint ("\n");
+ k = 0;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (OrigData.u.type0.BaseAddresses[j]) {
+ DbgPrint (" oAd%d:%08lx", j, OrigData.u.type0.BaseAddresses[j]);
+ k = 1;
+ }
+ }
+
+ //
+ // Restore original settings
+ //
+
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &OrigData,
+ sizeof (PciData)
+ );
+
+ //
+ // Next
+ //
+
+ if (k) {
+ DbgPrint ("\n\n");
+ }
+ }
+ }
+
+ }
+ DbgBreakPoint();
+}
+
+#endif // DBG && TEST_PCI
diff --git a/private/ntos/nthals/halflex/xxport.c b/private/ntos/nthals/halflex/xxport.c
new file mode 100644
index 000000000..3d0770236
--- /dev/null
+++ b/private/ntos/nthals/halflex/xxport.c
@@ -0,0 +1,769 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ jxport.c
+
+Abstract:
+
+ This module implements the code that provides communication between
+ the kernel debugger on a MIPS R3000 or R4000 Jazz system and the host
+ system.
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "jazzserp.h"
+
+VOID
+HalpGetDivisorFromBaud(
+ IN ULONG ClockRate,
+ IN LONG DesiredBaud,
+ OUT PSHORT AppropriateDivisor
+ );
+
+
+#pragma alloc_text(INIT,HalpGetDivisorFromBaud)
+
+
+//
+// BUGBUG Temporarily, we use counter to do the timeout
+//
+
+#define TIMEOUT_COUNT 1024*512
+
+//
+// BUGBUG Temp until we have a configuration manager.
+//
+
+PUCHAR KdComPortInUse = NULL;
+BOOLEAN KdUseModemControl = FALSE;
+
+//
+// Define serial port read and write addresses.
+//
+
+PSP_READ_REGISTERS SP_READ;
+PSP_WRITE_REGISTERS SP_WRITE;
+
+//
+// Define forward referenced prototypes.
+//
+
+SP_LINE_STATUS
+KdReadLsr (
+ IN BOOLEAN WaitReason
+ );
+
+//
+// Define baud rate divisor to be used on the debugger port.
+//
+
+SHORT HalpBaudRateDivisor = 6;
+
+
+ULONG
+HalpGetByte (
+ IN PCHAR Input,
+ IN BOOLEAN Wait
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+ Wait - Supplies a boolean value that detemines whether a timeout
+ is applied to the input operation.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error is encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+{
+
+ SP_LINE_STATUS LsrByte;
+ UCHAR DataByte;
+ ULONG TimeoutCount;
+
+ //
+ // Attempt to read a byte from the debugger port until a byte is
+ // available or until a timeout occurs.
+ //
+
+ TimeoutCount = Wait ? TIMEOUT_COUNT : 1;
+ do {
+ TimeoutCount -= 1;
+
+ //
+ // Wait until data is available in the receive buffer.
+ //
+
+ KeStallExecutionProcessor(1);
+ LsrByte = KdReadLsr(TRUE);
+ if (LsrByte.DataReady == 0) {
+ continue;
+ }
+
+ //
+ // Read input byte and store in callers buffer.
+ //
+
+ *Input = READ_REGISTER_UCHAR(&SP_READ->ReceiveBuffer);
+
+ //
+ // If using modem controls, then skip any incoming data while
+ // ReceiveData not set.
+ //
+
+ if (KdUseModemControl) {
+ DataByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+ if ( ((PSP_MODEM_STATUS)&DataByte)->ReceiveDetect == 0) {
+ continue;
+ }
+ }
+
+ //
+ // Return function value as the not of the error indicators.
+ //
+
+ if (LsrByte.ParityError ||
+ LsrByte.FramingError ||
+ LsrByte.OverrunError ||
+ LsrByte.BreakIndicator) {
+ return CP_GET_ERROR;
+ }
+
+ return CP_GET_SUCCESS;
+ } while(TimeoutCount != 0);
+
+ return CP_GET_NODATA;
+}
+
+BOOLEAN
+KdPortInitialize (
+ PDEBUG_PARAMETERS DebugParameters,
+ PLOADER_PARAMETER_BLOCK LoaderBlock,
+ BOOLEAN Initialize
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the serial port used by the kernel debugger
+ and must be called during system initialization.
+
+Arguments:
+
+ DebugParameter - Supplies a pointer to the debug port parameters.
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+ Initialize - Specifies a boolean value that determines whether the
+ debug port is initialized or just the debug port parameters
+ are captured.
+
+Return Value:
+
+ A value of TRUE is returned is the port was successfully initialized.
+ Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
+ UCHAR DataByte;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_SERIAL_DEVICE_DATA DeviceData;
+ PCM_PARTIAL_RESOURCE_LIST List;
+ ULONG MatchKey;
+ ULONG BaudRate;
+ ULONG BaudClock;
+
+ //
+ // Find the configuration information for the first serial port.
+ //
+
+ if (LoaderBlock != NULL) {
+ MatchKey = 0;
+ ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ ControllerClass,
+ SerialController,
+ &MatchKey);
+
+ } else {
+ ConfigurationEntry = NULL;
+ }
+
+ if (DebugParameters->BaudRate != 0) {
+ BaudRate = DebugParameters->BaudRate;
+ } else {
+ BaudRate = 19200;
+ }
+
+ //
+ // If the serial configuration entry was not found or the frequency
+ // specified is not supported, then default the baud clock to 1843200.
+ //
+
+ BaudClock = 1843200;
+
+ if (ConfigurationEntry != NULL) {
+ List = (PCM_PARTIAL_RESOURCE_LIST)ConfigurationEntry->ConfigurationData;
+ Descriptor = &List->PartialDescriptors[List->Count];
+ DeviceData = (PCM_SERIAL_DEVICE_DATA)Descriptor;
+ if ((DeviceData->BaudClock == 1843200) ||
+ (DeviceData->BaudClock == 4233600) ||
+ (DeviceData->BaudClock == 8000000)) {
+ BaudClock = DeviceData->BaudClock;
+ }
+ }
+
+ HalpGetDivisorFromBaud(
+ BaudClock,
+ BaudRate,
+ &HalpBaudRateDivisor
+ );
+
+ //
+ // If the debugger is not being enabled, then return.
+ //
+
+ if (Initialize == FALSE) {
+ return TRUE;
+ }
+
+ KdComPortInUse = HalpAllocateKdPortResources(&SP_READ,&SP_WRITE);
+
+ //
+ // Clear the divisor latch, clear all interrupt enables, and reset and
+ // disable the FIFO's.
+ //
+
+ WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, 0x0);
+ WRITE_REGISTER_UCHAR(&SP_WRITE->InterruptEnable, 0x0);
+ DataByte = 0;
+ ((PSP_FIFO_CONTROL)(&DataByte))->ReceiveFifoReset = 1;
+ ((PSP_FIFO_CONTROL)(&DataByte))->TransmitFifoReset = 1;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->FifoControl, DataByte);
+
+ //
+ // Set the divisor latch and set the baud rate to 19200 baud.
+ //
+ ((PSP_LINE_CONTROL)(&DataByte))->DivisorLatch = 1;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, DataByte);
+ WRITE_REGISTER_UCHAR(&SP_WRITE->TransmitBuffer, (UCHAR)(HalpBaudRateDivisor&0xff));
+ WRITE_REGISTER_UCHAR(&SP_WRITE->InterruptEnable, (UCHAR)(HalpBaudRateDivisor>>8));
+
+ //
+ // Clear the divisor latch and set the character size to eight bits
+ // with one stop bit and no parity checking.
+ //
+
+ DataByte = 0;
+ ((PSP_LINE_CONTROL)(&DataByte))->CharacterSize = EIGHT_BITS;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, DataByte);
+
+ //
+ // Set data terminal ready and request to send.
+ //
+
+ DataByte = 0;
+ ((PSP_MODEM_CONTROL)(&DataByte))->DataTerminalReady = 1;
+ ((PSP_MODEM_CONTROL)(&DataByte))->RequestToSend = 1;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->ModemControl, DataByte);
+
+ HalpFreeKdPortResources();
+
+ return TRUE;
+}
+
+ULONG
+KdPortGetByte (
+ OUT PUCHAR Input
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger.
+
+ N.B. It is assumed that the IRQL has been raised to the highest
+ level, and necessary multiprocessor synchronization has been
+ performed before this routine is called.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error is encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+{
+ return HalpGetByte(Input, TRUE);
+}
+
+ULONG
+KdPortPollByte (
+ OUT PUCHAR Input
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger iff a byte is available.
+
+ N.B. It is assumed that the IRQL has been raised to the highest
+ level, and necessary multiprocessor synchronization has been
+ performed before this routine is called.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+{
+
+ ULONG Status;
+
+ //
+ // Save port status, map the serial controller, get byte from the
+ // debugger port is one is avaliable, restore port status, unmap
+ // the serial controller, and return the operation status.
+ //
+
+ KdPortSave();
+ Status = HalpGetByte(Input, FALSE);
+ KdPortRestore();
+ return Status;
+}
+
+VOID
+KdPortPutByte (
+ IN UCHAR Output
+ )
+
+/*++
+
+Routine Description:
+
+ This routine puts a byte to the serial port used by the kernel debugger.
+
+ N.B. It is assumed that the IRQL has been raised to the highest level,
+ and necessary multiprocessor synchronization has been performed
+ before this routine is called.
+
+Arguments:
+
+ Output - Supplies the output data byte.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+
+ if (KdUseModemControl) {
+ //
+ // Modem control, make sure DSR, CTS and CD are all set before
+ // sending any data.
+ //
+
+ for (; ;) {
+ DataByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+ if ( ((PSP_MODEM_STATUS)&DataByte)->ClearToSend &&
+ ((PSP_MODEM_STATUS)&DataByte)->DataSetReady &&
+ ((PSP_MODEM_STATUS)&DataByte)->ReceiveDetect ) {
+ break;
+ }
+
+ KdReadLsr(FALSE);
+ }
+ }
+
+ //
+ // Wait for transmit ready.
+ //
+
+ while (KdReadLsr(FALSE).TransmitHoldingEmpty == 0 );
+
+ //
+ // Wait for data set ready.
+ //
+
+// do {
+// LsrByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+// } while (((PSP_MODEM_STATUS)(&LsrByte))->DataSetReady == 0);
+
+ //
+ // Transmit data.
+ //
+
+ WRITE_REGISTER_UCHAR(&SP_WRITE->TransmitBuffer, Output);
+ return;
+}
+
+VOID
+KdPortRestore (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine restores the state of the serial port after the kernel
+ debugger has been active.
+
+ N.B. This routine performs no function on the Jazz system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ HalpFreeKdPortResources();
+ return;
+}
+
+VOID
+KdPortSave (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine saves the state of the serial port and initializes the port
+ for use by the kernel debugger.
+
+ N.B. This routine performs no function on the Jazz system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ HalpAllocateKdPortResources(&SP_READ,&SP_WRITE);
+ return;
+}
+
+SP_LINE_STATUS
+KdReadLsr (
+ IN BOOLEAN WaitReason
+ )
+
+/*++
+
+Routine Description:
+
+ Returns current line status.
+
+ If status which is being waited for is ready, then the function
+ checks the current modem status and causes a possible display update
+ of the current statuses.
+
+Arguments:
+
+ WaitReason - Suuplies a boolean value that determines whether the line
+ status is required for a receive or transmit.
+
+Return Value:
+
+ The current line status is returned as the function value.
+
+--*/
+
+{
+
+ static UCHAR RingFlag = 0;
+ UCHAR DataLsr, DataMsr;
+
+ //
+ // Get the line status for a recevie or a transmit.
+ //
+
+ DataLsr = READ_REGISTER_UCHAR(&SP_READ->LineStatus);
+ if (WaitReason) {
+
+ //
+ // Get line status for receive data.
+ //
+
+ if (((PSP_LINE_STATUS)&DataLsr)->DataReady) {
+ return *((PSP_LINE_STATUS)&DataLsr);
+ }
+
+ } else {
+
+ //
+ // Get line status for transmit empty.
+ //
+
+ if (((PSP_LINE_STATUS)&DataLsr)->TransmitEmpty) {
+ return *((PSP_LINE_STATUS)&DataLsr);
+ }
+ }
+
+ DataMsr = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+ RingFlag |= ((PSP_MODEM_STATUS)&DataMsr)->RingIndicator ? 1 : 2;
+ if (RingFlag == 3) {
+
+ //
+ // The ring indicate line has toggled, use modem control from
+ // now on.
+ //
+
+ KdUseModemControl = TRUE;
+ }
+
+ return *((PSP_LINE_STATUS) &DataLsr);
+}
+
+VOID
+HalpGetDivisorFromBaud(
+ IN ULONG ClockRate,
+ IN LONG DesiredBaud,
+ OUT PSHORT AppropriateDivisor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine will determine a divisor based on an unvalidated
+ baud rate.
+
+Arguments:
+
+ ClockRate - The clock input to the controller.
+
+ DesiredBaud - The baud rate for whose divisor we seek.
+
+ AppropriateDivisor - Given that the DesiredBaud is valid, the
+ SHORT pointed to by this parameter will be set to the appropriate
+ value. If the requested baud rate is unsupportable on the machine
+ return a divisor appropriate for 19200.
+
+Return Value:
+
+ none.
+
+--*/
+
+{
+
+ SHORT calculatedDivisor;
+ ULONG denominator;
+ ULONG remainder;
+
+ //
+ // Allow up to a 1 percent error
+ //
+
+ ULONG maxRemain18 = 18432;
+ ULONG maxRemain30 = 30720;
+ ULONG maxRemain42 = 42336;
+ ULONG maxRemain80 = 80000;
+ ULONG maxRemain;
+
+ //
+ // Reject any non-positive bauds.
+ //
+
+ denominator = DesiredBaud*(ULONG)16;
+
+ if (DesiredBaud <= 0) {
+
+ *AppropriateDivisor = -1;
+
+ } else if ((LONG)denominator < DesiredBaud) {
+
+ //
+ // If the desired baud was so huge that it cause the denominator
+ // calculation to wrap, don't support it.
+ //
+
+ *AppropriateDivisor = -1;
+
+ } else {
+
+ if (ClockRate == 1843200) {
+ maxRemain = maxRemain18;
+ } else if (ClockRate == 3072000) {
+ maxRemain = maxRemain30;
+ } else if (ClockRate == 4233600) {
+ maxRemain = maxRemain42;
+ } else {
+ maxRemain = maxRemain80;
+ }
+
+ calculatedDivisor = (SHORT)(ClockRate / denominator);
+ remainder = ClockRate % denominator;
+
+ //
+ // Round up.
+ //
+
+ if (((remainder*2) > ClockRate) && (DesiredBaud != 110)) {
+
+ calculatedDivisor++;
+ }
+
+
+ //
+ // Only let the remainder calculations effect us if
+ // the baud rate is > 9600.
+ //
+
+ if (DesiredBaud >= 9600) {
+
+ //
+ // If the remainder is less than the maximum remainder (wrt
+ // the ClockRate) or the remainder + the maximum remainder is
+ // greater than or equal to the ClockRate then assume that the
+ // baud is ok.
+ //
+
+ if ((remainder >= maxRemain) && ((remainder+maxRemain) < ClockRate)) {
+ calculatedDivisor = -1;
+ }
+
+ }
+
+ //
+ // Don't support a baud that causes the denominator to
+ // be larger than the clock.
+ //
+
+ if (denominator > ClockRate) {
+
+ calculatedDivisor = -1;
+
+ }
+
+ //
+ // Ok, Now do some special casing so that things can actually continue
+ // working on all platforms.
+ //
+
+ if (ClockRate == 1843200) {
+
+ if (DesiredBaud == 56000) {
+ calculatedDivisor = 2;
+ }
+
+ } else if (ClockRate == 3072000) {
+
+ if (DesiredBaud == 14400) {
+ calculatedDivisor = 13;
+ }
+
+ } else if (ClockRate == 4233600) {
+
+ if (DesiredBaud == 9600) {
+ calculatedDivisor = 28;
+ } else if (DesiredBaud == 14400) {
+ calculatedDivisor = 18;
+ } else if (DesiredBaud == 19200) {
+ calculatedDivisor = 14;
+ } else if (DesiredBaud == 38400) {
+ calculatedDivisor = 7;
+ } else if (DesiredBaud == 56000) {
+ calculatedDivisor = 5;
+ }
+
+ } else if (ClockRate == 8000000) {
+
+ if (DesiredBaud == 14400) {
+ calculatedDivisor = 35;
+ } else if (DesiredBaud == 56000) {
+ calculatedDivisor = 9;
+ }
+
+ }
+
+ *AppropriateDivisor = calculatedDivisor;
+
+ }
+
+
+ if (*AppropriateDivisor == -1) {
+
+ HalpGetDivisorFromBaud(
+ ClockRate,
+ 19200,
+ AppropriateDivisor
+ );
+
+ }
+
+
+}
+
+
diff --git a/private/ntos/nthals/halflex/xxreturn.c b/private/ntos/nthals/halflex/xxreturn.c
new file mode 100644
index 000000000..bbd381e12
--- /dev/null
+++ b/private/ntos/nthals/halflex/xxreturn.c
@@ -0,0 +1,101 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxreturn.c
+
+Abstract:
+
+ This module implements the HAL return to firmware function.
+
+Author:
+
+ David N. Cutler (davec) 21-Aug-1991
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+VOID
+HalReturnToFirmware(
+ IN FIRMWARE_REENTRY Routine
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns control to the specified firmware routine.
+ In most cases it generates a soft reset by asserting the reset line
+ trough the keyboard controller.
+ The Keyboard controller is mapped using the same virtual address
+ and the same fixed entry as the DMA.
+
+Arguments:
+
+ Routine - Supplies a value indicating which firmware routine to invoke.
+
+Return Value:
+
+ Does not return.
+
+--*/
+
+{
+ KIRQL OldIrql;
+
+ //
+ // Case on the type of return.
+ //
+
+ switch (Routine) {
+ case HalHaltRoutine:
+
+ //
+ // Disable Interrupts.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // Hang looping.
+ //
+ for (;;) {
+ }
+
+ case HalPowerDownRoutine:
+ case HalRestartRoutine:
+ case HalRebootRoutine:
+ case HalInteractiveModeRoutine:
+
+ if (HalpResetDisplayParameters != NULL) {
+ (HalpResetDisplayParameters)(80,25);
+ }
+
+ HalpResetX86DisplayAdapter();
+
+ //
+ // Disable Interrupts.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ HalpAllocateArcsResources();
+ ArcReboot();
+
+ //
+ // Should never get here...
+ //
+
+ for (;;) {
+ }
+
+ default:
+ KdPrint(("HalReturnToFirmware invalid argument\n"));
+ DbgBreakPoint();
+ }
+}
diff --git a/private/ntos/nthals/halflex/xxsysint.c b/private/ntos/nthals/halflex/xxsysint.c
new file mode 100644
index 000000000..4f3e00a44
--- /dev/null
+++ b/private/ntos/nthals/halflex/xxsysint.c
@@ -0,0 +1,217 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxsysint.c
+
+Abstract:
+
+ This module implements the HAL enable/disable system interrupt, and
+ request interprocessor interrupt routines for a MIPS R3000 or R4000
+ Jazz system.
+
+Author:
+
+ David N. Cutler (davec) 6-May-1991
+ Michael D. Kinney 2-May-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+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 >= UNIFLEX_EISA_VECTORS &&
+ Vector <= (UNIFLEX_MAXIMUM_EISA_VECTOR) &&
+ Irql == UNIFLEX_EISA_DEVICE_LEVEL) {
+ HalpDisableEisaInterrupt(Vector);
+ }
+
+ if (Vector >= UNIFLEX_EISA1_VECTORS &&
+ Vector <= (UNIFLEX_MAXIMUM_EISA1_VECTOR) &&
+ Irql == UNIFLEX_EISA_DEVICE_LEVEL) {
+ HalpDisableEisaInterrupt(Vector);
+ }
+
+ //
+ // If the vector number is within the range of the PCI interrupts, then
+ // disable the PCI interrrupt.
+ //
+
+ if (Vector >= UNIFLEX_PCI_VECTORS &&
+ Vector <= (UNIFLEX_MAXIMUM_PCI_VECTOR) &&
+ Irql == UNIFLEX_PCI_DEVICE_LEVEL) {
+ HalpDisablePciInterrupt(Vector);
+ }
+
+ //
+ // Call platform specific routine
+ //
+
+ HalpDisablePlatformInterrupt(Vector,Irql);
+
+ //
+ // 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
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+ BOOLEAN Enabled = FALSE;
+
+ //
+ // 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 >= UNIFLEX_EISA_VECTORS &&
+ Vector <= (UNIFLEX_MAXIMUM_EISA_VECTOR) &&
+ Irql == UNIFLEX_EISA_DEVICE_LEVEL) {
+ HalpEnableEisaInterrupt( Vector, InterruptMode);
+ Enabled = TRUE;
+ }
+
+ if (Vector >= UNIFLEX_EISA1_VECTORS &&
+ Vector <= (UNIFLEX_MAXIMUM_EISA1_VECTOR) &&
+ Irql == UNIFLEX_EISA_DEVICE_LEVEL) {
+ HalpEnableEisaInterrupt( Vector, InterruptMode);
+ Enabled = TRUE;
+ }
+
+ //
+ // If the vector number is within the range of the PCI interrupts, then
+ // enable the PCI interrrupt.
+ //
+
+ if (Vector >= UNIFLEX_PCI_VECTORS &&
+ Vector <= (UNIFLEX_MAXIMUM_PCI_VECTOR) &&
+ Irql == UNIFLEX_PCI_DEVICE_LEVEL) {
+ HalpEnablePciInterrupt(Vector);
+ Enabled = TRUE;
+ }
+
+ //
+ // Call platform specific routine
+ //
+
+ if (!Enabled) {
+ Enabled = HalpEnablePlatformInterrupt(Vector,Irql,InterruptMode);
+ }
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+ return Enabled;
+}
+
+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.
+
+--*/
+
+{
+
+ return;
+}
diff --git a/private/ntos/nthals/halflex/xxtime.c b/private/ntos/nthals/halflex/xxtime.c
new file mode 100644
index 000000000..bddec03d2
--- /dev/null
+++ b/private/ntos/nthals/halflex/xxtime.c
@@ -0,0 +1,285 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxtime.c
+
+Abstract:
+
+ This module implements the HAL set/query realtime clock routines for
+ a MIPS R3000 or R4000 Jazz system.
+
+Author:
+
+ David N. Cutler (davec) 5-May-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "jazzrtc.h"
+#include "eisa.h"
+
+#define BCDToBinary(D) (10 * (((D) & 0xf0) >>4 ) + ((D) & 0x0f))
+#define BinaryToBCD(B) ((((B) & 0xff) / 10) << 4 ) | (((B) & 0xff) % 10)
+
+//
+// Define forward referenced procedure prototypes.
+//
+
+UCHAR
+HalpReadClockRegister (
+ UCHAR Register
+ );
+
+VOID
+HalpWriteClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ );
+
+BOOLEAN HalQueryRealTimeClock (OUT PTIME_FIELDS TimeFields)
+
+/*++
+
+Routine Description:
+
+ This routine queries the realtime clock.
+
+ N.B. This routine is required to provide any synchronization necessary
+ 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;
+ KIRQL 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.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+
+ 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 = 1900 + (CSHORT)BCDToBinary(HalpReadClockRegister(RTC_YEAR));
+ if (TimeFields->Year < 1992)
+ TimeFields->Year += 100;
+ TimeFields->Month = (CSHORT)BCDToBinary(HalpReadClockRegister(RTC_MONTH));
+ TimeFields->Day = (CSHORT)BCDToBinary(HalpReadClockRegister(RTC_DAY_OF_MONTH));
+ TimeFields->Weekday = (CSHORT)BCDToBinary(HalpReadClockRegister(RTC_DAY_OF_WEEK)) - 1;
+ TimeFields->Hour = (CSHORT)BCDToBinary(HalpReadClockRegister(RTC_HOUR));
+ TimeFields->Minute = (CSHORT)BCDToBinary(HalpReadClockRegister(RTC_MINUTE));
+ TimeFields->Second = (CSHORT)BCDToBinary(HalpReadClockRegister(RTC_SECOND));
+ TimeFields->Milliseconds = 0;
+
+ KeLowerIrql(OldIrql);
+ return TRUE;
+
+ } else {
+
+ KeLowerIrql(OldIrql);
+ return FALSE;
+ }
+}
+
+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.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL OldIrql;
+
+ //
+ // 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))->DayLightSavingsEnable = 1;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->HoursFormat = 1;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->DataMode = 0;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SetTime = 1;
+ HalpWriteClockRegister(RTC_CONTROL_REGISTERB, DataByte);
+
+ //
+ // Write the realtime clock values.
+ //
+
+ HalpWriteClockRegister(RTC_YEAR, (UCHAR)(BinaryToBCD(TimeFields->Year - 1900)));
+ HalpWriteClockRegister(RTC_MONTH, (UCHAR)BinaryToBCD(TimeFields->Month));
+ HalpWriteClockRegister(RTC_DAY_OF_MONTH, (UCHAR)BinaryToBCD(TimeFields->Day));
+ HalpWriteClockRegister(RTC_DAY_OF_WEEK, (UCHAR)(BinaryToBCD(TimeFields->Weekday + 1)));
+ HalpWriteClockRegister(RTC_HOUR, (UCHAR)BinaryToBCD(TimeFields->Hour));
+ HalpWriteClockRegister(RTC_MINUTE, (UCHAR)BinaryToBCD(TimeFields->Minute));
+ HalpWriteClockRegister(RTC_SECOND, (UCHAR)BinaryToBCD(TimeFields->Second));
+
+ //
+ // Set the realtime clock control to update the time.
+ //
+
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SetTime = 0;
+ 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.
+
+--*/
+
+{
+ //
+ // Insert the realtime clock register number, and write the value back
+ // to the EISA NMI enable register. This selects the realtime clock register
+ // that is read. Note this is a write only register and the EISA NMI
+ // is always enabled.
+ //
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase[0])->NmiEnable,
+ Register);
+
+ //
+ // Read the realtime clock register value.
+ //
+
+ return READ_REGISTER_UCHAR((PUCHAR)HalpRealTimeClockBase);
+}
+
+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:
+
+ The value of the register is returned as the function value.
+
+--*/
+
+{
+
+ //
+ // Insert the realtime clock register number, and write the value back
+ // to the EISA NMI enable register. This selects the realtime clock
+ // register that is written. Note this is a write only register and
+ // the EISA NMI is always enabled.
+ //
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase[0])->NmiEnable,
+ Register);
+
+ //
+ // Write the realtime clock register value.
+ //
+
+ WRITE_REGISTER_UCHAR((PUCHAR)HalpRealTimeClockBase, Value);
+
+ return;
+}