summaryrefslogtreecommitdiffstats
path: root/private/ntos/nthals/halflex/mips
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/mips
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/mips')
-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
20 files changed, 5306 insertions, 0 deletions
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;
+}