summaryrefslogtreecommitdiffstats
path: root/private/ntos/nthals/halsable/alpha
diff options
context:
space:
mode:
Diffstat (limited to 'private/ntos/nthals/halsable/alpha')
-rw-r--r--private/ntos/nthals/halsable/alpha/addrsup.c883
-rw-r--r--private/ntos/nthals/halsable/alpha/adjust.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/allstart.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/alphaio.s1332
-rw-r--r--private/ntos/nthals/halsable/alpha/bios.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/busdata.c136
-rw-r--r--private/ntos/nthals/halsable/alpha/cache.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/chipset.h1
-rw-r--r--private/ntos/nthals/halsable/alpha/ebsgdma.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/eeprom8k.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/eisasup.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/environ.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/ev4cache.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/ev4int.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/ev4ints.s6
-rw-r--r--private/ntos/nthals/halsable/alpha/ev4mchk.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/ev4mem.s7
-rw-r--r--private/ntos/nthals/halsable/alpha/ev4parit.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/ev4prof.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/fwreturn.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/haldebug.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/halpal.s7
-rw-r--r--private/ntos/nthals/halsable/alpha/haltsup.s7
-rw-r--r--private/ntos/nthals/halsable/alpha/icic.c94
-rw-r--r--private/ntos/nthals/halsable/alpha/icic.h62
-rw-r--r--private/ntos/nthals/halsable/alpha/idle.s7
-rw-r--r--private/ntos/nthals/halsable/alpha/info.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/inithal.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/intsup.s7
-rw-r--r--private/ntos/nthals/halsable/alpha/ioproc.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/iousage.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/lyintsup.c517
-rw-r--r--private/ntos/nthals/halsable/alpha/lyintsup.h50
-rw-r--r--private/ntos/nthals/halsable/alpha/lynxref.h111
-rw-r--r--private/ntos/nthals/halsable/alpha/machdep.h42
-rw-r--r--private/ntos/nthals/halsable/alpha/memory.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/pcibus.c118
-rw-r--r--private/ntos/nthals/halsable/alpha/pcisup.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/pcrtc.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/pcrtc.h102
-rw-r--r--private/ntos/nthals/halsable/alpha/pcserial.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/pcspeakr.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/perf8254.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/pintolin.h544
-rw-r--r--private/ntos/nthals/halsable/alpha/sable.h519
-rw-r--r--private/ntos/nthals/halsable/alpha/sableerr.c2081
-rw-r--r--private/ntos/nthals/halsable/alpha/sableio.s956
-rw-r--r--private/ntos/nthals/halsable/alpha/sableref.h280
-rw-r--r--private/ntos/nthals/halsable/alpha/sablertc.h194
-rw-r--r--private/ntos/nthals/halsable/alpha/sbinitnt.c1292
-rw-r--r--private/ntos/nthals/halsable/alpha/sbintr.s94
-rw-r--r--private/ntos/nthals/halsable/alpha/sbintsup.c113
-rw-r--r--private/ntos/nthals/halsable/alpha/sbmapio.c205
-rw-r--r--private/ntos/nthals/halsable/alpha/sbsysint.c456
-rw-r--r--private/ntos/nthals/halsable/alpha/siintsup.c1332
-rw-r--r--private/ntos/nthals/halsable/alpha/siintsup.h50
-rw-r--r--private/ntos/nthals/halsable/alpha/t2.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/vga.c7
-rw-r--r--private/ntos/nthals/halsable/alpha/xiintsup.c912
-rw-r--r--private/ntos/nthals/halsable/alpha/xiintsup.h50
-rw-r--r--private/ntos/nthals/halsable/alpha/xioref.h148
61 files changed, 12904 insertions, 0 deletions
diff --git a/private/ntos/nthals/halsable/alpha/addrsup.c b/private/ntos/nthals/halsable/alpha/addrsup.c
new file mode 100644
index 000000000..93fdf47dd
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/addrsup.c
@@ -0,0 +1,883 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ tbaqva.c (addrsup.c)
+
+Abstract:
+
+ This module contains the platform dependent code to create bus addreses
+ and QVAs for the Sable system.
+
+Author:
+
+ Joe Notarangelo 26-Oct-1993
+ Steve Jenness 26-Oct-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+#include "pci.h"
+#include "pcip.h"
+
+
+typedef PVOID QUASI_VIRTUAL_ADDRESS;
+
+QUASI_VIRTUAL_ADDRESS
+HalCreateQva(
+ IN PHYSICAL_ADDRESS PA,
+ IN PVOID VA
+ );
+
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system physical address for a specified I/O bus
+ address. The return value is suitable for use in a subsequent call to
+ MmMapIoSpace.
+
+Arguments:
+
+ BusHandler - Registered BUS_HANDLER for the target configuration space
+ Supplies the bus handler (bus no, interface type).
+
+ RootHandler - Registered BUS_HANDLER for the orginating
+ HalTranslateBusAddress request.
+
+ BusAddress - Supplies the bus relative address.
+
+ AddressSpace - Supplies the address space number for the device: 0 for
+ memory and 1 for I/O space. If the desired access mode is user mode,
+ then bit 1 must be TRUE.
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+
+Notes:
+
+ This is a variation of what began in the MIPS code. The intel code often
+ assumes that if an address is in I/O space, the bottom 32 bits of the
+ physical address can be used "like" a virtual address, and are returned
+ to the user. This doesn't work on MIPs machines where physical
+ addresses can be larger than 32 bits.
+
+ Since we are using superpage addresses for I/O on Alpha, we can do
+ almost what is done on intel. If AddressSpace is equal to 0 or 1, then
+ we assume the user is doing kernel I/O and we call
+ HalCreateQva to build a Quasi Virtual Address and return
+ that to the caller. We then set AddressSpace to a 1, so that the caller
+ will not call MmMapIoSpace. The Caller will use the low 32 bits of the
+ physical address we return as the VA. (Which we built a QVA in).
+ If the caller wants to access EISA I/O or Memory through user mode, then
+ the caller must set bit 1 in AddressSpace to a 1 (AddressSpace=2 or 3,
+ depending on whether EISA I/O or Memory), then the caller is returned the
+ 34 bit Physical address. The caller will then call MmMapIoSpace, or
+ ZwMapViewOfSection which in turn calls HalCreateQva to build a QVA out
+ of a VA mapped through the page tables.
+
+ **** Note ****
+
+ The QVA in user mode can only be used via the user-mode access macros.
+
+
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ INTERFACE_TYPE InterfaceType = BusHandler->InterfaceType;
+ ULONG BusNumber;
+ PVOID va = 0; // note, this is used for a placeholder
+
+ //
+ // The only buses available on Sable are an EISA bus and a PCI bus.
+ // We support any translations for EISA devices as well, though
+ // if they are true EISA devices they won't even be able to plug into
+ // the connectors!
+ //
+
+ if ( (InterfaceType != Isa) &&
+ (InterfaceType != Eisa) &&
+ (InterfaceType != PCIBus) &&
+ (InterfaceType != Internal) ) {
+
+ //
+ // Not on this system return nothing.
+ //
+
+#if HALDBG
+ DbgPrint( "HalTBA: Unhandled interface type = %x\n", InterfaceType );
+#endif // HALDBG
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+
+ //
+ // BusData is valid only for the PCI bus.
+ //
+
+ if( (InterfaceType == PCIBus) &&
+ (BusHandler != NULL) &&
+ (BusHandler->BusData != NULL) ) {
+
+ BusNumber = ((PPCIPBUSDATA)(BusHandler->BusData))->HwBusNumber;
+
+ } else {
+
+ //
+ // smdfix: (What should we do here?)
+ // OH MY GOD! We didn't get any BusData. Default to 0.
+ //
+
+ BusNumber = 0;
+
+ }
+
+ //
+ // Determine the address based on whether the bus address is in I/O space
+ // or bus memory space.
+ //
+
+ switch ( (ADDRESS_SPACE_TYPE)(*AddressSpace) ) {
+
+ case BusMemory: {
+
+ //
+ // The address is in PCI memory space, kernel mode.
+ //
+
+ switch( InterfaceType ) {
+
+ case Internal:
+
+ //
+ // SMDFIX: Make Internal bus constraints the same as Isa.
+ //
+
+ case Isa: {
+
+ //
+ // Can't go above 16MB (24 Bits) for Isa Buses
+ //
+
+ if( BusAddress.LowPart >= __16MB ) {
+
+#if HALDBG
+ DbgPrint ("Unsupported ISA address %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif // HALDBG
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+
+ //
+ // else fall through.
+ //
+
+ } // case Isa
+
+ case Eisa:
+
+ //
+ // Eisa is the same as PCI, with respect to kernel mode
+ // sparse and dense space memory support, i.e., its a full
+ // 32 bit space, supports dense memory access.
+ //
+
+ case PCIBus: {
+
+ if( BusNumber == 0 ) {
+
+ //
+ // PCI 0 Bus support.
+ // PCI0_MAX_SPARSE_MEMORY_ADDRESS= 128MB-1
+ // PCI0_MIN_DENSE_MEMORY_ADDRESS = 128MB
+ // PCI0_MAX_DENSE_MEMORY_ADDRESS = 1GB-1
+ //
+
+ if ( BusAddress.LowPart > PCI0_MAX_DENSE_MEMORY_ADDRESS ) {
+
+ //
+ // Unsupported dense PCI bus address.
+ //
+
+#if HALDBG
+ DbgPrint ("Unsupported PCI 0 address %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif // HALDBG
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+ else
+ if( BusAddress.LowPart >= PCI0_MIN_DENSE_MEMORY_ADDRESS &&
+ BusAddress.LowPart <= PCI0_MAX_DENSE_MEMORY_ADDRESS ) {
+
+ //
+ // Bus Address is in dense PCI memory space
+ //
+
+ //
+ // Start with the base physical address and add the
+ // offset
+ //
+
+ TranslatedAddress->QuadPart =
+ SABLE_PCI0_DENSE_MEMORY_PHYSICAL;
+
+ TranslatedAddress->QuadPart +=
+ (ULONGLONG)BusAddress.LowPart;
+
+ } else {
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart =
+ SABLE_PCI0_SPARSE_MEMORY_PHYSICAL;
+ TranslatedAddress->QuadPart +=
+ ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT);
+
+ }
+
+ //
+ // Now call HalCreateQva. This will create a QVA
+ // that we'll return to the caller. Then we will
+ // implicitly set AddressSpace to a 1. The caller then
+ // will not call MmMapIoSpace and will use the address
+ // we return as a VA.
+ //
+
+ TranslatedAddress->LowPart =
+ (ULONG) HalCreateQva( *TranslatedAddress, va);
+
+ //
+ // clear high longword for QVA
+ //
+
+ TranslatedAddress->HighPart = 0;
+
+ //
+ // dont let the user call MmMapIoSpace
+ //
+
+ *AddressSpace = 1;
+
+ return(TRUE);
+
+ } else { // if BusNumber == 0
+
+ //
+ // PCI 1 Bus support (64Bit Pci Bus).
+ // PCI1_MAX_SPARSE_MEMORY_ADDRESS = 64MB-1
+ // PCI1_MIN_DENSE_MEMORY_ADDRESS = 64MB
+ // PCI1_MAX_DENSE_MEMORY_ADDRESS = 1GB-1
+ //
+
+ if ( BusAddress.LowPart > PCI1_MAX_DENSE_MEMORY_ADDRESS ) {
+
+ //
+ // Unsupported dense PCI bus address.
+ //
+
+#if HALDBG
+ DbgPrint ("Unsupported PCI 1 address %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif // HALDBG
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+ else
+ if( BusAddress.LowPart >= PCI1_MIN_DENSE_MEMORY_ADDRESS &&
+ BusAddress.LowPart <= PCI1_MAX_DENSE_MEMORY_ADDRESS ) {
+
+ //
+ // Bus Address is in dense PCI memory space
+ //
+
+ //
+ // Start with the base physical address and add the
+ // offset
+ //
+
+ TranslatedAddress->QuadPart =
+ SABLE_PCI1_DENSE_MEMORY_PHYSICAL;
+
+ TranslatedAddress->QuadPart +=
+ (ULONGLONG)BusAddress.LowPart;
+
+ } else {
+
+ //
+ // Start with the base physical address and add the bus
+ // address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart =
+ SABLE_PCI1_SPARSE_MEMORY_PHYSICAL;
+
+ TranslatedAddress->QuadPart +=
+ ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT);
+
+
+ }
+
+ //
+ // Now call HalCreateQva. This will create a QVA
+ // that we'll return to the caller. Then we will implicitly
+ // set AddressSpace to a 1. The caller then will not call
+ // MmMapIoSpace and will use the address we return as a VA.
+ //
+
+ TranslatedAddress->LowPart =
+ (ULONG) HalCreateQva( *TranslatedAddress, va);
+
+ //
+ // clear high longword for QVA
+ //
+ TranslatedAddress->HighPart = 0;
+
+ //
+ // don't let the user call MmMapIoSpace
+ //
+
+ *AddressSpace = 1;
+
+ return(TRUE);
+
+ } // if (BusNumber == 0)
+
+ } // case PCIBus
+
+ } // switch( InterfaceType )
+
+ } // case BusMemory
+
+ case BusIo: {
+
+ //
+ // The address is in PCI I/O space, kernel mode.
+ //
+ switch( InterfaceType ) {
+
+ case Eisa:
+
+ //
+ // Eisa is the same as ISA, with respect to kernel mode
+ // sparse I/O space support, i.e., it is a 16 bit sparse
+ // space.
+ //
+
+ case Internal:
+
+ //
+ // SMDFIX: Make Internal bus constraints the same as Isa.
+ //
+
+ case Isa: {
+
+ //
+ // Can't go above 64KB (16 Bits) for Isa Buses
+ //
+
+ if( BusAddress.LowPart >= __64K ){
+
+#if HALDBG
+ DbgPrint ("Unsupported ISA IO address %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif // HALDBG
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+
+ //
+ // Fall through
+ //
+
+ } // case Isa
+
+ case PCIBus: {
+
+ if( BusNumber == 0 ) {
+
+ //
+ // PCI 0 Bus Support.
+ // PCI0_MAX_IO_ADDRESS = 16MB-1
+ //
+
+ if( BusAddress.LowPart >= PCI0_MAX_IO_ADDRESS ){
+
+#if HALDBG
+ DbgPrint ("Unsupported PCI 0 IO address %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif // HALDBG
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ } else {
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart =
+ SABLE_PCI0_SPARSE_IO_PHYSICAL;
+ TranslatedAddress->QuadPart +=
+ ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT);
+
+ //
+ // Now call HalCreateQva. This will create a QVA
+ // that we'll return to the caller. Then we will
+ // implicitly set AddressSpace to a 1. The caller then
+ // will not call MmMapIoSpace and will use the address
+ // we return as a VA.
+ //
+
+ TranslatedAddress->LowPart =
+ (ULONG) HalCreateQva( *TranslatedAddress, va);
+
+ TranslatedAddress->HighPart = 0;
+
+ //
+ // Make sure user doesn't call MmMapIoSpace.
+ //
+
+ *AddressSpace = 1;
+
+ return(TRUE);
+ }
+
+
+ } else { // if (BusNumber == 0)
+
+ //
+ // PCI 1 Bus Support.
+ // PCI1_MAX_SPARSE_IO_ADDRESS = 16MB-1
+ //
+
+ if( BusAddress.LowPart >= PCI1_MAX_SPARSE_IO_ADDRESS ){
+
+#if HALDBG
+ DbgPrint ("Unsupported PCI 1 IO address %x:%x\n",
+ BusAddress.HighPart,
+ BusAddress.LowPart);
+#endif // HALDBG
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ } else {
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ TranslatedAddress->QuadPart =
+ SABLE_PCI1_SPARSE_IO_PHYSICAL;
+//
+// smdfix:
+//
+// The above should actually check if this hal is running on a Lynx machine
+// since the location of PCI1_SPARSE_IO is different. For now we support
+// SABLE only.
+//
+// (LynxMachine)? LYNX_PCI1_SPARSE_IO_PHYSICAL: SABLE_PCI1_SPARSE_IO_PHYSICAL;
+//
+
+ TranslatedAddress->QuadPart +=
+ ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT);
+
+ //
+ // Now call HalCreateQva. This will create a QVA that
+ // we'll return to the caller. Then we will implicitly
+ // set AddressSpace to a 1. The caller then will not
+ // call MmMapIoSpace and will use the address we return
+ // as a VA.
+ //
+
+ TranslatedAddress->LowPart =
+ (ULONG) HalCreateQva( *TranslatedAddress, va);
+
+ TranslatedAddress->HighPart = 0;
+
+ //
+ // Make sure user doesn't call MmMapIoSpace.
+ //
+
+ *AddressSpace = 1;
+
+ return(TRUE);
+ }
+
+ } // if (BusNumber == 0)
+
+ } // case PCIBus
+
+ } // switch( InterfaceType )
+
+ } // case BusIo
+
+ case UserBusMemory: {
+
+ //
+ // The address is in PCI memory space, user mode.
+ //
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ if( BusNumber == 0 ) {
+ TranslatedAddress->QuadPart = SABLE_USER_PCI0_SPARSE_MEMORY_PHYSICAL;
+ } else {
+ TranslatedAddress->QuadPart = SABLE_USER_PCI1_SPARSE_MEMORY_PHYSICAL;
+ }
+
+ TranslatedAddress->QuadPart += ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT);
+
+ *AddressSpace = 0; // Let the user call MmMapIoSpace
+
+ return(TRUE);
+
+ }
+
+ case UserBusIo: {
+
+ //
+ // The address is in PCI I/O space, user mode.
+ //
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ if( BusNumber == 0 ) {
+ TranslatedAddress->QuadPart = SABLE_USER_PCI0_SPARSE_IO_PHYSICAL;
+ } else {
+ TranslatedAddress->QuadPart = SABLE_USER_PCI1_SPARSE_IO_PHYSICAL;
+ }
+
+ TranslatedAddress->QuadPart += ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT);
+
+ //
+ // Make sure user can call MmMapIoSpace.
+ //
+
+ *AddressSpace = 0;
+
+ return(TRUE);
+
+ }
+
+ case KernelPciDenseMemory:
+ case UserPciDenseMemory:
+ {
+
+ //
+ // The address is in PCI memory space, user mode.
+ //
+
+ //
+ // Start with the base physical address and add the
+ // bus address by converting it to the physical address.
+ //
+
+ if( BusNumber == 0 ) {
+ TranslatedAddress->QuadPart = SABLE_USER_PCI0_DENSE_MEMORY_PHYSICAL;
+ } else {
+ TranslatedAddress->QuadPart = SABLE_USER_PCI1_DENSE_MEMORY_PHYSICAL;
+ }
+
+ TranslatedAddress->QuadPart += ((ULONGLONG)BusAddress.LowPart);
+
+ //
+ // Let the user call MmMapIoSpace
+ //
+
+ *AddressSpace = 0;
+
+ return(TRUE);
+
+ }
+ } // switch (*AddressSpace)
+}
+
+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 an I/O space address (PCI I/O, PCI Memory),
+ then return the VA as the QVA.
+
+Arguments:
+
+ PA - the physical address generated by HalTranslateBusAddress
+
+ VA - the virtual address returned by MmMapIoSpace
+
+Return Value:
+
+ The returned value is a quasi virtual address in that it can be
+ added to and subtracted from, but it cannot be used to access the
+ bus directly. The top bits are set so that we can trap invalid
+ accesses in the memory management subsystem. All access should be
+ done through the Hal Access Routines in *ioacc.s if it was a superpage
+ kernel mode access. If it is usermode, then the user mode access
+ macros must be used.
+
+--*/
+{
+ PVOID qva;
+
+ //
+ // Clear bit 35 (if present) for user mode address spaces.
+ //
+
+ if( VA != NULL ){
+ PA.QuadPart &= 0x83FFFFFFFF;
+ }
+
+ if( (PA.QuadPart >= SABLE_PCI0_SPARSE_MEMORY_PHYSICAL) &&
+ (PA.QuadPart < SABLE_PCI1_SPARSE_MEMORY_PHYSICAL) ||
+
+ (PA.QuadPart >= SABLE_PCI1_SPARSE_MEMORY_PHYSICAL) &&
+ (PA.QuadPart < SABLE_CBUS_CSRS_PHYSICAL) ||
+
+ (PA.QuadPart >= SABLE_PCI0_SPARSE_IO_PHYSICAL) &&
+ (PA.QuadPart < SABLE_PCI0_DENSE_MEMORY_PHYSICAL) ||
+
+ (PA.QuadPart >= SABLE_PCI1_SPARSE_IO_PHYSICAL) &&
+ (PA.QuadPart <=
+ SABLE_PCI1_SPARSE_IO_PHYSICAL + PCI1_MAX_SPARSE_IO_ADDRESS) ){
+
+ //
+ // The physical address is within one of the sparse I/O spaces.
+ //
+
+ if (VA == 0) {
+
+ qva = (PVOID)(PA.QuadPart >> IO_BIT_SHIFT);
+
+ } else {
+
+ qva = (PVOID)((ULONG)VA >> IO_BIT_SHIFT);
+ }
+
+ qva = (PVOID)((ULONG)qva | QVA_ENABLE);
+
+ return(qva);
+ }
+ else if( PA.QuadPart >= SABLE_PCI0_DENSE_MEMORY_PHYSICAL &&
+ PA.QuadPart <= SABLE_PCI0_DENSE_MEMORY_PHYSICAL +
+ PCI0_MAX_DENSE_MEMORY_ADDRESS ) {
+
+ //
+ // The physical address is within the 1 GB dense space of PCI bus 0.
+ //
+
+ if (VA == 0) {
+
+ //
+ // Kernel mode: create a QVA
+ //
+ // Subtract out physical address base.
+ // Now we just have the PCI 0 bus address.
+
+ PA.QuadPart -= SABLE_PCI0_DENSE_MEMORY_PHYSICAL;
+
+ // Add in the QVA base for PCI Bus 0
+
+ PA.QuadPart += SABLE_PCI0_DENSE_MEMORY_QVA;
+
+ qva = (PVOID) PA.LowPart;
+
+ return(qva);
+
+ } else {
+
+ //
+ // Use mode, return the VA as the QVA
+ //
+
+ return(VA);
+ }
+ }
+ else if( PA.QuadPart >= SABLE_PCI1_DENSE_MEMORY_PHYSICAL &&
+ PA.QuadPart <= SABLE_PCI1_DENSE_MEMORY_PHYSICAL +
+ PCI1_MAX_DENSE_MEMORY_ADDRESS) {
+
+ //
+ // The physical address is within the 2 GB dense space of PCI bus 1.
+ //
+
+ if (VA == 0) {
+
+ // Subtract out physical address base.
+ // Now we just have the PCI 1 bus address.
+
+ PA.QuadPart -= SABLE_PCI1_DENSE_MEMORY_PHYSICAL;
+
+ // Add in the QVA base for PCI Bus 1
+
+ PA.QuadPart += SABLE_PCI1_DENSE_MEMORY_QVA;
+
+ qva = (PVOID) PA.LowPart;
+
+ return(qva);
+
+ } else {
+
+ //
+ // Use mode, return the VA as the QVA
+ //
+
+ return(VA);
+ }
+ }
+
+ //
+ // It is not an I/O space address, return the VA as the QVA
+ //
+
+ return(VA);
+
+}
+
+PVOID
+HalDereferenceQva(
+ PVOID Qva,
+ INTERFACE_TYPE InterfaceType,
+ ULONG BusNumber
+ )
+/*++
+
+Routine Description:
+
+ This function performs the inverse of the HalCreateQva for I/O addresses
+ that are memory-mapped (i.e. the quasi-virtual address was created from
+ a virtual address rather than a physical address).
+
+Arguments:
+
+ Qva - Supplies the quasi-virtual address to be converted back to a
+ virtual address.
+
+ InterfaceType - Supplies the interface type of the bus to which the
+ Qva pertains.
+
+ BusNumber - Supplies the bus number of the bus to which the Qva pertains.
+
+Return Value:
+
+ The Virtual Address from which the quasi-address was originally created
+ is returned.
+
+--*/
+{
+
+
+ //
+ // For Sable we have three supported bus types:
+ //
+ // Isa
+ // Eisa
+ // PCIBus
+ //
+
+ switch (InterfaceType ){
+
+ case Isa:
+ case Eisa:
+ case PCIBus:
+
+ //
+ // Support dense space: check to see if it's really
+ // a sparse space QVA.
+ //
+
+ if ( ((ULONG) Qva & QVA_SELECTORS) == QVA_ENABLE ) {
+ return( (PVOID)( (ULONG)Qva << IO_BIT_SHIFT ) );
+ } else {
+ return (Qva);
+ }
+ break;
+
+ default:
+
+ return NULL;
+
+ }
+
+
+}
diff --git a/private/ntos/nthals/halsable/alpha/adjust.c b/private/ntos/nthals/halsable/alpha/adjust.c
new file mode 100644
index 000000000..47c267fb8
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/adjust.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\adjust.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/allstart.c b/private/ntos/nthals/halsable/alpha/allstart.c
new file mode 100644
index 000000000..42f70b7ca
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/allstart.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\allstart.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/alphaio.s b/private/ntos/nthals/halsable/alpha/alphaio.s
new file mode 100644
index 000000000..efcac0fda
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/alphaio.s
@@ -0,0 +1,1332 @@
+/*++
+
+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
+
+ 4-April-1995 - Sameer Dekate
+
+ Added support for PCI 1 dense space.
+
+--*/
+
+#include "chipset.h"
+#include "halalpha.h"
+
+
+
+ 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(READ_REGISTER_UCHAR)
+
+ ALTERNATE_ENTRY(READ_PORT_UCHAR)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get byte we need if eisa
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, -0x4000 // 0xffff ffff ffff c000
+ sll t4, 28, t4 // 0xffff fc00 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 t2, 0xC0000000 // Bits telling if this is PCI 0 or PCI 1
+ and t2, a0, t2 // see if bits are lit.
+
+ ldiq t0, PCI_DENSE_BASE_PHYSICAL_SUPERPAGE // PCI 0
+ ldiq t1, PCI1_DENSE_BASE_PHYSICAL_SUPERPAGE // PCI 1
+
+ cmovne t2, t0, t4 // if PCI0 t0 -> t4
+ cmoveq t2, t1, t4 // if PCI1 t1 -> t4
+
+ or a0, t4, 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 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(READ_REGISTER_USHORT)
+
+ ALTERNATE_ENTRY(READ_PORT_USHORT)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get word
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, -0x4000 //
+ 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 t2, 0xC0000000 // Bits telling if this is PCI 0 or PCI 1
+ and t2, a0, t2 // see if bits are lit.
+
+ ldiq t0, PCI_DENSE_BASE_PHYSICAL_SUPERPAGE // PCI 0
+ ldiq t1, PCI1_DENSE_BASE_PHYSICAL_SUPERPAGE // PCI 1
+
+ cmovne t2, t0, t4 // if PCI0 t0 -> t4
+ cmoveq t2, t1, t4 // if PCI1 t1 -> t4
+
+ or a0, t4, 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 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(READ_REGISTER_ULONG)
+
+ ALTERNATE_ENTRY(READ_PORT_ULONG)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, -0x4000 //
+ 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 t2, 0xC0000000 // Bits telling if this is PCI 0 or PCI 1
+ and t2, a0, t2 // see if bits are lit.
+
+ ldiq t0, PCI_DENSE_BASE_PHYSICAL_SUPERPAGE // PCI 0
+ ldiq t1, PCI1_DENSE_BASE_PHYSICAL_SUPERPAGE // PCI 1
+
+ cmovne t2, t0, t4 // if PCI0 t0 -> t4
+ cmoveq t2, t1, t4 // if PCI1 t1 -> t4
+
+ or a0, t4, a0 // superpage mode: add offset to base
+
+ ldl v0, (a0) // get the longword
+
+ ret zero, (ra) // return
+
+ .end 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(WRITE_REGISTER_UCHAR)
+
+ ALTERNATE_ENTRY(WRITE_PORT_UCHAR)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get byte we need if eisa
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, -0x4000 //
+ 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 t2, 0xC0000000 // Bits telling if this is PCI 0 or PCI 1
+ and t2, a0, t2 // see if bits are lit.
+
+ ldiq t0, PCI_DENSE_BASE_PHYSICAL_SUPERPAGE // PCI 0
+ ldiq t1, PCI1_DENSE_BASE_PHYSICAL_SUPERPAGE // PCI 1
+
+ cmovne t2, t0, t4 // if PCI0 t0 -> t4
+ cmoveq t2, t1, t4 // if PCI1 t1 -> t4
+
+ or a0, t4, 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 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(WRITE_REGISTER_USHORT)
+
+ ALTERNATE_ENTRY(WRITE_PORT_USHORT)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 3, t3 // get word
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, -0x4000 //
+ 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 t2, 0xC0000000 // Bits telling if this is PCI 0 or PCI 1
+ and t2, a0, t2 // see if bits are lit.
+
+ ldiq t0, PCI_DENSE_BASE_PHYSICAL_SUPERPAGE // PCI 0
+ ldiq t1, PCI1_DENSE_BASE_PHYSICAL_SUPERPAGE // PCI 1
+
+ cmovne t2, t0, t4 // if PCI0 t0 -> t4
+ cmoveq t2, t1, t4 // if PCI1 t1 -> t4
+
+ or a0, t4, 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 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(WRITE_REGISTER_ULONG)
+
+ ALTERNATE_ENTRY(WRITE_PORT_ULONG)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, -0x4000 //
+ 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 t2, 0xC0000000 // Bits telling if this is PCI 0 or PCI 1
+ and t2, a0, t2 // see if bits are lit.
+
+ ldiq t0, PCI_DENSE_BASE_PHYSICAL_SUPERPAGE // PCI 0
+ ldiq t1, PCI1_DENSE_BASE_PHYSICAL_SUPERPAGE // PCI 1
+
+ cmovne t2, t0, t4 // if PCI0 t0 -> t4
+ cmoveq t2, t1, t4 // if PCI1 t1 -> t4
+
+ or a0, t4, a0 // superpage mode: add offset to base
+
+ stl a1, (a0) // store the longword
+ mb // order the write
+
+ ret zero, (ra) // return
+
+ .end 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(READ_PORT_BUFFER_UCHAR)
+
+ and a0, 3, t3 // get byte we need if eisa
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, -0x4000 // 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 READ_PORT_BUFFER_UCHAR
+
+
+ SBTTL( "Read Buffer from Port Space in Ushorts")
+//++
+//
+// VOID
+// READ_PORT_BUFFER_USHORT(
+// IN PVOID PortQva,
+// IN PUSHORT Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Read multiple words from the specified port address into the
+// destination buffer.
+//
+// Arguments:
+//
+// PortQva(a0) - Supplies the QVA of the port to read.
+//
+// Buffer(a1) - Supplies a pointer to the buffer to fill with
+// the data read from the port.
+//
+// Count(a2) - Supplies the number of words to read.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(READ_PORT_BUFFER_USHORT)
+
+ and a0, 3, t3 // get word we need
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, -0x4000 // 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 READ_PORT_BUFFER_USHORT
+
+ SBTTL( "Read Buffer from Port Space in Ulongs")
+//++
+//
+// VOID
+// READ_PORT_BUFFER_ULONG(
+// IN PVOID PortQva,
+// IN PULONG Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Read multiple longwords from the specified port address into the
+// destination buffer.
+//
+// Arguments:
+//
+// PortQva(a0) - Supplies the QVA of the port to read.
+//
+// Buffer(a1) - Supplies a pointer to the buffer to fill with
+// the data read from the port.
+//
+// Count(a2) - Supplies the number of longwords to read.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(READ_PORT_BUFFER_ULONG)
+
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+
+ ldiq t4, -0x4000 // 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 READ_PORT_BUFFER_ULONG
+
+
+ SBTTL( "Write Buffer to Port Space in Uchars")
+//++
+//
+// VOID
+// WRITE_PORT_BUFFER_UCHAR(
+// IN PVOID PortQva,
+// IN PUCHAR Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Write multiple bytes from the source buffer to the specified port
+// address.
+//
+// Arguments:
+//
+// PortQva(a0) - Supplies the QVA of the port to write.
+//
+// Buffer(a1) - Supplies a pointer to the buffer containing the data
+// to write to the port.
+//
+// Count(a2) - Supplies the number of bytes to write.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_PORT_BUFFER_UCHAR)
+
+ and a0, 3, t3 // get byte we need if eisa
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, -0x4000 // 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 WRITE_PORT_BUFFER_UCHAR
+
+ SBTTL( "Write Buffer to Port Space in Ushorts")
+//++
+//
+// VOID
+// WRITE_PORT_BUFFER_USHORT(
+// IN PVOID PortQva,
+// IN PSHORT Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Write multiple words from the source buffer to the specified port
+// address.
+//
+// Arguments:
+//
+// PortQva(a0) - Supplies the QVA of the port to write.
+//
+// Buffer(a1) - Supplies a pointer to the buffer containing the data
+// to write to the port.
+//
+// Count(a2) - Supplies the number of words to write.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_PORT_BUFFER_USHORT)
+
+ and a0, 3, t3 // get word we need
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, -0x4000 // 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 WRITE_PORT_BUFFER_USHORT
+
+
+ SBTTL( "Write Buffer to Port Space in Ulongs")
+//++
+//
+// VOID
+// WRITE_PORT_BUFFER_ULONG(
+// IN PVOID PortQva,
+// IN PULONG Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Write multiple longwords from the source buffer to the specified port
+// address.
+//
+// Arguments:
+//
+// PortQva(a0) - Supplies the QVA of the port to write.
+//
+// Buffer(a1) - Supplies a pointer to the buffer containing the data
+// to write to the port.
+//
+// Count(a2) - Supplies the number of longwords to write.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(WRITE_PORT_BUFFER_ULONG)
+
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+
+ ldiq t4, -0x4000 // 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 WRITE_PORT_BUFFER_ULONG
+
+
+ SBTTL( "Read Buffer from PCI Memory Space in Uchars")
+//++
+//
+// VOID
+// READ_REGISTER_BUFFER_UXXXXX(
+// IN PVOID RegisterQva,
+// IN PUCHAR Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Copies a buffer from PCI Memory Space to an in-memory buffer.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the starting QVA of the memory space buffer.
+//
+// Buffer(a1) - Supplies a pointer to the in-memory buffer to receive
+// the copied data.
+//
+// Count(a2) - Supplies the number of bytes, words or longwords to write.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(READ_REGISTER_BUFFER_ULONG)
+
+ sll a2, 1, a2 // convert number of longs to words
+
+ ALTERNATE_ENTRY(READ_REGISTER_BUFFER_USHORT)
+
+
+ sll a2, 1, a2 // convert number of words to chars
+
+ ALTERNATE_ENTRY(READ_REGISTER_BUFFER_UCHAR)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ beq t1, 1f // if (eq) go do sparse space
+
+//
+// Dense space access: QVA is an offset into dense space
+// Set IO address in t0
+//
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ ldiq t2, 0xC0000000 // Bits telling if this is PCI 0 or PCI 1
+ and t2, a0, t2 // see if bits are lit.
+
+ ldiq t0, PCI_DENSE_BASE_PHYSICAL_SUPERPAGE // PCI 0
+ ldiq t1, PCI1_DENSE_BASE_PHYSICAL_SUPERPAGE // PCI 1
+
+ cmovne t2, t0, t4 // if PCI0 t0 -> t4
+ cmoveq t2, t1, t4 // if PCI1 t1 -> t4
+
+ or a0, t4, 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, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, -0x4000 // 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 READ_REGISTER_BUFFER_ULONG // end for UCHAR & USHORT
+
+
+ SBTTL( "Write Buffer to PCI Memory Space in Uchars")
+//++
+//
+// VOID
+// WRITE_REGISTER_BUFFER_UXXXXX(
+// IN PVOID RegisterQva,
+// IN PUCHAR Buffer,
+// IN ULONG Count
+// )
+//
+// Routine Description:
+//
+// Copies an in-memory buffer to a PCI Memory Space buffer.
+//
+// Arguments:
+//
+// RegisterQva(a0) - Supplies the starting QVA of the memory space buffer.
+//
+// Buffer(a1) - Supplies a pointer to the in-memory source buffer.
+//
+// Count(a2) - Supplies the number of bytes, words to longwords to write.
+//
+// Return Value:
+//
+// None.
+//
+//--
+ LEAF_ENTRY(WRITE_REGISTER_BUFFER_ULONG)
+
+ sll a2, 1, a2 // convert number of longs to words
+
+ ALTERNATE_ENTRY(WRITE_REGISTER_BUFFER_USHORT)
+
+ sll a2, 1, a2 // convert number of words to chars
+
+ ALTERNATE_ENTRY(WRITE_REGISTER_BUFFER_UCHAR)
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ beq t1, 1f // if (eq) go do sparse space
+
+//
+// Dense space access: QVA is an offset into dense space
+// Set IO address in t0
+//
+
+ zap a0, 0xf0, a0 // clear <63:32>
+
+ ldiq t2, 0xC0000000 // Bits telling if this is PCI 0 or PCI 1
+ and t2, a0, t2 // see if bits are lit.
+
+ ldiq t0, PCI_DENSE_BASE_PHYSICAL_SUPERPAGE // PCI 0
+ ldiq t1, PCI1_DENSE_BASE_PHYSICAL_SUPERPAGE // PCI 1
+
+ cmovne t2, t0, t4 // if PCI0 t0 -> t4
+ cmoveq t2, t1, t4 // if PCI1 t1 -> t4
+
+ or a0, t4, 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, QVA_ENABLE,a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0 // t0 contains VA<33:0>
+ ldiq t4, -0x4000 // 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 WRITE_REGISTER_BUFFER_ULONG // end for UCHAR & USHORT
diff --git a/private/ntos/nthals/halsable/alpha/bios.c b/private/ntos/nthals/halsable/alpha/bios.c
new file mode 100644
index 000000000..3a9d3aa50
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/bios.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\bios.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/busdata.c b/private/ntos/nthals/halsable/alpha/busdata.c
new file mode 100644
index 000000000..2e805db9c
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/busdata.c
@@ -0,0 +1,136 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ busdata.c
+
+Abstract:
+
+ This module contains get/set bus data routines.
+
+Author:
+
+ Darryl E. Havens (darrylh) 11-Apr-1990
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+
+//
+// External Function Prototypes
+//
+
+ULONG
+HalpNoBusData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpRegisterInternalBusHandlers)
+#endif
+
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function registers the bushandlers for buses on the system
+ that will always be present on the system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PBUS_HANDLER Bus;
+
+ //
+ // Initalize BusHandler data before registering any handlers
+ //
+
+ HalpInitBusHandler ();
+
+ //
+ // Build the processor internal bus 0
+ //
+
+ HaliRegisterBusHandler (ProcessorInternal, // Bus Type
+ -1, // No config space
+ 0, // Bus Number
+ -1, // No parent bus type
+ 0, // No parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+
+ //
+ // Build internal-bus 0, or system level bus
+ //
+
+ HaliRegisterBusHandler (Internal, // Bus Type
+ -1, // No config space
+ 0, // Bus Number
+ -1, // No parent bus type
+ 0, // No parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+ Bus->TranslateBusAddress = HalpTranslateSystemBusAddress;
+
+ //
+ // Build Isa/Eisa bus #0
+ //
+
+ HaliRegisterBusHandler (Eisa, // Bus Type
+ EisaConfiguration, // Config space type
+ 0, // Internal bus #0
+ Internal, // Parent bus type
+ 0, // Parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler return
+
+ Bus->GetBusData = HalpGetEisaData;
+ Bus->AdjustResourceList = HalpAdjustEisaResourceList;
+
+ HaliRegisterBusHandler (Isa, // Bus Type
+ -1, // No config space
+ 0, // Internal bus #0
+ Eisa, // Parent bus type
+ 0, // Parent bus number
+ 0, // No extension data
+ NULL, // No install handler
+ &Bus); // Bushandler returne
+
+ Bus->GetBusData = HalpNoBusData;
+ Bus->AdjustResourceList = HalpAdjustIsaResourceList;
+
+}
diff --git a/private/ntos/nthals/halsable/alpha/cache.c b/private/ntos/nthals/halsable/alpha/cache.c
new file mode 100644
index 000000000..561528477
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/cache.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\cache.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/chipset.h b/private/ntos/nthals/halsable/alpha/chipset.h
new file mode 100644
index 000000000..93c34f79b
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/chipset.h
@@ -0,0 +1 @@
+#include "sable.h"
diff --git a/private/ntos/nthals/halsable/alpha/ebsgdma.c b/private/ntos/nthals/halsable/alpha/ebsgdma.c
new file mode 100644
index 000000000..f2f033fad
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/ebsgdma.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ebsgdma.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/eeprom8k.c b/private/ntos/nthals/halsable/alpha/eeprom8k.c
new file mode 100644
index 000000000..c03d04c0d
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/eeprom8k.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\eeprom8k.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/eisasup.c b/private/ntos/nthals/halsable/alpha/eisasup.c
new file mode 100644
index 000000000..0d46ef3e4
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/eisasup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\eisasup.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/environ.c b/private/ntos/nthals/halsable/alpha/environ.c
new file mode 100644
index 000000000..75015a0a0
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/environ.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\environ.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/ev4cache.c b/private/ntos/nthals/halsable/alpha/ev4cache.c
new file mode 100644
index 000000000..b0cf9e3be
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/ev4cache.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4cache.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/ev4int.c b/private/ntos/nthals/halsable/alpha/ev4int.c
new file mode 100644
index 000000000..8a10705d7
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/ev4int.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4int.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/ev4ints.s b/private/ntos/nthals/halsable/alpha/ev4ints.s
new file mode 100644
index 000000000..6df823ab6
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/ev4ints.s
@@ -0,0 +1,6 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+#include "..\halalpha\ev4ints.s"
+
diff --git a/private/ntos/nthals/halsable/alpha/ev4mchk.c b/private/ntos/nthals/halsable/alpha/ev4mchk.c
new file mode 100644
index 000000000..697087c15
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/ev4mchk.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4mchk.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/ev4mem.s b/private/ntos/nthals/halsable/alpha/ev4mem.s
new file mode 100644
index 000000000..f410d09a3
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/ev4mem.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4mem.s"
+
diff --git a/private/ntos/nthals/halsable/alpha/ev4parit.c b/private/ntos/nthals/halsable/alpha/ev4parit.c
new file mode 100644
index 000000000..74c6d0d00
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/ev4parit.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4parit.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/ev4prof.c b/private/ntos/nthals/halsable/alpha/ev4prof.c
new file mode 100644
index 000000000..7ecdfa8b7
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/ev4prof.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ev4prof.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/fwreturn.c b/private/ntos/nthals/halsable/alpha/fwreturn.c
new file mode 100644
index 000000000..65ae88cb8
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/fwreturn.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\fwreturn.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/haldebug.c b/private/ntos/nthals/halsable/alpha/haldebug.c
new file mode 100644
index 000000000..ce91863ec
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/haldebug.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\haldebug.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/halpal.s b/private/ntos/nthals/halsable/alpha/halpal.s
new file mode 100644
index 000000000..fc89f8370
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/halpal.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\halpal.s"
+
diff --git a/private/ntos/nthals/halsable/alpha/haltsup.s b/private/ntos/nthals/halsable/alpha/haltsup.s
new file mode 100644
index 000000000..b8a697144
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/haltsup.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\haltsup.s"
+
diff --git a/private/ntos/nthals/halsable/alpha/icic.c b/private/ntos/nthals/halsable/alpha/icic.c
new file mode 100644
index 000000000..7d853513a
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/icic.c
@@ -0,0 +1,94 @@
+/*++
+
+Copyright (c) 1995 Digital Equipment Corporation
+
+Module Name:
+
+ icic.c
+
+Abstract:
+
+ This module implements functions specific to the Interrupt
+ Controller IC (ICIC).
+
+Author:
+
+ Dave Richards 26-May-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "t2.h"
+#include "icic.h"
+
+
+ULONGLONG
+READ_ICIC_REGISTER(
+ IN PVOID TxQva,
+ IN ICIC_REGISTER IcIcRegister
+ )
+
+/*++
+
+Routine Description:
+
+ Read a 64-bit value from an ICIC register.
+
+Arguments:
+
+ TxQva - The QVA of the T3/T4 CSR space.
+
+ IcIcRegister - The register number to read.
+
+Return Value:
+
+ The 64-bit value read.
+
+--*/
+
+{
+ WRITE_T2_REGISTER( &((PT2_CSRS)TxQva)->Air, IcIcRegister );
+
+ return READ_T2_REGISTER( &((PT2_CSRS)TxQva)->Dir );
+}
+
+
+VOID
+WRITE_ICIC_REGISTER(
+ IN PVOID TxQva,
+ IN ICIC_REGISTER IcIcRegister,
+ IN ULONGLONG Value
+ )
+
+/*++
+
+Routine Description:
+
+ Write a 64-bit value to an ICIC register.
+
+Arguments:
+
+ TxQva - The QVA of the T3/T4 CSR space.
+
+ IcIcRegister - The register number to write.
+
+ Value - The 64-bit value to write.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ WRITE_T2_REGISTER( &((PT2_CSRS)TxQva)->Air, IcIcRegister );
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)TxQva)->Dir, Value );
+
+ (VOID)READ_T2_REGISTER( &((PT2_CSRS)TxQva)->Dir );
+}
diff --git a/private/ntos/nthals/halsable/alpha/icic.h b/private/ntos/nthals/halsable/alpha/icic.h
new file mode 100644
index 000000000..3c3407943
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/icic.h
@@ -0,0 +1,62 @@
+/*++
+
+Copyright (c) 1995 Digital Equipment Corporation
+
+Module Name:
+
+ icic.h
+
+Abstract:
+
+ This file defines the structures and definitions describing the
+ Interrupt Controller IC (ICIC).
+
+Author:
+
+ Dave Richards 23-May-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#ifndef _ICICH_
+#define _ICICH_
+
+typedef enum _ICIC_REGISTER {
+ IcIcMaskRegister = 0x40,
+ IcIcElcrRegister = 0x50,
+ IcIcEisaRegister = 0x60,
+ IcIcModeRegister = 0x70
+} ICIC_REGISTER;
+
+typedef ULONGLONG ICIC_MASK_REGISTER, *PICIC_MASK_REGISTER;
+typedef ULONGLONG ICIC_ELCR_REGISTER, *PICIC_ELCR_REGISTER;
+typedef ULONGLONG ICIC_EISA_REGISTER, *PICIC_EISA_REGISTER;
+
+typedef union _ICIC_MODE_REGISTER {
+ struct {
+ ULONGLONG Mode: 1;
+ ULONGLONG Reset: 1;
+ ULONGLONG Reserved: 62;
+ };
+ ULONGLONG all;
+} ICIC_MODE_REGISTER, *PICIC_MODE_REGISTER;
+
+ULONGLONG
+READ_ICIC_REGISTER(
+ IN PVOID TxQva,
+ IN ICIC_REGISTER IcIcRegister
+ );
+
+VOID
+WRITE_ICIC_REGISTER(
+ IN PVOID TxQva,
+ IN ICIC_REGISTER IcIcRegister,
+ IN ULONGLONG Value
+ );
+
+#endif // _ICICH_
diff --git a/private/ntos/nthals/halsable/alpha/idle.s b/private/ntos/nthals/halsable/alpha/idle.s
new file mode 100644
index 000000000..f517bab2f
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/idle.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\idle.s"
+
diff --git a/private/ntos/nthals/halsable/alpha/info.c b/private/ntos/nthals/halsable/alpha/info.c
new file mode 100644
index 000000000..22aef63a3
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/info.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\info.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/inithal.c b/private/ntos/nthals/halsable/alpha/inithal.c
new file mode 100644
index 000000000..a99cb9a1a
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/inithal.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\inithal.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/intsup.s b/private/ntos/nthals/halsable/alpha/intsup.s
new file mode 100644
index 000000000..4716cba36
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/intsup.s
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+#include "sablertc.h"
+#include "..\halalpha\intsup.s"
+
diff --git a/private/ntos/nthals/halsable/alpha/ioproc.c b/private/ntos/nthals/halsable/alpha/ioproc.c
new file mode 100644
index 000000000..cc65eacde
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/ioproc.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\ioproc.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/iousage.c b/private/ntos/nthals/halsable/alpha/iousage.c
new file mode 100644
index 000000000..83cbfb656
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/iousage.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\iousage.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/lyintsup.c b/private/ntos/nthals/halsable/alpha/lyintsup.c
new file mode 100644
index 000000000..b9f6486dc
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/lyintsup.c
@@ -0,0 +1,517 @@
+/*++
+
+Copyright (c) 1995 Digital Equipment Corporation
+
+Module Name:
+
+ lyintsup.c
+
+Abstract:
+
+ This module provides interrupt support for the Lynx family
+ Standard I/O board.
+
+Author:
+
+ Dave Richards 31-May-1995
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "t2.h"
+#include "icic.h"
+#include "xiintsup.h"
+
+//
+// Define the context structure for use by interrupt service routines.
+//
+
+typedef BOOLEAN (*PSECOND_LEVEL_DISPATCH)(
+ PKINTERRUPT InterruptObject
+ );
+
+//
+// Cached copies of the corresponding ICIC registers.
+//
+
+ICIC_ELCR_REGISTER LynxIcIcElcrRegister;
+ICIC_MASK_REGISTER LynxIcIcMaskRegister;
+
+
+ULONG
+HalpGetLynxSioInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+{
+ *Irql = DEVICE_LEVEL;
+ *Affinity = HAL_CPU0_MASK;
+
+ switch( BusInterruptLevel ){
+
+ case EisaInterruptLevel3:
+ return( LynxEisaIrq3Vector );
+
+ case EisaInterruptLevel4:
+ return( LynxEisaIrq4Vector );
+
+ case EisaInterruptLevel5:
+ return( LynxEisaIrq5Vector );
+
+ case EisaInterruptLevel6:
+ return( LynxEisaIrq6Vector );
+
+ case EisaInterruptLevel7:
+ return( LynxEisaIrq7Vector );
+
+ case EisaInterruptLevel9:
+ return( LynxEisaIrq9Vector );
+
+ case EisaInterruptLevel10:
+ return( LynxEisaIrq10Vector );
+
+ case EisaInterruptLevel11:
+ return( LynxEisaIrq11Vector );
+
+ case EisaInterruptLevel12:
+ return( LynxEisaIrq12Vector );
+
+ case EisaInterruptLevel14:
+ return( LynxEisaIrq14Vector );
+
+ case EisaInterruptLevel15:
+ return( LynxEisaIrq15Vector );
+
+ //
+ // Handle Vectors for the Internal bus devices.
+ //
+
+ case LynxMouseVector:
+ case LynxKeyboardVector:
+ case LynxFloppyVector:
+ case LynxSerialPort1Vector:
+ case LynxParallelPortVector:
+ case LynxSerialPort0Vector:
+ case LynxI2cVector:
+
+ //
+ // Handle Vectors for PCI devices.
+ //
+
+ case LynxScsi0Vector:
+ case LynxScsi1Vector:
+ case LynxPciSlot0AVector:
+ case LynxPciSlot0BVector:
+ case LynxPciSlot0CVector:
+ case LynxPciSlot0DVector:
+ case LynxPciSlot1AVector:
+ case LynxPciSlot1BVector:
+ case LynxPciSlot1CVector:
+ case LynxPciSlot1DVector:
+ case LynxPciSlot2AVector:
+ case LynxPciSlot2BVector:
+ case LynxPciSlot2CVector:
+ case LynxPciSlot2DVector:
+ case LynxPciSlot3AVector:
+ case LynxPciSlot3BVector:
+ case LynxPciSlot3CVector:
+ case LynxPciSlot3DVector:
+ case LynxPciSlot4AVector:
+ case LynxPciSlot4BVector:
+ case LynxPciSlot4CVector:
+ case LynxPciSlot4DVector:
+ case LynxPciSlot5AVector:
+ case LynxPciSlot5BVector:
+ case LynxPciSlot5CVector:
+ case LynxPciSlot5DVector:
+ case LynxPciSlot6AVector:
+ case LynxPciSlot6BVector:
+ case LynxPciSlot6CVector:
+ case LynxPciSlot6DVector:
+ case LynxPciSlot7AVector:
+ case LynxPciSlot7BVector:
+ case LynxPciSlot7CVector:
+ case LynxPciSlot7DVector:
+
+ return( BusInterruptLevel );
+
+ default:
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+ return HalpGetXioInterruptVector(
+ BusHandler,
+ RootHandler,
+ BusInterruptLevel,
+ BusInterruptVector,
+ Irql,
+ Affinity
+ );
+
+#else
+
+ *Irql = 0;
+ *Affinity = 0;
+ return 0;
+
+#endif
+
+ }
+}
+
+
+BOOLEAN
+HalpInitializeLynxSioInterrupts(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the ICIC on the Standard I/O module.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ TRUE.
+
+--*/
+
+{
+ T2_ICE Ice;
+ ICIC_EISA_REGISTER LynxIcIcEisaRegister;
+
+ //
+ // Initialize the interface between the T3/T4 and the ICIC.
+ //
+
+ Ice.all = 0;
+ Ice.EisaFlushAddress = 0x542;
+ Ice.IcEnable = 1;
+ Ice.HalfSpeedEnable = 0;
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Ice,
+ Ice.all );
+
+ //
+ // Initialize the ICIC Mask Register.
+ //
+
+ LynxIcIcMaskRegister = (ULONGLONG)-1;
+
+ WRITE_ICIC_REGISTER( T2_CSRS_QVA, IcIcMaskRegister,
+ LynxIcIcMaskRegister );
+
+ //
+ // Initialize the ICIC Edge/Level Control Register.
+ //
+
+ LynxIcIcElcrRegister =
+ ((ICIC_ELCR_REGISTER)1 << (LynxScsi0Vector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxScsi1Vector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot4AVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot4BVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot4CVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot4DVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot5AVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot5BVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot5CVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot5DVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot6AVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot6BVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot6CVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot6DVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot7AVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot7BVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot7CVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot7DVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot7DVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot0AVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot0BVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot0CVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot0DVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot1AVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot1BVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot1CVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot1DVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot2AVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot2BVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot2CVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot2DVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot3AVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot3BVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot3CVector - LynxBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (LynxPciSlot3DVector - LynxBaseVector));
+
+ WRITE_ICIC_REGISTER( T2_CSRS_QVA, IcIcElcrRegister,
+ LynxIcIcElcrRegister );
+
+ //
+ // Initialize the ICIC EISA Register.
+ //
+
+ LynxIcIcEisaRegister =
+ (1 << (LynxEisaIrq3Vector - LynxBaseVector)) |
+ (1 << (LynxEisaIrq4Vector - LynxBaseVector)) |
+ (1 << (LynxEisaIrq5Vector - LynxBaseVector)) |
+ (1 << (LynxEisaIrq6Vector - LynxBaseVector)) |
+ (1 << (LynxEisaIrq7Vector - LynxBaseVector)) |
+ (1 << (LynxEisaIrq9Vector - LynxBaseVector)) |
+ (1 << (LynxEisaIrq10Vector - LynxBaseVector)) |
+ (1 << (LynxEisaIrq11Vector - LynxBaseVector)) |
+ (1 << (LynxEisaIrq12Vector - LynxBaseVector)) |
+ (1 << (LynxEisaIrq14Vector - LynxBaseVector)) |
+ (1 << (LynxEisaIrq15Vector - LynxBaseVector));
+
+ WRITE_ICIC_REGISTER( T2_CSRS_QVA, IcIcEisaRegister,
+ LynxIcIcEisaRegister );
+
+ //
+ // Initialize the ICIC Mode Register.
+ //
+
+ WRITE_ICIC_REGISTER( T2_CSRS_QVA, IcIcModeRegister, (ULONGLONG)0 );
+
+ return TRUE;
+}
+
+BOOLEAN
+HalpLynxSioDispatch(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine dispatches interrupts received by the Standard I/O
+ ICIC.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A boolean value indicating whether the interrupt was handled by
+ the FLIH/SLIH.
+
+--*/
+
+{
+ T2_VAR Var;
+ PULONG DispatchCode;
+ PKINTERRUPT InterruptObject;
+ BOOLEAN ReturnValue;
+
+ //
+ // Get the interrupt vector.
+ //
+
+ Var.all = READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Var );
+
+ //
+ // If this is a passive release, ignore the interrupt.
+ //
+
+ if( Var.PassiveRelease == 1 ){
+
+ return(TRUE);
+
+ }
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ DispatchCode = (PULONG)PCR->InterruptRoutine[LynxBaseVector + Var.Vector];
+ InterruptObject = CONTAINING_RECORD(DispatchCode,
+ KINTERRUPT,
+ DispatchCode);
+
+ ReturnValue = ((PSECOND_LEVEL_DISPATCH)InterruptObject->DispatchAddress)(InterruptObject);
+
+ //
+ // Send an SEOI.
+ //
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Var, Var.Vector );
+
+ return(ReturnValue);
+}
+
+VOID
+HalpDisableLynxSioInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This routine disables interrupts associated with the Standard I/O
+ ICIC.
+
+Arguments:
+
+ Vector - The vector of the interrupt to disable.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONGLONG IrqMask;
+
+ if( (Vector >= LynxBaseVector) &&
+ (Vector <= LynxPciSlot3DVector) ){
+
+ //
+ // Compute the IRQ mask.
+ //
+
+ IrqMask = (ICIC_MASK_REGISTER)1 << (Vector - LynxBaseVector);
+
+ //
+ // Mask the interrupt.
+ //
+
+ LynxIcIcMaskRegister |= IrqMask;
+
+ //
+ // Update the ICIC Mask Register.
+ //
+
+ WRITE_ICIC_REGISTER( T2_CSRS_QVA, IcIcMaskRegister,
+ LynxIcIcMaskRegister );
+
+ } else {
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+ HalpDisableXioInterrupt( Vector );
+
+#endif
+
+ }
+}
+
+BOOLEAN
+HalpEnableLynxSioInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables interrupts associated with the Standard I/O
+ ICIC.
+
+Arguments:
+
+ Vector - The vector of the interrupt to enable.
+
+ InterruptMode - An indication of whether the interrupt should
+ be edge-triggered/level-sensitive.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONGLONG IrqMask;
+
+ if( (Vector >= LynxBaseVector) &&
+ (Vector <= LynxPciSlot3DVector) ){
+
+ //
+ // Compute the IRQ mask.
+ //
+
+ IrqMask = (ICIC_MASK_REGISTER)1 << (Vector - LynxBaseVector);
+
+ //
+ // For EISA interrupts InterruptMode indicates whether the interrupt
+ // is level sensitive (active low) or edge-triggered (low-to-high).
+ // We use this information to update the Edge/Level Control Register
+ // bit for this IRQ.
+ //
+
+ switch( Vector ){
+
+ case LynxEisaIrq3Vector:
+ case LynxEisaIrq4Vector:
+ case LynxEisaIrq5Vector:
+ case LynxEisaIrq6Vector:
+ case LynxEisaIrq7Vector:
+ case LynxEisaIrq9Vector:
+ case LynxEisaIrq10Vector:
+ case LynxEisaIrq11Vector:
+ case LynxEisaIrq12Vector:
+ case LynxEisaIrq14Vector:
+ case LynxEisaIrq15Vector:
+
+ //
+ // Set/Clear the ELCR bit (as appropriate).
+ //
+
+ if( InterruptMode == LevelSensitive ){
+ LynxIcIcElcrRegister |= IrqMask;
+ } else {
+ LynxIcIcElcrRegister &= ~IrqMask;
+ }
+
+ //
+ // Update the ICIC Edge/Level Control Register.
+ //
+
+ WRITE_ICIC_REGISTER( T2_CSRS_QVA, IcIcElcrRegister,
+ LynxIcIcElcrRegister );
+
+ break;
+
+ }
+
+ //
+ // Un-mask the interrupt.
+ //
+
+ LynxIcIcMaskRegister &= ~IrqMask;
+
+ //
+ // Update the ICIC Mask Register.
+ //
+
+ WRITE_ICIC_REGISTER( T2_CSRS_QVA, IcIcMaskRegister,
+ LynxIcIcMaskRegister );
+
+ return TRUE;
+
+ } else {
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+ return HalpEnableXioInterrupt( Vector, InterruptMode );
+
+#endif
+
+ }
+
+ return FALSE;
+}
diff --git a/private/ntos/nthals/halsable/alpha/lyintsup.h b/private/ntos/nthals/halsable/alpha/lyintsup.h
new file mode 100644
index 000000000..0f43e9b0d
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/lyintsup.h
@@ -0,0 +1,50 @@
+/*++
+
+Copyright (c) 1995 Digital Equipment Corporation
+
+Module Name:
+
+ lyintsup.h
+
+Abstract:
+
+ This header file contains prototypes for lyintsup.c.
+
+Author:
+
+ Dave Richards 31-May-1995
+
+Revision History:
+
+--*/
+
+ULONG
+HalpGetLynxSioInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+BOOLEAN
+HalpInitializeLynxSioInterrupts(
+ VOID
+ );
+
+BOOLEAN
+HalpLynxSioDispatch(
+ VOID
+ );
+
+VOID
+HalpDisableLynxSioInterrupt(
+ IN ULONG Vector
+ );
+
+BOOLEAN
+HalpEnableLynxSioInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
diff --git a/private/ntos/nthals/halsable/alpha/lynxref.h b/private/ntos/nthals/halsable/alpha/lynxref.h
new file mode 100644
index 000000000..5275062ff
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/lynxref.h
@@ -0,0 +1,111 @@
+/*++
+
+Copyright (c) 1995 Digital Equipment Corporation
+
+Module Name:
+
+ lynxref.h
+
+Abstract:
+
+ This file defines the structures and definitions of the Lynx
+ interrupt architecture.
+
+Author:
+
+ Dave Richards 12-May-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#ifndef _LYNXREFH_
+#define _LYNXREFH_
+
+#if !defined(_LANGUAGE_ASSEMBLY)
+
+enum _LYNX_INTERRUPT_VECTORS {
+
+ LynxBaseVector = 0x80, // Lynx/SIO Base Vector
+ LynxReservedVector = 0x80, //
+ LynxIcIcIrq0 = 0x80, //
+ LynxIcIcIrq1, //
+ LynxIcIcIrq2, // ESC interrupt
+ LynxMouseVector, // Mouse
+ LynxIcIcIrq4, //
+ LynxIcIcIrq5, //
+ LynxKeyboardVector, // Keyboard
+ LynxFloppyVector, // Floppy
+ LynxSerialPort1Vector, // Serial port 1 (COM2)
+ LynxParallelPortVector, // Parallel port
+ LynxEisaIrq3Vector, // EISA IRQ 3
+ LynxEisaIrq4Vector, // EISA IRQ 4
+ LynxEisaIrq5Vector, // EISA IRQ 5
+ LynxEisaIrq6Vector, // EISA IRQ 6
+ LynxEisaIrq7Vector, // EISA IRQ 7
+ LynxSerialPort0Vector, // Serial port 0 (COM1)
+ LynxEisaIrq9Vector, // EISA IRQ 9
+ LynxEisaIrq10Vector, // EISA IRQ 10
+ LynxEisaIrq11Vector, // EISA IRQ 11
+ LynxEisaIrq12Vector, // EISA IRQ 12
+ LynxIcIcIrq20, //
+ LynxEisaIrq14Vector, // EISA IRQ 14
+ LynxEisaIrq15Vector, // EISA IRQ 15
+ LynxI2cVector, // I^2C
+ LynxScsi0Vector = 0x98, // SCSI
+ RmLpLynxEthVector = 0x98, // RM/LP (Spanky) on-board Tulip
+ LynxIcIcIrq25, //
+ LynxIcIcIrq26, //
+ LynxIcIcIrq27, //
+ LynxScsi1Vector, // SCSI
+ LynxIcIcIrq29, //
+ LynxIcIcIrq30, //
+ LynxIcIcIrq31, //
+ LynxPciSlot4AVector, // PCI Slot 4 A
+ LynxPciSlot4BVector, // PCI Slot 4 B
+ LynxPciSlot4CVector, // PCI Slot 4 C
+ LynxPciSlot4DVector, // PCI Slot 4 D
+ LynxPciSlot5AVector, // PCI Slot 5 A
+ LynxPciSlot5BVector, // PCI Slot 5 B
+ LynxPciSlot5CVector, // PCI Slot 5 C
+ LynxPciSlot5DVector, // PCI Slot 5 D
+ LynxPciSlot6AVector, // PCI Slot 6 A
+ LynxPciSlot6BVector, // PCI Slot 6 B
+ LynxPciSlot6CVector, // PCI Slot 6 C
+ LynxPciSlot6DVector, // PCI Slot 6 D
+ LynxPciSlot7AVector, // PCI Slot 7 A
+ LynxPciSlot7BVector, // PCI Slot 7 B
+ LynxPciSlot7CVector, // PCI Slot 7 C
+ LynxPciSlot7DVector, // PCI Slot 7 D
+ LynxPciSlot0AVector, // PCI Slot 0 A
+ LynxPciSlot0BVector, // PCI Slot 0 B
+ LynxPciSlot0CVector, // PCI Slot 0 C
+ LynxPciSlot0DVector, // PCI Slot 0 D
+ LynxPciSlot1AVector, // PCI Slot 1 A
+ LynxPciSlot1BVector, // PCI Slot 1 B
+ LynxPciSlot1CVector, // PCI Slot 1 C
+ LynxPciSlot1DVector, // PCI Slot 1 D
+ LynxPciSlot2AVector, // PCI Slot 2 A
+ LynxPciSlot2BVector, // PCI Slot 2 B
+ LynxPciSlot2CVector, // PCI Slot 2 C
+ LynxPciSlot2DVector, // PCI Slot 2 D
+ LynxPciSlot3AVector, // PCI Slot 3 A
+ LynxPciSlot3BVector, // PCI Slot 3 B
+ LynxPciSlot3CVector, // PCI Slot 3 C
+ LynxPciSlot3DVector, // PCI Slot 3 D
+
+};
+
+//
+// The following variable indicates whether this is a Lynx platform.
+//
+
+extern BOOLEAN HalpLynxPlatform;
+
+#endif // _LANGUAGE_ASSEMBLY
+
+#endif // _LYNXREFH_
diff --git a/private/ntos/nthals/halsable/alpha/machdep.h b/private/ntos/nthals/halsable/alpha/machdep.h
new file mode 100644
index 000000000..c88134e44
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/machdep.h
@@ -0,0 +1,42 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ machdep.h
+
+Abstract:
+
+ This file includes the platform-dependent include files used to
+ build the HAL.
+
+Author:
+
+ Joe Notarangelo 01-Dec-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#ifndef _MACHDEP_
+#define _MACHDEP_
+
+//
+// Include Sable platform-specific definitions.
+//
+
+#include "sable.h"
+
+//
+// Include scatter/gather definitions.
+//
+
+#include "ebsgdma.h"
+
+#endif //_MACHDEP_
diff --git a/private/ntos/nthals/halsable/alpha/memory.c b/private/ntos/nthals/halsable/alpha/memory.c
new file mode 100644
index 000000000..76b1eb7df
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/memory.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\memory.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/pcibus.c b/private/ntos/nthals/halsable/alpha/pcibus.c
new file mode 100644
index 000000000..2f8eb2b84
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/pcibus.c
@@ -0,0 +1,118 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporationn, Digital Equipment Corporation
+
+Module Name:
+
+ pcibus.c
+
+Abstract:
+
+ Platform-specific PCI bus routines
+
+Author:
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "machdep.h"
+
+PCI_CONFIGURATION_TYPES
+HalpPCIConfigCycleType(
+ IN PBUS_HANDLER BusHandler
+ )
+{
+ BOOLEAN BusIsAcrossPPB;
+
+ BusIsAcrossPPB = ((PPCIPBUSDATA)(BusHandler->BusData))->BusIsAcrossPPB;
+
+ //
+ // If the bus is across a PCI-to-PCI bridge use type 1 configuration
+ // cycles, otherwise use type 0.
+ //
+
+ if( BusIsAcrossPPB ){
+
+ return PciConfigType1;
+
+ } else {
+
+ return PciConfigType0;
+
+ }
+}
+
+VOID
+HalpPCIConfigAddr(
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ PPCI_CFG_CYCLE_BITS pPciAddr
+ )
+{
+ PCI_CONFIGURATION_TYPES ConfigType;
+ ULONG HwBusNumber;
+
+ HwBusNumber = ((PPCIPBUSDATA)(BusHandler->BusData))->HwBusNumber;
+
+ ConfigType = HalpPCIConfigCycleType(BusHandler);
+
+ if( ConfigType == PciConfigType0 ){
+
+ //
+ // Initialize pPciAddr for a type 0 configuration cycle. Device
+ // number is mapped to address bits 11:24, which are wired to the
+ // IDSEL pins.
+ //
+
+ if( HwBusNumber == 0 ){
+
+ pPciAddr->u.AsULONG = (ULONG)
+ (HAL_MAKE_QVA(SABLE_PCI0_CONFIGURATION_PHYSICAL));
+
+ } else {
+
+ pPciAddr->u.AsULONG = (ULONG)
+ (HAL_MAKE_QVA(SABLE_PCI1_CONFIGURATION_PHYSICAL));
+ }
+
+ pPciAddr->u.AsULONG += (1 << (Slot.u.bits.DeviceNumber + 11));
+ pPciAddr->u.bits0.FunctionNumber = Slot.u.bits.FunctionNumber;
+ pPciAddr->u.bits0.Reserved1 = PciConfigType0;
+
+ } else {
+
+ //
+ // Initialize pPciAddr for a type 1 configuration cycle.
+ //
+
+ pPciAddr->u.AsULONG = 0;
+ pPciAddr->u.bits1.BusNumber = BusHandler->BusNumber;
+ pPciAddr->u.bits1.FunctionNumber = Slot.u.bits.FunctionNumber;
+ pPciAddr->u.bits1.DeviceNumber = Slot.u.bits.DeviceNumber;
+ pPciAddr->u.bits1.Reserved1 = PciConfigType1;
+
+ if( HwBusNumber == 0 ){
+
+ pPciAddr->u.AsULONG += (ULONG)
+ (HAL_MAKE_QVA(SABLE_PCI0_CONFIGURATION_PHYSICAL));
+
+ } else {
+
+ pPciAddr->u.AsULONG += (ULONG)
+ (HAL_MAKE_QVA(SABLE_PCI1_CONFIGURATION_PHYSICAL));
+
+ }
+
+ }
+
+ return;
+}
diff --git a/private/ntos/nthals/halsable/alpha/pcisup.c b/private/ntos/nthals/halsable/alpha/pcisup.c
new file mode 100644
index 000000000..360919f42
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/pcisup.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcisup.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/pcrtc.c b/private/ntos/nthals/halsable/alpha/pcrtc.c
new file mode 100644
index 000000000..2e57b87d6
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/pcrtc.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcrtc.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/pcrtc.h b/private/ntos/nthals/halsable/alpha/pcrtc.h
new file mode 100644
index 000000000..f4d1bff50
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/pcrtc.h
@@ -0,0 +1,102 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ d1287rtc.h
+
+Abstract:
+
+ This module is the header file that describes hardware structure
+ for the Dallas 1287 Toy clock.
+
+Author:
+
+ David N. Cutler (davec) 3-May-1991
+ Jeff McLeman (mcleman) 4-Jun-1992
+
+Revision History:
+
+ 94.01.16 Steve Jenness
+
+ Split out the Dallas RTC definitions from the platform specific
+ RTC definitions.
+
+--*/
+
+#ifndef _D1287RTC_
+#define _D1287RTC_
+
+//
+// Define Realtime Clock register numbers.
+//
+
+#define RTC_SECOND 0 // second of minute [0..59]
+#define RTC_SECOND_ALARM 1 // seconds to alarm
+#define RTC_MINUTE 2 // minute of hour [0..59]
+#define RTC_MINUTE_ALARM 3 // minutes to alarm
+#define RTC_HOUR 4 // hour of day [0..23]
+#define RTC_HOUR_ALARM 5 // hours to alarm
+#define RTC_DAY_OF_WEEK 6 // day of week [1..7]
+#define RTC_DAY_OF_MONTH 7 // day of month [1..31]
+#define RTC_MONTH 8 // month of year [1..12]
+#define RTC_YEAR 9 // year [00..99]
+#define RTC_CONTROL_REGISTERA 10 // control register A
+#define RTC_CONTROL_REGISTERB 11 // control register B
+#define RTC_CONTROL_REGISTERC 12 // control register C
+#define RTC_CONTROL_REGISTERD 13 // control register D
+
+
+#ifndef _LANGUAGE_ASSEMBLY
+
+//
+// Define Control Register A structure.
+//
+
+typedef struct _RTC_CONTROL_REGISTER_A {
+ UCHAR RateSelect : 4;
+ UCHAR TimebaseDivisor : 3;
+ UCHAR UpdateInProgress : 1;
+} RTC_CONTROL_REGISTER_A, *PRTC_CONTROL_REGISTER_A;
+
+//
+// Define Control Register B structure.
+//
+
+typedef struct _RTC_CONTROL_REGISTER_B {
+ UCHAR DayLightSavingsEnable : 1;
+ UCHAR HoursFormat : 1;
+ UCHAR DataMode : 1;
+ UCHAR SquareWaveEnable : 1;
+ UCHAR UpdateInterruptEnable : 1;
+ UCHAR AlarmInterruptEnable : 1;
+ UCHAR TimerInterruptEnable : 1;
+ UCHAR SetTime : 1;
+} RTC_CONTROL_REGISTER_B, *PRTC_CONTROL_REGISTER_B;
+
+//
+// Define Control Register C structure.
+//
+
+typedef struct _RTC_CONTROL_REGISTER_C {
+ UCHAR Fill : 4;
+ UCHAR UpdateInterruptFlag : 1;
+ UCHAR AlarmInterruptFlag : 1;
+ UCHAR TimeInterruptFlag : 1;
+ UCHAR InterruptRequest : 1;
+} RTC_CONTROL_REGISTER_C, *PRTC_CONTROL_REGISTER_C;
+
+//
+// Define Control Register D structure.
+//
+
+typedef struct _RTC_CONTROL_REGISTER_D {
+ UCHAR Fill : 7;
+ UCHAR ValidTime : 1;
+} RTC_CONTROL_REGISTER_D, *PRTC_CONTROL_REGISTER_D;
+
+#endif // _LANGUAGE_ASSEMBLY
+
+#endif // _SABLERTC_
diff --git a/private/ntos/nthals/halsable/alpha/pcserial.c b/private/ntos/nthals/halsable/alpha/pcserial.c
new file mode 100644
index 000000000..a2f159c48
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/pcserial.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcserial.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/pcspeakr.c b/private/ntos/nthals/halsable/alpha/pcspeakr.c
new file mode 100644
index 000000000..807b6f324
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/pcspeakr.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\pcspeakr.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/perf8254.c b/private/ntos/nthals/halsable/alpha/perf8254.c
new file mode 100644
index 000000000..5fade7e42
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/perf8254.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\perf8254.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/pintolin.h b/private/ntos/nthals/halsable/alpha/pintolin.h
new file mode 100644
index 000000000..d0cd18244
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/pintolin.h
@@ -0,0 +1,544 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ pintolin.h
+
+Abstract:
+
+ This file includes the platform-dependent Pin To Line Tables
+
+Author:
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ James Livingston (Digital) 23-June-1994
+
+ Extracted Sable table from common.
+
+ Dick Bissen [DEC] 12-May-1994
+
+ Changed EB66PCIPinToLineTable for pass2 of the module.
+
+--*/
+
+//
+// These tables represent the mapping from slot number and interrupt pin
+// into a PCI Interrupt Vector.
+// On Mustang and EB66, the interrupt vector is Interrupt Request Register bit
+// representing that interrupt + 1.
+// On EB66, the value also represents the Interrupt Mask Register Bit,
+// since it is identical to the Interrupt Read Register. On Mustang,
+// the Interrupt Mask Register only allows masking of all interrupts
+// from the two plug-in slots.
+//
+// Formally, these mappings can be expressed as:
+//
+// PCIPinToLine:
+// SlotNumber.DeviceNumber x InterruptPin -> InterruptLine
+//
+// LineToVector:
+// InterruptLine -> InterruptVector
+//
+// VectorToIRRBit:
+// InterruptVector -> InterruptRequestRegisterBit
+//
+// VectorToIMRBit:
+// InterruptVector -> InterruptMaskRegisterBit
+//
+// SlotNumberToIDSEL:
+// SlotNumber.DeviceNumber -> IDSEL
+//
+// subject to following invariants (predicates must always be true):
+//
+// Slot.DeviceNumber in {0,...,15}
+//
+// InterruptPin in {1, 2, 3, 4}
+//
+// InterruptRequestRegisterBit in {0,...,15}
+//
+// InterruptMaskRegisterBit in {0,...,15}
+//
+// PCIPinToLine(SlotNumber.DeviceNumber, InterruptPin) =
+// PCIPinToLineTable[SlotNumber.DeviceNumber, InterruptPin]
+// (Table-lookup function initialized below)
+//
+// LineToVector(InterruptLine) = PCI_VECTORS + InterruptLine
+//
+// VectorToIRRBit(InterruptVector) = InterruptVector - 1
+//
+// VectorToIMRBit(InterruptVector) [see below]
+//
+// SlotNumberToIDSEL(SlotNumber.DeviceNumber) = (1 << (Slot.DeviceNumber+11))
+//
+// where:
+//
+// SlotNumber.DeviceNumber:
+// Alpha AXP Platforms receive interrupts on local PCI buses only, which
+// are limited to 16 devices (PCI AD[11]-AD[26]). (We loose AD[17]-AD[31]
+// since PCI Config space is a sparse space, requiring a five-bit shift.)
+//
+// InterruptPin:
+// Each virtual slot has up to four interrupt pins INTA#, INTB#, INTC#, INTD#,
+// as per the PCI Spec. V2.0, Section 2.2.6. (FYI, only multifunction devices
+// use INTB#, INTC#, INTD#.)
+//
+// PCI configuration space indicates which interrupt pin a device will use
+// in the InterruptPin register, which has the values:
+//
+// INTA# = 1, INTB#=2, INTC#=3, INTD# = 4
+//
+// Note that there may be up to 8 functions/device on a PCI multifunction
+// device plugged into the option slots, e.g., Slot #0.
+// Each function has its own PCI configuration space, addressed
+// by the SlotNumber.FunctionNumber field, and will identify which
+// interrput pin of the four it will use in its own InterruptPin register.
+//
+// If the option is a PCI-PCI bridge, interrupts across the bridge will
+// somehow be combined to appear on some combination of the four
+// interrupt pins that the bridge plugs into.
+//
+// InterruptLine:
+// This PCI Configuration register, unlike x86 PC's, is maintained by
+// software and represents offset into PCI interrupt vectors.
+// Whenever HalGetBusData or HalGetBusDataByOffset is called,
+// HalpPCIPinToLine() computes the correct InterruptLine register value
+// by using the SablePCIPinToLineTable mapping.
+//
+// InterruptRequestRegisterBit:
+// 0xff is used to mark an invalid IRR bit, hence an invalid request
+// for a vector. Also, note that the 16 bits of the EB66 IRR must
+// be access as two 8-bit reads.
+//
+// InterruptMaskRegisterBit:
+// On EB66, the PinToLine table may also be find the to write the
+// InterruptMaskRegister. Formally, we can express this invariant as
+//
+// VectorToIMRBit(InterrruptVector) = InterruptVector - 1
+//
+// On Mustang, the table is useless. The InterruptMaskRegister has
+// only two bits the completely mask all interrupts from either
+// Slot #0 or Slot#1 (PCI AD[17] and AD[18]):
+//
+// InterruptVector in {3,4,5,6} then VectorToIMRBit(InterruptVector) = 0
+// InterruptVector in {7,8,9,10} then VectorToIMRBit(InterruptVector) = 1
+//
+// IDSEL:
+// For accessing PCI configuration space on a local PCI bus (as opposed
+// to over a PCI-PCI bridge), type 0 configuration cycles must be generated.
+// In this case, the IDSEL pin of the device to be accessed is tied to one
+// of the PCI Address lines AD[11] - AD[26]. (The function field in the
+// PCI address is used should we be accessing a multifunction device.)
+// Anyway, virtual slot 0 represents the device with IDSEL = AD[11], and
+// so on.
+//
+
+#if 0
+
+//
+// The following PinToLineTable is used with old
+// Standard I/O boards that didn't have the 5th 8259.
+// The 5th 8259 (Slave 3) was added to break out the
+// PCI A,B,C,D interrupts to separate interrupt pins.
+//
+
+ULONG OldSablePCIPinToLineTable[][4] = {
+ { EthernetPortVector, // Virtual Slot 0 = PCI_AD[11] Tulip
+ EthernetPortVector,
+ EthernetPortVector,
+ EthernetPortVector },
+
+ { ScsiPortVector, // Virtual Slot 1 = PCI_AD[12] SCSI
+ ScsiPortVector,
+ ScsiPortVector,
+ ScsiPortVector },
+
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 2 = PCI_AD[13] Eisa Bridge
+
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 3 = PCI_AD[14] Not used
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 4 = PCI_AD[15] Not used
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 5 = PCI_AD[16] Not used
+
+ { OldPciSlot0Vector, // Virtual Slot 6 = PCI_AD[17] Phys. Slot #0
+ OldPciSlot0Vector,
+ OldPciSlot0Vector,
+ OldPciSlot0Vector },
+
+ { OldPciSlot1Vector, // Virtual Slot 7 = PCI_AD[18] Phys. Slot #1
+ OldPciSlot1Vector,
+ OldPciSlot1Vector,
+ OldPciSlot1Vector },
+
+ { OldPciSlot2Vector, // Virtual Slot 8 = PCI_AD[19] Phys. Slot #2
+ OldPciSlot2Vector,
+ OldPciSlot2Vector,
+ OldPciSlot2Vector },
+
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 9 = PCI_AD[20] Not used
+ { 0xff, 0xff, 0xff, 0xff } // Virtual Slot 10 = PCI_AD[21] Not used
+};
+
+#endif
+
+//
+// Interrupt Vector Table Mapping for Sable (PCI 0)
+//
+
+ULONG SablePinToLineTable[][4] = {
+ { EthernetPortVector, // Virtual Slot 0 = PCI_AD[11] Tulip
+ EthernetPortVector,
+ EthernetPortVector,
+ EthernetPortVector },
+
+ { ScsiPortVector, // Virtual Slot 1 = PCI_AD[12] SCSI
+ ScsiPortVector,
+ ScsiPortVector,
+ ScsiPortVector },
+
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 2 = PCI_AD[13] Eisa Bridge
+
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 3 = PCI_AD[14] Not used
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 4 = PCI_AD[15] Not used
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 5 = PCI_AD[16] Not used
+
+ { PciSlot0AVector, // Virtual Slot 6 = PCI_AD[17] Phys. Slot #0
+ PciSlot0BVector,
+ PciSlot0CVector,
+ PciSlot0DVector },
+
+ { PciSlot1AVector, // Virtual Slot 7 = PCI_AD[18] Phys. Slot #1
+ PciSlot1BVector,
+ PciSlot1CVector,
+ PciSlot1DVector },
+
+ { PciSlot2AVector, // Virtual Slot 8 = PCI_AD[19] Phys. Slot #2
+ PciSlot2BVector,
+ PciSlot2CVector,
+ PciSlot2DVector },
+
+ { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 9 = PCI_AD[20] Not used
+ { 0xff, 0xff, 0xff, 0xff } // Virtual Slot 10 = PCI_AD[21] Not used
+};
+
+//
+// Interrupt Vector Table Mapping for Lynx (PCI 0)
+//
+
+ULONG LynxPinToLineTable1[][4] = {
+
+ { LynxReservedVector, // Virtual slot 0 - reserved
+ LynxReservedVector,
+ LynxReservedVector,
+ LynxReservedVector },
+
+ { LynxReservedVector, // Virtual slot 1 - reserved
+ LynxReservedVector,
+ LynxReservedVector,
+ LynxReservedVector },
+
+ { LynxReservedVector, // Virtual slot 2 - PCI-EISA Bridge
+ LynxReservedVector,
+ LynxReservedVector,
+ LynxReservedVector },
+
+ { LynxReservedVector, // Virtual slot 3 - PCI-PCI Bridge
+ LynxReservedVector,
+ LynxReservedVector,
+ LynxReservedVector },
+
+ { LynxScsi0Vector, // Virtual slot 4 - NCRC810A
+ LynxReservedVector,
+ LynxReservedVector,
+ LynxReservedVector },
+
+ { LynxReservedVector, // Virtual slot 5 - reserved
+ LynxReservedVector,
+ LynxReservedVector,
+ LynxReservedVector },
+
+ { LynxPciSlot4AVector, // Virtual slot 6 - PCI slot 4
+ LynxPciSlot4BVector,
+ LynxPciSlot4CVector,
+ LynxPciSlot4DVector },
+
+ { LynxPciSlot5AVector, // Virtual slot 7 - PCI slot 5
+ LynxPciSlot5BVector,
+ LynxPciSlot5CVector,
+ LynxPciSlot5DVector },
+
+ { LynxPciSlot6AVector, // Virtual slot 8 - PCI slot 6
+ LynxPciSlot6BVector,
+ LynxPciSlot6CVector,
+ LynxPciSlot6DVector },
+
+ { LynxPciSlot7AVector, // Virtual slot 9 - PCI slot 7
+ LynxPciSlot7BVector,
+ LynxPciSlot7CVector,
+ LynxPciSlot7DVector },
+
+ { LynxReservedVector, // Virtual slot 10 - reserved
+ LynxReservedVector,
+ LynxReservedVector,
+ LynxReservedVector }
+};
+
+ULONG LynxPinToLineTable2[][4] = {
+ { RmLpLynxEthVector, // Virtual slot 0 - dc21040 for RM/LP
+ LynxReservedVector,
+ LynxReservedVector,
+ LynxReservedVector },
+
+ { LynxScsi1Vector, // Virtual slot 1 - NCRC810A (SCSI)
+ LynxReservedVector,
+ LynxReservedVector,
+ LynxReservedVector },
+
+ { LynxReservedVector, // Virtual slot 2 - reserved
+ LynxReservedVector,
+ LynxReservedVector,
+ LynxReservedVector },
+
+ { LynxReservedVector, // Virtual slot 3 - reserved
+ LynxReservedVector,
+ LynxReservedVector,
+ LynxReservedVector },
+
+ { LynxReservedVector, // Virtual slot 4 - reserved
+ LynxReservedVector,
+ LynxReservedVector,
+ LynxReservedVector },
+
+ { LynxReservedVector, // Virtual slot 5 - reserved
+ LynxReservedVector,
+ LynxReservedVector,
+ LynxReservedVector },
+
+ { LynxPciSlot0AVector, // Virtual slot 6 - PCI slot 0
+ LynxPciSlot0BVector,
+ LynxPciSlot0CVector,
+ LynxPciSlot0DVector },
+
+ { LynxPciSlot1AVector, // Virtual slot 7 - PCI slot 1
+ LynxPciSlot1BVector,
+ LynxPciSlot1CVector,
+ LynxPciSlot1DVector },
+
+ { LynxPciSlot2AVector, // Virtual slot 8 - PCI slot 2
+ LynxPciSlot2BVector,
+ LynxPciSlot2CVector,
+ LynxPciSlot2DVector },
+
+ { LynxPciSlot3AVector, // Virtual slot 9 - PCI slot 3
+ LynxPciSlot3BVector,
+ LynxPciSlot3CVector,
+ LynxPciSlot3DVector },
+
+ { LynxReservedVector, // Virtual slot 10 - reserved
+ LynxReservedVector,
+ LynxReservedVector,
+ LynxReservedVector },
+
+ { LynxReservedVector, // Virtual slot 11 - reserved
+ LynxReservedVector,
+ LynxReservedVector,
+ LynxReservedVector },
+
+ { LynxReservedVector, // Virtual slot 12 - reserved
+ LynxReservedVector,
+ LynxReservedVector,
+ LynxReservedVector },
+
+ { LynxReservedVector, // Virtual slot 13 - reserved
+ LynxReservedVector,
+ LynxReservedVector,
+ LynxReservedVector },
+
+ { LynxReservedVector, // Virtual slot 14 - reserved
+ LynxReservedVector,
+ LynxReservedVector,
+ LynxReservedVector },
+
+ { LynxReservedVector, // Virtual slot 15 - reserved
+ LynxReservedVector,
+ LynxReservedVector,
+ LynxReservedVector }
+};
+
+#ifdef XIO_PASS1
+
+//
+// Interrupt Vector Table Mapping for XIO (Pass 1)
+//
+
+ULONG XioPinToLineTable[][4] = {
+ { XioReservedVector, // Virtual slot 0 - reserved
+ XioReservedVector,
+ XioReservedVector,
+ XioReservedVector },
+
+ { XioPciSlot0AVector, // Virtual Slot 1 = PCI Slot 0
+ XioPciSlot0BVector,
+ XioPciSlot0CVector,
+ XioPciSlot0DVector },
+
+ { XioPciSlot1AVector, // Virtual Slot 2 = PCI Slot 1
+ XioPciSlot1BVector,
+ XioPciSlot1CVector,
+ XioPciSlot1DVector }
+};
+
+#endif // XIO_PASS1
+
+#ifdef XIO_PASS2
+
+//
+// Interrupt Vector Table Mapping for XIO (Pass 2)
+//
+
+ULONG XioPinToLineTable1[][4] = {
+ { XioReservedVector, // Virtual slot 0 - reserved
+ XioReservedVector,
+ XioReservedVector,
+ XioReservedVector },
+
+ { XioReservedVector, // Virtual slot 1 - reserved
+ XioReservedVector,
+ XioReservedVector,
+ XioReservedVector },
+
+ { XioReservedVector, // Virtual slot 2 - reserved
+ XioReservedVector,
+ XioReservedVector,
+ XioReservedVector },
+
+ { XioReservedVector, // Virtual slot 3 - PCI-PCI Bridge
+ XioReservedVector,
+ XioReservedVector,
+ XioReservedVector },
+
+ { XioReservedVector, // Virtual slot 4 - reserved
+ XioReservedVector,
+ XioReservedVector,
+ XioReservedVector },
+
+ { XioReservedVector, // Virtual slot 5 - reserved
+ XioReservedVector,
+ XioReservedVector,
+ XioReservedVector },
+
+ { XioPciSlot4AVector, // Virtual slot 6 - PCI slot 4
+ XioPciSlot4BVector,
+ XioPciSlot4CVector,
+ XioPciSlot4DVector },
+
+ { XioPciSlot5AVector, // Virtual slot 7 - PCI slot 5
+ XioPciSlot5BVector,
+ XioPciSlot5CVector,
+ XioPciSlot5DVector },
+
+ { XioPciSlot6AVector, // Virtual slot 8 - PCI slot 6
+ XioPciSlot6BVector,
+ XioPciSlot6CVector,
+ XioPciSlot6DVector },
+
+ { XioPciSlot7AVector, // Virtual slot 9 - PCI slot 7
+ XioPciSlot7BVector,
+ XioPciSlot7CVector,
+ XioPciSlot7DVector },
+
+ { XioReservedVector, // Virtual slot 10 - reserved
+ XioReservedVector,
+ XioReservedVector,
+ XioReservedVector }
+};
+
+ULONG XioPinToLineTable2[][4] = {
+ { XioReservedVector, // Virtual slot 0 - reserved
+ XioReservedVector,
+ XioReservedVector,
+ XioReservedVector },
+
+ { XioReservedVector, // Virtual slot 1 - reserved
+ XioReservedVector,
+ XioReservedVector,
+ XioReservedVector },
+
+ { XioReservedVector, // Virtual slot 2 - reserved
+ XioReservedVector,
+ XioReservedVector,
+ XioReservedVector },
+
+ { XioReservedVector, // Virtual slot 3 - reserved
+ XioReservedVector,
+ XioReservedVector,
+ XioReservedVector },
+
+ { XioReservedVector, // Virtual slot 4 - reserved
+ XioReservedVector,
+ XioReservedVector,
+ XioReservedVector },
+
+ { XioReservedVector, // Virtual slot 5 - reserved
+ XioReservedVector,
+ XioReservedVector,
+ XioReservedVector },
+
+ { XioPciSlot0AVector, // Virtual slot 6 - PCI slot 0
+ XioPciSlot0BVector,
+ XioPciSlot0CVector,
+ XioPciSlot0DVector },
+
+ { XioPciSlot1AVector, // Virtual slot 7 - PCI slot 1
+ XioPciSlot1BVector,
+ XioPciSlot1CVector,
+ XioPciSlot1DVector },
+
+ { XioPciSlot2AVector, // Virtual slot 8 - PCI slot 2
+ XioPciSlot2BVector,
+ XioPciSlot2CVector,
+ XioPciSlot2DVector },
+
+ { XioPciSlot3AVector, // Virtual slot 9 - PCI slot 3
+ XioPciSlot3BVector,
+ XioPciSlot3CVector,
+ XioPciSlot3DVector },
+
+ { XioReservedVector, // Virtual slot 10 - reserved
+ XioReservedVector,
+ XioReservedVector,
+ XioReservedVector },
+
+ { XioReservedVector, // Virtual slot 11 - reserved
+ XioReservedVector,
+ XioReservedVector,
+ XioReservedVector },
+
+ { XioReservedVector, // Virtual slot 12 - reserved
+ XioReservedVector,
+ XioReservedVector,
+ XioReservedVector },
+
+ { XioReservedVector, // Virtual slot 13 - reserved
+ XioReservedVector,
+ XioReservedVector,
+ XioReservedVector },
+
+ { XioReservedVector, // Virtual slot 14 - reserved
+ XioReservedVector,
+ XioReservedVector,
+ XioReservedVector },
+
+ { XioReservedVector, // Virtual slot 15 - reserved
+ XioReservedVector,
+ XioReservedVector,
+ XioReservedVector }
+};
+
+#endif // XIO_PASS2
diff --git a/private/ntos/nthals/halsable/alpha/sable.h b/private/ntos/nthals/halsable/alpha/sable.h
new file mode 100644
index 000000000..52989dc94
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/sable.h
@@ -0,0 +1,519 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ sable.h
+
+Abstract:
+
+ This file defines the structures and definitions common to all
+ sable-based platforms.
+
+Author:
+
+ Joe Notarangelo 26-Oct-1993
+ Steve Jenness 26-Oct-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#ifndef _SABLEH_
+#define _SABLEH_
+
+
+#include "sableref.h" // Sable reference I/O structure
+#include "lynxref.h" // Lynx interrupt structure
+#include "xioref.h" // XIO interrupt structure
+#if !defined(_LANGUAGE_ASSEMBLY)
+#include "errframe.h"
+#endif
+
+//
+// Constants used by dense space I/O routines
+//
+
+#define SABLE_PCI0_DENSE_BASE_PHYSICAL_SUPERPAGE 0xfffffc03c0000000
+#define SABLE_PCI1_DENSE_BASE_PHYSICAL_SUPERPAGE 0xfffffc0180000000
+
+#define PCI_DENSE_BASE_PHYSICAL_SUPERPAGE \
+ (SABLE_PCI0_DENSE_BASE_PHYSICAL_SUPERPAGE - SABLE_PCI0_DENSE_MEMORY_QVA)
+
+#define PCI1_DENSE_BASE_PHYSICAL_SUPERPAGE \
+ (SABLE_PCI1_DENSE_BASE_PHYSICAL_SUPERPAGE - SABLE_PCI1_DENSE_MEMORY_QVA)
+
+#if !defined(_LANGUAGE_ASSEMBLY)
+
+#include "t2.h" // T2 chipset definitions
+#include "icic.h" // ICIC definitions
+
+//
+// QVA
+// HAL_MAKE_QVA(
+// ULONGLONG PhysicalAddress
+// )
+//
+// Routine Description:
+//
+// This macro returns the Qva for a physical address in system space.
+//
+// Arguments:
+//
+// PhysicalAddress - Supplies a 64-bit physical address.
+//
+// Return Value:
+//
+// The Qva associated with the physical address.
+//
+
+#define HAL_MAKE_QVA(PA) \
+ ( (PVOID)( QVA_ENABLE | (ULONG)(PA >> IO_BIT_SHIFT) ) )
+
+
+
+//
+// Define physical address spaces for SABLE.
+//
+// PCI0 - 32bit PCI bus
+// PCI1 - 64bit PCI bus
+//
+
+#define SABLE_PCI1_DENSE_MEMORY_PHYSICAL ((ULONGLONG)0x180000000)
+#define SABLE_PCI1_SPARSE_IO_PHYSICAL ((ULONGLONG)0x1C0000000)
+#define SABLE_PCI0_SPARSE_MEMORY_PHYSICAL ((ULONGLONG)0x200000000)
+#define SABLE_PCI1_SPARSE_MEMORY_PHYSICAL ((ULONGLONG)0x300000000)
+
+#define SABLE_CBUS_CSRS_PHYSICAL ((ULONGLONG)0x380000000)
+#define SABLE_CPU0_CSRS_PHYSICAL ((ULONGLONG)0x380000000)
+#define SABLE_CPU1_CSRS_PHYSICAL ((ULONGLONG)0x381000000)
+#define SABLE_CPU2_CSRS_PHYSICAL ((ULONGLONG)0x382000000)
+#define SABLE_CPU3_CSRS_PHYSICAL ((ULONGLONG)0x383000000)
+#define SABLE_CPU0_IPIR_PHYSICAL ((ULONGLONG)0x380000160)
+#define SABLE_CPU1_IPIR_PHYSICAL ((ULONGLONG)0x381000160)
+#define SABLE_CPU2_IPIR_PHYSICAL ((ULONGLONG)0x382000160)
+#define SABLE_CPU3_IPIR_PHYSICAL ((ULONGLONG)0x383000160)
+#define SABLE_MEM0_CSRS_PHYSICAL ((ULONGLONG)0x388000000)
+#define SABLE_MEM1_CSRS_PHYSICAL ((ULONGLONG)0x389000000)
+#define SABLE_MEM2_CSRS_PHYSICAL ((ULONGLONG)0x38A000000)
+#define SABLE_MEM3_CSRS_PHYSICAL ((ULONGLONG)0x38B000000)
+#define SABLE_T2_CSRS_PHYSICAL ((ULONGLONG)0x38E000000)
+#define SABLE_T4_CSRS_PHYSICAL ((ULONGLONG)0x38F000000)
+#define T2_CSRS_QVA (HAL_MAKE_QVA(SABLE_T2_CSRS_PHYSICAL))
+#define T4_CSRS_QVA (HAL_MAKE_QVA(SABLE_T4_CSRS_PHYSICAL))
+
+#define SABLE_PCI0_CONFIGURATION_PHYSICAL ((ULONGLONG)0x390000000)
+#define SABLE_PCI1_CONFIGURATION_PHYSICAL ((ULONGLONG)0x398000000)
+#define SABLE_PCI0_SPARSE_IO_PHYSICAL ((ULONGLONG)0x3A0000000)
+#define SABLE_PCI0_DENSE_MEMORY_PHYSICAL ((ULONGLONG)0x3C0000000)
+
+//
+// Define the limits of User mode Sparse and Dense space:
+//
+
+#define SABLE_USER_PCI1_DENSE_MEMORY_PHYSICAL (ULONGLONG)0x180000000
+#define SABLE_USER_PCI1_SPARSE_IO_PHYSICAL (ULONGLONG)0x1C0000000
+#define SABLE_USER_PCI1_SPARSE_IO_END_PHYSICAL (ULONGLONG)0x1E0000000
+#define SABLE_USER_PCI0_SPARSE_MEMORY_PHYSICAL (ULONGLONG)0x200000000
+#define SABLE_USER_PCI0_SPARSE_MEMORY_END_PHYSICAL (ULONGLONG)0x300000000
+#define SABLE_USER_PCI1_SPARSE_MEMORY_PHYSICAL (ULONGLONG)0x300000000
+#define SABLE_USER_PCI1_SPARSE_MEMORY_END_PHYSICAL (ULONGLONG)0x380000000
+#define SABLE_USER_PCI0_SPARSE_IO_PHYSICAL (ULONGLONG)0x3A0000000
+#define SABLE_USER_PCI0_SPARSE_IO_END_PHYSICAL (ULONGLONG)0x3C0000000
+#define SABLE_USER_PCI0_DENSE_MEMORY_PHYSICAL (ULONGLONG)0x3C0000000
+
+#define SABLE_EDGE_LEVEL_CSRS_PHYSICAL ((ULONGLONG)0x3A00004C0)
+#define SABLE_INTERRUPT_CSRS_PHYSICAL ((ULONGLONG)0x3A000A640)
+#define XIO_INTERRUPT_CSRS_PHYSICAL ((ULONGLONG)0x1C0000530)
+#define XIO_INTERRUPT_CSRS_QVA (HAL_MAKE_QVA(XIO_INTERRUPT_CSRS_PHYSICAL))
+
+//
+// Define Interrupt Controller CSRs.
+//
+
+#define SABLE_EDGE_LEVEL_CSRS_QVA (HAL_MAKE_QVA(SABLE_EDGE_LEVEL_CSRS_PHYSICAL))
+#define SABLE_INTERRUPT_CSRS_QVA (HAL_MAKE_QVA(SABLE_INTERRUPT_CSRS_PHYSICAL))
+
+//
+// Define the XIO_VECTOR <CIRQL1>
+//
+
+#define XIO_VECTOR UNUSED_VECTOR
+
+
+//
+// Define CPU CSRs and masks.
+//
+
+#define SABLE_CPU0_CSRS_QVA (HAL_MAKE_QVA(SABLE_CPU0_CSRS_PHYSICAL))
+#define SABLE_CPU1_CSRS_QVA (HAL_MAKE_QVA(SABLE_CPU1_CSRS_PHYSICAL))
+#define SABLE_CPU2_CSRS_QVA (HAL_MAKE_QVA(SABLE_CPU2_CSRS_PHYSICAL))
+#define SABLE_CPU3_CSRS_QVA (HAL_MAKE_QVA(SABLE_CPU3_CSRS_PHYSICAL))
+#define SABLE_MEM0_CSRS_QVA (HAL_MAKE_QVA(SABLE_MEM0_CSRS_PHYSICAL))
+#define SABLE_MEM1_CSRS_QVA (HAL_MAKE_QVA(SABLE_MEM1_CSRS_PHYSICAL))
+#define SABLE_MEM2_CSRS_QVA (HAL_MAKE_QVA(SABLE_MEM2_CSRS_PHYSICAL))
+#define SABLE_MEM3_CSRS_QVA (HAL_MAKE_QVA(SABLE_MEM3_CSRS_PHYSICAL))
+
+#define SABLE_PRIMARY_PROCESSOR ((ULONG)0x0)
+#define SABLE_SECONDARY_PROCESSOR ((ULONG)0x1)
+#define SABLE_MAXIMUM_PROCESSOR ((ULONG)0x3)
+#define HAL_PRIMARY_PROCESSOR (SABLE_PRIMARY_PROCESSOR)
+#define HAL_MAXIMUM_PROCESSOR (SABLE_MAXIMUM_PROCESSOR)
+
+//
+// Define the default processor frequency to be used before the actual
+// frequency can be determined.
+//
+
+#define DEFAULT_PROCESSOR_FREQUENCY_MHZ (275)
+
+enum {
+ NoError,
+ UncorrectableError,
+ CorrectableError
+} ErrorType;
+
+//
+// Define the list of CSR's...
+//
+
+typedef struct _SABLE_CPU_CSRS {
+ UCHAR Bcc; // B-Cache Control Register
+ UCHAR Bcce; // B-Cache Correctable Error Register
+ UCHAR Bccea; // B-Cache Correctable Error Address Register
+ UCHAR Bcue; // B-Cache Uncorrectable Error Register
+ UCHAR Bcuea; // B-Cache Uncorrectable Error Address Register
+ UCHAR Dter; // Duplicate Tag Error Register
+ UCHAR Cbctl; // System Bus Control Register
+ UCHAR Cb2; // System Bus Error Register
+ UCHAR Cbeal; // System Bus Error Address Low Register
+ UCHAR Cbeah; // System Bus Error Address High Register
+ UCHAR Pmbx; // Processor Mailbox Register
+ UCHAR Ipir; // Inter-Processor Interrupt Request Register
+ UCHAR Sic; // System Interrupt Clear Register
+ UCHAR Adlk; // Address Lock Register
+ UCHAR Madrl; // Miss Address Register
+ UCHAR Crrevs; // C4 Revision Register
+} SABLE_CPU_CSRS, *PSABLE_CPU_CSRS;
+
+//
+// Define the System Bus Control Register
+//
+
+typedef struct _SABLE_CBCTL_CSR{
+ ULONG DataWrongParity: 1; // 0
+ ULONG CaWrongParity: 2; // 1
+ ULONG EnableParityCheck: 1; // 3
+ ULONG ForceShared: 1; // 4
+ ULONG CommaderId: 3; // 5
+ ULONG Reserved0: 3; // 8
+ ULONG EnableCbusErrorInterrupt: 1; // 11
+ ULONG Reserved1: 1; // 12
+ ULONG SecondQuadwordSelect: 1; // 13
+ ULONG SelectDrack: 1; // 14
+ ULONG Reserved2: 17; // 15
+
+ ULONG DataWrongParityHigh: 1; // 32
+ ULONG CaWrongParityHigh: 2; // 33
+ ULONG EnableParityCheckHigh: 1; // 35
+ ULONG ForceSharedHigh: 1; // 36
+ ULONG CommanderIdHigh: 3; // 37
+ ULONG Reserved3: 3; // 40
+ ULONG EnableCbusErrorInterruptHigh: 1; // 43
+ ULONG DisableBackToBackArbitration: 1; // 44
+ ULONG SecondQuadwordSelectHigh: 1; // 45
+ ULONG SelectDrackHigh: 1; // 46
+ ULONG Reserved4: 17; // 47
+} SABLE_CBCTL_CSR, *PSABLE_CBCTL_CSR;
+
+//
+// Define all the System Bus (CobraBus or CBus) Control and Error Registers
+// listed above: Bcc, Bcce, Bccea, Bcue, Bcuea
+//
+
+typedef struct _SABLE_BCACHE_BCC_CSR0 {
+ union {
+ ULONG EnableAllocateL: 1; // 0
+ ULONG ForceFillSharedL: 1; // 1
+ ULONG EnbTagParCheckL: 1; // 2
+ ULONG FillWrongTagParL: 1; // 3
+ ULONG FillWrongContolParL: 1; // 4
+ ULONG FillWrongDupTagStoreParL: 1; // 5
+ ULONG EnableCorrectableErrorInterruptL: 1; // 6
+ ULONG EnableEDCCorrectionL: 1; // 7
+ ULONG EnableEDCCheckL: 1; // 8
+ ULONG EnableBCacheConditionIOUpdatesL: 1; // 9
+ ULONG DisableBlockWriteAroundL: 1; // 10
+ ULONG EnableBCacheInitL: 1; // 11
+ ULONG ForceEDCControlL: 1; // 12
+ ULONG SharedDirtyValidL: 3; // 13-15
+ ULONG EDCL: 14; // 16-29
+ ULONG Reserved1: 1; // 30
+ ULONG CacheSizeL: 1; // 31
+
+ ULONG EnableAllocateH: 1; // 32
+ ULONG ForceFillSharedH: 1; // 33
+ ULONG EnbTagParCheckH: 1; // 34
+ ULONG FillWronTagParH: 1; // 35
+ ULONG FillWrongContolParH: 1; // 36
+ ULONG FillWrongDupTagStoreParH: 1; // 37
+ ULONG EnableCorrectableErrorInterruptH: 1; // 38
+ ULONG EnableEDCCorrectionH: 1; // 39
+ ULONG EnableEDCCheckH: 1; // 40
+ ULONG EnableBCacheConditionIOUpdatesH: 1; // 41
+ ULONG DisableBlockWriteAroundH: 1; // 42
+ ULONG EnableBCacheInitH: 1; // 43
+ ULONG ForceEDCControlH: 1; // 44
+ ULONG SharedDirtyValidH: 3; // 45-47
+ ULONG EDCH: 14; // 48-61
+ ULONG Reserved2: 1; // 62
+ ULONG CacheSizeH: 1; // 63
+ };
+ ULONGLONG all;
+
+} SABLE_BCACHE_BCC_CSR0, *PSABLE_BCACHE_BCC_CSR0;
+
+//
+// Define the Backup Cache correctable error register
+//
+
+typedef struct _SABLE_BCACHE_BCCE_CSR1 {
+ union {
+ ULONG Reserved1: 2; // 0-1
+ ULONG MissedCorrectableError: 1; // 2
+ ULONG CorrectableError: 1; // 3
+ ULONG Reserved2: 4; // 4-7
+ ULONG ControlBitParity: 1; // 8
+ ULONG Shared: 1; // 9
+ ULONG Dirty: 1; // 10
+ ULONG Valid: 1; // 11
+ ULONG Reserved3: 5; // 12-16
+ ULONG EDCError1: 1; // 17
+ ULONG EDCSyndrome0: 7; // 18-24
+ ULONG EDCSyndrome2: 7; // 25-31
+ ULONG Reserved4: 2; // 32-33
+ ULONG MissedCorrectableErrorH: 1; // 34
+ ULONG CorrectableErrorH: 1; // 35
+ ULONG Undefined: 13; // 36-48
+ ULONG EDCError2: 1; // 49
+ ULONG EDCSyndrome1: 7; // 50-56
+ ULONG EDCSyndrome3: 7; // 57-63
+ };
+ ULONGLONG all;
+
+} SABLE_BCACHE_BCCE_CSR1, *PSABLE_BCACHE_BCCE_CSR1;
+
+
+//
+// Define the Backup Cache correctable error address register
+//
+
+typedef struct _SABLE_BCACHE_BCCEA_CSR2 {
+ union {
+ ULONG BcacheMapOffsetL: 17; // 0-16
+ ULONG Reserved1: 1; // 17
+ ULONG TagParityL: 1; // 18
+ ULONG TagValueL: 12; // 19-30
+ ULONG Reserved2: 1; // 31
+ ULONG BcacheMapOffsetH: 17; // 32-48
+ ULONG Reserved3: 1; // 49
+ ULONG TagParityH: 1; // 50
+ ULONG TagValueH: 12; // 51-62
+ ULONG Reserved4: 1; // 63
+ };
+ ULONGLONG all;
+
+} SABLE_BCACHE_BCCEA_CSR2, *PSABLE_BCACHE_BCCEA_CSR2;
+
+//
+// Define the Backup Cache uncorrectable error register
+//
+
+typedef struct _SABLE_BCACHE_BCUE_CSR3 {
+ union {
+ ULONG MissedParErrorL: 1; // 0
+ ULONG ParityErrorL: 1; // 1
+ ULONG MissedUncorrectableErrorL: 1; // 2
+ ULONG UncorrectableErrorL: 1; // 3
+ ULONG Reserved1: 4; // 4-7
+ ULONG ControlBitParityL: 1; // 8
+ ULONG Shared: 1; // 9
+ ULONG Dirty: 1; // 10
+ ULONG Valid: 1; // 11
+ ULONG Resrved2: 5; // 12-16
+ ULONG BCacheEDCError1: 1; // 17
+ ULONG EDCSyndrome0: 7; // 18-24
+ ULONG EDCSyndrome2: 7; // 25-31
+ ULONG MissedParErrorH: 1; // 32
+ ULONG ParityErrorH: 1; // 33
+ ULONG MissedUncorrectableErrorH: 1; // 34
+ ULONG UncorrectableErrorH: 1; // 35
+ ULONG Resreved3: 13; // 36-48
+ ULONG BCacheEDCError2: 1; // 49
+ ULONG EDCSyndrome1: 7; // 50-56
+ ULONG EDCSyndrome3: 7; // 57-63
+ };
+ ULONGLONG all;
+
+} SABLE_BCACHE_BCUE_CSR3, *PSABLE_BCACHE_BCUE_CSR3;
+
+//
+// Define the Backup Cache uncorrectable error address register
+//
+
+typedef struct _SABLE_BCACHE_BCUEA_CSR4 {
+ union {
+ ULONG BCacheMapOffsetL: 17; // 0-16
+ ULONG PredictedTagParL: 1; // 17
+ ULONG TagParityL: 1; // 18
+ ULONG TagValueL: 12; // 19-30
+ ULONG Reserved1: 1; // 31
+ ULONG BCacheMapOffsetH: 17; // 32-48
+ ULONG PredictedTagParH: 1; // 49
+ ULONG TagParityJ: 1; // 50
+ ULONG TagValueH: 12; // 51-62
+ ULONG Reserved2: 1; // 63
+
+ };
+ ULONGLONG all;
+} SABLE_BCACHE_BCUEA_CSR4, *PSABLE_BCACHE_BCUEA_CSR4;
+
+//
+// Define the memory module CSRs
+//
+
+typedef struct _SGL_MEM_CSR0 {
+ union {
+ ULONG ErrorSummary1: 1; // 0
+ ULONG SyncError1: 1; // 1
+ ULONG CAParityError1: 1; // 2
+ ULONG CAMissedParityError1: 1; // 3
+ ULONG WriteParityError1: 1; // 4
+ ULONG MissedWriteParityError1: 1; // 5
+ ULONG Reserved1: 2; // 6-7
+
+ ULONG CAParityErrorLW0: 1; // 8
+ ULONG CAParityErrorLW2: 1; // 9
+ ULONG ParityErrorLW0: 1; // 10
+ ULONG ParityErrorLW2: 1; // 11
+ ULONG ParityErrorLW4: 1; // 12
+ ULONG ParityErrorLW6: 1; // 13
+ ULONG Reserved2: 2; // 14-15
+
+ ULONG EDCUncorrectable1: 1; // 16
+ ULONG EDCMissedUncorrectable1: 1; // 17
+ ULONG EDCCorrectable1: 1; // 18
+ ULONG EDCMissdedCorrectable1: 1; // 19
+ ULONG Reserved3: 12; // 20-31
+
+ ULONG ErrorSummary2: 1; // 32
+ ULONG SyncError2: 1; // 33
+ ULONG CAParityError2: 1; // 34
+ ULONG CAMissedParityError2: 1; // 35
+ ULONG WriteParityError2: 1; // 36
+ ULONG MissedWriteParityError2: 1; // 37
+ ULONG Reserved4: 2; // 38-39
+
+ ULONG CAParityErrorLW1: 1; // 40
+ ULONG CAParityErrorLW3: 1; // 41
+ ULONG ParityErrorLW1: 1; // 42
+ ULONG ParityErrorLW3: 1; // 43
+ ULONG ParityErrorLW5: 1; // 44
+ ULONG ParityErrorLW7: 1; // 45
+ ULONG Reserved5: 2; // 46-47
+
+ ULONG EDCUncorrectable2: 1; // 48
+ ULONG EDCMissedUncorrectable2: 1; // 49
+ ULONG EDCCorrectable2: 1; // 50
+ ULONG EDCMissdedCorrectable2: 1; // 51
+ ULONG Reserved6: 12; // 52-63
+ };
+ ULONGLONG all;
+
+} SGL_MEM_CSR0, *PSGL_MEM_CSR0;
+
+//
+// Define the Interprocessor Interrupt Request Register.
+//
+
+typedef union _SABLE_IPIR_CSR{
+ struct{
+ ULONG RequestInterrupt: 1;
+ ULONG Reserved0: 31;
+ ULONG Undefined: 1;
+ ULONG Reserved1: 2;
+ ULONG RequestNodeHaltInterrupt: 1;
+ ULONG Reserved2: 28;
+ };
+ ULONGLONG all;
+} SABLE_IPIR_CSR, *PSABLE_IPIR_CSR;
+
+//
+// Define the System Interrupt Clear Register format.
+//
+
+typedef union _SABLE_SIC_CSR{
+ struct{
+ ULONG Undefined1: 1;
+ ULONG Undefined2: 1;
+ ULONG SystemBusErrorInterruptClear: 1;
+ ULONG Undefined3: 1;
+ ULONG Reserved1: 28;
+ ULONG IntervalTimerInterruptClear: 1;
+ ULONG SystemEventClear: 1;
+ ULONG Undefinded4: 1;
+ ULONG NodeHaltInterruptClear: 1;
+ ULONG Reserved2: 28;
+ };
+ ULONGLONG all;
+} SABLE_SIC_CSR, *PSABLE_SIC_CSR;
+
+//
+// Define the per-processor data structures allocated in the PCR
+// for each Sable processor.
+//
+
+typedef struct _SABLE_PCR{
+ ULONGLONG HalpCycleCount; // 64-bit per-processor cycle count
+ EV4ProfileCount ProfileCount; // Profile counter state, do not move
+ ULONGLONG IpirSva; // Superpage Va of per-processor IPIR CSR
+ PVOID CpuCsrsQva; // Qva of per-cpu csrs
+ EV4IrqStatus IrqStatusTable[MaximumIrq]; // Irq status table
+} SABLE_PCR, *PSABLE_PCR;
+
+#define HAL_PCR ( (PSABLE_PCR)(&(PCR->HalReserved)) )
+
+//
+// Define Miscellaneous Sable routines.
+//
+
+VOID
+WRITE_CPU_REGISTER(
+ PVOID,
+ ULONGLONG
+ );
+
+ULONGLONG
+READ_CPU_REGISTER(
+ PVOID
+ );
+
+ULONGLONG
+READ_MEM_REGISTER(
+ PVOID
+ );
+
+VOID
+HalpSableIpiInterrupt(
+ VOID
+ );
+
+#endif //!_LANGUAGE_ASSEMBLY
+
+#endif //_SABLEH_
diff --git a/private/ntos/nthals/halsable/alpha/sableerr.c b/private/ntos/nthals/halsable/alpha/sableerr.c
new file mode 100644
index 000000000..304678e17
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/sableerr.c
@@ -0,0 +1,2081 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ sableerr.c
+
+Abstract:
+
+ This module implements error handling (machine checks and error
+ interrupts) for the Sable platform.
+
+Author:
+
+ Joe Notarangelo 15-Feb-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+//jnfix - this module current only deals with errors initiated by the
+//jnfix - T2, there is nothing completed for CPU Asic errors
+
+#include "halp.h"
+#include "axp21064.h"
+#include "stdio.h"
+
+//
+// Declare the extern variable UncorrectableError declared in
+// inithal.c.
+//
+extern PERROR_FRAME PUncorrectableError;
+
+
+extern ULONG HalDisablePCIParityChecking;
+extern ULONG HalpMemorySlot[];
+extern ULONG HalpCPUSlot[];
+
+ULONG SlotToPhysicalCPU[4] = {3, 0, 1, 2};
+
+typedef BOOLEAN (*PSECOND_LEVEL_DISPATCH)(
+ PKINTERRUPT InterruptObject,
+ PVOID ServiceContext
+ );
+
+ULONG
+HalpTranslateSyndromToECC(
+ PULONG Syndrome
+ );
+
+VOID
+HalpSetMachineCheckEnables(
+ IN BOOLEAN DisableMachineChecks,
+ IN BOOLEAN DisableProcessorCorrectables,
+ IN BOOLEAN DisableSystemCorrectables
+ );
+
+VOID
+HalpSableReportFatalError(
+ VOID
+ );
+
+#define MAX_ERROR_STRING 128
+
+ULONG SGLCorrectedErrors = 0;
+
+
+VOID
+HalpInitializeMachineChecks(
+ IN BOOLEAN ReportCorrectableErrors
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes machine check handling for an APECS-based
+ system by clearing all pending errors in the COMANCHE and EPIC and
+ enabling correctable errors according to the callers specification.
+
+Arguments:
+
+ ReportCorrectableErrors - Supplies a boolean value which specifies
+ if correctable error reporting should be
+ enabled.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ T2_CERR1 Cerr1;
+ T2_PERR1 Perr1;
+ T2_IOCSR Iocsr;
+
+ //
+ // Clear any pending CBUS errors.
+ //
+
+ Cerr1.all = READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Cerr1 );
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Cerr1, Cerr1.all );
+
+ //
+ // Clear any pending PCI errors.
+ //
+
+ Perr1.all = READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Perr1 );
+
+ Perr1.ForceReadDataParityError64 = 0;
+ Perr1.ForceAddressParityError64 = 0;
+ Perr1.ForceWriteDataParityError64 = 0;
+ Perr1.DetectTargetAbort = 1;
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Perr1, Perr1.all );
+
+ //
+ // Enable the errors we want to handle in the T2 via the Iocsr,
+ // must read-modify-write Iocsr as it contains values we want to
+ // preserve.
+ //
+
+ Iocsr.all = READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Iocsr );
+
+ //
+ // Enable all of the hard error checking and error interrupts.
+ //
+
+ Iocsr.EnableTlbErrorCheck = 1;
+ Iocsr.EnableCxAckCheckForDma = 1;
+// Iocsr.EnableCommandOutOfSyncCheck = 1;
+ Iocsr.EnableCbusErrorInterrupt = 1;
+ Iocsr.EnableCbusParityCheck = 1;
+
+#if 0
+ //
+ // T3 Bug: There are 2 write buffers which can be used for PIO or
+ // PPC. By default they are initialized to PIO. However, using
+ // them for PIO causes T3 state machine errors. To work around this
+ // problem convert them to PPC buffers, instead. This decreases PIO
+ // performance.
+ //
+
+ if (Iocsr.T2RevisionNumber >= 4) {
+
+ Iocsr.EnablePpc1 = 1;
+ Iocsr.EnablePpc2 = 1;
+
+ }
+#endif // wkc - the SRM should be setting this now.
+
+ Iocsr.ForcePciRdpeDetect = 0;
+ Iocsr.ForcePciApeDetect = 0;
+ Iocsr.ForcePciWdpeDetect = 0;
+ Iocsr.EnablePciNmi = 1;
+ Iocsr.EnablePciDti = 1;
+ Iocsr.EnablePciSerr = 1;
+
+ if (HalDisablePCIParityChecking == 0xffffffff) {
+
+ //
+ // Disable PCI Parity Checking
+ //
+
+ Iocsr.EnablePciPerr = 0;
+ Iocsr.EnablePciRdp = 0;
+ Iocsr.EnablePciAp = 0;
+ Iocsr.EnablePciWdp = 0;
+
+ } else {
+
+ Iocsr.EnablePciPerr = !HalDisablePCIParityChecking;
+ Iocsr.EnablePciRdp = !HalDisablePCIParityChecking;
+ Iocsr.EnablePciAp = !HalDisablePCIParityChecking;
+ Iocsr.EnablePciWdp = !HalDisablePCIParityChecking;
+
+ }
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Iocsr,
+ Iocsr.all );
+
+ //
+ // Ascertain whether this is a Gamma or Lynx platform.
+ //
+
+ if( Iocsr.T2RevisionNumber >= 4 ){
+
+ HalpLynxPlatform = TRUE;
+
+ }
+
+ //
+ // Set the machine check enables within the EV4.
+ //
+
+ if( ReportCorrectableErrors == TRUE ){
+ HalpSetMachineCheckEnables( FALSE, FALSE, FALSE );
+ } else {
+ HalpSetMachineCheckEnables( FALSE, TRUE, TRUE );
+ }
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+ //
+ // The next line *may* generate a machine check. This would happen
+ // if an XIO module is not present in the system. It should be safe
+ // to take machine checks now. Here goes nothing...
+ //
+
+ Iocsr.all = READ_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Iocsr );
+
+ if( Iocsr.all != (ULONGLONG)-1 ){
+
+ HalpXioPresent = TRUE;
+
+ //
+ // Clear any pending CBUS errors.
+ //
+
+ Cerr1.all = READ_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Cerr1 );
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Cerr1, Cerr1.all );
+
+ //
+ // Clear any pending PCI errors.
+ //
+
+ Perr1.all = READ_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Perr1 );
+
+ Perr1.ForceReadDataParityError64 = 0;
+ Perr1.ForceAddressParityError64 = 0;
+ Perr1.ForceWriteDataParityError64 = 0;
+ Perr1.DetectTargetAbort = 1;
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Perr1, Perr1.all );
+
+ Iocsr.EnableTlbErrorCheck = 1;
+ Iocsr.EnableCxAckCheckForDma = 1;
+// Iocsr.EnableCommandOutOfSyncCheck = 1;
+ Iocsr.EnableCbusErrorInterrupt = 1;
+ Iocsr.EnableCbusParityCheck = 1;
+
+ //
+ // T3 Bug: There are 2 write buffers which can be used for PIO or
+ // PPC. By default they are initialized to PIO. However, using
+ // them for PIO causes T3 state machine errors. To work around
+ // this problem convert them to PPC buffers, instead. This
+ // decreases PIO performance.
+ //
+
+ Iocsr.EnablePpc1 = 1;
+ Iocsr.EnablePpc2 = 1;
+
+ Iocsr.EnablePciStall = 0;
+ Iocsr.ForcePciRdpeDetect = 0;
+ Iocsr.ForcePciApeDetect = 0;
+ Iocsr.ForcePciWdpeDetect = 0;
+ Iocsr.EnablePciNmi = 1;
+ Iocsr.EnablePciDti = 1;
+ Iocsr.EnablePciSerr = 1;
+
+ if (HalDisablePCIParityChecking == 0xffffffff) {
+
+ //
+ // Disable PCI Parity Checking
+ //
+
+ Iocsr.EnablePciRdp64 = 0;
+ Iocsr.EnablePciAp64 = 0;
+ Iocsr.EnablePciWdp64 = 0;
+ Iocsr.EnablePciPerr = 0;
+ Iocsr.EnablePciRdp = 0;
+ Iocsr.EnablePciAp = 0;
+ Iocsr.EnablePciWdp = 0;
+
+ } else {
+
+ Iocsr.EnablePciRdp64 = !HalDisablePCIParityChecking;
+ Iocsr.EnablePciAp64 = !HalDisablePCIParityChecking;
+ Iocsr.EnablePciWdp64 = !HalDisablePCIParityChecking;
+ Iocsr.EnablePciPerr = !HalDisablePCIParityChecking;
+ Iocsr.EnablePciRdp = !HalDisablePCIParityChecking;
+ Iocsr.EnablePciAp = !HalDisablePCIParityChecking;
+ Iocsr.EnablePciWdp = !HalDisablePCIParityChecking;
+
+ }
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Iocsr,
+ Iocsr.all );
+
+ }
+
+#endif
+
+#if HALDBG
+ if (HalDisablePCIParityChecking == 0) {
+ DbgPrint("sableerr: PCI Parity Checking ON\n");
+ } else if (HalDisablePCIParityChecking == 1) {
+ DbgPrint("sableerr: PCI Parity Checking OFF\n");
+ } else {
+ DbgPrint("sableerr: PCI Parity Checking OFF - not set by ARC yet\n");
+ }
+#endif
+
+ return;
+
+}
+
+
+VOID
+HalpBuildSableUncorrectableErrorFrame(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is called when an uncorrectable error occurs.
+ This routine builds the global Sable Uncorrectable Error frame.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+{
+ //
+ // We will *try* to get the CPU module information that was active at the
+ // time of the machine check.
+ // We will *try* to get as much information about the system, the CPU
+ // modules and the memory modules at the time of the crash.
+ //
+ extern ULONG HalpLogicalToPhysicalProcessor[HAL_MAXIMUM_PROCESSOR+1];
+ extern PSABLE_CPU_CSRS HalpSableCpuCsrs[HAL_MAXIMUM_PROCESSOR+1];
+ extern KAFFINITY HalpActiveProcessors;
+
+ PSABLE_CPU_CSRS CpuCsrsQva;
+ PSABLE_UNCORRECTABLE_FRAME sableuncorrerr = NULL;
+ PEXTENDED_ERROR PExtErr;
+ ULONG LogicalCpuNumber;
+ ULONG i = 0;
+ ULONG TotalNumberOfCpus = 0;
+ T2_IOCSR Iocsr;
+ T2_PERR1 Perr1;
+ T2_PERR2 Perr2;
+
+ if(PUncorrectableError){
+ sableuncorrerr = (PSABLE_UNCORRECTABLE_FRAME)
+ PUncorrectableError->UncorrectableFrame.RawSystemInformation;
+ PExtErr = &PUncorrectableError->UncorrectableFrame.ErrorInformation;
+ }
+
+ if(sableuncorrerr){
+ //
+ // Get the Error registers from all the CPU modules.
+ // Although called CPU error this is sable specific and not CPU
+ // specific the CPU error itself will be logged in the EV4 error frame.
+ // HalpActiveProcessors is a mask of all processors that are active.
+ // 8 bits per byte to get the total number of bits in KAFFINITY
+ //
+ DbgPrint("sableerr.c - HalpBuildSableUncorrectableErrorFrame :\n");
+ for(i = 0 ; i < sizeof(KAFFINITY)*8 ; i++ ) {
+ if( (HalpActiveProcessors >> i) & 0x1UL) {
+ LogicalCpuNumber = i;
+ TotalNumberOfCpus++;
+ }
+ else
+ continue;
+
+ CpuCsrsQva = HalpSableCpuCsrs[LogicalCpuNumber];
+
+ DbgPrint("\tCurrent CPU Module's[LN#=%d] CSRS QVA = %08lx\n",
+ LogicalCpuNumber, CpuCsrsQva);
+ DbgPrint("\n\t CPU Module Error Log : \n");
+
+ sableuncorrerr->CpuError[LogicalCpuNumber].Uncorrectable.Bcue =
+ READ_CPU_REGISTER(&((PSABLE_CPU_CSRS)CpuCsrsQva)->Bcue);
+ DbgPrint("\t\tBcue = %016Lx\n",
+ sableuncorrerr->CpuError[LogicalCpuNumber].Uncorrectable.Bcue);
+
+ sableuncorrerr->CpuError[LogicalCpuNumber].Uncorrectable.Bcuea =
+ READ_CPU_REGISTER(&((PSABLE_CPU_CSRS)CpuCsrsQva)->Bcuea);
+ DbgPrint("\t\tBcuea = %016Lx\n",
+ sableuncorrerr->CpuError[LogicalCpuNumber].Uncorrectable.Bcuea);
+
+ //
+ // If the Parity Error Bit is Set then
+ //
+ if(sableuncorrerr->CpuError[LogicalCpuNumber].Uncorrectable.Bcue &
+ (ULONGLONG)0x2) {
+ PUncorrectableError->UncorrectableFrame.Flags.
+ ExtendedErrorValid = 1;
+
+ PUncorrectableError->UncorrectableFrame.Flags.
+ ErrorStringValid = 1;
+ sprintf(PUncorrectableError->UncorrectableFrame.ErrorString,
+ "B-Cache Tag Error or Control Store Parity Error");
+ PUncorrectableError->UncorrectableFrame.Flags.
+ MemoryErrorSource = SYSTEM_CACHE;
+ PUncorrectableError->UncorrectableFrame.PhysicalAddress =
+ sableuncorrerr->CpuError[LogicalCpuNumber].Uncorrectable.Bcuea;
+ PUncorrectableError->UncorrectableFrame.Flags.
+ PhysicalAddressValid = 1;
+ PExtErr->CacheError.Flags.CacheBoardValid = 1;
+ PExtErr->CacheError.CacheBoardNumber = LogicalCpuNumber;
+ HalpGetProcessorInfo(&PExtErr->CacheError.ProcessorInfo);
+
+ }
+ if(sableuncorrerr->CpuError[LogicalCpuNumber].Uncorrectable.Bcue &
+ (ULONGLONG)0x8) {
+ PUncorrectableError->UncorrectableFrame.Flags.
+ MemoryErrorSource = SYSTEM_CACHE;
+ PUncorrectableError->UncorrectableFrame.PhysicalAddress =
+ sableuncorrerr->CpuError[LogicalCpuNumber].Uncorrectable.Bcuea;
+ PUncorrectableError->UncorrectableFrame.Flags.
+ PhysicalAddressValid = 1;
+
+ PUncorrectableError->UncorrectableFrame.Flags.
+ ExtendedErrorValid = 1;
+ PExtErr->CacheError.Flags.CacheBoardValid = 1;
+ PExtErr->CacheError.CacheBoardNumber = LogicalCpuNumber;
+ HalpGetProcessorInfo(&PExtErr->CacheError.ProcessorInfo);
+ }
+
+ sableuncorrerr->CpuError[LogicalCpuNumber].Dter =
+ READ_CPU_REGISTER(&((PSABLE_CPU_CSRS)CpuCsrsQva)->Dter);
+ DbgPrint("\t\tDter = %016Lx\n",
+ sableuncorrerr->CpuError[LogicalCpuNumber].Dter);
+
+ sableuncorrerr->CpuError[LogicalCpuNumber].Cberr =
+ READ_CPU_REGISTER(&((PSABLE_CPU_CSRS)CpuCsrsQva)->Cb2);
+ DbgPrint("\t\tCberr = %016Lx\n",
+ sableuncorrerr->CpuError[LogicalCpuNumber].Cberr);
+
+ sableuncorrerr->CpuError[LogicalCpuNumber].Cbeal =
+ READ_CPU_REGISTER(&((PSABLE_CPU_CSRS)CpuCsrsQva)->Cbeal);
+ DbgPrint("\t\tCbeal = %016Lx\n",
+ sableuncorrerr->CpuError[LogicalCpuNumber].Cbeal);
+
+ sableuncorrerr->CpuError[LogicalCpuNumber].Cbeah =
+ READ_CPU_REGISTER(&((PSABLE_CPU_CSRS)CpuCsrsQva)->Cbeah);
+ DbgPrint("\t\tCbeah = %016Lx\n",
+ sableuncorrerr->CpuError[LogicalCpuNumber].Cbeah);
+
+
+ //
+ // Fill in some of the control registers in the configuration
+ // structures.
+ //
+ DbgPrint("\n\t CPU Module Configuration : \n");
+ sableuncorrerr->Configuration.CpuConfigs[LogicalCpuNumber].Cbctl =
+ READ_CPU_REGISTER(&((PSABLE_CPU_CSRS)CpuCsrsQva)->Cbctl);
+ DbgPrint("\t\tCbctl = %016Lx\n",
+ sableuncorrerr->Configuration.CpuConfigs[LogicalCpuNumber].Cbctl);
+
+ sableuncorrerr->Configuration.CpuConfigs[LogicalCpuNumber].Pmbx =
+ READ_CPU_REGISTER(&((PSABLE_CPU_CSRS)CpuCsrsQva)->Pmbx);
+ DbgPrint("\t\tPmbx = %016Lx\n",
+ sableuncorrerr->Configuration.CpuConfigs[LogicalCpuNumber].Pmbx);
+
+ sableuncorrerr->Configuration.CpuConfigs[LogicalCpuNumber].C4rev =
+ READ_CPU_REGISTER(&((PSABLE_CPU_CSRS)CpuCsrsQva)->Crrevs);
+ DbgPrint("\t\tC4rev = %016Lx\n",
+ sableuncorrerr->Configuration.CpuConfigs[LogicalCpuNumber].C4rev);
+
+ }
+
+ sableuncorrerr->Configuration.NumberOfCpus = TotalNumberOfCpus;
+ DbgPrint("\tTotalNumberOfCpus = %d\n", TotalNumberOfCpus);
+
+ //
+ // Since I dont know how to get how many memory modules
+ // are available and which slots they are in we will skip
+ // the memory error logging. When we do this we will also fill in
+ // the memory configuration details.
+ //
+
+ //
+ // Get T2 errors.
+ //
+ DbgPrint("\n\tT2 Error Log :\n");
+ sableuncorrerr->IoChipsetError.Cerr1 =
+ READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Cerr1 );
+ DbgPrint("\t\tCerr1 = %016Lx\n",
+ sableuncorrerr->IoChipsetError.Cerr1);
+
+ Perr1.all = sableuncorrerr->IoChipsetError.Perr1 =
+ READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Perr1 );
+ DbgPrint("\t\tPerr1 = %016Lx\n",
+ sableuncorrerr->IoChipsetError.Perr1);
+
+ sableuncorrerr->IoChipsetError.Cerr2 =
+ READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Cerr2 );
+ DbgPrint("\t\tCerr2 = %016Lx\n",
+ sableuncorrerr->IoChipsetError.Cerr2);
+
+ sableuncorrerr->IoChipsetError.Cerr3 =
+ READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Cerr3 );
+ DbgPrint("\t\tCerr3 = %016Lx\n",
+ sableuncorrerr->IoChipsetError.Cerr3);
+
+ Perr2.all = sableuncorrerr->IoChipsetError.Perr2 =
+ READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Perr2 );
+ DbgPrint("\t\tPerr2 = %016Lx\n",
+ sableuncorrerr->IoChipsetError.Perr2);
+
+ if( (Perr1.WriteDataParityError == 1) ||
+ (Perr1.AddressParityError == 1) ||
+ (Perr1.ReadDataParityError == 1) ||
+ (Perr1.ParityError == 1) ||
+ (Perr1.SystemError == 1) ||
+ (Perr1.NonMaskableInterrupt == 1) ){
+
+ PUncorrectableError->UncorrectableFrame.PhysicalAddress =
+ Perr2.ErrorAddress;
+ PUncorrectableError->UncorrectableFrame.Flags.
+ PhysicalAddressValid = 1;
+ }
+
+
+
+ //
+ // T2 Configurations
+ //
+ DbgPrint("\n\tT2 Configuration :\n");
+ Iocsr.all = sableuncorrerr->Configuration.T2IoCsr =
+ READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Iocsr );
+ DbgPrint("\t\tIocsr = %016Lx\n",
+ sableuncorrerr->Configuration.T2IoCsr);
+
+ sableuncorrerr->Configuration.T2Revision = Iocsr.T2RevisionNumber;
+ DbgPrint("\t\tT2 Revision = %d\n",
+ sableuncorrerr->Configuration.T2Revision);
+
+
+ }
+
+ //
+ // Now fill in the Extended error information.
+ //
+ return;
+}
+
+
+BOOLEAN
+HalpPlatformMachineCheck(
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PKEXCEPTION_FRAME ExceptionFrame,
+ IN PKTRAP_FRAME TrapFrame
+ )
+/*++
+
+Routine Description:
+
+ This routine is given control when an hard error is acknowledged
+ by the APECS chipset. The routine is given the chance to
+ correct and dismiss the error.
+
+Arguments:
+
+ ExceptionRecord - Supplies a pointer to the exception record generated
+ at the point of the exception.
+
+ ExceptionFrame - Supplies a pointer to the exception frame generated
+ at the point of the exception.
+
+ TrapFrame - Supplies a pointer to the trap frame generated
+ at the point of the exception.
+
+Return Value:
+
+ TRUE is returned if the machine check has been handled and dismissed -
+ indicating that execution can continue. FALSE is return otherwise.
+
+--*/
+{
+//jnfix - again note that this only deals with errors signaled by the T2
+
+ T2_CERR1 Cerr1;
+ T2_PERR1 Perr1;
+ T2_PERR2 Perr2;
+ PLOGOUT_FRAME_21064 LogoutFrame;
+ ULONGLONG PA;
+ enum {
+ Pci0ConfigurationSpace,
+ Pci1ConfigurationSpace,
+ MemCsrSpace,
+ CPUCsrSpace,
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+ T4CsrSpace
+#endif
+ } AddressSpace;
+ PVOID TxCsrQva;
+ PALPHA_INSTRUCTION FaultingInstruction;
+ CHAR ErrSpace[32];
+
+ //
+ // Check if there are any CBUS errors pending. Any of these errors
+ // are fatal.
+ //
+
+ Cerr1.all = READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Cerr1 );
+
+ if( (Cerr1.UncorrectableReadError == 1) ||
+ (Cerr1.NoAcknowledgeError == 1) ||
+ (Cerr1.CommandAddressParityError == 1) ||
+ (Cerr1.MissedCommandAddressParity == 1) ||
+ (Cerr1.ResponderWriteDataParityError == 1) ||
+ (Cerr1.MissedRspWriteDataParityError == 1) ||
+ (Cerr1.ReadDataParityError == 1) ||
+ (Cerr1.MissedReadDataParityError == 1) ||
+ (Cerr1.CmdrWriteDataParityError == 1) ||
+ (Cerr1.BusSynchronizationError == 1) ||
+ (Cerr1.InvalidPfnError == 1) ){
+
+
+ sprintf(ErrSpace,"System Bus");
+ PUncorrectableError->UncorrectableFrame.Flags.AddressSpace =
+ IO_SPACE;
+ PUncorrectableError->UncorrectableFrame.ErrorInformation.
+ IoError.Interface = CBus;
+ goto FatalError;
+
+ }
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+ if( HalpXioPresent ){
+
+ Cerr1.all = READ_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Cerr1);
+
+ if( (Cerr1.UncorrectableReadError == 1) ||
+ (Cerr1.NoAcknowledgeError == 1) ||
+ (Cerr1.CommandAddressParityError == 1) ||
+ (Cerr1.MissedCommandAddressParity == 1) ||
+ (Cerr1.ResponderWriteDataParityError == 1) ||
+ (Cerr1.MissedRspWriteDataParityError == 1) ||
+ (Cerr1.ReadDataParityError == 1) ||
+ (Cerr1.MissedReadDataParityError == 1) ||
+ (Cerr1.CmdrWriteDataParityError == 1) ||
+ (Cerr1.BusSynchronizationError == 1) ||
+ (Cerr1.InvalidPfnError == 1) ){
+
+#if HALDBG
+ DbgPrint("HalpPlatformMachineCheck: T4 CERR1 = %Lx\n",
+ Cerr1.all);
+#endif
+
+ goto FatalError;
+
+ }
+
+ }
+
+#endif
+
+ //
+ // Check if there are any non-recoverable PCI errors.
+ //
+
+ Perr1.all = READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Perr1 );
+
+ if( (Perr1.WriteDataParityError == 1) ||
+ (Perr1.AddressParityError == 1) ||
+ (Perr1.ReadDataParityError == 1) ||
+ (Perr1.ParityError == 1) ||
+ (Perr1.SystemError == 1) ||
+ (Perr1.NonMaskableInterrupt == 1) ){
+
+ sprintf(ErrSpace,"PCI Bus");
+ PUncorrectableError->UncorrectableFrame.Flags.AddressSpace =
+ IO_SPACE;
+ PUncorrectableError->UncorrectableFrame.ErrorInformation.
+ IoError.Interface = PCIBus;
+ goto FatalError;
+
+ }
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+ //
+ // If the external I/O module is present, check the T4's CBUS and PCI
+ // error registers, as well.
+ //
+
+ if( HalpXioPresent ){
+
+ //
+ // Check if there are any non-recoverable PCI errors.
+ //
+
+ Perr1.all = READ_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Perr1 );
+
+ if( (Perr1.WriteDataParityError == 1) ||
+ (Perr1.AddressParityError == 1) ||
+ (Perr1.ReadDataParityError == 1) ||
+ (Perr1.ParityError == 1) ||
+ (Perr1.SystemError == 1) ||
+ (Perr1.NonMaskableInterrupt == 1) ){
+
+ goto FatalError;
+
+ }
+ }
+
+#endif
+
+ //
+ // Get a pointer to the EV4 machine check logout frame.
+ //
+
+ LogoutFrame = (PLOGOUT_FRAME_21064)
+ ExceptionRecord->ExceptionInformation[1];
+
+ //
+ // Get the physical address which caused the machine check.
+ //
+
+ PA = LogoutFrame->BiuAddr.QuadPart;
+
+ //
+ // We handle and dismiss 3 classes of machine checks:
+ //
+ // - Read accesses from PCI 0 configuration space
+ // - Read accesses from PCI 1 configuration space
+ // - Read accesses from T4 CSR space
+ //
+ // Any other type of machine check is fatal.
+ //
+ // The following set of conditionals check which address space the
+ // machine check occured in, to decide how to handle it.
+ //
+
+ if( (PA >= SABLE_PCI0_CONFIGURATION_PHYSICAL) &&
+ (PA < SABLE_PCI1_CONFIGURATION_PHYSICAL) ){
+
+ //
+ // The machine check occured in PCI 0 configuration space. Save
+ // the address space and a QVA to T2 CSR space, we'll need them
+ // below.
+ //
+
+ AddressSpace = Pci0ConfigurationSpace;
+ TxCsrQva = (PVOID)T2_CSRS_QVA;
+
+ } else if( (PA >= SABLE_PCI1_CONFIGURATION_PHYSICAL) &&
+ (PA < SABLE_PCI0_SPARSE_IO_PHYSICAL) ){
+
+ //
+ // The machine check occured in PCI 1 configuration space.
+ // Save the address space and a QVA to T2 CSR space, we'll
+ // need them below.
+ //
+
+ AddressSpace = Pci1ConfigurationSpace;
+ TxCsrQva = (PVOID)T4_CSRS_QVA;
+
+ } else if ( (PA >= SABLE_CPU0_CSRS_PHYSICAL) &&
+ (PA <= SABLE_CPU3_IPIR_PHYSICAL)) {
+
+ //
+ // The machine check occured within CPU CSR space. Save
+ // the address space, we'll need it below.
+ //
+
+ AddressSpace = CPUCsrSpace;
+
+ } else if ( (PA >= SABLE_MEM0_CSRS_PHYSICAL) &&
+ (PA < SABLE_T2_CSRS_PHYSICAL)) {
+
+ //
+ // The machine check occured within MEM CSR space. Save
+ // the address space, we'll need it below.
+ //
+
+ AddressSpace = MemCsrSpace;
+
+ //
+ // Just based on the physical address, we have determined
+ // we cannot handle this machine check.
+ //
+ } else
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+ if( (PA >= SABLE_T4_CSRS_PHYSICAL) &&
+ (PA < SABLE_PCI0_CONFIGURATION_PHYSICAL) ){
+
+ //
+ // The machine check occured within T4 CSR space. Save
+ // the address space, we'll need it below.
+ //
+
+ AddressSpace = T4CsrSpace;
+
+ } else
+
+#endif
+ {
+ goto FatalError;
+ }
+
+ //
+ // Get a pointer to the faulting instruction. (It is possible
+ // that the exception address is actually an instruction or two
+ // beyond the instruction which actually caused the machine check.)
+ //
+
+ FaultingInstruction = (PALPHA_INSTRUCTION)TrapFrame->Fir;
+
+ //
+ // There are typically 2 MBs which follow the load which caused the
+ // machine check. The exception address could be one of them.
+ // If it is, advance the instruction pointer ahead of them.
+ //
+
+ while( (FaultingInstruction->Memory.Opcode == MEMSPC_OP) &&
+ (FaultingInstruction->Memory.MemDisp == MB_FUNC) ){
+
+ FaultingInstruction--;
+
+ }
+
+ //
+ // If the instruction uses v0 as Ra (i.e. v0 is the target register
+ // of the instruction) then this would typically indicate an T2 or
+ // configuration space access routine, and getting a machine check
+ // therein is acceptable. Otherwise, we took it someplace else, and
+ // it is fatal.
+ //
+
+ if( FaultingInstruction->Memory.Ra != V0_REG ){
+
+ goto FatalError;
+
+ }
+
+ //
+ // Perform address space-dependent handling.
+ //
+
+ switch( AddressSpace ){
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+ case Pci0ConfigurationSpace:
+
+ //
+ // If no XIO module is present then we do not fix-up read accesses
+ // from PCI 1 configuration space. (This should never happen.)
+ //
+
+ if( !HalpXioPresent ){
+
+ goto FatalError;
+
+ }
+
+#endif
+
+ case Pci1ConfigurationSpace:
+
+ //
+ // Read the state of the T2/T4.
+ //
+
+ Perr1.all = READ_T2_REGISTER( &((PT2_CSRS)(TxCsrQva))->Perr1 );
+ Perr2.all = READ_T2_REGISTER( &((PT2_CSRS)(TxCsrQva))->Perr2 );
+ Cerr1.all = READ_T2_REGISTER( &((PT2_CSRS)(TxCsrQva))->Cerr1 );
+
+ //
+ // The T2/T4 responds differently when an error was received
+ // on type 0 and type 1 configuration cycles. For type 0 the
+ // T2/T4 detects and reports the device timeout. For type 1
+ // the PPB detects the timeout. Type 0 cycles error with
+ // the DeviceTimeout bit set. Type 1 cycles look just like
+ // NXM. Thus, the code below requires both checks.
+ //
+
+ if( (Perr1.DeviceTimeoutError != 1) &&
+ ((Perr1.all != 0) ||
+ (Cerr1.all != 0) ||
+ (Perr2.PciCommand != 0xA)) ){
+
+ goto FatalError;
+
+ }
+
+ //
+ // Clear any PCI or Cbus errors which may have been latched.
+ //
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(TxCsrQva))->Perr1, Perr1.all );
+
+ break;
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+ case T4CsrSpace:
+
+ //
+ // A read was performed from T4 CSR space when no XIO module was
+ // present. This was done, presumably, to detect the presence of
+ // the T4, and correspondingly, the XIO module. There is nothing
+ // special to do in this case, just fix-up the reference and
+ // dismiss the machine check.
+ //
+
+ break;
+#endif
+
+ case MemCsrSpace:
+ case CPUCsrSpace:
+
+ //
+ // A read was performed from Mem CSR space when no memory module was
+ // present. This was done, presumably, to detect the presence of
+ // a memory board.
+ //
+
+ break;
+
+ }
+
+ //
+ // Advance the instruction pointer.
+ //
+
+ TrapFrame->Fir += 4;
+
+ //
+ // Make it appear as if the load instruction read all ones.
+ //
+
+ TrapFrame->IntV0 = (ULONGLONG)-1;
+
+ //
+ // Dismiss the machine check.
+ //
+
+ return TRUE;
+
+
+//
+// The system is not well and cannot continue reliable execution.
+// Print some useful messages and return FALSE to indicate that the error
+// was not handled.
+//
+
+FatalError:
+ //
+ // Build the error frame. Later may be move it in front and use
+ // the field in the error frame rather than reading the error registers
+ // twice.
+ //
+
+ HalpBuildSableUncorrectableErrorFrame();
+
+ if(PUncorrectableError) {
+ PUncorrectableError->UncorrectableFrame.Flags.SystemInformationValid =
+ 1;
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+ sprintf(PUncorrectableError->UncorrectableFrame.ErrorString,
+ "Sable: Uncorrectable Error detected in %s", ErrSpace);
+ }
+
+
+ HalpSableReportFatalError();
+
+ return FALSE;
+
+}
+
+
+ULONG
+HalpTranslateSyndromToECC(
+ IN OUT PULONG Syndrome
+ )
+/*++
+
+Routine Description:
+
+ Translate the syndrome to a particular bit. If the syndrome indicates
+ a data bit, then return 0, if a check bit, then return 1.
+
+ In the place of the incoming syndrome, stuff the resulting bit.
+
+Arguments:
+
+ Syndrome Pointer to the syndrome
+
+Return Value:
+
+ 0 for data bit
+ 1 for check bit
+
+--*/
+{
+
+ static UCHAR SyndromeToECCTable[0xff] = {0, };
+ static BOOLEAN SyndromeToECCTableInitialized = FALSE;
+
+ ULONG Temp = *Syndrome;
+
+ //
+ // Initialize the table.
+ //
+
+ if (!SyndromeToECCTableInitialized) {
+ SyndromeToECCTableInitialized = TRUE;
+
+ //
+ // fill in the table
+ //
+
+ SyndromeToECCTable[0x1] = 0;
+ SyndromeToECCTable[0x2] = 1;
+ SyndromeToECCTable[0x4] = 2;
+ SyndromeToECCTable[0x8] = 3;
+ SyndromeToECCTable[0x10] = 4;
+ SyndromeToECCTable[0x20] = 5;
+ SyndromeToECCTable[0x40] = 6;
+
+ SyndromeToECCTable[0x4F] = 0;
+ SyndromeToECCTable[0x4A] = 1;
+ SyndromeToECCTable[0x52] = 2;
+ SyndromeToECCTable[0x54] = 3;
+ SyndromeToECCTable[0x57] = 4;
+ SyndromeToECCTable[0x58] = 5;
+ SyndromeToECCTable[0x5B] = 6;
+ SyndromeToECCTable[0x5D] = 7;
+ SyndromeToECCTable[0x23] = 8;
+ SyndromeToECCTable[0x25] = 9;
+ SyndromeToECCTable[0x26] = 10;
+ SyndromeToECCTable[0x29] = 11;
+ SyndromeToECCTable[0x2A] = 12;
+ SyndromeToECCTable[0x2C] = 13;
+ SyndromeToECCTable[0x31] = 14;
+ SyndromeToECCTable[0x34] = 15;
+ SyndromeToECCTable[0x0E] = 16;
+ SyndromeToECCTable[0x0B] = 17;
+ SyndromeToECCTable[0x13] = 18;
+ SyndromeToECCTable[0x15] = 19;
+ SyndromeToECCTable[0x16] = 20;
+ SyndromeToECCTable[0x19] = 21;
+ SyndromeToECCTable[0x1A] = 22;
+ SyndromeToECCTable[0x1C] = 23;
+ SyndromeToECCTable[0x62] = 24;
+ SyndromeToECCTable[0x64] = 25;
+ SyndromeToECCTable[0x67] = 26;
+ SyndromeToECCTable[0x68] = 27;
+ SyndromeToECCTable[0x6B] = 28;
+ SyndromeToECCTable[0x6D] = 29;
+ SyndromeToECCTable[0x70] = 30;
+ SyndromeToECCTable[0x75] = 31;
+ }
+
+ *Syndrome = SyndromeToECCTable[Temp];
+
+ if (Temp == 0x01 || Temp == 0x02 || Temp == 0x04 || Temp == 0x08 ||
+ Temp == 0x10 || Temp == 0x20 || Temp == 0x40) {
+ return 1;
+ } else {
+ return 0;
+ }
+
+}
+
+
+VOID
+HalpCPUCorrectableError(
+ IN ULONG PhysicalSlot,
+ IN OUT PCORRECTABLE_ERROR CorrPtr
+ )
+/*++
+
+Routine Description:
+
+ We have determined that a correctable error has occurred on a CPU
+ module -- the only thing this can be is a Bcache error. Populate the
+ correctable error frame.
+
+Arguments:
+
+ PhysicalSlot Physical CPU slot number
+ CorrPtr A pointer to the correctable error frame
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ SABLE_BCACHE_BCCE_CSR1 CSR1;
+ ULONG CERBase;
+ PULONGLONG VariableData = (PULONGLONG)CorrPtr->RawSystemInformation;
+
+ //
+ // Get CPU's bcache CER
+ //
+
+ CERBase = HalpCPUSlot[PhysicalSlot];
+ CSR1.all = READ_CPU_REGISTER((PVOID)(CERBase | 0x1));
+
+ //
+ // Set the bits, one by one
+ //
+
+ CorrPtr->Flags.AddressSpace = 1; // memory space
+ CorrPtr->Flags.PhysicalAddressValid = 0;
+ CorrPtr->Flags.ErrorBitMasksValid = 0;
+ CorrPtr->Flags.ExtendedErrorValid = 1;
+ CorrPtr->Flags.ProcessorInformationValid = 1;
+ CorrPtr->Flags.SystemInformationValid = 0;
+ CorrPtr->Flags.ServerManagementInformationValid = 0;
+ CorrPtr->Flags.MemoryErrorSource = 2; // processor cache
+
+ CorrPtr->Flags.ScrubError = 0; // ??
+ CorrPtr->Flags.LostCorrectable = CSR1.MissedCorrectableError |
+ CSR1.MissedCorrectableErrorH;
+
+
+ CorrPtr->Flags.LostAddressSpace = 0;
+ CorrPtr->Flags.LostMemoryErrorSource = 0;
+
+ CorrPtr->PhysicalAddress = 0;
+ CorrPtr->DataBitErrorMask = 0;
+ CorrPtr->CheckBitErrorMask = 0;
+
+ CorrPtr->ErrorInformation.CacheError.Flags.CacheLevelValid = 0;
+ CorrPtr->ErrorInformation.CacheError.Flags.CacheBoardValid = 0;
+ CorrPtr->ErrorInformation.CacheError.Flags.CacheSimmValid = 0;
+
+ CorrPtr->ErrorInformation.CacheError.ProcessorInfo.ProcessorType = 21064;
+ CorrPtr->ErrorInformation.CacheError.ProcessorInfo.ProcessorRevision = 0;
+ CorrPtr->ErrorInformation.CacheError.ProcessorInfo.PhysicalProcessorNumber =
+ SlotToPhysicalCPU[PhysicalSlot];
+ CorrPtr->ErrorInformation.CacheError.ProcessorInfo.LogicalProcessorNumber = 0;
+ CorrPtr->ErrorInformation.CacheError.CacheLevel = 0;
+ CorrPtr->ErrorInformation.CacheError.CacheSimm = 0;
+ CorrPtr->ErrorInformation.CacheError.TransferType = 0;
+
+ CorrPtr->RawProcessorInformationLength = 0;
+
+
+ //
+ // Dump raw Register Data (CSR0, 1, 2, 3, 4)
+ //
+
+ CorrPtr->RawSystemInformationLength = (5 * sizeof(ULONGLONG));
+
+ //
+ // Get CSR0 -- Bcache control register
+ //
+
+ *VariableData++ = READ_CPU_REGISTER((PVOID)(CERBase));
+
+ //
+ // Get CSR1 -- correctable error register
+ //
+
+ *VariableData++ = READ_MEM_REGISTER((PVOID)(CERBase | 0x1));
+
+ //
+ // Get CSR2 -- correctable error address register
+ //
+
+ *VariableData++ = READ_MEM_REGISTER((PVOID)(CERBase | 0x2));
+
+ //
+ // Get CSR3 -- uncorrectable error register
+ //
+
+ *VariableData++ = READ_MEM_REGISTER((PVOID)(CERBase | 0x3));
+
+ //
+ // Get CSR4 -- uncorrectable error address register
+ //
+
+ *VariableData++ = READ_MEM_REGISTER((PVOID)(CERBase | 0x4));
+
+ //
+ // wkcfix -- processor data?
+ //
+ // CorrPtr->RawProcessorInformationLength
+ // CorrPtr->RawProcessorInformation
+ //
+
+}
+
+
+VOID
+HalpMemoryCorrectableError(
+ IN ULONG PhysicalSlot,
+ IN OUT PCORRECTABLE_ERROR CorrPtr
+ )
+/*++
+
+Routine Description:
+
+ We have determined that a correctable error has occurred on a memory
+ module. Populate the correctable error frame.
+
+Arguments:
+
+ PhysicalSlot The physical slot of the falting board
+ CorrPtr A pointer to the correctable error frame
+
+Return Value:
+
+ None.
+
+--*/
+{
+ SGL_MEM_CSR0 CSR;
+ ULONG CSRBase;
+ PULONGLONG VariableData = (PULONGLONG)CorrPtr->RawSystemInformation;
+
+ //
+ // Get MEM modules base addr
+ //
+
+ CSRBase = HalpMemorySlot[PhysicalSlot];
+
+ //
+ // Get CSR0
+ //
+
+ CSR.all = READ_MEM_REGISTER((PVOID)CSRBase);
+
+ //
+ // Set the bits, one by one
+ //
+
+ CorrPtr->Flags.AddressSpace = 0; // ??
+ CorrPtr->Flags.PhysicalAddressValid = 0;
+ CorrPtr->Flags.ErrorBitMasksValid = 0;
+ CorrPtr->Flags.ExtendedErrorValid = 1;
+ CorrPtr->Flags.ProcessorInformationValid = 0;
+ CorrPtr->Flags.SystemInformationValid = 0;
+ CorrPtr->Flags.ServerManagementInformationValid = 0;
+ CorrPtr->Flags.MemoryErrorSource = 4; // processor memory
+
+ CorrPtr->PhysicalAddress = 0;
+ CorrPtr->DataBitErrorMask = 0;
+ CorrPtr->CheckBitErrorMask = 0;
+
+ CorrPtr->ErrorInformation.MemoryError.Flags.MemoryBoardValid = 0;
+ CorrPtr->ErrorInformation.MemoryError.Flags.MemorySimmValid = 0;
+
+ CorrPtr->ErrorInformation.MemoryError.MemoryBoard = PhysicalSlot;
+ CorrPtr->ErrorInformation.MemoryError.MemorySimm = 0;
+ CorrPtr->ErrorInformation.MemoryError.TransferType = 0;
+
+ CorrPtr->RawProcessorInformationLength = 0;
+
+ //
+ // Dump raw CSR data (CSRO, 1, 2, 4)
+ //
+
+ CorrPtr->RawSystemInformationLength = (4 * sizeof(ULONGLONG));
+ *VariableData++ = CSR.all;
+
+ //
+ // Get CSR1
+ //
+
+ CSR.all = READ_MEM_REGISTER((PVOID)(CSRBase | 0x1));
+ *VariableData++ = CSR.all;
+
+ //
+ // Get CSR2
+ //
+
+ CSR.all = READ_MEM_REGISTER((PVOID)(CSRBase | 0x2));
+ *VariableData++ = CSR.all;
+
+ //
+ // Get CSR4
+ //
+
+ CSR.all = READ_MEM_REGISTER((PVOID)(CSRBase | 0x4));
+ *VariableData++ = CSR.all;
+
+
+ //
+ // wkcfix -- processor data?
+ //
+ // CorrPtr->RawProcessorInformationLength
+ // CorrPtr->RawProcessorInformation
+ //
+
+}
+
+
+VOID
+HalpT2CorrectableError(
+ IN ULONG PhysicalSlot,
+ IN OUT PCORRECTABLE_ERROR CorrPtr
+ )
+/*++
+
+Routine Description:
+
+ We have determined that a correctable error has occurred on the CBus.
+ Populate the correctable error frame.
+
+Arguments:
+
+ Physical Slot
+ CorrPtr A pointer to the correctable error frame
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // This should never be called, because there are no correctable T2 errors.
+ //
+}
+
+
+
+ULONG
+HalpCheckCPUForError(
+ IN OUT PULONG Slot
+ )
+/*++
+
+Routine Description:
+
+ Check the CPU module CSR for BCACHE error.
+
+Arguments:
+
+ Slot The return value for the slot if an error is found
+
+Return Value:
+
+ Either CorrectableError or NoError
+
+--*/
+{
+
+ ULONG i;
+ SABLE_BCACHE_BCCE_CSR1 CSR1;
+ ULONG BaseCSRQVA;
+
+ //
+ // Run through the CPU modules looking for a correctable
+ // error.
+ //
+
+ for (i=0; i<4; i++) {
+
+ //
+ // If a cpu board is present, then use the QVA stored in that
+ // location -- if a CPU module is not present, then the value is 0.
+ //
+
+ if (HalpCPUSlot[i] != 0) {
+
+ BaseCSRQVA = HalpCPUSlot[i];
+
+ //
+ // Read the backup cache correctable error register (CSR1)
+ //
+
+ CSR1.all = READ_CPU_REGISTER((PVOID)(BaseCSRQVA | 0x1));
+
+ //
+ // Check the two correctable error bits -- if one at least one
+ // is set, then go off and build the frame and jump directly
+ // to the correctable error flow.
+ //
+
+ if (CSR1.CorrectableError || CSR1.CorrectableErrorH ||
+ CSR1.MissedCorrectableError || CSR1.MissedCorrectableErrorH) {
+
+ *Slot = i;
+ return CorrectableError;
+ }
+ }
+ }
+
+ return NoError;
+}
+
+
+ULONG
+HalpCheckMEMForError(
+ PULONG Slot
+ )
+/*++
+
+Routine Description:
+
+ Check the Memory module CSR for errors.
+
+Arguments:
+
+ Slot The return value for the slot if an error is found
+
+Return Value:
+
+ Either CorrectableError or NoError or UncorrectableError
+
+--*/
+{
+
+ SGL_MEM_CSR0 CSR;
+ ULONG i;
+ ULONG BaseCSRQVA;
+
+ //
+ // If we have fallen through the CPU correctable errors,
+ // check the Memory boards
+ //
+
+ for (i=0; i<4; i++) {
+
+ //
+ // If a memory board is present, then the value is the QVA of CSR0
+ // on that memory board. If not present, the value is 0.
+ //
+
+ if (HalpMemorySlot[i] != 0) {
+
+ BaseCSRQVA = HalpMemorySlot[i];
+
+ CSR.all = READ_MEM_REGISTER((PVOID)BaseCSRQVA);
+
+ //
+ // Sync Errors are NOT part of the summary registers (bogus
+ // if you ask me....), but check them first.
+ //
+
+ if (CSR.SyncError1 || CSR.SyncError2) {
+ *Slot = i;
+ return CorrectableError;
+ }
+
+ //
+ // The error summary bit indicates if ANY error bits are
+ // lit. If no error on this module, then skip to the next one.
+ //
+
+ if (CSR.ErrorSummary1 == 0 && CSR.ErrorSummary2 == 0) {
+ continue;
+ }
+
+ //
+ // Because one of the summary registers are set, then this memory
+ // module has indicated an error. Check the correctable bits. If
+ // any are set, then build a correctable error frame, otherwise,
+ // drop back 20 and punt.
+ //
+
+ *Slot = i;
+
+ if (CSR.EDCCorrectable1 || CSR.EDCCorrectable2 ||
+ CSR.EDCMissdedCorrectable1 || CSR.EDCMissdedCorrectable2) {
+
+ return CorrectableError;
+ } else {
+ return UncorrectableError;
+ }
+ }
+ }
+
+ return NoError;
+
+}
+
+
+ULONG
+HalpCheckT2ForError(
+ PULONG Slot
+ )
+/*++
+
+Routine Description:
+
+ Check the System Host Chips for Errors.
+
+Arguments:
+
+ Slot The return value for the QVA of the T2 of an error is returned.
+
+Return Value:
+
+ Either CorrectableError or NoError or UncorrectableError
+
+--*/
+{
+ T2_CERR1 Cerr1;
+
+ *Slot = 0;
+
+ //
+ // Run through the T2 chips (OK, they may be T2, or T3 or T4...)
+ // and check for correctable errors
+ //
+
+ Cerr1.all = READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Cerr1 );
+
+ if( (Cerr1.UncorrectableReadError == 1) ||
+ (Cerr1.NoAcknowledgeError == 1) ||
+ (Cerr1.CommandAddressParityError == 1) ||
+ (Cerr1.MissedCommandAddressParity == 1) ||
+ (Cerr1.ResponderWriteDataParityError == 1) ||
+ (Cerr1.MissedRspWriteDataParityError == 1) ||
+ (Cerr1.ReadDataParityError == 1) ||
+ (Cerr1.MissedReadDataParityError == 1) ||
+ (Cerr1.CmdrWriteDataParityError == 1) ||
+ (Cerr1.BusSynchronizationError == 1) ||
+ (Cerr1.InvalidPfnError == 1) ){
+
+ return UncorrectableError;
+ }
+
+ //
+ // There are no uncorrectable CBus errors
+ //
+
+ return NoError;
+}
+
+
+VOID
+HalpSableErrorInterrupt(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is entered as a result of an error interrupt from the
+ T2 on a Sable system. This function determines if the error is
+ fatal or recoverable and if recoverable performs the recovery and
+ error logging.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ static ERROR_FRAME Frame;
+
+ ULONG DetectedError;
+
+ ULONG Slot = 0;
+ PULONG DispatchCode;
+ PKINTERRUPT InterruptObject;
+ PKSPIN_LOCK ErrorlogSpinLock;
+ PCORRECTABLE_ERROR CorrPtr;
+ PBOOLEAN ErrorlogBusy;
+ ERROR_FRAME TempFrame;
+
+ //
+ // Get the interrupt information
+ //
+
+ DispatchCode = (PULONG)(PCR->InterruptRoutine[CORRECTABLE_VECTOR]);
+ InterruptObject = CONTAINING_RECORD(DispatchCode,
+ KINTERRUPT,
+ DispatchCode);
+
+ //
+ // Set various pointers so we can use them later.
+ //
+
+ CorrPtr = &TempFrame.CorrectableFrame;
+ ErrorlogBusy = (PBOOLEAN)((PUCHAR)InterruptObject->ServiceContext +
+ sizeof(PERROR_FRAME));
+ ErrorlogSpinLock = (PKSPIN_LOCK)((PUCHAR)ErrorlogBusy + sizeof(PBOOLEAN));
+
+ //
+ // Clear the data structures that we will use.
+ //
+
+ RtlZeroMemory(&TempFrame, sizeof(ERROR_FRAME));
+
+ //
+ // Find out if a CPU module had any errors
+ //
+
+ DetectedError = HalpCheckCPUForError(&Slot);
+
+ if (DetectedError == UncorrectableError) {
+ goto UCError;
+ } else if (DetectedError == CorrectableError) {
+ HalpCPUCorrectableError(Slot, CorrPtr);
+ goto CError;
+ }
+
+ //
+ // Find out if Memory module had any errors
+ //
+
+ DetectedError = HalpCheckMEMForError(&Slot);
+
+ if (DetectedError == UncorrectableError) {
+ goto UCError;
+ } else if (DetectedError == CorrectableError) {
+ HalpMemoryCorrectableError(Slot, CorrPtr);
+ goto CError;
+ }
+
+
+ //
+ // Find out if the T2's had any errors
+ //
+
+ DetectedError = HalpCheckT2ForError(&Slot);
+
+ if (DetectedError == UncorrectableError) {
+ goto UCError;
+ } else if (DetectedError == CorrectableError) {
+ HalpT2CorrectableError(Slot, CorrPtr);
+ goto CError;
+ } else {
+ return; // no error?
+ }
+
+CError:
+
+ //
+ // Build the rest of the error frame
+ //
+
+ SGLCorrectedErrors += 1;
+
+ TempFrame.FrameType = CorrectableFrame;
+ TempFrame.VersionNumber = ERROR_FRAME_VERSION;
+ TempFrame.SequenceNumber = SGLCorrectedErrors;
+ TempFrame.PerformanceCounterValue =
+ KeQueryPerformanceCounter(NULL).QuadPart;
+
+ //
+ // Acquire the spinlock.
+ //
+
+ KiAcquireSpinLock(ErrorlogSpinLock);
+
+ //
+ // Check to see if an errorlog operation is in progress already.
+ // Then add our platform info...
+ //
+
+ if (!*ErrorlogBusy) {
+
+ // wkc fix....
+
+ } else {
+
+ //
+ // An errorlog operation is in progress already. We will
+ // set various lost bits and then get out without doing
+ // an actual errorloging call.
+ //
+
+ Frame.CorrectableFrame.Flags.LostCorrectable = TRUE;
+ Frame.CorrectableFrame.Flags.LostAddressSpace =
+ TempFrame.CorrectableFrame.Flags.AddressSpace;
+ Frame.CorrectableFrame.Flags.LostMemoryErrorSource =
+ TempFrame.CorrectableFrame.Flags.MemoryErrorSource;
+ }
+
+ //
+ // Release the spinlock.
+ //
+
+ KiReleaseSpinLock(ErrorlogSpinLock);
+
+ //
+ // Dispatch to the secondary correctable interrupt service routine.
+ // The assumption here is that if this interrupt ever happens, then
+ // some driver enabled it, and the driver should have the ISR connected.
+ //
+
+ ((PSECOND_LEVEL_DISPATCH)InterruptObject->DispatchAddress)(
+ InterruptObject,
+ InterruptObject->ServiceContext
+ );
+
+ //
+ // Clear the error and return (wkcfix -- clear now? or in routines).
+ //
+
+ return;
+
+
+UCError: // wkcfix
+
+ //
+ // The interrupt indicates a fatal system error.
+ // Display information about the error and shutdown the machine.
+ //
+
+ HalpBuildSableUncorrectableErrorFrame();
+
+ if(PUncorrectableError) {
+ PUncorrectableError->UncorrectableFrame.Flags.SystemInformationValid =
+ 1;
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+ sprintf(PUncorrectableError->UncorrectableFrame.ErrorString,
+ "Sable: Uncorrectable Error interrupt from T2");
+ }
+
+
+ HalpSableReportFatalError();
+
+ KeBugCheckEx( DATA_BUS_ERROR,
+ 0xfacefeed, //jnfix - quick error interrupt id
+ 0,
+ 0,
+ (ULONG)PUncorrectableError );
+}
+
+
+VOID
+HalpSableReportFatalError(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function reports and interprets a fatal hardware error on
+ a Sable system. Currently, only the T2 error registers - CERR1 and PERR1
+ are used to interpret the error.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ T2_CERR1 Cerr1;
+ ULONGLONG Cerr2;
+ ULONGLONG Cerr3;
+ UCHAR OutBuffer[MAX_ERROR_STRING];
+ T2_PERR1 Perr1;
+ T2_PERR2 Perr2;
+ PCHAR parityErrString = NULL;
+ PEXTENDED_ERROR exterr;
+
+ if(PUncorrectableError) {
+ exterr = &PUncorrectableError->UncorrectableFrame.ErrorInformation;
+ parityErrString = PUncorrectableError->UncorrectableFrame.ErrorString;
+ }
+
+ //
+ // Begin the error output by acquiring ownership of the display
+ // and printing the dreaded banner.
+ //
+
+ HalAcquireDisplayOwnership(NULL);
+
+ HalDisplayString( "\nFatal system hardware error.\n\n" );
+
+ //
+ // Read both of the error registers. It is possible that more
+ // than one error was reported simulataneously.
+ //
+
+ Cerr1.all = READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Cerr1 );
+ Perr1.all = READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Perr1 );
+
+ //
+ // Read all of the relevant error address registers.
+ //
+
+ Cerr2 = READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Cerr2 );
+ Cerr3 = READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Cerr3 );
+
+ Perr2.all = READ_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Perr2 );
+
+ //
+ // Interpret any errors from CERR1.
+ //
+
+ sprintf( OutBuffer, "T2 CERR1 = 0x%Lx\n", Cerr1.all );
+ HalDisplayString( OutBuffer );
+
+ if( Cerr1.UncorrectableReadError == 1 ){
+
+ sprintf( OutBuffer,
+ "Uncorrectable read error, CBUS Address = 0x%Lx%16Lx\n",
+ Cerr3,
+ Cerr2 );
+ HalDisplayString( OutBuffer );
+
+ }
+
+ if( Cerr1.NoAcknowledgeError == 1 ){
+
+ sprintf( OutBuffer,
+ "No Acknowledgement Error, CBUS Address = 0x%Lx%16Lx\n",
+ Cerr3,
+ Cerr2 );
+ HalDisplayString( OutBuffer );
+
+ }
+
+ if( Cerr1.CommandAddressParityError == 1 ){
+
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+ sprintf( OutBuffer,
+ "Command Address Parity Error, CBUS Address = 0x%Lx%16Lx\n",
+ Cerr3,
+ Cerr2 );
+ HalDisplayString( OutBuffer );
+
+ if( Cerr1.CaParityErrorLw3 == 1 ){
+ sprintf( parityErrString,
+ "C/A Parity Error on longword 3\n");
+ HalDisplayString( "C/A Parity Error on longword 3\n" );
+ }
+
+ if( Cerr1.CaParityErrorLw2 == 1 ){
+ sprintf( parityErrString,
+ "C/A Parity Error on longword 2\n" );
+ HalDisplayString( "C/A Parity Error on longword 2\n" );
+ }
+
+ if( Cerr1.CaParityErrorLw1 == 1 ){
+ sprintf( parityErrString,
+ "C/A Parity Error on longword 1\n");
+ HalDisplayString( "C/A Parity Error on longword 1\n" );
+ }
+
+ if( Cerr1.CaParityErrorLw0 == 1 ){
+ sprintf( parityErrString,
+ "C/A Parity Error on longword 0\n" );
+ HalDisplayString( "C/A Parity Error on longword 0\n" );
+ }
+
+ }
+
+ if( Cerr1.MissedCommandAddressParity == 1 ){
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+ sprintf( parityErrString,
+ "Missed C/A Parity Error\n" );
+ HalDisplayString( "Missed C/A Parity Error\n" );
+ }
+
+ if( (Cerr1.ResponderWriteDataParityError == 1) ||
+ (Cerr1.ReadDataParityError == 1) ){
+
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+
+ sprintf( OutBuffer,
+ "T2 detected Data Parity error, CBUS Address = 0x%Lx16Lx\n",
+ Cerr3,
+ Cerr2 );
+ HalDisplayString( OutBuffer );
+
+ sprintf( OutBuffer,
+ "T2 was %s on error transaction\n",
+ Cerr1.ResponderWriteDataParityError == 1 ? "responder" :
+ "commander" );
+ HalDisplayString( OutBuffer );
+
+ if( Cerr1.DataParityErrorLw0 == 1 ){
+ sprintf( parityErrString,
+ "Data Parity on longword 0\n" );
+ HalDisplayString( "Data Parity on longword 0\n" );
+ }
+
+ if( Cerr1.DataParityErrorLw1 == 1 ){
+ sprintf( parityErrString,
+ "Data Parity on longword 1\n" );
+ HalDisplayString( "Data Parity on longword 1\n" );
+ }
+
+ if( Cerr1.DataParityErrorLw2 == 1 ){
+ sprintf( parityErrString,
+ "Data Parity on longword 2\n");
+ HalDisplayString( "Data Parity on longword 2\n" );
+ }
+
+ if( Cerr1.DataParityErrorLw3 == 1 ){
+ sprintf( parityErrString,
+ "Data Parity on longword 3\n" );
+ HalDisplayString( "Data Parity on longword 3\n" );
+ }
+
+ if( Cerr1.DataParityErrorLw4 == 1 ){
+ sprintf( parityErrString,
+ "Data Parity on longword 4\n" );
+ HalDisplayString( "Data Parity on longword 4\n" );
+ }
+
+ if( Cerr1.DataParityErrorLw5 == 1 ){
+ sprintf( parityErrString,
+ "Data Parity on longword 5\n" );
+ HalDisplayString( "Data Parity on longword 5\n" );
+ }
+
+ if( Cerr1.DataParityErrorLw6 == 1 ){
+ sprintf( parityErrString,
+ "Data Parity on longword 6\n" );
+ HalDisplayString( "Data Parity on longword 6\n" );
+ }
+
+ if( Cerr1.DataParityErrorLw7 == 1 ){
+ sprintf( parityErrString,
+ "Data Parity on longword 7\n" );
+ HalDisplayString( "Data Parity on longword 7\n" );
+ }
+
+ } //(Cerr1.ResponderWriteDataParityError == 1) || ...
+
+
+ if( Cerr1.MissedRspWriteDataParityError == 1 ){
+ HalDisplayString( "Missed data parity error as responder\n" );
+ }
+
+ if( Cerr1.MissedReadDataParityError == 1 ){
+ HalDisplayString( "Missed data parity error as commander\n" );
+ }
+
+
+ if( Cerr1.CmdrWriteDataParityError == 1 ){
+
+ sprintf( OutBuffer,
+ "Commander Write Parity Error, CBUS Address = 0x%Lx%16Lx\n",
+ Cerr3,
+ Cerr2 );
+ HalDisplayString( OutBuffer );
+
+ }
+
+ if( Cerr1.BusSynchronizationError == 1 ){
+
+ sprintf( OutBuffer,
+ "Bus Synchronization Error, CBUS Address = 0x%Lx%16Lx\n",
+ Cerr3,
+ Cerr2 );
+ HalDisplayString( OutBuffer );
+
+ }
+
+ if( Cerr1.InvalidPfnError == 1 ){
+
+ sprintf( OutBuffer,
+ "Invalid PFN for scatter/gather, CBUS Address = 0x%Lx%16Lx\n",
+ Cerr3,
+ Cerr2 );
+ HalDisplayString( OutBuffer );
+
+ }
+
+ //
+ // Interpret any errors from T2 PERR1.
+ //
+
+ sprintf( OutBuffer, "PERR1 = 0x%Lx\n", Perr1.all );
+ HalDisplayString( OutBuffer );
+
+ if( Perr1.WriteDataParityError == 1 ){
+
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+ sprintf( parityErrString,
+ "T2 (slave) detected write parity error\n");
+ PUncorrectableError->UncorrectableFrame.ErrorInformation.
+ IoError.BusAddress.LowPart = Perr2.ErrorAddress;
+ sprintf( OutBuffer,
+ "T2 (slave) detected write parity error, PCI Cmd: %x, PCI Address: %lx\n",
+ Perr2.PciCommand,
+ Perr2.ErrorAddress );
+ HalDisplayString( OutBuffer );
+
+ }
+
+ if( Perr1.AddressParityError == 1 ){
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+
+ sprintf( parityErrString,
+ "T2 (slave) detected address parity error\n");
+
+ PUncorrectableError->UncorrectableFrame.ErrorInformation.
+ IoError.BusAddress.LowPart = Perr2.ErrorAddress;
+ sprintf( OutBuffer,
+ "T2 (slave) detected address parity error, PCI Cmd: %x, PCI Address: %lx\n",
+ Perr2.PciCommand,
+ Perr2.ErrorAddress );
+ HalDisplayString( OutBuffer );
+
+ }
+
+ if( Perr1.ReadDataParityError == 1 ){
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+
+ sprintf( parityErrString,
+ "T2 (master) detected read parity error\n");
+
+ PUncorrectableError->UncorrectableFrame.ErrorInformation.
+ IoError.BusAddress.LowPart = Perr2.ErrorAddress;
+
+ sprintf( OutBuffer,
+ "T2 (master) detected read parity error, PCI Cmd: %x, PCI Address: %lx\n",
+ Perr2.PciCommand,
+ Perr2.ErrorAddress );
+ HalDisplayString( OutBuffer );
+
+ }
+
+ if( Perr1.ParityError == 1 ){
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+
+ sprintf( parityErrString,
+ "Participant asserted PERR#, parity error\n");
+
+ PUncorrectableError->UncorrectableFrame.ErrorInformation.
+ IoError.BusAddress.LowPart = Perr2.ErrorAddress;
+
+ sprintf( OutBuffer,
+ "Participant asserted PERR#, parity error, PCI Cmd: %x, PCI Address: %lx\n",
+ Perr2.PciCommand,
+ Perr2.ErrorAddress );
+ HalDisplayString( OutBuffer );
+
+ }
+
+ if( Perr1.ParityError == 1 ){
+ PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1;
+
+ sprintf( parityErrString,
+ "Slave asserted SERR#, parity error\n");
+
+ PUncorrectableError->UncorrectableFrame.ErrorInformation.
+ IoError.BusAddress.LowPart = Perr2.ErrorAddress;
+
+ sprintf( OutBuffer,
+ "Slave asserted SERR#, PCI Cmd: %x, PCI Address: %lx\n",
+ Perr2.PciCommand,
+ Perr2.ErrorAddress );
+ HalDisplayString( OutBuffer );
+
+ }
+
+ if( Perr1.DeviceTimeoutError == 1 ){
+
+ sprintf( OutBuffer,
+ "Device timeout error, PCI Cmd: %x, PCI Address: %lx\n",
+ Perr2.PciCommand,
+ Perr2.ErrorAddress );
+ HalDisplayString( OutBuffer );
+
+ }
+
+ if( Perr1.DeviceTimeoutError == 1 ){
+
+ HalDisplayString( "PCI NMI asserted.\n" );
+
+ }
+
+ return;
+
+}
diff --git a/private/ntos/nthals/halsable/alpha/sableio.s b/private/ntos/nthals/halsable/alpha/sableio.s
new file mode 100644
index 000000000..fd3a6f188
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/sableio.s
@@ -0,0 +1,956 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ sableio.s
+
+
+Abstract:
+
+ This contains assembler code routines for the Sable system.
+
+ 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:
+
+
+--*/
+
+#include "sable.h"
+#include "halalpha.h"
+
+.set noreorder
+
+
+ LEAF_ENTRY(WRITE_T2_REGISTER)
+
+ ALTERNATE_ENTRY(WRITE_CPU_REGISTER)
+
+ ALTERNATE_ENTRY(WRITE_MEM_REGISTER)
+
+/*++
+Routine Description:
+ Writes a T2, Memory Module or a CPU CSR.
+
+Arguments:
+ a0 QVA of register to be written.
+ a1 Longword to be written.
+
+Return Value:
+ None.
+--*/
+
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0
+ ldiq t4, -0x4000
+ sll t4, 28, t4
+ or t0, t4, t0 // superpage mode
+ stq a1, (t0) // write the quadword
+ mb // order the write
+ mb
+ ret zero, (ra)
+
+2:
+ BREAK_DEBUG_STOP // Bad Qva
+ ret zero, (ra)
+
+ .end WRITE_T2_REGISTER
+
+
+
+ LEAF_ENTRY(READ_T2_REGISTER)
+
+ ALTERNATE_ENTRY(READ_CPU_REGISTER)
+
+ ALTERNATE_ENTRY(READ_MEM_REGISTER)
+
+/*++
+
+Routine Description:
+ Read a T2, Memory Module or CPU CSR.
+
+Arguments:
+ a0 QVA of register to be read.
+
+Return Value:
+ The quadword read from the register.
+
+--*/
+
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
+ bne t1, 2f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0
+ ldiq t4, -0x4000
+ sll t4, 28, t4
+ or t0, t4, t0 // superpage mode
+
+ ldq v0, (t0) // read the register
+ mb // synchronize
+ mb //
+
+ ret zero, (ra)
+
+2:
+ BREAK_DEBUG_STOP // Bad Qva
+ ret zero, (ra)
+
+ .end READ_T2_REGISTER
+
+
+//
+// Values and structures used to access configuration space.
+//
+
+//
+// Define the QVA for the Configuration Cycle Type register within the
+// IOC.
+//
+
+// PASS 1 SABLE SUPPORT
+
+#define T2_HAE0_2_QVA (0xbc700008)
+#define T2_HAE02_CYCLETYPE_SHIFT 30
+#define T2_HAE02_CYCLETYPE_MASK 0xc0000000
+
+// PASS 2 SABLE SUPPORT
+
+#define T2_HAE0_3_QVA (0xbc700012)
+#define T2_HAE03_CYCLETYPE_SHIFT 30
+#define T2_HAE03_CYCLETYPE_MASK 0xc0000000
+#define T2_CONFIG_ADDR_QVA (0xbc800000)
+
+// T4 SUPPORT
+
+#define T4_HAE0_3_QVA (0xbc780012)
+#define T4_CONFIG_ADDR_QVA (0xbcc00000)
+
+#define T2_OR_T4 (0x00400000)
+
+//
+// Define the configuration routines stack frame.
+//
+
+ .struct 0
+CfgRa: .space 8 // return address
+CfgA0: .space 8 // saved ConfigurationAddress
+CfgA1: .space 8 // saved ConfigurationData
+CfgA2: .space 8 // padding for 16 byte alignment
+CfgFrameLength:
+
+
+//++
+//
+// ULONG
+// READ_CONFIG_UCHAR(
+// ULONG ConfigurationAddress,
+// ULONG ConfigurationCycleType
+// )
+//
+// Routine Description:
+//
+// Read an unsigned byte from PCI configuration space.
+//
+// Arguments:
+//
+// ConfigurationAddress(a0) - Supplies the QVA of configuration to be read.
+//
+// ConfigurationCycleType(a1) - Supplies the type of the configuration cycle.
+//
+// Return Value:
+//
+// (v0) Returns the value of configuration space at the specified location.
+//
+// N.B. - This routine follows a protocol for reading from PCI configuration
+// space that allows the HAL or firmware to fixup and continue
+// execution if no device exists at the configuration target address.
+// The protocol requires 2 rules:
+// (1) The configuration space load must use a destination register
+// of v0
+// (2) The instruction immediately following the configuration space
+// load must use v0 as an operand (it must consume the value
+// returned by the load)
+//
+//--
+
+ NESTED_ENTRY( READ_CONFIG_UCHAR, CfgFrameLength, zero )
+
+ lda sp, -CfgFrameLength(sp) // allocate stack frame
+ stq ra, CfgRa(sp) // save return address
+
+ PROLOGUE_END // end prologue
+
+//
+// Depending on whether it's a pass 1 or pass 2 sable the configuration
+// cycle type is in different registers
+//
+ ldl t0, T2VersionNumber // load version number
+ beq t0, 1f // if 0 then pass 1 sable
+
+
+//
+// PASS 2 sable or Xio access:
+// Cycle type are the only bits in HAE0_3 register
+//
+ stq a0, CfgA0(sp) // save config space address
+
+//
+// See if this was a request on the T4 or the T2 by looking at the
+// Config address passed in.
+//
+
+ ldil t1, T2_HAE0_3_QVA // address of T2's HAE0_3
+ ldil t2, T4_HAE0_3_QVA // address of T4's HAE0_3
+
+ ldil t0, T2_OR_T4 // Load mask to tell if T2 or T4
+ and a0, t0, t3 // mask out other bits
+ cmoveq t3, t1, a0 // if t3 == 0 then t1 -> a0
+ cmovne t3, t2, a0 // if t3 != 0 then t2 -> a0
+
+ sll a1, T2_HAE03_CYCLETYPE_SHIFT, a1 // put cycle type in position
+ bsr ra, WRITE_T2_REGISTER // write updated HAE
+
+ br zero, 2f // go do actual read
+
+//
+// PASS 1 sable
+// Merge the configuration cycle type into the HAE0_2 register within
+// the T2.
+//
+
+1:
+
+ stq a0, CfgA0(sp) // save config space address
+ stq a1, CfgA1(sp) // save config cycle type
+
+ ldil a0, T2_HAE0_2_QVA // address of HAE0_2
+ bsr ra, READ_T2_REGISTER // read current value
+
+ ldq a1, CfgA1(sp) // restore config cycle type
+ ldil t0, T2_HAE02_CYCLETYPE_MASK // get cycle type field mask
+ bic v0, t0, t0 // clear config cycle type field
+
+ sll a1, T2_HAE02_CYCLETYPE_SHIFT, a1// put cycle type in position
+ bis a1, t0, a1 // merge config cycle type
+
+ ldil a0, T2_HAE0_2_QVA // address of HAE0_2
+ bsr ra, WRITE_T2_REGISTER // write updated HAE
+
+//
+// Perform the read from configuration space after restoring the
+// configuration space address.
+//
+
+2:
+
+ ldq a0, CfgA0(sp) // restore config space address
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 0x3, t3 // capture byte lane
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set
+ bne t1, 3f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, -0x4000 //
+ sll t4, 28, t4 //
+ bis t0, t4, t0 // superpage mode
+
+ bis t0, IO_BYTE_LEN, t0 // or in the byte enables
+
+ ldl v0, (t0) // read the longword
+ extbl v0, t3, v0 // return byte from requested lane
+ // also, consume loaded value
+ // to cause a pipeline stall
+ mb // Sable requires MBs or the
+ mb // machine check may happen
+ // much later
+
+3: //
+ ldq ra, CfgRa(sp) // restore return address
+ lda sp, CfgFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // return
+
+ .end READ_CONFIG_UCHAR
+
+//++
+//
+// VOID
+// WRITE_CONFIG_UCHAR(
+// ULONG ConfigurationAddress,
+// UCHAR ConfigurationData,
+// ULONG ConfigurationCycleType
+// )
+//
+// Routine Description:
+//
+// Read an unsigned byte from PCI configuration space.
+//
+// Arguments:
+//
+// ConfigurationAddress(a0) - Supplies the QVA to write.
+//
+// ConfigurationData(a1) - Supplies the data to be written.
+//
+// ConfigurationCycleType(a2) - Supplies the type of the configuration cycle.
+//
+// Return Value:
+//
+// None.
+//
+// N.B. - The configuration address must exist within the address space
+// allocated to an existing PCI device. Otherwise, the access
+// below will initiate an unrecoverable machine check.
+//
+//--
+
+ NESTED_ENTRY( WRITE_CONFIG_UCHAR, CfgFrameLength, zero )
+
+ lda sp, -CfgFrameLength(sp) // allocate stack frame
+ stq ra, CfgRa(sp) // save return address
+
+ PROLOGUE_END // end prologue
+
+//
+// Depending on whether it's a pass 1 or pass 2 sable the configuration
+// cycle type is in different registers
+//
+ ldl t0, T2VersionNumber // load version number
+ beq t0, 1f // if 0 then pass 1 sable
+
+//
+// PASS 2 sable
+// Merge the configuration cycle type into the HAE0_3 register within
+// the T2.
+//
+
+ stq a0, CfgA0(sp) // save config space address
+ stq a1, CfgA1(sp) // save config data
+
+//
+// See if this was a request on the T4 or the T2 by looking at the
+// Config address passed in.
+//
+
+ ldil t1, T2_HAE0_3_QVA // address of T2's HAE0_3
+ ldil t2, T4_HAE0_3_QVA // address of T4's HAE0_3
+
+ ldil t0, T2_OR_T4 // Load mask to tell if T2 or T4
+ and a0, t0, t3 // mask out other bits
+ cmoveq t3, t1, a0 // if t3 == 0 then t1 -> a0
+ cmovne t3, t2, a0 // if t3 != 0 then t2 -> a0
+
+ sll a2, T2_HAE03_CYCLETYPE_SHIFT, a1 // put cycle type into position
+ bsr ra, WRITE_T2_REGISTER // write updated HAE
+
+ br zero, 2f
+
+//
+// Merge the configuration cycle type into the HAE0_3 register within
+// the T2.
+//
+
+1:
+ stq a0, CfgA0(sp) // save config space address
+ stq a1, CfgA1(sp) // save config data
+ stq a2, CfgA2(sp) // save config cycle type
+
+ ldil a0, T2_HAE0_2_QVA // address of HAE0_2
+ bsr ra, READ_T2_REGISTER // read current value
+
+ ldq a1, CfgA2(sp) // restore config cycle type
+ ldil t0, T2_HAE02_CYCLETYPE_MASK // get cycle type field mask
+ bic v0, t0, t0 // clear config cycle type field
+
+ sll a1, T2_HAE02_CYCLETYPE_SHIFT, a1 // put cycle type into position
+ bis a1, t0, a1 // merge config cycle type
+
+ ldil a0, T2_HAE0_2_QVA // address of HAE0_2
+ bsr ra, WRITE_T2_REGISTER // write updated HAE
+
+//
+// Perform the read from configuration space after restoring the
+// configuration space address and data.
+//
+2:
+
+ ldq a0, CfgA0(sp) // restore config space address
+ ldq a1, CfgA1(sp) // restore config data
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 0x3, t3 // capture byte lane
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE
+ bne t1, 3f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, -0x4000 //
+ sll t4, 28, t4 //
+ bis t0, t4, t0 // superpage mode
+
+ bis t0, IO_BYTE_LEN, t0 // or in the byte length indicator
+
+ insbl a1, t3, t4 // put byte in the appropriate lane
+ stl t4, (t0) // write the configuration byte
+ mb // synchronize
+ mb // synchronize
+
+3:
+ ldq ra, CfgRa(sp) // restore return address
+ lda sp, CfgFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // return
+
+ .end WRITE_CONFIG_UCHAR
+
+//++
+//
+// ULONG
+// READ_CONFIG_USHORT(
+// ULONG ConfigurationAddress,
+// ULONG ConfigurationCycleType
+// )
+//
+// Routine Description:
+//
+// Read a longword from PCI configuration space.
+//
+// Arguments:
+//
+// ConfigurationAddress(a0) - Supplies the QVA of quadword to be read.
+//
+// ConfigurationCycleType(a1) - Supplies the type of the configuration cycle.
+//
+// Return Value:
+//
+// (v0) Returns the value of configuration space at the specified location.
+//
+// N.B. - This routine follows a protocol for reading from PCI configuration
+// space that allows the HAL or firmware to fixup and continue
+// execution if no device exists at the configuration target address.
+// The protocol requires 2 rules:
+// (1) The configuration space load must use a destination register
+// of v0
+// (2) The instruction immediately following the configuration space
+// load must use v0 as an operand (it must consume the value
+// returned by the load)
+//--
+
+ NESTED_ENTRY( READ_CONFIG_USHORT, CfgFrameLength, zero )
+
+ lda sp, -CfgFrameLength(sp) // allocate stack frame
+ stq ra, CfgRa(sp) // save return address
+
+ PROLOGUE_END // end prologue
+
+//
+// Depending on whether it's a pass 1 or pass 2 sable the configuration
+// cycle type is in different registers
+//
+ ldl t0, T2VersionNumber // load version number
+ beq t0, 1f // if 0 then pass 1 sable
+
+//
+// Pass 2 Sable
+// Merge the configuration cycle type into the HAE0_2 register within
+// the T2.
+//
+
+ stq a0, CfgA0(sp) // save config space address
+
+//
+// See if this was a request on the T4 or the T2 by looking at the
+// Config address passed in.
+//
+
+ ldil t1, T2_HAE0_3_QVA // address of T2's HAE0_3
+ ldil t2, T4_HAE0_3_QVA // address of T4's HAE0_3
+
+ ldil t0, T2_OR_T4 // Load mask to tell if T2 or T4
+ and a0, t0, t3 // mask out other bits
+ cmoveq t3, t1, a0 // if t3 == 0 then t1 -> a0
+ cmovne t3, t2, a0 // if t3 != 0 then t2 -> a0
+
+ sll a1, T2_HAE03_CYCLETYPE_SHIFT, a1 // put cycle type into position
+ bsr ra, WRITE_T2_REGISTER // write updated HAE
+
+ br zero, 2f // go do actual io
+
+//
+// Pass 1 Sable
+// Merge the configuration cycle type into the HAE0_2 register within
+// the T2.
+//
+1:
+
+ stq a0, CfgA0(sp) // save config space address
+ stq a1, CfgA1(sp) // save config cycle type
+
+ ldil a0, T2_HAE0_2_QVA // address of HAE0_2
+ bsr ra, READ_T2_REGISTER // read current value
+
+ ldq a1, CfgA1(sp) // restore configuration cycle type
+ ldil t0, T2_HAE02_CYCLETYPE_MASK // get cycle type field mask
+ bic v0, t0, t0 // clear config cycle type field
+
+ sll a1, T2_HAE02_CYCLETYPE_SHIFT, a1 // put cycle type into position
+ bis a1, t0, a1 // merge config cycle type
+
+ ldil a0, T2_HAE0_2_QVA // address of HAE0_2
+ bsr ra, WRITE_T2_REGISTER // write updated HAE
+
+//
+// Perform the read from configuration space after restoring the
+// configuration space address.
+//
+2:
+ ldq a0, CfgA0(sp) // restore config space address
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 0x3, t3 // capture word offset
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set
+ bne t1, 3f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, -0x4000 //
+ sll t4, 28, t4 //
+ bis t0, t4, t0 // superpage mode
+
+ bis t0, IO_WORD_LEN, t0 // or in the byte enables
+
+ ldl v0, (t0) // read the longword
+ extwl v0, t3, v0 // return word from requested lanes
+ // also, consume loaded value
+ // to cause a pipeline stall
+ mb // Sable requires MBs or the
+ mb // machine check may happen
+ // much later
+
+3:
+
+ ldq ra, CfgRa(sp) // restore return address
+ lda sp, CfgFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // return
+
+ .end READ_CONFIG_USHORT
+
+//++
+//
+// VOID
+// WRITE_CONFIG_USHORT(
+// ULONG ConfigurationAddress,
+// USHORT ConfigurationData,
+// ULONG ConfigurationCycleType
+// )
+//
+// Routine Description:
+//
+// Read a longword from PCI configuration space.
+//
+// Arguments:
+//
+// ConfigurationAddress(a0) - Supplies the QVA to write.
+//
+// ConfigurationData(a1) - Supplies the data to be written.
+//
+// ConfigurationCycleType(a2) - Supplies the type of the configuration cycle.
+//
+// Return Value:
+//
+// (v0) Returns the value of configuration space at the specified location.
+//
+// N.B. - The configuration address must exist within the address space
+// allocated to an existing PCI device. Otherwise, the access
+// below will initiate an unrecoverable machine check.
+//
+//--
+
+ NESTED_ENTRY( WRITE_CONFIG_USHORT, CfgFrameLength, zero )
+
+ lda sp, -CfgFrameLength(sp) // allocate stack frame
+ stq ra, CfgRa(sp) // save return address
+
+ PROLOGUE_END // end prologue
+
+//
+// Depending on whether it's a pass 1 or pass 2 sable the configuration
+// cycle type is in different registers
+//
+
+ ldl t0, T2VersionNumber // load version number
+ beq t0, 1f // if 0 then pass 1 sable
+
+//
+// Pass 2 sable
+// Merge the configuration cycle type into the HAE0_2 register within
+// the T2.
+//
+
+ stq a0, CfgA0(sp) // save config space address
+ stq a1, CfgA1(sp) // save config data
+
+//
+// See if this was a request on the T4 or the T2 by looking at the
+// Config address passed in.
+//
+
+ ldil t1, T2_HAE0_3_QVA // address of T2's HAE0_3
+ ldil t2, T4_HAE0_3_QVA // address of T4's HAE0_3
+
+ ldil t0, T2_OR_T4 // Load mask to tell if T2 or T4
+ and a0, t0, t3 // mask out other bits
+ cmoveq t3, t1, a0 // if t3 == 0 then t1 -> a0
+ cmovne t3, t2, a0 // if t3 != 0 then t2 -> a0
+
+ sll a2, T2_HAE03_CYCLETYPE_SHIFT, a1 // put cycle type into position
+ bsr ra, WRITE_T2_REGISTER // write updated HAE
+
+ br zero, 2f // go do actual transfer
+
+
+//
+// Pass 1 sable
+// Merge the configuration cycle type into the HAE0_2 register within
+// the T2.
+//
+1:
+
+ stq a0, CfgA0(sp) // save config space address
+ stq a1, CfgA1(sp) // save config data
+ stq a2, CfgA2(sp) // save config cycle type
+
+ ldil a0, T2_HAE0_2_QVA // address of HAE0_2
+ bsr ra, READ_T2_REGISTER // read current value
+
+ ldq a1, CfgA2(sp) // restore configuration cycle type
+ ldil t0, T2_HAE02_CYCLETYPE_MASK // get cycle type field mask
+ bic v0, t0, t0 // clear config cycle type field
+
+ sll a1, T2_HAE02_CYCLETYPE_SHIFT, a1 // put cycle type into position
+ bis a1, t0, a1 // merge config cycle type
+
+ ldil a0, T2_HAE0_2_QVA // address of HAE0_2
+ bsr ra, WRITE_T2_REGISTER // write updated HAE
+
+
+//
+// Perform the read from configuration space after restoring the
+// configuration space address and data.
+//
+2:
+
+ ldq a0, CfgA0(sp) // restore config space address
+ ldq a1, CfgA1(sp) // restore config data
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ and a0, 0x3, t3 // capture word offset
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set
+ bne t1, 3f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, -0x4000 //
+ sll t4, 28, t4 //
+ bis t0, t4, t0 // superpage mode
+
+ bis t0, IO_WORD_LEN, t0 // or in the byte enables
+
+ inswl a1, t3, t4 // put data to appropriate lane
+ stl t4, (t0) // read the longword
+ mb // synchronize
+ mb // synchronize
+3:
+ ldq ra, CfgRa(sp) // restore return address
+ lda sp, CfgFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // return
+
+ .end WRITE_CONFIG_USHORT
+
+//++
+//
+// ULONG
+// READ_CONFIG_ULONG(
+// ULONG ConfigurationAddress,
+// ULONG ConfigurationCycleType
+// )
+//
+// Routine Description:
+//
+// Read a longword from PCI configuration space.
+//
+// Arguments:
+//
+// ConfigurationAddress(a0) - Supplies the QVA of quadword to be read.
+//
+// ConfigurationCycleType(a1) - Supplies the type of the configuration cycle.
+//
+// Return Value:
+//
+// (v0) Returns the value of configuration space at the specified location.
+//
+// N.B. - This routine follows a protocol for reading from PCI configuration
+// space that allows the HAL or firmware to fixup and continue
+// execution if no device exists at the configuration target address.
+// The protocol requires 2 rules:
+// (1) The configuration space load must use a destination register
+// of v0
+// (2) The instruction immediately following the configuration space
+// load must use v0 as an operand (it must consume the value
+// returned by the load)
+//--
+
+ NESTED_ENTRY( READ_CONFIG_ULONG, CfgFrameLength, zero )
+
+ lda sp, -CfgFrameLength(sp) // allocate stack frame
+ stq ra, CfgRa(sp) // save return address
+
+ PROLOGUE_END // end prologue
+
+//
+// Depending on whether it's a pass 1 or pass 2 sable the configuration
+// cycle type is in different registers
+//
+ ldl t0, T2VersionNumber // load version number
+ beq t0, 1f // if 0 then pass 1 sable
+
+//
+// PASS 2 sable:
+// Cycle type are the only bits in HAE0_3 register
+//
+ stq a0, CfgA0(sp) // save config space address
+
+//
+// See if this was a request on the T4 or the T2 by looking at the
+// Config address passed in.
+//
+
+ ldil t1, T2_HAE0_3_QVA // address of T2's HAE0_3
+ ldil t2, T4_HAE0_3_QVA // address of T4's HAE0_3
+
+ ldil t0, T2_OR_T4 // Load mask to tell if T2 or T4
+ and a0, t0, t3 // mask out other bits
+ cmoveq t3, t1, a0 // if t3 == 0 then t1 -> a0
+ cmovne t3, t2, a0 // if t3 != 0 then t2 -> a0
+
+ sll a1, T2_HAE03_CYCLETYPE_SHIFT, a1 // put cycle type in position
+ bsr ra, WRITE_T2_REGISTER // write updated HAE
+
+ br zero, 2f // go do actual read
+
+//
+// PASS 1 sable
+// Merge the configuration cycle type into the HAE0_2 register within
+// the T2.
+//
+
+1:
+
+ stq a0, CfgA0(sp) // save config space address
+ stq a1, CfgA1(sp) // save config cycle type
+
+ ldil a0, T2_HAE0_2_QVA // address of HAE0_2
+ bsr ra, READ_T2_REGISTER // read current value
+
+ ldq a1, CfgA1(sp) // restore config cycle type
+ ldil t0, T2_HAE02_CYCLETYPE_MASK // get cycle type field mask
+ bic v0, t0, t0 // clear config cycle type field
+
+ sll a1, T2_HAE02_CYCLETYPE_SHIFT, a1// put cycle type in position
+ bis a1, t0, a1 // merge config cycle type
+
+ ldil a0, T2_HAE0_2_QVA // address of HAE0_2
+ bsr ra, WRITE_T2_REGISTER // write updated HAE
+
+//
+// Perform the read from configuration space after restoring the
+// configuration space address.
+//
+
+2:
+ ldq a0, CfgA0(sp) // restore config space address
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set
+ bne t1, 3f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE,a0 // clear QVA fields
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, -0x4000 //
+ sll t4, 28, t4 //
+ or t0, t4, t0 // superpage mode
+
+ or t0, IO_LONG_LEN, t0 // or in the byte enables
+
+ ldl v0, (t0) // read the longword
+ bis v0, zero, t1 // consume loaded value to cause
+ // a pipeline stall
+ mb // Sable requires MBs or the
+ mb // machine check may happen
+ // much later
+3:
+ ldq ra, CfgRa(sp) // restore return address
+ lda sp, CfgFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // return
+
+ .end READ_CONFIG_ULONG
+
+
+//++
+//
+// VOID
+// WRITE_CONFIG_ULONG(
+// ULONG ConfigurationAddress,
+// ULONG ConfigurationData,
+// ULONG ConfigurationCycleType
+// )
+//
+// Routine Description:
+//
+// Read a longword from PCI configuration space.
+//
+// Arguments:
+//
+// ConfigurationAddress(a0) - Supplies the QVA to write.
+//
+// ConfigurationData(a1) - Supplies the data to be written.
+//
+// ConfigurationCycleType(a2) - Supplies the type of the configuration cycle.
+//
+// Return Value:
+//
+// (v0) Returns the value of configuration space at the specified location.
+//
+// N.B. - The configuration address must exist within the address space
+// allocated to an existing PCI device. Otherwise, the access
+// below will initiate an unrecoverable machine check.
+//
+//--
+
+ NESTED_ENTRY( WRITE_CONFIG_ULONG, CfgFrameLength, zero )
+
+ lda sp, -CfgFrameLength(sp) // allocate stack frame
+ stq ra, CfgRa(sp) // save return address
+
+ PROLOGUE_END // end prologue
+
+//
+// Depending on whether it's a pass 1 or pass 2 sable the configuration
+// cycle type is in different registers
+//
+
+ ldl t0, T2VersionNumber // load version number
+ beq t0, 1f // if 0 then pass 1 sable
+
+//
+// Pass 2 sable
+// Merge the configuration cycle type into the HAE0_2 register within
+// the T2.
+//
+
+ stq a0, CfgA0(sp) // save config space address
+ stq a1, CfgA1(sp) // save config data
+
+//
+// See if this was a request on the T4 or the T2 by looking at the
+// Config address passed in.
+//
+
+ ldil t1, T2_HAE0_3_QVA // address of T2's HAE0_3
+ ldil t2, T4_HAE0_3_QVA // address of T4's HAE0_3
+
+ ldil t0, T2_OR_T4 // Load mask to tell if T2 or T4
+ and a0, t0, t3 // mask out other bits
+ cmoveq t3, t1, a0 // if t3 == 0 then t1 -> a0
+ cmovne t3, t2, a0 // if t3 != 0 then t2 -> a0
+
+ sll a2, T2_HAE03_CYCLETYPE_SHIFT, a1 // put cycle type into position
+ bsr ra, WRITE_T2_REGISTER // write updated HAE
+
+ br zero, 2f // go do actual transfer
+
+
+//
+// Pass 1 sable
+// Merge the configuration cycle type into the HAE0_2 register within
+// the T2.
+//
+1:
+
+ stq a0, CfgA0(sp) // save config space address
+ stq a1, CfgA1(sp) // save config data
+ stq a2, CfgA2(sp) // save config cycle type
+
+ ldil a0, T2_HAE0_2_QVA // address of HAE0_2
+ bsr ra, READ_T2_REGISTER // read current value
+
+ ldq a1, CfgA2(sp) // restore configuration cycle type
+ ldil t0, T2_HAE02_CYCLETYPE_MASK // get cycle type field mask
+ bic v0, t0, t0 // clear config cycle type field
+
+ sll a1, T2_HAE02_CYCLETYPE_SHIFT, a1 // put cycle type into position
+ bis a1, t0, a1 // merge config cycle type
+
+ ldil a0, T2_HAE0_2_QVA // address of HAE0_2
+ bsr ra, WRITE_T2_REGISTER // write updated HAE
+
+//
+// Perform the read from configuration space after restoring the
+// configuration space address and data.
+//
+2:
+
+ ldq a0, CfgA0(sp) // restore config space address
+ ldq a1, CfgA1(sp) // restore config data
+
+ and a0, QVA_SELECTORS, t1 // get qva selector bits
+ xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set
+ bne t1, 3f // if ne, iff failed
+
+ zap a0, 0xf0, a0 // clear <63:32>
+ bic a0, QVA_ENABLE, a0 // clear QVA fields
+ sll a0, IO_BIT_SHIFT, t0 //
+ ldiq t4, -0x4000 //
+ sll t4, 28, t4 //
+ bis t0, t4, t0 // superpage mode
+
+ bis t0, IO_LONG_LEN, t0 // or in the byte enables
+
+ stl a1, (t0) // write the longword
+ mb // synchronize
+ mb // synchronize
+
+3: //
+ ldq ra, CfgRa(sp) // restore return address
+ lda sp, CfgFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // return
+
+ .end WRITE_CONFIG_ULONG
diff --git a/private/ntos/nthals/halsable/alpha/sableref.h b/private/ntos/nthals/halsable/alpha/sableref.h
new file mode 100644
index 000000000..b39ca9ce1
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/sableref.h
@@ -0,0 +1,280 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ sableref.h
+
+Abstract:
+
+ This file defines the structures and definitions describing the
+ basic Sable family IO structure. These definitions are common to
+ all sable family systems (Sable, Gamma, Lynx...)
+
+Author:
+
+ Steve Brooks 28-Dec 1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#ifndef _SABLEREFH_
+#define _SABLEREFH_
+
+//
+// Define QVA constants for SABLE.
+//
+
+#if !defined(QVA_ENABLE)
+
+#define QVA_ENABLE (0xA0000000) // Identify VA as a QVA
+
+#endif //QVA_ENABLE
+
+#define QVA_SELECTORS (0xE0000000) // QVA identification mask
+
+#define IO_BIT_SHIFT 0x05 // Bits to shift QVA
+
+#define IO_BYTE_OFFSET 0x20 // Offset to next byte
+#define IO_SHORT_OFFSET 0x40 // Offset to next short
+#define IO_LONG_OFFSET 0x80 // Offset to next long
+#define IO_QUAD_OFFSET 0x100 // Offset to next quad
+
+#define IO_BYTE_LEN 0x00 // Byte length
+#define IO_WORD_LEN 0x08 // Word length
+#define IO_TRIBYTE_LEN 0x10 // TriByte length
+#define IO_LONG_LEN 0x18 // Longword length
+
+//
+// Define size of I/O and memory space for Sable
+// Assume that the HAE==0. This reduces the maximum space from
+// 4Gbytes to 128Mbytes.
+//
+
+#define PCI0_MAX_IO_ADDRESS ((16*1024*1024) - 1)
+#define PCI0_MAX_SPARSE_MEMORY_ADDRESS ((128*1024*1024) - 1)
+#define PCI0_MIN_DENSE_MEMORY_ADDRESS (PCI0_MAX_SPARSE_MEMORY_ADDRESS + 1)
+#define PCI0_MAX_DENSE_MEMORY_ADDRESS (__1GB - 1)
+
+//
+// Definitions for 64Bit PCI Bus (PCI 1)
+//
+
+#define PCI1_MAX_SPARSE_IO_ADDRESS ((16*1024*1024) - 1)
+#define PCI1_MAX_SPARSE_MEMORY_ADDRESS ((64*1024*1024) - 1)
+#define PCI1_MIN_DENSE_MEMORY_ADDRESS (PCI1_MAX_SPARSE_MEMORY_ADDRESS + 1)
+#define PCI1_MAX_DENSE_MEMORY_ADDRESS (__1GB - 1)
+
+//
+// The following constants define the base QVA's for Sables
+// PCI dense spaces. The bus address is used as an offset into this space.
+//
+
+#define SABLE_PCI0_DENSE_MEMORY_QVA 0xc0000000
+#define SABLE_PCI1_DENSE_MEMORY_QVA 0x00000000
+
+// Highest Virtual local PCI Slot is 10 == PCI_AD[21]
+
+#define PCI_MAX_LOCAL_DEVICE 10
+
+//
+// Define physical processor numbers:
+//
+#define SABLE_CPU0 0
+#define SABLE_CPU1 1
+#define SABLE_CPU2 2
+#define SABLE_CPU3 3
+
+
+#if !defined(_LANGUAGE_ASSEMBLY)
+
+//
+// PCI CONFIG_ADDRESS configuration space offsets for Sable PCI devices
+// These are CPU address bit masks, shifted to set in a QVA.
+// PCI
+// IDSEL
+// -----
+#define PCI0_SCSI_HEADER_OFFSET (0x00020000 >> IO_BIT_SHIFT) // AD[12]
+#define PCI0_EISA_BRIDGE_HEADER_OFFSET (0x00040000 >> IO_BIT_SHIFT) // AD[13]
+#define PCI0_SLOT_0_HEADER_OFFSET (0x00400000 >> IO_BIT_SHIFT) // AD[17]
+#define PCI0_SLOT_1_HEADER_OFFSET (0x00800000 >> IO_BIT_SHIFT) // AD[18]
+
+
+//
+// Define the values for the Eisa/Isa bus interrupt levels.
+//
+
+typedef enum _SABLE_EISA_BUS_LEVELS{
+ EisaInterruptLevel3 = 3,
+ EisaInterruptLevel4 = 4,
+ EisaInterruptLevel5 = 5,
+ EisaInterruptLevel6 = 6,
+ EisaInterruptLevel7 = 7,
+ EisaInterruptLevel9 = 9,
+ EisaInterruptLevel10 = 10,
+ EisaInterruptLevel11 = 11,
+ EisaInterruptLevel12 = 12,
+ EisaInterruptLevel14 = 14,
+ EisaInterruptLevel15 = 15
+} SABLE_EISA_BUS_LEVELS, *PSABLE_EISA_BUS_LEVELS;
+
+
+//
+// N.B. The structure below defines the address offsets of the control
+// registers when used with the base QVA. It does NOT define the
+// size or structure of the individual registers.
+//
+typedef struct _SABLE_EDGE_LEVEL_CSRS{
+ UCHAR EdgeLevelControl1;
+ UCHAR EdgeLevelControl2;
+} SABLE_EDGE_LEVEL_CSRS, *PSABLE_EDGE_LEVEL_CSRS;
+
+typedef struct _SABLE_EDGE_LEVEL1_MASK{
+ UCHAR Irq3 : 1;
+ UCHAR Irq4 : 1;
+ UCHAR Irq5 : 1;
+ UCHAR Irq6 : 1;
+ UCHAR Irq7 : 1;
+ UCHAR Irq9 : 1;
+ UCHAR Irq10 : 1;
+ UCHAR Irq11 : 1;
+} SABLE_EDGE_LEVEL1_MASK, *PSABLE_EDGE_LEVEL1_MASK;
+
+typedef struct _SABLE_EDGE_LEVEL2_MASK{
+ UCHAR Irq12 : 1;
+ UCHAR Irq14 : 1;
+ UCHAR Irq15 : 1;
+ UCHAR Reserved : 4;
+ UCHAR Sab : 1;
+} SABLE_EDGE_LEVEL2_MASK, *PSABLE_EDGE_LEVEL2_MASK;
+
+typedef struct _SABLE_INTERRUPT_CSRS{
+ UCHAR InterruptAcknowledge;
+ UCHAR Filler0;
+ UCHAR MasterControl;
+ UCHAR MasterMask;
+ UCHAR Slave0Control;
+ UCHAR Slave0Mask;
+ UCHAR Filler1;
+ UCHAR Filler2;
+ UCHAR Slave1Control;
+ UCHAR Slave1Mask;
+ UCHAR Slave2Control;
+ UCHAR Slave2Mask;
+ UCHAR Slave3Control;
+ UCHAR Slave3Mask;
+} SABLE_INTERRUPT_CSRS, *PSABLE_INTERRUPT_CSRS;
+
+
+//
+// The Sable interrupt vectors are allocated to make dispatching code
+// as efficient as possible. The bits in the 8 bit vector are broken
+// into two fields (sssssooo):
+//
+// sssss - value that selects the slave
+// 0000x = Non-PIC interrupts (always the first 16 vectors)
+// 00010 = Master
+// 00100 = Slave 0
+// 01000 = Slave 1
+// 10000 = Slave 2
+// 10001 = Slave 3
+// ooo - vector offset for the slave
+//
+
+typedef enum _SABLE_INTERRUPT_VECTORS {
+
+ MasterBaseVector = 0x10,
+ MasterVector0 = 0x10,
+ Slave0CascadeVector,
+ MasterVector2,
+ Slave1CascadeVector,
+ Slave2CascadeVector,
+ Slave3CascadeVector,
+ MasterVector6,
+ MasterVector7,
+ MasterPassiveVector = 0x17,
+
+ Slave0BaseVector = 0x20,
+ PciSlot0AVector = 0x20,
+ ScsiPortVector,
+ EthernetPortVector,
+ MouseVector,
+ PciSlot1AVector,
+ PciSlot2AVector,
+ KeyboardVector,
+ FloppyVector,
+ Slave0PassiveVector = 0x27,
+
+ Slave1BaseVector = 0x40,
+ SerialPort1Vector = 0x40,
+ ParallelPortVector,
+ EisaIrq3Vector,
+ EisaIrq4Vector,
+ EisaIrq5Vector,
+ EisaIrq6Vector,
+ EisaIrq7Vector,
+ SerialPort0Vector,
+ Slave1PassiveVector = 0x47,
+
+ Slave2BaseVector = 0x80,
+ EisaIrq9Vector = 0x80,
+ EisaIrq10Vector,
+ EisaIrq11Vector,
+ EisaIrq12Vector,
+ PciSlot2BVector,
+ EisaIrq14Vector,
+ EisaIrq15Vector,
+ I2cVector,
+ Slave2PassiveVector = 0x87,
+
+ Slave3BaseVector = 0x88,
+ PciSlot0BVector = 0x88,
+ PciSlot1BVector,
+ PciSlot0CVector,
+ PciSlot1CVector,
+ PciSlot2CVector,
+ PciSlot0DVector,
+ PciSlot1DVector,
+ PciSlot2DVector,
+ Slave3PassiveVector = 0x8F,
+
+ MaximumSableVector
+
+} SABLE_INTERRUPT_VECTORS, *PSABLE_INTERRUPT_VECTORS;
+
+
+#define SlaveVectorMask (Slave0BaseVector | Slave1BaseVector | Slave2BaseVector | Slave3BaseVector)
+
+//
+// Define the position of the interrupt vectors within the
+// InterruptDispatchTable.
+//
+
+#define SABLE_VECTORS 0x20
+#define SABLE_VECTORS_MAXIMUM (SABLE_VECTORS + MaximumSableVector)
+
+// Highest PCI interrupt vector is in Sable Vector Space
+
+#define PCI_MAX_INTERRUPT_VECTOR MaximumSableVector
+
+//
+// Definitions for the old Standard I/O board (before
+// the 5th (Slave 3) 8259 was added to break out the
+// individual PCI A,B,C,D interrupt pins.
+//
+
+#define OldSlaveVectorMask (Slave0BaseVector | Slave1BaseVector | Slave2BaseVector)
+#define OldPciSlot0Vector PciSlot0AVector
+#define OldPciSlot1Vector PciSlot1AVector
+#define OldPciSlot2Vector PciSlot2AVector
+
+#endif // _LANGUAGE_ASSEMBLY
+
+#endif // _SABLEREFH_
diff --git a/private/ntos/nthals/halsable/alpha/sablertc.h b/private/ntos/nthals/halsable/alpha/sablertc.h
new file mode 100644
index 000000000..c0c0d1659
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/sablertc.h
@@ -0,0 +1,194 @@
+/*++
+
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ sablertc.h
+
+Abstract:
+
+ This module is the header file that describes the TOY clock
+ for the Sable.
+
+Author:
+
+ 94.01.16 Steve Jenness
+
+Revision History:
+
+ This file was accidentally removed. It has since been added back.
+ However, since the history information will be lost, the one liner
+ history information was put here.
+
+ Log for ntos\NTHALS\HALSABLE\ALPHA:
+
+ 02-25-94@13:05 V-SJEN3 addfile sablertc.h v1 [v-ntdec] latest Alpha Hal
+ 06-10-94@11:41 JVERT4 in sablertc.h v2 halsettimeincrement
+ 03-28-95@14:29 V-NTDEC1 in sablertc.h v3 fix for 9760 - NVRAM envi
+ 05-25-95@10:59 V-NTDEC1 delfile sablertc.h v4 checked in for 9760
+
+--*/
+
+#ifndef _SABLERTC_
+#define _SABLERTC_
+
+//
+// Sable's RTC is a Dallas Semiconductor 1287
+//
+
+// The APORT and DPORT CSR addresses are defined in a platform
+// specific file.
+
+//
+// The RTC NVRAM byte offsets are 0x0e -- 0x3f.
+//
+// Offsets 0x0E -- 0x3D are reserved for use by VMS/OSF.
+//
+
+#define RTC_RAM_NT_FLAGS0 0x3E // NT firmware flag set #0
+#define RTC_RAM_CONSOLE_SELECTION 0x3F // VMS/OSF/NT boot selection
+
+//
+// Define Realtime Clock register numbers.
+//
+
+#define RTC_SECOND 0 // second of minute [0..59]
+#define RTC_SECOND_ALARM 1 // seconds to alarm
+#define RTC_MINUTE 2 // minute of hour [0..59]
+#define RTC_MINUTE_ALARM 3 // minutes to alarm
+#define RTC_HOUR 4 // hour of day [0..23]
+#define RTC_HOUR_ALARM 5 // hours to alarm
+#define RTC_DAY_OF_WEEK 6 // day of week [1..7]
+#define RTC_DAY_OF_MONTH 7 // day of month [1..31]
+#define RTC_MONTH 8 // month of year [1..12]
+#define RTC_YEAR 9 // year [00..99]
+#define RTC_CONTROL_REGISTERA 10 // control register A
+#define RTC_CONTROL_REGISTERB 11 // control register B
+#define RTC_CONTROL_REGISTERC 12 // control register C
+#define RTC_CONTROL_REGISTERD 13 // control register D
+#define RTC_REGNUMBER_RTC_CR1 0x6A
+
+#ifndef _LANGUAGE_ASSEMBLY
+
+//
+// Define Control Register A structure.
+//
+
+typedef struct _RTC_CONTROL_REGISTER_A {
+ UCHAR RateSelect : 4;
+ UCHAR TimebaseDivisor : 3;
+ UCHAR UpdateInProgress : 1;
+} RTC_CONTROL_REGISTER_A, *PRTC_CONTROL_REGISTER_A;
+
+//
+// Define Control Register B structure.
+//
+
+typedef struct _RTC_CONTROL_REGISTER_B {
+ UCHAR DayLightSavingsEnable : 1;
+ UCHAR HoursFormat : 1;
+ UCHAR DataMode : 1;
+ UCHAR SquareWaveEnable : 1;
+ UCHAR UpdateInterruptEnable : 1;
+ UCHAR AlarmInterruptEnable : 1;
+ UCHAR TimerInterruptEnable : 1;
+ UCHAR SetTime : 1;
+} RTC_CONTROL_REGISTER_B, *PRTC_CONTROL_REGISTER_B;
+
+//
+// Define Control Register C structure.
+//
+
+typedef struct _RTC_CONTROL_REGISTER_C {
+ UCHAR Fill : 4;
+ UCHAR UpdateInterruptFlag : 1;
+ UCHAR AlarmInterruptFlag : 1;
+ UCHAR TimeInterruptFlag : 1;
+ UCHAR InterruptRequest : 1;
+} RTC_CONTROL_REGISTER_C, *PRTC_CONTROL_REGISTER_C;
+
+//
+// Define Control Register D structure.
+//
+
+typedef struct _RTC_CONTROL_REGISTER_D {
+ UCHAR Fill : 7;
+ UCHAR ValidTime : 1;
+} RTC_CONTROL_REGISTER_D, *PRTC_CONTROL_REGISTER_D;
+
+//
+// NT firmware flags in TOY NVRAM
+//
+
+typedef struct _RTC_RAM_NT_FLAGS_0 {
+ UCHAR AutoRunECU : 1; // Go directly to ECU
+ UCHAR ResetAfterECU : 1; // Force user to reset after ECU runs
+ UCHAR Fill : 5;
+ UCHAR ConfigurationBit : 1; // Serial line console only
+} RTC_RAM_NT_FLAGS_0, *PRTC_RAM_NT_FLAGS_0;
+
+#define RTC_RAM_NT_FLAGS_0_RUNARCAPP (0x01)
+#define RTC_RAM_NT_FLAGS_0_RESERVED (0x7E)
+#define RTC_RAM_NT_FLAGS_0_USECOM1FORIO (0x80)
+
+#endif //_LANGUAGE_ASSEMBLY
+
+//
+// Values for RTC_RAM_CONSOLE_SELECTION
+//
+
+#define RTC_RAM_CONSOLE_SELECTION_NT 1
+#define RTC_RAM_CONSOLE_SELECTION_VMS 2
+#define RTC_RAM_CONSOLE_SELECTION_OSF 3
+
+//
+// Define initialization values for Sable interval timer
+// rate is 7.8125 ms, 7812.5 us, 78125 clunks
+//
+// The Sable clock is divided by 2 by the
+// Multiprocessor interval clock phasing hardware.
+// The rate select is half what would otherwise be used.
+//
+// #define RTC_RATE_SELECT 0x01
+// #define RTC_PERIOD_IN_CLUNKS 78125
+
+#define RTC_TIMEBASE_DIVISOR 0x02
+
+//
+// Define initialization values for Sable interval timer
+// There are four different rates that are used under NT
+// (see page 9-8 of KN121 System Module Programmer's Reference)
+//
+// .976562 ms
+// 1.953125 ms
+// 3.90625 ms
+// 7.8125 ms
+//
+// The Sable clock is divided by 2 by the
+// Multiprocessor interval clock phasing hardware.
+// The rate select is half what would otherwise be used.
+//
+#define RTC_RATE_SELECT1 5
+#define RTC_RATE_SELECT2 6
+#define RTC_RATE_SELECT3 7
+#define RTC_RATE_SELECT4 8
+
+//
+// note that rates 1-3 have some rounding error,
+// since they are not expressible in even 100ns units
+//
+
+#define RTC_PERIOD_IN_CLUNKS1 9766
+#define RTC_PERIOD_IN_CLUNKS2 19531
+#define RTC_PERIOD_IN_CLUNKS3 39063
+#define RTC_PERIOD_IN_CLUNKS4 78125
+
+//
+// Defaults
+//
+#define MINIMUM_INCREMENT RTC_PERIOD_IN_CLUNKS1
+#define MAXIMUM_INCREMENT RTC_PERIOD_IN_CLUNKS4
+#define MAXIMUM_RATE_SELECT RTC_RATE_SELECT4
+
+#endif // _SABLERTC_
diff --git a/private/ntos/nthals/halsable/alpha/sbinitnt.c b/private/ntos/nthals/halsable/alpha/sbinitnt.c
new file mode 100644
index 000000000..d05e95631
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/sbinitnt.c
@@ -0,0 +1,1292 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ sbinitnt.c
+
+Abstract:
+
+
+ This module implements the platform-specific initialization for
+ a Sable system.
+
+Author:
+
+ Joe Notarangelo 25-Oct-1993
+ Steve Jenness 28-Oct-1993 (Sable)
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "sablertc.h"
+#include "halpcsl.h"
+#include "pci.h"
+#include "pcip.h"
+#include "isaaddr.h"
+#include "eisa.h"
+#include "iousage.h"
+#include "lyintsup.h"
+#include "siintsup.h"
+#include "xiintsup.h"
+#include "stdio.h"
+
+#include "fwcallbk.h"
+
+#include <ntverp.h>
+
+//
+// Include the header containing Error Frame Definitions(in halalpha).
+//
+#include "errframe.h"
+
+//
+// Define extern global buffer for the Uncorrectable Error Frame.
+// declared in halalpha\inithal.c
+//
+
+extern PERROR_FRAME PUncorrectableError;
+
+//
+// Don't change these values unless you know exactly what you are doing
+//
+#define HAE0_1_REGISTER_VALUE 0x0 // to address SPARSE PCI MEMORY
+#define HAE0_2_REGISTER_VALUE 0x0 // to address PCI IO space
+#define HAE0_3_REGISTER_VALUE 0x0 // For PCI config cycle type
+#define HAE0_4_REGISTER_VALUE 0x0 // to address DENCE PCI Memory
+
+ULONG HalpMemorySlot[4] = { (ULONG)SABLE_MEM0_CSRS_QVA,
+ (ULONG)SABLE_MEM1_CSRS_QVA,
+ (ULONG)SABLE_MEM2_CSRS_QVA,
+ (ULONG)SABLE_MEM3_CSRS_QVA };
+
+ULONG HalpCPUSlot[4] = { (ULONG)SABLE_CPU0_CSRS_QVA,
+ (ULONG)SABLE_CPU1_CSRS_QVA,
+ (ULONG)SABLE_CPU2_CSRS_QVA,
+ (ULONG)SABLE_CPU3_CSRS_QVA };
+
+//
+// Prototypes
+//
+
+VOID
+HalpInitializeHAERegisters(
+ VOID
+ );
+
+VOID
+HalpSenseCBusSlots(
+ VOID
+ );
+
+//
+// This is the PCI Memory space that cannot be used by anyone
+// and therefore the HAL says it is reserved for itself
+// Block out 8Mb to 144MB
+//
+
+ADDRESS_USAGE
+SablePCIMemorySpace = {
+ NULL, CmResourceTypeMemory, PCIUsage,
+ {
+ __8MB, (__32MB - __8MB), // Start=8MB; Length=24MB
+ 0,0
+ }
+};
+
+
+//
+// Define global data for builtin device interrupt enables.
+//
+
+USHORT HalpBuiltinInterruptEnable;
+
+//
+// Define global for saving the T2 Chipset's version
+//
+
+ULONG T2VersionNumber;
+
+// irql mask and tables
+//
+// irql 0 - passive
+// irql 1 - sfw apc level
+// irql 2 - sfw dispatch level
+// irql 3 - device low
+// irql 4 - device high
+// irql 5 - clock
+// irql 6 - real time, ipi, performance counters
+// irql 7 - error, mchk, nmi, halt
+//
+//
+// IDT mappings:
+// For the built-ins, GetInterruptVector will need more info,
+// or it will have to be built-in to the routines, since
+// these don't match IRQL levels in any meaningful way.
+//
+// 0 passive 8 perf cntr 1
+// 1 apc 9
+// 2 dispatch 10 PIC
+// 3 11
+// 4 12 errors
+// 5 clock 13
+// 6 perf cntr 0 14 halt
+// 7 nmi 15
+//
+// This is assuming the following prioritization:
+// nmi
+// halt
+// errors
+// performance counters
+// clock
+// pic
+
+//
+// The hardware interrupt pins are used as follows for Sable
+//
+// IRQ_H[0] = Hardware Error
+// IRQ_H[1] = PCI
+// IRQ_H[2] = External IO
+// IRQ_H[3] = IPI
+// IRQ_H[4] = Clock
+// IRQ_H[5] = NMI
+//
+
+// smjfix - This comment doesn't match what is currently happening in the
+// code. Plus it isn't clear that EISA and ISA entries can
+// be split apart.
+//
+// For information purposes: here is what the IDT division looks like:
+//
+// 000-015 Built-ins (we only use 8 entries; NT wants 10)
+// 016-031 ISA
+// 048-063 EISA
+// 080-095 PCI
+// 112-127 Turbo Channel
+// 128-255 unused, as are all other holes
+//
+
+//
+// Define the bus type, this value allows us to distinguish between
+// EISA and ISA systems.
+//
+
+// smjfix - Why is this here? It is a compile time constant for the
+// platform. This is useful only if one HAL is being used
+// for multiple platforms and is being passed from the firmware
+// or detected.
+
+ULONG HalpBusType = MACHINE_TYPE_EISA;
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+//
+// Is the external I/O module present?
+//
+
+BOOLEAN HalpXioPresent = FALSE;
+
+#endif
+
+//
+// Is this a Lynx platform?
+//
+
+BOOLEAN HalpLynxPlatform = FALSE;
+
+//
+// How many processors are ready to run?
+//
+
+ULONG HalpProcessors = 0;
+
+//
+// Define global data used to communicate new clock rates to the clock
+// interrupt service routine.
+//
+
+ULONG HalpCurrentTimeIncrement;
+ULONG HalpNextRateSelect;
+ULONG HalpNextTimeIncrement;
+ULONG HalpNewTimeIncrement;
+
+VOID
+HalpClearInterrupts(
+ );
+
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes interrupts for a Sable system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the initialization is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ ULONG DataLong;
+ ULONG Index;
+ ULONG Irq;
+ KIRQL Irql;
+ PKPRCB Prcb;
+ UCHAR Priority;
+ ULONG Vector;
+
+ Prcb = PCR->Prcb;
+
+ //
+ // Initialize interrupt handling for the primary processor and
+ // any system-wide interrupt initialization.
+ //
+
+ if( Prcb->Number == SABLE_PRIMARY_PROCESSOR ){
+
+ //
+ // Initialize HAL processor parameters based on estimated CPU speed.
+ // This must be done before HalpStallExecution is called. Compute integral
+ // megahertz first to avoid rounding errors due to imprecise cycle clock
+ // period values.
+ //
+
+ HalpInitializeProcessorParameters();
+
+ //
+ // Connect the Stall interrupt vector to the clock. When the
+ // profile count is calculated, we then connect the normal
+ // clock.
+
+//jnfix - this is a noop, can we change this
+ PCR->InterruptRoutine[CLOCK_VECTOR] = HalpStallInterrupt;
+
+#if !defined(NT_UP)
+
+ //
+ // Connect the interprocessor interrupt handler.
+ //
+
+ PCR->InterruptRoutine[IPI_VECTOR] = HalpSableIpiInterrupt;
+
+#endif //NT_UP
+
+ //
+ // Clear all pending interrupts
+ //
+
+ HalpClearInterrupts();
+
+ //
+ // Initialize SIO interrupts.
+ //
+
+ if( HalpLynxPlatform ){
+
+ HalpInitializeLynxSioInterrupts();
+
+ } else {
+
+ HalpInitializeSableSioInterrupts();
+
+ }
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+ //
+ // Initialize XIO interrupts.
+ //
+
+ if( HalpXioPresent ){
+
+ HalpInitializeXioInterrupts();
+
+ }
+
+#endif
+
+ //
+ // Initialize the 21064 interrupts on the current processor
+ // before enabling the individual interrupts.
+ //
+
+ HalpInitialize21064Interrupts();
+
+ //
+ // Enable the interrupts for the clock, ipi, pic, xio, APC, and DPC.
+ //
+ // jnfix - enable error interrupts later, including correctable
+
+ HalpEnable21064SoftwareInterrupt( Irql = APC_LEVEL );
+
+ HalpEnable21064SoftwareInterrupt( Irql = DISPATCH_LEVEL );
+
+ if( HalpLynxPlatform ){
+
+ PCR->InterruptRoutine[PIC_VECTOR] = HalpLynxSioDispatch;
+
+ } else {
+
+ PCR->InterruptRoutine[PIC_VECTOR] = HalpSableSioDispatch;
+
+ }
+
+ HalEnableSystemInterrupt(PIC_VECTOR, EISA_DEVICE_LEVEL,
+ LevelSensitive);
+
+ HalpEnable21064HardwareInterrupt( Irq = 1,
+ Irql = DEVICE_LEVEL,
+ Vector = PIC_VECTOR,
+ Priority = 1 );
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+ if( HalpXioPresent && HalpProcessors < 2 ){
+
+ PCR->InterruptRoutine[XIO_VECTOR] = HalpXioDispatch;
+ HalEnableSystemInterrupt(XIO_VECTOR, EISA_DEVICE_LEVEL,
+ LevelSensitive);
+
+ HalpEnable21064HardwareInterrupt( Irq = 2,
+ Irql = DEVICE_LEVEL,
+ Vector = XIO_VECTOR,
+ Priority = 1 );
+
+ }
+
+#endif
+
+ HalpEnable21064HardwareInterrupt( Irq = 4,
+ Irql = CLOCK2_LEVEL,
+ Vector = CLOCK_VECTOR,
+ Priority = 0 );
+
+#if !defined(NT_UP)
+
+ HalpEnable21064HardwareInterrupt( Irq = 3,
+ Irql = IPI_LEVEL,
+ Vector = IPI_VECTOR,
+ Priority = 0 );
+
+#endif //NT_UP
+
+ //
+ // Start the periodic interrupt from the RTC.
+ //
+
+ HalpProgramIntervalTimer(MAXIMUM_RATE_SELECT);
+
+ return TRUE;
+
+ } //end if Prcb->Number == SABLE_PRIMARY_PROCESSOR
+
+
+#if !defined(NT_UP)
+
+ //
+ // Initialize interrupts for the current, secondary processor.
+ //
+
+ //
+ // Connect the clock and ipi interrupt handlers.
+ // jnfix - For now these are the only interrupts we will accept on
+ // jnfix - secondary processors. Later we will add PCI interrupts
+ // jnfix - and the error interrupts.
+ //
+
+ PCR->InterruptRoutine[CLOCK_VECTOR] = HalpSecondaryClockInterrupt;
+ PCR->InterruptRoutine[IPI_VECTOR] = HalpSableIpiInterrupt;
+
+ //
+ // Initialize the 21064 interrupts for the current processor
+ // before enabling the individual interrupts.
+ //
+
+ HalpInitialize21064Interrupts();
+
+ //
+ // Enable the clock, ipi, APC, and DPC interrupts.
+ //
+
+ HalpEnable21064SoftwareInterrupt( Irql = APC_LEVEL );
+ HalpEnable21064SoftwareInterrupt( Irql = DISPATCH_LEVEL );
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+ if( HalpXioPresent && Prcb->Number == SABLE_SECONDARY_PROCESSOR ){
+
+ PCR->InterruptRoutine[XIO_VECTOR] = HalpXioDispatch;
+ HalEnableSystemInterrupt(XIO_VECTOR, EISA_DEVICE_LEVEL,
+ LevelSensitive);
+
+ HalpEnable21064HardwareInterrupt( Irq = 2,
+ Irql = DEVICE_LEVEL,
+ Vector = XIO_VECTOR,
+ Priority = 1 );
+
+ }
+
+#endif
+
+ HalpEnable21064HardwareInterrupt( Irq = 4,
+ Irql = CLOCK2_LEVEL,
+ Vector = CLOCK_VECTOR,
+ Priority = 0 );
+ HalpEnable21064HardwareInterrupt( Irq = 3,
+ Irql = IPI_LEVEL,
+ Vector = IPI_VECTOR,
+ Priority = 0 );
+
+#endif //NT_UP
+
+ return TRUE;
+
+}
+
+
+VOID
+HalpClearInterrupts(
+ )
+/*++
+
+Routine Description:
+
+ This function clears all pending interrupts on the Sable.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return;
+}
+
+
+VOID
+HalpSetTimeIncrement(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is responsible for setting the time increment for Sable
+ via a call into the kernel.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ //
+ // Set the time increment value.
+ //
+
+ HalpCurrentTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextRateSelect = 0;
+ KeSetTimeIncrement( MAXIMUM_INCREMENT, MINIMUM_INCREMENT );
+
+}
+
+//
+// Define global data used to calibrate and stall processor execution.
+//
+
+// smjfix - Where is this referenced?
+
+ULONG HalpProfileCountRate;
+
+VOID
+HalpInitializeClockInterrupts(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called during phase 1 initialization to complete
+ the initialization of clock interrupts. For Sable, this function
+ connects the true clock interrupt handler and initializes the values
+ required to handle profile interrupts.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Compute the profile interrupt rate.
+ //
+
+ HalpProfileCountRate = ((1000 * 1000 * 10) / KeQueryTimeIncrement());
+
+ //
+ // Set the time increment value and connect the real clock interrupt
+ // routine.
+ //
+
+ PCR->InterruptRoutine[CLOCK2_LEVEL] = HalpClockInterrupt;
+
+ return;
+}
+
+VOID
+HalpEstablishErrorHandler(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine performs the initialization necessary for the HAL to
+ begin servicing machine checks.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ BOOLEAN ReportCorrectables;
+
+ //
+ // Connect the machine check handler via the PCR. The machine check
+ // handler for Sable is the default EV4 parity-mode handler.
+ //
+
+ PCR->MachineCheckError = HalMachineCheck;
+
+ //
+ // Initialize machine check handling for Sable.
+ //
+
+ HalpInitializeMachineChecks( ReportCorrectables = FALSE );
+
+ return;
+}
+
+VOID
+HalpInitializeMachineDependent(
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+
+ This function performs any Sable-specific initialization based on
+ the current phase on initialization.
+
+Arguments:
+
+ Phase - Supplies an indicator for phase of initialization, phase 0 or
+ phase 1.
+
+ LoaderBlock - supplies the loader block passed in via the OsLoader.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PKPRCB Prcb;
+ PRESTART_BLOCK RestartBlock;
+ ULONGLONG Value;
+ T2_IOCSR Iocsr;
+
+ Prcb = PCR->Prcb;
+
+ if( Prcb->Number == HAL_PRIMARY_PROCESSOR) {
+
+ if( Phase == 0 ){
+
+ //
+ // Phase 0 Initialization.
+ //
+
+ //
+ // Determine how many processors are ready to run. We use
+ // this information to decide whether to split SIO/XIO
+ // interrupts across two processors or not.
+ //
+
+#ifdef NT_UP
+
+ HalpProcessors = 1;
+
+#else
+
+ HalpProcessors = 0;
+
+ for( RestartBlock = SYSTEM_BLOCK->RestartBlock;
+ RestartBlock != NULL;
+ RestartBlock = RestartBlock->NextRestartBlock ){
+
+ if( RestartBlock->BootStatus.ProcessorReady ){
+
+ HalpProcessors++;
+
+ }
+
+ }
+
+#endif
+
+ //
+ // Initialize the performance counter.
+ //
+
+ HalCalibratePerformanceCounter( NULL );
+
+
+ //
+ // Parse the loader block - this sets global for PCI parity check
+ //
+
+ HalpParseLoaderBlock( LoaderBlock );
+
+ //
+ // Re-establish Error Handler to pick up PCI parity changes
+ //
+
+ HalpEstablishErrorHandler();
+
+ //
+ // Determine the T2 Chipset's Version Number. Save Version in Global.
+ //
+ // T2VersionNumber Pass
+ //
+ // 000 1
+ // 001 2
+ //
+
+ Value = READ_T2_REGISTER(&((PT2_CSRS)(T2_CSRS_QVA))->Iocsr);
+ Iocsr = *(PT2_IOCSR)&Value;
+ T2VersionNumber = Iocsr.T2RevisionNumber;
+
+ HalpInitializeHAERegisters();
+
+ HalpSenseCBusSlots();
+
+ } else {
+
+ //
+ // Phase 1 Initialization.
+ //
+
+ //
+ // Initialize the existing bus handlers.
+ //
+
+ HalpRegisterInternalBusHandlers();
+
+ //
+ // Initialize the PCI bus.
+ //
+
+ HalpInitializePCIBus(LoaderBlock);
+
+ //
+ // Initialize profiling for the primary processor.
+ //
+
+ HalpInitializeProfiler();
+
+ }
+
+ } else {
+
+ //
+ // Connect the machine check handler via the PCR. The machine check
+ // handler for Sable is the default EV4 parity-mode handler. Note
+ // that this was done in HalpEstablishErrorHandler() for the
+ // primary processor.
+ //
+
+ PCR->MachineCheckError = HalMachineCheck;
+
+ //
+ // Initialize profiling on this secondary processor.
+ //
+
+ HalpInitializeProfiler();
+
+ }
+
+ 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.
+
+--*/
+
+{
+ UCHAR data;
+ SABLE_SIC_CSR Sic;
+
+ //
+ // Acknowledge the clock interrupt in the real time clock.
+ // We don't need to do an ACK to the RTC since we're using the
+ // DS1459A RTC's square wave instead of periodic interrupt to
+ // generate the periodic clock. Each processor board has it's own
+ // periodic clock interrupt latch that needs to be cleared.
+ //
+ // This code is MP safe since the Sic is per-processor.
+
+ RtlZeroMemory( &Sic, sizeof(Sic) );
+
+ Sic.IntervalTimerInterruptClear = 1;
+
+ WRITE_CPU_REGISTER( &((PSABLE_CPU_CSRS)(SABLE_CPU0_CSRS_QVA))->Sic,
+ *(PULONGLONG)&Sic );
+
+ return;
+}
+
+ULONG
+HalSetTimeIncrement (
+ IN ULONG DesiredIncrement
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to set the clock interrupt rate to the frequency
+ required by the specified time increment value.
+
+Arguments:
+
+ DesiredIncrement - Supplies desired number of 100ns units between clock
+ interrupts.
+
+Return Value:
+
+ The actual time increment in 100ns units.
+
+--*/
+
+{
+ ULONG NewTimeIncrement;
+ ULONG NextRateSelect;
+ 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);
+ if (DesiredIncrement < MINIMUM_INCREMENT) {
+ DesiredIncrement = MINIMUM_INCREMENT;
+ }
+ if (DesiredIncrement > MAXIMUM_INCREMENT) {
+ DesiredIncrement = MAXIMUM_INCREMENT;
+ }
+
+ //
+ // Find the allowed increment that is less than or equal to
+ // the desired increment.
+ //
+ if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS4) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS4;
+ NextRateSelect = RTC_RATE_SELECT4;
+ } else if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS3) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS3;
+ NextRateSelect = RTC_RATE_SELECT3;
+ } else if (DesiredIncrement >= RTC_PERIOD_IN_CLUNKS2) {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS2;
+ NextRateSelect = RTC_RATE_SELECT2;
+ } else {
+ NewTimeIncrement = RTC_PERIOD_IN_CLUNKS1;
+ NextRateSelect = RTC_RATE_SELECT1;
+ }
+
+ HalpNextRateSelect = NextRateSelect;
+ HalpNewTimeIncrement = NewTimeIncrement;
+
+ KeLowerIrql(OldIrql);
+
+ return NewTimeIncrement;
+}
+
+//
+//
+//
+VOID
+HalpInitializeHAERegisters(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function initializes the HAE registers in the T2 chipset.
+ It also register the holes in the PCI memory space if any.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ none
+
+--*/
+{
+ //
+ // Set Hae0_1, Hae0_2, Hae0_3 and Hae0_4 registers
+ //
+ // IMPORTANT: IF YOU CHANGE THE VALUE OF THE HAE0_1 REGISTERS PLEASE
+ // REMEMBER YOU WILL NEED TO CHANGE:
+ //
+ // PCI_MAX_MEMORY_ADDRESS IN halalpha\sable.h
+ // SablePCIMemorySpace in this file to report holes
+ //
+
+ // SPARSE SPACE: Hae0_1
+ //
+ // We set Hae0_1 to 0MB. Which means we have the following
+ // PCI Sparse Memory addresses:
+ // 0 to 8MB VALID. Hae0_1 Not used in address translation
+ // 8 to 16MB Invalid.
+ // 16 to 32MB Invalid. Used for Isa DMA copy for above 16MB
+ // 32 to 128MB VALID. Hae0_1 used in address translation
+
+ //
+ // All invalid addresses are reported to be used by the hal.
+ // see SablePCIMemorySpace above.
+ //
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Hae0_1,
+ HAE0_1_REGISTER_VALUE );
+
+
+ // PCI IO SPACE: Hae0_2
+ //
+ // We set Hae0_2 to MB. Which means we have the following
+ // PCI IO addresses:
+ // 0 to 64KB VALID. Hae0_2 Not used in address translation
+ // 64K to 16MB VALID. Hae0_2 is used in the address translation
+ //
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Hae0_2,
+ HAE0_2_REGISTER_VALUE );
+
+
+ if( T2VersionNumber != 0 ) {
+
+ // PCI CONFIG CYCLE TYPE: Hae0_3
+ //
+ // We default to zero
+ //
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Hae0_3,
+ HAE0_3_REGISTER_VALUE );
+
+ // PCI DENSE MEMORY: Hae0_4
+ //
+ // We default to zero
+ //
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Hae0_4,
+ HAE0_4_REGISTER_VALUE );
+
+ }
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+ //
+ // If the external I/O module is present, initialize the HAe
+ // register on the T4.
+ //
+
+ if( HalpXioPresent ){
+
+ //
+ // All invalid addresses are reported to be used by the hal.
+ // see SablePCIMemorySpace above.
+ //
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Hae0_1,
+ HAE0_1_REGISTER_VALUE );
+
+ //
+ // PCI IO SPACE: Hae0_2
+ //
+ // We set Hae0_2 to MB. Which means we have the following
+ // PCI IO addresses:
+ // 0 to 64KB VALID. Hae0_2 Not used in address translation
+ // 64K to 16MB VALID. Hae0_2 is used in the address translation
+ //
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Hae0_2,
+ HAE0_2_REGISTER_VALUE );
+
+
+ //
+ // PCI CONFIG CYCLE TYPE: Hae0_3
+ //
+ // We default to zero
+ //
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Hae0_3,
+ HAE0_3_REGISTER_VALUE );
+
+ //
+ // PCI DENSE MEMORY: Hae0_4
+ //
+ // We default to zero
+ //
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Hae0_4,
+ HAE0_4_REGISTER_VALUE );
+
+ }
+
+#endif
+
+ //
+ // Report that the SPARSE SPACE mapping to the Io subsystem
+ //
+
+ HalpRegisterAddressUsage (&SablePCIMemorySpace);
+
+}
+
+VOID
+HalpResetHAERegisters(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function resets the HAE registers in the chipset to 0.
+ This is routine called during a shutdown so that the prom
+ gets a predictable environment.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ none
+
+--*/
+{
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Hae0_1, 0 );
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Hae0_2, 0 );
+
+ if( T2VersionNumber != 0) {
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Hae0_3, 0 );
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T2_CSRS_QVA))->Hae0_4, 0 );
+
+ }
+
+ return;
+}
+
+
+VOID
+HalpSenseCBusSlots(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function Probes the Cbus looking for slots that are filled.
+ are only 8 Cbus locations we can look at (4 memory, 4 CPU).
+
+ If we find a module, we will fill in the table at the
+ appropriate location -- if no module is found, then place a
+ zero there.
+
+Note:
+
+ This routine will machine check in an empty slot -- and is expected.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ none
+
+--*/
+{
+
+ ULONG i;
+ ULONG CSR;
+
+ for (i=0; i<4; i++) {
+ if (HalpMemorySlot[i] != 0) {
+ CSR = (ULONG)READ_MEM_REGISTER((PVOID)HalpMemorySlot[i]);
+ if (CSR == 0xffffffff) {
+ HalpMemorySlot[i] = 0;
+ }
+#if HALDBG
+ if (HalpMemorySlot[i] == 0) {
+ DbgPrint("Memory Slot %d is EMPTY\n", i);
+ } else {
+ DbgPrint("Memory Slot %d is POPULATED\n", i);
+ }
+#endif
+ }
+ }
+
+ for (i=0; i<4; i++) {
+ if (HalpCPUSlot[i] != 0) {
+ CSR = (ULONG)READ_CPU_REGISTER((PVOID)HalpCPUSlot[i]);
+ if (CSR == 0xffffffff) {
+ HalpCPUSlot[i] = 0;
+ }
+#if HALDBG
+ if (HalpCPUSlot[i] == 0) {
+ DbgPrint("CPU Slot %d is EMPTY\n", i);
+ } else {
+ DbgPrint("CPU Slot %d is POPULATED\n", i);
+ }
+#endif
+ }
+ }
+}
+
+
+
+VOID
+HalpGetMachineDependentErrorFrameSizes(
+ PULONG RawProcessorSize,
+ PULONG RawSystemInfoSize
+ )
+/*++
+
+Routine Description:
+
+ This function returns the size of the system specific structures.
+
+
+Arguments:
+
+ RawProcessorSize - Pointer to a buffer that will receive the
+ size of the processor specific error information buffer.
+
+ RawSystemInfoSize - Pointer to a buffer that will receive the
+ size of the system specific error information buffer.
+
+Return Value:
+
+ none
+
+--*/
+{
+ *RawProcessorSize = sizeof(PROCESSOR_EV4_UNCORRECTABLE);
+ *RawSystemInfoSize = sizeof(SABLE_UNCORRECTABLE_FRAME);
+ return;
+}
+
+VOID
+HalpGetSystemInfo(SYSTEM_INFORMATION *SystemInfo)
+/*++
+
+Routine Description:
+
+ This function fills in the System information.
+
+
+Arguments:
+
+ SystemInfo - Pointer to the SYSTEM_INFORMATION buffer that needs
+ to be filled in.
+
+Return Value:
+
+ none
+
+--*/
+{
+ char systemtype[] = "Sable";
+ EXTENDED_SYSTEM_INFORMATION FwExtSysInfo;
+
+
+ VenReturnExtendedSystemInformation(&FwExtSysInfo);
+
+ RtlCopyMemory(SystemInfo->FirmwareRevisionId,
+ FwExtSysInfo.FirmwareVersion,
+ 16);
+
+
+ RtlCopyMemory(SystemInfo->SystemType,systemtype, 8);
+
+ SystemInfo->ClockSpeed =
+ ((1000 * 1000) + (PCR->CycleClockPeriod >> 1)) / PCR->CycleClockPeriod;
+
+ SystemInfo->SystemRevision = PCR->SystemRevision;
+
+ RtlCopyMemory(SystemInfo->SystemSerialNumber,
+ PCR->SystemSerialNumber,
+ 16);
+
+ SystemInfo->SystemVariant = PCR->SystemVariant;
+
+
+ SystemInfo->PalMajorVersion = PCR->PalMajorVersion;
+ SystemInfo->PalMinorVersion = PCR->PalMinorVersion;
+
+ SystemInfo->OsRevisionId = VER_PRODUCTBUILD;
+
+ //
+ // For now fill in dummy values.
+ //
+ SystemInfo->ModuleVariant = 1UL;
+ SystemInfo->ModuleRevision = 1UL;
+ SystemInfo->ModuleSerialNumber = 0;
+
+ return;
+}
+
+
+VOID
+HalpInitializeUncorrectableErrorFrame (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function Allocates an Uncorrectable Error frame for this
+ system and initializes the frame with certain constant/global
+ values.
+
+ This is routine called during machine dependent system
+ Initialization.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ none
+
+--*/
+{
+ PROCESSOR_EV4_UNCORRECTABLE processorFrame;
+ SABLE_UNCORRECTABLE_FRAME SableUnCorrrectable;
+
+ //
+ // If the Uncorrectable error buffer is not set then simply return
+ //
+ if(PUncorrectableError == NULL)
+ return;
+
+ PUncorrectableError->Signature = ERROR_FRAME_SIGNATURE;
+
+ PUncorrectableError->FrameType = UncorrectableFrame;
+
+ //
+ // ERROR_FRAME_VERSION is define in errframe.h and will
+ // change as and when there is a change in the errframe.h.
+ // This Version number helps the service, that reads this
+ // information from the dumpfile, to check if it knows about
+ // this frmae version type to decode. If it doesn't know, it
+ // will dump the entire frame to the EventLog with a message
+ // "Error Frame Version Mismatch".
+ //
+
+ PUncorrectableError->VersionNumber = ERROR_FRAME_VERSION;
+
+ //
+ // The sequence number will always be 1 for Uncorrectable errors.
+ //
+
+ PUncorrectableError->SequenceNumber = 1;
+
+ //
+ // The PerformanceCounterValue field is not used for Uncorrectable
+ // errors.
+ //
+
+ PUncorrectableError->PerformanceCounterValue = 0;
+
+ //
+ // We will fill in the UncorrectableFrame.SystemInfo here.
+ //
+ HalpGetSystemInfo(&PUncorrectableError->UncorrectableFrame.System);
+
+ PUncorrectableError->UncorrectableFrame.Flags.SystemInformationValid = 1;
+
+ return;
+}
+
diff --git a/private/ntos/nthals/halsable/alpha/sbintr.s b/private/ntos/nthals/halsable/alpha/sbintr.s
new file mode 100644
index 000000000..1ae7df100
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/sbintr.s
@@ -0,0 +1,94 @@
+// TITLE("Clock and Eisa Interrupt Handlers")
+//++
+//
+// Copyright (c) 1993 Digital Equipment Corporation
+//
+// Module Name:
+//
+// sbintr.s
+//
+// Abstract:
+//
+// This module implements first level interrupt handlers for the
+// Sable system.
+//
+// Author:
+//
+// Joe Notarangelo 29-Oct-1993
+// Steve Jenness 29-Oct-1993
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halalpha.h"
+
+ SBTTL("Interprocessor Interrupt")
+//++
+//
+// VOID
+// HalpSableIpiInterrupt
+// )
+//
+// Routine Description:
+//
+// This function is executed as the result of an interprocessor
+// interrupt asserted on the current processor. This function is
+// responsible for acknowledging the interrupt and dispatching to
+// the kernel for processing.
+//
+// Arguments:
+//
+// TrapFrame (fp/s6) - Supplies a pointer to the trap frame for
+// the interrupt.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSableIpiInterrupt)
+
+//
+// Acknowledge the IPI interrupt by clearing the RequestInterrupt bit
+// of the IPIR register for the current processor.
+//
+// N.B. - Clearing the RequestInterrupt bit of the IPIR is accomplished
+// by writing a zero to the register. This eliminates the need
+// to perform a read-modify-write operation but loses the state
+// of the RequestNodeHaltInterrupt bit. Currently, this is fine
+// because the RequestNodeHalt feature is not used. Were it to
+// be used in the future, then this short-cut would have to be
+// reconsidered.
+//
+// N.B. - The code to write a sable CPU register is inlined here for
+// performance.
+//
+
+//jnfix - define elsewhere
+#define PcHalIpirSva 0x18
+
+ call_pal rdpcr // v0 = pcr base address
+
+ ldq v0, PcHalReserved + PcHalIpirSva(v0) // get per-processor
+ // CPU IPIR SVA
+ stq zero, (v0) // clear IPIR
+ mb // synchronize the write
+
+//
+// Call the kernel to processor the interprocessor request.
+//
+ ldl t0, __imp_KeIpiInterrupt
+ jmp zero, (t0) // call kernel to process
+
+//
+// Control is returned from KeIpiInterrupt to the caller.
+//
+
+ .end HalpSableIpiInterrupt
+
diff --git a/private/ntos/nthals/halsable/alpha/sbintsup.c b/private/ntos/nthals/halsable/alpha/sbintsup.c
new file mode 100644
index 000000000..66e167389
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/sbintsup.c
@@ -0,0 +1,113 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ sbintsup.c
+
+Abstract:
+
+ This module provides support for Sable-specific interrupts.
+
+Author:
+
+ Steve Jenness 28-Oct-1993
+ Joe Notarangelo 28-Oct-1993
+
+Revision History:
+
+--*/
+
+
+#include "halp.h"
+
+VOID
+HalpAcknowledgeClockInterrupt(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Acknowledge the clock interrupt from the interval timer. The interval
+ timer for Sable comes from the Dallas DS1287A real-time clock. Sable
+ uses the Square Wave from the RTC and distributes it out of phase
+ to each of the processors. The acknowledgement of the interrupt is
+ done by clearing an interrupt latch on each processor board.
+
+ The interrupt generated directly by the RTC is not used and does not
+ need to be acknowledged.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PSABLE_CPU_CSRS CurrentCpuCsrs;
+ SABLE_SIC_CSR Sic;
+
+ CurrentCpuCsrs = HAL_PCR->CpuCsrsQva;
+
+ //
+ // Acknowledge the interval timer interrupt on the current processor.
+ //
+
+ Sic.all = 0;
+ Sic.IntervalTimerInterruptClear = 1;
+
+ WRITE_CPU_REGISTER( &CurrentCpuCsrs->Sic,
+ *(PULONGLONG)&Sic );
+
+ return;
+}
+
+VOID
+HalpAcknowledgeIpiInterrupt(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Acknowledge the interprocessor interrupt on the current processor.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ PSABLE_CPU_CSRS CurrentCpuCsrs;
+
+ CurrentCpuCsrs = HAL_PCR->CpuCsrsQva;
+
+ //
+ // Acknowledge the interprocessor interrupt by clearing the
+ // RequestInterrupt bit of the IPIR register for the current processor.
+ //
+ // N.B. - Clearing the RequestInterrupt bit of the IPIR is accomplished
+ // by writing a zero to the register. This eliminates the need
+ // to perform a read-modify-write operation but loses the state
+ // of the RequestNodeHaltInterrupt bit. Currently, this is fine
+ // because the RequestNodeHalt feature is not used. Were it to
+ // be used in the future, then this short-cut would have to be
+ // reconsidered.
+ //
+
+ WRITE_CPU_REGISTER( &CurrentCpuCsrs->Ipir,
+ (ULONGLONG)0 );
+
+ return;
+
+}
diff --git a/private/ntos/nthals/halsable/alpha/sbmapio.c b/private/ntos/nthals/halsable/alpha/sbmapio.c
new file mode 100644
index 000000000..f902b1506
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/sbmapio.c
@@ -0,0 +1,205 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ ebmapio.c
+
+Abstract:
+
+ This module contains the functions to map HAL-accessed I/O addresses
+ on the Sable system.
+
+Author:
+
+ Joe Notarangelo 25-Oct-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "isaaddr.h"
+
+
+//
+// Define global data used to locate the EISA control space.
+//
+
+PVOID HalpEisaControlBase;
+PVOID HalpEisaIntAckBase;
+PVOID HalpCMOSRamBase;
+
+//
+// Define the array that maps logical processor numbers to the corresponding
+// QVA for that processor's CPU CSRs.
+//
+
+PSABLE_CPU_CSRS HalpSableCpuCsrs[HAL_MAXIMUM_PROCESSOR+1];
+
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL I/O space for a Sable
+ system using the Quasi VA.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, then a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ PVOID PciIoSpaceBase;
+
+#if !defined(AXP_FIRMWARE)
+
+ PKPRCB Prcb;
+ extern HalpLogicalToPhysicalProcessor[HAL_MAXIMUM_PROCESSOR+1];
+
+ Prcb = PCR->Prcb;
+
+ //
+ // Assign CPU specific CSR address
+ //
+
+ switch( HalpLogicalToPhysicalProcessor[Prcb->Number] ) {
+
+ case SABLE_CPU0:
+ HAL_PCR->IpirSva = SABLE_CPU0_IPIR_PHYSICAL | SUPERPAGE_ENABLE;
+ HAL_PCR->CpuCsrsQva = SABLE_CPU0_CSRS_QVA;
+ HalpSableCpuCsrs[Prcb->Number] = SABLE_CPU0_CSRS_QVA;
+ break;
+
+ case SABLE_CPU1:
+ HAL_PCR->IpirSva = SABLE_CPU1_IPIR_PHYSICAL | SUPERPAGE_ENABLE;
+ HAL_PCR->CpuCsrsQva = SABLE_CPU1_CSRS_QVA;
+ HalpSableCpuCsrs[Prcb->Number] = SABLE_CPU1_CSRS_QVA;
+ break;
+
+ case SABLE_CPU2:
+ HAL_PCR->IpirSva = SABLE_CPU2_IPIR_PHYSICAL | SUPERPAGE_ENABLE;
+ HAL_PCR->CpuCsrsQva = SABLE_CPU2_CSRS_QVA;
+ HalpSableCpuCsrs[Prcb->Number] = SABLE_CPU2_CSRS_QVA;
+ break;
+
+ case SABLE_CPU3:
+ HAL_PCR->IpirSva = SABLE_CPU3_IPIR_PHYSICAL | SUPERPAGE_ENABLE;
+ HAL_PCR->CpuCsrsQva = SABLE_CPU3_CSRS_QVA;
+ HalpSableCpuCsrs[Prcb->Number] = SABLE_CPU3_CSRS_QVA;
+ break;
+
+ default:
+#ifdef HALDBG
+ DbgPrint("HalpMapIoSpace: Invalid Cpu number %d\n", Prcb->Number);
+ DbgBreakPoint();
+#else
+ ;
+#endif // HALDBG
+ }
+
+#endif // AXP_FIRMWARE
+
+ //
+ // Map EISA control space.
+ //
+
+ PciIoSpaceBase = HAL_MAKE_QVA( SABLE_PCI0_SPARSE_IO_PHYSICAL );
+ HalpEisaControlBase = PciIoSpaceBase;
+
+ HalpCMOSRamBase = (PVOID)
+ ( (ULONG)HAL_MAKE_QVA( SABLE_PCI0_SPARSE_IO_PHYSICAL ) +
+ CMOS_ISA_PORT_ADDRESS );
+
+ //
+ // Map the real-time clock registers.
+ //
+
+ HalpRtcAddressPort = (PVOID)((ULONG)PciIoSpaceBase + RTC_ISA_ADDRESS_PORT);
+ HalpRtcDataPort = (PVOID)((ULONG)PciIoSpaceBase + RTC_ISA_DATA_PORT);
+
+ return TRUE;
+
+}
+
+ULONG
+HalpMapDebugPort(
+ IN ULONG ComPort,
+ OUT PULONG ReadQva,
+ OUT PULONG WriteQva
+ )
+/*++
+
+Routine Description:
+
+ This routine maps the debug com port so that the kernel debugger
+ may function - if called it is called very earlier in the boot sequence.
+
+Arguments:
+
+ ComPort - Supplies the number of the com port to use as the debug port.
+
+ ReadQva - Receives the QVA used to access the read registers of the debug
+ port.
+
+ WriteQva - Receives the QVA used to access the write registers of the
+ debug port.
+
+Return Value:
+
+ Returns the base bus address of the device used as the debug port.
+
+--*/
+{
+ ULONG ComPortAddress;
+ ULONG PortQva;
+
+ //
+ // Compute the port address, based on the desired com port.
+ //
+
+ switch( ComPort ){
+
+ case 1:
+
+ ComPortAddress = COM1_ISA_PORT_ADDRESS;
+ break;
+
+ case 2:
+ default:
+
+ ComPortAddress = COM2_ISA_PORT_ADDRESS;
+
+ }
+
+ //
+ // Return the QVAs for read and write access.
+ //
+
+ PortQva = (ULONG)HAL_MAKE_QVA(SABLE_PCI0_SPARSE_IO_PHYSICAL) +
+ ComPortAddress;
+
+ *ReadQva = PortQva;
+ *WriteQva = PortQva;
+
+ return ComPortAddress;
+
+}
diff --git a/private/ntos/nthals/halsable/alpha/sbsysint.c b/private/ntos/nthals/halsable/alpha/sbsysint.c
new file mode 100644
index 000000000..3dd114faa
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/sbsysint.c
@@ -0,0 +1,456 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ sbsysint.c
+
+Abstract:
+
+ This module implements the HAL enable/disable system interrupt, and
+ request interprocessor interrupt routines for the Sable system.
+
+Author:
+
+ Joe Notarangelo 29-Oct-1993
+ Steve Jenness 29-Oct-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "axp21064.h"
+#include "siintsup.h"
+#include "lyintsup.h"
+#include "xiintsup.h"
+
+//
+// Define reference to the builtin device interrupt enables.
+//
+
+extern USHORT HalpBuiltinInterruptEnable;
+
+
+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.
+
+--*/
+
+{
+ ULONG Irq;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level and acquire the system interrupt
+ // lock.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+ //
+ // If the vector is a performance counter vector or one of the internal
+ // device vectors then disable the interrupt for the 21064.
+ //
+
+ switch( Vector ){
+
+ //
+ // Performance counter 0 interrupt (internal to 21064)
+ //
+
+ case PC0_VECTOR:
+ case PC0_SECONDARY_VECTOR:
+
+ HalpDisable21064PerformanceInterrupt( PC0_VECTOR );
+
+ break;
+
+ //
+ // Performance counter 1 interrupt (internal to 21064)
+ //
+
+ case PC1_VECTOR:
+ case PC1_SECONDARY_VECTOR:
+
+ HalpDisable21064PerformanceInterrupt( PC1_VECTOR );
+
+ break;
+
+ default:
+
+ if( Irql == DEVICE_LEVEL ){
+
+ if( HalpLynxPlatform ){
+
+ HalpDisableLynxSioInterrupt( Vector );
+
+ } else {
+
+ HalpDisableSableSioInterrupt( Vector );
+
+ }
+
+ }
+
+ break;
+
+ }
+
+ //
+ // Release the system interrupt lock and restore the IRWL.
+ //
+
+ KiReleaseSpinLock(&HalpSystemInterruptLock);
+
+ KeLowerIrql(OldIrql);
+}
+
+BOOLEAN
+HalEnableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is enabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ TRUE if the system interrupt was enabled
+
+--*/
+
+{
+ BOOLEAN Enabled = FALSE;
+ ULONG Irq;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // If the vector is a performance counter vector or one of the
+ // internal device vectors then perform 21064-specific enable.
+ //
+
+ switch (Vector) {
+
+ //
+ // Performance counter 0 (internal to 21064)
+ //
+
+ case PC0_VECTOR:
+ case PC0_SECONDARY_VECTOR:
+
+ HalpEnable21064PerformanceInterrupt( PC0_VECTOR, Irql );
+ Enabled = TRUE;
+ break;
+
+ //
+ // Performance counter 1 (internal to 21064)
+ //
+
+ case PC1_VECTOR:
+ case PC1_SECONDARY_VECTOR:
+
+ HalpEnable21064PerformanceInterrupt( PC1_VECTOR, Irql );
+ Enabled = TRUE;
+ break;
+
+ default:
+
+ if( HalpLynxPlatform ){
+
+ Enabled = HalpEnableLynxSioInterrupt( Vector, InterruptMode );
+
+ } else {
+
+ Enabled = HalpEnableSableSioInterrupt( Vector, InterruptMode );
+
+ }
+
+ break;
+
+ }
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+
+ 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;
+
+ //
+ // Handle the special internal bus defined for the processor itself
+ // and used to control the performance counters in the 21064.
+ //
+
+ if( InterfaceType == ProcessorInternal ) {
+
+ Vector = HalpGet21064PerformanceVector( BusInterruptLevel, Irql );
+
+ if( Vector != 0 ){
+
+ //
+ // Success
+ //
+
+ *Affinity = HalpActiveProcessors;
+ return Vector;
+
+ } else {
+
+ //
+ // Unrecognized processor interrupt.
+ //
+
+ *Irql = 0;
+ *Affinity = 0;
+ return 0;
+
+ }
+
+ }
+
+ //
+ // Handle Isa/Eisa bus and Internal devices.
+ //
+ // N.B. The bus interrupt level is the actual E/ISA signal name for
+ // option boards while the bus interrupt level is the actual
+ // interrupt vector number for internal devices. The interrupt
+ // vectors for internal devices are specified in the firmware
+ // configuration and are agreed upon between the firmware and this
+ // code.
+ //
+
+ if( (InterfaceType == Internal) ||
+ (InterfaceType == Isa) ||
+ (InterfaceType == PCIBus) ||
+ (InterfaceType == Eisa) ){
+
+ if( HalpLynxPlatform ){
+
+ return HalpGetLynxSioInterruptVector(
+ BusHandler,
+ RootHandler,
+ BusInterruptLevel,
+ BusInterruptVector,
+ Irql,
+ Affinity
+ );
+
+ } else {
+
+ return HalpGetSableSioInterruptVector(
+ BusHandler,
+ RootHandler,
+ BusInterruptLevel,
+ BusInterruptVector,
+ Irql,
+ Affinity
+ );
+
+ }
+
+ }
+
+
+ //
+ // Not an interface supported on Alpha systems
+ //
+
+ *Irql = 0;
+ *Affinity = 0;
+ return(0);
+
+}
+
+VOID
+HalRequestIpi (
+ IN ULONG Mask
+ )
+
+/*++
+
+Routine Description:
+
+ This routine requests an interprocessor interrupt on a set of processors.
+
+Arguments:
+
+ Mask - Supplies the set of processors that are sent an interprocessor
+ interrupt.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ SABLE_IPIR_CSR Ipir;
+ extern PSABLE_CPU_CSRS HalpSableCpuCsrs[HAL_MAXIMUM_PROCESSOR+1];
+
+ //
+ // Set up to request an interprocessor interrupt.
+ //
+
+ Ipir.all = 0;
+ Ipir.RequestInterrupt = 1;
+
+ //
+ // N.B. Sable supports up to 4 processors only.
+ //
+ // N.B. A read-modify-write is not performed on the Ipir register
+ // which implies that the value of the request halt interrupt
+ // bit may be lost. Currently, this is not an important
+ // consideration because that feature is not being used.
+ // If later it is used than more consideration must be given
+ // to the possibility of losing the bit.
+ //
+
+ //
+ // The request mask is specified as a mask of the logical processors
+ // that must receive IPI requests. HalpSableCpuCsrs[] contains the
+ // CPU CSRs address for the logical processors.
+ //
+
+ //
+ // Request an IPI for processor 0 if requested.
+ //
+
+ if( Mask & HAL_CPU0_MASK ){
+
+ WRITE_CPU_REGISTER( &(HalpSableCpuCsrs[SABLE_CPU0]->Ipir), Ipir.all );
+
+ }
+
+ //
+ // Request an IPI for processor 1 if requested.
+ //
+
+ if( Mask & HAL_CPU1_MASK ){
+
+ WRITE_CPU_REGISTER( &(HalpSableCpuCsrs[SABLE_CPU1]->Ipir), Ipir.all );
+
+ }
+
+ //
+ // Request an IPI for processor 2 if requested.
+ //
+
+ if( Mask & HAL_CPU2_MASK ){
+
+ WRITE_CPU_REGISTER( &(HalpSableCpuCsrs[SABLE_CPU2]->Ipir), Ipir.all );
+
+ }
+
+ //
+ // Request an IPI for processor 3 if requested.
+ //
+
+ if( Mask & HAL_CPU3_MASK ){
+
+ WRITE_CPU_REGISTER( &(HalpSableCpuCsrs[SABLE_CPU3]->Ipir), Ipir.all );
+
+ }
+
+
+
+
+ return;
+}
diff --git a/private/ntos/nthals/halsable/alpha/siintsup.c b/private/ntos/nthals/halsable/alpha/siintsup.c
new file mode 100644
index 000000000..6ea2a3784
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/siintsup.c
@@ -0,0 +1,1332 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ siintsup.c
+
+Abstract:
+
+ This module provides interrupt support for the Sable Standard I/O
+ board.
+
+Author:
+
+ Steve Jenness 28-Oct-1993
+ Joe Notarangelo 28-Oct-1993
+
+Revision History:
+
+--*/
+
+
+#include "halp.h"
+#include "eisa.h"
+#include "xiintsup.h"
+
+//
+// The following is the interrupt object used for DMA controller interrupts.
+// DMA controller interrupts occur when a memory parity error occurs or a
+// programming error occurs to the DMA controller.
+//
+
+KINTERRUPT HalpEisaNmiInterrupt;
+
+UCHAR EisaNMIMsg[] = "NMI: Eisa IOCHKERR board x\n";
+
+//
+// The following function is called when an EISA NMI occurs.
+//
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+//
+// Define save area for 8259 interrupt mask registers.
+//
+// N.B. - Mask values of 1 indicate that the interrupt is disabled.
+//
+
+UCHAR MasterInterruptMask;
+UCHAR Slave0InterruptMask;
+UCHAR Slave1InterruptMask;
+UCHAR Slave2InterruptMask;
+UCHAR Slave3InterruptMask;
+
+//
+// Define save area for Edge/Level controls.
+//
+// N.B. - Mask values of 1 indicate that the interrupt is level triggered.
+// Mask values of 0 indicate that the interrupt is edge triggered.
+//
+
+SABLE_EDGE_LEVEL1_MASK EdgeLevel1Mask;
+SABLE_EDGE_LEVEL2_MASK EdgeLevel2Mask;
+
+//
+// Define the context structure for use by interrupt service routines.
+//
+
+typedef BOOLEAN (*PSECOND_LEVEL_DISPATCH)(
+ PKINTERRUPT InterruptObject
+ );
+
+
+ULONG
+HalpGetSableSioInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+{
+ *Irql = DEVICE_LEVEL;
+ *Affinity = HAL_CPU0_MASK;
+
+ switch( BusInterruptLevel ){
+
+ case EisaInterruptLevel3:
+ return( SABLE_VECTORS + EisaIrq3Vector );
+
+ case EisaInterruptLevel4:
+ return( SABLE_VECTORS + EisaIrq4Vector );
+
+ case EisaInterruptLevel5:
+ return( SABLE_VECTORS + EisaIrq5Vector );
+
+ case EisaInterruptLevel6:
+ return( SABLE_VECTORS + EisaIrq6Vector );
+
+ case EisaInterruptLevel7:
+ return( SABLE_VECTORS + EisaIrq7Vector );
+
+ case EisaInterruptLevel9:
+ return( SABLE_VECTORS + EisaIrq9Vector );
+
+ case EisaInterruptLevel10:
+ return( SABLE_VECTORS + EisaIrq10Vector );
+
+ case EisaInterruptLevel11:
+ return( SABLE_VECTORS + EisaIrq11Vector );
+
+ case EisaInterruptLevel12:
+ return( SABLE_VECTORS + EisaIrq12Vector );
+
+ case EisaInterruptLevel14:
+ return( SABLE_VECTORS + EisaIrq14Vector );
+
+ case EisaInterruptLevel15:
+ return( SABLE_VECTORS + EisaIrq15Vector );
+
+ //
+ // Handle Vectors for the Internal bus devices.
+ //
+
+ case MouseVector:
+ case KeyboardVector:
+ case FloppyVector:
+ case SerialPort1Vector:
+ case ParallelPortVector:
+ case SerialPort0Vector:
+ case I2cVector:
+
+ //
+ // Handle Vectors for PCI devices.
+ //
+
+ case ScsiPortVector:
+ case EthernetPortVector:
+ case PciSlot0AVector:
+ case PciSlot0BVector:
+ case PciSlot0CVector:
+ case PciSlot0DVector:
+ case PciSlot1AVector:
+ case PciSlot1BVector:
+ case PciSlot1CVector:
+ case PciSlot1DVector:
+ case PciSlot2AVector:
+ case PciSlot2BVector:
+ case PciSlot2CVector:
+ case PciSlot2DVector:
+
+ return( SABLE_VECTORS + BusInterruptLevel );
+
+ default:
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+ return HalpGetXioInterruptVector(
+ BusHandler,
+ RootHandler,
+ BusInterruptLevel,
+ BusInterruptVector,
+ Irql,
+ Affinity
+ );
+
+#else
+
+ *Irql = 0;
+ *Affinity = 0;
+ return 0;
+
+#endif
+
+ }
+}
+
+
+BOOLEAN
+HalpInitializeSableSioInterrupts(
+ VOID
+ )
+
+/*++
+
+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;
+ KIRQL oldIrql;
+
+#if 0
+
+// smjfix - EISA NMI support needs to be done.
+
+ //
+ // Initialize the EISA NMI interrupt.
+ //
+
+ KeInitializeInterrupt( &HalpEisaNmiInterrupt,
+ HalHandleNMI,
+ NULL,
+ NULL,
+ EISA_NMI_VECTOR,
+ EISA_NMI_LEVEL,
+ EISA_NMI_LEVEL,
+ LevelSensitive,
+ FALSE,
+ 0,
+ FALSE
+ );
+
+ //
+ // Don't fail if the interrupt cannot be connected.
+ //
+
+ KeConnectInterrupt( &HalpEisaNmiInterrupt );
+
+ //
+ // Clear the Eisa NMI disable bit. This bit is the high order of the
+ // NMI enable register.
+ //
+
+ DataByte = 0;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable,
+ DataByte
+ );
+
+ //
+ // Enable Software-Generated NMI interrupts by setting bit 1 of port 0x461.
+ //
+
+ DataByte = 0x02;
+
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl,
+ DataByte
+ );
+
+#endif //0
+
+ //
+ // Raise the IRQL while the Sable interrupt controllers are initialized.
+ //
+
+ KeRaiseIrql(EISA_DEVICE_LEVEL, &oldIrql);
+
+ //
+ // Initialize the Sable interrupt controllers. The interrupt structure
+ // is one master interrupt controller with 3 cascaded slave controllers.
+ // Proceed through each control word programming each of the controllers.
+ //
+
+ //
+ // Default all E/ISA interrupts to edge triggered.
+ //
+
+ RtlZeroMemory( &EdgeLevel1Mask, sizeof(EdgeLevel1Mask) );
+ RtlZeroMemory( &EdgeLevel2Mask, sizeof(EdgeLevel2Mask) );
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_EDGE_LEVEL_CSRS)SABLE_EDGE_LEVEL_CSRS_QVA)->EdgeLevelControl1,
+ *(PUCHAR)&EdgeLevel1Mask
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_EDGE_LEVEL_CSRS)SABLE_EDGE_LEVEL_CSRS_QVA)->EdgeLevelControl2,
+ *(PUCHAR)&EdgeLevel2Mask
+ );
+
+ //
+ // Write control word 1 for each of the controllers, indicate
+ // that initialization is in progress and the control word 4 will
+ // be used.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1;
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->MasterControl,
+ DataByte
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave0Control,
+ DataByte
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave1Control,
+ DataByte
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave2Control,
+ DataByte
+ );
+
+// smjfix - conditionalize under Pass 2 T2.
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave3Control,
+ DataByte
+ );
+
+ //
+ // Write control word 2 for each of the controllers, set the base
+ // interrupt vector for each controller.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->MasterMask,
+ MasterBaseVector
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave0Mask,
+ Slave0BaseVector
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave1Mask,
+ Slave1BaseVector
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave2Mask,
+ Slave2BaseVector
+ );
+
+// smjfix - conditionalize under Pass 2 T2.
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave3Mask,
+ Slave3BaseVector
+ );
+ //
+ // The third initialization control word set the controls for slave mode.
+ // The master ICW3 uses bit position and the slave ICW3 uses a numeric.
+ //
+
+// smjfix - conditionalize under Pass 2 T2.
+
+ DataByte = ( (1 << (Slave0CascadeVector & 0x7)) |
+ (1 << (Slave1CascadeVector & 0x7)) |
+ (1 << (Slave2CascadeVector & 0x7)) |
+ (1 << (Slave3CascadeVector & 0x7))
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->MasterMask,
+ DataByte
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave0Mask,
+ (Slave0CascadeVector & 0x7)
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave1Mask,
+ (Slave1CascadeVector & 0x7)
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave2Mask,
+ (Slave2CascadeVector & 0x7)
+ );
+
+// smjfix - conditionalize under Pass 2 T2.
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave3Mask,
+ (Slave3CascadeVector & 0x7)
+ );
+ //
+ // 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;
+#ifdef SIO_AEOI
+ ((PINITIALIZATION_COMMAND_4) &DataByte)->AutoEndOfInterruptMode = 1;
+#endif
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->MasterMask,
+ DataByte
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave0Mask,
+ DataByte
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave1Mask,
+ DataByte
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave2Mask,
+ DataByte
+ );
+
+// smjfix - conditionalize under Pass 2 T2.
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave3Mask,
+ DataByte
+ );
+
+ //
+ // Disable all of the interrupts except the slave interrupts to the
+ // master controller.
+ //
+
+// smjfix - conditionalize under Pass 2 T2.
+
+ MasterInterruptMask = (UCHAR)( ~( (1 << (Slave0CascadeVector & 0x7)) |
+ (1 << (Slave1CascadeVector & 0x7)) |
+ (1 << (Slave2CascadeVector & 0x7)) |
+ (1 << (Slave3CascadeVector & 0x7))
+ )
+ );
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->MasterMask,
+ MasterInterruptMask
+ );
+
+ Slave0InterruptMask = 0xFF;
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave0Mask,
+ Slave0InterruptMask
+ );
+
+ Slave1InterruptMask = 0xFF;
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave1Mask,
+ Slave1InterruptMask
+ );
+
+ Slave2InterruptMask = 0xFF;
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave2Mask,
+ Slave2InterruptMask
+ );
+
+// smjfix - conditionalize under Pass 2 T2.
+
+ Slave3InterruptMask = 0xFF;
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave3Mask,
+ Slave3InterruptMask
+ );
+
+ //
+ // Restore IRQL level.
+ //
+
+ KeLowerIrql(oldIrql);
+
+ return(TRUE);
+}
+
+BOOLEAN
+HalpSableSioDispatch(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is entered as a result of an interrupt being generated
+ via the vector that is directly connected to EISA device interrupt.
+
+ This routine is responsible for determining the
+ source of the interrupt, performing the secondary dispatch and
+ acknowledging the interrupt in the 8259 controllers.
+
+ N.B. This interrupt is directly connected and therefore, no argument
+ values are defined.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+
+{
+ UCHAR interruptVector;
+ PKPRCB Prcb;
+ BOOLEAN returnValue;
+ USHORT IdtIndex;
+ UCHAR MasterInService;
+ UCHAR Slave0InService;
+ UCHAR Slave1InService;
+ UCHAR Slave2InService;
+ UCHAR Slave3InService;
+ PULONG DispatchCode;
+ PKINTERRUPT InterruptObject;
+
+ //
+ // Acknowledge the Interrupt controller and receive the returned
+ // interrupt vector.
+ //
+
+ interruptVector = READ_REGISTER_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS)
+ SABLE_INTERRUPT_CSRS_QVA)->InterruptAcknowledge
+ );
+
+ switch( interruptVector ){
+
+ //
+ // Check for possible passive release in the master controller.
+ //
+
+//jnfix - #define for 0x0b
+ case MasterPassiveVector:
+
+#ifdef SIO_AEOI
+
+ //
+ // If the passive release vector has not been enabled, then we can
+ // dismiss it now.
+ //
+
+ if( MasterInterruptMask & 0x80 ){
+ return TRUE;
+ }
+
+#else // SIO_AEOI
+
+ //
+ // Read Master in service mask.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->MasterControl,
+ 0x0B
+ );
+
+ MasterInService = READ_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->MasterControl);
+
+ if( !(MasterInService & 0x80) ) {
+
+ //
+ // Send end of interrupt to clear the passive release in the master
+ // controller.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->MasterControl,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ return TRUE;
+ }
+
+#endif // SIO_AEOI
+
+ break;
+
+
+ //
+ // Check for possible passive release in the slave0 controller.
+ //
+
+ case Slave0PassiveVector:
+
+#ifdef SIO_AEOI
+
+ //
+ // If the passive release vector has not been enabled, then we can
+ // dismiss it now.
+ //
+
+ if( Slave0InterruptMask & 0x80 ){
+ return TRUE;
+ }
+
+#else // SIO_AEOI
+
+ //
+ // Read Slave 0 in service mask.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave0Control,
+ 0x0B
+ );
+
+ Slave0InService = READ_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave0Control);
+
+ if( !(Slave0InService & 0x80) ) {
+
+ //
+ // Send end of interrupt to clear the passive release in the master
+ // controller.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->MasterControl,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ return TRUE;
+ }
+
+#endif // SIO_AEOI
+
+ break;
+
+ //
+ // Check for possible passive release in the slave1 controller.
+ //
+
+ case Slave1PassiveVector:
+
+#ifdef SIO_AEOI
+
+ //
+ // If the passive release vector has not been enabled, then we can
+ // dismiss it now.
+ //
+
+ if( Slave1InterruptMask & 0x80 ){
+ return TRUE;
+ }
+
+#else // SIO_AEOI
+
+ //
+ // Read Slave 1 in service mask.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave1Control,
+ 0x0B
+ );
+
+ Slave1InService = READ_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave1Control);
+
+ if( !(Slave1InService & 0x80) ) {
+
+ //
+ // Send end of interrupt to clear the passive release in the master
+ // controller.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->MasterControl,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ return TRUE;
+ }
+
+#endif // SIO_AEOI
+
+ break;
+
+ //
+ // Check for possible passive release in the slave2 controller.
+ //
+
+ case Slave2PassiveVector:
+
+#ifdef SIO_AEOI
+
+ //
+ // If the passive release vector has not been enabled, then we can
+ // dismiss it now.
+ //
+
+ if( Slave2InterruptMask & 0x80 ){
+ return TRUE;
+ }
+
+#else // SIO_AEOI
+
+ //
+ // Read Slave 2 in service mask.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave2Control,
+ 0x0B
+ );
+
+ Slave2InService = READ_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave2Control);
+
+ if( !(Slave2InService & 0x80) ) {
+
+ //
+ // Send end of interrupt to clear the passive release in the master
+ // controller.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->MasterControl,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ return TRUE;
+ }
+
+#endif // SIO_AEOI
+
+ break;
+
+// smjfix - conditionalize under Pass 2 T2.
+
+ //
+ // Check for possible passive release in the slave3 controller.
+ //
+
+ case Slave3PassiveVector:
+
+#ifdef SIO_AEOI
+
+ //
+ // If the passive release vector has not been enabled, then we can
+ // dismiss it now.
+ //
+
+ if( Slave3InterruptMask & 0x80 ){
+ return TRUE;
+ }
+
+#else // SIO_AEOI
+
+ //
+ // Read Slave 3 in service mask.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave3Control,
+ 0x0B
+ );
+
+ Slave3InService = READ_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave3Control);
+
+ if( !(Slave3InService & 0x80) ) {
+
+ //
+ // Send end of interrupt to clear the passive release in the master
+ // controller.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->MasterControl,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ return TRUE;
+ }
+
+#endif // SIO_AEOI
+
+ break;
+
+ //
+ // The vector is NOT a possible passive release.
+ //
+
+ default:
+
+ break;
+
+ } //end switch( interruptVector )
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ IdtIndex = interruptVector + SABLE_VECTORS;
+ DispatchCode = (PULONG)PCR->InterruptRoutine[IdtIndex];
+ InterruptObject = CONTAINING_RECORD(DispatchCode,
+ KINTERRUPT,
+ DispatchCode);
+
+ returnValue = ((PSECOND_LEVEL_DISPATCH)InterruptObject->DispatchAddress)(InterruptObject);
+
+#ifndef SIO_AEOI
+
+ //
+ // Dismiss the interrupt in the 8259 interrupt controllers.
+ // If this is a cascaded interrupt then the interrupt must be dismissed in
+ // both controllers.
+ //
+
+ switch (interruptVector & SlaveVectorMask) {
+
+ case Slave0BaseVector:
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave0Control,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+ break;
+
+ case Slave1BaseVector:
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave1Control,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+ break;
+
+ case Slave2BaseVector:
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave2Control,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+ break;
+
+ case Slave3BaseVector:
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave3Control,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+ break;
+ }
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->MasterControl,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+#endif // SIO_AEOI
+
+ return(returnValue);
+
+}
+
+VOID
+HalpDisableSableSioInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function Disables the Sable bus specified Sable bus interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the Sable interrupt that is Disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Interrupt;
+
+ if( ((Vector >= SABLE_VECTORS + MasterBaseVector) &&
+ (Vector <= SABLE_VECTORS + MasterPassiveVector)) ||
+ ((Vector >= SABLE_VECTORS + Slave0BaseVector) &&
+ (Vector <= SABLE_VECTORS + Slave0PassiveVector)) ||
+ ((Vector >= SABLE_VECTORS + Slave1BaseVector) &&
+ (Vector <= SABLE_VECTORS + Slave1PassiveVector)) ||
+ ((Vector >= SABLE_VECTORS + Slave2BaseVector) &&
+ (Vector <= SABLE_VECTORS + Slave2PassiveVector)) ||
+ ((Vector >= SABLE_VECTORS + Slave3BaseVector) &&
+ (Vector <= SABLE_VECTORS + Slave3PassiveVector)) ){
+
+ //
+ // Calculate the Sable relative interrupt vector.
+ //
+
+ Vector -= SABLE_VECTORS;
+
+ //
+ // Compute the interrupt within the interrupt controller.
+ //
+
+ Interrupt = Vector & ~SlaveVectorMask;
+
+ //
+ // Disable the interrupt for the appropriate interrupt controller.
+ //
+
+ switch (Vector & SlaveVectorMask) {
+
+ case Slave0BaseVector:
+
+ Slave0InterruptMask |= (UCHAR) 1 << Interrupt;
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave0Mask,
+ Slave0InterruptMask
+ );
+
+ break;
+
+ case Slave1BaseVector:
+
+ Slave1InterruptMask |= (UCHAR) 1 << Interrupt;
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave1Mask,
+ Slave1InterruptMask
+ );
+
+ break;
+
+ case Slave2BaseVector:
+
+ Slave2InterruptMask |= (UCHAR) 1 << Interrupt;
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave2Mask,
+ Slave2InterruptMask
+ );
+
+ break;
+
+ case Slave3BaseVector:
+
+ Slave3InterruptMask |= (UCHAR) 1 << Interrupt;
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave3Mask,
+ Slave3InterruptMask
+ );
+
+ break;
+
+ case MasterBaseVector:
+
+ break;
+ }
+
+ } else {
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+ HalpDisableXioInterrupt( Vector );
+
+#endif
+
+ }
+}
+
+BOOLEAN
+HalpEnableSableSioInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the Sable specified interrupt in the
+ appropriate 8259 interrupt controllers. It also supports the
+ edge/level control for EISA bus interrupts. By default, all interrupts
+ are edge detected (and latched).
+
+Arguments:
+
+ Vector - Supplies the vector of the Sable interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched (Edge).
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG Interrupt;
+ UCHAR ModeBit;
+
+ if( ((Vector >= SABLE_VECTORS + MasterBaseVector) &&
+ (Vector <= SABLE_VECTORS + MasterPassiveVector)) ||
+ ((Vector >= SABLE_VECTORS + Slave0BaseVector) &&
+ (Vector <= SABLE_VECTORS + Slave0PassiveVector)) ||
+ ((Vector >= SABLE_VECTORS + Slave1BaseVector) &&
+ (Vector <= SABLE_VECTORS + Slave1PassiveVector)) ||
+ ((Vector >= SABLE_VECTORS + Slave2BaseVector) &&
+ (Vector <= SABLE_VECTORS + Slave2PassiveVector)) ||
+ ((Vector >= SABLE_VECTORS + Slave3BaseVector) &&
+ (Vector <= SABLE_VECTORS + Slave3PassiveVector)) ){
+
+ //
+ // Calculate the Sable relative interrupt vector.
+ //
+
+ Vector -= SABLE_VECTORS;
+
+ //
+ // Compute the interrupt within the interrupt controller.
+ //
+
+ Interrupt = Vector & ~SlaveVectorMask;
+
+ //
+ // Enable the interrupt for the appropriate interrupt controller.
+ //
+
+ switch( Vector & SlaveVectorMask ) {
+
+ case Slave0BaseVector:
+
+ Slave0InterruptMask &= (UCHAR) ~(1 << Interrupt);
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave0Mask,
+ Slave0InterruptMask
+ );
+
+ break;
+
+ case Slave1BaseVector:
+
+ if( InterruptMode == LevelSensitive )
+ ModeBit = 1;
+ else
+ ModeBit = 0;
+
+ switch( Vector ) {
+
+ case EisaIrq3Vector:
+ EdgeLevel1Mask.Irq3 = ModeBit;
+ break;
+
+ case EisaIrq4Vector:
+ EdgeLevel1Mask.Irq4 = ModeBit;
+ break;
+
+ case EisaIrq5Vector:
+ EdgeLevel1Mask.Irq5 = ModeBit;
+ break;
+
+ case EisaIrq6Vector:
+ EdgeLevel1Mask.Irq6 = ModeBit;
+ break;
+
+ case EisaIrq7Vector:
+ EdgeLevel1Mask.Irq7 = ModeBit;
+ break;
+ }
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_EDGE_LEVEL_CSRS)SABLE_EDGE_LEVEL_CSRS_QVA)->EdgeLevelControl1,
+ *(PUCHAR)&EdgeLevel1Mask
+ );
+
+ Slave1InterruptMask &= (UCHAR) ~(1 << Interrupt);
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave1Mask,
+ Slave1InterruptMask
+ );
+
+ break;
+
+ case Slave2BaseVector:
+
+ if( InterruptMode == LevelSensitive )
+ ModeBit = 1;
+ else
+ ModeBit = 0;
+
+ switch( Vector ) {
+
+ case EisaIrq9Vector:
+ EdgeLevel1Mask.Irq9 = ModeBit;
+ break;
+
+ case EisaIrq10Vector:
+ EdgeLevel1Mask.Irq10 = ModeBit;
+ break;
+
+ case EisaIrq11Vector:
+ EdgeLevel1Mask.Irq11 = ModeBit;
+ break;
+
+ case EisaIrq12Vector:
+ EdgeLevel2Mask.Irq12 = ModeBit;
+ break;
+
+ case EisaIrq14Vector:
+ EdgeLevel2Mask.Irq14 = ModeBit;
+ break;
+
+ case EisaIrq15Vector:
+ EdgeLevel2Mask.Irq15 = ModeBit;
+ break;
+ }
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_EDGE_LEVEL_CSRS)SABLE_EDGE_LEVEL_CSRS_QVA)->EdgeLevelControl1,
+ *(PUCHAR)&EdgeLevel1Mask
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_EDGE_LEVEL_CSRS)SABLE_EDGE_LEVEL_CSRS_QVA)->EdgeLevelControl2,
+ *(PUCHAR)&EdgeLevel2Mask
+ );
+
+ Slave2InterruptMask &= (UCHAR) ~(1 << Interrupt);
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave2Mask,
+ Slave2InterruptMask
+ );
+
+ break;
+
+ case Slave3BaseVector:
+
+ Slave3InterruptMask &= (UCHAR) ~(1 << Interrupt);
+
+ WRITE_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->Slave3Mask,
+ Slave3InterruptMask
+ );
+
+ break;
+
+ case MasterBaseVector:
+
+ break;
+ }
+
+ } else {
+
+#if defined(XIO_PASS1) || defined(XIO_PASS2)
+
+ return HalpEnableXioInterrupt( Vector, InterruptMode );
+
+#else
+
+ return FALSE;
+
+#endif
+
+ }
+
+ return TRUE;
+}
+
+
+#if 0 //jnfix - add NMI handling later
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ This function is called when an EISA NMI occurs. It print the appropriate
+ status information and bugchecks.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object
+
+ ServiceContext - Bug number to call bugcheck with.
+
+Return Value:
+
+ Returns TRUE.
+
+--*/
+{
+ UCHAR StatusByte;
+ UCHAR EisaPort;
+ ULONG port;
+ ULONG AddressSpace = 1; // 1 = I/O address space
+ BOOLEAN Status;
+ PHYSICAL_ADDRESS BusAddress;
+ PHYSICAL_ADDRESS TranslatedAddress;
+
+ StatusByte =
+ READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus);
+
+ if (StatusByte & 0x80) {
+ HalDisplayString ("NMI: Parity Check / Parity Error\n");
+ }
+
+ if (StatusByte & 0x40) {
+ HalDisplayString ("NMI: Channel Check / IOCHK\n");
+ }
+
+ //
+ // This is an Eisa machine, check for extnded nmi information...
+ //
+
+ StatusByte = READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl);
+
+ if (StatusByte & 0x80) {
+ HalDisplayString ("NMI: Fail-safe timer\n");
+ }
+
+ if (StatusByte & 0x40) {
+ HalDisplayString ("NMI: Bus Timeout\n");
+ }
+
+ if (StatusByte & 0x20) {
+ HalDisplayString ("NMI: Software NMI generated\n");
+ }
+
+ //
+ // Look for any Eisa expansion board. See if it asserted NMI.
+ //
+
+ BusAddress.HighPart = 0;
+
+ for (EisaPort = 0; EisaPort <= 0xf; EisaPort++)
+ {
+ BusAddress.LowPart = (EisaPort << 12) + 0xC80;
+
+ Status = HalTranslateBusAddress(Eisa, // InterfaceType
+ 0, // BusNumber
+ BusAddress,
+ &AddressSpace, // 1=I/O address space
+ &TranslatedAddress); // QVA
+ if (Status == FALSE)
+ {
+ UCHAR pbuf[80];
+ sprintf(pbuf,
+ "Unable to translate bus address %x for EISA slot %d\n",
+ BusAddress.LowPart, EisaPort);
+ HalDisplayString(pbuf);
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+ }
+
+ port = TranslatedAddress.LowPart;
+
+ WRITE_PORT_UCHAR ((PUCHAR) port, 0xff);
+ StatusByte = READ_PORT_UCHAR ((PUCHAR) port);
+
+ if ((StatusByte & 0x80) == 0) {
+ //
+ // Found valid Eisa board, Check to see if it's
+ // if IOCHKERR is asserted.
+ //
+
+ StatusByte = READ_PORT_UCHAR ((PUCHAR) port+4);
+ if (StatusByte & 0x2) {
+ EisaNMIMsg[25] = (EisaPort > 9 ? 'A'-10 : '0') + EisaPort;
+ HalDisplayString (EisaNMIMsg);
+ }
+ }
+ }
+
+#if 0
+ // Reset NMI interrupts (for debugging purposes only).
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl, 0x00);
+ WRITE_PORT_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl, 0x02);
+#endif
+
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+ return(TRUE);
+}
+
+#endif //0
+
+//smjfix - This routine should be removed. The eisasup.c module should be
+// broken apart and restructured.
+
+//
+// This is a stub routine required because all of the EISA support is in
+// a single module in halalpha\eisasup.c.
+//
+
+UCHAR
+HalpAcknowledgeEisaInterrupt(
+ IN PVOID ServiceContext
+ )
+{
+ DbgPrint("HalpAcknowledgeEisaInterrupt: this should not be called on Sable");
+ DbgBreakPoint();
+
+ return(0);
+}
diff --git a/private/ntos/nthals/halsable/alpha/siintsup.h b/private/ntos/nthals/halsable/alpha/siintsup.h
new file mode 100644
index 000000000..dcaf4a029
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/siintsup.h
@@ -0,0 +1,50 @@
+/*++
+
+Copyright (c) 1995 Digital Equipment Corporation
+
+Module Name:
+
+ siintsup.h
+
+Abstract:
+
+ This header file contains prototypes for siintsup.c.
+
+Author:
+
+ Dave Richards 31-May-1995
+
+Revision History:
+
+--*/
+
+ULONG
+HalpGetSableSioInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+BOOLEAN
+HalpInitializeSableSioInterrupts(
+ VOID
+ );
+
+BOOLEAN
+HalpSableSioDispatch(
+ VOID
+ );
+
+VOID
+HalpDisableSableSioInterrupt(
+ IN ULONG Vector
+ );
+
+BOOLEAN
+HalpEnableSableSioInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
diff --git a/private/ntos/nthals/halsable/alpha/t2.c b/private/ntos/nthals/halsable/alpha/t2.c
new file mode 100644
index 000000000..f333da400
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/t2.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\t2.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/vga.c b/private/ntos/nthals/halsable/alpha/vga.c
new file mode 100644
index 000000000..764c585af
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/vga.c
@@ -0,0 +1,7 @@
+//
+// This file simply includes the source file from the common Alpha
+// HAL directory.
+//
+
+#include "..\halalpha\vga.c"
+
diff --git a/private/ntos/nthals/halsable/alpha/xiintsup.c b/private/ntos/nthals/halsable/alpha/xiintsup.c
new file mode 100644
index 000000000..4c14ce127
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/xiintsup.c
@@ -0,0 +1,912 @@
+/*++
+
+Copyright (c) 1995 Digital Equipment Corporation
+
+Module Name:
+
+ xiintsup.c
+
+Abstract:
+
+ This module provides interrupt support for the Sable/Gamma/Lynx
+ External I/O module.
+
+Author:
+
+ Dave Richarda 1-June-1995
+
+Revision History:
+
+--*/
+
+#ifdef XIO_PASS1
+
+#include "halp.h"
+#include "eisa.h"
+#include "sableref.h"
+#include "xiintsup.h"
+
+//
+// External I/O 8259 Mask registers.
+//
+
+UCHAR XioMasterInterruptMask;
+UCHAR XioSlaveInterruptMask;
+
+//
+// Define the context structure for use by interrupt service routines.
+//
+
+typedef BOOLEAN (*PSECOND_LEVEL_DISPATCH)(
+ PKINTERRUPT InterruptObject
+ );
+
+extern ULONG HalpProcessors;
+
+
+ULONG
+HalpGetXioInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+{
+ if( HalpXioPresent ){
+
+ switch( BusInterruptLevel ){
+
+ case XioPciSlot0AVector:
+ case XioPciSlot0BVector:
+ case XioPciSlot0CVector:
+ case XioPciSlot0DVector:
+ case XioPciSlot1AVector:
+ case XioPciSlot1BVector:
+ case XioPciSlot1CVector:
+ case XioPciSlot1DVector:
+
+ *Irql = PCI_DEVICE_LEVEL;
+
+ if( HalpProcessors > 1 ){
+ *Affinity = HAL_CPU1_MASK;
+ } else {
+ *Affinity = HAL_CPU0_MASK;
+ }
+
+ return( SABLE_VECTORS + BusInterruptLevel );
+
+ }
+ }
+
+ //
+ // The caller specified a bus level not support by this platform.
+ //
+
+ *Irql = 0;
+ *Affinity = 0;
+ return(0);
+}
+
+
+BOOLEAN
+HalpInitializeXioInterrupts(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine does the following:
+ (1) initializes the Xio 8259 interrupt registers
+ (2) initializes structures necessary for EISA operations
+ (3) connects the intermediate interrupt dispatcher.
+ (4) 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 Xio interrupt controllers. The interrupt structure
+ // is one master interrupt controller with 1 cascaded slave controller.
+ // Proceed through each control word programming each of the controllers.
+ //
+
+ //
+ // Write control word 1 for each of the controllers, indicate
+ // that initialization is in progress and the control word 4 will
+ // be used.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1;
+// ((PINITIALIZATION_COMMAND_1) &DataByte)->LevelTriggeredMode = 1;
+ DataByte |= 0x04;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1;
+
+ WRITE_PORT_UCHAR(
+ &((PXIO_INTERRUPT_CSRS) XIO_INTERRUPT_CSRS_QVA)->MasterControl,
+ DataByte
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PXIO_INTERRUPT_CSRS) XIO_INTERRUPT_CSRS_QVA)->SlaveControl,
+ DataByte
+ );
+
+ //
+ // Write control word 2 for each of the controllers, set the base
+ // interrupt vector for each controller.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PXIO_INTERRUPT_CSRS) XIO_INTERRUPT_CSRS_QVA)->MasterMask,
+ XioMasterBaseVector
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PXIO_INTERRUPT_CSRS) XIO_INTERRUPT_CSRS_QVA)->SlaveMask,
+ XioSlaveBaseVector
+ );
+
+ //
+ // The third initialization control word set the controls for slave mode.
+ // The master ICW3 uses bit position and the slave ICW3 uses a numeric.
+ //
+
+ DataByte = (1 << (XioSlaveCascadeVector & ~XioMasterBaseVector) );
+
+ WRITE_PORT_UCHAR(
+ &((PXIO_INTERRUPT_CSRS) XIO_INTERRUPT_CSRS_QVA)->MasterMask,
+ DataByte
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PXIO_INTERRUPT_CSRS) XIO_INTERRUPT_CSRS_QVA)->SlaveMask,
+ (XioSlaveCascadeVector & ~XioMasterBaseVector)
+ );
+
+ //
+ // 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;
+#ifdef XIO_AEOI
+ ((PINITIALIZATION_COMMAND_4) &DataByte)->AutoEndOfInterruptMode = 1;
+#endif
+
+ WRITE_PORT_UCHAR(
+ &((PXIO_INTERRUPT_CSRS) XIO_INTERRUPT_CSRS_QVA)->MasterMask,
+ DataByte
+ );
+
+ WRITE_PORT_UCHAR(
+ &((PXIO_INTERRUPT_CSRS) XIO_INTERRUPT_CSRS_QVA)->SlaveMask,
+ DataByte
+ );
+
+ //
+ // Disable all of the interrupts except the slave interrupts to the
+ // master controller.
+ //
+
+ XioMasterInterruptMask =
+ (UCHAR)( ~(1 << (XioSlaveCascadeVector & ~XioMasterBaseVector)) );
+
+ WRITE_PORT_UCHAR(
+ &((PXIO_INTERRUPT_CSRS) XIO_INTERRUPT_CSRS_QVA)->MasterMask,
+ XioMasterInterruptMask
+ );
+
+ XioSlaveInterruptMask = 0xFF;
+
+ WRITE_PORT_UCHAR(
+ &((PXIO_INTERRUPT_CSRS) XIO_INTERRUPT_CSRS_QVA)->SlaveMask,
+ XioSlaveInterruptMask
+ );
+
+ return TRUE;
+
+}
+
+BOOLEAN
+HalpXioDispatch(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is entered as a result of an interrupt being generated
+ via the vector that is directly connected XIO device interrupt.
+
+ This routine is responsible for determining the
+ source of the interrupt, performing the secondary dispatch and
+ acknowledging the interrupt in the 8259 controllers.
+
+ N.B. This interrupt is directly connected and therefore, no argument
+ values are defined.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+
+{
+ UCHAR interruptVector;
+ BOOLEAN returnValue;
+ USHORT IdtIndex;
+ UCHAR InService;
+ PULONG DispatchCode;
+ PKINTERRUPT InterruptObject;
+
+ //
+ // Acknowledge the Interrupt controller and receive the returned
+ // interrupt vector.
+ //
+
+ interruptVector = READ_REGISTER_UCHAR(
+ &((PXIO_INTERRUPT_CSRS)
+ XIO_INTERRUPT_CSRS_QVA)->InterruptAcknowledge
+ );
+
+ //
+ // If we get a passive release, send a non-specific end of interrupt
+ // command and return TRUE, indicating that we processed the interrupt.
+ //
+
+ switch( interruptVector ){
+
+ case XioMasterPassiveReleaseVector:
+
+#ifdef XIO_AEOI
+
+ //
+ // If the passive release vector has not been enabled, then we can
+ // dismiss it now.
+ //
+
+ if( XioMasterInterruptMask & 0x80 ){
+ return TRUE;
+ }
+
+#else // XIO_AEOI
+
+ //
+ // Read the "in-service" mask.
+ //
+
+ WRITE_PORT_UCHAR( &((PSABLE_INTERRUPT_CSRS)SABLE_INTERRUPT_CSRS_QVA)->MasterControl,
+ 0x0B
+ );
+
+ InService = READ_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->MasterControl
+ );
+
+ if( (InService & 0x80) == 0 ){
+
+ //
+ // Send end of interrupt to clear the passive release in the
+ // master controller.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PXIO_INTERRUPT_CSRS) XIO_INTERRUPT_CSRS_QVA)->MasterControl,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ return TRUE;
+
+ }
+
+#endif // XIO_AEOI
+
+ break;
+
+ case XioSlavePassiveReleaseVector:
+
+#ifdef XIO_AEOI
+
+ //
+ // If the passive release vector has not been enabled, then we can
+ // dismiss it now.
+ //
+
+ if( XioSlaveInterruptMask & 0x80 ){
+ return TRUE;
+ }
+
+#else // XIO_AEOI
+
+ //
+ // Read the "in-service" mask.
+ //
+
+ WRITE_PORT_UCHAR( &((PSABLE_INTERRUPT_CSRS)SABLE_INTERRUPT_CSRS_QVA)->SlaveControl,
+ 0x0B
+ );
+
+ InService = READ_PORT_UCHAR(
+ &((PSABLE_INTERRUPT_CSRS) SABLE_INTERRUPT_CSRS_QVA)->SlaveControl
+ );
+
+ if( (InService & 0x80) == 0 ){
+
+ //
+ // Send end of interrupt to clear the passive release in the
+ // slave controller.
+ //
+
+ WRITE_PORT_UCHAR(
+ &((PXIO_INTERRUPT_CSRS) XIO_INTERRUPT_CSRS_QVA)->SlaveControl,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ return TRUE;
+
+ }
+
+#endif // XIO_AEOI
+
+ break;
+
+ }
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ IdtIndex = interruptVector + SABLE_VECTORS;
+ DispatchCode = (PULONG)PCR->InterruptRoutine[IdtIndex];
+ InterruptObject = CONTAINING_RECORD(DispatchCode,
+ KINTERRUPT,
+ DispatchCode);
+
+ returnValue = ((PSECOND_LEVEL_DISPATCH)InterruptObject->DispatchAddress)(InterruptObject);
+
+#ifndef XIO_AEOI
+
+ //
+ // Dismiss the interrupt in the 8259 interrupt controllers.
+ // If this is a cascaded interrupt then the interrupt must be dismissed in
+ // both controllers.
+ //
+
+ if( (interruptVector & XioSlaveBaseVector) == XioSlaveBaseVector ){
+
+ WRITE_PORT_UCHAR(
+ &((PXIO_INTERRUPT_CSRS) XIO_INTERRUPT_CSRS_QVA)->SlaveControl,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ }
+
+ WRITE_PORT_UCHAR(
+ &((PXIO_INTERRUPT_CSRS) XIO_INTERRUPT_CSRS_QVA)->MasterControl,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+#endif // XIO_AEOI
+
+ return(returnValue);
+
+}
+
+
+
+VOID
+HalpDisableXioInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function Disables the External IO specified interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the Xio interrupt that is Disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG Interrupt;
+
+ if( (Vector >= SABLE_VECTORS + XioMasterBaseVector) &&
+ (Vector <= SABLE_VECTORS + XioSlavePassiveReleaseVector) ){
+
+ //
+ // Calculate the Xio relative interrupt vector.
+ //
+
+ Vector -= SABLE_VECTORS;
+
+ //
+ // Compute the interrupt within the interrupt controller.
+ //
+
+ Interrupt = Vector & 0x7;
+
+ //
+ // Enable the interrupt for the appropriate interrupt controller.
+ //
+
+ if( (Vector & XioSlaveBaseVector) == XioSlaveBaseVector ){
+
+ XioSlaveInterruptMask |= (UCHAR) (1 << Interrupt);
+
+ WRITE_PORT_UCHAR(
+ &((PXIO_INTERRUPT_CSRS) XIO_INTERRUPT_CSRS_QVA)->SlaveMask,
+ XioSlaveInterruptMask
+ );
+
+ }
+ }
+}
+
+BOOLEAN
+HalpEnableXioInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the Xio specified interrupt in the
+ appropriate 8259 interrupt controllers. It also supports the
+ edge/level control for EISA bus interrupts. By default, all interrupts
+ are edge detected (and latched).
+
+Arguments:
+
+ Vector - Supplies the vector of the Xio interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched (Edge).
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG Interrupt;
+
+ if( (Vector >= SABLE_VECTORS + XioMasterBaseVector) &&
+ (Vector <= SABLE_VECTORS + XioSlavePassiveReleaseVector) ){
+
+ //
+ // Calculate the Xio relative interrupt vector.
+ //
+
+ Vector -= SABLE_VECTORS;
+
+ //
+ // Compute the interrupt within the interrupt controller.
+ //
+
+ Interrupt = Vector & 0x7;
+
+ //
+ // Enable the interrupt for the appropriate interrupt controller.
+ //
+
+ if( (Vector & XioSlaveBaseVector) == XioSlaveBaseVector ){
+
+ XioSlaveInterruptMask &= (UCHAR) ~(1 << Interrupt);
+
+ WRITE_PORT_UCHAR(
+ &((PXIO_INTERRUPT_CSRS) XIO_INTERRUPT_CSRS_QVA)->SlaveMask,
+ XioSlaveInterruptMask
+ );
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+#endif // XIO_PASS1
+
+#ifdef XIO_PASS2
+
+#include "halp.h"
+#include "t2.h"
+#include "icic.h"
+#include "xiintsup.h"
+
+//
+// Define the context structure for use by interrupt service routines.
+//
+
+typedef BOOLEAN (*PSECOND_LEVEL_DISPATCH)(
+ PKINTERRUPT InterruptObject
+ );
+
+extern ULONG HalpProcessors;
+
+//
+// Cached copies of the corresponding ICIC register(s).
+//
+
+ICIC_MASK_REGISTER XioIcIcMaskRegister;
+
+
+ULONG
+HalpGetXioInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+{
+ if( HalpXioPresent ){
+
+ switch( BusInterruptLevel ){
+
+ //
+ // Handle Vectors for PCI devices.
+ //
+
+ case XioPciSlot0AVector:
+ case XioPciSlot0BVector:
+ case XioPciSlot0CVector:
+ case XioPciSlot0DVector:
+ case XioPciSlot1AVector:
+ case XioPciSlot1BVector:
+ case XioPciSlot1CVector:
+ case XioPciSlot1DVector:
+ case XioPciSlot2AVector:
+ case XioPciSlot2BVector:
+ case XioPciSlot2CVector:
+ case XioPciSlot2DVector:
+ case XioPciSlot3AVector:
+ case XioPciSlot3BVector:
+ case XioPciSlot3CVector:
+ case XioPciSlot3DVector:
+ case XioPciSlot4AVector:
+ case XioPciSlot4BVector:
+ case XioPciSlot4CVector:
+ case XioPciSlot4DVector:
+ case XioPciSlot5AVector:
+ case XioPciSlot5BVector:
+ case XioPciSlot5CVector:
+ case XioPciSlot5DVector:
+ case XioPciSlot6AVector:
+ case XioPciSlot6BVector:
+ case XioPciSlot6CVector:
+ case XioPciSlot6DVector:
+ case XioPciSlot7AVector:
+ case XioPciSlot7BVector:
+ case XioPciSlot7CVector:
+ case XioPciSlot7DVector:
+
+ *Irql = DEVICE_LEVEL;
+
+ if( HalpProcessors > 1 ){
+ *Affinity = HAL_CPU1_MASK;
+ } else {
+ *Affinity = HAL_CPU0_MASK;
+ }
+
+ return( BusInterruptLevel );
+
+ }
+ }
+
+ *Irql = 0;
+ *Affinity = 0;
+ return 0;
+}
+
+
+BOOLEAN
+HalpInitializeXioInterrupts(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the ICIC on the Standard I/O module.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ TRUE.
+
+--*/
+
+{
+ T2_ICE Ice;
+ ICIC_ELCR_REGISTER XioIcIcElcrRegister;
+
+ //
+ // Initialize the interface between the T3/T4 and the ICIC.
+ //
+
+ Ice.all = 0;
+ Ice.EisaFlushAddress = 0x542;
+ Ice.IcEnable = 1;
+ Ice.HalfSpeedEnable = 0;
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Ice,
+ Ice.all );
+
+ //
+ // Initialize the ICIC Mask Register.
+ //
+
+ XioIcIcMaskRegister = (ULONGLONG)-1;
+
+ WRITE_ICIC_REGISTER( T4_CSRS_QVA, IcIcMaskRegister,
+ XioIcIcMaskRegister );
+
+ //
+ // Initialize the ICIC Edge/Level Control Register.
+ //
+
+ XioIcIcElcrRegister =
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot4AVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot4BVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot4CVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot4DVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot5AVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot5BVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot5CVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot5DVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot6AVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot6BVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot6CVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot6DVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot7AVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot7BVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot7CVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot7DVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot7DVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot0AVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot0BVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot0CVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot0DVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot1AVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot1BVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot1CVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot1DVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot2AVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot2BVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot2CVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot2DVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot3AVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot3BVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot3CVector - XioBaseVector)) |
+ ((ICIC_ELCR_REGISTER)1 << (XioPciSlot3DVector - XioBaseVector));
+
+ WRITE_ICIC_REGISTER( T4_CSRS_QVA, IcIcElcrRegister,
+ XioIcIcElcrRegister );
+
+ //
+ // Initialize the ICIC EISA Register.
+ //
+
+ WRITE_ICIC_REGISTER( T4_CSRS_QVA, IcIcEisaRegister, (ULONGLONG)0 );
+
+ //
+ // Initialize the ICIC Mode Register.
+ //
+
+ WRITE_ICIC_REGISTER( T4_CSRS_QVA, IcIcModeRegister, (ULONGLONG)0 );
+
+ return TRUE;
+}
+
+
+BOOLEAN
+HalpXioDispatch(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine dispatches interrupts received by the External I/O
+ ICIC.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A boolean value indicating whether the interrupt was handled by
+ the FLIH/SLIH.
+
+--*/
+
+{
+ T2_VAR Var;
+ PULONG DispatchCode;
+ PKINTERRUPT InterruptObject;
+ BOOLEAN ReturnValue;
+
+ //
+ // Get the interrupt vector.
+ //
+
+ Var.all = READ_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Var );
+
+ //
+ // If this is a passive release, ignore the interrupt.
+ //
+
+ if( Var.PassiveRelease == 1 ){
+
+ return(TRUE);
+
+ }
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ DispatchCode = (PULONG)PCR->InterruptRoutine[XioBaseVector + Var.Vector];
+ InterruptObject = CONTAINING_RECORD(DispatchCode,
+ KINTERRUPT,
+ DispatchCode);
+
+ ReturnValue = ((PSECOND_LEVEL_DISPATCH)InterruptObject->DispatchAddress)(InterruptObject);
+
+ //
+ // Send an SEOI.
+ //
+
+ WRITE_T2_REGISTER( &((PT2_CSRS)(T4_CSRS_QVA))->Var, Var.Vector );
+
+ return(ReturnValue);
+}
+
+VOID
+HalpDisableXioInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This routine disables interrupts associated with the External I/O
+ ICIC.
+
+Arguments:
+
+ Vector - The vector of the interrupt to disable.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONGLONG IrqMask;
+
+ if( (Vector >= XioBaseVector) &&
+ (Vector <= XioPciSlot3DVector) ){
+
+ //
+ // Compute the IRQ mask.
+ //
+
+ IrqMask = (ICIC_MASK_REGISTER)1 << (Vector - XioBaseVector);
+
+ //
+ // Mask the interrupt.
+ //
+
+ XioIcIcMaskRegister |= IrqMask;
+
+ //
+ // Update the ICIC Mask Register.
+ //
+
+ WRITE_ICIC_REGISTER( T4_CSRS_QVA, IcIcMaskRegister,
+ XioIcIcMaskRegister );
+
+ }
+}
+
+BOOLEAN
+HalpEnableXioInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables interrupts associated with the External I/O
+ ICIC.
+
+Arguments:
+
+ Vector - The vector of the interrupt to enable.
+
+ InterruptMode - An indication of whether the interrupt should
+ be edge-triggered/level-sensitive. (Ignored)
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONGLONG IrqMask;
+
+ if( (Vector >= XioBaseVector) &&
+ (Vector <= XioPciSlot3DVector) ){
+
+ //
+ // Compute the IRQ mask.
+ //
+
+ IrqMask = (ICIC_MASK_REGISTER)1 << (Vector - XioBaseVector);
+
+ //
+ // Un-mask the interrupt.
+ //
+
+ XioIcIcMaskRegister &= ~IrqMask;
+
+ //
+ // Update the ICIC Mask Register.
+ //
+
+ WRITE_ICIC_REGISTER( T4_CSRS_QVA, IcIcMaskRegister,
+ XioIcIcMaskRegister );
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+#endif // XIO_PASS2
diff --git a/private/ntos/nthals/halsable/alpha/xiintsup.h b/private/ntos/nthals/halsable/alpha/xiintsup.h
new file mode 100644
index 000000000..01b39ffd3
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/xiintsup.h
@@ -0,0 +1,50 @@
+/*++
+
+Copyright (c) 1995 Digital Equipment Corporation
+
+Module Name:
+
+ xiintsup.h
+
+Abstract:
+
+ This header file contains prototypes for xiintsup.c.
+
+Author:
+
+ Dave Richards 31-May-1995
+
+Revision History:
+
+--*/
+
+ULONG
+HalpGetXioInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+BOOLEAN
+HalpInitializeXioInterrupts(
+ VOID
+ );
+
+BOOLEAN
+HalpXioDispatch(
+ VOID
+ );
+
+VOID
+HalpDisableXioInterrupt(
+ IN ULONG Vector
+ );
+
+BOOLEAN
+HalpEnableXioInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
diff --git a/private/ntos/nthals/halsable/alpha/xioref.h b/private/ntos/nthals/halsable/alpha/xioref.h
new file mode 100644
index 000000000..4b2b2bde0
--- /dev/null
+++ b/private/ntos/nthals/halsable/alpha/xioref.h
@@ -0,0 +1,148 @@
+/*++
+
+Copyright (c) 1995 Digital Equipment Corporation
+
+Module Name:
+
+ xioref.h
+
+Abstract:
+
+ This file defines the structures and definitions of the XIO
+ interrupt architecture.
+
+Author:
+
+ Dave Richards 12-May-1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#ifndef _XIOREFH_
+#define _XIOREFH_
+
+#ifndef _LANGUAGE_ASSEMBLY
+
+#ifdef XIO_PASS1
+
+typedef struct _XIO_INTERRUPT_CSRS{
+ UCHAR InterruptAcknowledge; // IO Address 0x0532
+ UCHAR Filler0; //
+ UCHAR MasterControl; // IO Address 0x0534
+ UCHAR MasterMask; // IO Address 0x0535
+ UCHAR SlaveControl; // IO Address 0x0536
+ UCHAR SlaveMask; // IO Address 0x0537
+} XIO_INTERRUPT_CSRS, *PXIO_INTERRUPT_CSRS;
+
+enum _XIO_INTERRUPT_VECTORS {
+
+ XioMasterBaseVector = 0x30,
+ XioReservedVector = 0x30,
+ XioSlaveCascadeVector,
+ XioMasterPassiveReleaseVector = 0x37,
+
+ XioSlaveBaseVector = 0x38,
+ XioPciSlot0AVector = 0x38,
+ XioPciSlot0BVector,
+ XioPciSlot0CVector,
+ XioPciSlot0DVector,
+ XioPciSlot1AVector,
+ XioPciSlot1BVector,
+ XioPciSlot1CVector,
+ XioPciSlot1DVector,
+ XioSlavePassiveReleaseVector = 0x3f,
+
+};
+
+#endif // XIO_PASS1
+
+#ifdef XIO_PASS2
+
+enum _XIO_INTERRUPT_VECTORS {
+
+ XioBaseVector = 0xc0, // XIO Base Vector
+ XioReservedVector = 0xc0, //
+ XioIcIcIrq0 = 0xc0, //
+ XioIcIcIrq1, //
+ XioIcIcIrq2, //
+ XioIcIcIrq3, //
+ XioIcIcIrq4, //
+ XioIcIcIrq5, //
+ XioIcIcIrq6, //
+ XioIcIcIrq7, //
+ XioIcIcIrq8, //
+ XioIcIcIrq9, //
+ XioIcIcIrq10, //
+ XioIcIcIrq11, //
+ XioIcIcIrq12, //
+ XioIcIcIrq13, //
+ XioIcIcIrq14, //
+ XioIcIcIrq15, //
+ XioIcIcIrq16, //
+ XioIcIcIrq17, //
+ XioIcIcIrq18, //
+ XioIcIcIrq19, //
+ XioIcIcIrq20, //
+ XioIcIcIrq21, //
+ XioIcIcIrq22, //
+ XioIcIcIrq23, //
+ XioIcIcIrq24, //
+ XioIcIcIrq25, //
+ XioIcIcIrq26, //
+ XioIcIcIrq27, //
+ XioIcIcIrq28, //
+ XioIcIcIrq29, //
+ XioIcIcIrq30, //
+ XioIcIcIrq31, //
+ XioPciSlot4AVector, // PCI Slot 4 A
+ XioPciSlot4BVector, // PCI Slot 4 B
+ XioPciSlot4CVector, // PCI Slot 4 C
+ XioPciSlot4DVector, // PCI Slot 4 D
+ XioPciSlot5AVector, // PCI Slot 5 A
+ XioPciSlot5BVector, // PCI Slot 5 B
+ XioPciSlot5CVector, // PCI Slot 5 C
+ XioPciSlot5DVector, // PCI Slot 5 D
+ XioPciSlot6AVector, // PCI Slot 6 A
+ XioPciSlot6BVector, // PCI Slot 6 B
+ XioPciSlot6CVector, // PCI Slot 6 C
+ XioPciSlot6DVector, // PCI Slot 6 D
+ XioPciSlot7AVector, // PCI Slot 7 A
+ XioPciSlot7BVector, // PCI Slot 7 B
+ XioPciSlot7CVector, // PCI Slot 7 C
+ XioPciSlot7DVector, // PCI Slot 7 D
+ XioPciSlot0AVector, // PCI Slot 0 A
+ XioPciSlot0BVector, // PCI Slot 0 B
+ XioPciSlot0CVector, // PCI Slot 0 C
+ XioPciSlot0DVector, // PCI Slot 0 D
+ XioPciSlot1AVector, // PCI Slot 1 A
+ XioPciSlot1BVector, // PCI Slot 1 B
+ XioPciSlot1CVector, // PCI Slot 1 C
+ XioPciSlot1DVector, // PCI Slot 1 D
+ XioPciSlot2AVector, // PCI Slot 2 A
+ XioPciSlot2BVector, // PCI Slot 2 B
+ XioPciSlot2CVector, // PCI Slot 2 C
+ XioPciSlot2DVector, // PCI Slot 2 D
+ XioPciSlot3AVector, // PCI Slot 3 A
+ XioPciSlot3BVector, // PCI Slot 3 B
+ XioPciSlot3CVector, // PCI Slot 3 C
+ XioPciSlot3DVector // PCI Slot 3 D
+
+};
+
+#endif // XIO_PASS2
+
+//
+// The following variable indicates whether an XIO module is present
+// in the system.
+//
+
+extern BOOLEAN HalpXioPresent;
+
+#endif // _LANGUAGE_ASSEMBLY
+
+#endif // _XIOREFH_