From e611b132f9b8abe35b362e5870b74bce94a1e58e Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 16 May 2020 20:51:50 -0700 Subject: initial commit --- private/ntos/nthals/hallego/alpha/addrsup.c | 590 +++++++++++ private/ntos/nthals/hallego/alpha/adjust.c | 7 + private/ntos/nthals/hallego/alpha/allstart.c | 7 + private/ntos/nthals/hallego/alpha/alphaio.s | 7 + private/ntos/nthals/hallego/alpha/apecs.c | 7 + private/ntos/nthals/hallego/alpha/apecserr.c | 7 + private/ntos/nthals/hallego/alpha/apecsio.s | 7 + private/ntos/nthals/hallego/alpha/bios.c | 7 + private/ntos/nthals/hallego/alpha/busdata.c | 129 +++ private/ntos/nthals/hallego/alpha/cache.c | 7 + private/ntos/nthals/hallego/alpha/chipset.h | 1 + private/ntos/nthals/hallego/alpha/cmos8k.c | 2 + private/ntos/nthals/hallego/alpha/ebsgdma.c | 7 + private/ntos/nthals/hallego/alpha/eisasup.c | 7 + private/ntos/nthals/hallego/alpha/ev4cache.c | 7 + private/ntos/nthals/hallego/alpha/ev4int.c | 7 + private/ntos/nthals/hallego/alpha/ev4ints.s | 6 + private/ntos/nthals/hallego/alpha/ev4mchk.c | 7 + private/ntos/nthals/hallego/alpha/ev4mem.s | 7 + private/ntos/nthals/hallego/alpha/ev4prof.c | 7 + private/ntos/nthals/hallego/alpha/fwreturn.c | 7 + private/ntos/nthals/hallego/alpha/haldebug.c | 7 + private/ntos/nthals/hallego/alpha/halpal.s | 7 + private/ntos/nthals/hallego/alpha/idle.s | 7 + private/ntos/nthals/hallego/alpha/info.c | 7 + private/ntos/nthals/hallego/alpha/inithal.c | 7 + private/ntos/nthals/hallego/alpha/intsup.s | 7 + private/ntos/nthals/hallego/alpha/ioproc.c | 74 ++ private/ntos/nthals/hallego/alpha/iousage.c | 647 ++++++++++++ private/ntos/nthals/hallego/alpha/iousage.h | 107 ++ private/ntos/nthals/hallego/alpha/legodef.h | 671 ++++++++++++ private/ntos/nthals/hallego/alpha/lginitnt.c | 1409 ++++++++++++++++++++++++++ private/ntos/nthals/hallego/alpha/lgintr.s | 121 +++ private/ntos/nthals/hallego/alpha/lgintsup.c | 732 +++++++++++++ private/ntos/nthals/hallego/alpha/lgmapio.c | 232 +++++ private/ntos/nthals/hallego/alpha/lgsysint.c | 679 +++++++++++++ private/ntos/nthals/hallego/alpha/machdep.h | 46 + private/ntos/nthals/hallego/alpha/memory.c | 7 + private/ntos/nthals/hallego/alpha/nvenv.c | 1 + private/ntos/nthals/hallego/alpha/nvram.c | 1 + private/ntos/nthals/hallego/alpha/pcd8584.c | 653 ++++++++++++ private/ntos/nthals/hallego/alpha/pcd8584.h | 196 ++++ private/ntos/nthals/hallego/alpha/pcf8574.c | 336 ++++++ private/ntos/nthals/hallego/alpha/pcf8574.h | 175 ++++ private/ntos/nthals/hallego/alpha/pcibus.c | 111 ++ private/ntos/nthals/hallego/alpha/pciir.c | 646 ++++++++++++ private/ntos/nthals/hallego/alpha/pcisio.c | 587 +++++++++++ private/ntos/nthals/hallego/alpha/pcisup.c | 7 + private/ntos/nthals/hallego/alpha/pcrtc.c | 7 + private/ntos/nthals/hallego/alpha/pcserial.c | 7 + private/ntos/nthals/hallego/alpha/pcspeakr.c | 7 + private/ntos/nthals/hallego/alpha/perfcntr.c | 7 + private/ntos/nthals/hallego/alpha/pintolin.h | 273 +++++ private/ntos/nthals/hallego/alpha/smerr.c | 390 +++++++ private/ntos/nthals/hallego/alpha/smir.c | 722 +++++++++++++ private/ntos/nthals/hallego/alpha/smsup.c | 363 +++++++ private/ntos/nthals/hallego/alpha/vga.c | 7 + private/ntos/nthals/hallego/bushnd.c | 7 + private/ntos/nthals/hallego/drivesup.c | 7 + private/ntos/nthals/hallego/hal.aps | 0 private/ntos/nthals/hallego/hal.rc | 11 + private/ntos/nthals/hallego/hal.src | 7 + private/ntos/nthals/hallego/makefile | 6 + private/ntos/nthals/hallego/makefile.inc | 5 + private/ntos/nthals/hallego/sources | 111 ++ 65 files changed, 10257 insertions(+) create mode 100644 private/ntos/nthals/hallego/alpha/addrsup.c create mode 100644 private/ntos/nthals/hallego/alpha/adjust.c create mode 100644 private/ntos/nthals/hallego/alpha/allstart.c create mode 100644 private/ntos/nthals/hallego/alpha/alphaio.s create mode 100644 private/ntos/nthals/hallego/alpha/apecs.c create mode 100644 private/ntos/nthals/hallego/alpha/apecserr.c create mode 100644 private/ntos/nthals/hallego/alpha/apecsio.s create mode 100644 private/ntos/nthals/hallego/alpha/bios.c create mode 100644 private/ntos/nthals/hallego/alpha/busdata.c create mode 100644 private/ntos/nthals/hallego/alpha/cache.c create mode 100644 private/ntos/nthals/hallego/alpha/chipset.h create mode 100644 private/ntos/nthals/hallego/alpha/cmos8k.c create mode 100644 private/ntos/nthals/hallego/alpha/ebsgdma.c create mode 100644 private/ntos/nthals/hallego/alpha/eisasup.c create mode 100644 private/ntos/nthals/hallego/alpha/ev4cache.c create mode 100644 private/ntos/nthals/hallego/alpha/ev4int.c create mode 100644 private/ntos/nthals/hallego/alpha/ev4ints.s create mode 100644 private/ntos/nthals/hallego/alpha/ev4mchk.c create mode 100644 private/ntos/nthals/hallego/alpha/ev4mem.s create mode 100644 private/ntos/nthals/hallego/alpha/ev4prof.c create mode 100644 private/ntos/nthals/hallego/alpha/fwreturn.c create mode 100644 private/ntos/nthals/hallego/alpha/haldebug.c create mode 100644 private/ntos/nthals/hallego/alpha/halpal.s create mode 100644 private/ntos/nthals/hallego/alpha/idle.s create mode 100644 private/ntos/nthals/hallego/alpha/info.c create mode 100644 private/ntos/nthals/hallego/alpha/inithal.c create mode 100644 private/ntos/nthals/hallego/alpha/intsup.s create mode 100644 private/ntos/nthals/hallego/alpha/ioproc.c create mode 100644 private/ntos/nthals/hallego/alpha/iousage.c create mode 100644 private/ntos/nthals/hallego/alpha/iousage.h create mode 100644 private/ntos/nthals/hallego/alpha/legodef.h create mode 100644 private/ntos/nthals/hallego/alpha/lginitnt.c create mode 100644 private/ntos/nthals/hallego/alpha/lgintr.s create mode 100644 private/ntos/nthals/hallego/alpha/lgintsup.c create mode 100644 private/ntos/nthals/hallego/alpha/lgmapio.c create mode 100644 private/ntos/nthals/hallego/alpha/lgsysint.c create mode 100644 private/ntos/nthals/hallego/alpha/machdep.h create mode 100644 private/ntos/nthals/hallego/alpha/memory.c create mode 100644 private/ntos/nthals/hallego/alpha/nvenv.c create mode 100644 private/ntos/nthals/hallego/alpha/nvram.c create mode 100644 private/ntos/nthals/hallego/alpha/pcd8584.c create mode 100644 private/ntos/nthals/hallego/alpha/pcd8584.h create mode 100644 private/ntos/nthals/hallego/alpha/pcf8574.c create mode 100644 private/ntos/nthals/hallego/alpha/pcf8574.h create mode 100644 private/ntos/nthals/hallego/alpha/pcibus.c create mode 100644 private/ntos/nthals/hallego/alpha/pciir.c create mode 100644 private/ntos/nthals/hallego/alpha/pcisio.c create mode 100644 private/ntos/nthals/hallego/alpha/pcisup.c create mode 100644 private/ntos/nthals/hallego/alpha/pcrtc.c create mode 100644 private/ntos/nthals/hallego/alpha/pcserial.c create mode 100644 private/ntos/nthals/hallego/alpha/pcspeakr.c create mode 100644 private/ntos/nthals/hallego/alpha/perfcntr.c create mode 100644 private/ntos/nthals/hallego/alpha/pintolin.h create mode 100644 private/ntos/nthals/hallego/alpha/smerr.c create mode 100644 private/ntos/nthals/hallego/alpha/smir.c create mode 100644 private/ntos/nthals/hallego/alpha/smsup.c create mode 100644 private/ntos/nthals/hallego/alpha/vga.c create mode 100644 private/ntos/nthals/hallego/bushnd.c create mode 100644 private/ntos/nthals/hallego/drivesup.c create mode 100644 private/ntos/nthals/hallego/hal.aps create mode 100644 private/ntos/nthals/hallego/hal.rc create mode 100644 private/ntos/nthals/hallego/hal.src create mode 100644 private/ntos/nthals/hallego/makefile create mode 100644 private/ntos/nthals/hallego/makefile.inc create mode 100644 private/ntos/nthals/hallego/sources (limited to 'private/ntos/nthals/hallego') diff --git a/private/ntos/nthals/hallego/alpha/addrsup.c b/private/ntos/nthals/hallego/alpha/addrsup.c new file mode 100644 index 000000000..2a7deb1f6 --- /dev/null +++ b/private/ntos/nthals/hallego/alpha/addrsup.c @@ -0,0 +1,590 @@ +/*++ + +Copyright (c) 1993 Digital Equipment Corporation + +Module Name: + + addrsup.c + +Abstract: + + This module contains the platform dependent code to create bus addreses + and QVAs for the Avanti system. + +Author: + + Joe Notarangelo 22-Oct-1993 + +Environment: + + Kernel mode + +Revision History: + + Eric Rehm (Digital) 03-Jan-1994 + Added PCIBus(0) and dense space support to all routines. + + Gene Morgan (Digital) 11-Oct-1995 + Initial LEGO version -- adapted from Avanti + +--*/ + +#include "halp.h" +#include "eisa.h" +#include "legodef.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 BUSHANDLER for the target configuration space + Supplies the bus handler (bus no, interface type). + + RootHandler - Registered BUSHANDLER 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 = BusHandler->BusNumber; + + PVOID va = 0; // note, this is used for a placeholder + + // + // The only buses available on Avanti are an ISA 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) { + + // + // Not on this system return nothing. + // + + *AddressSpace = 0; + TranslatedAddress->LowPart = 0; + return(FALSE); + } + + // + // 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 Isa: { + + // + // Can't go above 16MB (24 Bits) for Isa Buses + // + if( BusAddress.LowPart >= __16MB ){ + + *AddressSpace = 0; + TranslatedAddress->LowPart = 0; + return(FALSE); + + } + + break; + + } // case Isa + + case PCIBus: { + + if ( BusAddress.LowPart > PCI_MAX_DENSE_MEMORY_ADDRESS ) { + + // + // Unsupported dense PCI bus address. + // +#if HALDBG + DbgPrint ("Unsupported PCI address %x:%x\n", + BusAddress.HighPart, + BusAddress.LowPart); +#endif + *AddressSpace = 0; + TranslatedAddress->LowPart = 0; + return(FALSE); + } + else if( BusAddress.LowPart >= PCI_MIN_DENSE_MEMORY_ADDRESS && + BusAddress.LowPart <= PCI_MAX_DENSE_MEMORY_ADDRESS ) { + +#if HALDBG + DbgPrint ("Translating PCI kernel dense address %x:%x\n", + BusAddress.HighPart, + BusAddress.LowPart); +#endif + // + // Bus Address is in dense PCI memory space + // + + // + // QVA, as such, is simply the PCI bus address + // + + TranslatedAddress->LowPart = BusAddress.LowPart; + + // + // clear high longword for QVA + // + + TranslatedAddress->HighPart = 0; + + // + // dont let the user call MmMapIoSpace + // + + *AddressSpace = 1; + + return (TRUE); + + + } + + // + // Bus Address is in sparse PCI memory space + // + + +#if HALDBG + DbgPrint ("Translating PCI kernel sparse address %x:%x\n", + BusAddress.HighPart, + BusAddress.LowPart); +#endif + + break; + } // case PCIBus + + case Eisa: { + break; + } // case Eisa + + } // switch( InterfaceType ) + + // + // Start with the base physical address and add the + // bus address by converting it to the physical address. + // + + TranslatedAddress->QuadPart = APECS_PCI_MEMORY_BASE_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); + + } // case BusMemory + + + case BusIo: { + + // + // The address is in PCI I/O space, kernel mode. + // + + switch( InterfaceType ) { + + case Isa: { + // + // Can't go above 64KB (16 Bits) for Isa Buses + // + if( BusAddress.LowPart >= __64K ){ + + *AddressSpace = 0; + TranslatedAddress->LowPart = 0; + return(FALSE); + + } + break; + } // case Isa + + case PCIBus: { + + // + // PCI IO space is always below 16MB (24 Bits) BusAddress + // If the address cannot be mapped, just return FALSE. + // + // IMPORTANT: For now we have set HAXR2 to 0(see ebinitnt.c) + // + if( BusAddress.LowPart >= __16MB ){ + + *AddressSpace = 0; + TranslatedAddress->LowPart = 0; + return(FALSE); + + } + // + // if the BusAddress.LowPart is > 64K then we use the HAXR2 + // register. + // + break; + } // case PCIBus + + case Eisa: { + break; + } // case Eisa + + } // switch( InterfaceType ) + + + // + // Start with the base physical address and add the + // bus address by converting it to the physical address. + // + + TranslatedAddress->QuadPart = APECS_PCI_IO_BASE_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; // clear high longword for QVA + + *AddressSpace = 1; // Make sure user doesn't call + // MmMapIoSpace. + + return(TRUE); + + } // 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. + // + + TranslatedAddress->QuadPart = APECS_PCI_MEMORY_BASE_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. + // + + TranslatedAddress->QuadPart = APECS_PCI_IO_BASE_PHYSICAL; + TranslatedAddress->QuadPart += ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT); + + *AddressSpace = 0; // Make sure user can call + // MmMapIoSpace. + + return(TRUE); + + } + + + case KernelPciDenseMemory: + case UserPciDenseMemory: + { + + // + // The address is in PCI memory space, user mode. + // Note that ISA and EISA buses can also request this space + // + + // + // Start with the base physical address and add the + // bus address by converting it to the physical address. + // + + TranslatedAddress->QuadPart = APECS_PCI_DENSE_BASE_PHYSICAL; + TranslatedAddress->QuadPart += BusAddress.LowPart; + + *AddressSpace = 0; // Let the user call MmMapIoSpace + + return(TRUE); + + } + + default: { + + // + // Unsupported address space. + + *AddressSpace = 0; + TranslatedAddress->LowPart = 0; + return(FALSE); + + } + + + } +} + +PVOID +HalCreateQva( + IN PHYSICAL_ADDRESS PA, + IN PVOID VA + ) + +/*++ + +Routine Description: + + This function is called two ways. First, from HalTranslateBusAddress, + if the caller is going to run in kernel mode and use superpages. + The second way is if the user is going to access in user mode. + MmMapIoSpace or ZwViewMapOfSection will call this. + + If the input parameter VA is zero, then we assume super page and build + a QUASI virtual address that is only usable by calling the hal I/O + access routines. + + if the input parameter VA is non-zero, we assume the user has either + called MmMapIoSpace or ZwMapViewOfSection and will use the user mode + access macros. + + If the PA is not a sparse I/O space address (PCI I/O, PCI Memory), + then return the VA as the QVA. + +Arguments: + + PA - the physical address generated by HalTranslateBusAddress + + VA - the virtual address returned by MmMapIoSpace + +Return Value: + + The returned value is a quasi virtual address in that it can be + added to and subtracted from, but it cannot be used to access the + bus directly. The top bits are set so that we can trap invalid + accesses in the memory management subsystem. All access should be + done through the Hal Access Routines in *ioacc.s if it was a superpage + kernel mode access. If it is usermode, then the user mode access + macros must be used. + +--*/ +{ + + PVOID qva; + + if( (PA.QuadPart >= APECS_COMANCHE_BASE_PHYSICAL) + && (PA.QuadPart < APECS_PCI_DENSE_BASE_PHYSICAL) + ) + { + + // + // 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); + } + + // + // It is not a sparse 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 Lego we have only bus types: + // + // Isa + // PCIBus + // + // We will allow Eisa as an alias for Isa. All other values not named + // above will be considered bogus. + // + + switch (InterfaceType ){ + + case Isa: + case Eisa: + case PCIBus: + + // + // Support dense space: check to see if it's really + // a sparse space QVA. + // + + if ( ((ULONG) Qva & QVA_SELECTORS) == QVA_ENABLE ) + { + return( (PVOID)( (ULONG)Qva << IO_BIT_SHIFT ) ); + } + else + { + return (Qva); + } + break; + + + default: + + return NULL; + + } + + +} diff --git a/private/ntos/nthals/hallego/alpha/adjust.c b/private/ntos/nthals/hallego/alpha/adjust.c new file mode 100644 index 000000000..47c267fb8 --- /dev/null +++ b/private/ntos/nthals/hallego/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/hallego/alpha/allstart.c b/private/ntos/nthals/hallego/alpha/allstart.c new file mode 100644 index 000000000..42f70b7ca --- /dev/null +++ b/private/ntos/nthals/hallego/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/hallego/alpha/alphaio.s b/private/ntos/nthals/hallego/alpha/alphaio.s new file mode 100644 index 000000000..d2fe61a53 --- /dev/null +++ b/private/ntos/nthals/hallego/alpha/alphaio.s @@ -0,0 +1,7 @@ +// +// This file simply includes the source file from the common Alpha +// HAL directory. +// + +#include "..\halalpha\alphaio.s" + diff --git a/private/ntos/nthals/hallego/alpha/apecs.c b/private/ntos/nthals/hallego/alpha/apecs.c new file mode 100644 index 000000000..06eb91348 --- /dev/null +++ b/private/ntos/nthals/hallego/alpha/apecs.c @@ -0,0 +1,7 @@ +// +// This file simply includes the source file from the common Alpha +// HAL directory. +// + +#include "..\halalpha\apecs.c" + diff --git a/private/ntos/nthals/hallego/alpha/apecserr.c b/private/ntos/nthals/hallego/alpha/apecserr.c new file mode 100644 index 000000000..441154cc9 --- /dev/null +++ b/private/ntos/nthals/hallego/alpha/apecserr.c @@ -0,0 +1,7 @@ +// +// This file simply includes the source file from the common Alpha +// HAL directory. +// + +#include "..\halalpha\apecserr.c" + diff --git a/private/ntos/nthals/hallego/alpha/apecsio.s b/private/ntos/nthals/hallego/alpha/apecsio.s new file mode 100644 index 000000000..27bb7caa7 --- /dev/null +++ b/private/ntos/nthals/hallego/alpha/apecsio.s @@ -0,0 +1,7 @@ +// +// This file simply includes the source file from the common Alpha +// HAL directory. +// + +#include "..\halalpha\apecsio.s" + diff --git a/private/ntos/nthals/hallego/alpha/bios.c b/private/ntos/nthals/hallego/alpha/bios.c new file mode 100644 index 000000000..3a9d3aa50 --- /dev/null +++ b/private/ntos/nthals/hallego/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/hallego/alpha/busdata.c b/private/ntos/nthals/hallego/alpha/busdata.c new file mode 100644 index 000000000..b04915a0e --- /dev/null +++ b/private/ntos/nthals/hallego/alpha/busdata.c @@ -0,0 +1,129 @@ +/*++ + + +Copyright (c) 1989 Microsoft Corporation +Copyright (c) 1994 Digital Equipment 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: + + Gene Morgan [Digital] 11-Oct-1995 + + Initial version for Lego. Adapted from Avanti. + + +--*/ + +#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 bus #0 + // + + HaliRegisterBusHandler (Isa, // Bus Type + -1, // No config space + 0, // Internal bus #0 + Internal, // Parent bus type + 0, // Parent bus number + 0, // No extension data + NULL, // No install handler + &Bus); // Bushandler return + + Bus->GetBusData = HalpNoBusData; + Bus->AdjustResourceList = HalpAdjustIsaResourceList; + +} diff --git a/private/ntos/nthals/hallego/alpha/cache.c b/private/ntos/nthals/hallego/alpha/cache.c new file mode 100644 index 000000000..561528477 --- /dev/null +++ b/private/ntos/nthals/hallego/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/hallego/alpha/chipset.h b/private/ntos/nthals/hallego/alpha/chipset.h new file mode 100644 index 000000000..0a72ef8cb --- /dev/null +++ b/private/ntos/nthals/hallego/alpha/chipset.h @@ -0,0 +1 @@ +#include "apecs.h" diff --git a/private/ntos/nthals/hallego/alpha/cmos8k.c b/private/ntos/nthals/hallego/alpha/cmos8k.c new file mode 100644 index 000000000..483709b57 --- /dev/null +++ b/private/ntos/nthals/hallego/alpha/cmos8k.c @@ -0,0 +1,2 @@ +#include "..\halalpha\cmos8k.c" + diff --git a/private/ntos/nthals/hallego/alpha/ebsgdma.c b/private/ntos/nthals/hallego/alpha/ebsgdma.c new file mode 100644 index 000000000..f2f033fad --- /dev/null +++ b/private/ntos/nthals/hallego/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/hallego/alpha/eisasup.c b/private/ntos/nthals/hallego/alpha/eisasup.c new file mode 100644 index 000000000..0d46ef3e4 --- /dev/null +++ b/private/ntos/nthals/hallego/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/hallego/alpha/ev4cache.c b/private/ntos/nthals/hallego/alpha/ev4cache.c new file mode 100644 index 000000000..b0cf9e3be --- /dev/null +++ b/private/ntos/nthals/hallego/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/hallego/alpha/ev4int.c b/private/ntos/nthals/hallego/alpha/ev4int.c new file mode 100644 index 000000000..8a10705d7 --- /dev/null +++ b/private/ntos/nthals/hallego/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/hallego/alpha/ev4ints.s b/private/ntos/nthals/hallego/alpha/ev4ints.s new file mode 100644 index 000000000..6df823ab6 --- /dev/null +++ b/private/ntos/nthals/hallego/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/hallego/alpha/ev4mchk.c b/private/ntos/nthals/hallego/alpha/ev4mchk.c new file mode 100644 index 000000000..697087c15 --- /dev/null +++ b/private/ntos/nthals/hallego/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/hallego/alpha/ev4mem.s b/private/ntos/nthals/hallego/alpha/ev4mem.s new file mode 100644 index 000000000..f410d09a3 --- /dev/null +++ b/private/ntos/nthals/hallego/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/hallego/alpha/ev4prof.c b/private/ntos/nthals/hallego/alpha/ev4prof.c new file mode 100644 index 000000000..7ecdfa8b7 --- /dev/null +++ b/private/ntos/nthals/hallego/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/hallego/alpha/fwreturn.c b/private/ntos/nthals/hallego/alpha/fwreturn.c new file mode 100644 index 000000000..65ae88cb8 --- /dev/null +++ b/private/ntos/nthals/hallego/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/hallego/alpha/haldebug.c b/private/ntos/nthals/hallego/alpha/haldebug.c new file mode 100644 index 000000000..ce91863ec --- /dev/null +++ b/private/ntos/nthals/hallego/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/hallego/alpha/halpal.s b/private/ntos/nthals/hallego/alpha/halpal.s new file mode 100644 index 000000000..fc89f8370 --- /dev/null +++ b/private/ntos/nthals/hallego/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/hallego/alpha/idle.s b/private/ntos/nthals/hallego/alpha/idle.s new file mode 100644 index 000000000..f517bab2f --- /dev/null +++ b/private/ntos/nthals/hallego/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/hallego/alpha/info.c b/private/ntos/nthals/hallego/alpha/info.c new file mode 100644 index 000000000..22aef63a3 --- /dev/null +++ b/private/ntos/nthals/hallego/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/hallego/alpha/inithal.c b/private/ntos/nthals/hallego/alpha/inithal.c new file mode 100644 index 000000000..a99cb9a1a --- /dev/null +++ b/private/ntos/nthals/hallego/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/hallego/alpha/intsup.s b/private/ntos/nthals/hallego/alpha/intsup.s new file mode 100644 index 000000000..a7d9f8f4f --- /dev/null +++ b/private/ntos/nthals/hallego/alpha/intsup.s @@ -0,0 +1,7 @@ +// +// This file simply includes the source file from the common Alpha +// HAL directory. +// +#include "pcrtc.h" +#include "..\halalpha\intsup.s" + diff --git a/private/ntos/nthals/hallego/alpha/ioproc.c b/private/ntos/nthals/hallego/alpha/ioproc.c new file mode 100644 index 000000000..14af7ad42 --- /dev/null +++ b/private/ntos/nthals/hallego/alpha/ioproc.c @@ -0,0 +1,74 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + ioproc.c + +Abstract: + + Stub functions for UP hals. + +Author: + + Ken Reneris (kenr) 22-Jan-1991 + +Environment: + + Kernel mode only. + +Revision History: + + Added to Avanti Hals (Sameer Dekate) 04-May-1994 + +--*/ + +#include "halp.h" +#include "iousage.h" + +UCHAR HalName[] = "Alpha Compatible PCI/Eisa/Isa HAL"; + +BOOLEAN +HalpInitMP ( + IN ULONG Phase, + IN PLOADER_PARAMETER_BLOCK LoaderBlock + ); + +VOID HalpInitializePciBuses (VOID); +VOID HalpInitOtherBuses (VOID); + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(INIT,HalpInitMP) +#pragma alloc_text(INIT,HalpInitOtherBuses) +#endif + + + +BOOLEAN +HalpInitMP ( + IN ULONG Phase, + IN PLOADER_PARAMETER_BLOCK LoaderBlock + ) +{ + return TRUE; + // do nothing +} + + +VOID +HalpResetAllProcessors ( + VOID + ) +{ + // Just return, that will invoke the standard PC reboot code +} + + +VOID +HalpInitOtherBuses ( + VOID + ) +{ + // no other internal buses supported +} diff --git a/private/ntos/nthals/hallego/alpha/iousage.c b/private/ntos/nthals/hallego/alpha/iousage.c new file mode 100644 index 000000000..6ac8f6f4e --- /dev/null +++ b/private/ntos/nthals/hallego/alpha/iousage.c @@ -0,0 +1,647 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + iousage.c + +Abstract: + +Author: + + Ken Reneris (kenr) + +Environment: + + Kernel mode only. + +Revision History: + + Chao Chen 1-25-1995 + +--*/ + +#include "halp.h" +#include "iousage.h" + +// +// Externals. +// + +extern KAFFINITY HalpActiveProcessors; + +// +// Private resource list. +// + +static PBUS_USAGE HalpBusUsageList = NULL; +static PRESOURCE_USAGE HalpResourceUsageList = NULL; + +// +// Default HAL name. +// + +#define MAX_NAME_LENGTH 256 +UCHAR HalRegisteredName[MAX_NAME_LENGTH] = "Alpha Compatible PCI/EISA/ISA HAL"; + +// +// Function prototype. +// + +VOID +HalpReportResourceUsage ( + IN PUNICODE_STRING HalName + ); + +VOID +HalpGetResourceSortValue ( + IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc, + OUT PULONG sortscale, + OUT PLARGE_INTEGER sortvalue + ); + +// +// Pragma stuff. +// + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(INIT,HalpRegisterHalName) +#pragma alloc_text(INIT,HalpRegisterBusUsage) +#pragma alloc_text(INIT,HalpRegisterResourceUsage) +#pragma alloc_text(INIT,HalReportResourceUsage) +#pragma alloc_text(INIT,HalpReportResourceUsage) +#pragma alloc_text(INIT,HalpGetResourceSortValue) +#endif + +// +// Function definitions. +// + + +VOID +HalpRegisterHalName( + IN PUCHAR NewHalName + ) +/*++ + +Routine Description: + + Allow the HAL to register a name string. + +Arguments: + + HalName - Supplies a pointer to the HAL name to register. + +Return Value: + + None. + +--*/ +{ + + strncpy( HalRegisteredName, NewHalName, MAX_NAME_LENGTH ); + return; +} + + + +VOID +HalpRegisterBusUsage ( + IN INTERFACE_TYPE BusType + ) +/*++ + +Routine Description: + + Register the different bus types in the system. + +Arguments: + + BusType - bus type that requires registering. + +Return Value: + + None. + +--*/ +{ + PBUS_USAGE Temp; + + // + // Allocate the buffer to store the bus information. + // + + Temp = (PBUS_USAGE)ExAllocatePool(NonPagedPool, sizeof(BUS_USAGE)); + + // + // Save the bus type. + // + + Temp->BusType = BusType; + + // + // Add the bus type to the head of the list. + // + + Temp->Next = HalpBusUsageList; + HalpBusUsageList = Temp; +} + + + +VOID +HalpRegisterResourceUsage ( + IN PRESOURCE_USAGE Resource + ) +/*++ + +Routine Description: + + Register the resources used internally by the HAL to the I/O system. + +Arguments: + + Resource - resource that requires registering. + +Return Value: + + None. + +--*/ +{ + PRESOURCE_USAGE Temp; + + // + // Allocate the buffer to store the resource information. + // + + Temp = (PRESOURCE_USAGE)ExAllocatePool(NonPagedPool, sizeof(RESOURCE_USAGE)); + + // + // Copy the resource to the buffer we allocated. + // + + RtlCopyMemory(Temp, Resource, sizeof(RESOURCE_USAGE)); + + // + // Add the resource to the head of the resource list. + // + + Temp->Next = HalpResourceUsageList; + HalpResourceUsageList = Temp; +} + + + +VOID +HalReportResourceUsage ( + VOID + ) +/*++ + +Routine Description: + + Report the resources used internally by the HAL to the I/O system. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + ANSI_STRING AHalName; + UNICODE_STRING UHalName; + + // + // Convert the string. + // + + RtlInitAnsiString (&AHalName, HalRegisteredName); + RtlAnsiStringToUnicodeString (&UHalName, &AHalName, TRUE); + + // + // Report the resources registered as in use by the HAL. + // + + HalpReportResourceUsage(&UHalName); + + RtlFreeUnicodeString(&UHalName); +} + + + +VOID +HalpGetResourceSortValue ( + IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc, + OUT PULONG sortscale, + OUT PLARGE_INTEGER sortvalue + ) +/*++ + +Routine Description: + + Used by HalpReportResourceUsage in order to properly sort + partial_resource_descriptors. + +Arguments: + + pRCurLoc - resource descriptor + +Return Value: + + sortscale - scaling of resource descriptor for sorting + sortvalue - value to sort on + + +--*/ +{ + + switch (pRCurLoc->Type) { + case CmResourceTypeInterrupt: + *sortscale = 0; + sortvalue->QuadPart = pRCurLoc->u.Interrupt.Level; + break; + + case CmResourceTypePort: + *sortscale = 1; + *sortvalue = pRCurLoc->u.Port.Start; + break; + + case CmResourceTypeMemory: + *sortscale = 2; + *sortvalue = pRCurLoc->u.Memory.Start; + break; + + case CmResourceTypeDma: + *sortscale = 3; + sortvalue->QuadPart = pRCurLoc->u.Dma.Channel; + break; + + default: + *sortscale = 4; + sortvalue->QuadPart = 0; + break; + } +} + + + +VOID +HalpReportResourceUsage ( + IN PUNICODE_STRING HalName + ) +/*++ + +Routine Description: + + This routine registers the resources for the hal. + +Arguments: + + HalName - the name of the hal to be registered. + +Return Value: + + None. + +--*/ +{ + PCM_RESOURCE_LIST RawResourceList, TranslatedResourceList; + PCM_FULL_RESOURCE_DESCRIPTOR pRFullDesc, pTFullDesc; + PCM_PARTIAL_RESOURCE_LIST pRPartList, pTPartList; + PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc, pTCurLoc; + PCM_PARTIAL_RESOURCE_DESCRIPTOR pRSortLoc, pTSortLoc; + CM_PARTIAL_RESOURCE_DESCRIPTOR RPartialDesc, TPartialDesc; + ULONG i, j, k, ListSize, Count; + ULONG curscale, sortscale; + LARGE_INTEGER curvalue, sortvalue; + PHYSICAL_ADDRESS PhyAddress; + PBUS_USAGE CurrentBus; + PRESOURCE_USAGE CurrentResource; + + // + // Allocate some space to build the resource structure. + // + + RawResourceList= + (PCM_RESOURCE_LIST)ExAllocatePool(NonPagedPool, PAGE_SIZE*2); + TranslatedResourceList= + (PCM_RESOURCE_LIST)ExAllocatePool(NonPagedPool, PAGE_SIZE*2); + + // + // This functions assumes unset fields are zero. + // + + RtlZeroMemory (RawResourceList, PAGE_SIZE*2); + RtlZeroMemory (TranslatedResourceList, PAGE_SIZE*2); + + // + // Initialize the lists + // + + RawResourceList->List[0].InterfaceType = (INTERFACE_TYPE) -1; + pRFullDesc = RawResourceList->List; + pRCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) RawResourceList->List; + pTCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) TranslatedResourceList->List; + + // + // Report all the HAL resources. + // + + CurrentBus = HalpBusUsageList; + + while (CurrentBus) { + + // + // Start at the head of the resource list for each bus type. + // + + CurrentResource = HalpResourceUsageList; + + while (CurrentResource) { + + // + // Register the resources for a particular bus. + // + + if (CurrentBus->BusType == CurrentResource->BusType) { + + switch (CurrentResource->ResourceType) { + + case CmResourceTypeInterrupt: + + // + // Process interrupt resources. + // + + RPartialDesc.Type = CmResourceTypeInterrupt; + RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive; + + if (CurrentResource->u.InterruptMode == Latched) + RPartialDesc.Flags = CM_RESOURCE_INTERRUPT_LATCHED; + else + RPartialDesc.Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE; + + RPartialDesc.u.Interrupt.Vector = + CurrentResource->u.BusInterruptVector; + RPartialDesc.u.Interrupt.Level = + CurrentResource->u.BusInterruptVector; + RPartialDesc.u.Interrupt.Affinity = HalpActiveProcessors; + + RtlCopyMemory(&TPartialDesc, &RPartialDesc, sizeof(TPartialDesc)); + TPartialDesc.u.Interrupt.Vector = + CurrentResource->u.SystemInterruptVector; + TPartialDesc.u.Interrupt.Level = + CurrentResource->u.SystemIrql; + + break; + + case CmResourceTypePort: + case CmResourceTypeMemory: + + // + // Process port and memory resources. + // + + RPartialDesc.Type = CurrentResource->ResourceType; + RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive; + + if (RPartialDesc.Type == CmResourceTypePort) { + + // + // In IO space. + // + + i = 1; + RPartialDesc.Flags = CM_RESOURCE_PORT_IO; + + } else { + + // + // In memory space. + // + + i = 0; + RPartialDesc.Flags = CM_RESOURCE_MEMORY_READ_WRITE; + } + + // + // Notice: assume u.Memory and u.Port have the same layout. + // + + RPartialDesc.u.Memory.Start.HighPart = 0; + RPartialDesc.u.Memory.Start.LowPart = CurrentResource->u.Start; + RPartialDesc.u.Memory.Length = CurrentResource->u.Length; + + RtlCopyMemory(&TPartialDesc, &RPartialDesc, sizeof(TPartialDesc)); + + // + // Translate the address. + // + + HalTranslateBusAddress(CurrentResource->BusType, + CurrentResource->BusNumber, + RPartialDesc.u.Memory.Start, + &i, + &PhyAddress ); + + TPartialDesc.u.Memory.Start = PhyAddress; + + if ((RPartialDesc.Type == CmResourceTypePort) && (i == 0)) + TPartialDesc.Flags = CM_RESOURCE_PORT_MEMORY; + + break; + + case CmResourceTypeDma: + + // + // Process dma resources. + // + + RPartialDesc.Type = CmResourceTypeDma; + RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive; + + RPartialDesc.u.Dma.Channel = CurrentResource->u.DmaChannel; + RPartialDesc.u.Dma.Port = CurrentResource->u.DmaPort; + + RtlCopyMemory(&TPartialDesc, &RPartialDesc, sizeof(TPartialDesc)); + TPartialDesc.u.Dma.Channel = CurrentResource->u.DmaChannel; + TPartialDesc.u.Dma.Port = CurrentResource->u.DmaPort; + + break; + + default: + + // + // Got a resource we don't know. Bail out! + // + + goto NextResource; + } + + // + // Include the current resource in the HAL list. + // + + if (pRFullDesc->InterfaceType != CurrentBus->BusType) { + + // + // Interface type changed, add another full section + // + + RawResourceList->Count++; + TranslatedResourceList->Count++; + + pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR)pRCurLoc; + pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR)pTCurLoc; + + pRFullDesc->InterfaceType = CurrentBus->BusType; + pTFullDesc->InterfaceType = CurrentBus->BusType; + + pRPartList = &pRFullDesc->PartialResourceList; + pTPartList = &pTFullDesc->PartialResourceList; + + // + // Bump current location pointers up + // + + pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors; + pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors; + } + + // + // Add current resource in. + // + + pRPartList->Count++; + pTPartList->Count++; + RtlCopyMemory(pRCurLoc, &RPartialDesc, sizeof(RPartialDesc)); + RtlCopyMemory(pTCurLoc, &TPartialDesc, sizeof(TPartialDesc)); + + pRCurLoc++; + pTCurLoc++; + } + + // + // Finished with this resource, move to the next one. + // + + NextResource: + CurrentResource = CurrentResource->Next; + } + + // + // Finished with this bus, move to the next one. + // + + CurrentBus = CurrentBus->Next; + } + + // + // Do the actual reporting. + // + + ListSize = (ULONG)(((PUCHAR)pRCurLoc) - ((PUCHAR)RawResourceList)); + + // + // The HAL's resource usage structures have been built + // Sort the partial lists based on the Raw resource values. + // + + pRFullDesc = RawResourceList->List; + pTFullDesc = TranslatedResourceList->List; + + for (i=0; i < RawResourceList->Count; i++) { + + pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors; + pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors; + Count = pRFullDesc->PartialResourceList.Count; + + for (j=0; j < Count; j++) { + HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue); + + pRSortLoc = pRCurLoc; + pTSortLoc = pTCurLoc; + + for (k=j; k < Count; k++) { + HalpGetResourceSortValue (pRSortLoc, &sortscale, &sortvalue); + + if (sortscale < curscale || + (sortscale == curscale && + (sortvalue.QuadPart < curvalue.QuadPart)) ){ + + // + // Swap the elements. + // + + RtlCopyMemory (&RPartialDesc, pRCurLoc, sizeof RPartialDesc); + RtlCopyMemory (pRCurLoc, pRSortLoc, sizeof RPartialDesc); + RtlCopyMemory (pRSortLoc, &RPartialDesc, sizeof RPartialDesc); + + // + // Swap translated descriptor as well. + // + + RtlCopyMemory (&TPartialDesc, pTCurLoc, sizeof TPartialDesc); + RtlCopyMemory (pTCurLoc, pTSortLoc, sizeof TPartialDesc); + RtlCopyMemory (pTSortLoc, &TPartialDesc, sizeof TPartialDesc); + + // + // Get new curscale & curvalue. + // + + HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue); + } + + pRSortLoc++; + pTSortLoc++; + } + + pRCurLoc++; + pTCurLoc++; + } + + pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc; + pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc; + } + + // + // Inform the IO system of our resources. + // + + IoReportHalResourceUsage(HalName, + RawResourceList, + TranslatedResourceList, + ListSize); + + ExFreePool (RawResourceList); + ExFreePool (TranslatedResourceList); + + // + // Free all registered buses. + // + + while (HalpBusUsageList) { + + CurrentBus = HalpBusUsageList; + HalpBusUsageList = HalpBusUsageList->Next; + ExFreePool(CurrentBus); + } + + // + // Free all registered resources. + // + + while (HalpResourceUsageList) { + + CurrentResource = HalpResourceUsageList; + HalpResourceUsageList = HalpResourceUsageList->Next; + ExFreePool(CurrentResource); + } +} + diff --git a/private/ntos/nthals/hallego/alpha/iousage.h b/private/ntos/nthals/hallego/alpha/iousage.h new file mode 100644 index 000000000..b54cd179a --- /dev/null +++ b/private/ntos/nthals/hallego/alpha/iousage.h @@ -0,0 +1,107 @@ +/*++ + +Copyright (c) 1993-1995 Microsoft Corporation +Copyright (c) 1993-1995 Digital Equipment Corporation + +Module Name: + + iousage.h + +Abstract: + + This header file defines the iousage definitions + +Author: + + Sameer Dekate 5-3-1994 + + +Revision History: + + Chao Chen 1-25-1995 + +--*/ + +// +// Resource usage information +// + +// +// Bus usage information. +// + +typedef struct _HalBusUsage{ + INTERFACE_TYPE BusType; + struct _HalBusUsage *Next; +} BUS_USAGE, *PBUS_USAGE; + +// +// Address usage information. +// + +typedef struct _HalResourceUsage { + + // + // Common elements. + // + + INTERFACE_TYPE BusType; + ULONG BusNumber; + CM_RESOURCE_TYPE ResourceType; + struct _HalResourceUsage *Next; + + // + // Resource type specific. + // + + union { + + // + // Address usage. + // + + struct { + ULONG Start; + ULONG Length; + }; + + // + // Vector type specific. + // + + struct { + KINTERRUPT_MODE InterruptMode; + ULONG BusInterruptVector; + ULONG SystemInterruptVector; + KIRQL SystemIrql; + }; + + // + // Dma type specific. + // + + struct { + ULONG DmaChannel; + ULONG DmaPort; + }; + } u; +} RESOURCE_USAGE, *PRESOURCE_USAGE; + +// +// Functions to report HAL's resource usage. +// + +VOID +HalpRegisterHalName( + IN PUCHAR HalName + ); + +VOID +HalpRegisterBusUsage ( + IN INTERFACE_TYPE BusType + ); + +VOID +HalpRegisterResourceUsage ( + IN PRESOURCE_USAGE Resource + ); diff --git a/private/ntos/nthals/hallego/alpha/legodef.h b/private/ntos/nthals/hallego/alpha/legodef.h new file mode 100644 index 000000000..14213c792 --- /dev/null +++ b/private/ntos/nthals/hallego/alpha/legodef.h @@ -0,0 +1,671 @@ +/*++ + +Copyright (c) 1993,1995,1996 Digital Equipment Corporation + +Module Name: + + legodef.h + +Abstract: + + This module specifies platform-specific definitions for the + Lego modules. + +Author: + + Joe Notarangelo 25-Oct-1993 + +Revision History: + + Gene Morgan [Digital] 11-Oct-1995 + Initial version for Lego. Adapted from Avanti. + + Gene Morgan 15-Apr-1996 + New Platform Name strings + +--*/ + +#ifndef _LEGODEF_ +#define _LEGODEF_ + +#include "alpharef.h" +#include "apecs.h" +#include "isaaddr.h" + +//**************************************************************** +// Lego family configurations +// (PCI/ISA slots and backplane features). +// +// PCI "Virtual slot" concept comes from Microsoft's pci.h file. +// +//**************************************************************** + +// Atacama -- Baby-AT form factor +// +#define NUMBER_ATACAMA_ISA_SLOTS 4 +#define NUMBER_ATACAMA_PCI_SLOTS 3 // 2 are 64-bit. NCR810 is in what would be 2nd slot + +// +// Gobi -- 15 slot backplane +// +// Addition of one DECchip 21052 PPB yields 4 32-bit PCI slots (at cost of one 32-bit slot). +// NCR810 is gone, too. +// +// Gobi PCI config +// Slot function IDSEL int pin routing (mod 4) +// ---- -------- ----- ---------------------- +// 20 PCI-PCI bridge 31 +3 +// 19 64-bit slot 30 +2 +// 18 64-bit slot 29 +1 +// 17 32-bit slot 28 +0 +// +// 15 bridge 1 slot 31 +0 +// 14 bridge 1 slot 30 +1 +// 13 bridge 1 slot 29 +2 +// 12 bridge 1 slot 28 +3 +// +// 7 ISA SIO 18 -- +// +#define NUMBER_GOBI_ISA_SLOTS 5 +#define NUMBER_GOBI_PCI_SLOTS 7 + +// Sahara -- 20 slot backplane +// +// Addition of another 21052... +// +#define NUMBER_SAHARA_ISA_SLOTS 7 +#define NUMBER_SAHARA_PCI_SLOTS 10 + +// Generic -- use Sahara's values +// +// ??? Used ??? +// +#define NUMBER_ISA_SLOTS (NUMBER_SAHARA_ISA_SLOTS) +#define NUMBER_PCI_SLOTS (NUMBER_SAHARA_PCI_SLOTS) + +// Lowest virtual local PCI slot is 17 == IDSEL PCI_AD[28] +// Highest Virtual local PCI Slot is 20 == IDSEL PCI_AD[31] +// This gives the following slot layout: +// +// Virtual Device Physical Device/slot IDSEL +// 17 1 28 +// 18 2 29 +// 19 3 30 +// 20 4 31 +// +// Used for sizing Pin-to-Line table. +// +#define PCI_MIN_LOCAL_DEVICE 17 //[wem] not used +#define PCI_MAX_LOCAL_DEVICE 20 + +// LEGO Family Members - +// +// concatenate cpu and backplane type to get family type +// + +#define CPU_UNKNOWN 0x0 // Can't tell what CPU +#define CPU_LEGO_K2 0x1 // K2 CPU card + +#define BACKPLANE_UNKNOWN 0x0 // Can't determine backplane -- assume PICMIG-compliant +#define BACKPLANE_ATACAMA 0x1 +#define BACKPLANE_GOBI 0x2 +#define BACKPLANE_SAHARA 0x3 + +// +// Backplane/CPU feature mask +// + +#define LEGO_FEATURE_INT_ACCEL 0x01 +#define LEGO_FEATURE_SERVER_MGMT 0x02 +#define LEGO_FEATURE_WATCHDOG 0x04 // PSU (not in first rev of K2) +#define LEGO_FEATURE_OCP_DISPLAY 0x08 // I2C bus and PCF8574s are present +#define LEGO_FEATURE_PSU 0x10 // System has DMCC backplane with support + // for multiple power supplies + +#define LEGO_NUMBER_OF_FEATURES 5 + +// +// Server Management Conditions +// + +#define LEGO_CONDITION_OVERTEMP 0x01 +#define LEGO_CONDITION_CPU_OVERTEMP 0x02 +#define LEGO_CONDITION_CPU_TEMPOK 0x04 +#define LEGO_CONDITION_BADFAN 0x08 +#define LEGO_CONDITION_CPU_BADFAN 0x10 +#define LEGO_CONDITION_POWER1_BAD 0x20 +#define LEGO_CONDITION_POWER2_BAD 0x40 + +#define CONDITION_QUERY 0x10000 // force recheck of server management register + +#define LEGO_NUMBER_OF_CONDITIONS 7 + +// +// Define known Lego platform names. +// + +#define PLATFORM_NAME_LEGO_K2 "LegoK2" +#define PLATFORM_NAME_K2_ATA "LegoK2A" // Atacama +#define PLATFORM_NAME_K2_GOBI "LegoK2G" // Gobi +#define PLATFORM_NAME_K2_SAHA "LegoK2S" // Sahara +#define PLATFORM_NAME_UNKNOWN "LegoUnk" // Unknown + +// +// PCI Interrupt routing types +// +// PCI Interrupts in LEGO may be routed in one of three ways: +// SIO - INTA .. INTD off the PCI bus routed through the SIO. +// DIRECT - INTA .. INTD off the PCI bus routed to an interrupt +// register. +// FULL - INTA .. INTD from each primary or bridged slot (64 signals) +// routed to one of four interrupt registers. +// +#define PCI_INTERRUPT_ROUTING_SIO 1 +#define PCI_INTERRUPT_ROUTING_FULL 2 +#define PCI_INTERRUPT_ROUTING_DIRECT 3 + + +//******************************************************* +// +// End Lego-specific configuration info +// +// Lego-specific register layouts and addresses +// are at the end of this file. +// +//******************************************************* + +//[wem] same as avanti.h +// +#define PCI_SPARSE_IO_BASE_QVA ((ULONG)(HAL_MAKE_QVA(APECS_PCI_IO_BASE_PHYSICAL))) //[wem] LEGO-OK + +// +// PCI-E/ISA Bridge chip configuration space base is at physical address +// 0x1e0000000. The equivalent QVA is: +// ((0x1e0000000 + cache line offset) >> IO_BIT_SHIFT) | QVA_ENABLE +// +// N.B.: The PCI configuration space address is what we're really referring +// to, here; both symbols are useful. +// + +#define PCI_REVISION (0x0100 >> IO_BIT_SHIFT) + +#define PCI_CONFIGURATION_BASE_QVA 0xaf000000 +#define PCI_CONFIG_CYCLE_TYPE_0 0x0 // Local PCI device +#define PCI_CONFIG_CYCLE_TYPE_1 0x1 // Nested PCI device + +#define PCI_ISA_BRIDGE_HEADER_OFFSET (0x00070000 >> IO_BIT_SHIFT) // AD[18] //[wem] LEGO-OK + +// +// PCI-ISA Bridge Non-Configuration control register offsets. +// These offsets are in PCI I/O space and should be ored with +// PCI_SPARSE_IO_BASE_QVA. +// + +#define SIO_II_EDGE_LEVEL_CONTROL_1 (0x9a00 >> IO_BIT_SHIFT) //[wem] LEGO-OK +#define SIO_II_EDGE_LEVEL_CONTROL_2 (0x9a20 >> IO_BIT_SHIFT) + +// +// Register offsets for unique functions on Lego. Some of these are offsets +// into ISA I/O space -- they cannot be reached via PCI I/O space. +// + +// PCI offsets... +// + +#define PCI_INDEX (0x04c0 >> IO_BIT_SHIFT) //[wem] 0x4DC0 for LEGO ? +#define PCI_DATA (0x04e0 >> IO_BIT_SHIFT) //[wem] 0x4DE0 for LEGO ? + +// +// PCI-ISA Bridge Configuration register offsets. +// + +#define PCI_VENDOR_ID (0x0000 >> IO_BIT_SHIFT) //[wem] LEGO-OK +#define PCI_DEVICE_ID (0x0040 >> IO_BIT_SHIFT) +#define PCI_COMMAND (0x0080 >> IO_BIT_SHIFT) +#define PCI_DEVICE_STATUS (0x00c0 >> IO_BIT_SHIFT) +#define PCI_REVISION (0x0100 >> IO_BIT_SHIFT) +#define PCI_CONTROL (0x0800 >> IO_BIT_SHIFT) +#define PCI_ARBITER_CONTROL (0x0820 >> IO_BIT_SHIFT) +#define UTIL_BUS_CHIP_SELECT_ENAB_A (0x09c0 >> IO_BIT_SHIFT) +#define UTIL_BUS_CHIP_SELECT_ENAB_B (0x09e0 >> IO_BIT_SHIFT) +#define PIRQ0_ROUTE_CONTROL (0x0c00 >> IO_BIT_SHIFT) +#define PIRQ1_ROUTE_CONTROL (0x0c20 >> IO_BIT_SHIFT) +#define PIRQ2_ROUTE_CONTROL (0x0c40 >> IO_BIT_SHIFT) +#define PIRQ3_ROUTE_CONTROL (0x0c60 >> IO_BIT_SHIFT) + +// +// SIO-II value for setting edge/level operation in the control words. +// + +#define IRQ0_LEVEL_SENSITIVE 0x01 +#define IRQ1_LEVEL_SENSITIVE 0x02 +#define IRQ2_LEVEL_SENSITIVE 0x04 +#define IRQ3_LEVEL_SENSITIVE 0x08 +#define IRQ4_LEVEL_SENSITIVE 0x10 +#define IRQ5_LEVEL_SENSITIVE 0x20 +#define IRQ6_LEVEL_SENSITIVE 0x40 +#define IRQ7_LEVEL_SENSITIVE 0x80 +#define IRQ8_LEVEL_SENSITIVE 0x01 +#define IRQ9_LEVEL_SENSITIVE 0x02 +#define IRQ10_LEVEL_SENSITIVE 0x04 +#define IRQ11_LEVEL_SENSITIVE 0x08 +#define IRQ12_LEVEL_SENSITIVE 0x10 +#define IRQ13_LEVEL_SENSITIVE 0x20 +#define IRQ14_LEVEL_SENSITIVE 0x40 +#define IRQ15_LEVEL_SENSITIVE 0x80 + +// +// Values for PIRQ route control settings. +// see 82378 SIO spec, section 4.1.27 +// + +#define PIRQX_ROUTE_IRQ3 0x03 +#define PIRQX_ROUTE_IRQ4 0x04 +#define PIRQX_ROUTE_IRQ5 0x05 +#define PIRQX_ROUTE_IRQ6 0x06 +#define PIRQX_ROUTE_IRQ7 0x07 +#define PIRQX_ROUTE_IRQ9 0x09 +#define PIRQX_ROUTE_IRQ10 0x0a +#define PIRQX_ROUTE_IRQ11 0x0b +#define PIRQX_ROUTE_IRQ12 0x0c +#define PIRQX_ROUTE_IRQ14 0x0d +#define PIRQX_ROUTE_IRQ15 0x0f +#define PIRQX_ROUTE_ENABLE 0x00 +#define PIRQX_ROUTE_DISABLE 0x80 + +// +// Define primary (and only) CPU on Lego system +// + +#define HAL_PRIMARY_PROCESSOR ((ULONG)0x0) +#define HAL_MAXIMUM_PROCESSOR ((ULONG)0x0) + +// +// Define the default processor clock frequency used before the actual +// value can be determined. +// + +#define DEFAULT_PROCESSOR_FREQUENCY_MHZ (233) + +#if !defined (_LANGUAGE_ASSEMBLY) + +#if !defined (AXP_FIRMWARE) +// +// Define the per-processor data structures allocated in the PCR +// for each EV4 processor. +// +typedef struct _LEGO_PCR{ + ULONGLONG HalpCycleCount; // 64-bit per-processor cycle count + EV4ProfileCount ProfileCount; // Profile counter state, do not move + EV4IrqStatus IrqStatusTable[MaximumIrq]; // Irq status table +} LEGO_PCR, *PLEGO_PCR; + +#endif + +#define HAL_PCR ( (PLEGO_PCR)(&(PCR->HalReserved)) ) + +#endif + +//************************************************** +// +// The remainder of this file contain Lego-specific +// definitions. +// +//************************************************** + +// The Lego server management data structure +// +// The server management register is at ISA address 506h. +// +// The SINT signals are routed to CPU IRQ5. Writing a 1 to an SINT +// bit will clear the interrupt (an edge will reassert it). The temperature +// sensors can clear and reassert themselves, the fan sensors are one-shots. +// +// The NMI signals are routed to CPU IRQ3. The bits cannot be cleared, only +// masked. +// +// Note: PINT and MPINT bits are not in first rev of K2. +// +#if !defined(_LANGUAGE_ASSEMBLY) + +typedef union _LEGO_SRV_MGMT{ + struct { + USHORT CpuTempRestored : 1; // rw - SINT1 + USHORT CpuTempFailure : 1; // rw - SINT2 + USHORT EnclFanFailure : 1; // rw - SINT3 + USHORT EnclTempFailureNmi : 1; // ro - SNMI1 + USHORT CpuFanFailureNmi : 1; // ro - SNMI2 + USHORT IntMask : 1; // rw - MSINT - set to mask SINT[1..3] + USHORT NmiMask : 1; // rw - MSNMI - set to mask SNMI[1..2] + USHORT PowerOff : 1; // rw - POFF - set to switch off power + USHORT PsuMask : 1; // rw - MPINT - set to mask PINT[2..1] + USHORT Psu1Failure : 1; // rw - PINT1 - PSU status change + USHORT Psu2Failure : 1; // rw - PINT2 - PSU status change + USHORT Reserved : 5; // ro/undefined + }; + USHORT All; +} LEGO_SRV_MGMT, *PLEGO_SRV_MGMT; + +// The Lego watchdog timer data structure +// The watchdog timer register is at ISA address 504h. +// +// The WINT signal is routed to CPU IRQ5. The interrupt +// is cleared by writing a 1 to WINT. +// +// Notes: +// WMODE, T1CF, and T2CF can be written iff the watchdog is disabled. +// The watchdog cannot be disabled if timer 2 running. +// To disable the watchdog: +// (WPHAS==0) ? WEN = 0 : WPHAS = 1, WEN = 0; +// If timer two is allowed to expire, a system-wide reset occurs. +// Write 1 to WPHAS, WINT to clear them. +// +typedef union _LEGO_WATCHDOG{ + struct { + USHORT TimerOnePeriod : 3; // rw - T1CF[2:0] + USHORT TimerTwoPeriod : 3; // rw - T2CF[2:0] + USHORT Enabled : 1; // rw - WEN - set to enable timer + USHORT Mode : 1; // rw - WMODE - see WATCHDOG_MODE_* + USHORT Phase : 1; // rw - WPHAS - see WATCHDOG_PHASE_* + USHORT Interrupt : 1; // rw - WINT - timer one expired. + USHORT Reserved : 6; // ro/undefined + }; + USHORT All; +} LEGO_WATCHDOG, *PLEGO_WATCHDOG; + +// Watchdog phase - detect whether timer (phase) one or two is running. +// Writing one to the phase bit will place timer in phase one. +// +#define WATCHDOG_PHASE_ONE 0 +#define WATCHDOG_PHASE_TWO 1 + +// Watchdog mode - select whether to run in one-timer or two-timer mode +// +#define WATCHDOG_MODE_2TIMER 0 +#define WATCHDOG_MODE_1TIMER 1 + +#define WATCHDOG_MODE_DISABLED 2 + +// Timeout periods for timers 1 and 2 +// +#define WATCHDOG_PERIOD_10MS 0 +#define WATCHDOG_PERIOD_100MS 1 +#define WATCHDOG_PERIOD_500MS 2 +#define WATCHDOG_PERIOD_1S 3 +#define WATCHDOG_PERIOD_8S 4 +#define WATCHDOG_PERIOD_60S 5 +#define WATCHDOG_PERIOD_300S 6 +#define WATCHDOG_PERIOD_1200S 7 + +// Lego PCI Interrupt Support +// +// Define registers used for facilitating PCI interrupt processing: +// Configuration register (LEGO_PCI_INT_CONFIG) - controls interrupt routing +// Master Interrupt register (LEGO_PCI_INT_MASTER) - slot-level int and mask +// Interrupt Registers 1-4 (LEGO_PCI_INT_REGISTER) - device-level int and mask +// The interrupt registers may hold interrupt and mask signals for a single +// primary slot, or for the four slots that may reside behind the bridge. +// +// The registers are all defined as 16-bit registers since LEGO's ISA bus +// is limited to 16-bit reads and writes. +// + +// Lego PCI Interrupt Support Configuration Register (ISA address 502h) +// CFG - read-only field that identifies which primary slots hold bridges. +// ADR - used to establish the base address of the 4 4-byte interrupt registers. +// +typedef union _LEGO_PCI_INT_CONFIG{ + struct { + USHORT BackplaneConfig : 4; // ro - CFG[4:1] - see LEGO_CONFIG_* + USHORT IntRegisterBaseAddr : 12; // rw - ADR[15:4] + }; + USHORT All; +} LEGO_PCI_INT_CONFIG, *PLEGO_PCI_INT_CONFIG; + +// Configurations +// +// Value is a bitmask that indicates which primary slots are +// bridges -- the rightmost bit is for device 1. +// +#define LEGO_CONFIG_ATACAMA 0x0 // b0000 - all primary slots are connectors +#define LEGO_CONFIG_GOBI 0x1 // b0001 - primary slot one is a PPB +#define LEGO_CONFIG_SAHARA 0x3 // b0011 - primary slots one and two are PPBs + +// Lego PCI Interrupt Support Master Register (ISA address 500h) +// +// INTE and INTF and reserved for on-board PCI functions. Their use +// is not currently defined. +// +// OWN - controls who drives bits 13-15 on a read to the Interrupt Master Register +// 0 (default) - backplane drives the bits on a read +// 1 - cpu card drives the bits +// +typedef union _LEGO_PCI_INT_MASTER{ + struct { + USHORT Interrupt : 4; // ro - INTA..INTD + USHORT InterruptRes : 2; // ro - INTE,F **reserved** + USHORT IntMask : 4; // rw - MINTA..MINTD + USHORT IntMaskRes : 2; // rw - MINTE,F **reserved** + USHORT IntOwner : 1; // rw - OWN + USHORT IntRegMaskEnable : 1; // rw - MSKEN + USHORT InterruptEnable : 1; // rw - PCIE + USHORT InterruptMode : 1; // rw - MODE + }; + USHORT All; +} LEGO_PCI_INT_MASTER, *PLEGO_PCI_INT_MASTER; + +#define INTA 0x1 +#define INTB 0x2 +#define INTC 0x4 +#define INTD 0x8 + +#define SLOT1INTA (INTA) +#define SLOT1INTB (INTB) +#define SLOT1INTC (INTC) +#define SLOT1INTD (INTD) +#define SLOT2INTA (INTA<<4) +#define SLOT2INTB (INTB<<4) +#define SLOT2INTC (INTC<<4) +#define SLOT2INTD (INTD<<4) +#define SLOT3INTA (INTA<<8) +#define SLOT3INTB (INTB<<8) +#define SLOT3INTC (INTC<<8) +#define SLOT3INTD (INTD<<8) +#define SLOT4INTA (INTA<<12) +#define SLOT4INTB (INTB<<12) +#define SLOT4INTC (INTC<<12) +#define SLOT4INTD (INTD<<12) + +// Lego PCI Interrupt Support -- Interrupt Register. +// +typedef union _LEGO_PCI_INT_REGISTER { + union { + struct { + USHORT Slot1IntA : 1; // ro - S1IA + USHORT Slot1IntB : 1; // ro - S1IB + USHORT Slot1IntC : 1; // ro - S1IC + USHORT Slot1IntD : 1; // ro - S1ID + USHORT Slot2IntA : 1; // ro - S2IA + USHORT Slot2IntB : 1; // ro - S2IB + USHORT Slot2IntC : 1; // ro - S2IC + USHORT Slot2IntD : 1; // ro - S2ID + USHORT Slot3IntA : 1; // ro - S3IA + USHORT Slot3IntB : 1; // ro - S3IB + USHORT Slot3IntC : 1; // ro - S3IC + USHORT Slot3IntD : 1; // ro - S3ID + USHORT Slot4IntA : 1; // ro - S4IA + USHORT Slot4IntB : 1; // ro - S4IB + USHORT Slot4IntC : 1; // ro - S4IC + USHORT Slot4IntD : 1; // ro - S4ID + } bridge; + struct { + USHORT IntA : 1; // ro - IA + USHORT IntB : 1; // ro - IB + USHORT IntC : 1; // ro - IC + USHORT IntD : 1; // ro - ID + USHORT Reserved : 12; // ro - reserved + } primary; + } slot; + USHORT All; +} LEGO_PCI_INT_REGISTER, *PLEGO_PCI_INT_REGISTER; + +// Lego PCI Interrupt Support -- Interrupt Mask Register. +// +typedef union _LEGO_PCI_INT_MASK_REGISTER { + union { + struct { + USHORT Slot1MaskIntA : 1; // rw - MS1IA + USHORT Slot1MaskIntB : 1; // rw - MS1IB + USHORT Slot1MaskIntC : 1; // rw - MS1IC + USHORT Slot1MaskIntD : 1; // rw - MS1ID + USHORT Slot2MaskIntA : 1; // rw - MS2IA + USHORT Slot2MaskIntB : 1; // rw - MS2IB + USHORT Slot2MaskIntC : 1; // rw - MS2IC + USHORT Slot2MaskIntD : 1; // rw - MS2ID + USHORT Slot3MaskIntA : 1; // rw - MS3IA + USHORT Slot3MaskIntB : 1; // rw - MS3IB + USHORT Slot3MaskIntC : 1; // rw - MS3IC + USHORT Slot3MaskIntD : 1; // rw - MS3ID + USHORT Slot4MaskIntA : 1; // rw - MS4IA + USHORT Slot4MaskIntB : 1; // rw - MS4IB + USHORT Slot4MaskIntC : 1; // rw - MS4IC + USHORT Slot4MaskIntD : 1; // rw - MS4ID + } bridge; + struct { + USHORT MaskIntA : 1; // rw - MIA + USHORT MaskIntB : 1; // rw - MIB + USHORT MaskIntC : 1; // rw - MIC + USHORT MaskIntD : 1; // rw - MID + USHORT Reserved : 12; // ro - reserved + } primary; + } slot; + USHORT All; +} LEGO_PCI_INT_MASK_REGISTER, *PLEGO_PCI_INT_MASK_REGISTER; + +#endif //!_LANGUAGE_ASSEMBLY + +// Define "non-standard" primary interrupts for Lego/K2 +// +#define PCI_VECTOR PRIMARY0_VECTOR // from alpharef.h +#define SERVER_MGMT_VECTOR PRIMARY1_VECTOR + +#define SERVER_MGMT_VECTORS 80 + +// server management conditions (via CPU IRQ5) +// +#define WATCHDOG_VECTOR (0 + SERVER_MGMT_VECTORS) +#define SM_WARNING_VECTOR (1 + SERVER_MGMT_VECTORS) +#define SM_PSU_FAILURE_VECTOR (2 + SERVER_MGMT_VECTORS) + +// NMI conditions (via CPU IRQ3) +// +#define SM_ERROR_VECTOR (5 + SERVER_MGMT_VECTORS) +#define HALT_BUTTON_VECTOR (6 + SERVER_MGMT_VECTORS) + +#define MAXIMUM_SERVER_MGMT_VECTOR (7 + SERVER_MGMT_VECTORS) + +// +// Define interrupt level for server management interrupts, +// including watchdog timer. +// Level should be high, but not as high as NMI +// Using IPI_LEVEL, which is normally for interprocessor interrupts, +//[wem] ??? IPI_LEVEL is between NMI and CLOCK levels -- is this OK ? +// + +#define SERVER_MGMT_LEVEL IPI_LEVEL // from alpharef.h + +// +// Highest PCI interrupt vector is in ISA Vector Space +// Standard vectors are defined in alpharef.h +// + +#define ISA_DEVICE_VECTORS (ISA_VECTORS) +#define PCI_DEVICE_VECTORS (PCI_VECTORS) +#define LEGO_MAXIMUM_PCI_VECTOR (PCI_VECTORS + 0x50) //[wem] 16 vectors wasted + +// Lego device port ISA offsets - 16-bit access only + +// +// server management and watchdog timer control +// + +#define SERVER_MANAGEMENT_REGISTER 0x506 +#define WATCHDOG_REGISTER 0x504 + +// +// PCI interrupt control registers +// + +#define PCI_INTERRUPT_MASTER_REGISTER 0x500 +#define PCI_INTERRUPT_CONFIG_REGISTER 0x502 + +// +// Base address of interrupt and mask registers +// +// The actual base address is determined by reading the IntRegisterBaseAddr field +// of the config register. This is presumably the value established by SROM. [wem] check this +// + +#define PCI_INTERRUPT_BASE_REGISTER 0x510 + +// +// offsets from base address set in IntRegisterBaseAddr field of +// PCI_INTERRUPT_CONFIG_REGISTER (set to PCI_INTERRUPT_BASE_REGISTER). +// +// NOTE: USHORT accesses can be made to these offsets, or ULONG accesses +// can be made to the PCI_INTERRUPT_REGISTER_* offsets to read/write +// the interrupt state and interrupt mask in a single access. +// + +#define MAXIMUM_PCI_INTERRUPT_REGISTERS 4 +#define PCI_INTERRUPT_REGISTER_1 (0x00) // << IO_SHORT_OFFSET) +#define PCI_INTMASK_REGISTER_1 (0x02) +#define PCI_INTERRUPT_REGISTER_2 (0x04) +#define PCI_INTMASK_REGISTER_2 (0x06) +#define PCI_INTERRUPT_REGISTER_3 (0x08) +#define PCI_INTMASK_REGISTER_3 (0x0a) +#define PCI_INTERRUPT_REGISTER_4 (0x0c) +#define PCI_INTMASK_REGISTER_4 (0x0e) + +// +// PCI vector offsets. Interrupt vectors that originate from register +// 1 start at 0x11 for bit position 0. So, when servicing an interrupt from +// register 1, you must add 0x11 to the bit position to get the interrupt +// vector. Likewise, if you have an interrupt vector, and you would like to +// determine which interrupt register it resides in, you can use the vector +// offsets to determine this. All vectors in interrupt register 1 are between +// 0x11 and 0x20. All vectors in interrupt register 2 are between 0x21 and +// 0x30, and so on. Subtracting the vector offset for a register from the +// interrupt vector will give you the bit position of the vector. For example, +// Vector 0x14 corresponds to bit 3 of interrupt register 1, Vector 0x27 +// corresponds to bit 6 of interrupt register 2, and so on. +// +//[wem] used? +// + +#define REGISTER_1_VECTOR_OFFSET 0x00 +#define REGISTER_2_VECTOR_OFFSET 0x10 +#define REGISTER_3_VECTOR_OFFSET 0x20 +#define REGISTER_4_VECTOR_OFFSET 0x30 + +// +// I2C Interface -- via PCF8584 +// +// The PCF8584 presents 2 ports: +// Control Status Register, or CSR (ISA address 509h) - +// Register Window (data port) (ISA address 508h) - +// +// I2C support is via pcd8584.h,.c +// +// I2C bus in Lego has a single device -- the OCP. +// +// OCP support is via pcf8574.c +// + +#define I2C_INTERFACE_DATA_PORT 0x508 +#define I2C_INTERFACE_CSR_PORT 0x509 +#define I2C_INTERFACE_LENGTH 0x2 +#define I2C_INTERFACE_MASK 0x1 + + +#endif // _LEGODEF_ diff --git a/private/ntos/nthals/hallego/alpha/lginitnt.c b/private/ntos/nthals/hallego/alpha/lginitnt.c new file mode 100644 index 000000000..205a87096 --- /dev/null +++ b/private/ntos/nthals/hallego/alpha/lginitnt.c @@ -0,0 +1,1409 @@ +/*++ + +Copyright (c) 1993 Digital Equipment Corporation +Copyright (c) 1994,1996 Digital Equipment Corporation + + +Module Name: + + lginitnt.c + +Abstract: + + This module implements the platform-specific initialization for + a Lego system. + +Author: + + Joe Notarangelo 25-Oct-1993 + +Environment: + + Kernel mode only. + +Revision History: + + Gene Morgan [Digital] 11-Oct-1995 + Initial version for Lego. Adapted from Avanti and Mikasa. + + Gene Morgan 15-Apr-1996 + Error loggin/correction, OCP model/speed display, + screen display of server management features. + +--*/ + +#include "halp.h" +#include "pcrtc.h" +#include "legodef.h" +#include "halpcsl.h" +#include "eisa.h" +#include "pci.h" +#include "pcip.h" +#include "iousage.h" +#include "arccodes.h" +#include "pcf8574.h" +#include "errframe.h" +#include "stdio.h" + +#include "fwcallbk.h" + +#include // to get the product build number. +// +// Define extern global buffer for the Uncorrectable Error Frame. +// declared in halalpha\inithal.c +// + +extern PERROR_FRAME PUncorrectableError; + +//[wem] +//[wem] *******************DEBUG********************* +//[wem] + +#ifdef WEMDBG +extern PVOID DBG_IOBASE; + +#define DBGPUTCHR(c) \ + { UCHAR lsr; \ + while (1) { \ + lsr = READ_REGISTER_UCHAR ((PUCHAR)(((ULONG)DBG_IOBASE) | 0x3FD)); \ + if ((lsr & 0x60) != 0) \ + break; \ + } \ + WRITE_REGISTER_UCHAR ((PUCHAR)(((ULONG)DBG_IOBASE) | 0x3F8), c ); \ + } +#else + +#define DBGPUTCHR(c) + +#endif + +VOID +DBGPUTNL(VOID); + +VOID +DBGPUTHEXB(UCHAR Datum); + +VOID +DBGPUTHEXL(ULONG Datum); + +VOID +DBGPUTHEXP(PVOID Datum); + +VOID +DBGPUTSTR(UCHAR *str); + +//[wem] +//[wem] *******************DEBUG********************* +//[wem] + +// +// Product Naming data. +// +PCHAR HalpFamilyName = "DMCC"; //[wem] ??? real values needed +PCHAR HalpProductName = "Alpha 21064A PICMG SBC"; +ULONG HalpProcessorNumber = 4; + +// Qvas for Server Management and Watchdog Timer functions +// +extern PVOID HalpLegoWatchdogQva; +extern PVOID HalpLegoServerMgmtQva; + +// +// Globals for conveying Cpu and Backplane type +// +BOOLEAN HalpLegoCpu; +BOOLEAN HalpLegoBackplane; +ULONG HalpLegoCpuType; +ULONG HalpLegoBackplaneType; +UCHAR HalpLegoFeatureMask; +ULONG HalpLegoPciRoutingType; + +// +// True if we are servicing watchdog +// +BOOLEAN HalpLegoServiceWatchdog; +BOOLEAN HalpLegoWatchdogSingleMode; +BOOLEAN LegoDebugWatchdogIsr; + +// +// True if someone has "enabled" interrupts +// for a particular server management event. +// +BOOLEAN HalpLegoDispatchWatchdog; +BOOLEAN HalpLegoDispatchNmi; +BOOLEAN HalpLegoDispatchInt; +BOOLEAN HalpLegoDispatchPsu; +BOOLEAN HalpLegoDispatchHalt; + +#define MAX_INIT_MSG (80) + +// +// Define global data for builtin device interrupt enables. +// + +USHORT HalpBuiltinInterruptEnable; + + +// 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 Lego/K2 +// +// IRQ_H[0] = EPIC Error +// IRQ_H[1] = PCI Interrupt (if PCI Interrupt controller enabled) +// IRQ_H[2] = PIC (ISA Device interrupt) +// IRQ_H[3] = NMI, Server management fatal errors, Halt button +// IRQ_H[4] = Clock +// IRQ_H[5] = Watchdog timer, Server Management warning conditions + +// +// 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 +// 064-127 PCI +// 128-144 Server Management and Watchdog Timer +// 144-255 unused, as are all other holes +// +//[wem] Here's what it is really like (as per alpharef.h and legodef.h) +// +// 000-019 Built-ins DEVICE_VECTORS - MAXIMUM_BUILTIN_VECTOR +// 020-029 Platform-specific PRIMARY_VECTORS, PRIMARY0_VECTOR - PRIMARY9_VECTOR +// 048-063 EISA & ISA ISA_VECTORS - MAXIMUM_ISA_VECTOR +// 080-089 Server Mgmt and Watchdog Timer SERVER_MGMT_VECTORS - MAXIMUM_SERVER_MGMT_VECTORS +// 100-164 PCI PCI_VECTORS - MAXIMUM_PCI_VECTOR +// 165-255 unused, as are all other holes +// +//[wem] Here's what Lego uses for PCI +// +// 117-180 PCI (64h + 11h through 64h + 50h) Same size range, just shifted (16 vectors wasted). +// PCI_VECTORS - LEGO_MAXIMUM_PCI_VECTOR +// 181-255 unused, as are all other holes + +// +// HalpClockFrequency is the processor cycle counter frequency in units +// of cycles per second (Hertz). It is a large number (e.g., 125,000,000) +// but will still fit in a ULONG. +// +// HalpClockMegaHertz is the processor cycle counter frequency in units +// of megahertz. It is a small number (e.g., 125) and is also the number +// of cycles per microsecond. The assumption here is that clock rates will +// always be an integral number of megahertz. +// +// Having the frequency available in both units avoids multiplications, or +// especially divisions in time critical code. +// + +extern ULONG HalpClockFrequency; +extern ULONG HalpClockMegaHertz; +// +// Define the bus type, this value allows us to distinguish between +// EISA and ISA systems. +// +ULONG HalpBusType = MACHINE_TYPE_ISA; + +// +// Define global data used to communicate new clock rates to the clock +// interrupt service routine. +// + +ULONG HalpCurrentTimeIncrement; +ULONG HalpNextRateSelect; +ULONG HalpNextTimeIncrement; +ULONG HalpNewTimeIncrement; + + +VOID +HalpInitializeHAERegisters( + VOID + ); + +VOID +HalpClearInterrupts( + ); + +BOOLEAN +HalpInitializeLegoInterrupts( + VOID + ); + +VOID +HalpParseLoaderBlock( + PLOADER_PARAMETER_BLOCK LoaderBlock + ); + +VOID +HalpRegisterPlatformResources( + VOID + ); + +VOID +HalpDetermineMachineType( + VOID + ); + + +BOOLEAN +HalpInitializeInterrupts ( + VOID + ) + +/*++ + +Routine Description: + + This function initializes interrupts for a Lego/K2 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; + UCHAR Priority; + ULONG Vector; + + // + // Initialize HAL private data from the PCR. This must be done before + // HalpStallExecution is called. + // + + // + // Compute integral megahertz first to + // avoid rounding errors due to imprecise cycle clock period values. + // + + HalpClockMegaHertz = + ((1000 * 1000) + (PCR->CycleClockPeriod >> 1)) / PCR->CycleClockPeriod; + HalpClockFrequency = HalpClockMegaHertz * (1000 * 1000); + + // + // Connect the Stall interrupt vector to the clock. When the + // profile count is calculated, we then connect the normal + // clock. + + PCR->InterruptRoutine[CLOCK2_LEVEL] = HalpStallInterrupt; + + // + // Clear all pending interrupts + // + + HalpClearInterrupts(); + + // + // Start the peridodic interrupt from the RTC + // + HalpProgramIntervalTimer(MAXIMUM_RATE_SELECT); + +//jnfix, wkc - init the Eisa interrupts after the chip, don't init the +// PIC here, fix halenablesysteminterrupt to init the pic +// interrrupt, as in sable + + // + // Initialize the PCI/ISA interrupt controller. + // + + HalpInitializeLegoInterrupts(); + + // + // Initialize the 21064 interrupts. + // + + HalpInitialize21064Interrupts(); + + HalpEnable21064SoftwareInterrupt( Irql = APC_LEVEL ); + + HalpEnable21064SoftwareInterrupt( Irql = DISPATCH_LEVEL ); + + HalpEnable21064HardwareInterrupt( Irq = 5, + Irql = SERVER_MGMT_LEVEL, + Vector = SERVER_MGMT_VECTOR, + Priority = 0 ); + + HalpEnable21064HardwareInterrupt( Irq = 4, + Irql = CLOCK_LEVEL, + Vector = CLOCK_VECTOR, + Priority = 0 ); + + HalpEnable21064HardwareInterrupt( Irq = 3, + Irql = HIGH_LEVEL, + Vector = EISA_NMI_VECTOR, + Priority = 0 ); + + HalpEnable21064HardwareInterrupt( Irq = 2, + Irql = DEVICE_LEVEL, + Vector = PIC_VECTOR, + Priority = 0 ); + + if (HalpLegoPciRoutingType == PCI_INTERRUPT_ROUTING_FULL) { + + HalpEnable21064HardwareInterrupt( Irq = 1, + Irql = PCI_DEVICE_LEVEL, + Vector = PCI_VECTOR, + Priority = 0 ); +#if DBG + } else { + DbgPrint("Irq 1 disabled -- PCI interrupts via SIO\n"); +#endif + } + + return TRUE; + +} + + +VOID +HalpClearInterrupts( + ) +/*++ + +Routine Description: + + This function no longer does anything. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + return; +} + + +VOID +HalpSetTimeIncrement( + VOID + ) +/*++ + +Routine Description: + + This routine is responsible for setting the time increment for an EV4 + based machine 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. +// + +ULONG HalpProfileCountRate; + +VOID +HalpInitializeClockInterrupts( + VOID + ) + +/*++ + +Routine Description: + + This function is called during phase 1 initialization to complete + the initialization of clock interrupts. For EV4, this function + connects the true clock interrupt handler and initializes the values + required to handle profile interrupts. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + LEGO_WATCHDOG WdRegister; + + // + // 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; + + // + // If desired, turn on the watchdog timer + // + + if (HalpLegoServiceWatchdog) { + + WdRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoWatchdogQva ); + WdRegister.Enabled = 1; + WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoWatchdogQva, WdRegister.All); + + } + + 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. + // + + PCR->MachineCheckError = HalMachineCheck; + + // + // Initialize error handling for APECS. + // + + HalpInitializeMachineChecks( ReportCorrectables = TRUE ); + + return; +} + +VOID +HalpInitializeMachineDependent( + IN ULONG Phase, + IN PLOADER_PARAMETER_BLOCK LoaderBlock + ) +/*++ + +Routine Description: + + This function performs any EV4-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 a pointer to the loader block. + +Return Value: + + None. + +--*/ +{ + UCHAR MsgBuffer[MAX_INIT_MSG]; + CHAR MhzString[9]; + + if( Phase == 0 ){ + + // + // Phase 0 Initialization. + // + + // + // Parse the Loader Parameter block looking for PCI entry to determine + // if PCI parity should be disabled + // + HalpParseLoaderBlock( LoaderBlock ); + + // + // Re-establish the error handler, to reflect the parity checking + // + HalpEstablishErrorHandler(); + + HalpInitializeHAERegisters(); + + // + // Determine what flavor platform we are on + // + HalpDetermineMachineType(); + + } else { + + // + // Phase 1 Initialization. + // + + // + // Initialize the existing bus handlers. + // + HalpRegisterInternalBusHandlers(); + + // + // Initialize PCI Bus. + // + HalpInitializePCIBus (LoaderBlock); + + // + // Initialize profiler. + // + HalpInitializeProfiler(); + + // + // Print out a cool-o message + // + + sprintf(MsgBuffer, + "Digital Equipment Corporation %s %s\n", + HalpFamilyName, + HalpProductName); + + HalDisplayString(MsgBuffer); + + // + // Display system speed on the OCP + // + + sprintf (MhzString, " 4A/%3d ", HalpClockMegaHertz); + HalpOcpInitDisplay(); + HalpOcpPutSlidingString(MhzString,8); + + // + // Register HAL name and I/O resources + // + + HalpRegisterPlatformResources(); + + } + + return; +} + + + +VOID +HalpRegisterPlatformResources( + VOID + ) +/*++ + +Routine Description: + + Register I/O resources used by the HAL. + +Arguments: + + HalName - Supplies a pointer to the name for the HAL. + +Return Value: + + None. + +--*/ +{ + RESOURCE_USAGE Resource; + UCHAR HalName[256]; + + // + // Register the buses. + // + + HalpRegisterBusUsage(Internal); + HalpRegisterBusUsage(Isa); + HalpRegisterBusUsage(PCIBus); + + // + // Register the name of the HAL. + // + + sprintf(HalName, + "%s %s, %d Mhz, PCI/ISA HAL\n", + HalpFamilyName, + HalpProductName, + HalpClockMegaHertz ); + + HalpRegisterHalName( HalName ); + + // + // Report the apecs mapping to the Io subsystem + // + // This is the PCI Memory space that cannot be used by anyone + // and therefore the HAL says it is reserved for itself + // + //[wem] ??? check register resource for PCI memory ? + // + + Resource.BusType = PCIBus; + Resource.BusNumber = 0; + Resource.ResourceType = CmResourceTypeMemory; + Resource.Next = NULL; + Resource.u.Start = __8MB; + Resource.u.Length = __32MB - __8MB; + HalpRegisterResourceUsage(&Resource); + + // + // Register the interrupt vector used for the cascaded interrupt + // on the 8254s. + // + + Resource.BusType = Isa; + Resource.BusNumber = 0; + Resource.ResourceType = CmResourceTypeInterrupt; + Resource.u.InterruptMode = Latched; + Resource.u.BusInterruptVector = 2; + Resource.u.SystemInterruptVector = 2; + Resource.u.SystemIrql = 2; + HalpRegisterResourceUsage(&Resource); + + // + // Register machine specific io/memory addresses. + // + + Resource.BusType = Isa; + Resource.BusNumber = 0; + Resource.ResourceType = CmResourceTypePort; + Resource.u.Start = I2C_INTERFACE_DATA_PORT; + Resource.u.Length = I2C_INTERFACE_LENGTH; + HalpRegisterResourceUsage(&Resource); + +//[wem] ??? What is this? +// Resource.u.Start = SUPERIO_INDEX_PORT; +// Resource.u.Length = SUPERIO_PORT_LENGTH; +// HalpRegisterResourceUsage(&Resource); + + // + // Register the DMA channel used for the cascade. + // + + Resource.BusType = Isa; + Resource.BusNumber = 0; + Resource.ResourceType = CmResourceTypeDma; + Resource.u.DmaPort = 0x0; + Resource.u.DmaChannel = 0x4; + HalpRegisterResourceUsage(&Resource); +} + + +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. + +--*/ + +{ + + HalpAcknowledgeClockInterrupt(); + + 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 EPIC/APECS chipset. + +Arguments: + + none + +Return Value: + + none + +--*/ +{ + // + // We set HAXR1 to 0. This means no address extension + // + + WRITE_EPIC_REGISTER( &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->Haxr1, 0); + + // + // We set HAXR2 to 0. Which means we have the following + // PCI IO addresses: + // 0 to 64KB VALID. HAXR2 Not used in address translation + // 64K to 16MB VALID. HAXR2 is used in the address translation + // + + WRITE_EPIC_REGISTER( &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->Haxr2, 0); + +#if 0 +#if DBG + DumpEpic(); +#endif // DBG +#endif +} + + +VOID +HalpResetHAERegisters( + VOID + ) +/*++ + +Routine Description: + + This function resets the HAE registers in the EPIC/APECS chipset to 0. + This is routine called during a shutdown so that the prom + gets a predictable environment. + +Arguments: + + none + +Return Value: + + none + +--*/ +{ + WRITE_EPIC_REGISTER( &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->Haxr1, 0 ); + WRITE_EPIC_REGISTER( &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->Haxr2, 0 ); +} + + +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(APECS_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[] = "LegoK2"; // 8 char max. + 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: + + Allocate an Uncorrectable Error frame for this + system and initializes the frame with certain constant/global + values. + + Called during machine dependent system initialization. + +Arguments: + + none + +Return Value: + + none + +--*/ +{ + PROCESSOR_EV4_UNCORRECTABLE processorFrame; + APECS_UNCORRECTABLE_FRAME LegoUnCorrrectable; //[wem] used? + + // + // 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; +} + + +VOID +HalpDetermineMachineType( + VOID + ) +/*++ + +Routine Description: + + Determine which Lego variant of backplane and cpu we're on + and set HalpLegoCpu, HalpLegoBackplane, HalpLegoCpuType, + and HalpLegoBackplaneType accordingly. + +Arguments: + + None. + +Return value: + + None. + +Notes: + + [wem] ??? Missing - method of detecting OCP Display from HAL + +--*/ +{ + PSYSTEM_ID SystemId; + PUCHAR ProductId; + LEGO_SRV_MGMT SmRegister; + LEGO_WATCHDOG WdRegister; + BOOLEAN PsuMask; + UCHAR temp; + + // + // Get the ProductId, and see if it is one of the + // Lego strings. + // + // Product ID is only eight characters! + // + + SystemId = ArcGetSystemId(); + + ProductId = &SystemId->ProductId[0]; + +#if DBG + DbgPrint("ProductId: %s, product type: ",ProductId); +#endif + + if (strstr(ProductId,PLATFORM_NAME_K2_ATA)!=0) { + +#if DBG + DbgPrint("K2+Atacama"); +#endif + + HalpLegoCpu = TRUE; + HalpLegoBackplane = TRUE; + HalpLegoCpuType = CPU_LEGO_K2; + HalpLegoBackplaneType = BACKPLANE_ATACAMA; + HalpLegoPciRoutingType = PCI_INTERRUPT_ROUTING_FULL; + + } else if (strstr(ProductId,PLATFORM_NAME_K2_GOBI)!=0) { + +#if DBG + DbgPrint("K2+Gobi"); +#endif + + HalpLegoCpu = TRUE; + HalpLegoBackplane = TRUE; + HalpLegoCpuType = CPU_LEGO_K2; + HalpLegoBackplaneType = BACKPLANE_GOBI; + HalpLegoPciRoutingType = PCI_INTERRUPT_ROUTING_FULL; + + } else if (strstr(ProductId,PLATFORM_NAME_K2_SAHA)!=0) { + +#if DBG + DbgPrint("K2+Sahara"); +#endif + + HalpLegoCpu = TRUE; + HalpLegoBackplane = TRUE; + HalpLegoCpuType = CPU_LEGO_K2; + HalpLegoBackplaneType = BACKPLANE_SAHARA; + HalpLegoPciRoutingType = PCI_INTERRUPT_ROUTING_FULL; + + } else if (strstr(ProductId,PLATFORM_NAME_LEGO_K2)!=0) { + +#if DBG + DbgPrint("K2+unknown backplane"); +#endif + + HalpLegoCpu = TRUE; + HalpLegoBackplane = FALSE; + HalpLegoCpuType = CPU_LEGO_K2; + HalpLegoBackplaneType = BACKPLANE_UNKNOWN; + HalpLegoPciRoutingType = PCI_INTERRUPT_ROUTING_SIO; + + } else { + +#if DBG + DbgPrint("unknown cpu, unknown backplane"); +#endif + HalpLegoCpu = FALSE; + HalpLegoBackplane = FALSE; + HalpLegoCpuType = CPU_UNKNOWN; + HalpLegoBackplaneType = BACKPLANE_UNKNOWN; + HalpLegoPciRoutingType = PCI_INTERRUPT_ROUTING_SIO; + + } + +#if DBG + DbgPrint("\n"); +#endif + + // + // Read environment variable to get PCI Interrupt Routing + // + // If environment variable is absent or unreadable, use + // default setting of PCI_INTERRUPT_ROUTING_SIO + // + { + ARC_STATUS Status; + CHAR Buffer[16]; + + Status = HalGetEnvironmentVariable ("LGPCII",16,Buffer); + +#if DBG + DbgPrint("Get LGPCII = %s\n",Buffer); +#endif + + if (Status==ESUCCESS) { + + if (tolower(*Buffer) == 's') { + HalpLegoPciRoutingType = PCI_INTERRUPT_ROUTING_SIO; + } + else if (tolower(*Buffer) == 'f') { + HalpLegoPciRoutingType = PCI_INTERRUPT_ROUTING_FULL; + } + else if (tolower(*Buffer) == 'd') { + HalpLegoPciRoutingType = PCI_INTERRUPT_ROUTING_DIRECT; + } + else { + // + // Bad setting + // + HalpLegoPciRoutingType = PCI_INTERRUPT_ROUTING_SIO; + } + } + else { + // + // No setting - use default + // + HalpLegoPciRoutingType = PCI_INTERRUPT_ROUTING_SIO; + } + } + + HalDisplayString ("DMCC Interrupt Routing: "); + + HalDisplayString ((HalpLegoPciRoutingType==PCI_INTERRUPT_ROUTING_SIO) ? "ISA PIRQs" : + (HalpLegoPciRoutingType==PCI_INTERRUPT_ROUTING_DIRECT) ? "Interrupt Registers" : + (HalpLegoPciRoutingType==PCI_INTERRUPT_ROUTING_FULL) ? "Interrupt Accelerator" : "Unknown!"); + + HalDisplayString ("\n"); + +#if DBG + DbgPrint("\n"); + DbgPrint("Interrupt Routing is via "); + DbgPrint((HalpLegoPciRoutingType == PCI_INTERRUPT_ROUTING_SIO) + ? "SIO.\n\r" : "Interrupt accelerator.\n\r"); +#endif + + // Setup feature mask + // + HalpLegoFeatureMask = 0; + if (HalpLegoCpu) { + + // Is watchdog timer present? + // + WdRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoWatchdogQva ); + if (WdRegister.All != 0xffff) { + HalpLegoFeatureMask |= LEGO_FEATURE_WATCHDOG; + } + + // Is server management register present? + // + SmRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva ); + if (SmRegister.All != 0xffff) { + HalpLegoFeatureMask |= LEGO_FEATURE_SERVER_MGMT; + + // Is multiple PSU support present? + // Write 0 then 1 into PSU mask bit, and read it + // back each time to see if setting sticks. + // + PsuMask = (SmRegister.PsuMask == 1); // save setting + SmRegister.PsuMask = 0; // clear mask + WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva, SmRegister.All ); + SmRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva ); + + if (SmRegister.PsuMask == 0) { + // + // mask bit is cleared + // + SmRegister.PsuMask = 1; // set mask + WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva, SmRegister.All ); + SmRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva ); + + if (SmRegister.PsuMask == 1) { + // + // mask bit is set. Feature is + // present, restore mask bit's original setting + // + HalpLegoFeatureMask |= LEGO_FEATURE_PSU; + SmRegister.PsuMask = (PsuMask) ? 1 : 0; + WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva, SmRegister.All ); + } + } + } + temp = HalpLegoFeatureMask; + if (temp != 0) { + HalDisplayString ("DMCC Platform Features: "); + if ((temp & LEGO_FEATURE_WATCHDOG) != 0) { + temp &= ~LEGO_FEATURE_WATCHDOG; + HalDisplayString ("Watchdog Timer"); + HalDisplayString ((temp!=0)?", ":"."); + } + if ((temp & LEGO_FEATURE_SERVER_MGMT) != 0) { + temp &= ~LEGO_FEATURE_SERVER_MGMT; + HalDisplayString ("Server Management"); + HalDisplayString ((temp!=0)?", ":"."); + } + if ((HalpLegoFeatureMask & LEGO_FEATURE_PSU) != 0) { + HalDisplayString ("Multiple PSU Support."); + } + HalDisplayString ("\n"); + } else { + HalDisplayString("No LEGO Platform Features detected!\n"); + } + + if ((HalpLegoFeatureMask & LEGO_FEATURE_WATCHDOG) != 0) { + + // + // Read environment variable to get Watchdog Timer setting + // + // If environment variable is absent or unreadable, use + // default setting of NOT HalpLegoServiceWatchdog + // + + { + ARC_STATUS Status; + CHAR Buffer[16]; + + Status = HalGetEnvironmentVariable ("LGWD",16,Buffer); + + #if DBG + DbgPrint("Get LGWD = %s\n",Buffer); + #endif + + if (Status==ESUCCESS) { + + if (Buffer[0]=='0') { + HalpLegoServiceWatchdog = TRUE; + HalpLegoWatchdogSingleMode = FALSE; + } + else if (Buffer[0]=='1') { + HalpLegoServiceWatchdog = TRUE; + HalpLegoWatchdogSingleMode = TRUE; + } + else { + HalpLegoServiceWatchdog = FALSE; + } + + // + // Check for special debug variable -- if set, + // don't service the watchdog in the clock ISR + // + + Status = HalGetEnvironmentVariable ("LGWDD",16,Buffer); + + if (Status==ESUCCESS) { + LegoDebugWatchdogIsr = TRUE; + } + else { + LegoDebugWatchdogIsr = FALSE; + } + + } + else { + // + // No setting - use default + // + + HalpLegoServiceWatchdog = FALSE; + HalpLegoWatchdogSingleMode = FALSE; + LegoDebugWatchdogIsr = FALSE; + } + } + + HalDisplayString("DMCC Watchdog Timer is "); + if (HalpLegoServiceWatchdog) { + HalDisplayString("active "); + HalDisplayString((HalpLegoWatchdogSingleMode) + ? "(single timeout)." + : "(double timeout)."); + } + else { + HalDisplayString("inactive."); + } + HalDisplayString("\n"); + } + else { + HalpLegoServiceWatchdog = FALSE; + } + } +} diff --git a/private/ntos/nthals/hallego/alpha/lgintr.s b/private/ntos/nthals/hallego/alpha/lgintr.s new file mode 100644 index 000000000..f9de5d6ef --- /dev/null +++ b/private/ntos/nthals/hallego/alpha/lgintr.s @@ -0,0 +1,121 @@ +// TITLE("Lego PCI/ServerMgmt Interrupt Handler") +//++ +// +// Copyright (c) 1994,1995 Digital Equipment Corporation +// +// Module Name: +// +// lgintr.s +// +// Abstract: +// +// This module implements first level interrupt handlers for Lego +// +// Author: +// +// Joe Notarangelo 08-Jul-1993 +// +// Environment: +// +// Kernel mode only. +// +// Revision History: +// +// 29-Apr-1994 James Livingston +// Adapt from Avanti ebintr.s for Mikasa +// +// 3-Nov-1995 Gene Morgan +// Initial version for Lego. Adapt from Mikasa's mkintr.s, +// add Server Management dispatch. +// +//-- + +#include "halalpha.h" + + SBTTL("Lego PCI Interrupt Handler") +//++ +// +// VOID +// HalpPciInterruptHandler +// IN PKINTERRUPT Interrupt, +// IN PVOID ServiceContext +// ) +// +// Routine Description: +// +// This function is executed as the result of an interrupt on the PCI I/O +// bus. The function is responsible for calling HalpPciDispatch to +// appropriately dispatch the interrupt. +// +// N.B. This function exists only to capture the trap frame and forward +// the interrupt to HalpPciDispatch. +// +// Arguments: +// +// Interrupt (a0) - Supplies a pointer to the interrupt object. +// +// ServiceContext (a1) - Supplies a pointer to the service context for +// PCI interrupts. +// +// TrapFrame (fp/s6) - Supplies a pointer to the trap frame for +// the interrupt. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalpPciInterruptHandler) + + bis fp, zero, a2 // capture trap frame as argument + br zero, HalpPciDispatch // dispatch the interrupt to the PCI handler + + ret zero, (ra) // will never get here + + .end HalpPciInterruptHandler + + + SBTTL("Lego Server Management Interrupt Handler") +//++ +// +// VOID +// HalpPciInterruptHandler +// IN PKINTERRUPT Interrupt, +// IN PVOID ServiceContext +// ) +// +// Routine Description: +// +// This function is executed as the result of an interrupt on the +// CPU IRQ pin allocated to Lego Server Management functions. +// The function is responsible for calling HalpServerMgmtDispatch() to +// appropriately dispatch the interrupt. +// +// N.B. This function exists only to capture the trap frame and forward +// the interrupt to HalpServerMgmtDispatch. +// +// Arguments: +// +// Interrupt (a0) - Supplies a pointer to the interrupt object. +// +// ServiceContext (a1) - Supplies a pointer to the service context for +// Server Management interrupts. +// +// TrapFrame (fp/s6) - Supplies a pointer to the trap frame for +// the interrupt. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalpServerMgmtInterruptHandler) + + bis fp, zero, a2 // capture trap frame as argument + br zero, HalpServerMgmtDispatch // dispatch the interrupt to the PCI handler + + ret zero, (ra) // will never get here + + .end HalpServerMgmtInterruptHandler diff --git a/private/ntos/nthals/hallego/alpha/lgintsup.c b/private/ntos/nthals/hallego/alpha/lgintsup.c new file mode 100644 index 000000000..2b2e73beb --- /dev/null +++ b/private/ntos/nthals/hallego/alpha/lgintsup.c @@ -0,0 +1,732 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation +Copyright (c) 1992,1993,1995,1996 Digital Equipment Corporation + +Module Name: + + lgintsup.c + +Abstract: + + The module provides the interrupt support for Lego systems. + +Author: + + Eric Rehm (DEC) 29-December-1993 + +Revision History: + + James Livingston (DEC) 30-Apr-1994 + Adapted from Avanti module for Mikasa. + + Janet Schneider (Digital) 27-July-1995 + Added support for the Noritake. + + Gene Morgan (Digital) 25-Oct-1995 + Initial version for Lego. Adapted from Mikasa's mkintsup.c. + + Gene Morgan 15-Apr-1996 + Service watchdog timer. + +--*/ + +#include "halp.h" +#include "eisa.h" +#include "ebsgdma.h" +#include "legodef.h" +#include "pcrtc.h" +#include "pintolin.h" + +// +// Server management and watchdog timer control +// +extern PVOID HalpLegoServerMgmtQva; +extern PVOID HalpLegoWatchdogQva; + +extern BOOLEAN HalpLegoServiceWatchdog; +extern BOOLEAN HalpLegoWatchdogSingleMode; +extern BOOLEAN LegoDebugWatchdogIsr; + +extern BOOLEAN HalpLegoDispatchNmi; +extern BOOLEAN HalpLegoDispatchHalt; + +// +// Global to control whether halt button triggers breakpoint +// 0 -> no breakpoint +// !0 -> breakpoint when halt button is pressed +// +ULONG HalpHaltButtonBreak = 0; + +// +// PCI Interrupt control +// +extern PVOID HalpLegoPciInterruptConfigQva; +extern PVOID HalpLegoPciInterruptMasterQva; +extern PVOID HalpLegoPciInterruptRegisterBaseQva; +extern PVOID HalpLegoPciInterruptRegisterQva[]; +extern PVOID HalpLegoPciIntMaskRegisterQva[]; + +// +// Import globals declared in HalpMapIoSpace. +// + +extern PVOID HalpServerControlQva; + +// Count NMI interrupts +// +ULONG NMIcount = 0; + +// Declare the interrupt structures and spinlocks for the intermediate +// interrupt dispatchers. +// +KINTERRUPT HalpPciInterrupt; +KINTERRUPT HalpServerMgmtInterrupt; + +// 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; + +// +// Declare the interrupt handler for the PCI bus. The interrupt dispatch +// routine, HalpPciDispatch, is called from this handler. +// + +BOOLEAN +HalpPciInterruptHandler( + IN PKINTERRUPT Interrupt, + IN PVOID ServiceContext + ); + +// +// Declare the interrupt handler for Server Management and Watchdog Timer +// functions. The interrupt dispatch routine, HalpServermgmtDispatch, is +// called from this handler. +// + +BOOLEAN +HalpServerMgmtInterruptHandler( + IN PKINTERRUPT Interrupt, + IN PVOID ServiceContext + ); + +// +// Declare the interrupt handler for the EISA bus. The interrupt dispatch +// routine, HalpEisaDispatch, is called from this handler. +// + +BOOLEAN +HalpEisaInterruptHandler( + IN PKINTERRUPT Interrupt, + IN PVOID ServiceContext + ); + +// +// The following function initializes NMI handling. +// + +VOID +HalpInitializeNMI( + VOID + ); + +// +// The following function is called when an EISA NMI occurs. +// + +BOOLEAN +HalHandleNMI( + IN PKINTERRUPT Interrupt, + IN PVOID ServiceContext + ); + +VOID +HalpInitializePciInterrupts( + VOID + ); + +VOID +HalpInitializeServerMgmtInterrupts( + VOID + ); + + +// +// External routines +// + +BOOLEAN +LegoServerMgmtDelayedShutdown( + ULONG DelaySeconds + ); + +VOID +LegoServerMgmtReportFatalError( + USHORT SmRegAll + ); + + + +BOOLEAN +HalpInitializeLegoInterrupts( + VOID + ) + +/*++ + +Routine Description: + + This routine initializes the structures necessary for EISA & PCI operations + and connects the intermediate interrupt dispatchers. It also initializes + the ISA interrupt controller; Lego's SIO-based interrupt controller is + compatible with Avanti and with the EISA interrupt contoller used on Jensen. + +Arguments: + + None. + +Return Value: + + If the second level interrupt dispatchers are connected, then a value of + TRUE is returned. Otherwise, a value of FALSE is returned. + +--*/ + +{ + KIRQL oldIrql; + + // + // Initialize the EISA NMI interrupt. + // + + HalpInitializeNMI(); + + // + // Directly connect the ISA interrupt dispatcher to the level for + // ISA bus interrupt. + // + // N.B. This vector is reserved for exclusive use by the HAL (see + // interrupt initialization. + // + + PCR->InterruptRoutine[PIC_VECTOR] = HalpSioDispatch; + HalEnableSystemInterrupt(PIC_VECTOR, ISA_DEVICE_LEVEL, LevelSensitive); + + // + // Initialize the interrupt dispatchers for PCI & Server management interrupts. + // + + KeInitializeInterrupt( &HalpPciInterrupt, + HalpPciInterruptHandler, + (PVOID) HalpLegoPciInterruptMasterQva, // Service Context + (PKSPIN_LOCK)NULL, + PCI_VECTOR, + PCI_DEVICE_LEVEL, + PCI_DEVICE_LEVEL, + LevelSensitive, + TRUE, + 0, + FALSE + ); + + if (!KeConnectInterrupt( &HalpPciInterrupt )) { + return(FALSE); + } + + KeInitializeInterrupt( &HalpServerMgmtInterrupt, + HalpServerMgmtInterruptHandler, + (PVOID) HalpLegoServerMgmtQva, // Service Context is... + (PKSPIN_LOCK)NULL, + SERVER_MGMT_VECTOR, + SERVER_MGMT_LEVEL, + SERVER_MGMT_LEVEL, + LevelSensitive, + TRUE, + 0, + FALSE + ); + + if (!KeConnectInterrupt( &HalpServerMgmtInterrupt )) { + return(FALSE); + } + + // + // Intitialize interrupt controller + // + + KeRaiseIrql(ISA_DEVICE_LEVEL, &oldIrql); + + // + // We must initialize the SIO's PICs, for ISA interrupts. + // + + HalpInitializeSioInterrupts(); + + // + // There's no initialization required for the Lego PCI interrupt + // "controller," as it's the wiring of the hardware, rather than a + // PIC like the 82c59 that directs interrupts. We do set the IMR to + // zero to disable all interrupts, initially. + // + + HalpInitializePciInterrupts(); + + // + // Setup server management interrupts. + // On return, server management interrupts will be unmasked, + // but secondary dispatch will not be performed unless appropriate + // boolean has been set due to enable call. + // + + HalpInitializeServerMgmtInterrupts(); + + // + // Restore the IRQL. + // + + KeLowerIrql(oldIrql); + + // + // Initialize the EISA DMA mode registers to a default value. + // Disable all of the DMA channels except channel 4 which is the + // cascade of channels 0-3. + // + + WRITE_PORT_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort.AllMask, + 0x0F + ); + + WRITE_PORT_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort.AllMask, + 0x0E + ); + + return(TRUE); +} + + +VOID +HalpInitializeNMI( + VOID + ) +/*++ + +Routine Description: + + This function is called to intialize SIO NMI interrupts. + +Arguments: + + None. + +Return Value: + + None. +--*/ +{ + UCHAR DataByte; + + // + // Initialize the SIO 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. Note that the other bits should be left as + // they are, according to the chip's documentation. + // + //[wem] ?? Avanti simply writes zero to NmiEnable -- OK + + DataByte = READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable); + ((PNMI_ENABLE)(&DataByte))->NmiDisable = 0; + WRITE_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable, DataByte); + +#ifdef DBG + DbgPrint("HalpIntializeNMI: wrote 0x%x to NmiEnable\n", DataByte); +#endif + +} + +BOOLEAN +HalHandleNMI( + IN PKINTERRUPT Interrupt, + IN PVOID ServiceContext + ) +/*++ + +Routine Description: + + This function is called when an EISA NMI occurs. It prints 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. + +--*/ +{ + LEGO_SRV_MGMT SmRegister; + UCHAR NmiControl, NmiStatus; + BOOLEAN GotSerr, GotIochk, GotSmFan, GotSmTemp, GotHalt; + + NMIcount++; + +#if DBG + if (NMIcount<5) { + DbgPrint("II<"); + } + if (NMIcount % 100 == 0) { + DbgPrint("II<%08x><", NMIcount); + } +#endif + + GotSerr = GotIochk = GotSmFan = GotSmTemp = GotHalt = FALSE; + + // + // Set the Eisa NMI disable bit. We do this to mask further NMI + // interrupts while we're servicing this one. + // + NmiControl = READ_PORT_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable); + ((PNMI_ENABLE)(&NmiControl))->NmiDisable = 1; + WRITE_PORT_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable, NmiControl); + +#ifdef DBG + DbgPrint("HalHandleNMI: wrote 0x%x to NmiEnable\n", NmiControl); +#endif + + NmiStatus = + READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus); + + if (NmiStatus & 0x80) { + GotSerr = TRUE; + +#ifdef DBG + DbgPrint("HalHandleNMI: Parity Check / Parity Error\n"); + DbgPrint("HalHandleNMI: NMI Status = 0x%x\n", NmiStatus); +#endif + HalAcquireDisplayOwnership(NULL); + HalDisplayString ("NMI: Parity Check / Parity Error\n"); + KeBugCheck(NMI_HARDWARE_FAILURE); + return (TRUE); + } + + if (NmiStatus & 0x40) { + GotIochk = TRUE; +#ifdef DBG + DbgPrint("HalHandleNMI: Channel Check / IOCHK\n"); + DbgPrint("HalHandleNMI: NMI Status = 0x%x\n", NmiStatus); +#endif + HalAcquireDisplayOwnership(NULL); + HalDisplayString ("NMI: Channel Check / IOCHK\n"); + KeBugCheck(NMI_HARDWARE_FAILURE); + return (TRUE); + } + + // Read server management register + // Events that can be reported as NMI are: + // Enclosure temperature too high + // CPU Fan failure + // + // For now, generate a bugcheck. + // [wem] Future: perform secondary dispatch to give + // driver shot at reporting problem. + // + SmRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva ); + + GotSmFan = SmRegister.CpuFanFailureNmi == 1; + GotSmTemp = SmRegister.EnclTempFailureNmi == 1; + + if (GotSmFan || GotSmTemp) { + +#ifdef DBG + DbgPrint("HalHandleNMI: Server management NMI\n"); + DbgPrint("HalHandleNMI: NMI Status = 0x%x\n", NmiStatus); + DbgPrint("HalHandleNMI: Server Management Status = 0x%x\n", SmRegister); +#endif + + // + // If secondary dispatch enabled, do it now. + // +#if 0 + if (HalpLegoDispatchNmi + && ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[SM_ERROR_VECTOR])( + PCR->InterruptRoutine[SM_ERROR_VECTOR], + TrapFrame) + ) { + return TRUE; + } +#endif + + // + // Build uncorrectable error frame and + // prepare for orderly shutdown + // + // The delayed shutdown depends on watchdog timer support + // A power off cannot be directly done since KeBugChk() turns + // off interrupts, so there's no way to get control back. + // + // WARNING: Pick a delay that allows a dump to complete. + // + + LegoServerMgmtReportFatalError(SmRegister.All); + LegoServerMgmtDelayedShutdown(8); // Issue reset in 8 seconds + + HalAcquireDisplayOwnership(NULL); + + HalDisplayString ("NMI: Hardware Failure -- "); + HalDisplayString ((SmRegister.CpuFanFailureNmi==1) ? "CPU fan failed." + : "Enclosure termperature too high."); + HalDisplayString ("\nSystem Power Down will be attempted in 8 seconds...\n\n"); + KeBugCheck(NMI_HARDWARE_FAILURE); + return (TRUE); + } + + + // + // Halt button was hit. + // + // [wem] Perform second-level dispatch here too? + // + if (!GotSerr && !GotIochk && !GotSmFan && !GotSmTemp) { + + // + // If secondary dispatch enabled, do it now. + // +#if 0 + if (HalpLegoDispatchHalt + && ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[HALT_BUTTON_VECTOR])( + PCR->InterruptRoutine[HALT_BUTTON_VECTOR], + TrapFrame) + ) { + return TRUE; + } +#endif + + GotHalt = TRUE; + HalDisplayString ("NMI: Halt button pressed.\n"); + + if (HalpHaltButtonBreak) { + DbgBreakPoint(); + } + + return (TRUE); + } + + // + // Clear and re-enable SERR# and IOCHK#, then re-enable NMI + // + +#ifdef DBG + DbgPrint("HalHandleNMI: Shouldn't get here!\n"); +#endif + + if (GotSerr) { +#ifdef DBG + DbgPrint("HalHandleNMI: Resetting SERR#; NMI count = %d\n", NMIcount); +#endif + // + // Reset SERR# (and disable it), then re-enable it. + // + WRITE_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus, 0x04); + WRITE_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus, 0); + } + + if (GotIochk) { +#ifdef DBG + DbgPrint("HalHandleNMI: Resetting IOCHK#; NMI count = %d\n", NMIcount); +#endif + // + // Reset IOCHK# (and disable it), then re-enable it. + // + WRITE_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus, 0x08); + WRITE_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus, 0); + } + + if (GotSmFan || GotSmTemp) { + // + // Reset Server management condition. + // + // Interrupt must be cleared or the NMI will continue + // to occur. + // + SmRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva ); + if (GotSmFan) { + SmRegister.CpuFanFailureNmi = 1; + } + else { + SmRegister.EnclTempFailureNmi = 1; + } + WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva, SmRegister.All ); + } + + // + // Clear the Eisa NMI disable bit. This re-enables NMI interrupts, + // now that we're done servicing this one. + // + NmiControl = READ_PORT_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable); + ((PNMI_ENABLE)(&NmiControl))->NmiDisable = 0; + WRITE_PORT_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable, NmiControl); +#ifdef DBG + DbgPrint("HalHandleNMI: wrote 0x%x to NmiEnable\n", NmiControl); +#endif + + return(TRUE); +} + +VOID +HalpAcknowledgeClockInterrupt( + VOID + ) +/*++ + +Routine Description: + + Acknowledge the clock interrupt from the interval timer. The interval + timer for Lego comes from the Dallas real-time clock. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + LEGO_WATCHDOG WdRegister; + + static LEGO_WATCHDOG WdRegisterDbg; + static ULONG DbgWdCnt = 0; + static ULONG WdNextService = 0; + static BOOLEAN WdIntervalSet = FALSE; + + // + // Make watchdog service interval a function of the timer period. + // + +#if 1 + static ULONG WdServiceIntervals[8] = {1, 1, 5, 15, 100, 600, 3000, 20000}; +#else + static ULONG WdServiceIntervals[8] = {1, 1, 1, 1, 1, 1, 1, 1}; +#endif + + // + // Acknowledge the clock interrupt by reading the control register C of + // the Real Time Clock. + // + + HalpReadClockRegister( RTC_CONTROL_REGISTERC ); + + // + // If we are to service the Watchdog Timer, do it here + // + // Setting Phase to one will restart the timer... + // [wem] this needs more work. For example, no need to touch it each clock tick!... + // + + if (HalpLegoServiceWatchdog) { + + if (WdNextService==0) { + + // + // read register to get service interval + // + + WdRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoWatchdogQva ); + WdNextService = WdServiceIntervals[WdRegister.TimerOnePeriod]; + +#if DBG + if (!WdIntervalSet) { + DbgPrint(" ",WdRegister.All); + DbgPrint(" ",WdNextService); + WdRegisterDbg.All = WdRegister.All; + WdIntervalSet = TRUE; + } +#endif + } + + WdNextService--; + + // + // If service interval falls to zero, read register to service timer + // + + if (WdNextService==0) { + + WdRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoWatchdogQva ); + +#if DBG + + if (WdRegisterDbg.All != WdRegister.All) { + WdRegisterDbg.All = WdRegister.All; + DbgWdCnt = 0; + } + + if (DbgWdCnt < 2) { + DbgPrint(" ",WdRegister.All); + } + + if ((DbgWdCnt % 10000)==0) { + DbgPrint(" ",WdRegister.All); + DbgWdCnt = 1; + } + + DbgWdCnt++; +#endif + + // + // Reset the timer. This is done by writing 1 then 0 + // to the Watchdog register's Phase bit + // + // If LegoDebugWatchdogIsr is true, let watchdog timer expire. + // This will result in a watchdog interrupt or a system reset + // depending on the watchdog mode. + // + + if (!LegoDebugWatchdogIsr) { +#if 0 + if (HalpLegoWatchdogSingleMode) { + WdRegister.Mode = WATCHDOG_MODE_1TIMER; + } +#endif + WdRegister.Phase = 1; + WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoWatchdogQva, WdRegister.All); + WdRegister.Phase = 0; + WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoWatchdogQva, WdRegister.All); + } + } + } +} diff --git a/private/ntos/nthals/hallego/alpha/lgmapio.c b/private/ntos/nthals/hallego/alpha/lgmapio.c new file mode 100644 index 000000000..02f14a08b --- /dev/null +++ b/private/ntos/nthals/hallego/alpha/lgmapio.c @@ -0,0 +1,232 @@ +/*++ + +Copyright (c) 1993 Digital Equipment Corporation + +Module Name: + + lgmapio.c + +Abstract: + + This module contains the functions to map HAL-accessed I/O addresses + on the Lego systems. + +Author: + + Joe Notarangelo 25-Oct-1993 + +Environment: + + Kernel mode + +Revision History: + + Gene Morgan [Digital] 11-Oct-1995 + + Initial version for Lego. Adapted from Avanti and Mikasa + + +--*/ + +#include "halp.h" +#include "legodef.h" + +// +// Define global data used to locate the EISA control space. +// + +PVOID HalpEisaControlBase; +PVOID HalpEisaIntAckBase; +PVOID HalpCMOSRamBase; + +// +// SIO's Int Ack Register (if it exists) +// +// Used when interrupt accelerator is active, and we +// must not generate PCI Interrupt Acknowledge cycles +// for ISA devices. +// + +PVOID HalpSioIntAckQva; + +// +// Server management and watchdog timer control +// +PVOID HalpLegoServerMgmtQva; +PVOID HalpLegoWatchdogQva; + +// +// PCI Interrupt control +// +PVOID HalpLegoPciInterruptConfigQva; +PVOID HalpLegoPciInterruptMasterQva; +PVOID HalpLegoPciInterruptRegisterBaseQva; +PVOID HalpLegoPciInterruptRegisterQva[4]; +PVOID HalpLegoPciIntMaskRegisterQva[4]; + + +BOOLEAN +HalpMapIoSpace ( + VOID + ) + +/*++ + +Routine Description: + + This routine maps the HAL I/O space for Lego + system using the Quasi VA mechanism. + +Arguments: + + None. + +Return Value: + + If the initialization is successfully completed, than a value of TRUE + is returned. Otherwise, a value of FALSE is returned. + +--*/ + +{ + PVOID PciIoSpaceBase; + + // + // Map base addresses in QVA space. + // + + PciIoSpaceBase = HAL_MAKE_QVA( APECS_PCI_IO_BASE_PHYSICAL ); + + HalpEisaControlBase = PciIoSpaceBase; + + // + // Interrupt Acknowledge ports + // + + HalpEisaIntAckBase = HAL_MAKE_QVA( APECS_PCI_INTACK_BASE_PHYSICAL ); + HalpSioIntAckQva = (PVOID)((ULONG)PciIoSpaceBase + 0x238); + + // + // CMOS ram addresses encoded in nvram.c - kept for commonality + // in environ.c + // + //[wem] NOTE: halavant version of ebmapio.c sets HalpCMOSRamBase to (PVOID)0 ??? + // + + HalpCMOSRamBase = (PVOID) ((ULONG)PciIoSpaceBase + 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); + + // + // Map Lego server management and watchog control registers + // + + HalpLegoServerMgmtQva = (PVOID)((ULONG)PciIoSpaceBase | SERVER_MANAGEMENT_REGISTER); + HalpLegoWatchdogQva = (PVOID)((ULONG)PciIoSpaceBase | WATCHDOG_REGISTER); + + // + // Map Lego PCI Interrupt control registers + // + + HalpLegoPciInterruptConfigQva = (PVOID)((ULONG)PciIoSpaceBase | PCI_INTERRUPT_CONFIG_REGISTER); + HalpLegoPciInterruptMasterQva = (PVOID)((ULONG)PciIoSpaceBase | PCI_INTERRUPT_MASTER_REGISTER); + HalpLegoPciInterruptRegisterBaseQva = (PVOID)((ULONG)PciIoSpaceBase | PCI_INTERRUPT_BASE_REGISTER); + + // + // Lego PCI interrupt state and interrupt mask registers + // + // NOTE: The InterruptRegister Qvas can be used to access the interrupt + // state (via USHORT), or the interrupt state and interrupt mask (via ULONG). + // The IntMaskRegister Qvas can only be used to access the interrupt + // mask (via USHORT). + // + + HalpLegoPciIntMaskRegisterQva[0] = + (PVOID)((ULONG)HalpLegoPciInterruptRegisterBaseQva | PCI_INTMASK_REGISTER_1); + HalpLegoPciIntMaskRegisterQva[1] = + (PVOID)((ULONG)HalpLegoPciInterruptRegisterBaseQva | PCI_INTMASK_REGISTER_2); + HalpLegoPciIntMaskRegisterQva[2] = + (PVOID)((ULONG)HalpLegoPciInterruptRegisterBaseQva | PCI_INTMASK_REGISTER_3); + HalpLegoPciIntMaskRegisterQva[3] = + (PVOID)((ULONG)HalpLegoPciInterruptRegisterBaseQva | PCI_INTMASK_REGISTER_4); + + HalpLegoPciInterruptRegisterQva[0] = + (PVOID)((ULONG)HalpLegoPciInterruptRegisterBaseQva | PCI_INTERRUPT_REGISTER_1); + HalpLegoPciInterruptRegisterQva[1] = + (PVOID)((ULONG)HalpLegoPciInterruptRegisterBaseQva | PCI_INTERRUPT_REGISTER_2); + HalpLegoPciInterruptRegisterQva[2] = + (PVOID)((ULONG)HalpLegoPciInterruptRegisterBaseQva | PCI_INTERRUPT_REGISTER_3); + HalpLegoPciInterruptRegisterQva[3] = + (PVOID)((ULONG)HalpLegoPciInterruptRegisterBaseQva | PCI_INTERRUPT_REGISTER_4); + + 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(APECS_PCI_IO_BASE_PHYSICAL) + ComPortAddress; + + *ReadQva = PortQva; + *WriteQva = PortQva; + + return ComPortAddress; + +} diff --git a/private/ntos/nthals/hallego/alpha/lgsysint.c b/private/ntos/nthals/hallego/alpha/lgsysint.c new file mode 100644 index 000000000..e735721bf --- /dev/null +++ b/private/ntos/nthals/hallego/alpha/lgsysint.c @@ -0,0 +1,679 @@ +/*++ + +Copyright (c) 1993,1995,1996 Digital Equipment Corporation + +Module Name: + + lgsysint.c + +Abstract: + + This module implements the HAL enable/disable system interrupt, and + request interprocessor interrupt routines for the Lego system. + +Author: + + Joe Notarangelo 25-Oct-1993 + +Environment: + + Kernel mode + +Revision History: + + Gene Morgan [Digital] 11-Oct-1995 + Initial version for Lego. Adapted from Avanti and Mikasa + + Gene Morgan 15-Apr-1996 + Remove debugging code. + Add error logging for server management events (e.g., fan and temp) + + +--*/ + +#include "halp.h" +#include "legodef.h" +#include "axp21064.h" + + + +extern ULONG HalpLegoPciRoutingType; +extern BOOLEAN HalpServerMgmtLoggingEnabled; + +// +// External function prototypes +// + +ULONG +HalpGet21064CorrectableVector( + IN ULONG BusInterruptLevel, + OUT PKIRQL Irql + ); + +VOID +HalpSetMachineCheckEnables( + IN BOOLEAN DisableMachineChecks, + IN BOOLEAN DisableProcessorCorrectables, + IN BOOLEAN DisableSystemCorrectables + ); + +// +// Local function prototypes +// + +VOID +HalpDisablePciInterrupt( + IN ULONG Vector + ); + +VOID +HalpDisableServerMgmtInterrupt( + IN ULONG Vector + ); + +VOID +HalpEnablePciInterrupt( + IN ULONG Vector, + IN KINTERRUPT_MODE InterruptMode + ); + +VOID +HalpEnableServerMgmtInterrupt( + IN ULONG Vector, + IN KINTERRUPT_MODE InterruptMode + ); + +// +// Define reference to the builtin device interrupt enables. +// + +extern USHORT HalpBuiltinInterruptEnable; + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE,HalpGetSystemInterruptVector) +#endif + + +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. + // + + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + + // + // If the vector number is within the range of the + // Server Management interrupts, then disable the appropriate + // interrupt. + // + if (Vector >= SERVER_MGMT_VECTORS && + Vector < MAXIMUM_SERVER_MGMT_VECTOR && + Irql == SERVER_MGMT_LEVEL) { + +#if DBG + DbgPrint("Dm<%02x>",Vector); +#endif + HalpDisableServerMgmtInterrupt(Vector); + } + + // + // If the vector number is within the range of the + // ISA interrupts, then disable the ISA interrupt. + // + else if (Vector >= ISA_DEVICE_VECTORS && + Vector < MAXIMUM_ISA_VECTOR && + Irql == ISA_DEVICE_LEVEL) { + +#if DBG + DbgPrint("Ds<%02x>",Vector); +#endif + HalpDisableSioInterrupt(Vector); + } + + // + // If the vector number is within the range of the + // PCI interrupts, then disable the PCI interrupt. + // + else if (Vector >= PCI_DEVICE_VECTORS && + Vector < LEGO_MAXIMUM_PCI_VECTOR && + Irql == PCI_DEVICE_LEVEL) { + +#if DBG + DbgPrint("Dp<%02x>",Vector); +#endif + HalpDisablePciInterrupt(Vector); + } + + // + // If the vector is a performance counter vector or one of the internal + // device vectors then disable the interrupt for the 21064. + // + + else { + + switch (Vector) { + + // + // Performance counter 0 interrupt (internal to 21064) + // + + case PC0_VECTOR: + case PC0_SECONDARY_VECTOR: + +#if DBG + DbgPrint("Dc0<%02x>",Vector); +#endif + HalpDisable21064PerformanceInterrupt( PC0_VECTOR ); + break; + + // + // Performance counter 1 interrupt (internal to 21064) + // + + case PC1_VECTOR: + case PC1_SECONDARY_VECTOR: + +#if DBG + DbgPrint("Dc1<%02x>",Vector); +#endif + HalpDisable21064PerformanceInterrupt( PC1_VECTOR ); + break; + + case CORRECTABLE_VECTOR: + + // + // Disable the correctable error interrupt. + // + + { + EPIC_ECSR Ecsr; + + Ecsr.all = READ_EPIC_REGISTER( + &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->EpicControlAndStatusRegister ); + + Ecsr.Dcei = 0x0; + + WRITE_EPIC_REGISTER( + &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->EpicControlAndStatusRegister, + Ecsr.all ); + + HalpSetMachineCheckEnables( FALSE, TRUE, TRUE ); + + // + // Disable logging of server management errors as well + // + + HalpServerMgmtLoggingEnabled = FALSE; + + break; + } + +#if DBG + default: + + // + // unrecognized + // + + DbgPrint("D?<%02x>",Vector); +#endif + } //end switch Vector + } + + // + // Lower IRQL to the previous level. + // + + KeLowerIrql(OldIrql); + return; +} + +BOOLEAN +HalEnableSystemInterrupt ( + IN ULONG Vector, + IN KIRQL Irql, + IN KINTERRUPT_MODE InterruptMode + ) + +/*++ + +Routine Description: + + This routine enables the specified system interrupt. + +Arguments: + + Vector - Supplies the vector of the system interrupt that is enabled. + + Irql - Supplies the IRQL of the interrupting source. + + InterruptMode - Supplies the mode of the interrupt; + LevelSensitive or Latched. + +Return Value: + + TRUE if the system interrupt was enabled + +--*/ + +{ + BOOLEAN Enabled = FALSE; + ULONG Irq; + KIRQL OldIrql; + + // + // Raise IRQL to the highest level. + // + + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + + // + // If the vector number is within the range of the + // Server Management interrupts, then enable the appropriate + // interrrupt. + // + if (Vector >= SERVER_MGMT_VECTORS && + Vector < MAXIMUM_SERVER_MGMT_VECTOR && + Irql == SERVER_MGMT_LEVEL) { + +#if DBG + DbgPrint("Em<%02x,%02x>",Vector,InterruptMode); +#endif + HalpEnableServerMgmtInterrupt(Vector,InterruptMode); + Enabled = TRUE; + } + + // + // If the vector number is within the range of the + // ISA interrupts, then enable the ISA interrupt and + // set the Level/Edge register. + // + else if (Vector >= ISA_DEVICE_VECTORS && + Vector < MAXIMUM_ISA_VECTOR && + Irql == ISA_DEVICE_LEVEL) { + +#if DBG + DbgPrint("Es<%02x,%02x>",Vector,InterruptMode); +#endif + HalpEnableSioInterrupt( Vector, InterruptMode ); + Enabled = TRUE; + } + + // + // If the vector number is within the range of the + // PCI interrupts, then enable the PCI interrupt. + // + else if (Vector >= PCI_DEVICE_VECTORS && + Vector < LEGO_MAXIMUM_PCI_VECTOR && + Irql == PCI_DEVICE_LEVEL) { + +#if DBG + DbgPrint("Ep<%02x,%02x>",Vector,InterruptMode); +#endif + HalpEnablePciInterrupt(Vector, InterruptMode); + Enabled = TRUE; + } + + // + // If the vector is a performance counter vector or one of the + // internal device vectors then perform 21064-specific enable. + // + else { + + switch (Vector) { + + // + // Performance counter 0 (internal to 21064) + // + + case PC0_VECTOR: + case PC0_SECONDARY_VECTOR: + +#if DBG + DbgPrint("Ec0<%02x,%02x>",Vector,Irql); +#endif + HalpEnable21064PerformanceInterrupt( PC0_VECTOR, Irql ); + Enabled = TRUE; + break; + + // + // Performance counter 1 (internal to 21064) + // + + case PC1_VECTOR: + case PC1_SECONDARY_VECTOR: + +#if DBG + DbgPrint("Ec1<%02x,%02x>",Vector,Irql); +#endif + HalpEnable21064PerformanceInterrupt( PC1_VECTOR, Irql ); + Enabled = TRUE; + break; + + case CORRECTABLE_VECTOR: + + // + // Enable the correctable error interrupt. + // + + { + EPIC_ECSR Ecsr; + + Ecsr.all = READ_EPIC_REGISTER( + &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->EpicControlAndStatusRegister ); + + Ecsr.Dcei = 0x1; + + WRITE_EPIC_REGISTER( + &((PEPIC_CSRS)(APECS_EPIC_BASE_QVA))->EpicControlAndStatusRegister, + Ecsr.all ); + + HalpSetMachineCheckEnables( FALSE, FALSE, FALSE ); + + // + // Will log server management errors as well + // + + HalpServerMgmtLoggingEnabled = TRUE; + + Enabled = TRUE; + break; + + } + +#if DBG + default: + + // + // not enabled + // + + DbgPrint("E?<%02x,%02x,%02x>",Vector,Irql,InterruptMode); +#endif + + } //end switch Vector + } + + // + // 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 ISA 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; + +#if DBG + DbgPrint("GIV< l:%02x, v:%02x => ", + BusInterruptLevel,BusInterruptVector); +#endif + + *Affinity = 1; + + switch (InterfaceType) { + + case ProcessorInternal: + + // + // Handle the internal defined for the processor itself + // and used to control the performance counters and + // correctable errors in the 21064. + // + + Vector = HalpGet21064PerformanceVector(BusInterruptLevel,Irql); + + if (Vector != 0) { + +#if DBG + DbgPrint("PIperf: i:%02x, v:%02x >.", Vector, *Irql); +#endif + + return Vector; // Performance counter interrupt + } + + Vector = HalpGet21064CorrectableVector( BusInterruptLevel,Irql); + + if (Vector != 0) { + +#if DBG + DbgPrint("PIcorr: i:%02x, v:%02x >.", Vector, *Irql); +#endif + + return Vector; // Correctable error interrupt + } + + // Check for unrecognized processor interrupt. + // + if (Vector == 0) { + *Irql = 0; + *Affinity = 0; + } + +#if DBG + DbgPrint("PI: i:00, v:00 >."); +#endif + return Vector; // zero if unrecognized interrupt + + case Internal: + + // + // This bus type is for things connected to the processor + // in some way other than a standard bus, e.g., (E)ISA, PCI. + // Since devices on this "bus," apart from the special case of + // the processor, above, interrupt via the 82c59 cascade in the + // ESC, we assign vectors based on (E)ISA_VECTORS - see below. + // Firmware must agree on these vectors, as it puts them in + // the CDS. + // + // Assume interrupt can be mapped to Lego System Management. + // [wem] ??? check this ? + // + *Irql = SERVER_MGMT_LEVEL; + + // The vector is equal to the specified bus level plus + // SERVER_MGMT_VECTORS. + // +#if DBG + DbgPrint("SM: i:%02x, v:%02x >.", + SERVER_MGMT_LEVEL, + BusInterruptLevel + SERVER_MGMT_VECTORS); +#endif + return(BusInterruptLevel + SERVER_MGMT_VECTORS); + + case PCIBus: + + //[wem] if interrupt accelerator is enabled, direct + // PCI interrupts via the PCI_DEVICE_VECTORS + // Otherwise, fall into the ISA case... + // + if (HalpLegoPciRoutingType == PCI_INTERRUPT_ROUTING_FULL) { + + // + // All PCI devices coming in on same CPU IRQ pin + // + *Irql = PCI_DEVICE_LEVEL; + + // + // The vector is equal to the specified bus level + // plus the PCI Device Vector base + // +#if DBG + DbgPrint("PCI: i:%02x, v:%02x >.", + PCI_DEVICE_LEVEL, + BusInterruptLevel + PCI_DEVICE_VECTORS); +#endif + return((BusInterruptLevel) + PCI_DEVICE_VECTORS); + +#if DBG + } else { + + // + // Fall into ISA interrupt handling code + // + + DbgPrint("PCI*"); +#endif + } + + case Isa: + + // + // Assumes all ISA devices coming in on same pin + // + *Irql = ISA_DEVICE_LEVEL; + + // + // The vector is equal to the specified bus level plus + // the ISA_VECTOR. This is assuming that the ISA levels + // not assigned Interrupt Levels in the Beta programming + // guide are unused in the LCA system. Otherwise, need + // a different encoding scheme. + // + // Not all interrupt levels are actually supported on Beta; + // Should we make some of them illegal here? + // + +#if DBG + DbgPrint("ISA: i:%02x, v:%02x >.", + ISA_DEVICE_LEVEL, + BusInterruptLevel + ISA_DEVICE_VECTORS); +#endif + return(BusInterruptLevel + ISA_DEVICE_VECTORS); + + case Eisa: + + //[wem] Should never occur + // + // Assumes all EISA devices coming in on same pin + // + *Irql = EISA_DEVICE_LEVEL; + + // + // The vector is equal to the specified bus level plus the EISA_VECTOR. + // + return(BusInterruptLevel + EISA_VECTORS); + + default: + + // + // Not an interface supported on Lego systems + // +#if DBG + DbgPrint("LGSYSINT: InterfaceType (%d) not supported.\n", + InterfaceType); +#endif +#if DBG + DbgPrint("?: i:00, v:00 >."); +#endif + *Irql = 0; + *Affinity = 0; + return(0); + + } //end switch(InterfaceType) + +} + +VOID +HalRequestIpi ( + IN ULONG Mask + ) + +/*++ + +Routine Description: + + This routine requests an interprocessor interrupt on a set of processors. + This routine performs no function on an Avanti because it is a + uni-processor system. + +Arguments: + + Mask - Supplies the set of processors that are sent an interprocessor + interrupt. + +Return Value: + + None. + +--*/ + +{ + + return; +} diff --git a/private/ntos/nthals/hallego/alpha/machdep.h b/private/ntos/nthals/hallego/alpha/machdep.h new file mode 100644 index 000000000..264be0ec2 --- /dev/null +++ b/private/ntos/nthals/hallego/alpha/machdep.h @@ -0,0 +1,46 @@ +/*++ + +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: + + Gene Morgan [Digital] 11-Oct-1995 + + Initial version for Lego. Adapted from Avanti. + + +--*/ + +#ifndef _MACHDEP_ +#define _MACHDEP_ + +// +// Include Lego platform-specific definitions. +// + +#include "legodef.h" + +// +// Include scatter/gather definitions. +// + +#include "ebsgdma.h" + +#endif //_MACHDEP_ diff --git a/private/ntos/nthals/hallego/alpha/memory.c b/private/ntos/nthals/hallego/alpha/memory.c new file mode 100644 index 000000000..76b1eb7df --- /dev/null +++ b/private/ntos/nthals/hallego/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/hallego/alpha/nvenv.c b/private/ntos/nthals/hallego/alpha/nvenv.c new file mode 100644 index 000000000..ba5a5c8f7 --- /dev/null +++ b/private/ntos/nthals/hallego/alpha/nvenv.c @@ -0,0 +1 @@ +#include "..\halalpha\nvenv.c" diff --git a/private/ntos/nthals/hallego/alpha/nvram.c b/private/ntos/nthals/hallego/alpha/nvram.c new file mode 100644 index 000000000..879c41c68 --- /dev/null +++ b/private/ntos/nthals/hallego/alpha/nvram.c @@ -0,0 +1 @@ +#include "..\halalpha\nvram.c" diff --git a/private/ntos/nthals/hallego/alpha/pcd8584.c b/private/ntos/nthals/hallego/alpha/pcd8584.c new file mode 100644 index 000000000..981a3aca3 --- /dev/null +++ b/private/ntos/nthals/hallego/alpha/pcd8584.c @@ -0,0 +1,653 @@ +/*++ + +Copyright (c) 1994,1995,1996 Digital Equipment Corporation + +Module Name: + + pcd8584.c + +Abstract: + + This module contains the routines that support operations + on the PCD8584 I2C bus controller. + +Author: + + James Livingston [DEC] 13-Sep-1994 + +Environment: + + Alpha AXP ARC firmware + +Revision History: + + Gene Morgan (Digital) 08-Nov-1995 + Adapted for LEGO platforms from Mikasa + + Gene Morgan 15-Apr-1996 + Cleanup, fix OCP corruption problem. + + +--*/ + +#include +#include "halp.h" +#include "string.h" +#include "arccodes.h" +#include "pcd8584.h" + +extern PVOID HalpEisaControlBase; + +BOOLEAN PcdValid = FALSE; + +// +// I2C data and csr ports. +// +ULONG I2cInterfaceCsrPort; +ULONG I2cInterfaceDataPort; + +// +// Data for testing internal registers in the PCD8584 I2C bus controller. +// +I2C_TEST_REG I2cTestReg[] = { "CSR", I2C_STATUS, 0x3d, 0xff, + "S0", I2C_DATA, 0x7f, I2C_S0, + "S2", I2C_DATA, 0x1f, I2C_S2, + "S3", I2C_DATA, 0xff, I2C_S3, + }; + +// +// External prototypes +// + +static VOID +FwStallExecution ( + IN ULONG MicroSeconds + ) +{ + HalpStallExecution(MicroSeconds); +} + +// +// Private function prototypes +// + +VOID +FwPcdWrite( + IN UCHAR Argument, + IN UCHAR Register + ); + +UCHAR +FwPcdRead( + IN UCHAR Register + ); + +ARC_STATUS +FwPcdStatusWaitWithTimeout( + BOOLEAN BusIdle, + BOOLEAN PendingInterrupt, + BOOLEAN AckByte, + ULONG Timeout + ); + +// +// Code begins. +// + +ARC_STATUS +FwPcdInit( + ULONG I2cCsrPort, + ULONG I2cDataPort + ) +/*++ + +Routine Description: + + This function initializes the PCD8584 I2C controller for use in + writing to the LCD display on the Mikasa Operator Control Panel. + +Arguments: + + None. + +Return Value: + + ESUCCESS - Everything's ready to go. + ENODEV - Something's wrong. + +--*/ + +{ + UCHAR Datum; + UCHAR DataRead; + ARC_STATUS Status; + ULONG i; + + // + // Set the csr and data port for I2C bus. + // + I2cInterfaceCsrPort = I2cCsrPort; + I2cInterfaceDataPort = I2cDataPort; + +#if 0 // Done by firmware -- don't do it again + + // + // Write the PIN bit to "1", as Dave Baird discovered was a + // requirement some years back. + // + // This should turn off ESO + // + //[wem] ??? needed for Lego ? + // + FwPcdWrite(I2C_PIN, I2C_STATUS); + FwPcdWrite(I2C_PIN, I2C_STATUS); + + // + // Initialize the PCD8584 with its own node address. A write + // to this register must be the first access to the device + // after a reset. + // + //[wem] OK for Lego. + // + Datum = (I2C_MASTER_NODE >> 1) & 0x7f; + FwPcdWrite(I2C_S0P, I2C_STATUS); //[wem] Lego spec recommends I2C_PIN also + FwPcdWrite(I2C_S0P, I2C_STATUS); //[wem] Lego spec recommends I2C_PIN also + FwPcdWrite(Datum, I2C_DATA); + FwPcdWrite(Datum, I2C_DATA); + + // + // Define clock frequencies for the I2C bus. After this is done + // we should be able to write to a node on the bus. + // + //[wem] OK for Lego. + // + FwPcdWrite(I2C_S2, I2C_STATUS); //[wem] Lego spec recommends I2C_PIN also + FwPcdWrite(I2C_S2, I2C_STATUS); //[wem] Lego spec recommends I2C_PIN also + FwPcdWrite(I2C_CLOCK, I2C_DATA); + FwPcdWrite(I2C_CLOCK, I2C_DATA); + + // jwlfix - this is to see what we can read from the PCD8584. + // We'll want to get rid of it when things start doing + // what we want. For now, it's a good verification that + // we're able to reach the device. + // + //[wem] If all the reads return 0xFF, assume no I2C bus is present (and return ENODEV) + // +#if 0 + for (i = 0; i < 4; i++) { + if (I2cTestReg[i].Setup != -1) { + FwPcdWrite(I2cTestReg[i].Setup, I2C_STATUS); + } + DataRead = FwPcdRead(I2cTestReg[i].Target); + +#ifdef DBG + DbgPrint("Pcd8584: register %s = 0x%2x\r\n", I2cTestReg[i].Name, + DataRead); +#endif + if (DataRead != (UCHAR)0xFF) { + // Good. + PcdValid = TRUE; + } + } +#else + PcdValid = TRUE; +#endif + + // + // Issue Stop command (twice) + // + //[wem] recommended for Lego. + // + FwPcdWrite(I2C_STOP, I2C_STATUS); + FwPcdWrite(I2C_STOP, I2C_STATUS); + +#if 0 //[wem] needed for Lego ? + // + // Now write communication initialization + // to the PCD8584 CSR (S1). + // This must be done only once, so we do it here. + // + + FwPcdWrite(I2C_INIT, I2C_STATUS); //[wem] Lego spec recommends I2C_PIN | I2C_ACKB also +#endif +#endif + + PcdValid = TRUE; + + return ((PcdValid) ? ESUCCESS : ENODEV); +} + + +VOID +FwPcdWrite( + UCHAR Argument, + UCHAR Register + ) +/*++ + +Routine Description: + + This function writes a byte to one of the two EISA interface + registers of the PCD8584 I2C bus controller. + +Arguments: + + Argument - The byte to be written. + + Register - Selector for the EISA port to be written. + +Return Value: + + None. + +--*/ + +{ + ULONG Offset = Register ? I2cInterfaceCsrPort : I2cInterfaceDataPort; + + WRITE_PORT_UCHAR((PUCHAR)((ULONG)HalpEisaControlBase | Offset), Argument); + + return; +} + +UCHAR +FwPcdRead( + UCHAR Register + ) +/*++ + +Routine Description: + + This function reads a byte from one of the two EISA interface + registers of the PCD8584 I2C bus controller. + +Arguments: + + Register - Selector for the EISA port to be read. + +Return Value: + + Character supplied by the PCD8584. + +--*/ + +{ + ULONG Offset = Register ? I2cInterfaceCsrPort : I2cInterfaceDataPort; + UCHAR Datum; + + Datum = READ_PORT_UCHAR((PUCHAR)((ULONG)HalpEisaControlBase | Offset)); + + return Datum; +} + +ARC_STATUS +FwI2cWrite( + UCHAR Node, + UCHAR Datum + ) +/*++ + +Routine Description: + + This function sends a data byte to the specified node on the I2C bus. + +Arguments: + + Node - The I2C address to which the data byte should go. + + Datum - The data byte. + +Return Value: + + ESUCCESS - The operation succeeded. + ENODEV - Something's wrong. + +--*/ + +{ + BOOLEAN BusIdle; + BOOLEAN PendingInterrupt; + BOOLEAN AckByte; + ARC_STATUS Status; + ULONG Timeout; + ULONG Count; + +#if 0 + if (!PcdValid) return ENODEV; +#endif + + // + // Set timeout to 100ms. + // + + Timeout = 100 * 1000; + + // + // Mask off the low-order node number bit, then write the + // result to the PCD8584 DATA register. + // + + Status = FwPcdStatusWaitWithTimeout( BusIdle = TRUE, + PendingInterrupt = FALSE, + AckByte = FALSE, + Timeout ); + if( Status != ESUCCESS ){ +#if DBG + DbgPrint ("I2C: Timeout waiting for bus idle, status=%X\r\n",Status); +#endif + return Status; + } + + FwPcdWrite((Node & 0xfe) | I2C_WRITE_DIR, I2C_DATA); + + // + // Now start up the PCD8584 communication with the specified node. + // + Count = 10; + while (1) { + + FwPcdWrite(I2C_START, I2C_STATUS); + + FwStallExecution(__1MSEC*1); // The device is picky about how quickly + // you may access it again. + // Wait for PIN to drop + // + //[wem] Lego repeated start inside loop -- is this OK ? + //[wem] Lego -- is 10ms long enough? + // + Status = FwPcdStatusWaitWithTimeout( BusIdle = FALSE, + PendingInterrupt = TRUE, + AckByte = FALSE, + 10 * 1000 ); + if( Status == ESUCCESS){ + break; + } else { + if (Count-- == 0) { +#if DBG + DbgPrint ("I2C: Timeout during addr phase, status=%X\r\n",Status); +#endif + return Status; // status from wait + } + } + } + + // + // Write the desired datum onto the bus. We can do this lots of + // times, if we wish, without restarting the process. That'll be + // another direction of exploration, as time permits. + // + + + //[wem] Should check for LRB (lost arbitration) set before writing. + //[wem] If LRB set, then issue Stop. + + FwPcdWrite(Datum, I2C_DATA); + FwPcdWrite(I2C_START, I2C_STATUS); + + // + //[wem] Wait for PIN to drop + // + + FwStallExecution(__1MSEC*1); // The device is picky about how quickly + // you may access it again. + + Status = FwPcdStatusWaitWithTimeout( BusIdle = FALSE, + PendingInterrupt = TRUE, + AckByte = FALSE, + Timeout ); + if( Status != ESUCCESS ){ +#if DBG + DbgPrint ("I2C: Timeout during data phase, status=%X\r\n",Status); +#endif + return Status; // status from wait + } + + // + // Finally, close down the communication with the target node. + // + //[wem] If LRB is still clear, it is safe to issue + //[wem] another data write. Otherwise, must issue Stop. + + FwStallExecution(__1MSEC*1); // The device is picky about how quickly + + Count = 10; + while (1) { + + FwPcdWrite(I2C_STOP, I2C_STATUS); + + FwStallExecution(__1MSEC*1); // The device is picky about how quickly + // you may access it again. + + // Wait for PIN to drop + // + //[wem] Lego repeated start inside loop -- is this OK ? + //[wem] Lego -- is 10ms long enough? + // + Status = FwPcdStatusWaitWithTimeout( BusIdle = FALSE, + PendingInterrupt = TRUE, + AckByte = TRUE, + 10 * 1000 ); + if( Status == ESUCCESS){ + break; + } else { + if (Count-- == 0) { +#if DBG + DbgPrint ("I2C: Timeout during stop, status=%X\r\n",Status); +#endif + return Status; // status from wait + } + } + } + + // + // And this writes just a single byte to the I2C bus; whew! We'd + // like to get smarter, when this works right. + // + + return ESUCCESS; +} + +ARC_STATUS +FwI2cRead( + IN UCHAR Node, + OUT PUCHAR ReadDatum + ) +/*++ + +Routine Description: + + This function receives a single data byte from a node on + the I2C bus. + +Arguments: + + Node - The I2C address from which the data byte should come. + +Return Value: + + The data byte. + +--*/ + +{ + ARC_STATUS Status; + + *ReadDatum = 0; + Status = ESUCCESS; + + if (!PcdValid) return ENODEV; + +// jwlfix - currently unused function, and probably incorrect. +#if 0 + I2C_STATUS_BITS I2cStatus; + + // + // Mask off the low-order node number bit, then write the + // result to the PCD8584 DATA register. + // + do { + I2cStatus.All = FwPcdRead(I2C_STATUS); + } while (I2cStatus.NotBusBusy == 0); + FwPcdWrite((Node & 0xfe) | I2C_READ_DIR, I2C_DATA); + + // + // Now start up the PCD8584 communication with the specified node. + // + do { + I2cStatus.All = FwPcdRead(I2C_STATUS); + } while (I2cStatus.NotBusBusy == 0); + FwPcdWrite(I2C_START, I2C_STATUS); + + // + // Read the desired datum from the bus: first wait for PIN to + // clear, then NACK the transmission, since we're only reading + // the single byte; next, read a byte. That byte is the + // address we wrote into the data port, increased by one. Why? + // Dunno; that's just what happens, currently. + // + do { + I2cStatus.All = FwPcdRead(I2C_STATUS); + } while (I2cStatus.NotPendingInterrupt == 1); + FwPcdWrite(I2C_NACK, I2C_STATUS); + ReadDatum = FwPcdRead(I2C_DATA); + // + // Now we wait for PIN to clear, saying that we've received + // the byte acutally sent by the node, and then read that. + // + do { + I2cStatus.All = FwPcdRead(I2C_STATUS); + } while (I2cStatus.NotPendingInterrupt == 1); + ReadDatum = FwPcdRead(I2C_DATA); + + // + // Finally, close down the communication with the target node. + // + FwPcdWrite(I2C_STOP, I2C_STATUS); +#endif + return Status; +} + + +ARC_STATUS +FwPcdStatusWaitWithTimeout ( + BOOLEAN BusIdle, + BOOLEAN PendingInterrupt, + BOOLEAN AckByte, + ULONG Timeout + ) +/*++ + +Routine Description: + + Wait for the desired I2C bus status state with a timeout value. + + N.B. - This routine will only wait for one of the two states that + can be specified. + +Arguments: + + BusIdle - Supplies a boolean that if true specifies that the + routine should wait for status to indicate that the bus is + not busy (NotBusBusy == 1). + + PendingInterrupt - Supplies a boolean that if true specifies that + the routine should wait for status to indicate that + there is a pending interrupt (NotPendingInterrupt == 0). + + AckByte - true indicates that the routine should wait for + status to indicate that status == PIN + ACKB + + Timeout - Supplies the timeout value in microseconds. + +Return Value: + + The status of the operation. ESUCCESS is returned if the specified + status is read on the bus before the timeout expires. EBUSY is + returned if the operation times out. + +Notes: + + [wem] This routine should also check for lost arbitration. + +--*/ + +{ + LONG CyclesBeforeTimeout; + ULONG CycleCount; +#if 0 //[wem] redundant? + extern ULONG HalpClockMegaHertz; +#endif + ULONG ElapsedCycles; + I2C_STATUS_BITS I2cStatus; + ULONG PreviousCycleCount; + ARC_STATUS Status; + int MinLoopCnt; + + // + // Compute Cycles to wait. + // + + CyclesBeforeTimeout = Timeout * HalpClockMegaHertz; + + // + // Capture initial time. + // + + PreviousCycleCount = HalpRpcc(); + + // + // Continue the loop while waiting for the timeout. Assume timeout + // status. + // + + Status = EBUSY; + + while( CyclesBeforeTimeout > 0){ + + I2cStatus.All = FwPcdRead(I2C_STATUS); + + // + // Check for bus not busy. + // + + if( (BusIdle == TRUE) && (I2cStatus.NotBusBusy == 1) ){ + Status = ESUCCESS; + break; + } + + // + // Check for pending interrupt. + // + //[wem] AckByte case is to recognize successful + //[wem] stop command for Lego. + // + + if (PendingInterrupt == TRUE) { + if (AckByte == TRUE) { + if (I2cStatus.NotPendingInterrupt == 1 + && I2cStatus.NotBusBusy == 1) { + Status = ESUCCESS; + break; + } + } else { + if (I2cStatus.NotPendingInterrupt == 0) { + Status = ESUCCESS; + break; + } + } + } + + // + // Update the number of cycles remaining before timeout. + // + + CycleCount = HalpRpcc(); + ElapsedCycles = CycleCount - PreviousCycleCount; + CyclesBeforeTimeout -= ElapsedCycles; + PreviousCycleCount = CycleCount; + + } + + return Status; + +} diff --git a/private/ntos/nthals/hallego/alpha/pcd8584.h b/private/ntos/nthals/hallego/alpha/pcd8584.h new file mode 100644 index 000000000..3344e42c5 --- /dev/null +++ b/private/ntos/nthals/hallego/alpha/pcd8584.h @@ -0,0 +1,196 @@ +/*++ + +Copyright (c) 1994 Digital Equipment Corporation + +Module Name: + + pcd8584.h + +Abstract: + + This module contains the definitions that support the PCD8584 I2C + bus controller. + +Author: + + James Livingston [DEC] 13-Sep-1994 + +Environment: + + Alpha AXP ARC firmware + +Revision History: + + Gene Morgan (Digital) 08-Nov-1995 + Adapted for LEGO platforms from Mikasa + +--*/ + +#if !defined (_LANGUAGE_ASSEMBLY) +// +// jwlfix - These definitions are used in unused test code. +// +typedef struct _I2C_TEST_REG { + PUCHAR Name; + ULONG Target; + UCHAR Mask; + UCHAR Setup; +} I2C_TEST_REG, *PI2C_TEST_REG; + +// +// The following definitions are used to program the PCD8584 I2C bus +// controller. +// +typedef union _I2C_CONTROL_BITS{ + struct { + UCHAR AckEachByte: 1; + UCHAR SendStop: 1; + UCHAR SendStart: 1; + UCHAR ExtInterruptEnable: 1; + UCHAR Reserved: 2; + UCHAR EnableSerialOutput: 1; + UCHAR NotPendingInterrupt: 1; + }; + UCHAR All; +} I2C_CONTROL_BITS, *PI2C_CONTROL_BITS; + +typedef union _I2C_STATUS_BITS{ + struct { + UCHAR NotBusBusy: 1; + UCHAR LostArbitration: 1; + UCHAR AddressedAsSlave: 1; + UCHAR Address0LastRBit: 1; + UCHAR BusError: 1; + UCHAR ExternalStop: 1; + UCHAR Reserved: 1; + UCHAR NotPendingInterrupt: 1; + }; + UCHAR All; +} I2C_STATUS_BITS, *PI2C_STATUS_BITS; + +#endif // !defined (_LANGUAGE_ASSEMBLY) + +#define __1MSEC 1000 +#define __HALF_MSEC 500 +#define __1USEC 1 + +#define I2C_DATA 0 +#define I2C_STATUS 1 +#define I2C_MASTER_NODE 0xb6 + +//[wem] It probably doesn't matter, but I2C_MASTER_NODE +//[wem] should be in machine dependent file. +//#define I2C_MASTER_NODE 0xaa //[wem] as per LEGO spec + +// +// Control register bit definitions +// +#define I2C_S0 0x00 // Data register +#define I2C_S0P 0x00 // Own address register +#define I2C_S2 0x20 // Clock register +#define I2C_S3 0x10 // Interrupt vector register + +// +// Clock register SCL (data clocking) frequency bit definitions +// +#define I2C_SCL_90 0x00 // 90 KHz +#define I2C_SCL_45 0x01 // 45 KHz +#define I2C_SCL_11 0x02 // 11 KHz +#define I2C_SCL_15 0x03 // 1.5 KHz + +// +// Clock register input clock frequency bit definitions. +// +#define I2C_CLOCK_3 0x00 // 3 MHz +#define I2C_CLOCK_443 0x10 // 4.3 MHz +#define I2C_CLOCK_6 0x14 // 6 MHz +#define I2C_CLOCK_8 0x18 // 8 MHz +#define I2C_CLOCK_12 0x1c // 12 MHz + +// +// I2C bus control byte bit definitions +// +#define I2C_ACKB 0x01 // Ack each byte sent +#define I2C_STO 0x02 // Send stop condition +#define I2C_STA 0x04 // Send start condition +#define I2C_ENI 0x08 // Enable external interrupt +#define I2C_ESO 0x40 // Enable serial output +#define I2C_PIN 0x80 // Pending interrupt NOT + +// +// Data direction (PCD8584 state) flags +// +#define I2C_WRITE_DIR 0x00 +#define I2C_READ_DIR 0x01 +#define I2C_IDLE 0x02 +#define I2C_S_WRITE 0x03 +#define I2C_S_READ 0x04 +#define I2C_SR_DONE 0x0a + +// +// Setup condition constants for this implementation. +// +// Dave Baird's and Carey McMasters' choices: +//#define I2C_CLOCK (I2C_SCL_90 | I2C_CLOCK_6) +// +// LEGO Settings [wem] ??? check this ? +// +// I2C_CLOCK should be in machine-dependent section, +// unlike the bulk of this file. +// +//#define I2C_CLOCK (I2C_SCL_90 | I2C_CLOCK_12) +// +#define I2C_CLOCK (I2C_SCL_90 | I2C_CLOCK_8) + +// +// jwlfix - These would need to be defined as bit-field assignments, +// e.g., +// +// I2C_STOP: +// --------- +// ((PI2C_CONTROL_BITS)&Datum)->AckEachByte = 1; +// ((PI2C_CONTROL_BITS)&Datum)->SendStop = 1; +// ((PI2C_CONTROL_BITS)&Datum)->EnableSerialOutput = 1; +// ((PI2C_CONTROL_BITS)&Datum)->NotPendingInterrupt = 1; +// +// for stylistic consistency. We'll see if that's a better +// way to do it after the function's running. I suppose it's +// a matter of what the compiler generates, in each case. +// +#define I2C_STOP (I2C_S0 | I2C_ESO | I2C_ACKB | I2C_STO | I2C_PIN) +#if 0 //[wem] set PIN for Lego. +#define I2C_START (I2C_S0 | I2C_ESO | I2C_ACKB | I2C_STA) +#else +#define I2C_START (I2C_S0 | I2C_ESO | I2C_ACKB | I2C_STA | I2C_PIN) +#endif +#define I2C_INIT (I2C_S0 | I2C_ESO) +#define I2C_NACK (I2C_S0 | I2C_ESO) +#define I2C_ACK (I2C_S0 | I2C_ESO | I2C_ACKB) + +#define I2C_MASTER_TYPE 0 +#define I2C_LED_TYPE 1 + +// +// Function prototypes +// +#if !defined (_LANGUAGE_ASSEMBLY) + +ARC_STATUS +FwPcdInit( + ULONG I2cCsrPort, + ULONG I2cDataPort + ); + +ARC_STATUS +FwI2cWrite( + UCHAR Node, + UCHAR Datum + ); + +ARC_STATUS +FwI2cRead( + IN UCHAR Node, + OUT PUCHAR ReadDatum + ); + +#endif // !defined (_LANGUAGE_ASSEMBLY) diff --git a/private/ntos/nthals/hallego/alpha/pcf8574.c b/private/ntos/nthals/hallego/alpha/pcf8574.c new file mode 100644 index 000000000..65f1f21ec --- /dev/null +++ b/private/ntos/nthals/hallego/alpha/pcf8574.c @@ -0,0 +1,336 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation +Copyright (c) 1994,1995,1996 Digital Equipment Corporation + +Module Name: + + pcf8574.c + +Abstract: + + This module contains the routines that operate the 8-character + display on Lego's Operator Console Panel. + + The OCP display is implemented via two PCF8574's, which + drive the LED display, select which character position will + be written, and select which character to write. + + This module uses a subset of interface defined in ocplcd.c for + Mikasa and others. Lego uses a much simpler device, so some of + the functions defined for Mikasa are not needed. + +Author: + + Gene Morgan (Digital) + +Environment: + + Alpha AXP ARC firmware. + +Revision History: + + Gene Morgan (Digital) 11-Nov-1995 + Initial version + + Gene Morgan 15-Apr-1996 + Cleanup, add HalpOcpTestDisplay() and HalpOcpPutSlidingString() + +--*/ + +#include "halp.h" +#include "legodef.h" +#include "arccodes.h" +#include "pcf8574.h" +#include "pcd8584.h" + +// +// OcpValid -- Gate for access to OCP. +// Init code will set to TRUE if OCP is reachable +// If FALSE, OCP access routines become no-ops +// + +BOOLEAN OcpValid = FALSE; + +ARC_STATUS +HalpOcpInitDisplay( + VOID + ) +/*++ + +Routine Description: + + Initialize the display and the PCF8574 control register. + + This sequence must be completed before any characters + are written to the device. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + ARC_STATUS sts; + + if (OcpValid) { + + //[wem] Attempt to reach OCP device? + //[wem] Or let FwI2cWrite() fail? + // + //return ENODEV; + + return ESUCCESS; + } + + FwPcdInit(I2C_INTERFACE_CSR_PORT, I2C_INTERFACE_DATA_PORT); + + // + // Issue a reset. + // + +#if 0 //[wem] not tested + + sts = FwI2cWrite(OCP_SLAVE_CONTROL, OCP_CMD_INIT); // Turn on Reset, Chip Enable, and Read + if (sts != ESUCCESS) { + OcpValid = FALSE; + return sts; + } + + sts = FwI2cWrite(OCP_SLAVE_CONTROL, OCP_CMD_INITCLR); // Clear Reset, leave Chip Enable asserted + if (sts != ESUCCESS) { + OcpValid = FALSE; + return sts; + } +#endif + + OcpValid = TRUE; + + return ESUCCESS; +} + +VOID +HalpOcpTestDisplay( + VOID + ) +/*++ + +Routine Description: + + Display text sequences to allow visual checkout + of OCP. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + + UCHAR string[9] = " "; + int index, i, j, k; + + for (index=0;index<100;index++) { + string[7] = 'A' + (index % 26); + HalpOcpPutString(string, 8, 0); + for (i=0;i<7;i++) { + string[i] = string[i+1]; + } + } + + for (i=0;i<32;i++) { + + string[0] = '0' + (i / 10); + string[1] = '0' + (i % 10); + string[2] = ' '; + string[3] = ' '; + HalpOcpPutString(string, 4, 0); + + HalpStallExecution(__1MSEC * 100); + + for (j=0;j<8;j++) { + string[j] = (i*8)+j; + } + + for (j=0;j<5;j++) { + HalpOcpPutString(string, 8, 0); + } + + HalpStallExecution(__1MSEC * 100); + } +} + +VOID +HalpOcpClearDisplay( + VOID + ) + +/*++ + +Routine Description: + + Clear the display of the Operator Control + Panel (OCP). + +Arguments: + + None + +Return Value: + + None. + +Notes: + + (1) Turn on Reset, Chip Enable, and Write + (2) Clear Reset, leave Chip Enable asserted + +--*/ +{ + + if (!OcpValid) return; + + FwI2cWrite(OCP_SLAVE_CONTROL, OCP_CMD_RESET); + FwI2cWrite(OCP_SLAVE_CONTROL, OCP_CMD_CLEAR); + +} + +VOID +HalpOcpPutString( + IN PUCHAR String, + IN ULONG Count, + IN ULONG Start + ) + +/*++ + +Routine Description: + + Prints a string to the Operator Control + Panel (OCP). + +Arguments: + + String - An ASCII character string for display on the OCP. + Count - The number of characters in the argument string. + Start - Starting position on the OCP (0..7) + +Return Value: + + None. + +--*/ +{ + PUCHAR ArgString = String; + ULONG CharCount, End; + + if (!OcpValid) return; + + // + // Limit the string to a maximum of OCP_SIZE characters. + // + End = (Start+Count > OCP_SIZE) ? OCP_SIZE : Start+Count; + + for (CharCount = Start; CharCount < End; CharCount++) { + HalpOcpPutByte((UCHAR)CharCount, *ArgString++); + } + return; +} + +VOID +HalpOcpPutSlidingString( + IN PUCHAR String, + IN ULONG Count + ) + +/*++ + +Routine Description: + + Prints a sliding string to the Operator Control + Panel (OCP). + +Arguments: + + String - An ASCII character string for display on the OCP. + Count - The number of characters in the argument string. + +Return Value: + + None. + +--*/ +{ + UCHAR DisplayString[OCP_SIZE]; + int index, i; + int count = Count; + + if (!OcpValid) return; + + for (i=0;i char 0 (Left) + +-- Front Panel | | 0xF -> char 7 (Right) + Reset | +-- Front Panel Write + 1 -> reset | 0 -> write, 1 -> read + +-- Front Panel Chip Enable + 0 -> FPAD, FPWR, and data are valid + + Current implementation always writes 1 to the reserved bit, and the + initialization sequence clears FPWR (i.e., set to read). It is not known + whether these actions are necessary. +--*/ +// The Display Data register receives or delivers a single byte, +// depending on the setting of FPWR. +// + +// +// OCP Slave addresses +// + +#define OCP_SLAVE_CONTROL 0x40 // Display Address and Control register +#define OCP_SLAVE_DATA 0x42 // Display Data register +#define OCP_SIZE 8 // 8 character display + +// +// OCP Display Address and Control definitions +// + +#define OCP_FP_RESET 0x80 // FPRST -- Set to perform reset +#define OCP_FP_RES 0x40 // RES -- Reserved, currently always set +#define OCP_FP_ENABLE 0x20 // FPCE -- Clear to assert valid address and data +#define OCP_FP_READ 0x10 // FPWR -- Set to perform read +#define OCP_FP_ADDRESS(pos) ((UCHAR)(0x8 | (pos & 0x7))) + // FPAD3..FPAD0 -- Display character address +// +// OCP Command Settings +// + +// +// OCP_CMD_RESET issues a reset to the OCP (which clears the display) +// OCP_CMD_CLEAR clears reset + +#define OCP_CMD_RESET ((UCHAR)(OCP_FP_RES | OCP_FP_RESET) | OCP_FP_ADDRESS(0)) +#define OCP_CMD_CLEAR ((UCHAR)(OCP_FP_RES) | OCP_FP_ADDRESS(0)) + +// +// OCP_CMD_READY is sent before data is issued +// OCP_CMD_ISSUE indicates that the address and data for the transfer are valid +// + +#define OCP_CMD_READY ((UCHAR)(OCP_FP_RES | OCP_FP_ENABLE)) +#define OCP_CMD_ISSUE(cmd) ((UCHAR)(cmd & ~OCP_FP_ENABLE)) + +// +// Init sequence -- not tested. +// + +#define OCP_CMD_INIT ((UCHAR)(OCP_FP_RES | OCP_FP_RESET | OCP_FP_ENABLE)) +#define OCP_CMD_INITCLR ((UCHAR)(OCP_CMD_INIT & ~OCP_FP_RESET)) + +// +// Function prototypes. +// +#if !defined (_LANGUAGE_ASSEMBLY) + +// FwOcpInitDisplay +// Call once to set the OCP display to a known state +// Returns: +// ESUCCESS - Initialization was successful +// ENODEV - OCP couldn't be reached +// +ARC_STATUS +HalpOcpInitDisplay( + VOID + ); + +// HalpOcpTestDisplay +// Perfom visual test of OCP +// +VOID +HalpOcpTestDisplay( + VOID + ); + +// HalpOcpClearDisplay +// Clear display +VOID +HalpOcpClearDisplay( + VOID + ); + +// FwOcpPutString +// Call to display a string on the OCP display. +// +VOID +HalpOcpPutString( + IN PUCHAR String, + IN ULONG Count, + IN ULONG Start + ); + +// HalpOcpPutSlidingString +// Display a string on the OCP display. +// +VOID +HalpOcpPutSlidingString( + IN PUCHAR String, + IN ULONG Count + ); + +// FwOcpPutByte +// Call to a display a single byte on the OCP display. +VOID +HalpOcpPutByte( + UCHAR Position, + UCHAR Datum + ); + +#endif // !defined (_LANGUAGE_ASSEMBLY) + +#endif // _PCF8574_ diff --git a/private/ntos/nthals/hallego/alpha/pcibus.c b/private/ntos/nthals/hallego/alpha/pcibus.c new file mode 100644 index 000000000..472054ee0 --- /dev/null +++ b/private/ntos/nthals/hallego/alpha/pcibus.c @@ -0,0 +1,111 @@ +/*++ + + +Copyright (c) 1993 Microsoft Corporationn, Digital Equipment Corporation + +Module Name: + + pcibus.c + +Abstract: + + Platform-specific PCI bus routines + +Author: + +Environment: + + Kernel mode + +Revision History: + + Gene Morgan [Digital] 11-Oct-1995 + + Initial version for Lego. Adapted from Avanti. + + +--*/ + +#include "halp.h" +#include "pci.h" +#include "pcip.h" +#include "machdep.h" + +// Highest numbered bus detected during PCI configuration +// +extern ULONG PCIMaxBus; + + + +PCI_CONFIGURATION_TYPES +HalpPCIConfigCycleType( + IN PBUS_HANDLER BusHandler + ) +{ + if (BusHandler->BusNumber == 0) { + return PciConfigType0; + } else { + return PciConfigType1; + } +} + + +VOID +HalpPCIConfigAddr ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + PPCI_CFG_CYCLE_BITS pPciAddr + ) +{ + PCI_CONFIGURATION_TYPES ConfigType; + + ConfigType = HalpPCIConfigCycleType(BusHandler); + + if (ConfigType == PciConfigType0) + { + // + // Initialize PciAddr for a type 0 configuration cycle + // + // Device number is mapped to address bits 11:24. + // In APECS pass 2, the format of a type 0 cycle is the same as the + // format of a type 1. Note that HalpValidPCISlot has already + // done bounds checking on DeviceNumber. + // + // PciAddr can be intialized for different bus numbers + // with distinct configuration spaces here. + // + + pPciAddr->u.AsULONG = (ULONG) APECS_PCI_CONFIG_BASE_QVA; + pPciAddr->u.AsULONG += ( (Slot.u.bits.DeviceNumber) << 11 ); + + pPciAddr->u.bits0.FunctionNumber = Slot.u.bits.FunctionNumber; + pPciAddr->u.bits0.Reserved1 = PciConfigType0; + +#if HALDBG + DbgPrint("HalpPCIConfigAddr: Type 0 PCI Config Access @ %x\n", pPciAddr->u.AsULONG); +#endif // DBG + + } + else + { + // + // Initialize PciAddr for a type 1 configuration cycle + // + // + + pPciAddr->u.AsULONG = (ULONG) APECS_PCI_CONFIG_BASE_QVA; + 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 HALDBG + DbgPrint("Type 1 PCI Config Access @ %x\n", pPciAddr->u.AsULONG); +#endif // DBG + + } + + return; +} + + diff --git a/private/ntos/nthals/hallego/alpha/pciir.c b/private/ntos/nthals/hallego/alpha/pciir.c new file mode 100644 index 000000000..d1e8fe7e9 --- /dev/null +++ b/private/ntos/nthals/hallego/alpha/pciir.c @@ -0,0 +1,646 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation +Copyright (c) 1992,1993,1994,1995,1996 Digital Equipment Corporation + +Module Name: + + pciir.c + +Abstract: + + The module provides the interrupt support for the Lego's PCI + interrupts. + +Author: + + James Livingston 2-May-1994 + +Revision History: + + Janet Schneider (Digital) 27-July-1995 + Added support for the Noritake. + + Gene Morgan (Digital) 28-Oct-1995 + Initial version for Lego. Adapted from Mikasa/Noritake. + + Gene Morgan 15-Apr-1996 + Fix PICMG-mode initialization. + +--*/ + +#include "halp.h" + +// +// Define external function prototypes +// + +UCHAR +HalpAcknowledgePciInterrupt( + PVOID ServiceContext + ); + +// +// Import save area for PCI interrupt mask register. +// +USHORT HalpLegoPciInterruptMasterMask; + +// Cache current contents of interrupt mask registers +// +USHORT HalpLegoPciInterruptMask[4]; + +// +// PCI Interrupt control -- defined in I/O mapping module +// +extern PVOID HalpLegoPciInterruptConfigQva; +extern PVOID HalpLegoPciInterruptMasterQva; +extern PVOID HalpLegoPciInterruptRegisterBaseQva; +extern PVOID HalpLegoPciInterruptRegisterQva[]; +extern PVOID HalpLegoPciIntMaskRegisterQva[]; + +// +// Globals for conveying Cpu and Backplane type +// +extern BOOLEAN HalpLegoCpu; +extern BOOLEAN HalpLegoBackplane; +extern ULONG HalpLegoCpuType; +extern ULONG HalpLegoBackplaneType; +extern UCHAR HalpLegoFeatureMask; +extern ULONG HalpLegoPciRoutingType; + +VOID +DbgDumpIntRegs( + VOID + ) +{ +#if DBG + LEGO_PCI_INT_MASTER MasterRegister; + USHORT MaskReg[4]; + USHORT IntReg[4]; + int i; + + MasterRegister.All = READ_REGISTER_USHORT((PUSHORT)HalpLegoPciInterruptMasterQva); + + MaskReg[0] = READ_REGISTER_USHORT( (PUSHORT) HalpLegoPciIntMaskRegisterQva[0]); + MaskReg[1] = READ_REGISTER_USHORT( (PUSHORT) HalpLegoPciIntMaskRegisterQva[1]); + MaskReg[2] = READ_REGISTER_USHORT( (PUSHORT) HalpLegoPciIntMaskRegisterQva[2]); + MaskReg[3] = READ_REGISTER_USHORT( (PUSHORT) HalpLegoPciIntMaskRegisterQva[3]); + + IntReg[0] = READ_REGISTER_USHORT( (PUSHORT) HalpLegoPciInterruptRegisterQva[0]); + IntReg[1] = READ_REGISTER_USHORT( (PUSHORT) HalpLegoPciInterruptRegisterQva[1]); + IntReg[2] = READ_REGISTER_USHORT( (PUSHORT) HalpLegoPciInterruptRegisterQva[2]); + IntReg[3] = READ_REGISTER_USHORT( (PUSHORT) HalpLegoPciInterruptRegisterQva[3]); + + DbgPrint ("\nMaster: %04X\n",MasterRegister.All); + DbgPrint (" Mask: %04X %04X %04X %04X\n", MaskReg[0], MaskReg[1], MaskReg[2], MaskReg[3]); + DbgPrint ("IntReg: %04X %04X %04X %04X\n", IntReg[0], IntReg[1], IntReg[2], IntReg[3]); +#endif +} + + +VOID +HalpInitializePciInterrupts( + VOID + ) + +/*++ + +Routine Description: + + This routine initializes the Lego PCI interrupts. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + LEGO_PCI_INT_CONFIG ConfigRegister; + LEGO_PCI_INT_MASTER MasterRegister; + +#if DBG + // + // Dump current contents of master and config interrupt registers + // + ConfigRegister.All = READ_REGISTER_USHORT((PUSHORT)HalpLegoPciInterruptConfigQva); + MasterRegister.All = READ_REGISTER_USHORT((PUSHORT)HalpLegoPciInterruptMasterQva); + + DbgPrint("PCI-INTACC[config:%04x,master:%04x]\n", + ConfigRegister.All, MasterRegister.All); +#endif + + + if (HalpLegoPciRoutingType != PCI_INTERRUPT_ROUTING_FULL) { + + // + // disable interrupt accelerator and return + // + + MasterRegister.All = READ_REGISTER_USHORT((PUSHORT)HalpLegoPciInterruptMasterQva); //[wem] added PEFT + MasterRegister.InterruptMode = 0; // MODE - select SIO routing + MasterRegister.InterruptEnable = 0; // valid iff MODE==0 + MasterRegister.IntRegMaskEnable = 0; + MasterRegister.IntMask = 0; + WRITE_REGISTER_USHORT( (PUSHORT)HalpLegoPciInterruptMasterQva, + MasterRegister.All ); + + MasterRegister.All = READ_REGISTER_USHORT((PUSHORT)HalpLegoPciInterruptMasterQva); +#if DBG + DbgPrint("PCI-INTACC[config:%04x,master:%04x]\n", + ConfigRegister.All, MasterRegister.All); +#endif + + MasterRegister.InterruptMode = 0; // MODE - select SIO routing + MasterRegister.InterruptEnable = 0; // valid iff MODE==0 + MasterRegister.IntRegMaskEnable = 0; + MasterRegister.IntMask = 0; + WRITE_REGISTER_USHORT( (PUSHORT)HalpLegoPciInterruptMasterQva, + MasterRegister.All ); + +#if DBG + MasterRegister.All = READ_REGISTER_USHORT((PUSHORT)HalpLegoPciInterruptMasterQva); + + DbgPrint("PCI-INTACC[config:%04x,master:%04x]\n", + ConfigRegister.All, MasterRegister.All); +#endif + return; + } + + // + // Initialize the Lego PCI interrupts. There's a master + // interrupt and mask register, plus individual interrupt + // and mask registers for each physical slot. + // + // 1. Write base address of interrupt registers. + // 2. Write MODE, MSKEN, and MINT[D:A]. + // 3. Set all mask bits to "disabled". + // + + ConfigRegister.All = 0; + ConfigRegister.IntRegisterBaseAddr = PCI_INTERRUPT_BASE_REGISTER >> 4; + WRITE_REGISTER_USHORT( (PUSHORT)HalpLegoPciInterruptConfigQva, + ConfigRegister.All ); + + // + // Set interrupt accelerator mode + // Mask interrupts until interrupt registers are setup. + // + // Note: The interrupt mask in the master register is always clear + // + + MasterRegister.All = 0; + MasterRegister.InterruptMode = 1; // MODE + MasterRegister.InterruptEnable = 0; // valid iff MODE==0 + MasterRegister.IntRegMaskEnable = 1; // valid iff MODE==1 +#if 0 //[wem] remove PEFT + MasterRegister.IntMask = HalpLegoPciInterruptMasterMask; +#endif + WRITE_REGISTER_USHORT( (PUSHORT)HalpLegoPciInterruptMasterQva, + MasterRegister.All ); + + // + // Turn on mask bits for each interrupt register + // + + HalpLegoPciInterruptMask[0] = (USHORT)~0; + HalpLegoPciInterruptMask[1] = (USHORT)~0; + HalpLegoPciInterruptMask[2] = (USHORT)~0; + HalpLegoPciInterruptMask[3] = (USHORT)~0; + + WRITE_REGISTER_USHORT( (PUSHORT) HalpLegoPciIntMaskRegisterQva[0], + HalpLegoPciInterruptMask[0] ); + WRITE_REGISTER_USHORT( (PUSHORT) HalpLegoPciIntMaskRegisterQva[1], + HalpLegoPciInterruptMask[1] ); + WRITE_REGISTER_USHORT( (PUSHORT) HalpLegoPciIntMaskRegisterQva[2], + HalpLegoPciInterruptMask[2] ); + WRITE_REGISTER_USHORT( (PUSHORT) HalpLegoPciIntMaskRegisterQva[3], + HalpLegoPciInterruptMask[3] ); + + // Turn off mask bits in master interrupt register + // + MasterRegister.All = 0; + MasterRegister.InterruptMode = 1; // MODE + MasterRegister.InterruptEnable = 0; // valid iff MODE==0 + MasterRegister.IntRegMaskEnable = 1; // valid iff MODE==1 + MasterRegister.IntMask = (USHORT)~(INTA | INTB | INTC | INTD); + WRITE_REGISTER_USHORT( (PUSHORT)HalpLegoPciInterruptMasterQva, + MasterRegister.All ); + +#if DBG + DbgDumpIntRegs(); +#endif + +} + + +VOID +HalpDisablePciInterrupt( + IN ULONG Vector + ) + +/*++ + +Routine Description: + + This function disables the PCI interrupt specified by Vector. + +Arguments: + + Vector - Supplies the vector of the PCI interrupt to disable. + +Return Value: + + None. + +Notes: + + The register contents are cached in HalpLegoPciInterruptMask + array. [wem] ??? Is this safe ? + +--*/ + +{ + ULONG RegSelect; + USHORT BitMask, NewMask; + + // Remove offset to yield register and bit position. + // + Vector -= PCI_DEVICE_VECTORS; + + // High order nibble of Vector selects the register, low order + // selects the bit. + // + RegSelect = (Vector >> 4) - 1; + BitMask = 1 << ((Vector & 0xf) - 1); + + // Assume the current state of the interrupt mask register + // is in HalpLegoPciInterruptMask. + // + // Set bit indicated by Vector to disable interrupts + // + NewMask = HalpLegoPciInterruptMask[RegSelect] | BitMask; + + // If changed, write new register contents + // + if (NewMask != HalpLegoPciInterruptMask[RegSelect]) { + HalpLegoPciInterruptMask[RegSelect] = NewMask; + WRITE_REGISTER_USHORT( (PUSHORT) + HalpLegoPciIntMaskRegisterQva[RegSelect], + HalpLegoPciInterruptMask[RegSelect] ); + } + +#if DBG + DbgPrint("\nDisable PCI vector: %02X", Vector); + DbgDumpIntRegs(); +#endif + +} + + +VOID +HalpEnablePciInterrupt( + IN ULONG Vector, + IN KINTERRUPT_MODE InterruptMode + ) + +/*++ + +Routine Description: + + This function enables the PCI interrupt specified by Vector. +Arguments: + + Vector - Supplies the vector of the PCI interrupt that is enabled. + + InterruptMode - Supplies the mode of the interrupt; + LevelSensitive or Latched (ignored for Lego PCI + interrupts; they're always levels). + +Return Value: + + None. + +--*/ + +{ + ULONG RegSelect; + USHORT BitMask, NewMask; + + // + // Remove offset to yield register and bit position. + // + + Vector -= PCI_DEVICE_VECTORS; + + // + // High order nibble of Vector selects the register, low order + // selects the bit. + // + + RegSelect = (Vector >> 4) - 1; + BitMask = 1 << ((Vector & 0xf) - 1); + + // + // Assume the current state of the interrupt mask register + // is in HalpLegoPciInterruptMask. + // + // Clear bit indicated by Vector to enable interrupts. + // + + NewMask = HalpLegoPciInterruptMask[RegSelect] & ~BitMask; + + // + // If changed, write new register contents + // + + if (NewMask != HalpLegoPciInterruptMask[RegSelect]) { + HalpLegoPciInterruptMask[RegSelect] = NewMask; + WRITE_REGISTER_USHORT( (PUSHORT) + HalpLegoPciIntMaskRegisterQva[RegSelect], + HalpLegoPciInterruptMask[RegSelect] ); + } + +#if DBG + DbgPrint("\nEnable PCI vector: %02X", Vector); + DbgPrint("\n Old: %04X, New: %04X", HalpLegoPciInterruptMask[RegSelect], NewMask); + DbgDumpIntRegs(); +#endif + +} + +// Table for mapping from per-slot interrupt signal +// to which slot to service. +// Index is 4-bit value representing interrupt status for +// +// Current priority ordering is slot 1, 2, 3, 4 +// Index zero has no meaning, but it should do no harm. +// +// +USHORT +HighestPrioritySlot[16] = { +// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f // value + 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 // slot (based from zero) + }; + +ULONG +HighestPrioritySlotHits[4][16] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + +UCHAR +HighestPriorityLine ( + LEGO_PCI_INT_MASTER MasterReg + ) +/*++ + +Routine Description: + + Policy routine for determining which PCI device to service next. + +Arguments: + + MasterReg -- current Lego Master Interrupt register. Interrupt + field indicates which slots have pending interrupts. + +Return Value: + + Value in range of 0..64, indicating which device should be serviced. + +--*/ +{ + USHORT IntReg; + + UCHAR Nib; + USHORT IrContents; + USHORT RegSelect, BitSelect; + int i; + + RegSelect = HighestPrioritySlot[MasterReg.Interrupt]; + + // Read interrupt register for slot + // + IntReg = READ_REGISTER_USHORT( (PUSHORT) + HalpLegoPciInterruptRegisterQva[RegSelect]); + + if (IntReg==0) + return 0xff; + + // Find lowest numbered bit. + // + BitSelect = 0; + while (IntReg!=0) { + Nib = IntReg & 0xf; + if (Nib != 0) { + BitSelect += HighestPrioritySlot[Nib]; + break; + } + IntReg = IntReg >> 4; + BitSelect += 4; + } + + +#if DBG + if (HighestPrioritySlotHits[RegSelect][BitSelect]++ == 0) { + DbgPrint("\nSlot: %d, %d", RegSelect, BitSelect); + DbgDumpIntRegs(); + } +#endif + + return ((RegSelect + 1) << 4) + (BitSelect + 1); + +} + +UCHAR +HalpAcknowledgePciInterrupt( + PVOID ServiceContext + ) +/*++ + +Routine Description: + + Acknowledge the PCI interrupt. Return the vector number of the + highest priority pending interrupt. + +Arguments: + + ServiceContext - Service context of the interrupt service - supplies + a QVA to Lego's Master PCI interrupt register. + +Return Value: + + + Return the value of the highest priority pending interrupt, + or 0xff if none. + +--*/ +{ + LEGO_PCI_INT_MASTER MasterReg; + UCHAR InterruptVector; + + UCHAR ISAVector = 0; //[wem] DEBUG - ack PCI int + + static ULONG Count = 0; + + // + // Check the master register to see which primary slot is + // requesting service (slot may be a PPB requesting service + // on behalf of one of its slots). Then check that slot's + // interrupt register. + // + // A set bit in the master or slot register indicates an active + // interrupt. Note that if the interrupt is masked, the bit will + // not be set. Also note that the code does not use the master + // register's mask bits unless all PCI interrupts need to be + // disabled at once. + // + // Scan is currently depth-first from slot 1 to slot 4. For + // each slot, INTA is serviced first and INTD serviced last. + // + // [wem] There's some interesting opportunities here. + // For example, it is possible to scan and detect how many + // waiting interrupts there are. It is also possible remember + // last vector and scan forward from that point (as in round + // robin), or to implement a fairness algorithm that incorporates + // priority. + // + +#if 0 + // + //[wem] This requires an interrupt controller to respond to the + // interrupt acknowledge. The SIO has been programmed to not + // respond, so someone else has to do it (the interrupt accelerator?). + // + + ISAVector = READ_PORT_UCHAR(HalpEisaIntAckBase); +#endif + + // Read master register. + // + MasterReg.All = READ_REGISTER_USHORT( + (PUSHORT) HalpLegoPciInterruptMasterQva); + + if (MasterReg.Interrupt==0) { + return 0xff; // no interrupts + } + + // Scan + // + InterruptVector = HighestPriorityLine (MasterReg); + +#if DBG + if (Count++ < 5 && ISAVector != 0xff) { + DbgPrint("",ISAVector,InterruptVector); + } +#endif + + return( InterruptVector ); +} + + +BOOLEAN +HalpPciDispatch( + IN PKINTERRUPT Interrupt, + IN PVOID ServiceContext, + IN PKTRAP_FRAME TrapFrame + ) +/*++ + +Routine Description: + + This routine is entered as the result of an interrupt having been generated + via the vector connected to the PCI device interrupt object. Its function + is to call the second-level interrupt dispatch routine. + + This service routine could have been connected as follows, where the + ISR is the assembly wrapper that does the handoff to this function: + + KeInitializeInterrupt( &Interrupt, + HalpPciInterruptHandler, + (PVOID) HalpPciIrQva, + (PKSPIN_LOCK)NULL, + PCI_VECTOR, + PCI_DEVICE_LEVEL, + PCI_DEVICE_LEVEL, + LevelSensitive, + TRUE, + 0, + FALSE); + + KeConnectInterrupt(&Interrupt); + +Arguments: + + Interrupt - Supplies a pointer to the interrupt object. + + ServiceContext - Supplies a pointer to the PCI interrupt register. + + TrapFrame - Supplies a pointer to the trap frame for this interrupt. + +Return Value: + + Returns the value returned from the second level routine. + +--*/ +{ + UCHAR PCIVector; + BOOLEAN returnValue; + USHORT PCRInOffset; + + //[wem] DEBUG - count SIO dispatch entries + // + static long PciCount = 0; + +#if DBG //[wem] + PciCount++; + if (PciCount<5) { + DbgPrint("II<"); + } + if (PciCount % 5000 == 0) { + DbgPrint("II<%08x><",PciCount); + } +#endif + + // + // Acknowledge interrupt and receive the returned interrupt vector. + // If we got 0xff back, there were no enabled interrupts, so we + // signal that with a FALSE return, immediately. + // + + PCIVector = HalpAcknowledgePciInterrupt(ServiceContext); + + if (PCIVector == 0xff) { + +#if DBG //[wem] + if (PciCount<5 || (PciCount % 5000) == 0) { + DbgPrint("ff>."); + } +#endif + return( FALSE ); + } + + // Compute new vector based on PCI bus state + // + PCRInOffset = PCIVector + PCI_DEVICE_VECTORS; + + // Re-dispatch via new vector + // + returnValue = ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[PCRInOffset])( + PCR->InterruptRoutine[PCRInOffset], + TrapFrame + ); + +#if DBG //[wem] + if (PciCount<5 || (PciCount % 5000) == 0) { + DbgPrint("%02x>.",returnValue); + } +#endif + + return( returnValue ); +} diff --git a/private/ntos/nthals/hallego/alpha/pcisio.c b/private/ntos/nthals/hallego/alpha/pcisio.c new file mode 100644 index 000000000..91153d23c --- /dev/null +++ b/private/ntos/nthals/hallego/alpha/pcisio.c @@ -0,0 +1,587 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation +Copyright (c) 1992, 1993, 1994 Digital Equipment Corporation + +Module Name: + + pic8259.c + +Abstract: + + The module provides the interrupt support for the PCI SIO + programmable interrupt controller. + + +Author: + + Eric Rehm (DEC) 4-Feburary-1994 + +Revision History: + + +--*/ + +#include "halp.h" +#include "eisa.h" + +#if 0 //[wem] not yet +extern PVOID HalpSioIntAckQva; +extern ULONG HalpLegoPciRoutingType; +#endif + +// +// Import save area for SIO interrupt mask registers. +// + +UCHAR HalpSioInterrupt1Mask; +UCHAR HalpSioInterrupt2Mask; +UCHAR HalpSioInterrupt1Level; +UCHAR HalpSioInterrupt2Level; + +// +// Define the context structure for use by interrupt service routines. +// + +typedef BOOLEAN (*PSECOND_LEVEL_DISPATCH)( + PKINTERRUPT InterruptObject + ); + + +VOID +HalpInitializeSioInterrupts ( + VOID + ) + +/*++ + +Routine Description: + + This routine initializes the standard dual 8259 programmable interrupt + controller. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + UCHAR DataByte; + + // + // Initialize the SIO interrupt controller. There are two cascaded + // interrupt controllers, each of which must initialized with 4 initialize + // control words. + // + + DataByte = 0; + ((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1; + ((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1; + + WRITE_PORT_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0, + DataByte + ); + + WRITE_PORT_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0, + DataByte + ); + + // + // The second intitialization control word sets the iterrupt vector to + // 0-15. + // + + DataByte = 0; + + WRITE_PORT_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1, + DataByte + ); + + DataByte = 0x08; + + WRITE_PORT_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1, + DataByte + ); + + // + // The thrid initialization control word set the controls for slave mode. + // The master ICW3 uses bit position and the slave ICW3 uses a numberic. + // + + DataByte = 1 << SLAVE_IRQL_LEVEL; + + WRITE_PORT_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1, + DataByte + ); + + DataByte = SLAVE_IRQL_LEVEL; + + WRITE_PORT_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1, + DataByte + ); + + // + // The fourth initialization control word is used to specify normal + // end-of-interrupt mode and not special-fully-nested mode. + // + + DataByte = 0; + ((PINITIALIZATION_COMMAND_4) &DataByte)->I80x86Mode = 1; + + WRITE_PORT_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1, + DataByte + ); + + WRITE_PORT_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1, + DataByte + ); + + + // + // Disable all of the interrupts except the slave. + // + + HalpSioInterrupt1Mask = (UCHAR)(~(1 << SLAVE_IRQL_LEVEL)); + + WRITE_PORT_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1, + HalpSioInterrupt1Mask + ); + + HalpSioInterrupt2Mask = 0xFF; + + WRITE_PORT_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1, + HalpSioInterrupt2Mask + ); + + + // + // Initialize the edge/level register masks to 0 which is the default + // edge sensitive value. + // + + HalpSioInterrupt1Level = 0; + HalpSioInterrupt2Level = 0; + + return; + +} + +VOID +HalpDisableSioInterrupt( + IN ULONG Vector + ) + +/*++ + +Routine Description: + + This function Disables the SIO bus specified SIO bus interrupt. + +Arguments: + + Vector - Supplies the vector of the ESIA interrupt that is Disabled. + +Return Value: + + None. + +--*/ + +{ + + // + // Calculate the SIO interrupt vector. + // + + Vector -= ISA_VECTORS; + + // + // Determine if this vector is for interrupt controller 1 or 2. + // + + if (Vector & 0x08) { + + // + // The interrupt is in controller 2. + // + + Vector &= 0x7; + + HalpSioInterrupt2Mask |= (UCHAR) 1 << Vector; + WRITE_PORT_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1, + HalpSioInterrupt2Mask + ); + + } else { + + // + // The interrupt is in controller 1. + // + + Vector &= 0x7; + + // + // never disable IRQL2, it is the slave interrupt + // + + if (Vector != SLAVE_IRQL_LEVEL) { + HalpSioInterrupt1Mask |= (ULONG) 1 << Vector; + WRITE_PORT_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1, + HalpSioInterrupt1Mask + ); + } + + } + +} + +VOID +HalpEnableSioInterrupt( + IN ULONG Vector, + IN KINTERRUPT_MODE InterruptMode + ) + +/*++ + +Routine Description: + + This function enables the SIO bus specified SIO bus interrupt. +Arguments: + + Vector - Supplies the vector of the SIO interrupt that is enabled. + + InterruptMode - Supplies the mode of the interrupt; LevelSensitive or + Latched. + +Return Value: + + None. + +--*/ + +{ + + // + // Calculate the SIO interrupt vector. + // + + Vector -= ISA_VECTORS; + + // + // Determine if this vector is for interrupt controller 1 or 2. + // + + if (Vector & 0x08) { + + // + // The interrupt is in controller 2. + // + + Vector &= 0x7; + + HalpSioInterrupt2Mask &= (UCHAR) ~(1 << Vector); + WRITE_PORT_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1, + HalpSioInterrupt2Mask + ); + + // + // Set the level/edge control register. + // + + if (InterruptMode == LevelSensitive) { + + HalpSioInterrupt2Level |= (UCHAR) (1 << Vector); + + } else { + + HalpSioInterrupt2Level &= (UCHAR) ~(1 << Vector); + + } + + WRITE_PORT_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2EdgeLevel, + HalpSioInterrupt2Level + ); + + } else { + + // + // The interrupt is in controller 1. + // + + Vector &= 0x7; + + HalpSioInterrupt1Mask &= (UCHAR) ~(1 << Vector); + WRITE_PORT_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1, + HalpSioInterrupt1Mask + ); + + // + // Set the level/edge control register. + // + + if (InterruptMode == LevelSensitive) { + + HalpSioInterrupt1Level |= (UCHAR) (1 << Vector); + + } else { + + HalpSioInterrupt1Level &= (UCHAR) ~(1 << Vector); + + } + + WRITE_PORT_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1EdgeLevel, + HalpSioInterrupt1Level + ); + } + +} + +UCHAR +HalpAcknowledgeSioInterrupt( + PVOID ServiceContext + ) +/*++ + +Routine Description: + + Acknowledge the Sio interrupt. Return the vector number of the + highest priority pending interrupt. + +Arguments: + + ServiceContext - Service context of the interrupt service - supplies + a QVA to Lego's Master PCI interrupt register. + +Return Value: + + + Return the value of the highest priority pending interrupt, + or 0xff if none. + +--*/ +{ + UCHAR ISAVector; + UCHAR Int1Isr; + UCHAR Int2Isr; + + // + // If PCI interrupts are being routed through the SIO, then + // a write to HalpEisaIntAckBase will generate a correct + // PCI Interrupt Acknowledge cycle for both PCI and ISA devices. + // + // If PCI interrupts are being routed through the interrupt + // accelerator, then the Interrupt Acknowledge cannot be issued + // on the PCI bus (since the SIO no longer has complete knowledge + // of interrupts). Instead, ISA interrupts must be acknowledged + // via a special port of the SIO, and PCI interrupts must be + // acknowledged via a PCI Interrupt Acknowledge (but that's another + // story). + // + + +#if 0 //[wem] not yet + if (HalpLegoPciRoutingType == PCI_INTERRUPT_ROUTING_FULL) { + + // + // The interrupt accelerator is active. Issue the + // interrupt acknowledge directly to the SIO + // + + ISAVector = READ_PORT_UCHAR(HalpSioIntAckQva); + } + else { + + // The interrupt accelerator is in PICMG mode. All + // interrupts are going through the SIO, so a PCI + // interrupt acknowledge is safe. + // + ISAVector = READ_PORT_UCHAR(HalpEisaIntAckBase); + } +#else + + // + // Acknowledge the PCI/ISA interrupt via the SIO + // + // Note: This path is not used for PCI interrupts when + // interrupt accelerator is active. + // + + ISAVector = READ_PORT_UCHAR(HalpEisaIntAckBase); + +#endif + + + if ((ISAVector & 0x07) == 0x07) { + + // + // Check for a passive release by looking at the inservice register. + // If there is a real IRQL7 interrupt, just go along normally. If there + // is not, then it is a passive release. So just dismiss it. + // + + WRITE_PORT_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0, + 0x0B + ); + + Int1Isr = READ_PORT_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0); + + // + // do second controller + // + + WRITE_PORT_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0, + 0x0B + ); + + Int2Isr = READ_PORT_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0); + + + if (!(Int2Isr & 0x80) && !(Int1Isr & 0x80)) { + + // + // Clear the master controller to clear situation + // + + if (!(Int2Isr & 0x80)) { + WRITE_PORT_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0, + NONSPECIFIC_END_OF_INTERRUPT + ); + + } + + return 0xFF; // ecrfix - now returns a value + + } + + } + + return ISAVector & 0x0F; + +} + + +BOOLEAN +HalpSioDispatch( + VOID + ) +/*++ + +Routine Description: + + This routine is entered as the result of an interrupt being generated + via the vector that is directly connected to an interrupt object that + describes the SIO device interrupts. Its function is to call the second + level interrupt dispatch routine and acknowledge the interrupt at the SIO + controller. + +Arguments: + + None. + +Return Value: + + Returns the value returned from the second level routine. + +--*/ +{ + UCHAR ISAVector; + PKPRCB Prcb; + BOOLEAN returnValue; + USHORT PCRInOffset; + PULONG DispatchCode; + PKINTERRUPT InterruptObject; + + //[wem] DEBUG - count SIO dispatch entries + // + static long SioCount = 0; + +#if DBG + SioCount++; + if (SioCount<5) { + DbgPrint("II<"); + } + if (SioCount % 1000 == 0) { + DbgPrint("II<%08x><",SioCount); + } +#endif + + // + // Acknowledge the Interrupt controller and receive the returned + // interrupt vector. + // + + ISAVector = HalpAcknowledgeSioInterrupt(NULL); + + if (ISAVector==0xff) + return FALSE; + + // + // Dispatch to the secondary interrupt service routine. + // + + PCRInOffset = ISAVector + ISA_VECTORS; + DispatchCode = (PULONG)PCR->InterruptRoutine[PCRInOffset]; + InterruptObject = CONTAINING_RECORD(DispatchCode, + KINTERRUPT, + DispatchCode); + + returnValue = ((PSECOND_LEVEL_DISPATCH)InterruptObject->DispatchAddress)(InterruptObject); + + // + // Dismiss the interrupt in the SIO interrupt controllers. + // + + // + // If this is a cascaded interrupt then the interrupt must be dismissed in + // both controlles. + // + + if (ISAVector & 0x08) { + + WRITE_PORT_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0, + NONSPECIFIC_END_OF_INTERRUPT + ); + + } + + WRITE_PORT_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0, + NONSPECIFIC_END_OF_INTERRUPT + ); + +#if DBG //[wem] + if (SioCount<5 || (SioCount % 1000)==0) { + DbgPrint("%02x>.", returnValue); + } +#endif + + return(returnValue); +} + + diff --git a/private/ntos/nthals/hallego/alpha/pcisup.c b/private/ntos/nthals/hallego/alpha/pcisup.c new file mode 100644 index 000000000..360919f42 --- /dev/null +++ b/private/ntos/nthals/hallego/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/hallego/alpha/pcrtc.c b/private/ntos/nthals/hallego/alpha/pcrtc.c new file mode 100644 index 000000000..2e57b87d6 --- /dev/null +++ b/private/ntos/nthals/hallego/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/hallego/alpha/pcserial.c b/private/ntos/nthals/hallego/alpha/pcserial.c new file mode 100644 index 000000000..a2f159c48 --- /dev/null +++ b/private/ntos/nthals/hallego/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/hallego/alpha/pcspeakr.c b/private/ntos/nthals/hallego/alpha/pcspeakr.c new file mode 100644 index 000000000..807b6f324 --- /dev/null +++ b/private/ntos/nthals/hallego/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/hallego/alpha/perfcntr.c b/private/ntos/nthals/hallego/alpha/perfcntr.c new file mode 100644 index 000000000..6c0a8f892 --- /dev/null +++ b/private/ntos/nthals/hallego/alpha/perfcntr.c @@ -0,0 +1,7 @@ +// +// This file simply includes the source file from the common Alpha +// HAL directory. +// + +#include "..\halalpha\perfcntr.c" + diff --git a/private/ntos/nthals/hallego/alpha/pintolin.h b/private/ntos/nthals/hallego/alpha/pintolin.h new file mode 100644 index 000000000..86843acd3 --- /dev/null +++ b/private/ntos/nthals/hallego/alpha/pintolin.h @@ -0,0 +1,273 @@ +/*++ + +Copyright (c) 1993 Microsoft Corporation +Copyright (c) 1994,1995,1996 Digital Equipment Corporation + +Module Name: + + pintolin.h + +Abstract: + + This file includes the platform-dependent Pin To Line Tables for Lego + +Author: + +Environment: + + Kernel mode + +Revision History: + + Gene Morgan [Digital] 15-Apr-1996 + Fix swapped PICMG-mode (ISA shared mode) lines -- affects + Gobi and Sahara bridged slots (first and third) if interrupts + in use. + +--*/ + +// +// These tables represent the mapping from slot number and interrupt pin +// into a PCI Interrupt Vector. +// On Mustang, EB66, and Lego, the interrupt vector is Interrupt Request Register bit +// representing that interrupt + 1. +// On EB66 and Lego, 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_DEVICE_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 //[wem] ???problem? +// are limited to 16 devices (PCI AD[11]-AD[26]). (We loose AD[17]-AD[31] //[wem] ???problem? +// since PCI Config space is a sparse space, requiring a five-bit shift.) //[wem] ???problem? +// +// 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 +// be combined to appear on some combination of the four interrupt pins +// that the bridge plugs into. On Lego platforms, that routing is dictated by +// the PICMG specification. +// +// 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 HalpPCIPinToLineTable 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[31]. (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. +// + +// +// Interrupt Vector Table Mapping for Lego +// +// You can limit init table to MAX_PCI_LOCAL_DEVICES entries. +// The virtual slot range on lego is 17-20, so +// MAX_PCI_LOCAL_DEVICE is defined as 20 in the platform dependent +// header file (legodef.H). HalpValidPCISlot assures us that +// we won't ever try to set an InterruptLine register of a slot +// greater than Virtual slot 20 = PCI_AD[31]. +// + +ULONG *HalpPCIPinToLineTable; + +// +// Interrupt Vector Table Mapping for Lego +// +// Lego PCI interrupts are mapped to ISA IRQs in the table below. +// +// Limit init table to 20 entries, which is the +// MAX_PCI_LOCAL_DEVICES for Lego. +// We won't ever try to set an InterruptLine register of a slot +// less than virtual slot 17 = PCI_AD[28] +// or greater than Virtual slot 20 = PCI_AD[31]. +// + +#define SLOT_UNREACHABLE { 0xff, 0xff, 0xff, 0xff } + +#define SLOTS_UNREACHABLE_8 \ + SLOT_UNREACHABLE, SLOT_UNREACHABLE, SLOT_UNREACHABLE, SLOT_UNREACHABLE, \ + SLOT_UNREACHABLE, SLOT_UNREACHABLE, SLOT_UNREACHABLE, SLOT_UNREACHABLE + +#define SLOTS_UNREACHABLE_12 \ + SLOTS_UNREACHABLE_8, \ + SLOT_UNREACHABLE, SLOT_UNREACHABLE, SLOT_UNREACHABLE, SLOT_UNREACHABLE + + +#define SLOTS_UNREACHABLE_17 \ + SLOTS_UNREACHABLE_12, \ + SLOT_UNREACHABLE, SLOT_UNREACHABLE, SLOT_UNREACHABLE, SLOT_UNREACHABLE, \ + SLOT_UNREACHABLE + +#define PTL0 0xa +#define PTL1 0xf +#define PTL2 0x9 +#define PTL3 0xb + +// Pin to Line Table for primary (bus 0) slots +// when PCI Interrupts routed through SIO +// +// **tested** +// +ULONG LegoPCIPinToLineTableIsa[][4]= +{ + SLOTS_UNREACHABLE_17, // Virtual Slots 0..16 = PCI_AD[11..27] + { PTL0, PTL1, PTL2, PTL3 }, // Virtual Slot 17 = PCI_AD[28] Slot #4 + { PTL3, PTL0, PTL1, PTL2 }, // Virtual Slot 18 = PCI_AD[29] Slot #3 + { PTL2, PTL3, PTL0, PTL1 }, // Virtual Slot 19 = PCI_AD[30] Slot #2 + { PTL1, PTL2, PTL3, PTL0 } // Virtual Slot 20 = PCI_AD[31] Slot #1 +}; + +// Slot 2 is SCSI (NCR810) on Atacama. +// Give it a dedicated SIO IRQ (as Avanti and friends do) +// +// **tested** +// +ULONG LegoPCIPinToLineTableIsaAtacama[][4]= +{ + SLOTS_UNREACHABLE_17, // Virtual Slots 0..16 = PCI_AD[11..27] + { PTL0, PTL1, PTL2, PTL3 }, // Virtual Slot 17 = PCI_AD[28] Slot #4 + { PTL3, PTL0, PTL1, PTL2 }, // Virtual Slot 18 = PCI_AD[29] Slot #3 -- SCSI + { PTL2, 0xff, 0xff, 0xff }, // Virtual Slot 19 = PCI_AD[30] Slot #2 + { PTL1, PTL2, PTL3, PTL0 } // Virtual Slot 20 = PCI_AD[31] Slot #1 +}; + +// Pin to Line Table for Bus 1 slots when PCI Interrupts +// routed through SIO. Bus 1 is behind a PPB in primary slot 1. +// +ULONG LegoPCIPinToLineTableIsaBus1[][4]= +{ + SLOTS_UNREACHABLE_12, // Virtual Slots 0..11 = PCI_AD[11..27] + { PTL1, PTL2, PTL3, PTL0 }, // Virtual Slot 12 = PCI_AD[28] Slot #4 + { PTL2, PTL3, PTL0, PTL1 }, // Virtual Slot 13 = PCI_AD[29] Slot #3 + { PTL3, PTL0, PTL1, PTL2 }, // Virtual Slot 14 = PCI_AD[30] Slot #2 + { PTL0, PTL1, PTL2, PTL3 } // Virtual Slot 15 = PCI_AD[31] Slot #1 +}; + +// Pin to Line Table for Bus 2 slots when PCI Interrupts +// routed through SIO. Bus 2 is behind a PPB in primary slot 2. +// +ULONG LegoPCIPinToLineTableIsaBus2[][4]= +{ + SLOTS_UNREACHABLE_8, // Virtual Slots 0..7 = PCI_AD[11..27] + { PTL2, PTL3, PTL0, PTL1 }, // Virtual Slot 8 = PCI_AD[28] Slot #4 + { PTL3, PTL0, PTL1, PTL2 }, // Virtual Slot 9 = PCI_AD[29] Slot #3 + { PTL0, PTL1, PTL2, PTL3 }, // Virtual Slot 10 = PCI_AD[30] Slot #2 + { PTL1, PTL2, PTL3, PTL0 } // Virtual Slot 11 = PCI_AD[31] Slot #1 +}; + +// Pin to Line Table for primary (bus 0) slots when Lego PCI Interrupt routing enabled +// +ULONG LegoPCIPinToLineTable[][4]= +{ + SLOTS_UNREACHABLE_17, // Virtual Slots 0..16 = PCI_AD[11..27] + { 0x41, 0x42, 0x43, 0x44 }, // Virtual Slot 17 = PCI_AD[28] Slot #4 + { 0x31, 0x32, 0x33, 0x34 }, // Virtual Slot 18 = PCI_AD[29] Slot #3 + { 0x21, 0x22, 0x23, 0x24 }, // Virtual Slot 19 = PCI_AD[30] Slot #2 + { 0x11, 0x12, 0x13, 0x14 } // Virtual Slot 20 = PCI_AD[31] Slot #1 +}; + +// Pin to Line Table for Bus 1 slots when Lego PCI Interrupt routing enabled +// Bus 1 is behind a PPB in primary slot 1 +// +ULONG LegoPCIPinToLineTableBus1[][4]= +{ + SLOTS_UNREACHABLE_12, // Virtual Slots 0..11 = PCI_AD[11..27] + { 0x1d, 0x1e, 0x1f, 0x20 }, // Virtual Slot 12 = PCI_AD[28] Slot #7 (Gobi) or #6 (Sahara) + { 0x19, 0x1a, 0x1b, 0x1c }, // Virtual Slot 13 = PCI_AD[29] Slot #6 or #5 + { 0x15, 0x16, 0x17, 0x18 }, // Virtual Slot 14 = PCI_AD[30] Slot #5 or #4 + { 0x11, 0x12, 0x13, 0x14 } // Virtual Slot 15 = PCI_AD[31] Slot #4 or #3 +}; + +// Pin to Line Table for Bus 2 slots when Lego PCI Interrupt routing enabled +// Bus 2 is behind a PPB in primary slot 2 +// +ULONG LegoPCIPinToLineTableBus2[][4]= +{ + SLOTS_UNREACHABLE_8, // Virtual Slots 0..7 = PCI_AD[11..27] + { 0x2d, 0x2e, 0x2f, 0x30 }, // Virtual Slot 8 = PCI_AD[28] Slot #10 + { 0x29, 0x2a, 0x2b, 0x2c }, // Virtual Slot 9 = PCI_AD[29] Slot #9 + { 0x25, 0x26, 0x27, 0x28 }, // Virtual Slot 10 = PCI_AD[30] Slot #8 + { 0x21, 0x22, 0x23, 0x24 } // Virtual Slot 11 = PCI_AD[31] Slot #7 +}; + diff --git a/private/ntos/nthals/hallego/alpha/smerr.c b/private/ntos/nthals/hallego/alpha/smerr.c new file mode 100644 index 000000000..993131568 --- /dev/null +++ b/private/ntos/nthals/hallego/alpha/smerr.c @@ -0,0 +1,390 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation +Copyright (c) 1996 Digital Equipment Corporation + +Module Name: + + smerr.c + +Abstract: + + The module provides the error logging support for Lego's + Server Management and Watchdog timer functions. + +Author: + + Gene Morgan (Digital) 17-Apr-1996 + +Revision History: + + Gene Morgan (Digital) 17-Apr-1996 + Initial version. + +--*/ + +#include "halp.h" +#include "errframe.h" + +// +// Context structure used interrupt service routines. +// + +typedef BOOLEAN (*PSECOND_LEVEL_DISPATCH)( + PKINTERRUPT InterruptObject, + PVOID ServiceContext + ); + +// +// External variable UncorrectableError is declared in inithal.c. +// + +extern PERROR_FRAME PUncorrectableError; + +// +// Counter for correctable events +// + +extern ULONG CorrectedMemoryReads; +ULONG ServerMgmtEvents = 0; + +BOOLEAN HalpServerMgmtLoggingEnabled; + +// +// External function prototypes +// + +UCHAR +HalpAcknowledgeServerMgmtInterrupt( + PVOID ServiceContext + ); + +int +sprintf( char *, const char *, ... ); + +// +// Local prototypes +// + +VOID +LegoServerMgmtReportWarningCondition( + BOOLEAN ReportWatchdog, + USHORT SmRegAll, + USHORT WdRegAll + ); + +VOID +LegoServerMgmtReportFatalError( + USHORT SmRegAll + ); + + +// +// Local routines +// + +VOID +LegoServerMgmtReportWarningCondition( + BOOLEAN ReportWatchdog, + USHORT SmRegAll, + USHORT WdRegAll + ) +/*++ + +Routine Description: + + Report "correctable error" condition to error log. + +Arguments: + + ReportWd -- reporting watchdog timer expiration + SmRegAll -- copy of server management register that is to be reported + (if ReportWd == FALSE) + WdRegAll -- copy of watchdog register that is to be reported + (if ReportWd == TRUE) + +Return Value: + + None + +Notes: + +--*/ +{ + LEGO_SRV_MGMT SmRegister; + LEGO_WATCHDOG WdRegister; + + static ERROR_FRAME Frame; // Copy here for error logger's use + + ERROR_FRAME TempFrame; // Build frame here + PCORRECTABLE_ERROR CorrPtr; + PEXTENDED_ERROR PExtended; + + PBOOLEAN ErrorlogBusy; + PULONG DispatchCode; + PKINTERRUPT InterruptObject; + PKSPIN_LOCK ErrorlogSpinLock; + + // + // Copy provided register values + // + + WdRegister.All = WdRegAll; + SmRegister.All = SmRegAll; + + // + // Update the number of correctable errors. + // + + CorrectedMemoryReads += 1; // sequence number for all correctable errors + ServerMgmtEvents += 1; + + + // + // If error logger not available, do not attempt + // to log an error. + // + + if (!HalpServerMgmtLoggingEnabled) { + return; + } + + // + // Init the error frame struct + // + + RtlZeroMemory(&TempFrame, sizeof(ERROR_FRAME)); + + // + // Fill in the error frame information. + // + + TempFrame.Signature = ERROR_FRAME_SIGNATURE; + TempFrame.FrameType = CorrectableFrame; + TempFrame.VersionNumber = ERROR_FRAME_VERSION; + TempFrame.SequenceNumber = CorrectedMemoryReads; + TempFrame.PerformanceCounterValue = KeQueryPerformanceCounter(NULL).QuadPart; + + // + // Fill in the specific error information + // + + CorrPtr = &TempFrame.CorrectableFrame; + CorrPtr->Flags.SystemInformationValid = 1; + CorrPtr->Flags.AddressSpace = UNIDENTIFIED; + CorrPtr->Flags.MemoryErrorSource = UNIDENTIFIED; + + CorrPtr->Flags.ExtendedErrorValid = 1; + + PExtended = &CorrPtr->ErrorInformation; + + if (ReportWatchdog) { + + // + // Unexpected watchdog timer expiration + // + + PExtended->SystemError.Flags.WatchDogExpiredValid = 1; + PExtended->SystemError.WatchdogExpiration = WdRegister.All; // Watchdog timer expired + + } + else { + + // + // Server management warning condition + // + + if (SmRegister.EnclFanFailure) { + PExtended->SystemError.Flags.FanNumberValid = 1; + PExtended->SystemError.FanNumber = 2; // Enclosure Fan died + } + else if (SmRegister.CpuTempFailure) { + PExtended->SystemError.Flags.TempSensorNumberValid = 1; + PExtended->SystemError.TempSensorNumber = 1; // CPU temp sensor alert + } + else if (SmRegister.CpuTempRestored) { + PExtended->SystemError.Flags.TempSensorNumberValid = 1; + PExtended->SystemError.TempSensorNumber = 101; // CPU temp sensor OK + } + else if (SmRegister.Psu1Failure) { + PExtended->SystemError.Flags.PowerSupplyNumberValid = 1; + PExtended->SystemError.PowerSupplyNumber = 1; // Power supply #1 dead + } + else if (SmRegister.Psu2Failure) { + PExtended->SystemError.Flags.PowerSupplyNumberValid = 1; + PExtended->SystemError.PowerSupplyNumber = 2; // Power supply #2 dead + } + else { + + // + // Error didn't match any expected value -- leave extended error info flag on, + // leave all condition flags off. + // + + CorrPtr->Flags.ExtendedErrorValid = 1; + +#if HALDBG + DbgPrint("smerr: No Server Mgmt error to report!\n"); + +#endif + } + + } + + // + // Correctable frame complete + // + + + // + // Get the interrupt object. + // + + DispatchCode = (PULONG)(PCR->InterruptRoutine[CORRECTABLE_VECTOR]); + InterruptObject = CONTAINING_RECORD(DispatchCode, + KINTERRUPT, + DispatchCode); + + // + // Acquire spinlock for exclusive access to error frame. + // + + ErrorlogBusy = (PBOOLEAN)((PUCHAR)InterruptObject->ServiceContext + sizeof(PERROR_FRAME)); + ErrorlogSpinLock = (PKSPIN_LOCK)((PUCHAR)ErrorlogBusy + sizeof(PBOOLEAN)); + + KiAcquireSpinLock(ErrorlogSpinLock); + + // + // Check to see if an errorlog operation is in progress already. + // + + if (!*ErrorlogBusy) { + + // + // Set the raw system information. + // + + CorrPtr->RawSystemInformationLength = 0; + CorrPtr->RawSystemInformation = NULL; + + // + // Set the raw processor information. Disregard at the moment. + // + + CorrPtr->RawProcessorInformationLength = 0; + + // + // Set reporting processor information. Disregard at the moment. + // + + CorrPtr->Flags.ProcessorInformationValid = 0; + + // + // Copy the information that we need to log. + // + + RtlCopyMemory(&Frame, + &TempFrame, + sizeof(ERROR_FRAME)); + + // + // Put frame into ISR service context. + // + + *(PERROR_FRAME *)InterruptObject->ServiceContext = &Frame; + + } else { + + // + // An errorlog operation is in progress already. We will + // set various lost bits and then get out without doing + // an actual errorloging call. + // + // Chao claims it is not possible to reach this on a UP system. + // + + 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); +} + +VOID +LegoServerMgmtReportFatalError( + USHORT SmRegAll + ) +/*++ + +Routine Description: + + Report an uncorrectable error. + +Arguments: + + SmRegAll -- copy of server management register that is to be reported + +Return Value: + + None + +Notes: + +--*/ +{ + LEGO_SRV_MGMT SmRegister; + PEXTENDED_ERROR PExtended; + + SmRegister.All = SmRegAll; + + // + // Load fields of uncorrectable error record + // + + if (PUncorrectableError) { + + PUncorrectableError->UncorrectableFrame.Flags.SystemInformationValid = 1; + PUncorrectableError->UncorrectableFrame.Flags.AddressSpace = UNIDENTIFIED; + PUncorrectableError->UncorrectableFrame.Flags.MemoryErrorSource = UNIDENTIFIED; + + PUncorrectableError->UncorrectableFrame.Flags.ErrorStringValid = 1; + + PUncorrectableError->UncorrectableFrame.Flags.ExtendedErrorValid = 1; + PExtended = &PUncorrectableError->UncorrectableFrame.ErrorInformation; + + if (SmRegister.CpuFanFailureNmi) { + PExtended->SystemError.Flags.FanNumberValid = 1; + PExtended->SystemError.FanNumber = 1; // CPU Fan + sprintf(PUncorrectableError->UncorrectableFrame.ErrorString, + "CPU fan failed."); + } + else if (SmRegister.EnclTempFailureNmi) { + PExtended->SystemError.Flags.TempSensorNumberValid = 1; + PExtended->SystemError.TempSensorNumber = 2; // Enclosure sensor + sprintf(PUncorrectableError->UncorrectableFrame.ErrorString, + "Enclosure temperature too high for safe operation."); + } + else { + PUncorrectableError->UncorrectableFrame.Flags.ExtendedErrorValid = 0; + sprintf(PUncorrectableError->UncorrectableFrame.ErrorString, + "Unknown server management NMI failure."); // BUG! + } + } +} diff --git a/private/ntos/nthals/hallego/alpha/smir.c b/private/ntos/nthals/hallego/alpha/smir.c new file mode 100644 index 000000000..3fe96ccff --- /dev/null +++ b/private/ntos/nthals/hallego/alpha/smir.c @@ -0,0 +1,722 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation +Copyright (c) 1992,1993,1994,1995,1996 Digital Equipment Corporation + +Module Name: + + smir.c + +Abstract: + + The module provides the interrupt support for Lego's + Server Management and Watchdog timer functions. + +Author: + + Gene Morgan (Digital) 3-Nov-1995 + +Revision History: + + Gene Morgan (Digital) 3-Nov-1995 + Initial version for Lego. Adapted from Mikasa/Noritake. + + Gene Morgan 15-Apr-1996 + Service Watchdog Timer. + +--*/ + +#include "halp.h" + +// +// Define external function prototypes +// + +UCHAR +HalpAcknowledgeServerMgmtInterrupt( + PVOID ServiceContext + ); + +VOID +LegoServerMgmtReportWarningCondition( + BOOLEAN ReportWatchdog, + USHORT SmRegAll, + USHORT WdRegAll + ); + +BOOLEAN +HalpLegoShutdownWatchdog( + VOID + ); + + +// +// Save area for interrupt mask register. +// +USHORT HalpLegoServerMgmtInterruptMask; + +// +// Server management and watchdog timer control. +// defined/setup in lgmapio.c +// +extern PVOID HalpLegoServerMgmtQva; +extern PVOID HalpLegoWatchdogQva; + +// +// Globals for conveying Cpu and Backplane type +// +extern BOOLEAN HalpLegoCpu; +extern BOOLEAN HalpLegoBackplane; +extern ULONG HalpLegoCpuType; +extern ULONG HalpLegoBackplaneType; +extern UCHAR HalpLegoFeatureMask; +extern BOOLEAN HalpLegoServiceWatchdog; + +// +// Track whether error logger is available +// +extern BOOLEAN HalpServerMgmtLoggingEnabled; + +// +// True if someone has "enabled" interrupts +// for a particular server management event. +// +extern BOOLEAN HalpLegoDispatchWatchdog; +extern BOOLEAN HalpLegoDispatchNmi; +extern BOOLEAN HalpLegoDispatchInt; +extern BOOLEAN HalpLegoDispatchPsu; +extern BOOLEAN HalpLegoDispatchHalt; + + +VOID +HalpInitializeServerMgmtInterrupts( + VOID + ) + +/*++ + +Routine Description: + + This routine initializes the Lego + Server Management and Watchdog Timer functions + +Arguments: + + None. + +Return Value: + + None. + +Notes: + + Goal is to set the Server Management and Watchdog + functions to a known state. + +--*/ +{ + LEGO_SRV_MGMT SmRegister; + LEGO_WATCHDOG WdRegister; + + // + // Initial state is error logger is not available + // + + HalpServerMgmtLoggingEnabled = FALSE; + + // + // Assume watchdog is idle. + // There's no interrupt mask bit, so no work needs to be done here. + // + + if (HalpLegoFeatureMask & LEGO_FEATURE_WATCHDOG) { + + // + // Do nothing until clock is started. + // + + HalpLegoDispatchWatchdog = FALSE; + + } + + // Set the mask bits for all Server Management functions + // (i.e., block interrupts) + // + if (HalpLegoFeatureMask & LEGO_FEATURE_SERVER_MGMT) { + SmRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva ); + SmRegister.IntMask = 0; + SmRegister.NmiMask = 0; + SmRegister.PsuMask = 0; // not present on all platforms + WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva, SmRegister.All ); + + HalpLegoDispatchNmi = FALSE; + HalpLegoDispatchInt = FALSE; + HalpLegoDispatchPsu = FALSE; + HalpLegoDispatchHalt = FALSE; + } +} + + +VOID +HalpDisableServerMgmtInterrupt( + IN ULONG Vector + ) + +/*++ + +Routine Description: + + This function disables the Server Management + or Watchdog Timer interrupt specified by Vector. + +Arguments: + + Vector - Supplies the vector of the interrupt to disable. + +Return Value: + + None. + +Notes: + + An interrupt is masked by setting the appropriate mask bit to 1. + The halt button cannot be masked. + +--*/ + +{ + LEGO_SRV_MGMT SmRegister; + LEGO_WATCHDOG WdRegister; + + // dispatch on vector to determine which interrupt mask to clear + // + switch (Vector) { + + case WATCHDOG_VECTOR: + // + // Disable Watchdog timer interrupts (and the timer itself) + // + // If timer is running and timer 2 is active, timer 2 + // must be stopped before the timer can be disabled. + // + + HalpLegoShutdownWatchdog(); + + // + // Re-enable timer but stop performing secondary dispatch + // + + WdRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoWatchdogQva ); + WdRegister.Enabled = 1; + WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoWatchdogQva, WdRegister.All ); + + HalpLegoDispatchWatchdog = FALSE; + break; + + case SM_WARNING_VECTOR: + +#if 0 + SmRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva ); + SmRegister.IntMask = 1; + WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva, SmRegister.All ); +#endif + + HalpLegoDispatchInt = FALSE; + break; + + case SM_ERROR_VECTOR: + +#if 0 + SmRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva ); + SmRegister.NmiMask = 1; + WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva, SmRegister.All ); +#endif + + HalpLegoDispatchNmi = FALSE; + break; + + case SM_PSU_FAILURE_VECTOR: + +#if 0 + SmRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva ); + SmRegister.PsuMask = 1; + WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva, SmRegister.All ); +#endif + + HalpLegoDispatchPsu = FALSE; + break; + + case HALT_BUTTON_VECTOR: + // + // Halt button cannot be masked -- ignore + // + + HalpLegoDispatchHalt = FALSE; + break; + + default: + // + // Error - unrecognized vector + // + break; + } +} + + +VOID +HalpEnableServerMgmtInterrupt( + IN ULONG Vector, + IN KINTERRUPT_MODE InterruptMode + ) + +/*++ + +Routine Description: + + This function enables the Server Management or + Watchdog Timer interrupt specified by Vector. + +Arguments: + + Vector - Supplies the vector of the interrupt to be enabled. + + InterruptMode - Supplies the mode of the interrupt; + LevelSensitive or Latched //[wem] ??? check this ??? + +Return Value: + + None. + +Notes: + + An interrupt is enabled by clearing the appropriate mask bit (i.e., set to 0). + The halt button cannot be masked. + +--*/ + +{ + LEGO_SRV_MGMT SmRegister; + LEGO_WATCHDOG WdRegister; + + // dispatch on vector to determine which interrupt mask to clear + // + switch (Vector) { + + case WATCHDOG_VECTOR: + // + // Enable Watchdog timer interrupts (and the timer itself) + // Assume all other aspects of the timer are correctly setup, but: + // + // If timer is already running and timer 2 is active, re-establish timer 1. + // + + HalpLegoShutdownWatchdog(); + + WdRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoWatchdogQva ); + WdRegister.Enabled = 1; + WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoWatchdogQva, WdRegister.All ); + + // + // Watchdog is enabled and Timer 1 is now running + // + + HalpLegoDispatchWatchdog = TRUE; + break; + + case SM_WARNING_VECTOR: + +#if 0 + SmRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva ); + SmRegister.IntMask = 0; + WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva, SmRegister.All ); +#endif + HalpLegoDispatchInt = TRUE; + break; + + case SM_ERROR_VECTOR: + +#if 0 + SmRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva ); + SmRegister.NmiMask = 0; + WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva, SmRegister.All ); +#endif + HalpLegoDispatchNmi = TRUE; + break; + + case SM_PSU_FAILURE_VECTOR: + +#if 0 + SmRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva ); + SmRegister.PsuMask = 0; + WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva, SmRegister.All ); +#endif + HalpLegoDispatchPsu = TRUE; + break; + + case HALT_BUTTON_VECTOR: + + // + // Halt button cannot be masked. + // + + HalpLegoDispatchHalt = TRUE; + break; + + default: + + // + // Error - unrecognized vector + // + + break; + } + +} + +UCHAR +HalpAcknowledgeServerMgmtInterrupt( + PVOID ServiceContext + ) +/*++ + +Routine Description: + + Acknowledge the Server Management interrupt. Return vector number of the + highest priority pending interrupt. + +Arguments: + + ServiceContext - Service context of the interrupt service - supplies + a QVA to Lego's Server Management interrupt register. + +Return Value: + + Return the value of the highest priority pending interrupt, + or 0xff if none. + +--*/ +{ + LEGO_SRV_MGMT SmRegister; + LEGO_WATCHDOG WdRegister; + UCHAR Vector; + + // + // Check the watchdog and server management registers to see which + // event occurred. + // + // Read watchdog first since it is most probable cause of interrupt + // + + // + // Value to return if no match + // + + Vector = 0xFF; + + // + // Check Watchdog register's interrupt bit. + // + + WdRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoWatchdogQva ); + +#if DBG + DbgPrint(" ",WdRegister.All); +#endif + + if (WdRegister.Interrupt==1) { + + Vector = (WATCHDOG_VECTOR - SERVER_MGMT_VECTORS); + +#if DBG + DbgPrint(" ",WdRegister.All); +#endif + + } + else { + + // + // Check Server Management register bits + // + + SmRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva ); + +#if DBG + DbgPrint(" ",SmRegister.All); +#endif + + if (SmRegister.CpuTempFailure==1 + || SmRegister.CpuTempRestored==1 + || SmRegister.EnclFanFailure==1) { + + Vector = (SM_WARNING_VECTOR - SERVER_MGMT_VECTORS); + } + else if (SmRegister.Psu1Failure==1 + || SmRegister.Psu2Failure) { + + Vector = (SM_PSU_FAILURE_VECTOR - SERVER_MGMT_VECTORS); + } + } + + return Vector; +} + + +BOOLEAN +HalpServerMgmtDispatch( + IN PKINTERRUPT Interrupt, + IN PVOID ServiceContext, + IN PKTRAP_FRAME TrapFrame + ) +/*++ + +Routine Description: + + This routine is entered as the result of an interrupt having been generated + via the vector connected to the Server Management device interrupt object. + Its function is to call the second-level interrupt dispatch routine. + + If the second level dispatch doesn't handle, then this routine will perform + default handling. + + This service routine could have been connected as follows, where the + ISR is the assembly wrapper that does the handoff to this function: + + KeInitializeInterrupt( &Interrupt, + HalpServerMgmtInterruptHandler, + (PVOID) HalpLegoServerMgmtInterruptQva, + (PKSPIN_LOCK)NULL, + SERVER_MGMT_VECTOR, + SERVER_MGMT_DEVICE_LEVEL, + SERVER_MGMT_DEVICE_LEVEL, + LevelSensitive, + TRUE, + 0, + FALSE); + + KeConnectInterrupt(&Interrupt); + +Arguments: + + Interrupt - Supplies a pointer to the interrupt object. + + ServiceContext - Supplies a pointer to the Server Management + interrupt register. + + TrapFrame - Supplies a pointer to the trap frame for this interrupt. + +Return Value: + + Returns the value returned from the second level routine. + +Notes: + + Only the CPU IRQ5 interrupts come through here. Server management + NMIs are handled by HalpHandleNmi() + +--*/ +{ + UCHAR SmVector; + BOOLEAN returnValue; + LEGO_SRV_MGMT SmRegister, SmRegisterLog; + LEGO_WATCHDOG WdRegister, WdRegisterLog; + + BOOLEAN LogIt = FALSE; + BOOLEAN LogWatchdog = FALSE; + + // + // [wem] DEBUG - count SM dispatch entries + // + static long IntCount = 0; + +#if DBG //[wem] + IntCount++; + if (IntCount<5) { + DbgPrint("II<"); + } + if (IntCount % 1000 == 0) { + DbgPrint("II<%08x><", IntCount); + } +#endif + + // + // Acknowledge interrupt and receive the returned interrupt vector. + // If we got 0xff back, there were no enabled interrupts, so we + // signal that with a FALSE return, immediately. + // + + SmVector = HalpAcknowledgeServerMgmtInterrupt(ServiceContext); + +#if DBG + DbgPrint(" ",SmVector); +#endif + + if (SmVector == ((UCHAR)0xff)) { + +#if DBG //[wem] + if (IntCount<5 || (IntCount % 1000)==0) { + DbgPrint("ff>."); + } +#endif + return( FALSE ); + } + + SmVector += SERVER_MGMT_VECTORS; + +#if DBG + DbgPrint(" ",SmVector); +#endif + + switch (SmVector) { + + case WATCHDOG_VECTOR: + + if (HalpLegoDispatchWatchdog + && ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[SmVector])( + PCR->InterruptRoutine[SmVector], + TrapFrame) + ) { + return TRUE; + } + + WdRegisterLog.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoWatchdogQva ); + +#if DBG + DbgPrint(" ",WdRegisterLog.All); +#endif + + if (HalpLegoServiceWatchdog) { + + // + // Get control of the watchdog timer + // + + HalpLegoShutdownWatchdog(); + + // + // Re-enable it + // + + WdRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoWatchdogQva ); + WdRegister.Enabled = 1; + WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoWatchdogQva, WdRegister.All); + + returnValue = TRUE; + } + else { + + // + // Dismiss the interrupt -- but system is on the way down! + // + + WdRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoWatchdogQva ); + WdRegister.Interrupt = 1; + WdRegister.Enabled = 1; + WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoWatchdogQva, WdRegister.All ); + + // + // Interrupt not serviced + // + + returnValue = FALSE; + + } + + LogIt = TRUE; + LogWatchdog = TRUE; + + break; + + case SM_WARNING_VECTOR: + + if (HalpLegoDispatchInt + && ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[SmVector])( + PCR->InterruptRoutine[SmVector], + TrapFrame) + ) { + return TRUE; + } + + SmRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva ); + SmRegisterLog.All = SmRegister.All; + + // Handle any that were not handled by secondary dispatch + // + if (SmRegister.CpuTempRestored==1) { + HalDisplayString ("Server Management: CPU Temperature restored.\n"); + } + if (SmRegister.CpuTempFailure==1) { + HalDisplayString ("Server Management: CPU Temperature warning.\n"); + } + if (SmRegister.EnclFanFailure==1) { + HalDisplayString ("Server Management: System fan failure.\n"); + } + + // Any interrupts will be cleared + // Don't touch PSU interrupts + // + SmRegister.Psu1Failure = 0; + SmRegister.Psu2Failure = 0; + WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva, SmRegister.All ); + + LogIt = TRUE; + returnValue = TRUE; + break; + + case SM_PSU_FAILURE_VECTOR: + + if (HalpLegoDispatchPsu + && ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[SmVector])( + PCR->InterruptRoutine[SmVector], + TrapFrame) + ) { + return TRUE; + } + + SmRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva ); + SmRegisterLog.All = SmRegister.All; + + // + // Handle any that were not handled by secondary dispatch + // + + if (SmRegister.Psu1Failure==1) { + HalDisplayString ("Server Management: PSU 1 has failed.\n"); + } + if (SmRegister.Psu2Failure==1) { + HalDisplayString ("Server Management: PSU 2 has failed.\n"); + } + + // Any interrupts will be cleared + // Don't touch fan/temperature interrupts + // + SmRegister.CpuTempRestored = 0; + SmRegister.CpuTempFailure = 0; + SmRegister.EnclFanFailure = 0; + WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva, SmRegister.All ); + + LogIt = TRUE; + returnValue = TRUE; + + break; + + + default: + returnValue = FALSE; //[wem] Error -- bugcheck? + } + +#if DBG //[wem] + if (IntCount<5 || (IntCount % 1000)==0) { + DbgPrint("%02x>.", returnValue); + } +#endif + + // + // Post "correctable" error record to error log. + // + + if (LogIt) { + LegoServerMgmtReportWarningCondition(LogWatchdog, SmRegisterLog.All,WdRegisterLog.All); + } + + return( returnValue ); +} diff --git a/private/ntos/nthals/hallego/alpha/smsup.c b/private/ntos/nthals/hallego/alpha/smsup.c new file mode 100644 index 000000000..c84269e4e --- /dev/null +++ b/private/ntos/nthals/hallego/alpha/smsup.c @@ -0,0 +1,363 @@ +/*++ + +Copyright (c) 1996 Digital Equipment Corporation + +Module Name: + + smsup.c + +Abstract: + + Server Management support + +Author: + + Gene Morgan (Digital) 28-Apr-1996 + +Revision History: + +--*/ + +#include "halp.h" +#include "pcf8574.h" + + +// +// Local prototypes +// + +BOOLEAN +HalpLegoShutdownWatchdog( + VOID + ); + +VOID +HalpLegoInitWatchdog( + UCHAR WdMode, + UCHAR WdTimer1, + UCHAR WdTimer2, + BOOLEAN Enabled + ); + +VOID +HalpPowerOff( + VOID + ); + +BOOLEAN +LegoServerMgmtDelayedShutdown( + ULONG DelaySeconds + ); + + +// +// Server management and watchdog timer control. +// defined/setup in lgmapio.c +// +extern PVOID HalpLegoServerMgmtQva; +extern PVOID HalpLegoWatchdogQva; + +// +// Globals for conveying Cpu and Backplane type +// +extern BOOLEAN HalpLegoCpu; +extern BOOLEAN HalpLegoBackplane; +extern ULONG HalpLegoCpuType; +extern ULONG HalpLegoBackplaneType; +extern UCHAR HalpLegoFeatureMask; +extern BOOLEAN HalpLegoServiceWatchdog; + + +BOOLEAN +HalpLegoShutdownWatchdog( + VOID + ) + +/*++ + +Routine Description: + + Shutdown the wtachdog timer. + + +Arguments: + + None. + +Return Value: + + TRUE if watchdog was successfully shut down, FALSE otherwise. + +Notes: + + Algorithm works if watchdog is in stage one or two. + + On TRUE return, Watchdog is ready to be enabled. + On FALSE return, watchdog is running, reset will eventually occur. + +--*/ +{ + LEGO_WATCHDOG WdRegister; + ULONG Count; +#if DBG + ULONG DbgCnt; + + DbgCnt = 0; + DbgPrint(" 10) { + DbgPrint(">10> "); + break; + } +#endif + } + +#if DBG + DbgPrint("%d> ",DbgCnt); +#endif + + // + // Return TRUE if count not exhausted + // + return (Count > 0); + +} + + +VOID +HalpLegoInitWatchdog( + UCHAR WdMode, + UCHAR WdTimer1, + UCHAR WdTimer2, + BOOLEAN Enabled + ) +/*++ + +Routine Description: + + Setup the Lego watchdog timer. + +Arguments: + + WdMode, WdTimer1, WdTimer2 -- new parameters for watchdog timer + Enabled -- TRUE if timer should be started + +Return Value: + + None. + + ++*/ +{ + LEGO_WATCHDOG WdRegister; + + if (HalpLegoFeatureMask & LEGO_FEATURE_WATCHDOG) { + + // + // Disable watchdog in case it was running + // + + HalpLegoShutdownWatchdog(); + } + + if (HalpLegoFeatureMask & LEGO_FEATURE_WATCHDOG) { + + // + // Set mode and timers, leave disabled for now + // HAL will enable the timer during its initialization + // + + WdRegister.All = 0; + WdRegister.Mode = WdMode; + WdRegister.TimerOnePeriod = WdTimer1; + WdRegister.TimerTwoPeriod = WdTimer2; + +#if DBG + DbgPrint("Watchdog setting: %04x\n",WdRegister.All); +#endif + WRITE_REGISTER_USHORT((PUSHORT)HalpLegoWatchdogQva,WdRegister.All); + + if (Enabled) { + WdRegister.Enabled = 1; + WRITE_REGISTER_USHORT((PUSHORT)HalpLegoWatchdogQva,WdRegister.All); + } + } +} + + +VOID +HalpPowerOff( + VOID + ) +/*++ + +Routine Description: + + Shutdown the system (i.e., shutdown power supply) + +Arguments: + + None. + +Return Value: + + Doesn't return. + +Notes: + + This will work iff the proper connections to the power supply exists. + + ++*/ +{ + LEGO_SRV_MGMT SmRegister; + UCHAR Buffer[2]; + int i,j,k; + + // + // Set the power off bit in the server management register + // + // [wem] ??? Currently it appears that toggling the bit 1->0 triggers + // the shutdown. Toggle it both ways just in case... + + SmRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva); + SmRegister.PowerOff = 0; + WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva,SmRegister.All); + SmRegister.PowerOff = 1; + WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva,SmRegister.All); + + // + // Wait forever if necessary + // + + i=j=k=0; + HalpOcpPutString("SHUT:000", 8, 0); + Buffer[1] = '\0'; + + while (1) { + + if (i == 10) { + i = 0; + if (j == 10) { + j = 0; + if (k == 10) { + k = 0; + } + HalpOcpPutString(((k & 1)==0)?"DOWN":"SHUT", 4, 0); + Buffer[0] = '0' + k; + HalpOcpPutString(Buffer, 1, 5); + k++; + } + Buffer[0] = '0' + j; + HalpOcpPutString(Buffer, 1, 6); + j++; + } + Buffer[0] = '0' + i; + HalpOcpPutString(Buffer, 1, 7); + i++; + } + +} + +BOOLEAN +LegoServerMgmtDelayedShutdown( + ULONG DelaySeconds + ) +/*++ + +Routine Description: + + Schedule a powerdown. + + Current algorithm: + 1. Shutdown watchdog. + 2. Init watchdog for requested delay and single-stage timeout + (since interrupts will be shut off + 3. Set boolean to indicate power-down in progress + 4. return TRUE if power-down will occur + + When reset is performed, firmware will get control, rediscover + failure, and act accordingly. + + Problem? will shutdown or KeBugCheck disable interrupts? May have to do + something else... + +Arguments: + + DelaySeconds -- desired delay. Should match capabilities of watchdog. + +Return Value: + + TRUE if reset successfully initiated + +Notes: + +--*/ +{ + BOOLEAN WillShutdown; + UCHAR Period; + ULONG Count; + + // + // If watchdog not present, bail out + // + + if (!(HalpLegoFeatureMask & LEGO_FEATURE_WATCHDOG)) { + return FALSE; + } + + // + // Shutdown watchdog, then set it up for the + // requested delay. + // + + WillShutdown = HalpLegoShutdownWatchdog(); + + if (WillShutdown) { + if (DelaySeconds <= 1) { + Period = WATCHDOG_PERIOD_1S; + } + else if (DelaySeconds <= 8) { + Period = WATCHDOG_PERIOD_8S; + } + else if (DelaySeconds <= 60) { + Period = WATCHDOG_PERIOD_60S; + } + else if (DelaySeconds <= 300) { + Period = WATCHDOG_PERIOD_300S; + } + else if (DelaySeconds <= 1200) { + Period = WATCHDOG_PERIOD_1200S; + } + + HalpLegoInitWatchdog(WATCHDOG_MODE_1TIMER, + Period, + Period, + TRUE); + } + + return WillShutdown; // Power-off attempt failed! +} diff --git a/private/ntos/nthals/hallego/alpha/vga.c b/private/ntos/nthals/hallego/alpha/vga.c new file mode 100644 index 000000000..764c585af --- /dev/null +++ b/private/ntos/nthals/hallego/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/hallego/bushnd.c b/private/ntos/nthals/hallego/bushnd.c new file mode 100644 index 000000000..a1e648dc1 --- /dev/null +++ b/private/ntos/nthals/hallego/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/hallego/drivesup.c b/private/ntos/nthals/hallego/drivesup.c new file mode 100644 index 000000000..38259e5f4 --- /dev/null +++ b/private/ntos/nthals/hallego/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/hallego/hal.aps b/private/ntos/nthals/hallego/hal.aps new file mode 100644 index 000000000..e69de29bb diff --git a/private/ntos/nthals/hallego/hal.rc b/private/ntos/nthals/hallego/hal.rc new file mode 100644 index 000000000..3cba4ad89 --- /dev/null +++ b/private/ntos/nthals/hallego/hal.rc @@ -0,0 +1,11 @@ +#include + +#include + +#define VER_FILETYPE VFT_DLL +#define VER_FILESUBTYPE VFT2_UNKNOWN +#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL" +#define VER_INTERNALNAME_STR "hal.dll" + +#include "common.ver" + diff --git a/private/ntos/nthals/hallego/hal.src b/private/ntos/nthals/hallego/hal.src new file mode 100644 index 000000000..da778bb9d --- /dev/null +++ b/private/ntos/nthals/hallego/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/hallego/makefile b/private/ntos/nthals/hallego/makefile new file mode 100644 index 000000000..6ee4f43fa --- /dev/null +++ b/private/ntos/nthals/hallego/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/hallego/makefile.inc b/private/ntos/nthals/hallego/makefile.inc new file mode 100644 index 000000000..75668f3d2 --- /dev/null +++ b/private/ntos/nthals/hallego/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\hallego.lib + copy $** $@ diff --git a/private/ntos/nthals/hallego/sources b/private/ntos/nthals/hallego/sources new file mode 100644 index 000000000..fe9f99c01 --- /dev/null +++ b/private/ntos/nthals/hallego/sources @@ -0,0 +1,111 @@ +!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=hallego +TARGETPATH=$(BASEDIR)\public\sdk\lib + +ALPHA_WARNING_LEVEL=-W3 +C_DEFINES=-DEV4 -DAPECS -DTAGGED_NVRAM + +NT_UP=1 + +!IF $(ALPHA) + +TARGETTYPE=HAL + +!ELSE + +TARGETTYPE=DRIVER + +!ENDIF + +INCLUDES=..\..\inc;..\..\ke;..\..\io;..\..\fw\alpha;..\..\fastfat;..\halalpha + +SOURCES= + +ALPHA_SOURCES=hal.rc \ + bushnd.c \ + drivesup.c \ + alpha\allstart.c \ + alpha\alphaio.s \ + alpha\apecs.c \ + alpha\apecserr.c \ + alpha\apecsio.s \ + alpha\adjust.c \ + alpha\bios.c \ + alpha\cache.c \ + alpha\cmos8k.c \ + alpha\ebsgdma.c \ + alpha\eisasup.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\idle.s \ + alpha\info.c \ + alpha\inithal.c \ + alpha\intsup.s \ + alpha\ioproc.c \ + alpha\iousage.c \ + alpha\memory.c \ + alpha\nvram.c \ + alpha\nvenv.c \ + alpha\pcibus.c \ + alpha\pcisio.c \ + alpha\pcisup.c \ + alpha\pcrtc.c \ + alpha\pcserial.c \ + alpha\pcspeakr.c \ + alpha\perfcntr.c \ + alpha\vga.c \ + alpha\addrsup.c \ + alpha\busdata.c \ + alpha\lginitnt.c \ + alpha\lgintsup.c \ + alpha\lgintr.s \ + alpha\lgmapio.c \ + alpha\lgsysint.c \ + alpha\pciir.c \ + alpha\smir.c \ + alpha\smerr.c \ + alpha\smsup.c \ + alpha\pcf8574.c \ + alpha\pcd8584.c + +DLLDEF=obj\*\hal.def + +!IF $(ALPHA) + +NTTARGETFILES=$(TARGETPATH)\alpha\hal.lib \ + $(TARGETPATH)\alpha\hal.dll + +!ENDIF -- cgit v1.2.3