diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/nthals/halsable | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to 'private/ntos/nthals/halsable')
72 files changed, 13196 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_ diff --git a/private/ntos/nthals/halsable/bushnd.c b/private/ntos/nthals/halsable/bushnd.c new file mode 100644 index 000000000..a1e648dc1 --- /dev/null +++ b/private/ntos/nthals/halsable/bushnd.c @@ -0,0 +1,7 @@ +// +// This file simply includes the common sources from the current HAL +// directory. When the structure is finally changed, the real file should +// be in this directory. +// + +#include "..\bushnd.c" diff --git a/private/ntos/nthals/halsable/dirs b/private/ntos/nthals/halsable/dirs new file mode 100644 index 000000000..a2a38f0fd --- /dev/null +++ b/private/ntos/nthals/halsable/dirs @@ -0,0 +1,24 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + dirs. + +Abstract: + + This file specifies the subdirectories of the current directory that + contain component makefiles. + + +Author: + + +NOTE: Commented description of this file is in \nt\bak\bin\dirs.tpl + +!ENDIF + +DIRS=up + +OPTIONAL_DIRS=mp diff --git a/private/ntos/nthals/halsable/drivesup.c b/private/ntos/nthals/halsable/drivesup.c new file mode 100644 index 000000000..38259e5f4 --- /dev/null +++ b/private/ntos/nthals/halsable/drivesup.c @@ -0,0 +1,7 @@ +// +// This file simply includes the common sources from the current HAL +// directory. When the structure is finally changed, the real file should +// be in this directory. +// + +#include "..\drivesup.c" diff --git a/private/ntos/nthals/halsable/hal.rc b/private/ntos/nthals/halsable/hal.rc new file mode 100644 index 000000000..3cba4ad89 --- /dev/null +++ b/private/ntos/nthals/halsable/hal.rc @@ -0,0 +1,11 @@ +#include <windows.h> + +#include <ntverp.h> + +#define VER_FILETYPE VFT_DLL +#define VER_FILESUBTYPE VFT2_UNKNOWN +#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL" +#define VER_INTERNALNAME_STR "hal.dll" + +#include "common.ver" + diff --git a/private/ntos/nthals/halsable/hal.src b/private/ntos/nthals/halsable/hal.src new file mode 100644 index 000000000..da778bb9d --- /dev/null +++ b/private/ntos/nthals/halsable/hal.src @@ -0,0 +1,7 @@ +// +// This file simply includes the common sources from the current HAL +// directory. When the structure is finally changed, the real file should +// be in this directory. +// + +#include "..\hal.src" diff --git a/private/ntos/nthals/halsable/mp/makefile b/private/ntos/nthals/halsable/mp/makefile new file mode 100644 index 000000000..6ee4f43fa --- /dev/null +++ b/private/ntos/nthals/halsable/mp/makefile @@ -0,0 +1,6 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/private/ntos/nthals/halsable/mp/makefile.inc b/private/ntos/nthals/halsable/mp/makefile.inc new file mode 100644 index 000000000..6985ce07a --- /dev/null +++ b/private/ntos/nthals/halsable/mp/makefile.inc @@ -0,0 +1,5 @@ +obj\alpha\hal.def: ..\..\hal.src + rcpp -P -f ..\..\hal.src -DALPHA=1 $(C_DEFINES) -g obj\alpha\hal.def + +$(TARGETPATH)\alpha\hal.lib: $(TARGETPATH)\alpha\halsabmp.lib + copy $** $@ diff --git a/private/ntos/nthals/halsable/mp/sources b/private/ntos/nthals/halsable/mp/sources new file mode 100644 index 000000000..3e7936dc4 --- /dev/null +++ b/private/ntos/nthals/halsable/mp/sources @@ -0,0 +1,107 @@ +!IF 0 + +Copyright (c) 1993 Microsoft Corporation + +Module Name: + + sources. + +Abstract: + + This file specifies the target component being built and the list of + sources files needed to build that component. Also specifies optional + compiler switches and libraries that are unique for the component being + built. + + +Author: + + David N. Cutler (davec) 12-Apr-1993 + +NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl + +!ENDIF + +MAJORCOMP=ntos +MINORCOMP=hal + +TARGETNAME=halsabmp +TARGETPATH=$(BASEDIR)\public\sdk\lib + +ALPHA_WARNING_LEVEL=-W3 -WX +C_DEFINES=-DEV4 -DAXPSABLE -DRTC_SQE -DEISA_PLATFORM -DSIO_AEOI + +NT_UP=0 + +!IF $(ALPHA) + +TARGETTYPE=HAL + +!ELSE + +TARGETTYPE=DRIVER + +!ENDIF + +INCLUDES=..\alpha;..\..\..\inc;..\..\..\ke;..\..\..\io;..\..\..\fw\alpha;..\..\..\fastfat;..\..\halalpha + +SOURCES= + +ALPHA_SOURCES=..\hal.rc \ + ..\bushnd.c \ + ..\drivesup.c \ + ..\alpha\adjust.c \ + ..\alpha\allstart.c \ + ..\alpha\alphaio.s \ + ..\alpha\bios.c \ + ..\alpha\cache.c \ + ..\alpha\ebsgdma.c \ + ..\alpha\eeprom8k.c \ + ..\alpha\eisasup.c \ + ..\alpha\environ.c \ + ..\alpha\ev4cache.c \ + ..\alpha\ev4int.c \ + ..\alpha\ev4ints.s \ + ..\alpha\ev4mchk.c \ + ..\alpha\ev4mem.s \ + ..\alpha\ev4prof.c \ + ..\alpha\fwreturn.c \ + ..\alpha\haldebug.c \ + ..\alpha\halpal.s \ + ..\alpha\icic.c \ + ..\alpha\idle.s \ + ..\alpha\info.c \ + ..\alpha\inithal.c \ + ..\alpha\intsup.s \ + ..\alpha\iousage.c \ + ..\alpha\ioproc.c \ + ..\alpha\lyintsup.c \ + ..\alpha\memory.c \ + ..\alpha\pcisup.c \ + ..\alpha\pcrtc.c \ + ..\alpha\pcserial.c \ + ..\alpha\pcspeakr.c \ + ..\alpha\perf8254.c \ + ..\alpha\siintsup.c \ + ..\alpha\t2.c \ + ..\alpha\vga.c \ + ..\alpha\xiintsup.c \ + ..\alpha\addrsup.c \ + ..\alpha\busdata.c \ + ..\alpha\pcibus.c \ + ..\alpha\sableerr.c \ + ..\alpha\sableio.s \ + ..\alpha\sbinitnt.c \ + ..\alpha\sbintr.s \ + ..\alpha\sbintsup.c \ + ..\alpha\sbmapio.c \ + ..\alpha\sbsysint.c + +DLLDEF=obj\*\hal.def + +!IF $(ALPHA) + +NTTARGETFILES=$(TARGETPATH)\alpha\hal.lib \ + $(TARGETPATH)\alpha\hal.dll + +!ENDIF diff --git a/private/ntos/nthals/halsable/up/makefile b/private/ntos/nthals/halsable/up/makefile new file mode 100644 index 000000000..6ee4f43fa --- /dev/null +++ b/private/ntos/nthals/halsable/up/makefile @@ -0,0 +1,6 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/private/ntos/nthals/halsable/up/makefile.inc b/private/ntos/nthals/halsable/up/makefile.inc new file mode 100644 index 000000000..76942c78b --- /dev/null +++ b/private/ntos/nthals/halsable/up/makefile.inc @@ -0,0 +1,5 @@ +obj\alpha\hal.def: ..\..\hal.src + rcpp -P -f ..\..\hal.src -DALPHA=1 $(C_DEFINES) -g obj\alpha\hal.def + +$(TARGETPATH)\alpha\hal.lib: $(TARGETPATH)\alpha\halsabup.lib + copy $** $@ diff --git a/private/ntos/nthals/halsable/up/sources b/private/ntos/nthals/halsable/up/sources new file mode 100644 index 000000000..84207c08c --- /dev/null +++ b/private/ntos/nthals/halsable/up/sources @@ -0,0 +1,107 @@ +!IF 0 + +Copyright (c) 1993 Microsoft Corporation + +Module Name: + + sources. + +Abstract: + + This file specifies the target component being built and the list of + sources files needed to build that component. Also specifies optional + compiler switches and libraries that are unique for the component being + built. + + +Author: + + David N. Cutler (davec) 12-Apr-1993 + +NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl + +!ENDIF + +MAJORCOMP=ntos +MINORCOMP=hal + +TARGETNAME=halsabup +TARGETPATH=$(BASEDIR)\public\sdk\lib + +ALPHA_WARNING_LEVEL=-W3 -WX +C_DEFINES=-DEV4 -DAXPSABLE -DRTC_SQE -DEISA_PLATFORM -DSIO_AEOI + +NT_UP=1 + +!IF $(ALPHA) + +TARGETTYPE=HAL + +!ELSE + +TARGETTYPE=DRIVER + +!ENDIF + +INCLUDES=..\alpha;..\..\..\inc;..\..\..\ke;..\..\..\io;..\..\..\fw\alpha;..\..\..\fastfat;..\..\halalpha + +SOURCES= + +ALPHA_SOURCES=..\hal.rc \ + ..\bushnd.c \ + ..\drivesup.c \ + ..\alpha\adjust.c \ + ..\alpha\allstart.c \ + ..\alpha\alphaio.s \ + ..\alpha\bios.c \ + ..\alpha\cache.c \ + ..\alpha\ebsgdma.c \ + ..\alpha\eeprom8k.c \ + ..\alpha\eisasup.c \ + ..\alpha\environ.c \ + ..\alpha\ev4cache.c \ + ..\alpha\ev4int.c \ + ..\alpha\ev4ints.s \ + ..\alpha\ev4mchk.c \ + ..\alpha\ev4mem.s \ + ..\alpha\ev4prof.c \ + ..\alpha\fwreturn.c \ + ..\alpha\haldebug.c \ + ..\alpha\halpal.s \ + ..\alpha\icic.c \ + ..\alpha\idle.s \ + ..\alpha\info.c \ + ..\alpha\inithal.c \ + ..\alpha\intsup.s \ + ..\alpha\iousage.c \ + ..\alpha\ioproc.c \ + ..\alpha\lyintsup.c \ + ..\alpha\memory.c \ + ..\alpha\pcisup.c \ + ..\alpha\pcrtc.c \ + ..\alpha\pcserial.c \ + ..\alpha\pcspeakr.c \ + ..\alpha\perf8254.c \ + ..\alpha\siintsup.c \ + ..\alpha\t2.c \ + ..\alpha\vga.c \ + ..\alpha\xiintsup.c \ + ..\alpha\addrsup.c \ + ..\alpha\busdata.c \ + ..\alpha\pcibus.c \ + ..\alpha\sableio.s \ + ..\alpha\sableerr.c \ + ..\alpha\sbinitnt.c \ + ..\alpha\sbintr.s \ + ..\alpha\sbintsup.c \ + ..\alpha\sbmapio.c \ + ..\alpha\sbsysint.c + +DLLDEF=obj\*\hal.def + +!IF $(ALPHA) + +NTTARGETFILES=$(TARGETPATH)\alpha\hal.lib \ + $(TARGETPATH)\alpha\hal.dll + +!ENDIF |