From e611b132f9b8abe35b362e5870b74bce94a1e58e Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 16 May 2020 20:51:50 -0700 Subject: initial commit --- private/ntos/nthals/halflex/adjust.c | 185 ++ private/ntos/nthals/halflex/allstart.c | 56 + private/ntos/nthals/halflex/alpha/addrsup.c | 820 +++++++++ private/ntos/nthals/halflex/alpha/alphaio.s | 1482 ++++++++++++++++ private/ntos/nthals/halflex/alpha/apoc.h | 167 ++ private/ntos/nthals/halflex/alpha/arcssup.c | 87 + private/ntos/nthals/halflex/alpha/dtidef.h | 149 ++ private/ntos/nthals/halflex/alpha/ev4int.c | 955 ++++++++++ private/ntos/nthals/halflex/alpha/ev4ints.s | 300 ++++ private/ntos/nthals/halflex/alpha/ev4prof.c | 585 +++++++ private/ntos/nthals/halflex/alpha/ev5ints.s | 397 +++++ private/ntos/nthals/halflex/alpha/ev5prof.c | 747 ++++++++ private/ntos/nthals/halflex/alpha/evclock.s | 119 ++ private/ntos/nthals/halflex/alpha/evxcache.c | 823 +++++++++ private/ntos/nthals/halflex/alpha/evxmem.s | 231 +++ private/ntos/nthals/halflex/alpha/evxprof.c | 342 ++++ private/ntos/nthals/halflex/alpha/halpal.s | 276 +++ private/ntos/nthals/halflex/alpha/info.c | 128 ++ private/ntos/nthals/halflex/alpha/initsys.c | 579 +++++++ private/ntos/nthals/halflex/alpha/intsup.c | 393 +++++ private/ntos/nthals/halflex/alpha/jxhalp.h | 404 +++++ private/ntos/nthals/halflex/alpha/jxmapio.c | 103 ++ private/ntos/nthals/halflex/alpha/minitlb.c | 221 +++ private/ntos/nthals/halflex/alpha/pcisup.c | 897 ++++++++++ private/ntos/nthals/halflex/alpha/perfcntr.c | 262 +++ private/ntos/nthals/halflex/alpha/portsup.c | 93 + private/ntos/nthals/halflex/alpha/xxidle.s | 62 + private/ntos/nthals/halflex/alpha/xxinitnt.c | 194 +++ private/ntos/nthals/halflex/busdata.c | 175 ++ private/ntos/nthals/halflex/bushnd.c | 7 + private/ntos/nthals/halflex/drivesup.c | 7 + private/ntos/nthals/halflex/hal.rc | 11 + private/ntos/nthals/halflex/hal.src | 7 + private/ntos/nthals/halflex/halp.h | 453 +++++ private/ntos/nthals/halflex/ioproc.c | 112 ++ private/ntos/nthals/halflex/iousage.c | 515 ++++++ private/ntos/nthals/halflex/iousage.h | 77 + private/ntos/nthals/halflex/makefile | 6 + private/ntos/nthals/halflex/makefile.inc | 5 + private/ntos/nthals/halflex/mips/addrsup.c | 204 +++ private/ntos/nthals/halflex/mips/arcssup.c | 144 ++ private/ntos/nthals/halflex/mips/dtidef.h | 150 ++ private/ntos/nthals/halflex/mips/flushio.c | 282 +++ private/ntos/nthals/halflex/mips/gambit.h | 54 + private/ntos/nthals/halflex/mips/info.c | 116 ++ private/ntos/nthals/halflex/mips/initsys.c | 405 +++++ private/ntos/nthals/halflex/mips/intsup.c | 240 +++ private/ntos/nthals/halflex/mips/j4cache.s | 1091 ++++++++++++ private/ntos/nthals/halflex/mips/j4flshbf.s | 61 + private/ntos/nthals/halflex/mips/j4prof.c | 290 ++++ private/ntos/nthals/halflex/mips/jxhalp.h | 122 ++ private/ntos/nthals/halflex/mips/jxmapio.c | 192 +++ private/ntos/nthals/halflex/mips/pcisup.c | 1008 +++++++++++ private/ntos/nthals/halflex/mips/portsup.c | 137 ++ private/ntos/nthals/halflex/mips/x4clock.s | 210 +++ private/ntos/nthals/halflex/mips/x4tb.s | 109 ++ private/ntos/nthals/halflex/mips/xxcalstl.c | 253 +++ private/ntos/nthals/halflex/mips/xxidle.s | 79 + private/ntos/nthals/halflex/mips/xxinitnt.c | 159 ++ private/ntos/nthals/halflex/pcip.h | 138 ++ private/ntos/nthals/halflex/platform.h | 194 +++ private/ntos/nthals/halflex/sources | 141 ++ private/ntos/nthals/halflex/uniflex.h | 108 ++ private/ntos/nthals/halflex/x86bios.c | 599 +++++++ private/ntos/nthals/halflex/xxbeep.c | 125 ++ private/ntos/nthals/halflex/xxclock.c | 174 ++ private/ntos/nthals/halflex/xxdisp.c | 293 ++++ private/ntos/nthals/halflex/xxebsup.c | 2375 +++++++++++++++++++++++++ private/ntos/nthals/halflex/xxenvirv.c | 106 ++ private/ntos/nthals/halflex/xxhwsup.c | 1250 ++++++++++++++ private/ntos/nthals/halflex/xxinithl.c | 286 +++ private/ntos/nthals/halflex/xxpcisup.c | 2391 ++++++++++++++++++++++++++ private/ntos/nthals/halflex/xxport.c | 769 +++++++++ private/ntos/nthals/halflex/xxreturn.c | 101 ++ private/ntos/nthals/halflex/xxsysint.c | 217 +++ private/ntos/nthals/halflex/xxtime.c | 285 +++ 76 files changed, 27290 insertions(+) create mode 100644 private/ntos/nthals/halflex/adjust.c create mode 100644 private/ntos/nthals/halflex/allstart.c create mode 100644 private/ntos/nthals/halflex/alpha/addrsup.c create mode 100644 private/ntos/nthals/halflex/alpha/alphaio.s create mode 100644 private/ntos/nthals/halflex/alpha/apoc.h create mode 100644 private/ntos/nthals/halflex/alpha/arcssup.c create mode 100644 private/ntos/nthals/halflex/alpha/dtidef.h create mode 100644 private/ntos/nthals/halflex/alpha/ev4int.c create mode 100644 private/ntos/nthals/halflex/alpha/ev4ints.s create mode 100644 private/ntos/nthals/halflex/alpha/ev4prof.c create mode 100644 private/ntos/nthals/halflex/alpha/ev5ints.s create mode 100644 private/ntos/nthals/halflex/alpha/ev5prof.c create mode 100644 private/ntos/nthals/halflex/alpha/evclock.s create mode 100644 private/ntos/nthals/halflex/alpha/evxcache.c create mode 100644 private/ntos/nthals/halflex/alpha/evxmem.s create mode 100644 private/ntos/nthals/halflex/alpha/evxprof.c create mode 100644 private/ntos/nthals/halflex/alpha/halpal.s create mode 100644 private/ntos/nthals/halflex/alpha/info.c create mode 100644 private/ntos/nthals/halflex/alpha/initsys.c create mode 100644 private/ntos/nthals/halflex/alpha/intsup.c create mode 100644 private/ntos/nthals/halflex/alpha/jxhalp.h create mode 100644 private/ntos/nthals/halflex/alpha/jxmapio.c create mode 100644 private/ntos/nthals/halflex/alpha/minitlb.c create mode 100644 private/ntos/nthals/halflex/alpha/pcisup.c create mode 100644 private/ntos/nthals/halflex/alpha/perfcntr.c create mode 100644 private/ntos/nthals/halflex/alpha/portsup.c create mode 100644 private/ntos/nthals/halflex/alpha/xxidle.s create mode 100644 private/ntos/nthals/halflex/alpha/xxinitnt.c create mode 100644 private/ntos/nthals/halflex/busdata.c create mode 100644 private/ntos/nthals/halflex/bushnd.c create mode 100644 private/ntos/nthals/halflex/drivesup.c create mode 100644 private/ntos/nthals/halflex/hal.rc create mode 100644 private/ntos/nthals/halflex/hal.src create mode 100644 private/ntos/nthals/halflex/halp.h create mode 100644 private/ntos/nthals/halflex/ioproc.c create mode 100644 private/ntos/nthals/halflex/iousage.c create mode 100644 private/ntos/nthals/halflex/iousage.h create mode 100644 private/ntos/nthals/halflex/makefile create mode 100644 private/ntos/nthals/halflex/makefile.inc create mode 100644 private/ntos/nthals/halflex/mips/addrsup.c create mode 100644 private/ntos/nthals/halflex/mips/arcssup.c create mode 100644 private/ntos/nthals/halflex/mips/dtidef.h create mode 100644 private/ntos/nthals/halflex/mips/flushio.c create mode 100644 private/ntos/nthals/halflex/mips/gambit.h create mode 100644 private/ntos/nthals/halflex/mips/info.c create mode 100644 private/ntos/nthals/halflex/mips/initsys.c create mode 100644 private/ntos/nthals/halflex/mips/intsup.c create mode 100644 private/ntos/nthals/halflex/mips/j4cache.s create mode 100644 private/ntos/nthals/halflex/mips/j4flshbf.s create mode 100644 private/ntos/nthals/halflex/mips/j4prof.c create mode 100644 private/ntos/nthals/halflex/mips/jxhalp.h create mode 100644 private/ntos/nthals/halflex/mips/jxmapio.c create mode 100644 private/ntos/nthals/halflex/mips/pcisup.c create mode 100644 private/ntos/nthals/halflex/mips/portsup.c create mode 100644 private/ntos/nthals/halflex/mips/x4clock.s create mode 100644 private/ntos/nthals/halflex/mips/x4tb.s create mode 100644 private/ntos/nthals/halflex/mips/xxcalstl.c create mode 100644 private/ntos/nthals/halflex/mips/xxidle.s create mode 100644 private/ntos/nthals/halflex/mips/xxinitnt.c create mode 100644 private/ntos/nthals/halflex/pcip.h create mode 100644 private/ntos/nthals/halflex/platform.h create mode 100644 private/ntos/nthals/halflex/sources create mode 100644 private/ntos/nthals/halflex/uniflex.h create mode 100644 private/ntos/nthals/halflex/x86bios.c create mode 100644 private/ntos/nthals/halflex/xxbeep.c create mode 100644 private/ntos/nthals/halflex/xxclock.c create mode 100644 private/ntos/nthals/halflex/xxdisp.c create mode 100644 private/ntos/nthals/halflex/xxebsup.c create mode 100644 private/ntos/nthals/halflex/xxenvirv.c create mode 100644 private/ntos/nthals/halflex/xxhwsup.c create mode 100644 private/ntos/nthals/halflex/xxinithl.c create mode 100644 private/ntos/nthals/halflex/xxpcisup.c create mode 100644 private/ntos/nthals/halflex/xxport.c create mode 100644 private/ntos/nthals/halflex/xxreturn.c create mode 100644 private/ntos/nthals/halflex/xxsysint.c create mode 100644 private/ntos/nthals/halflex/xxtime.c (limited to 'private/ntos/nthals/halflex') diff --git a/private/ntos/nthals/halflex/adjust.c b/private/ntos/nthals/halflex/adjust.c new file mode 100644 index 000000000..c42bacc93 --- /dev/null +++ b/private/ntos/nthals/halflex/adjust.c @@ -0,0 +1,185 @@ +/*++ + + +Copyright (C) 1989-1995 Microsoft Corporation +Copyright (c) 1994,1995 Digital Equipment Corporation + +Module Name: + + adjust.c + +Abstract: + + This module contains platform-independent slot resource adjust routines. + +Environment: + + Kernel mode + + +--*/ + +#include "halp.h" + + + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE,HalpAdjustResourceListUpperLimits) +#endif + +VOID +HalpAdjustResourceListUpperLimits ( + IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList, + IN LARGE_INTEGER MaximumPortAddress, + IN LARGE_INTEGER MaximumMemoryAddress, + IN ULONG MaximumInterruptVector, + IN ULONG MaximumDmaChannel + ) +/*++ + +Routine Description: + + Adjust a pResource list with respect to the upper bounds supplied. + (A resource is changed only if it execceds the maximum.) + +Arguments: + + pResouceList - Resource list to be checked. + + MaximumPortAddress - Maximum I/O port allowed. + + MaximumMemoryAddress - Maximum I/O memory address allowed. + + MaximumInterruptVector - Maximum interrupt vector allowed. + + MaximumDmaChannel - Maximum dma channel allowed. + +Return Value: + + None. + +--*/ +{ + PIO_RESOURCE_REQUIREMENTS_LIST CompleteList; + PIO_RESOURCE_LIST ResourceList; + PIO_RESOURCE_DESCRIPTOR Descriptor; + ULONG alt, cnt; + + + // + // Walk each ResourceList and shrink any values to system limits + // + + CompleteList = *pResourceList; + ResourceList = CompleteList->List; + + for (alt=0; alt < CompleteList->AlternativeLists; alt++) { + Descriptor = ResourceList->Descriptors; + for (cnt = ResourceList->Count; cnt; cnt--) { + + // + // Make sure descriptor limits fall within the + // CompleteList->InterfaceType & CompleteList->BusNumber. + // + // + + switch (Descriptor->Type) { + case CmResourceTypePort: + if (Descriptor->u.Port.MaximumAddress.QuadPart > + MaximumPortAddress.QuadPart) { + + Descriptor->u.Port.MaximumAddress = MaximumPortAddress; + } + + break; + + case CmResourceTypeInterrupt: + if (Descriptor->u.Interrupt.MaximumVector > + MaximumInterruptVector ) { + + Descriptor->u.Interrupt.MaximumVector = + MaximumInterruptVector; + } + break; + + case CmResourceTypeMemory: + if (Descriptor->u.Memory.MaximumAddress.QuadPart > + MaximumMemoryAddress.QuadPart) { + + Descriptor->u.Memory.MaximumAddress = + MaximumMemoryAddress; + } + break; + + case CmResourceTypeDma: + if (Descriptor->u.Dma.MaximumChannel > + MaximumDmaChannel ) { + + Descriptor->u.Dma.MaximumChannel = + MaximumDmaChannel; + } + break; + +#if DBG + default: + DbgPrint ("HalAdjustResourceList: Unkown resource type\n"); + break; +#endif + } + + // + // Next descriptor + // + Descriptor++; + } + + // + // Next Resource List + // + ResourceList = (PIO_RESOURCE_LIST) Descriptor; + } + +} + +NTSTATUS +HalpAdjustIsaResourceList ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList + ) +/*++ + +Routine Description: + + The function adjusts pResourceList to keep it in the bounds of ISA bus + resources. + +Arguments: + + BusHandler - Registered BUSHANDLER for the target configuration space + + RootHandler - Register BUSHANDLER for the orginating HalAdjustResourceList request. + + pResourceList - Supplies the PIO_RESOURCE_REQUIREMENTS_LIST to be checked. + +Return Value: + + STATUS_SUCCESS + +--*/ +{ + LARGE_INTEGER li64k, limem; + + li64k.QuadPart = 0xffff; + limem.QuadPart = 0xffffff; + + HalpAdjustResourceListUpperLimits ( + pResourceList, + li64k, // Bus supports up to I/O port 0xFFFF + limem, // Bus supports up to memory 0xFFFFFF + 15, // Bus supports up to 15 IRQs + 7 // Bus supports up to Dma channel 7 + ); + + return STATUS_SUCCESS; +} diff --git a/private/ntos/nthals/halflex/allstart.c b/private/ntos/nthals/halflex/allstart.c new file mode 100644 index 000000000..8d81b6eb8 --- /dev/null +++ b/private/ntos/nthals/halflex/allstart.c @@ -0,0 +1,56 @@ +/*++ + +Copyright (c) 1994 Microsoft Corporation + +Module Name: + + allstart.c + +Abstract: + + + This module implements the platform specific operations that must be + performed after all processors have been started. + +Author: + + David N. Cutler (davec) 19-Jun-1994 + +Environment: + + Kernel mode only. + +Revision History: + +--*/ + +#include "halp.h" + +BOOLEAN +HalAllProcessorsStarted ( + VOID + ) + +/*++ + +Routine Description: + + This function executes platform specific operations that must be + performed after all processors have been started. It is called + for each processor in the host configuration. + +Arguments: + + None. + +Return Value: + + If platform specific operations are successful, then return TRUE. + Otherwise, return FALSE. + +--*/ + +{ + + return TRUE; +} diff --git a/private/ntos/nthals/halflex/alpha/addrsup.c b/private/ntos/nthals/halflex/alpha/addrsup.c new file mode 100644 index 000000000..08174ae45 --- /dev/null +++ b/private/ntos/nthals/halflex/alpha/addrsup.c @@ -0,0 +1,820 @@ +/*++ + +Copyright (c) 1993 Digital Equipment Corporation + +Module Name: + + addrsup.c + +Abstract: + + This module contains the platform dependent code to create bus addreses + and QVAs for the EB64+ system. + +Author: + + Joe Notarangelo 22-Oct-1993 + +Environment: + + Kernel mode + +Revision History: + + Dick Bissen (Digital) 30-Jun-1994 + Added code to check the new PCI Memory MAp address range which is + impacted by the EPEC HAXR1. + + Eric Rehm (Digital) 03-Jan-1994 + Added PCIBus(0) and dense space support to all routines. + +--*/ + +#include "halp.h" + +typedef PVOID QUASI_VIRTUAL_ADDRESS; + +#define HAL_MAKE_LQVA(PA) (LONGLONG)HAL_MAKE_QVA(PA) +#define HAL_MAKE_TA(PA,ByteOffset) (LONGLONG)(PA) + (LONGLONG)((ByteOffset) << IO_BIT_SHIFT) + +#define KERNEL_PCI_VGA_VIDEO_ROM (LONGLONG)(0x8000000000000000) +#define USER_PCI_VGA_VIDEO_ROM (LONGLONG)(0x4000000000000000) + +PLATFORM_RANGE_LIST Apoc10Trebbia13RangeList[] = { + { Isa , 0, BusIo, 1, HAL_MAKE_LQVA(TREB1_APOC1_ISA_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff }, + { Isa , 0, BusMemory, 1, HAL_MAKE_LQVA(TREB1_APOC1_ISA_MEMORY_BASE_PHYSICAL) , 0x00000000, 0x00ffffff }, + + { Isa , 0, UserBusIo, 0, TREB1_APOC1_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { Isa , 0, UserBusMemory, 0, TREB1_APOC1_ISA_MEMORY_BASE_PHYSICAL , 0x00000000, 0x00ffffff }, + + { Isa , 1, BusIo, 1, HAL_MAKE_LQVA(TREB1_APOC1_ISA1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff }, + { Isa , 1, BusMemory, 1, HAL_MAKE_LQVA(TREB1_APOC1_ISA1_MEMORY_BASE_PHYSICAL)+0xa0000, 0x000a0000, 0x000bffff }, + { Isa , 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff }, + + { Isa , 1, UserBusIo, 0, TREB1_APOC1_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { Isa , 1, UserBusMemory, 0, HAL_MAKE_TA(TREB1_APOC1_ISA1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff }, + { Isa , 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB1_APOC1_ISA1_MEMORY_BASE_PHYSICAL, 0x000c0000, 0x000c7fff }, + + { Eisa , 0, BusIo, 1, HAL_MAKE_LQVA(TREB1_APOC1_ISA_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff }, + { Eisa , 0, BusMemory, 1, HAL_MAKE_LQVA(TREB1_APOC1_ISA_MEMORY_BASE_PHYSICAL) , 0x00000000, 0x07ffffff }, + + { Eisa , 0, UserBusIo, 0, TREB1_APOC1_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { Eisa , 0, UserBusMemory, 0, TREB1_APOC1_ISA_MEMORY_BASE_PHYSICAL , 0x00000000, 0x07ffffff }, + + { Eisa , 1, BusIo, 1, HAL_MAKE_LQVA(TREB1_APOC1_ISA1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff }, + { Eisa , 1, BusMemory, 1, HAL_MAKE_LQVA(TREB1_APOC1_ISA1_MEMORY_BASE_PHYSICAL)+0xa0000, 0x000a0000, 0x000bffff }, + { Eisa , 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff }, + + { Eisa , 1, UserBusIo, 0, TREB1_APOC1_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { Eisa , 1, UserBusMemory, 0, HAL_MAKE_TA(TREB1_APOC1_ISA1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff }, + { Eisa , 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB1_APOC1_ISA1_MEMORY_BASE_PHYSICAL, 0x000c0000, 0x000c7fff }, + + { PCIBus, 0, BusIo, 1, HAL_MAKE_LQVA(TREB1_APOC1_PCI_IO_BASE_PHYSICAL) , 0x00000000, 0x07ffffff }, + { PCIBus, 0, BusMemory, 1, HAL_MAKE_LQVA(TREB1_APOC1_PCI_HIGH_MEMORY_BASE_PHYSICAL) , 0x40000000, 0x47ffffff }, + + { PCIBus, 0, UserBusIo, 0, TREB1_APOC1_PCI_IO_BASE_PHYSICAL , 0x00000000, 0x07ffffff }, + { PCIBus, 0, UserBusMemory, 0, TREB1_APOC1_PCI_HIGH_MEMORY_BASE_PHYSICAL , 0x40000000, 0x47ffffff }, + + { PCIBus, 1, BusIo, 1, HAL_MAKE_LQVA(TREB1_APOC1_PCI_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff }, + { PCIBus, 1, BusMemory, 1, HAL_MAKE_LQVA(TREB1_APOC1_PCI_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff }, + { PCIBus, 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff }, + { PCIBus, 1, BusMemory, 1, HAL_MAKE_LQVA(TREB1_APOC1_PCI_HIGH_MEMORY_BASE_PHYSICAL) , 0x40000000, 0x47ffffff }, + + { PCIBus, 1, UserBusIo, 0, TREB1_APOC1_PCI_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { PCIBus, 1, UserBusMemory, 0, HAL_MAKE_TA(TREB1_APOC1_PCI_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff }, + { PCIBus, 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB1_APOC1_PCI_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff }, + { PCIBus, 1, UserBusMemory, 0, TREB1_APOC1_PCI_HIGH_MEMORY_BASE_PHYSICAL , 0x40000000, 0x47ffffff }, + + { MaximumInterfaceType, 0, 0, 0, 0 , 0 , 0 } +}; + +PLATFORM_RANGE_LIST Apoc20Trebbia13RangeList[] = { + { Isa , 0, BusIo, 1, HAL_MAKE_LQVA(TREB1_APOC2_ISA_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff }, + { Isa , 0, BusMemory, 1, HAL_MAKE_LQVA(TREB1_APOC2_ISA_MEMORY_BASE_PHYSICAL) , 0x00000000, 0x00ffffff }, + + { Isa , 0, UserBusIo, 0, TREB1_APOC2_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { Isa , 0, UserBusMemory, 0, TREB1_APOC2_ISA_MEMORY_BASE_PHYSICAL , 0x00000000, 0x00ffffff }, + + { Isa , 1, BusIo, 1, HAL_MAKE_LQVA(TREB1_APOC2_ISA1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff }, + { Isa , 1, BusMemory, 1, HAL_MAKE_LQVA(TREB1_APOC2_ISA1_MEMORY_BASE_PHYSICAL)+0xa0000, 0x000a0000, 0x000bffff }, + { Isa , 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM|HAL_MAKE_LQVA(APOC2_TRANSLATED_MEMORY_BASE_PHYSICAL) , 0x000c0000, 0x000c7fff }, + + { Isa , 1, UserBusIo, 0, TREB1_APOC2_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { Isa , 1, UserBusMemory, 0, HAL_MAKE_TA(TREB1_APOC2_ISA1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff }, + { Isa , 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB1_APOC2_ISA1_MEMORY_BASE_PHYSICAL, 0x000c0000, 0x000c7fff }, + + { Eisa , 0, BusIo, 1, HAL_MAKE_LQVA(TREB1_APOC2_ISA_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff }, + { Eisa , 0, BusMemory, 1, HAL_MAKE_LQVA(TREB1_APOC2_ISA_MEMORY_BASE_PHYSICAL) , 0x00000000, 0x07ffffff }, + + { Eisa , 0, UserBusIo, 0, TREB1_APOC2_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { Eisa , 0, UserBusMemory, 0, TREB1_APOC2_ISA_MEMORY_BASE_PHYSICAL , 0x00000000, 0x07ffffff }, + + { Eisa , 1, BusIo, 1, HAL_MAKE_LQVA(TREB1_APOC2_ISA1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff }, + { Eisa , 1, BusMemory, 1, HAL_MAKE_LQVA(TREB1_APOC2_ISA1_MEMORY_BASE_PHYSICAL)+0xa0000, 0x000a0000, 0x000bffff }, + { Eisa , 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM|HAL_MAKE_LQVA(APOC2_TRANSLATED_MEMORY_BASE_PHYSICAL) , 0x000c0000, 0x000c7fff }, + + { Eisa , 1, UserBusIo, 0, TREB1_APOC2_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { Eisa , 1, UserBusMemory, 0, HAL_MAKE_TA(TREB1_APOC2_ISA1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff }, + { Eisa , 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB1_APOC2_ISA1_MEMORY_BASE_PHYSICAL, 0x000c0000, 0x000c7fff }, + + { PCIBus, 0, BusIo, 1, HAL_MAKE_LQVA(TREB1_APOC2_PCI_IO_BASE_PHYSICAL) , 0x00000000, 0x07ffffff }, + { PCIBus, 0, BusMemory, 1, HAL_MAKE_LQVA(TREB1_APOC2_PCI_HIGH_MEMORY_BASE_PHYSICAL) , 0x40000000, 0x47ffffff }, + + { PCIBus, 0, UserBusIo, 0, TREB1_APOC2_PCI_IO_BASE_PHYSICAL , 0x00000000, 0x07ffffff }, + { PCIBus, 0, UserBusMemory, 0, TREB1_APOC2_PCI_HIGH_MEMORY_BASE_PHYSICAL , 0x40000000, 0x47ffffff }, + + { PCIBus, 1, BusIo, 1, HAL_MAKE_LQVA(TREB1_APOC2_PCI_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff }, + { PCIBus, 1, BusMemory, 1, HAL_MAKE_LQVA(TREB1_APOC2_PCI_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff }, + { PCIBus, 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM|HAL_MAKE_LQVA(APOC2_TRANSLATED_MEMORY_BASE_PHYSICAL) , 0x000c0000, 0x000c7fff }, + { PCIBus, 1, BusMemory, 1, HAL_MAKE_LQVA(TREB1_APOC2_PCI_HIGH_MEMORY_BASE_PHYSICAL) , 0x40000000, 0x47ffffff }, + + { PCIBus, 1, UserBusIo, 0, TREB1_APOC2_PCI_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { PCIBus, 1, UserBusMemory, 0, HAL_MAKE_TA(TREB1_APOC2_PCI_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff }, + { PCIBus, 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB1_APOC2_PCI_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff }, + { PCIBus, 1, UserBusMemory, 0, TREB1_APOC2_PCI_HIGH_MEMORY_BASE_PHYSICAL , 0x40000000, 0x47ffffff }, + + { MaximumInterfaceType, 0, 0, 0, 0 , 0 , 0 } +}; + +PLATFORM_RANGE_LIST Rogue0Trebbia13RangeList[] = { + { Isa , 0, BusIo, 1, HAL_MAKE_LQVA(TREB1_ROGUE_ISA_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff }, + { Isa , 0, BusMemory, 1, HAL_MAKE_LQVA(TREB1_ROGUE_ISA_MEMORY_BASE_PHYSICAL) , 0x00000000, 0x00ffffff }, + + { Isa , 0, UserBusIo, 0, TREB1_ROGUE_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { Isa , 0, UserBusMemory, 0, TREB1_ROGUE_ISA_MEMORY_BASE_PHYSICAL , 0x00000000, 0x00ffffff }, + + { Isa , 1, BusIo, 1, HAL_MAKE_LQVA(TREB1_ROGUE_ISA1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff }, + { Isa , 1, BusMemory, 1, HAL_MAKE_LQVA(TREB1_ROGUE_ISA1_MEMORY_BASE_PHYSICAL)+0xa0000, 0x000a0000, 0x000bffff }, + { Isa , 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff }, + + { Isa , 1, UserBusIo, 0, TREB1_ROGUE_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { Isa , 1, UserBusMemory, 0, HAL_MAKE_TA(TREB1_ROGUE_ISA1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff }, + { Isa , 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB1_ROGUE_ISA1_MEMORY_BASE_PHYSICAL, 0x000c0000, 0x000c7fff }, + + { Eisa , 0, BusIo, 1, HAL_MAKE_LQVA(TREB1_ROGUE_ISA_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff }, + { Eisa , 0, BusMemory, 1, HAL_MAKE_LQVA(TREB1_ROGUE_ISA_MEMORY_BASE_PHYSICAL) , 0x00000000, 0x07ffffff }, + + { Eisa , 0, UserBusIo, 0, TREB1_ROGUE_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { Eisa , 0, UserBusMemory, 0, TREB1_ROGUE_ISA_MEMORY_BASE_PHYSICAL , 0x00000000, 0x07ffffff }, + + { Eisa , 1, BusIo, 1, HAL_MAKE_LQVA(TREB1_ROGUE_ISA1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff }, + { Eisa , 1, BusMemory, 1, HAL_MAKE_LQVA(TREB1_ROGUE_ISA1_MEMORY_BASE_PHYSICAL)+0xa0000, 0x000a0000, 0x000bffff }, + { Eisa , 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff }, + + { Eisa , 1, UserBusIo, 0, TREB1_ROGUE_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { Eisa , 1, UserBusMemory, 0, HAL_MAKE_TA(TREB1_ROGUE_ISA1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff }, + { Eisa , 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB1_ROGUE_ISA1_MEMORY_BASE_PHYSICAL, 0x000c0000, 0x000c7fff }, + + { PCIBus, 0, BusIo, 1, HAL_MAKE_LQVA(TREB1_ROGUE_PCI_IO_BASE_PHYSICAL) , 0x00000000, 0x07ffffff }, + { PCIBus, 0, BusMemory, 1, HAL_MAKE_LQVA(TREB1_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL) , 0x40000000, 0x47ffffff }, + + { PCIBus, 0, UserBusIo, 0, TREB1_ROGUE_PCI_IO_BASE_PHYSICAL , 0x00000000, 0x07ffffff }, + { PCIBus, 0, UserBusMemory, 0, TREB1_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL , 0x40000000, 0x47ffffff }, + + { PCIBus, 1, BusIo, 1, HAL_MAKE_LQVA(TREB1_ROGUE_PCI_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff }, + { PCIBus, 1, BusMemory, 1, HAL_MAKE_LQVA(TREB1_ROGUE_PCI_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff }, + { PCIBus, 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff }, + { PCIBus, 1, BusMemory, 1, HAL_MAKE_LQVA(TREB1_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL) , 0x40000000, 0x47ffffff }, + + { PCIBus, 1, UserBusIo, 0, TREB1_ROGUE_PCI_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { PCIBus, 1, UserBusMemory, 0, HAL_MAKE_TA(TREB1_ROGUE_PCI_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff }, + { PCIBus, 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB1_ROGUE_PCI_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff }, + { PCIBus, 1, UserBusMemory, 0, TREB1_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL , 0x40000000, 0x47ffffff }, + + { MaximumInterfaceType, 0, 0, 0, 0 , 0 , 0 } +}; + +PLATFORM_RANGE_LIST Rogue1Trebbia13RangeList[] = { + { Isa , 0, BusIo, 1, HAL_MAKE_LQVA(TREB1_ROGUE_ISA_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff }, + { Isa , 0, BusMemory, 1, HAL_MAKE_LQVA(TREB1_ROGUE_ISA_MEMORY_BASE_PHYSICAL) , 0x00000000, 0x00ffffff }, + + { Isa , 0, UserBusIo, 0, TREB1_ROGUE_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { Isa , 0, UserBusMemory, 0, TREB1_ROGUE_ISA_MEMORY_BASE_PHYSICAL , 0x00000000, 0x00ffffff }, + + { Isa , 1, BusIo, 1, HAL_MAKE_LQVA(TREB1_ROGUE_ISA1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff }, + { Isa , 1, BusMemory, 1, HAL_MAKE_LQVA(TREB1_ROGUE_ISA1_MEMORY_BASE_PHYSICAL)+0xa0000, 0x000a0000, 0x000bffff }, + { Isa , 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff }, + + { Isa , 1, UserBusIo, 0, TREB1_ROGUE_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { Isa , 1, UserBusMemory, 0, HAL_MAKE_TA(TREB1_ROGUE_ISA1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff }, + { Isa , 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB1_ROGUE_ISA1_MEMORY_BASE_PHYSICAL, 0x000c0000, 0x000c7fff }, + + { Eisa , 0, BusIo, 1, HAL_MAKE_LQVA(TREB1_ROGUE_ISA_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff }, + { Eisa , 0, BusMemory, 1, HAL_MAKE_LQVA(TREB1_ROGUE_ISA_MEMORY_BASE_PHYSICAL) , 0x00000000, 0x07ffffff }, + + { Eisa , 0, UserBusIo, 0, TREB1_ROGUE_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { Eisa , 0, UserBusMemory, 0, TREB1_ROGUE_ISA_MEMORY_BASE_PHYSICAL , 0x00000000, 0x07ffffff }, + + { Eisa , 1, BusIo, 1, HAL_MAKE_LQVA(TREB1_ROGUE_ISA1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff }, + { Eisa , 1, BusMemory, 1, HAL_MAKE_LQVA(TREB1_ROGUE_ISA1_MEMORY_BASE_PHYSICAL)+0xa0000, 0x000a0000, 0x000bffff }, + { Eisa , 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff }, + + { Eisa , 1, UserBusIo, 0, TREB1_ROGUE_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { Eisa , 1, UserBusMemory, 0, HAL_MAKE_TA(TREB1_ROGUE_ISA1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff }, + { Eisa , 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB1_ROGUE_ISA1_MEMORY_BASE_PHYSICAL, 0x000c0000, 0x000c7fff }, + + { PCIBus, 0, BusIo, 1, HAL_MAKE_LQVA(TREB1_ROGUE_PCI_IO_BASE_PHYSICAL) , 0x00000000, 0x07ffffff }, + { PCIBus, 0, BusMemory, 1, HAL_MAKE_LQVA(TREB1_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL) , 0x40000000, 0x47ffffff }, + + { PCIBus, 0, UserBusIo, 0, TREB1_ROGUE_PCI_IO_BASE_PHYSICAL , 0x00000000, 0x07ffffff }, + { PCIBus, 0, UserBusMemory, 0, TREB1_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL , 0x40000000, 0x47ffffff }, + + { PCIBus, 1, BusIo, 1, HAL_MAKE_LQVA(TREB1_ROGUE_PCI_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff }, + { PCIBus, 1, BusMemory, 1, HAL_MAKE_LQVA(TREB1_ROGUE_PCI_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff }, + { PCIBus, 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff }, + { PCIBus, 1, BusMemory, 1, HAL_MAKE_LQVA(TREB1_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL) , 0x40000000, 0x47ffffff }, + + { PCIBus, 1, UserBusIo, 0, TREB1_ROGUE_PCI_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { PCIBus, 1, UserBusMemory, 0, HAL_MAKE_TA(TREB1_ROGUE_PCI_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff }, + { PCIBus, 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB1_ROGUE_PCI_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff }, + { PCIBus, 1, UserBusMemory, 0, TREB1_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL , 0x40000000, 0x47ffffff }, + + { MaximumInterfaceType, 0, 0, 0, 0 , 0 , 0 } +}; + +PLATFORM_RANGE_LIST Apoc10Trebbia20RangeList[] = { + { Isa , 0, BusIo, 1, HAL_MAKE_LQVA(TREB2_APOC1_ISA_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff }, + { Isa , 0, BusMemory, 1, HAL_MAKE_LQVA(TREB2_APOC1_ISA_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff }, + { Isa , 0, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff }, + + { Isa , 0, UserBusIo, 0, TREB2_APOC1_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { Isa , 0, UserBusMemory, 0, HAL_MAKE_TA(TREB2_APOC1_ISA_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff }, + { Isa , 0, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_APOC1_ISA_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff }, + + { Isa , 1, BusIo, 1, HAL_MAKE_LQVA(TREB2_APOC1_ISA1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff }, + { Isa , 1, BusMemory, 1, HAL_MAKE_LQVA(TREB2_APOC1_ISA1_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff }, + { Isa , 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff }, + + { Isa , 1, UserBusIo, 0, TREB2_APOC1_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { Isa , 1, UserBusMemory, 0, HAL_MAKE_TA(TREB2_APOC1_ISA1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff }, + { Isa , 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_APOC1_ISA1_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff }, + + { Eisa , 0, BusIo, 1, HAL_MAKE_LQVA(TREB2_APOC1_ISA_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff }, + { Eisa , 0, BusMemory, 1, HAL_MAKE_LQVA(TREB2_APOC1_ISA_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff }, + { Eisa , 0, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff }, + + { Eisa , 0, UserBusIo, 0, TREB2_APOC1_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { Eisa , 0, UserBusMemory, 0, HAL_MAKE_TA(TREB2_APOC1_ISA_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff }, + { Eisa , 0, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_APOC1_ISA_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff }, + + { Eisa , 1, BusIo, 1, HAL_MAKE_LQVA(TREB2_APOC1_ISA1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff }, + { Eisa , 1, BusMemory, 1, HAL_MAKE_LQVA(TREB2_APOC1_ISA1_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff }, + { Eisa , 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff }, + + { Eisa , 1, UserBusIo, 0, TREB2_APOC1_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { Eisa , 1, UserBusMemory, 0, HAL_MAKE_TA(TREB2_APOC1_ISA1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff }, + { Eisa , 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_APOC1_ISA1_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff }, + + { PCIBus, 0, BusIo, 1, HAL_MAKE_LQVA(TREB2_APOC1_PCI_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff }, + { PCIBus, 0, BusMemory, 1, HAL_MAKE_LQVA(TREB2_APOC1_PCI_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff }, + { PCIBus, 0, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff }, + { PCIBus, 0, BusMemory, 1, HAL_MAKE_LQVA(TREB2_APOC1_PCI_HIGH_MEMORY_BASE_PHYSICAL) , 0x40000000, 0x47ffffff }, + + { PCIBus, 0, UserBusIo, 0, TREB2_APOC1_PCI_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { PCIBus, 0, UserBusMemory, 0, HAL_MAKE_TA(TREB2_APOC1_PCI_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff }, + { PCIBus, 0, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_APOC1_PCI_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff }, + { PCIBus, 0, UserBusMemory, 0, TREB2_APOC1_PCI_HIGH_MEMORY_BASE_PHYSICAL , 0x40000000, 0x47ffffff }, + + { PCIBus, 1, BusIo, 1, HAL_MAKE_LQVA(TREB2_APOC1_PCI1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff }, + { PCIBus, 1, BusMemory, 1, HAL_MAKE_LQVA(TREB2_APOC1_PCI1_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff }, + { PCIBus, 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff }, + { PCIBus, 1, BusMemory, 1, HAL_MAKE_LQVA(TREB2_APOC1_PCI_HIGH_MEMORY_BASE_PHYSICAL) , 0x40000000, 0x47ffffff }, + + { PCIBus, 1, UserBusIo, 0, TREB2_APOC1_PCI1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { PCIBus, 1, UserBusMemory, 0, HAL_MAKE_TA(TREB2_APOC1_PCI1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff }, + { PCIBus, 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_APOC1_PCI1_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff }, + { PCIBus, 1, UserBusMemory, 0, TREB2_APOC1_PCI_HIGH_MEMORY_BASE_PHYSICAL , 0x40000000, 0x47ffffff }, + + { MaximumInterfaceType, 0, 0, 0, 0 , 0 , 0 } +}; + +PLATFORM_RANGE_LIST Apoc20Trebbia20RangeList[] = { + { Isa , 0, BusIo, 1, HAL_MAKE_LQVA(TREB2_APOC2_ISA_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff }, + { Isa , 0, BusMemory, 1, HAL_MAKE_LQVA(TREB2_APOC2_ISA_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff }, + { Isa , 0, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM|HAL_MAKE_LQVA(APOC2_TRANSLATED_MEMORY_BASE_PHYSICAL) , 0x000c0000, 0x000c7fff }, + { Isa , 0, KernelPciDenseMemory, 2, APOC2_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff }, + + { Isa , 0, UserBusIo, 0, TREB2_APOC2_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { Isa , 0, UserBusMemory, 0, HAL_MAKE_TA(TREB2_APOC2_ISA_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff }, + { Isa , 0, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_APOC2_ISA_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff }, + { Isa , 0, UserPciDenseMemory, 2, APOC2_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff }, + + { Isa , 1, BusIo, 1, HAL_MAKE_LQVA(TREB2_APOC2_ISA1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff }, + { Isa , 1, BusMemory, 1, HAL_MAKE_LQVA(TREB2_APOC2_ISA1_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff }, + { Isa , 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM|HAL_MAKE_LQVA(APOC2_TRANSLATED_MEMORY_BASE_PHYSICAL) , 0x000c0000, 0x000c7fff }, + { Isa , 1, KernelPciDenseMemory, 2, APOC2_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff }, + + { Isa , 1, UserBusIo, 0, TREB2_APOC2_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { Isa , 1, UserBusMemory, 0, HAL_MAKE_TA(TREB2_APOC2_ISA1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff }, + { Isa , 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_APOC2_ISA1_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff }, + { Isa , 1, UserPciDenseMemory, 2, APOC2_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff }, + + { Eisa , 0, BusIo, 1, HAL_MAKE_LQVA(TREB2_APOC2_ISA_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff }, + { Eisa , 0, BusMemory, 1, HAL_MAKE_LQVA(TREB2_APOC2_ISA_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff }, + { Eisa , 0, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM|HAL_MAKE_LQVA(APOC2_TRANSLATED_MEMORY_BASE_PHYSICAL) , 0x000c0000, 0x000c7fff }, + { Eisa , 0, KernelPciDenseMemory, 2, APOC2_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff }, + + { Eisa , 0, UserBusIo, 0, TREB2_APOC2_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { Eisa , 0, UserBusMemory, 0, HAL_MAKE_TA(TREB2_APOC2_ISA_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff }, + { Eisa , 0, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_APOC2_ISA_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff }, + { Eisa , 0, UserPciDenseMemory, 2, APOC2_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff }, + + { Eisa , 1, BusIo, 1, HAL_MAKE_LQVA(TREB2_APOC2_ISA1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff }, + { Eisa , 1, BusMemory, 1, HAL_MAKE_LQVA(TREB2_APOC2_ISA1_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff }, + { Eisa , 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM|HAL_MAKE_LQVA(APOC2_TRANSLATED_MEMORY_BASE_PHYSICAL) , 0x000c0000, 0x000c7fff }, + { Eisa , 1, KernelPciDenseMemory, 2, APOC2_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff }, + + { Eisa , 1, UserBusIo, 0, TREB2_APOC2_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { Eisa , 1, UserBusMemory, 0, HAL_MAKE_TA(TREB2_APOC2_ISA1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff }, + { Eisa , 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_APOC2_ISA1_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff }, + { Eisa , 1, UserPciDenseMemory, 2, APOC2_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff }, + + { PCIBus, 0, BusIo, 1, HAL_MAKE_LQVA(TREB2_APOC2_PCI_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff }, + { PCIBus, 0, BusMemory, 1, HAL_MAKE_LQVA(TREB2_APOC2_PCI_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff }, + { PCIBus, 0, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM|HAL_MAKE_LQVA(APOC2_TRANSLATED_MEMORY_BASE_PHYSICAL) , 0x000c0000, 0x000c7fff }, + { PCIBus, 0, BusMemory, 1, HAL_MAKE_LQVA(TREB2_APOC2_PCI_HIGH_MEMORY_BASE_PHYSICAL) , 0x40000000, 0x47ffffff }, + { PCIBus, 0, KernelPciDenseMemory, 2, APOC2_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff }, + { PCIBus, 0, KernelPciDenseMemory, 2, APOC2_PCI_DENSE_BASE_PHYSICAL+0x40000000 , 0x40000000, 0x7fffffff }, + + { PCIBus, 0, UserBusIo, 0, TREB2_APOC2_PCI_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { PCIBus, 0, UserBusMemory, 0, HAL_MAKE_TA(TREB2_APOC2_PCI_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff }, + { PCIBus, 0, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_APOC2_PCI_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff }, + { PCIBus, 0, UserBusMemory, 0, TREB2_APOC2_PCI_HIGH_MEMORY_BASE_PHYSICAL , 0x40000000, 0x47ffffff }, + { PCIBus, 0, UserPciDenseMemory, 2, APOC2_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff }, + { PCIBus, 0, UserPciDenseMemory, 2, APOC2_PCI_DENSE_BASE_PHYSICAL+0x40000000 , 0x40000000, 0x7fffffff }, + + { PCIBus, 1, BusIo, 1, HAL_MAKE_LQVA(TREB2_APOC2_PCI1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff }, + { PCIBus, 1, BusMemory, 1, HAL_MAKE_LQVA(TREB2_APOC2_PCI1_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff }, + { PCIBus, 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM|HAL_MAKE_LQVA(APOC2_TRANSLATED_MEMORY_BASE_PHYSICAL) , 0x000c0000, 0x000c7fff }, + { PCIBus, 1, BusMemory, 1, HAL_MAKE_LQVA(TREB2_APOC2_PCI_HIGH_MEMORY_BASE_PHYSICAL) , 0x40000000, 0x47ffffff }, + { PCIBus, 1, KernelPciDenseMemory, 2, APOC2_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff }, + { PCIBus, 1, KernelPciDenseMemory, 2, APOC2_PCI_DENSE_BASE_PHYSICAL+0x40000000 , 0x40000000, 0x7fffffff }, + + { PCIBus, 1, UserBusIo, 0, TREB2_APOC2_PCI1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { PCIBus, 1, UserBusMemory, 0, HAL_MAKE_TA(TREB2_APOC2_PCI1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff }, + { PCIBus, 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_APOC2_PCI1_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff }, + { PCIBus, 1, UserBusMemory, 0, TREB2_APOC2_PCI_HIGH_MEMORY_BASE_PHYSICAL , 0x40000000, 0x47ffffff }, + { PCIBus, 1, UserPciDenseMemory, 2, APOC2_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff }, + { PCIBus, 1, UserPciDenseMemory, 2, APOC2_PCI_DENSE_BASE_PHYSICAL+0x40000000 , 0x40000000, 0x7fffffff }, + + { MaximumInterfaceType, 0, 0, 0, 0 , 0 , 0 } +}; + +PLATFORM_RANGE_LIST Rogue0Trebbia20RangeList[] = { + { Isa , 0, BusIo, 1, HAL_MAKE_LQVA(TREB2_ROGUE_ISA_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff }, + { Isa , 0, BusMemory, 1, HAL_MAKE_LQVA(TREB2_ROGUE_ISA_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff }, + { Isa , 0, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff }, + + { Isa , 0, UserBusIo, 0, TREB2_ROGUE_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { Isa , 0, UserBusMemory, 0, HAL_MAKE_TA(TREB2_ROGUE_ISA_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff }, + { Isa , 0, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_ROGUE_ISA_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff }, + + { Isa , 1, BusIo, 1, HAL_MAKE_LQVA(TREB2_ROGUE_ISA1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff }, + { Isa , 1, BusMemory, 1, HAL_MAKE_LQVA(TREB2_ROGUE_ISA1_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff }, + { Isa , 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff }, + + { Isa , 1, UserBusIo, 0, TREB2_ROGUE_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { Isa , 1, UserBusMemory, 0, HAL_MAKE_TA(TREB2_ROGUE_ISA1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff }, + { Isa , 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_ROGUE_ISA1_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff }, + + { Eisa , 0, BusIo, 1, HAL_MAKE_LQVA(TREB2_ROGUE_ISA_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff }, + { Eisa , 0, BusMemory, 1, HAL_MAKE_LQVA(TREB2_ROGUE_ISA_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff }, + { Eisa , 0, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff }, + + { Eisa , 0, UserBusIo, 0, TREB2_ROGUE_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { Eisa , 0, UserBusMemory, 0, HAL_MAKE_TA(TREB2_ROGUE_ISA_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff }, + { Eisa , 0, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_ROGUE_ISA_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff }, + + { Eisa , 1, BusIo, 1, HAL_MAKE_LQVA(TREB2_ROGUE_ISA1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff }, + { Eisa , 1, BusMemory, 1, HAL_MAKE_LQVA(TREB2_ROGUE_ISA1_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff }, + { Eisa , 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff }, + + { Eisa , 1, UserBusIo, 0, TREB2_ROGUE_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { Eisa , 1, UserBusMemory, 0, HAL_MAKE_TA(TREB2_ROGUE_ISA1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff }, + { Eisa , 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_ROGUE_ISA1_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff }, + + { PCIBus, 0, BusIo, 1, HAL_MAKE_LQVA(TREB2_ROGUE_PCI_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff }, + { PCIBus, 0, BusMemory, 1, HAL_MAKE_LQVA(TREB2_ROGUE_PCI_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff }, + { PCIBus, 0, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff }, + { PCIBus, 0, BusMemory, 1, HAL_MAKE_LQVA(TREB2_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL) , 0x40000000, 0x47ffffff }, + + { PCIBus, 0, UserBusIo, 0, TREB2_ROGUE_PCI_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { PCIBus, 0, UserBusMemory, 0, HAL_MAKE_TA(TREB2_ROGUE_PCI_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff }, + { PCIBus, 0, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_ROGUE_PCI_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff }, + { PCIBus, 0, UserBusMemory, 0, TREB2_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL , 0x40000000, 0x47ffffff }, + + { PCIBus, 1, BusIo, 1, HAL_MAKE_LQVA(TREB2_ROGUE_PCI1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff }, + { PCIBus, 1, BusMemory, 1, HAL_MAKE_LQVA(TREB2_ROGUE_PCI1_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff }, + { PCIBus, 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff }, + { PCIBus, 1, BusMemory, 1, HAL_MAKE_LQVA(TREB2_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL) , 0x40000000, 0x47ffffff }, + + { PCIBus, 1, UserBusIo, 0, TREB2_ROGUE_PCI1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { PCIBus, 1, UserBusMemory, 0, HAL_MAKE_TA(TREB2_ROGUE_PCI1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff }, + { PCIBus, 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_ROGUE_PCI1_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff }, + { PCIBus, 1, UserBusMemory, 0, TREB2_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL , 0x40000000, 0x47ffffff }, + + { MaximumInterfaceType, 0, 0, 0, 0 , 0 , 0 } +}; + +PLATFORM_RANGE_LIST Rogue1Trebbia20RangeList[] = { + { Isa , 0, BusIo, 1, HAL_MAKE_LQVA(TREB2_ROGUE_ISA_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff }, + { Isa , 0, BusMemory, 1, HAL_MAKE_LQVA(TREB2_ROGUE_ISA_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff }, + { Isa , 0, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff }, + { Isa , 0, KernelPciDenseMemory, 2, ROGUE_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff }, + + { Isa , 0, UserBusIo, 0, TREB2_ROGUE_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { Isa , 0, UserBusMemory, 0, HAL_MAKE_TA(TREB2_ROGUE_ISA_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff }, + { Isa , 0, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_ROGUE_ISA_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff }, + { Isa , 0, UserPciDenseMemory, 2, ROGUE_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff }, + + { Isa , 1, BusIo, 1, HAL_MAKE_LQVA(TREB2_ROGUE_ISA1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff }, + { Isa , 1, BusMemory, 1, HAL_MAKE_LQVA(TREB2_ROGUE_ISA1_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff }, + { Isa , 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff }, + { Isa , 1, KernelPciDenseMemory, 2, ROGUE_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff }, + + { Isa , 1, UserBusIo, 0, TREB2_ROGUE_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { Isa , 1, UserBusMemory, 0, HAL_MAKE_TA(TREB2_ROGUE_ISA1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff }, + { Isa , 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_ROGUE_ISA1_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff }, + { Isa , 1, UserPciDenseMemory, 2, ROGUE_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff }, + + { Eisa , 0, BusIo, 1, HAL_MAKE_LQVA(TREB2_ROGUE_ISA_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff }, + { Eisa , 0, BusMemory, 1, HAL_MAKE_LQVA(TREB2_ROGUE_ISA_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff }, + { Eisa , 0, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff }, + { Eisa , 0, KernelPciDenseMemory, 2, ROGUE_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff }, + + { Eisa , 0, UserBusIo, 0, TREB2_ROGUE_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { Eisa , 0, UserBusMemory, 0, HAL_MAKE_TA(TREB2_ROGUE_ISA_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff }, + { Eisa , 0, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_ROGUE_ISA_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff }, + { Eisa , 0, UserPciDenseMemory, 2, ROGUE_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff }, + + { Eisa , 1, BusIo, 1, HAL_MAKE_LQVA(TREB2_ROGUE_ISA1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff }, + { Eisa , 1, BusMemory, 1, HAL_MAKE_LQVA(TREB2_ROGUE_ISA1_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff }, + { Eisa , 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff }, + { Eisa , 1, KernelPciDenseMemory, 2, ROGUE_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff }, + + { Eisa , 1, UserBusIo, 0, TREB2_ROGUE_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { Eisa , 1, UserBusMemory, 0, HAL_MAKE_TA(TREB2_ROGUE_ISA1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff }, + { Eisa , 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_ROGUE_ISA1_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff }, + { Eisa , 1, UserPciDenseMemory, 2, ROGUE_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff }, + + { PCIBus, 0, BusIo, 1, HAL_MAKE_LQVA(TREB2_ROGUE_PCI_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff }, + { PCIBus, 0, BusMemory, 1, HAL_MAKE_LQVA(TREB2_ROGUE_PCI_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff }, + { PCIBus, 0, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff }, + { PCIBus, 0, BusMemory, 1, HAL_MAKE_LQVA(TREB2_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL) , 0x40000000, 0x47ffffff }, + { PCIBus, 0, KernelPciDenseMemory, 2, ROGUE_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff }, + { PCIBus, 0, KernelPciDenseMemory, 2, ROGUE_PCI_DENSE_BASE_PHYSICAL+0x40000000 , 0x40000000, 0x7fffffff }, + + { PCIBus, 0, UserBusIo, 0, TREB2_ROGUE_PCI_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { PCIBus, 0, UserBusMemory, 0, HAL_MAKE_TA(TREB2_ROGUE_PCI_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff }, + { PCIBus, 0, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_ROGUE_PCI_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff }, + { PCIBus, 0, UserBusMemory, 0, TREB2_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL , 0x40000000, 0x47ffffff }, + { PCIBus, 0, UserPciDenseMemory, 2, ROGUE_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff }, + { PCIBus, 0, UserPciDenseMemory, 2, ROGUE_PCI_DENSE_BASE_PHYSICAL+0x40000000 , 0x40000000, 0x7fffffff }, + + { PCIBus, 1, BusIo, 1, HAL_MAKE_LQVA(TREB2_ROGUE_PCI1_IO_BASE_PHYSICAL) , 0x00000000, 0x0000ffff }, + { PCIBus, 1, BusMemory, 1, HAL_MAKE_LQVA(TREB2_ROGUE_PCI1_MEMORY_BASE_PHYSICAL)+0xa0000 , 0x000a0000, 0x000bffff }, + { PCIBus, 1, BusMemory, 1, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff }, + { PCIBus, 1, BusMemory, 1, HAL_MAKE_LQVA(TREB2_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL) , 0x40000000, 0x47ffffff }, + { PCIBus, 1, KernelPciDenseMemory, 2, ROGUE_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff }, + { PCIBus, 1, KernelPciDenseMemory, 2, ROGUE_PCI_DENSE_BASE_PHYSICAL+0x40000000 , 0x40000000, 0x7fffffff }, + + { PCIBus, 1, UserBusIo, 0, TREB2_ROGUE_PCI1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { PCIBus, 1, UserBusMemory, 0, HAL_MAKE_TA(TREB2_ROGUE_PCI1_MEMORY_BASE_PHYSICAL,0xa0000) , 0x000a0000, 0x000bffff }, + { PCIBus, 1, UserBusMemory, 0, USER_PCI_VGA_VIDEO_ROM|TREB2_ROGUE_PCI1_MEMORY_BASE_PHYSICAL , 0x000c0000, 0x000c7fff }, + { PCIBus, 1, UserBusMemory, 0, TREB2_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL , 0x40000000, 0x47ffffff }, + { PCIBus, 1, UserPciDenseMemory, 2, ROGUE_PCI_DENSE_BASE_PHYSICAL+0x000a0000 , 0x000a0000, 0x000bffff }, + { PCIBus, 1, UserPciDenseMemory, 2, ROGUE_PCI_DENSE_BASE_PHYSICAL+0x40000000 , 0x40000000, 0x7fffffff }, + + { MaximumInterfaceType, 0, 0, 0, 0 , 0 , 0 } +}; + +QUASI_VIRTUAL_ADDRESS +HalCreateQva( + IN PHYSICAL_ADDRESS PA, + IN PVOID VA + ); + + +BOOLEAN +HalpTranslateSystemBusAddress( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PHYSICAL_ADDRESS BusAddress, + IN OUT PULONG AddressSpace, + OUT PPHYSICAL_ADDRESS TranslatedAddress + ) + +{ + ULONG i; + INTERFACE_TYPE InterfaceType = BusHandler->InterfaceType; + ULONG BusNumber = BusHandler->BusNumber; + LONGLONG Offset; + PVOID va = 0; // note, this is used for a placeholder + +//BusAddress.HighPart = 0; +//DbgPrint("HalTranslateBusAddress(IT=%d,BN=%d,BA=%08x %08x,AS=%d)\n\r",InterfaceType,BusNumber,BusAddress.HighPart,BusAddress.LowPart,*AddressSpace); + + // + // PCI Bus 0 is different than PCI Bus 1, but all other PCI busses are the same a PCI Bus 1 + // + + if (InterfaceType == PCIBus) { + + switch (HalpMotherboardType) { + case TREBBIA13 : + if (BusNumber > 1) { + BusNumber = 1; + } + break; + + case TREBBIA20 : + if (BusNumber == 0) { + + // + // There are no resources in PCI Bus #0. It only contains the memory system and bridges. + // + + *AddressSpace = 0; + TranslatedAddress->LowPart = 0; + return(FALSE); + } + + if (BusNumber >= HalpSecondPciBridgeBusNumber) { + BusNumber = 1; + } else { + BusNumber = 0; + } + break; + + default : + +//DbgPrint(" Invalid Motherboard Type\n\r"); + + *AddressSpace = 0; + TranslatedAddress->LowPart = 0; + return(FALSE); + } + } + + // + // If the VGA decodes are not enabled on the DEC PCI-PCI bridge associated with this + // memory range, then fail the translation. + // + + if (!(HalpVgaDecodeBusNumber & (1<LowPart = 0; + return(FALSE); + } + + // + // Search the table for a valid mapping. + // + + for(i=0;HalpRangeList[i].InterfaceType!=MaximumInterfaceType;i++) { + + if (HalpRangeList[i].InterfaceType == InterfaceType && + HalpRangeList[i].BusNumber == BusNumber && + HalpRangeList[i].AddressType == (ADDRESS_SPACE_TYPE)(*AddressSpace) && + BusAddress.QuadPart >= HalpRangeList[i].Base && + BusAddress.QuadPart <= HalpRangeList[i].Limit ) { + + TranslatedAddress->QuadPart = HalpRangeList[i].SystemBase; + *AddressSpace = HalpRangeList[i].SystemAddressSpace; + + if (TranslatedAddress->QuadPart & KERNEL_PCI_VGA_VIDEO_ROM) { + TranslatedAddress->QuadPart &= ~KERNEL_PCI_VGA_VIDEO_ROM; + TranslatedAddress->QuadPart += (LONGLONG)HalpPlatformSpecificExtension->PciVideoExpansionRomAddress; + } + + if (TranslatedAddress->QuadPart & USER_PCI_VGA_VIDEO_ROM) { + TranslatedAddress->QuadPart &= ~USER_PCI_VGA_VIDEO_ROM; + TranslatedAddress->QuadPart += (LONGLONG)(HalpPlatformSpecificExtension->PciVideoExpansionRomAddress << IO_BIT_SHIFT); + } + + Offset = BusAddress.QuadPart - HalpRangeList[i].Base; + if (*AddressSpace == 0) { + Offset = Offset << IO_BIT_SHIFT; + } + + TranslatedAddress->QuadPart += Offset; + + if (*AddressSpace == 0) { + if (HalpIoArchitectureType != EV5_PROCESSOR_MODULE) { + if (!HalpMiniTlbAllocateEntry(HalCreateQva(*TranslatedAddress,va),TranslatedAddress)) { + +//DbgPrint("HalTranslateBusAddress(IT=%d,BN=%d,BA=%08x %08x,AS=%d)\n\r",InterfaceType,BusNumber,BusAddress.HighPart,BusAddress.LowPart,*AddressSpace); +//DbgPrint(" Failed to allocate MiniTlb\n\r"); + + // + // A valid mapping was found, but the resources needed for the mapping could not be allocated. + // + + *AddressSpace = 0; + TranslatedAddress->LowPart = 0; + return(FALSE); + } + } + } + + // + // If this is a UserPciDenseMemory mapping then let user call MmMapIoSpace() + // + + if (*AddressSpace == 2) { + *AddressSpace = 0; + } + +//DbgPrint(" TranslatedAddress = %08x %08x AS=%d\n\r",TranslatedAddress->HighPart,TranslatedAddress->LowPart,*AddressSpace); + + return(TRUE); + } + } + +//DbgPrint("HalTranslateBusAddress(IT=%d,BN=%d,BA=%08x %08x,AS=%d)\n\r",InterfaceType,BusNumber,BusAddress.HighPart,BusAddress.LowPart,*AddressSpace); +//DbgPrint(" Failed\n\r"); + + // + // A valid mapping was not found. + // + + *AddressSpace = 0; + TranslatedAddress->QuadPart = 0; + return(FALSE); +} + +PVOID +HalCreateQva( + IN PHYSICAL_ADDRESS PA, + IN PVOID VA + ) + +/*++ + +Routine Description: + + This function is called two ways. First, from HalTranslateBusAddress, + if the caller is going to run in kernel mode and use superpages. + The second way is if the user is going to access in user mode. + MmMapIoSpace or ZwViewMapOfSection will call this. + + If the input parameter VA is zero, then we assume super page and build + a QUASI virtual address that is only usable by calling the hal I/O + access routines. + + if the input parameter VA is non-zero, we assume the user has either + called MmMapIoSpace or ZwMapViewOfSection and will use the user mode + access macros. + + If the PA is not a sparse I/O space address (PCI I/O, PCI Memory), + then return the VA as the QVA. + +Arguments: + + PA - the physical address generated by HalTranslateBusAddress + + VA - the virtual address returned by MmMapIoSpace + +Return Value: + + The returned value is a quasi virtual address in that it can be + added to and subtracted from, but it cannot be used to access the + bus directly. The top bits are set so that we can trap invalid + accesses in the memory management subsystem. All access should be + done through the Hal Access Routines in *ioacc.s if it was a superpage + kernel mode access. If it is usermode, then the user mode access + macros must be used. + +--*/ +{ + PVOID qva; + ULONG AddressSpace; + + if (VA != 0) { + + AddressSpace = PA.HighPart & 0x0f; + + // + // See if the physical address is in cached memory space. + // + + if (AddressSpace == 0 && PA.LowPart < 0x40000000) { + + return(VA); + } + + // + // See if the physical address is in PCI dense memory. + // + + if (AddressSpace == ((HalpPciDenseBasePhysicalSuperPage >> 32) & 0x0f)) { + + return(VA); + } + + // + // See if the physical address is in non cached memory. + // + + if (AddressSpace == ((HalpNoncachedDenseBasePhysicalSuperPage >> 32) & 0x0f) && PA.LowPart < 0x40000000) { + + return(VA); + } + } + + // + // Otherwise, the physical address is within one of the sparse I/O spaces. + // + + if (VA == 0) { + + qva = (PVOID)(RtlLargeIntegerShiftRight(PA, IO_BIT_SHIFT).LowPart & ~(DTI_QVA_SELECTORS)); + qva = (PVOID)((ULONG)qva | DTI_QVA_ENABLE); + + + } else { + + qva = (PVOID)((ULONG)VA >> IO_BIT_SHIFT); + qva = (PVOID)((ULONG)qva | QVA_ENABLE); + + } + + return(qva); +} + +PVOID +HalDereferenceQva( + PVOID Qva, + INTERFACE_TYPE InterfaceType, + ULONG BusNumber + ) +/*++ + +Routine Description: + + This function performs the inverse of the HalCreateQva for I/O addresses + that are memory-mapped (i.e. the quasi-virtual address was created from + a virtual address rather than a physical address). + +Arguments: + + Qva - Supplies the quasi-virtual address to be converted back to a + virtual address. + + InterfaceType - Supplies the interface type of the bus to which the + Qva pertains. + + BusNumber - Supplies the bus number of the bus to which the Qva pertains. + +Return Value: + + The Virtual Address from which the quasi-address was originally created + is returned. + +--*/ +{ + // + // For EB64+ we have only 2 bus types: + // + // Isa + // PCIBus + // + // We will allow Eisa as an alias for Isa. All other values not named + // above will be considered bogus. + // + + switch (InterfaceType ){ + + case Isa: + case Eisa: + case PCIBus: + + // + // Support dense space: check to see if it's really + // a sparse space QVA. + // + + if ( ((ULONG) Qva & DTI_QVA_SELECTORS) == DTI_QVA_ENABLE ) + { + return( (PVOID)( (ULONG)Qva << IO_BIT_SHIFT ) ); + } + else + { + return (Qva); + } + break; + + + default: + + return NULL; + + } +} + diff --git a/private/ntos/nthals/halflex/alpha/alphaio.s b/private/ntos/nthals/halflex/alpha/alphaio.s new file mode 100644 index 000000000..f9d7471c6 --- /dev/null +++ b/private/ntos/nthals/halflex/alpha/alphaio.s @@ -0,0 +1,1482 @@ +/*++ + +Copyright (c) 1993 Digital Equipment Corporation + +Module Name: + + alphaio.s + + +Abstract: + + The module contains the functions to turn quasi virtual + addresses into an Alpha superpage virtual address + and then read or write based on the request. + (We are using EV4 64-bit superpage mode.) + +Author: + + Joe Notarangelo 25-Oct-1993 + +Environment: + + Executes in kernel mode. + +Revision History: + + 12-Jul-1994 - Eric Rehm - Added dense space I/O + + 27-July-1994 - Sameer Dekate + + Make a common file for all machines and optimize Read/Write + register buffer routines. Made a common routine with different + entry points for READ & WRITE_REGISTER_BUFFER routines + +--*/ + +#include "halalpha.h" +#include "apoc.h" + + + +//////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////// + + .struct 0 + .space 8 // filler for octaword alignment +IoRa: .space 8 // space for return address +IoS0: .space 8 // space for S0 +IoS1: .space 8 // space for S1 +IoS2: .space 8 // space for S2 +IoIrql: .space 8 // space for local variable +IoFrameLength: // + +//////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////// + +#define EV4_IO(FastIoRoutine) \ + ldq t0, HalpPciDenseBasePhysicalSuperPage; \ + ldl t1, HalpIoArchitectureType; \ + beq t1, FastIoRoutine; \ + and a0, DTI_QVA_SELECTORS, t1; \ + xor t1, DTI_QVA_ENABLE, t1; \ + bne t1, FastIoRoutine; \ + lda sp, -IoFrameLength(sp); \ + stq ra, IoRa(sp); \ + stq s0, IoS0(sp); \ + stq s1, IoS1(sp); \ + stq s2, IoS2(sp); \ + or a0, a0, s0; \ + or a1, a1, s1; \ + or a2, a2, s2; \ + or zero, HIGH_LEVEL, a0; \ + addq sp, IoIrql, a1; \ + bsr ra, KeRaiseIrql; \ + or s0, s0, a0; \ + bsr ra, HalpMiniTlbResolve; \ + or v0, v0, a0; \ + or s1, s1, a1; \ + or s2, s2, a2; \ + ldq t0, HalpPciDenseBasePhysicalSuperPage; \ + bsr ra, FastIoRoutine; \ + or v0, v0, s0; \ + ldq a0, IoIrql(sp); \ + and a0, 0xff, a0; \ + bsr ra, KeLowerIrql; \ + or s0, s0, v0; \ + ldq s2, IoS2(sp); \ + ldq s1, IoS1(sp); \ + ldq s0, IoS0(sp); \ + ldq ra, IoRa(sp); \ + lda sp, IoFrameLength(sp); \ + ret zero, (ra) + +//////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////// + + LEAF_ENTRY(READ_REGISTER_UCHAR) + ALTERNATE_ENTRY(READ_PORT_UCHAR) + EV4_IO(EV5_READ_PORT_UCHAR) + .end READ_REGISTER_UCHAR + + LEAF_ENTRY(READ_REGISTER_USHORT) + ALTERNATE_ENTRY(READ_PORT_USHORT) + EV4_IO(EV5_READ_PORT_USHORT) + .end READ_REGISTER_USHORT + + LEAF_ENTRY(READ_REGISTER_ULONG) + ALTERNATE_ENTRY(READ_PORT_ULONG) + EV4_IO(EV5_READ_PORT_ULONG) + .end READ_REGISTER_ULONG + + LEAF_ENTRY(WRITE_REGISTER_UCHAR) + ALTERNATE_ENTRY(WRITE_PORT_UCHAR) + EV4_IO(EV5_WRITE_PORT_UCHAR) + .end WRITE_REGISTER_UCHAR + + LEAF_ENTRY(WRITE_REGISTER_USHORT) + ALTERNATE_ENTRY(WRITE_PORT_USHORT) + EV4_IO(EV5_WRITE_PORT_USHORT) + .end WRITE_REGISTER_USHORT + + LEAF_ENTRY(WRITE_REGISTER_ULONG) + ALTERNATE_ENTRY(WRITE_PORT_ULONG) + EV4_IO(EV5_WRITE_PORT_ULONG) + .end WRITE_REGISTER_ULONG + + LEAF_ENTRY(READ_PORT_BUFFER_UCHAR) + EV4_IO(EV5_READ_PORT_BUFFER_UCHAR) + .end READ_PORT_BUFFER_UCHAR + + LEAF_ENTRY(READ_PORT_BUFFER_USHORT) + EV4_IO(EV5_READ_PORT_BUFFER_USHORT) + .end READ_PORT_BUFFER_USHORT + + LEAF_ENTRY(READ_PORT_BUFFER_ULONG) + EV4_IO(EV5_READ_PORT_BUFFER_ULONG) + .end READ_PORT_BUFFER_ULONG + + LEAF_ENTRY(WRITE_PORT_BUFFER_UCHAR) + EV4_IO(EV5_WRITE_PORT_BUFFER_UCHAR) + .end WRITE_PORT_BUFFER_UCHAR + + LEAF_ENTRY(WRITE_PORT_BUFFER_USHORT) + EV4_IO(EV5_WRITE_PORT_BUFFER_USHORT) + .end WRITE_PORT_BUFFER_USHORT + + LEAF_ENTRY(WRITE_PORT_BUFFER_ULONG) + EV4_IO(EV5_WRITE_PORT_BUFFER_ULONG) + .end WRITE_PORT_BUFFER_ULONG + + LEAF_ENTRY(READ_REGISTER_BUFFER_UCHAR) + EV4_IO(EV5_READ_REGISTER_BUFFER_UCHAR) + .end READ_REGISTER_BUFFER_UCHAR + + LEAF_ENTRY(READ_REGISTER_BUFFER_USHORT) + EV4_IO(EV5_READ_REGISTER_BUFFER_USHORT) + .end READ_REGISTER_BUFFER_USHORT + + LEAF_ENTRY(READ_REGISTER_BUFFER_ULONG) + EV4_IO(EV5_READ_REGISTER_BUFFER_ULONG) + .end READ_REGISTER_BUFFER_ULONG + + LEAF_ENTRY(WRITE_REGISTER_BUFFER_UCHAR) + EV4_IO(EV5_WRITE_REGISTER_BUFFER_UCHAR) + .end WRITE_REGISTER_BUFFER_UCHAR + + LEAF_ENTRY(WRITE_REGISTER_BUFFER_USHORT) + EV4_IO(EV5_WRITE_REGISTER_BUFFER_USHORT) + .end WRITE_REGISTER_BUFFER_USHORT + + LEAF_ENTRY(WRITE_REGISTER_BUFFER_ULONG) + EV4_IO(EV5_WRITE_REGISTER_BUFFER_ULONG) + .end WRITE_REGISTER_BUFFER_ULONG + +//////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////// + + SBTTL( "Read I/O byte" ) +//++ +// +// UCHAR +// READ_REGISTER_UCHAR( +// IN PVOID RegisterQva +// ) +// +// Routine Description: +// +// Reads a byte location in PCI bus memory or I/O space. +// +// Arguments: +// +// RegisterQva(a0) - Supplies the QVA of the I/O byte to read. +// +// Return Value: +// +// v0 - Returns the value read from I/O space. +// +//-- + + LEAF_ENTRY(EV5_READ_REGISTER_UCHAR) + + ALTERNATE_ENTRY(EV5_READ_PORT_UCHAR) + + and a0, DTI_QVA_SELECTORS, t1 // get qva selector bits + and a0, 3, t3 // get byte we need if eisa + xor t1, DTI_QVA_ENABLE, t1 // ok iff DTI_QVA_ENABLE set in selectors + bne t1, 2f // if ne, iff failed + + zap a0, 0xf0, a0 // clear <63:32> + bic a0, DTI_QVA_ENABLE,a0 // clear QVA fields so shift is correct + sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0> + ldiq t4, -0x3080 // 0xffff ffff ffff cf80 + sll t4, 28, t4 // 0xffff fcf8 0000 0000 + or t0, t4, t0 // superpage mode + + mb + ldl v0, (t0) // get the longword + extbl v0, t3, v0 // get correct byte if eisa + + ret zero, (ra) // return + +// +// Dense space access: QVA is an offset into dense space +// + +2: + and a0, 3, t3 // get byte we need + zap a0, 0xf0, a0 // clear <63:32> + bic a0, 3, a0 // clear <1:0> to get aligned longword + +// ldiq t0, PCI_DENSE_BASE_PHYSICAL_SUPERPAGE + or a0, t0, a0 // superpage mode: add offset to base + + ldl v0, (a0) // get the longword + extbl v0, t3, v0 // get correct byte + + ret zero, (ra) // return + + .end EV5_READ_REGISTER_UCHAR + + + SBTTL( "Read I/O word(16 bits)" ) +//++ +// +// USHORT +// READ_REGISTER_USHORT( +// IN PVOID RegisterQva +// ) +// +// Routine Description: +// +// Reads a word location in PCI bus memory or I/O space. +// +// Arguments: +// +// RegisterQva(a0) - Supplies the QVA of the I/O word to read. +// +// Return Value: +// +// v0 - Returns the value read from I/O space. +// +//-- + + LEAF_ENTRY(EV5_READ_REGISTER_USHORT) + + ALTERNATE_ENTRY(EV5_READ_PORT_USHORT) + + and a0, DTI_QVA_SELECTORS, t1 // get qva selector bits + and a0, 3, t3 // get word + xor t1, DTI_QVA_ENABLE, t1 // ok iff DTI_QVA_ENABLE set in selectors + bne t1, 2f // if ne, iff failed + + zap a0, 0xf0, a0 // clear <63:32> + bic a0, DTI_QVA_ENABLE,a0 // clear QVA fields so shift is correct + sll a0, IO_BIT_SHIFT, t0 // + ldiq t4, -0x3080 // + sll t4, 28, t4 // + or t0, t4, t0 // superpage mode + + or t0, IO_WORD_LEN, t0 // or in the byte enables + + mb + ldl v0, (t0) // get the longword + extwl v0,t3,v0 // get the correct word + + ret zero, (ra) // return + +// +// Dense space access: QVA is an offset into dense space +// + +2: + and a0, 3, t3 // get word we need + zap a0, 0xf0, a0 // clear <63:32> + bic a0, 3, a0 // clear <1:0> to get aligned longword + +// ldiq t0, PCI_DENSE_BASE_PHYSICAL_SUPERPAGE + or a0,t0, a0 // superpage mode: add offset to base + + ldl v0, (a0) // get the longword + extwl v0, t3, v0 // get correct word + + ret zero, (ra) // return + + .end EV5_READ_REGISTER_USHORT + + + SBTTL( "Read I/O longword(32 bits)" ) +//++ +// +// ULONG +// READ_REGISTER_ULONG( +// IN PVOID RegisterQva +// ) +// +// Routine Description: +// +// Reads a longword location in PCI bus memory or I/O space. +// +// Arguments: +// +// RegisterQva(a0) - Supplies the QVA of the I/O longword to read. +// +// Return Value: +// +// v0 - Returns the value read from I/O space. +// +//-- + + LEAF_ENTRY(EV5_READ_REGISTER_ULONG) + + ALTERNATE_ENTRY(EV5_READ_PORT_ULONG) + + and a0, DTI_QVA_SELECTORS, t1 // get qva selector bits + xor t1, DTI_QVA_ENABLE, t1 // ok iff DTI_QVA_ENABLE set in selectors + bne t1, 2f // if ne, iff failed + + zap a0, 0xf0, a0 // clear <63:32> + bic a0, DTI_QVA_ENABLE,a0 // clear QVA fields so shift is correct + sll a0, IO_BIT_SHIFT, t0 // + ldiq t4, -0x3080 // + sll t4, 28, t4 // + or t0, t4, t0 // superpage mode + + or t0, IO_LONG_LEN, t0 // or in the byte enables + + mb + ldl v0, (t0) // read the longword + + ret zero, (ra) // return + +// +// Dense space access: QVA is an offset into dense space +// + +2: + zap a0, 0xf0, a0 // clear <63:32> + +// ldiq t0, PCI_DENSE_BASE_PHYSICAL_SUPERPAGE + or a0, t0, a0 // superpage mode: add offset to base + + ldl v0, (a0) // get the longword + + ret zero, (ra) // return + + .end EV5_READ_REGISTER_ULONG + + SBTTL( "Write I/O byte" ) +//++ +// +// VOID +// WRITE_REGISTER_UCHAR( +// IN PVOID RegisterQva, +// IN UCHAR Value +// ) +// +// Routine Description: +// +// Writes a byte location in PCI bus memory or I/O space. +// +// Arguments: +// +// RegisterQva(a0) - Supplies the QVA of the I/O byte to write. +// +// Value(a1) - Supplies the value written to I/O space. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(EV5_WRITE_REGISTER_UCHAR) + + ALTERNATE_ENTRY(EV5_WRITE_PORT_UCHAR) + + and a0, DTI_QVA_SELECTORS, t1 // get qva selector bits + and a0, 3, t3 // get byte we need if eisa + xor t1, DTI_QVA_ENABLE, t1 // ok iff DTI_QVA_ENABLE set in selectors + bne t1, 2f // if ne, iff failed + + zap a0, 0xf0, a0 // clear <63:32> + bic a0, DTI_QVA_ENABLE,a0 // clear QVA fields so shift is correct + sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0> + ldiq t4, -0x3080 // + sll t4, 28, t4 // + or t0, t4, t0 // superpage mode + + insbl a1,t3,t4 // put the byte in the correct position + stl t4, (t0) // write the byte + mb // order the write + + ret zero, (ra) // return + +// +// Dense space access: QVA is an offset into dense space +// + +2: + and a0, 3, t3 // get byte we need if eisa + zap a0, 0xf0, a0 // clear <63:32> + bic a0, 3, a0 // clear <1:0> to get aligned longword + +// ldiq t0, PCI_DENSE_BASE_PHYSICAL_SUPERPAGE + or a0, t0, a0 // superpage mode: add offset to base + + ldl t1, (a0) // get the long + mskbl t1, t3, t1 // mask the proper byte + insbl a1, t3, t2 // put byte into position + bis t1, t2, t1 // merge byte in result + stl t1, (a0) // store the result + mb // order the write + + ret zero, (ra) // return + + .end EV5_WRITE_REGISTER_UCHAR + + + SBTTL( "Write I/O word (16 bits)" ) +//++ +// +// VOID +// WRITE_REGISTER_USHORT( +// IN PVOID RegisterQva, +// IN USHORT Value +// ) +// +// Routine Description: +// +// Writes a word location in PCI bus memory or I/O space. +// +// Arguments: +// +// RegisterQva(a0) - Supplies the QVA of the I/O word to write. +// +// Value(a1) - Supplies the value written to I/O space. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(EV5_WRITE_REGISTER_USHORT) + + ALTERNATE_ENTRY(EV5_WRITE_PORT_USHORT) + + and a0, DTI_QVA_SELECTORS, t1 // get qva selector bits + and a0, 3, t3 // get word + xor t1, DTI_QVA_ENABLE, t1 // ok iff DTI_QVA_ENABLE set in selectors + bne t1, 2f // if ne, iff failed + + zap a0, 0xf0, a0 // clear <63:32> + bic a0, DTI_QVA_ENABLE,a0 // clear QVA fields so shift is correct + sll a0, IO_BIT_SHIFT, t0 // + ldiq t4, -0x3080 // + sll t4, 28, t4 // + or t0, t4, t0 // superpage mode + + or t0, IO_WORD_LEN, t0 // or in the byte enables + + inswl a1,t3,t2 // put the word in the correct place + stl t2, (t0) // write the word + mb // order the write + + ret zero, (ra) // return + +// +// Dense space access: QVA is an offset into dense space +// + +2: + and a0, 3, t3 // get byte we need if eisa + zap a0, 0xf0, a0 // clear <63:32> + bic a0, 3, a0 // clear <1:0> to get aligned longword + +// ldiq t0, PCI_DENSE_BASE_PHYSICAL_SUPERPAGE + or a0, t0, a0 // superpage mode: add offset to base + + ldl t1, (a0) // get the long + mskwl t1, t3, t1 // mask the proper word + inswl a1, t3, t2 // put word into position + bis t1, t2, t1 // merge in result + stl t1, (a0) // store the result + mb // order the write + + ret zero, (ra) // return + + .end EV5_WRITE_REGISTER_USHORT + + + SBTTL( "Write I/O longword (32 bits)" ) +//++ +// +// VOID +// WRITE_REGISTER_ULONG( +// IN PVOID RegisterQva, +// IN ULONG Value +// ) +// +// Routine Description: +// +// Writes a longword location in PCI bus memory or I/O space. +// +// Arguments: +// +// RegisterQva(a0) - Supplies the QVA of the I/O longword to write. +// +// Value(a1) - Supplies the value written to I/O space. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(EV5_WRITE_REGISTER_ULONG) + + ALTERNATE_ENTRY(EV5_WRITE_PORT_ULONG) + + and a0, DTI_QVA_SELECTORS, t1 // get qva selector bits + xor t1, DTI_QVA_ENABLE, t1 // ok iff DTI_QVA_ENABLE set in selectors + bne t1, 2f // if ne, iff failed + + zap a0, 0xf0, a0 // clear <63:32> + bic a0, DTI_QVA_ENABLE,a0 // clear QVA fields so shift is correct + sll a0, IO_BIT_SHIFT, t0 // + ldiq t4, -0x3080 // + sll t4, 28, t4 // + or t0, t4, t0 // superpage mode + + or t0, IO_LONG_LEN, t0 // or in the byte enables + + stl a1, (t0) // write the longword + mb // order the write + + ret zero, (ra) // return + +// +// Dense space access: QVA is an offset into dense space +// + +2: + zap a0, 0xf0, a0 // clear <63:32> +// ldiq t0, PCI_DENSE_BASE_PHYSICAL_SUPERPAGE + or a0, t0, a0 // superpage mode: add offset to base + + stl a1, (a0) // store the longword + mb // order the write + + ret zero, (ra) // return + + .end EV5_WRITE_REGISTER_ULONG + + +//++ +// +// VOID +// READ_PORT_BUFFER_UCHAR( +// IN PVOID PortQva, +// IN PUCHAR Buffer, +// IN ULONG Count +// ) +// +// Routine Description: +// +// Read multiple bytes from the specified port address into the +// destination buffer. +// +// Arguments: +// +// PortQva(a0) - Supplies the QVA of the port to read. +// +// Buffer(a1) - Supplies a pointer to the buffer to fill with +// the data read from the port. +// +// Count(a2) - Supplies the number of bytes to read. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(EV5_READ_PORT_BUFFER_UCHAR) + + and a0, 3, t3 // get byte we need if eisa + zap a0, 0xf0, a0 // clear <63:32> + + bic a0, DTI_QVA_ENABLE,a0 // clear QVA fields so shift is correct + sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0> + ldiq t4, -0x3080 // t4=ffff ffff ffff c000 + sll t4, 28, t4 // t4=ffff fc00 0000 0000 + or t0, t4, t0 // superpage mode + + beq a2, 3f // if count==0 return +2: + ldl v0, (t0) // get the longword + subl a2, 1, a2 // decrement count + extbl v0,t3,v0 // get the correct byte + stb v0,(a1) // cheat and let the assembler do it + addl a1, 1, a1 // next byte in buffer + bne a2, 2b // while count != 0 +3: + + ret zero, (ra) // return + + .end EV5_READ_PORT_BUFFER_UCHAR + + + SBTTL( "Read Buffer from Port Space in Ushorts") +//++ +// +// VOID +// READ_PORT_BUFFER_USHORT( +// IN PVOID PortQva, +// IN PUSHORT Buffer, +// IN ULONG Count +// ) +// +// Routine Description: +// +// Read multiple words from the specified port address into the +// destination buffer. +// +// Arguments: +// +// PortQva(a0) - Supplies the QVA of the port to read. +// +// Buffer(a1) - Supplies a pointer to the buffer to fill with +// the data read from the port. +// +// Count(a2) - Supplies the number of words to read. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(EV5_READ_PORT_BUFFER_USHORT) + + and a0, 3, t3 // get word we need + zap a0, 0xf0, a0 // clear <63:32> + + bic a0, DTI_QVA_ENABLE,a0 // clear QVA fields so shift is correct + sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0> + ldiq t4, -0x3080 // t4=ffff ffff ffff c000 + sll t4, 28, t4 // t4=ffff fc00 0000 0000 + or t0, t4, t0 // superpage mode + or t0, IO_WORD_LEN, t0 // or in the byte enables + + beq a2, 3f // if count==0 return +2: + ldl v0, (t0) // get the longword + subl a2, 1, a2 // decrement count + extwl v0,t3,v0 // get the correct word + stw v0,(a1) // cheat and let the assembler do it + addl a1, 2, a1 // next word in buffer + bne a2, 2b // while count != 0 +3: + + ret zero, (ra) // return + + .end EV5_READ_PORT_BUFFER_USHORT + + SBTTL( "Read Buffer from Port Space in Ulongs") +//++ +// +// VOID +// READ_PORT_BUFFER_ULONG( +// IN PVOID PortQva, +// IN PULONG Buffer, +// IN ULONG Count +// ) +// +// Routine Description: +// +// Read multiple longwords from the specified port address into the +// destination buffer. +// +// Arguments: +// +// PortQva(a0) - Supplies the QVA of the port to read. +// +// Buffer(a1) - Supplies a pointer to the buffer to fill with +// the data read from the port. +// +// Count(a2) - Supplies the number of longwords to read. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(EV5_READ_PORT_BUFFER_ULONG) + + zap a0, 0xf0, a0 // clear <63:32> + + bic a0, DTI_QVA_ENABLE,a0 // clear QVA fields so shift is correct + sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0> + + ldiq t4, -0x3080 // t4=ffff ffff ffff c000 + sll t4, 28, t4 // t4=ffff fc00 0000 0000 + or t0, t4, t0 // superpage mode + or t0, IO_LONG_LEN, t0 // or in the byte enables + + beq a2, 3f // if count==0 return +2: + ldl v0, (t0) // get the longword + subl a2, 1, a2 // decrement count + stl v0,(a1) // cheat and let the assembler do it + addl a1, 4, a1 // next word in buffer + bne a2, 2b // while count != 0 +3: + + ret zero, (ra) // return + + .end EV5_READ_PORT_BUFFER_ULONG + + + SBTTL( "Write Buffer to Port Space in Uchars") +//++ +// +// VOID +// WRITE_PORT_BUFFER_UCHAR( +// IN PVOID PortQva, +// IN PUCHAR Buffer, +// IN ULONG Count +// ) +// +// Routine Description: +// +// Write multiple bytes from the source buffer to the specified port +// address. +// +// Arguments: +// +// PortQva(a0) - Supplies the QVA of the port to write. +// +// Buffer(a1) - Supplies a pointer to the buffer containing the data +// to write to the port. +// +// Count(a2) - Supplies the number of bytes to write. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(EV5_WRITE_PORT_BUFFER_UCHAR) + + and a0, 3, t3 // get byte we need if eisa + zap a0, 0xf0, a0 // clear <63:32> + + bic a0, DTI_QVA_ENABLE,a0 // clear QVA fields so shift is correct + sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0> + ldiq t4, -0x3080 // t4=ffff ffff ffff c000 + sll t4, 28, t4 // t4=ffff fc00 0000 0000 + or t0, t4, t0 // superpage mode + + beq a2, 3f // if count==0 return +2: + ldq_u t1, 0(a1) // get quad surrounding byte + subl a2, 1, a2 // decrement count + extbl t1, a1, t1 // extract appropriate byte + addl a1, 1, a1 // increment buffer pointer + insbl t1, t3, t1 // put byte to appropriate lane + stl t1, 0(t0) // store to port + mb // push writes off chip + bne a2, 2b // while count != 0 + +3: + + ret zero, (ra) // return + + .end EV5_WRITE_PORT_BUFFER_UCHAR + + SBTTL( "Write Buffer to Port Space in Ushorts") +//++ +// +// VOID +// WRITE_PORT_BUFFER_USHORT( +// IN PVOID PortQva, +// IN PSHORT Buffer, +// IN ULONG Count +// ) +// +// Routine Description: +// +// Write multiple words from the source buffer to the specified port +// address. +// +// Arguments: +// +// PortQva(a0) - Supplies the QVA of the port to write. +// +// Buffer(a1) - Supplies a pointer to the buffer containing the data +// to write to the port. +// +// Count(a2) - Supplies the number of words to write. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(EV5_WRITE_PORT_BUFFER_USHORT) + + and a0, 3, t3 // get word we need + zap a0, 0xf0, a0 // clear <63:32> + + bic a0, DTI_QVA_ENABLE,a0 // clear QVA fields so shift is correct + sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0> + ldiq t4, -0x3080 // t4=ffff ffff ffff c000 + sll t4, 28, t4 // t4=ffff fc00 0000 0000 + or t0, t4, t0 // superpage mode + or t0, IO_WORD_LEN, t0 // or in the byte enables + + beq a2, 3f // if count==0 return +2: + ldq_u t1, 0(a1) // get quad surrounding word + subl a2, 1, a2 // decrement count + extwl t1, a1, t1 // extract appropriate word + addl a1, 2, a1 // increment buffer pointer + inswl t1, t3, t1 // put word in appropriate lane + stl t1, 0(t0) // store to port + mb // push writes off chip + bne a2, 2b // while count != 0 + +3: + + ret zero, (ra) // return + + .end EV5_WRITE_PORT_BUFFER_USHORT + + + SBTTL( "Write Buffer to Port Space in Ulongs") +//++ +// +// VOID +// WRITE_PORT_BUFFER_ULONG( +// IN PVOID PortQva, +// IN PULONG Buffer, +// IN ULONG Count +// ) +// +// Routine Description: +// +// Write multiple longwords from the source buffer to the specified port +// address. +// +// Arguments: +// +// PortQva(a0) - Supplies the QVA of the port to write. +// +// Buffer(a1) - Supplies a pointer to the buffer containing the data +// to write to the port. +// +// Count(a2) - Supplies the number of longwords to write. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(EV5_WRITE_PORT_BUFFER_ULONG) + + zap a0, 0xf0, a0 // clear <63:32> + bic a0, DTI_QVA_ENABLE,a0 // clear QVA fields so shift is correct + sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0> + ldiq t4, -0x3080 // t4=ffff ffff ffff c000 + sll t4, 28, t4 // t4=ffff fc00 0000 0000 + or t0, t4, t0 // superpage mode + or t0, IO_LONG_LEN, t0 // or in the byte enables + + beq a2, 3f // if count==0 return +2: + ldl t1, 0(a1) // a1 must be longword aligned + subl a2, 1, a2 // decrement count + stl t1, 0(t0) // store to port + mb // push writes off chip + addl a1, 4, a1 // increment buffer + bne a2, 2b // while count != 0 + +3: + + ret zero, (ra) // return + + .end EV5_WRITE_PORT_BUFFER_ULONG + + + SBTTL( "Read Buffer from PCI Memory Space in Uchars") +//++ +// +// VOID +// READ_REGISTER_BUFFER_UXXXXX( +// IN PVOID RegisterQva, +// IN PUCHAR Buffer, +// IN ULONG Count +// ) +// +// Routine Description: +// +// Copies a buffer from PCI Memory Space to an in-memory buffer. +// +// Arguments: +// +// RegisterQva(a0) - Supplies the starting QVA of the memory space buffer. +// +// Buffer(a1) - Supplies a pointer to the in-memory buffer to receive +// the copied data. +// +// Count(a2) - Supplies the number of bytes, words or longwords to write. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(EV5_READ_REGISTER_BUFFER_ULONG) + + sll a2, 1, a2 // convert number of longs to words + + ALTERNATE_ENTRY(EV5_READ_REGISTER_BUFFER_USHORT) + + + sll a2, 1, a2 // convert number of words to chars + + ALTERNATE_ENTRY(EV5_READ_REGISTER_BUFFER_UCHAR) + + and a0, DTI_QVA_SELECTORS, t1 // get qva selector bits + xor t1, DTI_QVA_ENABLE, t1 // ok iff DTI_QVA_ENABLE set in selectors + beq t1, 1f // if (eq) go do sparse space + +// +// Dense space access: QVA is an offset into dense space +// Set IO address in t0 +// + zap a0, 0xf0, a0 // clear <63:32> +// ldiq t0, PCI_DENSE_BASE_PHYSICAL_SUPERPAGE + or a0, t0, t0 // superpage mode: add offset to base + + ldil a3, 1 // Offset to next byte + ldil a4, 4 // Offset to next long + ldil a5, 0 // LONG LEN ENABLE + + br zero 2f // go do the actual transfer + +// +// Sparse memory +// Set IO address in t0 +// + +1: + zap a0, 0xf0, a0 // clear <63:32> + bic a0, DTI_QVA_ENABLE,a0 // clear QVA fields so shift is correct + sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0> + ldiq t4, -0x3080 // 0xffff ffff ffff c000 + sll t4, 28, t4 // 0xffff fc00 0000 0000 + or t0, t4, t0 // superpage mode + + ldil a3, IO_BYTE_OFFSET // Offset to next byte + ldil a4, IO_LONG_OFFSET // Offset to next long + ldil a5, IO_LONG_LEN // LONG LEN ENABLE + +// +// Do the ACTUAL TRANSFER +// a2 = count in characters +// + +2: + beq a2, 60f // if count == 0 goto 60f (return) + +// +// Check alignment of src and destn +// + + and a0, 3, t3 // source alignment = t3 + and a1, 3, t2 // destination alignment = t2 + xor t2, t3, t4 // t4 = t2 xor t3 + bne t4, 70f // if (t4!=0) do unaligned copy + // else do byte copies till alignment + + beq t3, 20f // if t3==0 go do long word copies + // else do byte copies till alignment + +// +// Src and Destn are not longword aligned but have same alignment +// (sympathetically aligned) copy till alignment +// + +10: + beq a2, 60f // if count == 0 goto 60f (return) + + ldl v0, 0(t0) // get the longword + subl a2, 1, a2 // decrement count + extbl v0, t3,v0 // get the correct byte + stb v0, (a1) // cheat and let the assembler do it + addq t0, a3, t0 // next I/O address + addl a1, 1, a1 // next byte in buffer + addl t3, 1, t3 // next byte in lane + and t3, 3, t3 // longword lanes + bne t3, 10b // while unaligned + +// +// Src and Destn have same alignment and are longword aligned +// + +20: + srl a2, 2, t3 // t3= #longwords to move + beq t3, 40f // if #longwords == 0 goto 40f + or t0, a5, t0 // We will now do LONG READS + +30: + ldl v0, 0(t0) // get the longword + subl t3, 1, t3 // decrement long word count + stl v0, (a1) // store the longword at destn + addq t0, a4, t0 // next I/O address + addl a1, 4, a1 // next longword in buffer + bne t3, 30b // while #longwords > 0 + +// +// Do byte copies of remaining data uncopied +// + bic t0, a5, t0 // We will now do BYTE READS +40: + and a2, 3, a2 // remaining Bytes to copy + beq a2, 60f // if count == 0 goto 60f + +50: + ldl v0, 0(t0) // get the longword + subl a2, 1, a2 // decrement count + extbl v0, t3,v0 // get the correct byte + stb v0, (a1) // cheat and let the assembler do it + addl a1, 1, a1 // next byte in buffer + addq t0, a3, t0 // next I/O address + addl t3, 1, t3 // next byte in lane + and t3, 3, t3 // longword lanes + bne a2, 50b // while count > 0 + +60: + + ret zero, (ra) // return + + +// +// source IO alignment != destination memory alignment +// move enough bytes to longword align the IO source +// then move 32bit (longwords) storing unaligned into memory +// then move residual bytes +// +// Align src IO addresses; unaligned destn memory +// + +70: + beq t3, 90f // branch if source is long aligned +// +// Move bytes until IO src is at a longword boundary or bytes exhausted +// + +80: + beq a2, 130f // if count == 0 goto 130f (return) + + ldl v0, 0(t0) // get the longword + subl a2, 1, a2 // decrement count + extbl v0, t3,v0 // get the correct byte + stb v0, (a1) // cheat and let the assembler do it + addl a1, 1, a1 // next byte in buffer + addq t0, a3, t0 // next I/O address + addl t3, 1, t3 // next byte in lane + and t3, 3, t3 // longword lanes + bne t3, 80b // while unaligned + +// +// aligned IO source, unaligned memory destination +// + +90: + srl a2, 3, t3 // quadwords to move + beq t3, 110f // if no quads finish with bytes copies + + or t0, a5, t0 // We will now do LONG READS + +100: + // + // Decoding for Comment: + // S= sign, X= overwritten byte, V= Valid byte,assume destn align a1= 2 + // + ldl t1, 0(t0) // load LW 0 from IO src SSSS 4321 + ldq_u t4, 0(a1) // load destn merge XXVV VVVV + ldq_u t5, 7(a1) // load destn next merge VVXX XXXX + subl t3, 1, t3 // decrement quadwords to move + + addq t0, a4, t0 // add LONG OFFSET to t0 + ldl t2, 0(t0) // load LW 1 from IO src SSSS 8765 + + mskql t4, a1, t4 // mask low LW for merge 00VV VVVV + mskqh t5, a1, t5 // mask high LW for merge VV00 0000 + + zap t1, 0xf0, t1 // clear high LW for long 0 0000 4321 + sll t2, 32, t2 // get long 1 to high longword 8765 0000 + bis t1, t2, t1 // merge read quadword together8765 4321 + + addq t0, a4, t0 // increment to next long + + insql t1, a1, t6 // position low QW for merge 2100 0000 + insqh t1, a1, t7 // position high QW for merge 0087 6543 + + bis t4, t6, t4 // merge new data, low QW 21VV VVVV + bis t5, t7, t5 // merge new data, high QW VV87 6543 + + stq_u t5, 7(a1) // write high quadword + stq_u t4, 0(a1) // write low quadword + + lda a1, 8(a1) // increment memory pointer + bne t3, 100b // while quadwords to move + +// +// Do byte copies of the remaining data not yet copied +// + bic t0, a5, t0 // We will now do BYTE READS +110: + and a2, 7, a2 // remaining bytes to copy + beq a2, 130f // if count == 0 goto 130f (return) + +120: + ldl v0, 0(t0) // get the longword + subl a2, 1, a2 // decrement count + extbl v0, t3,v0 // get the correct byte + stb v0, (a1) // cheat and let the assembler do it + addl a1, 1, a1 // next byte in buffer + addq t0, a3, t0 // next I/O address + addl t3, 1, t3 // next byte in lane + and t3, 3, t3 // longword lanes + bne a2, 120b // while count != 0 + +130: + + ret zero, (ra) // return + + .end EV5_READ_REGISTER_BUFFER_ULONG // end for UCHAR & USHORT + + + SBTTL( "Write Buffer to PCI Memory Space in Uchars") +//++ +// +// VOID +// WRITE_REGISTER_BUFFER_UXXXXX( +// IN PVOID RegisterQva, +// IN PUCHAR Buffer, +// IN ULONG Count +// ) +// +// Routine Description: +// +// Copies an in-memory buffer to a PCI Memory Space buffer. +// +// Arguments: +// +// RegisterQva(a0) - Supplies the starting QVA of the memory space buffer. +// +// Buffer(a1) - Supplies a pointer to the in-memory source buffer. +// +// Count(a2) - Supplies the number of bytes, words to longwords to write. +// +// Return Value: +// +// None. +// +//-- + LEAF_ENTRY(EV5_WRITE_REGISTER_BUFFER_ULONG) + + sll a2, 1, a2 // convert number of longs to words + + ALTERNATE_ENTRY(EV5_WRITE_REGISTER_BUFFER_USHORT) + + sll a2, 1, a2 // convert number of words to chars + + ALTERNATE_ENTRY(EV5_WRITE_REGISTER_BUFFER_UCHAR) + + and a0, DTI_QVA_SELECTORS, t1 // get qva selector bits + xor t1, DTI_QVA_ENABLE, t1 // ok iff DTI_QVA_ENABLE set in selectors + beq t1, 1f // if (eq) go do sparse space + +// +// Dense space access: QVA is an offset into dense space +// Set IO address in t0 +// + + zap a0, 0xf0, a0 // clear <63:32> +// ldiq t0, PCI_DENSE_BASE_PHYSICAL_SUPERPAGE + or a0, t0, t0 // superpage mode: add offset to base + + ldil a3, 1 // Offset to next byte + ldil a4, 4 // Offset to next long + ldil a5, 0 // LONG LEN ENABLE + + br zero, 2f // go do the actual transfer + +// +// Sparse Space +// Set IO address in t0 +// + +1: + zap a0, 0xf0, a0 // clear <63:32> + bic a0, DTI_QVA_ENABLE,a0 // clear QVA fields so shift is correct + sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0> + ldiq t4, -0x3080 // 0xffff ffff ffff c000 + sll t4, 28, t4 // 0xffff fc00 0000 0000 + or t0, t4, t0 // superpage mode + + ldil a3, IO_BYTE_OFFSET // Offset to next byte + ldil a4, IO_LONG_OFFSET // Offset to next long + ldil a5, IO_LONG_LEN // LONG LEN ENABLE + +// +// Do the ACTUAL TRANSFER +// a2 = count in characters +// + +2: + beq a2, 60f // if count == 0 goto 60f (return) + +// +// Check alignment of src and destn +// + and a0, 3, t3 // destn alignment = t3 + and a1, 3, t2 // src alignment = t2 + xor t2, t3, t4 // t4 = t2 xor t3 + bne t4, 70f // if (t4!=0) do unaligned copy + // else do byte copies till alignment + + beq t3, 20f // if t3==0 go do longword copies + // else do byte copies till alignment + +// +// Src and Destn are not longword aligned but have same alignment +// (sympathetically aligned) copy till alignment +// + +10: + beq a2, 60f // if count == 0 goto 60f (return) + + ldq_u t1, 0(a1) // get quad surrounding byte + subl a2, 1, a2 // decrement count + extbl t1, a1, t1 // extract appropriate byte + addl a1, 1, a1 // increment buffer pointer + insbl t1, t3, t1 // get proper lane + stl t1, 0(t0) // store byte to buffer (BYTE ENABLED) + addq t0, a3, t0 // increment I/O buffer + addl t3, 1, t3 // increment bytelane + and t3, 3, t3 // longwords only + bne t3, 10b // loop while not long aligned + +// +// Src and Destn have same alignment and are longword aligned +// + +20: + srl a2, 2, t3 // t3= #longwords to move + beq t3, 40f // if #longwords == 0 goto 40f + or t0, a5, t0 // We will now do LONG WRITE + +30: + ldl t1, 0(a1) // get the longword + addl a1, 4, a1 // increment buffer pointer + subl t3, 1, t3 // decrement #longwords by 1 + stl t1, 0(t0) // store long to buffer + addq t0, a4, t0 // increment I/O buffer + bne t3, 30b // while #longwords > 0 + +// +// Do byte copies of remaining data uncopied +// + bic t0, a5, t0 // Stop doing LONG WRITE + +40: + and a2, 3, a2 // remaining Bytes to copy + beq a2, 60f // if count == 0 goto 60f (return) + +50: + ldq_u t1, 0(a1) // get quad surrounding byte + subl a2, 1, a2 // decrement count + extbl t1, a1, t1 // extract appropriate byte + addl a1, 1, a1 // increment buffer pointer + insbl t1, t3, t1 // get proper lane + stl t1, 0(t0) // store to buffer + addq t0, a3, t0 // increment I/O buffer + addl t3, 1, t3 // increment bytelane + and t3, 3, t3 // longwords only + bne a2, 50b // while count != 0 + +60: + mb // push writes off chip + + ret zero, (ra) // return + +// +// destn IO alignment != Src memory alignment +// move enough bytes to longword align the IO destn +// then move 32bit (longwords) reading unaligned data from memory +// then move residual bytes +// + +70: + beq t3, 90f // branch if destn is long aligned + +// +// Move bytes until IO destn is at a longword boundary or bytes exhausted +// + +80: + beq a2, 130f // if count == 0 goto 130f (return) + + ldq_u t1, 0(a1) // get quad surrounding byte + extbl t1, a1, t1 // extract appropriate byte + insbl t1, t3, t1 // get proper lane + stl t1, 0(t0) // store byte to buffer (BYTE ENABLED) + subl a2, 1, a2 // decrement count + addl a1, 1, a1 // increment buffer pointer + addq t0, a3, t0 // increment I/O buffer + addl t3, 1, t3 // increment bytelane + and t3, 3, t3 // longwords only + bne t3, 80b // loop if not long aligned + +// +// aligned IO destn, unaligned memory src +// + +90: + srl a2, 3, t3 // t3 = quadwords to move + beq t3, 110f // if no quads finish with bytes copies + + or t0, a5, t0 // We will now do LONG WRITES + +100: + ldq_u t1, 0(a1) // load low source quadword + ldq_u t2, 7(a1) // load high source quadword + extql t1, a1, t1 // extract low portion of quadword + extqh t2, a1, t2 // extract high portion of quadword + or t1, t2, t1 // merge to get the source quadword + stl t1, 0(t0) // store the long word (LONG ENABLED) + + lda a1, 8(a1) // next source quadword + srl t1, 32, t1 // get high longword into position + subl t3, 1, t3 // decrement number of quadwords to move + addq t0, a4, t0 // add LONG OFFSET to t0 + stl t1, (t0) // store the second long word + + addq t0, a4, t0 // increment to next dest. long + bne t3, 100b // while quadwords to move +// +// Do byte copies of the remaining data not yet copied +// + bic t0, a5, t0 // We will now do BYTE WRITES +110: + and a2, 7, a2 // remaining Bytes to copy + beq a2, 130f // if count == 0 goto 130f (return) + +120: + ldq_u t1, 0(a1) // get quad surrounding byte + subl a2, 1, a2 // decrement count + extbl t1, a1, t1 // extract appropriate byte + addl a1, 1, a1 // increment buffer pointer + insbl t1, t3, t1 // get proper lane + stl t1, 0(t0) // store byte to buffer (BYTE ENABLED) + addq t0, a3, t0 // increment I/O buffer + addl t3, 1, t3 // increment bytelane + and t3, 3, t3 // longwords only + bne a2, 120b // while count != 0 + +130: + mb // push writes off chip + + ret zero, (ra) // return + + .end EV5_WRITE_REGISTER_BUFFER_ULONG // end for UCHAR & USHORT + + +//++ +// +// VOID +// HalpWriteAbsoluteUlong( +// IN ULONG HighPart, +// IN ULONG LowPart, +// IN ULONG Value +// ) +// +// Routine Description: +// +// Writes Value to the processor address given in HighPart and LowPart. +// +// Arguments: +// +// HighPart(a0) - Upper 32 bits of address +// +// LowPart(a1) - Lower 32 bits of address +// +// Value(a2) - Value to write +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalpWriteAbsoluteUlong) + sll a0, 32, t0 // Shift Upper 32 bits of address into position + zap t0, 0x0f, t0 // Clear lower 32 bits of shifted address + zap a1, 0xf0, a1 // Clear upper 32 of lower part of address + or a1, t0, t0 // Build 64 bit address + stl a2, 0x0(t0) // Write value to address + mb // Memory Barrier + ret zero, (ra) // return + .end HalpWriteAbsoluteUlong + +//++ +// +// ULONG +// HalpReadAbsoluteUlong( +// IN ULONG HighPart, +// IN ULONG LowPart +// ) +// +// Routine Description: +// +// Reads a value from the processor address given in HighPart and LowPart. +// +// Arguments: +// +// HighPart(a0) - Upper 32 bits of address +// +// LowPart(a1) - Lower 32 bits of address +// +// Return Value: +// +// 32 bit value read from the processor address. +// +//-- + + LEAF_ENTRY(HalpReadAbsoluteUlong) + sll a0, 32, t0 // Shift Upper 32 bits of address into position + zap t0, 0x0f, t0 // Clear lower 32 bits of shifted address + zap a1, 0xf0, a1 // Clear upper 32 of lower part of address + or a1, t0, t0 // Build 64 bit address + mb // Memory Barrier + ldl v0, 0x0(t0) // Read value from address + ret zero, (ra) // return + .end HalpReadAbsoluteUlong + + diff --git a/private/ntos/nthals/halflex/alpha/apoc.h b/private/ntos/nthals/halflex/alpha/apoc.h new file mode 100644 index 000000000..85e3a8dc2 --- /dev/null +++ b/private/ntos/nthals/halflex/alpha/apoc.h @@ -0,0 +1,167 @@ +/*++ + +Copyright (c) 1995 DeskStation Technology + +Module Name: + + apoc.h + +Abstract: + + This file contains definitions specific to the Apocalypse (ALPHA EV5) + and Rogue (ALPHA EV4) processor modules. + +Author: + + Michael D. Kinney 1-May-1995 + +Environment: + + Kernel mode + +Revision History: + + +--*/ + +#define DTI_QVA_ENABLE (0x80000000) // Identify VA as a QVA +#define DTI_QVA_SELECTORS (0xc0000000) // QVA identification mask + +#define IO_BIT_SHIFT 0x05 // Bits to shift QVA + +#define IO_BYTE_OFFSET 0x20 // Offset to next byte +#define IO_SHORT_OFFSET 0x40 // Offset to next short +#define IO_LONG_OFFSET 0x80 // Offset to next long + +#define IO_BYTE_LEN 0x00 // Byte length +#define IO_WORD_LEN 0x08 // Word length +#define IO_TRIBYTE_LEN 0x10 // TriByte length +#define IO_LONG_LEN 0x18 // Longword length + +// +// Constant used by dense space I/O routines +// + +#define APOC1_PCI_DENSE_BASE_PHYSICAL_SUPERPAGE ((ULONGLONG)0xfffffcfb00000000) +#define APOC2_PCI_DENSE_BASE_PHYSICAL_SUPERPAGE ((ULONGLONG)0xfffffcfe00000000) +#define ROGUE_PCI_DENSE_BASE_PHYSICAL_SUPERPAGE ((ULONGLONG)0xfffffc0100000000) + +// +// Noncached Dense Memory address spaces. +// + +#define APOC1_NONCACHED_DENSE_BASE_PHYSICAL_SUPERPAGE ((ULONGLONG)0xfffffcfb00000000) +#define APOC2_NONCACHED_DENSE_BASE_PHYSICAL_SUPERPAGE ((ULONGLONG)0xfffffcfb00000000) +#define ROGUE_NONCACHED_DENSE_BASE_PHYSICAL_SUPERPAGE ((ULONGLONG)0xfffffc0100000000) + +// +// QVA +// HAL_MAKE_QVA( +// ULONGLONG PhysicalAddress +// ) +// +// Routine Description: +// +// This macro returns the Qva for a physical address in system space. +// +// Arguments: +// +// PhysicalAddress - Supplies a 64-bit physical address. +// +// Return Value: +// +// The Qva associated with the physical address. +// + +#define HAL_MAKE_QVA(PA) \ + ( (PVOID)( DTI_QVA_ENABLE | (ULONG)((PA) >> IO_BIT_SHIFT) & ~(DTI_QVA_SELECTORS) ) ) + + + +// +// Define physical address spaces for Apocalypse +// + +#define TREB1_APOC1_ISA_IO_BASE_PHYSICAL ((ULONGLONG)0x0c00000000) +#define TREB1_APOC1_ISA_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0a00000000) +#define TREB1_APOC1_ISA1_IO_BASE_PHYSICAL ((ULONGLONG)0x0d00000000) +#define TREB1_APOC1_ISA1_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0900000000) +#define TREB1_APOC1_PCI_IO_BASE_PHYSICAL ((ULONGLONG)0x0d00000000) +#define TREB1_APOC1_PCI_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0900000000) +#define TREB1_APOC1_PCI_HIGH_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0800000000) + +#define TREB1_APOC2_ISA_IO_BASE_PHYSICAL ((ULONGLONG)0x0c00000000) +#define TREB1_APOC2_ISA_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0a00000000) +#define TREB1_APOC2_ISA1_IO_BASE_PHYSICAL ((ULONGLONG)0x0d00000000) +#define TREB1_APOC2_ISA1_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0900000000) +#define TREB1_APOC2_PCI_IO_BASE_PHYSICAL ((ULONGLONG)0x0d00000000) +#define TREB1_APOC2_PCI_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0900000000) +#define TREB1_APOC2_PCI_HIGH_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0800000000) + +#define TREB2_APOC1_ISA_IO_BASE_PHYSICAL ((ULONGLONG)0x0d00000000) +#define TREB2_APOC1_ISA_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0900000000) +#define TREB2_APOC1_ISA1_IO_BASE_PHYSICAL ((ULONGLONG)0x0c00000000) +#define TREB2_APOC1_ISA1_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0a00000000) +#define TREB2_APOC1_PCI_IO_BASE_PHYSICAL ((ULONGLONG)0x0d00000000) +#define TREB2_APOC1_PCI_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0900000000) +#define TREB2_APOC1_PCI1_IO_BASE_PHYSICAL ((ULONGLONG)0x0c00000000) +#define TREB2_APOC1_PCI1_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0a00000000) +#define TREB2_APOC1_PCI_HIGH_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0800000000) + +#define TREB2_APOC2_ISA_IO_BASE_PHYSICAL ((ULONGLONG)0x0d00000000) +#define TREB2_APOC2_ISA_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0900000000) +#define TREB2_APOC2_ISA1_IO_BASE_PHYSICAL ((ULONGLONG)0x0c00000000) +#define TREB2_APOC2_ISA1_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0a00000000) +#define TREB2_APOC2_PCI_IO_BASE_PHYSICAL ((ULONGLONG)0x0d00000000) +#define TREB2_APOC2_PCI_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0900000000) +#define TREB2_APOC2_PCI1_IO_BASE_PHYSICAL ((ULONGLONG)0x0c00000000) +#define TREB2_APOC2_PCI1_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0a00000000) +#define TREB2_APOC2_PCI_HIGH_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0800000000) + +#define APOC1_PCI_CONFIG_BASE_PHYSICAL ((ULONGLONG)0xfffffcfe00000000) +#define APOC1_PCI_CONFIG0_BASE_PHYSICAL ((ULONGLONG)0xfffffcfe00000000) +#define APOC1_PCI_CONFIG1_BASE_PHYSICAL ((ULONGLONG)0xfffffcff00000000) +#define APOC1_PCI_DENSE_BASE_PHYSICAL ((ULONGLONG)0x0b00000000) + +#define APOC2_PCI_CONFIG_BASE_PHYSICAL ((ULONGLONG)0xfffffcb800000000) +#define APOC2_PCI_CONFIG0_BASE_PHYSICAL ((ULONGLONG)0xfffffcb800000000) +#define APOC2_PCI_CONFIG1_BASE_PHYSICAL ((ULONGLONG)0xfffffcd800000000) +#define APOC2_PCI_DENSE_BASE_PHYSICAL ((ULONGLONG)0x0e00000000) +#define APOC2_TRANSLATED_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0f00000000) + +#define APOC_DMA_CACHE_BASE_PHYSICAL ((ULONGLONG)0x0b007c0000) +#define APOC_CACHE_FLUSH_BASE_PHYSICAL ((ULONGLONG)0x003fe00000) +#define APOC_DMA_CACHE_SIZE 0x00040000 +#define APOC_CACHE_FLUSH_SIZE 0x00200000 + +// +// Define physical address spaces for Rogue +// + +#define ROGUE_TRANSLATED_BASE_PHYSICAL ((ULONGLONG)0x0a00000000) + +#define TREB1_ROGUE_ISA_IO_BASE_PHYSICAL ((ULONGLONG)0x0000000000) +#define TREB1_ROGUE_ISA_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0040000000) +#define TREB1_ROGUE_ISA1_IO_BASE_PHYSICAL ((ULONGLONG)0x0080000000) +#define TREB1_ROGUE_ISA1_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x00c0000000) +#define TREB1_ROGUE_PCI_IO_BASE_PHYSICAL ((ULONGLONG)0x0080000000) +#define TREB1_ROGUE_PCI_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x00c0000000) +#define TREB1_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0100000000) + +#define TREB2_ROGUE_ISA_IO_BASE_PHYSICAL ((ULONGLONG)0x0080000000) +#define TREB2_ROGUE_ISA_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x00c0000000) +#define TREB2_ROGUE_ISA1_IO_BASE_PHYSICAL ((ULONGLONG)0x0000000000) +#define TREB2_ROGUE_ISA1_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0040000000) +#define TREB2_ROGUE_PCI_IO_BASE_PHYSICAL ((ULONGLONG)0x0080000000) +#define TREB2_ROGUE_PCI_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x00c0000000) +#define TREB2_ROGUE_PCI1_IO_BASE_PHYSICAL ((ULONGLONG)0x0000000000) +#define TREB2_ROGUE_PCI1_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0040000000) +#define TREB2_ROGUE_PCI_HIGH_MEMORY_BASE_PHYSICAL ((ULONGLONG)0x0100000000) + +#define ROGUE_PCI_CONFIG0_BASE_PHYSICAL ((ULONGLONG)0x0200000000) +#define ROGUE_PCI_CONFIG1_BASE_PHYSICAL ((ULONGLONG)0x03c0000000) +#define ROGUE_PCI_DENSE_BASE_PHYSICAL ((ULONGLONG)0x0100000000) +#define ROGUE_DMA_CACHE_BASE_PHYSICAL ((ULONGLONG)0x01007c0000) +#define ROGUE_CACHE_FLUSH_BASE_PHYSICAL ((ULONGLONG)0x003fc00000) +#define ROGUE_DMA_CACHE_SIZE 0x00040000 +#define ROGUE_CACHE_FLUSH_SIZE 0x00400000 diff --git a/private/ntos/nthals/halflex/alpha/arcssup.c b/private/ntos/nthals/halflex/alpha/arcssup.c new file mode 100644 index 000000000..6169f9c3b --- /dev/null +++ b/private/ntos/nthals/halflex/alpha/arcssup.c @@ -0,0 +1,87 @@ +/*++ + +Copyright (c) 1995 DeskStation Technology + +Module Name: + + arcssup.c + +Abstract: + + This module allocates resources before a call to the ARCS Firmware, and + frees those reources after the call returns. + +Author: + + Michael D. Kinney 30-Apr-1995 + +Environment: + + Kernel mode + +Revision History: + +--*/ + +#include "halp.h" + +static KIRQL HalpArcsIrql; + +VOID +HalpAllocateArcsResources ( + VOID + ) + +/*++ + +Routine Description: + + This routine allocated resources required before an ARCS Firmware call is made. + On an ALPHA system, this is a NULL function. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + + +{ + if (HalpIoArchitectureType != EV5_PROCESSOR_MODULE) { + KeRaiseIrql(HIGH_LEVEL, &HalpArcsIrql); + HalpMiniTlbSaveState(); + } +} + +VOID +HalpFreeArcsResources ( + VOID + ) + +/*++ + +Routine Description: + + This routine frees the TLB entry that was reserved for the ARCS + Firmware call. On an ALPHA system, this is a NULL function. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + if (HalpIoArchitectureType != EV5_PROCESSOR_MODULE) { + HalpMiniTlbRestoreState(); + KeLowerIrql(HalpArcsIrql); + } +} diff --git a/private/ntos/nthals/halflex/alpha/dtidef.h b/private/ntos/nthals/halflex/alpha/dtidef.h new file mode 100644 index 000000000..2301a1556 --- /dev/null +++ b/private/ntos/nthals/halflex/alpha/dtidef.h @@ -0,0 +1,149 @@ +/*++ BUILD Version: 0005 // Increment this if a change has global effects + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + dtidef.h + +Abstract: + + This module is the header file that describes hardware addresses + for the Jazz system. + +Author: + + David N. Cutler (davec) 26-Nov-1990 + +Revision History: + +--*/ + +#ifndef _DTIDEF_ +#define _DTIDEF_ + +#include "uniflex.h" +#include "apoc.h" +#include "platform.h" + +// +// Define the data structure returned by a private vector firmware function +// that contains a set of system parameters. +// + +typedef struct PLATFORM_SPECIFIC_EXTENSION { + UCHAR PciInterruptToIsaIrq[12]; + ULONG PciVideoExpansionRomAddress; + PVOID AdvancedSetupInfo; +} PLATFORM_SPECIFIC_EXTENSION; + +typedef struct TREB13SETUPINFO { + ULONG Reserved1:16; + ULONG Drive0Type:4; + ULONG Drive1Type:4; + ULONG PciInterruptToIsaIrq0:4; + ULONG PciInterruptToIsaIrq8:4; + ULONG PciInterruptToIsaIrq1:4; + ULONG PciInterruptToIsaIrq9:4; + ULONG PciInterruptToIsaIrq2:4; + ULONG PciInterruptToIsaIrq10:4; + ULONG PciInterruptToIsaIrq3:4; + ULONG PciInterruptToIsaIrq11:4; + ULONG Lpt1Irq:8; + ULONG Lpt2Irq:8; + ULONG Lpt3Irq:8; + ULONG SerialMousePort:8; + ULONG EnableAmd1:1; + ULONG EnableAmd2:1; + ULONG EnableX86Emulator:1; + ULONG Reserved2:5; + ULONG LoadEmbeddedScsiDrivers:1; + ULONG Reserved3:7; + ULONG LoadSoftScsiDrivers:1; + ULONG LoadFlashScsiDrivers:1; + ULONG Reserved4:6; + ULONG EnableDelays:1; + ULONG Reserved5:7; + ULONG ResetDelay:8; + ULONG DetectDelay:8; + ULONG EnableIdeDriver:1; + ULONG Reserved6:7; +} TREB13SETUPINFO; + +typedef struct TREB20SETUPINFO { + ULONG Isa0Drive0Type:4; + ULONG Isa0Drive1Type:4; + ULONG Isa1Drive0Type:4; + ULONG Isa1Drive1Type:4; + ULONG SerialMousePort:8; + ULONG Isa0Lpt1Irq:8; + ULONG Isa0Lpt2Irq:8; + ULONG Isa0Lpt3Irq:8; + ULONG Isa1Lpt1Irq:8; + ULONG Isa1Lpt2Irq:8; + ULONG Isa1Lpt3Irq:8; + ULONG EnableNcr:1; + ULONG EnableX86Emulator:1; + ULONG LoadEmbeddedScsiDrivers:1; + ULONG LoadSoftScsiDrivers:1; + ULONG LoadFlashScsiDrivers:1; + ULONG EnableDelays:1; + ULONG EnableIdeDriver:1; + ULONG Reserved1:1; + ULONG ResetDelay:8; + ULONG DetectDelay:8; + ULONG PciInterruptToIsaIrq0:4; + ULONG PciInterruptToIsaIrq1:4; + ULONG PciInterruptToIsaIrq2:4; + ULONG PciInterruptToIsaIrq3:4; + ULONG PciInterruptToIsaIrq4:4; + ULONG PciInterruptToIsaIrq5:4; + ULONG PciInterruptToIsaIrq6:4; + ULONG PciInterruptToIsaIrq7:4; + ULONG PciInterruptToIsaIrq8:4; + ULONG PciInterruptToIsaIrq9:4; + ULONG NcrTermLow:1; + ULONG NcrTermHigh:1; + ULONG Reserved2:6; +} TREB20SETUPINFO; + +// +// Define the data structure used to describe all bus translations. +// + +typedef struct PLATFORM_RANGE_LIST { + INTERFACE_TYPE InterfaceType; + ULONG BusNumber; + ADDRESS_SPACE_TYPE AddressType; + ULONG SystemAddressSpace; + LONGLONG SystemBase; + LONGLONG Base; + LONGLONG Limit; +} PLATFORM_RANGE_LIST, *PPLATFORM_RANGE_LIST; + +// +// Define clock constants and clock levels. +// + +#define UNIFLEX_CLOCK_LEVEL UNIFLEX_EISA_VECTORS+0 // Interval clock level is on ISA IRQ 0 +#define UNIFLEX_ISA_DEVICE_LEVEL 5 // ISA bus interrupt level +#define UNIFLEX_EISA_DEVICE_LEVEL 5 // EISA bus interrupt level +#define UNIFLEX_PCI_DEVICE_LEVEL 5 // PCI bus interrupt level +#define UNIFLEX_CLOCK2_LEVEL UNIFLEX_CLOCK_LEVEL + +// +// Define EISA device interrupt vectors. +// + +#define UNIFLEX_ISA_VECTORS 48 +#define UNIFLEX_MAXIMUM_ISA_VECTOR (15 + UNIFLEX_ISA_VECTORS) +#define UNIFLEX_EISA_VECTORS 48 +#define UNIFLEX_MAXIMUM_EISA_VECTOR (15 + UNIFLEX_EISA_VECTORS) +#define UNIFLEX_ISA1_VECTORS 64 +#define UNIFLEX_MAXIMUM_ISA1_VECTOR (15 + UNIFLEX_ISA1_VECTORS) +#define UNIFLEX_EISA1_VECTORS 64 +#define UNIFLEX_MAXIMUM_EISA1_VECTOR (15 + UNIFLEX_EISA1_VECTORS) +#define UNIFLEX_PCI_VECTORS 100 +#define UNIFLEX_MAXIMUM_PCI_VECTOR (15 + UNIFLEX_PCI_VECTORS) + +#endif // _DTIDEF_ diff --git a/private/ntos/nthals/halflex/alpha/ev4int.c b/private/ntos/nthals/halflex/alpha/ev4int.c new file mode 100644 index 000000000..7b64b42c8 --- /dev/null +++ b/private/ntos/nthals/halflex/alpha/ev4int.c @@ -0,0 +1,955 @@ +/*++ + +Copyright (C) 1993-1995 Digital Equipment Corporation + +Module Name: + + ev4int.c + +Abstract: + + This module implements the support routines to enable/disable DECchip + 21064-specific interrupts. + +Environment: + + Kernel mode + +--*/ + +#include "halp.h" +#include "axp21064.h" + +VOID +HalpUpdate21064PriorityTable( + VOID + ); + +VOID +HalpCachePcrValues( + VOID + ); + + + +VOID +HalpInitialize21064Interrupts( + VOID + ) +/*++ + +Routine Description: + + This routine initializes the data structures for the 21064 + interrupt enable/disable routines. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + ULONG Index; + EV4Irq Irq; + + // + // Initialize each entry in the Irq Status Table. + // + + for( Irq=Irq0; IrqIrqStatusTable[Irq].Enabled = FALSE; + HAL_21064_PCR->IrqStatusTable[Irq].Irql = PASSIVE_LEVEL; + HAL_21064_PCR->IrqStatusTable[Irq].Vector = PASSIVE_VECTOR; + HAL_21064_PCR->IrqStatusTable[Irq].Priority = 0; + } + + HalpUpdate21064PriorityTable(); + + // + // Write IrqlMask table entries for the Software Subtable. + // + + Index = IRQLMASK_SFW_SUBTABLE_21064; + + PCR->IrqlMask[Index].IrqlTableIndex = PASSIVE_LEVEL; + PCR->IrqlMask[Index].IDTIndex = PASSIVE_VECTOR; + Index += 1; + + PCR->IrqlMask[Index].IrqlTableIndex = APC_LEVEL; + PCR->IrqlMask[Index].IDTIndex = APC_VECTOR; + Index += 1; + + PCR->IrqlMask[Index].IrqlTableIndex = DISPATCH_LEVEL; + PCR->IrqlMask[Index].IDTIndex = DISPATCH_VECTOR; + Index += 1; + + PCR->IrqlMask[Index].IrqlTableIndex = DISPATCH_LEVEL; + PCR->IrqlMask[Index].IDTIndex = DISPATCH_VECTOR; + + // + // Write the IrqlMask table entries for the Performance Counter Subtable. + // + + Index = IRQLMASK_PC_SUBTABLE_21064; + + PCR->IrqlMask[Index].IrqlTableIndex = PASSIVE_LEVEL; + PCR->IrqlMask[Index].IDTIndex = PASSIVE_VECTOR; + Index += 1; + + PCR->IrqlMask[Index].IrqlTableIndex = PROFILE_LEVEL; + PCR->IrqlMask[Index].IDTIndex = PC0_VECTOR; + Index += 1; + + PCR->IrqlMask[Index].IrqlTableIndex = PROFILE_LEVEL; + PCR->IrqlMask[Index].IDTIndex = PC1_VECTOR; + Index += 1; + + PCR->IrqlMask[Index].IrqlTableIndex = PROFILE_LEVEL; + PCR->IrqlMask[Index].IDTIndex = PC1_VECTOR; + + return; + +} + +VOID +HalpUpdate21064PriorityTable( + VOID + ) +/*++ + +Routine Description: + + This function updates the Irql Mask Table in the PCR of the current + processor. It is called whenever an interrupt is enabled or disabled. + The source of the data used to update the table is the global + IrqStatusTable. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + ULONG InterruptMask; + EV4Irq Irq; + KIRQL Irql; + ULONG IrqlMaskIndex; + UCHAR Priority; + ULONG Vector; + + // + // Cycle through each entry of the interrupt mask table for the + // hardware entries. For each entry, compute the highest priority + // entry that could be asserted for the mask entry and is enabled. + // The priority is determined first by Irql level, higher Irql + // indicates higher priority, and then, if there are multiple + // enabled, asserted interrupts of the same Irql, by a relative + // priority that was assigned by the caller when the interrupt + // was enabled. + // + + for( InterruptMask=0; + InterruptMask < IRQLMASK_HDW_SUBTABLE_21064_ENTRIES; + InterruptMask++ ){ + + Vector = PASSIVE_VECTOR; + Irql = PASSIVE_LEVEL; + Priority = 0; + + // + // Check if each Irq is asserted and enabled for this interrupt + // mask. + // + + for( Irq=Irq0; IrqIrqStatusTable[Irq].Enabled == TRUE) && + (HAL_21064_PCR->IrqStatusTable[Irq].Irql >= Irql) ){ + + // + // If the new Irq has a higher Irql than the highest + // currently selected or has a higher relative priority + // then this is the Irq to be selected if this mask + // pattern is selected. + // + + if( (HAL_21064_PCR->IrqStatusTable[Irq].Irql > Irql) || + (HAL_21064_PCR->IrqStatusTable[Irq].Priority > Priority) ){ + + Irql = HAL_21064_PCR->IrqStatusTable[Irq].Irql; + Priority = HAL_21064_PCR->IrqStatusTable[Irq].Priority; + Vector = HAL_21064_PCR->IrqStatusTable[Irq].Vector; + + } + + } + } + + IrqlMaskIndex = IRQLMASK_HDW_SUBTABLE_21064 + InterruptMask; + PCR->IrqlMask[IrqlMaskIndex].IrqlTableIndex = Irql; + PCR->IrqlMask[IrqlMaskIndex].IDTIndex = (USHORT)Vector; + } +} + +VOID +HalpDisable21064HardwareInterrupt( + IN ULONG Irq + ) +/*++ + +Routine Description: + + This routine disables the interrupt connected to the specified Irq + pin on the 21064. + +Arguments: + + Irq - Supplies the number of the Irq pin for the interrupt that is disabled. + +Return Value: + + None. + +--*/ +{ + + KIRQL IrqlIndex; + PIETEntry_21064 IetEntry; + KIRQL OldIrql; + + // + // Raise IRQL to the highest level. + // + + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + + IetEntry = (PIETEntry_21064)(&PCR->IrqlTable); + IrqlIndex = PASSIVE_LEVEL; + + // + // Update the enable table for all the Irqls such that the interrupt + // is disabled. + // + + while( IrqlIndex <= HIGH_LEVEL ){ + + switch( Irq ){ + + case Irq0: + + IetEntry[IrqlIndex].Irq0Enable = 0; + break; + + case Irq1: + + IetEntry[IrqlIndex].Irq1Enable = 0; + break; + + case Irq2: + + IetEntry[IrqlIndex].Irq2Enable = 0; + break; + + case Irq3: + + IetEntry[IrqlIndex].Irq3Enable = 0; + break; + + case Irq4: + + IetEntry[IrqlIndex].Irq4Enable = 0; + break; + + case Irq5: + + IetEntry[IrqlIndex].Irq5Enable = 0; + break; + + + } //end switch( Irq ) + + IrqlIndex++; + + } //end while IrqlIndex <= HIGH_LEVEL + + // + // Update the Irq status table and reflect the changes in the + // PCR IrqlMask table. + // + + HAL_21064_PCR->IrqStatusTable[Irq].Enabled = FALSE; + + // + // Alert the PAL that the enable table has changed so that it can + // reload the new values. + // + + HalpCachePcrValues(); + + // + // Lower IRQL to the previous level. + // + + KeLowerIrql(OldIrql); + return; + +} + + +VOID +HalpDisable21064SoftwareInterrupt( + IN KIRQL Irql + ) +/*++ + +Routine Description: + + This routine disables the indicated software interrupt level. + +Arguments: + + Irql - Supplies the software interrupt level to disable (APC_LEVEL or + DISPATCH_LEVEL). + +Return Value: + + None. + +--*/ +{ + + PIETEntry_21064 IetEntry; + KIRQL OldIrql; + + // + // Raise IRQL to the highest level. + // + + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + + IetEntry = (PIETEntry_21064)(&PCR->IrqlTable); + + switch( Irql ){ + + // + // APC Interrupt level. + // + + case APC_LEVEL: + + IetEntry[PASSIVE_LEVEL].ApcEnable = 0; + break; + + // + // DPC Interrupt level. + // + + case DISPATCH_LEVEL: + + IetEntry[PASSIVE_LEVEL].DispatchEnable = 0; + IetEntry[APC_LEVEL].DispatchEnable = 0; + break; + + // + // Unrecognized software interrupt level. + // + + default: + + NOTHING; + +#if HALDBG + + DbgPrint( "HalpDisable21064SoftwareInterrupt, Bad software level= %x\n", + Irql ); + +#endif //HALDBG + + } + + // + // Alert the PAL that the enable table has changed so that it can + // reload the new values. + // + + HalpCachePcrValues(); + + // + // Lower IRQL to the previous level. + // + + KeLowerIrql(OldIrql); + return; +} + + +VOID +HalpDisable21064PerformanceInterrupt( + IN ULONG Vector + ) +/*++ + +Routine Description: + + This routine disables the specified performance counter interrupt. + +Arguments: + + Vector - Supplies the interrupt vector number of the performance counter + interrupt which is disabled. + +Return Value: + + None. + +--*/ +{ + + KIRQL IrqlIndex; + PIETEntry_21064 IetEntry; + KIRQL OldIrql; + + // + // Raise IRQL to the highest level. + // + + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + + IetEntry = (PIETEntry_21064)(&PCR->IrqlTable); + IrqlIndex = PASSIVE_LEVEL; + + // + // Update the enable table for all the Irqls such that the interrupt + // is disabled. + // + + while( IrqlIndex <= HIGH_LEVEL ){ + + switch( Vector ){ + + case PC0_VECTOR: + case PC0_SECONDARY_VECTOR: + + IetEntry[IrqlIndex].PerformanceCounter0Enable = 0; + break; + + case PC1_VECTOR: + case PC1_SECONDARY_VECTOR: + + IetEntry[IrqlIndex].PerformanceCounter1Enable = 0; + break; + + + } //end switch( Vector ) + + IrqlIndex++; + + } //end while IrqlIndex <= HIGH_LEVEL + + // + // Alert the PAL that the enable table has changed so that it can + // reload the new values. + // + + HalpCachePcrValues(); + + // + // Lower IRQL to the previous level. + // + + KeLowerIrql(OldIrql); + return; +} + +VOID +HalpDisable21064CorrectableInterrupt( + VOID + ) +/*++ + +Routine Description: + + This routine disables the correctable read error interrupt. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + + KIRQL IrqlIndex; + PIETEntry_21064 IetEntry; + KIRQL OldIrql; + + // + // Raise IRQL to the highest level. + // + + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + + IetEntry = (PIETEntry_21064)(&PCR->IrqlTable); + IrqlIndex = PASSIVE_LEVEL; + + // + // Update the enable table for all the Irqls such that the interrupt + // is disabled. + // + + while( IrqlIndex <= HIGH_LEVEL ){ + + IetEntry[IrqlIndex].CorrectableReadEnable = 0; + + IrqlIndex++; + + } //end while IrqlIndex <= HIGH_LEVEL + + // + // Alert the PAL that the enable table has changed so that it can + // reload the new values. + // + + HalpCachePcrValues(); + + // + // Lower IRQL to the previous level. + // + + KeLowerIrql(OldIrql); + return; +} + +VOID +HalpEnable21064HardwareInterrupt ( + IN ULONG Irq, + IN KIRQL Irql, + IN ULONG Vector, + IN UCHAR Priority + ) + +/*++ + +Routine Description: + + This routine enables the specified system interrupt. + +Arguments: + + Irq - Supplies the IRQ pin number of the interrupt that is enabled. + + Irql - Supplies the Irql of the interrupting source. + + Vector - Supplies the interrupt vector for the enabled interrupt. + + Priority - Supplies the relative priority of the interrupt in comparison + with other Irqs of the same Irql. + +Return Value: + + None. + +--*/ + +{ + + KIRQL IrqlIndex; + PIETEntry_21064 IetEntry; + KIRQL OldIrql; + + // + // Raise IRQL to the highest level. + // + + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + + + IetEntry = (PIETEntry_21064)(&PCR->IrqlTable); + IrqlIndex = PASSIVE_LEVEL; + + // + // Update the enable table for each Irql that the interrupt should + // be enabled. + // + + while( IrqlIndex < Irql ){ + + switch( Irq ){ + + case Irq0: + + IetEntry[IrqlIndex].Irq0Enable = 1; + break; + + case Irq1: + + IetEntry[IrqlIndex].Irq1Enable = 1; + break; + + case Irq2: + + IetEntry[IrqlIndex].Irq2Enable = 1; + break; + + case Irq3: + + IetEntry[IrqlIndex].Irq3Enable = 1; + break; + + case Irq4: + + IetEntry[IrqlIndex].Irq4Enable = 1; + break; + + case Irq5: + + IetEntry[IrqlIndex].Irq5Enable = 1; + break; + + } // end switch( Vector ) + + IrqlIndex++; + + } //end while IrqlIndex < Irql + + // + // Populate the interrupt status table and then update the Irql Mask + // table. + // + + HAL_21064_PCR->IrqStatusTable[Irq].Enabled = TRUE; + HAL_21064_PCR->IrqStatusTable[Irq].Vector = Vector; + HAL_21064_PCR->IrqStatusTable[Irq].Irql = Irql; + HAL_21064_PCR->IrqStatusTable[Irq].Priority = Priority; + + HalpUpdate21064PriorityTable(); + + // + // Alert the PAL that the enable table has changed so that it can + // reload the new values. + // + + HalpCachePcrValues(); + + // + // Lower IRQL to the previous level. + // + + KeLowerIrql(OldIrql); + return; +} + + +VOID +HalpEnable21064SoftwareInterrupt( + IN KIRQL Irql + ) +/*++ + +Routine Description: + + This routine enables the indicated software interrupt level. + +Arguments: + + Irql - Supplies the software interrupt level to enable (APC_LEVEL or + DISPATCH_LEVEL). + +Return Value: + + None. + +--*/ +{ + + PIETEntry_21064 IetEntry; + KIRQL OldIrql; + + // + // Raise IRQL to the highest level. + // + + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + + IetEntry = (PIETEntry_21064)(&PCR->IrqlTable); + + switch( Irql ){ + + // + // APC Interrupt level. + // + + case APC_LEVEL: + + IetEntry[PASSIVE_LEVEL].ApcEnable = 1; + break; + + // + // DPC Interrupt level. + // + + case DISPATCH_LEVEL: + + IetEntry[PASSIVE_LEVEL].DispatchEnable = 1; + IetEntry[APC_LEVEL].DispatchEnable = 1; + break; + + // + // Unrecognized software interrupt level. + // + + default: + + NOTHING; + +#if HALDBG + + DbgPrint( "HalpEnable21064SoftwareInterrupt, Bad software level= %x\n", + Irql ); + +#endif //HALDBG + + } + + // + // Alert the PAL that the enable table has changed so that it can + // reload the new values. + // + + HalpCachePcrValues(); + + // + // Lower IRQL to the previous level. + // + + KeLowerIrql(OldIrql); + return; + +} + + +VOID +HalpEnable21064PerformanceInterrupt ( + IN ULONG Vector, + IN KIRQL Irql + ) + +/*++ + +Routine Description: + + This routine enables the specified performance counter interrupt. + +Arguments: + + Vector - Supplies the vector of the performance counter interrupt that is + enabled. + + Irql - Supplies the Irql of the performance counter interrupt. + +Return Value: + + None. + +--*/ + +{ + + KIRQL IrqlIndex; + PIETEntry_21064 IetEntry; + KIRQL OldIrql; + + // + // Raise IRQL to the highest level. + // + + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + + + IetEntry = (PIETEntry_21064)(&PCR->IrqlTable); + IrqlIndex = PASSIVE_LEVEL; + + // + // Update the enable table for each Irql that the interrupt should + // be enabled. + // + + while( IrqlIndex < Irql ){ + + switch( Vector ){ + + case PC0_VECTOR: + case PC0_SECONDARY_VECTOR: + + IetEntry[IrqlIndex].PerformanceCounter0Enable = 1; + break; + + case PC1_VECTOR: + case PC1_SECONDARY_VECTOR: + + IetEntry[IrqlIndex].PerformanceCounter1Enable = 1; + break; + + } // end switch( Vector ) + + IrqlIndex++; + + } //end while IrqlIndex < Irql + + // + // Alert the PAL that the enable table has changed so that it can + // reload the new values. + // + + HalpCachePcrValues(); + + // + // Lower IRQL to the previous level. + // + + KeLowerIrql(OldIrql); + return; +} + +VOID +HalpEnable21064CorrectableInterrupt ( + IN KIRQL Irql + ) + +/*++ + +Routine Description: + + This routine enables the correctable read error interrupt. + +Arguments: + + Irql - Supplies the Irql of the correctable read error interrupt. + +Return Value: + + None. + +--*/ + +{ + + KIRQL IrqlIndex; + PIETEntry_21064 IetEntry; + KIRQL OldIrql; + + // + // Raise IRQL to the highest level. + // + + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + + + IetEntry = (PIETEntry_21064)(&PCR->IrqlTable); + IrqlIndex = PASSIVE_LEVEL; + + // + // Update the enable table for each Irql that the interrupt should + // be enabled. + // + + while( IrqlIndex < Irql ){ + + IetEntry[IrqlIndex].CorrectableReadEnable = 1; + + IrqlIndex++; + + } //end while IrqlIndex < Irql + + // + // Alert the PAL that the enable table has changed so that it can + // reload the new values. + // + + HalpCachePcrValues(); + + // + // Lower IRQL to the previous level. + // + + KeLowerIrql(OldIrql); + return; +} + + +ULONG +HalpGet21064PerformanceVector( + IN ULONG BusInterruptLevel, + OUT PKIRQL Irql + ) + +/*++ + +Routine Description: + + This function returns the system interrupt vector and IRQL level + corresponding to the specified performance counter interrupt. + +Arguments: + + BusInterruptLevel - Supplies the performance counter number. + + Irql - Returns the system request priority. + +Return Value: + + Returns the system interrupt vector corresponding to the specified device. + +--*/ + +{ + + // + // Handle the special internal bus defined for the processor itself + // and used to control the performance counters in the 21064. + // + + *Irql = PROFILE_LEVEL; + + switch( BusInterruptLevel ){ + + // + // Performance Counter 0 + // + + case 0: + + return PC0_SECONDARY_VECTOR; + + // + // Performance Counter 1 + // + + case 1: + + return PC1_SECONDARY_VECTOR; + + } //end switch( BusInterruptLevel ) + + // + // Unrecognized. + // + + *Irql = 0; + return 0; + +} + diff --git a/private/ntos/nthals/halflex/alpha/ev4ints.s b/private/ntos/nthals/halflex/alpha/ev4ints.s new file mode 100644 index 000000000..08fdaadc0 --- /dev/null +++ b/private/ntos/nthals/halflex/alpha/ev4ints.s @@ -0,0 +1,300 @@ +//++ +// +// Copyright (C) 1994,1995 Microsoft Corporation +// +// Module Name: +// +// ev4ints.s +// +// Abstract: +// +// This module implements EV4-specific interrupt handlers. +// (the performance counters) +// +// +// Environment: +// +// Kernel mode only. +// +// +//-- +#include "halalpha.h" + +#define PC0_SECONDARY_VECTOR 11 +#define PC1_SECONDARY_VECTOR 13 +#define PcProfileCount0 PcHalReserved+8 +#define PcProfileCount1 PcProfileCount0+4 +#define PcProfileCountReload0 PcProfileCount1+4 +#define PcProfileCountReload1 PcProfileCountReload0+4 + + .struct 0 + .space 8 // reserved for alignment +PrRa: .space 8 // space for return address +PrFrameLength: // + + SBTTL("Performance Counter 0 Interrupt") +//++ +// +// VOID +// Halp21064PerformanceCounter0Interrupt +// ) +// +// Routine Description: +// +// This function is executed as the result of an interrupt from the +// internal microprocessor performance counter 0. The interrupt +// may be used to signal the completion of a profile event. +// If profiling is current active, the function determines if the +// profile interval has expired and if so dispatches to the standard +// system routine to update the system profile time. If profiling +// is not active then the function performs a secondary dispatch for +// performance counter 0. +// +// Arguments: +// +// TrapFrame (fp/s6) - Supplies a pointer to the trap frame for +// the interrupt. +// +// Return Value: +// +// TRUE is returned. +// +//-- + + NESTED_ENTRY(Halp21064PerformanceCounter0Interrupt, PrFrameLength, zero ) + + lda sp, -PrFrameLength(sp) // allocate a stack frame + stq ra, PrRa(sp) // save the return address + + PROLOGUE_END // + + call_pal rdpcr // v0 = pcr base address + + ldl t0, PcProfileCount0(v0) // capture the current profile count + beq t0, 20f // if eq, profiling not active + +// +// Profiling is active. Decrement the interval count and if it has +// reached zero then call the kernel profile routine. +// + + subl t0, 1, t0 // decrement the interval count + bne t0, 10f // if ne, interval has not expired + +// +// The profile interval has expired. Reset the profile interval count +// and process the profile interrupt. +// + + ldl t0, PcProfileCountReload0(v0) // get the new tick count + stl t0, PcProfileCount0(v0) // reset the profile interval count + + ldl a1, Halp21064ProfileSource0 + bis fp, zero, a0 // pass trap frame pointer + ldl t1, __imp_KeProfileInterruptWithSource + jsr ra, (t1) // process the profile interrupt + + br zero, 40f // common return + +// +// The profile interval has not expired. Update the decremented count. +// + +10: + stl t0, PcProfileCount0(v0) // update profile interval count + br zero, 40f // common return + +// +// Profiling is not active. Therefore, this interrupt was caused by +// a performance counter driver. Deliver a secondary dispatch. +// + +20: + + ldil a0, PC0_SECONDARY_VECTOR // get IDT vector for secondary + s4addl a0, v0, a0 // a0 = PCR + IDT index + ldl a0, PcInterruptRoutine(a0) // get service routine address + jsr ra, (a0) // call interrupt service routine + +// +// Setup for return. +// + +40: + ldil v0, TRUE // set return value = TRUE + ldq ra, PrRa(sp) // restore return address + lda sp, PrFrameLength(sp) // deallocate the stack frame + ret zero, (ra) // return + + .end Halp21064PerformanceCounter0Interrupt + + + SBTTL("Performance Counter 1 Interrupt") +//++ +// +// VOID +// Halp21064PerformanceCounter1Interrupt +// ) +// +// Routine Description: +// +// This function is executed as the result of an interrupt from the +// internal microprocessor performance counter 1. The interrupt +// may be used to signal the completion of a profile event. +// If profiling is current active, the function determines if the +// profile interval has expired and if so dispatches to the standard +// system routine to update the system profile time. If profiling +// is not active then the function performs a secondary dispatch for +// performance counter 1. +// +// Arguments: +// +// TrapFrame (fp/s6) - Supplies a pointer to the trap frame for +// the interrupt. +// +// Return Value: +// +// TRUE is returned. +// +//-- + + NESTED_ENTRY(Halp21064PerformanceCounter1Interrupt, PrFrameLength, zero ) + + lda sp, -PrFrameLength(sp) // allocate a stack frame + stq ra, PrRa(sp) // save the return address + + PROLOGUE_END // + + call_pal rdpcr // v0 = pcr base address + + ldl t0, PcProfileCount1(v0) // capture the current profile count + beq t0, 20f // if eq, profiling not active + +// +// Profiling is active. Decrement the interval count and if it has +// reached zero then call the kernel profile routine. +// + + subl t0, 1, t0 // decrement the interval count + bne t0, 10f // if ne, interval has not expired + +// +// The profile interval has expired. Reset the profile interval count +// and process the profile interrupt. +// + + ldl t0, PcProfileCountReload1(v0) // get the new tick count + stl t0, PcProfileCount1(v0) // reset the profile interval count + + ldl a1, Halp21064ProfileSource1 + bis fp, zero, a0 // pass trap frame pointer + ldl t1, __imp_KeProfileInterruptWithSource + jsr ra, (t1) // process the profile interrupt + + br zero, 40f // common return + +// +// The profile interval has not expired. Update the decremented count. +// + +10: + stl t0, PcProfileCount1(v0) // update profile interval count + br zero, 40f // common return + +// +// Profiling is not active. Therefore, this interrupt was caused by +// a performance counter driver. Deliver a secondary dispatch. +// + +20: + + ldil a0, PC1_SECONDARY_VECTOR // get IDT vector for secondary + s4addl a0, v0, a0 // a0 = PCR + IDT index + ldl a0, PcInterruptRoutine(a0) // get service routine address + jsr ra, (a0) // call interrupt service routine + +// +// Setup for return. +// + +40: + ldil v0, TRUE // set return value = TRUE + ldq ra, PrRa(sp) // restore return address + lda sp, PrFrameLength(sp) // deallocate the stack frame + ret zero, (ra) // return + + .end Halp21064PerformanceCounter1Interrupt + +//++ +// +// VOID +// Halp21064WritePerformanceCounter( +// IN ULONG PerformanceCounter, +// IN BOOLEAN Enable, +// IN ULONG MuxControl OPTIONAL, +// IN ULONG EventCount OPTIONAL +// ) +// +// Routine Description: +// +// Write the specified microprocessor internal performance counter. +// +// Arguments: +// +// PerformanceCounter(a0) - Supplies the number of the performance counter +// to write. +// +// Enable(a1) - Supplies a boolean that indicates if the performance +// counter should be enabled or disabled. +// +// MuxControl(a2) - Supplies the mux control value which selects which +// type of event to count when the counter is enabled. +// +// EventCount(a3) - Supplies the event interval when the counter is +// enabled. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(Halp21064WritePerformanceCounter) + + call_pal wrperfmon // write the counter + + ret zero, (ra) // return + + .end Halp21064WritePerformanceCounter + +//++ +// +// VOID +// Halp21064ClearLockRegister( +// PVOID LockAddress +// ) +// +// Routine Description: +// +// This function is called on every interrupt to clear the lock bit. +// +// Arguments: +// +// ClearLockAddress(a0) - Address in which to perform the conditional store. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(Halp21064ClearLockRegister) + + mb // Force all previous write off chip + stl_c zero, 0x0(a0) // Clear the lock register + mb // Force the write to clear the lock register off chip + ret zero, (ra) // return + + .end Halp21064ClearLockRegister + + diff --git a/private/ntos/nthals/halflex/alpha/ev4prof.c b/private/ntos/nthals/halflex/alpha/ev4prof.c new file mode 100644 index 000000000..53dc896c6 --- /dev/null +++ b/private/ntos/nthals/halflex/alpha/ev4prof.c @@ -0,0 +1,585 @@ +/*++ + +Copyright (C) 1994,1995 Digital Equipment Corporation + +Module Name: + + ev4prof.c + +Abstract: + + This module implements the Profile Counter using the performance + counters within the EV4 core. This module is appropriate for all + machines based on microprocessors using the EV4 core. + + N.B. - This module assumes that all processors in a multiprocessor + system are running the microprocessor at the same clock speed. + +Environment: + + Kernel mode + +--*/ + +#include "halp.h" +#include "axp21064.h" + + +// +// Define space in the HAL-reserved part of the PCR structure for each +// performance counter's interval count +// +// Note that ev4ints.s depends on these positions in the PCR. +// +#define PCRProfileCount ((PULONG)(HAL_21064_PCR->ProfileCount.ProfileCount)) +#define PCRProfileCountReload ((PULONG)(&HAL_21064_PCR->ProfileCount.ProfileCountReload)) + + +// +// Define the currently selected profile source for each counter +// +KPROFILE_SOURCE Halp21064ProfileSource0; +KPROFILE_SOURCE Halp21064ProfileSource1; + +#define INTERVAL_DELTA (10) + +// +// Define the mapping between possible profile sources and the +// CPU-specific settings. +// +typedef struct _HALP_PROFILE_MAPPING { + BOOLEAN Supported; + ULONG MuxControl; + ULONG Counter; + ULONG EventCount; + ULONG NumberOfTicks; +} HALP_PROFILE_MAPPING, *PHALP_PROFILE_MAPPING; + +HALP_PROFILE_MAPPING Halp21064ProfileMapping[ProfileMaximum] = + { + {TRUE, Ev4TotalCycles, Ev4PerformanceCounter0, Ev4CountEvents2xx12, 10}, + {FALSE, 0, 0, 0, 0}, + {TRUE, Ev4TotalIssues, Ev4PerformanceCounter0, Ev4CountEvents2xx16, 10}, + {TRUE, Ev4PipelineDry, Ev4PerformanceCounter0, Ev4CountEvents2xx16, 10}, + {TRUE, Ev4LoadInstruction, Ev4PerformanceCounter0, Ev4CountEvents2xx12, 10}, + {TRUE, Ev4PipelineFrozen, Ev4PerformanceCounter0, Ev4CountEvents2xx16, 10}, + {TRUE, Ev4BranchInstructions, Ev4PerformanceCounter0, Ev4CountEvents2xx12, 10}, + {TRUE, Ev4TotalNonIssues, Ev4PerformanceCounter0, Ev4CountEvents2xx16, 10}, + {TRUE, Ev4DcacheMiss, Ev4PerformanceCounter1, Ev4CountEvents2xx12, 10}, + {TRUE, Ev4IcacheMiss, Ev4PerformanceCounter1, Ev4CountEvents2xx12, 10}, + {FALSE, 0, 0, 0, 0}, + {TRUE, Ev4BranchMispredicts, Ev4PerformanceCounter1, Ev4CountEvents2xx12, 10}, + {TRUE, Ev4StoreInstructions, Ev4PerformanceCounter1, Ev4CountEvents2xx12, 10}, + {TRUE, Ev4FPInstructions, Ev4PerformanceCounter1, Ev4CountEvents2xx12, 10}, + {TRUE, Ev4IntegerOperate, Ev4PerformanceCounter1, Ev4CountEvents2xx12, 10}, + {TRUE, Ev4DualIssues, Ev4PerformanceCounter1, Ev4CountEvents2xx12, 10}, + {FALSE, 0, 0, 0, 0}, + {FALSE, 0, 0, 0, 0}, + {TRUE, Ev4PalMode, Ev4PerformanceCounter0, Ev4CountEvents2xx16, 10}, + {TRUE, Ev4TotalCycles, Ev4PerformanceCounter0, Ev4CountEvents2xx16, 10}, + {FALSE, 0, 0, 0, 0}, + {FALSE, 0, 0, 0, 0} + }; + +BOOLEAN +HalQueryProfileInterval( + IN KPROFILE_SOURCE Source + ); + +NTSTATUS +HalSetProfileSourceInterval( + IN KPROFILE_SOURCE ProfileSource, + IN OUT ULONG *Interval + ); + + + +NTSTATUS +Halp21064ProfileSourceInformation ( + OUT PVOID Buffer, + IN ULONG BufferLength, + OUT PULONG ReturnedLength + ) +/*++ + +Routine Description: + + Returns the HAL_PROFILE_SOURCE_INFORMATION for this processor. + +Arguments: + + Buffer - output buffer + BufferLength - length of buffer on input + ReturnedLength - The length of data returned + +Return Value: + + STATUS_SUCCESS + STATUS_BUFFER_TOO_SMALL - The ReturnedLength contains the buffersize + currently needed. + +--*/ +{ + PHAL_PROFILE_SOURCE_INFORMATION SourceInfo; + NTSTATUS Status; + + + if (BufferLength != sizeof(HAL_PROFILE_SOURCE_INFORMATION)) { + Status = STATUS_INFO_LENGTH_MISMATCH; + return Status; + } + + SourceInfo = (PHAL_PROFILE_SOURCE_INFORMATION)Buffer; + SourceInfo->Supported = HalQueryProfileInterval(SourceInfo->Source); + + if (SourceInfo->Supported) { + SourceInfo->Interval = + Halp21064ProfileMapping[SourceInfo->Source].EventCount * + Halp21064ProfileMapping[SourceInfo->Source].NumberOfTicks; + if (SourceInfo->Source == ProfileTotalIssues) { + // + // Convert total issues/2 back into total issues + // + SourceInfo->Interval = SourceInfo->Interval * 2; + } + } + + Status = STATUS_SUCCESS; + return Status; +} + +NTSTATUS +Halp21064ProfileSourceInterval ( + OUT PVOID Buffer, + IN ULONG BufferLength + ) +/*++ + +Routine Description: + + Returns the HAL_PROFILE_SOURCE_INTERVAL for this processor. + +Arguments: + + Buffer - output buffer + BufferLength - length of buffer on input + +Return Value: + + STATUS_SUCCESS + STATUS_BUFFER_TOO_SMALL - The ReturnedLength contains the buffersize + currently needed. + +--*/ +{ + PHAL_PROFILE_SOURCE_INTERVAL Interval; + NTSTATUS Status; + + + if (BufferLength != sizeof(HAL_PROFILE_SOURCE_INTERVAL)) { + Status = STATUS_INFO_LENGTH_MISMATCH; + return Status; + } + + Interval = (PHAL_PROFILE_SOURCE_INTERVAL)Buffer; + Status = HalSetProfileSourceInterval(Interval->Source, + &Interval->Interval); + return Status; +} + +VOID +Halp21064InitializeProfiler( + VOID + ) +/*++ + +Routine Description: + + This routine is called during initialization to initialize profiling + for each processor in the system. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + PKINTERRUPT InterruptObject; + KIRQL Irql; + PKPRCB Prcb = PCR->Prcb; + ULONG Vector; + + // + // Establish the profile interrupt as the interrupt handler for + // all performance counter interrupts. + // + + PCR->InterruptRoutine[PC0_VECTOR] = Halp21064PerformanceCounter0Interrupt; + PCR->InterruptRoutine[PC1_VECTOR] = Halp21064PerformanceCounter1Interrupt; + + return; + +} + + +BOOLEAN +Hal21064QueryProfileInterval( + IN KPROFILE_SOURCE Source + ) + +/*++ + +Routine Description: + + Given a profile source, returns whether or not that source is + supported. + +Arguments: + + Source - Supplies the profile source + +Return Value: + + TRUE - Profile source is supported + + FALSE - Profile source is not supported + +--*/ + +{ + if (Source > (sizeof(Halp21064ProfileMapping)/sizeof(HALP_PROFILE_MAPPING))) { + return(FALSE); + } + + return(Halp21064ProfileMapping[Source].Supported); +} + + +NTSTATUS +Hal21064SetProfileSourceInterval( + IN KPROFILE_SOURCE ProfileSource, + IN OUT ULONG *Interval + ) + +/*++ + +Routine Description: + + Sets the profile interval for a specified profile source + +Arguments: + + ProfileSource - Supplies the profile source + + Interval - Supplies the specified profile interval + Returns the actual profile interval + +Return Value: + + NTSTATUS + +--*/ + +{ + ULONG FastTickPeriod; + ULONG SlowTickPeriod; + ULONG TickPeriod; + ULONGLONG CountEvents; + ULONG FastCountEvents; + ULONG SlowCountEvents; + ULONGLONG TempInterval; + + if (!HalQueryProfileInterval(ProfileSource)) { + return(STATUS_NOT_IMPLEMENTED); + } + + if (ProfileSource == ProfileTime) { + + // + // Convert the clock tick period (in 100ns units ) into + // a cycle count period + // + + CountEvents = ((ULONGLONG)(*Interval) * 100000) / PCR->CycleClockPeriod; + } else if (ProfileSource == ProfileTotalIssues) { + + // + // Convert the total issue events into the wonky + // total issues/2 form implemented by EV4. + // + + CountEvents = (ULONGLONG)(*Interval / 2); + } else { + CountEvents = (ULONGLONG)*Interval; + } + + if (Halp21064ProfileMapping[ProfileSource].Counter == Ev4PerformanceCounter1) { + FastCountEvents = Ev4CountEvents2xx8; + SlowCountEvents = Ev4CountEvents2xx12; + } else { + FastCountEvents = Ev4CountEvents2xx12; + SlowCountEvents = Ev4CountEvents2xx16; + } + + // + // Limit the interval to the smallest interval we can time. + // + if (CountEvents < FastCountEvents) { + CountEvents = (ULONGLONG)FastCountEvents; + } + + // + // Assume we will use the fast event count + // + Halp21064ProfileMapping[ProfileSource].EventCount = FastCountEvents; + Halp21064ProfileMapping[ProfileSource].NumberOfTicks = + (ULONG)((CountEvents + FastCountEvents - 1) / FastCountEvents); + + // + // See if we can successfully use the slower period. If the requested + // interval is greater than the slower tick period and the difference + // between the requested interval and the interval that we can deliver + // with the slower clock is acceptable, then use the slower clock. + // We define an acceptable difference as a difference of less than + // INTERVAL_DELTA of the requested interval. + // + if (CountEvents > SlowCountEvents) { + ULONG NewInterval; + + NewInterval = (ULONG)(((CountEvents + SlowCountEvents-1) / + SlowCountEvents) * SlowCountEvents); + if (((NewInterval - CountEvents) * 100 / CountEvents) < INTERVAL_DELTA) { + Halp21064ProfileMapping[ProfileSource].EventCount = SlowCountEvents; + Halp21064ProfileMapping[ProfileSource].NumberOfTicks = NewInterval / SlowCountEvents; + } + } + + *Interval = Halp21064ProfileMapping[ProfileSource].EventCount * + Halp21064ProfileMapping[ProfileSource].NumberOfTicks; + + if (ProfileSource == ProfileTime) { + // + // Convert cycle count back into 100ns clock ticks + // + // Use 64-bit integer to prevent overflow. + // + TempInterval = (ULONGLONG)(*Interval) * (ULONGLONG)(PCR->CycleClockPeriod); + *Interval = (ULONG)(TempInterval / 100000); + } else if (ProfileSource == ProfileTotalIssues) { + // + // Convert issues/2 count back into issues + // + TempInterval = (ULONGLONG)(*Interval) * 2; + *Interval = (ULONG)TempInterval; + } + return(STATUS_SUCCESS); +} + + +ULONG +Hal21064SetProfileInterval ( + IN ULONG Interval + ) + +/*++ + +Routine Description: + + This routine sets the profile interrupt interval. + +Arguments: + + Interval - Supplies the desired profile interval in 100ns units. + +Return Value: + + The actual profile interval. + +--*/ + +{ + ULONG NewInterval; + + NewInterval = Interval; + HalSetProfileSourceInterval(ProfileTime, &NewInterval); + return(NewInterval); +} + + + +VOID +Hal21064StartProfileInterrupt ( + KPROFILE_SOURCE ProfileSource + ) + +/*++ + +Routine Description: + + This routine turns on the profile interrupt. + + N.B. This routine must be called at PROCLK_LEVEL while holding the + profile lock. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + ULONG PerformanceCounter; + ULONG MuxControl; + ULONG EventCount; + + // + // Check input to see if we are turning on a source that is + // supported. If it is unsupported, just return. + // + + if ((ProfileSource > (sizeof(Halp21064ProfileMapping)/sizeof(HALP_PROFILE_MAPPING))) || + (!Halp21064ProfileMapping[ProfileSource].Supported)) { + return; + } + + // + // Set the performance counter within the processor to begin + // counting total cycles. + // + PerformanceCounter = Halp21064ProfileMapping[ProfileSource].Counter; + MuxControl = Halp21064ProfileMapping[ProfileSource].MuxControl; + + if (PerformanceCounter == Ev4PerformanceCounter0) { + + Halp21064ProfileSource0 = ProfileSource; + EventCount = (Halp21064ProfileMapping[ProfileSource].EventCount == Ev4CountEvents2xx12) ? + Ev4EventCountHigh : + Ev4EventCountLow; + Halp21064WritePerformanceCounter( PerformanceCounter, + TRUE, + MuxControl, + EventCount ); + + PCRProfileCountReload[0] = Halp21064ProfileMapping[ProfileSource].NumberOfTicks; + PCRProfileCount[0] = Halp21064ProfileMapping[ProfileSource].NumberOfTicks; + + // + // Enable the performance counter interrupt. + // + + HalEnableSystemInterrupt ( PC0_VECTOR, + PROFILE_LEVEL, + LevelSensitive ); + + + } else { + + Halp21064ProfileSource1 = ProfileSource; + EventCount = (Halp21064ProfileMapping[ProfileSource].EventCount == Ev4CountEvents2xx12) ? + Ev4EventCountLow : + Ev4EventCountHigh; + Halp21064WritePerformanceCounter( PerformanceCounter, + TRUE, + MuxControl, + EventCount ); + + PCRProfileCountReload[1] = Halp21064ProfileMapping[ProfileSource].NumberOfTicks; + PCRProfileCount[1] = Halp21064ProfileMapping[ProfileSource].NumberOfTicks; + + // + // Enable the performance counter interrupt. + // + + HalEnableSystemInterrupt ( PC1_VECTOR, + PROFILE_LEVEL, + LevelSensitive ); + } + + return; +} + + +VOID +Hal21064StopProfileInterrupt ( + KPROFILE_SOURCE ProfileSource + ) + +/*++ + +Routine Description: + + This routine turns off the profile interrupt. + + N.B. This routine must be called at PROCLK_LEVEL while holding the + profile lock. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + ULONG PerformanceCounter; + ULONG Vector; + + // + // Check input to see if we are turning off a source that is + // supported. If it is unsupported, just return. + // + + if ((ProfileSource > (sizeof(Halp21064ProfileMapping)/sizeof(HALP_PROFILE_MAPPING))) || + (!Halp21064ProfileMapping[ProfileSource].Supported)) { + return; + } + + // + // Stop the performance counter from interrupting. + // + + PerformanceCounter = Halp21064ProfileMapping[ProfileSource].Counter; + Halp21064WritePerformanceCounter( PerformanceCounter, + FALSE, + 0, + 0 ); + + // + // Disable the performance counter interrupt. + // + if (PerformanceCounter == Ev4PerformanceCounter0) { + HalDisableSystemInterrupt( PC0_VECTOR, PROFILE_LEVEL ); + + // + // Clear the current profile count. Can't clear value in PCR + // since a profile interrupt could be pending or in progress + // so clear the reload counter. + // + + PCRProfileCountReload[0] = 0; + } else { + HalDisableSystemInterrupt( PC1_VECTOR, PROFILE_LEVEL ); + + // + // Clear the current profile count. Can't clear value in PCR + // since a profile interrupt could be pending or in progress + // so clear the reload counter. + // + + PCRProfileCountReload[0] = 0; + } + + return; +} + diff --git a/private/ntos/nthals/halflex/alpha/ev5ints.s b/private/ntos/nthals/halflex/alpha/ev5ints.s new file mode 100644 index 000000000..71319eb58 --- /dev/null +++ b/private/ntos/nthals/halflex/alpha/ev5ints.s @@ -0,0 +1,397 @@ +//++ +// +// Copyright (c) 1994 Microsoft Corporation +// +// Module Name: +// +// ev5ints.s +// +// Abstract: +// +// This module implements EV5-specific interrupt handlers. +// (the performance counters) +// +// Author: +// +// John Vert (jvert) 15-Nov-1994 +// Steve Brooks 14-Feb-1994 (modified from ev4ints.s) +// +// Environment: +// +// Kernel mode only. +// +// Revision History: +// +//-- +#include "halalpha.h" + +#define PC0_SECONDARY_VECTOR 11 +#define PC1_SECONDARY_VECTOR 13 +#define PC2_SECONDARY_VECTOR 16 // SjBfix. This is actually PC3_VECTOR +#define PcProfileCount0 PcHalReserved+20 +#define PcProfileCount1 PcProfileCount0+4 +#define PcProfileCount2 PcProfileCount1+4 +#define PcProfileCountReload0 PcProfileCount2+4 +#define PcProfileCountReload1 PcProfileCountReload0+4 +#define PcProfileCountReload2 PcProfileCountReload1+4 + + .struct 0 + .space 8 // reserved for alignment +PrRa: .space 8 // space for return address +PrFrameLength: // + + SBTTL("Performance Counter 0 Interrupt") +//++ +// +// VOID +// Halp21164PerformanceCounter0Interrupt +// ) +// +// Routine Description: +// +// This function is executed as the result of an interrupt from the +// internal microprocessor performance counter 0. The interrupt +// may be used to signal the completion of a profile event. +// If profiling is current active, the function determines if the +// profile interval has expired and if so dispatches to the standard +// system routine to update the system profile time. If profiling +// is not active then the function performs a secondary dispatch for +// performance counter 0. +// +// Arguments: +// +// TrapFrame (fp/s6) - Supplies a pointer to the trap frame for +// the interrupt. +// +// Return Value: +// +// TRUE is returned. +// +//-- + + NESTED_ENTRY(Halp21164PerformanceCounter0Interrupt, PrFrameLength, zero ) + + lda sp, -PrFrameLength(sp) // allocate a stack frame + stq ra, PrRa(sp) // save the return address + + PROLOGUE_END // + + call_pal rdpcr // v0 = pcr base address + + ldl t0, PcProfileCount0(v0) // capture the current profile count + beq t0, 20f // if eq, profiling not active + +// +// Profiling is active. Decrement the interval count and if it has +// reached zero then call the kernel profile routine. +// + + subl t0, 1, t0 // decrement the interval count + bne t0, 10f // if ne, interval has not expired + +// +// The profile interval has expired. Reset the profile interval count +// and process the profile interrupt. +// + + ldl t0, PcProfileCountReload0(v0) // get the new tick count + stl t0, PcProfileCount0(v0) // reset the profile interval count + + ldl a1, Halp21164ProfileSource0 + bis fp, zero, a0 // pass trap frame pointer + ldl t1, __imp_KeProfileInterruptWithSource + jsr ra, (t1) // process the profile interrupt + + br zero, 40f // common return + +// +// The profile interval has not expired. Update the decremented count. +// + +10: + stl t0, PcProfileCount0(v0) // update profile interval count + br zero, 40f // common return + +// +// Profiling is not active. Therefore, this interrupt was caused by +// a performance counter driver. Deliver a secondary dispatch. +// + +20: + + ldil a0, PC0_SECONDARY_VECTOR // get IDT vector for secondary + s4addl a0, v0, a0 // a0 = PCR + IDT index + ldl a0, PcInterruptRoutine(a0) // get service routine address + jsr ra, (a0) // call interrupt service routine + +// +// Setup for return. +// + +40: + ldil v0, TRUE // set return value = TRUE + ldq ra, PrRa(sp) // restore return address + lda sp, PrFrameLength(sp) // deallocate the stack frame + ret zero, (ra) // return + + .end Halp21164PerformanceCounter0Interrupt + + + SBTTL("Performance Counter 1 Interrupt") +//++ +// +// VOID +// Halp21164PerformanceCounter1Interrupt +// ) +// +// Routine Description: +// +// This function is executed as the result of an interrupt from the +// internal microprocessor performance counter 1. The interrupt +// may be used to signal the completion of a profile event. +// If profiling is current active, the function determines if the +// profile interval has expired and if so dispatches to the standard +// system routine to update the system profile time. If profiling +// is not active then the function performs a secondary dispatch for +// performance counter 1. +// +// Arguments: +// +// TrapFrame (fp/s6) - Supplies a pointer to the trap frame for +// the interrupt. +// +// Return Value: +// +// TRUE is returned. +// +//-- + + NESTED_ENTRY(Halp21164PerformanceCounter1Interrupt, PrFrameLength, zero ) + + lda sp, -PrFrameLength(sp) // allocate a stack frame + stq ra, PrRa(sp) // save the return address + + PROLOGUE_END // + + call_pal rdpcr // v0 = pcr base address + + ldl t0, PcProfileCount1(v0) // capture the current profile count + beq t0, 20f // if eq, profiling not active + +// +// Profiling is active. Decrement the interval count and if it has +// reached zero then call the kernel profile routine. +// + + subl t0, 1, t0 // decrement the interval count + bne t0, 10f // if ne, interval has not expired + +// +// The profile interval has expired. Reset the profile interval count +// and process the profile interrupt. +// + + ldl t0, PcProfileCountReload1(v0) // get the new tick count + stl t0, PcProfileCount1(v0) // reset the profile interval count + + ldl a1, Halp21164ProfileSource1 + bis fp, zero, a0 // pass trap frame pointer + ldl t1, __imp_KeProfileInterruptWithSource + jsr ra, (t1) // process the profile interrupt + + br zero, 40f // common return + +// +// The profile interval has not expired. Update the decremented count. +// + +10: + stl t0, PcProfileCount1(v0) // update profile interval count + br zero, 40f // common return + +// +// Profiling is not active. Therefore, this interrupt was caused by +// a performance counter driver. Deliver a secondary dispatch. +// + +20: + + ldil a0, PC1_SECONDARY_VECTOR // get IDT vector for secondary + s4addl a0, v0, a0 // a0 = PCR + IDT index + ldl a0, PcInterruptRoutine(a0) // get service routine address + jsr ra, (a0) // call interrupt service routine + +// +// Setup for return. +// + +40: + ldil v0, TRUE // set return value = TRUE + ldq ra, PrRa(sp) // restore return address + lda sp, PrFrameLength(sp) // deallocate the stack frame + ret zero, (ra) // return + + .end Halp21164PerformanceCounter1Interrupt + + SBTTL("Performance Counter 2 Interrupt") +//++ +// +// VOID +// Halp21164PerformanceCounter2Interrupt +// ) +// +// Routine Description: +// +// This function is executed as the result of an interrupt from the +// internal microprocessor performance counter 2. The interrupt +// may be used to signal the completion of a profile event. +// If profiling is current active, the function determines if the +// profile interval has expired and if so dispatches to the standard +// system routine to update the system profile time. If profiling +// is not active then the function performs a secondary dispatch for +// performance counter 2. +// +// Arguments: +// +// TrapFrame (fp/s6) - Supplies a pointer to the trap frame for +// the interrupt. +// +// Return Value: +// +// TRUE is returned. +// +//-- + + NESTED_ENTRY(Halp21164PerformanceCounter2Interrupt, PrFrameLength, zero ) + + lda sp, -PrFrameLength(sp) // allocate a stack frame + stq ra, PrRa(sp) // save the return address + + PROLOGUE_END // + + call_pal rdpcr // v0 = pcr base address + + ldl t0, PcProfileCount2(v0) // capture the current profile count + beq t0, 20f // if eq, profiling not active + +// +// Profiling is active. Decrement the interval count and if it has +// reached zero then call the kernel profile routine. +// + + subl t0, 1, t0 // decrement the interval count + bne t0, 10f // if ne, interval has not expired + +// +// The profile interval has expired. Reset the profile interval count +// and process the profile interrupt. +// + + ldl t0, PcProfileCountReload2(v0) // get the new tick count + stl t0, PcProfileCount2(v0) // reset the profile interval count + + ldl a1, Halp21164ProfileSource2 + bis fp, zero, a0 // pass trap frame pointer + ldl t1, __imp_KeProfileInterruptWithSource + jsr ra, (t1) // process the profile interrupt + + br zero, 40f // common return + +// +// The profile interval has not expired. Update the decremented count. +// + +10: + stl t0, PcProfileCount2(v0) // update profile interval count + br zero, 40f // common return + +// +// Profiling is not active. Therefore, this interrupt was caused by +// a performance counter driver. Deliver a secondary dispatch. +// + +20: + + ldil a0, PC2_SECONDARY_VECTOR // get IDT vector for secondary + s4addl a0, v0, a0 // a0 = PCR + IDT index + ldl a0, PcInterruptRoutine(a0) // get service routine address + jsr ra, (a0) // call interrupt service routine + +// +// Setup for return. +// + +40: + ldil v0, TRUE // set return value = TRUE + ldq ra, PrRa(sp) // restore return address + lda sp, PrFrameLength(sp) // deallocate the stack frame + ret zero, (ra) // return + + .end Halp21164PerformanceCounter2Interrupt + +//++ +// +// ULONGLONG +// HalpRead21164PerformanceCounter( +// VOID +// ) +// +// Routine Description: +// +// Read the processor performance counter register +// +// Arguments: +// +// None. +// +// Return Value: +// +// The current value of the performance counter register. +// +//-- + + LEAF_ENTRY(HalpRead21164PerformanceCounter) + + bis zero, 1, a1 // indicate read operation + call_pal wrperfmon // read the performance counter + + ret zero, (ra) // return to caller + + .end HalpRead21164PerformanceCounter + + +//++ +// +// VOID +// HalpWrite21164PerformanceCounter( +// ULONGLONG PmCtr +// ULONG CboxMux1 +// ULONG CboxMux2 +// ) +// +// Routine Description: +// +// Write the processor performance counter register +// +// Arguments: +// +// PmCtr(a0) - value to be written to the performance counter +// CboxMux1(a1) - value to be written to Cbox mux 1 select (optional) +// CboxMux2(a2) - value to be written to Cbox mux 2 select (optional) +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalpWrite21164PerformanceCounter) + + bis zero, a2, a3 // move arguments up + bis zero, a1, a2 // + bis zero, zero, a1 // indicate write operation + call_pal wrperfmon // write the performance counter + + ret zero, (ra) + + .end HalpWrite21164PerformanceCounter diff --git a/private/ntos/nthals/halflex/alpha/ev5prof.c b/private/ntos/nthals/halflex/alpha/ev5prof.c new file mode 100644 index 000000000..625fba304 --- /dev/null +++ b/private/ntos/nthals/halflex/alpha/ev5prof.c @@ -0,0 +1,747 @@ +/*++ + +Copyright (c) 1994 Digital Equipment Corporation + +Module Name: + + ev5prof.c + +Abstract: + + This module implements the Profile Counter using the performance + counters within the EV5 core. This module is appropriate for all + machines based on microprocessors using the EV5 core. + + N.B. - This module assumes that all processors in a multiprocessor + system are running the microprocessor at the same clock speed. + +Author: + + Steve Brooks 14-Feb-1995 (adapted from ev4prof.c) + +Environment: + + Kernel mode + +Revision History: + +--*/ + +#include "halp.h" +#include "axp21164.h" + +// +// Default Number of Profile Clock Ticks per sample +// + +ULONG Halp21164NumberOfTicks = 1; +ULONG Halp21164NumberOfTicksReload; + +// +// Define space in the HAL-reserved part of the PCR structure for each +// performance counter's interval count +// +// Note that ev5ints.s depends on these positions in the PCR. +// +#define PCRProfileCount ((PULONG)(HAL_21164_PCR->ProfileCount.ProfileCount)) +#define PCRProfileCountReload ((PULONG)(&HAL_21164_PCR->ProfileCount.ProfileCountReload)) + + +// +// Define the currently selected profile source for each counter +// +KPROFILE_SOURCE Halp21164ProfileSource0; +KPROFILE_SOURCE Halp21164ProfileSource1; +KPROFILE_SOURCE Halp21164ProfileSource2; + +#define INTERVAL_DELTA (10) + +// +// Define the mapping between possible profile sources and the +// CPU-specific settings. +// +typedef struct _HALP_PROFILE_MAPPING { + BOOLEAN Supported; + ULONG MuxControl; + ULONG Counter; + ULONG EventCount; + ULONG NumberOfTicks; +} HALP_PROFILE_MAPPING, *PHALP_PROFILE_MAPPING; + +HALP_PROFILE_MAPPING Halp21164ProfileMapping[ProfileMaximum] = +{ + {TRUE, Ev5Cycles, Ev5PerformanceCounter0, Ev5CountEvents2xx16, 10}, + {FALSE, 0,0,0,0}, + {TRUE, Ev5Instructions, Ev5PerformanceCounter0, Ev5CountEvents2xx16, 10}, + {TRUE, Ev5PipeDry, Ev5PerformanceCounter1, Ev5CountEvents2xx16, 10}, + {TRUE, Ev5LoadsIssued, Ev5PerformanceCounter1, Ev5CountEvents2xx16, 10}, + {FALSE, 0,0,0,0}, + {TRUE, Ev5AllFlowIssued, Ev5PerformanceCounter1, Ev5CountEvents2xx16, 10}, + {TRUE, Ev5NonIssue, Ev5PerformanceCounter1, Ev5CountEvents2xx16, 10}, + {TRUE, Ev5DcacheLDMisses, Ev5PerformanceCounter2, Ev5CountEvents2xx14, 10}, + {TRUE, Ev5IcacheRFBMisses, Ev5PerformanceCounter2, Ev5CountEvents2xx14, 10}, + {FALSE, 0,0,0,0}, + {TRUE, Ev5BRMispredicts, Ev5PerformanceCounter2, Ev5CountEvents2xx14, 10}, + {TRUE, Ev5StoresIssued, Ev5PerformanceCounter1, Ev5CountEvents2xx16, 10}, + {TRUE, Ev5FPOpsIssued, Ev5PerformanceCounter1, Ev5CountEvents2xx16, 10}, + {TRUE, Ev5IntOpsIssued, Ev5PerformanceCounter1, Ev5CountEvents2xx16, 10}, + {TRUE, Ev5DualIssue, Ev5PerformanceCounter1, Ev5CountEvents2xx16, 10}, + {TRUE, Ev5TripleIssue, Ev5PerformanceCounter1, Ev5CountEvents2xx16, 10}, + {TRUE, Ev5QuadIssue, Ev5PerformanceCounter1, Ev5CountEvents2xx16, 10}, + {FALSE, 0,0,0,0}, + {TRUE, Ev5Cycles, Ev5PerformanceCounter0, Ev5CountEvents2xx16, 10}, + {TRUE, Ev5IcacheIssued, Ev5PerformanceCounter1, Ev5CountEvents2xx16, 10}, + {TRUE, Ev5DcacheAccesses,Ev5PerformanceCounter1, Ev5CountEvents2xx16, 10}, + {TRUE, Ev5MBStallCycles, Ev5PerformanceCounter2, Ev5CountEvents2xx14, 10}, + {TRUE, Ev5LDxLInstIssued,Ev5PerformanceCounter2, Ev5CountEvents2xx14, 10} +}; + +BOOLEAN +HalQueryProfileInterval( + IN KPROFILE_SOURCE Source + ); + +NTSTATUS +HalSetProfileSourceInterval( + IN KPROFILE_SOURCE ProfileSource, + IN OUT ULONG *Interval + ); + +VOID +Halp21164UpdatePerformanceCounter( + IN ULONG PerformanceCounter, + IN ULONG MuxControl, + IN ULONG EventCount + ); + + +NTSTATUS +Halp21164ProfileSourceInformation ( + OUT PVOID Buffer, + IN ULONG BufferLength, + OUT PULONG ReturnedLength + ) +/*++ + +Routine Description: + + Returns the HAL_PROFILE_SOURCE_INFORMATION for this processor. + +Arguments: + + Buffer - output buffer + BufferLength - length of buffer on input + ReturnedLength - The length of data returned + +Return Value: + + STATUS_SUCCESS + STATUS_BUFFER_TOO_SMALL - The ReturnedLength contains the buffersize + currently needed. + +--*/ +{ + PHAL_PROFILE_SOURCE_INFORMATION SourceInfo; + NTSTATUS Status; + + + if (BufferLength != sizeof(HAL_PROFILE_SOURCE_INFORMATION)) { + Status = STATUS_INFO_LENGTH_MISMATCH; + return Status; + } + + SourceInfo = (PHAL_PROFILE_SOURCE_INFORMATION)Buffer; + SourceInfo->Supported = HalQueryProfileInterval(SourceInfo->Source); + + if (SourceInfo->Supported) { + SourceInfo->Interval = + Halp21164ProfileMapping[SourceInfo->Source].EventCount * + Halp21164ProfileMapping[SourceInfo->Source].NumberOfTicks; + } + + Status = STATUS_SUCCESS; + return Status; +} + +NTSTATUS +Halp21164ProfileSourceInterval ( + OUT PVOID Buffer, + IN ULONG BufferLength + ) +/*++ + +Routine Description: + + Returns the HAL_PROFILE_SOURCE_INTERVAL for this processor. + +Arguments: + + Buffer - output buffer + BufferLength - length of buffer on input + +Return Value: + + STATUS_SUCCESS + STATUS_BUFFER_TOO_SMALL - The ReturnedLength contains the buffersize + currently needed. + +--*/ +{ + PHAL_PROFILE_SOURCE_INTERVAL Interval; + NTSTATUS Status; + + + if (BufferLength != sizeof(HAL_PROFILE_SOURCE_INTERVAL)) { + Status = STATUS_INFO_LENGTH_MISMATCH; + return Status; + } + + Interval = (PHAL_PROFILE_SOURCE_INTERVAL)Buffer; + Status = HalSetProfileSourceInterval(Interval->Source, + &Interval->Interval); + return Status; +} + +VOID +Halp21164InitializeProfiler( + VOID + ) +/*++ + +Routine Description: + + This routine is called during initialization to initialize profiling + for each processor in the system. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + + // + // Establish the profile interrupt as the interrupt handler for + // all performance counter interrupts. + // + + PCR->InterruptRoutine[PC0_VECTOR] = Halp21164PerformanceCounter0Interrupt; + PCR->InterruptRoutine[PC1_VECTOR] = Halp21164PerformanceCounter1Interrupt; + PCR->InterruptRoutine[PC2_VECTOR] = Halp21164PerformanceCounter2Interrupt; + + return; + +} + + +BOOLEAN +Hal21164QueryProfileInterval( + IN KPROFILE_SOURCE Source + ) + +/*++ + +Routine Description: + + Given a profile source, returns whether or not that source is + supported. + +Arguments: + + Source - Supplies the profile source + +Return Value: + + TRUE - Profile source is supported + + FALSE - Profile source is not supported + +--*/ + +{ + if (Source > (sizeof(Halp21164ProfileMapping)/sizeof(HALP_PROFILE_MAPPING))) { + return(FALSE); + } + + return(Halp21164ProfileMapping[Source].Supported); +} + + +NTSTATUS +Hal21164SetProfileSourceInterval( + IN KPROFILE_SOURCE ProfileSource, + IN OUT ULONG *Interval + ) + +/*++ + +Routine Description: + + Sets the profile interval for a specified profile source + +Arguments: + + ProfileSource - Supplies the profile source + + Interval - Supplies the specified profile interval + Returns the actual profile interval + +Return Value: + + NTSTATUS + +--*/ + +{ + ULONG FastTickPeriod; + ULONG SlowTickPeriod; + ULONG TickPeriod; + ULONG FastCountEvents; + ULONG SlowCountEvents; + ULONGLONG CountEvents; + ULONGLONG TempInterval; + + if (!HalQueryProfileInterval(ProfileSource)) { + return(STATUS_NOT_IMPLEMENTED); + } + + if (ProfileSource == ProfileTime) { + + // + // Convert the clock tick period (in 100ns units ) into + // a cycle count period + // + + CountEvents = ((ULONGLONG)(*Interval) * 100000) / PCR->CycleClockPeriod; + } else { + CountEvents = (ULONGLONG)*Interval; + } + + FastCountEvents = Ev5CountEvents2xx8; + SlowCountEvents = Ev5CountEvents2xx16; + + if (Halp21164ProfileMapping[ProfileSource].Counter == Ev5PerformanceCounter0) { + FastCountEvents = Ev5CountEvents2xx16; + } + else if (Halp21164ProfileMapping[ProfileSource].Counter == Ev5PerformanceCounter2) { + SlowCountEvents = Ev5CountEvents2xx14; + } + + // + // Limit the interval to the smallest interval we can time. + // + if (CountEvents < FastCountEvents) { + CountEvents = (ULONGLONG)FastCountEvents; + } + + // + // Assume we will use the fast event count + // + Halp21164ProfileMapping[ProfileSource].EventCount = FastCountEvents; + Halp21164ProfileMapping[ProfileSource].NumberOfTicks = + (ULONG)((CountEvents + FastCountEvents - 1) / FastCountEvents); + + // + // See if we can successfully use the slower period. If the requested + // interval is greater than the slower tick period and the difference + // between the requested interval and the interval that we can deliver + // with the slower clock is acceptable, then use the slower clock. + // We define an acceptable difference as a difference of less than + // INTERVAL_DELTA of the requested interval. + // + if (CountEvents > SlowCountEvents) { + ULONG NewInterval; + + NewInterval = (ULONG)(((CountEvents + SlowCountEvents-1) / + SlowCountEvents) * SlowCountEvents); + if (((NewInterval - CountEvents) * 100 / CountEvents) < INTERVAL_DELTA) { + Halp21164ProfileMapping[ProfileSource].EventCount = SlowCountEvents; + Halp21164ProfileMapping[ProfileSource].NumberOfTicks = NewInterval / SlowCountEvents; + } + } + + *Interval = Halp21164ProfileMapping[ProfileSource].EventCount * + Halp21164ProfileMapping[ProfileSource].NumberOfTicks; + + if (ProfileSource == ProfileTime) { + // + // Convert cycle count back into 100ns clock ticks + // + // Use 64-bit integer to prevent overflow. + // + TempInterval = (ULONGLONG)(*Interval) * (ULONGLONG)(PCR->CycleClockPeriod); + *Interval = (ULONG)(TempInterval / 100000); + } + return(STATUS_SUCCESS); +} + + +ULONG +Hal21164SetProfileInterval ( + IN ULONG Interval + ) + +/*++ + +Routine Description: + + This routine sets the profile interrupt interval. + +Arguments: + + Interval - Supplies the desired profile interval in 100ns units. + +Return Value: + + The actual profile interval. + +--*/ + +{ + ULONG NewInterval; + + NewInterval = Interval; + HalSetProfileSourceInterval(ProfileTime, &NewInterval); + return(NewInterval); +} + + + +VOID +Hal21164StartProfileInterrupt ( + KPROFILE_SOURCE ProfileSource + ) + +/*++ + +Routine Description: + + This routine turns on the profile interrupt. + + N.B. This routine must be called at PROCLK_LEVEL while holding the + profile lock. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + ULONG PerformanceCounter; + ULONG MuxControl; + ULONG EventCount; + + // + // Check input to see if we are turning on a source that is + // supported. If it is unsupported, just return. + // + + if ((ProfileSource > (sizeof(Halp21164ProfileMapping)/sizeof(HALP_PROFILE_MAPPING))) || + (!Halp21164ProfileMapping[ProfileSource].Supported)) { + return; + } + + // + // Set the performance counter within the processor to begin + // counting total cycles. + // + PerformanceCounter = Halp21164ProfileMapping[ProfileSource].Counter; + MuxControl = Halp21164ProfileMapping[ProfileSource].MuxControl; + + if (PerformanceCounter == Ev5PerformanceCounter0) { + + EventCount = (Halp21164ProfileMapping[ProfileSource].EventCount == + Ev5CountEvents2xx16) ? Ev5EventCountLow + : Ev5EventCountHigh; + + Halp21164ProfileSource0 = ProfileSource; + Halp21164UpdatePerformanceCounter( PerformanceCounter, + MuxControl, + EventCount ); + + PCRProfileCountReload[0] = Halp21164ProfileMapping[ProfileSource].NumberOfTicks; + PCRProfileCount[0] = Halp21164ProfileMapping[ProfileSource].NumberOfTicks; + + // + // Enable the performance counter interrupt. + // + + HalEnableSystemInterrupt ( PC0_VECTOR, + PROFILE_LEVEL, + LevelSensitive ); + + + } else if (PerformanceCounter == Ev5PerformanceCounter1) { + + EventCount = (Halp21164ProfileMapping[ProfileSource].EventCount == + Ev5CountEvents2xx16) ? Ev5EventCountLow + : Ev5EventCountHigh; + + Halp21164ProfileSource1 = ProfileSource; + Halp21164UpdatePerformanceCounter( PerformanceCounter, + MuxControl, + EventCount ); + + PCRProfileCountReload[1] = Halp21164ProfileMapping[ProfileSource].NumberOfTicks; + PCRProfileCount[1] = Halp21164ProfileMapping[ProfileSource].NumberOfTicks; + + // + // Enable the performance counter interrupt. + // + + HalEnableSystemInterrupt ( PC1_VECTOR, + PROFILE_LEVEL, + LevelSensitive ); + + } else if (PerformanceCounter == Ev5PerformanceCounter2) { + + EventCount = (Halp21164ProfileMapping[ProfileSource].EventCount == + Ev5CountEvents2xx14) ? Ev5EventCountLow + : Ev5EventCountHigh; + + Halp21164ProfileSource2 = ProfileSource; + Halp21164UpdatePerformanceCounter( PerformanceCounter, + MuxControl, + EventCount ); + + PCRProfileCountReload[2] = Halp21164ProfileMapping[ProfileSource].NumberOfTicks; + PCRProfileCount[2] = Halp21164ProfileMapping[ProfileSource].NumberOfTicks; + + // + // Enable the performance counter interrupt. + // + + HalEnableSystemInterrupt ( PC2_VECTOR, + PROFILE_LEVEL, + LevelSensitive ); + } + + return; +} + + +VOID +Hal21164StopProfileInterrupt ( + KPROFILE_SOURCE ProfileSource + ) + +/*++ + +Routine Description: + + This routine turns off the profile interrupt. + + N.B. This routine must be called at PROCLK_LEVEL while holding the + profile lock. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + ULONG PerformanceCounter; + ULONG Vector; + + // + // Check input to see if we are turning off a source that is + // supported. If it is unsupported, just return. + // + + if ((ProfileSource > (sizeof(Halp21164ProfileMapping)/sizeof(HALP_PROFILE_MAPPING))) || + (!Halp21164ProfileMapping[ProfileSource].Supported)) { + return; + } + + // + // Stop the performance counter from interrupting. + // + + PerformanceCounter = Halp21164ProfileMapping[ProfileSource].Counter; + Halp21164UpdatePerformanceCounter( PerformanceCounter, + 0, + Ev5CounterDisable ); + + // + // Disable the performance counter interrupt. + // + if (PerformanceCounter == Ev5PerformanceCounter0) { + + HalDisableSystemInterrupt( PC0_VECTOR, PROFILE_LEVEL ); + + // + // Clear the current profile count. Can't clear value in PCR + // since a profile interrupt could be pending or in progress + // so clear the reload counter. + // + + PCRProfileCountReload[0] = 0; + + } else if (PerformanceCounter == Ev5PerformanceCounter1) { + + HalDisableSystemInterrupt( PC1_VECTOR, PROFILE_LEVEL ); + + // + // Clear the current profile count. Can't clear value in PCR + // since a profile interrupt could be pending or in progress + // so clear the reload counter. + // + + PCRProfileCountReload[1] = 0; + + } else if (PerformanceCounter == Ev5PerformanceCounter2) { + + HalDisableSystemInterrupt( PC2_VECTOR, PROFILE_LEVEL ); + + // + // Clear the current profile count. Can't clear value in PCR + // since a profile interrupt could be pending or in progress + // so clear the reload counter. + // + + PCRProfileCountReload[2] = 0; + } + + return; +} + + +VOID +Halp21164UpdatePerformanceCounter( + IN ULONG PerformanceCounter, + IN ULONG MuxControl, + IN ULONG EventCount + ) +//++ +// +// Routine Description: +// +// Write the specified microprocessor internal performance counter. +// +// Arguments: +// +// PerformanceCounter(a0) - Supplies the number of the performance counter +// to write. +// +// MuxControl(a2) - Supplies the mux control value which selects which +// type of event to count when the counter is enabled. +// +// EventCount(a3) - Supplies the event interval when the counter is +// enabled. +// +// Return Value: +// +// None. +// +//-- + +{ + PMCTR_21164 PmCtr; // the performance counter register + ULONG CboxMux1 = 0; // CBOX select 1 mux value + ULONG CboxMux2 = 0; // CBOX select 2 mux value + + PmCtr.all = HalpRead21164PerformanceCounter(); + + // + // Check for special values first: + // + + if ( MuxControl >= Ev5PcSpecial ) { + + switch( MuxControl ) { + + // + // Count JsrRet Issued + // + + case Ev5JsrRetIssued: + + PmCtr.Ctl1 = EventCount; + PmCtr.Sel1 = Ev5FlowChangeInst; + PmCtr.Sel2 = Ev5PCMispredicts; + break; + + // + // Count CondBr Issued + // + + case Ev5CondBrIssued: + + PmCtr.Ctl1 = EventCount; + PmCtr.Sel1 = Ev5FlowChangeInst; + PmCtr.Sel2 = Ev5BRMispredicts; + break; + + // + // Count all flow change inst Issued + // + + case Ev5AllFlowIssued: + + PmCtr.Ctl1 = EventCount; + PmCtr.Sel1 = Ev5FlowChangeInst; + + if ( (PmCtr.Sel2 == Ev5PCMispredicts) || + (PmCtr.Sel2 == Ev5BRMispredicts)) { + + PmCtr.Sel2 = Ev5LongStalls; + + } + break; + + // + // Must be an Scache counter. Select the appropriate counter + // in Sel1 or Sel2, and pass the CBOX mux value to WritePerfCounter + // + + default: + + if ( MuxControl <= Ev5ScSystemCmdReq ) { + + PmCtr.Ctl1 = EventCount; + PmCtr.Sel1 = Ev5CBOXInput1; + CboxMux1 = MuxControl - Ev5ScMux1; + + } else if ( MuxControl <= Ev5ScSysReadReq ) { + + PmCtr.Ctl2 = EventCount; + PmCtr.Sel2 = Ev5CBOXInput2; + CboxMux2 = MuxControl - Ev5ScMux2; + + } + + } // switch + + } else if ( PerformanceCounter == Ev5PerformanceCounter0 ) { + + PmCtr.Ctl0 = EventCount; + PmCtr.Sel0 = MuxControl; + + } else if ( PerformanceCounter == Ev5PerformanceCounter1 ) { + + PmCtr.Ctl1 = EventCount; + PmCtr.Sel1 = MuxControl; + + } else if ( PerformanceCounter == Ev5PerformanceCounter2 ) { + + PmCtr.Ctl2 = EventCount; + PmCtr.Sel2 = MuxControl; + + } + + HalpWrite21164PerformanceCounter(PmCtr.all, CboxMux1, CboxMux2); +} diff --git a/private/ntos/nthals/halflex/alpha/evclock.s b/private/ntos/nthals/halflex/alpha/evclock.s new file mode 100644 index 000000000..aaaf6cd27 --- /dev/null +++ b/private/ntos/nthals/halflex/alpha/evclock.s @@ -0,0 +1,119 @@ +//++ +// +// Copyright (c) 1993 Digital Equipment Corporation +// +// Module Name: +// +// intsup.s +// +// Abstract: +// +// This module implements first level interrupt handlers. +// +// Author: +// +// Joe Notarangelo 08-Jul-1993 +// +// Environment: +// +// Kernel mode only. +// +// Revision History: +// +// 24-Sep-93 Joe Notarangelo +// Make this module platform-independent. +//-- + +#include "halalpha.h" + + SBTTL("System Clock Interrupt") +//++ +// +// VOID +// HalpClockInterrupt( +// ) +// +// Routine Description: +// +// This function is executed for each interval timer interrupt on +// the primary processor. The routine is responsible for acknowledging the +// interrupt and calling the kernel to update the system time. +// In addition, this routine checks for breakins from the kernel debugger +// and maintains the 64 bit performance counter based upon the +// processor cycle counter. +// +// Arguments: +// +// TrapFrame (fp/s6) - Supplies a pointer to the trap frame for +// the interrupt. +// +// Return Value: +// +// None. +// +//-- + + .struct 0 + .space 8 // filler for octaword alignment +CiRa: .space 8 // space for return address +CiFrameLength: // + + NESTED_ENTRY(HalpClockInterrupt, CiFrameLength, zero ) + + lda sp, -CiFrameLength(sp) // allocate stack frame + stq ra, CiRa(sp) // save return address + + PROLOGUE_END + +// +// Call the kernel to update the system time. +// + ldl a1, HalpCurrentTimeIncrement // Get current time increment + bis fp, zero, a0 // a0 = pointer to trap frame + ldl t0, __imp_KeUpdateSystemTime + jsr ra, (t0) // call kernel + + ldl t0, HalpNextTimeIncrement // Get next time increment + stl t0, HalpCurrentTimeIncrement // Set CurrentTimeIncrement to NextTimeIncrement + ldl a0, HalpNextIntervalCount // Get next interval count. If 0, then no change required. + beq a0, 10f // See if time increment is to be changed + bsr ra, HalpProgramIntervalTimer // Program timer with new rate select + ldl t0, HalpNewTimeIncrement // Get HalpNewTimeIncrement + stl t0, HalpNextTimeIncrement // Set HalpNextTimeIncrement to HalpNewTimeIncrement + stl zero, HalpNextIntervalCount // Set HalpNextIntervalCount to 0 + +// +// Call to handle performance counter wrap. +// +10: + bsr ra, HalpCheckPerformanceCounter // check for perf. counter wrap + +#if DEVL + +// +// Check for a breakin request from the kernel debugger. +// + + ldl t0, __imp_KdPollBreakIn + jsr ra, (t0) // check for breakin requested + beq v0, 30f // if eq[false], no breakin + ldl t0, __imp_DbgBreakPointWithStatus + lda a0, DBG_STATUS_CONTROL_C + jsr ra, (t0) // send status to debugger + +30: + +#endif //DEVL + +// +// Return to the caller. +// + + ldq ra, CiRa(sp) // restore return address + lda sp, CiFrameLength(sp) // deallocate stack frame + ret zero, (ra) // return to caller + + .end HalpClockInterrupt + + + diff --git a/private/ntos/nthals/halflex/alpha/evxcache.c b/private/ntos/nthals/halflex/alpha/evxcache.c new file mode 100644 index 000000000..12237a517 --- /dev/null +++ b/private/ntos/nthals/halflex/alpha/evxcache.c @@ -0,0 +1,823 @@ +/*++ + +Copyright (c) 1992, 1993 Digital Equipment Corporation + +Module Name: + + ev4cache.c + +Abstract: + + This file contains the routines for managing the caches on machines + based on the DECchip 21064 microprocessor. + + EV4 has primary I and D caches of 8KB each, both write-through. + Any systems based on EV4 are expected to have an external backup cache + which is write-back, but it is also coherent with all DMA operations. The + primary caches are shadowed by the backup, and on a write hit, the + primary data (but not instruction) cache is invalidated. + Consequently, the routines to flush,sweep,purge,etc the data + stream are nops on EV4, but the corresponding routines for the + Istream must ensure that we cannot hit in the primary I cache + after a DMA operation. + + EV4 has a write buffer which contains 4 32-byte entries, which + must be flushable before DMA operations. The MB instruction is + used to accomplish this. + + There is no coloring support on EV4, so Color operations are + null. Zero page is unsupported because it has no users. Copy + page is not special because we lack coloring. + + We had to make a philosophical decision about what interfaces to + support in this file. (Almost) none of the interfaces defined in + the HAL spec are actually supported in either the i386 or MIPS + code. The i386 stream has almost no cache support at all. The + Mips stream has cache support, but most routines also refer to + coloring. Should we use the Spec'ed interfaces, or the Mips + interfaces? I have elected the Mips interfaces because they are + in use, and we are stealing much of the Mips code which expects + these interfaces. Besides, the only change we might make is to + remove the coloring arguments, but they may be used on Alpha + machines at some future date. + +Author: + + Miche Baker-Harvey (miche) 29-May-1992 + +Revision History: + + + 13-Jul-1992 Jeff McLeman (mcleman) + use HalpMb to do a memory barrier. Also, alter code and use super + pages to pass to rtl memory routines. + + 10-Jul-1992 Jeff McLeman (mcleman) + use HalpImb to call pal. + + 06-Jul-1992 Jeff McLeman (mcleman) + Move routine KeFlushDcache into this module. + Use only one memory barrier in the KeFlushWriteBuffer + routine. This is because the PAL for the EVx will + make sure the proper write ordering is done in PAL mode. + +--*/ + // Include files + +#include "halp.h" + + + +VOID +HalFlushDcache ( + IN BOOLEAN AllProcessors + ); + +// +// Cache and write buffer flush functions. +// + + +VOID +HalChangeColorPage ( + IN PVOID NewColor, + IN PVOID OldColor, + IN ULONG PageFrame + ) +/*++ + +Routine Description: + + This function changes the color of a page if the old and new colors + do not match. DECchip 21064-based machines do not have page coloring, and + therefore, this function performs no operation. + +Arguments: + + NewColor - Supplies the page aligned virtual address of the + new color of the page to change. + + OldColor - Supplies the page aligned virtual address of the + old color of the page to change. + + pageFrame - Supplies the page frame number of the page that + is changed. + +Return Value: + + None. + +--*/ +{ + return; +} + +VOID +HalFlushDcachePage ( + IN PVOID Color, + IN ULONG PageFrame, + IN ULONG Length + ) +/*++ + +Routine Description: + + This function flushes (invalidates) up to a page of data from the + data cache. + +Arguments: + + Color - Supplies the starting virtual address and color of the + data that is flushed. + PageFrame - Supplies the page frame number of the page that + is flushed. + + Length - Supplies the length of the region in the page that is + flushed. + +Return Value: + + None. + +--*/ +{ + return; +} + +VOID +HalFlushIoBuffers ( + IN PMDL Mdl, + IN BOOLEAN ReadOperation, + IN BOOLEAN DmaOperation + ) +/*++ +Routine Description: + + This function flushes the I/O buffer specified by the memory descriptor + list from the data cache on the current processor. + +Arguments: + + Mdl - Supplies a pointer to a memory descriptor list that describes the + I/O buffer location. + + ReadOperation - Supplies a boolean value that determines whether the I/O + operation is a read into memory. + + DmaOperation - Supplies a boolean value that determines whether the I/O + operation is a DMA operation. + +Return Value: + + None. + +--*/ +{ + ULONG CacheSegment; + ULONG Length; + ULONG Offset; + PULONG PageFrame; + ULONG Address; + volatile ULONG i; + volatile ULONG j; + + if (DmaOperation!=FALSE) { + + HalpMb(); // force all previous writes off chip + + Offset = Mdl->ByteOffset; + Length = Mdl->ByteCount; + PageFrame = (PULONG)(Mdl + 1); + + // + // Export or purge the specified page segments from the data and + // instruction caches as appropriate. + // + + do { + if (Length >= (PAGE_SIZE - Offset)) { + CacheSegment = PAGE_SIZE - Offset; + } else { + CacheSegment = Length; + } + + if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) { + + if (HalpModuleHardwareFlushing) { + + Address = *PageFrame << PAGE_SHIFT; + if (Address & 0x2000) { + HalpWriteAbsoluteUlong(0xfffffce9,0x00000010,(Address >> 14) & 0xffff); + } else { + HalpWriteAbsoluteUlong(0xfffffce8,0x00000010,(Address >> 14) & 0xffff); + } + + } else { + + Address = (*PageFrame << PAGE_SHIFT) & 0x001fffff; + for(i=0;i>21)&0x1ff)<<8); + HalpWriteAbsoluteUlong(0xfffffc03,0x00000004,((Address>>13)&0xff)<<9); + HalpReadAbsoluteUlong(0xfffffc03,0x00000000); + + } else { + + Address = (*PageFrame << PAGE_SHIFT) & 0x0007ffff; + for(i=0;iMdlFlags & MDL_IO_PAGE_READ) { + + // + // The operation is a page read, thus the istream must + // be flushed. + // + HalpImb(); + } + } + } +} + +VOID +HalpCleanIoBuffers ( + IN PMDL Mdl, + IN BOOLEAN ReadOperation, + IN BOOLEAN DmaOperation + ) +/*++ +Routine Description: + + This function flushes the I/O buffer specified by the memory descriptor + list from the data cache on the current processor. + +Arguments: + + Mdl - Supplies a pointer to a memory descriptor list that describes the + I/O buffer location. + + ReadOperation - Supplies a boolean value that determines whether the I/O + operation is a read into memory. + + DmaOperation - Supplies a boolean value that determines whether the I/O + operation is a DMA operation. + +Return Value: + + None. + +--*/ +{ + ULONG CacheSegment; + ULONG Length; + ULONG Offset; + PULONG PageFrame; + ULONG Address; + volatile ULONG i; + volatile ULONG j; + +// // +// // If this is an EV4 or an EV45, then do nothing on the backend of DMA operations +// // +// +// if (HalpIoArchitectureType != EV5_PROCESSOR_MODULE) { +// return; +// } + + if (DmaOperation!=FALSE) { + + HalpMb(); // force all previous writes off chip + + Offset = Mdl->ByteOffset; + Length = Mdl->ByteCount; + PageFrame = (PULONG)(Mdl + 1); + + // + // Export or purge the specified page segments from the data and + // instruction caches as appropriate. + // + + do { + if (Length >= (PAGE_SIZE - Offset)) { + CacheSegment = PAGE_SIZE - Offset; + } else { + CacheSegment = Length; + } + + if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) { + + if (HalpModuleHardwareFlushing) { + + Address = *PageFrame << PAGE_SHIFT; + if (Address & 0x2000) { + HalpWriteAbsoluteUlong(0xfffffce9,0x00000010,(Address >> 14) & 0xffff); + } else { + HalpWriteAbsoluteUlong(0xfffffce8,0x00000010,(Address >> 14) & 0xffff); + } + + } else { + + Address = (*PageFrame << PAGE_SHIFT) & 0x001fffff; + for(i=0;i>21)&0x1ff)<<8); + HalpWriteAbsoluteUlong(0xfffffc03,0x00000004,((Address>>13)&0xff)<<9); + HalpReadAbsoluteUlong(0xfffffc03,0x00000000); + + } else { + + Address = (*PageFrame << PAGE_SHIFT) & 0x0007ffff; + for(i=0;iMdlFlags & MDL_IO_PAGE_READ) { + + // + // The operation is a page read, thus the istream must + // be flushed. + // + HalpImb(); + } + } +} + + +VOID +HalpGoodCleanIoBuffers ( + IN PMDL Mdl, + IN BOOLEAN ReadOperation, + IN BOOLEAN DmaOperation + ) +/*++ +Routine Description: + + This function flushes the I/O buffer specified by the memory descriptor + list from the data cache on the current processor. + +Arguments: + + Mdl - Supplies a pointer to a memory descriptor list that describes the + I/O buffer location. + + ReadOperation - Supplies a boolean value that determines whether the I/O + operation is a read into memory. + + DmaOperation - Supplies a boolean value that determines whether the I/O + operation is a DMA operation. + +Return Value: + + None. + +--*/ +{ + ULONG CacheSegment; + ULONG Length; + ULONG Offset; + PULONG PageFrame; + ULONG Address; + volatile ULONG i; + volatile ULONG j; + + if (DmaOperation!=FALSE) { + + HalpMb(); // force all previous writes off chip + + Offset = Mdl->ByteOffset; + Length = Mdl->ByteCount; + PageFrame = (PULONG)(Mdl + 1); + + // + // Export or purge the specified page segments from the data and + // instruction caches as appropriate. + // + + do { + if (Length >= (PAGE_SIZE - Offset)) { + CacheSegment = PAGE_SIZE - Offset; + } else { + CacheSegment = Length; + } + + if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) { + + Address = ((*PageFrame << PAGE_SHIFT) + Offset) & 0x001fffc0; + j = *(volatile ULONG *)((ULONG)HalpCacheFlushBase+Address); + Address = ((*PageFrame << PAGE_SHIFT) + Offset + 0x40) & 0x001fffc0; + j = *(volatile ULONG *)((ULONG)HalpCacheFlushBase+Address); + Address = ((*PageFrame << PAGE_SHIFT) + CacheSegment - 1) & 0x001fffc0; + j = *(volatile ULONG *)((ULONG)HalpCacheFlushBase+Address); + + } else { + + Address = ((*PageFrame << PAGE_SHIFT) + Offset) & 0x000fffe0; + j = *(volatile ULONG *)((ULONG)HalpCacheFlushBase+Address); + Address = ((*PageFrame << PAGE_SHIFT) + CacheSegment - 1) & 0x000fffe0; + j = *(volatile ULONG *)((ULONG)HalpCacheFlushBase+Address); + } + + PageFrame += 1; + Length -= CacheSegment; + Offset = 0; + } while(Length != 0); + } + + // + // The Dcache coherency is maintained in hardware. The Icache coherency + // is maintained by invalidating the istream on page read operations. + // + HalpMb(); // synchronize this processors view of memory + if (ReadOperation) { + HalpMb(); // not issued until previous mb completes + if (Mdl->MdlFlags & MDL_IO_PAGE_READ) { + + // + // The operation is a page read, thus the istream must + // be flushed. + // + HalpImb(); + } + } +} + + + +VOID +HalPurgeDcachePage ( + IN PVOID Color, + IN ULONG PageFrame, + IN ULONG Length + ) +/*++ +Routine Description: + + This function purges (invalidates) up to a page of data from the + data cache. + +Arguments: + + Color - Supplies the starting virtual address and color of the + data that is purged. + + PageFrame - Supplies the page frame number of the page that + is purged. + + Length - Supplies the length of the region in the page that is + purged. + +Return Value: + + None. + +--*/ +{ + return; +} + + +VOID +HalPurgeIcachePage ( + IN PVOID Color, + IN ULONG PageFrame, + IN ULONG Length + ) +/*++ + +Routine Description: + + This function purges (invalidates) up to a page fo data from the + instruction cache. + +Arguments: + + Color - Supplies the starting virtual address and color of the + data that is purged. + + PageFrame - Supplies the page frame number of the page that + is purged. + + Length - Supplies the length of the region in the page that is + purged. + +Return Value: + + None. + +--*/ +{ + // + // The call to HalpImb calls PAL to flush the Icache, which ensures that + // any stale hits will be invalidated + // + HalpImb; +} + +VOID +HalSweepDcache ( + VOID + ) +/*++ + +Routine Description: + + This function sweeps (invalidates) the entire data cache. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + return; +} + +VOID +HalSweepDcacheRange ( + IN PVOID BaseAddress, + IN ULONG Length + ) +/*++ + +Routine Description: + + This function flushes the specified range of addresses from the data + cache on the current processor. + +Arguments: + + BaseAddress - Supplies the starting physical address of a range of + physical addresses that are to be flushed from the data cache. + + Length - Supplies the length of the range of physical addresses + that are to be flushed from the data cache. + +Return Value: + + None. + +--*/ +{ + return; +} + +VOID +HalSweepIcache ( + VOID + ) +/*++ + +Routine Description: + + This function sweeps (invalidates) the entire instruction cache. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + // + // The call to HalpImb calls PAL to flush the Icache, which ensures that + // any stale hits will be invalidated + // + HalpImb; + return; +} + +VOID +HalSweepIcacheRange ( + IN PVOID BaseAddress, + IN ULONG Length + ) +/*++ + +Routine Description: + + This function flushes the specified range of addresses from the + instruction cache on the current processor. + +Arguments: + + BaseAddress - Supplies the starting physical address of a range of + physical addresses that are to be flushed from the instruction cache. + + Length - Supplies the length of the range of physical addresses + that are to be flushed from the instruction cache. + +Return Value: + + None. + +--*/ +{ + // + // The call to HalpImb calls PAL to flush the Icache, which ensures that + // any stale hits will be invalidated + // + HalpImb; + +} + +VOID +KeFlushWriteBuffer ( + VOID + ) + +{ + // + // We flush the write buffer by doing a series of memory + // barrier operations. It still isn't clear if we need + // to do two/four of them to flush the buffer, or if one + // to order the writes is suffcient + // + + HalpMb; + return; +} + +VOID +KeFlushDcache ( + IN BOOLEAN AllProcessors, + IN PVOID BaseAddress OPTIONAL, + IN ULONG Length + ) + +/*++ + +Routine Description: + + This function flushes the data cache on all processors that are currently + running threads which are children of the current process or flushes the + data cache on all processors in the host configuration. + +Arguments: + + AllProcessors - Supplies a boolean value that determines which data + caches are flushed. + +Return Value: + + None. + +--*/ + +{ + UNREFERENCED_PARAMETER(BaseAddress); + UNREFERENCED_PARAMETER(Length); + + HalFlushDcache(AllProcessors); + return; +} + +VOID +HalFlushDcache ( + IN BOOLEAN AllProcessors + ) + +/*++ + +Routine Description: + + This function flushes the data cache on all processors that are currently + running threads which are children of the current process or flushes the + data cache on all processors in the host configuration. + +Arguments: + + AllProcessors - Supplies a boolean value that determines which data + caches are flushed. + +Return Value: + + None. + +--*/ + +{ + + // + // Sweep (index/writeback/invalidate) the data cache. + // + + HalSweepDcache(); + return; +} + +ULONG +HalGetDmaAlignmentRequirement ( + VOID + ) + +/*++ + +Routine Description: + + This function returns the alignment requirements for DMA transfers on + host system. + +Arguments: + + None. + +Return Value: + + The DMA alignment requirement is returned as the fucntion value. + +--*/ + +{ +// if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) { +// return 0x40; +// } else { +// return 0x20; +// } + + // + // Checked builds will not run with an alignment other than 0x08. It generated assertions + // when buffers are not aligned correctly and this sometimes happens on the ALPHA builds. + // However, SCSI Tape device will not work unless the alignment value is correct. So, + // for right now SCSI Tape devices can not be used with a checked build. + // + // Free builds do not have the assertions for unaligned buffers, so we can set the + // alignment value to the systems actual cache line size. This means that SCSI Tape + // devices will work with a free build and a free HAL. + // + +#ifdef DEBUG + return 0x08; +#else + return 0x40; +#endif +} diff --git a/private/ntos/nthals/halflex/alpha/evxmem.s b/private/ntos/nthals/halflex/alpha/evxmem.s new file mode 100644 index 000000000..532a67b6a --- /dev/null +++ b/private/ntos/nthals/halflex/alpha/evxmem.s @@ -0,0 +1,231 @@ +// TITLE("EV4 Memory Operations") +//++ +// +// Copyright (C) 1994,1995 Digital Equipment Corporation +// +// Module Name: +// +// ev4mem.s +// +// Abstract: +// +// This module implements EV4 memory operations that require assembly +// language. +// +// Environment: +// +// HAL, Kernel mode only. +// +// +// +//-- + +#include "ksalpha.h" + +#define ZERO_BLOCK_SIZE (256) +#define ZERO_LOOPS (PAGE_SIZE/ZERO_BLOCK_SIZE) + +//++ +// +// VOID +// HalEV4ZeroPage ( +// IN PVOID NewColor, +// IN PVOID OldColor, +// IN ULONG PageFrame +// ) +// +// Routine Description: +// +// This function zeros a page of memory. +// +// Arguments: +// +// NewColor (a0) - Supplies the page aligned virtual address of the +// new color of the page that is zeroed. +// +// OldColor (a1) - Supplies the page aligned virtual address of the +// old color of the page that is zeroed. +// +// PageFrame (a2) - Supplies the page frame number of the page that +// is zeroed. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalZeroPage) + + ldl t0, HalpIoArchitectureType + beq t0, HalpEV5ZeroPage + +HalpEV4ZeroPage: + + .set noreorder // hand scheduled + +// +// Map the page via the 43-bit super-page on EV4. +// + + ldiq t0, -0x4000 // 0xffff ffff ffff c000 + sll a2, PAGE_SHIFT, t1 // physical address of page + + sll t0, 28, t0 // 0xffff fc00 0000 0000 + ldil t2, ZERO_LOOPS // set count of loops to run + + bis t0, t1, t0 // set super-page enable + physical + bis zero, zero, zero // for branch alignment + +// +// Zero the page in a loop, zeroing 256 bytes per iteration. This number +// was chosen to tradeoff loop overhead versus the overhead of fetching +// Icache blocks. +// + +10: + stq zero, 0x00(t0) // + subl t2, 1, t2 // decrement the loop count + + stq zero, 0x08(t0) // + stt f31, 0x10(t0) // + + stq zero, 0x18(t0) // + stt f31, 0x20(t0) // + + stq zero, 0x28(t0) // + stt f31, 0x30(t0) // + + stq zero, 0x38(t0) // + stt f31, 0x40(t0) // + + stq zero, 0x48(t0) // + stt f31, 0x50(t0) // + + stq zero, 0x58(t0) // + stt f31, 0x60(t0) // + + stq zero, 0x68(t0) // + stt f31, 0x70(t0) // + + stq zero, 0x78(t0) // + stt f31, 0x80(t0) // + + stq zero, 0x88(t0) // + stt f31, 0x90(t0) // + + stq zero, 0x98(t0) // + stt f31, 0xa0(t0) // + + stq zero, 0xa8(t0) // + stt f31, 0xb0(t0) // + + bis t0, zero, t1 // copy base register + stq zero, 0xb8(t0) // + + stq zero, 0xc0(t0) // + stt f31, 0xc8(t0) // + + stq zero, 0xd0(t0) // + stt f31, 0xd8(t0) // + + stq zero, 0xe0(t0) // + lda t0, 0x100(t0) // increment to next block + + stq zero, 0xe8(t1) // + stt f31, 0xf0(t1) // + + stt f31, 0xf8(t1) // use stt for dual issue with bne + bne t2, 10b // while count > 0 + + ret zero, (ra) // return + + + .set reorder // + +HalpEV5ZeroPage: + + .set noreorder // hand scheduled + +// +// Map the page via the 43-bit super-page on EV5. +// + + ldiq t0, -0x4000 // 0xffff ffff ffff c000 + sll a2, PAGE_SHIFT, t1 // physical address of page + + sll t0, 28, t0 // 0xffff fc00 0000 0000 + ldil t2, ZERO_LOOPS // set count of loops to run + + bis t0, t1, t0 // set super-page enable + physical + br zero, 10f // start the zeroing + +// +// Zero the page in a loop, zeroing 256 bytes per iteration. This number +// was chosen to tradeoff loop overhead versus the overhead of fetching +// Icache blocks. +// + + .align 4 // align as branch target +10: + stq zero, 0x00(t0) // + subl t2, 1, t2 // decrement the loop count + + stq zero, 0x08(t0) // + stq zero, 0x10(t0) // + + stq zero, 0x18(t0) // + stq zero, 0x20(t0) // + + stq zero, 0x28(t0) // + stq zero, 0x30(t0) // + + stq zero, 0x38(t0) // + stq zero, 0x40(t0) // + + stq zero, 0x48(t0) // + stq zero, 0x50(t0) // + + stq zero, 0x58(t0) // + stq zero, 0x60(t0) // + + stq zero, 0x68(t0) // + stq zero, 0x70(t0) // + + stq zero, 0x78(t0) // + stq zero, 0x80(t0) // + + stq zero, 0x88(t0) // + stq zero, 0x90(t0) // + + stq zero, 0x98(t0) // + stq zero, 0xa0(t0) // + + stq zero, 0xa8(t0) // + stq zero, 0xb0(t0) // + + stq zero, 0xb8(t0) // + bis t0, zero, t1 // copy base register + + stq zero, 0xc0(t0) // + stq zero, 0xc8(t0) // + + stq zero, 0xd0(t0) // + stq zero, 0xd8(t0) // + + stq zero, 0xe0(t0) // + lda t0, 0x100(t0) // increment to next block + + stq zero, 0xe8(t1) // + stq zero, 0xf0(t1) // + + stq zero, 0xf8(t1) // use stt for dual issue with bne + bne t2, 10b // while count > 0 + + ret zero, (ra) // return + + + .set reorder // + + .end HalZeroPage + diff --git a/private/ntos/nthals/halflex/alpha/evxprof.c b/private/ntos/nthals/halflex/alpha/evxprof.c new file mode 100644 index 000000000..4e296e5fc --- /dev/null +++ b/private/ntos/nthals/halflex/alpha/evxprof.c @@ -0,0 +1,342 @@ +/*++ + +Copyright (c) 1994 Digital Equipment Corporation + +Module Name: + + evxprof.c + +Abstract: + + This module implements the Profile Counter using the performance + counters within the EV5 core. This module is appropriate for all + machines based on microprocessors using the EV5 core. + + N.B. - This module assumes that all processors in a multiprocessor + system are running the microprocessor at the same clock speed. + +Author: + + Michael D. Kinney 14-Aug-1995 + +Environment: + + Kernel mode + +Revision History: + +--*/ + +#include "halp.h" + +BOOLEAN +Hal21064QueryProfileInterval( + IN KPROFILE_SOURCE Source + ); + +BOOLEAN +Hal21164QueryProfileInterval( + IN KPROFILE_SOURCE Source + ); + +NTSTATUS +Hal21064SetProfileSourceInterval( + IN KPROFILE_SOURCE ProfileSource, + IN OUT ULONG *Interval + ); + +NTSTATUS +Hal21164SetProfileSourceInterval( + IN KPROFILE_SOURCE ProfileSource, + IN OUT ULONG *Interval + ); + +ULONG +Hal21064SetProfileInterval ( + IN ULONG Interval + ); + +ULONG +Hal21164SetProfileInterval ( + IN ULONG Interval + ); + +VOID +Hal21064StartProfileInterrupt ( + KPROFILE_SOURCE ProfileSource + ); + +VOID +Hal21164StartProfileInterrupt ( + KPROFILE_SOURCE ProfileSource + ); + +VOID +Hal21064StopProfileInterrupt ( + KPROFILE_SOURCE ProfileSource + ); + +VOID +Hal21164StopProfileInterrupt ( + KPROFILE_SOURCE ProfileSource + ); + + +BOOLEAN +HalQueryProfileInterval( + IN KPROFILE_SOURCE Source + ) + +/*++ + +Routine Description: + + Given a profile source, returns whether or not that source is + supported. + +Arguments: + + Source - Supplies the profile source + +Return Value: + + TRUE - Profile source is supported + + FALSE - Profile source is not supported + +--*/ + +{ + if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) { + return(Hal21164QueryProfileInterval(Source)); + } else { + return(Hal21064QueryProfileInterval(Source)); + } +} + + +NTSTATUS +HalSetProfileSourceInterval( + IN KPROFILE_SOURCE ProfileSource, + IN OUT ULONG *Interval + ) + +/*++ + +Routine Description: + + Sets the profile interval for a specified profile source + +Arguments: + + ProfileSource - Supplies the profile source + + Interval - Supplies the specified profile interval + Returns the actual profile interval + +Return Value: + + NTSTATUS + +--*/ + +{ + if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) { + return(Hal21164SetProfileSourceInterval(ProfileSource,Interval)); + } else { + return(Hal21064SetProfileSourceInterval(ProfileSource,Interval)); + } +} + + +ULONG +HalSetProfileInterval ( + IN ULONG Interval + ) + +/*++ + +Routine Description: + + This routine sets the profile interrupt interval. + +Arguments: + + Interval - Supplies the desired profile interval in 100ns units. + +Return Value: + + The actual profile interval. + +--*/ + +{ + if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) { + return(Hal21164SetProfileInterval(Interval)); + } else { + return(Hal21064SetProfileInterval(Interval)); + } +} + + + +VOID +HalStartProfileInterrupt ( + KPROFILE_SOURCE ProfileSource + ) + +/*++ + +Routine Description: + + This routine turns on the profile interrupt. + + N.B. This routine must be called at PROCLK_LEVEL while holding the + profile lock. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) { + Hal21164StartProfileInterrupt(ProfileSource); + } else { + Hal21064StartProfileInterrupt(ProfileSource); + } +} + + +VOID +HalStopProfileInterrupt ( + KPROFILE_SOURCE ProfileSource + ) + +/*++ + +Routine Description: + + This routine turns off the profile interrupt. + + N.B. This routine must be called at PROCLK_LEVEL while holding the + profile lock. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) { + Hal21164StopProfileInterrupt(ProfileSource); + } else { + Hal21064StopProfileInterrupt(ProfileSource); + } +} + + +VOID +HalpInitializeProfiler( + VOID + ) +/*++ + +Routine Description: + + This routine is called during initialization to initialize profiling + for each processor in the system. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) { + Halp21164InitializeProfiler(); + } else { + Halp21064InitializeProfiler(); + } +} + +NTSTATUS +HalpProfileSourceInformation ( + OUT PVOID Buffer, + IN ULONG BufferLength, + OUT PULONG ReturnedLength + ) +/*++ + +Routine Description: + + Returns the HAL_PROFILE_SOURCE_INFORMATION for this processor. + +Arguments: + + Buffer - output buffer + BufferLength - length of buffer on input + ReturnedLength - The length of data returned + +Return Value: + + STATUS_SUCCESS + STATUS_BUFFER_TOO_SMALL - The ReturnedLength contains the buffersize + currently needed. + +--*/ + +{ + if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) { + return(Halp21164ProfileSourceInformation(Buffer,BufferLength,ReturnedLength)); + } else { + return(Halp21064ProfileSourceInformation(Buffer,BufferLength,ReturnedLength)); + } +} + +NTSTATUS +HalpProfileSourceInterval ( + OUT PVOID Buffer, + IN ULONG BufferLength + ) +/*++ + +Routine Description: + + Returns the HAL_PROFILE_SOURCE_INTERVAL for this processor. + +Arguments: + + Buffer - output buffer + BufferLength - length of buffer on input + +Return Value: + + STATUS_SUCCESS + STATUS_BUFFER_TOO_SMALL - The ReturnedLength contains the buffersize + currently needed. + +--*/ + +{ + if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) { + return(Halp21164ProfileSourceInterval(Buffer,BufferLength)); + } else { + return(Halp21064ProfileSourceInterval(Buffer,BufferLength)); + } +} diff --git a/private/ntos/nthals/halflex/alpha/halpal.s b/private/ntos/nthals/halflex/alpha/halpal.s new file mode 100644 index 000000000..d34a29084 --- /dev/null +++ b/private/ntos/nthals/halflex/alpha/halpal.s @@ -0,0 +1,276 @@ +// TITLE("Alpha PAL funtions for HAL") +//++ +// +// Copyright (c) 1992 Digital Equipment Corporation +// Copyright (c) 1993 Digital Equipment Corporation +// +// Module Name: +// +// halpal.s +// +// Abstract: +// +// This module implements routines to call PAL functions +// from the Hal. +// +// +// Author: +// +// Jeff McLeman (mcleman) 09-Jul-1992 +// +// Environment: +// +// Kernel mode only. +// +// Revision History: +// +// 13-Jul-1992 Jeff McLeman (mcleman) +// add HalpMb to functions. +// +// 14-Dec-1993 Joe Notarangelo +// use new encoding to return to firmware: HalpReboot instead of +// HalpHalt +//-- + +#include "halalpha.h" + +//++ +// +// VOID +// HalpReboot( +// ) +// +// Routine Description: +// +// This function merely calls the PAL to reboot the Alpha processor. +// This is used to restart the console firmware. (Note, MIPS does +// not have a HALT instruction, so there had to be a mechanism to +// restart the firware. Alpha merely reboots, which causes a jump +// to firmware PAL, which restarts the firmware.) +// +// Arguments: +// +// None. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalpReboot) + + REBOOT // call the PAL to reboot + + .end HalpReboot + +//++ +// +// VOID +// HalpSwppal( +// ) +// +// Routine Description: +// +// This function merely calls the PAL to issue a SWPPAL +// on the Alpha processor... +// +// Arguments: +// +// a0 The physical address to do the Swappal to. +// a1 -- a5 Any other arguments to the PALcode. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalpSwppal) + + SWPPAL // call the PAL to do a swap_pal + + ret zero,(ra) + + .end HalpSwppal + + +//++ +// +// VOID +// HalpImb( +// ) +// +// Routine Description: +// +// This function merely calls the PAL to issue an Instruction +// Memory Barrier on the Alpha processor.. +// +// Arguments: +// +// None. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalpImb) + + IMB // call the PAL to do an IMB + + ret zero,(ra) + + .end HalpImb + + +//++ +// +// VOID +// HalpMb( +// ) +// +// Routine Description: +// +// This function merely calls the PAL to issue a general +// Memory Barrier on the Alpha processor.. +// +// Arguments: +// +// None. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalpMb) + + mb // memory barrier + + ret zero, (ra) + + .end HalpMb + +//++ +// +// VOID +// HalpCachePcrValues( +// ) +// +// Routine Description: +// +// This function merely calls the PAL to cache values in the +// PCR for faster access. +// +// Arguments: +// +// None. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalpCachePcrValues) + + CACHE_PCR_VALUES // call the palcode + + ret zero,(ra) + + .end HalpCachePcrValues +//++ +// +// ULONG +// HalpRpcc( +// ) +// +// Routine Description: +// +// This function executes the RPCC (read processor cycle counter) +// instruction. +// +// Arguments: +// +// None. +// +// Return Value: +// +// The low-order 32 bits of the processor cycle counter is returned +// as the function value. +// N.B. At 125 MHz this counter wraps about every 30 seconds. It is +// the caller's responsibility to deal with overflow or wraparound. +// +//-- + + LEAF_ENTRY(HalpRpcc) + + rpcc v0 // get rpcc value + addl v0, zero, v0 // extend + + ret zero, (ra) // return + + .end HalpRpcc + + +//++ +// +// MCES +// HalpReadMces( +// VOID +// ) +// +// Routine Description: +// +// Read the state of the MCES (Machine Check Error Summary) +// internal processor register. +// +// Arguments: +// +// None. +// +// Return Value: +// +// v0 - Current MCES value. +//-- + + LEAF_ENTRY(HalpReadMces) + + GET_MACHINE_CHECK_ERROR_SUMMARY // v0 = current value + + ret zero, (ra) // return + + .end HalpReadMces + + +//++ +// +// MCES +// HalpWriteMces( +// IN MCES Mces +// ) +// +// Routine Description: +// +// Update the current value of the MCES internal processor register. +// +// Arguments: +// +// Mces(a0) - Supplies the new value for the MCES register. +// +// Return Value: +// +// v0 - Previous MCES value. +// +//-- + + LEAF_ENTRY(HalpWriteMces) + + WRITE_MACHINE_CHECK_ERROR_SUMMARY // v0 = previous value + + ret zero, (ra) // return + + .end HalpWriteMces diff --git a/private/ntos/nthals/halflex/alpha/info.c b/private/ntos/nthals/halflex/alpha/info.c new file mode 100644 index 000000000..02e46848b --- /dev/null +++ b/private/ntos/nthals/halflex/alpha/info.c @@ -0,0 +1,128 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation +Copyright (c) 1994 Digital Equipment Corporation + +Module Name: + + info.c + +Abstract: + +Author: + + Ken Reneris (kenr) 08-Aug-1994 + +Environment: + + Kernel mode only. + +Revision History: + +--*/ + + +#include "halp.h" + +#ifdef _PNP_POWER_ +HAL_CALLBACKS HalCallback; +#endif // _PNP_POWER_ + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE,HaliQuerySystemInformation) +#pragma alloc_text(PAGE,HaliSetSystemInformation) +#endif + + +NTSTATUS +HaliQuerySystemInformation( + IN HAL_QUERY_INFORMATION_CLASS InformationClass, + IN ULONG BufferSize, + OUT PVOID Buffer, + OUT PULONG ReturnedLength + ) +/*++ + +Routine Description: + + The function returns system-wide information controlled by the HAL for a + variety of classes. + +Arguments: + + InformationClass - Information class of the request. + + BufferSize - Size of buffer supplied by the caller. + + Buffer - Supplies the space to store the data. + + ReturnedLength - Supplies a count in bytes of the amount of data returned. + +Return Value: + + STATUS_SUCCESS or error. + +--*/ +{ + NTSTATUS Status; + + switch (InformationClass) { + case HalProfileSourceInformation: + Status = HalpProfileSourceInformation ( + Buffer, + BufferSize, + ReturnedLength); + break; + + default: + Status = STATUS_INVALID_LEVEL; + break; + } + + return(Status); +} + +NTSTATUS +HaliSetSystemInformation ( + IN HAL_SET_INFORMATION_CLASS InformationClass, + IN ULONG BufferSize, + IN PVOID Buffer + ) +/*++ + +Routine Description: + + The function allows setting of various fields return by + HalQuerySystemInformation. + +Arguments: + + InformationClass - Information class of the request. + + BufferSize - Size of buffer supplied by the caller. + + Buffer - Supplies the data to be set. + +Return Value: + + STATUS_SUCCESS or error. + +--*/ +{ + NTSTATUS Status; + + switch (InformationClass) { + + case HalProfileSourceInterval: + Status = HalpProfileSourceInterval ( + Buffer, + BufferSize); + break; + + default: + Status = STATUS_INVALID_LEVEL; + break; + } + + return Status; +} diff --git a/private/ntos/nthals/halflex/alpha/initsys.c b/private/ntos/nthals/halflex/alpha/initsys.c new file mode 100644 index 000000000..de6d38930 --- /dev/null +++ b/private/ntos/nthals/halflex/alpha/initsys.c @@ -0,0 +1,579 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + initsys.c + +Abstract: + + This module implements the platform specific portions of the + HAL initialization. + +Author: + + Michael D. Kinney 3-May-1995 + +Environment: + + Kernel mode only. + +Revision History: + +--*/ + +#include "halp.h" +#include "pci.h" +#include "pcip.h" + +// +// Type Declarations +// + +typedef +VOID +(*POPERATING_SYSTEM_STARTED) ( + VOID + ); + +// +// Define global data used to determine the type of system I/O architecture to use. +// + +ULONG HalpIoArchitectureType = UNKNOWN_PROCESSOR_MODULE; + +// +// Define global data used to calibrate and stall processor execution. +// + +ULONG HalpProfileCountRate; + +ULONG IoSpaceAlreadyMapped = FALSE; +ULONG HalpModuleChipSetRevision = MODULE_CHIP_SET_REVISION_UNKNOWN; +BOOLEAN HalpModuleHardwareFlushing; +UCHAR HalpSecondPciBridgeBusNumber = 2; +ULONG HalpMotherboardType = MOTHERBOARD_UNKNOWN; +UCHAR *HalpInterruptLineToBit; +UCHAR *HalpBitToInterruptLine; +UCHAR *HalpInterruptLineToVirtualIsa; +UCHAR *HalpVirtualIsaToInterruptLine; +ULONGLONG HalpNoncachedDenseBasePhysicalSuperPage; +ULONGLONG HalpPciDenseBasePhysicalSuperPage; +ULONGLONG HalpPciConfig0BasePhysical; +ULONGLONG HalpPciConfig1BasePhysical; +ULONGLONG HalpIsaIoBasePhysical; +ULONGLONG HalpIsa1IoBasePhysical; +ULONGLONG HalpIsaMemoryBasePhysical; +ULONGLONG HalpIsa1MemoryBasePhysical; +ULONGLONG HalpPciIoBasePhysical; +ULONGLONG HalpPci1IoBasePhysical; +ULONGLONG HalpPciMemoryBasePhysical; +ULONGLONG HalpPci1MemoryBasePhysical; +PPLATFORM_RANGE_LIST HalpRangeList = NULL; +ULONG HalpIntel82378BusNumber = 0; +ULONG HalpIntel82378DeviceNumber = 0; +ULONG HalpSecondIntel82378DeviceNumber = 0; +ULONG HalpNonExistentPciDeviceMask = ~TREB20_MOTHERBOARD_PCI_DEVICE_MASK; +ULONG HalpNonExistentPci1DeviceMask = 0; +ULONG HalpNonExistentPci2DeviceMask = 0; +ULONG HalpNumberOfIsaBusses; +ULONG HalpVgaDecodeBusNumber; + +// +// Function prototypes. +// + +VOID +HalpGetPlatformParameterBlock( + VOID + ); + +ULONG FindIntel82378(ULONG Dec2105xBusNumber,ULONG Dec2105xDeviceNumber,ULONG BusNumber,ULONG IsaBusNumber) + +{ + ULONG i; + ULONG MaxDevice; + + if (BusNumber == 0) { + MaxDevice = PCI_MAX_LOCAL_DEVICE; + } else { + MaxDevice = 31; + } + for(i=0;i<=MaxDevice;i++) { + + if (HalpPciLowLevelConfigRead(BusNumber,i,0,0) == 0x04848086) { + return(i); + } + } + return(0); + } + +VOID +HalpGetIoArchitectureType( + VOID + ) + +/*++ + +Routine Description: + + This function gets the I/O Architecture Type from the Platform Parameter Block + retrieved from the firmware. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + ULONG Device16; + ULONG Device17; + + // + // If the I/O Architecture Type is already known, then just return. + // + + if (HalpIoArchitectureType != UNKNOWN_PROCESSOR_MODULE) { + return; + } + + // + // If the Platform Parameter Block has not been retrieved from the firmware, + // then do it now. + // + + if (HalpPlatformParameterBlock == NULL) { + HalpGetPlatformParameterBlock(); + } + + // + // Check for the 21164(EV5) Apocolypse Module Type. + // + + if (strcmp(HalpPlatformParameterBlock->ModuleName,"APOCALYPSE1.0")==0) { + HalpIoArchitectureType = EV5_PROCESSOR_MODULE; + } + + // + // Check for the 21064(EV4) Rogue Module Type. + // + + if (strcmp(HalpPlatformParameterBlock->ModuleName,"ROGUE2.0")==0) { + HalpIoArchitectureType = EV4_PROCESSOR_MODULE; + } + + // + // If the I/O Architecture Type is still unknown then HALT. + // + + if (HalpIoArchitectureType == UNKNOWN_PROCESSOR_MODULE) { + for(;;); + } + + // + // Get the processor module's chip set revision. + // + + HalpModuleChipSetRevision = HalpGetModuleChipSetRevision(); + + // + // Limit the chip set revision to the highest one allowed by this HAL. + // + + if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE && HalpModuleChipSetRevision > EV5_MAX_CHIP_SET_REVISION) { + HalpModuleChipSetRevision = EV5_MAX_CHIP_SET_REVISION; + } + + if (HalpIoArchitectureType == EV4_PROCESSOR_MODULE && HalpModuleChipSetRevision > EV4_MAX_CHIP_SET_REVISION) { + HalpModuleChipSetRevision = EV4_MAX_CHIP_SET_REVISION; + } + + // + // See if the module chip set supports hardware flushing. + // + + HalpModuleHardwareFlushing = TRUE; + + if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) { + switch (HalpModuleChipSetRevision) { + case 0 : HalpModuleHardwareFlushing = FALSE; + break; + } + } + + // + // Determine base physical address of Dense PCI Space and the PCI Configuration Spaces + // + + if (HalpIoArchitectureType == EV4_PROCESSOR_MODULE) { + HalpNoncachedDenseBasePhysicalSuperPage = ROGUE_NONCACHED_DENSE_BASE_PHYSICAL_SUPERPAGE; + HalpPciDenseBasePhysicalSuperPage = ROGUE_PCI_DENSE_BASE_PHYSICAL_SUPERPAGE; + HalpPciConfig0BasePhysical = ROGUE_PCI_CONFIG0_BASE_PHYSICAL; + HalpPciConfig1BasePhysical = ROGUE_PCI_CONFIG1_BASE_PHYSICAL; + } + + if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE && (HalpModuleChipSetRevision==0 || HalpModuleChipSetRevision==1)) { + HalpNoncachedDenseBasePhysicalSuperPage = APOC1_NONCACHED_DENSE_BASE_PHYSICAL_SUPERPAGE; + HalpPciDenseBasePhysicalSuperPage = APOC1_PCI_DENSE_BASE_PHYSICAL_SUPERPAGE; + HalpPciConfig0BasePhysical = APOC1_PCI_CONFIG0_BASE_PHYSICAL; + HalpPciConfig1BasePhysical = APOC1_PCI_CONFIG1_BASE_PHYSICAL; + } + + if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE && HalpModuleChipSetRevision==2) { + HalpNoncachedDenseBasePhysicalSuperPage = APOC2_NONCACHED_DENSE_BASE_PHYSICAL_SUPERPAGE; + HalpPciDenseBasePhysicalSuperPage = APOC2_PCI_DENSE_BASE_PHYSICAL_SUPERPAGE; + HalpPciConfig0BasePhysical = APOC2_PCI_CONFIG0_BASE_PHYSICAL; + HalpPciConfig1BasePhysical = APOC2_PCI_CONFIG1_BASE_PHYSICAL; + } + + // + // Determine the motherboard type. Assume TREBBIA20 so we can do some config cycles. + // + + HalpMotherboardType = TREBBIA20; + + Device16 = HalpPciLowLevelConfigRead(0,0x10,0,0); + Device17 = HalpPciLowLevelConfigRead(0,0x11,0,0); + + // + // Now assume motherboard type is unknown and check out values returned from config cycles. + // + + HalpMotherboardType = MOTHERBOARD_UNKNOWN; + + if (Device16 == 0x00211011 && Device17 == 0x00211011) { + HalpMotherboardType = TREBBIA20; + + // + // Find and initialize up to two Jubilee adapters. + // + + HalpNumberOfIsaBusses = 1; + HalpIntel82378BusNumber = 1; + HalpIntel82378DeviceNumber = FindIntel82378(0,0x11,1,0); + HalpSecondPciBridgeBusNumber = (UCHAR)((HalpPciLowLevelConfigRead(0,0x10,0,0x18) >> 8) & 0xff); + HalpSecondIntel82378DeviceNumber = FindIntel82378(0,0x10,HalpSecondPciBridgeBusNumber,1); + if (HalpSecondIntel82378DeviceNumber != 0) { + HalpNumberOfIsaBusses = 2; + } + HalpVgaDecodeBusNumber = 0x00; + if (HalpPciLowLevelConfigRead(0,0x11,0,0x3c) & 0x00080000) { + HalpVgaDecodeBusNumber |= 0x01; + } + if (HalpPciLowLevelConfigRead(0,0x10,0,0x3c) & 0x00080000) { + HalpVgaDecodeBusNumber |= 0x02; + } + } + + if (Device16 == 0x04848086 && Device17 == 0x00011011) { + HalpMotherboardType = TREBBIA13; + HalpNumberOfIsaBusses = 1; + HalpIntel82378BusNumber = 0; + HalpIntel82378DeviceNumber = 0x10; + HalpVgaDecodeBusNumber = 0x01; + if (HalpPciLowLevelConfigRead(0,0x11,0,0x3c) & 0x00080000) { + HalpVgaDecodeBusNumber |= 0x02; + } + } + + // + // If the Motherboard Type is unknown then HALT. + // + + if (HalpMotherboardType == MOTHERBOARD_UNKNOWN) { + for(;;); + } + + // + // Determine the PCI interrupt translation tables. + // + + if (HalpMotherboardType == TREBBIA13) { + HalpNonExistentPciDeviceMask = ~TREB13_MOTHERBOARD_PCI_DEVICE_MASK; + HalpNonExistentPci1DeviceMask = 0; + HalpNonExistentPci2DeviceMask = 0; + HalpInterruptLineToBit = Treb13InterruptLineToBit; + HalpBitToInterruptLine = Treb13BitToInterruptLine; + HalpInterruptLineToVirtualIsa = Treb13InterruptLineToVirtualIsa; + HalpVirtualIsaToInterruptLine = Treb13VirtualIsaToInterruptLine; + if (HalpPlatformParameterBlock->FirmwareRevision >= 50) { + if (!((TREB13SETUPINFO *)(HalpPlatformSpecificExtension->AdvancedSetupInfo))->EnableAmd1) { + HalpNonExistentPciDeviceMask |= (1 << 0x0d); + } + if (!((TREB13SETUPINFO *)(HalpPlatformSpecificExtension->AdvancedSetupInfo))->EnableAmd2) { + HalpNonExistentPciDeviceMask |= (1 << 0x0f); + } + } + } + if (HalpMotherboardType == TREBBIA20) { + HalpNonExistentPciDeviceMask = ~TREB20_MOTHERBOARD_PCI_DEVICE_MASK; + HalpNonExistentPci1DeviceMask = 0; + HalpNonExistentPci2DeviceMask = 0; + HalpInterruptLineToBit = Treb20InterruptLineToBit; + HalpBitToInterruptLine = Treb20BitToInterruptLine; + HalpInterruptLineToVirtualIsa = Treb20InterruptLineToVirtualIsa; + HalpVirtualIsaToInterruptLine = Treb20VirtualIsaToInterruptLine; + if (HalpPlatformParameterBlock->FirmwareRevision >= 50) { + if (!((TREB20SETUPINFO *)(HalpPlatformSpecificExtension->AdvancedSetupInfo))->EnableNcr) { + HalpNonExistentPci2DeviceMask |= (1 << 0x07); + } + } + } + + // + // Determine base physical address of thr ISA IO Address Space and the address translation table. + // + + if (HalpIoArchitectureType == EV4_PROCESSOR_MODULE) { + if (HalpMotherboardType == TREBBIA13) { + HalpIsaIoBasePhysical = TREB1_ROGUE_ISA_IO_BASE_PHYSICAL; + HalpIsa1IoBasePhysical = (ULONGLONG)(0); + HalpIsaMemoryBasePhysical = TREB1_ROGUE_ISA_MEMORY_BASE_PHYSICAL; + HalpIsa1MemoryBasePhysical = (ULONGLONG)(0); + HalpPciIoBasePhysical = TREB1_ROGUE_PCI_IO_BASE_PHYSICAL; + HalpPci1IoBasePhysical = (ULONGLONG)(0); + HalpPciMemoryBasePhysical = TREB1_ROGUE_PCI_MEMORY_BASE_PHYSICAL; + HalpPci1MemoryBasePhysical = (ULONGLONG)(0); + if (HalpModuleChipSetRevision == 0) { + HalpRangeList = Rogue0Trebbia13RangeList; + } + if (HalpModuleChipSetRevision == 1) { + HalpRangeList = Rogue1Trebbia13RangeList; + } + } + if (HalpMotherboardType == TREBBIA20) { + HalpIsaIoBasePhysical = TREB2_ROGUE_ISA_IO_BASE_PHYSICAL; + HalpIsa1IoBasePhysical = TREB2_ROGUE_ISA1_IO_BASE_PHYSICAL; + HalpIsaMemoryBasePhysical = TREB2_ROGUE_ISA_MEMORY_BASE_PHYSICAL; + HalpIsa1MemoryBasePhysical = TREB2_ROGUE_ISA1_MEMORY_BASE_PHYSICAL; + HalpPciIoBasePhysical = TREB2_ROGUE_PCI_IO_BASE_PHYSICAL; + HalpPci1IoBasePhysical = TREB2_ROGUE_PCI1_IO_BASE_PHYSICAL; + HalpPciMemoryBasePhysical = TREB2_ROGUE_PCI_MEMORY_BASE_PHYSICAL; + HalpPci1MemoryBasePhysical = TREB2_ROGUE_PCI1_MEMORY_BASE_PHYSICAL; + if (HalpModuleChipSetRevision == 0) { + HalpRangeList = Rogue0Trebbia20RangeList; + } + if (HalpModuleChipSetRevision == 1) { + HalpRangeList = Rogue1Trebbia20RangeList; + } + } + } + + if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE && (HalpModuleChipSetRevision==0 || HalpModuleChipSetRevision==1)) { + if (HalpMotherboardType == TREBBIA13) { + HalpIsaIoBasePhysical = TREB1_APOC1_ISA_IO_BASE_PHYSICAL; + HalpIsa1IoBasePhysical = (ULONGLONG)(0); + HalpIsaMemoryBasePhysical = TREB1_APOC1_ISA_MEMORY_BASE_PHYSICAL; + HalpIsa1MemoryBasePhysical = (ULONGLONG)(0); + HalpPciIoBasePhysical = TREB1_APOC1_PCI_IO_BASE_PHYSICAL; + HalpPci1IoBasePhysical = (ULONGLONG)(0); + HalpPciMemoryBasePhysical = TREB1_APOC1_PCI_MEMORY_BASE_PHYSICAL; + HalpPci1MemoryBasePhysical = (ULONGLONG)(0); + HalpRangeList = Apoc10Trebbia13RangeList; + } + if (HalpMotherboardType == TREBBIA20) { + HalpIsaIoBasePhysical = TREB2_APOC1_ISA_IO_BASE_PHYSICAL; + HalpIsa1IoBasePhysical = TREB2_APOC1_ISA1_IO_BASE_PHYSICAL; + HalpIsaMemoryBasePhysical = TREB2_APOC1_ISA_MEMORY_BASE_PHYSICAL; + HalpIsa1MemoryBasePhysical = TREB2_APOC1_ISA1_MEMORY_BASE_PHYSICAL; + HalpPciIoBasePhysical = TREB2_APOC1_PCI_IO_BASE_PHYSICAL; + HalpPci1IoBasePhysical = TREB2_APOC1_PCI1_IO_BASE_PHYSICAL; + HalpPciMemoryBasePhysical = TREB2_APOC1_PCI_MEMORY_BASE_PHYSICAL; + HalpPci1MemoryBasePhysical = TREB2_APOC1_PCI1_MEMORY_BASE_PHYSICAL; + HalpRangeList = Apoc10Trebbia20RangeList; + } + } + + if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE && HalpModuleChipSetRevision==2) { + if (HalpMotherboardType == TREBBIA13) { + HalpIsaIoBasePhysical = TREB1_APOC2_ISA_IO_BASE_PHYSICAL; + HalpIsa1IoBasePhysical = (ULONGLONG)(0); + HalpIsaMemoryBasePhysical = TREB1_APOC2_ISA_MEMORY_BASE_PHYSICAL; + HalpIsa1MemoryBasePhysical = (ULONGLONG)(0); + HalpPciIoBasePhysical = TREB1_APOC2_PCI_IO_BASE_PHYSICAL; + HalpPci1IoBasePhysical = (ULONGLONG)(0); + HalpPciMemoryBasePhysical = TREB1_APOC2_PCI_MEMORY_BASE_PHYSICAL; + HalpPci1MemoryBasePhysical = (ULONGLONG)(0); + HalpRangeList = Apoc20Trebbia13RangeList; + } + if (HalpMotherboardType == TREBBIA20) { + HalpIsaIoBasePhysical = TREB2_APOC2_ISA_IO_BASE_PHYSICAL; + HalpIsa1IoBasePhysical = TREB2_APOC2_ISA1_IO_BASE_PHYSICAL; + HalpIsaMemoryBasePhysical = TREB2_APOC2_ISA_MEMORY_BASE_PHYSICAL; + HalpIsa1MemoryBasePhysical = TREB2_APOC2_ISA1_MEMORY_BASE_PHYSICAL; + HalpPciIoBasePhysical = TREB2_APOC2_PCI_IO_BASE_PHYSICAL; + HalpPci1IoBasePhysical = TREB2_APOC2_PCI1_IO_BASE_PHYSICAL; + HalpPciMemoryBasePhysical = TREB2_APOC2_PCI_MEMORY_BASE_PHYSICAL; + HalpPci1MemoryBasePhysical = TREB2_APOC2_PCI1_MEMORY_BASE_PHYSICAL; + HalpRangeList = Apoc20Trebbia20RangeList; + } + } + + + // + // If the address translation table is still NULL then HALT. + // + + if (HalpRangeList == NULL) { + for(;;); + } +} + +BOOLEAN +HalpInitSystem ( + IN ULONG Phase, + IN PLOADER_PARAMETER_BLOCK LoaderBlock + ) + +/*++ + +Routine Description: + + This function initializes the Hardware Architecture Layer (HAL). + +Arguments: + + Phase - Supplies the initialization phase (zero or one). + + LoaderBlock - Supplies a pointer to a loader parameter block. + +Return Value: + + A value of TRUE is returned is the initialization was successfully + complete. Otherwise a value of FALSE is returend. + +--*/ + + +{ + POPERATING_SYSTEM_STARTED PrivateOperatingSystemStarted; + PSYSTEM_PARAMETER_BLOCK SystemParameterBlock = SYSTEM_BLOCK; + PHYSICAL_ADDRESS CacheFlushPhysicalAddress; + + if (Phase == 0) { + + // + // Phase 0 initialization. + // + + HalpGetIoArchitectureType(); + + if (HalpIoArchitectureType != EV5_PROCESSOR_MODULE) { + + // + // Inform the firmware that an operating system has taken control of the system. + // + + if ((SystemParameterBlock->VendorVectorLength / 4) >= 50) { + PrivateOperatingSystemStarted = *(POPERATING_SYSTEM_STARTED *)((ULONG)(SystemParameterBlock->VendorVector) + 50*4); + if (PrivateOperatingSystemStarted != NULL) { + PrivateOperatingSystemStarted(); + } + } + } + + // + // Map all I/O Spaces used by the HAL + // + + HalpMapIoSpace(); + IoSpaceAlreadyMapped = TRUE; + + HalpInitializeX86DisplayAdapter(); + + // + // Initialize Dma Cache Parameters + // + + if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) { + HalpMapBufferSize = APOC_DMA_CACHE_SIZE; + HalpMapBufferPhysicalAddress.QuadPart = APOC_DMA_CACHE_BASE_PHYSICAL; + } else { + HalpMapBufferSize = ROGUE_DMA_CACHE_SIZE; + HalpMapBufferPhysicalAddress.QuadPart = ROGUE_DMA_CACHE_BASE_PHYSICAL; + } + + return TRUE; + + } else { + + UCHAR Message[80]; + + // + // Phase 1 initialization. + // + + if (HalpMotherboardType == TREBBIA13) { + HalDisplayString("DeskStation Technology UniFlex/Raptor 3 Motherboard Rev. 1\n\r"); + } + + if (HalpMotherboardType == TREBBIA20) { + HalDisplayString("DeskStation Technology Raptor ReFlex Motherboard Rev. 2\n\r"); + } + + if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) { + sprintf(Message,"DeskStation Technology ALPHA 21164 Processor Module Rev. %d\n\r",HalpModuleChipSetRevision); + } else { + sprintf(Message,"DeskStation Technology ALPHA 21064A Processor Module Rev. %d\n\r",HalpModuleChipSetRevision); + } + HalDisplayString(Message); + + if (HalpModuleHardwareFlushing == TRUE) { + HalDisplayString("Hardware Flushing is Enabled\n\r"); + } else { + HalDisplayString("Hardware Flushing is Disabled\n\r"); + } + + // + // Compute the profile interrupt rate. + // + + HalpProfileCountRate = ((1000 * 1000 * 10) / KeQueryTimeIncrement()); + + // + // Map Cache Flush Region. + // + + if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) { + CacheFlushPhysicalAddress.QuadPart = APOC_CACHE_FLUSH_BASE_PHYSICAL; + HalpCacheFlushBase = MmMapIoSpace(CacheFlushPhysicalAddress,APOC_CACHE_FLUSH_SIZE,TRUE); + } else { + CacheFlushPhysicalAddress.QuadPart = ROGUE_CACHE_FLUSH_BASE_PHYSICAL; + HalpCacheFlushBase = MmMapIoSpace(CacheFlushPhysicalAddress,ROGUE_CACHE_FLUSH_SIZE,TRUE); + } + + // + // Set the time increment value and connect the real clock interrupt + // routine. + // + + PCR->InterruptRoutine[UNIFLEX_CLOCK2_LEVEL] = HalpClockInterrupt; + + HalpEnableEisaInterrupt(UNIFLEX_CLOCK2_LEVEL,Latched); + + // + // Initialize profiler. + // + + HalpInitializeProfiler(); + + // + // Initialize the existing bus handlers. + // + + HalpRegisterInternalBusHandlers(); + + // + // Initialize the PCI bus. + // + + HalpInitializePCIBus (); + } +} + diff --git a/private/ntos/nthals/halflex/alpha/intsup.c b/private/ntos/nthals/halflex/alpha/intsup.c new file mode 100644 index 000000000..7f5fa0f36 --- /dev/null +++ b/private/ntos/nthals/halflex/alpha/intsup.c @@ -0,0 +1,393 @@ +/*++ + +Copyright (c) 1995 DeskStation Technology + +Module Name: + + intsup.c + +Abstract: + + This module implements the HAL enable/disable system interrupt for + platform specific vectors. + +Author: + + Michael D. Kinney 14-May-1995 + +Environment: + + Kernel mode + +Revision History: + +--*/ + +#include "halp.h" + +VOID +HalpDisablePlatformInterrupt ( + IN ULONG Vector, + IN KIRQL Irql + ) + +/*++ + +Routine Description: + + This routine disables the specified system interrupt. + +Arguments: + + Vector - Supplies the vector of the system interrupt that is disabled. + + Irql - Supplies the IRQL of the interrupting source. + +Return Value: + + None. + +--*/ + +{ + // + // If the vector is a performance counter vector we will ignore + // the enable - the performance counters are enabled directly by + // the wrperfmon callpal. Wrperfmon must be controlled directly + // by the driver. + // + + switch (Vector) { + + case PC0_VECTOR: + case PC1_VECTOR: + case PC2_VECTOR: + + break; + + } //end switch Vector + + return; +} + + +BOOLEAN +HalpEnablePlatformInterrupt ( + IN ULONG Vector, + IN KIRQL Irql, + IN KINTERRUPT_MODE InterruptMode + ) + +/*++ + +Routine Description: + + This routine enables the specified system interrupt. + +Arguments: + + Vector - Supplies the vector of the system interrupt that is enabled. + + Irql - Supplies the IRQL of the interrupting source. + + InterruptMode - Supplies the mode of the interrupt; LevelSensitive or + Latched. + +Return Value: + + TRUE if the system interrupt was enabled + +--*/ + +{ + BOOLEAN Enabled = FALSE; + + // + // If the vector is a performance counter vector we will ignore + // the enable - the performance counters are enabled directly by + // the wrperfmon callpal. Wrperfmon must be controlled directly + // by the driver. + // + + switch (Vector) { + + case PC0_VECTOR: + case PC1_VECTOR: + case PC2_VECTOR: + + Enabled = TRUE; + break; + + } //end switch Vector + + return Enabled; + +} + +ULONG +HalpGetSystemInterruptVector( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN ULONG BusInterruptLevel, + IN ULONG BusInterruptVector, + OUT PKIRQL Irql, + OUT PKAFFINITY Affinity + ) + +/*++ + +Routine Description: + + This function returns the system interrupt vector and IRQL level + corresponding to the specified bus interrupt level and/or vector. The + system interrupt vector and IRQL are suitable for use in a subsequent call + to KeInitializeInterrupt. + + We only use InterfaceType, and BusInterruptLevel. BusInterruptVector + for ISA and EISA are the same as the InterruptLevel, so ignore. + +Arguments: + + BusHandler - Registered BUSHANDLER for the target configuration space + + RootHandler - Registered BUSHANDLER for the orginating HalGetBusData + request. + + BusInterruptLevel - Supplies the bus specific interrupt level. + + BusInterruptVector - Supplies the bus specific interrupt vector. + + Irql - Returns the system request priority. + + Affinity - Returns the affinity for the requested vector + +Return Value: + + Returns the system interrupt vector corresponding to the specified device. + +--*/ + +{ + INTERFACE_TYPE InterfaceType = BusHandler->InterfaceType; + ULONG BusNumber = BusHandler->BusNumber; + + ULONG Vector; + + *Affinity = 1; + + if (InterfaceType == ProcessorInternal) { + + // + // Handle the internal defined for the processor itself + // and used to control the performance counters in the 21064. + // + + if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) { + if( (Vector = HalpGet21164PerformanceVector( BusInterruptLevel, + Irql)) != 0 ){ + + // + // Performance counter was successfully recognized. + // + + return Vector; + + } else { + + // + // Unrecognized processor interrupt. + // + + *Irql = 0; + *Affinity = 0; + return 0; + + } //end if Vector + } else { + if( (Vector = HalpGet21064PerformanceVector( BusInterruptLevel, + Irql)) != 0 ){ + + // + // Performance counter was successfully recognized. + // + + return Vector; + + } else { + + // + // Unrecognized processor interrupt. + // + + *Irql = 0; + *Affinity = 0; + return 0; + + } //end if Vector + } + + } else if ( (InterfaceType==PCI_BUS && BusInterruptLevel>=0x0 && BusInterruptLevel<=0x0f) || + (HalpMotherboardType==TREBBIA13 && InterfaceType==Isa && BusNumber==1) ) { + + ULONG i; + + for(i=0;i<12;i++) { + if (BusInterruptLevel == HalpPlatformSpecificExtension->PciInterruptToIsaIrq[i]) { + + *Irql = UNIFLEX_PCI_DEVICE_LEVEL; + + BusInterruptLevel = HalpVirtualIsaInterruptToInterruptLine(i) - 0x10; + + return(BusInterruptLevel + UNIFLEX_PCI_VECTORS); + } + } + + // + // Unrecognized interrupt + // + + *Irql = 0; + *Affinity = 0; + return(0); + + } else if (InterfaceType == PCIBus && BusInterruptLevel >= 0x10) { + + // + // Assumes all PCI devices coming in on same pin + // + + *Irql = UNIFLEX_PCI_DEVICE_LEVEL; + + BusInterruptLevel -= 0x10; + + // + // The vector is equal to the specified bus level plus the PCI_VECTOR. + // + + return(BusInterruptLevel + UNIFLEX_PCI_VECTORS); + + } else if (InterfaceType == Isa) { + + // + // Assumes all ISA devices coming in on same pin + // + + *Irql = UNIFLEX_ISA_DEVICE_LEVEL; + + // + // The vector is equal to the specified bus level plus the ISA_VECTOR. + // This is assuming that the ISA levels not assigned Interrupt Levels + // in the Beta programming guide are unused in the LCA system. + // Otherwise, need a different encoding scheme. + // + // Not all interrupt levels are actually supported on Beta; + // Should we make some of them illegal here? + + if (BusNumber == 0) { + return(BusInterruptLevel + UNIFLEX_ISA_VECTORS); + } + if (BusNumber == 1) { + return(BusInterruptLevel + UNIFLEX_ISA1_VECTORS); + } + } else if (InterfaceType == Eisa) { + + // + // Assumes all EISA devices coming in on same pin + // + + *Irql = UNIFLEX_EISA_DEVICE_LEVEL; + + // + // The vector is equal to the specified bus level plus the EISA_VECTOR. + // + + if (BusNumber == 0) { + return(BusInterruptLevel + UNIFLEX_EISA_VECTORS); + } + if (BusNumber == 1) { + return(BusInterruptLevel + UNIFLEX_EISA1_VECTORS); + } + + } else { + + // + // Not an interface supported on EB64P systems + // + + *Irql = 0; + *Affinity = 0; + return(0); + } +} + +ULONG +HalpGet21164PerformanceVector( + IN ULONG BusInterruptLevel, + OUT PKIRQL Irql + ) + +/*++ + +Routine Description: + + This function returns the system interrupt vector and IRQL level + corresponding to the specified performance counter interrupt. + +Arguments: + + BusInterruptLevel - Supplies the performance counter number. + + Irql - Returns the system request priority. + +Return Value: + + Returns the system interrupt vector corresponding to the specified device. + +--*/ + +{ + + // + // Handle the special internal bus defined for the processor itself + // and used to control the performance counters in the 21164. + // + + *Irql = PROFILE_LEVEL; + + switch( BusInterruptLevel ){ + + // + // Performance Counter 0 + // + + case 0: + + return PC0_SECONDARY_VECTOR; + + // + // Performance Counter 1 + // + + case 1: + + return PC1_SECONDARY_VECTOR; + + // + // Performance Counter 2 + // + + case 2: + + return PC2_SECONDARY_VECTOR; + + } //end switch( BusInterruptLevel ) + + // + // Unrecognized. + // + + *Irql = 0; + return 0; + +} + diff --git a/private/ntos/nthals/halflex/alpha/jxhalp.h b/private/ntos/nthals/halflex/alpha/jxhalp.h new file mode 100644 index 000000000..84a06ca18 --- /dev/null +++ b/private/ntos/nthals/halflex/alpha/jxhalp.h @@ -0,0 +1,404 @@ +/*++ BUILD Version: 0001 // Increment this if a change has global effects + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + jxhalp.h + +Abstract: + + This header file defines the private Hardware Architecture Layer (HAL) + Jazz specific interfaces, defines and structures. + +Author: + + Jeff Havens (jhavens) 20-Jun-91 + + +Revision History: + +--*/ + +#ifndef _JXHALP_ +#define _JXHALP_ + + +typedef enum _ADDRESS_SPACE_TYPE{ + BusMemory=0, + BusIo = 1, + UserBusMemory = 2, + UserBusIo = 3, + KernelPciDenseMemory = 4, + UserPciDenseMemory = 6, +} ADDRESS_SPACE_TYPE, *PADDRESS_SPACE_TYPE; + + +// +// Define microprocessor-specific function prototypes and structures. +// + +// +// 21164 (EV4) processor family. +// + +typedef struct _EV5ProfileCount { + ULONG ProfileCount[3]; + ULONG ProfileCountReload[3]; +} EV5ProfileCount, *PEV5ProfileCount; + +// +// 21064 (EV4) processor family. +// + +typedef enum _EV4Irq{ + Irq0 = 0, + Irq1 = 1, + Irq2 = 2, + Irq3 = 3, + Irq4 = 4, + Irq5 = 5, + MaximumIrq +} EV4Irq, *PEV4Irq; + +typedef struct _EV4IrqStatus{ + ULONG Vector; + BOOLEAN Enabled; + KIRQL Irql; + UCHAR Priority; +} EV4IrqStatus, *PEV4IrqStatus; + +typedef struct _EV4ProfileCount { + ULONG ProfileCount[2]; + ULONG ProfileCountReload[2]; +} EV4ProfileCount, *PEV4ProfileCount; + +VOID +HalpInitialize21064Interrupts( + VOID + ); + +VOID +HalpDisable21064HardwareInterrupt( + IN ULONG Irq + ); + +VOID +HalpDisable21064SoftwareInterrupt( + IN KIRQL Irql + ); + +VOID +HalpDisable21064PerformanceInterrupt( + IN ULONG Vector + ); + +VOID +HalpEnable21064HardwareInterrupt( + IN ULONG Irq, + IN KIRQL Irql, + IN ULONG Vector, + IN UCHAR Priority + ); + +VOID +HalpEnable21064SoftwareInterrupt( + IN KIRQL Irql + ); + +VOID +HalpInitialize21064Interrupts( + VOID + ); + +VOID +HalpEnable21064PerformanceInterrupt( + IN ULONG Vector, + IN KIRQL Irql + ); + +ULONG +HalpGet21064PerformanceVector( + IN ULONG BusInterruptLevel, + OUT PKIRQL Irql + ); + +// +// 21164 (EV5) processor family. +// + +typedef struct _EB164_PCR{ + ULONGLONG HalpCycleCount; // 64-bit per-processor cycle count + ULONG Reserved[3]; // Pad ProfileCount to offset 20 + EV5ProfileCount ProfileCount; // Profile counter state + } EB164_PCR, *PEB164_PCR; + +#define HAL_21164_PCR ( (PEB164_PCR)(&(PCR->HalReserved)) ) + +// +// 21064 (EV4) processor family. +// + +typedef struct _EB64P_PCR { + ULONGLONG HalpCycleCount; // 64-bit per-processor cycle count + EV4ProfileCount ProfileCount; // Profile counter state, do not move + EV4IrqStatus IrqStatusTable[MaximumIrq]; // Irq status table +} EB64P_PCR, *PEB64P_PCR; + +#define HAL_21064_PCR ( (PEB64P_PCR)(&(PCR->HalReserved)) ) + +// +// Define used to determine if a page is within the DMA Cache range. +// + +#define HALP_PAGE_IN_DMA_CACHE(Page) \ + (Page >= (0x40000/2)) + +// +// Define global data used to locate the EISA control space and the realtime +// clock registers. +// + + + +extern PVOID HalpCacheFlushBase; +extern ULONG HalpClockFrequency; +extern ULONG HalpClockMegaHertz; +extern ULONG HalpIoArchitectureType; +extern ULONG HalpModuleChipSetRevision; +extern ULONG HalpMotherboardType; +extern BOOLEAN HalpModuleHardwareFlushing; +extern UCHAR *HalpInterruptLineToBit; +extern UCHAR *HalpBitToInterruptLine; +extern UCHAR *HalpInterruptLineToVirtualIsa; +extern UCHAR *HalpVirtualIsaToInterruptLine; +extern ULONGLONG HalpNoncachedDenseBasePhysicalSuperPage; +extern ULONGLONG HalpPciDenseBasePhysicalSuperPage; +extern ULONGLONG HalpPciConfig0BasePhysical; +extern ULONGLONG HalpPciConfig1BasePhysical; +extern ULONGLONG HalpIsaIoBasePhysical; +extern ULONGLONG HalpIsa1IoBasePhysical; +extern ULONGLONG HalpIsaMemoryBasePhysical; +extern ULONGLONG HalpIsa1MemoryBasePhysical; +extern ULONGLONG HalpPciIoBasePhysical; +extern ULONGLONG HalpPci1IoBasePhysical; +extern ULONGLONG HalpPciMemoryBasePhysical; +extern ULONGLONG HalpPci1MemoryBasePhysical; +extern PPLATFORM_RANGE_LIST HalpRangeList; +extern UCHAR HalpSecondPciBridgeBusNumber; +extern ULONG PCIMaxBus; +extern ULONG HalpIntel82378BusNumber; +extern ULONG HalpIntel82378DeviceNumber; +extern ULONG HalpSecondIntel82378DeviceNumber; +extern ULONG HalpNonExistentPciDeviceMask; +extern ULONG HalpNonExistentPci1DeviceMask; +extern ULONG HalpNonExistentPci2DeviceMask; + +extern PLATFORM_RANGE_LIST Apoc10Trebbia13RangeList[]; +extern PLATFORM_RANGE_LIST Apoc10Trebbia20RangeList[]; +extern PLATFORM_RANGE_LIST Apoc20Trebbia13RangeList[]; +extern PLATFORM_RANGE_LIST Apoc20Trebbia20RangeList[]; +extern PLATFORM_RANGE_LIST Rogue0Trebbia13RangeList[]; +extern PLATFORM_RANGE_LIST Rogue1Trebbia13RangeList[]; +extern PLATFORM_RANGE_LIST Rogue0Trebbia20RangeList[]; +extern PLATFORM_RANGE_LIST Rogue1Trebbia20RangeList[]; + +extern UCHAR Treb13InterruptLineToBit[]; +extern UCHAR Treb13BitToInterruptLine[]; +extern UCHAR Treb13InterruptLineToVirtualIsa[]; +extern UCHAR Treb13VirtualIsaToInterruptLine[]; +extern UCHAR Treb20InterruptLineToBit[]; +extern UCHAR Treb20BitToInterruptLine[]; +extern UCHAR Treb20InterruptLineToVirtualIsa[]; +extern UCHAR Treb20VirtualIsaToInterruptLine[]; +extern ULONG HalpNumberOfIsaBusses; +extern ULONG HalpVgaDecodeBusNumber; + +VOID +HalpMb ( + ); + +VOID +HalpImb ( + ); + +VOID +HalpCachePcrValues ( + ); + +ULONG +HalpRpcc ( + ); + +ULONG +HalpReadAbsoluteUlong ( + IN ULONG HighPart, + IN ULONG LowPart + ); + +VOID +HalpWriteAbsoluteUlong ( + IN ULONG HighPart, + IN ULONG LowPart, + IN ULONG Value + ); + +ULONG +HalpGetModuleChipSetRevision( + VOID + ); + +VOID +HalpInitialize21164Interrupts( + VOID + ); + +VOID +HalpStart21164Interrupts( + VOID + ); + +VOID +HalpInitializeProfiler( + VOID + ); + +NTSTATUS +HalpProfileSourceInformation ( + OUT PVOID Buffer, + IN ULONG BufferLength, + OUT PULONG ReturnedLength + ); + +NTSTATUS +HalpProfileSourceInterval ( + OUT PVOID Buffer, + IN ULONG BufferLength + ); + + +VOID +Halp21064InitializeProfiler( + VOID + ); + +NTSTATUS +Halp21064ProfileSourceInformation ( + OUT PVOID Buffer, + IN ULONG BufferLength, + OUT PULONG ReturnedLength + ); + +NTSTATUS +Halp21064ProfileSourceInterval ( + OUT PVOID Buffer, + IN ULONG BufferLength + ); + + +VOID +Halp21164InitializeProfiler( + VOID + ); + +NTSTATUS +Halp21164ProfileSourceInformation ( + OUT PVOID Buffer, + IN ULONG BufferLength, + OUT PULONG ReturnedLength + ); + +NTSTATUS +Halp21164ProfileSourceInterval ( + OUT PVOID Buffer, + IN ULONG BufferLength + ); + + +ULONG +HalpGet21164PerformanceVector( + IN ULONG BusInterruptLevel, + OUT PKIRQL Irql + ); + +ULONGLONG +HalpRead21164PerformanceCounter( + VOID + ); + +VOID +HalpWrite21164PerformanceCounter( + ULONGLONG PmCtr, + ULONG CBOXMux1, + ULONG CBOXMux2 + ); + +VOID +Halp21064PerformanceCounter0Interrupt ( + VOID + ); + +VOID +Halp21064PerformanceCounter1Interrupt ( + VOID + ); + +VOID +Halp21164PerformanceCounter0Interrupt ( + VOID + ); + +VOID +Halp21164PerformanceCounter1Interrupt ( + VOID + ); + +VOID +Halp21164PerformanceCounter2Interrupt ( + VOID + ); + +VOID +Halp21064WritePerformanceCounter( + IN ULONG PerformanceCounter, + IN BOOLEAN Enable, + IN ULONG MuxControl OPTIONAL, + IN ULONG EventCount OPTIONAL + ); + +VOID +Halp21064ClearLockRegister( + PVOID LockAddress + ); + +VOID +HalpMiniTlbSaveState( + VOID + ); + +VOID +HalpMiniTlbRestoreState( + VOID + ); + +ULONG +HalpMiniTlbAllocateEntry( + PVOID Qva, + PPHYSICAL_ADDRESS TranslatedAddress + ); + +VOID +HalpCleanIoBuffers( + IN PMDL Mdl, + IN BOOLEAN ReadOperation, + IN BOOLEAN DmaOperation + ); + +ULONG HalpPciLowLevelConfigRead( + ULONG BusNumber, + ULONG DeviceNumber, + ULONG FunctionNumber, + ULONG Register + ); + +#endif // _JXHALP_ diff --git a/private/ntos/nthals/halflex/alpha/jxmapio.c b/private/ntos/nthals/halflex/alpha/jxmapio.c new file mode 100644 index 000000000..c46ebb8ee --- /dev/null +++ b/private/ntos/nthals/halflex/alpha/jxmapio.c @@ -0,0 +1,103 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + jxmapio.c + +Abstract: + + This module implements the mapping of HAL I/O space a MIPS R3000 + or R4000 Jazz system. + +Author: + + David N. Cutler (davec) 28-Apr-1991 + +Environment: + + Kernel mode + +Revision History: + +--*/ + +#include "halp.h" + + +// +// Define global data used to locate the EISA control space and the realtime +// clock registers. +// + +PVOID HalpEisaControlBase[MAX_EISA_BUSSES]; +PVOID HalpEisaMemoryBase[MAX_EISA_BUSSES]; +PVOID HalpPciControlBase[MAX_PCI_BUSSES]; +PVOID HalpPciMemoryBase[MAX_PCI_BUSSES]; +PVOID HalpRealTimeClockBase; +PVOID HalpCacheFlushBase; + + +BOOLEAN +HalpMapIoSpace ( + VOID + ) + +/*++ + +Routine Description: + + This routine maps the HAL I/O space for a MIPS R3000 or R4000 Jazz + system. + +Arguments: + + None. + +Return Value: + + If the initialization is successfully completed, than a value of TRUE + is returned. Otherwise, a value of FALSE is returned. + +--*/ + +{ + // + // Map EISA control space. Map all 16 slots. This is done so the NMI + // code can probe the cards. + // + + HalpEisaControlBase[0] = HAL_MAKE_QVA(HalpIsaIoBasePhysical); + HalpEisaControlBase[1] = HAL_MAKE_QVA(HalpIsa1IoBasePhysical); + + // + // Map realtime clock registers. + // + + HalpRealTimeClockBase = (PVOID)((ULONG)(HAL_MAKE_QVA(HalpIsaIoBasePhysical)) + 0x71); + + // + // Map ISA Memory Space. + // + + HalpEisaMemoryBase[0] = HAL_MAKE_QVA(HalpIsaMemoryBasePhysical); + HalpEisaMemoryBase[1] = HAL_MAKE_QVA(HalpIsa1MemoryBasePhysical); + + // + // Map PCI control space. Map all 16 slots. This is done so the NMI + // code can probe the cards. + // + + HalpPciControlBase[0] = HAL_MAKE_QVA(HalpPciIoBasePhysical); + HalpPciControlBase[1] = HAL_MAKE_QVA(HalpPci1IoBasePhysical); + + // + // Map PCI Memory Space. + // + + HalpPciMemoryBase[0] = HAL_MAKE_QVA(HalpPciMemoryBasePhysical); + HalpPciMemoryBase[1] = HAL_MAKE_QVA(HalpPci1MemoryBasePhysical); + + return TRUE; +} diff --git a/private/ntos/nthals/halflex/alpha/minitlb.c b/private/ntos/nthals/halflex/alpha/minitlb.c new file mode 100644 index 000000000..0b29f5cd8 --- /dev/null +++ b/private/ntos/nthals/halflex/alpha/minitlb.c @@ -0,0 +1,221 @@ +/*++ + +Copyright (c) 1995 DeskStation Technology + +Module Name: + + minitlb.c + +Abstract: + + This module contains the support functions for the TLB that allows + access to the sparse address spaces. + +Author: + + Michael D. Kinney 8-Aug-1995 + +Environment: + + Kernel mode + +Revision History: + +--*/ + +#include "halp.h" + +#define MINI_TLB_ATTRIBUTES_HIGH 0xfffffc03 +#define MINI_TLB_ATTRIBUTES_LOW 0xc0000004 +#define MINI_TLB_ENTRY_HIGH 0xfffffc03 + +UCHAR HalpMiniTlbAttributesLookupTable[16] = { + 0, // ISA I/O Space 0x00000000 - 0x01ffffff + 0, // ISA Memory Space 0x00000000 - 0x01ffffff + 1, // PCI I/O Space 0x00000000 - 0x01ffffff + 1, // PCI Memory Space 0x00000000 - 0x01ffffff + 1, // PCI High Memory Space 0x40000000 - 0x41ffffff + 1, // PCI High Memory Space 0x42000000 - 0x43ffffff + 1, // PCI High Memory Space 0x44000000 - 0x45ffffff + 1, // PCI High Memory Space 0x46000000 - 0x47ffffff + 3, // PCI Config Type 0 Space Devices 0-13 0x00000000 - 0x01ffffff + 3, // PCI Config Type 0 Space Device 14 0x02000000 - 0x03ffffff + 3, // PCI Config Type 0 Space Device 15 0x04000000 - 0x05ffffff + 3, // PCI Config Type 0 Space Device 16 0x08000000 - 0x09ffffff + 3, // PCI Config Type 0 Space Device 17 0x10000000 - 0x11ffffff + 3, // PCI Config Type 0 Space Device 18 0x20000000 - 0x21ffffff + 3, // PCI Config Type 0 Space Device 19 0x40000000 - 0x41ffffff + 3 // PCI Config Type 1 Space 0x00000000 - 0x01ffffff + }; + +UCHAR HalpMiniTlbEntryLookupTable[16] = { + 0x80, // ISA I/O Space 0x00000000 - 0x01ffffff + 0x00, // ISA Memory Space 0x00000000 - 0x01ffffff + 0x80, // PCI I/O Space 0x00000000 - 0x01ffffff + 0x00, // PCI Memory Space 0x00000000 - 0x01ffffff + 0x20, // PCI High Memory Space 0x40000000 - 0x41ffffff + 0x21, // PCI High Memory Space 0x42000000 - 0x43ffffff + 0x22, // PCI High Memory Space 0x44000000 - 0x45ffffff + 0x23, // PCI High Memory Space 0x46000000 - 0x47ffffff + 0x00, // PCI Config Type 0 Space Devices 0-13 0x00000000 - 0x01ffffff + 0x01, // PCI Config Type 0 Space Device 14 0x02000000 - 0x03ffffff + 0x02, // PCI Config Type 0 Space Device 15 0x04000000 - 0x05ffffff + 0x04, // PCI Config Type 0 Space Device 16 0x08000000 - 0x09ffffff + 0x08, // PCI Config Type 0 Space Device 17 0x10000000 - 0x11ffffff + 0x10, // PCI Config Type 0 Space Device 18 0x20000000 - 0x21ffffff + 0x20, // PCI Config Type 0 Space Device 19 0x40000000 - 0x41ffffff + 0x80 // PCI Config Type 1 Space 0x00000000 - 0x01ffffff + }; + +ULONG HalpMiniTlbEntryAddressLow[4] = { + 0x1000000c, // Mini TLB Entry 0 + 0x5000000c, // Mini TLB Entry 1 + 0x9000000c, // Mini TLB Entry 2 + 0xd000000c // Mini TLB Entry 3 + }; + +UCHAR HalpMiniTlbAttributes = 0x00; +UCHAR HalpMiniTlbEntry[4] = {0x00,0x00,0x00,0x00}; + +UCHAR HalpMiniTlbTag[4] = {0xff, 0xff, 0xff, 0xff}; +ULONG HalpMiniTlbIndex = 0; +ULONG HalpMiniTlbEntries = 4; + +VOID +HalpMiniTlbProgramEntry( + ULONG Index + ) + +{ + HalpMiniTlbAttributes &= (~(0x03 << (Index * 2))); + HalpMiniTlbAttributes |= (HalpMiniTlbAttributesLookupTable[HalpMiniTlbTag[Index]] << (Index * 2)); + HalpMiniTlbEntry[Index] = HalpMiniTlbEntryLookupTable[HalpMiniTlbTag[Index]]; + HalpWriteAbsoluteUlong(MINI_TLB_ATTRIBUTES_HIGH,MINI_TLB_ATTRIBUTES_LOW,((ULONG)HalpMiniTlbAttributes)<<8); + HalpWriteAbsoluteUlong(MINI_TLB_ENTRY_HIGH,HalpMiniTlbEntryAddressLow[Index],((ULONG)HalpMiniTlbEntry[Index])<<8); +} + +VOID +HalpMiniTlbSaveState( + VOID + ) + +{ +} + +VOID +HalpMiniTlbRestoreState( + VOID + ) + +{ + ULONG i; + + for(i=0;i<4;i++) { + if (HalpMiniTlbTag[i]!=0xff) { + HalpMiniTlbProgramEntry(i); + } + } +} + +ULONG +HalpMiniTlbMatch( + PVOID Qva, + ULONG StartIndex + ) + +{ + ULONG Tag; + ULONG i; + + Tag = ((ULONG)(Qva) >> 25) & 0x0f; + for(i=StartIndex;i<4 && HalpMiniTlbTag[i]!=Tag;i++); + return(i); +} + +ULONG +HalpMiniTlbAllocateEntry( + PVOID Qva, + PPHYSICAL_ADDRESS TranslatedAddress + ) + +{ + ULONG Index; + + // + // Check for a tag match among the fixed TLB entries. + // + + Index = HalpMiniTlbMatch(Qva,HalpMiniTlbEntries); + + if (Index==4) { + + // + // There was no match, so check for an available TLB entry. + // + + if (HalpMiniTlbEntries<=1) { + + // + // No TLB entries were available. Return NULL + // + + return(FALSE); + } + + // + // A TLB entry was available. Fill it in. + // + + HalpMiniTlbEntries--; + Index = HalpMiniTlbEntries; + HalpMiniTlbTag[Index] = (UCHAR)(((ULONG)(Qva) >> 25) & 0x0f); + HalpMiniTlbProgramEntry(Index); + + // + // Reset the random replacement index + // + + HalpMiniTlbIndex = 0; + } + + TranslatedAddress->QuadPart = ROGUE_TRANSLATED_BASE_PHYSICAL; + TranslatedAddress->QuadPart += (Index << 30) | (((ULONG)(Qva) & 0x01ffffff) << IO_BIT_SHIFT); + return(TRUE); +} + + +PVOID +HalpMiniTlbResolve( + PVOID Qva + ) + +{ + ULONG Index; + + // + // Check for a tag match among all the TLB entries + // + + Index = HalpMiniTlbMatch(Qva,0); + + if (Index==4) { + + // + // There was no match, so replace one of the TLB entries + // + + Index = HalpMiniTlbIndex; + HalpMiniTlbTag[Index] = (UCHAR)(((ULONG)(Qva) >> 25) & 0x0f); + HalpMiniTlbProgramEntry(Index); + + // + // Point random replacement index at next available entry. + // + + HalpMiniTlbIndex++; + if (HalpMiniTlbIndex >= HalpMiniTlbEntries) { + HalpMiniTlbIndex = 0; + } + } + return( (PVOID)(DTI_QVA_ENABLE | ((0x08 | Index) << 25) | ((ULONG)(Qva) & 0x01ffffff)) ); +} diff --git a/private/ntos/nthals/halflex/alpha/pcisup.c b/private/ntos/nthals/halflex/alpha/pcisup.c new file mode 100644 index 000000000..6d708835e --- /dev/null +++ b/private/ntos/nthals/halflex/alpha/pcisup.c @@ -0,0 +1,897 @@ +/*++ + +Copyright (c) 1995 DeskStation Technology + +Module Name: + + pcisup.c + +Abstract: + + This module contains the routines that support PCI configuration cycles + and PCI interrupts. + +Author: + + Michael D. Kinney 30-Apr-1995 + +Environment: + + Kernel mode + +Revision History: + + +--*/ + +#include "halp.h" +#include "pci.h" +#include "pcip.h" + +#define INVALID_PCI_CONFIGURATION_ADDRESS (0xffffff00) +#define NO_PCI_DEVSEL_DATA_VALUE (0xffffffff) + +// +// The following tables are used to map between PCI interrupt pins, PCI interrupt lines, +// and virtual ISA interrupt indexes. The Uniflex architecture uses a 16 bit interrupt +// controller for ISA interrupts and all PCI interrupts. An InterruptLine value of 0x20 +// is reserved for the ISA PIC. InterruptLine values between 0x10 and 0x20 are reserved +// for PCI devices. InterruptLine values between 0x00 and 0x0f are reserved for ISA IRQs. +// + +UCHAR Treb13InterruptLineToBit[0x11] = {7,2,3,1,4,5,6,9,10,11,16,16,16,16,15,14,0}; +UCHAR Treb13BitToInterruptLine[0x10] = {0x10,0x03,0x01,0x02,0x04,0x05,0x06,0x00,0x00,0x07,0x08,0x09,0x00,0x00,0x0f,0x0e}; +UCHAR Treb13InterruptLineToVirtualIsa[0x10] = {0,1,2,3,8,9,10,11,4,5,0,0,0,0,0,0}; +UCHAR Treb13VirtualIsaToInterruptLine[0x10] = {0x10,0x11,0x12,0x13,0x18,0x19,0,0,0x14,0x15,0x16,0x17,0,0,0,0}; + +UCHAR Treb20InterruptLineToBit[0x11] = {1,2,3,4,5,6,7,8,9,16,16,16,16,16,16,16,0}; +UCHAR Treb20BitToInterruptLine[0x10] = {0x10,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00}; +UCHAR Treb20InterruptLineToVirtualIsa[0x11] = {0,1,2,3,4,5,6,7,8,0,0,0,0,0,0,0,9}; +UCHAR Treb20VirtualIsaToInterruptLine[0x10] = {0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x20,0,0,0,0,0,0}; + +// +// Interrupt mask for all active PCI interrupts including ISA Bus PICs +// + +static volatile ULONG HalpPciInterruptMask; + +// +// Interrupt mask for PCI interrupts that have been connected through device drivers. +// + +static volatile ULONG HalpPciDeviceInterruptMask; + +// +// Interrupt mask showing which bit cooresponds to ISA Bus #0 PIC +// + +static volatile ULONG HalpEisaInterruptMask; + +// +// Interrupt mask showing which bit cooresponds to ISA Bus #1 PIC +// + +static volatile ULONG HalpEisa1InterruptMask; + +VOID +HalpWritePciInterruptRegister( + VOID + ) + +/*++ + +Routine Description: + + This function writes the interrupt mask register for PCI interrupts. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + + { + if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) { + HalpWriteAbsoluteUlong(0xfffffca8,0x00000010, (HalpPciInterruptMask & 0xff) << 8); + HalpWriteAbsoluteUlong(0xfffffc88,0x00000010, HalpPciInterruptMask & 0xff00); + } else { + HalpWriteAbsoluteUlong(0xfffffc03,0x2000000c, HalpPciInterruptMask & 0xff); + HalpWriteAbsoluteUlong(0xfffffc03,0x6000000c, HalpPciInterruptMask >> 8); + } + } + +ULONG +HalpReadPciInterruptRegister( + VOID + ) + +/*++ + +Routine Description: + + This function reads the interrupt status register for PCI interrupts. + +Arguments: + + None. + +Return Value: + + The lower 16 bits contains the status of each interrupt line going to the PCI + interrupt controller. + +--*/ + + { + if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) { + return ( ((HalpReadAbsoluteUlong(0xfffffca8,0x00000000)>>8)&0xff) | + (HalpReadAbsoluteUlong(0xfffffc88,0x00000000) & 0xff00) ); + } else { + return ( (HalpReadAbsoluteUlong(0xfffffc03,0x2000000c) &0xff) | + ((HalpReadAbsoluteUlong(0xfffffc03,0x6000000c)<<8) & 0xff00) ); + } + } + +ULONG +HalpGetModuleChipSetRevision( + VOID + ) + +/*++ + +Routine Description: + + This function identifies the chip set revision of the processor module installed in the + system. + +Arguments: + + None. + +Return Value: + + The chip set revision. + +--*/ + +{ + ULONG Temp; + ULONG ReturnValue; + + if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) { + Temp = HalpPciInterruptMask; + HalpPciInterruptMask = 0; + HalpWritePciInterruptRegister(); + ReturnValue = (HalpReadPciInterruptRegister() >> 4) & 0x0f; + HalpPciInterruptMask = Temp; + HalpWritePciInterruptRegister(); + } + if (HalpIoArchitectureType == EV4_PROCESSOR_MODULE) { + ReturnValue = HalpReadAbsoluteUlong(0xfffffc03,0xe000000c); + ReturnValue = (ReturnValue & 0x0f) ^ ((ReturnValue >> 4) & 0x0f); + } + return(ReturnValue); +} + +VOID +HalpSetPciInterruptBit ( + ULONG Bit + ) + +/*++ + +Routine Description: + + This function sets a bit in the PCI interrupt mask and writes the new mask + to the interrupt controller. + +Arguments: + + Bit - The bit number to set in the PCI interrupt mask. + +Return Value: + + None. + +--*/ + +{ + HalpPciDeviceInterruptMask = HalpPciDeviceInterruptMask | (1<= UNIFLEX_PCI_VECTORS && Vector <= UNIFLEX_MAXIMUM_PCI_VECTOR) { + HalpSetPciInterruptBit(HalpInterruptLineToBit[Vector-UNIFLEX_PCI_VECTORS]); + } +} + +VOID +HalpDisablePciInterrupt ( + IN ULONG Vector + ) + +/*++ + +Routine Description: + + This function disables a PCI interrupt. + +Arguments: + + Vector - Specifies the interrupt to disable. + +Return Value: + + None. + +--*/ + +{ + if (Vector >= UNIFLEX_PCI_VECTORS && Vector <= UNIFLEX_MAXIMUM_PCI_VECTOR) { + HalpClearPciInterruptBit(HalpInterruptLineToBit[Vector-UNIFLEX_PCI_VECTORS]); + } +} + +ULONG +HalpVirtualIsaInterruptToInterruptLine ( + IN ULONG Index + ) + +/*++ + +Routine Description: + + This function maps a virtual ISA interrupt to a PCI interrupt line value. + This provides the ability to use an ISA device driver on a PCI device. + +Arguments: + + Index - Index into a platform specific table that maps PCI interrupts to + virtual ISA interrupts. + +Return Value: + + None. + +--*/ + +{ + return(HalpVirtualIsaToInterruptLine[Index]); +} + + +ULONG HalpClearLockCacheLineAddress[32]; + +BOOLEAN +HalpPciDispatch( + IN PKINTERRUPT Interrupt, + IN PVOID ServiceContext + ) + +/*++ + +Routine Description: + + This is the interrupt dispatcher for all PCI interrupts. + +Arguments: + + Interrupt - Supplies a pointer to the interrupt object. + + ServiceContext - not used. + +Return Value: + + Returns the value returned from the second level routine. + +--*/ + +{ + ULONG PciInterruptStatus; + PULONG dispatchCode; + PKINTERRUPT interruptObject; + USHORT PCRInOffset; + BOOLEAN returnValue = FALSE; + ULONG i; + + if (HalpIoArchitectureType != EV5_PROCESSOR_MODULE) { + Halp21064ClearLockRegister(&(HalpClearLockCacheLineAddress[16])); + } + + // + // Get the active interrupt bits + // + + PciInterruptStatus = HalpReadPciInterruptRegister(); + + // + // See if this is the interrupt for ISA Bus #0 PIC + // + + if (PciInterruptStatus & HalpEisaInterruptMask) { + + returnValue = HalpEisaDispatch(Interrupt,ServiceContext,0); + + // + // If there really was an interrupt on ISA Bus #0, then return now. + // + + if (returnValue) { + return(returnValue); + } + } + + // + // See if this is the interrupt for ISA Bus #1 PIC + // + + if (PciInterruptStatus & HalpEisa1InterruptMask) { + + returnValue = HalpEisaDispatch(Interrupt,ServiceContext,1); + + // + // If there really was an interrupt on ISA Bus #1, then return now. + // + + if (returnValue) { + return(returnValue); + } + } + + // + // Only keep interrupt bits that have been connected by device drivers. + // + + PciInterruptStatus &= HalpPciDeviceInterruptMask; + + // + // Dispatch to the ISRs of interrupts that have been connected by device drivers. + // + + for(i=0;i<16;i++) { + if (PciInterruptStatus & (1<InterruptRoutine[PCRInOffset]); + interruptObject = CONTAINING_RECORD(dispatchCode, + KINTERRUPT, + DispatchCode); + + returnValue = + ((PSECONDARY_DISPATCH)interruptObject->DispatchAddress) + (interruptObject); + } + } + + return(returnValue); +} + +UCHAR HalpGetInterruptLine(ULONG BusNumber,ULONG DeviceNumber,ULONG InterruptPin) + +/*++ + +Routine Description: + + This routine maps a PCI interrupt described by the device's bus number, device number, and + interrupt pin into the interrupt line value that is stored in the PCI config header. + +Arguments: + + BusNumber - PCI bus number of the device. + + DeviceNumber - PCI device number of the device. + + InterruptPin - PCI interrupt pin of the device (A=1,B=2,C=3,D=4). + +Return Value: + + Returns the PCI Interrupt Line value for the PCI device. + +--*/ + +{ + UCHAR InterruptLine; + + if (HalpMotherboardType == TREBBIA13) { + + if (BusNumber > 1) + { + BusNumber = 1; + } + + switch (BusNumber<<16 | DeviceNumber<<8 | InterruptPin) { + case 0x010401 : InterruptLine = 0x10; break; // Bus 1, Device 4, Int A + case 0x010601 : InterruptLine = 0x11; break; // Bus 1, Device 6, Int A + case 0x010501 : InterruptLine = 0x12; break; // Bus 1, Device 5, Int A + case 0x010701 : InterruptLine = 0x13; break; // Bus 1, Device 7, Int A + case 0x010402 : InterruptLine = 0x17; break; // Bus 1, Device 4, Int B + case 0x010602 : InterruptLine = 0x14; break; // Bus 1, Device 6, Int B + case 0x010502 : InterruptLine = 0x14; break; // Bus 1, Device 5, Int B + case 0x010702 : InterruptLine = 0x17; break; // Bus 1, Device 7, Int B + case 0x010403 : InterruptLine = 0x18; break; // Bus 1, Device 4, Int C + case 0x010603 : InterruptLine = 0x15; break; // Bus 1, Device 6, Int C + case 0x010503 : InterruptLine = 0x15; break; // Bus 1, Device 5, Int C + case 0x010703 : InterruptLine = 0x18; break; // Bus 1, Device 7, Int C + case 0x010404 : InterruptLine = 0x19; break; // Bus 1, Device 4, Int D + case 0x010604 : InterruptLine = 0x16; break; // Bus 1, Device 6, Int D + case 0x010504 : InterruptLine = 0x16; break; // Bus 1, Device 5, Int D + case 0x010704 : InterruptLine = 0x19; break; // Bus 1, Device 7, Int D + case 0x000d01 : InterruptLine = 0x1e; break; // Bus 0, Device 13, Int A + case 0x000f01 : InterruptLine = 0x1f; break; // Bus 0, Device 15, Int A + case 0x001001 : InterruptLine = 0x20; break; // Bus 0, Device 16, Int A + default : InterruptLine = 0xff; break; + } + } + + if (HalpMotherboardType == TREBBIA20) { + + if (BusNumber == 0) { + return(0xff); + } + + if (BusNumber >= HalpSecondPciBridgeBusNumber) { + BusNumber = 1; + } else { + BusNumber = 0; + } + + switch (BusNumber<<16 | DeviceNumber<<8 | InterruptPin) { + case 0x000401 : InterruptLine = 0x20; break; + + case 0x000501 : + case 0x000603 : + case 0x000704 : InterruptLine = 0x10; break; + + case 0x000502 : + case 0x000604 : + case 0x000701 : InterruptLine = 0x11; break; + + case 0x000503 : + case 0x000601 : + case 0x000702 : InterruptLine = 0x12; break; + + case 0x000504 : + case 0x000602 : + case 0x000703 : InterruptLine = 0x13; break; + + case 0x010401 : + case 0x010504 : + case 0x010603 : InterruptLine = 0x14; break; + + case 0x010402 : + case 0x010501 : + case 0x010604 : InterruptLine = 0x15; break; + + case 0x010403 : + case 0x010502 : + case 0x010601 : InterruptLine = 0x16; break; + + case 0x010404 : + case 0x010503 : + case 0x010602 : InterruptLine = 0x17; break; + + case 0x010701 : InterruptLine = 0x18; break; + + default : InterruptLine = 0xff; break; + } + } + + return(InterruptLine); +} + + +VOID +HalpConnectInterruptDispatchers( + VOID + ) + +/*++ + +Routine Description: + + This function connects the PCI interrupt dispatch routine and enables + ISA interrupts so they will generate processor interrupts. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + UCHAR InterruptLine; + + if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) { + PCR->InterruptRoutine[22] = (PKINTERRUPT_ROUTINE)HalpPciDispatch; + } else { + PCR->InterruptRoutine[14] = (PKINTERRUPT_ROUTINE)HalpPciDispatch; + } + +//DbgPrint("Intel82378 : Bus=%d Device=%d\n\r",HalpIntel82378BusNumber,HalpIntel82378DeviceNumber); +//DbgPrint("SecondIntel82378 : Bus=%d Device=%d\n\r",HalpSecondPciBridgeBusNumber,HalpSecondIntel82378DeviceNumber); + + InterruptLine = HalpGetInterruptLine(HalpIntel82378BusNumber,HalpIntel82378DeviceNumber,1); + HalpEisaInterruptMask = 0x0000; + if (InterruptLine != 0xff) { + HalpEisaInterruptMask = (1 << HalpInterruptLineToBit[InterruptLine-0x10]) & 0xffff; + } + + InterruptLine = HalpGetInterruptLine(HalpSecondPciBridgeBusNumber,HalpSecondIntel82378DeviceNumber,1); + HalpEisa1InterruptMask = 0x0000; + if (InterruptLine != 0xff) { + HalpEisa1InterruptMask = (1 << HalpInterruptLineToBit[InterruptLine-0x10]) & 0xffff; + } + +//DbgPrint("HalpEisaInterruptMask = %08x\n\r",HalpEisaInterruptMask); +//DbgPrint("HalpEisa1InterruptMask = %08x\n\r",HalpEisa1InterruptMask); + + // + // Enable ISA Interrupts on Apocolypse's PIC + // + + HalpPciDeviceInterruptMask = 0x0000; + HalpPciInterruptMask = HalpEisaInterruptMask | HalpEisa1InterruptMask; + HalpWritePciInterruptRegister(); +} + + +VOID +HalpDisableAllInterrupts( + VOID + ) + +/*++ + +Routine Description: + + This function disables all external interrupt sources. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + ULONG i; + + // + // Mask off all ISA Interrupts + // + + for(i=0;iu.AsULONG = INVALID_PCI_CONFIGURATION_ADDRESS; + return; + } + + if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) { + pPciAddr->u.AsULONG = 1 << (3 + Slot.u.bits.DeviceNumber); + } else { + pPciAddr->u.AsULONG = 1 << (11 + Slot.u.bits.DeviceNumber); + } + pPciAddr->u.bits0.FunctionNumber = Slot.u.bits.FunctionNumber; + pPciAddr->u.bits0.Reserved1 = PciConfigType0; + if (HalpIoArchitectureType == EV4_PROCESSOR_MODULE) { + pPciAddr->u.AsULONG &= 0x01ffffff; + pPciAddr->u.AsULONG += (ULONG)HAL_MAKE_QVA(HalpPciConfig0BasePhysical); + if (Slot.u.bits.DeviceNumber >= 14 && Slot.u.bits.DeviceNumber <= 19) { + pPciAddr->u.AsULONG += (Slot.u.bits.DeviceNumber-13) << 25; + } + } + } else { + + // + // See if this is a nonexistant PCI device on the otherside of the First PCI-PCI Bridge + // + + if (BusNumber == 1 && (1 << Slot.u.bits.DeviceNumber) & HalpNonExistentPci1DeviceMask) { + pPciAddr->u.AsULONG = INVALID_PCI_CONFIGURATION_ADDRESS; + return; + } + + // + // See if this is a nonexistant PCI device on the otherside of the Second PCI-PCI Bridge + // + + if (BusNumber == HalpSecondPciBridgeBusNumber && (1 << Slot.u.bits.DeviceNumber) & HalpNonExistentPci2DeviceMask) { + pPciAddr->u.AsULONG = INVALID_PCI_CONFIGURATION_ADDRESS; + return; + } + + // + // Initialize PciAddr for a type 1 configuration cycle + // + + pPciAddr->u.AsULONG = 0; + if (HalpIoArchitectureType == EV4_PROCESSOR_MODULE) { + pPciAddr->u.AsULONG = (ULONG)HAL_MAKE_QVA(HalpPciConfig1BasePhysical); + } + pPciAddr->u.bits1.BusNumber = BusNumber; + pPciAddr->u.bits1.FunctionNumber = Slot.u.bits.FunctionNumber; + pPciAddr->u.bits1.DeviceNumber = Slot.u.bits.DeviceNumber; + pPciAddr->u.bits1.Reserved1 = PciConfigType1; + } + + return; +} + +ULONG READ_CONFIG_Ux( + IN PVOID ConfigurationAddress, + IN ULONG ConfigurationType, + IN ULONG Offset + ) + +{ + switch(ConfigurationType) { + case PciConfigType0 : + return(HalpReadAbsoluteUlong((ULONG)(HalpPciConfig0BasePhysical >> 32), + (ULONG)HalpPciConfig0BasePhysical + ((ULONG)ConfigurationAddress << IO_BIT_SHIFT) + Offset)); + case PciConfigType1 : + return(HalpReadAbsoluteUlong((ULONG)(HalpPciConfig1BasePhysical >> 32), + (ULONG)HalpPciConfig1BasePhysical + ((ULONG)ConfigurationAddress << IO_BIT_SHIFT) + Offset)); + } + return(NO_PCI_DEVSEL_DATA_VALUE); +} + +VOID WRITE_CONFIG_Ux( + IN PVOID ConfigurationAddress, + IN ULONG ConfigurationType, + IN ULONG Offset, + IN ULONG Value + ) + +{ + switch(ConfigurationType) { + case PciConfigType0 : + HalpWriteAbsoluteUlong((ULONG)(HalpPciConfig0BasePhysical >> 32), + (ULONG)HalpPciConfig0BasePhysical + ((ULONG)ConfigurationAddress << IO_BIT_SHIFT) + Offset, + Value); + break; + case PciConfigType1 : + HalpWriteAbsoluteUlong((ULONG)(HalpPciConfig1BasePhysical >> 32), + (ULONG)HalpPciConfig1BasePhysical + ((ULONG)ConfigurationAddress << IO_BIT_SHIFT) + Offset, + Value); + break; + } +} + +UCHAR +READ_CONFIG_UCHAR( + IN PVOID ConfigurationAddress, + IN ULONG ConfigurationType + ) + +{ + if (((ULONG)ConfigurationAddress & 0xffffff00) == INVALID_PCI_CONFIGURATION_ADDRESS) { + return((UCHAR)NO_PCI_DEVSEL_DATA_VALUE); + } + if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) { + return((UCHAR)(READ_CONFIG_Ux(ConfigurationAddress,ConfigurationType,IO_BYTE_LEN) >> (8*((ULONG)ConfigurationAddress & 0x03)))); + } else { + return(READ_REGISTER_UCHAR(ConfigurationAddress)); + } +} + +USHORT +READ_CONFIG_USHORT( + IN PVOID ConfigurationAddress, + IN ULONG ConfigurationType + ) + +{ + if (((ULONG)ConfigurationAddress & 0xffffff00) == INVALID_PCI_CONFIGURATION_ADDRESS) { + return((USHORT)NO_PCI_DEVSEL_DATA_VALUE); + } + if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) { + return((USHORT)(READ_CONFIG_Ux(ConfigurationAddress,ConfigurationType,IO_WORD_LEN) >> (8*((ULONG)ConfigurationAddress & 0x03)))); + } else { + return(READ_REGISTER_USHORT(ConfigurationAddress)); + } +} + +ULONG +READ_CONFIG_ULONG( + IN PVOID ConfigurationAddress, + IN ULONG ConfigurationType + ) + +{ + if (((ULONG)ConfigurationAddress & 0xffffff00) == INVALID_PCI_CONFIGURATION_ADDRESS) { + return((ULONG)NO_PCI_DEVSEL_DATA_VALUE); + } + if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) { + return(READ_CONFIG_Ux(ConfigurationAddress,ConfigurationType,IO_LONG_LEN) >> (8*((ULONG)ConfigurationAddress & 0x03))); + } else { + return(READ_REGISTER_ULONG(ConfigurationAddress)); + } +} + +VOID +WRITE_CONFIG_UCHAR( + IN PVOID ConfigurationAddress, + IN UCHAR ConfigurationData, + IN ULONG ConfigurationType + ) + +{ + if (((ULONG)ConfigurationAddress & 0xffffff00) != INVALID_PCI_CONFIGURATION_ADDRESS) { + if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) { + WRITE_CONFIG_Ux(ConfigurationAddress,ConfigurationType,IO_BYTE_LEN,(ULONG)ConfigurationData << (8*((ULONG)ConfigurationAddress & 0x03))); + } else { + WRITE_REGISTER_UCHAR(ConfigurationAddress,ConfigurationData); + } + } +} + +VOID +WRITE_CONFIG_USHORT( + IN PVOID ConfigurationAddress, + IN USHORT ConfigurationData, + IN ULONG ConfigurationType + ) + +{ + if (((ULONG)ConfigurationAddress & 0xffffff00) != INVALID_PCI_CONFIGURATION_ADDRESS) { + if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) { + WRITE_CONFIG_Ux(ConfigurationAddress,ConfigurationType,IO_WORD_LEN,(ULONG)ConfigurationData << (8*((ULONG)ConfigurationAddress & 0x03))); + } else { + WRITE_REGISTER_USHORT(ConfigurationAddress,ConfigurationData); + } + } +} + +VOID +WRITE_CONFIG_ULONG( + IN PVOID ConfigurationAddress, + IN ULONG ConfigurationData, + IN ULONG ConfigurationType + ) + +{ + if (((ULONG)ConfigurationAddress & 0xffffff00) != INVALID_PCI_CONFIGURATION_ADDRESS) { + if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) { + WRITE_CONFIG_Ux(ConfigurationAddress,ConfigurationType,IO_LONG_LEN,ConfigurationData << (8*((ULONG)ConfigurationAddress & 0x03))); + } else { + WRITE_REGISTER_ULONG(ConfigurationAddress,ConfigurationData); + } + } +} + +ULONG HalpPciLowLevelConfigRead( + ULONG BusNumber, + ULONG DeviceNumber, + ULONG FunctionNumber, + ULONG Register + ) + +{ + PCI_SLOT_NUMBER SlotNumber; + PCI_CFG_CYCLE_BITS PciCfg; + ULONG ConfigurationCycleType; + + SlotNumber.u.AsULONG = 0; + SlotNumber.u.bits.DeviceNumber = DeviceNumber; + SlotNumber.u.bits.FunctionNumber = FunctionNumber; + + HalpPCIConfigAddr(BusNumber,SlotNumber,&PciCfg); + ConfigurationCycleType = PciCfg.u.bits.Reserved1; + PciCfg.u.bits.Reserved1 = 0; + PciCfg.u.bits0.RegisterNumber = Register>>2; + return(READ_CONFIG_ULONG((PVOID)PciCfg.u.AsULONG,ConfigurationCycleType)); +} diff --git a/private/ntos/nthals/halflex/alpha/perfcntr.c b/private/ntos/nthals/halflex/alpha/perfcntr.c new file mode 100644 index 000000000..d9a0c4975 --- /dev/null +++ b/private/ntos/nthals/halflex/alpha/perfcntr.c @@ -0,0 +1,262 @@ +/*++ + +Copyright (c) 1992, 1993 Digital Equipment Corporation + +Module Name: + + perfcntr.c + +Abstract: + + This module implements the interfaces that access the system + performance counter and the calibrated stall. The functions implemented + in this module are suitable for uniprocessor systems only. + +Author: + + Jeff McLeman (mcleman) 05-June-1992 + +Environment: + + Kernel mode + +Revision History: + + + Rod Gamache [DEC] 9-Mar-1993 + Fix profile clock. + + +--*/ + +#include "halp.h" +#include "eisa.h" + +// +// Define and initialize the 64-bit count of total system cycles used +// as the performance counter. +// + +ULONGLONG HalpCycleCount = 0; + + +LARGE_INTEGER +KeQueryPerformanceCounter ( + OUT PLARGE_INTEGER Frequency OPTIONAL + ) + +/*++ + +Routine Description: + + This routine returns the current performance counter value and the + performance counter frequency. + +Arguments: + + Frequency - Supplies an optional pointer to a variable which receives + the performance counter frequency in Hertz. + +Return Value: + + The current performance counter value is returned as the function + value. + +--*/ + +{ + + LARGE_INTEGER LocalRpccTime; + ULONG RpccValue; + + // + // Obtain the current value of the processor cycle counter and adjust + // the upper 32 bits if a roll-over occurred since the last time the + // Rpcc value was checked (at least oncce per clock interrupt). This + // code may be interrupted so we must fetch HalpRpccTimec atomically. + // + + *(PULONGLONG)&LocalRpccTime = HalpCycleCount; + RpccValue = HalpRpcc(); + if (RpccValue < LocalRpccTime.LowPart) { + LocalRpccTime.HighPart += 1; + } + LocalRpccTime.LowPart = RpccValue; + + + // + // If the frequency parameter is specified, then return the performance + // counter frequency as the current system time frequency. + // + + if (ARGUMENT_PRESENT(Frequency) != FALSE) { + Frequency->LowPart = HalpClockFrequency; + Frequency->HighPart = 0; + } + + // + // Return the current processor cycle counter as the function value. + // + + return LocalRpccTime; +} + + +VOID +HalCalibratePerformanceCounter ( + IN volatile PLONG Number + ) + +/*++ + +Routine Description: + + This routine resets the performance counter value for the current + processor to zero. The reset is done such that the resulting value + is closely synchronized with other processors in the configuration. + +Arguments: + + Number - Supplies a pointer to count of the number of processors in + the configuration. + +Return Value: + + None. + +--*/ + +{ + +//HalDisplayString("HalCalibratePerformanceCounter()\n\r"); + + // + // ****** Warning ****** + // + // This is a stub routine. It should clear the current value of the + // performance counter. It is really only needed in an MP system where, + // close, but not exact synchronization of the performance counters + // are needed. See MIPS code in halfxs\mips\j4prof.c for a method of + // synchronizing. + // + + return; +} + + +VOID +HalpCheckPerformanceCounter( + VOID + ) +/*++ + +Routine Description: + + This function is called every system clock interrupt in order to + check for wrap of the performance counter. The function must handle + a wrap if it is detected. + + N.B. - This function must be called at CLOCK_LEVEL. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + + LARGE_INTEGER LocalRpccTime; + ULONG RpccValue; + + // + // Update the low part of the performance counter directly from the + // rpcc count. Check for wrap of the rpcc count, if wrap has occurred + // then increment the high part of the performance counter. + // + + LocalRpccTime.QuadPart = HalpCycleCount; + RpccValue = HalpRpcc(); + + if (RpccValue < LocalRpccTime.LowPart) { + LocalRpccTime.HighPart += 1; + } + + LocalRpccTime.LowPart = RpccValue; + + HalpCycleCount = LocalRpccTime.QuadPart; + + return; + +} + + +VOID +KeStallExecutionProcessor ( + IN ULONG Microseconds + ) + +/*++ + +Routine Description: + + This function stalll execution of the current processor for the specified + number of microseconds. + +Arguments: + + Microseconds - Supplies the number of microseconds to stall. + +Return Value: + + None. + +--*/ + +{ + + LONG StallCyclesRemaining; // signed value + ULONG PreviousRpcc, CurrentRpcc; + + // + // Get the value of the RPCC as soon as we enter + // + + PreviousRpcc = HalpRpcc(); + + // + // Compute the number of cycles to stall + // + + StallCyclesRemaining = Microseconds * HalpClockMegaHertz; + + // + // Wait while there are stall cycles remaining. + // The accuracy of this routine is limited by the + // length of this while loop. + // + + while (StallCyclesRemaining > 0) { + + CurrentRpcc = HalpRpcc(); + + // + // The subtraction always works because the Rpcc + // is a wrapping long-word. If it wraps, we still + // get the positive number we want. + // + + StallCyclesRemaining -= (CurrentRpcc - PreviousRpcc); + + // + // remember this RPCC value + // + + PreviousRpcc = CurrentRpcc; + } + +} + diff --git a/private/ntos/nthals/halflex/alpha/portsup.c b/private/ntos/nthals/halflex/alpha/portsup.c new file mode 100644 index 000000000..ec96fcebd --- /dev/null +++ b/private/ntos/nthals/halflex/alpha/portsup.c @@ -0,0 +1,93 @@ +/*++ + +Copyright (c) 1995 DeskStation Technology + +Module Name: + + portsup.c + +Abstract: + + This module implements the code that provides the resources required to + access the serial port that is used for the kernel debugger. + +Author: + + Michael D. Kinney 30-Apr-1995 + +Environment: + + Kernel mode + +Revision History: + +--*/ + +#include "halp.h" + +#define SERIAL_PORT_COM1 0x3F8 + +VOID +HalpGetIoArchitectureType( + VOID + ); + +PUCHAR HalpAllocateKdPortResources( + OUT PVOID *SP_READ, + OUT PVOID *SP_WRITE + ) + +/*++ + +Routine Description: + + This function allocates the resources needed by the kernel debugger to + access a serial port. For an ALPHA processor, all I/O ports can be + accessed through super page addresses, so this function just maps the + serial port into the super page address range. + +Arguments: + + SP_READ - Quasi virtual address to use for I/O read operations. + + SP_WRITE - Quasi virtual address to use for I/O write operations. + +Return Value: + + The bus relative address of the COM port being used as a kernel debugger. + +--*/ + +{ + HalpGetIoArchitectureType(); + + *SP_READ = (PVOID)((ULONG)(HAL_MAKE_QVA(HalpIsaIoBasePhysical)) + SERIAL_PORT_COM1); + *SP_WRITE = (PVOID)((ULONG)(HAL_MAKE_QVA(HalpIsaIoBasePhysical)) + SERIAL_PORT_COM1); + + return((PUCHAR)(SERIAL_PORT_COM1)); +} + +VOID HalpFreeKdPortResources( + VOID + ) + +/*++ + +Routine Description: + + This function deallocates the resources needed by the kernel debugger to + access a serial port. For an ALPHA processor, no resources were actually + allocated, so this is a NULL function. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ +} diff --git a/private/ntos/nthals/halflex/alpha/xxidle.s b/private/ntos/nthals/halflex/alpha/xxidle.s new file mode 100644 index 000000000..0d53d7aed --- /dev/null +++ b/private/ntos/nthals/halflex/alpha/xxidle.s @@ -0,0 +1,62 @@ +// TITLE("Processor Idle Support") +//++ +// +// Copyright (c) 1992 Digital Equipment Corporation +// Copyright (c) 1993 Digital Equipment Corporation +// +// Module Name: +// +// idle.s +// +// Abstract: +// +// This module implements the HalProcessorIdle interface +// +// Author: +// +// John Vert (jvert) 11-May-1994 +// +// Environment: +// +// Revision History: +// +//-- +#include "halalpha.h" + + + SBTTL("Processor Idle") +//++ +// +// VOID +// HalProcessorIdle( +// VOID +// ) +// +// Routine Description: +// +// This function is called when the current processor is idle with +// interrupts disabled. There is no thread active and there are no +// DPCs to process. Therefore, power can be switched to a standby +// mode until the the next interrupt occurs on the current processor. +// +// N.B. This routine is entered with interrupts disabled. This routine +// must do any power management enabling necessary, enable interrupts, +// then either return or wait for an interrupt. +// +// Arguments: +// +// None. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalProcessorIdle) + + ENABLE_INTERRUPTS // no power management, just + // enable interrupts and return + ret zero, (ra) + + .end HalProcessorIdle diff --git a/private/ntos/nthals/halflex/alpha/xxinitnt.c b/private/ntos/nthals/halflex/alpha/xxinitnt.c new file mode 100644 index 000000000..45e0cb356 --- /dev/null +++ b/private/ntos/nthals/halflex/alpha/xxinitnt.c @@ -0,0 +1,194 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + xxinitnt.c + +Abstract: + + + This module implements the interrupt initialization for a MIPS R3000 + or R4000 system. + +Author: + + David N. Cutler (davec) 26-Apr-1991 + +Environment: + + Kernel mode only. + +Revision History: + +--*/ + +#include "halp.h" + + +UCHAR Halp21164IrqlTable[] = {00, // Irql 0 + 01, // Irql 1 + 02, // Irql 2 + 20, // Irql 3 + 21, // Irql 4 + 22, // Irql 5 + 23, // Irql 6 + 31}; // Irql 7 + +// +// HalpClockFrequency is the processor cycle counter frequency in units +// of cycles per second (Hertz). It is a large number (e.g., 125,000,000) +// but will still fit in a ULONG. +// +// HalpClockMegaHertz is the processor cycle counter frequency in units +// of megahertz. It is a small number (e.g., 125) and is also the number +// of cycles per microsecond. The assumption here is that clock rates will +// always be an integral number of megahertz. +// +// Having the frequency available in both units avoids multiplications, or +// especially divisions in time critical code. +// + +#define DEFAULT_21164_PROCESSOR_FREQUENCY_MHZ 300; +#define DEFAULT_21064_PROCESSOR_FREQUENCY_MHZ 275; + +ULONG HalpClockFrequency; +ULONG HalpClockMegaHertz = DEFAULT_21064_PROCESSOR_FREQUENCY_MHZ; + +BOOLEAN +HalpInitializeInterrupts ( + VOID + ) + +/*++ + +Routine Description: + + This function initializes interrupts for a MIPS R3000 or R4000 system. + +Arguments: + + None. + +Return Value: + + A value of TRUE is returned if the initialization is successfully + completed. Otherwise a value of FALSE is returned. + +--*/ + +{ + ULONG Index; + ULONG Irq; + KIRQL Irql; + UCHAR Priority; + ULONG Vector; + + // + // Mask sure that all processor interrupts are inactive by masking off all device + // interrupts in the system's Programable Interrupt Controllers. + // + + HalpDisableAllInterrupts(); + + if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) { + + // + // Initialize the IRQL translation tables in the PCR. These tables are + // used by the interrupt dispatcher to determine the new IRQL. They are + // also used by the routines that raise and lower IRQL. + // + + for (Index = 0; Index < sizeof(Halp21164IrqlTable); Index++) { + PCR->IrqlTable[Index] = Halp21164IrqlTable[Index]; + } + } + + // + // Initialize HAL private data from the PCR. This must be done before + // HalpStallExecution is called. Compute integral megahertz first to + // avoid rounding errors due to imprecise cycle clock period values. + // + + HalpClockMegaHertz = ((1000 * 1000) + (PCR->CycleClockPeriod >> 1)) / PCR->CycleClockPeriod; + HalpClockFrequency = HalpClockMegaHertz * (1000 * 1000); + + // + // Connect the Stall interrupt vector to the clock. When the + // profile count is calculated, we then connect the normal + // clock. + + + PCR->InterruptRoutine[UNIFLEX_CLOCK2_LEVEL] = HalpStallInterrupt; + + // + // Start the heartbeat timer + // + + HalSetTimeIncrement(MAXIMUM_INCREMENT); + HalpProgramIntervalTimer(HalpNextIntervalCount); + + // + // Initialize the PCI/ISA interrupt controller. + // + + HalpCreateDmaStructures(); + + if (HalpIoArchitectureType == EV5_PROCESSOR_MODULE) { + + // + // Initialize the 21164 interrupts. + // + + HalpCachePcrValues(0); // Enable all HW INTS on 21164 + + } else { + + // + // Initialize the 21064 interrupts. + // + + HalpInitialize21064Interrupts(); + + HalpEnable21064SoftwareInterrupt( Irql = APC_LEVEL ); + HalpEnable21064SoftwareInterrupt( Irql = DISPATCH_LEVEL ); + + HalpEnable21064HardwareInterrupt(Irq = 2, +// Irql = DEVICE_LEVEL, + Irql = UNIFLEX_PCI_DEVICE_LEVEL, +// Vector = PIC_VECTOR, + Vector = 14, + Priority = 0 ); + + } + + return TRUE; +} + +VOID +HalpStallInterrupt ( + VOID + ) + +/*++ + +Routine Description: + + This function serves as the stall calibration interrupt service + routine. It is executed in response to system clock interrupts + during the initialization of the HAL layer. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + return; +} diff --git a/private/ntos/nthals/halflex/busdata.c b/private/ntos/nthals/halflex/busdata.c new file mode 100644 index 000000000..7ae3a7987 --- /dev/null +++ b/private/ntos/nthals/halflex/busdata.c @@ -0,0 +1,175 @@ +/*++ + + +Copyright (C) 1989-1995 Microsoft Corporation +Copyright (C) 1994,1995 Digital Equipment Corporation + +Module Name: + + busdata.c + +Abstract: + + This module contains get/set bus data routines. + +Environment: + + Kernel mode + +--*/ + +#include "halp.h" + +// +// External Function Prototypes +// + +ULONG +HalpNoBusData ( + IN PVOID BusHandler, + IN PVOID RootHandler, + IN ULONG SlotNumber, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ); + +NTSTATUS +HalpIsaInstallHandler( + IN PBUS_HANDLER Bus + ); + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(INIT,HalpRegisterInternalBusHandlers) +#endif + + +VOID +HalpRegisterInternalBusHandlers ( + VOID + ) +/*++ + +Routine Description: + + This function registers the bushandlers for buses on the system + that will always be present on the system. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + PBUS_HANDLER Bus; + + // + // Initalize BusHandler data before registering any handlers + // + + HalpInitBusHandler (); + + // + // Build the processor internal bus 0 + // + + HaliRegisterBusHandler (ProcessorInternal, // Bus Type + -1, // No config space + 0, // Bus Number + -1, // No parent bus type + 0, // No parent bus number + 0, // No extension data + NULL, // No install handler + &Bus); // Bushandler return + + Bus->GetInterruptVector = HalpGetSystemInterruptVector; + + // + // Build internal-bus 0, or system level bus + // + + HaliRegisterBusHandler (Internal, // Bus Type + -1, // No config space + 0, // Bus Number + -1, // No parent bus type + 0, // No parent bus number + 0, // No extension data + NULL, // No install handler + &Bus); // Bushandler return + + Bus->GetInterruptVector = HalpGetSystemInterruptVector; + Bus->TranslateBusAddress = HalpTranslateSystemBusAddress; + + // + // Build Isa bus #0 + // + + HaliRegisterBusHandler (Isa, // Bus Type + -1, // No config space + 0, // Internal bus #0 + Internal, // Parent bus type + 0, // Parent bus number + 0, // No extension data + HalpIsaInstallHandler, // Install handler + &Bus); // Bushandler return + + // + // Build Isa bus #1 + // + + HaliRegisterBusHandler (Isa, // Bus Type + -1, // No config space + 1, // Internal bus #1 + Internal, // Parent bus type + 0, // Parent bus number + 0, // No extension data + HalpIsaInstallHandler, // Install handler + &Bus); // Bushandler return + + // + // Build Eisa bus #0 + // + + HaliRegisterBusHandler (Eisa, // Bus Type + -1, // No config space + 0, // Internal bus #0 + Internal, // Parent bus type + 0, // Parent bus number + 0, // No extension data + HalpIsaInstallHandler, // Install handler + &Bus); // Bushandler return + + // + // Build Eisa bus #1 + // + + HaliRegisterBusHandler (Eisa, // Bus Type + -1, // No config space + 1, // Internal bus #0 + Internal, // Parent bus type + 0, // Parent bus number + 0, // No extension data + HalpIsaInstallHandler, // Install handler + &Bus); // Bushandler return + +} + +NTSTATUS +HalpIsaInstallHandler( + IN PBUS_HANDLER Bus + ) + +{ + // + // Fill in ISA handlers + // + + Bus->GetBusData = HalpNoBusData; + Bus->AdjustResourceList = HalpAdjustIsaResourceList; + + return STATUS_SUCCESS; +} diff --git a/private/ntos/nthals/halflex/bushnd.c b/private/ntos/nthals/halflex/bushnd.c new file mode 100644 index 000000000..a1e648dc1 --- /dev/null +++ b/private/ntos/nthals/halflex/bushnd.c @@ -0,0 +1,7 @@ +// +// This file simply includes the common sources from the current HAL +// directory. When the structure is finally changed, the real file should +// be in this directory. +// + +#include "..\bushnd.c" diff --git a/private/ntos/nthals/halflex/drivesup.c b/private/ntos/nthals/halflex/drivesup.c new file mode 100644 index 000000000..38259e5f4 --- /dev/null +++ b/private/ntos/nthals/halflex/drivesup.c @@ -0,0 +1,7 @@ +// +// This file simply includes the common sources from the current HAL +// directory. When the structure is finally changed, the real file should +// be in this directory. +// + +#include "..\drivesup.c" diff --git a/private/ntos/nthals/halflex/hal.rc b/private/ntos/nthals/halflex/hal.rc new file mode 100644 index 000000000..3cba4ad89 --- /dev/null +++ b/private/ntos/nthals/halflex/hal.rc @@ -0,0 +1,11 @@ +#include + +#include + +#define VER_FILETYPE VFT_DLL +#define VER_FILESUBTYPE VFT2_UNKNOWN +#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL" +#define VER_INTERNALNAME_STR "hal.dll" + +#include "common.ver" + diff --git a/private/ntos/nthals/halflex/hal.src b/private/ntos/nthals/halflex/hal.src new file mode 100644 index 000000000..da778bb9d --- /dev/null +++ b/private/ntos/nthals/halflex/hal.src @@ -0,0 +1,7 @@ +// +// This file simply includes the common sources from the current HAL +// directory. When the structure is finally changed, the real file should +// be in this directory. +// + +#include "..\hal.src" diff --git a/private/ntos/nthals/halflex/halp.h b/private/ntos/nthals/halflex/halp.h new file mode 100644 index 000000000..b6cc7cfdd --- /dev/null +++ b/private/ntos/nthals/halflex/halp.h @@ -0,0 +1,453 @@ +/*++ BUILD Version: 0003 // Increment this if a change has global effects + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + halp.h + +Abstract: + + This header file defines the private Hardware Architecture Layer (HAL) + interfaces. + +Author: + + David N. Cutler (davec) 25-Apr-1991 + + +Revision History: + +--*/ + +#ifndef _HALP_ +#define _HALP_ +#include "nthal.h" +#include "hal.h" +#include "hali.h" +#include "dtidef.h" +#include "jxhalp.h" +#include "string.h" + + +#define __0K (ULONG)(0x0) +#define __0MB (ULONG)(0x0) +#define __0GB (ULONG)(0x0) +#define __2K (ULONG)(0x800) +#define __4K (ULONG)(0x1000) +#define __8K (ULONG)(0x2000) +#define __16K (ULONG)(0x4000) +#define __32K (ULONG)(0x8000) +#define __64K (ULONG)(0x10000) +#define __128K (ULONG)(0x20000) +#define __256K (ULONG)(0x40000) +#define __512K (ULONG)(0x80000) +#define __1MB (ULONG)(0x100000) +#define __2MB (ULONG)(0x200000) +#define __4MB (ULONG)(0x400000) +#define __8MB (ULONG)(0x800000) +#define __16MB (ULONG)(0x1000000) +#define __32MB (ULONG)(0x2000000) +#define __64MB (ULONG)(0x4000000) +#define __128MB (ULONG)(0x8000000) +#define __256MB (ULONG)(0x10000000) +#define __512MB (ULONG)(0x20000000) +#define __1GB (ULONG)(0x40000000) +#define __2GB (ULONG)(0x80000000) + +// +// Define the context structure for use by the interrupt routine. +// + +typedef BOOLEAN (*PSECONDARY_DISPATCH)( + PVOID InterruptRoutine + ); + +// +// Define adapter object structure. +// + +typedef struct _ADAPTER_OBJECT { + CSHORT Type; + CSHORT Size; + struct _ADAPTER_OBJECT *MasterAdapter; + ULONG MapRegistersPerChannel; + ULONG BusNumber; + PVOID AdapterBaseVa; + PVOID MapRegisterBase; + ULONG NumberOfMapRegisters; + ULONG CommittedMapRegisters; + struct _WAIT_CONTEXT_BLOCK *CurrentWcb; + KDEVICE_QUEUE ChannelWaitQueue; + PKDEVICE_QUEUE RegisterWaitQueue; + LIST_ENTRY AdapterQueue; + KSPIN_LOCK SpinLock; + PRTL_BITMAP MapRegisters; + PUCHAR PagePort; + UCHAR ChannelNumber; + UCHAR AdapterNumber; + USHORT DmaPortAddress; + UCHAR AdapterMode; + BOOLEAN NeedsMapRegisters; + BOOLEAN MasterDevice; + BOOLEAN Width16Bits; + BOOLEAN ScatterGather; +} ADAPTER_OBJECT; + +// +// Define function prototypes. +// + +BOOLEAN +HalpInitSystem ( + IN ULONG Phase, + IN PLOADER_PARAMETER_BLOCK LoaderBlock + ); + +VOID +HalpDisablePlatformInterrupt ( + IN ULONG Vector, + IN KIRQL Irql + ); + +BOOLEAN +HalpEnablePlatformInterrupt ( + IN ULONG Vector, + IN KIRQL Irql, + IN KINTERRUPT_MODE InterruptMode + ); + +BOOLEAN +HalpCreateEisaStructures( + ULONG BusNumber + ); + +VOID +HalpDisableEisaInterrupt( + IN ULONG Vector + ); + +BOOLEAN +HalpEisaDispatch( + IN PKINTERRUPT Interrupt, + IN PVOID ServiceContext, + IN ULONG BusNumber + ); + +BOOLEAN +HalpPciDispatch( + IN PKINTERRUPT Interrupt, + IN PVOID ServiceContext + ); + +VOID +HalpEnableEisaInterrupt( + IN ULONG Vector, + IN KINTERRUPT_MODE InterruptMode + ); + +ULONG +HalpAllocateTbEntry ( + VOID + ); + +VOID +HalpFreeTbEntry ( + VOID + ); + +BOOLEAN +HalpCalibrateStall ( + VOID + ); + +VOID +HalpClockInterrupt ( + VOID + ); + +BOOLEAN +HalpCreateDmaStructures ( + VOID + ); + +BOOLEAN +HalpInitializeDisplay ( + IN PLOADER_PARAMETER_BLOCK LoaderBlock + ); + +BOOLEAN +HalpInitializeInterrupts ( + VOID + ); + +BOOLEAN +HalpMapIoSpace ( + VOID + ); + +VOID +HalpProfileInterrupt ( + VOID + ); + +VOID +HalpStallInterrupt ( + VOID + ); + +VOID +HalpInitializeX86DisplayAdapter ( + VOID + ); + +VOID +HalpResetX86DisplayAdapter ( + VOID + ); + +VOID +HalpProgramIntervalTimer ( + IN ULONG IntervalCount + ); + +VOID +HalpConnectInterruptDispatchers( + VOID + ); + +VOID +HalpEnablePciInterrupt( + IN ULONG Vector + ); + +VOID +HalpDisablePciInterrupt( + IN ULONG Vector + ); + +VOID +HalpDisableAllInterrupts ( + ); + +ULONG +HalpVirtualIsaInterruptToInterruptLine ( + IN ULONG Index + ); + +ULONG +HalpReadPciData ( + IN ULONG BusNumber, + IN ULONG SlotNumber, + OUT PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ); + +ULONG +HalpWritePciData ( + IN ULONG BusNumber, + IN ULONG SlotNumber, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ); + +VOID +HalpAllocateArcsResources ( + VOID + ); + +VOID +HalpFreeArcsResources ( + VOID + ); + +PUCHAR +HalpAllocateKdPortResources( + PVOID *SP_READ, + PVOID *SP_WRITE + ); + +VOID +HalpFreeKdPortResources( + VOID + ); + +// +// Define Bus Handler support function prototypes. +// + + +VOID +HalpRegisterInternalBusHandlers ( + VOID + ); + +ULONG +HalpGetSystemInterruptVector( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN ULONG BusInterruptLevel, + IN ULONG BusInterruptVector, + OUT PKIRQL Irql, + OUT PKAFFINITY Affinity + ); + +BOOLEAN +HalpTranslateSystemBusAddress( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PHYSICAL_ADDRESS BusAddress, + IN OUT PULONG AddressSpace, + OUT PPHYSICAL_ADDRESS TranslatedAddress + ); + + +VOID +HalpAdjustResourceListUpperLimits ( + IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList, + IN LARGE_INTEGER MaximumPortAddress, + IN LARGE_INTEGER MaximumMemoryAddress, + IN ULONG MaximumInterruptVector, + IN ULONG MaximumDmaChannel + ); + +// +// +// + +NTSTATUS +HalpAdjustIsaResourceList ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList + ); + +// +// Define PCI support function prototypes. +// + +VOID +HalpInitializePCIBus ( + VOID + ); + +PBUS_HANDLER +HalpAllocateAndInitPCIBusHandler ( + IN ULONG BusNo + ); + +VOID +HalpRegisterPCIInstallHandler( + IN PINSTALL_BUS_HANDLER MachineSpecificPCIInstallHandler +); + +NTSTATUS +HalpDefaultPCIInstallHandler( + IN PBUS_HANDLER Bus + ); + +VOID +HalpDeterminePCIDevicesPresent( + IN PBUS_HANDLER Bus +); + +BOOLEAN +HalpInitializePCIInterrupts( + VOID + ); + +VOID +HalpEnablePCIInterrupt( + IN ULONG Vector + ); + +VOID +HalpDisablePCIInterrupt( + IN ULONG Vector + ); + +BOOLEAN +HalpPCIInterruptHandler( + IN PKINTERRUPT Interrupt, + IN PVOID ServiceContext + ); + +UCHAR +READ_CONFIG_UCHAR( + IN PVOID ConfigurationAddress, + IN ULONG ConfigurationType + ); + +USHORT +READ_CONFIG_USHORT( + IN PVOID ConfigurationAddress, + IN ULONG ConfigurationType + ); + +ULONG +READ_CONFIG_ULONG( + IN PVOID ConfigurationAddress, + IN ULONG ConfigurationType + ); + +VOID +WRITE_CONFIG_UCHAR( + IN PVOID ConfigurationAddress, + IN UCHAR ConfigurationData, + IN ULONG ConfigurationType + ); + +VOID +WRITE_CONFIG_USHORT( + IN PVOID ConfigurationAddress, + IN USHORT ConfigurationData, + IN ULONG ConfigurationType + ); + +VOID +WRITE_CONFIG_ULONG( + IN PVOID ConfigurationAddress, + IN ULONG ConfigurationData, + IN ULONG ConfigurationType + ); + +NTSTATUS +HalpMachineSpecificPCIInstallHandler( + IN PBUS_HANDLER Bus + ); + +// +// Define external references. +// + +extern PVOID HalpEisaControlBase[MAX_EISA_BUSSES]; +extern PVOID HalpEisaMemoryBase[MAX_EISA_BUSSES]; +extern PVOID HalpPciControlBase[MAX_PCI_BUSSES]; +extern PVOID HalpPciMemoryBase[MAX_PCI_BUSSES]; +extern PVOID HalpRealTimeClockBase; +extern PLATFORM_PARAMETER_BLOCK *HalpPlatformParameterBlock; +extern PLATFORM_SPECIFIC_EXTENSION *HalpPlatformSpecificExtension; + +extern PHAL_RESET_DISPLAY_PARAMETERS HalpResetDisplayParameters; + +extern ULONG HalpCurrentTimeIncrement; +extern ULONG HalpNextIntervalCount; +extern ULONG HalpNextTimeIncrement; +extern ULONG HalpNewTimeIncrement; +extern ULONG HalpProfileCountRate; + +extern PADAPTER_OBJECT MasterAdapterObject; + +// +// Map buffer prameters. These are initialized in HalInitSystem +// + +extern PHYSICAL_ADDRESS HalpMapBufferPhysicalAddress; + +extern ULONG HalpMapBufferSize; + +extern ULONG HalpBusType; + +#endif // _HALP_ diff --git a/private/ntos/nthals/halflex/ioproc.c b/private/ntos/nthals/halflex/ioproc.c new file mode 100644 index 000000000..450f8e46d --- /dev/null +++ b/private/ntos/nthals/halflex/ioproc.c @@ -0,0 +1,112 @@ +/*++ + +Copyright (C) 1991-1995 Microsoft Corporation + +Module Name: + + ioproc.c + +Abstract: + + Stub functions for UP hals. + +Environment: + + Kernel mode only. + + +--*/ + +#include "halp.h" +#include "iousage.h" + +UCHAR HalName[] = "DeskStation Technology UniFlex PCI/Eisa/Isa HAL"; + +VOID +HalpInitializePCIBus ( + VOID + ); + +BOOLEAN +HalpInitMP ( + IN ULONG Phase, + IN PLOADER_PARAMETER_BLOCK LoaderBlock + ); + +VOID HalpInitializePciBuses (VOID); +VOID HalpInitOtherBuses (VOID); + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(INIT,HalpInitMP) +#pragma alloc_text(INIT,HalStartNextProcessor) +#pragma alloc_text(INIT,HalReportResourceUsage) +#pragma alloc_text(INIT,HalReportResourceUsage) +#pragma alloc_text(INIT,HalpInitOtherBuses) +#endif + + + +BOOLEAN +HalpInitMP ( + IN ULONG Phase, + IN PLOADER_PARAMETER_BLOCK LoaderBlock + ) +{ + return TRUE; + // do nothing +} + + +VOID +HalpResetAllProcessors ( + VOID + ) +{ + // Just return, that will invoke the standard PC reboot code +} + + +BOOLEAN +HalStartNextProcessor ( + IN PLOADER_PARAMETER_BLOCK pLoaderBlock, + IN PKPROCESSOR_STATE pProcessorState + ) +{ + // no other processors + return FALSE; +} + + +VOID +HalReportResourceUsage ( + VOID + ) +{ + INTERFACE_TYPE interfacetype; + ANSI_STRING AHalName; + UNICODE_STRING UHalName; + + switch (HalpBusType) { + case UNIFLEX_MACHINE_TYPE_ISA: + case UNIFLEX_MACHINE_TYPE_EISA: interfacetype = Isa; break; + default: interfacetype = Internal; break; + } + + RtlInitAnsiString (&AHalName, HalName); + RtlAnsiStringToUnicodeString (&UHalName, &AHalName, TRUE); + HalpReportResourceUsage ( + &UHalName, // descriptive name + interfacetype // device space interface type + ); + + RtlFreeUnicodeString (&UHalName); +} + + +VOID +HalpInitOtherBuses ( + VOID + ) +{ + // no other internal buses supported +} diff --git a/private/ntos/nthals/halflex/iousage.c b/private/ntos/nthals/halflex/iousage.c new file mode 100644 index 000000000..9b30da08e --- /dev/null +++ b/private/ntos/nthals/halflex/iousage.c @@ -0,0 +1,515 @@ +/*++ + +Copyright (C) 1991-1995 Microsoft Corporation + +Module Name: + + iousage.c + +Abstract: + +Environment: + + Kernel mode only. + +--*/ + +#include "halp.h" +#include "iousage.h" + +// +// Define constants for system IDTs +// + +#define MAXIMUM_IDTVECTOR 0xff +#define MAXIMUM_PRIMARY_VECTOR 0xff +#define PRIMARY_VECTOR_BASE 0x30 // 0-2f are x86 trap vectors + +// +// From usage.c +// + +extern KAFFINITY HalpActiveProcessors; + +ADDRESS_USAGE *HalpAddressUsageList; + +// +// IDT vector usage info +// + +IDTUsage HalpIDTUsage[MAXIMUM_IDTVECTOR]; + +VOID +HalpGetResourceSortValue ( + IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc, + OUT PULONG sortscale, + OUT PLARGE_INTEGER sortvalue + ); + + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(INIT,HalpEnableInterruptHandler) +#pragma alloc_text(INIT,HalpRegisterVector) +#pragma alloc_text(INIT,HalpGetResourceSortValue) +#pragma alloc_text(INIT,HalpReportResourceUsage) +#endif + + +VOID +HalpEnableInterruptHandler ( + IN UCHAR ReportFlags, + IN ULONG BusInterruptVector, + IN ULONG SystemInterruptVector, + IN KIRQL SystemIrql, + IN VOID (*HalInterruptServiceRoutine)(VOID), + IN KINTERRUPT_MODE InterruptMode + ) +/*++ + +Routine Description: + + This function connects & registers an IDT vectors usage by the HAL. + +Arguments: + +Return Value: + +--*/ +{ + // + // Remember which vector the hal is connecting so it can be reported + // later on + // + HalpRegisterVector (ReportFlags, BusInterruptVector, SystemInterruptVector, SystemIrql); + + + // + // Connect the IDT and enable the vector now + // + +#if 0 + KiSetHandlerAddressToIDT(SystemInterruptVector, HalInterruptServiceRoutine); +#endif //0 + HalEnableSystemInterrupt(SystemInterruptVector, SystemIrql, InterruptMode); +} + + +VOID +HalpRegisterVector ( + IN UCHAR ReportFlags, + IN ULONG BusInterruptVector, + IN ULONG SystemInterruptVector, + IN KIRQL SystemIrql + ) +/*++ + +Routine Description: + + This registers an IDT vectors usage by the HAL. + +Arguments: + +Return Value: + +--*/ +{ +#if DBG + // There are only 0ff IDT entries... + ASSERT (SystemInterruptVector <= MAXIMUM_IDTVECTOR && + BusInterruptVector <= MAXIMUM_IDTVECTOR); +#endif + + // + // Remember which vector the hal is connecting so it can be reported + // later on + // + + HalpIDTUsage[SystemInterruptVector].Flags = ReportFlags; + HalpIDTUsage[SystemInterruptVector].Irql = SystemIrql; + HalpIDTUsage[SystemInterruptVector].BusReleativeVector = (UCHAR) BusInterruptVector; +} + + +VOID +HalpGetResourceSortValue ( + IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc, + OUT PULONG sortscale, + OUT PLARGE_INTEGER sortvalue + ) +/*++ + +Routine Description: + + Used by HalpReportResourceUsage in order to properly sort + partial_resource_descriptors. + +Arguments: + + pRCurLoc - resource descriptor + +Return Value: + + sortscale - scaling of resource descriptor for sorting + sortvalue - value to sort on + + +--*/ +{ + switch (pRCurLoc->Type) { + case CmResourceTypeInterrupt: + *sortscale = 0; + sortvalue->QuadPart = pRCurLoc->u.Interrupt.Level; + break; + + case CmResourceTypePort: + *sortscale = 1; + *sortvalue = pRCurLoc->u.Port.Start; + break; + + case CmResourceTypeMemory: + *sortscale = 2; + *sortvalue = pRCurLoc->u.Memory.Start; + break; + + default: + *sortscale = 4; + sortvalue->QuadPart = 0; + break; + } +} + + +VOID +HalpReportResourceUsage ( + IN PUNICODE_STRING HalName, + IN INTERFACE_TYPE DeviceInterfaceToUse + ) +/*++ + +Routine Description: + +Arguments: + +Return Value: + +--*/ +{ + PCM_RESOURCE_LIST RawResourceList, TranslatedResourceList; + PCM_FULL_RESOURCE_DESCRIPTOR pRFullDesc, pTFullDesc; + PCM_PARTIAL_RESOURCE_LIST pRPartList, pTPartList; + PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc, pTCurLoc; + PCM_PARTIAL_RESOURCE_DESCRIPTOR pRSortLoc, pTSortLoc; + CM_PARTIAL_RESOURCE_DESCRIPTOR RPartialDesc, TPartialDesc; + ULONG i, j, k, ListSize, Count; + ULONG curscale, sortscale; + UCHAR pass, reporton; + INTERFACE_TYPE interfacetype; + ULONG CurrentIDT, CurrentElement; + ADDRESS_USAGE *CurrentAddress; + LARGE_INTEGER curvalue, sortvalue; + PHYSICAL_ADDRESS TempAddress; + + // + // Allocate some space to build the resource structure + // + + RawResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (NonPagedPool, PAGE_SIZE*2); + TranslatedResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (NonPagedPool, PAGE_SIZE*2); + + // This functions assumes unset fields are zero + RtlZeroMemory (RawResourceList, PAGE_SIZE*2); + RtlZeroMemory (TranslatedResourceList, PAGE_SIZE*2); + + // + // Initialize the lists + // + + RawResourceList->List[0].InterfaceType = (INTERFACE_TYPE) -1; + + pRFullDesc = RawResourceList->List; + pRCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) RawResourceList->List; + pTCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) TranslatedResourceList->List; + + // + // Make sure all vectors 00-2f are reserved + // 00-1E reserved by Intel + // 1F reserved by Intel for APIC (apc priority level) + // 20-2e reserved by Microsoft + // 2f reserved by Microsoft for APIC (dpc priority level) + // + + for(i=0; i < PRIMARY_VECTOR_BASE; i++) { + if (!(HalpIDTUsage[i].Flags & IDTOwned)) { + HalpIDTUsage[i].Flags = InternalUsage; + HalpIDTUsage[i].BusReleativeVector = (UCHAR) i; + } + } + + for(pass=0; pass < 3; pass++) { + + switch(pass) { + + case 0: { +#if DBG +DbgPrint("Device LIST...\n"); +#endif // DBG + // + // First pass - build resource lists for resources reported + // reported against device usage. + // + + reporton = DeviceUsage & ~IDTOwned; + interfacetype = DeviceInterfaceToUse; + break; + } + + case 1: { +#if DBG +DbgPrint("Internal LIST...\n"); +#endif // DBG + // + // Second pass = build reousce lists for resources reported + // as internal usage. + // + + reporton = InternalUsage & ~IDTOwned; + interfacetype = Internal; + break; + } + + case 2: { +#if DBG +DbgPrint("PCI LIST...\n"); +#endif // DBG + // + // Third pass = build reousce lists for resources reported + // as PCI usage. + // + + reporton = PCIUsage & ~IDTOwned; + interfacetype = PCIBus; + break; + } + } + + CurrentIDT = 0; + CurrentElement = 0; + CurrentAddress = HalpAddressUsageList; + + for (; ;) { + if (CurrentIDT <= MAXIMUM_IDTVECTOR) { + // + // Check to see if CurrentIDT needs to be reported + // + + if (!(HalpIDTUsage[CurrentIDT].Flags & reporton)) { + // Don't report on this one + CurrentIDT++; + continue; + } + + // + // Report CurrentIDT resource + // + + RPartialDesc.Type = CmResourceTypeInterrupt; + RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive; + RPartialDesc.Flags = + HalpIDTUsage[CurrentIDT].Flags & InterruptLatched ? + CM_RESOURCE_INTERRUPT_LATCHED : + CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE; + RPartialDesc.u.Interrupt.Vector = HalpIDTUsage[CurrentIDT].BusReleativeVector; + RPartialDesc.u.Interrupt.Level = HalpIDTUsage[CurrentIDT].BusReleativeVector; + RPartialDesc.u.Interrupt.Affinity = HalpActiveProcessors; + + RtlCopyMemory (&TPartialDesc, &RPartialDesc, sizeof TPartialDesc); + TPartialDesc.u.Interrupt.Vector = CurrentIDT; + TPartialDesc.u.Interrupt.Level = HalpIDTUsage[CurrentIDT].Irql; + + CurrentIDT++; + + } else { + + // + // Check to see if CurrentAddress needs to be reported + // + + if (!CurrentAddress) { + break; // No addresses left + } + + if (!(CurrentAddress->Flags & reporton)) { + // Don't report on this list + CurrentElement = 0; + CurrentAddress = CurrentAddress->Next; + continue; + } + + if (!CurrentAddress->Element[CurrentElement].Length) { + // End of current list, go to next list + CurrentElement = 0; + CurrentAddress = CurrentAddress->Next; + continue; + } + + // + // Report CurrentAddress + // + + RPartialDesc.Type = (UCHAR) CurrentAddress->Type; + RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive; + + if (RPartialDesc.Type == CmResourceTypePort) { + i = 1; // address space port + RPartialDesc.Flags = CM_RESOURCE_PORT_IO; + } else { + i = 0; // address space memory + RPartialDesc.Flags = CM_RESOURCE_MEMORY_READ_WRITE; + } + + // Notice: assuming u.Memory and u.Port have the same layout + RPartialDesc.u.Memory.Start.HighPart = 0; + RPartialDesc.u.Memory.Start.LowPart = + CurrentAddress->Element[CurrentElement].Start; + + RPartialDesc.u.Memory.Length = + CurrentAddress->Element[CurrentElement].Length; + +#if DBG +DbgPrint("Start=0x%x Lenght=0x%x\n", RPartialDesc.u.Memory.Start.LowPart, RPartialDesc.u.Memory.Length); +#endif // DBG + + // translated address = Raw address + RtlCopyMemory (&TPartialDesc, &RPartialDesc, sizeof TPartialDesc); + HalTranslateBusAddress ( + interfacetype, // device bus or internal + 0, // bus number + RPartialDesc.u.Memory.Start, // source address + &i, // address space + &TempAddress ); // aligned translated address + + TPartialDesc.u.Memory.Start = TempAddress; // TPartialDesc is pack(4) + +#if DBG +DbgPrint("TRANSLATED ADDRESS Start=0x%x Lenght=0x%x\n", TPartialDesc.u.Memory.Start.LowPart, TPartialDesc.u.Memory.Length); +#endif // DBG + + if (RPartialDesc.Type == CmResourceTypePort && i == 0) { + TPartialDesc.Flags = CM_RESOURCE_PORT_MEMORY; + } + + CurrentElement++; + } + + // + // Include the current resource in the HALs list + // + + if (pRFullDesc->InterfaceType != interfacetype) { + // + // Interface type changed, add another full section + // + + RawResourceList->Count++; + TranslatedResourceList->Count++; + + pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc; + pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc; + + pRFullDesc->InterfaceType = interfacetype; + pTFullDesc->InterfaceType = interfacetype; + + pRPartList = &pRFullDesc->PartialResourceList; + pTPartList = &pTFullDesc->PartialResourceList; + + // + // Bump current location pointers up + // + pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors; + pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors; + } + + + pRPartList->Count++; + pTPartList->Count++; + RtlCopyMemory (pRCurLoc, &RPartialDesc, sizeof RPartialDesc); + RtlCopyMemory (pTCurLoc, &TPartialDesc, sizeof TPartialDesc); + + pRCurLoc++; + pTCurLoc++; + } + } + + ListSize = (ULONG) ( ((PUCHAR) pRCurLoc) - ((PUCHAR) RawResourceList) ); + + // + // The HAL's resource usage structures have been built + // Sort the partial lists based on the Raw resource values + // + + pRFullDesc = RawResourceList->List; + pTFullDesc = TranslatedResourceList->List; + + for (i=0; i < RawResourceList->Count; i++) { + + pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors; + pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors; + Count = pRFullDesc->PartialResourceList.Count; + + for (j=0; j < Count; j++) { + HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue); + + pRSortLoc = pRCurLoc; + pTSortLoc = pTCurLoc; + + for (k=j; k < Count; k++) { + HalpGetResourceSortValue (pRSortLoc, &sortscale, &sortvalue); + + if (sortscale < curscale || + (sortscale == curscale && + (sortvalue.QuadPart < curvalue.QuadPart)) ) { + + // + // Swap the elements.. + // + + RtlCopyMemory (&RPartialDesc, pRCurLoc, sizeof RPartialDesc); + RtlCopyMemory (pRCurLoc, pRSortLoc, sizeof RPartialDesc); + RtlCopyMemory (pRSortLoc, &RPartialDesc, sizeof RPartialDesc); + + // swap translated descriptor as well + RtlCopyMemory (&TPartialDesc, pTCurLoc, sizeof TPartialDesc); + RtlCopyMemory (pTCurLoc, pTSortLoc, sizeof TPartialDesc); + RtlCopyMemory (pTSortLoc, &TPartialDesc, sizeof TPartialDesc); + + // get new curscale & curvalue + HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue); + } + + pRSortLoc++; + pTSortLoc++; + } + + pRCurLoc++; + pTCurLoc++; + } + + pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc; + pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc; + } + + + // + // Inform the IO system of our resources.. + // + + IoReportHalResourceUsage ( + HalName, + RawResourceList, + TranslatedResourceList, + ListSize + ); + + ExFreePool (RawResourceList); + ExFreePool (TranslatedResourceList); +} diff --git a/private/ntos/nthals/halflex/iousage.h b/private/ntos/nthals/halflex/iousage.h new file mode 100644 index 000000000..a9153a982 --- /dev/null +++ b/private/ntos/nthals/halflex/iousage.h @@ -0,0 +1,77 @@ +/*++ + +Copyright (C) 1991-1995 Microsoft Corporation +Copyright (c) 1992-1995 Digital Equipment Corporation + +Module Name: + + iousage.h + +Abstract: + + This header file defines the iousage definitions + + +--*/ + +// +// External Function Prototypes +// + +VOID +HalpEnableInterruptHandler ( + IN UCHAR ReportFlags, + IN ULONG BusInterruptVector, + IN ULONG SystemInterruptVector, + IN KIRQL SystemIrql, + IN VOID (*HalInterruptServiceRoutine)(VOID), + IN KINTERRUPT_MODE InterruptMode + ); + +VOID +HalpRegisterVector ( + IN UCHAR ReportFlags, + IN ULONG BusInterruptVector, + IN ULONG SystemInterruptVector, + IN KIRQL SystemIrql + ); + +VOID +HalpReportResourceUsage ( + IN PUNICODE_STRING HalName, + IN INTERFACE_TYPE DeviceInterfaceToUse + ); +// +// Resource usage information +// + +#pragma pack(1) +typedef struct { + UCHAR Flags; + KIRQL Irql; + UCHAR BusReleativeVector; +} IDTUsage; + +typedef struct _HalAddressUsage{ + struct _HalAddressUsage *Next; + CM_RESOURCE_TYPE Type; // Port or Memory + UCHAR Flags; // same as IDTUsage.Flags + struct { + ULONG Start; + ULONG Length; + } Element[]; +} ADDRESS_USAGE; +#pragma pack() + +#define IDTOwned 0x01 // IDT is not available for others +#define InterruptLatched 0x02 // Level or Latched +#define InternalUsage 0x11 // Report usage on internal bus +#define DeviceUsage 0x21 // Report usage on device bus +#define PCIUsage 0x41 // Report usage on PCI bus + +extern IDTUsage HalpIDTUsage[]; +extern ADDRESS_USAGE *HalpAddressUsageList; + +#define HalpRegisterAddressUsage(a) \ + (a)->Next = HalpAddressUsageList, HalpAddressUsageList = (a); + diff --git a/private/ntos/nthals/halflex/makefile b/private/ntos/nthals/halflex/makefile new file mode 100644 index 000000000..6ee4f43fa --- /dev/null +++ b/private/ntos/nthals/halflex/makefile @@ -0,0 +1,6 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/private/ntos/nthals/halflex/makefile.inc b/private/ntos/nthals/halflex/makefile.inc new file mode 100644 index 000000000..ad15f5255 --- /dev/null +++ b/private/ntos/nthals/halflex/makefile.inc @@ -0,0 +1,5 @@ +obj\*\hal.def: hal.src + cl /EP hal.src -D$(PROCESSOR_ARCHITECTIRE)=1 $(C_DEFINES) > obj\*\hal.def + +$(TARGETPATH)\*\$(DDKBUILDENV)\hal.lib: $(TARGETPATH)\*\$(DDKBUILDENV)\halflex.lib + copy $** $@ diff --git a/private/ntos/nthals/halflex/mips/addrsup.c b/private/ntos/nthals/halflex/mips/addrsup.c new file mode 100644 index 000000000..795e529a5 --- /dev/null +++ b/private/ntos/nthals/halflex/mips/addrsup.c @@ -0,0 +1,204 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + ixphwsup.c + +Abstract: + + This module contains the HalpXxx routines for the NT I/O system that + are hardware dependent. Were these routines not hardware dependent, + they would normally reside in the internal.c module. + +Author: + + Michael D. Kinney 30-Apr-1995 + +Environment: + + Kernel mode, local to I/O system + +Revision History: + + +--*/ + +#include "halp.h" + +#define KERNEL_PCI_VGA_VIDEO_ROM (LONGLONG)(0x8000000000000000) + +PLATFORM_RANGE_LIST Gambit20Trebbia13RangeList[] = { + { Isa , 0, BusIo, 0, TREB1_GAMBIT_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { Isa , 0, BusMemory, 0, TREB1_GAMBIT_ISA_MEMORY_BASE_PHYSICAL , 0x00000000, 0x00ffffff }, + + { Isa , 1, BusIo, 0, TREB1_GAMBIT_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { Isa , 1, BusMemory, 0, TREB1_GAMBIT_ISA1_MEMORY_BASE_PHYSICAL+0xa0000 , 0x000a0000, 0x000bffff }, + { Isa , 1, BusMemory, 0, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff }, + + { Eisa , 0, BusIo, 0, TREB1_GAMBIT_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { Eisa , 0, BusMemory, 0, TREB1_GAMBIT_ISA_MEMORY_BASE_PHYSICAL , 0x00000000, 0xffffffff }, + + { Eisa , 1, BusIo, 0, TREB1_GAMBIT_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { Eisa , 1, BusMemory, 0, TREB1_GAMBIT_ISA1_MEMORY_BASE_PHYSICAL+0xa0000 , 0x000a0000, 0x000bffff }, + { Eisa , 1, BusMemory, 0, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff }, + + { PCIBus, 0, BusIo, 0, TREB1_GAMBIT_PCI_IO_BASE_PHYSICAL , 0x00000000, 0xffffffff }, + { PCIBus, 0, BusMemory, 0, TREB1_GAMBIT_PCI_MEMORY_BASE_PHYSICAL+0x40000000 , 0x40000000, 0xffffffff }, + + { PCIBus, 1, BusIo, 0, TREB1_GAMBIT_PCI_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { PCIBus, 1, BusMemory, 0, TREB1_GAMBIT_PCI_MEMORY_BASE_PHYSICAL+0xa0000 , 0x000a0000, 0x000bffff }, + { PCIBus, 1, BusMemory, 0, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff }, + { PCIBus, 1, BusMemory, 0, TREB1_GAMBIT_PCI_MEMORY_BASE_PHYSICAL+0x40000000 , 0x40000000, 0xffffffff }, + + { MaximumInterfaceType, 0, 0, 0, 0 , 0 , 0 } +}; + +PLATFORM_RANGE_LIST Gambit20Trebbia20RangeList[] = { + { Isa , 0, BusIo, 0, TREB2_GAMBIT_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { Isa , 0, BusMemory, 0, TREB2_GAMBIT_ISA_MEMORY_BASE_PHYSICAL+0xa0000 , 0x000a0000, 0x000bffff }, + { Isa , 0, BusMemory, 0, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff }, + + { Isa , 1, BusIo, 0, TREB2_GAMBIT_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { Isa , 1, BusMemory, 0, TREB2_GAMBIT_ISA1_MEMORY_BASE_PHYSICAL+0xa0000 , 0x000a0000, 0x000bffff }, + { Isa , 1, BusMemory, 0, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff }, + + { Eisa , 0, BusIo, 0, TREB2_GAMBIT_ISA_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { Eisa , 0, BusMemory, 0, TREB2_GAMBIT_ISA_MEMORY_BASE_PHYSICAL+0xa0000 , 0x000a0000, 0x000bffff }, + { Eisa , 0, BusMemory, 0, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff }, + + { Eisa , 1, BusIo, 0, TREB2_GAMBIT_ISA1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { Eisa , 1, BusMemory, 0, TREB2_GAMBIT_ISA1_MEMORY_BASE_PHYSICAL+0xa0000 , 0x000a0000, 0x000bffff }, + { Eisa , 1, BusMemory, 0, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff }, + + { PCIBus, 0, BusIo, 0, TREB2_GAMBIT_PCI_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { PCIBus, 0, BusMemory, 0, TREB2_GAMBIT_PCI_MEMORY_BASE_PHYSICAL+0xa0000 , 0x000a0000, 0x000bffff }, + { PCIBus, 0, BusMemory, 0, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff }, + { PCIBus, 0, BusMemory, 0, TREB2_GAMBIT_PCI_MEMORY_BASE_PHYSICAL+0x40000000 , 0x40000000, 0xffffffff }, + + { PCIBus, 1, BusIo, 0, TREB2_GAMBIT_PCI1_IO_BASE_PHYSICAL , 0x00000000, 0x0000ffff }, + { PCIBus, 1, BusMemory, 0, TREB2_GAMBIT_PCI1_MEMORY_BASE_PHYSICAL+0xa0000 , 0x000a0000, 0x000bffff }, + { PCIBus, 1, BusMemory, 0, KERNEL_PCI_VGA_VIDEO_ROM , 0x000c0000, 0x000c7fff }, + { PCIBus, 1, BusMemory, 0, TREB2_GAMBIT_PCI1_MEMORY_BASE_PHYSICAL+0x40000000 , 0x40000000, 0xffffffff }, + + { MaximumInterfaceType, 0, 0, 0, 0 , 0 , 0 } +}; + + +BOOLEAN +HalpTranslateSystemBusAddress( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PHYSICAL_ADDRESS BusAddress, + IN OUT PULONG AddressSpace, + OUT PPHYSICAL_ADDRESS TranslatedAddress + ) + +{ + ULONG i; + INTERFACE_TYPE InterfaceType = BusHandler->InterfaceType; + ULONG BusNumber = BusHandler->BusNumber; + LONGLONG Offset; + PVOID va = 0; // note, this is used for a placeholder + +//BusAddress.HighPart = 0; +//DbgPrint("HalTranslateBusAddress(IT=%d,BN=%d,BA=%08x %08x,AS=%d)\n\r",InterfaceType,BusNumber,BusAddress.HighPart,BusAddress.LowPart,*AddressSpace); + + // + // PCI Bus 0 is different than PCI Bus 1, but all other PCI busses are the same a PCI Bus 1 + // + + if (InterfaceType == PCIBus) { + + switch (HalpMotherboardType) { + case TREBBIA13 : + if (BusNumber > 1) { + BusNumber = 1; + } + break; + + case TREBBIA20 : + if (BusNumber == 0) { + + // + // There are no resources in PCI Bus #0. It only contains the memory system and bridges. + // + + *AddressSpace = 0; + TranslatedAddress->LowPart = 0; + return(FALSE); + } + + if (BusNumber >= HalpSecondPciBridgeBusNumber) { + BusNumber = 1; + } else { + BusNumber = 0; + } + break; + + default : + +//DbgPrint(" Invalid Motherboard Type\n\r"); + + *AddressSpace = 0; + TranslatedAddress->LowPart = 0; + return(FALSE); + } + } + + // + // If the VGA decodes are not enabled on the DEC PCI-PCI bridge associated with this + // memory range, then fail the translation. + // + + if (!(HalpVgaDecodeBusNumber & (1<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<=12) { + return; + } + HalpPciDeviceInterruptMask = HalpPciDeviceInterruptMask & ~(1<= 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<InterruptRoutine[PCRInOffset]); + interruptObject = CONTAINING_RECORD(dispatchCode, + KINTERRUPT, + DispatchCode); + + returnValue = + ((PSECONDARY_DISPATCH)interruptObject->DispatchAddress) + (interruptObject); + } + } + + return(returnValue); +} + +UCHAR HalpGetInterruptLine(ULONG BusNumber,ULONG DeviceNumber,ULONG InterruptPin) + +/*++ + +Routine Description: + + This routine maps a PCI interrupt described by the device's bus number, device number, and + interrupt pin into the interrupt line value that is stored in the PCI config header. + +Arguments: + + BusNumber - PCI bus number of the device. + + DeviceNumber - PCI device number of the device. + + InterruptPin - PCI interrupt pin of the device (A=1,B=2,C=3,D=4). + +Return Value: + + Returns the PCI Interrupt Line value for the PCI device. + +--*/ + +{ + UCHAR InterruptLine; + + if (HalpMotherboardType == TREBBIA13) { + + if (BusNumber > 1) + { + BusNumber = 1; + } + + switch (BusNumber<<16 | DeviceNumber<<8 | InterruptPin) { + case 0x010401 : InterruptLine = 0x10; break; // Bus 1, Device 4, Int A + case 0x010601 : InterruptLine = 0x11; break; // Bus 1, Device 6, Int A + case 0x010501 : InterruptLine = 0x12; break; // Bus 1, Device 5, Int A + case 0x010701 : InterruptLine = 0x13; break; // Bus 1, Device 7, Int A + case 0x010402 : InterruptLine = 0x17; break; // Bus 1, Device 4, Int B + case 0x010602 : InterruptLine = 0x14; break; // Bus 1, Device 6, Int B + case 0x010502 : InterruptLine = 0x14; break; // Bus 1, Device 5, Int B + case 0x010702 : InterruptLine = 0x17; break; // Bus 1, Device 7, Int B + case 0x010403 : InterruptLine = 0x15; break; // Bus 1, Device 4, Int C + case 0x010603 : InterruptLine = 0x15; break; // Bus 1, Device 6, Int C + case 0x010503 : InterruptLine = 0x15; break; // Bus 1, Device 5, Int C + case 0x010703 : InterruptLine = 0x15; break; // Bus 1, Device 7, Int C + case 0x010404 : InterruptLine = 0x16; break; // Bus 1, Device 4, Int D + case 0x010604 : InterruptLine = 0x16; break; // Bus 1, Device 6, Int D + case 0x010504 : InterruptLine = 0x16; break; // Bus 1, Device 5, Int D + case 0x010704 : InterruptLine = 0x16; break; // Bus 1, Device 7, Int D + case 0x000d01 : InterruptLine = 0x1e; break; // Bus 0, Device 13, Int A + case 0x000f01 : InterruptLine = 0x1f; break; // Bus 0, Device 15, Int A + case 0x001001 : InterruptLine = 0x20; break; // Bus 0, Device 16, Int A + default : InterruptLine = 0xff; break; + } + } + + if (HalpMotherboardType == TREBBIA20) { + + if (BusNumber == 0) { + return(0xff); + } + + if (BusNumber >= HalpSecondPciBridgeBusNumber) { + BusNumber = 1; + } else { + BusNumber = 0; + } + + switch (BusNumber<<16 | DeviceNumber<<8 | InterruptPin) { + case 0x000401 : InterruptLine = 0x20; break; + + case 0x000501 : + case 0x000603 : + case 0x000704 : InterruptLine = 0x10; break; + + case 0x000502 : + case 0x000604 : + case 0x000701 : InterruptLine = 0x11; break; + + case 0x000503 : + case 0x000601 : + case 0x000702 : InterruptLine = 0x12; break; + + case 0x000504 : + case 0x000602 : + case 0x000703 : InterruptLine = 0x13; break; + + case 0x010401 : + case 0x010504 : + case 0x010603 : InterruptLine = 0x14; break; + + case 0x010402 : + case 0x010501 : + case 0x010604 : InterruptLine = 0x15; break; + + case 0x010403 : + case 0x010502 : + case 0x010601 : InterruptLine = 0x16; break; + + case 0x010404 : + case 0x010503 : + case 0x010602 : InterruptLine = 0x17; break; + + case 0x010701 : InterruptLine = 0x18; break; + + default : InterruptLine = 0xff; break; + } + } + + return(InterruptLine); +} + +VOID +HalpConnectInterruptDispatchers ( + VOID + ) + +/*++ + +Routine Description: + + This function connects the PCI interrupt dispatch routine and enables + ISA interrupts so they will generate processor interrupts. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + UCHAR InterruptLine; + + // + // Initialize the EISA interrupt dispatcher and the PCI interrupt dispatcher + // + + PCR->InterruptRoutine[UNIFLEX_PCI_DEVICE_LEVEL] = (PKINTERRUPT_ROUTINE)HalpPciDispatch; + PCR->InterruptRoutine[UNIFLEX_EISA_DEVICE_LEVEL] = (PKINTERRUPT_ROUTINE)HalpEisa0Dispatch; + +DbgPrint("Intel82378 : Bus=%d Device=%d\n\r",HalpIntel82378BusNumber,HalpIntel82378DeviceNumber); +DbgPrint("SecondIntel82378 : Bus=%d Device=%d\n\r",HalpSecondPciBridgeBusNumber,HalpSecondIntel82378DeviceNumber); + + InterruptLine = HalpGetInterruptLine(HalpIntel82378BusNumber,HalpIntel82378DeviceNumber,1); + HalpEisaInterruptMask = 0x0000; + if (InterruptLine != 0xff) { + HalpEisaInterruptMask = (1 << HalpInterruptLineToBit[InterruptLine-0x10]) & 0xffff; + } + + InterruptLine = HalpGetInterruptLine(HalpSecondPciBridgeBusNumber,HalpSecondIntel82378DeviceNumber,1); + HalpEisa1InterruptMask = 0x0000; + if (InterruptLine != 0xff) { + HalpEisa1InterruptMask = (1 << HalpInterruptLineToBit[InterruptLine-0x10]) & 0xffff; + } + +DbgPrint("HalpEisaInterruptMask = %08x\n\r",HalpEisaInterruptMask); +DbgPrint("HalpEisa1InterruptMask = %08x\n\r",HalpEisa1InterruptMask); + + // + // Enable ISA Interrupts on Gambit's PIC + // + + HalpPciInterruptMask = HalpGetMemoryMode(); + HalpPciInterruptMask |= (HalpEisaInterruptMask | HalpEisa1InterruptMask); + HalpWritePciInterruptMask(); +} + +VOID +HalpDisableAllInterrupts( + VOID + ) + +/*++ + +Routine Description: + + This function disables all external interrupt sources. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + ULONG VirtualAddress; + + VirtualAddress = (ULONG)HalpAllocateIoMapping(HalpIsaIoBasePhysical); + WRITE_REGISTER_UCHAR(VirtualAddress+0x21,0xff); + WRITE_REGISTER_UCHAR(VirtualAddress+0xa1,0xff); + HalpFreeIoMapping(); + + if (HalpNumberOfIsaBusses > 1) { + VirtualAddress = (ULONG)HalpAllocateIoMapping(HalpIsa1IoBasePhysical); + WRITE_REGISTER_UCHAR(VirtualAddress+0x21,0xff); + WRITE_REGISTER_UCHAR(VirtualAddress+0xa1,0xff); + HalpFreeIoMapping(); + } + + VirtualAddress = (ULONG)HalpAllocateIoMapping(GAMBIT_PCI_INTERRUPT_BASE_PHYSICAL); + + HalpPciInterruptMask = ((READ_REGISTER_ULONG(VirtualAddress+0x08) & 0x08) << 4); + WRITE_REGISTER_ULONG(VirtualAddress+0x00,HalpPciInterruptMask&0x0f); + WRITE_REGISTER_ULONG(VirtualAddress+0x08,(HalpPciInterruptMask>>4)&0x0f); + WRITE_REGISTER_ULONG(VirtualAddress+0x10,(HalpPciInterruptMask>>8)&0x0f); + HalpFreeIoMapping(); + + HalpPciDeviceInterruptMask = 0x0000; +} + +ULONG HalpPciConfigStructuresInitialized = FALSE; +PVOID HalpPciConfig0BaseAddress[0x20]; +PVOID HalpPciConfig1BaseAddress[0x100]; + +PCI_CONFIGURATION_TYPES +HalpPCIConfigCycleType (IN ULONG BusNumber) +{ + if (BusNumber == 0) { + return PciConfigType0; + } else if (BusNumber < PCIMaxBus) { + return PciConfigType1; + } else { + return PciConfigTypeInvalid; + } +} + +VOID +HalpPCIConfigAddr ( + IN ULONG BusNumber, + IN PCI_SLOT_NUMBER Slot, + PPCI_CFG_CYCLE_BITS pPciAddr + ) +{ + + PCI_CONFIGURATION_TYPES ConfigType; + + // + // If the Configuration Base Address tables have not been initialized, then + // initialize them to NULL. + // + + if (HalpPciConfigStructuresInitialized == FALSE) { + + ULONG i; + + for(i=0;i<0x20;HalpPciConfig0BaseAddress[i++]=NULL); + for(i=0;i<0xff;HalpPciConfig1BaseAddress[i++]=NULL); + HalpPciConfigStructuresInitialized = TRUE; + } + + ConfigType = HalpPCIConfigCycleType(BusNumber); + + if (ConfigType == PciConfigType0) { + + // + // Initialize PciAddr for a type 0 configuration cycle + // + + // + // See if this is a nonexistant device on PCI Bus 0 + // + + if ( (1 << Slot.u.bits.DeviceNumber) & HalpNonExistentPciDeviceMask ) { + pPciAddr->u.AsULONG = INVALID_PCI_CONFIGURATION_ADDRESS; + return; + } + + if (HalpPciConfig0BaseAddress[Slot.u.bits.DeviceNumber] == NULL) { + + PHYSICAL_ADDRESS physicalAddress; + + physicalAddress.QuadPart = HalpPciConfig0BasePhysical; + physicalAddress.QuadPart += (1 << (11 + Slot.u.bits.DeviceNumber)); + HalpPciConfig0BaseAddress[Slot.u.bits.DeviceNumber] = MmMapIoSpace(physicalAddress,0x800,FALSE); + + // + // If the mapping failed, then the return value is INVALID_PCI_CONFIGURATION_ADDRESS. + // This will cause Config Reads to return 0xffffffff, and Config Writes to do nothing. + // + + if (HalpPciConfig0BaseAddress[Slot.u.bits.DeviceNumber] == NULL) { + pPciAddr->u.AsULONG = INVALID_PCI_CONFIGURATION_ADDRESS; + return; + } + + } + pPciAddr->u.AsULONG = (ULONG)HalpPciConfig0BaseAddress[Slot.u.bits.DeviceNumber]; + pPciAddr->u.AsULONG += ((Slot.u.bits.FunctionNumber & 0x07) << 8); + pPciAddr->u.bits0.Reserved1 = PciConfigType0; + +#if DBG + DbgPrint("HalpPCIConfigAddr: Type 0 PCI Config Access @ %x\n", pPciAddr->u.AsULONG); +#endif // DBG + + } else { + + // + // See if this is a nonexistant PCI device on the otherside of the First PCI-PCI Bridge + // + + if (BusNumber == 1 && (1 << Slot.u.bits.DeviceNumber) & HalpNonExistentPci1DeviceMask) { + pPciAddr->u.AsULONG = INVALID_PCI_CONFIGURATION_ADDRESS; + return; + } + + // + // See if this is a nonexistant PCI device on the otherside of the Second PCI-PCI Bridge + // + + if (BusNumber == HalpSecondPciBridgeBusNumber && (1 << Slot.u.bits.DeviceNumber) & HalpNonExistentPci2DeviceMask) { + pPciAddr->u.AsULONG = INVALID_PCI_CONFIGURATION_ADDRESS; + return; + } + + // + // Initialize PciAddr for a type 1 configuration cycle + // + + if (HalpPciConfig1BaseAddress[BusNumber] == NULL) { + + PHYSICAL_ADDRESS physicalAddress; + + physicalAddress.QuadPart = HalpPciConfig1BasePhysical; + physicalAddress.QuadPart += ((BusNumber & 0xff) << 16); + HalpPciConfig1BaseAddress[BusNumber] = MmMapIoSpace(physicalAddress,0x10000,FALSE); + + // + // If the mapping failed, then the return value is INVALID_PCI_CONFIGURATION_ADDRESS. + // This will cause Config Reads to return 0xffffffff, and Config Writes to do nothing. + // + + if (HalpPciConfig1BaseAddress[BusNumber] == NULL) { + pPciAddr->u.AsULONG = INVALID_PCI_CONFIGURATION_ADDRESS; + return; + } + + } + pPciAddr->u.AsULONG = (ULONG)HalpPciConfig1BaseAddress[BusNumber]; + pPciAddr->u.AsULONG += ((Slot.u.bits.DeviceNumber & 0x1f) << 11); + pPciAddr->u.AsULONG += ((Slot.u.bits.FunctionNumber & 0x07) << 8); + pPciAddr->u.bits0.Reserved1 = PciConfigType1; + +#if DBG + DbgPrint("Type 1 PCI Config Access @ %x\n", pPciAddr->u.AsULONG); +#endif // DBG + + } + + return; +} + +UCHAR +READ_CONFIG_UCHAR( + IN PVOID ConfigurationAddress, + IN ULONG ConfigurationType + ) + +{ + if (((ULONG)ConfigurationAddress & 0xffffff00) == INVALID_PCI_CONFIGURATION_ADDRESS) { + return((UCHAR)NO_PCI_DEVSEL_DATA_VALUE); + } + return(READ_REGISTER_UCHAR(ConfigurationAddress)); +} + +USHORT +READ_CONFIG_USHORT( + IN PVOID ConfigurationAddress, + IN ULONG ConfigurationType + ) + +{ + if (((ULONG)ConfigurationAddress & 0xffffff00) == INVALID_PCI_CONFIGURATION_ADDRESS) { + return((USHORT)NO_PCI_DEVSEL_DATA_VALUE); + } + return(READ_REGISTER_USHORT(ConfigurationAddress)); +} + +ULONG +READ_CONFIG_ULONG( + IN PVOID ConfigurationAddress, + IN ULONG ConfigurationType + ) + +{ + if (((ULONG)ConfigurationAddress & 0xffffff00) == INVALID_PCI_CONFIGURATION_ADDRESS) { + return((ULONG)NO_PCI_DEVSEL_DATA_VALUE); + } + return(READ_REGISTER_ULONG(ConfigurationAddress)); +} + +VOID +WRITE_CONFIG_UCHAR( + IN PVOID ConfigurationAddress, + IN UCHAR ConfigurationData, + IN ULONG ConfigurationType + ) + +{ + if (((ULONG)ConfigurationAddress & 0xffffff00) != INVALID_PCI_CONFIGURATION_ADDRESS) { + WRITE_REGISTER_UCHAR(ConfigurationAddress,ConfigurationData); + } +} + +VOID +WRITE_CONFIG_USHORT( + IN PVOID ConfigurationAddress, + IN USHORT ConfigurationData, + IN ULONG ConfigurationType + ) + +{ + if (((ULONG)ConfigurationAddress & 0xffffff00) != INVALID_PCI_CONFIGURATION_ADDRESS) { + WRITE_REGISTER_USHORT(ConfigurationAddress,ConfigurationData); + } +} + +VOID +WRITE_CONFIG_ULONG( + IN PVOID ConfigurationAddress, + IN ULONG ConfigurationData, + IN ULONG ConfigurationType + ) + +{ + if (((ULONG)ConfigurationAddress & 0xffffff00) != INVALID_PCI_CONFIGURATION_ADDRESS) { + WRITE_REGISTER_ULONG(ConfigurationAddress,ConfigurationData); + } +} + +LONGLONG HalpMapPciConfigBaseAddress( + IN ULONG BusNumber, + IN ULONG DeviceNumber, + IN ULONG FunctionNumber, + IN ULONG Register + ) + +{ + LONGLONG BaseAddress; + + if (BusNumber == 0) { + BaseAddress = HalpPciConfig0BasePhysical + + (1 << (11+(DeviceNumber & 0x1f))) + + ((FunctionNumber & 0x07) << 8) + + Register; + } else { + BaseAddress = HalpPciConfig1BasePhysical + + ((BusNumber & 0xff) << 16) + + ((DeviceNumber & 0x1f) << 11) + + ((FunctionNumber & 0x07) << 8) + + Register; + } + return(BaseAddress); +} + +ULONG HalpPciLowLevelConfigRead( + IN ULONG BusNumber, + IN ULONG DeviceNumber, + IN ULONG FunctionNumber, + IN ULONG Register + ) + +/*++ + +Routine Description: + + This function allocates the resources needed to perform a single PCI + configuration read cycle. The read data is returned. For a MIPS processor, + a single TLB entry is borrowed so that I/O reads and writes can be performed + to PCI configuration space. + +Return Value: + + Data retuned by the PCI config cycle. + +--*/ + +{ + LONGLONG BaseAddress; + PVOID VirtualAddress; + ULONG ReturnValue; + + BaseAddress = HalpMapPciConfigBaseAddress(BusNumber,DeviceNumber,FunctionNumber,Register&0xfc); + VirtualAddress = HalpAllocateIoMapping(BaseAddress); + ReturnValue = READ_REGISTER_ULONG(VirtualAddress); + HalpFreeIoMapping(); + return(ReturnValue); +} + +VOID HalpPostCard(UCHAR Value) + +{ + LONGLONG BaseAddress; + PVOID VirtualAddress; + + BaseAddress = HalpMapPciConfigBaseAddress(HalpIntel82378BusNumber,HalpIntel82378DeviceNumber,0,0x4f); + VirtualAddress = HalpAllocateIoMapping(BaseAddress); + WRITE_REGISTER_UCHAR(VirtualAddress,0xcf); + HalpFreeIoMapping(); + + VirtualAddress = HalpAllocateIoMapping(HalpIsaIoBasePhysical + 0x420); + Value = (Value & 0x7f) | (READ_REGISTER_UCHAR(VirtualAddress) & 0x80); + HalpFreeIoMapping(); + + VirtualAddress = HalpAllocateIoMapping(HalpIsaIoBasePhysical + 0xc00); + WRITE_REGISTER_UCHAR(VirtualAddress,Value); + HalpFreeIoMapping(); + + BaseAddress = HalpMapPciConfigBaseAddress(HalpIntel82378BusNumber,HalpIntel82378DeviceNumber,0,0x4f); + VirtualAddress = HalpAllocateIoMapping(BaseAddress); + WRITE_REGISTER_UCHAR(VirtualAddress,0x4f); + HalpFreeIoMapping(); +} diff --git a/private/ntos/nthals/halflex/mips/portsup.c b/private/ntos/nthals/halflex/mips/portsup.c new file mode 100644 index 000000000..9e0171440 --- /dev/null +++ b/private/ntos/nthals/halflex/mips/portsup.c @@ -0,0 +1,137 @@ +/*++ + +Copyright (c) 1995 DeskStation Technology + +Module Name: + + portsup.c + +Abstract: + + This module implements the code that provides the resources required to + access the serial port that is used for the kernel debugger. + +Author: + + Michael D. Kinney 30-Apr-1995 + +Environment: + + Kernel mode + +Revision History: + +--*/ + +#include "halp.h" + +#define HEADER_FILE +#include "kxmips.h" + +#define SP_VIRTUAL_BASE 0xffffa000 +#define SERIAL_PORT_COM1 0x3F8 + +VOID +HalpGetIoArchitectureType( + VOID + ); + +// +// Define hardware PTE's that map the serial port used by the debugger. +// + +ENTRYLO HalpPte[2]; + +PUCHAR HalpAllocateKdPortResources( + OUT PVOID *SP_READ, + OUT PVOID *SP_WRITE + ) + +/*++ + +Routine Description: + + This function allocates the resources needed by the kernel debugger to + access a serial port. For a MIPS processor, a single TLB entry is borrowed + so that I/O reads and writes can be performed to the serial port. + +Arguments: + + SP_READ - Kernel virtual address to use for I/O read operations. + + SP_WRITE - Kernel virtual address to use for I/O write operations. + +Return Value: + + The bus relative address of the COM port being used as a kernel debugger. + +--*/ + +{ + ULONG KdPortEntry; + + HalpGetIoArchitectureType(); + + // + // Map the serial port into the system virtual address space by loading + // a TB entry. + // + + HalpPte[0].PFN = (ULONG)(HalpIsaIoBasePhysical >> 12); + HalpPte[0].G = 1; + HalpPte[0].V = 1; + HalpPte[0].D = 1; + + // + // Allocate a TB entry, set the uncached policy in the PTE that will + // map the serial controller, and initialize the second PTE. + // + + KdPortEntry = HalpAllocateTbEntry(); + HalpPte[0].C = UNCACHED_POLICY; + + HalpPte[1].PFN = 0; + HalpPte[1].G = 1; + HalpPte[1].V = 0; + HalpPte[1].D = 0; + HalpPte[1].C = 0; + + // + // Map the serial controller through a fixed TB entry. + // + + KeFillFixedEntryTb((PHARDWARE_PTE)&HalpPte[0], + (PVOID)SP_VIRTUAL_BASE, + KdPortEntry); + + *SP_READ = (PVOID)(SP_VIRTUAL_BASE + SERIAL_PORT_COM1); + *SP_WRITE = (PVOID)(SP_VIRTUAL_BASE + SERIAL_PORT_COM1); + + return((PUCHAR)(SERIAL_PORT_COM1)); +} + +VOID HalpFreeKdPortResources( + VOID + ) + +/*++ + +Routine Description: + + This function deallocates the resources needed by the kernel debugger to + access a serial port. For a MIPS processor, this simply frees the TLB entry + that was borrowed. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + HalpFreeTbEntry(); +} diff --git a/private/ntos/nthals/halflex/mips/x4clock.s b/private/ntos/nthals/halflex/mips/x4clock.s new file mode 100644 index 000000000..0e8475007 --- /dev/null +++ b/private/ntos/nthals/halflex/mips/x4clock.s @@ -0,0 +1,210 @@ +#if defined(R4000) + +// TITLE("Interval and Profile Clock Interrupts") +//++ +// +// Copyright (c) 1991 Microsoft Corporation +// +// Module Name: +// +// x4clock.s +// +// Abstract: +// +// This module implements the code necessary to field and process the +// interval and profile clock interrupts on a MIPS R4000 system. +// +// Author: +// +// David N. Cutler (davec) 26-Apr-1991 +// +// Environment: +// +// Kernel mode only. +// +// Revision History: +// +//-- + +#include "halmips.h" + + SBTTL("System Clock Interrupt") +//++ +// +// Routine Description: +// +// This routine is entered as the result of an interrupt generated by +// the interval timer. Its function is to acknowledge the interrupt and +// transfer control to the standard system routine to update the system +// time and the execution time of the current thread and process. +// +// Arguments: +// +// s8 - Supplies a pointer to a trap frame. +// +// Return Value: +// +// None. +// +//-- + + .struct 0 +CiArgs: .space 4 * 4 // saved arguments + .space 3 * 4 // fill +CiRa: .space 4 // saved return address +CiFrameLength: // + + NESTED_ENTRY(HalpClockInterrupt, CiFrameLength, zero) + + subu sp,sp,CiFrameLength // allocate stack frame + sw ra,CiRa(sp) // save return address + + PROLOGUE_END + + move a0,s8 // set address of trap frame + lw a1,HalpCurrentTimeIncrement // Get current time increment + jal KeUpdateSystemTime // update system time + lw t0,HalpNextTimeIncrement // Get NextTimeIncrement + sw t0,HalpCurrentTimeIncrement // Set CurrentTimeIncrement to NextTimeIncrement + lw a0,HalpNextIntervalCount // Get Next Interval Count. If 0, then no change required + beq zero,a0,5f // See if time increment is to be changed + jal HalpProgramIntervalTimer // Program timer with new interval count value + lw t0,HalpNewTimeIncrement // Get HalpNewTimeIncrement + sw t0,HalpNextTimeIncrement // Set HalpNextTimeIncrement to HalpNewTimeIncrement + sw zero,HalpNextIntervalCount // Set HalpNextIntervalCount to 0 +5: + lw t0,KdDebuggerEnabled // check if debugger enabled + lbu t0,0(t0) // + beq zero,t0,10f // if eq, debugger not enabled + jal KdPollBreakIn // check if breakin is requested + beq zero,v0,10f // if eq, no breakin requested + li a0, DBG_STATUS_CONTROL_C // break in and send + jal DbgBreakPointWithStatus // status to debugger +10: lw ra,CiRa(sp) // restore return address + addu sp,sp,CiFrameLength // deallocate stack frame + j ra // return + + .end HalpClockInterrupt + + SBTTL("Profile Clock Interrupt") +//++ +// +// Routine Description: +// +// This routine is entered as the result of an interrupt generated by the +// profile clock. Its function is to acknowledge the profile interrupt, +// compute the next compare value, update the performance counter, and +// transfer control to the standard system routine to process any active +// profiles. +// +// Arguments: +// +// s8 - Supplies a pointer to a trap frame. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalpProfileInterrupt) + + .set noreorder + .set noat + mfc0 t1,count // get current count value + mfc0 t0,compare // get current comparison value + addu t1,t1,8 // factor in lost cycles + subu t1,t1,t0 // compute initial count value + mtc0 t0,compare // dismiss interrupt + mtc0 t1,count // set new count register value + .set at + .set reorder + + la t1,HalpPerformanceCounter // get performance counter address + lw t2,LiLowPart(t1) // get low part of performance count + lw t3,LiHighPart(t1) // get high part of performance count + addu t2,t2,t0 // update low part of performance count + sw t2,LiLowPart(t1) // store low part of performance count + sltu t4,t2,t0 // generate carry into high part + addu t3,t3,t4 // update high part of performance count + sw t3,LiHighPart(t1) // store high part of performance count + move a0,s8 // set address of trap frame + j KeProfileInterrupt // process profile entries + + .end HalpProfileInterrupt + + SBTTL("Read Count Register") +//++ +// +// ULONG +// HalpReadCountRegister ( +// VOID +// ); +// +// Routine Description: +// +// This routine reads the current value of the count register and +// returns the value. +// +// Arguments: +// +// None. +// +// Return Value: +// +// Current value of the count register. +// +//-- + + LEAF_ENTRY(HalpReadCountRegister) + + .set noreorder + .set noat + mfc0 v0,count // get count register value + .set at + .set reorder + + j ra // return + + .end HalpReadCountRegister + + SBTTL("Write Compare Register And Clear") +//++ +// +// ULONG +// HalpWriteCompareRegisterAndClear ( +// IN ULONG Value +// ); +// +// Routine Description: +// +// This routine reads the current value of the count register, writes +// the value of the compare register, clears the count register, and +// returns the previous value of the count register. +// +// Arguments: +// +// Value - Supplies the value written to the compare register. +// +// Return Value: +// +// Previous value of the count register. +// +//-- + + LEAF_ENTRY(HalpWriteCompareRegisterAndClear) + + .set noreorder + .set noat + mfc0 v0,count // get count register value + mtc0 a0,compare // set compare register value + li t0,7 // set lost cycle count + mtc0 t0,count // set count register to zero + .set at + .set reorder + + j ra // return + + .end HalpWriteCompareRegisterAndClear + +#endif diff --git a/private/ntos/nthals/halflex/mips/x4tb.s b/private/ntos/nthals/halflex/mips/x4tb.s new file mode 100644 index 000000000..d399da2ac --- /dev/null +++ b/private/ntos/nthals/halflex/mips/x4tb.s @@ -0,0 +1,109 @@ +#if defined(R4000) + +// TITLE("AllocateFree TB Entry") +//++ +// +// Copyright (c) 1992-1993 Microsoft Corporation +// +// Module Name: +// +// x4tb.s +// +// Abstract: +// +// This module implements allocates and frees fixed TB entries using the +// wired register. +// +// Environment: +// +// Kernel mode only. +// +//-- + +#include "halmips.h" + + SBTTL("Allocate Tb Entry") +//++ +// +// ULONG +// HalpAllocateTbEntry ( +// VOID +// ) +// +// Routine Description: +// +// This function allocates the TB entry specified by the wired register +// and increments the wired register. +// +// Arguments: +// +// None. +// +// Return Value: +// +// The index of the allocated TB entry. +// +//-- + + LEAF_ENTRY(HalpAllocateTbEntry) + + DISABLE_INTERRUPTS(t0) // disable interrupts + + .set noreorder + .set noat + mfc0 v0,wired // get contents of wired register + nop // fill + addu v1,v0,1 // allocate TB entry + mtc0 v1,wired // + .set at + .set reorder + + ENABLE_INTERRUPTS(t0) // enable interrupts + + j ra // return + + .end HalpAllocateTbEntry + + SBTTL("Free Tb Entry") +//++ +// +// VOID +// HalpAllocateTbEntry ( +// VOID +// ) +// +// Routine Description: +// +// This function frees the TB entry specified by the wired register +// and decrements the wired register. +// +// Arguments: +// +// None. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalpFreeTbEntry) + + DISABLE_INTERRUPTS(t0) // disable interrupts + + .set noreorder + .set noat + mfc0 v0,wired // get contents of wired register + nop // fill + subu v1,v0,1 // free TB entry + mtc0 v1,wired // + .set at + .set reorder + + ENABLE_INTERRUPTS(t0) // enable interrupts + + j ra // return + + .end HalpFreeTbEntry + +#endif diff --git a/private/ntos/nthals/halflex/mips/xxcalstl.c b/private/ntos/nthals/halflex/mips/xxcalstl.c new file mode 100644 index 000000000..e1ce0b6b0 --- /dev/null +++ b/private/ntos/nthals/halflex/mips/xxcalstl.c @@ -0,0 +1,253 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + xxcalstl.c + +Abstract: + + + This module implements the calibration of the stall execution HAL + service, computes the count rate for the profile clock, and connects + the clock and profile interrupts for a MIPS R3000 or R4000 system. + +Author: + + David N. Cutler (davec) 26-Apr-1991 + +Environment: + + Kernel mode only. + +Revision History: + +--*/ + +#include "halp.h" + +// +// Define global data used to calibrate and stall processor execution. +// + +ULONG HalpProfileCountRate; +ULONG volatile HalpStallEnd; +ULONG volatile HalpStallStart; + +BOOLEAN +HalpCalibrateStall ( + VOID + ) + +/*++ + +Routine Description: + + This function calibrates the stall execution HAL service and connects + the clock and profile interrupts to the appropriate NT service routines. + +Arguments: + + None. + +Return Value: + + A value of TRUE is returned if the calibration is successfully + completed. Otherwise a value of FALSE is returned. + +--*/ + +{ + + ULONG Index; + KIRQL OldIrql; + PKPRCB Prcb; + + // + // Start the system clock to interrupt at MAXIMUM_INCREMENT intervals. + // + // N.B. MAXIMUM_INCREMENT is in 100ns units. + // + + HalSetTimeIncrement(MAXIMUM_INCREMENT); + HalpProgramIntervalTimer(HalpNextIntervalCount); + HalpEnableEisaInterrupt(UNIFLEX_CLOCK2_LEVEL,Latched); /* Enable Timer1,Counter0 interrupt */ + + // + // Use a range of scale factors from 50ns down to 10ns assuming a + // five instruction stall loop. + // + + for (Index = 50; Index > 0; Index -= 10) { + + // + // Disable all interrupts and establish calibration parameters. + // + + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + + // + // Set the scale factor, stall count, starting stall count, and + // ending stall count values. + // + + PCR->StallScaleFactor = 1000 / (Index * 5); + PCR->StallExecutionCount = 0; + HalpStallStart = 0; + HalpStallEnd = 0; + + // + // Enable interrupts and stall execution. + // + + KeLowerIrql(OldIrql); + + // + // Stall execution for (MAXIMUM_INCREMENT / 10) * 4 us. + // + + KeStallExecutionProcessor((MAXIMUM_INCREMENT / 10) * 4); + + // + // If both the starting and ending stall counts have been captured, + // then break out of loop. + // + + if ((HalpStallStart != 0) && (HalpStallEnd != 0)) { + break; + } + + } + + // + // Compute the profile interrupt rate. + // + + HalpProfileCountRate = + HalpProfileCountRate * ((1000 * 1000 * 10) / MAXIMUM_INCREMENT); + + // + // Compute the stall execution scale factor. + // + + PCR->StallScaleFactor = (HalpStallEnd - HalpStallStart + + ((MAXIMUM_INCREMENT / 10) - 1)) / (MAXIMUM_INCREMENT / 10); + + if (PCR->StallScaleFactor <= 0) { + PCR->StallScaleFactor = 1; + } + + // + // Get the address of the processor control block for the current + // processor. + // + + Prcb = PCR->Prcb; + + // + // Connect the real clock interrupt routine. + // + + PCR->InterruptRoutine[UNIFLEX_CLOCK2_LEVEL] = HalpClockInterrupt; + + // + // Write the compare register and clear the count register, and + // connect the profile interrupt. + // + + HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT); + PCR->InterruptRoutine[PROFILE_LEVEL] = HalpProfileInterrupt; + + return TRUE; +} + +VOID +KeStallExecutionProcessor ( + IN ULONG MicroSeconds + ) + +/*++ + +Routine Description: + + This function stalls execution of the current processor for the specified + number of microseconds. + +Arguments: + + MicroSeconds - Supplies the number of microseconds that execution is to + be stalled. + +Return Value: + + None. + +--*/ + +{ + + ULONG Index; + + // + // Use the stall scale factor to determine the number of iterations + // the wait loop must be executed to stall the processor for the + // specified number of microseconds. + // + + Index = MicroSeconds * PCR->StallScaleFactor; + do { + PCR->StallExecutionCount += 1; + Index -= 1; + } while (Index > 0); + + return; +} + +VOID +HalpStallInterrupt ( + VOID + ) + +/*++ + +Routine Description: + + This function serves as the stall calibration interrupt service + routine. It is executed in response to system clock interrupts + during the initialization of the HAL layer. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + // + // If this is the very first interrupt, then wait for the second + // interrupt before starting the timing interval. Else, if this + // the second interrupt, then capture the starting stall count + // and clear the count register on R4000 processors. Else, if this + // is the third interrupt, then capture the ending stall count and + // the ending count register on R4000 processors. Else, if this is + // the fourth or subsequent interrupt, then simply dismiss it. + // + + if ((HalpStallStart == 0) && (HalpStallEnd == 0)) { + HalpStallEnd = 1; + + } else if ((HalpStallStart == 0) && (HalpStallEnd != 0)) { + HalpStallStart = PCR->StallExecutionCount; + HalpStallEnd = 0; + HalpWriteCompareRegisterAndClear(0); + } else if ((HalpStallStart != 0) && (HalpStallEnd == 0)) { + HalpStallEnd = PCR->StallExecutionCount; + HalpProfileCountRate = HalpWriteCompareRegisterAndClear(0); + } + return; +} diff --git a/private/ntos/nthals/halflex/mips/xxidle.s b/private/ntos/nthals/halflex/mips/xxidle.s new file mode 100644 index 000000000..d0cd9c78b --- /dev/null +++ b/private/ntos/nthals/halflex/mips/xxidle.s @@ -0,0 +1,79 @@ +// TITLE("Processor Idle") +//++ +// +// Copyright (c) 1994 Microsoft Corporation +// +// Module Name: +// +// xxidle.s +// +// Abstract: +// +// This module implements system platform dependent power management +// support. +// +// Author: +// +// David N. Cutler (davec) 5-Mar-1994 +// +// Environment: +// +// Kernel mode only. +// +// Revision History: +// +//-- + +#include "halmips.h" + + SBTTL("Processor Idle") +//++ +// +// VOID +// HalProcessorIdle( +// VOID +// ) +// +// Routine Description: +// +// This function is called when the current processor is idle with +// interrupts disabled. There is no thread active and there are no +// DPCs to process. Therefore, power can be switched to a standby +// mode until the the next interrupt occurs on the current processor. +// +// N.B. This routine is entered with IE in PSR clear. This routine +// must do any power management enabling necessary, set the IE +// bit in PSR, then either return or wait for an interrupt. +// +// Arguments: +// +// None. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalProcessorIdle) + +// +// Perform power management enabling. +// + + .set noreorder + .set noat + mfc0 v0,psr // get current PSR + nop // fill + or v0,v0,1 << PSR_IE // set interrupt enable. + mtc0 v0,psr // enable interrupts + .set at + .set reorder + +// +// Wait for an interrupt if supported. +// + + j ra // return + + .end HalProcessorIdle diff --git a/private/ntos/nthals/halflex/mips/xxinitnt.c b/private/ntos/nthals/halflex/mips/xxinitnt.c new file mode 100644 index 000000000..b8b757141 --- /dev/null +++ b/private/ntos/nthals/halflex/mips/xxinitnt.c @@ -0,0 +1,159 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + xxinitnt.c + +Abstract: + + + This module implements the interrupt initialization for a MIPS R3000 + or R4000 system. + +Author: + + David N. Cutler (davec) 26-Apr-1991 + +Environment: + + Kernel mode only. + +Revision History: + +--*/ + +#include "halp.h" + +// +// Define the IRQL mask and level mapping table. +// +// These tables are transfered to the PCR and determine the priority of +// interrupts. +// +// N.B. The two software interrupt levels MUST be the lowest levels. +// + +UCHAR HalpIrqlMask[] = {4, 3, 3, 3, 3, 3, 3, 3, // 0000 - 0111 high 4-bits + 8, 8, 8, 8, 8, 8, 8, 8, // 1000 - 1111 high 4-bits + 0, 1, 2, 2, 3, 3, 3, 3, // 0000 - 0111 low 4-bits + 4, 4, 4, 4, 4, 4, 4, 4}; // 1000 - 1111 low 4-bits + +UCHAR HalpIrqlTable[] = {0x8f, // IRQL 0 + 0x8e, // IRQL 1 + 0x8c, // IRQL 2 + 0x88, // IRQL 3 + 0x80, // IRQL 4 + 0x80, // IRQL 5 + 0x80, // IRQL 6 + 0x80, // IRQL 7 + 0x00}; // IRQL 8 + + +VOID +HalpCountInterrupt ( + VOID + ) + +/*++ + +Routine Description: + + This function serves as the R4000 count/compare interrupt service + routine early in the system initialization. Its only function is + to field and acknowledge count/compare interrupts during the system + boot process. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + + // + // Acknowledge the R4000 count/compare interrupt. + // + + HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT); + return; +} + + +BOOLEAN +HalpInitializeInterrupts ( + VOID + ) + +/*++ + +Routine Description: + + This function initializes interrupts for a MIPS R3000 or R4000 system. + +Arguments: + + None. + +Return Value: + + A value of TRUE is returned if the initialization is successfully + completed. Otherwise a value of FALSE is returned. + +--*/ + +{ + ULONG Index; + PKPRCB Prcb; + + // + // Mask sure that all processor interrupts are inactive by masking off all device + // interrupts in the system's Programable Interrupt Controllers. + // + + HalpDisableAllInterrupts(); + + // + // Get the address of the processor control block for the current + // processor. + // + + Prcb = PCR->Prcb; + + // + // Initialize the IRQL translation tables in the PCR. These tables are + // used by the interrupt dispatcher to determine the new IRQL and the + // mask value that is to be loaded into the PSR. They are also used by + // the routines that raise and lower IRQL to load a new mask value into + // the PSR. + // + + for (Index = 0; Index < sizeof(HalpIrqlMask); Index += 1) { + PCR->IrqlMask[Index] = HalpIrqlMask[Index]; + } + + for (Index = 0; Index < sizeof(HalpIrqlTable); Index += 1) { + PCR->IrqlTable[Index] = HalpIrqlTable[Index]; + } + + // + // Connect the clock interrupt to the stall interrupt routine. + // + + PCR->InterruptRoutine[UNIFLEX_CLOCK2_LEVEL] = HalpStallInterrupt; + + // + // Connect the R4000 count/compare interrupt to the early interrupt + // routine. + // + + PCR->InterruptRoutine[PROFILE_LEVEL] = HalpCountInterrupt; + + return TRUE; +} diff --git a/private/ntos/nthals/halflex/pcip.h b/private/ntos/nthals/halflex/pcip.h new file mode 100644 index 000000000..2d8527914 --- /dev/null +++ b/private/ntos/nthals/halflex/pcip.h @@ -0,0 +1,138 @@ +/*++ BUILD Version: 0000 Increment this if a change has global effects + +Copyright (C) 1994,1995 Microsoft Corporation +Copyright (C) 1994,1995 Digital Equipment Corporation + +Module Name: + + pcip.h + +Abstract: + + This header file defines the private PCI bus HAL interfaces and + data types. + +--*/ +// +// Hal specific PCI bus structures +// + +#define PCI_CONFIG_TYPE(PciData) ((PciData)->HeaderType & ~PCI_MULTIFUNCTION) + +#define PCI_MAX_BUSSES 256 + +#define PciBitIndex(Dev,Fnc) (Fnc*32 + Dev) + +// +// Define PCI configuration cycle types. +// +typedef enum _PCI_CONFIGURATION_TYPES { + PciConfigTypeInvalid = -1, + PciConfigType0 = 0, + PciConfigType1 = 1 +} PCI_CONFIGURATION_TYPES, *PPCI_CONFIGURATION_TYPES; + +typedef struct _PCI_CFG_CYCLE_BITS { + union { + struct { + ULONG Reserved1:2; + ULONG Reserved2:30; + } bits; // Generic Config Cycle + + struct { + ULONG Reserved1:2; + ULONG RegisterNumber:6; + ULONG FunctionNumber:3; + ULONG Idsel:21; + } bits0; // Type0 Config Cycle + + struct { + ULONG Reserved1:2; + ULONG RegisterNumber:6; + ULONG FunctionNumber:3; + ULONG DeviceNumber:5; + ULONG BusNumber:8; + ULONG Reserved2:7; + ULONG Enable:1; + } bits1; // Type 1 Config Cycle + + ULONG AsULONG; + } u; +} PCI_CFG_CYCLE_BITS, *PPCI_CFG_CYCLE_BITS; + +// +// Define PCI cycle/command types. +// + +typedef enum _PCI_COMMAND_TYPES{ + PciCommandInterruptAcknowledge = 0x0, + PciCommandSpecialCycle = 0x1, + PciCommandIoRead = 0x2, + PciCommandIoWrite = 0x3, + PciCommandMemoryRead = 0x6, + PciCommandMemoryWrite = 0x7, + PciCommandConfigurationRead = 0xa, + PciCommandConfigurationWrite = 0xb, + PciCommandMemoryReadMultiple = 0xc, + PciCommandDualAddressCycle = 0xd, + PciCommandMemoryReadLine = 0xe, + PciCommandMemoryWriteAndInvalidate = 0xf, + MaximumPciCommand +} PCI_COMMAND_TYPES, *PPCI_COMMAND_TYPES; + +// +// PCI platform-specific functions +// + + +PCI_CONFIGURATION_TYPES +HalpPCIConfigCycleType ( + IN ULONG BusNumber + ); + +VOID +HalpPCIConfigAddr ( + IN ULONG BusNumber, + IN PCI_SLOT_NUMBER Slot, + PPCI_CFG_CYCLE_BITS pPciAddr + ); + + +// +// Define PCI configuration cycle types. +// + +typedef enum _PCI_TYPE0_CONFIG_TYPE { + PciConfigType0AsIdsel, + PciConfigType0AsDeviceNumber +} PCI_TYPE0_CONFIG_TYPE, *PPCI_TYPE0_CONFIG_TYPE; + + +typedef struct tagPCIPBUSDATA { + + // + // NT Defined PCI data + // + + PCIBUSDATA CommonData; + + // + // Common alpha hal specific data + // + + PVOID ConfigBaseQva; + PCI_TYPE0_CONFIG_TYPE PciType0ConfigType; + BOOLEAN BusIsAcrossPPB; + + RTL_BITMAP DevicePresent; + ULONG DevicePresentBits[PCI_MAX_DEVICES * PCI_MAX_FUNCTION / 32]; + + ULONG MaxDevice; + + // + // Platform-specific storage + // + + PVOID PlatformSpecificData; + +} PCIPBUSDATA, *PPCIPBUSDATA; diff --git a/private/ntos/nthals/halflex/platform.h b/private/ntos/nthals/halflex/platform.h new file mode 100644 index 000000000..b679d15a6 --- /dev/null +++ b/private/ntos/nthals/halflex/platform.h @@ -0,0 +1,194 @@ +/*++ + +Copyright (c) 1995 DeskStation Technology + +Module Name: + + platform.h + +Abstract: + + This file contains definitions specific to private vector calls into + the ARCSBIOS firmware. + +Author: + + Michael D. Kinney 1-May-1995 + +Environment: + + Kernel mode + +Revision History: + + +--*/ + +#define MAX_PROCESSORS 32 +#define MAX_SYSTEM_INTERRUPTS 256 +#define MAX_SYSTEM_EXCEPTIONS 64 +#define MAX_INTERRUPTS_PER_BUS 32 +#define ARC_NAME_LENGTH 128 +#define IDENTIFIER_LENGTH 64 +#define MAX_SIMM_SOCKETS 32 +#define MAX_BUSSES 16 +#define NUMBEROFNVRAMSECTIONS 5 + +typedef enum { ISA_BUS, EISA_BUS, VESA_BUS, PCI_BUS, PROCESSOR_BUS, MAXIMUM_BUS } BUS_TYPE; + +typedef enum { IO_SPACE, MEMORY_SPACE, CONFIGURATION_TYPE_0_SPACE, CONFIGURATION_TYPE_1_SPACE, MAX_ADDRESS_SPACE_TYPE } ADDRESS_SPACE_TYPE; + +typedef enum { EDGE, LEVEL} INTERRUPT_MODE; + +typedef enum {UnifiedCache,SplitCache,NoCache} CACHE_TYPE; + +typedef struct { + CHAR VendorId[8]; + CHAR ProductId[8]; + } + SYSTEMID; + +typedef struct CACHE_DESCRIPTION + { + ULONG NumberOfSets; // Number of associative sets + ULONG RefillSize; // Number of lines read per refill + ULONG LineSize; // Size of refill in bytes + ULONG Size; // Size of cache set in bytes + } + CACHE_DESCRIPTION; + +typedef struct SPLIT_CACHE_DESCRIPTION + { + CACHE_DESCRIPTION Instruction; // Configuration information on the insruction cache of a split cache + CACHE_DESCRIPTION Data; // Configuration information on the data cache of a split cache + } + SPLIT_CACHE_DESCRIPTION; + +typedef struct PROCESSOR_CACHE_DESCRIPTION + { + CACHE_TYPE CacheType; // Cache type(i.e. Split or Unified) + ULONG CoherentWithDma; // TRUE if cache is coherent with DMA reads and writes + union + { + CACHE_DESCRIPTION UnifiedCache; // Configuration information on a unified cache + SPLIT_CACHE_DESCRIPTION SplitCache; // Configuration information on a split cache + }; + } + PROCESSOR_CACHE_DESCRIPTION; + +typedef struct PROCESSOR + { + UCHAR *CpuIdentifier; // Pointer to the CPU's identifier + UCHAR *FpuIdentifier; // Pointer to the FPU's identifier + UCHAR *CpuName; // Pointer to the CPU's print name + UCHAR RevisionName[IDENTIFIER_LENGTH]; // CPU's revision print name + ULONG InternalClockSpeed; // Internal clock speed in MHz + ULONG ExternalClockSpeed; // External clock speed in MHz + ULONG StallExecutionDelay; // Count used in calibrated 1 us delay loop + PROCESSOR_CACHE_DESCRIPTION FirstLevel; // Primary cache configuration information + PROCESSOR_CACHE_DESCRIPTION SecondLevel; // Secondary cache configuration information + PROCESSOR_CACHE_DESCRIPTION ThirdLevel; // Third level cache configuration information + } + PROCESSOR; + +typedef struct SIMM_SOCKET + { + UCHAR Name[IDENTIFIER_LENGTH]; // Print string for the socket's name + UCHAR Size[IDENTIFIER_LENGTH]; // Print string for the socket's size + } + SIMM_SOCKET; + +typedef struct SYSTEM_IO_BUS + { + BUS_TYPE BusType; // Type of bus(i.e. ISA, EISA, VESA, PCI) + ULONG BusNumber; // Bus number starting from 0 + ULONG BusConfigurationError; // TRUE if the bus is not configured correctly + ULONG AlliasedBus; // TRUE if this bus is an allias of another bus + ULONG DmaCacheOffset; // Bus Physical Offset of Dma Cache + PHYSICAL_ADDRESS AddressSpace[MAX_ADDRESS_SPACE_TYPE]; // Processor physical address for each address space type + PVOID VirtualAddress[MAX_ADDRESS_SPACE_TYPE]; // Processor virtual address for each address space type + ULONG NumberOfPhysicalSlots; // Number of physical slots in bus + ULONG NumberOfVirtualSlots; // Number of virtual slots in bus + } + SYSTEM_IO_BUS; + +typedef struct PLATFORM_DEVICE_INFO + { + UCHAR FloppyDriveATypeInformation; + UCHAR FloppyDriveBTypeInformation; + UCHAR Lpt1IrqInformation; + UCHAR Lpt2IrqInformation; + UCHAR Lpt3IrqInformation; + UCHAR SerialMouseInformation; + UCHAR CheckEisaSlots; + UCHAR LoadEmbeddedScsiDrivers; + UCHAR LoadFlashScsiDrivers; + UCHAR LoadSoftScsiDrivers; + UCHAR EnableDelays; + UCHAR ResetDelay; + UCHAR DetectDelay; + UCHAR EnableIDEDriver; + UCHAR EnableX86Emulator; + } + PLATFORM_DEVICE_INFO; + +typedef struct { + ULONG StartOffset; + ULONG EndOffset; + ULONG CheckSumOffset; + } + NVRAMDETAILS; + +typedef struct PLATFORM_PARAMETER_BLOCK + { + SYSTEMID SystemId; // VendorID and ProductID for this platform + UCHAR ArchitectureName[16]; // String for the processor architecture(MIPS,ALPHA,X86,PPC) + UCHAR ModuleName[16]; // String used to identify the module(MOLDAU,TYNE,GAMBIT,ROGUE,COBRA) + + USHORT ArcVersion; // Major Version of ARC Specification + USHORT ArcRevision; // Minor Revision of ARC Specification + ULONG FirmwareRevision; // ARCS BIOS Firmware Revision + + ULONG MultiProcessorSystem; // TRUE if system is an MP system + ULONG NumberOfCpus; // Total number of CPUs in the system + PROCESSOR Processor[MAX_PROCESSORS]; // Configuration information on each processor + PROCESSOR_CACHE_DESCRIPTION External; // Configuration information on a shared external cache + + ULONG MemorySize; // Main memory size in bytes + ULONG SimmConfigurationError; // TRUE if the SIMMs are not correctly configured + SIMM_SOCKET SimmSocket[MAX_SIMM_SOCKETS]; // Configuration information on SIMMs + + ULONG DmaCacheError; // TRUE if the DMA cache did not pass the memory test + ULONG DmaCacheVirtualAddress; // Processor virtual address of the DMA cache + PHYSICAL_ADDRESS DmaCachePhysicalAddress; // Processor physical address of the DMA cache + ULONG DmaCacheSize; // Size of the DMA Cache in bytes + ULONG DmaAlignmentRequirement; // DMA Buffer Alignment requirement in bytes + + SYSTEM_IO_BUS SystemIoBus[MAX_BUSSES]; // Configuration information on system busses + + ULONG InterruptDispatchTable[MAX_SYSTEM_INTERRUPTS]; // Dispatch table for processor and bus interrupts + ULONG ExceptionDispatchTable[MAX_SYSTEM_EXCEPTIONS]; // Dispatch table for processor exceptions + + ULONG FirmwareBaseAddress; // Memory address for the start of the firmware code/data + ULONG FirmwareSize; // Size of the firmware code/data section in bytes + ULONG HeapStart; // Memory address for the start of the firmware heap + ULONG HeapEnd; // Memory address for the end of the firmware heap + ULONG StackBaseAddress; // Memory address for the start of the firmware stack + ULONG StackSize; // Size of the firmware stack section in bytes + ULONG ImageLibraryBaseAddress; // Memory address for the start of the image library + ULONG ImageLibrarySize; // Size of the image library in bytes + + UCHAR ConsoleOutAdapterName[ARC_NAME_LENGTH]; // ARC name for the console out device's adapter + UCHAR ConsoleOutName[ARC_NAME_LENGTH]; // ARC name for the console out device + UCHAR ProductIdentifier[IDENTIFIER_LENGTH]; // Product identifier string + UCHAR ProductName[IDENTIFIER_LENGTH]; // Product name string + UCHAR HelpAboutBoxString[IDENTIFIER_LENGTH]; // Help about box string + + PLATFORM_DEVICE_INFO PlatformDeviceInfo; // System info on how to detect I/O devices + + NVRAMDETAILS NVRAMDetails[NUMBEROFNVRAMSECTIONS]; // Describes organization of NVRAM. + + PVOID PlatformSpecificExtension; // Platform Specific Extension + } + PLATFORM_PARAMETER_BLOCK; + diff --git a/private/ntos/nthals/halflex/sources b/private/ntos/nthals/halflex/sources new file mode 100644 index 000000000..26c244e5d --- /dev/null +++ b/private/ntos/nthals/halflex/sources @@ -0,0 +1,141 @@ +!IF 0 + +Copyright (c) 1993 Microsoft Corporation + +Module Name: + + sources. + +Abstract: + + This file specifies the target component being built and the list of + sources files needed to build that component. Also specifies optional + compiler switches and libraries that are unique for the component being + built. + + +Author: + + David N. Cutler (davec) 8-Apr-1993 + +NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl + +!ENDIF + +MAJORCOMP=ntos +MINORCOMP=hal + +TARGETNAME=halflex +TARGETPATH=\nt\public\sdk\lib + +TARGETTYPE=HAL + +INCLUDES=..\x86new;..\inc;..\..\inc + +!IF $(MIPS) +TARGETLIBS=\nt\private\ntos\nthals\x86new\obj\*\x86new.lib \ + \nt\public\sdk\lib\*\libcntpr.lib + +MIPS_ENABLE_MIPS3=1 +MSC_WARNING_LEVEL=/W3 + +!ENDIF + +!IF $(ALPHA) +TARGETLIBS=\nt\public\sdk\lib\*\libcntpr.lib + +ALPHA_WARNING_LEVEL=-W3 +C_DEFINES=-DEV5 -DTAGGED_NVRAM +NT_UP=1 + +!ENDIF + +SOURCES= + +ALPHA_SOURCES=hal.rc \ + adjust.c \ + bushnd.c \ + drivesup.c \ + allstart.c \ + busdata.c \ + ioproc.c \ + iousage.c \ + xxbeep.c \ + xxclock.c \ + xxdisp.c \ + xxebsup.c \ + xxenvirv.c \ + xxhwsup.c \ + xxinithl.c \ + xxpcisup.c \ + xxport.c \ + xxreturn.c \ + xxsysint.c \ + xxtime.c \ + x86bios.c \ + alpha\addrsup.c \ + alpha\arcssup.c \ + alpha\evxcache.c \ + alpha\ev4prof.c \ + alpha\ev5prof.c \ + alpha\evxprof.c \ + alpha\initsys.c \ + alpha\intsup.c \ + alpha\jxmapio.c \ + alpha\minitlb.c \ + alpha\pcisup.c \ + alpha\perfcntr.c \ + alpha\portsup.c \ + alpha\xxinitnt.c \ + alpha\alphaio.s \ + alpha\ev4int.c \ + alpha\ev4ints.s \ + alpha\ev5ints.s \ + alpha\evxmem.s \ + alpha\halpal.s \ + alpha\evclock.s \ + alpha\info.c \ + alpha\xxidle.s + +MIPS_SOURCES=hal.rc \ + adjust.c \ + bushnd.c \ + drivesup.c \ + allstart.c \ + busdata.c \ + ioproc.c \ + iousage.c \ + xxbeep.c \ + xxclock.c \ + xxdisp.c \ + xxebsup.c \ + xxenvirv.c \ + xxhwsup.c \ + xxinithl.c \ + xxpcisup.c \ + xxport.c \ + xxreturn.c \ + xxsysint.c \ + xxtime.c \ + x86bios.c \ + mips\addrsup.c \ + mips\arcssup.c \ + mips\flushio.c \ + mips\info.c \ + mips\initsys.c \ + mips\jxmapio.c \ + mips\intsup.c \ + mips\j4prof.c \ + mips\pcisup.c \ + mips\portsup.c \ + mips\xxcalstl.c \ + mips\xxinitnt.c \ + mips\xxidle.s \ + mips\x4tb.s \ + mips\j4flshbf.s \ + mips\j4cache.s \ + mips\x4clock.s + +DLLDEF=obj\*\hal.def + +NTTARGETFILES=$(TARGETPATH)\*\hal.lib diff --git a/private/ntos/nthals/halflex/uniflex.h b/private/ntos/nthals/halflex/uniflex.h new file mode 100644 index 000000000..6a239d454 --- /dev/null +++ b/private/ntos/nthals/halflex/uniflex.h @@ -0,0 +1,108 @@ +/*++ + +Copyright (c) 1995 DeskStation Technology + +Module Name: + + platform.h + +Abstract: + + This file contains definitions specific to the UNIFLEX motherboard. + +Author: + + Michael D. Kinney 1-May-1995 + +Environment: + + Kernel mode + +Revision History: + + +--*/ + +// +// Define the motherboard types +// + +#define MOTHERBOARD_UNKNOWN 0 +#define TREBBIA13 1 +#define TREBBIA20 2 + +// +// Define the processor module types +// + +#define EV5_PROCESSOR_MODULE 0 +#define EV4_PROCESSOR_MODULE 1 +#define R4600_PROCESSOR_MODULE 2 +#define UNKNOWN_PROCESSOR_MODULE 0xffffffff + +// +// Define the module chip set revision constants +// + +#define EV4_MAX_CHIP_SET_REVISION 1 +#define EV5_MAX_CHIP_SET_REVISION 2 +#define MODULE_CHIP_SET_REVISION_UNKNOWN 0xffffffff + +// +// Define the bus types +// + +#define UNIFLEX_MACHINE_TYPE_ISA 0 +#define UNIFLEX_MACHINE_TYPE_EISA 1 + +#define MAX_EISA_BUSSES 2 +#define MAX_PCI_BUSSES 2 +#define MAX_DMA_CHANNELS_PER_EISA_BUS 8 + +// +// Define the maximum number of map registers that can be requested at one time +// if actual map registers are required for the transfer. +// + +#define MAXIMUM_ISA_MAP_REGISTER (0x10000/PAGE_SIZE) + +#define COPY_BUFFER 0xFFFFFFFF + +#define NO_SCATTER_GATHER 0x00000001 + +#define NULL_MAP_REGISTER_BASE (PVOID)(0xfffffffe) + +typedef volatile struct _TRANSLATION_ENTRY { + PVOID VirtualAddress; + ULONG PhysicalAddress; + ULONG Index; +} TRANSLATION_ENTRY, *PTRANSLATION_ENTRY; + +// +// Define the maximum and minimum time increment values in 100ns units. +// +// N.B. these values are as close to exact values as possible given the input +// clock of 1.19318167 hz (14.31818 / 12) +// + +#define MAXIMUM_INCREMENT (99968) // Time increment in 100ns units - Approx 10 ms +#define MINIMUM_INCREMENT (10032) // Time increment in 100ns units - Approx 1 ms + +// +// Define clock constants. +// + +#define AT_BUS_OSC 14318180 // 14.31818 MHz Crystal + +// +// Define UniFlex PCI Bus #0 motherboard device mask. +// + +#define TREB13_MOTHERBOARD_PCI_DEVICE_MASK (ULONG)((1<<0x0d) | (1<<0x0f) | (1<<0x10) | (1<<0x11)) +#define TREB20_MOTHERBOARD_PCI_DEVICE_MASK (ULONG)((1<<0x10) | (1<<0x11)) + +// +// Highest Virtual local PCI Slot is 20 == IDSEL PCI_AD[31] +// + +#define PCI_MAX_LOCAL_DEVICE 20 diff --git a/private/ntos/nthals/halflex/x86bios.c b/private/ntos/nthals/halflex/x86bios.c new file mode 100644 index 000000000..7968bca21 --- /dev/null +++ b/private/ntos/nthals/halflex/x86bios.c @@ -0,0 +1,599 @@ +/*++ + +Copyright (c) 1994 Microsoft Corporation + +Module Name: + + x86bios.c + +Abstract: + + + This module implements the platform specific interface between a device + driver and the execution of x86 ROM bios code for the device. + +Author: + + David N. Cutler (davec) 17-Jun-1994 + +Environment: + + Kernel mode only. + +Revision History: + +--*/ + +#include "halp.h" +#include "pci.h" +#include "xm86.h" +#include "x86new.h" + +// +// The X86 Emulator built into the HAL is suported on MIPS and PPC, +// but not ALPHA. If this is an ALPHA system, then don't include the +// code that uses the X86 emulator in the HAL. Instead, use the X86 +// emulator built in the Firmware if one is available. +// + +#ifndef ALPHA +#define ENABLE_HAL_X86_EMULATOR +#endif + +typedef struct FIRMWARE_INT_ARGUMENTS { + ULONG pEAX; + ULONG pEBX; + ULONG pECX; + ULONG pEDX; + ULONG pESI; + ULONG pEDI; + ULONG pEBP; + USHORT pES; + USHORT pDS; + USHORT pFlags; +} FIRMWARE_INT_ARGUMENTS, *PFIRMWARE_INT_ARGUMENTS; + +#ifdef ENABLE_HAL_X86_EMULATOR + +extern ULONG x86BiosIoSpace; +ULONG HalpPciConfigAddress; + +#endif + +ULONG HalpX86BiosInitialized = FALSE; +ULONG HalpEnableInt10Calls = FALSE; +ULONG HalpUseFirmwareX86Emulator = FALSE; + +typedef +VOID +(*PVENDOR_EXECUTE_INT) ( + IN USHORT Type, + IN PFIRMWARE_INT_ARGUMENTS Context + ); + +PVENDOR_EXECUTE_INT VendorX86ExecuteInt; + +VOID HalpInitializeX86DisplayAdapter() + +/*++ + +Routine Description: + + This function performs the initialization required to use an X86 emulator. + If a firmware level X86 emulator is available, then that emulator will be used. + Otherwise, we will default to using the emulator built into the HAL if it is + available. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + XM86_CONTEXT Context; + PSYSTEM_PARAMETER_BLOCK SystemParameterBlock = SYSTEM_BLOCK; + PCI_SLOT_NUMBER SlotNumber; + PPCI_COMMON_CONFIG PciData; + UCHAR buffer[PCI_COMMON_HDR_LENGTH]; + ULONG PciLength; + ULONG PciBus; + ULONG PciDevice; + ULONG PciFunction; + ULONG PciVideoAdapterFound; + + // + // If EISA I/O Ports or EISA Memory could not be mapped, then leave the + // X86 BIOS Emulator disabled. + // + + if (HalpEisaControlBase[0] == NULL || HalpEisaMemoryBase[0] == NULL) { + return; + } + + // + // If Firmware level X86 Bios Emulator exists, then use that instead of the + // one built into the HAL. + // + + if ((SystemParameterBlock->VendorVectorLength/4) >= 34) { + + VendorX86ExecuteInt = + *(PVENDOR_EXECUTE_INT *)((ULONG)(SystemParameterBlock->VendorVector) + 34*4); + + if (VendorX86ExecuteInt != NULL) { + HalpX86BiosInitialized = TRUE; + HalpUseFirmwareX86Emulator = TRUE; + HalpEnableInt10Calls = TRUE; + return; + } + } + +#ifdef ENABLE_HAL_X86_EMULATOR + + // + // Attempt to initialize the Display Adapter by executing the Display Adapters + // initialization code in its BIOS. The standard for PC video adapters is for + // the BIOS to reside at 0xC000:0000 on the ISA bus. + // + + PciVideoAdapterFound = FALSE; + PciData = (PPCI_COMMON_CONFIG) buffer; + PciBus = 0; + do { + for(PciDevice=0;PciDevice < PCI_MAX_DEVICES;PciDevice++) { + PciFunction = 0; + do { + SlotNumber.u.AsULONG = 0; + SlotNumber.u.bits.DeviceNumber = PciDevice; + SlotNumber.u.bits.FunctionNumber = PciFunction; + + PciLength = HalGetBusData ( + PCIConfiguration, + PciBus, + SlotNumber.u.AsULONG, + PciData, + PCI_COMMON_HDR_LENGTH + ); + + if (PciLength==0) { + break; + } + + if (PciData->VendorID == PCI_INVALID_VENDORID) { + break; + } + + if ( (PciData->BaseClass == 0x00 && PciData->SubClass == 0x01) || + (PciData->BaseClass == 0x03 && PciData->SubClass == 0x00) ) { + PciVideoAdapterFound = TRUE; + break; + } + if (PciFunction == 0 && ((PciData->HeaderType & 0x80)==0)) { + break; + } + PciFunction++; + } while (PciFunction < PCI_MAX_FUNCTION); + if (PciLength==0 || PciVideoAdapterFound) { + break; + } + } + if (PciLength==0 || PciVideoAdapterFound) { + break; + } + PciBus++; + } while (PciLength!=0); + + if (PciVideoAdapterFound) { + if (PciBus < HalpSecondPciBridgeBusNumber) { + x86BiosInitializeBios(HalpPciControlBase[0], HalpPciMemoryBase[0]); + } else { + x86BiosInitializeBios(HalpPciControlBase[1], HalpPciMemoryBase[1]); + } + Context.Eax = (PciBus<<8) | (PciDevice<<3) | PciFunction; + } else { + x86BiosInitializeBios(HalpEisaControlBase[0], HalpEisaMemoryBase[0]); + Context.Eax = 0; + } + HalpX86BiosInitialized = TRUE; + + Context.Ecx = 0; + Context.Edx = 0; + Context.Ebx = 0; + Context.Ebp = 0; + Context.Esi = 0; + Context.Edi = 0; + + if (x86BiosInitializeAdapter(0xc0000, &Context, NULL, NULL) != XM_SUCCESS) { + HalpEnableInt10Calls = FALSE; + return; + } + + HalpEnableInt10Calls = TRUE; + +#endif +} + +VOID HalpResetX86DisplayAdapter() + +/*++ + +Routine Description: + + This function invokes the X86 emulator to initialize a text mode 80x25 display. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + XM86_CONTEXT Context; + + // + // Make INT 10 call to initialize 80x25 color text mode. + // + + Context.Eax = 0x0003; // Function 0, Mode 3 + Context.Ebx = 0; + Context.Ecx = 0; + Context.Edx = 0; + Context.Esi = 0; + Context.Edi = 0; + Context.Ebp = 0; + + HalCallBios(0x10, + &Context.Eax, + &Context.Ebx, + &Context.Ecx, + &Context.Edx, + &Context.Esi, + &Context.Edi, + &Context.Ebp); +} + + +BOOLEAN +HalCallBios ( + IN ULONG BiosCommand, + IN OUT PULONG Eax, + IN OUT PULONG Ebx, + IN OUT PULONG Ecx, + IN OUT PULONG Edx, + IN OUT PULONG Esi, + IN OUT PULONG Edi, + IN OUT PULONG Ebp + ) + +/*++ + +Routine Description: + + This function provides the platform specific interface between a device + driver and the execution of the x86 ROM bios code for the specified ROM + bios command. + +Arguments: + + BiosCommand - Supplies the ROM bios command to be emulated. + + Eax to Ebp - Supplies the x86 emulation context. + +Return Value: + + A value of TRUE is returned if the specified function is executed. + Otherwise, a value of FALSE is returned. + +--*/ + +{ + FIRMWARE_INT_ARGUMENTS Arguments; + XM86_CONTEXT Context; + + // + // If the X86 BIOS Emulator has not been initialized then fail all INT calls. + // + + if (HalpX86BiosInitialized == FALSE) { + return(FALSE); + } + + // + // If the Video Adapter initialization failed, then we can not make INT 10 calls. + // + + if (BiosCommand == 0x10 && HalpEnableInt10Calls == FALSE) { + return(FALSE); + } + + if (HalpUseFirmwareX86Emulator == TRUE) { + + // + // Make private vector call to the emulator in the firmware. + // + + Arguments.pEAX = *Eax; + Arguments.pEBX = *Ebx; + Arguments.pECX = *Ecx; + Arguments.pEDX = *Edx; + Arguments.pESI = *Esi; + Arguments.pEDI = *Edi; + Arguments.pEBP = *Ebp; + Arguments.pES = 0; + Arguments.pDS = 0; + Arguments.pFlags = 0; + + HalpAllocateArcsResources(); + + VendorX86ExecuteInt((USHORT)BiosCommand,&Arguments); + + HalpFreeArcsResources(); + + *Eax = Arguments.pEAX; + *Ebx = Arguments.pEBX; + *Ecx = Arguments.pECX; + *Edx = Arguments.pEDX; + *Esi = Arguments.pESI; + *Edi = Arguments.pEDI; + *Ebp = Arguments.pEBP; + + } + else { + +#ifdef ENABLE_HAL_X86_EMULATOR + + // + // Make call to emulator build into HAL + // + + Context.Eax = *Eax; + Context.Ebx = *Ebx; + Context.Ecx = *Ecx; + Context.Edx = *Edx; + Context.Esi = *Esi; + Context.Edi = *Edi; + Context.Ebp = *Ebp; + + if (x86BiosExecuteInterrupt((UCHAR)BiosCommand, &Context, NULL, NULL) != XM_SUCCESS) { + return FALSE; + } + + *Eax = Context.Eax; + *Ebx = Context.Ebx; + *Ecx = Context.Ecx; + *Edx = Context.Edx; + *Esi = Context.Esi; + *Edi = Context.Edi; + *Ebp = Context.Ebp; + +#endif + + } + + return TRUE; +} + +#ifdef ENABLE_HAL_X86_EMULATOR + +ULONG +x86BiosReadIoSpace ( + IN XM_OPERATION_DATATYPE DataType, + IN USHORT PortNumber + ) + +/*++ + +Routine Description: + + This function reads from emulated I/O space. + +Arguments: + + DataType - Supplies the datatype for the read operation. + + PortNumber - Supplies the port number in I/O space to read from. + +Return Value: + + The value read from I/O space is returned as the function value. + + N.B. If an aligned operation is specified, then the individual + bytes are read from the specified port one at a time and + assembled into the specified datatype. + +--*/ + +{ + + ULONG Result; + ULONG PciBusNumber; + PCI_SLOT_NUMBER SlotNumber; + + union { + PUCHAR Byte; + PUSHORT Word; + PULONG Long; + } u; + + // + // Compute port address and read port. + // + + // + // If PortNumber is in ISA Motherboard space, then overide the base address of + // the IO space with ISA space, otherwise, use the base address passed in on + // initialization. + // + + if (PortNumber < 0x1000 && ((PortNumber & 0x3ff) < 0x100)) { + u.Long = (PULONG)((ULONG)HalpEisaControlBase[0] + PortNumber); + } else { + u.Long = (PULONG)(x86BiosIoSpace + PortNumber); + } + + if (DataType == BYTE_DATA) { + Result = READ_REGISTER_UCHAR(u.Byte); + + } else if (DataType == LONG_DATA) { + + // + // If PortNumber is attempting to access the PCI config registers defined for X86 systems, + // intercept them, and make the appropriate HAL call to get the PCI confoguration data. + // + + if (PortNumber == 0xcf8) { + Result = HalpPciConfigAddress; + } else if (PortNumber == 0xcfc && (HalpPciConfigAddress & 0x80000000)) { + PciBusNumber = (HalpPciConfigAddress >> 16) & 0xff; + SlotNumber.u.AsULONG = 0; + SlotNumber.u.bits.DeviceNumber = (HalpPciConfigAddress >> 11) & 0x1f; + SlotNumber.u.bits.FunctionNumber = (HalpPciConfigAddress >> 8) & 0x07; + HalGetBusDataByOffset (PCIConfiguration, + PciBusNumber, + SlotNumber.u.AsULONG, + &Result, + HalpPciConfigAddress & 0xfc, + 4 + ); + + } else { + if (((ULONG)u.Long & 0x3) != 0) { + Result = (READ_REGISTER_UCHAR(u.Byte + 0)) | + (READ_REGISTER_UCHAR(u.Byte + 1) << 8) | + (READ_REGISTER_UCHAR(u.Byte + 2) << 16) | + (READ_REGISTER_UCHAR(u.Byte + 3) << 24); + + } else { + Result = READ_REGISTER_ULONG(u.Long); + } + } + + } else { + if (((ULONG)u.Word & 0x1) != 0) { + Result = (READ_REGISTER_UCHAR(u.Byte + 0)) | + (READ_REGISTER_UCHAR(u.Byte + 1) << 8); + + } else { + Result = READ_REGISTER_USHORT(u.Word); + } + } + + return Result; +} + +VOID +x86BiosWriteIoSpace ( + IN XM_OPERATION_DATATYPE DataType, + IN USHORT PortNumber, + IN ULONG Value + ) + +/*++ + +Routine Description: + + This function write to emulated I/O space. + + N.B. If an aligned operation is specified, then the individual + bytes are written to the specified port one at a time. + +Arguments: + + DataType - Supplies the datatype for the write operation. + + PortNumber - Supplies the port number in I/O space to write to. + + Value - Supplies the value to write. + +Return Value: + + None. + +--*/ + +{ + ULONG PciBusNumber; + PCI_SLOT_NUMBER SlotNumber; + + union { + PUCHAR Byte; + PUSHORT Word; + PULONG Long; + } u; + + // + // Compute port address and read port. + // + + // + // If PortNumber is in ISA Motherboard space, then overide the base address of + // the IO space with ISA space, otherwise, use the base address passed in on + // initialization. + // + + if (PortNumber < 0x1000 && ((PortNumber & 0x3ff) < 0x100)) { + u.Long = (PULONG)((ULONG)HalpEisaControlBase[0] + PortNumber); + } else { + u.Long = (PULONG)(x86BiosIoSpace + PortNumber); + } + + if (DataType == BYTE_DATA) { + WRITE_REGISTER_UCHAR(u.Byte, (UCHAR)Value); + + } else if (DataType == LONG_DATA) { + + // + // If PortNumber is attempting to access the PCI config registers defined for X86 systems, + // intercept them, and make the appropriate HAL call to get the PCI confoguration data. + // + + if (PortNumber == 0xcf8) { + HalpPciConfigAddress = Value; + } else if (PortNumber == 0xcfc) { + PciBusNumber = (HalpPciConfigAddress >> 16) & 0xff; + SlotNumber.u.AsULONG = 0; + SlotNumber.u.bits.DeviceNumber = (HalpPciConfigAddress >> 11) & 0x1f; + SlotNumber.u.bits.FunctionNumber = (HalpPciConfigAddress >> 8) & 0x07; + HalSetBusDataByOffset (PCIConfiguration, + PciBusNumber, + SlotNumber.u.AsULONG, + &Value, + HalpPciConfigAddress & 0xfc, + 4 + ); + + } else { + if (((ULONG)u.Long & 0x3) != 0) { + WRITE_REGISTER_UCHAR(u.Byte + 0, (UCHAR)(Value)); + WRITE_REGISTER_UCHAR(u.Byte + 1, (UCHAR)(Value >> 8)); + WRITE_REGISTER_UCHAR(u.Byte + 2, (UCHAR)(Value >> 16)); + WRITE_REGISTER_UCHAR(u.Byte + 3, (UCHAR)(Value >> 24)); + + } else { + WRITE_REGISTER_ULONG(u.Long, Value); + } + } + + } else { + if (((ULONG)u.Word & 0x1) != 0) { + WRITE_REGISTER_UCHAR(u.Byte + 0, (UCHAR)(Value)); + WRITE_REGISTER_UCHAR(u.Byte + 1, (UCHAR)(Value >> 8)); + + } else { + WRITE_REGISTER_USHORT(u.Word, (USHORT)Value); + } + } + + return; +} + +#endif diff --git a/private/ntos/nthals/halflex/xxbeep.c b/private/ntos/nthals/halflex/xxbeep.c new file mode 100644 index 000000000..b3beef50e --- /dev/null +++ b/private/ntos/nthals/halflex/xxbeep.c @@ -0,0 +1,125 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + jxbeep.c + +Abstract: + + This module implements the HAL speaker "beep" routines for a MIPS + system. + +Author: + + +Environment: + + Kernel mode + +Revision History: + +--*/ + +#include "halp.h" +#include "eisa.h" + + +BOOLEAN +HalMakeBeep( + IN ULONG Frequency + ) + +/*++ + +Routine Description: + + This function sets the frequency of the speaker, causing it to sound a + tone. The tone will sound until the speaker is explicitly turned off, + so the driver is responsible for controlling the duration of the tone. + +Arguments: + + Frequency - Supplies the frequency of the desired tone. A frequency of + 0 means the speaker should be shut off. + +Return Value: + + TRUE - Operation was successful (frequency within range or zero). + FALSE - Operation was unsuccessful (frequency was out of range). + Current tone (if any) is unchanged. + +--*/ + +{ + KIRQL oldIrql; + NMI_STATUS NmiStatus; + PEISA_CONTROL controlBase; + TIMER_CONTROL timerControl; + ULONG newCount; + + controlBase = HalpEisaControlBase[0]; + + KeRaiseIrql(DISPATCH_LEVEL, &oldIrql); + + // + // Stop the speaker. + // + + *((PUCHAR) &NmiStatus) = READ_REGISTER_UCHAR(&controlBase->NmiStatus); + + NmiStatus.SpeakerGate = 0; + NmiStatus.SpeakerData = 0; + + WRITE_REGISTER_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus)); + + if (Frequency == 0) { + KeLowerIrql(oldIrql); + return(TRUE); + } + + // + // Calculate the new counter value. + // + + newCount = (AT_BUS_OSC/12) / Frequency; + + // + // The new count must be less than 16 bits in value. + // + + if (newCount >= 0x10000) { + KeLowerIrql(oldIrql); + return(FALSE); + } + + // + // Set the speaker timer to the correct mode. + // + + timerControl.BcdMode = 0; + timerControl.Mode = TM_SQUARE_WAVE; + timerControl.SelectByte = SB_LSB_THEN_MSB; + timerControl.SelectCounter = SELECT_COUNTER_2; + + WRITE_REGISTER_UCHAR(&controlBase->CommandMode1, *((PUCHAR) &timerControl)); + + // + // Set the speaker timer to the correct mode. + // + + WRITE_REGISTER_UCHAR(&controlBase->SpeakerTone, (UCHAR)(newCount & 0xff)); + WRITE_REGISTER_UCHAR(&controlBase->SpeakerTone, (UCHAR)(newCount >> 8)); + + // + // Start the speaker. + // + + NmiStatus.SpeakerGate = 1; + NmiStatus.SpeakerData = 1; + + WRITE_REGISTER_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus)); + KeLowerIrql(oldIrql); + return(TRUE); +} diff --git a/private/ntos/nthals/halflex/xxclock.c b/private/ntos/nthals/halflex/xxclock.c new file mode 100644 index 000000000..3a05b3ac1 --- /dev/null +++ b/private/ntos/nthals/halflex/xxclock.c @@ -0,0 +1,174 @@ +/*++ + +Copyright (c) 1994 Microsoft Corporation + +Module Name: + + xxclock.c + +Abstract: + + + This module implements the function necesssary to change the clock + interrupt rate. + +Author: + + David N. Cutler (davec) 7-Feb-1994 + +Environment: + + Kernel mode only. + +Revision History: + +--*/ + +#include "halp.h" +#include "eisa.h" + +// +// Define clock count and time table. +// + +typedef struct _COUNT_ENTRY { + ULONG Count; + ULONG Time; +} COUNT_ENTRY, *PCOUNT_ENTRY; + +COUNT_ENTRY TimeTable[] = { + {1197, 10032}, + {2394, 20064}, + {3591, 30096}, + {4767, 39952}, + {5964, 49984}, + {7161, 60016}, + {8358, 70048}, + {9555, 80080}, + {10731, 89936}, + {11928, 99968} + }; + +// +// Define global data used to communicate new clock rates to the clock +// interrupt service routine. +// + +ULONG HalpCurrentTimeIncrement; +ULONG HalpNextIntervalCount; +ULONG HalpNextTimeIncrement; +ULONG HalpNewTimeIncrement; + +VOID +HalpProgramIntervalTimer( + IN ULONG IntervalCount + ) + +/*++ + +Routine Description: + + This function is called to program the interval timer. It is used during + Phase 1 initialization to start the heartbeat timer. It also used by + the clock interrupt interrupt routine to change the hearbeat timer rate + when a call to HalSetTimeIncrement has been made in the previous time slice. + +Arguments: + + IntervalCount - Supplies cound value to be placed in the timer/counter. + +Return Value: + + None + +--*/ + +{ + + PEISA_CONTROL controlBase; + TIMER_CONTROL timerControl; + + // + // Set the system clock timer to the correct mode. + // + + timerControl.BcdMode = 0; + timerControl.Mode = TM_SQUARE_WAVE; + timerControl.SelectByte = SB_LSB_THEN_MSB; + timerControl.SelectCounter = SELECT_COUNTER_0; + + controlBase = HalpEisaControlBase[0]; + + WRITE_REGISTER_UCHAR(&controlBase->CommandMode1, *((PUCHAR) &timerControl)); + + // + // Set the system clock timer to the correct frequency. + // + + WRITE_REGISTER_UCHAR(&controlBase->Timer1, (UCHAR)IntervalCount); + WRITE_REGISTER_UCHAR(&controlBase->Timer1, (UCHAR)(IntervalCount >> 8)); +} + +ULONG +HalSetTimeIncrement ( + IN ULONG DesiredIncrement + ) + +/*++ + +Routine Description: + + This function is called to set the clock interrupt rate to the frequency + required by the specified time increment value. + + N.B. This function is only executed on the processor that keeps the + system time. + +Arguments: + + DesiredIncrement - Supplies desired number of 100ns units between clock + interrupts. + +Return Value: + + The actual time increment in 100ns units. + +--*/ + +{ + + ULONG Index; + KIRQL OldIrql; + + // + // Raise IRQL to the highest level, set the new clock interrupt + // parameters, lower IRQl, and return the new time increment value. + // + + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + + // + // The new clock count value is selected from a precomputed table of + // count/time pairs. The values in the table were selected for their + // accuracy and closeness to the values of 1ms, 2ms, 3ms, etc. to 10ms. + // + // N.B. The NT executive guarantees that this function will never + // be called with the desired incrment less than the minimum + // increment or greater than the maximum increment. + // + + for (Index = 0; Index < sizeof(TimeTable) / sizeof(COUNT_ENTRY); Index += 1) { + if (DesiredIncrement <= TimeTable[Index].Time) { + break; + } + } + + if (DesiredIncrement < TimeTable[Index].Time) { + Index -= 1; + } + + HalpNextIntervalCount = TimeTable[Index].Count; + HalpNewTimeIncrement = TimeTable[Index].Time; + KeLowerIrql(OldIrql); + return HalpNewTimeIncrement; +} diff --git a/private/ntos/nthals/halflex/xxdisp.c b/private/ntos/nthals/halflex/xxdisp.c new file mode 100644 index 000000000..2722c3223 --- /dev/null +++ b/private/ntos/nthals/halflex/xxdisp.c @@ -0,0 +1,293 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + jxdisp.c + +Abstract: + + This module implements the HAL display initialization and output routines + for a MIPS R3000 or R4000 Jazz system. + +Author: + + Andre Vachon (andreva) 09-May-1992 + David N. Cutler (davec) 27-Apr-1991 + Michael D. Kinney 30-Apr-1995 + +Environment: + + Kernel mode + +Revision History: + +--*/ + +#include "halp.h" + +#define CSI 0x9b +#define MAX_DISPLAY_BUFFER 256 + +int sprintf(); + +extern ULONG IoSpaceAlreadyMapped; + +static UCHAR DisplayInitializationString[] = {CSI,'3','7',';','4','4','m',CSI,'2','J',0}; +static UCHAR CarriageReturnString[] = {10,13,0}; + +static ULONG HalOwnsDisplay = FALSE; +static ULONG DisplayFile; + +static UCHAR DisplayBuffer[MAX_DISPLAY_BUFFER]; +static ULONG DisplayBufferInitialized = FALSE; + +PHAL_RESET_DISPLAY_PARAMETERS HalpResetDisplayParameters; + + +VOID +HalAcquireDisplayOwnership ( + IN PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters + ) + +/*++ + +Routine Description: + + This routine switches ownership of the display away from the HAL to + the system display driver. It is called when the system has reached + a point during bootstrap where it is self supporting and can output + its own messages. Once ownership has passed to the system display + driver any attempts to output messages using HalDisplayString must + result in ownership of the display reverting to the HAL and the + display hardware reinitialized for use by the HAL. + +Arguments: + + ResetDisplayParameters - if non-NULL the address of a function + the hal can call to reset the video card. The function returns + TRUE if the display was reset. + +Return Value: + + None. + +--*/ + +{ + HalpAllocateArcsResources(); + ArcClose(DisplayFile); + HalpFreeArcsResources(); + HalOwnsDisplay = FALSE; + HalpResetDisplayParameters = ResetDisplayParameters; + return; +} + + +VOID +HalDisplayString ( + PUCHAR String + ) + +/*++ + +Routine Description: + + This routine displays a character string on the display screen. + +Arguments: + + String - Supplies a pointer to the characters that are to be displayed. + +Return Value: + + None. + +--*/ + +{ + ULONG Count; + ULONG i; + + if (DisplayBufferInitialized==FALSE) { + DisplayBufferInitialized = TRUE; + strcpy(DisplayBuffer,""); + } + + if (IoSpaceAlreadyMapped == FALSE) { + if ((strlen(DisplayBuffer)+strlen(String)) < MAX_DISPLAY_BUFFER) { + strcat(DisplayBuffer,String); + } + return; + } + + if (HalOwnsDisplay==FALSE) { + + if (HalpResetDisplayParameters != NULL) { + (HalpResetDisplayParameters)(80,25); + } + + HalpResetX86DisplayAdapter(); + + HalpAllocateArcsResources(); + + ArcOpen(ArcGetEnvironmentVariable("ConsoleOut"),ArcOpenWriteOnly,&DisplayFile); + ArcWrite(DisplayFile,DisplayInitializationString,strlen(DisplayInitializationString),&Count); + if (strlen(DisplayBuffer)!=0) { + + for(i=0;iCursorMaxXPosition; + *HeightInLines = DisplayStatus->CursorMaxYPosition; + *CursorColumn = DisplayStatus->CursorXPosition; + *CursorRow = DisplayStatus->CursorYPosition; + + return; +} + +VOID +HalSetDisplayParameters ( + IN ULONG CursorColumn, + IN ULONG CursorRow + ) + +/*++ + +Routine Description: + + This routine set the current cursor position on the display area. + +Arguments: + + CursorColumn - Supplies the new display column position. + + CursorRow - Supplies a the new display row position. + +Return Value: + + None. + +--*/ + +{ + CHAR SetCursorPositionString[20]; + ULONG Count; + + // + // If the HAL does not already own the display, then print an empty string. + // This guarantees that the file descriptor DisplayFile is valid. + // + + if (!HalOwnsDisplay) { + HalDisplayString(""); + } + + // + // Build ANSI sequence to set the cursor position. + // + + sprintf(SetCursorPositionString,"%c%d;%dH",CSI,CursorRow,CursorColumn); + + HalpAllocateArcsResources(); + + ArcWrite(DisplayFile,SetCursorPositionString,strlen(SetCursorPositionString),&Count); + + HalpFreeArcsResources(); + + return; +} diff --git a/private/ntos/nthals/halflex/xxebsup.c b/private/ntos/nthals/halflex/xxebsup.c new file mode 100644 index 000000000..203c21720 --- /dev/null +++ b/private/ntos/nthals/halflex/xxebsup.c @@ -0,0 +1,2375 @@ +/*++ + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + ixhwsup.c + +Abstract: + + This module contains the IoXxx routines for the NT I/O system that + are hardware dependent. Were these routines not hardware dependent, + they would reside in the iosubs.c module. + +Author: + + Darryl E. Havens (darrylh) 11-Apr-1990 + +Environment: + + Kernel mode + +Revision History: + + +--*/ + +#include "halp.h" +#include "eisa.h" + +// +// Define save area for EISA adapter objects. +// + +PADAPTER_OBJECT HalpEisaAdapter[MAX_EISA_BUSSES][MAX_DMA_CHANNELS_PER_EISA_BUS]; + +UCHAR HalpEisaInterrupt1Mask[MAX_EISA_BUSSES]; +UCHAR HalpEisaInterrupt2Mask[MAX_EISA_BUSSES]; +UCHAR HalpEisaInterrupt1Level[MAX_EISA_BUSSES]; +UCHAR HalpEisaInterrupt2Level[MAX_EISA_BUSSES]; + +PADAPTER_OBJECT +HalpAllocateAdapter( + IN ULONG MapRegistersPerChannel, + IN PVOID AdapterBaseVa, + IN PVOID ChannelNumber + ); + + +VOID +HalpCopyBufferMap( + IN PMDL Mdl, + IN PTRANSLATION_ENTRY translationEntry, + IN PVOID CurrentVa, + IN ULONG Length, + IN BOOLEAN WriteToDevice + ) + +/*++ + +Routine Description: + + This routine copies the specified data between the user buffer and the + map register buffer. First, the user buffer is mapped, if need be then + the data is copied. Finally, the user buffer will be unmapped, if need be. + +Arguments: + + Mdl - Pointer to the Mdl that describes the pages of memory that are + being read or written. + + translationEntry - The address of the base map register that has been + allocated to the device driver for use in mapping the xfer. + + CurrentVa - Current Virtual Address in the buffer described by the Mdl + that the transfer is being done to or from. + + Length - The length of the transfer. This determines the number of map + registers that need to be written to map the transfer. + + WriteToDevice - A Boolean value that indicates whether this is a write + to the device from memory of vise-versa. + +Return Value: + + None + +--*/ + +{ + + PCCHAR bufferAddress; + PCCHAR mapAddress; + + // + // Get the system address of the MDL. + // + + bufferAddress = MmGetSystemAddressForMdl(Mdl); + + // + // Calculate the actual start of the buffer based on the system VA and + // the current VA. + // + + bufferAddress += (PCCHAR) CurrentVa - (PCCHAR) MmGetMdlVirtualAddress(Mdl); + + mapAddress = (PCCHAR) translationEntry->VirtualAddress + + BYTE_OFFSET(CurrentVa); + + // + // Flush all writes off chip + // + + HalpMb(); + HalpMb(); + + // + // Copy the data between the user buffer and the map buffer. + // + + if (WriteToDevice) { + + RtlMoveMemory( mapAddress, bufferAddress, Length); + + } else { + + RtlMoveMemory ( bufferAddress, mapAddress, Length); + + } + + // + // Flush all writes off chip + // + + HalpMb(); + HalpMb(); +} + + +NTSTATUS +HalAllocateAdapterChannel( + IN PADAPTER_OBJECT AdapterObject, + IN PWAIT_CONTEXT_BLOCK Wcb, + IN ULONG NumberOfMapRegisters, + IN PDRIVER_CONTROL ExecutionRoutine + ) +/*++ + +Routine Description: + + This routine allocates the adapter channel specified by the adapter object. + This is accomplished by placing the device object of the driver that wants + to allocate the adapter on the adapter's queue. If the queue is already + "busy", then the adapter has already been allocated, so the device object + is simply placed onto the queue and waits until the adapter becomes free. + + Once the adapter becomes free (or if it already is), then the driver's + execution routine is invoked. + + Also, a number of map registers may be allocated to the driver by specifying + a non-zero value for NumberOfMapRegisters. Then the map register must be + allocated from the master adapter. Once there are a sufficient number of + map registers available, then the execution routine is called and the + base address of the allocated map registers in the adapter is also passed + to the driver's execution routine. + +Arguments: + + AdapterObject - Pointer to the adapter control object to allocate to the + driver. + + Wcb - Supplies a wait context block for saving the allocation parameters. + The DeviceObject, CurrentIrp and DeviceContext should be initalized. + + NumberOfMapRegisters - The number of map registers that are to be allocated + from the channel, if any. + + ExecutionRoutine - The address of the driver's execution routine that is + invoked once the adapter channel (and possibly map registers) have been + allocated. + +Return Value: + + Returns STATUS_SUCESS unless too many map registers are requested. + +Notes: + + Note that this routine MUST be invoked at DISPATCH_LEVEL or above. + +--*/ +{ + + PADAPTER_OBJECT MasterAdapter; + BOOLEAN Busy = FALSE; + IO_ALLOCATION_ACTION Action; + KIRQL Irql; + LONG MapRegisterNumber; + BOOLEAN MappingRequired; + + // + // Begin by obtaining a pointer to the master adapter associated with this + // request. + // + + MasterAdapter = AdapterObject->MasterAdapter; + + // + // Initialize the device object's wait context block in case this device + // must wait before being able to allocate the adapter. + // + + Wcb->DeviceRoutine = ExecutionRoutine; + Wcb->NumberOfMapRegisters = NumberOfMapRegisters; + + // + // Allocate the adapter object for this particular device. If the + // adapter cannot be allocated because it has already been allocated + // to another device, then return to the caller now; otherwise, + // continue. + // + + if (!KeInsertDeviceQueue( &AdapterObject->ChannelWaitQueue, + &Wcb->WaitQueueEntry )) { + + // + // Save the parameters in case there are not enough map registers. + // + + AdapterObject->NumberOfMapRegisters = NumberOfMapRegisters; + AdapterObject->CurrentWcb = Wcb; + + // + // The adapter was not busy so it has been allocated. Now check + // to see whether this driver wishes to allocate any map registers. + // Ensure that this adapter has enough total map registers + // to satisfy the request. + // + + MappingRequired = FALSE; + + if (NumberOfMapRegisters != 0 && AdapterObject->NeedsMapRegisters) { + MappingRequired = TRUE; + } + + if (MappingRequired) { + + // + // Lock the map register bit map and the adapter queue in the + // master adapter object. The channel structure offset is used as + // a hint for the register search. + // + + if (NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) { + AdapterObject->NumberOfMapRegisters = 0; + IoFreeAdapterChannel(AdapterObject); + + return(STATUS_INSUFFICIENT_RESOURCES); + } + + KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql ); + + MapRegisterNumber = -1; + + if (IsListEmpty( &MasterAdapter->AdapterQueue)) { + + MapRegisterNumber = RtlFindClearBitsAndSet( + MasterAdapter->MapRegisters, + NumberOfMapRegisters, + 0 + ); + } + + if (MapRegisterNumber == -1) { + + // + // There were not enough free map registers. Queue this request + // on the master adapter where is will wait until some registers + // are deallocated. + // + + InsertTailList( &MasterAdapter->AdapterQueue, + &AdapterObject->AdapterQueue + ); + Busy = 1; + + } else { + + // + // Calculate the map register base from the allocated map + // register and base of the master adapter object. + // + + AdapterObject->MapRegisterBase = (PVOID)((PTRANSLATION_ENTRY) + MasterAdapter->MapRegisterBase + MapRegisterNumber); + + // + // Set the no scatter/gather flag if scatter/gather not + // supported. + // + + if (!AdapterObject->ScatterGather) { + + AdapterObject->MapRegisterBase = (PVOID) + ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER); + + } + } + + KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql ); + + } else { + + AdapterObject->MapRegisterBase = NULL_MAP_REGISTER_BASE; + AdapterObject->NumberOfMapRegisters = 0; + } + + // + // If there were either enough map registers available or no map + // registers needed to be allocated, invoke the driver's execution + // routine now. + // + + if (!Busy) { + + AdapterObject->CurrentWcb = Wcb; + Action = ExecutionRoutine( Wcb->DeviceObject, + Wcb->CurrentIrp, + AdapterObject->MapRegisterBase, + Wcb->DeviceContext ); + + // + // If the driver would like to have the adapter deallocated, + // then release the adapter object. + // + + if (Action == DeallocateObject) { + + IoFreeAdapterChannel( AdapterObject ); + + } else if (Action == DeallocateObjectKeepRegisters) { + + // + // Set the NumberOfMapRegisters = 0 in the adapter object. + // This will keep IoFreeAdapterChannel from freeing the + // registers. After this it is the driver's responsiblity to + // keep track of the number of map registers. + // + + AdapterObject->NumberOfMapRegisters = 0; + IoFreeAdapterChannel(AdapterObject); + + } + } + } + return(STATUS_SUCCESS); +} + +PVOID +HalAllocateCrashDumpRegisters( + IN PADAPTER_OBJECT AdapterObject, + IN PULONG NumberOfMapRegisters + ) +/*++ + +Routine Description: + + This routine is called during the crash dump disk driver's initialization + to allocate a number map registers permanently. + +Arguments: + + AdapterObject - Pointer to the adapter control object to allocate to the + driver. + NumberOfMapRegisters - Number of map registers requested. This field is + updated with the number of registers allocated in the event that less + were available than requested. + +Return Value: + + Returns STATUS_SUCESS if map registers allocated. + +--*/ +{ + PADAPTER_OBJECT MasterAdapter; + ULONG MapRegisterNumber; + + // + // Begin by obtaining a pointer to the master adapter associated with this + // request. + // + + MasterAdapter = AdapterObject->MasterAdapter; + + // + // Check to see whether this driver needs to allocate any map registers. + // + + if (AdapterObject->NeedsMapRegisters) { + + // + // Ensure that this adapter has enough total map registers to satisfy + // the request. + // + + if (*NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) { + AdapterObject->NumberOfMapRegisters = 0; + return NULL; + } + + // + // Attempt to allocate the required number of map registers w/o + // affecting those registers that were allocated when the system + // crashed. + // + + MapRegisterNumber = (ULONG)-1; + + MapRegisterNumber = RtlFindClearBitsAndSet( + MasterAdapter->MapRegisters, + *NumberOfMapRegisters, + 0 + ); + + if (MapRegisterNumber == (ULONG)-1) { + + // + // Not enough free map registers were found, so they were busy + // being used by the system when it crashed. Force the appropriate + // number to be "allocated" at the base by simply overjamming the + // bits and return the base map register as the start. + // + + RtlSetBits( + MasterAdapter->MapRegisters, + 0, + *NumberOfMapRegisters + ); + MapRegisterNumber = 0; + + } + + // + // Calculate the map register base from the allocated map + // register and base of the master adapter object. + // + + AdapterObject->MapRegisterBase = (PVOID)((PTRANSLATION_ENTRY) + MasterAdapter->MapRegisterBase + MapRegisterNumber); + + // + // Set the no scatter/gather flag if scatter/gather not + // supported. + // + + if (!AdapterObject->ScatterGather) { + AdapterObject->MapRegisterBase = (PVOID) + ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER); + } + + } else { + + AdapterObject->MapRegisterBase = NULL_MAP_REGISTER_BASE; + AdapterObject->NumberOfMapRegisters = 0; + } + + return AdapterObject->MapRegisterBase; +} + +PADAPTER_OBJECT +HalGetAdapter( + IN PDEVICE_DESCRIPTION DeviceDescriptor, + OUT PULONG NumberOfMapRegisters + ) + +/*++ + +Routine Description: + + This function returns the appropriate adapter object for the device defined + in the device description structure. This code works for Isa and Eisa + systems. + +Arguments: + + DeviceDescriptor - Supplies a description of the deivce. + + NumberOfMapRegisters - Returns the maximum number of map registers which + may be allocated by the device driver. + +Return Value: + + A pointer to the requested adapter object or NULL if an adapter could not + be created. + +--*/ + +{ + PADAPTER_OBJECT adapterObject; + PVOID adapterBaseVa; + UCHAR channelNumber; + ULONG controllerNumber; + DMA_EXTENDED_MODE extendedMode; + UCHAR adapterMode; + ULONG numberOfMapRegisters; + BOOLEAN useChannel; + BOOLEAN eisaSystem; + ULONG maximumLength; + + eisaSystem = HalpBusType == UNIFLEX_MACHINE_TYPE_EISA ? TRUE : FALSE; + + // + // Determine if the the channel number is important. Master cards on + // Eisa and Mca do not use a channel number. + // + + if (DeviceDescriptor->InterfaceType != Isa && + DeviceDescriptor->Master) { + + useChannel = FALSE; + } else { + + useChannel = TRUE; + } + + // + // Limit the maximum length to 2 GB this is done so that the BYTES_TO_PAGES + // macro works correctly. + // + + maximumLength = DeviceDescriptor->MaximumLength & 0x7fffffff; + + // + // Channel 4 cannot be used since it is used for chaining. Return null if + // it is requested. + // + + if (DeviceDescriptor->DmaChannel == 4 && useChannel) { + + return(NULL); + } + + // + // Determine the number of map registers required based on the maximum + // transfer length, up to a maximum number. + // + + numberOfMapRegisters = BYTES_TO_PAGES(maximumLength) + + 1; + + // + // If the device is an ISA device, then limit the number of map registers. + // + + if (DeviceDescriptor->InterfaceType == Isa) { + numberOfMapRegisters = numberOfMapRegisters > MAXIMUM_ISA_MAP_REGISTER ? + MAXIMUM_ISA_MAP_REGISTER : numberOfMapRegisters; + } + + // + // Make sure there where enough registers allocated initalize to support + // this size relaibly. This implies there must be to chunks equal to + // the allocatd size. This is only a problem on Isa systems where the + // map buffers cannot cross 64KB boundtires. + // + + if (!eisaSystem && + numberOfMapRegisters > HalpMapBufferSize / (PAGE_SIZE * 2)) { + + numberOfMapRegisters = (HalpMapBufferSize / (PAGE_SIZE * 2)); + } + + // + // If the device is not a master then it only needs one map register + // and does scatter/Gather. + // + + if (DeviceDescriptor->ScatterGather && !DeviceDescriptor->Master) { + + numberOfMapRegisters = 1; + } + + // + // Set the channel number number. + // + + channelNumber = (UCHAR)(DeviceDescriptor->DmaChannel & 0x03); + + // + // Set the adapter base address to the Base address register and controller + // number. + // + + if (!(DeviceDescriptor->DmaChannel & 0x04)) { + + controllerNumber = 1; + adapterBaseVa = (PVOID) &((PEISA_CONTROL) HalpEisaControlBase[DeviceDescriptor->BusNumber])->Dma1BasePort; + + } else { + + controllerNumber = 2; + adapterBaseVa = &((PEISA_CONTROL) HalpEisaControlBase[DeviceDescriptor->BusNumber])->Dma2BasePort; + + } + + // + // Determine if a new adapter object is necessary. If so then allocate it. + // + + if (useChannel && HalpEisaAdapter[DeviceDescriptor->BusNumber][DeviceDescriptor->DmaChannel] != NULL) { + + adapterObject = HalpEisaAdapter[DeviceDescriptor->BusNumber][DeviceDescriptor->DmaChannel]; + + if (adapterObject->NeedsMapRegisters) { + + if (numberOfMapRegisters > adapterObject->MapRegistersPerChannel) { + + adapterObject->MapRegistersPerChannel = numberOfMapRegisters; + } + } + + } else { + + // + // Allocate an adapter object. + // + + adapterObject = (PADAPTER_OBJECT) HalpAllocateAdapter( + numberOfMapRegisters, + adapterBaseVa, + NULL + ); + + if (adapterObject == NULL) { + + return(NULL); + + } + + if (useChannel) { + + HalpEisaAdapter[DeviceDescriptor->BusNumber][DeviceDescriptor->DmaChannel] = adapterObject; + + } + + // + // Set the maximum number of map registers for this channel bus on + // the number requested and the type of device. + // + + if (numberOfMapRegisters) { + + // + // The speicified number of registers are actually allowed to be + // allocated. + // + + adapterObject->MapRegistersPerChannel = numberOfMapRegisters; + + // + // Increase the commitment for the map registers. + // + + if (DeviceDescriptor->Master) { + + // + // Master I/O devices use several sets of map registers double + // their commitment. + // + + MasterAdapterObject->CommittedMapRegisters += + numberOfMapRegisters * 2; + + } else { + + MasterAdapterObject->CommittedMapRegisters += + numberOfMapRegisters; + + } + + adapterObject->NeedsMapRegisters = TRUE; + + } else { + + // + // No real map registers were allocated. If this is a master + // device, then the device can have as may registers as it wants. + // + + adapterObject->NeedsMapRegisters = FALSE; + + if (DeviceDescriptor->Master) { + + adapterObject->MapRegistersPerChannel = BYTES_TO_PAGES( + maximumLength + ) + + 1; + + } else { + + // + // The device only gets one register. It must call + // IoMapTransfer repeatedly to do a large transfer. + // + + adapterObject->MapRegistersPerChannel = 1; + } + } + } + + adapterObject->ScatterGather = DeviceDescriptor->ScatterGather; + *NumberOfMapRegisters = adapterObject->MapRegistersPerChannel; + + // + // If the device is a 32 bit bus mastering device, then set field in AdapterObject. + // + + if (DeviceDescriptor->InterfaceType == PCIBus && DeviceDescriptor->Master) { + adapterObject->NeedsMapRegisters = FALSE; + } + + // + // If the channel number is not used then we are finished. The rest of + // the work deals with channels. + // + + if (!useChannel) { + return(adapterObject); + } + + // + // Setup the pointers to all the random registers. + // + + adapterObject->BusNumber = DeviceDescriptor->BusNumber; + + adapterObject->ChannelNumber = channelNumber; + + if (controllerNumber == 1) { + + switch (channelNumber) { + + case 0: + adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel0; + break; + + case 1: + adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel1; + break; + + case 2: + adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel2; + break; + + case 3: + adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel3; + break; + } + + // + // Set the adapter number. + // + + adapterObject->AdapterNumber = 1; + + // + // Save the extended mode register address. + // + + adapterBaseVa = + &((PEISA_CONTROL) HalpEisaControlBase[DeviceDescriptor->BusNumber])->Dma1ExtendedModePort; + + } else { + + switch (channelNumber) { + case 1: + adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel5; + break; + + case 2: + adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel6; + break; + + case 3: + adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel7; + break; + } + + // + // Set the adapter number. + // + + adapterObject->AdapterNumber = 2; + + // + // Save the extended mode register address. + // + adapterBaseVa = + &((PEISA_CONTROL) HalpEisaControlBase[DeviceDescriptor->BusNumber])->Dma2ExtendedModePort; + + } + + + adapterObject->Width16Bits = FALSE; + + if (eisaSystem) { + + // + // Initialzie the extended mode port. + // + + *((PUCHAR) &extendedMode) = 0; + extendedMode.ChannelNumber = channelNumber; + + switch (DeviceDescriptor->DmaSpeed) { + case Compatible: + extendedMode.TimingMode = COMPATIBLITY_TIMING; + break; + + case TypeA: + extendedMode.TimingMode = TYPE_A_TIMING; + break; + + case TypeB: + extendedMode.TimingMode = TYPE_B_TIMING; + break; + + case TypeC: + extendedMode.TimingMode = BURST_TIMING; + break; + + default: + ObDereferenceObject( adapterObject ); + + return(NULL); + + } + + switch (DeviceDescriptor->DmaWidth) { + case Width8Bits: + extendedMode.TransferSize = BY_BYTE_8_BITS; + break; + + case Width16Bits: + extendedMode.TransferSize = BY_BYTE_16_BITS; + + // + // Note Width16bits should not be set here because there is no need + // to shift the address and the transfer count. + // + + break; + + case Width32Bits: + extendedMode.TransferSize = BY_BYTE_32_BITS; + break; + + default: + ObDereferenceObject( adapterObject ); + + return(NULL); + + } + + WRITE_REGISTER_UCHAR( adapterBaseVa, *((PUCHAR) &extendedMode)); + + } else if (!DeviceDescriptor->Master) { + + switch (DeviceDescriptor->DmaWidth) { + case Width8Bits: + + // + // The channel must use controller 1. + // + + if (controllerNumber != 1) { + ObDereferenceObject( adapterObject ); + + return(NULL); + } + + break; + + case Width16Bits: + + // + // The channel must use controller 2. + // + + if (controllerNumber != 2) { + ObDereferenceObject( adapterObject ); + + return(NULL); + } + + adapterObject->Width16Bits = TRUE; + break; + + default: + ObDereferenceObject( adapterObject ); + + return(NULL); + + } + } + + // + // Initialize the adapter mode register value to the correct parameters, + // and save them in the adapter object. + // + + adapterMode = 0; + ((PDMA_EISA_MODE) &adapterMode)->Channel = adapterObject->ChannelNumber; + + adapterObject->MasterDevice = FALSE; + + if (DeviceDescriptor->Master) { + + adapterObject->MasterDevice = TRUE; + + ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE; + + // + // Set the mode, and enable the request. + // + + if (adapterObject->AdapterNumber == 1) { + + // + // This request is for DMA controller 1 + // + + PDMA1_CONTROL dmaControl; + + dmaControl = adapterObject->AdapterBaseVa; + + WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode ); + + // + // Unmask the DMA channel. + // + + WRITE_REGISTER_UCHAR( + &dmaControl->SingleMask, + (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber) + ); + + } else { + + // + // This request is for DMA controller 1 + // + + PDMA2_CONTROL dmaControl; + + dmaControl = adapterObject->AdapterBaseVa; + + WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode ); + + // + // Unmask the DMA channel. + // + + WRITE_REGISTER_UCHAR( + &dmaControl->SingleMask, + (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber) + ); + + } + + } else if (DeviceDescriptor->DemandMode) { + + ((PDMA_EISA_MODE) &adapterMode)->RequestMode = DEMAND_REQUEST_MODE; + + } else { + + ((PDMA_EISA_MODE) &adapterMode)->RequestMode = SINGLE_REQUEST_MODE; + + } + + if (DeviceDescriptor->AutoInitialize) { + + ((PDMA_EISA_MODE) &adapterMode)->AutoInitialize = 1; + + } + + adapterObject->AdapterMode = adapterMode; + + return(adapterObject); +} + +VOID +HalpMapTransferHelper( + IN PMDL Mdl, + IN PVOID CurrentVa, + IN ULONG TransferLength, + IN PULONG PageFrame, + IN OUT PULONG Length + ) + +/*++ + +Routine Description: + + Helper routine for bus master transfers that cross a page + boundary. This routine is separated out from the IoMapTransfer + fast path in order to minimize the total instruction path + length taken for the common network case where the entire + buffer being mapped is contained within one page. + +Arguments: + + Mdl - Pointer to the MDL that describes the pages of memory that are + being read or written. + + CurrentVa - Current virtual address in the buffer described by the MDL + that the transfer is being done to or from. + + TransferLength = Supplies the current transferLength + + PageFrame - Supplies a pointer to the starting page frame of the transfer + + Length - Supplies the length of the transfer. This determines the + number of map registers that need to be written to map the transfer. + Returns the length of the transfer which was actually mapped. + +Return Value: + + None. *Length will be updated + +--*/ + +{ + do { + if (*PageFrame + 1 != *(PageFrame + 1)) { + break; + } + TransferLength += PAGE_SIZE; + PageFrame++; + + } while ( TransferLength < *Length ); + + + // + // Limit the Length to the maximum TransferLength. + // + + if (TransferLength < *Length) { + *Length = TransferLength; + } +} + +PHYSICAL_ADDRESS +IoMapTransfer( + IN PADAPTER_OBJECT AdapterObject, + IN PMDL Mdl, + IN PVOID MapRegisterBase, + IN PVOID CurrentVa, + IN OUT PULONG Length, + IN BOOLEAN WriteToDevice + ) + +/*++ + +Routine Description: + + This routine is invoked to set up the map registers in the DMA controller + to allow a transfer to or from a device. + +Arguments: + + AdapterObject - Pointer to the adapter object representing the DMA + controller channel that has been allocated. + + Mdl - Pointer to the MDL that describes the pages of memory that are + being read or written. + + MapRegisterBase - The address of the base map register that has been + allocated to the device driver for use in mapping the transfer. + + CurrentVa - Current virtual address in the buffer described by the MDL + that the transfer is being done to or from. + + Length - Supplies the length of the transfer. This determines the + number of map registers that need to be written to map the transfer. + Returns the length of the transfer which was actually mapped. + + WriteToDevice - Boolean value that indicates whether this is a write + to the device from memory (TRUE), or vice versa. + +Return Value: + + Returns the logical address that should be used bus master controllers. + +--*/ + +{ + BOOLEAN useBuffer; + ULONG transferLength; + ULONG logicalAddress; + PHYSICAL_ADDRESS returnAddress; + ULONG index; + PULONG pageFrame; + PUCHAR bytePointer; + UCHAR adapterMode; + UCHAR dataByte; + PTRANSLATION_ENTRY translationEntry; + ULONG pageOffset; + KIRQL Irql; + + pageOffset = BYTE_OFFSET(CurrentVa); + pageFrame = (PULONG)(Mdl+1); + pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT; + logicalAddress = ((*pageFrame << PAGE_SHIFT) + pageOffset); + + if (MapRegisterBase==NULL_MAP_REGISTER_BASE) { + + pageOffset = BYTE_OFFSET(CurrentVa); + + // + // Calculate how much of the transfer is contiguous + // + transferLength = PAGE_SIZE - pageOffset; + pageFrame = (PULONG)(Mdl+1); + pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT; + + // + // Compute the starting address of the transfer + // + + returnAddress.LowPart = logicalAddress; + returnAddress.HighPart = 0; + + // + // If the transfer is not completely contained within + // a page, call the helper to compute the appropriate + // length. + // + if (transferLength < *Length) { + HalpMapTransferHelper(Mdl, CurrentVa, transferLength, pageFrame, Length); + } + + return(returnAddress); + } + + transferLength = *Length; + + // + // Determine if the data transfer needs to use the map buffer. + // + + // + // If *pageFrame is in the DMA Cache, then it was allocated by HalAllocateCommonBuffer(), + // and should not be mapped. + // + + if (MapRegisterBase != NULL_MAP_REGISTER_BASE && !HALP_PAGE_IN_DMA_CACHE(*pageFrame)) { + + // + // Strip no scatter/gather flag. + // + + translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER); + + // + // If there are map registers, then update the index to indicate + // how many have been used. + // + + index = translationEntry->Index; + translationEntry->Index += ADDRESS_AND_SIZE_TO_SPAN_PAGES( + CurrentVa, + transferLength + ); + + // + // Force IoMapTransfer() to use the map buffer. + // + + logicalAddress = (translationEntry + index)->PhysicalAddress + pageOffset; + useBuffer = TRUE; + + if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER) { + + translationEntry->Index = COPY_BUFFER; + index = 0; + + } + + // + // Copy the data if necessary. + // + + if (useBuffer && WriteToDevice) { + + HalpCopyBufferMap(Mdl, + translationEntry, + CurrentVa, + transferLength, + WriteToDevice); + } + } + + // + // Return the length. + // + + *Length = transferLength; + + // + // We only support 32 bits, but the return is 64. Just + // zero extend + // + + returnAddress.LowPart = logicalAddress; + returnAddress.HighPart = 0; + + // + // If no adapter was specificed then there is no more work to do so + // return. + // + + if (AdapterObject == NULL || AdapterObject->MasterDevice) { + + return(returnAddress); + } + + // + // Determine the mode based on the transfer direction. + // + + adapterMode = AdapterObject->AdapterMode; + ((PDMA_EISA_MODE) &adapterMode)->TransferType = (UCHAR) (WriteToDevice ? + WRITE_TRANSFER : READ_TRANSFER); + + bytePointer = (PUCHAR) &logicalAddress; + + if (AdapterObject->Width16Bits) { + + // + // If this is a 16 bit transfer then adjust the length and the address + // for the 16 bit DMA mode. + // + + transferLength >>= 1; + + // + // In 16 bit DMA mode the low 16 bits are shifted right one and the + // page register value is unchanged. So save the page register value + // and shift the logical address then restore the page value. + // + + dataByte = bytePointer[2]; + logicalAddress >>= 1; + bytePointer[2] = dataByte; + + } + + + // + // grab the spinlock for the system DMA controller + // + + KeAcquireSpinLock( &AdapterObject->MasterAdapter->SpinLock, &Irql ); + + // + // Determine the controller number based on the Adapter number. + // + + if (AdapterObject->AdapterNumber == 1) { + + // + // This request is for DMA controller 1 + // + + PDMA1_CONTROL dmaControl; + + dmaControl = AdapterObject->AdapterBaseVa; + + WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 ); + + WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode ); + + WRITE_REGISTER_UCHAR( + &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber] + .DmaBaseAddress, + bytePointer[0] + ); + + WRITE_REGISTER_UCHAR( + &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber] + .DmaBaseAddress, + bytePointer[1] + ); + + WRITE_REGISTER_UCHAR( + ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase[AdapterObject->BusNumber])->DmaPageLowPort) + + (ULONG)AdapterObject->PagePort, + bytePointer[2] + ); + + if (HalpBusType == UNIFLEX_MACHINE_TYPE_EISA) { + + // + // Write the high page register with zero value. This enable a special mode + // which allows ties the page register and base count into a single 24 bit + // address register. + // + + WRITE_REGISTER_UCHAR( + ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase[AdapterObject->BusNumber])->DmaPageHighPort) + + (ULONG)AdapterObject->PagePort, + 0 + ); + } + + // + // Notify DMA chip of the length to transfer. + // + + WRITE_REGISTER_UCHAR( + &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber] + .DmaBaseCount, + (UCHAR) ((transferLength - 1) & 0xff) + ); + + WRITE_REGISTER_UCHAR( + &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber] + .DmaBaseCount, + (UCHAR) ((transferLength - 1) >> 8) + ); + + + // + // Set the DMA chip to read or write mode; and unmask it. + // + + WRITE_REGISTER_UCHAR( + &dmaControl->SingleMask, + (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber) + ); + + } else { + + // + // This request is for DMA controller 2 + // + + PDMA2_CONTROL dmaControl; + + dmaControl = AdapterObject->AdapterBaseVa; + + WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 ); + + WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode ); + + WRITE_REGISTER_UCHAR( + &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber] + .DmaBaseAddress, + bytePointer[0] + ); + + WRITE_REGISTER_UCHAR( + &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber] + .DmaBaseAddress, + bytePointer[1] + ); + + WRITE_REGISTER_UCHAR( + ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase[AdapterObject->BusNumber])->DmaPageLowPort) + + (ULONG)AdapterObject->PagePort, + bytePointer[2] + ); + + if (HalpBusType == UNIFLEX_MACHINE_TYPE_EISA) { + + // + // Write the high page register with zero value. This enable a special mode + // which allows ties the page register and base count into a single 24 bit + // address register. + // + + WRITE_REGISTER_UCHAR( + ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase[AdapterObject->BusNumber])->DmaPageHighPort) + + (ULONG)AdapterObject->PagePort, + 0 + ); + } + + // + // Notify DMA chip of the length to transfer. + // + + WRITE_REGISTER_UCHAR( + &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber] + .DmaBaseCount, + (UCHAR) ((transferLength - 1) & 0xff) + ); + + WRITE_REGISTER_UCHAR( + &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber] + .DmaBaseCount, + (UCHAR) ((transferLength - 1) >> 8) + ); + + + // + // Set the DMA chip to read or write mode; and unmask it. + // + + WRITE_REGISTER_UCHAR( + &dmaControl->SingleMask, + (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber) + ); + + } + KeReleaseSpinLock (&AdapterObject->MasterAdapter->SpinLock, Irql); + + return(returnAddress); +} + +BOOLEAN +IoFlushAdapterBuffers( + IN PADAPTER_OBJECT AdapterObject, + IN PMDL Mdl, + IN PVOID MapRegisterBase, + IN PVOID CurrentVa, + IN ULONG Length, + IN BOOLEAN WriteToDevice + ) + +/*++ + +Routine Description: + + This routine flushes the DMA adapter object buffers. For the Jazz system + its clears the enable flag which aborts the dma. + +Arguments: + + AdapterObject - Pointer to the adapter object representing the DMA + controller channel. + + Mdl - A pointer to a Memory Descriptor List (MDL) that maps the locked-down + buffer to/from which the I/O occured. + + MapRegisterBase - A pointer to the base of the map registers in the adapter + or DMA controller. + + CurrentVa - The current virtual address in the buffer described the the Mdl + where the I/O operation occurred. + + Length - Supplies the length of the transfer. + + WriteToDevice - Supplies a BOOLEAN value that indicates the direction of + the data transfer was to the device. + +Return Value: + + TRUE - No errors are detected so the transfer must succeed. + +--*/ + +{ + PTRANSLATION_ENTRY translationEntry; + PULONG pageFrame; + BOOLEAN masterDevice; + PVOID OriginalCurrentVa; + + OriginalCurrentVa = CurrentVa; + + pageFrame = (PULONG)(Mdl+1); + pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT; + + masterDevice = AdapterObject == NULL || AdapterObject->MasterDevice ? + TRUE : FALSE; + +#if defined(_ALPHA_) + + HalpCleanIoBuffers(Mdl,!WriteToDevice,TRUE); +// HalFlushIoBuffers(Mdl,!WriteToDevice,TRUE); + +#endif + + if (MapRegisterBase==NULL_MAP_REGISTER_BASE) { + return(TRUE); + } + + // + // If this is a slave device, then stop the DMA controller. + // + + if (!masterDevice) { + + // + // Mask the DMA request line so that DMA requests cannot occur. + // + + if (AdapterObject->AdapterNumber == 1) { + + // + // This request is for DMA controller 1 + // + + PDMA1_CONTROL dmaControl; + + dmaControl = AdapterObject->AdapterBaseVa; + + WRITE_REGISTER_UCHAR( + &dmaControl->SingleMask, + (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber) + ); + + } else { + + // + // This request is for DMA controller 2 + // + + PDMA2_CONTROL dmaControl; + + dmaControl = AdapterObject->AdapterBaseVa; + + WRITE_REGISTER_UCHAR( + &dmaControl->SingleMask, + (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber) + ); + + } + + } + + // + // If there are no map registers being used then just return TRUE. + // If *pageFrame is in the DMA Cache, then it was allocated by HalAllocateCommonBuffer(), + // and was not be mapped. So, just return TRUE. + // + + if (MapRegisterBase == NULL_MAP_REGISTER_BASE || HALP_PAGE_IN_DMA_CACHE(*pageFrame)) { + return(TRUE); + } + + // + // Determine if the data needs to be copied to the orginal buffer. + // This only occurs if the data tranfer is from the device, the + // MapReisterBase is not NULL and the transfer spans a page. + // + + if (!WriteToDevice) { + + // + // Strip no scatter/gather flag. + // + + translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER); + + // + // If this is not a master device, then just transfer the buffer. + // + + if (!masterDevice) { + + // + // Copy only the bytes that have actually been transfered. + // + + Length -= HalReadDmaCounter(AdapterObject); + + } + + // + // The adapter does not support scatter/gather copy the buffer. + // + + HalpCopyBufferMap(Mdl, + translationEntry, + CurrentVa, + Length, + WriteToDevice); + +#if defined(_MIPS_) + + // + // If this is a page read then flush the buffer from the primary data cache so + // it can be potentially read into the primary instruction cache. + // + + if ( (Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0) { + + ULONG transferLength; + ULONG partialLength; + + if (Length > PCR->FirstLevelDcacheSize) { + HalSweepDcache(); + } else { + + CurrentVa = OriginalCurrentVa; + + transferLength = PAGE_SIZE - BYTE_OFFSET(CurrentVa); + partialLength = transferLength; + pageFrame = (PULONG)(Mdl+1); + pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT; + + while( transferLength <= Length ){ + + HalFlushDcachePage(CurrentVa,*pageFrame,partialLength); + + (PCCHAR) CurrentVa += partialLength; + partialLength = PAGE_SIZE; + + transferLength += partialLength; + pageFrame++; + } + + partialLength = Length - transferLength + partialLength; + + if (partialLength) { + + HalFlushDcachePage(CurrentVa,*pageFrame,partialLength); + } + } + } + +#endif + + } + + // + // Strip no scatter/gather flag. + // + + translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER); + + // + // Clear index in map register. + // + + translationEntry->Index = 0; + + return TRUE; +} + +ULONG +HalReadDmaCounter( + IN PADAPTER_OBJECT AdapterObject + ) +/*++ + +Routine Description: + + This function reads the DMA counter and returns the number of bytes left + to be transfered. + +Arguments: + + AdapterObject - Supplies a pointer to the adapter object to be read. + +Return Value: + + Returns the number of bytes still be be transfered. + +--*/ + +{ + ULONG count; + ULONG high; + + if (AdapterObject->PagePort) { + + // + // Determine the controller number based on the Adapter number. + // + + if (AdapterObject->AdapterNumber == 1) { + + // + // This request is for DMA controller 1 + // + + PDMA1_CONTROL dmaControl; + + dmaControl = AdapterObject->AdapterBaseVa; + + // + // Initialize count to a value which will not match. + // + + count = 0xFFFF00; + + // + // Loop until the same high byte is read twice. + // + + do { + + high = count; + + WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 ); + + // + // Read the current DMA count. + // + + count = READ_REGISTER_UCHAR( + &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber] + .DmaBaseCount + ); + + count |= READ_REGISTER_UCHAR( + &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber] + .DmaBaseCount + ) << 8; + + } while ((count & 0xFFFF00) != (high & 0xFFFF00)); + + } else { + + // + // This request is for DMA controller 2 + // + + PDMA2_CONTROL dmaControl; + + dmaControl = AdapterObject->AdapterBaseVa; + + // + // Initialize count to a value which will not match. + // + + count = 0xFFFF00; + + // + // Loop until the same high byte is read twice. + // + + do { + + high = count; + + WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 ); + + // + // Read the current DMA count. + // + + count = READ_REGISTER_UCHAR( + &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber] + .DmaBaseCount + ); + + count |= READ_REGISTER_UCHAR( + &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber] + .DmaBaseCount + ) << 8; + + } while ((count & 0xFFFF00) != (high & 0xFFFF00)); + + } + + // + // The DMA counter has a bias of one and can only be 16 bit long. + // + + count = (count + 1) & 0xFFFF; + + } + + return(count); +} + +VOID +HalpEnableEisaInterrupt( + IN ULONG Vector, + IN KINTERRUPT_MODE InterruptMode + ) + +/*++ + +Routine Description: + + This function enables the EISA bus specified EISA bus interrupt and sets + the level/edge register to the requested value. + +Arguments: + + Vector - Supplies the vector of the ESIA interrupt that is enabled. + + InterruptMode - Supplies the mode of the interrupt; LevelSensitive or + Latched. + +Return Value: + + None. + +--*/ + +{ + ULONG BusNumber; + + if (Vector >= UNIFLEX_EISA_VECTORS && Vector <= UNIFLEX_MAXIMUM_EISA_VECTOR) { + + BusNumber = 0; + + // + // Calculate the EISA interrupt vector. + // + + Vector -= UNIFLEX_EISA_VECTORS; + } + + if (Vector >= UNIFLEX_EISA1_VECTORS && Vector <= UNIFLEX_MAXIMUM_EISA1_VECTOR) { + + BusNumber = 1; + + // + // Calculate the EISA interrupt vector. + // + + Vector -= UNIFLEX_EISA1_VECTORS; + } + + // + // Determine if this vector is for interrupt controller 1 or 2. + // + + if (Vector & 0x08) { + + // + // The interrupt is in controller 2. + // + + Vector &= 0x7; + + HalpEisaInterrupt2Mask[BusNumber] &= (UCHAR) ~(1 << Vector); + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt2ControlPort1, + HalpEisaInterrupt2Mask[BusNumber] + ); + + // + // Set the level/edge control register. + // + + if (InterruptMode == LevelSensitive) { + + HalpEisaInterrupt2Level[BusNumber] |= (UCHAR) (1 << Vector); + + } else { + + HalpEisaInterrupt2Level[BusNumber] &= (UCHAR) ~(1 << Vector); + + } + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt2EdgeLevel, + HalpEisaInterrupt2Level[BusNumber] + ); + + } else { + + // + // The interrupt is in controller 1. + // + + Vector &= 0x7; + + HalpEisaInterrupt1Mask[BusNumber] &= (UCHAR) ~(1 << Vector); + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt1ControlPort1, + HalpEisaInterrupt1Mask[BusNumber] + ); + + // + // Set the level/edge control register. + // + + if (InterruptMode == LevelSensitive) { + + HalpEisaInterrupt1Level[BusNumber] |= (UCHAR) (1 << Vector); + + } else { + + HalpEisaInterrupt1Level[BusNumber] &= (UCHAR) ~(1 << Vector); + + } + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt1EdgeLevel, + HalpEisaInterrupt1Level[BusNumber] + ); + } + +} + +VOID +HalpDisableEisaInterrupt( + IN ULONG Vector + ) + +/*++ + +Routine Description: + + This function Disables the EISA bus specified EISA bus interrupt. + +Arguments: + + Vector - Supplies the vector of the ESIA interrupt that is Disabled. + +Return Value: + + None. + +--*/ + +{ + ULONG BusNumber; + + if (Vector >= UNIFLEX_EISA_VECTORS && Vector <= UNIFLEX_MAXIMUM_EISA_VECTOR) { + + BusNumber = 0; + + // + // Calculate the EISA interrupt vector. + // + + Vector -= UNIFLEX_EISA_VECTORS; + } + + if (Vector >= UNIFLEX_EISA1_VECTORS && Vector <= UNIFLEX_MAXIMUM_EISA1_VECTOR) { + + BusNumber = 1; + + // + // Calculate the EISA interrupt vector. + // + + Vector -= UNIFLEX_EISA1_VECTORS; + } + + // + // Determine if this vector is for interrupt controller 1 or 2. + // + + if (Vector & 0x08) { + + // + // The interrupt is in controller 2. + // + + Vector &= 0x7; + + HalpEisaInterrupt2Mask[BusNumber] |= (UCHAR) 1 << Vector; + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt2ControlPort1, + HalpEisaInterrupt2Mask[BusNumber] + ); + + } else { + + // + // The interrupt is in controller 1. + // + + Vector &= 0x7; + + HalpEisaInterrupt1Mask[BusNumber] |= (ULONG) 1 << Vector; + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt1ControlPort1, + HalpEisaInterrupt1Mask[BusNumber] + ); + + } + +} + +BOOLEAN +HalpCreateEisaStructures ( + ULONG BusNumber + ) + +/*++ + +Routine Description: + + This routine initializes the structures necessary for EISA operations + and connects the intermediate interrupt dispatcher. It also initializes the + EISA interrupt controller. + +Arguments: + + None. + +Return Value: + + If the second level interrupt dispatcher is connected, then a value of + TRUE is returned. Otherwise, a value of FALSE is returned. + +--*/ + +{ + UCHAR DataByte; + + // + // Initialize the EISA interrupt controller. There are two cascaded + // interrupt controllers, each of which must initialized with 4 initialize + // control words. + // + + DataByte = 0; + ((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1; + ((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1; + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt1ControlPort0, + DataByte + ); + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt2ControlPort0, + DataByte + ); + + // + // The second intitialization control word sets the iterrupt vector to + // 0-15. + // + + DataByte = 0; + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt1ControlPort1, + DataByte + ); + + DataByte = 0x08; + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt2ControlPort1, + DataByte + ); + + // + // The thrid initialization control word set the controls for slave mode. + // The master ICW3 uses bit position and the slave ICW3 uses a numberic. + // + + DataByte = 1 << SLAVE_IRQL_LEVEL; + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt1ControlPort1, + DataByte + ); + + DataByte = SLAVE_IRQL_LEVEL; + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt2ControlPort1, + DataByte + ); + + // + // The fourth initialization control word is used to specify normal + // end-of-interrupt mode and not special-fully-nested mode. + // + + DataByte = 0; + ((PINITIALIZATION_COMMAND_4) &DataByte)->I80x86Mode = 1; + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt1ControlPort1, + DataByte + ); + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt2ControlPort1, + DataByte + ); + + + // + // Disable all of the interrupts except the slave. + // + + HalpEisaInterrupt1Mask[BusNumber] = (UCHAR)(~(1 << SLAVE_IRQL_LEVEL)); + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt1ControlPort1, + HalpEisaInterrupt1Mask[BusNumber] + ); + + HalpEisaInterrupt2Mask[BusNumber] = 0xFF; + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt2ControlPort1, + HalpEisaInterrupt2Mask[BusNumber] + ); + + // + // Initialize the edge/level register masks to 0 which is the default + // edge sensitive value. + // + + HalpEisaInterrupt1Level[BusNumber] = 0; + HalpEisaInterrupt2Level[BusNumber] = 0; + + // + // Initialize the DMA mode registers to a default value. + // Disable all of the DMA channels except channel 4 which is that + // cascade of channels 0-3. + // + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Dma1BasePort.AllMask, + 0x0F + ); + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Dma2BasePort.AllMask, + 0x0E + ); + + HalpConnectInterruptDispatchers(); + + return(TRUE); +} + +BOOLEAN +HalpEisaDispatch( + IN PKINTERRUPT Interrupt, + IN PVOID ServiceContext, + IN ULONG BusNumber + ) + +{ + volatile UCHAR LowerVector; + volatile UCHAR UpperVector; + volatile UCHAR UpperVector1; + volatile PULONG dispatchCode; + volatile PKINTERRUPT interruptObject; + volatile USHORT PCRInOffset; + volatile BOOLEAN returnValue = FALSE; + + // + // Send a POLL Command to Interrupt Controller 2 + // + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL)HalpEisaControlBase[BusNumber])->Interrupt2ControlPort0, + 0x0c + ); + + // + // Read the interrupt vector + // + + UpperVector = READ_REGISTER_UCHAR(&((PEISA_CONTROL)HalpEisaControlBase[BusNumber])->Interrupt2ControlPort0); + + // + // See if there is a real interrupt on Interrupt Controller 2 + // + + if (UpperVector & 0x80) { + + UpperVector = UpperVector & 0x07; + + if (BusNumber == 0) { + PCRInOffset = UpperVector + 8 + UNIFLEX_EISA_VECTORS; + } + if (BusNumber == 1) { + PCRInOffset = UpperVector + 8 + UNIFLEX_EISA1_VECTORS; + } + + // + // Dispatch to the secondary interrupt service routine. + // + + dispatchCode = (PULONG)(PCR->InterruptRoutine[PCRInOffset]); + interruptObject = CONTAINING_RECORD(dispatchCode, + KINTERRUPT, + DispatchCode); + + returnValue = + ((PSECONDARY_DISPATCH)interruptObject->DispatchAddress) + (interruptObject); + + // + // Clear the interrupt from Interrupt Controller 2 + // + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL)HalpEisaControlBase[BusNumber])->Interrupt2ControlPort0, + NONSPECIFIC_END_OF_INTERRUPT + ); + + // + // Send a POLL Command to Interrupt Controller 2 + // + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL)HalpEisaControlBase[BusNumber])->Interrupt2ControlPort0, + 0x0c + ); + + // + // Read the interrupt vector + // + + UpperVector1 = READ_REGISTER_UCHAR(&((PEISA_CONTROL)HalpEisaControlBase[BusNumber])->Interrupt2ControlPort0); + + if ((UpperVector1 & 0x80) && (UpperVector1 & 0x07) == UpperVector) { + + UCHAR DataByte; + +//DbgPrint("ERROR : Interrupt controller 2 stuck on ISA bus %d : UpperVector1 = %02x\n\r",BusNumber,UpperVector1); + + // + // Initialize the EISA interrupt controller. There are two cascaded + // interrupt controllers, each of which must initialized with 4 initialize + // control words. + // + + DataByte = 0; + ((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1; + ((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1; + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt2ControlPort0, + DataByte + ); + + // + // The second intitialization control word sets the iterrupt vector to + // 0-15. + // + + DataByte = 0x70; + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt2ControlPort1, + DataByte + ); + + // + // The thrid initialization control word set the controls for slave mode. + // The master ICW3 uses bit position and the slave ICW3 uses a numberic. + // + + DataByte = SLAVE_IRQL_LEVEL; + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt2ControlPort1, + DataByte + ); + + // + // The fourth initialization control word is used to specify normal + // end-of-interrupt mode and not special-fully-nested mode. + // + + DataByte = 0; + ((PINITIALIZATION_COMMAND_4) &DataByte)->I80x86Mode = 1; + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt2ControlPort1, + DataByte + ); + + // + // Program the interrupt mask register for the upper PIC + // + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt2ControlPort1, + HalpEisaInterrupt2Mask[BusNumber] + ); + + // + // Program the interrupt edge/level register for the upper PIC + // + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt2EdgeLevel, + HalpEisaInterrupt2Level[BusNumber] + ); + } + + return(returnValue); + } + + // + // Send a POLL Command to Interrupt Controller 1 + // + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase[BusNumber])->Interrupt1ControlPort0, + 0x0c + ); + + // + // Read the interrupt vector + // + + LowerVector = READ_REGISTER_UCHAR(&((PEISA_CONTROL)HalpEisaControlBase[BusNumber])->Interrupt1ControlPort0); + + // + // See if there is a real interrupt on Interrupt Controller 1 + // + + if (LowerVector & 0x80) { + + LowerVector = LowerVector & 0x07; + + if (LowerVector!=0x02) { + + // + // This interrupt is on the first interrupt controller + // + + if (BusNumber == 0) { + PCRInOffset = LowerVector + UNIFLEX_EISA_VECTORS; + } + if (BusNumber == 1) { + PCRInOffset = LowerVector + UNIFLEX_EISA1_VECTORS; + } + + // + // Dispatch to the secondary interrupt service routine. + // + + // + // The interrupt vector for CLOCK2_LEVEL is directly connected by the HAL. + // If the interrupt is on CLOCK2_LEVEL then vector to the address stored + // in the PCR. Otherwise, bypass the thunk code in the interrupt object + // whose address is stored in the PCR. + // + + if (PCRInOffset == UNIFLEX_CLOCK2_LEVEL) { + + returnValue = + ((PSECONDARY_DISPATCH)PCR->InterruptRoutine[PCRInOffset]) + (PCR->InterruptRoutine[PCRInOffset]); + + } else { + + dispatchCode = (PULONG)(PCR->InterruptRoutine[PCRInOffset]); + interruptObject = CONTAINING_RECORD(dispatchCode, + KINTERRUPT, + DispatchCode); + + returnValue = + ((PSECONDARY_DISPATCH)interruptObject->DispatchAddress) + (interruptObject); + + } + } + + // + // Clear the interrupt from Interrupt Controller 1 + // + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL)HalpEisaControlBase[BusNumber])->Interrupt1ControlPort0, + NONSPECIFIC_END_OF_INTERRUPT + ); + + return(returnValue); + } + + // + // Spurrious Interrupt. Return FALSE + // + + return(returnValue); +} diff --git a/private/ntos/nthals/halflex/xxenvirv.c b/private/ntos/nthals/halflex/xxenvirv.c new file mode 100644 index 000000000..1b81d4cad --- /dev/null +++ b/private/ntos/nthals/halflex/xxenvirv.c @@ -0,0 +1,106 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + jxenvirv.c + +Abstract: + + This module implements the HAL get and set environment variable routines + for a MIPS system. + +Author: + + Michael D. Kinney 30-Apr-1995 + +Environment: + + Kernel mode + +Revision History: + +--*/ + +#include "halp.h" +#include "arccodes.h" + +ARC_STATUS +HalGetEnvironmentVariable ( + IN PCHAR Variable, + IN USHORT Length, + OUT PCHAR Buffer + ) + +/*++ + +Routine Description: + + This function locates an environment variable and returns its value. + +Arguments: + + Variable - Supplies a pointer to a zero terminated environment variable + name. + + Length - Supplies the length of the value buffer in bytes. + + Buffer - Supplies a pointer to a buffer that receives the variable value. + +Return Value: + + ESUCCESS is returned if the enviroment variable is located. Otherwise, + ENOENT is returned. + +--*/ + +{ + CHAR *Value; + + HalpAllocateArcsResources(); + Value = ArcGetEnvironmentVariable(Variable); + HalpFreeArcsResources(); + + if (Value==NULL) + return(ENOENT); + if (strlen(Value)>Length) + return(ENOENT); + strcpy(Buffer,Value); + return ESUCCESS; +} + + +ARC_STATUS +HalSetEnvironmentVariable ( + IN PCHAR Variable, + IN PCHAR Value + ) + +/*++ + +Routine Description: + + This function creates an environment variable with the specified value. + +Arguments: + + Variable - Supplies a pointer to an environment variable name. + + Value - Supplies a pointer to the environment variable value. + +Return Value: + + ESUCCESS is returned if the environment variable is created. Otherwise, + ENOMEM is returned. + +--*/ + +{ + ARC_STATUS ReturnValue; + + HalpAllocateArcsResources(); + ReturnValue = ArcSetEnvironmentVariable(Variable,Value); + HalpFreeArcsResources(); + return(ReturnValue); +} diff --git a/private/ntos/nthals/halflex/xxhwsup.c b/private/ntos/nthals/halflex/xxhwsup.c new file mode 100644 index 000000000..06f2d77d3 --- /dev/null +++ b/private/ntos/nthals/halflex/xxhwsup.c @@ -0,0 +1,1250 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + ixphwsup.c + +Abstract: + + This module contains the HalpXxx routines for the NT I/O system that + are hardware dependent. Were these routines not hardware dependent, + they would normally reside in the internal.c module. + +Author: + + Darryl E. Havens (darrylh) 11-Apr-1990 + +Environment: + + Kernel mode, local to I/O system + +Revision History: + + +--*/ + +#include "halp.h" +#include "pci.h" + + +// +// Some devices require a phyicially contiguous data buffers for DMA transfers. +// Map registers are used give the appearance that all data buffers are +// contiguous. In order to pool all of the map registers a master +// adapter object is used. This object is allocated and saved internal to this +// file. It contains a bit map for allocation of the registers and a queue +// for requests which are waiting for more map registers. This object is +// allocated during the first request to allocate an adapter which requires +// map registers. +// + +extern POBJECT_TYPE IoAdapterObjectType; + +PADAPTER_OBJECT MasterAdapterObject; + +// +// Map buffer prameters. These are initialized in HalInitSystem +// + +extern PHYSICAL_ADDRESS HalpMapBufferPhysicalAddress; +extern ULONG HalpMapBufferSize; + + +BOOLEAN +HalpGrowMapBuffers( + PADAPTER_OBJECT AdapterObject, + ULONG Amount + ) +/*++ + +Routine Description: + + This function attempts to allocate additional map buffers for use by I/O + devices. The map register table is updated to indicate the additional + buffers. + +Arguments: + + AdapterObject - Supplies the adapter object for which the buffers are to be + allocated. + + Amount - Indicates the size of the map buffers which should be allocated. + +Return Value: + + TRUE is returned if the memory could be allocated. + + FALSE is returned if the memory could not be allocated. + +--*/ +{ + ULONG MapBufferPhysicalAddress; + PVOID MapBufferVirtualAddress; + PTRANSLATION_ENTRY TranslationEntry; + LONG NumberOfPages; + LONG i; + KIRQL Irql; + BOOLEAN eisaSystem; + PMDL MapBufferMdl; + + eisaSystem = HalpBusType == UNIFLEX_MACHINE_TYPE_EISA ? TRUE : FALSE; + + KeAcquireSpinLock( &AdapterObject->SpinLock, &Irql ); + + NumberOfPages = BYTES_TO_PAGES(Amount); + + // + // Make sure there is room for the addition pages. The maximum number of + // slots needed is equal to NumberOfPages + Amount / 64K + 1. + // + + i = BYTES_TO_PAGES(HalpMapBufferSize) - (NumberOfPages + + (NumberOfPages * PAGE_SIZE) / 0x10000 + 1 + + AdapterObject->NumberOfMapRegisters); + + if (i < 0) { + + // + // Reduce the allocatation amount to so it will fit. + // + + NumberOfPages += i; + } + + if (NumberOfPages <= 0) { + // + // No more memory can be allocated. + // + + KeReleaseSpinLock( &AdapterObject->SpinLock, Irql ); + return(FALSE); + + } + + + if (AdapterObject->NumberOfMapRegisters == 0 && HalpMapBufferSize) { + + NumberOfPages = BYTES_TO_PAGES(HalpMapBufferSize); + + // + // Since this is the initial allocation, use the buffer allocated by + // HalInitSystem rather than allocationg a new one. + // + + MapBufferPhysicalAddress = HalpMapBufferPhysicalAddress.LowPart; + + // + // Map the buffer for access. + // + + + // On an R4000 system, this space should be mapped with caches + // disabled to avoid having to perform page exports on IO writes + // and page purges on IO reads. + + MapBufferVirtualAddress = MmMapIoSpace( + HalpMapBufferPhysicalAddress, + HalpMapBufferSize, + FALSE // Cache disabled. + ); + + if (MapBufferVirtualAddress == NULL) { + + // + // The buffer could not be mapped. + // + + HalpMapBufferSize = 0; + + KeReleaseSpinLock( &AdapterObject->SpinLock, Irql ); + return(FALSE); + } + + // + // Flush all references to the map buffer from the caches. + // + + MapBufferMdl = MmCreateMdl(NULL,MapBufferVirtualAddress,HalpMapBufferSize); + MmBuildMdlForNonPagedPool(MapBufferMdl); + HalFlushIoBuffers(MapBufferMdl,TRUE,TRUE); + IoFreeMdl(MapBufferMdl); + } + + // + // Initailize the map registers where memory has been allocated. + // + + TranslationEntry = ((PTRANSLATION_ENTRY) AdapterObject->MapRegisterBase) + + AdapterObject->NumberOfMapRegisters; + + for (i = 0; i < NumberOfPages; i++) { + + // + // Make sure the perivous entry is physically contiguous with the next + // entry and that a 64K physical bountry is not crossed unless this + // is an Eisa system. + // + + if (TranslationEntry != AdapterObject->MapRegisterBase && + (((TranslationEntry - 1)->PhysicalAddress + PAGE_SIZE) != + MapBufferPhysicalAddress || (!eisaSystem && + ((TranslationEntry - 1)->PhysicalAddress & ~0x0ffff) != + (MapBufferPhysicalAddress & ~0x0ffff)))) { + + // + // An entry needs to be skipped in the table. This entry will + // remain marked as allocated so that no allocation of map + // registers will cross this bountry. + // + + TranslationEntry++; + AdapterObject->NumberOfMapRegisters++; + + } + + // + // Clear the bits where the memory has been allocated. + // + + RtlClearBits( + AdapterObject->MapRegisters, + TranslationEntry - (PTRANSLATION_ENTRY) + AdapterObject->MapRegisterBase, + 1 + ); + + TranslationEntry->VirtualAddress = MapBufferVirtualAddress; + TranslationEntry->PhysicalAddress = MapBufferPhysicalAddress; + TranslationEntry++; + (PCCHAR) MapBufferVirtualAddress += PAGE_SIZE; + MapBufferPhysicalAddress += PAGE_SIZE; + + } + + // + // Remember the number of pages that where allocated. + // + + AdapterObject->NumberOfMapRegisters += NumberOfPages; + + KeReleaseSpinLock( &AdapterObject->SpinLock, Irql ); + return(TRUE); +} + +PADAPTER_OBJECT +HalpAllocateAdapter( + IN ULONG MapRegistersPerChannel, + IN PVOID AdapterBaseVa, + IN PVOID ChannelNumber + ) + +/*++ + +Routine Description: + + This routine allocates and initializes an adapter object to represent an + adapter or a DMA controller on the system. If no map registers are required + then a standalone adapter object is allocated with no master adapter. + + If map registers are required, then a master adapter object is used to + allocate the map registers. For Isa systems these registers are really + phyically contiguous memory pages. + +Arguments: + + MapRegistersPerChannel - Specifies the number of map registers that each + channel provides for I/O memory mapping. + + AdapterBaseVa - Address of the the DMA controller. + + ChannelNumber - Unused. + +Return Value: + + The function value is a pointer to the allocate adapter object. + +--*/ + +{ + + PADAPTER_OBJECT AdapterObject; + OBJECT_ATTRIBUTES ObjectAttributes; + ULONG Size; + ULONG BitmapSize; + HANDLE Handle; + NTSTATUS Status; + + UNREFERENCED_PARAMETER(ChannelNumber); + + // + // Initalize the master adapter if necessary. + // + + if (MasterAdapterObject == NULL && AdapterBaseVa != (PVOID) -1) { + + MasterAdapterObject = HalpAllocateAdapter( + MapRegistersPerChannel, + (PVOID) -1, + NULL + ); + + // + // If we could not allocate the master adapter then give up. + // + if (MasterAdapterObject == NULL) { + + return(NULL); + } + } + + // + // Begin by initializing the object attributes structure to be used when + // creating the adapter object. + // + + InitializeObjectAttributes( &ObjectAttributes, + NULL, + OBJ_PERMANENT, + (HANDLE) NULL, + (PSECURITY_DESCRIPTOR) NULL + ); + + // + // Determine the size of the adapter object. If this is the master object + // then allocate space for the register bit map; otherwise, just allocate + // an adapter object. + // + if (AdapterBaseVa == (PVOID) -1) { + + // + // Allocate a bit map large enough HalpMapBufferSize / PAGE_SIZE + // of map register buffers. + // + + BitmapSize = (((sizeof( RTL_BITMAP ) + + (( (HalpMapBufferSize/PAGE_SIZE) + (HalpMapBufferSize/0x10000) + 1 ) + 7 >> 3)) + 3) & ~3); + + Size = sizeof( ADAPTER_OBJECT ) + BitmapSize; + + } else { + + Size = sizeof( ADAPTER_OBJECT ); + + } + + // + // Now create the adapter object. + // + + Status = ObCreateObject( KernelMode, + *((POBJECT_TYPE *)IoAdapterObjectType), + &ObjectAttributes, + KernelMode, + (PVOID) NULL, + Size, + 0, + 0, + (PVOID *)&AdapterObject ); + + // + // Reference the object. + // + + if (NT_SUCCESS(Status)) { + + Status = ObReferenceObjectByPointer( + AdapterObject, + FILE_READ_DATA | FILE_WRITE_DATA, + *((POBJECT_TYPE *)IoAdapterObjectType), + KernelMode + ); + + } + + // + // If the adapter object was successfully created, then attempt to insert + // it into the the object table. + // + + if (NT_SUCCESS( Status )) { + + Status = ObInsertObject( AdapterObject, + NULL, + FILE_READ_DATA | FILE_WRITE_DATA, + 0, + (PVOID *) NULL, + &Handle ); + + if (NT_SUCCESS( Status )) { + + ZwClose( Handle ); + + // + // Initialize the adapter object itself. + // + + AdapterObject->Type = IO_TYPE_ADAPTER; + AdapterObject->Size = (USHORT) Size; + AdapterObject->MapRegistersPerChannel = 1; + AdapterObject->AdapterBaseVa = AdapterBaseVa; + + if (MapRegistersPerChannel) { + + AdapterObject->MasterAdapter = MasterAdapterObject; + + } else { + + AdapterObject->MasterAdapter = NULL; + + } + + // + // Initialize the channel wait queue for this + // adapter. + // + + KeInitializeDeviceQueue( &AdapterObject->ChannelWaitQueue ); + + // + // If this is the MasterAdatper then initialize the register bit map, + // AdapterQueue and the spin lock. + // + + if ( AdapterBaseVa == (PVOID) -1 ) { + + KeInitializeSpinLock( &AdapterObject->SpinLock ); + + InitializeListHead( &AdapterObject->AdapterQueue ); + + AdapterObject->MapRegisters = (PVOID) ( AdapterObject + 1); + + RtlInitializeBitMap( AdapterObject->MapRegisters, + (PULONG) (((PCHAR) (AdapterObject->MapRegisters)) + sizeof( RTL_BITMAP )), + ( (HalpMapBufferSize/PAGE_SIZE) + (HalpMapBufferSize/0x10000) + 1 ) + ); + // + // Set all the bits in the memory to indicate that memory + // has not been allocated for the map buffers + // + + RtlSetAllBits( AdapterObject->MapRegisters ); + AdapterObject->NumberOfMapRegisters = 0; + AdapterObject->CommittedMapRegisters = 0; + + // + // ALlocate the memory map registers. + // + + AdapterObject->MapRegisterBase = ExAllocatePool( + NonPagedPool, + ((HalpMapBufferSize/PAGE_SIZE) + (HalpMapBufferSize/0x10000) + 1 ) * + sizeof(TRANSLATION_ENTRY) + ); + + if (AdapterObject->MapRegisterBase == NULL) { + + ObDereferenceObject( AdapterObject ); + AdapterObject = NULL; + return(NULL); + + } + + // + // Zero the map registers. + // + + RtlZeroMemory( + AdapterObject->MapRegisterBase, + ((HalpMapBufferSize/PAGE_SIZE) + (HalpMapBufferSize/0x10000) + 1 ) * + sizeof(TRANSLATION_ENTRY) + ); + + if (!HalpGrowMapBuffers(AdapterObject,HalpMapBufferSize)) + { + + // + // If no map registers could be allocated then free the + // object. + // + + ObDereferenceObject( AdapterObject ); + AdapterObject = NULL; + return(NULL); + + } + } + + } else { + + // + // An error was incurred for some reason. Set the return value + // to NULL. + // + + AdapterObject = (PADAPTER_OBJECT) NULL; + } + } else { + + AdapterObject = (PADAPTER_OBJECT) NULL; + + } + + + return AdapterObject; + +} + +IO_ALLOCATION_ACTION +HalpAllocationRoutine ( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID MapRegisterBase, + IN PVOID Context + ) + +/*++ + +Routine Description: + + This function is called by HalAllocateAdapterChannel when sufficent resources + are available to the driver. This routine saves the MapRegisterBase, + and set the event pointed to by the context parameter. + +Arguments: + + DeviceObject - Supplies a pointer where the map register base should be + stored. + + Irp - Unused. + + MapRegisterBase - Supplied by the Io subsystem for use in IoMapTransfer. + + Context - Supplies a pointer to an event which is set to indicate the + AdapterObject has been allocated. + +Return Value: + + DeallocateObjectKeepRegisters - Indicates the adapter should be freed + and mapregisters should remain allocated after return. + +--*/ + +{ + + UNREFERENCED_PARAMETER(Irp); + + *((PVOID *) DeviceObject) = MapRegisterBase; + + (VOID) KeSetEvent( (PKEVENT) Context, 0L, FALSE ); + + return(DeallocateObjectKeepRegisters); +} + +PVOID +HalAllocateCommonBuffer( + IN PADAPTER_OBJECT AdapterObject, + IN ULONG Length, + OUT PPHYSICAL_ADDRESS LogicalAddress, + IN BOOLEAN CacheEnabled + ) +/*++ + +Routine Description: + + This function allocates the memory for a common buffer and maps so that it + can be accessed by a master device and the CPU. + +Arguments: + + AdapterObject - Supplies a pointer to the adapter object used by this + device. + + Length - Supplies the length of the common buffer to be allocated. + + LogicalAddress - Returns the logical address of the common buffer. + + CacheEnable - Indicates whether the memeory is cached or not. + +Return Value: + + Returns the virtual address of the common buffer. If the buffer cannot be + allocated then NULL is returned. + +--*/ + +{ + PVOID virtualAddress; + PVOID mapRegisterBase; + ULONG numberOfMapRegisters; + WAIT_CONTEXT_BLOCK wcb; + KEVENT allocationEvent; + NTSTATUS status; + KIRQL irql; + PTRANSLATION_ENTRY translationEntry; + UCHAR SavedNeedsMapRegisters; + ULONG SavedMapRegistersPerChannel; + PADAPTER_OBJECT SavedMasterAdapter; + + numberOfMapRegisters = BYTES_TO_PAGES(Length); + + SavedNeedsMapRegisters = AdapterObject->NeedsMapRegisters; + SavedMapRegistersPerChannel = AdapterObject->MapRegistersPerChannel; + SavedMasterAdapter = AdapterObject->MasterAdapter; + AdapterObject->NeedsMapRegisters = TRUE; + AdapterObject->MapRegistersPerChannel = numberOfMapRegisters; + AdapterObject->MasterAdapter = MasterAdapterObject; + + // + // Initialize an event. + // + + KeInitializeEvent( &allocationEvent, NotificationEvent, FALSE); + + // + // Initialize the wait context block. Use the device object to indicate + // where the map register base should be stored. + // + + wcb.DeviceObject = &mapRegisterBase; + wcb.CurrentIrp = NULL; + wcb.DeviceContext = &allocationEvent; + + // + // Allocate the adapter and the map registers. + // + + KeRaiseIrql(DISPATCH_LEVEL, &irql); + + status = HalAllocateAdapterChannel( + AdapterObject, + &wcb, + numberOfMapRegisters, + HalpAllocationRoutine + ); + + KeLowerIrql(irql); + + if (!NT_SUCCESS(status)) { + + // + // Cleanup and return NULL. + // + + AdapterObject->NeedsMapRegisters = SavedNeedsMapRegisters; + AdapterObject->MapRegistersPerChannel = SavedMapRegistersPerChannel; + AdapterObject->MasterAdapter = SavedMasterAdapter; + return(NULL); + + } + + // + // Wait for the map registers to be allocated. + // + + status = KeWaitForSingleObject( + &allocationEvent, + Executive, + KernelMode, + FALSE, + NULL + ); + + if (!NT_SUCCESS(status)) { + + // + // Cleanup and return NULL. + // + + AdapterObject->NeedsMapRegisters = SavedNeedsMapRegisters; + AdapterObject->MapRegistersPerChannel = SavedMapRegistersPerChannel; + AdapterObject->MasterAdapter = SavedMasterAdapter; + return(NULL); + + } + + translationEntry = (PTRANSLATION_ENTRY) ((ULONG)mapRegisterBase & ~NO_SCATTER_GATHER); + LogicalAddress->HighPart = 0; + LogicalAddress->LowPart = translationEntry->PhysicalAddress; + + if (CacheEnabled) { + virtualAddress = (PVOID)(KSEG0_BASE | LogicalAddress->LowPart); + } else { + virtualAddress = translationEntry->VirtualAddress; + } + + AdapterObject->NeedsMapRegisters = SavedNeedsMapRegisters; + AdapterObject->MapRegistersPerChannel = SavedMapRegistersPerChannel; + AdapterObject->MasterAdapter = SavedMasterAdapter; + return(virtualAddress); +} + +BOOLEAN +HalFlushCommonBuffer( + IN PADAPTER_OBJECT AdapterObject, + IN ULONG Length, + IN PHYSICAL_ADDRESS LogicalAddress, + IN PVOID VirtualAddress + ) +/*++ + +Routine Description: + + This function is called to flush any hardware adapter buffers when the + driver needs to read data written by an I/O master device to a common + buffer. + +Arguments: + + AdapterObject - Supplies a pointer to the adapter object used by this + device. + + Length - Supplies the length of the common buffer. This should be the same + value used for the allocation of the buffer. + + LogicalAddress - Supplies the logical address of the common buffer. This + must be the same value return by HalAllocateCommonBuffer. + + VirtualAddress - Supplies the virtual address of the common buffer. This + must be the same value return by HalAllocateCommonBuffer. + +Return Value: + + Returns TRUE if no errors were detected; otherwise, FALSE is return. + +--*/ + +{ + return(TRUE); +} + +VOID +HalFreeCommonBuffer( + IN PADAPTER_OBJECT AdapterObject, + IN ULONG Length, + IN PHYSICAL_ADDRESS LogicalAddress, + IN PVOID VirtualAddress, + IN BOOLEAN CacheEnabled + ) +/*++ + +Routine Description: + + This function frees a common buffer and all of the resouces it uses. + +Arguments: + + AdapterObject - Supplies a pointer to the adapter object used by this + device. + + Length - Supplies the length of the common buffer. This should be the same + value used for the allocation of the buffer. + + LogicalAddress - Supplies the logical address of the common buffer. This + must be the same value return by HalAllocateCommonBuffer. + + VirtualAddress - Supplies the virtual address of the common buffer. This + must be the same value return by HalAllocateCommonBuffer. + + CacheEnable - Indicates whether the memeory is cached or not. + +Return Value: + + None + +--*/ + +{ + PTRANSLATION_ENTRY mapRegisterBase; + ULONG numberOfMapRegisters; + ULONG mapRegisterNumber; + UCHAR SavedNeedsMapRegisters; + PADAPTER_OBJECT SavedMasterAdapter; + + if (MasterAdapterObject != NULL) { + + SavedNeedsMapRegisters = AdapterObject->NeedsMapRegisters; + SavedMasterAdapter = AdapterObject->MasterAdapter; + AdapterObject->NeedsMapRegisters = TRUE; + AdapterObject->MasterAdapter = MasterAdapterObject; + + // + // Calculate the number of map registers, the map register number and + // the map register base. + // + + numberOfMapRegisters = ADDRESS_AND_SIZE_TO_SPAN_PAGES(VirtualAddress, Length); + mapRegisterNumber = (LogicalAddress.LowPart - HalpMapBufferPhysicalAddress.LowPart) >> PAGE_SHIFT; + + mapRegisterBase = (PTRANSLATION_ENTRY) MasterAdapterObject->MapRegisterBase + + mapRegisterNumber; + + // + // Free the map registers. + // + + IoFreeMapRegisters( + AdapterObject, + (PVOID) mapRegisterBase, + numberOfMapRegisters + ); + + AdapterObject->NeedsMapRegisters = SavedNeedsMapRegisters; + AdapterObject->MasterAdapter = SavedMasterAdapter; + + } + + return; + +} + +VOID +IoFreeAdapterChannel( + IN PADAPTER_OBJECT AdapterObject + ) + +/*++ + +Routine Description: + + This routine is invoked to deallocate the specified adapter object. + Any map registers that were allocated are also automatically deallocated. + No checks are made to ensure that the adapter is really allocated to + a device object. However, if it is not, then kernel will bugcheck. + + If another device is waiting in the queue to allocate the adapter object + it will be pulled from the queue and its execution routine will be + invoked. + +Arguments: + + AdapterObject - Pointer to the adapter object to be deallocated. + +Return Value: + + None. + +--*/ + +{ + PKDEVICE_QUEUE_ENTRY Packet; + PWAIT_CONTEXT_BLOCK Wcb; + PADAPTER_OBJECT MasterAdapter; + BOOLEAN Busy = FALSE; + IO_ALLOCATION_ACTION Action; + KIRQL Irql; + LONG MapRegisterNumber; + + // + // Begin by getting the address of the master adapter. + // + + MasterAdapter = AdapterObject->MasterAdapter; + + // + // Pull requests of the adapter's device wait queue as long as the + // adapter is free and there are sufficient map registers available. + // + + while( TRUE ) { + + // + // Begin by checking to see whether there are any map registers that + // need to be deallocated. If so, then deallocate them now. + // + + if (AdapterObject->NumberOfMapRegisters != 0) { + IoFreeMapRegisters( AdapterObject, + AdapterObject->MapRegisterBase, + AdapterObject->NumberOfMapRegisters + ); + } + + // + // Simply remove the next entry from the adapter's device wait queue. + // If one was successfully removed, allocate any map registers that it + // requires and invoke its execution routine. + // + + Packet = KeRemoveDeviceQueue( &AdapterObject->ChannelWaitQueue ); + if (Packet == NULL) { + + // + // There are no more requests break out of the loop. + // + + break; + } + + Wcb = CONTAINING_RECORD( Packet, + WAIT_CONTEXT_BLOCK, + WaitQueueEntry ); + + AdapterObject->CurrentWcb = Wcb; + AdapterObject->NumberOfMapRegisters = Wcb->NumberOfMapRegisters; + + // + // Check to see whether this driver wishes to allocate any map + // registers. If so, then queue the device object to the master + // adapter queue to wait for them to become available. If the driver + // wants map registers, ensure that this adapter has enough total + // map registers to satisfy the request. + // + + if (Wcb->NumberOfMapRegisters != 0 && + AdapterObject->MasterAdapter != NULL) { + + // + // Lock the map register bit map and the adapter queue in the + // master adapter object. The channel structure offset is used as + // a hint for the register search. + // + + KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql ); + + MapRegisterNumber = -1; + + if (IsListEmpty( &MasterAdapter->AdapterQueue)) { + MapRegisterNumber = RtlFindClearBitsAndSet( MasterAdapter->MapRegisters, + Wcb->NumberOfMapRegisters, + 0 + ); + } + if (MapRegisterNumber == -1) { + + // + // There were not enough free map registers. Queue this request + // on the master adapter where is will wait until some registers + // are deallocated. + // + + InsertTailList( &MasterAdapter->AdapterQueue, + &AdapterObject->AdapterQueue + ); + Busy = 1; + + } else { + + AdapterObject->MapRegisterBase = (PVOID)((PTRANSLATION_ENTRY) + MasterAdapter->MapRegisterBase + MapRegisterNumber); + + // + // Set the no scatter/gather flag if scatter/gather not + // supported. + // + + if (!AdapterObject->ScatterGather) { + + AdapterObject->MapRegisterBase = (PVOID) + ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER); + + } + } + + KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql ); + + } else { + + AdapterObject->MapRegisterBase = NULL_MAP_REGISTER_BASE; + AdapterObject->NumberOfMapRegisters = 0; + + } + + // + // If there were either enough map registers available or no map + // registers needed to be allocated, invoke the driver's execution + // routine now. + // + + if (!Busy) { + AdapterObject->CurrentWcb = Wcb; + Action = Wcb->DeviceRoutine( Wcb->DeviceObject, + Wcb->CurrentIrp, + AdapterObject->MapRegisterBase, + Wcb->DeviceContext ); + + // + // If the execution routine would like to have the adapter + // deallocated, then release the adapter object. + // + + if (Action == KeepObject) { + + // + // This request wants to keep the channel a while so break + // out of the loop. + // + + break; + + } + + // + // If the driver wants to keep the map registers then set the + // number allocated to 0. This keeps the deallocation routine + // from deallocating them. + // + + if (Action == DeallocateObjectKeepRegisters) { + AdapterObject->NumberOfMapRegisters = 0; + } + + } else { + + // + // This request did not get the requested number of map registers so + // out of the loop. + // + + break; + } + } +} + +VOID +IoFreeMapRegisters( + PADAPTER_OBJECT AdapterObject, + PVOID MapRegisterBase, + ULONG NumberOfMapRegisters + ) +/*++ + +Routine Description: + + This routine deallocates the map registers for the adapter. If there are + any queued adapter waiting for an attempt is made to allocate the next + entry. + +Arguments: + + AdapterObject - The adapter object to where the map register should be + returned. + + MapRegisterBase - The map register base of the registers to be deallocated. + + NumberOfMapRegisters - The number of registers to be deallocated. + +Return Value: + + None + +--+*/ +{ + PADAPTER_OBJECT MasterAdapter; + LONG MapRegisterNumber; + PWAIT_CONTEXT_BLOCK Wcb; + PLIST_ENTRY Packet; + IO_ALLOCATION_ACTION Action; + KIRQL Irql; + + + // + // Begin by getting the address of the master adapter. + // + + if (AdapterObject->MasterAdapter != NULL && MapRegisterBase != NULL_MAP_REGISTER_BASE) { + + MasterAdapter = AdapterObject->MasterAdapter; + + } else { + + // + // There are no map registers to return. + // + + return; + } + + // + // Strip no scatter/gather flag. + // + + MapRegisterBase = (PVOID) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER); + + MapRegisterNumber = (PTRANSLATION_ENTRY) MapRegisterBase - + (PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase; + + // + // Acquire the master adapter spinlock which locks the adapter queue and the + // bit map for the map registers. + // + + KeAcquireSpinLock(&MasterAdapter->SpinLock, &Irql); + + // + // Return the registers to the bit map. + // + + RtlClearBits( MasterAdapter->MapRegisters, + MapRegisterNumber, + NumberOfMapRegisters + ); + + // + // Process any requests waiting for map registers in the adapter queue. + // Requests are processed until a request cannot be satisfied or until + // there are no more requests in the queue. + // + + while(TRUE) { + + if ( IsListEmpty(&MasterAdapter->AdapterQueue) ){ + break; + } + + Packet = RemoveHeadList( &MasterAdapter->AdapterQueue ); + AdapterObject = CONTAINING_RECORD( Packet, + ADAPTER_OBJECT, + AdapterQueue + ); + Wcb = AdapterObject->CurrentWcb; + + // + // Attempt to allocate map registers for this request. Use the previous + // register base as a hint. + // + + MapRegisterNumber = RtlFindClearBitsAndSet( MasterAdapter->MapRegisters, + AdapterObject->NumberOfMapRegisters, + MasterAdapter->NumberOfMapRegisters + ); + + if (MapRegisterNumber == -1) { + + // + // There were not enough free map registers. Put this request back on + // the adapter queue where is came from. + // + + InsertHeadList( &MasterAdapter->AdapterQueue, + &AdapterObject->AdapterQueue + ); + + break; + + } + + KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql ); + + AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY) + MasterAdapter->MapRegisterBase + MapRegisterNumber); + + // + // Set the no scatter/gather flag if scatter/gather not + // supported. + // + + if (!AdapterObject->ScatterGather) { + + AdapterObject->MapRegisterBase = (PVOID) + ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER); + + } + + // + // Invoke the driver's execution routine now. + // + + Action = Wcb->DeviceRoutine( Wcb->DeviceObject, + Wcb->CurrentIrp, + AdapterObject->MapRegisterBase, + Wcb->DeviceContext ); + + // + // If the driver wishes to keep the map registers then set the number + // allocated to zero and set the action to deallocate object. + // + + if (Action == DeallocateObjectKeepRegisters) { + AdapterObject->NumberOfMapRegisters = 0; + Action = DeallocateObject; + } + + // + // If the driver would like to have the adapter deallocated, + // then deallocate any map registers allocated and then release + // the adapter object. + // + + if (Action == DeallocateObject) { + + // + // The map registers registers are deallocated here rather than in + // IoFreeAdapterChannel. This limits the number of times + // this routine can be called recursively possibly overflowing + // the stack. The worst case occurs if there is a pending + // request for the adapter that uses map registers and whos + // excution routine decallocates the adapter. In that case if there + // are no requests in the master adapter queue, then IoFreeMapRegisters + // will get called again. + // + + if (AdapterObject->NumberOfMapRegisters != 0) { + + // + // Deallocate the map registers and clear the count so that + // IoFreeAdapterChannel will not deallocate them again. + // + + KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql ); + + RtlClearBits( MasterAdapter->MapRegisters, + MapRegisterNumber, + AdapterObject->NumberOfMapRegisters + ); + + AdapterObject->NumberOfMapRegisters = 0; + + KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql ); + } + + IoFreeAdapterChannel( AdapterObject ); + } + + KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql ); + + } + + KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql ); +} + +BOOLEAN +HalpCreateDmaStructures ( + VOID + ) + +/*++ + +Routine Description: + + This routine initializes the structures necessary for DMA operations + and connects the intermediate interrupt dispatcher. It also connects + an interrupt handler to the DMA channel interrupt. + +Arguments: + + None. + +Return Value: + + If the second level interrupt dispatcher is connected, then a value of + TRUE is returned. Otherwise, a value of FALSE is returned. + +--*/ + +{ + ULONG i; + BOOLEAN ReturnValue; + + // + // Initialize EISA bus interrupts. + // + + for(i=0;iVendorVectorLength / 4) >= 37) { + PrivateGetPlatformParameterBlock = *(PGET_PLATFORM_PARAMETER_BLOCK *)((ULONG)(SystemParameterBlock->VendorVector) + 37*4); + PrivateGetPlatformParameterBlock(&HalpPlatformParameterBlock); + HalpPlatformSpecificExtension = (PLATFORM_SPECIFIC_EXTENSION *)(HalpPlatformParameterBlock->PlatformSpecificExtension); + } else { + + // + // HALT system. No platform parameter block available. + // + + for(;;); + } +} + +BOOLEAN +HalInitSystem ( + IN ULONG Phase, + IN PLOADER_PARAMETER_BLOCK LoaderBlock + ) + +/*++ + +Routine Description: + + This function initializes the Hardware Architecture Layer (HAL) for a + MIPS R3000 or R4000 system. + +Arguments: + + Phase - Supplies the initialization phase (zero or one). + + LoaderBlock - Supplies a pointer to a loader parameter block. + +Return Value: + + A value of TRUE is returned is the initialization was successfully + complete. Otherwise a value of FALSE is returend. + +--*/ +{ + PKPRCB Prcb; + ULONG BuildType = 0; + + Prcb = KeGetCurrentPrcb(); + if (Phase == 0) { + + // + // Phase 0 initialization. + // + + // + // Verify that the processor block major version number conform + // to the system that is being loaded. + // + + if (Prcb->MajorVersion != PRCB_MAJOR_VERSION) { + KeBugCheck(MISMATCHED_HAL); + } + + // + // Set the active processor affinity mask. + // + + HalpActiveProcessors = 1 << Prcb->Number; + + // + // Set the DMA I/O Coherency to not coherent. This means that the instruction + // cache is not coherent with DMA, and the data cache is not coherent with DMA + // on either reads or writes. + // + + KeSetDmaIoCoherency(0); + + // + // Set the time increment value. + // + + HalpCurrentTimeIncrement = MAXIMUM_INCREMENT; + HalpNextTimeIncrement = MAXIMUM_INCREMENT; + HalpNextIntervalCount = 0; + KeSetTimeIncrement(MAXIMUM_INCREMENT, MINIMUM_INCREMENT); + + // + // Fill in handlers for APIs which this HAL supports + // + + HalQuerySystemInformation = HaliQuerySystemInformation; + HalSetSystemInformation = HaliSetSystemInformation; + HalRegisterBusHandler = HaliRegisterBusHandler; + HalHandlerForBus = HaliHandlerForBus; + HalHandlerForConfigSpace = HaliHandlerForConfigSpace; + + // + // Get Platform Parameter Block from Firmware + // + + HalpGetPlatformParameterBlock(); + + // + // Do platform specific initialization. + // + + HalpInitSystem(Phase,LoaderBlock); + + // + // Initialize interrupts. + // + + HalpInitializeInterrupts(); + + // + // Register HAL Reserved Address Spaces + // + +// HalpRegisterAddressUsage (&UniFlexPCIMainMemorySpace); +// HalpRegisterAddressUsage (&UniFlexPCIReservedMemorySpace); +// HalpRegisterAddressUsage (&UniFlexPCIReservedIoSpace); + + return TRUE; + + } else { + + // + // Phase 1 initialization. + // + + // + // Do platform specific initialization. + // + + HalpInitSystem(Phase,LoaderBlock); + + return TRUE; + } +} + + +VOID +HalInitializeProcessor ( + IN ULONG Number + ) + +/*++ + +Routine Description: + + This function is called early in the initialization of the kernel + to perform platform dependent initialization for each processor + before the HAL Is fully functional. + + N.B. When this routine is called, the PCR is present but is not + fully initialized. + +Arguments: + + Number - Supplies the number of the processor to initialize. + +Return Value: + + None. + +--*/ + +{ + return; +} + +VOID +HalpVerifyPrcbVersion () +{ + +} + + + diff --git a/private/ntos/nthals/halflex/xxpcisup.c b/private/ntos/nthals/halflex/xxpcisup.c new file mode 100644 index 000000000..ebe41bd0d --- /dev/null +++ b/private/ntos/nthals/halflex/xxpcisup.c @@ -0,0 +1,2391 @@ +/*++ + + +Copyright (C) 1989-1995 Microsoft Corporation +Copyright (C) 1994,1995 Digital Equipment Corporation + +Module Name: + + pcisup.c + +Abstract: + + Platform-independent PCI bus routines + +Environment: + + Kernel mode + +--*/ + +#include "halp.h" +#include "pci.h" +#include "pcip.h" + +typedef ULONG (*FncConfigIO) ( + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +typedef struct { + FncConfigIO ConfigRead[3]; + FncConfigIO ConfigWrite[3]; +} CONFIG_HANDLER, *PCONFIG_HANDLER; + + +// +// Define PCI slot validity +// +typedef enum _VALID_SLOT { + InvalidBus = 0, + InvalidSlot, + ValidSlot +} VALID_SLOT; + +// +// Local prototypes for routines supporting PCI bus handler routines +// + +ULONG +HalpGetPCIData ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN ULONG Slot, + IN PUCHAR Buffer, + IN ULONG Offset, + IN ULONG Length + ); + +ULONG +HalpSetPCIData ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN ULONG Slot, + IN PUCHAR Buffer, + IN ULONG Offset, + IN ULONG Length + ); + + +NTSTATUS +HalpAdjustPCIResourceList ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList + ); + + +NTSTATUS +HalpAssignPCISlotResources ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PUNICODE_STRING RegistryPath, + IN PUNICODE_STRING DriverClassName OPTIONAL, + IN PDRIVER_OBJECT DriverObject, + IN PDEVICE_OBJECT DeviceObject OPTIONAL, + IN ULONG Slot, + IN OUT PCM_RESOURCE_LIST *pAllocatedResources + ); + +VOID +HalpReadPCIConfig ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ); + +VOID +HalpWritePCIConfig ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ); + +VALID_SLOT +HalpValidPCISlot ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot + ); + +VOID +HalpPCIConfig ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PUCHAR Buffer, + IN ULONG Offset, + IN ULONG Length, + IN FncConfigIO *ConfigIO + ); + +ULONG HalpPCIReadUlong ( + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +ULONG HalpPCIReadUchar ( + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +ULONG HalpPCIReadUshort ( + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +ULONG HalpPCIWriteUlong ( + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +ULONG HalpPCIWriteUchar ( + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +ULONG HalpPCIWriteUshort ( + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +VOID +HalpPCILine2PinNop ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER SlotNumber, + IN PPCI_COMMON_CONFIG PciNewData, + IN PPCI_COMMON_CONFIG PciOldData + ); + +VOID +HalpPCIPin2LineNop ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER SlotNumber, + IN PPCI_COMMON_CONFIG PciData + ); + +#if DBG +BOOLEAN +HalpValidPCIAddr( + IN PBUS_HANDLER BusHandler, + IN PHYSICAL_ADDRESS BAddr, + IN ULONG Length, + IN ULONG AddressSpace + ); +#endif + +// +// Local prototypes of functions that are not built for Alpha AXP firmware +// + +NTSTATUS +HalpAssignPCISlotResources ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PUNICODE_STRING RegistryPath, + IN PUNICODE_STRING DriverClassName OPTIONAL, + IN PDRIVER_OBJECT DriverObject, + IN PDEVICE_OBJECT DeviceObject OPTIONAL, + IN ULONG Slot, + IN OUT PCM_RESOURCE_LIST *pAllocatedResources + ); + +#if DBG +VOID +HalpTestPci ( + ULONG + ); +#endif + +// +// Pragmas to assign functions to different kinds of pages. +// + +#if !defined(AXP_FIRMWARE) +#ifdef ALLOC_PRAGMA +#pragma alloc_text(INIT,HalpInitializePCIBus) +#pragma alloc_text(INIT,HalpAllocateAndInitPCIBusHandler) +#pragma alloc_text(INIT,HalpRegisterPCIInstallHandler ) +#pragma alloc_text(INIT,HalpDefaultPCIInstallHandler ) +#pragma alloc_text(INIT,HalpDeterminePCIDevicesPresent ) +#pragma alloc_text(PAGE,HalpAssignPCISlotResources) +#pragma alloc_text(PAGE,HalpAdjustPCIResourceList) +#endif // ALLOC_PRAGMA +#endif // !defined(AXP_FIRMWARE) + +#ifdef AXP_FIRMWARE + +#define ExFreePool(PoolData) + +#pragma alloc_text(DISTEXT, HalpInitializePCIBus ) +#pragma alloc_text(DISTEXT, HalpAllocateAndInitPCIBusHandler) +#pragma alloc_text(DISTEXT, HalpRegisterPCIInstallHandler ) +#pragma alloc_text(DISTEXT, HalpDefaultPCIInstallHandler ) +#pragma alloc_text(DISTEXT, HalpDeterminePCIDevicesPresent ) +#pragma alloc_text(DISTEXT, HalpGetPCIData ) +#pragma alloc_text(DISTEXT, HalpSetPCIData ) +#pragma alloc_text(DISTEXT, HalpReadPCIConfig ) +#pragma alloc_text(DISTEXT, HalpWritePCIConfig ) +#pragma alloc_text(DISTEXT, HalpValidPCISlot ) +#if DBG +#pragma alloc_text(DISTEXT, HalpValidPCIAddr ) +#endif +#pragma alloc_text(DISTEXT, HalpPCIConfig ) +#pragma alloc_text(DISTEXT, HalpPCIReadUchar ) +#pragma alloc_text(DISTEXT, HalpPCIReadUshort ) +#pragma alloc_text(DISTEXT, HalpPCIReadUlong ) +#pragma alloc_text(DISTEXT, HalpPCIWriteUchar ) +#pragma alloc_text(DISTEXT, HalpPCIWriteUshort ) +#pragma alloc_text(DISTEXT, HalpPCIWriteUlong ) +#pragma alloc_text(DISTEXT, HalpAssignPCISlotResources) +#pragma alloc_text(DISTEXT, HalpAdjustPCIResourceList) + +#endif // AXP_FIRMWARE + + +// +// Globals +// + +KSPIN_LOCK HalpPCIConfigLock; +BOOLEAN PCIInitialized = FALSE; +ULONG PCIMaxLocalDevice; +ULONG PCIMaxDevice; +ULONG PCIMaxBus; +PINSTALL_BUS_HANDLER PCIInstallHandler = HalpDefaultPCIInstallHandler; + +CONFIG_HANDLER PCIConfigHandlers = { + { + HalpPCIReadUlong, // 0 + HalpPCIReadUchar, // 1 + HalpPCIReadUshort // 2 + }, + { + HalpPCIWriteUlong, // 0 + HalpPCIWriteUchar, // 1 + HalpPCIWriteUshort // 2 + } +}; +UCHAR PCIDeref[4][4] = { {0,1,2,2},{1,1,1,1},{2,1,2,2},{1,1,1,1} }; + +WCHAR rgzMultiFunctionAdapter[] = L"\\Registry\\Machine\\Hardware\\Description\\System\\MultifunctionAdapter"; +WCHAR rgzConfigurationData[] = L"Configuration Data"; +WCHAR rgzIdentifier[] = L"Identifier"; +WCHAR rgzPCIIndetifier[] = L"PCI"; + +#define Is64BitBaseAddress(a) \ + (((a & PCI_ADDRESS_IO_SPACE) == 0) && \ + ((a & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_64BIT)) + + +VOID +HalpInitializePCIBus ( + VOID + ) +/*++ + +Routine Description: + + The function intializes global PCI bus state from the registry. + + The Arc firmware is responsible for building configuration information + about the number of PCI buses on the system and nature (local vs. secondary + - across a PCI-PCI bridge) of the each bus. This state is held in + PCIRegInfo. + + The maximum virtual slot number on the local (type 0 config cycle) + PCI bus is registered here, based on the machine dependent define + PCI_MAX_LOCAL_DEVICE. This state is carried in PCIMaxLocalDevice. + + The maximum number of virtual slots on a secondary bus is fixed by the + PCI Specification and is represented by PCI_MAX_DEVICES. This + state is held in PCIMaxDevice. + +Arguments: + + None. + +Return Value: + + None. + + +--*/ +{ + +#if !defined(AXP_FIRMWARE) + + // + // x86 Hal's can query the registry, while on Alpha pltforms we cannot. + // So we let the ARC firmware actually configure the bus/bridges. + // + + PCI_SLOT_NUMBER SlotNumber; + ULONG DeviceNumber; + ULONG FunctionNumber; + PCI_COMMON_CONFIG CommonConfig; + ULONG BusNumber; + ULONG ibus; + PBUS_HANDLER Bus0; + + // + // Has the PCI bus already been initialized? + // + + if (PCIInitialized) { + return; + } + + // + // Intialize PCI configuration to the maximum configuration for starters. + // + + PCIMaxLocalDevice = PCI_MAX_LOCAL_DEVICE; + PCIMaxDevice = PCI_MAX_DEVICES - 1; + + // + // Unless there exists any PCI-to-PCI bridges, there will only be 1 + // bus. + // + + PCIMaxBus = 1; + + // + // For each "local" PCI bus present, allocate a handler structure and + // fill in the dispatch functions + // + // After we determine how many "remote" PCI buses are present, we will + // add them. + // + + for (ibus = 0; ibus < PCIMaxBus; ibus++) { + + // + // If handler not already built, do it now + // + + if (!HaliHandlerForBus (PCIBus, ibus)) { + HalpAllocateAndInitPCIBusHandler (ibus); + } + } + // + // Initialize the slot number struct. + // + + SlotNumber.u.AsULONG = 0; + + // + // Loop through each device. + // + + Bus0 = HaliHandlerForBus(PCIBus, 0); + + for (DeviceNumber = 0; DeviceNumber < PCI_MAX_DEVICES; DeviceNumber++) { + + SlotNumber.u.bits.DeviceNumber = DeviceNumber; + + // + // Loop through each function. + // + + for (FunctionNumber = 0; FunctionNumber < PCI_MAX_FUNCTION; FunctionNumber++) { + SlotNumber.u.bits.FunctionNumber = FunctionNumber; + + // + // Read the device's configuration space. + // + + HalpReadPCIConfig(Bus0, + SlotNumber, + &CommonConfig, + 0, + PCI_COMMON_HDR_LENGTH); + + // + // No device exists at this device/function number. + // + + if (CommonConfig.VendorID == PCI_INVALID_VENDORID) { + + // + // If this is the first function number, then break, because + // we know a priori there will not be any devices on the + // other function numbers. + // + + if (FunctionNumber == 0) { + break; + } + + // + // Check the next function number. + // + + continue; + } + + // + // A PCI-to-PCI bridge has been discovered. + // + + if (CommonConfig.BaseClass == 0x06 && + CommonConfig.SubClass == 0x04 && + CommonConfig.ProgIf == 0x00) { + + // + // Get the subordinate bus number (which is the highest + // numbered bus this bridge will forward to) and add 1. + // + + BusNumber = CommonConfig.u.type1.SubordinateBus + 1; + + // + // The maximum subordinate across the local bus is the + // maximum number of busses. + // + + if (PCIMaxBus < BusNumber) { + PCIMaxBus = BusNumber; + } + } + + // + // If this is not a multi-function device then break out now. + // + + if ((CommonConfig.HeaderType & PCI_MULTIFUNCTION) == 0) { + break; + } + } + } + + // + // For each additional PCI bus present, allocate a handler structure and + // fill in the dispatch functions. If there are no additional + // PCI buses, (i.e., no PCI-PCI bridges were found), this loop + // will exit before a single iteration. + // + + for (ibus = 1; ibus < PCIMaxBus; ibus++) { + + // + // If handler not already built, do it now + // + + if (!HaliHandlerForBus (PCIBus, ibus)) { + HalpAllocateAndInitPCIBusHandler (ibus); + } + } + + KeInitializeSpinLock (&HalpPCIConfigLock); + PCIInitialized = TRUE; + +#if DBG + HalpTestPci (0); +#endif + +#else + + PCIMaxLocalDevice = PCI_MAX_LOCAL_DEVICE; + PCIMaxDevice = PCI_MAX_DEVICES - 1; + PCIMaxBus = PCI_MAX_BUSSES; + + // + // Note: + // Firmware will allocate bus handlers during + // PCI configuration. + // + + KeInitializeSpinLock (&HalpPCIConfigLock); + PCIInitialized = TRUE; + +#endif // !AXP_FIRMWARE + +} + +PBUS_HANDLER +HalpAllocateAndInitPCIBusHandler ( + IN ULONG BusNo + ) +{ + PBUS_HANDLER Bus; + + HaliRegisterBusHandler ( + PCIBus, // Interface type + PCIConfiguration, // Has this configuration space + BusNo, // Bus Number + Internal, // child of this bus + 0, // and number + sizeof (PCIPBUSDATA), // sizeof bus specific buffer + PCIInstallHandler, // PCI install handler + &Bus); // Bushandler return + + return Bus; +} + +NTSTATUS +HalpDefaultPCIInstallHandler( + IN PBUS_HANDLER Bus + ) +{ + PPCIPBUSDATA BusData; + + // + // Fill in PCI handlers + // + + Bus->GetBusData = (PGETSETBUSDATA) HalpGetPCIData; + Bus->SetBusData = (PGETSETBUSDATA) HalpSetPCIData; + Bus->AdjustResourceList = (PADJUSTRESOURCELIST) HalpAdjustPCIResourceList; + Bus->AssignSlotResources = (PASSIGNSLOTRESOURCES) HalpAssignPCISlotResources; + + BusData = (PPCIPBUSDATA) Bus->BusData; + + // + // Fill in common PCI data + // + + BusData->CommonData.Tag = PCI_DATA_TAG; + BusData->CommonData.Version = PCI_DATA_VERSION; + BusData->CommonData.ReadConfig = (PciReadWriteConfig)HalpReadPCIConfig; + BusData->CommonData.WriteConfig = (PciReadWriteConfig)HalpWritePCIConfig; + BusData->CommonData.Pin2Line = (PciPin2Line)HalpPCIPin2LineNop; + BusData->CommonData.Line2Pin = (PciLine2Pin)HalpPCILine2PinNop; + + + // set defaults + // + // ecrfix - if we knew more about the PCI bus at this + // point (e.g., local vs. across bridge, PCI config + // space base QVA, APECS vs. Sable T2/T4 vs. LCA4 vs. ??? config + // cycle type 0 mechanism), we could put this info into + // the "BusData" structure. The nice thing about this is + // that we could eliminate the platform-dependent module + // PCIBUS.C. + // + + BusData->MaxDevice = PCI_MAX_DEVICES - 1; // not currently used anywhere + +#if !defined(AXP_FIRMWARE) + // + // Perform DevicePresent scan for this bus. + // + + HalpDeterminePCIDevicesPresent(Bus); +#endif // !AXP_FIRMWARE + + return STATUS_SUCCESS; +} + +VOID +HalpRegisterPCIInstallHandler( + IN PINSTALL_BUS_HANDLER MachineSpecificPCIInstallHandler +) +/*++ + +Routine Description: + + The function register's a machine-specific PCI Install Handler. + This allows a specific platform to override the default PCI install + handler, DefaultPCIInstallHandler(). + +Arguments: + + MachineSpecificPCIInstallHandler - Function that provides machine + specific PCI Bus Handler setup. + +Return Value: + + None. + + +--*/ +{ + PCIInstallHandler = MachineSpecificPCIInstallHandler; + + return; +} + +VOID +HalpDeterminePCIDevicesPresent( + IN PBUS_HANDLER Bus +) +/*++ + +Routine Description: + + The function determines which PCI devices and functions are + present on a given PCI bus. An RTL_BITMAP vector in the bus handler's + PCI-specific BusData is updated to reflect the devices that actually + exist on this bus. + + THIS COULD BE DONE IN FIRMWARE! + +Arguments: + + Bus - BusHandler for the bus to be searched. This bus handler must + have already been allocated and initialized. + +Return Value: + + None. + + +--*/ +{ + PCI_COMMON_CONFIG CommonConfig; + PCI_SLOT_NUMBER Slot; + ULONG DeviceNumber; + ULONG FunctionNumber; + ULONG cnt; + RTL_BITMAP DevicePresent; + PPCIPBUSDATA BusData; + + // + // Formally disable DevicePresent checking for this bus. + // + + BusData = (PPCIPBUSDATA) Bus->BusData; + BusData->DevicePresent.Buffer = NULL; + + // + // Initialize local copy of device present bitmap + // (Can't update bus handler data because we need to probe + // the bus in question.) + // + + RtlInitializeBitMap (&DevicePresent, + BusData->DevicePresentBits, 256); + + // + // For this bus, probe each possible slot. If no device + // is present than indicate that in the DevicePresent structure. + // + + Slot.u.AsULONG = 0; + + for( DeviceNumber=0; DeviceNumber < PCI_MAX_DEVICES; DeviceNumber++ ){ + + Slot.u.bits.DeviceNumber = DeviceNumber; + + for (FunctionNumber = 0; FunctionNumber < PCI_MAX_FUNCTION; FunctionNumber++) + { + + Slot.u.bits.FunctionNumber = FunctionNumber; + + // + // Read only first ULONG of PCI config space, which + // contains the Vendor ID. + // + // (DevicePresent checking is *not* in effect yet + // for this bus.) + // + + HalpReadPCIConfig(Bus, + Slot, + &CommonConfig, + 0, + sizeof(ULONG)); + + // + // See if a device & function is present. If so, set a bit. + // + + if (CommonConfig.VendorID != PCI_INVALID_VENDORID) { + cnt = PciBitIndex(Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber); + RtlSetBits (&DevicePresent, cnt, 1); + } + + } // end for( FunctionNumber=0; ... + + } // end for( DeviceNumber=0; ... + + // + // Update bus data now that we know what's present on the bus. + // (DevicePresent checking is now in effect yet for this bus.) + // + + BusData->DevicePresent = DevicePresent; + + return; + +} + + +ULONG +HalpGetPCIData ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN ULONG Slot, + IN PUCHAR Buffer, + IN ULONG Offset, + IN ULONG Length + ) +/*++ + +Routine Description: + + The function returns the PCI bus data for a device. + +Arguments: + + BusHandler - Registered BUSHANDLER for the target configuration space + + RootHandler - Register BUSHANDLER for the orginating HalGetBusData request. + + VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word) + + Buffer - Supplies the space to store the data. + + Length - Supplies a count in bytes of the maximum amount to return. + +Return Value: + + Returns the amount of data stored into the buffer. + + If this PCI slot has never been set, then the configuration information + returned is zeroed. + + +--*/ +{ + PPCI_COMMON_CONFIG PciData; + UCHAR iBuffer[PCI_COMMON_HDR_LENGTH]; + ULONG Len; + PCI_SLOT_NUMBER PciSlot; + + if (Length > sizeof (PCI_COMMON_CONFIG)) { + Length = sizeof (PCI_COMMON_CONFIG); + } + + Len = 0; + PciData = (PPCI_COMMON_CONFIG) iBuffer; + PciSlot = *((PPCI_SLOT_NUMBER) &Slot); + + if (Offset >= PCI_COMMON_HDR_LENGTH) { + // + // The user did not request any data from the common + // header. Verify the PCI device exists, then continue + // in the device specific area. + // + + HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, sizeof(ULONG)); + + // + // Check for invalid slot + // + + if (PciData->VendorID == PCI_INVALID_VENDORID) { + return 0; + } + + } else { + + // + // Caller requested at least some data within the + // common header. Read the whole header, effect the + // fields we need to and then copy the user's requested + // bytes from the header + // + + // + // Read this PCI devices slot data + // + + Len = PCI_COMMON_HDR_LENGTH; + HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, Len); + + // + // Check for invalid slot + // + + if (PciData->VendorID == PCI_INVALID_VENDORID || + PCI_CONFIG_TYPE (PciData) != 0) { + PciData->VendorID = PCI_INVALID_VENDORID; + Len = 2; // only return invalid id + } + + // + // Copy whatever data overlaps into the callers buffer + // + + if (Len < Offset) { + // no data at caller's buffer + return 0; + } + + Len -= Offset; + if (Len > Length) { + Len = Length; + } + + RtlMoveMemory(Buffer, iBuffer + Offset, Len); + + Offset += Len; + Buffer += Len; + Length -= Len; + } + + if (Length) { + if (Offset >= PCI_COMMON_HDR_LENGTH) { + // + // The remaining Buffer comes from the Device Specific + // area - put on the kitten gloves and read from it. + // + // Specific read/writes to the PCI device specific area + // are guarenteed: + // + // Not to read/write any byte outside the area specified + // by the caller. (this may cause WORD or BYTE references + // to the area in order to read the non-dword aligned + // ends of the request) + // + // To use a WORD access if the requested length is exactly + // a WORD long. + // + // To use a BYTE access if the requested length is exactly + // a BYTE long. + // + + HalpReadPCIConfig (BusHandler, PciSlot, Buffer, Offset, Length); + + + Len += Length; + } + } + + return Len; +} + +ULONG +HalpSetPCIData ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN ULONG Slot, + IN PUCHAR Buffer, + IN ULONG Offset, + IN ULONG Length + ) +/*++ + +Routine Description: + + The function returns the Pci bus data for a device. + +Arguments: + + BusHandler - Registered BUSHANDLER for the target configuration space + + RootHandler - Register BUSHANDLER for the orginating HalSetBusData request. + + VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word) + + Buffer - Supplies the space to store the data. + + Length - Supplies a count in bytes of the maximum amount to return. + +Return Value: + + Returns the amount of data stored into the buffer. + +--*/ +{ + PPCI_COMMON_CONFIG PciData, PciData2; + UCHAR iBuffer[PCI_COMMON_HDR_LENGTH]; + UCHAR iBuffer2[PCI_COMMON_HDR_LENGTH]; + ULONG Len; + PCI_SLOT_NUMBER PciSlot; + + if (Length > sizeof (PCI_COMMON_CONFIG)) { + Length = sizeof (PCI_COMMON_CONFIG); + } + + + Len = 0; + PciData = (PPCI_COMMON_CONFIG) iBuffer; + PciData2 = (PPCI_COMMON_CONFIG) iBuffer2; + PciSlot = *((PPCI_SLOT_NUMBER) &Slot); + + + if (Offset >= PCI_COMMON_HDR_LENGTH) { + // + // The user did not request any data from the common + // header. Verify the PCI device exists, then continue in + // the device specific area. + // + + HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, sizeof(ULONG)); + + if (PciData->VendorID == PCI_INVALID_VENDORID || + PciData->VendorID == 0x00) { + return 0; + } + + } else { + + // + // Caller requested to set at least some data within the + // common header. + // + + Len = PCI_COMMON_HDR_LENGTH; + HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, Len); + if (PciData->VendorID == PCI_INVALID_VENDORID || + PciData->VendorID == 0x00 || + PCI_CONFIG_TYPE (PciData) != 0) { + + // no device, or header type unkown + return 0; + } + + // + // Copy COMMON_HDR values to buffer2, then overlay callers changes. + // + + RtlMoveMemory (iBuffer2, iBuffer, Len); + + Len -= Offset; + if (Len > Length) { + Len = Length; + } + + RtlMoveMemory (iBuffer2+Offset, Buffer, Len); + +#if DBG + // + // Verify R/O fields haven't changed + // + if (PciData2->VendorID != PciData->VendorID || + PciData2->DeviceID != PciData->DeviceID || + PciData2->RevisionID != PciData->RevisionID || + PciData2->ProgIf != PciData->ProgIf || + PciData2->SubClass != PciData->SubClass || + PciData2->BaseClass != PciData->BaseClass || + PciData2->HeaderType != PciData->HeaderType || + PciData2->BaseClass != PciData->BaseClass || + PciData2->u.type0.MinimumGrant != PciData->u.type0.MinimumGrant || + PciData2->u.type0.MaximumLatency != PciData->u.type0.MaximumLatency) { + DbgPrint ("PCI SetBusData: Read-Only configation value changed\n"); + DbgBreakPoint (); + } +#endif // DBG + // + // Set new PCI configuration + // + + HalpWritePCIConfig (BusHandler, PciSlot, iBuffer2+Offset, Offset, Len); + + Offset += Len; + Buffer += Len; + Length -= Len; + } + + if (Length) { + + if (Offset >= PCI_COMMON_HDR_LENGTH) { + // + // The remaining Buffer comes from the Device Specific + // area - put on the kitten gloves and write it + // + // Specific read/writes to the PCI device specific area + // are guarenteed: + // + // Not to read/write any byte outside the area specified + // by the caller. (this may cause WORD or BYTE references + // to the area in order to read the non-dword aligned + // ends of the request) + // + // To use a WORD access if the requested length is exactly + // a WORD long. + // + // To use a BYTE access if the requested length is exactly + // a BYTE long. + // + + HalpWritePCIConfig (BusHandler, PciSlot, Buffer, Offset, Length); + + Len += Length; + } + } + + return Len; +} + +VOID +HalpPCILine2PinNop ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER SlotNumber, + IN PPCI_COMMON_CONFIG PciNewData, + IN PPCI_COMMON_CONFIG PciOldData + ) +{ + // line-pin mappings not needed on alpha machines + return ; +} + +VOID +HalpPCIPin2LineNop ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER SlotNumber, + IN PPCI_COMMON_CONFIG PciData + ) +{ + // line-pin mappings not needed on alpha machines + return ; +} + +VOID +HalpReadPCIConfig ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ) +{ +#if 0 + if (!HalpValidPCISlot (BusHandler, Slot)) { + // + // Invalid SlotID return no data + // + + RtlFillMemory (Buffer, Length, (UCHAR) -1); + return ; + } + + HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length, + PCIConfigHandlers.ConfigRead); +#endif // 0 + + // + // Read the slot, if it's valid. + // Otherwise, return an Invalid VendorId for a invalid slot on an existing bus + // or a null (zero) buffer if we have a non-existant bus. + // + + switch (HalpValidPCISlot (BusHandler, Slot)) + { + + case ValidSlot: + + HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length, + PCIConfigHandlers.ConfigRead); + break; + + case InvalidSlot: + + // + // Invalid SlotID return no data (Invalid Slot ID = 0xFFFF) + // + + RtlFillMemory (Buffer, Length, (UCHAR) -1); + break ; + + case InvalidBus: + + // + // Invalid Bus, return return no data + // + + RtlFillMemory (Buffer, Length, (UCHAR) 0); + break ; + } + + return; + +} + +VOID +HalpWritePCIConfig ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ) +{ + + if (HalpValidPCISlot (BusHandler, Slot) != ValidSlot) { + // + // Invalid SlotID do nothing + // + return ; + } + + HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length, + PCIConfigHandlers.ConfigWrite); +} + +VALID_SLOT +HalpValidPCISlot ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot + ) +{ + ULONG BusNumber; + PPCIPBUSDATA BusData; + PCI_SLOT_NUMBER Slot2; + PCI_CONFIGURATION_TYPES PciConfigType; + UCHAR HeaderType; + ULONG i, bit; + + BusNumber = BusHandler->BusNumber; + BusData = (PPCIPBUSDATA) BusHandler->BusData; + + if (Slot.u.bits.Reserved != 0) { + return FALSE; + } + + // + // If the initial device probe has been completed and no device + // is present for this slot then simply return invalid slot. + // + + bit = PciBitIndex(Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber); + + if( ( (BusData->DevicePresent).Buffer != NULL) && + !RtlCheckBit(&BusData->DevicePresent, bit) ) { + +#if HALDBG + + DbgPrint( "Config access supressed for bus = %d, device = %d, function = %d\n", + BusNumber, + Slot.u.bits.DeviceNumber, + Slot.u.bits.FunctionNumber ); + +#endif // HALDBG + + return InvalidSlot; + } + + + // + // Get the config cycle type for the proposed bus. + // (PciConfigTypeInvalid indicates a non-existent bus.) + // + + PciConfigType = HalpPCIConfigCycleType(BusNumber); + + // + // The number of devices allowed on a local PCI bus may be different + // than that across a PCI-PCI bridge. + // + + switch(PciConfigType) { + case PciConfigType0: + + if (Slot.u.bits.DeviceNumber > PCIMaxLocalDevice) { +#if HALDBG + DbgPrint("Invalid local PCI Slot %x\n", Slot.u.bits.DeviceNumber); +#endif + return InvalidSlot; + } + break; + + case PciConfigType1: + + if (Slot.u.bits.DeviceNumber > PCIMaxDevice) { +#if HALDBG + DbgPrint("Invalid remote PCI Slot %x\n", Slot.u.bits.DeviceNumber); +#endif + return InvalidSlot; + } + break; + + case PciConfigTypeInvalid: + +#if HALDBG + DbgPrint("Invalid PCI Bus %x\n", BusNumber); +#endif + return InvalidBus; + break; + + } + + // + // Check function number + // + + if (Slot.u.bits.FunctionNumber == 0) { + return ValidSlot; + } + + // + // Non zero function numbers are only supported if the + // device has the PCI_MULTIFUNCTION bit set in it's header + // + + i = Slot.u.bits.DeviceNumber; + + // + // Read DeviceNumber, Function zero, to determine if the + // PCI supports multifunction devices + // + + Slot2 = Slot; + Slot2.u.bits.FunctionNumber = 0; + + HalpReadPCIConfig ( + BusHandler, + Slot2, + &HeaderType, + FIELD_OFFSET (PCI_COMMON_CONFIG, HeaderType), + sizeof (UCHAR) + ); + + if (!(HeaderType & PCI_MULTIFUNCTION) || (HeaderType == 0xFF)) { + // this device doesn't exists or doesn't support MULTIFUNCTION types + return InvalidSlot; + } + + return ValidSlot; +} + +VOID +HalpPCIConfig ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PUCHAR Buffer, + IN ULONG Offset, + IN ULONG Length, + IN FncConfigIO *ConfigIO + ) +{ + KIRQL OldIrql; + ULONG i; + PCI_CFG_CYCLE_BITS PciAddr; + ULONG BusNumber; + + BusNumber = BusHandler->BusNumber; + + // + // Setup platform-dependent state for configuration space access + // + + HalpPCIConfigAddr(BusNumber, Slot, &PciAddr); + + // + // Synchronize with PCI config space + // + + KeAcquireSpinLock (&HalpPCIConfigLock, &OldIrql); + + // + // Do the I/O to PCI configuration space + // + + while (Length) { + i = PCIDeref[Offset % sizeof(ULONG)][Length % sizeof(ULONG)]; + i = ConfigIO[i] (&PciAddr, Buffer, Offset); + + Offset += i; + Buffer += i; + Length -= i; + } + + // + // Release spinlock + // + + KeReleaseSpinLock (&HalpPCIConfigLock, OldIrql); + + return; +} + +ULONG +HalpPCIReadUchar ( + IN PPCI_CFG_CYCLE_BITS PciCfg, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + ULONG ConfigurationCycleType; + + // + // The configuration cycle type is extracted from bits[1:0] of PciCfg. + // + // Since an LCA4 register generates the configuration cycle type + // on the PCI bus, and because Offset bits[1:0] are used to + // generate the PCI byte enables (C/BE[3:0]), clear PciCfg bits [1:0] + // out before adding in Offset. + // + + ConfigurationCycleType = PciCfg->u.bits.Reserved1; + PciCfg->u.bits.Reserved1 = 0; + + *Buffer = READ_CONFIG_UCHAR ((PUCHAR) (PciCfg->u.AsULONG + Offset), + ConfigurationCycleType); + + // + // Reset state to preserve config cycle type across calls + // + + PciCfg->u.bits.Reserved1 = ConfigurationCycleType; + + return sizeof (UCHAR); +} + +ULONG +HalpPCIReadUshort ( + IN PPCI_CFG_CYCLE_BITS PciCfg, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + ULONG ConfigurationCycleType; + + ConfigurationCycleType = PciCfg->u.bits.Reserved1; + PciCfg->u.bits.Reserved1 = 0; + + *((PUSHORT) Buffer) = READ_CONFIG_USHORT ((PUSHORT) (PciCfg->u.AsULONG + Offset), + ConfigurationCycleType); + // + // Reset state to preserve config cycle type across calls + // + + PciCfg->u.bits.Reserved1 = ConfigurationCycleType; + + return sizeof (USHORT); +} + +ULONG +HalpPCIReadUlong ( + IN PPCI_CFG_CYCLE_BITS PciCfg, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + ULONG ConfigurationCycleType; + + ConfigurationCycleType = PciCfg->u.bits.Reserved1; + PciCfg->u.bits.Reserved1 = 0; + + *((PULONG) Buffer) = READ_CONFIG_ULONG ((PULONG) (PciCfg->u.AsULONG + Offset), + ConfigurationCycleType); + // + // Reset state to preserve config cycle type across calls + // + + PciCfg->u.bits.Reserved1 = ConfigurationCycleType; + + return sizeof (ULONG); +} + + +ULONG +HalpPCIWriteUchar ( + IN PPCI_CFG_CYCLE_BITS PciCfg, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + ULONG ConfigurationCycleType; + + ConfigurationCycleType = PciCfg->u.bits.Reserved1; + PciCfg->u.bits.Reserved1 = 0; + + WRITE_CONFIG_UCHAR ((PUCHAR) (PciCfg->u.AsULONG + Offset), *Buffer, + ConfigurationCycleType); + // + // Reset state to preserve config cycle type across calls + // + + PciCfg->u.bits.Reserved1 = ConfigurationCycleType; + + return sizeof (UCHAR); +} + +ULONG +HalpPCIWriteUshort ( + IN PPCI_CFG_CYCLE_BITS PciCfg, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + ULONG ConfigurationCycleType; + + ConfigurationCycleType = PciCfg->u.bits.Reserved1; + PciCfg->u.bits.Reserved1 = 0; + + WRITE_CONFIG_USHORT ((PUSHORT) (PciCfg->u.AsULONG + Offset), *((PUSHORT) Buffer), + ConfigurationCycleType); + // + // Reset state to preserve config cycle type across calls + // + + PciCfg->u.bits.Reserved1 = ConfigurationCycleType; + + return sizeof (USHORT); +} + +ULONG +HalpPCIWriteUlong ( + IN PPCI_CFG_CYCLE_BITS PciCfg, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + ULONG ConfigurationCycleType; + + ConfigurationCycleType = PciCfg->u.bits.Reserved1; + PciCfg->u.bits.Reserved1 = 0; + + WRITE_CONFIG_ULONG ((PULONG) (PciCfg->u.AsULONG + Offset), *((PULONG) Buffer), + ConfigurationCycleType); + // + // Reset state to preserve config cycle type across calls + // + + PciCfg->u.bits.Reserved1 = ConfigurationCycleType; + + return sizeof (ULONG); +} + +#if DBG + +BOOLEAN +HalpValidPCIAddr( + IN PBUS_HANDLER BusHandler, + IN PHYSICAL_ADDRESS BAddr, + IN ULONG Length, + IN ULONG AddressSpace) +/*++ + +Routine Description: + + Checks to see that the begining and ending 64 bit PCI bus addresses + of the 32 bit range of length Length are supported on the system. + +Arguments: + + BAddr - the 64 bit starting address + + Length - a 32 bit length + + AddressSpace - is this I/O (1) or memory space (0) + +Return Value: + + TRUE or FALSE + +--*/ +{ + PHYSICAL_ADDRESS EAddr, TBAddr, TEAddr; + LARGE_INTEGER LiILen; + ULONG inIoSpace, inIoSpace2; + BOOLEAN flag, flag2; + ULONG BusNumber; + + BusNumber = BusHandler->BusNumber; + + // + // Translated address to system global setting and verify + // resource is available. + // + // Note that this code will need to be changed to support + // 64 bit PCI bus addresses. + // + + LiILen.QuadPart = (ULONG)(Length - 1); // Inclusive length + EAddr.QuadPart = BAddr.QuadPart + LiILen.QuadPart; + + inIoSpace = inIoSpace2 = AddressSpace; + + flag = HalTranslateBusAddress ( PCIBus, + BusNumber, + BAddr, + &inIoSpace, + &TBAddr + ); + + flag2 = HalTranslateBusAddress (PCIBus, + BusNumber, + EAddr, + &inIoSpace2, + &TEAddr + ); + + if (flag == FALSE || flag2 == FALSE || inIoSpace != inIoSpace2) { + + // + // HalAdjustResourceList should ensure that the returned range + // for the bus is within the bus limits and no translation + // within those limits should ever fail + // + + DbgPrint ("HalpValidPCIAddr: Error return for HalTranslateBusAddress %x.%x:%x %x.%x:%x\n", + BAddr.HighPart, BAddr.LowPart, flag, + EAddr.HighPart, EAddr.LowPart, flag2); + return FALSE; + } + + return TRUE; +} + +#endif + + +NTSTATUS +HalpAssignPCISlotResources ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PUNICODE_STRING RegistryPath, + IN PUNICODE_STRING DriverClassName OPTIONAL, + IN PDRIVER_OBJECT DriverObject, + IN PDEVICE_OBJECT DeviceObject OPTIONAL, + IN ULONG Slot, + IN OUT PCM_RESOURCE_LIST *pAllocatedResources + ) +/*++ + +Routine Description: + + Reads the targeted device to determine the firmwaire-assigned resources. + Calls IoReportResources to report/confirm them. + Returns the assignments to the caller. + +Arguments: + +Return Value: + + STATUS_SUCCESS or error + +--*/ +{ + NTSTATUS status; + PUCHAR WorkingPool; + PPCI_COMMON_CONFIG PciData, PciOrigData; + PCI_SLOT_NUMBER PciSlot; + + PCM_RESOURCE_LIST CmRes; + PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc; + PHYSICAL_ADDRESS BAddr; + ULONG addr; + ULONG Command; + ULONG cnt, len; + BOOLEAN conflict; + + ULONG i, j, m, length, holdvalue; + ULONG BusNumber; + + BusNumber = BusHandler->BusNumber; + + *pAllocatedResources = NULL; + PciSlot = *((PPCI_SLOT_NUMBER) &Slot); + + // + // Allocate some pool for working space + // + + i = sizeof (CM_RESOURCE_LIST) + + sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR) * (PCI_TYPE0_ADDRESSES + 2) + + PCI_COMMON_HDR_LENGTH * 2; + + WorkingPool = (PUCHAR) ExAllocatePool (PagedPool, i); + if (!WorkingPool) { + return STATUS_NO_MEMORY; + } + + // + // Zero initialize pool, and get pointers into memory - here we allocate + // a single chunk of memory and partition it into three pieces, pointed + // to by three separate pointers. + // + + RtlZeroMemory (WorkingPool, i); + CmRes = (PCM_RESOURCE_LIST) WorkingPool; + PciData = (PPCI_COMMON_CONFIG)(WorkingPool + i - PCI_COMMON_HDR_LENGTH * 2); + PciOrigData = (PPCI_COMMON_CONFIG)(WorkingPool + i - PCI_COMMON_HDR_LENGTH); + + // + // Read the PCI device configuration + // + + HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH); + if (PciData->VendorID == PCI_INVALID_VENDORID || // empty slot + PciData->VendorID == 0x00) { // non-existant bus + ExFreePool (WorkingPool); + return STATUS_NO_SUCH_DEVICE; + } + + // + // Make a copy of the devices current settings + // + + RtlMoveMemory (PciOrigData, PciData, PCI_COMMON_HDR_LENGTH); + + // + // Set resources to all bits on to see what type of resources + // are required. + // + + for (j=0; j < PCI_TYPE0_ADDRESSES; j++) { + PciData->u.type0.BaseAddresses[j] = 0xFFFFFFFF; + } + + PciData->u.type0.ROMBaseAddress = 0xFFFFFFFF; + + PciData->Command &= ~(PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE); + PciData->u.type0.ROMBaseAddress &= ~PCI_ROMADDRESS_ENABLED; + HalpWritePCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH); + HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH); + + // + // Build an CM_RESOURCE_LIST for the PCI device to report resources + // to IoReportResourceUsage. + // + // This code does *not* use IoAssignoResources, as the PCI + // address space resources have been previously assigned by the ARC firmware + // + + CmRes->Count = 1; + CmRes->List[0].InterfaceType = PCIBus; + CmRes->List[0].BusNumber = BusNumber; + + CmRes->List[0].PartialResourceList.Count = 0; + + // + // Set current CM_RESOURCE_LIST version and revision + // + + CmRes->List[0].PartialResourceList.Version = 0; + CmRes->List[0].PartialResourceList.Revision = 0; + + CmDesc = CmRes->List[0].PartialResourceList.PartialDescriptors; + +#if DBG + DbgPrint ("HalAssignSlotResources: Resource List V%d.%d for slot %x:\n", + CmRes->List[0].PartialResourceList.Version, + CmRes->List[0].PartialResourceList.Revision, + Slot); + +#endif + + // + // Interrupt resource + // + + if (PciData->u.type0.InterruptPin) { + + CmDesc->Type = CmResourceTypeInterrupt; + CmDesc->ShareDisposition = CmResourceShareShared; + CmDesc->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE; + + CmDesc->u.Interrupt.Level = PciData->u.type0.InterruptLine; + CmDesc->u.Interrupt.Vector = PciData->u.type0.InterruptLine; + +#if DBG + DbgPrint (" INT Level %x, Vector %x\n", + CmDesc->u.Interrupt.Level, CmDesc->u.Interrupt.Vector ); +#endif + + CmRes->List[0].PartialResourceList.Count++; + CmDesc++; + } + + // + // Add a memory or port resoruce for each PCI resource + // (Compute the ROM address as well. Just append it to the Base + // Address table.) + // + + holdvalue = PciData->u.type0.BaseAddresses[PCI_TYPE0_ADDRESSES]; + PciData->u.type0.BaseAddresses[PCI_TYPE0_ADDRESSES] = + PciData->u.type0.ROMBaseAddress & ~PCI_ADDRESS_IO_SPACE; + + Command = PciOrigData->Command; + for (j=0; j < PCI_TYPE0_ADDRESSES + 1; j++) { + if (PciData->u.type0.BaseAddresses[j]) { + addr = i = PciData->u.type0.BaseAddresses[j]; + + // + // calculate the length necessary - note there is more complicated + // code in the x86 HAL that probably isn't necessary + // + + length = ~(i & ~((i & 1) ? 3 : 15)) + 1; + + // + // I/O space resource + // + + if (addr & PCI_ADDRESS_IO_SPACE) { + + CmDesc->Type = CmResourceTypePort; + CmDesc->ShareDisposition = CmResourceShareDeviceExclusive; + CmDesc->Flags = CM_RESOURCE_PORT_IO; + + BAddr.LowPart = PciOrigData->u.type0.BaseAddresses[j] & ~3; + BAddr.HighPart = 0; + +#if DBG + HalpValidPCIAddr(BusHandler, BAddr, length, 1); // I/O space +#endif + + CmDesc->u.Port.Start = BAddr; + CmDesc->u.Port.Length = length; + Command |= PCI_ENABLE_IO_SPACE; +#if DBG + DbgPrint (" IO Start %x:%08x, Len %x\n", + CmDesc->u.Port.Start.HighPart, CmDesc->u.Port.Start.LowPart, + CmDesc->u.Port.Length ); +#endif + // + // Memory space resource + // + + } else { + + CmDesc->Type = CmResourceTypeMemory; + CmDesc->ShareDisposition = CmResourceShareDeviceExclusive; + + if (j == PCI_TYPE0_ADDRESSES) { + // this is a ROM address + if ((PciOrigData->u.type0.ROMBaseAddress & PCI_ROMADDRESS_ENABLED) == 0) { + // + // Ignore expansion ROMs which are not enabled by + // the firmware/ROM BIOS. + // + + continue; + } + CmDesc->Flags = CM_RESOURCE_MEMORY_READ_ONLY; + BAddr.LowPart = PciOrigData->u.type0.ROMBaseAddress & + ~PCI_ROMADDRESS_ENABLED; + BAddr.HighPart = 0; + } else { + // this is a memory space base address + CmDesc->Flags = CM_RESOURCE_MEMORY_READ_WRITE; + BAddr.LowPart = PciOrigData->u.type0.BaseAddresses[j] & ~15; + BAddr.HighPart = 0; + } + +#if DBG + HalpValidPCIAddr(BusHandler, BAddr, length, 0); // Memory space +#endif + + CmDesc->u.Memory.Start = BAddr; + CmDesc->u.Memory.Length = length; + Command |= PCI_ENABLE_MEMORY_SPACE; +#if DBG + DbgPrint (" MEM Start %x:%08x, Len %x\n", + CmDesc->u.Memory.Start.HighPart, CmDesc->u.Memory.Start.LowPart, + CmDesc->u.Memory.Length ); +#endif + } + + CmRes->List[0].PartialResourceList.Count++; + CmDesc++; + + if (Is64BitBaseAddress(addr)) { + // skip upper half of 64 bit address since we + // only supports 32 bits PCI addresses for now. + j++; + } + } + } + + // + // Setup the resource list. + // Count only the acquired resources. + // + + *pAllocatedResources = CmRes; + cnt = CmRes->List[0].PartialResourceList.Count; + len = sizeof (CM_RESOURCE_LIST) + + cnt * sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR); + +#if DBG + DbgPrint("HalAssignSlotResources: Acq. Resourses = %d (len %x list %x\n)", + cnt, len, *pAllocatedResources); +#endif + + // + // Report the IO resource assignments + // + + if (!DeviceObject) { + status = IoReportResourceUsage ( + DriverClassName, + DriverObject, // DriverObject + *pAllocatedResources, // DriverList + len, // DriverListSize + DeviceObject, // DeviceObject + NULL, // DeviceList + 0, // DeviceListSize + FALSE, // override conflict + &conflict // conflicted detected + ); + } else { + status = IoReportResourceUsage ( + DriverClassName, + DriverObject, // DriverObject + NULL, // DriverList + 0, // DriverListSize + DeviceObject, + *pAllocatedResources, // DeviceList + len, // DeviceListSize + FALSE, // override conflict + &conflict // conflicted detected + ); + } + + if (NT_SUCCESS(status) && conflict) { + + // + // IopReportResourceUsage saw a conflict? + // + +#if DBG + DbgPrint("HalAssignSlotResources: IoAssignResources detected a conflict: %x\n", + status); +#endif + status = STATUS_CONFLICTING_ADDRESSES; + goto CleanUp; + } + + if (!NT_SUCCESS(status)) { +#if DBG + DbgPrint("HalAssignSlotResources: IoAssignResources failed: %x\n", status); +#endif + goto CleanUp; + } + + // + // Restore orginial data, turning on the appropiate decodes + // + +#if DBG + DbgPrint ("HalAssignSlotResources: IoReportResourseUsage succeeded\n"); +#endif + + // enable IO & Memory decodes + + PciOrigData->Command |= (USHORT) Command; + + HalpWritePCIConfig ( + BusHandler, + PciSlot, + PciOrigData, + 0, + PCI_COMMON_HDR_LENGTH + ); + +#if DBG + DbgPrint ("HalAssignSlotResources: PCI Config Space updated with Command = %x\n", + Command); +#endif + +CleanUp: + if (!NT_SUCCESS(status)) { + + // + // Failure, if there are any allocated resources free them + // + + i = 0; + if (*pAllocatedResources) { + + if (!DeviceObject) { + status = IoReportResourceUsage ( + DriverClassName, + DriverObject, // DriverObject + (PCM_RESOURCE_LIST) &i, // DriverList + sizeof (i), // DriverListSize + DeviceObject, + NULL, // DeviceList + 0, // DeviceListSize + FALSE, // override conflict + &conflict // conflicted detected + ); + } else { + status = IoReportResourceUsage ( + DriverClassName, + DriverObject, // DriverObject + NULL, // DriverList + 0, // DriverListSize + DeviceObject, + (PCM_RESOURCE_LIST) &i, // DeviceList + sizeof (i), // DeviceListSize + FALSE, // override conflict + &conflict // conflicted detected + ); + } + + ExFreePool (*pAllocatedResources); + *pAllocatedResources = NULL; + } + + // + // Restore the device settings as we found them, enable memory + // and io decode after setting base addresses + // + + HalpWritePCIConfig ( + BusHandler, + PciSlot, + PciOrigData, + FIELD_OFFSET (PCI_COMMON_CONFIG, Status), + PCI_COMMON_HDR_LENGTH - FIELD_OFFSET (PCI_COMMON_CONFIG, Status) + ); + + HalpWritePCIConfig ( + BusHandler, + PciSlot, + PciOrigData, + 0, + FIELD_OFFSET (PCI_COMMON_CONFIG, Status) + ); + } + + return status; +} + + +NTSTATUS +HalpAdjustPCIResourceList ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList + ) +/*++ + +Routine Description: + + The function adjusts a PCI pResourceList and forces it to match the + pre-configured values in PCI configuration space for this device. + +Arguments: + + BusHandler - Registered BUSHANDLER for the target configuration space + + RootHandler - Register BUSHANDLER for the orginating HalAdjustResourceList request. + + pResourceList - Supplies the PIO_RESOURCE_REQUIREMENTS_LIST to be checked. + +Return Value: + + STATUS_SUCCESS + +--*/ +{ + UCHAR buffer[PCI_COMMON_HDR_LENGTH]; + PCI_SLOT_NUMBER PciSlot; + PPCI_COMMON_CONFIG PciData; + PIO_RESOURCE_REQUIREMENTS_LIST CompleteList; + PIO_RESOURCE_LIST ResourceList; + PIO_RESOURCE_DESCRIPTOR Descriptor; + ULONG alt, cnt, bcnt; + ULONG MemoryBaseAddress, RomIndex; + PULONG BaseAddress[PCI_TYPE0_ADDRESSES + 1]; + + // + // Fix any requested resources for this device to be the + // value set in PCI configuration space for this device. + // + + // + // Get PCI common configuration space for this slot + // + + PciSlot = *((PPCI_SLOT_NUMBER) &(*pResourceList)->SlotNumber), + PciData = (PPCI_COMMON_CONFIG) buffer; + + HalGetBusData ( + PCIConfiguration, + BusHandler->BusNumber, + PciSlot.u.AsULONG, + PciData, + PCI_COMMON_HDR_LENGTH + ); + + if (PciData->VendorID == PCI_INVALID_VENDORID || + PCI_CONFIG_TYPE (PciData) != 0) { + return STATUS_UNSUCCESSFUL; + } + + // + // Copy base addresses based on configuration data type + // + + switch (PCI_CONFIG_TYPE(PciData)) { + case 0 : + for (bcnt=0; bcnt < PCI_TYPE0_ADDRESSES; bcnt++) { + BaseAddress[bcnt] = &PciData->u.type0.BaseAddresses[bcnt]; + } + BaseAddress[bcnt] = &PciData->u.type0.ROMBaseAddress; + RomIndex = bcnt; + break; + case 1: + for (bcnt=0; bcnt < PCI_TYPE1_ADDRESSES; bcnt++) { + BaseAddress[bcnt] = &PciData->u.type1.BaseAddresses[bcnt]; + } + BaseAddress[bcnt] = &PciData->u.type0.ROMBaseAddress; + RomIndex = bcnt; + break; + + default: + return STATUS_NO_SUCH_DEVICE; + } + + // + // Walk each ResourceList and confine resources + // to preconfigured settings. + // + + CompleteList = *pResourceList; + ResourceList = CompleteList->List; + ResourceList->Version = 1; + ResourceList->Revision = 1; + + for (alt=0; alt < CompleteList->AlternativeLists; alt++) { + Descriptor = ResourceList->Descriptors; + + // + // For each alternative list, reset to review entire + // set of Base Address registers + // + // We assume that the order of resource descriptors for + // each alternative list matches the order of the + // PCI configuration space base address registers + // + + bcnt = 0; + + for (cnt = ResourceList->Count; cnt; cnt--) { + + // + // Limit desctiptor to to preconfigured setting + // held in the InterruptLine register. + // + + switch (Descriptor->Type) { + case CmResourceTypeInterrupt: + + // + // Confine interrupt vector to preconfigured setting. + // + + Descriptor->u.Interrupt.MinimumVector = PciData->u.type0.InterruptLine; + Descriptor->u.Interrupt.MaximumVector = PciData->u.type0.InterruptLine; + break; + + case CmResourceTypePort: + + // + // Assure that requested descriptor is valid + // + + if (bcnt > RomIndex) { + return STATUS_INVALID_PARAMETER; + } + + // + // Confine to preconfigured setting. + // + + Descriptor->u.Port.MinimumAddress.QuadPart = + *BaseAddress[bcnt++] & ~0x3; + + Descriptor->u.Port.MaximumAddress.QuadPart = + Descriptor->u.Port.MinimumAddress.QuadPart + + Descriptor->u.Port.Length - 1; + +#if HALDBG + DbgPrint("AdjustPCIResourceList\nPort: MinimumAddress set to %x\n", + Descriptor->u.Port.MinimumAddress.QuadPart); + + DbgPrint(" MaximumAddress set to %x\n", + Descriptor->u.Port.MaximumAddress.QuadPart); +#endif + + break; + + case CmResourceTypeMemory: + + // + // Assure that requested descriptor is valid + // + + if (bcnt > RomIndex) { + return STATUS_INVALID_PARAMETER; + } + + // + // Confine to preconfigured setting. + // + + MemoryBaseAddress = *BaseAddress[bcnt]; + + if (bcnt == RomIndex) { + Descriptor->u.Memory.MinimumAddress.QuadPart = + *BaseAddress[bcnt++] & ~PCI_ROMADDRESS_ENABLED; + } else { + Descriptor->u.Memory.MinimumAddress.QuadPart = + *BaseAddress[bcnt++] & ~0xF; + } + + Descriptor->u.Memory.MaximumAddress.QuadPart = + Descriptor->u.Memory.MinimumAddress.QuadPart + + Descriptor->u.Memory.Length - 1; + + if (Is64BitBaseAddress(MemoryBaseAddress)) { + // skip upper half of 64 bit address since we + // only supports 32 bits PCI addresses for now. + bcnt++; + } + + +#if HALDBG + DbgPrint("AdjustPCIResourceList\nMemory: MinimumAddress set to %x\n", + Descriptor->u.Memory.MinimumAddress.QuadPart); + + DbgPrint(" MaximumAddress set to %x\n", + Descriptor->u.Memory.MaximumAddress.QuadPart); +#endif + break; + + case CmResourceTypeDma: + break; + + default: + return STATUS_INVALID_PARAMETER; + } + + // + // Next descriptor + // + Descriptor++; + } + + // + // Next Resource List + // + ResourceList = (PIO_RESOURCE_LIST) Descriptor; + } + return STATUS_SUCCESS; +} + +#define TEST_PCI 1 + +#if DBG && TEST_PCI + +VOID HalpTestPci (ULONG flag2) +{ + PCI_SLOT_NUMBER SlotNumber; + PCI_COMMON_CONFIG PciData, OrigData; + ULONG i, f, j, k, bus; + BOOLEAN flag; + + if (!flag2) { + return ; + } + + DbgBreakPoint (); + SlotNumber.u.bits.Reserved = 0; + + // + // Read every possible PCI Device/Function and display it's + // default info. + // + // (note this destories it's current settings) + // + + flag = TRUE; + for (bus = 0; flag; bus++) { + + for (i = 0; i < 32; i++) { + SlotNumber.u.bits.DeviceNumber = i; + + for (f = 0; f < 8; f++) { + SlotNumber.u.bits.FunctionNumber = f; + + + j = HalGetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + sizeof (PciData) + ); + + if (j == 0) { + // out of buses + flag = FALSE; + break; + } + + if (j < PCI_COMMON_HDR_LENGTH) { + continue; + } + + HalSetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + 1 + ); + + HalGetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + sizeof (PciData) + ); + + memcpy (&OrigData, &PciData, sizeof PciData); + + for (j=0; j < PCI_TYPE0_ADDRESSES; j++) { + PciData.u.type0.BaseAddresses[j] = 0xFFFFFFFF; + } + + PciData.u.type0.ROMBaseAddress = 0xFFFFFFFF; + + HalSetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + sizeof (PciData) + ); + + HalGetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + sizeof (PciData) + ); + + DbgPrint ("PCI Bus %d Slot %2d %2d ID:%04lx-%04lx Rev:%04lx", + bus, i, f, PciData.VendorID, PciData.DeviceID, + PciData.RevisionID); + + if (PciData.u.type0.InterruptPin) { + DbgPrint (" IntPin:%x", PciData.u.type0.InterruptPin); + } + + if (PciData.u.type0.InterruptLine) { + DbgPrint (" IntLine:%x", PciData.u.type0.InterruptLine); + } + + if (PciData.u.type0.ROMBaseAddress) { + DbgPrint (" ROM:%08lx", PciData.u.type0.ROMBaseAddress); + } + + DbgPrint ("\n ProgIf:%04x SubClass:%04x BaseClass:%04lx\n", + PciData.ProgIf, PciData.SubClass, PciData.BaseClass); + + k = 0; + for (j=0; j < PCI_TYPE0_ADDRESSES; j++) { + if (PciData.u.type0.BaseAddresses[j]) { + DbgPrint (" Ad%d:%08lx", j, PciData.u.type0.BaseAddresses[j]); + k = 1; + } + } + + if (PciData.u.type0.ROMBaseAddress == 0xC08001) { + + PciData.u.type0.ROMBaseAddress = 0xC00001; + HalSetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + sizeof (PciData) + ); + + HalGetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + sizeof (PciData) + ); + + DbgPrint ("\n Bogus rom address, edit yields:%08lx", + PciData.u.type0.ROMBaseAddress); + } + if (k) { + DbgPrint ("\n"); + } + + if (PciData.VendorID == 0x8086) { + // dump complete buffer + DbgPrint ("Command %x, Status %x, BIST %x\n", + PciData.Command, PciData.Status, + PciData.BIST + ); + + DbgPrint ("CacheLineSz %x, LatencyTimer %x", + PciData.CacheLineSize, PciData.LatencyTimer + ); + + for (j=0; j < 192; j++) { + if ((j & 0xf) == 0) { + DbgPrint ("\n%02x: ", j + 0x40); + } + DbgPrint ("%02x ", PciData.DeviceSpecific[j]); + } + DbgPrint ("\n"); + } + + // + // now print original data + // + + if (OrigData.u.type0.ROMBaseAddress) { + DbgPrint (" oROM:%08lx", OrigData.u.type0.ROMBaseAddress); + } + + DbgPrint ("\n"); + k = 0; + for (j=0; j < PCI_TYPE0_ADDRESSES; j++) { + if (OrigData.u.type0.BaseAddresses[j]) { + DbgPrint (" oAd%d:%08lx", j, OrigData.u.type0.BaseAddresses[j]); + k = 1; + } + } + + // + // Restore original settings + // + + HalSetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &OrigData, + sizeof (PciData) + ); + + // + // Next + // + + if (k) { + DbgPrint ("\n\n"); + } + } + } + + } + DbgBreakPoint(); +} + +#endif // DBG && TEST_PCI diff --git a/private/ntos/nthals/halflex/xxport.c b/private/ntos/nthals/halflex/xxport.c new file mode 100644 index 000000000..3d0770236 --- /dev/null +++ b/private/ntos/nthals/halflex/xxport.c @@ -0,0 +1,769 @@ +/*++ + +Copyright (c) 1991-1993 Microsoft Corporation + +Module Name: + + jxport.c + +Abstract: + + This module implements the code that provides communication between + the kernel debugger on a MIPS R3000 or R4000 Jazz system and the host + system. + +Environment: + + Kernel mode + +Revision History: + +--*/ + +#include "halp.h" +#include "jazzserp.h" + +VOID +HalpGetDivisorFromBaud( + IN ULONG ClockRate, + IN LONG DesiredBaud, + OUT PSHORT AppropriateDivisor + ); + + +#pragma alloc_text(INIT,HalpGetDivisorFromBaud) + + +// +// BUGBUG Temporarily, we use counter to do the timeout +// + +#define TIMEOUT_COUNT 1024*512 + +// +// BUGBUG Temp until we have a configuration manager. +// + +PUCHAR KdComPortInUse = NULL; +BOOLEAN KdUseModemControl = FALSE; + +// +// Define serial port read and write addresses. +// + +PSP_READ_REGISTERS SP_READ; +PSP_WRITE_REGISTERS SP_WRITE; + +// +// Define forward referenced prototypes. +// + +SP_LINE_STATUS +KdReadLsr ( + IN BOOLEAN WaitReason + ); + +// +// Define baud rate divisor to be used on the debugger port. +// + +SHORT HalpBaudRateDivisor = 6; + + +ULONG +HalpGetByte ( + IN PCHAR Input, + IN BOOLEAN Wait + ) + +/*++ + +Routine Description: + + This routine gets a byte from the serial port used by the kernel + debugger. + +Arguments: + + Input - Supplies a pointer to a variable that receives the input + data byte. + + Wait - Supplies a boolean value that detemines whether a timeout + is applied to the input operation. + +Return Value: + + CP_GET_SUCCESS is returned if a byte is successfully read from the + kernel debugger line. + + CP_GET_ERROR is returned if an error is encountered during reading. + + CP_GET_NODATA is returned if timeout occurs. + +--*/ + +{ + + SP_LINE_STATUS LsrByte; + UCHAR DataByte; + ULONG TimeoutCount; + + // + // Attempt to read a byte from the debugger port until a byte is + // available or until a timeout occurs. + // + + TimeoutCount = Wait ? TIMEOUT_COUNT : 1; + do { + TimeoutCount -= 1; + + // + // Wait until data is available in the receive buffer. + // + + KeStallExecutionProcessor(1); + LsrByte = KdReadLsr(TRUE); + if (LsrByte.DataReady == 0) { + continue; + } + + // + // Read input byte and store in callers buffer. + // + + *Input = READ_REGISTER_UCHAR(&SP_READ->ReceiveBuffer); + + // + // If using modem controls, then skip any incoming data while + // ReceiveData not set. + // + + if (KdUseModemControl) { + DataByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus); + if ( ((PSP_MODEM_STATUS)&DataByte)->ReceiveDetect == 0) { + continue; + } + } + + // + // Return function value as the not of the error indicators. + // + + if (LsrByte.ParityError || + LsrByte.FramingError || + LsrByte.OverrunError || + LsrByte.BreakIndicator) { + return CP_GET_ERROR; + } + + return CP_GET_SUCCESS; + } while(TimeoutCount != 0); + + return CP_GET_NODATA; +} + +BOOLEAN +KdPortInitialize ( + PDEBUG_PARAMETERS DebugParameters, + PLOADER_PARAMETER_BLOCK LoaderBlock, + BOOLEAN Initialize + ) + +/*++ + +Routine Description: + + This routine initializes the serial port used by the kernel debugger + and must be called during system initialization. + +Arguments: + + DebugParameter - Supplies a pointer to the debug port parameters. + + LoaderBlock - Supplies a pointer to the loader parameter block. + + Initialize - Specifies a boolean value that determines whether the + debug port is initialized or just the debug port parameters + are captured. + +Return Value: + + A value of TRUE is returned is the port was successfully initialized. + Otherwise, a value of FALSE is returned. + +--*/ + +{ + + PCONFIGURATION_COMPONENT_DATA ConfigurationEntry; + UCHAR DataByte; + PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor; + PCM_SERIAL_DEVICE_DATA DeviceData; + PCM_PARTIAL_RESOURCE_LIST List; + ULONG MatchKey; + ULONG BaudRate; + ULONG BaudClock; + + // + // Find the configuration information for the first serial port. + // + + if (LoaderBlock != NULL) { + MatchKey = 0; + ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot, + ControllerClass, + SerialController, + &MatchKey); + + } else { + ConfigurationEntry = NULL; + } + + if (DebugParameters->BaudRate != 0) { + BaudRate = DebugParameters->BaudRate; + } else { + BaudRate = 19200; + } + + // + // If the serial configuration entry was not found or the frequency + // specified is not supported, then default the baud clock to 1843200. + // + + BaudClock = 1843200; + + if (ConfigurationEntry != NULL) { + List = (PCM_PARTIAL_RESOURCE_LIST)ConfigurationEntry->ConfigurationData; + Descriptor = &List->PartialDescriptors[List->Count]; + DeviceData = (PCM_SERIAL_DEVICE_DATA)Descriptor; + if ((DeviceData->BaudClock == 1843200) || + (DeviceData->BaudClock == 4233600) || + (DeviceData->BaudClock == 8000000)) { + BaudClock = DeviceData->BaudClock; + } + } + + HalpGetDivisorFromBaud( + BaudClock, + BaudRate, + &HalpBaudRateDivisor + ); + + // + // If the debugger is not being enabled, then return. + // + + if (Initialize == FALSE) { + return TRUE; + } + + KdComPortInUse = HalpAllocateKdPortResources(&SP_READ,&SP_WRITE); + + // + // Clear the divisor latch, clear all interrupt enables, and reset and + // disable the FIFO's. + // + + WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, 0x0); + WRITE_REGISTER_UCHAR(&SP_WRITE->InterruptEnable, 0x0); + DataByte = 0; + ((PSP_FIFO_CONTROL)(&DataByte))->ReceiveFifoReset = 1; + ((PSP_FIFO_CONTROL)(&DataByte))->TransmitFifoReset = 1; + WRITE_REGISTER_UCHAR(&SP_WRITE->FifoControl, DataByte); + + // + // Set the divisor latch and set the baud rate to 19200 baud. + // + ((PSP_LINE_CONTROL)(&DataByte))->DivisorLatch = 1; + WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, DataByte); + WRITE_REGISTER_UCHAR(&SP_WRITE->TransmitBuffer, (UCHAR)(HalpBaudRateDivisor&0xff)); + WRITE_REGISTER_UCHAR(&SP_WRITE->InterruptEnable, (UCHAR)(HalpBaudRateDivisor>>8)); + + // + // Clear the divisor latch and set the character size to eight bits + // with one stop bit and no parity checking. + // + + DataByte = 0; + ((PSP_LINE_CONTROL)(&DataByte))->CharacterSize = EIGHT_BITS; + WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, DataByte); + + // + // Set data terminal ready and request to send. + // + + DataByte = 0; + ((PSP_MODEM_CONTROL)(&DataByte))->DataTerminalReady = 1; + ((PSP_MODEM_CONTROL)(&DataByte))->RequestToSend = 1; + WRITE_REGISTER_UCHAR(&SP_WRITE->ModemControl, DataByte); + + HalpFreeKdPortResources(); + + return TRUE; +} + +ULONG +KdPortGetByte ( + OUT PUCHAR Input + ) + +/*++ + +Routine Description: + + This routine gets a byte from the serial port used by the kernel + debugger. + + N.B. It is assumed that the IRQL has been raised to the highest + level, and necessary multiprocessor synchronization has been + performed before this routine is called. + +Arguments: + + Input - Supplies a pointer to a variable that receives the input + data byte. + +Return Value: + + CP_GET_SUCCESS is returned if a byte is successfully read from the + kernel debugger line. + + CP_GET_ERROR is returned if an error is encountered during reading. + + CP_GET_NODATA is returned if timeout occurs. + +--*/ + +{ + return HalpGetByte(Input, TRUE); +} + +ULONG +KdPortPollByte ( + OUT PUCHAR Input + ) + +/*++ + +Routine Description: + + This routine gets a byte from the serial port used by the kernel + debugger iff a byte is available. + + N.B. It is assumed that the IRQL has been raised to the highest + level, and necessary multiprocessor synchronization has been + performed before this routine is called. + +Arguments: + + Input - Supplies a pointer to a variable that receives the input + data byte. + +Return Value: + + CP_GET_SUCCESS is returned if a byte is successfully read from the + kernel debugger line. + + CP_GET_ERROR is returned if an error encountered during reading. + + CP_GET_NODATA is returned if timeout occurs. + +--*/ + +{ + + ULONG Status; + + // + // Save port status, map the serial controller, get byte from the + // debugger port is one is avaliable, restore port status, unmap + // the serial controller, and return the operation status. + // + + KdPortSave(); + Status = HalpGetByte(Input, FALSE); + KdPortRestore(); + return Status; +} + +VOID +KdPortPutByte ( + IN UCHAR Output + ) + +/*++ + +Routine Description: + + This routine puts a byte to the serial port used by the kernel debugger. + + N.B. It is assumed that the IRQL has been raised to the highest level, + and necessary multiprocessor synchronization has been performed + before this routine is called. + +Arguments: + + Output - Supplies the output data byte. + +Return Value: + + None. + +--*/ + +{ + + UCHAR DataByte; + + if (KdUseModemControl) { + // + // Modem control, make sure DSR, CTS and CD are all set before + // sending any data. + // + + for (; ;) { + DataByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus); + if ( ((PSP_MODEM_STATUS)&DataByte)->ClearToSend && + ((PSP_MODEM_STATUS)&DataByte)->DataSetReady && + ((PSP_MODEM_STATUS)&DataByte)->ReceiveDetect ) { + break; + } + + KdReadLsr(FALSE); + } + } + + // + // Wait for transmit ready. + // + + while (KdReadLsr(FALSE).TransmitHoldingEmpty == 0 ); + + // + // Wait for data set ready. + // + +// do { +// LsrByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus); +// } while (((PSP_MODEM_STATUS)(&LsrByte))->DataSetReady == 0); + + // + // Transmit data. + // + + WRITE_REGISTER_UCHAR(&SP_WRITE->TransmitBuffer, Output); + return; +} + +VOID +KdPortRestore ( + VOID + ) + +/*++ + +Routine Description: + + This routine restores the state of the serial port after the kernel + debugger has been active. + + N.B. This routine performs no function on the Jazz system. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + HalpFreeKdPortResources(); + return; +} + +VOID +KdPortSave ( + VOID + ) + +/*++ + +Routine Description: + + This routine saves the state of the serial port and initializes the port + for use by the kernel debugger. + + N.B. This routine performs no function on the Jazz system. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + HalpAllocateKdPortResources(&SP_READ,&SP_WRITE); + return; +} + +SP_LINE_STATUS +KdReadLsr ( + IN BOOLEAN WaitReason + ) + +/*++ + +Routine Description: + + Returns current line status. + + If status which is being waited for is ready, then the function + checks the current modem status and causes a possible display update + of the current statuses. + +Arguments: + + WaitReason - Suuplies a boolean value that determines whether the line + status is required for a receive or transmit. + +Return Value: + + The current line status is returned as the function value. + +--*/ + +{ + + static UCHAR RingFlag = 0; + UCHAR DataLsr, DataMsr; + + // + // Get the line status for a recevie or a transmit. + // + + DataLsr = READ_REGISTER_UCHAR(&SP_READ->LineStatus); + if (WaitReason) { + + // + // Get line status for receive data. + // + + if (((PSP_LINE_STATUS)&DataLsr)->DataReady) { + return *((PSP_LINE_STATUS)&DataLsr); + } + + } else { + + // + // Get line status for transmit empty. + // + + if (((PSP_LINE_STATUS)&DataLsr)->TransmitEmpty) { + return *((PSP_LINE_STATUS)&DataLsr); + } + } + + DataMsr = READ_REGISTER_UCHAR(&SP_READ->ModemStatus); + RingFlag |= ((PSP_MODEM_STATUS)&DataMsr)->RingIndicator ? 1 : 2; + if (RingFlag == 3) { + + // + // The ring indicate line has toggled, use modem control from + // now on. + // + + KdUseModemControl = TRUE; + } + + return *((PSP_LINE_STATUS) &DataLsr); +} + +VOID +HalpGetDivisorFromBaud( + IN ULONG ClockRate, + IN LONG DesiredBaud, + OUT PSHORT AppropriateDivisor + ) + +/*++ + +Routine Description: + + This routine will determine a divisor based on an unvalidated + baud rate. + +Arguments: + + ClockRate - The clock input to the controller. + + DesiredBaud - The baud rate for whose divisor we seek. + + AppropriateDivisor - Given that the DesiredBaud is valid, the + SHORT pointed to by this parameter will be set to the appropriate + value. If the requested baud rate is unsupportable on the machine + return a divisor appropriate for 19200. + +Return Value: + + none. + +--*/ + +{ + + SHORT calculatedDivisor; + ULONG denominator; + ULONG remainder; + + // + // Allow up to a 1 percent error + // + + ULONG maxRemain18 = 18432; + ULONG maxRemain30 = 30720; + ULONG maxRemain42 = 42336; + ULONG maxRemain80 = 80000; + ULONG maxRemain; + + // + // Reject any non-positive bauds. + // + + denominator = DesiredBaud*(ULONG)16; + + if (DesiredBaud <= 0) { + + *AppropriateDivisor = -1; + + } else if ((LONG)denominator < DesiredBaud) { + + // + // If the desired baud was so huge that it cause the denominator + // calculation to wrap, don't support it. + // + + *AppropriateDivisor = -1; + + } else { + + if (ClockRate == 1843200) { + maxRemain = maxRemain18; + } else if (ClockRate == 3072000) { + maxRemain = maxRemain30; + } else if (ClockRate == 4233600) { + maxRemain = maxRemain42; + } else { + maxRemain = maxRemain80; + } + + calculatedDivisor = (SHORT)(ClockRate / denominator); + remainder = ClockRate % denominator; + + // + // Round up. + // + + if (((remainder*2) > ClockRate) && (DesiredBaud != 110)) { + + calculatedDivisor++; + } + + + // + // Only let the remainder calculations effect us if + // the baud rate is > 9600. + // + + if (DesiredBaud >= 9600) { + + // + // If the remainder is less than the maximum remainder (wrt + // the ClockRate) or the remainder + the maximum remainder is + // greater than or equal to the ClockRate then assume that the + // baud is ok. + // + + if ((remainder >= maxRemain) && ((remainder+maxRemain) < ClockRate)) { + calculatedDivisor = -1; + } + + } + + // + // Don't support a baud that causes the denominator to + // be larger than the clock. + // + + if (denominator > ClockRate) { + + calculatedDivisor = -1; + + } + + // + // Ok, Now do some special casing so that things can actually continue + // working on all platforms. + // + + if (ClockRate == 1843200) { + + if (DesiredBaud == 56000) { + calculatedDivisor = 2; + } + + } else if (ClockRate == 3072000) { + + if (DesiredBaud == 14400) { + calculatedDivisor = 13; + } + + } else if (ClockRate == 4233600) { + + if (DesiredBaud == 9600) { + calculatedDivisor = 28; + } else if (DesiredBaud == 14400) { + calculatedDivisor = 18; + } else if (DesiredBaud == 19200) { + calculatedDivisor = 14; + } else if (DesiredBaud == 38400) { + calculatedDivisor = 7; + } else if (DesiredBaud == 56000) { + calculatedDivisor = 5; + } + + } else if (ClockRate == 8000000) { + + if (DesiredBaud == 14400) { + calculatedDivisor = 35; + } else if (DesiredBaud == 56000) { + calculatedDivisor = 9; + } + + } + + *AppropriateDivisor = calculatedDivisor; + + } + + + if (*AppropriateDivisor == -1) { + + HalpGetDivisorFromBaud( + ClockRate, + 19200, + AppropriateDivisor + ); + + } + + +} + + diff --git a/private/ntos/nthals/halflex/xxreturn.c b/private/ntos/nthals/halflex/xxreturn.c new file mode 100644 index 000000000..bbd381e12 --- /dev/null +++ b/private/ntos/nthals/halflex/xxreturn.c @@ -0,0 +1,101 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + jxreturn.c + +Abstract: + + This module implements the HAL return to firmware function. + +Author: + + David N. Cutler (davec) 21-Aug-1991 + +Revision History: + +--*/ + +#include "halp.h" + +VOID +HalReturnToFirmware( + IN FIRMWARE_REENTRY Routine + ) + +/*++ + +Routine Description: + + This function returns control to the specified firmware routine. + In most cases it generates a soft reset by asserting the reset line + trough the keyboard controller. + The Keyboard controller is mapped using the same virtual address + and the same fixed entry as the DMA. + +Arguments: + + Routine - Supplies a value indicating which firmware routine to invoke. + +Return Value: + + Does not return. + +--*/ + +{ + KIRQL OldIrql; + + // + // Case on the type of return. + // + + switch (Routine) { + case HalHaltRoutine: + + // + // Disable Interrupts. + // + + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + + // + // Hang looping. + // + for (;;) { + } + + case HalPowerDownRoutine: + case HalRestartRoutine: + case HalRebootRoutine: + case HalInteractiveModeRoutine: + + if (HalpResetDisplayParameters != NULL) { + (HalpResetDisplayParameters)(80,25); + } + + HalpResetX86DisplayAdapter(); + + // + // Disable Interrupts. + // + + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + + HalpAllocateArcsResources(); + ArcReboot(); + + // + // Should never get here... + // + + for (;;) { + } + + default: + KdPrint(("HalReturnToFirmware invalid argument\n")); + DbgBreakPoint(); + } +} diff --git a/private/ntos/nthals/halflex/xxsysint.c b/private/ntos/nthals/halflex/xxsysint.c new file mode 100644 index 000000000..4f3e00a44 --- /dev/null +++ b/private/ntos/nthals/halflex/xxsysint.c @@ -0,0 +1,217 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + jxsysint.c + +Abstract: + + This module implements the HAL enable/disable system interrupt, and + request interprocessor interrupt routines for a MIPS R3000 or R4000 + Jazz system. + +Author: + + David N. Cutler (davec) 6-May-1991 + Michael D. Kinney 2-May-1995 + +Environment: + + Kernel mode + +Revision History: + +--*/ + +#include "halp.h" + +VOID +HalDisableSystemInterrupt ( + IN ULONG Vector, + IN KIRQL Irql + ) + +/*++ + +Routine Description: + + This routine disables the specified system interrupt. + +Arguments: + + Vector - Supplies the vector of the system interrupt that is disabled. + + Irql - Supplies the IRQL of the interrupting source. + +Return Value: + + None. + +--*/ + +{ + + KIRQL OldIrql; + + // + // Raise IRQL to the highest level. + // + + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + + // + // If the vector number is within the range of the EISA interrupts, then + // disable the EISA interrrupt. + // + + if (Vector >= UNIFLEX_EISA_VECTORS && + Vector <= (UNIFLEX_MAXIMUM_EISA_VECTOR) && + Irql == UNIFLEX_EISA_DEVICE_LEVEL) { + HalpDisableEisaInterrupt(Vector); + } + + if (Vector >= UNIFLEX_EISA1_VECTORS && + Vector <= (UNIFLEX_MAXIMUM_EISA1_VECTOR) && + Irql == UNIFLEX_EISA_DEVICE_LEVEL) { + HalpDisableEisaInterrupt(Vector); + } + + // + // If the vector number is within the range of the PCI interrupts, then + // disable the PCI interrrupt. + // + + if (Vector >= UNIFLEX_PCI_VECTORS && + Vector <= (UNIFLEX_MAXIMUM_PCI_VECTOR) && + Irql == UNIFLEX_PCI_DEVICE_LEVEL) { + HalpDisablePciInterrupt(Vector); + } + + // + // Call platform specific routine + // + + HalpDisablePlatformInterrupt(Vector,Irql); + + // + // Lower IRQL to the previous level. + // + + KeLowerIrql(OldIrql); + return; +} + +BOOLEAN +HalEnableSystemInterrupt ( + IN ULONG Vector, + IN KIRQL Irql, + IN KINTERRUPT_MODE InterruptMode + ) + +/*++ + +Routine Description: + + This routine enables the specified system interrupt. + +Arguments: + + Vector - Supplies the vector of the system interrupt that is enabled. + + Irql - Supplies the IRQL of the interrupting source. + + InterruptMode - Supplies the mode of the interrupt; LevelSensitive or + Latched. + +Return Value: + + TRUE if the system interrupt was enabled + +--*/ + +{ + + KIRQL OldIrql; + BOOLEAN Enabled = FALSE; + + // + // Raise IRQL to the highest level. + // + + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + + // + // If the vector number is within the range of the EISA interrupts, then + // enable the EISA interrrupt and set the Level/Edge register. + // + + if (Vector >= UNIFLEX_EISA_VECTORS && + Vector <= (UNIFLEX_MAXIMUM_EISA_VECTOR) && + Irql == UNIFLEX_EISA_DEVICE_LEVEL) { + HalpEnableEisaInterrupt( Vector, InterruptMode); + Enabled = TRUE; + } + + if (Vector >= UNIFLEX_EISA1_VECTORS && + Vector <= (UNIFLEX_MAXIMUM_EISA1_VECTOR) && + Irql == UNIFLEX_EISA_DEVICE_LEVEL) { + HalpEnableEisaInterrupt( Vector, InterruptMode); + Enabled = TRUE; + } + + // + // If the vector number is within the range of the PCI interrupts, then + // enable the PCI interrrupt. + // + + if (Vector >= UNIFLEX_PCI_VECTORS && + Vector <= (UNIFLEX_MAXIMUM_PCI_VECTOR) && + Irql == UNIFLEX_PCI_DEVICE_LEVEL) { + HalpEnablePciInterrupt(Vector); + Enabled = TRUE; + } + + // + // Call platform specific routine + // + + if (!Enabled) { + Enabled = HalpEnablePlatformInterrupt(Vector,Irql,InterruptMode); + } + + // + // Lower IRQL to the previous level. + // + + KeLowerIrql(OldIrql); + return Enabled; +} + +VOID +HalRequestIpi ( + IN ULONG Mask + ) + +/*++ + +Routine Description: + + This routine requests an interprocessor interrupt on a set of processors. + +Arguments: + + Mask - Supplies the set of processors that are sent an interprocessor + interrupt. + +Return Value: + + None. + +--*/ + +{ + + return; +} diff --git a/private/ntos/nthals/halflex/xxtime.c b/private/ntos/nthals/halflex/xxtime.c new file mode 100644 index 000000000..bddec03d2 --- /dev/null +++ b/private/ntos/nthals/halflex/xxtime.c @@ -0,0 +1,285 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + jxtime.c + +Abstract: + + This module implements the HAL set/query realtime clock routines for + a MIPS R3000 or R4000 Jazz system. + +Author: + + David N. Cutler (davec) 5-May-1991 + +Environment: + + Kernel mode + +Revision History: + +--*/ + +#include "halp.h" +#include "jazzrtc.h" +#include "eisa.h" + +#define BCDToBinary(D) (10 * (((D) & 0xf0) >>4 ) + ((D) & 0x0f)) +#define BinaryToBCD(B) ((((B) & 0xff) / 10) << 4 ) | (((B) & 0xff) % 10) + +// +// Define forward referenced procedure prototypes. +// + +UCHAR +HalpReadClockRegister ( + UCHAR Register + ); + +VOID +HalpWriteClockRegister ( + UCHAR Register, + UCHAR Value + ); + +BOOLEAN HalQueryRealTimeClock (OUT PTIME_FIELDS TimeFields) + +/*++ + +Routine Description: + + This routine queries the realtime clock. + + N.B. This routine is required to provide any synchronization necessary + to query the realtime clock information. + +Arguments: + + TimeFields - Supplies a pointer to a time structure that receives + the realtime clock information. + +Return Value: + + If the power to the realtime clock has not failed, then the time + values are read from the realtime clock and a value of TRUE is + returned. Otherwise, a value of FALSE is returned. + +--*/ + +{ + + UCHAR DataByte; + KIRQL OldIrql; + + // + // If the realtime clock battery is still functioning, then read + // the realtime clock values, and return a function value of TRUE. + // Otherwise, return a function value of FALSE. + // + + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + + + DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERD); + if (((PRTC_CONTROL_REGISTER_D)(&DataByte))->ValidTime == 1) { + + // + // Wait until the realtime clock is not being updated. + // + + do { + DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERA); + } while (((PRTC_CONTROL_REGISTER_A)(&DataByte))->UpdateInProgress == 1); + + // + // Read the realtime clock values. + // + + TimeFields->Year = 1900 + (CSHORT)BCDToBinary(HalpReadClockRegister(RTC_YEAR)); + if (TimeFields->Year < 1992) + TimeFields->Year += 100; + TimeFields->Month = (CSHORT)BCDToBinary(HalpReadClockRegister(RTC_MONTH)); + TimeFields->Day = (CSHORT)BCDToBinary(HalpReadClockRegister(RTC_DAY_OF_MONTH)); + TimeFields->Weekday = (CSHORT)BCDToBinary(HalpReadClockRegister(RTC_DAY_OF_WEEK)) - 1; + TimeFields->Hour = (CSHORT)BCDToBinary(HalpReadClockRegister(RTC_HOUR)); + TimeFields->Minute = (CSHORT)BCDToBinary(HalpReadClockRegister(RTC_MINUTE)); + TimeFields->Second = (CSHORT)BCDToBinary(HalpReadClockRegister(RTC_SECOND)); + TimeFields->Milliseconds = 0; + + KeLowerIrql(OldIrql); + return TRUE; + + } else { + + KeLowerIrql(OldIrql); + return FALSE; + } +} + +BOOLEAN HalSetRealTimeClock (IN PTIME_FIELDS TimeFields) + +/*++ + +Routine Description: + + This routine sets the realtime clock. + + N.B. This routine is required to provide any synchronization necessary + to set the realtime clock information. + +Arguments: + + TimeFields - Supplies a pointer to a time structure that specifies the + realtime clock information. + +Return Value: + + If the power to the realtime clock has not failed, then the time + values are written to the realtime clock and a value of TRUE is + returned. Otherwise, a value of FALSE is returned. + +--*/ + +{ + + UCHAR DataByte; + KIRQL OldIrql; + + // + // If the realtime clock battery is still functioning, then write + // the realtime clock values, and return a function value of TRUE. + // Otherwise, return a function value of FALSE. + // + + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + + DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERD); + if (((PRTC_CONTROL_REGISTER_D)(&DataByte))->ValidTime == 1) { + + // + // Set the realtime clock control to set the time. + // + + DataByte = 0; + ((PRTC_CONTROL_REGISTER_B)(&DataByte))->DayLightSavingsEnable = 1; + ((PRTC_CONTROL_REGISTER_B)(&DataByte))->HoursFormat = 1; + ((PRTC_CONTROL_REGISTER_B)(&DataByte))->DataMode = 0; + ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SetTime = 1; + HalpWriteClockRegister(RTC_CONTROL_REGISTERB, DataByte); + + // + // Write the realtime clock values. + // + + HalpWriteClockRegister(RTC_YEAR, (UCHAR)(BinaryToBCD(TimeFields->Year - 1900))); + HalpWriteClockRegister(RTC_MONTH, (UCHAR)BinaryToBCD(TimeFields->Month)); + HalpWriteClockRegister(RTC_DAY_OF_MONTH, (UCHAR)BinaryToBCD(TimeFields->Day)); + HalpWriteClockRegister(RTC_DAY_OF_WEEK, (UCHAR)(BinaryToBCD(TimeFields->Weekday + 1))); + HalpWriteClockRegister(RTC_HOUR, (UCHAR)BinaryToBCD(TimeFields->Hour)); + HalpWriteClockRegister(RTC_MINUTE, (UCHAR)BinaryToBCD(TimeFields->Minute)); + HalpWriteClockRegister(RTC_SECOND, (UCHAR)BinaryToBCD(TimeFields->Second)); + + // + // Set the realtime clock control to update the time. + // + + ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SetTime = 0; + HalpWriteClockRegister(RTC_CONTROL_REGISTERB, DataByte); + + KeLowerIrql(OldIrql); + return TRUE; + + } else { + + KeLowerIrql(OldIrql); + return FALSE; + } +} + +UCHAR +HalpReadClockRegister ( + UCHAR Register + ) + +/*++ + +Routine Description: + + This routine reads the specified realtime clock register. + +Arguments: + + Register - Supplies the number of the register whose value is read. + +Return Value: + + The value of the register is returned as the function value. + +--*/ + +{ + // + // Insert the realtime clock register number, and write the value back + // to the EISA NMI enable register. This selects the realtime clock register + // that is read. Note this is a write only register and the EISA NMI + // is always enabled. + // + + WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase[0])->NmiEnable, + Register); + + // + // Read the realtime clock register value. + // + + return READ_REGISTER_UCHAR((PUCHAR)HalpRealTimeClockBase); +} + +VOID +HalpWriteClockRegister ( + UCHAR Register, + UCHAR Value + ) + +/*++ + +Routine Description: + + This routine writes the specified value to the specified realtime + clock register. + +Arguments: + + Register - Supplies the number of the register whose value is written. + + Value - Supplies the value that is written to the specified register. + +Return Value: + + The value of the register is returned as the function value. + +--*/ + +{ + + // + // Insert the realtime clock register number, and write the value back + // to the EISA NMI enable register. This selects the realtime clock + // register that is written. Note this is a write only register and + // the EISA NMI is always enabled. + // + + WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase[0])->NmiEnable, + Register); + + // + // Write the realtime clock register value. + // + + WRITE_REGISTER_UCHAR((PUCHAR)HalpRealTimeClockBase, Value); + + return; +} -- cgit v1.2.3