diff options
Diffstat (limited to 'private/ntos/nthals/halpinna/alpha')
53 files changed, 8306 insertions, 0 deletions
diff --git a/private/ntos/nthals/halpinna/alpha/addrsup.c b/private/ntos/nthals/halpinna/alpha/addrsup.c new file mode 100644 index 000000000..d271cc07a --- /dev/null +++ b/private/ntos/nthals/halpinna/alpha/addrsup.c @@ -0,0 +1,596 @@ +/*++ + +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 Mikasa EV5 (Pinnacle) system. + +Author: + + Joe Notarangelo 22-Oct-1993 + +Environment: + + Kernel mode + +Revision History: + + Scott Lee (Digital) 29-Nov-1995 + Adapted this from Mikasa version for Mikasa EV5 (Pinnacle) systems. + +--*/ + +#include "halp.h" +#include "eisa.h" +#include "mikasa.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 buses available on Mikasa are EISA and PCI. + // We support any translations for ISA devices as well, + // since they can plug into EISA slots just fine. + // + + 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 Eisa: + + // + // Eisa is the same as PCI, with respect to kernel mode + // sparse and dense space memory support, i.e., its a full 32 bit space, + // supports dense memory access. + // + + case PCIBus: { + + if ( BusAddress.LowPart > PCI_MAX_DENSE_MEMORY_ADDRESS ) { + + // + // Unsupported dense PCI bus address. + // +#if HALDBG + DbgPrint ("Unsupported PCI/EISA 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/EISA 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/EISA memory space + // + +#if HALDBG + DbgPrint ("Translating PCI kernel sparse address %x:%x\n", + BusAddress.HighPart, + BusAddress.LowPart); +#endif + + break; + } // case PCIBus, Eisa + + } // switch( InterfaceType ) + + // + // Start with the base physical address and add the + // bus address by converting it to the physical address. + // + + TranslatedAddress->QuadPart = CIA_PCI_SPARSE_MEMORY_PHYSICAL; + TranslatedAddress->QuadPart += ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT); + + // + // Now call HalCreateQva. This will create a QVA + // that we'll return to the caller. Then we will explicitly 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 Eisa: + + // + // Eisa is the same as ISA, with respect to kernel mode + // sparse I/O space support, i.e., it is a 16 bit sparse + // space. + // + + case 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 HAER2 + // register. + // + break; + } // case PCIBus + + + } // switch( InterfaceType ) + + // + // Start with the base physical address and add the + // bus address by converting it to the physical address. + // + + TranslatedAddress->QuadPart = CIA_PCI_SPARSE_IO_PHYSICAL; + TranslatedAddress->QuadPart += ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT); + + // + // Now call HalCreateQva. This will create a QVA + // that we'll return to the caller. Then we will explicitly 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 = CIA_PCI_SPARSE_MEMORY_PHYSICAL; + TranslatedAddress->QuadPart |= EV5_USER_IO_ADDRESS_SPACE; + TranslatedAddress->QuadPart += ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT); + + *AddressSpace = 0; // Let the user call MmMapIoSpace + + return(TRUE); + + } // case UserBusMemory + + 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 = CIA_PCI_SPARSE_IO_PHYSICAL; + TranslatedAddress->QuadPart |= EV5_USER_IO_ADDRESS_SPACE; + TranslatedAddress->QuadPart += ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT); + + *AddressSpace = 0; // Let the user call MmMapIoSpace + + return(TRUE); + + } // case UserBusIo + + 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 = CIA_PCI_DENSE_MEMORY_PHYSICAL; + TranslatedAddress->QuadPart |= EV5_USER_IO_ADDRESS_SPACE; + TranslatedAddress->QuadPart += BusAddress.LowPart; + + *AddressSpace = 0; // Let the user call MmMapIoSpace + + return(TRUE); + + } // case UserPciDenseMemory + + default: { + + // + // Unsupported address space. + // + + *AddressSpace = 0; + TranslatedAddress->LowPart = 0; + return(FALSE); + } // default + + } +} + +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. + +--*/ +{ + + PHYSICAL_ADDRESS PhysicalOffset; + PVOID qva; + + if( (PA.QuadPart >= CIA_PCI_DENSE_MEMORY_PHYSICAL) && + (PA.QuadPart <= (CIA_PCI_DENSE_MEMORY_PHYSICAL + + PCI_MAX_DENSE_MEMORY_ADDRESS)) ){ + + // + // Kernel-mode physical dense address, return VA. + // + + return(VA); + + } else if( (PA.QuadPart >= + (CIA_PCI_DENSE_MEMORY_PHYSICAL | EV5_USER_IO_ADDRESS_SPACE) ) && + (PA.QuadPart < + (CIA_PCI_DENSE_MEMORY_PHYSICAL | EV5_USER_IO_ADDRESS_SPACE + + PCI_MAX_DENSE_MEMORY_ADDRESS) ) ){ + + // + // User-mode physical dense address, return VA. + // + + return(VA); + + } else { + + // + // The physical address is within one of the sparse I/O spaces. + // + + if (VA == 0) { + + PhysicalOffset.QuadPart = PA.QuadPart - CIA_QVA_PHYSICAL_BASE; + qva = (PVOID)(PhysicalOffset.QuadPart >> IO_BIT_SHIFT); + } else { + + qva = (PVOID)((ULONG)VA >> IO_BIT_SHIFT); + } + + qva = (PVOID)((ULONG)qva | QVA_ENABLE); + + return(qva); + } + +} + + +PVOID +HalDereferenceQva( + PVOID Qva, + INTERFACE_TYPE InterfaceType, + ULONG BusNumber + ) +/*++ + +Routine Description: + + This function performs the inverse of the HalCreateQva for I/O addresses + that are memory-mapped (i.e. the quasi-virtual address was created from + a virtual address rather than a physical address). + +Arguments: + + Qva - Supplies the quasi-virtual address to be converted back to a + virtual address. + + InterfaceType - Supplies the interface type of the bus to which the + Qva pertains. + + BusNumber - Supplies the bus number of the bus to which the Qva pertains. + +Return Value: + + The Virtual Address from which the quasi-address was originally created + is returned. + +--*/ +{ + + // + // For Mikasa we have support three bus types: + // + // Isa + // Eisa + // PCIBus + // + + switch (InterfaceType ){ + + case Isa: + case Eisa: + case PCIBus: + + // + // Support PCI Dense space: check to see if it's really + // a 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/halpinna/alpha/adjust.c b/private/ntos/nthals/halpinna/alpha/adjust.c new file mode 100644 index 000000000..47c267fb8 --- /dev/null +++ b/private/ntos/nthals/halpinna/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/halpinna/alpha/allstart.c b/private/ntos/nthals/halpinna/alpha/allstart.c new file mode 100644 index 000000000..42f70b7ca --- /dev/null +++ b/private/ntos/nthals/halpinna/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/halpinna/alpha/bios.c b/private/ntos/nthals/halpinna/alpha/bios.c new file mode 100644 index 000000000..3a9d3aa50 --- /dev/null +++ b/private/ntos/nthals/halpinna/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/halpinna/alpha/busdata.c b/private/ntos/nthals/halpinna/alpha/busdata.c new file mode 100644 index 000000000..af95247cd --- /dev/null +++ b/private/ntos/nthals/halpinna/alpha/busdata.c @@ -0,0 +1,138 @@ +/*++ + + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + busdata.c + +Abstract: + + This module contains get/set bus data routines. + +Author: + + Darryl E. Havens (darrylh) 11-Apr-1990 + +Environment: + + Kernel mode + +Revision History: + + James Livingston 29-Apr-1994 + Adapted from Avanti module for Mikasa. + +--*/ + +#include "halp.h" + +// +// External Function Prototypes +// + +ULONG +HalpNoBusData ( + IN PVOID BusHandler, + IN PVOID RootHandler, + IN ULONG SlotNumber, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ); + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(INIT,HalpRegisterInternalBusHandlers) +#endif + + +VOID +HalpRegisterInternalBusHandlers ( + VOID + ) +/*++ + +Routine Description: + + This function registers the bushandlers for buses on the system + that will always be present on the system. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + PBUS_HANDLER Bus; + + // + // Initalize BusHandler data before registering any handlers + // + + HalpInitBusHandler (); + + // + // Build the processor internal bus 0 + // + + HaliRegisterBusHandler (ProcessorInternal, // Bus Type + -1, // No config space + 0, // Bus Number + -1, // No parent bus type + 0, // No parent bus number + 0, // No extension data + NULL, // No install handler + &Bus); // Bushandler return + + Bus->GetInterruptVector = HalpGetSystemInterruptVector; + + // + // Build internal-bus 0, or system level bus + // + + HaliRegisterBusHandler (Internal, // Bus Type + -1, // No config space + 0, // Bus Number + -1, // No parent bus type + 0, // No parent bus number + 0, // No extension data + NULL, // No install handler + &Bus); // Bushandler return + + Bus->GetInterruptVector = HalpGetSystemInterruptVector; + Bus->TranslateBusAddress = HalpTranslateSystemBusAddress; + + // + // Build Isa/Eisa bus #0 + // + + HaliRegisterBusHandler (Eisa, // Bus Type + EisaConfiguration, // Config space type + 0, // Internal bus #0 + Internal, // Parent bus type + 0, // Parent bus number + 0, // No extension data + NULL, // No install handler + &Bus); // Bushandler return + + Bus->GetBusData = HalpGetEisaData; + Bus->AdjustResourceList = HalpAdjustEisaResourceList; + + HaliRegisterBusHandler (Isa, // Bus Type + -1, // No config space + 0, // Internal bus #0 + Eisa, // Parent bus type + 0, // Parent bus number + 0, // No extension data + NULL, // No install handler + &Bus); // Bushandler returne + + Bus->GetBusData = HalpNoBusData; + Bus->AdjustResourceList = HalpAdjustIsaResourceList; + +} diff --git a/private/ntos/nthals/halpinna/alpha/cache.c b/private/ntos/nthals/halpinna/alpha/cache.c new file mode 100644 index 000000000..b058d72ef --- /dev/null +++ b/private/ntos/nthals/halpinna/alpha/cache.c @@ -0,0 +1 @@ +#include "..\halalpha\cache.c" diff --git a/private/ntos/nthals/halpinna/alpha/chipset.h b/private/ntos/nthals/halpinna/alpha/chipset.h new file mode 100644 index 000000000..9d4e28d6e --- /dev/null +++ b/private/ntos/nthals/halpinna/alpha/chipset.h @@ -0,0 +1 @@ +#include "cia.h" diff --git a/private/ntos/nthals/halpinna/alpha/cia.c b/private/ntos/nthals/halpinna/alpha/cia.c new file mode 100644 index 000000000..7948bfe16 --- /dev/null +++ b/private/ntos/nthals/halpinna/alpha/cia.c @@ -0,0 +1,7 @@ +// +// This file simply includes the source file from the common Alpha +// HAL directory. +// + +#include "..\halalpha\cia.c" + diff --git a/private/ntos/nthals/halpinna/alpha/ciaaddr.c b/private/ntos/nthals/halpinna/alpha/ciaaddr.c new file mode 100644 index 000000000..890d692a6 --- /dev/null +++ b/private/ntos/nthals/halpinna/alpha/ciaaddr.c @@ -0,0 +1 @@ +#include "..\halalpha\ciaaddr.c" diff --git a/private/ntos/nthals/halpinna/alpha/ciaerr.c b/private/ntos/nthals/halpinna/alpha/ciaerr.c new file mode 100644 index 000000000..7ab595861 --- /dev/null +++ b/private/ntos/nthals/halpinna/alpha/ciaerr.c @@ -0,0 +1,1636 @@ +/*++ + +Copyright (c) 1994 Digital Equipment Corporation + +Module Name: + + ciaerr.c + +Abstract: + + This module implements error handling functions for the CIA ASIC. + +Author: + + Joe Notarangelo 26-Jul-1994 + +Environment: + + Kernel mode + +Revision History: + + +--*/ + +#include "halp.h" +#include "cia.h" +#include "stdio.h" + +// +// Externals and globals. +// + +// +// Declare the extern variable UncorrectableError declared in +// inithal.c. +// +extern PERROR_FRAME PUncorrectableError; + +extern ULONG HalDisablePCIParityChecking; +ULONG CiaCorrectedErrors = 0; + +// +// Define the context structure for use by interrupt service routines. +// + +typedef BOOLEAN (*PSECOND_LEVEL_DISPATCH)( + PKINTERRUPT InterruptObject, + PVOID ServiceContext + ); + +// +// Function prototypes. +// + +VOID +HalpSetMachineCheckEnables( + IN BOOLEAN DisableMachineChecks, + IN BOOLEAN DisableProcessorCorrectables, + IN BOOLEAN DisableSystemCorrectables + ); + +VOID +HalpUpdateMces( + IN BOOLEAN ClearMachineCheck, + IN BOOLEAN ClearCorrectableError + ); + +// +// Allocate a flag that indicates when a PCI Master Abort is expected. +// PCI Master Aborts are signaled on configuration reads to non-existent +// PCI slots. A non-zero value indicates that a Master Abort is expected. +// + +ULONG HalpMasterAbortExpected = 0; + + +VOID +HalpInitializeCiaMachineChecks( + IN BOOLEAN ReportCorrectableErrors, + IN BOOLEAN PciParityChecking + ) +/*++ + +Routine Description: + + This routine initializes machine check handling for a CIA-based + system by clearing all pending errors in the CIA registers and + enabling correctable errors according to the callers specification. + +Arguments: + + ReportCorrectableErrors - Supplies a boolean value which specifies + if correctable error reporting should be + enabled. + +Return Value: + + None. + +--*/ +{ + CIA_CONTROL CiaControl; + CIA_ERR CiaError; + CIA_ERR_MASK CiaErrMask; + + // + // Clear any pending error bits in the CIA_ERR register: + // + + CiaError.all = 0; // Clear all bits + + CiaError.CorErr = 1; // Correctable error + CiaError.UnCorErr = 1; // Uncorrectable error + CiaError.CpuPe = 1; // Ev5 bus parity error + CiaError.MemNem = 1; // Nonexistent memory error + CiaError.PciSerr = 1; // PCI bus serr detected + CiaError.PciPerr = 1; // PCI bus perr detected + CiaError.PciAddrPe = 1; // PCI bus address parity error + CiaError.RcvdMasAbt = 1; // Pci Master Abort + CiaError.RcvdTarAbt = 1; // Pci Target Abort + CiaError.PaPteInv = 1; // Invalid Pte + CiaError.FromWrtErr = 1; // Invalid write to flash rom + CiaError.IoaTimeout = 1; // Io Timeout occurred + CiaError.LostCorErr = 1; // Lost correctable error + CiaError.LostUnCorErr = 1; // Lost uncorrectable error + CiaError.LostCpuPe = 1; // Lost Ev5 bus parity error + CiaError.LostMemNem = 1; // Lost Nonexistent memory error + CiaError.LostPciPerr = 1; // Lost PCI bus perr detected + CiaError.LostPciAddrPe = 1; // Lost PCI bus address parity error + CiaError.LostRcvdMasAbt = 1; // Lost Pci Master Abort + CiaError.LostRcvdTarAbt = 1; // Lost Pci Target Abort + CiaError.LostPaPteInv = 1; // Lost Invalid Pte + CiaError.LostFromWrtErr = 1; // Lost Invalid write to flash rom + CiaError.LostIoaTimeout = 1; // Lost Io Timeout occurred + CiaError.ErrValid = 1; // Self explanatory + + WRITE_CIA_REGISTER( &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaErr, + CiaError.all + ); + + // + // sclfix - We will read the values set by firmware and change it if + // necessary. + // + + CiaErrMask.all = + READ_CIA_REGISTER(&((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->ErrMask); + + CiaErrMask.MemNem = 1; // Enable Nonexistent memory error + + // + // Determine PCI parity checking. + // + + CiaControl.all = READ_CIA_REGISTER( + &((PCIA_GENERAL_CSRS)(CIA_GENERAL_CSRS_QVA))->CiaCtrl ); + + if (PciParityChecking == FALSE) { + + CiaControl.AddrPeEn = 0; // Disable PCI address parity checking + CiaControl.PerrEn = 0; // Disable PCI data parity checking + + CiaErrMask.PciPerr = 0; // Disable PCI bus perr detected + CiaErrMask.PciAddrPe = 0; // Disable PCI bus address parity error + + } else { + + CiaControl.AddrPeEn = PciParityChecking; + CiaControl.PerrEn = PciParityChecking; + + CiaErrMask.PciPerr = PciParityChecking; + CiaErrMask.PciAddrPe = PciParityChecking; + + } + + CiaErrMask.CorErr = (ReportCorrectableErrors == TRUE); + + WRITE_CIA_REGISTER( &((PCIA_GENERAL_CSRS)(CIA_GENERAL_CSRS_QVA))->CiaCtrl, + CiaControl.all + ); + + WRITE_CIA_REGISTER( &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->ErrMask, + CiaErrMask.all + ); + + // + // Set the machine check enables within the EV5. + // + + if( ReportCorrectableErrors == TRUE ){ + + HalpSetMachineCheckEnables( FALSE, FALSE, FALSE ); + + } else { + + HalpSetMachineCheckEnables( FALSE, TRUE, TRUE ); + } + + return; + +} + +#define MAX_ERROR_STRING 128 + + +BOOLEAN +HalpCiaUncorrectableError( + VOID + ) +/*++ + +Routine Description: + + Read the CIA error register and determine if an uncorrectable error + is latched in the error bits. + +Arguments: + + None. + +Return Value: + + TRUE is returned if an uncorrectable error has been detected. FALSE + is returned otherwise. + +--*/ +{ + CIA_ERR CiaError; + + + CiaError.all = READ_CIA_REGISTER( + &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaErr ); + + // + // If no error is valid then an uncorrectable error was not detected. + // + + if( CiaError.ErrValid == 0 ){ + return FALSE; + } + + // + // Check each of the individual uncorrectable error bits, if any is set + // then return TRUE. + // + + if( (CiaError.UnCorErr == 1) || + (CiaError.CpuPe == 1) || + (CiaError.MemNem == 1) || + (CiaError.PciSerr == 1) || + (CiaError.PciPerr == 1) || + (CiaError.PciAddrPe == 1) || + (CiaError.RcvdMasAbt == 1) || + (CiaError.RcvdTarAbt == 1) || + (CiaError.PaPteInv == 1) || + (CiaError.FromWrtErr == 1) || + (CiaError.IoaTimeout == 1) ){ + + return TRUE; + + } + + // + // None of the uncorrectable error conditions were detected. + // + + return FALSE; + +} + + +VOID +HalpBuildCiaConfigurationFrame( + PCIA_CONFIGURATION pConfiguration + ) +{ + pConfiguration->CiaRev = READ_CIA_REGISTER( + &((PCIA_GENERAL_CSRS)(CIA_GENERAL_CSRS_QVA))->CiaRevision ); + + pConfiguration->CiaCtrl = READ_CIA_REGISTER( + &((PCIA_GENERAL_CSRS)(CIA_GENERAL_CSRS_QVA))->CiaCtrl ); + + pConfiguration->Mcr = READ_CIA_REGISTER( + &((PCIA_MEMORY_CSRS)(CIA_MEMORY_CSRS_QVA))->Mcr ); + + pConfiguration->Mba0 = READ_CIA_REGISTER( + &((PCIA_MEMORY_CSRS)(CIA_MEMORY_CSRS_QVA))->Mba0 ); + + pConfiguration->Mba2 = READ_CIA_REGISTER( + &((PCIA_MEMORY_CSRS)(CIA_MEMORY_CSRS_QVA))->Mba2 ); + + pConfiguration->Mba4 = READ_CIA_REGISTER( + &((PCIA_MEMORY_CSRS)(CIA_MEMORY_CSRS_QVA))->Mba4 ); + + pConfiguration->Mba6 = READ_CIA_REGISTER( + &((PCIA_MEMORY_CSRS)(CIA_MEMORY_CSRS_QVA))->Mba6 ); + + pConfiguration->Mba8 = READ_CIA_REGISTER( + &((PCIA_MEMORY_CSRS)(CIA_MEMORY_CSRS_QVA))->Mba8 ); + + pConfiguration->MbaA = READ_CIA_REGISTER( + &((PCIA_MEMORY_CSRS)(CIA_MEMORY_CSRS_QVA))->MbaA ); + + pConfiguration->MbaC = READ_CIA_REGISTER( + &((PCIA_MEMORY_CSRS)(CIA_MEMORY_CSRS_QVA))->MbaC ); + + pConfiguration->MbaE = READ_CIA_REGISTER( + &((PCIA_MEMORY_CSRS)(CIA_MEMORY_CSRS_QVA))->MbaE ); + + pConfiguration->Tmg0 = READ_CIA_REGISTER( + &((PCIA_MEMORY_CSRS)(CIA_MEMORY_CSRS_QVA))->Tmg0 ); + + pConfiguration->Tmg1 = READ_CIA_REGISTER( + &((PCIA_MEMORY_CSRS)(CIA_MEMORY_CSRS_QVA))->Tmg1 ); + + pConfiguration->Tmg2 = READ_CIA_REGISTER( + &((PCIA_MEMORY_CSRS)(CIA_MEMORY_CSRS_QVA))->Tmg2 ); + +} + + +VOID +HalpCiaReportFatalError( + VOID + ) +/*++ + +Routine Description: + + This function reports and interprets a fatal hardware error + detected by the CIA chipset. It is assumed that HalGetDisplayOwnership() + has been called prior to this function. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + UCHAR OutBuffer[ MAX_ERROR_STRING ]; + CIA_ERR CiaError; + CIA_STAT CiaStat; + CIA_SYN CiaSyn; + CIA_CONTROL CiaControl; + CIA_MEM_ERR0 MemErr0; + CIA_MEM_ERR1 MemErr1; + CIA_PCI_ERR0 PciErr0; + CIA_PCI_ERR1 PciErr1; + CIA_PCI_ERR2 PciErr2; + CIA_CPU_ERR0 CpuErr0; + CIA_CPU_ERR1 CpuErr1; + + PUNCORRECTABLE_ERROR uncorr = NULL; + PCIA_UNCORRECTABLE_FRAME ciauncorr = NULL; + PEXTENDED_ERROR PExtErr; + + // + // We will Build the uncorrectable error frame as we read + // the registers to report the error to the blue screen. + // We generate the extended error frame as we generate + // extended messages to print to the screen. + // + + if(PUncorrectableError){ + uncorr = (PUNCORRECTABLE_ERROR) + &PUncorrectableError->UncorrectableFrame; + ciauncorr = (PCIA_UNCORRECTABLE_FRAME) + PUncorrectableError->UncorrectableFrame.RawSystemInformation; + PExtErr = &PUncorrectableError->UncorrectableFrame.ErrorInformation; + } + if(uncorr){ + uncorr->Flags.ProcessorInformationValid = 1; + HalpGetProcessorInfo(&uncorr->ReportingProcessor); + } + + if(ciauncorr) + HalpBuildCiaConfigurationFrame(&ciauncorr->Configuration); + // + // Read the CIA Error register and decode its contents: + // + + CiaError.all = (ULONG)READ_CIA_REGISTER( + &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaErr + ); + + if(ciauncorr) + ciauncorr->CiaErr = CiaError.all ; + + // + // Read the rest of the error registers and then unlock them by + // writing to CIA_ERR + // + + CiaStat.all = (ULONG)READ_CIA_REGISTER( + &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaStat + ); + + + CiaSyn.all = (ULONG)READ_CIA_REGISTER( + &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaSyn + ); + + + MemErr0.all = (ULONG)READ_CIA_REGISTER( + &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->MemErr0 + ); + + + MemErr1.all = (ULONG)READ_CIA_REGISTER( + &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->MemErr1 + ); + + + PciErr0.all = (ULONG)READ_CIA_REGISTER( + &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->PciErr0 + ); + + + PciErr1.PciAddress = (ULONG)READ_CIA_REGISTER( + &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->PciErr1 + ); + + PciErr2.PciAddress = (ULONG)READ_CIA_REGISTER( + &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->PciErr2 + ); + + CpuErr0.all = (ULONG)READ_CIA_REGISTER( + &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CpuErr0 + ); + + + CpuErr1.all = (ULONG)READ_CIA_REGISTER( + &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CpuErr1 + ); + + CiaControl.all = READ_CIA_REGISTER( + &((PCIA_GENERAL_CSRS)(CIA_GENERAL_CSRS_QVA))->CiaCtrl); + + if(ciauncorr){ + ciauncorr->CiaStat = CiaStat.all; + ciauncorr->CiaSyn = CiaSyn.all; + ciauncorr->MemErr0 = MemErr0.all; + ciauncorr->MemErr1 = MemErr1.all; + ciauncorr->PciErr0 = PciErr0.all; + ciauncorr->PciErr1 = PciErr1.PciAddress; + + ciauncorr->PciErr2 = (ULONG)READ_CIA_REGISTER( + &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->PciErr2 + ); + ciauncorr->CpuErr0 = CpuErr0.all; + + ciauncorr->CpuErr1 = CpuErr1.all; + + ciauncorr->ErrMask = (ULONG)READ_CIA_REGISTER( + &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->ErrMask + ); + + } + + WRITE_CIA_REGISTER( &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaErr, + CiaError.all + ); + + + sprintf( OutBuffer, "CIA_CTRL : %08x\n", CiaControl.all ); + HalDisplayString( OutBuffer ); + DbgPrint( OutBuffer ); + + sprintf( OutBuffer, "CIA_ERR : %08x\n", CiaError.all ); + HalDisplayString( OutBuffer ); + DbgPrint( OutBuffer ); + + sprintf( OutBuffer, "CIA_STAT : %08x\n", CiaStat.all ); + HalDisplayString( OutBuffer ); + DbgPrint( OutBuffer ); + + sprintf( OutBuffer, "CIA_SYN : %08x\n", CiaSyn.all ); + HalDisplayString( OutBuffer ); + DbgPrint( OutBuffer ); + + sprintf( OutBuffer, "PCI_ERR0 : %08x\n", PciErr0.all ); + HalDisplayString( OutBuffer ); + DbgPrint( OutBuffer ); + + sprintf( OutBuffer, "PCI_ERR1 : %08x\n", PciErr1.PciAddress ); + HalDisplayString( OutBuffer ); + DbgPrint( OutBuffer ); + + sprintf( OutBuffer, "PCI_ERR2 : %08x\n", PciErr2.PciAddress ); + HalDisplayString( OutBuffer ); + DbgPrint( OutBuffer ); + + sprintf( OutBuffer, "CPU_ERR0 : %08x\n", CpuErr0.all ); + HalDisplayString( OutBuffer ); + DbgPrint( OutBuffer ); + + sprintf( OutBuffer, "CPU_ERR1 : %08x\n", CpuErr1.all ); + HalDisplayString( OutBuffer ); + DbgPrint( OutBuffer ); + + sprintf( OutBuffer, "MEM_ERR0 : %08x\n", MemErr0.all ); + HalDisplayString( OutBuffer ); + DbgPrint( OutBuffer ); + + sprintf( OutBuffer, "MEM_ERR1 : %08x\n", MemErr1.all ); + HalDisplayString( OutBuffer ); + DbgPrint( OutBuffer ); + + // + // If no valid error then no interpretation. + // + + if ( CiaError.ErrValid == 0 ){ + + return; // No CIA error detected + + } + + // + // Interpret any detected errors: + // + + if ( CiaError.UnCorErr == 1 ){ + + sprintf( OutBuffer, + "CIA Uncorrectable ECC error, Addr=%x%x, Cmd=%x\n", + CpuErr1.Addr34_32, // bits 34:32 + CpuErr0.Addr, // bits 31:4 + CpuErr1.Cmd + ); + if(uncorr){ + uncorr->Flags.ErrorStringValid = 1; + strcpy( uncorr->ErrorString, OutBuffer); + } + + } else if ( CiaError.CpuPe == 1 ){ + + sprintf( OutBuffer, + "EV5 bus parity error, Addr=%x%x, Cmd=%x\n", + CpuErr1.Addr34_32, // bits 34:32 + CpuErr0.Addr, // bits 31:4 + CpuErr1.Cmd + ); + if(uncorr){ + uncorr->Flags.ErrorStringValid = 1; + strcpy( uncorr->ErrorString, OutBuffer); + } + + } else if ( CiaError.MemNem == 1 ){ + + sprintf( OutBuffer, + "CIA Access to non-existent memory, Source=%s, Addr=%x%x\n", + MemErr1.MemPortSrc == 1 ? "DMA" : "CPU", + MemErr1.MemPortSrc == 1 ? 0 : MemErr1.Addr33_32, + MemErr1.MemPortSrc == 1 ? PciErr1.PciAddress : MemErr0.Addr31_4 + ); + if(uncorr){ + uncorr->Flags.ErrorStringValid = 1; + strcpy( uncorr->ErrorString, OutBuffer); + } + + } else if ( CiaError.PciSerr == 1 ){ + + sprintf( OutBuffer, + "PCI bus SERR detected, Cmd=%x, Window=%d, Addr=%x\n", + PciErr0.Cmd, + PciErr0.Window, + PciErr1.PciAddress + ); + + if(uncorr){ + uncorr->Flags.ErrorStringValid = 1; + strcpy( uncorr->ErrorString, OutBuffer); + uncorr->Flags.AddressSpace = IO_SPACE; + uncorr->Flags.PhysicalAddressValid = 1; + uncorr->PhysicalAddress = PciErr1.PciAddress; + + uncorr->Flags.ExtendedErrorValid = 1; + PExtErr->IoError.Interface = PCIBus; + PExtErr->IoError.BusNumber = 0; + PExtErr->IoError.BusAddress.LowPart = PciErr1.PciAddress; + } + + } else if ( CiaError.PciPerr == 1 ){ + + sprintf( OutBuffer, + "PCI bus Data Parity error, Cmd=%x, Window=%d, Addr=%x\n", + PciErr0.Cmd, + PciErr0.Window, + PciErr1.PciAddress + ); + + if(uncorr){ + uncorr->Flags.ErrorStringValid = 1; + strcpy( uncorr->ErrorString, OutBuffer); + uncorr->Flags.AddressSpace = IO_SPACE; + uncorr->Flags.PhysicalAddressValid = 1; + uncorr->PhysicalAddress = PciErr1.PciAddress; + + uncorr->Flags.ExtendedErrorValid = 1; + PExtErr->IoError.Interface = PCIBus; + PExtErr->IoError.BusNumber = 0; + PExtErr->IoError.BusAddress.LowPart = PciErr1.PciAddress; + } + + } else if ( CiaError.PciAddrPe == 1 ){ + + sprintf( OutBuffer, + "Pci bus Address Parity error, Cmd=%x, Window=%x, Addr=%x\n", + PciErr0.Cmd, + PciErr0.Window, + PciErr1.PciAddress + ); + if(uncorr){ + uncorr->Flags.ErrorStringValid = 1; + strcpy( uncorr->ErrorString, OutBuffer); + uncorr->Flags.AddressSpace = IO_SPACE; + uncorr->Flags.PhysicalAddressValid = 1; + uncorr->PhysicalAddress = PciErr1.PciAddress; + + uncorr->Flags.ExtendedErrorValid = 1; + PExtErr->IoError.Interface = PCIBus; + PExtErr->IoError.BusNumber = 0; + PExtErr->IoError.BusAddress.LowPart = PciErr1.PciAddress; + } + + } else if ( CiaError.RcvdMasAbt == 1 ){ + + sprintf( OutBuffer, + "PCI Master abort occurred, Cmd=%x, Window=%x, Addr=%x\n", + PciErr0.Cmd, + PciErr0.Window, + PciErr1.PciAddress + ); + if(uncorr){ + uncorr->Flags.ErrorStringValid = 1; + strcpy( uncorr->ErrorString, OutBuffer); + uncorr->Flags.AddressSpace = IO_SPACE; + uncorr->Flags.PhysicalAddressValid = 1; + uncorr->PhysicalAddress = PciErr1.PciAddress; + + uncorr->Flags.ExtendedErrorValid = 1; + PExtErr->IoError.Interface = PCIBus; + PExtErr->IoError.BusNumber = 0; + PExtErr->IoError.BusAddress.LowPart = PciErr1.PciAddress; + } + + } else if ( CiaError.RcvdTarAbt == 1 ){ + + sprintf( OutBuffer, + "PCI Target abort occurred, Cmd=%x, Window=%x, Addr=%x\n", + PciErr0.Cmd, + PciErr0.Window, + PciErr1.PciAddress + ); + if(uncorr){ + uncorr->Flags.ErrorStringValid = 1; + strcpy( uncorr->ErrorString, OutBuffer); + uncorr->Flags.AddressSpace = IO_SPACE; + uncorr->Flags.PhysicalAddressValid = 1; + uncorr->PhysicalAddress = PciErr1.PciAddress; + + uncorr->Flags.ExtendedErrorValid = 1; + PExtErr->IoError.Interface = PCIBus; + PExtErr->IoError.BusNumber = 0; + PExtErr->IoError.BusAddress.LowPart = PciErr1.PciAddress; + } + + } else if ( CiaError.PaPteInv == 1 ){ + + sprintf( OutBuffer, + "Invalid Scatter/Gather PTE, Cmd=%x, Window=%x, Addr=%x\n", + PciErr0.Cmd, + PciErr0.Window, + PciErr1.PciAddress + ); + if(uncorr){ + uncorr->Flags.ErrorStringValid = 1; + strcpy( uncorr->ErrorString, OutBuffer); + uncorr->Flags.AddressSpace = IO_SPACE; + uncorr->Flags.PhysicalAddressValid = 1; + uncorr->PhysicalAddress = PciErr1.PciAddress; + + uncorr->Flags.ExtendedErrorValid = 1; + PExtErr->IoError.Interface = PCIBus; + PExtErr->IoError.BusNumber = 0; + PExtErr->IoError.BusAddress.LowPart = PciErr1.PciAddress; + } + + } else if ( CiaError.FromWrtErr == 1 ){ + + sprintf( OutBuffer, + "Write to Flash ROM with FROM_WRT_EN clear" + ); + if(uncorr){ + uncorr->Flags.ErrorStringValid = 1; + strcpy( uncorr->ErrorString, OutBuffer); + } + + } else if ( CiaError.IoaTimeout == 1){ + + sprintf( OutBuffer, + "PCI bus I/O timeout occurred, Cmd=%x, Window=%x, Addr=%x\n", + PciErr0.Cmd, + PciErr0.Window, + PciErr1.PciAddress + ); + if(uncorr){ + uncorr->Flags.ErrorStringValid = 1; + strcpy( uncorr->ErrorString, OutBuffer); + uncorr->Flags.AddressSpace = IO_SPACE; + uncorr->Flags.PhysicalAddressValid = 1; + uncorr->PhysicalAddress = PciErr1.PciAddress; + + uncorr->Flags.ExtendedErrorValid = 1; + PExtErr->IoError.Interface = PCIBus; + PExtErr->IoError.BusNumber = 0; + PExtErr->IoError.BusAddress.LowPart = PciErr1.PciAddress; + } + } + + + // + // Output the detected error message: + // + + HalDisplayString( "\n" ); + HalDisplayString( OutBuffer ); + +#if HALDBG + DbgPrint( OutBuffer ); +#endif + + + // + // Check for lost errors and output message if any occurred: + // + + if ( (CiaError.all & CIA_ERR_LOST_MASK) != 0 ){ + + HalDisplayString("\nCIA Lost errors were detected\n\n"); + } + + return; // Fatal error detected +} + + +BOOLEAN +HalpCiaMachineCheck( + IN PEXCEPTION_RECORD ExceptionRecord, + IN PKEXCEPTION_FRAME ExceptionFrame, + IN PKTRAP_FRAME TrapFrame + ) +/*++ + +Routine Description: + + This routine is given control when an hard error is acknowledged + by the CIA chipset. The routine is given the chance to + correct and dismiss the error. + +Arguments: + + ExceptionRecord - Supplies a pointer to the exception record generated + at the point of the exception. + + ExceptionFrame - Supplies a pointer to the exception frame generated + at the point of the exception. + + TrapFrame - Supplies a pointer to the trap frame generated + at the point of the exception. + +Return Value: + + TRUE is returned if the machine check has been handled and dismissed - + indicating that execution can continue. FALSE is return otherwise. + +--*/ +{ + CIA_ERR CiaError; + + // + // Read the CIA error register to determine the source of the + // error. + // + + CiaError.all = READ_CIA_REGISTER( + &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaErr ); + +#if HALDBG + + DbgPrint( "Cia Mchk: 0x%x\n", CiaError.all ); + +#endif //HALDBG + + // + // Check that an error is valid. If it is not this is a pretty + // weird fatal condition. + // + + if( CiaError.ErrValid == 0 ){ + DbgPrint( "Error reported but error valid = 0, CiaErr = 0x%x\n", + CiaError.all ); + goto FatalError; + } + + // + // Check for any uncorrectable error other than a master abort + // on a PCI transaction. Any of these other errors indicate a + // fatal condition. + // + + if( (CiaError.UnCorErr == 1) || // Uncorrectable error + (CiaError.CpuPe == 1) || // Ev5 bus parity error + (CiaError.MemNem == 1) || // Nonexistent memory error + (CiaError.PciSerr == 1) || // PCI bus serr detected + (CiaError.PciPerr == 1) || // PCI bus perr detected + (CiaError.PciAddrPe == 1) || // PCI bus address parity error + (CiaError.RcvdTarAbt == 1) || // Pci Target Abort + (CiaError.PaPteInv == 1) || // Invalid Pte + (CiaError.FromWrtErr == 1) || // Invalid write to flash rom + (CiaError.IoaTimeout == 1) || // Io Timeout occurred + (CiaError.LostUnCorErr == 1) || // Lost uncorrectable error + (CiaError.LostCpuPe == 1) || // Lost Ev5 bus parity error + (CiaError.LostMemNem == 1) || // Lost Nonexistent memory error + (CiaError.LostPciPerr == 1) || // Lost PCI bus perr detected + (CiaError.LostPciAddrPe == 1) || // Lost PCI address parity error + (CiaError.LostRcvdMasAbt == 1) || // Lost Pci Master Abort + (CiaError.LostRcvdTarAbt == 1) || // Lost Pci Target Abort + (CiaError.LostPaPteInv == 1) || // Lost Invalid Pte + (CiaError.LostFromWrtErr == 1) || // Lost Invalid write to flash rom + (CiaError.LostIoaTimeout == 1) // Lost Io Timeout occurred + ){ + DbgPrint( "Explicit fatal error, CiaErr = 0x%x\n", + CiaError.all ); + goto FatalError; + } + + // + // Check for a PCI configuration read error. The CIA experiences + // a master abort on a read to a non-existent PCI slot. + // + + if( (CiaError.RcvdMasAbt == 1) && (HalpMasterAbortExpected != 0) ){ + + // + // So far, the error looks like a PCI configuration space read + // that accessed a device that does not exist. In order to fix + // this up we expect that the original faulting instruction must + // be a load with v0 as the destination register. Unfortunately, + // machine checks are not precise exceptions so we may have exectued + // many instructions since the faulting load. For EV5 a pair of + // memory barrier instructions following the load will stall the pipe + // waiting for load completion before the second memory barrier can + // be issued. Therefore, we expect the exception PC to point to either + // the load instruction of one of the two memory barriers. We will + // assume that if the exception pc is not an mb that instead it + // points to the load that machine checked. We must be careful to + // not reexectute the load. + // + + ALPHA_INSTRUCTION FaultingInstruction; + BOOLEAN PreviousInstruction = FALSE; + + FaultingInstruction.Long = *(PULONG)((ULONG)TrapFrame->Fir); + if( FaultingInstruction.Memory.Opcode != MEMSPC_OP ){ + + // + // Exception pc does not point to a memory barrier, return + // to the instruction after the exception pc. + // + + TrapFrame->Fir += 4; + + } + + // + // The error has matched all of our conditions. Fix it up by + // writing the value 0xffffffff into the destination of the load. + // + + TrapFrame->IntV0 = (ULONGLONG)0xffffffffffffffff; + + // + // Clear the error condition in CIA_ERR. + // + + CiaError.all = 0; + CiaError.RcvdMasAbt = 1; + CiaError.ErrValid = 1; + WRITE_CIA_REGISTER( &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaErr, + CiaError.all ); + + return TRUE; + + } //end if( (CiaError.RcvdMasAbt == 1) && (HalpMasterAbortExpected != 0) ) + + DbgPrint( "Unexpected master abort\n" ); + +// +// The system is not well and cannot continue reliable execution. +// Print some useful messages and return FALSE to indicate that the error +// was not handled. +// + +FatalError: + + DbgPrint( "Handling fatal error\n" ); + + // + // Clear the error condition in the MCES register. + // + + HalpUpdateMces( TRUE, TRUE ); + + // + // Proceed to display the error. + // + + HalAcquireDisplayOwnership(NULL); + + // + // Display the dreaded banner. + // + + HalDisplayString( "\nFatal system hardware error.\n\n" ); + + + HalpCiaReportFatalError(); + + return( FALSE ); + +} + +BOOLEAN +HalpTranslateSynToEcc( + PULONG Syndrome + ) +/*++ + +Routine Description: + + Translate a syndrome code to ECC error bit code. + +Arguments: + + Syndrome - pointer to the syndrome. + +Return Value: + + True if a data bit is in error. False otherwise. + +--*/ +{ + static UCHAR SynToEccTable[0xff] = {0, }; + static BOOLEAN SynToEccTableInitialized = FALSE; + ULONG Temp; + + // + // Initialize the table. + // + + if (!SynToEccTableInitialized) { + + SynToEccTableInitialized = TRUE; + + // + // Fill in the table. + // + + SynToEccTable[0x01] = 0; + SynToEccTable[0x02] = 1; + SynToEccTable[0x04] = 2; + SynToEccTable[0x08] = 3; + SynToEccTable[0x10] = 4; + SynToEccTable[0x20] = 5; + SynToEccTable[0x40] = 6; + SynToEccTable[0x80] = 7; + SynToEccTable[0xce] = 0; + SynToEccTable[0xcb] = 1; + SynToEccTable[0xd3] = 2; + SynToEccTable[0xd5] = 3; + SynToEccTable[0xd6] = 4; + SynToEccTable[0xd9] = 5; + SynToEccTable[0xda] = 6; + SynToEccTable[0xdc] = 7; + SynToEccTable[0x23] = 8; + SynToEccTable[0x25] = 9; + SynToEccTable[0x26] = 10; + SynToEccTable[0x29] = 11; + SynToEccTable[0x2a] = 12; + SynToEccTable[0x2c] = 13; + SynToEccTable[0x31] = 14; + SynToEccTable[0x34] = 15; + SynToEccTable[0x0e] = 16; + SynToEccTable[0x0b] = 17; + SynToEccTable[0x13] = 18; + SynToEccTable[0x15] = 19; + SynToEccTable[0x16] = 20; + SynToEccTable[0x19] = 21; + SynToEccTable[0x1a] = 22; + SynToEccTable[0x1c] = 23; + SynToEccTable[0xe3] = 24; + SynToEccTable[0xe5] = 25; + SynToEccTable[0xe6] = 26; + SynToEccTable[0xe9] = 27; + SynToEccTable[0xea] = 28; + SynToEccTable[0xec] = 29; + SynToEccTable[0xf1] = 30; + SynToEccTable[0xf4] = 31; + SynToEccTable[0x4f] = 32; + SynToEccTable[0x4a] = 33; + SynToEccTable[0x52] = 34; + SynToEccTable[0x54] = 35; + SynToEccTable[0x57] = 36; + SynToEccTable[0x58] = 37; + SynToEccTable[0x5b] = 38; + SynToEccTable[0x5d] = 39; + SynToEccTable[0xa2] = 40; + SynToEccTable[0xa4] = 41; + SynToEccTable[0xa7] = 42; + SynToEccTable[0xa8] = 43; + SynToEccTable[0xab] = 44; + SynToEccTable[0xad] = 45; + SynToEccTable[0xb0] = 46; + SynToEccTable[0xb5] = 47; + SynToEccTable[0x8f] = 48; + SynToEccTable[0x8a] = 49; + SynToEccTable[0x92] = 50; + SynToEccTable[0x94] = 51; + SynToEccTable[0x97] = 52; + SynToEccTable[0x98] = 53; + SynToEccTable[0x9b] = 54; + SynToEccTable[0x9d] = 55; + SynToEccTable[0x62] = 56; + SynToEccTable[0x64] = 57; + SynToEccTable[0x67] = 58; + SynToEccTable[0x68] = 59; + SynToEccTable[0x6b] = 60; + SynToEccTable[0x6d] = 61; + SynToEccTable[0x70] = 62; + SynToEccTable[0x75] = 63; + } + + // + // Tranlate the syndrome code. + // + + Temp = *Syndrome; + *Syndrome = SynToEccTable[Temp]; + + // + // Is it a data bit or a check bit in error? + // + + if (Temp == 0x01 || Temp == 0x02 || Temp == 0x04 || Temp == 0x08 || + Temp == 0x10 || Temp == 0x20 || Temp == 0x40 || Temp == 0x80) { + + return FALSE; + + } else { + + return TRUE; + } +} + + + +VOID +HalpCiaErrorInterrupt( + VOID + ) +/*++ + +Routine Description: + + Handle a CIA correctable error interrupt. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + static ERROR_FRAME Frame; + static CIA_CORRECTABLE_FRAME AlcorFrame; + + ERROR_FRAME TempFrame; + PCORRECTABLE_ERROR CorrPtr; + PBOOLEAN ErrorlogBusy; + PULONG DispatchCode; + ULONG Syndrome; + PKINTERRUPT InterruptObject; + PKSPIN_LOCK ErrorlogSpinLock; + + CIA_ERR CiaError; + CIA_STAT CiaStat; + CIA_SYN CiaSyn; + CIA_MEM_ERR0 MemErr0; + CIA_MEM_ERR1 MemErr1; + CIA_PCI_ERR0 PciErr0; + CIA_PCI_ERR1 PciErr1; + CIA_PCI_ERR2 PciErr2; + + // + // The error is expected to be a corrected ECC error on a DMA or + // Scatter/Gather TLB read/write. Read the error registers relevant + // to this error. + // + + CiaError.all = READ_CIA_REGISTER( + &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaErr ); + + // + // Check if an error is latched into the CIA. + // + + if( CiaError.ErrValid == 0 ){ + +#if HALDBG + + DbgPrint( "Cia error interrupt without valid CIA error\n" ); + +#endif //HALDBG + + return; + } + + // + // Check for the correctable error bit. + // + + if( CiaError.CorErr == 0 ){ + +#if HALDBG + + DbgPrint( "Cia error interrupt without correctable error indicated\n" ); + +#endif //HALDBG + + } + + // + // Real error, get the interrupt object. + // + + DispatchCode = (PULONG)(PCR->InterruptRoutine[CORRECTABLE_VECTOR]); + InterruptObject = CONTAINING_RECORD(DispatchCode, + KINTERRUPT, + DispatchCode); + + // + // Set various pointers so we can use them later. + // + + CorrPtr = &TempFrame.CorrectableFrame; + ErrorlogBusy = (PBOOLEAN)((PUCHAR)InterruptObject->ServiceContext + + sizeof(PERROR_FRAME)); + ErrorlogSpinLock = (PKSPIN_LOCK)((PUCHAR)ErrorlogBusy + sizeof(PBOOLEAN)); + + // + // Clear the data structures that we will use. + // + + RtlZeroMemory(&TempFrame, sizeof(ERROR_FRAME)); + + // + // Increment the number of CIA correctable errors. + // + + CiaCorrectedErrors += 1; + + CiaStat.all = READ_CIA_REGISTER( + &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaStat ); + + CiaSyn.all = READ_CIA_REGISTER( + &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaSyn ); + + MemErr0.all = READ_CIA_REGISTER( + &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->MemErr0 ); + + MemErr1.all = READ_CIA_REGISTER( + &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->MemErr1 ); + + PciErr0.all = READ_CIA_REGISTER( + &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->PciErr0 ); + + PciErr1.PciAddress = READ_CIA_REGISTER( + &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->PciErr1 ); + + PciErr2.PciAddress = READ_CIA_REGISTER( + &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->PciErr2 ); + + + // + // Print a correctable error message to the debugger. + // + +#if HALDBG + DbgPrint( "CIA Correctable Error Number %d, state follows: \n", + CiaCorrectedErrors ); + DbgPrint( "\tCIA_ERR : 0x%x\n", CiaError.all ); + DbgPrint( "\tCIA_STAT: 0x%x\n", CiaStat.all ); + DbgPrint( "\tCIA_SYN : 0x%x\n", CiaSyn.all ); + DbgPrint( "\tCIA_MEM0: 0x%x\n", MemErr0.all ); + DbgPrint( "\tCIA_MEM1: 0x%x\n", MemErr1.all ); + DbgPrint( "\tPCI_ERR0: 0x%x\n", PciErr0.all ); +#endif //HALDBG + + // + // Fill in the error frame information. + // + + TempFrame.Signature = ERROR_FRAME_SIGNATURE; + TempFrame.FrameType = CorrectableFrame; + TempFrame.VersionNumber = ERROR_FRAME_VERSION; + TempFrame.SequenceNumber = CiaCorrectedErrors; + TempFrame.PerformanceCounterValue = + KeQueryPerformanceCounter(NULL).QuadPart; + + // + // Check for lost error. + // + + if( CiaError.LostCorErr ) { + + // + // Since the error registers are locked from a previous error, + // we don't know where the error came from. Mark everything + // as UNIDENTIFIED. + // + + CorrPtr->Flags.LostCorrectable = 1; + CorrPtr->Flags.LostAddressSpace = UNIDENTIFIED; + CorrPtr->Flags.LostMemoryErrorSource = UNIDENTIFIED; + } + + // + // Set error bit error masks. + // + + CorrPtr->Flags.ErrorBitMasksValid = 1; + Syndrome = CiaSyn.all; + + if ( HalpTranslateSynToEcc(&Syndrome) ) + CorrPtr->DataBitErrorMask = 1 << Syndrome; + else + CorrPtr->CheckBitErrorMask = 1 << Syndrome; + + // + // Determine error type. + // + switch (CiaStat.DmSt) { + + case CIA_IO_WRITE_ECC: + + // + // I/O write ECC error occurred. + // + + CorrPtr->Flags.AddressSpace = IO_SPACE; + + CorrPtr->Flags.ExtendedErrorValid = 1; + CorrPtr->ErrorInformation.IoError.Interface = PCIBus; + CorrPtr->ErrorInformation.IoError.BusNumber = 0; + CorrPtr->ErrorInformation.IoError.BusAddress.LowPart= PciErr1.PciAddress; + CorrPtr->ErrorInformation.IoError.TransferType = BUS_IO_WRITE; + break; + + case CIA_DMA_READ_ECC: + + CorrPtr->Flags.AddressSpace = MEMORY_SPACE; + CorrPtr->Flags.ExtendedErrorValid = 1; + + // + // Where did the error come from? + // + + if ( CiaStat.PaCpuRes == CIA_PROCESSOR_CACHE_ECC ) { + + // + // Correctable error comes from processor cache. + // + + CorrPtr->Flags.MemoryErrorSource = PROCESSOR_CACHE; + + // + // DMA read or TLB miss error occurred. + // + + if ( CiaStat.TlbMiss ) + CorrPtr->ErrorInformation.CacheError.TransferType = TLB_MISS_READ; + else + CorrPtr->ErrorInformation.CacheError.TransferType = BUS_DMA_READ; + + } else if ( CiaStat.PaCpuRes == CIA_SYSTEM_CACHE_ECC ) { + + // + // Correctable error comes from system cache. + // + + CorrPtr->Flags.MemoryErrorSource = SYSTEM_CACHE; + + // + // DMA read or TLB miss error occurred. + // + + if ( CiaStat.TlbMiss ) + CorrPtr->ErrorInformation.CacheError.TransferType = TLB_MISS_READ; + else + CorrPtr->ErrorInformation.CacheError.TransferType = BUS_DMA_READ; + + } else { + + // + // Correctable error comes from system memory. + // + + CorrPtr->Flags.MemoryErrorSource = SYSTEM_MEMORY; + + // + // DMA read or TLB miss error occurred. + // + + if ( CiaStat.TlbMiss ) + CorrPtr->ErrorInformation.MemoryError.TransferType = TLB_MISS_READ; + else + CorrPtr->ErrorInformation.MemoryError.TransferType = BUS_DMA_READ; + } + + break; + + case CIA_DMA_WRITE_ECC: + + CorrPtr->Flags.AddressSpace = MEMORY_SPACE; + CorrPtr->Flags.ExtendedErrorValid = 1; + + // + // Where did the error come from? + // + + if ( CiaStat.PaCpuRes == CIA_PROCESSOR_CACHE_ECC ) { + + // + // Correctable error comes from processor cache. + // + + CorrPtr->Flags.MemoryErrorSource = PROCESSOR_CACHE; + + // + // DMA write or TLB miss error occurred. + // + + if ( CiaStat.TlbMiss ) + CorrPtr->ErrorInformation.CacheError.TransferType = TLB_MISS_WRITE; + else + CorrPtr->ErrorInformation.CacheError.TransferType = BUS_DMA_WRITE; + + } else if ( CiaStat.PaCpuRes == CIA_SYSTEM_CACHE_ECC ) { + + // + // Correctable error comes from system cache. + // + + CorrPtr->Flags.MemoryErrorSource = SYSTEM_CACHE; + + // + // DMA write or TLB miss error occurred. + // + + if ( CiaStat.TlbMiss ) + CorrPtr->ErrorInformation.CacheError.TransferType = TLB_MISS_WRITE; + else + CorrPtr->ErrorInformation.CacheError.TransferType = BUS_DMA_WRITE; + + } else { + + // + // Correctable error comes from system memory. + // + + CorrPtr->Flags.MemoryErrorSource = SYSTEM_MEMORY; + + // + // DMA write or TLB miss error occurred. + // + + if ( CiaStat.TlbMiss ) + CorrPtr->ErrorInformation.MemoryError.TransferType = TLB_MISS_WRITE; + else + CorrPtr->ErrorInformation.MemoryError.TransferType = BUS_DMA_WRITE; + + // + // + } + + break; + + case CIA_IO_READ_ECC: + + // + // I/O read ECC error occurred. + // + + CorrPtr->Flags.AddressSpace = IO_SPACE; + + CorrPtr->Flags.ExtendedErrorValid = 1; + CorrPtr->ErrorInformation.IoError.Interface = PCIBus; + CorrPtr->ErrorInformation.IoError.BusNumber = 0; + CorrPtr->ErrorInformation.IoError.BusAddress.LowPart= PciErr1.PciAddress; + CorrPtr->ErrorInformation.IoError.TransferType = BUS_IO_READ; + break; + + default: + + // + // Something strange happened. Don't know where the error occurred. + // + + CorrPtr->Flags.AddressSpace = UNIDENTIFIED; + break; + } + + // + // Get the physical address where the error occurred. + // + + CorrPtr->Flags.PhysicalAddressValid = 1; + CorrPtr->PhysicalAddress = (MemErr1.all & 0xff) << 32; + CorrPtr->PhysicalAddress |= MemErr0.all; + + // + // Get bits 7:0 of the address from the PCI address. + // + + CorrPtr->PhysicalAddress |= PciErr1.PciAddress & 0xff; + + // + // Scrub the error if it's any type of memory error. + // + + if ( CorrPtr->Flags.AddressSpace == MEMORY_SPACE && + CorrPtr->Flags.PhysicalAddressValid ) + CorrPtr->Flags.ScrubError = 1; + + // + // Acquire the spinlock. + // + + KiAcquireSpinLock(ErrorlogSpinLock); + + // + // Check to see if an errorlog operation is in progress already. + // + + if (!*ErrorlogBusy) { + + // + // The error is expected to be a corrected ECC error on a DMA or + // Scatter/Gather TLB read/write. Read the error registers relevant + // to this error. + // + + AlcorFrame.CiaErr = CiaError.all; + + AlcorFrame.CiaStat = CiaStat.all; + + AlcorFrame.CiaSyn = CiaSyn.all; + + AlcorFrame.MemErr0 = MemErr0.all; + + AlcorFrame.MemErr1 = MemErr1.all; + + AlcorFrame.PciErr0 = PciErr0.all; + + AlcorFrame.PciErr1 = PciErr1.PciAddress; + + AlcorFrame.PciErr2 = PciErr2.PciAddress; + + // + // Read the CIA configuration registers for logging information. + // + + AlcorFrame.Configuration.CiaRev = + READ_CIA_REGISTER( &((PCIA_GENERAL_CSRS) + (CIA_GENERAL_CSRS_QVA))->CiaRevision ); + + AlcorFrame.Configuration.CiaCtrl = + READ_CIA_REGISTER( &((PCIA_GENERAL_CSRS) + (CIA_GENERAL_CSRS_QVA))->CiaCtrl ); + + AlcorFrame.Configuration.Mcr = + READ_CIA_REGISTER( &((PCIA_MEMORY_CSRS) + (CIA_MEMORY_CSRS_QVA))->Mcr ); + + AlcorFrame.Configuration.Mba0 = + READ_CIA_REGISTER( &((PCIA_MEMORY_CSRS) + (CIA_MEMORY_CSRS_QVA))->Mba0 ); + + AlcorFrame.Configuration.Mba2 = + READ_CIA_REGISTER( &((PCIA_MEMORY_CSRS) + (CIA_MEMORY_CSRS_QVA))->Mba2 ); + + AlcorFrame.Configuration.Mba4 = + READ_CIA_REGISTER( &((PCIA_MEMORY_CSRS) + (CIA_MEMORY_CSRS_QVA))->Mba4 ); + + AlcorFrame.Configuration.Mba6 = + READ_CIA_REGISTER( &((PCIA_MEMORY_CSRS) + (CIA_MEMORY_CSRS_QVA))->Mba6 ); + + AlcorFrame.Configuration.Mba8 = + READ_CIA_REGISTER( &((PCIA_MEMORY_CSRS) + (CIA_MEMORY_CSRS_QVA))->Mba8 ); + + AlcorFrame.Configuration.MbaA = + READ_CIA_REGISTER( &((PCIA_MEMORY_CSRS) + (CIA_MEMORY_CSRS_QVA))->MbaA ); + + AlcorFrame.Configuration.MbaC = + READ_CIA_REGISTER( &((PCIA_MEMORY_CSRS) + (CIA_MEMORY_CSRS_QVA))->MbaC ); + + AlcorFrame.Configuration.MbaE = + READ_CIA_REGISTER( &((PCIA_MEMORY_CSRS) + (CIA_MEMORY_CSRS_QVA))->MbaE ); + + AlcorFrame.Configuration.Tmg0 = + READ_CIA_REGISTER( &((PCIA_MEMORY_CSRS) + (CIA_MEMORY_CSRS_QVA))->Tmg0 ); + + AlcorFrame.Configuration.Tmg1 = + READ_CIA_REGISTER( &((PCIA_MEMORY_CSRS) + (CIA_MEMORY_CSRS_QVA))->Tmg1 ); + + AlcorFrame.Configuration.Tmg2 = + READ_CIA_REGISTER( &((PCIA_MEMORY_CSRS) + (CIA_MEMORY_CSRS_QVA))->Tmg2 ); + + AlcorFrame.Configuration.CacheCnfg = + PCR->SecondLevelCacheSize; + + // + // Set the raw system information. + // + + CorrPtr->RawSystemInformationLength = sizeof(CIA_CORRECTABLE_FRAME); + CorrPtr->RawSystemInformation = &AlcorFrame; + + // + // Set the raw processor information. Disregard at the moment. + // + + CorrPtr->RawProcessorInformationLength = 0; + + // + // Set reporting processor information. Disregard at the moment. + // + + CorrPtr->Flags.ProcessorInformationValid = 0; + + // + // Set system information. Disregard at the moment. + // + + CorrPtr->Flags.SystemInformationValid = 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. + // + + Frame.CorrectableFrame.Flags.LostCorrectable = TRUE; + Frame.CorrectableFrame.Flags.LostAddressSpace = + TempFrame.CorrectableFrame.Flags.AddressSpace; + Frame.CorrectableFrame.Flags.LostMemoryErrorSource = + TempFrame.CorrectableFrame.Flags.MemoryErrorSource; + } + + // + // Release the spinlock. + // + + KiReleaseSpinLock(ErrorlogSpinLock); + + // + // Dispatch to the secondary correctable interrupt service routine. + // The assumption here is that if this interrupt ever happens, then + // some driver enabled it, and the driver should have the ISR connected. + // + + ((PSECOND_LEVEL_DISPATCH)InterruptObject->DispatchAddress)( + InterruptObject, + InterruptObject->ServiceContext + ); + + + // + // Clear the corrected error status bit and return to continue + // execution. + // + + CiaError.all = 0; + CiaError.CorErr = 1; + WRITE_CIA_REGISTER( &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaErr, + CiaError.all ); + + return; + +} diff --git a/private/ntos/nthals/halpinna/alpha/ciaio.s b/private/ntos/nthals/halpinna/alpha/ciaio.s new file mode 100644 index 000000000..16202a7e1 --- /dev/null +++ b/private/ntos/nthals/halpinna/alpha/ciaio.s @@ -0,0 +1,7 @@ +// +// This file simply includes the source file from the common Alpha +// HAL directory. +// + +#include "..\halalpha\ciaio.s" + diff --git a/private/ntos/nthals/halpinna/alpha/cmos8k.c b/private/ntos/nthals/halpinna/alpha/cmos8k.c new file mode 100644 index 000000000..091dfa410 --- /dev/null +++ b/private/ntos/nthals/halpinna/alpha/cmos8k.c @@ -0,0 +1,7 @@ +// +// This file simply includes the source file from the common Alpha +// HAL directory. +// + +#include "..\halalpha\cmos8k.c" + diff --git a/private/ntos/nthals/halpinna/alpha/devintr.s b/private/ntos/nthals/halpinna/alpha/devintr.s new file mode 100644 index 000000000..d861febd2 --- /dev/null +++ b/private/ntos/nthals/halpinna/alpha/devintr.s @@ -0,0 +1,7 @@ +// +// This file simply includes the source file from the common Alpha +// HAL directory. +// + +#include "..\halalpha\devintr.s" + diff --git a/private/ntos/nthals/halpinna/alpha/ebsgdma.c b/private/ntos/nthals/halpinna/alpha/ebsgdma.c new file mode 100644 index 000000000..f2f033fad --- /dev/null +++ b/private/ntos/nthals/halpinna/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/halpinna/alpha/eisasup.c b/private/ntos/nthals/halpinna/alpha/eisasup.c new file mode 100644 index 000000000..0d46ef3e4 --- /dev/null +++ b/private/ntos/nthals/halpinna/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/halpinna/alpha/environ.c b/private/ntos/nthals/halpinna/alpha/environ.c new file mode 100644 index 000000000..75015a0a0 --- /dev/null +++ b/private/ntos/nthals/halpinna/alpha/environ.c @@ -0,0 +1,7 @@ +// +// This file simply includes the source file from the common Alpha +// HAL directory. +// + +#include "..\halalpha\environ.c" + diff --git a/private/ntos/nthals/halpinna/alpha/ev5cache.c b/private/ntos/nthals/halpinna/alpha/ev5cache.c new file mode 100644 index 000000000..cd83f7451 --- /dev/null +++ b/private/ntos/nthals/halpinna/alpha/ev5cache.c @@ -0,0 +1,7 @@ +// +// This file simply includes the source file from the common Alpha +// HAL directory. +// + +#include "..\halalpha\ev5cache.c" + diff --git a/private/ntos/nthals/halpinna/alpha/ev5int.c b/private/ntos/nthals/halpinna/alpha/ev5int.c new file mode 100644 index 000000000..23727330f --- /dev/null +++ b/private/ntos/nthals/halpinna/alpha/ev5int.c @@ -0,0 +1,7 @@ +// +// This file simply includes the source file from the common Alpha +// HAL directory. +// + +#include "..\halalpha\ev5int.c" + diff --git a/private/ntos/nthals/halpinna/alpha/ev5ints.s b/private/ntos/nthals/halpinna/alpha/ev5ints.s new file mode 100644 index 000000000..18dce1072 --- /dev/null +++ b/private/ntos/nthals/halpinna/alpha/ev5ints.s @@ -0,0 +1,6 @@ +// +// This file simply includes the source file from the common Alpha +// HAL directory. +// +#include "..\halalpha\ev5ints.s" + diff --git a/private/ntos/nthals/halpinna/alpha/ev5mchk.c b/private/ntos/nthals/halpinna/alpha/ev5mchk.c new file mode 100644 index 000000000..0bedd3dfc --- /dev/null +++ b/private/ntos/nthals/halpinna/alpha/ev5mchk.c @@ -0,0 +1,7 @@ +// +// This file simply includes the source file from the common Alpha +// HAL directory. +// + +#include "..\halalpha\ev5mchk.c" + diff --git a/private/ntos/nthals/halpinna/alpha/ev5mem.s b/private/ntos/nthals/halpinna/alpha/ev5mem.s new file mode 100644 index 000000000..dcad6563c --- /dev/null +++ b/private/ntos/nthals/halpinna/alpha/ev5mem.s @@ -0,0 +1,7 @@ +// +// This file simply includes the source file from the common Alpha +// HAL directory. +// + +#include "..\halalpha\ev5mem.s" + diff --git a/private/ntos/nthals/halpinna/alpha/ev5prof.c b/private/ntos/nthals/halpinna/alpha/ev5prof.c new file mode 100644 index 000000000..839438fd9 --- /dev/null +++ b/private/ntos/nthals/halpinna/alpha/ev5prof.c @@ -0,0 +1,7 @@ +// +// This file simply includes the source file from the common Alpha +// HAL directory. +// + +#include "..\halalpha\ev5prof.c" + diff --git a/private/ntos/nthals/halpinna/alpha/fwreturn.c b/private/ntos/nthals/halpinna/alpha/fwreturn.c new file mode 100644 index 000000000..65ae88cb8 --- /dev/null +++ b/private/ntos/nthals/halpinna/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/halpinna/alpha/haldebug.c b/private/ntos/nthals/halpinna/alpha/haldebug.c new file mode 100644 index 000000000..ce91863ec --- /dev/null +++ b/private/ntos/nthals/halpinna/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/halpinna/alpha/halpal.s b/private/ntos/nthals/halpinna/alpha/halpal.s new file mode 100644 index 000000000..fc89f8370 --- /dev/null +++ b/private/ntos/nthals/halpinna/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/halpinna/alpha/haltsup.s b/private/ntos/nthals/halpinna/alpha/haltsup.s new file mode 100644 index 000000000..b8a697144 --- /dev/null +++ b/private/ntos/nthals/halpinna/alpha/haltsup.s @@ -0,0 +1,7 @@ +// +// This file simply includes the source file from the common Alpha +// HAL directory. +// + +#include "..\halalpha\haltsup.s" + diff --git a/private/ntos/nthals/halpinna/alpha/idle.s b/private/ntos/nthals/halpinna/alpha/idle.s new file mode 100644 index 000000000..f517bab2f --- /dev/null +++ b/private/ntos/nthals/halpinna/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/halpinna/alpha/info.c b/private/ntos/nthals/halpinna/alpha/info.c new file mode 100644 index 000000000..22aef63a3 --- /dev/null +++ b/private/ntos/nthals/halpinna/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/halpinna/alpha/inithal.c b/private/ntos/nthals/halpinna/alpha/inithal.c new file mode 100644 index 000000000..b4eb90ca7 --- /dev/null +++ b/private/ntos/nthals/halpinna/alpha/inithal.c @@ -0,0 +1,7 @@ +// +// This file simply includes the source file from the common Alpha +// HAL directory. +// + +#include "..\halalcor\alpha\inithal.c" + diff --git a/private/ntos/nthals/halpinna/alpha/intsup.s b/private/ntos/nthals/halpinna/alpha/intsup.s new file mode 100644 index 000000000..a7d9f8f4f --- /dev/null +++ b/private/ntos/nthals/halpinna/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/halpinna/alpha/ioproc.c b/private/ntos/nthals/halpinna/alpha/ioproc.c new file mode 100644 index 000000000..d4bd5b0b2 --- /dev/null +++ b/private/ntos/nthals/halpinna/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/halpinna/alpha/iousage.c b/private/ntos/nthals/halpinna/alpha/iousage.c new file mode 100644 index 000000000..ba57097d8 --- /dev/null +++ b/private/ntos/nthals/halpinna/alpha/iousage.c @@ -0,0 +1,648 @@ +/*++ + +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/halpinna/alpha/iousage.h b/private/ntos/nthals/halpinna/alpha/iousage.h new file mode 100644 index 000000000..b54cd179a --- /dev/null +++ b/private/ntos/nthals/halpinna/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/halpinna/alpha/machdep.h b/private/ntos/nthals/halpinna/alpha/machdep.h new file mode 100644 index 000000000..51b1c8dbe --- /dev/null +++ b/private/ntos/nthals/halpinna/alpha/machdep.h @@ -0,0 +1,42 @@ +/*++ + +Copyright (c) 1993 Digital Equipment Corporation + +Module Name: + + machdep.h + +Abstract: + + This file includes the platform-dependent include files used to + build the HAL. + +Author: + + Joe Notarangelo 01-Dec-1993 + +Environment: + + Kernel mode + +Revision History: + + +--*/ + +#ifndef _MACHDEP_ +#define _MACHDEP_ + +// +// Include Mikasa platform-specific definitions. +// + +#include "mikasa.h" + +// +// Include scatter/gather definitions. +// + +#include "ebsgdma.h" + +#endif //_MACHDEP_ diff --git a/private/ntos/nthals/halpinna/alpha/memory.c b/private/ntos/nthals/halpinna/alpha/memory.c new file mode 100644 index 000000000..76b1eb7df --- /dev/null +++ b/private/ntos/nthals/halpinna/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/halpinna/alpha/mikasa.h b/private/ntos/nthals/halpinna/alpha/mikasa.h new file mode 100644 index 000000000..70ad29504 --- /dev/null +++ b/private/ntos/nthals/halpinna/alpha/mikasa.h @@ -0,0 +1,796 @@ +/*++ + +Copyright (c) 1993 Digital Equipment Corporation + +Module Name: + + mikasa.h + +Abstract: + + This module specifies platform-specific definitions for the + Mikasa EV5 modules. + +Author: + + Joe Notarangelo 25-Oct-1993 + +Revision History: + + Scott Lee 29-Nov-1995 + Adapted from Mikasa module for Mikasa EV5 (Pinnacle). + +--*/ + +#ifndef _MIKASA_ +#define _MIKASA_ + +#include "alpharef.h" +#include "cia.h" +#include "isaaddr.h" +#include "axp21164.h" + +// +// sclfix - These defines are not used. +// +// #define NUMBER_MIKASA_EISA_SLOTS 7 +// #define NUMBER_MIKASA_PCI_SLOTS 3 +// #define NUMBER_MIKASA_COMBO_SLOTS 1 +// +// #define NUMBER_NORITAKE_EISA_SLOTS 2 +// #define NUMBER_NORITAKE_PCI_SLOTS 7 +// + +// +// Highest local PCI virtual slot number is 14 == IDSEL PCI_AD[25] +// + +#define PCI_MAX_LOCAL_DEVICE 14 + +#if !defined (_LANGUAGE_ASSEMBLY) +#if !defined (AXP_FIRMWARE) + +// +// Define the per-processor data structures allocated in the PCR +// for each EV5 processor. +// + +typedef struct _MIKASA_PCR{ + ULONGLONG HalpCycleCount; // 64-bit per-processor cycle count + ULONG Reserved[3]; // Pad ProfileCount to offset 20 + EV5ProfileCount ProfileCount; // Profile counter state +} MIKASA_PCR, *PMIKASA_PCR; + +#endif + +// +// Define the Mikasa server management data structure. +// + +typedef union _MIKASA_SRV{ + struct { + UCHAR FlashRomEnable : 1; // rw + UCHAR DcPowerDisable : 1; // rw + UCHAR HaltIncoming : 1; // ro + UCHAR TempFail : 1; // ro + UCHAR DcOk1 : 1; // ro + UCHAR DcOk2 : 1; // ro + UCHAR Fan1Fault : 1; // ro + UCHAR Fan2Fault : 1; // ro + }; + UCHAR All; +} MIKASA_SRV, *PMIKASA_SRV; + +// +// Define the Mikasa interrupt mask register. This is how we enable +// and disable individual PCI interrupts. Actually, it's here more +// for reference, since the interrupt enable/disable is done with a +// computational algorithm. +// + +typedef union _MIKASA_IMR{ + struct { + ULONG Slot0IntA : 1; + ULONG Slot0IntB : 1; + ULONG Slot0IntC : 1; + ULONG Slot0IntD : 1; + ULONG Slot1IntA : 1; + ULONG Slot1IntB : 1; + ULONG Slot1IntC : 1; + ULONG Slot1IntD : 1; + ULONG Slot2IntA : 1; + ULONG Slot2IntB : 1; + ULONG Slot2IntC : 1; + ULONG Slot2IntD : 1; + ULONG Ncr810Scsi : 1; + ULONG PwrInt : 1; + ULONG TempWarn : 1; + ULONG Reserved : 17; + }; + ULONG All; +} MIKASA_IMR, *PMIKASA_IMR; + +// +// Define the Noritake server management data structure. +// + +typedef union _NORITAKE_SRV{ + struct { + UCHAR FlashRomEnable : 1; // rw + UCHAR DcPowerDisable : 1; // rw + UCHAR Reserved1: 2; + UCHAR HaltIncoming : 1; // ro + UCHAR FlashReady: 1; // ro + UCHAR Reserved2: 1; + UCHAR EmbeddedVGAStatus: 1; // rw + }; + UCHAR All; +} NORITAKE_SRV, *PNORITAKE_SRV; + +// +// Define the Noritake interrupt mask registers. This is how we enable +// and disable individual PCI interrupts. Actually, it's here more +// for reference, since the interrupt enable/disable is done with a +// computational algorithm. +// + +// +// Note: Slots 0 through 2 are on PCI bus 0, and slots 3 through 6 are +// on PCI bus 1. +// + +typedef union _NORITAKE_IMR1{ + struct { + ULONG SumIr2And3 : 1; + ULONG QLogic: 1; + ULONG Slot0IntA : 1; + ULONG Slot0IntB : 1; + ULONG Slot1IntA : 1; + ULONG Slot1IntB : 1; + ULONG Slot2IntA : 1; + ULONG Slot2IntB : 1; + ULONG Slot3IntA : 1; + ULONG Slot3IntB : 1; + ULONG Slot4IntA : 1; + ULONG Slot4IntB : 1; + ULONG Slot5IntA : 1; + ULONG Slot5IntB : 1; + ULONG Slot6IntA : 1; + ULONG Slot6IntB : 1; + ULONG Reserved : 16; + }; + ULONG ALL; +} NORITAKE_IMR1, *PNORITAKE_IMR1; + +typedef union _NORITAKE_IMR2{ + struct { + ULONG SumUnmaskedIr2 : 1; + ULONG SecondaryPCIBusInt : 1; + ULONG Slot0IntC : 1; + ULONG Slot0IntD : 1; + ULONG Slot1IntC : 1; + ULONG Slot1IntD : 1; + ULONG Slot2IntC : 1; + ULONG Slot2IntD : 1; + ULONG Slot3IntC : 1; + ULONG Slot3IntD : 1; + ULONG Slot4IntC : 1; + ULONG Slot4IntD : 1; + ULONG Slot5IntC : 1; + ULONG Slot5IntD : 1; + ULONG Slot6IntC : 1; + ULONG Slot6IntD : 1; + ULONG Reserved : 16; + }; + ULONG ALL; +} NORITAKE_IMR2, *PNORITAKE_IMR2; + +typedef union _NORITAKE_IMR3{ + struct { + ULONG Reserved1 : 2; + ULONG Power2Int : 1; + ULONG Power1Int : 1; + ULONG TempFail : 1; + ULONG TempWarn : 1; + ULONG Fan2Fail : 1; + ULONG Fan1Fail : 1; + ULONG Reserved2 : 24; + }; + ULONG ALL; +} NORITAKE_IMR3, *PNORITAKE_IMR3; + +// +// Define the Corelle server management data structure. +// + +typedef union _CORELLE_SRV { + struct { + UCHAR FlashRomEnable : 1; // rw + UCHAR SoftShut : 1; // rw + UCHAR CPU_HALT : 1; // rw + UCHAR TempShutDisable: 1; // rw + UCHAR HaltIncoming : 1; // ro + UCHAR VGAReset: 1; // ro + UCHAR WatchDogEnable: 1; // rw + UCHAR WatchDogBiscuit: 1; // rw + }; + UCHAR All; +} CORELLE_SRV, *PCORELLE_SRV; + +// +// Define the Corelle interrupt mask registers. This is how we enable +// and disable individual PCI interrupts. Actually, it's here more +// for reference, since the interrupt enable/disable is done with a +// computational algorithm. +// + +typedef union _CORELLE_IMR1{ + struct { + ULONG SumIr2 : 1; + ULONG QLogic : 1; + ULONG Slot0IntA : 1; + ULONG Slot0IntB : 1; + ULONG Slot1IntA : 1; + ULONG Slot1IntB : 1; + ULONG Slot2IntA : 1; + ULONG Slot2IntB : 1; + ULONG Slot3IntA : 1; + ULONG Slot3IntB : 1; + ULONG S3Trio64 : 1; + ULONG Reserved1 : 1; + ULONG TempFailInt : 1; + ULONG TempWarnInt : 1; + ULONG Fan1FailInt : 1; + ULONG Fan2FailInt : 1; + ULONG Reserved2 : 16; + }; + ULONG ALL; +} CORELLE_IMR1, *PCORELLE_IMR1; + +typedef union _CORELLE_IMR2{ + struct { + ULONG Reserved1 : 2; + ULONG Slot0IntC : 1; + ULONG Slot0IntD : 1; + ULONG Slot1IntC : 1; + ULONG Slot1IntD : 1; + ULONG Slot2IntC : 1; + ULONG Slot2IntD : 1; + ULONG Slot3IntC : 1; + ULONG Slot3IntD : 1; + ULONG Reserved2 : 22; + }; + ULONG ALL; +} CORELLE_IMR2, *PCORELLE_IMR2; + +#endif //!_LANGUAGE_ASSEMBLY + +#define HAL_PCR ( (PMIKASA_PCR)(&(PCR->HalReserved)) ) + +#define PCI_VECTOR PRIMARY0_VECTOR // from alpharef.h +#define PCI_MAX_INTERRUPT_VECTOR MAXIMUM_PCI_VECTOR // from alpharef.h + +#define PCI_SPARSE_IO_BASE_QVA \ + ((ULONG)(HAL_MAKE_QVA(CIA_PCI_SPARSE_IO_PHYSICAL))) + +// +// The combined Vendor ID, Device ID for the PCEB of the PCI/EISA bridge +// chip set. +// +#define INTEL_PCI_EISA_BRIDGE_ID 0x04828086 + +// +// N.B.: The PCI configuration space address is what we're really referring +// to, here. +// + +#define PCI_CONFIGURATION_BASE_QVA \ + ((ULONG)(HAL_MAKE_QVA(CIA_PCI_CONFIGURATION_PHYSICAL))) + +#define PCI_CONFIG_CYCLE_TYPE_0 0x0 // Local PCI device +#define PCI_CONFIG_CYCLE_TYPE_1 0x1 // Nested PCI device + +#define PCI_EISA_BRIDGE_HEADER_OFFSET (0x00070000 >> IO_BIT_SHIFT) // AD[18] + +// +// PCI-EISA Bridge Non-Configuration control register offsets. These should +// be simply ored with PCI_SPARSE_IO_BASE_QVA; they match what's in the +// Intel handbook for the 82374EB (ESC). +// +#define ESC_EDGE_LEVEL_CONTROL_1 0x4d0 +#define ESC_EDGE_LEVEL_CONTROL_2 0x4d1 +#define ESC_CMOS_ISA_PORT 0x800 + +// +// BIOS timer address port. This value is stuffed into PCEB configuration +// space at PCEB/ESC cofiguration. +// +#define BIOS_TIMER_PORT 0x78 + +// +// Mikasa-unique registers, accessed via PCI_SPARSE_IO_BASE_QVA, via the +// same protocol as above. Locations of these are intermixed with +// ESC-specific and ordinary ISA registers in this space. N.B.: the +// term "port" is used for compatibility with PC industry terminology. +// We know Alphas don't have I/O instructions, nor ports, as such. +// +#define COMBO_CHIP_CONFIG_INDEX_PORT 0x398 +#define COMBO_CHIP_CONFIG_DATA_PORT 0x399 + +// +// Define I2C constants +// + +#define I2C_INTERFACE_DATA_PORT 0x530 +#define I2C_INTERFACE_CSR_PORT 0x531 +#define I2C_INTERFACE_LENGTH 0x2 +#define I2C_INTERFACE_MASK 0x1 + +// +// This is the same for both Noritake and Mikasa +// + +#define SERVER_MANAGEMENT_REGISTER 0x532 + +// +// Noritake interrupt and interrupt mask register offsets. +// + +#define PCI_INTERRUPT_BASE_ADDRESS 0x540 +#define PCI_INTERRUPT_REGISTER_1 0x542 +#define PCI_INTERRUPT_REGISTER_2 0x544 +#define PCI_INTERRUPT_REGISTER_3 0x546 +#define PCI_INTERRUPT_MASK_REGISTER_1 0x54A +#define PCI_INTERRUPT_MASK_REGISTER_2 0x54C +#define PCI_INTERRUPT_MASK_REGISTER_3 0x54E + +// +// Noritake 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. All vectors in interrupt register 3 are between 0x31 and 0x38. +// 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. +// + +#define REGISTER_1_VECTOR_OFFSET 0x11 +#define REGISTER_2_VECTOR_OFFSET 0x21 +#define REGISTER_3_VECTOR_OFFSET 0x31 + + +// +// Corelle PCI vector offset. Interrupt vectors that originate from register 1 +// start at 0x10 for bit position 0. Interrupt vectors that originate from +// register 2 start at 0x20 for bit position 0. + +#define CORELLE_INTERRUPT1_OFFSET 0x10 +#define CORELLE_INTERRUPT2_OFFSET 0x20 + +// +// Mikasa interrupt and interrupt mask register offsets. +// + +#define PCI_INTERRUPT_REGISTER 0x534 +#define PCI_INTERRUPT_MASK_REGISTER 0x536 + +// +// Define the index and data ports for the NS Super IO (87312) chip. +// + +#define SUPERIO_INDEX_PORT 0x398 +#define SUPERIO_DATA_PORT 0x399 +#define SUPERIO_PORT_LENGTH 0x2 + +// +// PCI Sparse I/O space offsets for unique functions on the ESC. They are +// used as the offsets above. +// + +#define ESC_CONFIG_ADDRESS 0x22 +#define ESC_CONFIG_DATA 0x23 + +// +// ESC configuration register index addresses. The protocol is: +// write the configuration register address (one of the following) +// into ESC_CONTROL_INDEX, then write the data into ESC_CONTROL_DATA. +// +#define ESC_INDEX_ESC_ID 0x02 // write 0xf to enable +#define ESC_INDEX_REVISION_ID 0x08 // ro +#define ESC_INDEX_MODE_SELECT 0x40 // rw +#define ESC_INDEX_BIOS_CHIP_SELECT_A 0x42 // rw +#define ESC_INDEX_BIOS_CHIP_SELECT_B 0x43 // rw +#define ESC_INDEX_BCLK_CLOCK_DIVISOR 0x4d // rw +#define ESC_INDEX_PERIPHERAL_CHIP_SELECT_A 0x4e // rw +#define ESC_INDEX_PERIPHERAL_CHIP_SELECT_B 0x4f // rw +#define ESC_INDEX_EISA_ID_BYTE_1 0x50 // rw +#define ESC_INDEX_EISA_ID_BYTE_2 0x51 // rw +#define ESC_INDEX_EISA_ID_BYTE_3 0x52 // rw +#define ESC_INDEX_EISA_ID_BYTE_4 0x53 // rw +#define ESC_INDEX_SG_RELOCATE_BASE 0x57 // rw +#define ESC_INDEX_PIRQ0_ROUTE_CONTROL 0x60 // rw +#define ESC_INDEX_PIRQ1_ROUTE_CONTROL 0x61 // rw +#define ESC_INDEX_PIRQ2_ROUTE_CONTROL 0x62 // rw +#define ESC_INDEX_PIRQ3_ROUTE_CONTROL 0x63 // rw +#define ESC_INDEX_GPCS0_BASE_LOW 0x64 // rw +#define ESC_INDEX_GPCS0_BASE_HIGH 0x65 // rw +#define ESC_INDEX_GPCS0_MASK 0x66 // rw +#define ESC_INDEX_GPCS1_BASE_LOW 0x68 // rw +#define ESC_INDEX_GPCS1_BASE_HIGH 0x69 // rw +#define ESC_INDEX_GPCS1_MASK 0x6a // rw +#define ESC_INDEX_GPCS2_BASE_LOW 0x6c // rw +#define ESC_INDEX_GPCS2_BASE_HIGH 0x6d // rw +#define ESC_INDEX_GPCS2_MASK 0x6e // rw +#define ESC_INDEX_GP_XBUS_CONTROL 0x6f // rw + +#if !defined (_LANGUAGE_ASSEMBLY) + +typedef union _ESC_MODESEL{ + struct { + UCHAR EisaMasterSupport: 2; + UCHAR Reserved1: 1; + UCHAR SystemErrorEnable : 1; + UCHAR EscSelect : 1; + UCHAR CramPageEnable : 1; + UCHAR MreqPirqEnable : 1; + UCHAR Reserved2: 2; + }; + UCHAR All; +}ESC_MODESEL, *PESC_MODESEL; + +#define MS_4_EISA_MASTERS 0x00 +#define MS_6_EISA_MASTERS 0x01 +#define MS_7_EISA_MASTERS 0x02 +#define MS_8_EISA_MASTERS 0x03 +#define MS_RESERVED_MASK 0x84 + +#define BIOSCSA_RESERVED_MASK 0xc0 +#define BIOSCSB_RESERVED_MASK 0xf0 + +#define GPXBC_RESERVED_MASK 0xf8 + +typedef union _ESC_CLKDIV{ + struct { + UCHAR ClockDivisor: 3; + UCHAR Reserved1: 1; + UCHAR MouseInterruptEnable : 1; + UCHAR CoprocessorError : 1; + UCHAR Reserved2: 2; + }; + UCHAR All; +}ESC_CLKDIV, *PESC_CLKDIV; + +#define CLKDIV_33MHZ_EISA 0x00 +#define CLKDIV_25MHZ_EISA 0x01 +#define CLKDIV_RESERVED_MASK 0xc8 + +typedef union _ESC_PCSA{ + struct { + UCHAR RtcDecode: 1; + UCHAR KeyboardControllerDecode: 1; + UCHAR FloppyDiskSecondaryDecode : 1; + UCHAR FloppyDiskPrimaryDecode : 1; + UCHAR IdeDecode : 1; + UCHAR FloppyIdeSpaceSecondary : 1; + UCHAR Reserved : 2; + }; + UCHAR All; +}ESC_PCSA, *PESC_PCSA; + +#define PCSA_RESERVED_MASK 0xc0 + +typedef union _ESC_PCSB{ + struct { + UCHAR SerialPortADecode: 2; + UCHAR SerialPortBDecode: 2; + UCHAR ParallelPortDecode : 2; + UCHAR Port92Decode : 1; + UCHAR CramDecode : 1; + }; + UCHAR All; +}ESC_PCSB, *PESC_PCSB; + +#define PCSB_DECODE_DISABLE 0x3 + +typedef union _ESC_PIRQ{ + struct { + UCHAR IrqxRoutingBits: 7; + UCHAR RoutePciInterrupts: 1; + }; + UCHAR All; +}ESC_PIRQ, *PESC_PIRQ; + +#define PIRQ_DISABLE_ROUTING 0x01 +#define PIRQ_ENABLE_ROUTING 0x00 + +typedef union _ESC_GPXBC{ + struct { + UCHAR EnableGpcs0: 1; + UCHAR EnableGpcs1: 1; + UCHAR EnableGpcs2: 1; + UCHAR Reserved: 5; + }; + UCHAR All; +}ESC_GPXBC, *PESC_GPXBC; + +#endif // !_LANGUAGE_ASSEMBLY + +// +// PCI-EISA Bridge Configuration register offsets. These should be +// simply ored with PCI_CONFIGURATION_BASE_QVA; they match what's +// in the Intel handbook for the 82375EB (PCEB). +// +#define PCI_VENDOR_ID 0x00 // ro +#define PCI_DEVICE_ID 0x02 // ro +#define PCI_COMMAND 0x04 // rw +#define PCI_DEVICE_STATUS 0x06 // ro, rw clear +#define PCI_REVISION 0x08 // ro +#define PCI_MASTER_LATENCY_TIMER 0x0d // rw +#define PCI_CONTROL 0x40 // rw +#define PCI_ARBITER_CONTROL 0x41 // rw +#define PCI_ARBITER_PRIORITY_CONTROL 0x42 // rw +#define PCI_MEMCS_CONTROL 0x44 // rw +#define PCI_MEMCS_BOTTOM_OF_HOLE 0x45 // rw +#define PCI_MEMCS_TOP_OF_HOLE 0x46 // rw +#define PCI_MEMCS_TOP_OF_MEMORY 0x47 // rw +#define PCI_EISA_ADDRESS_DECODE_CONTROL_1 0x48 // rw +#define PCI_ISA_IO_RECOVERY_TIME_CONTROL 0x4c // rw +#define PCI_MEMCS_ATTRIBUTE_REGISTER_1 0x54 // rw +#define PCI_MEMCS_ATTRIBUTE_REGISTER_2 0x55 // rw +#define PCI_MEMCS_ATTRIBUTE_REGISTER_3 0x56 // rw +#define PCI_DECODE_CONTROL 0x58 // rw +#define PCI_EISA_ADDRESS_DECODE_CONTROL_2 0x5a // rw +#define PCI_EISA_TO_PCI_MEMORY_REGIONS_ATTR 0x5c // rw +#define PCI_EISA_TO_PCI_MEMORY_REGION1_REGISTER 0x60 // rw +#define PCI_EISA_TO_PCI_MEMORY_REGION2_REGISTER 0x64 // rw +#define PCI_EISA_TO_PCI_MEMORY_REGION3_REGISTER 0x68 // rw +#define PCI_EISA_TO_PCI_MEMORY_REGION4_REGISTER 0x6c // rw +#define PCI_EISA_TO_PCI_IO_REGION1_REGISTER 0x70 // rw +#define PCI_EISA_TO_PCI_IO_REGION2_REGISTER 0x74 // rw +#define PCI_EISA_TO_PCI_IO_REGION3_REGISTER 0x78 // rw +#define PCI_EISA_TO_PCI_IO_REGION4_REGISTER 0x7c // rw +#define PCI_BIOS_TIMER_BASE_ADDRESS 0x80 // rw +#define PCI_EISA_LATENCY_TIMER_CONTROL_REGISTER 0x84 // rw + +#if !defined (_LANGUAGE_ASSEMBLY) + +// +// Structure definitions of registers in PCEB PCI configuration space. +// fields marked "Not supported" are Intel placeholders, apparently. +// + +typedef union _PCEB_PCICMD{ + struct { + USHORT IoSpaceEnable : 1; + USHORT MemorySpaceEnable : 1; + USHORT BusMasterEnable : 1; + USHORT SpecialCycleEnable: 1; // Not supported + USHORT MemoryWriteInvalidateEnable : 1; // Not supported + USHORT VgaPaletteSnoop : 1; // Not supported + USHORT ParityErrorEnable : 1; + USHORT WaitStateControl : 1; // Not supported + USHORT SerreEnable : 1; // Not supported + USHORT Reserved : 7; + }; + USHORT All; +} PCEB_PCICMD, *PPCEB_PCICMD; + +typedef union _PCEB_PCISTS{ + struct { + USHORT Reserved : 9; + USHORT DevselTiming: 2; // ro + USHORT SignaledTargetAbort : 1; // Not supported + USHORT ReceivedTargetAbort: 1; // r/wc + USHORT MasterAbort : 1; // r/wc + USHORT Serrs : 1; // Not supported + USHORT ParityError: 1; // r/wc + }; + USHORT All; +} PCEB_PCISTS, *PPCEB_PCISTS; + +typedef union _PCEB_MLT{ + struct { + UCHAR Reserved : 3; + UCHAR LatencyTimerCount: 5; + }; + UCHAR All; +} PCEB_MLT, *PPCEB_MLT; + +typedef union _PCEB_PCICON{ + struct { + UCHAR Reserved1 : 2; + UCHAR PciPostedWriteBuffersEnable: 1; + UCHAR SubtractDecodeSamplePoint: 2; + UCHAR InterruptAcknowledgeEnable: 1; + UCHAR EisaToPciLineBuffersEnable: 1; + UCHAR Reserved2 : 1; + }; + UCHAR All; +} PCEB_PCICON, *PPCEB_PCICON; + +#define PCICON_SDSP_SLOW 0x00 +#define PCICON_SDSP_TYPICAL 0x01 +#define PCICON_SDSP_FAST 0x02 + +typedef union _PCEB_ARBCON{ + struct { + UCHAR GuaranteedAccessTimeEnable : 1; + UCHAR BusLockEnable: 1; + UCHAR CpuBusParkEnable: 1; + UCHAR MasterRetryTimer: 2; + UCHAR Reserved : 2; + UCHAR AutoPereqControlEnable: 1; + }; + UCHAR All; +} PCEB_ARBCON, *PPCEB_ARBCON; + +#define ARBCON_RETRY_TIMER_DISABLE 0x00 +#define ARBCON_16_PCICLKS_UNMASK 0x01 +#define ARBCON_32_PCICLKS_UNMASK 0x02 +#define ARBCON_64_PCICLKS_UNMASK 0x03 + +typedef union _PCEB_ARBPRI{ + struct { + UCHAR Bank0FixedPriorityMode : 1; + UCHAR Bank1FixedPriorityMode: 1; + UCHAR Bank2FixedPriorityMode: 2; + UCHAR Bank0RotateEnable: 1; + UCHAR Bank1RotateEnable: 1; + UCHAR Bank2RotateEnable: 1; + UCHAR Bank3RotateEnable: 1; + }; + UCHAR All; +} PCEB_ARBPRI, *PPCEB_ARBPRI; + +#define ARBPRI_BANK0_BANK3_BANK1 0x00 +#define ARBPRI_BANK3_BANK1_BANK0 0x10 +#define ARBPRI_BANK1_BANK0_BANK3 0x01 + +typedef union _PCEB_MCSCON{ + struct { + UCHAR ReadEnable512To640 : 1; + UCHAR WriteEnable512To640: 1; + UCHAR ReadEnableUpper64K: 1; + UCHAR WriteEnableUpper64K: 1; + UCHAR MemcsMasterEnable: 1; + UCHAR Reserved: 3; + }; + UCHAR All; +} PCEB_MCSCON, *PPCEB_MCSCON; + +typedef union _PCEB_EADC1{ + struct { + USHORT Block0To512 : 1; + USHORT Block512To640: 1; + USHORT Block640To768: 1; + USHORT Reserved: 5; + USHORT Block768To784: 1; + USHORT Block784To800: 1; + USHORT Block800To816: 1; + USHORT Block816To832: 1; + USHORT Block832To848: 1; + USHORT Block848To864: 1; + USHORT Block864To880: 1; + USHORT Block880To896: 1; + }; + UCHAR All; +} PCEB_EADC1, *PPCEB_EADC1; + +typedef union _PCEB_IORT{ + struct { + UCHAR RecoveryTimes16Bit : 2; + UCHAR RecoveryEnable16Bit: 1; + UCHAR RecoveryTimes8Bit : 3; + UCHAR RecoveryEnable8Bit: 1; + UCHAR Reserved: 1; + }; + UCHAR All; +} PCEB_IORT, *PPCEB_IORT; + +#define IORT_16BIT_1BCLK 0x01 +#define IORT_16BIT_2BCLKS 0x02 +#define IORT_16BIT_3BCLKS 0x03 +#define IORT_16BIT_4BCLKS 0x00 + +#define IORT_8BIT_1BCLK 0x01 +#define IORT_8BIT_2BCLKS 0x02 +#define IORT_8BIT_3BCLKS 0x03 +#define IORT_8BIT_4BCLKS 0x04 +#define IORT_8BIT_5BCLKS 0x05 +#define IORT_8BIT_6BCLKS 0x06 +#define IORT_8BIT_7BCLKS 0x07 +#define IORT_8BIT_8BCLKS 0x00 + +typedef union _PCEB_PDCON{ + struct { + UCHAR PciDecodeMode : 1; + UCHAR Reserved1: 3; + UCHAR DecodeControlIde : 1; + UCHAR DecodeControl8259 : 1; + UCHAR Reserved2: 2; + }; + UCHAR All; +} PCEB_PDCON, *PPCEB_PDCON; + +#define SUBTRACTIVE_DECODE 0x00 +#define NEGATIVE_DECODE 0x01 + +typedef struct _PCEB_EPMRA{ + struct { + UCHAR Region1Attribute : 1; + UCHAR Region2Attribute : 1; + UCHAR Region3Attribute : 1; + UCHAR Region4Attribute : 1; + UCHAR Reserved: 4; + }; + UCHAR All; +} PCEB_EPMRA, *PPCEB_EPMRA; + +#define REGION_BUFFERED 0x01 + +typedef struct _PCEB_MEMREGN{ + USHORT BaseAddress; + USHORT LimitAddress; +} PCEB_MEMREGN, *PPCEB_MEMREGN; + +typedef union _PCEB_IOREGN{ + struct { + ULONG Reserved1: 2; + ULONG BaseAddress : 14; + ULONG Reserved2: 2; + ULONG LimitAddress : 14; + }; + ULONG All; +} PCEB_IOREGN, *PPCEB_IOREGN; + +typedef union _PCEB_BTMR{ + struct { + USHORT BiosTimerEnable: 1; + USHORT Reserved: 1; + USHORT BaseAddress2thru15 : 14; + }; + USHORT All; +} PCEB_BTMR, *PPCEB_BTMR; + +#endif + +// +// ESC 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 + +// +// Define primary (and only) CPU on an Mikasa 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 (200) + +#endif // _MIKASA_ diff --git a/private/ntos/nthals/halpinna/alpha/mkinitnt.c b/private/ntos/nthals/halpinna/alpha/mkinitnt.c new file mode 100644 index 000000000..30bd816bc --- /dev/null +++ b/private/ntos/nthals/halpinna/alpha/mkinitnt.c @@ -0,0 +1,970 @@ +/*++ + +Copyright (c) 1993 Digital Equipment Corporation + +Module Name: + + mkinitnt.c + +Abstract: + + + This module implements the platform-specific initialization for + an Mikasa EV5 (Pinnacle) system. + +Author: + + Joe Notarangelo 25-Oct-1993 + +Environment: + + Kernel mode only. + +Revision History: + + Scott Lee 29-Nov-1995 + Adapted from Mikasa module for Mikasa EV5 (Pinnacle). + +--*/ + +#include "halp.h" +#include "pcrtc.h" +#include "mikasa.h" +#include "halpcsl.h" +#include "eisa.h" +#include "pci.h" +#include "pcip.h" +#include "iousage.h" +#include "stdio.h" + +#include "fwcallbk.h" + +#include <ntverp.h> // to get the product build number. + + +// +// Define extern global buffer for the Uncorrectable Error Frame. +// declared in halalpha\inithal.c +// + +extern PERROR_FRAME PUncorrectableError; + + +// +// Define the Product Naming data. +// + +PCHAR HalpFamilyName = "AlphaServer"; +PCHAR HalpProductName; +ULONG HalpProcessorNumber = 5; + +#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 Mikasa +// +// IRQ_H[0] = EPIC Error +// IRQ_H[1] = EISA Interrupt (PIC) +// IRQ_H[2] = PCI Interrupt +// IRQ_H[3] = Reserved +// IRQ_H[4] = Clock +// IRQ_H[5] = NMI (includes Halt) + +// +// For information purposes: here is what the IDT division looks like: +// +// 000-015 Built-ins (we only use 8 entries; NT wants 10) +// 016-031 ISA +// 048-063 EISA +// 080-095 PCI +// 112-127 Turbo Channel +// 128-255 unused, as are all other holes +// + +// +// Define the bus type, this value allows us to distinguish between +// EISA and ISA systems. We're only interested in distinguishing +// between just those two buses. +// +ULONG HalpBusType = MACHINE_TYPE_EISA; + +// +// This is the PCI Memory space that cannot be used by anyone +// and therefore the HAL says it is reserved for itself +// + +//ADDRESS_USAGE +//MikasaPCIMemorySpace = { +// NULL, CmResourceTypeMemory, PCIUsage, +// { +// __8MB, ( __32MB - __8MB ), // Start=8MB; Length=24MB +// 0,0 +// } +//}; + +// +// Define global data used to communicate new clock rates to the clock +// interrupt service routine. +// + +ULONG HalpCurrentTimeIncrement; +ULONG HalpNextRateSelect; +ULONG HalpNextTimeIncrement; +ULONG HalpNewTimeIncrement; + +// +// Define external references. +// + +extern ULONG HalDisablePCIParityChecking; + +// +// Determines if the platform is a Noritake or a Corelle. +// + +BOOLEAN HalpNoritakePlatform; +BOOLEAN HalpCorellePlatform; + +// +// Function prototypes. +// + +VOID +HalpPinnacleErrorInterrupt( + VOID + ); + +VOID +HalpNmiInterrupt( + VOID + ); + +VOID +HalpClearInterrupts( + VOID + ); + +BOOLEAN +HalpInitializeMikasaAndNoritakeInterrupts( + VOID + ); + +VOID +HalpParseLoaderBlock( + PLOADER_PARAMETER_BLOCK LoaderBlock + ); + +VOID +HalpRegisterPlatformResources( + PUCHAR HalName + ); + +VOID +HalpDetermineMachineType( + VOID + ); + + +BOOLEAN +HalpInitializeInterrupts( + VOID + ) + +/*++ + +Routine Description: + + This function initializes interrupts for an Alpha system. + +Arguments: + + None. + +Return Value: + + A value of TRUE is returned if the initialization is successfully + completed. Otherwise a value of FALSE is returned. + +--*/ + +{ + + extern ULONG Halp21164CorrectedErrorInterrupt(); + extern ULONG HalpCiaErrorInterrupt(); + extern ULONG HalpDeviceInterrupt(); + extern ULONG HalpHaltInterrupt(); + ULONG Vector; + + // + // Initialize HAL processor parameters based on estimated CPU speed. + // This must be done before HalpStallExecution is called. Compute integral + // megahertz first to avoid rounding errors due to imprecise cycle clock + // period values. + // + + HalpInitializeProcessorParameters(); + + // + // Connect the Stall interrupt vector to the clock. When the + // profile count is calculated, we then connect the normal + // clock. + + + PCR->InterruptRoutine[CLOCK2_LEVEL] = HalpStallInterrupt; + + // + // Start the peridodic interrupt from the RTC + // + + HalpProgramIntervalTimer(MAXIMUM_RATE_SELECT); + +// jwlfix - Does the following apply to me on Mikasa? +// +//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 EISA, PCI and NMI interrupts. + // + + HalpInitializeMikasaAndNoritakeInterrupts(); + + // + // Initialize the 21164 interrupts. + // + + HalpInitialize21164Interrupts(); + + PCR->InterruptRoutine[EV5_IRQ0_VECTOR] = + (PKINTERRUPT_ROUTINE)HalpCiaErrorInterrupt; + + PCR->InterruptRoutine[EV5_IRQ1_VECTOR] = + (PKINTERRUPT_ROUTINE)HalpDeviceInterrupt; + + PCR->InterruptRoutine[EV5_IRQ2_VECTOR] = + (PKINTERRUPT_ROUTINE)HalpClockInterrupt; + + PCR->InterruptRoutine[EV5_HALT_VECTOR] = + (PKINTERRUPT_ROUTINE)HalpHaltInterrupt; + + PCR->InterruptRoutine[EV5_IPL30] = + (PKINTERRUPT_ROUTINE)HalpNmiInterrupt; + + PCR->InterruptRoutine[EV5_IPL31] = // machine check vector + (PKINTERRUPT_ROUTINE)HalpPinnacleErrorInterrupt; + + PCR->InterruptRoutine[EV5_CRD_VECTOR] = + (PKINTERRUPT_ROUTINE)Halp21164CorrectedErrorInterrupt; + + HalpStart21164Interrupts(); + + return TRUE; + +} + + +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. + +--*/ + +{ + + // + // Compute the profile interrupt rate. + // + + HalpProfileCountRate = ((1000 * 1000 * 10) / KeQueryTimeIncrement()); + + // + // Set the time increment value and connect the real clock interrupt + // routine. + // + + PCR->InterruptRoutine[CLOCK2_LEVEL] = HalpClockInterrupt; + + return; +} + + +VOID +HalpEstablishErrorHandler( + VOID + ) +/*++ + +Routine Description: + + This routine performs the initialization necessary for the HAL to + begin servicing machine checks. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + BOOLEAN PciParityChecking; + BOOLEAN ReportCorrectables; + + // + // Connect the machine check handler via the PCR. + // + + PCR->MachineCheckError = HalMachineCheck; + + // + // Initialize error handling for CIA. + // + + HalpInitializeCiaMachineChecks( ReportCorrectables = FALSE, + PciParityChecking = FALSE ); + + 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. + +--*/ +{ + ULONG BusIrql; + ULONG BusNumber; + UCHAR MsgBuffer[MAX_INIT_MSG]; + BOOLEAN ReportCorrectables; + BOOLEAN PciParityChecking; + + 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 ); + + // + // Establish the error handler, to reflect the parity checking + // + + PciParityChecking = (BOOLEAN) (HalDisablePCIParityChecking == 0); + HalpInitializeCiaMachineChecks(ReportCorrectables = TRUE, + PciParityChecking); + + // + // Determine which platform we are running on. + // + + HalpDetermineMachineType(); + + } else { + + // + // Phase 1 Initialization. + // + + // + // Initialize the existing bus handlers. + // + + HalpRegisterInternalBusHandlers(); + + // + // Initialize PCI Bus. + // + + HalpInitializePCIBus (LoaderBlock); + + // + // Initialize profiler. + // + + HalpInitializeProfiler(); + + // + // Print a message with version number. + // + + if ( HalpCorellePlatform ) { + HalpProductName = "800"; + } else { + HalpProductName = "1000"; + } + + sprintf( MsgBuffer, + "Digital Equipment Corporation %s %s %d/%d\n", + HalpFamilyName, + HalpProductName, + HalpProcessorNumber, + HalpClockMegaHertz ); + + HalDisplayString( MsgBuffer ); + + // + // Register the name of the HAL. + // + + sprintf( MsgBuffer, + "%s %s %d/%d PCI/EISA HAL", + HalpFamilyName, + HalpProductName, + HalpProcessorNumber, + HalpClockMegaHertz ); + + HalpRegisterPlatformResources( MsgBuffer ); + + } + + return; + +} + +VOID +HalpRegisterPlatformResources( + PUCHAR HalName + ) +/*++ + +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; + + // + // Register the buses. + // + + HalpRegisterBusUsage(Internal); + HalpRegisterBusUsage(Eisa); + HalpRegisterBusUsage(Isa); + HalpRegisterBusUsage(PCIBus); + + // + // Register the name of the HAL. + // + + HalpRegisterHalName( HalName ); + + // + // 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); + + 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.DmaChannel = 0x4; + Resource.u.DmaPort = 0x0; + 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 +HalpGetMachineDependentErrorFrameSizes( + PULONG RawProcessorSize, + PULONG RawSystemInfoSize + ) +/*++ + +Routine Description: + + This function is called from HalpAllocateUncorrectableErrorFrame. + This function retuns the size of the system specific error frame + sizes. + +Arguments: + + RawProcessorSize - Processor-specific uncorrectable frame size. + + RawSystemInfoSize - system-specific uncorrectable frame size. + +Return Value: + + None. + +--*/ +{ + *RawProcessorSize = sizeof(PROCESSOR_EV5_UNCORRECTABLE); + *RawSystemInfoSize = sizeof(CIA_UNCORRECTABLE_FRAME); + return; +} + +VOID +HalpGetSystemInfo(SYSTEM_INFORMATION *SystemInfo) +/*++ + +Routine Description: + + Fills in the system information structure. + NOTE: Must later investigate the Fw call to get the firmware revision + ID. Must also figure out a way to get the OS version (preferebly the + build number). + +Arguments: + + SystemInfo - Pointer to the SYSTEM_INFORMATION structure. + +Return Value: + + None + +--*/ +{ + char systemtype[] = "Pinnacle"; + EXTENDED_SYSTEM_INFORMATION FwExtSysInfo; + + + if ( HalpCorellePlatform ) { + strcpy(systemtype, "Corelle"); + } + + VenReturnExtendedSystemInformation(&FwExtSysInfo); + + RtlCopyMemory(SystemInfo->FirmwareRevisionId, + FwExtSysInfo.FirmwareVersion, + 16); + + + RtlCopyMemory(SystemInfo->SystemType,systemtype, 8); + + SystemInfo->ClockSpeed = + ((1000 * 1000) + (PCR->CycleClockPeriod >> 1)) / PCR->CycleClockPeriod; + + SystemInfo->SystemRevision = PCR->SystemRevision; + + RtlCopyMemory(SystemInfo->SystemSerialNumber, + PCR->SystemSerialNumber, + 16); + + SystemInfo->SystemVariant = PCR->SystemVariant; + + + SystemInfo->PalMajorVersion = PCR->PalMajorVersion; + SystemInfo->PalMinorVersion = PCR->PalMinorVersion; + + SystemInfo->OsRevisionId = VER_PRODUCTBUILD; + + // + // For now fill in dummy values. + // + SystemInfo->ModuleVariant = 1UL; + SystemInfo->ModuleRevision = 1UL; + SystemInfo->ModuleSerialNumber = 0; + + return; +} + + + +VOID +HalpInitializeUncorrectableErrorFrame ( + VOID + ) +/*++ + +Routine Description: + + This function Allocates an Uncorrectable Error frame for this + system and initializes the frame with certain constant/global + values. + + This is routine called during machine dependent system + Initialization. + +Arguments: + + none + +Return Value: + + none + +--*/ +{ + // + // 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: + + This routine will determine which the platform we are running and set + HalpNoritakePlatform and HalpCorellePlatform accordingly. + +Arguments: + + None. + +Return value: + + None. + +--*/ +{ + + PSYSTEM_ID SystemId; + + // + // Get the ProductId, and determine the machine type. + // + + SystemId = ArcGetSystemId(); + + if((strstr( &SystemId->ProductId[0], "Pintake" ) != 0) || + (strstr( &SystemId->ProductId[0], "PinNor") != 0)) { + + HalpNoritakePlatform = TRUE; + HalpCorellePlatform = FALSE; + + } else if ( strstr(&SystemId->ProductId[0], "Corelle" ) != 0) { + + HalpNoritakePlatform = FALSE; + HalpCorellePlatform = TRUE; + + } else { + + HalpNoritakePlatform = FALSE; + HalpCorellePlatform = FALSE; + + } + +} + +// +//jnfix +// +// This routine is bogus and does not apply to Mikasa EV5 and the call should +// be ripped out of fwreturn (or at least changed to something that is more +// abstract). +// + +VOID +HalpResetHAERegisters( + VOID + ) +{ + return; +} + +// +//jnfix - this variable is needed because the clock interrupt handler +// - in intsup.s was made to be familiar with ev4prof.c, unfortunate +// - since we don't use ev4prof.c, so for now this is a hack, later +// - we will either fix intsup.s or create a new intsup.s that does +// - not have this hack +// + +ULONG HalpNumberOfTicksReload; diff --git a/private/ntos/nthals/halpinna/alpha/mkintsup.c b/private/ntos/nthals/halpinna/alpha/mkintsup.c new file mode 100644 index 000000000..f957e5312 --- /dev/null +++ b/private/ntos/nthals/halpinna/alpha/mkintsup.c @@ -0,0 +1,1075 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation +Copyright (c) 1992, 1993 Digital Equipment Corporation + +Module Name: + + mkintsup.c + +Abstract: + + The module provides the interrupt support for Mikasa EV5 (Pinnacle) systems. + +Author: + + Eric Rehm (DEC) 29-December-1993 + +Revision History: + + Scott Lee (DEC) 30-Nov-1995 + Adapted from Mikasa module for Mikasa EV5 (Pinnacle). + +--*/ + + +#include "halp.h" +#include "eisa.h" +#include "ebsgdma.h" +#include "mikasa.h" +#include "pcrtc.h" +#include "pintolin.h" + +// +// Import globals declared in HalpMapIoSpace. +// + +extern PVOID HalpServerControlQva; + +extern PVOID HalpMikasaPciIrQva; +extern PVOID HalpMikasaPciImrQva; + +extern PVOID HalpNoritakePciIr1Qva; +extern PVOID HalpNoritakePciIr2Qva; +extern PVOID HalpNoritakePciIr3Qva; +extern PVOID HalpNoritakePciImr1Qva; +extern PVOID HalpNoritakePciImr2Qva; +extern PVOID HalpNoritakePciImr3Qva; + +extern PVOID HalpCorellePciIr1Qva; +extern PVOID HalpCorellePciIr2Qva; +extern PVOID HalpCorellePciImr1Qva; +extern PVOID HalpCorellePciImr2Qva; + +// +// Import global from PCI interrupt management functions. +// +extern USHORT HalpMikasaPciInterruptMask; + +extern USHORT HalpNoritakePciInterrupt1Mask; +extern USHORT HalpNoritakePciInterrupt2Mask; +extern USHORT HalpNoritakePciInterrupt3Mask; + +extern USHORT HalpCorellePciInterrupt1Mask; +extern USHORT HalpCorellePciInterrupt2Mask; + +// +// Define reference to platform identifier +// + +extern BOOLEAN HalpNoritakePlatform; +extern BOOLEAN HalpCorellePlatform; + +// +// Declare the interrupt structures and spinlocks for the intermediate +// interrupt dispatchers. +// + + KINTERRUPT HalpPciInterrupt; + KINTERRUPT HalpEisaInterrupt; + +// +// Declare the interrupt dispatch routine for PCI/EISA interrupts. The +// interrupt dispatch routine, HalpPciDispatch or HalpEisaDispatch, is called +// from this handler. + +BOOLEAN +HalpDeviceDispatch( + IN PKINTERRUPT Interrupt, + IN PVOID ServiceContext, + IN PKTRAP_FRAME TrapFrame +); + + +BOOLEAN +HalpPciDispatch( + IN PKINTERRUPT Interrupt, + IN PVOID ServiceContext, + IN PKTRAP_FRAME TrapFrame + ); + +// +// The following is the interrupt object used for DMA controller interrupts. +// DMA controller interrupts occur when a memory parity error occurs or a +// programming error occurs to the DMA controller. +// + +KINTERRUPT HalpEisaNmiInterrupt; + +UCHAR EisaNMIMsg[] = "NMI: Eisa IOCHKERR board x\n"; +ULONG NMIcount = 0; + +// +// 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 + ); + +// +// PCI initialization routines +// + +VOID +HalpInitializeMikasaPciInterrupts( + VOID + ); + +VOID +HalpInitializeNoritakePciInterrupts( + VOID + ); + +VOID +HalpInitializeCorellePciInterrupts( + VOID + ); + + +BOOLEAN +HalpInitializeMikasaAndNoritakeInterrupts( + VOID + ) + +/*++ + +Routine Description: + + This routine initializes the structures necessary for EISA & PCI operations + and connects the intermediate interrupt dispatchers. It also initializes + the EISA interrupt controller; the Mikasa, Noritake, and Corelle ESC + interrupt controllers are compatible with the EISA interrupt controller + 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(); + + + // + // Intitialize interrupt controller + // + + KeRaiseIrql(DEVICE_HIGH_LEVEL, &oldIrql); + + // + // There's no initialization required for the Mikasa 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. + // + // The Noritake requires a separate routine to setup the 3 interrupt + // mask registers correctly. + // + // Corelle requires a separate routine to setup the 2 interrupt mask + // registers correctly. + // + + if( HalpNoritakePlatform ) { + + HalpInitializeNoritakePciInterrupts(); + + } else if ( HalpCorellePlatform ) { + + HalpInitializeCorellePciInterrupts(); + + } else { + + HalpInitializeMikasaPciInterrupts(); + + } + + // + // We must initialize the ESC's PICs, for EISA interrupts. + // + + HalpInitializeEisaInterrupts(); + + // + // 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); +} + + + +BOOLEAN +HalpDeviceDispatch( + IN PKINTERRUPT Interrupt, + IN PVOID ServiceContext, + IN PKTRAP_FRAME TrapFrame + ) +/*++ + +Routine Description: + + This function is entered as a result of an interrupt being generated via + the vector that is connected to an interrupt object associated with the + PCI/EISA device interrupts. Its function is to call the second-level + interrupt dispatch routine. + +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. + +--*/ +{ + USHORT IrContents; + BOOLEAN returnValue; + + // + // Read the PCI interrupt register. + // + + if (HalpNoritakePlatform) { + + IrContents = + ~(0xffff & READ_PORT_USHORT((PUSHORT)HalpNoritakePciIr1Qva)); + IrContents &= HalpNoritakePciInterrupt1Mask; + + } else if ( HalpCorellePlatform ) { + + IrContents = + ~(0xffff & READ_PORT_USHORT((PUSHORT)HalpCorellePciIr1Qva)); + IrContents &= HalpCorellePciInterrupt1Mask; + + } else { + + IrContents = + ~(0xffff & READ_PORT_USHORT((PUSHORT)HalpMikasaPciIrQva)); + IrContents &= HalpMikasaPciInterruptMask; + + } + + // + // Determine whether a PCI interrupt or an EISA interrupt occurred + // + + if (IrContents) { + + // + // PCI interrupt. Call HalpPciDispatch. + // + + if (HalpNoritakePlatform) { + + returnValue = HalpPciDispatch(Interrupt, HalpNoritakePciIr1Qva, + TrapFrame); + + } else if ( HalpCorellePlatform ) { + + returnValue = HalpPciDispatch(Interrupt, HalpCorellePciIr1Qva, + TrapFrame); + + } else { + + returnValue = HalpPciDispatch(Interrupt, HalpMikasaPciIrQva, + TrapFrame); + + } + + } else { + + // + // EISA interrupt. Call HalpEisaDispatch. + // + + returnValue = HalpEisaDispatch(Interrupt, HalpEisaIntAckBase, + TrapFrame); + + } + + return returnValue; + +} + + + +VOID +HalpNmiInterrupt ( + VOID + ) + +/*++ + +Routine Description: + + This routine handles the NMI interrupts that are routed to pwr_fail_irq_h. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + + // + // Call HalHandleNMI to handle the interrupt + // + + HalHandleNMI(NULL, NULL); + +} + + + +VOID +HalpInitializeNMI( + VOID + ) +/*++ + +Routine Description: + + This function is called to initialize ESC NMI interrupts. + +Arguments: + + None. + +Return Value: + + None. +--*/ +{ + UCHAR DataByte; + + // + // Initialize the ESC 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. + // + + DataByte = READ_PORT_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable); + ((PNMI_ENABLE)(&DataByte))->NmiDisable = 0; + WRITE_PORT_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable, DataByte); +#ifdef HALDBG + DbgPrint("HalpIntializeNMI: wrote 0x%x to NmiEnable\n\r", DataByte); +#endif + +} + +// jwlfix - I'll have to make this do something useful, since the console +// halt button on Mikasa is connected to this interrupt. To start, +// it will be a useful way to see if the interrupt gets connected. +// The simple path is to check the server management register to +// see if the "halt" button has been pressed on the operator's +// console, and then initiate a hardware reset. On the other hand, +// a server might not want to be halted so readily as that. + +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. + +--*/ +{ + UCHAR StatusByte; + UCHAR EisaPort; + ULONG port; + ULONG AddressSpace = 1; // 1 = I/O address space + BOOLEAN Status; + PHYSICAL_ADDRESS BusAddress; + PHYSICAL_ADDRESS TranslatedAddress; + UCHAR Datum; + ULONG Ir1Contents, Ir3Contents; + + NMIcount++; + + // + // Set the Eisa NMI disable bit. We do this to mask further NMI + // interrupts while we're servicing this one. + // + Datum = READ_PORT_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable); + ((PNMI_ENABLE)(&Datum))->NmiDisable = 1; + WRITE_PORT_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable, Datum); +#ifdef HALDBG + DbgPrint("HalpIntializeNMI: wrote 0x%x to NmiEnable\n\r", Datum); +#endif + + StatusByte = + READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus); + + if (StatusByte & 0x80) { +#ifdef HALDBG + DbgPrint("HalHandleNMI: Parity Check / Parity Error\n"); + DbgPrint("HalHandleNMI: StatusByte = 0x%x\r\n", StatusByte); +#else + // + // jwlfix - For the present, we're commenting out an NMI parity + // error bugcheck, until investigation into its causes + // yields a better solution. + // + // HalDisplayString ("NMI: Parity Check / Parity Error\n"); + // KeBugCheck(NMI_HARDWARE_FAILURE); + // return (TRUE); +#endif + } + + // + // Handle the server management interrupts. + // sclfix - We will dismiss these interrupts for now. This will need to be + // change once we decide how to handle server management features. + // + + Datum = READ_PORT_UCHAR((PUCHAR)HalpServerControlQva ); + + if (HalpNoritakePlatform) { + + Ir3Contents = (ULONG)(READ_PORT_USHORT((PUSHORT)HalpNoritakePciIr3Qva)); + + if (((PNORITAKE_SRV)(&Datum))->HaltIncoming == 0 || + ((PNORITAKE_IMR3)(&Status))->TempWarn == 0 || + ((PNORITAKE_IMR3)(&Status))->Power2Int == 0 || + ((PNORITAKE_IMR3)(&Status))->Power1Int == 0 || + ((PNORITAKE_IMR3)(&Status))->Fan2Fail == 0 || + ((PNORITAKE_IMR3)(&Status))->Fan1Fail == 0) { + +#ifdef HALDBG + DbgPrint("HalHandleNMI: Server management NMI\n"); + DbgPrint("HalHandleNMI: StatusByte = 0x%x\r\n", StatusByte); + DbgPrint("HalHandleNMI: Server management byte = 0x%x\r\n", Datum); + DbgPrint("HalHandleNMI: Ir3 contents = 0x%x\r\n", Ir3Contents); +#endif + + } + + } else if (HalpCorellePlatform) { + + Ir1Contents = (ULONG)(READ_PORT_USHORT((PUSHORT)HalpCorellePciIr1Qva)); + + if (((PCORELLE_SRV)(&Datum))->HaltIncoming == 0 || + ((PCORELLE_IMR1)(&Status))->TempFailInt == 0 || + ((PCORELLE_IMR1)(&Status))->TempWarnInt == 0 || + ((PCORELLE_IMR1)(&Status))->Fan1FailInt == 0 || + ((PCORELLE_IMR1)(&Status))->Fan2FailInt == 0) { + +#ifdef HALDBG + DbgPrint("HalHandleNMI: Server management NMI\n"); + DbgPrint("HalHandleNMI: StatusByte = 0x%x\r\n", StatusByte); + DbgPrint("HalHandleNMI: Server managemnt byte = 0x%x\r\n", Datum); + DbgPrint("HalHandleNMI: Ir1 contents = 0x%x\r\n", Ir1Contents); +#endif + + } + + } else { + + if (((PMIKASA_SRV)(&Datum))->HaltIncoming == 0 || + ((PMIKASA_SRV)(&Datum))->TempFail == 1 || + ((PMIKASA_SRV)(&Datum))->DcOk1 == 0 || + ((PMIKASA_SRV)(&Datum))->DcOk2 == 0 || + ((PMIKASA_SRV)(&Datum))->Fan1Fault == 0 || + ((PMIKASA_SRV)(&Datum))->Fan2Fault == 0) { + +#ifdef HALDBG + DbgPrint("HalHandleNMI: Server management NMI\n"); + DbgPrint("HalHandleNMI: StatusByte = 0x%x\r\n", StatusByte); + DbgPrint("HalHandleNMI: Server Management Byte = 0x%x\r\n", Datum); +#endif + + } + + } + + + if (StatusByte & 0x40) { +#ifdef HALDBG + DbgPrint("HalHandleNMI: Channel Check / IOCHK\n"); + DbgPrint("HalHandleNMI: StatusByte = 0x%x\r\n", StatusByte); +#else + HalDisplayString ("NMI: Channel Check / IOCHK\n"); + KeBugCheck(NMI_HARDWARE_FAILURE); + return (TRUE); +#endif + } + +#if 0 + // jwlfix - This code can be added in later, as we have need + // for it. It's good to have it here, for when it + // might be of use. + // + // This is an Eisa machine, check for extnded nmi information... + // + + StatusByte = READ_PORT_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl); + + if (StatusByte & 0x80) { + HalDisplayString ("NMI: Fail-safe timer\n"); + } + + if (StatusByte & 0x40) { + HalDisplayString ("NMI: Bus Timeout\n"); + } + + if (StatusByte & 0x20) { + HalDisplayString ("NMI: Software NMI generated\n"); + } + + // + // Look for any Eisa expansion board. See if it asserted NMI. + // + // jwlfix - The following doesn't work, at this moment; it's + // likey the 12-bit shift, which should be a 5-bit + // shift on Mikasa. + // + + BusAddress.HighPart = 0; + + for (EisaPort = 0; EisaPort <= 0xf; EisaPort++) + { + BusAddress.LowPart = (EisaPort << 12) + 0xC80; + + Status = HalTranslateBusAddress(Eisa, // InterfaceType + 0, // BusNumber + BusAddress, + &AddressSpace, // 1=I/O address space + &TranslatedAddress); // QVA + if (Status == FALSE) + { + UCHAR pbuf[80]; + sprintf(pbuf, + "Unable to translate bus address %x for EISA slot %d\n", + BusAddress.LowPart, EisaPort); + HalDisplayString(pbuf); + KeBugCheck(NMI_HARDWARE_FAILURE); + } + + port = TranslatedAddress.LowPart; + + WRITE_PORT_UCHAR ((PUCHAR) port, 0xff); + StatusByte = READ_PORT_UCHAR ((PUCHAR) port); + + if ((StatusByte & 0x80) == 0) { + // + // Found valid Eisa board, Check to see if its + // IOCHKERR is asserted. + // + + StatusByte = READ_PORT_UCHAR ((PUCHAR) port+4); + if (StatusByte & 0x2) { + EisaNMIMsg[25] = (EisaPort > 9 ? 'A'-10 : '0') + EisaPort; + HalDisplayString (EisaNMIMsg); + KeBugCheck(NMI_HARDWARE_FAILURE); + } + } + } +#ifdef HALDBG + // Reset extended NMI interrupts (for debugging purposes only). + WRITE_PORT_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl, 0x00); + WRITE_PORT_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl, 0x02); +#endif +#endif + +#ifdef HALDBG + DbgPrint("HalHandleNMI: Resetting PERR#; NMI count = %d\r\n", NMIcount); +#endif + + // + // Reset PERR# and disable it. + // + WRITE_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus, 0x04); + + // + // now enable it again. + // + WRITE_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus, 0); + + // + // Clear the Eisa NMI disable bit. This re-enables NMI interrupts, + // now that we're done servicing this one. + // + Datum = READ_PORT_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable); + ((PNMI_ENABLE)(&Datum))->NmiDisable = 0; + WRITE_PORT_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable, Datum); +#ifdef HALDBG + DbgPrint("HalpIntializeNMI: wrote 0x%x to NmiEnable\n\r", Datum); +#endif + + return(TRUE); +} + +UCHAR +HalpAcknowledgeEisaInterrupt( + PVOID ServiceContext + ) +/*++ + +Routine Description: + + Acknowledge the EISA interrupt from the programmable interrupt controller. + Return the vector number of the highest priority pending interrupt. + +Arguments: + + ServiceContext - Service context of the interrupt service supplies + a pointer to the EISA interrupt acknowledge register. + +Return Value: + + Return the value of the highest priority pending interrupt. + +--*/ +{ + UCHAR InterruptVector; + + // + // Read the interrupt vector from the PIC. + // + + InterruptVector = (UCHAR) (INTERRUPT_ACKNOWLEDGE(ServiceContext)); + + return( InterruptVector ); + +} + + +UCHAR +HalpAcknowledgeMikasaPciInterrupt( + 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 pointer to the Mikasa PCI interrupt register QVA. + +Return Value: + + Return the value of the highest priority pending interrupt. + +--*/ +{ + UCHAR InterruptVector = 0; + USHORT IrContents; + int i; + + // + // Find the first zero bit in the register, starting from the highest + // order bit. This implies a priority ordering that makes a certain + // amount of sense, in that bits 14 and 13 indicate temperature and + // power faults, while bit 12 is the Ncr53c810. Note that it's + // necessary to add one to the bit number to make the interrupt + // vector, a unit-origin value in the pin-to-line table. We do + // this by starting i at 16 and ending it at 1; that means zero + // is a non-enabled interrupt indication. + // + + // + // First, get and complement the interrupt register, so that the + // pending interrupts will be the "1" bits. Then mask with the + // enabled mask, HalpMikasaPciInterruptMask; + // + + IrContents = ~(0xffff & READ_PORT_USHORT( (PUSHORT)ServiceContext )); + IrContents &= HalpMikasaPciInterruptMask; + + for (i = 16; i >= 1; i-- ) { + if ( IrContents & 0x8000 ) { + InterruptVector = i; + break; + } else { + IrContents <<= 1; + } + } + return( InterruptVector ); + +} + + +UCHAR +HalpAcknowledgeNoritakePciInterrupt( + 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 pointer to the Noritake PCI interrupt register 1 QVA. + +Return Value: + + Return the value of the highest priority pending interrupt. + +--*/ +{ + UCHAR InterruptVector = 0; + USHORT IrContents; + int i; + + // + // Interrupt1 register contains the sum of all interrupts of Interrupt2 + // and Interrupt3 registers in bit 0. The rest of the register contains + // the A and B interrupts of the 7 PCI slots. Interrupt2 register + // contains the sum of all of the unmasked interrupts of Interrupt 2 in bit + // 0. Bit 1 is asserted when any secondary PCI bus interrupt is asserted + // (including those in interrupt register 1) and the posted write buffers + // in the PPB have been flushed. The rest of the register contians the C + // and D interrupts of all of the slots. Interrupt3 register contains some + // safety and reliability interrupts. Please see mikasa.h for the + // definitions of which interrupt is at which bit in the register. + // + // Each bit in the registers corresponds to an interrupt vector (which + // will later have PCI_VECTORS added to it.) This vector can be obtained + // by adding the vector offset for that register to the bit position. + // These offsets are also defined in mikasa.h. + // + // All registers are "reverse-logic" (active low), where a 0 means that an + // interrupt is waiting. That is why we must complement the contents of + // the register before we mask with HalpNoritakePciInterruptXMask. + // + + // + // First, get and complement the first interrupt register, so that the + // pending interrupts will be the "1" bits. Then mask with the + // enabled mask, HalpNoritakePciInterrupt1Mask; + // + + IrContents = + ~(0xffff & READ_PORT_USHORT((PUSHORT)HalpNoritakePciIr1Qva)); + IrContents &= HalpNoritakePciInterrupt1Mask; + + // + // Position bit 1 as the lowest bit. We will start checking here - this + // is the first "real" interrupt. + // + + IrContents >>= 1; + + for( i = 1; i < 16; i++ ) { + if( IrContents & 0x1 ) { + InterruptVector = i + REGISTER_1_VECTOR_OFFSET; + break; + } + IrContents >>= 1; + } + + + if( InterruptVector == 0 ) { + + // + // We didn't find any interrupts in interrupt register 1. + // Check interrupt register 2. + // + + IrContents = + ~(0xffff & READ_PORT_USHORT((PUSHORT)HalpNoritakePciIr2Qva)); + IrContents &= HalpNoritakePciInterrupt2Mask; + + // + // Position bit 2 in the lowest bit. We will start checking here - + // this is the first "real" interrupt. + // + + IrContents >>= 2; + + for( i = 2; i < 16; i++ ) { + if( IrContents & 0x1 ) { + InterruptVector = i + REGISTER_2_VECTOR_OFFSET; + break; + } + IrContents >>= 1; + } + + if( InterruptVector == 0 ) { + + // + // We didn't find any interrupts in interrupt register 2. + // Check Interrupt Register 3. + // + + IrContents = ~(0xffff & + READ_PORT_USHORT((PUSHORT)HalpNoritakePciIr3Qva)); + IrContents &= HalpNoritakePciInterrupt3Mask; + + // + // Position bit 2 in the lowest bit. We will start checking here - + // this is the first "real" interrupt. + // + + IrContents >>= 2; + + for( i = 2; i < 6; i++ ) { + if( IrContents & 0x1 ) { + InterruptVector = i + REGISTER_3_VECTOR_OFFSET; + break; + } + IrContents >>= 1; + } + + } + + } + + return( InterruptVector ); + +} + + +UCHAR +HalpAcknowledgeCorellePciInterrupt( + 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 pointer to the Noritake PCI interrupt register 1 QVA. + +Return Value: + + Return the value of the highest priority pending interrupt. + +--*/ +{ + + UCHAR InterruptVector = 0; + USHORT IrContents; + int i; + + // + // Interrupt register 1 contains the INTA and INTB interrupts. Bit 0 of + // the interrupt register contains the sum of all interrupts in interrupt + // register 2 which contains the INTC and INTD interrupts. The interrupts + // for the onboard SCSI (QLOGIC) and video (S3 TRIO 64) are also contained + // in interrupt register 1. All the signals in the interrupt registers are + // active low. + + // + // First, get and complement the first interrupt register, so that the + // pending interrupts will be the "1" bits. Then mask with the + // enabled mask, HalpCorellePciInterrupt1Mask; + // + + IrContents = + ~(0xffff & READ_PORT_USHORT((PUSHORT)HalpCorellePciIr1Qva)); + IrContents &= HalpCorellePciInterrupt1Mask; + + // + // We will check for interrupts by starting from bit 1 of interrupt + // register 1. We will stop at bit 10 since bit 11 is reserved and always + // 1 and bit 12 to 15 are server management related interrupts. + // + + IrContents >>= 1; + + for (i = 1; i < 11; i++) { + + if (IrContents & 0x1) { + + InterruptVector = i + CORELLE_INTERRUPT1_OFFSET; + break; + + } + + IrContents >>= 1; + + } + + if (InterruptVector == 0) { + + // + // Did not find any interrupts in interrupt register 1. Check interrupt + // register 2. + // + + IrContents = ~(0xffff & READ_PORT_USHORT((PUSHORT)HalpCorellePciIr2Qva)); + IrContents &= HalpCorellePciInterrupt2Mask; + + // + // We will start at bit 2 and stop at bit 9. The other bits are reserved + // and always 1. + // + + IrContents >>= 2; + + for (i = 2; i < 10; i++) { + + if (IrContents & 0x1) { + + InterruptVector = i + CORELLE_INTERRUPT2_OFFSET; + break; + + } + + IrContents >>= 1; + + } + + } + + return (InterruptVector); + +} + + + +VOID +HalpAcknowledgeClockInterrupt( + VOID + ) +/*++ + +Routine Description: + + Acknowledge the clock interrupt from the interval timer. The interval + timer for Mikasa comes from a Dallas real-time clock. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + + // + // Acknowledge the clock interrupt by reading the control register C of + // the Real Time Clock. + // + + HalpReadClockRegister( RTC_CONTROL_REGISTERC ); + + return; +} + diff --git a/private/ntos/nthals/halpinna/alpha/mkmapio.c b/private/ntos/nthals/halpinna/alpha/mkmapio.c new file mode 100644 index 000000000..717436b9e --- /dev/null +++ b/private/ntos/nthals/halpinna/alpha/mkmapio.c @@ -0,0 +1,240 @@ +/*++ + +Copyright (c) 1993 Digital Equipment Corporation + +Module Name: + + mkmapio.c + +Abstract: + + This module contains the functions to map HAL-accessed I/O addresses + on the Mikasa EV5 (Pinnacle) system. + +Author: + + Joe Notarangelo 25-Oct-1993 + +Environment: + + Kernel mode + +Revision History: + + Scott Lee 29-Nov-1995 + Adapted from Mikasa module for Mikasa EV5 (Pinnacle) systems. + +--*/ + +#include "halp.h" +#include "mikasa.h" + +// +// Define global data used to locate the EISA control space. +// + +PVOID HalpEisaControlBase; +PVOID HalpEisaIntAckBase; +PVOID HalpCMOSRamBase; +PVOID HalpServerControlQva; + +PVOID HalpMikasaPciIrQva; +PVOID HalpMikasaPciImrQva; + +PVOID HalpNoritakePciIr1Qva; +PVOID HalpNoritakePciIr2Qva; +PVOID HalpNoritakePciIr3Qva; +PVOID HalpNoritakePciImr1Qva; +PVOID HalpNoritakePciImr2Qva; +PVOID HalpNoritakePciImr3Qva; + +PVOID HalpCorellePciIr1Qva; +PVOID HalpCorellePciIr2Qva; +PVOID HalpCorellePciImr1Qva; +PVOID HalpCorellePciImr2Qva; + + + +BOOLEAN +HalpMapIoSpace ( + VOID + ) + +/*++ + +Routine Description: + + This routine maps the HAL I/O space for a Mikasa 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( CIA_PCI_SPARSE_IO_PHYSICAL ); + + HalpEisaControlBase = PciIoSpaceBase; + HalpEisaIntAckBase = HAL_MAKE_QVA( CIA_PCI_INTACK_PHYSICAL ); + + // + // Set up the Mikasa interrupt registers. + // + // Map PCI interrupt and interrupt mask registers. The former register + // receives the interrupt state of each individual pin in each PCI slot, + // the state of the NCR 53C810 interrupt, and two server management + // interrupts' states. The PCI interrupt mask register can mask each + // of the interrupts in the IR. + // + + HalpMikasaPciIrQva = (PVOID)((ULONG)PciIoSpaceBase + + PCI_INTERRUPT_REGISTER); + HalpMikasaPciImrQva = (PVOID)((ULONG)PciIoSpaceBase + + PCI_INTERRUPT_MASK_REGISTER); + + // + // Set up the Noritake interrupt registers. + // + // Map the PCI interrupt and interrupt mask registers for Noritake. + // There are three interrupt registers, and three mask registers. + // The exact contents are described in mikasa.h. + // + // The Base Address Register of the interrupt registers is set up in SROM. + // We can change this if we choose. + // + + HalpNoritakePciIr1Qva = (PVOID)((ULONG)PciIoSpaceBase + + PCI_INTERRUPT_REGISTER_1); + HalpNoritakePciImr1Qva = (PVOID)((ULONG)PciIoSpaceBase + + PCI_INTERRUPT_MASK_REGISTER_1); + + HalpNoritakePciIr2Qva = (PVOID)((ULONG)PciIoSpaceBase + + PCI_INTERRUPT_REGISTER_2); + HalpNoritakePciImr2Qva = (PVOID)((ULONG)PciIoSpaceBase + + PCI_INTERRUPT_MASK_REGISTER_2); + + HalpNoritakePciIr3Qva = (PVOID)((ULONG)PciIoSpaceBase + + PCI_INTERRUPT_REGISTER_3); + HalpNoritakePciImr3Qva = (PVOID)((ULONG)PciIoSpaceBase + + PCI_INTERRUPT_MASK_REGISTER_3); + + + // + // Set up the Corelle interrupt registers. + // + // Map the PCI interrupt and interrupt mask registers for Corelle. + // There are two interrupt registers, and two mask registers. The exact + // contents are described in mikasa.h. + // + + HalpCorellePciIr1Qva = (PVOID)((ULONG)PciIoSpaceBase + + PCI_INTERRUPT_REGISTER_1); + HalpCorellePciImr1Qva = (PVOID)((ULONG)PciIoSpaceBase + + PCI_INTERRUPT_MASK_REGISTER_1); + + HalpCorellePciIr2Qva = (PVOID)((ULONG)PciIoSpaceBase + + PCI_INTERRUPT_REGISTER_2); + HalpCorellePciImr2Qva = (PVOID)((ULONG)PciIoSpaceBase + + PCI_INTERRUPT_MASK_REGISTER_2); + + // + // Map the Mikasa server management register. This single byte register + // contains the bits that enable control of the high-availability options + // on Mikasa. This is at the same location in the Noritake, but it has a + // slightly different content. + // + + HalpServerControlQva = (PVOID)((ULONG)PciIoSpaceBase + + SERVER_MANAGEMENT_REGISTER); + // + // Map CMOS RAM address. + // + + HalpCMOSRamBase = (PVOID)((ULONG)PciIoSpaceBase + ESC_CMOS_ISA_PORT); + + // + // Map the real-time clock registers. + // + + HalpRtcAddressPort = (PVOID)((ULONG)PciIoSpaceBase + RTC_ISA_ADDRESS_PORT); + HalpRtcDataPort = (PVOID)((ULONG)PciIoSpaceBase + RTC_ISA_DATA_PORT); + + return TRUE; + +} + +ULONG +HalpMapDebugPort( + IN ULONG ComPort, + OUT PULONG ReadQva, + OUT PULONG WriteQva + ) +/*++ + +Routine Description: + + This routine maps the debug com port so that the kernel debugger + may function - if called it is called very earlier in the boot sequence. + +Arguments: + + ComPort - Supplies the number of the com port to use as the debug port. + + ReadQva - Receives the QVA used to access the read registers of the debug + port. + + WriteQva - Receives the QVA used to access the write registers of the + debug port. + +Return Value: + + Returns the base bus address of the device used as the debug port. + +--*/ +{ + ULONG ComPortAddress; + ULONG PortQva; + + // + // Compute the port address, based on the desired com port. + // + + switch( ComPort ){ + + case 1: + + ComPortAddress = COM1_ISA_PORT_ADDRESS; + break; + + case 2: + default: + + ComPortAddress = COM2_ISA_PORT_ADDRESS; + + } + + // + // Return the QVAs for read and write access. + // + + PortQva = (ULONG)HAL_MAKE_QVA(CIA_PCI_SPARSE_IO_PHYSICAL) + ComPortAddress; + + *ReadQva = PortQva; + *WriteQva = PortQva; + + return ComPortAddress; + +} diff --git a/private/ntos/nthals/halpinna/alpha/mksysint.c b/private/ntos/nthals/halpinna/alpha/mksysint.c new file mode 100644 index 000000000..51e7ba0a8 --- /dev/null +++ b/private/ntos/nthals/halpinna/alpha/mksysint.c @@ -0,0 +1,545 @@ +/*++ + +Copyright (c) 1993 Digital Equipment Corporation + +Module Name: + + mkinitnt.c + +Abstract: + + This module implements the HAL enable/disable system interrupt, and + request interprocessor interrupt routines for the Mikasa EV5 system. + +Author: + + Joe Notarangelo 25-Oct-1993 + +Environment: + + Kernel mode + +Revision History: + + Scott Lee 30-Nov-1995 + Adapted from Mikasa module for Mikasa EV5 (Pinnacle). + +--*/ + +#include "halp.h" +#include "mikasa.h" +#include "axp21164.h" + +// +// Function prototype +// + +VOID +HalpDisableMikasaPciInterrupt( + IN ULONG Vector + ); + +VOID +HalpDisableNoritakePciInterrupt( + IN ULONG Vector + ); + +VOID +HalpDisableCorellePciInterrupt( + IN ULONG Vector + ); + +VOID +HalpEnableMikasaPciInterrupt( + IN ULONG Vector, + IN KINTERRUPT_MODE InterruptMode + ); + +VOID +HalpEnableNoritakePciInterrupt( + IN ULONG Vector, + IN KINTERRUPT_MODE InterruptMode + ); + +VOID +HalpEnableCorellePciInterrupt( + IN ULONG Vector, + IN KINTERRUPT_MODE InterruptMode + ); + +VOID +HalpSetMachineCheckEnables( + IN BOOLEAN DisableMachineChecks, + IN BOOLEAN DisableProcessorCorrectables, + IN BOOLEAN DisableSystemCorrectables + ); + +// +// Define reference to the builtin device interrupt enables. +// +extern USHORT HalpBuiltinInterruptEnable; + +// +// Define reference to platform identifier +// + +extern BOOLEAN HalpNoritakePlatform; +extern BOOLEAN HalpCorellePlatform; + + +VOID +HalDisableSystemInterrupt ( + IN ULONG Vector, + IN KIRQL Irql + ) + +/*++ + +Routine Description: + + This routine disables the specified system interrupt. + +Arguments: + + Vector - Supplies the vector of the system interrupt that is disabled. + + Irql - Supplies the IRQL of the interrupting source. + +Return Value: + + None. + +--*/ + +{ + + KIRQL OldIrql; + + // + // Raise IRQL to the highest level. + // + + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + + // + // If the vector number is within the range of the EISA interrupts, then + // disable the EISA interrrupt. + // + + if (Vector >= EISA_VECTORS && + Vector < MAXIMUM_EISA_VECTOR && + Irql == DEVICE_HIGH_LEVEL) { + HalpDisableEisaInterrupt(Vector); + } + + // + // If the vector number is within the range of the PCI interrupts, then + // disable the PCI interrrupt. + // + + if (Vector >= PCI_VECTORS && + Vector < MAXIMUM_PCI_VECTOR && + Irql == DEVICE_HIGH_LEVEL) { + + if( HalpNoritakePlatform ) { + + HalpDisableNoritakePciInterrupt(Vector); + + } else if ( HalpCorellePlatform ) { + + HalpDisableCorellePciInterrupt(Vector); + + } else { + + HalpDisableMikasaPciInterrupt(Vector); + + } + + } + + // + // If the vector is a performance counter vector we will ignore + // the enable - the performance counters are enabled directly by + // the wrperfmon callpal. Wrperfmon must be controlled directly + // by the driver. + // + + switch (Vector) { + + case PC0_VECTOR: + case PC1_VECTOR: + case PC2_VECTOR: + + break; + + case CORRECTABLE_VECTOR: + + // + // Disable the correctable error interrupt. + // + + { + CIA_ERR_MASK CiaErrMask; + + CiaErrMask.all = READ_CIA_REGISTER( + &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->ErrMask); + + CiaErrMask.CorErr = 0x0; + + WRITE_CIA_REGISTER(&((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->ErrMask, + CiaErrMask.all + ); + + HalpSetMachineCheckEnables( FALSE, TRUE, TRUE ); + } + + break; + + } //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; + KIRQL OldIrql; + + // + // Raise IRQL to the highest level. + // + + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + + // + // If the vector number is within the range of the EISA interrupts, then + // enable the EISA interrrupt and set the Level/Edge register. + // + + if (Vector >= EISA_VECTORS && + Vector < MAXIMUM_EISA_VECTOR && + Irql == DEVICE_HIGH_LEVEL) { + HalpEnableEisaInterrupt( Vector, InterruptMode ); + Enabled = TRUE; + } + + // + // If the vector number is within the range of the PCI interrupts, then + // enable the PCI interrrupt. + // + + if (Vector >= PCI_VECTORS && + Vector < MAXIMUM_PCI_VECTOR && + Irql == DEVICE_HIGH_LEVEL) { + + if( HalpNoritakePlatform ) { + + HalpEnableNoritakePciInterrupt( Vector, InterruptMode ); + + } else if ( HalpCorellePlatform ) { + + HalpEnableCorellePciInterrupt( Vector, InterruptMode ); + + } else { + + HalpEnableMikasaPciInterrupt( Vector, InterruptMode ); + + } + + Enabled = TRUE; + } + + // + // If the vector is a performance counter vector we will ignore + // the enable - the performance counters are enabled directly by + // the wrperfmon callpal. Wrperfmon must be controlled directly + // by the driver. + // + + switch (Vector) { + + case PC0_VECTOR: + case PC1_VECTOR: + case PC2_VECTOR: + + Enabled = TRUE; + break; + + case CORRECTABLE_VECTOR: + + // + // Enable the correctable error interrupt. + // + + { + CIA_ERR_MASK CiaErrMask; + + CiaErrMask.all = READ_CIA_REGISTER( + &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->ErrMask); + + CiaErrMask.CorErr = 0x1; + + WRITE_CIA_REGISTER(&((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->ErrMask, + CiaErrMask.all + ); + + HalpSetMachineCheckEnables( FALSE, FALSE, FALSE ); + } + + Enabled = TRUE; + break; + + } //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 EISA and ISA are the same as the InterruptLevel, so ignore. + +jwlfix - How does the above apply to PCI when it's done as in Mikasa? I've + made the assumption the the same is true, but that must be checked. + +Arguments: + + BusHandler - Registered BUSHANDLER for the target configuration space + + RootHandler - Registered BUSHANDLER for the orginating HalGetBusData + request. + + BusInterruptLevel - Supplies the bus-specific interrupt level. + + BusInterruptVector - Supplies the bus-specific interrupt vector. + + Irql - Returns the system request priority. + + Affinity - Returns the affinity for the requested vector + +Return Value: + + Returns the system interrupt vector corresponding to the specified device. + +--*/ + +{ + INTERFACE_TYPE InterfaceType = BusHandler->InterfaceType; + ULONG BusNumber = BusHandler->BusNumber; + + ULONG Vector; + + *Affinity = 1; + + switch (InterfaceType) { + + case ProcessorInternal: + + // + // Handle the internal defined for the processor itself + // and used to control the performance counters in the 21164. + // + + if( (Vector = HalpGet21164PerformanceVector( BusInterruptLevel, + Irql)) != 0 ){ + + // + // Performance counter was successfully recognized. + // + + *Affinity = HalpActiveProcessors; + return Vector; + + } else if ((Vector = HalpGet21164CorrectableVector( BusInterruptLevel, + Irql)) != 0 ){ + + // + // Correctable error interrupt was sucessfully recognized. + // + + *Affinity = 1; + return Vector; + + } else { + + // + // Unrecognized processor interrupt. + // + + *Irql = 0; + *Affinity = 0; + return 0; + + } //end if Vector + + break; + + 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. + // + + *Irql = DEVICE_HIGH_LEVEL; + + return(BusInterruptLevel + ISA_VECTORS); + break; + + case Isa: + + // + // Assumes all ISA devices coming in on same processor pin + // + + *Irql = DEVICE_HIGH_LEVEL; + + // + // The vector is equal to the specified bus level plus ISA_VECTORS. + // N.B.: this encoding technique uses the notion of defining a + // base interrupt vector in the space defined by the constant, + // ISA_VECTORS, which may or may not differ from EISA_VECTORS or + // PCI_VECTORS. + // + + return(BusInterruptLevel + ISA_VECTORS); + break; + + + case Eisa: + + // + // Assumes all EISA devices coming in on same processor pin + // + + *Irql = DEVICE_HIGH_LEVEL; + + // + // The vector is equal to the specified bus level plus the EISA_VECTOR. + // + + return(BusInterruptLevel + EISA_VECTORS); + break; + + case PCIBus: + + // + // Assumes all PCI devices coming in on same processor pin + // + + *Irql = DEVICE_HIGH_LEVEL; + + // + // The vector is equal to the specified bus level plus the PCI_VECTOR + // + + return(BusInterruptLevel + PCI_VECTORS); + + break; + + default: + + // + // Not an interface supported on Mikasa systems. + // +#if defined(HALDBG) + DbgPrint("MKSYSINT: InterfaceType (%d) not supported on Mikasa\r\n", + InterfaceType); +#endif + + *Irql = 0; + *Affinity = 0; + return(0); + break; + + } //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 Mikasa 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/halpinna/alpha/nvenv.c b/private/ntos/nthals/halpinna/alpha/nvenv.c new file mode 100644 index 000000000..ba5a5c8f7 --- /dev/null +++ b/private/ntos/nthals/halpinna/alpha/nvenv.c @@ -0,0 +1 @@ +#include "..\halalpha\nvenv.c" diff --git a/private/ntos/nthals/halpinna/alpha/nvram.c b/private/ntos/nthals/halpinna/alpha/nvram.c new file mode 100644 index 000000000..879c41c68 --- /dev/null +++ b/private/ntos/nthals/halpinna/alpha/nvram.c @@ -0,0 +1 @@ +#include "..\halalpha\nvram.c" diff --git a/private/ntos/nthals/halpinna/alpha/pcibus.c b/private/ntos/nthals/halpinna/alpha/pcibus.c new file mode 100644 index 000000000..60bff018e --- /dev/null +++ b/private/ntos/nthals/halpinna/alpha/pcibus.c @@ -0,0 +1,100 @@ +/*++ + +Copyright (c) 1993 Microsoft Corporation, Digital Equipment Corporation + + +Module Name: + + pcibus.c + +Abstract: + + Platform-specific PCI bus routines + +Author: + +Environment: + + Kernel mode + +Revision History: + + 29-Nov-1995 Scott Lee + Adapted from Mikasa module for Mikasa EV5 (Pinnacle). + +--*/ + +#include "halp.h" +#include "pci.h" +#include "pcip.h" +#include "machdep.h" + +// +// Reference variable that defines largest PCI bus number. +// +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 + // + // 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) CIA_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) CIA_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/halpinna/alpha/pciesc.c b/private/ntos/nthals/halpinna/alpha/pciesc.c new file mode 100644 index 000000000..49142ea83 --- /dev/null +++ b/private/ntos/nthals/halpinna/alpha/pciesc.c @@ -0,0 +1,7 @@ +// +// This file simply includes the source file from the common Alpha +// HAL directory. +// + +#include "..\halalpha\pciesc.c" + diff --git a/private/ntos/nthals/halpinna/alpha/pciir.c b/private/ntos/nthals/halpinna/alpha/pciir.c new file mode 100644 index 000000000..10c9e3af6 --- /dev/null +++ b/private/ntos/nthals/halpinna/alpha/pciir.c @@ -0,0 +1,703 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation +Copyright (c) 1992, 1993, 1994 Digital Equipment Corporation + +Module Name: + + pciir.c + +Abstract: + + The module provides the interrupt support for the Mikasa's PCI + interrupts. + +Author: + + James Livingston 2-May-1994 + +Revision History: + + Janet Schneider (Digital) 27-July-1995 + Added support for the Noritake. + +--*/ + +#include "halp.h" + +// +// Define external function prototypes +// + +UCHAR +HalpAcknowledgeMikasaPciInterrupt( + PVOID ServiceContext + ); + +UCHAR +HalpAcknowledgeNoritakePciInterrupt( + PVOID ServiceContext + ); + +UCHAR +HalpAcknowledgeCorellePciInterrupt( + PVOID ServiceContext + ); + +// +// Import save area for PCI interrupt mask register. +// + +USHORT HalpMikasaPciInterruptMask; + +USHORT HalpNoritakePciInterrupt1Mask; +USHORT HalpNoritakePciInterrupt2Mask; +USHORT HalpNoritakePciInterrupt3Mask; + +USHORT HalpCorellePciInterrupt1Mask; +USHORT HalpCorellePciInterrupt2Mask; + +// +// Reference for globals defined in I/O mapping module. +// +extern PVOID HalpMikasaPciIrQva; +extern PVOID HalpMikasaPciImrQva; + +extern PVOID HalpNoritakePciIr1Qva; +extern PVOID HalpNoritakePciIr2Qva; +extern PVOID HalpNoritakePciIr3Qva; +extern PVOID HalpNoritakePciImr1Qva; +extern PVOID HalpNoritakePciImr2Qva; +extern PVOID HalpNoritakePciImr3Qva; + +extern PVOID HalpCorellePciIr1Qva; +extern PVOID HalpCorellePciIr2Qva; +extern PVOID HalpCorellePciImr1Qva; +extern PVOID HalpCorellePciImr2Qva; + +// +// Define reference to platform identifier +// + +extern BOOLEAN HalpNoritakePlatform; +extern BOOLEAN HalpCorellePlatform; + + +VOID +HalpInitializeMikasaPciInterrupts( + VOID + ) + +/*++ + +Routine Description: + + This routine initializes the Mikasa PCI interrupts. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + + // + // Initialize the Mikasa PCI interrupts. There is a single interrupt mask + // that permits individual interrupts to be enabled or disabled by + // setting the appropriate bit in the interrupt mask register. We + // initialize them all to "disabled". + // + + HalpMikasaPciInterruptMask = 0; + WRITE_PORT_USHORT( (PUSHORT)HalpMikasaPciImrQva, + HalpMikasaPciInterruptMask ); + +} + + +VOID +HalpInitializeNoritakePciInterrupts( + VOID + ) + +/*++ + +Routine Description: + + This routine initializes the Noritake PCI interrupts. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + + // + // Initialize the Noritake PCI interrupts. There are three interrupt masks + // that permit individual interrupts to be enabled or disabled by + // setting the appropriate bit in the interrupt mask register. We + // initialize them all to "disabled", except for the SUM bits. (Bit 0 + // in IR1, and bits 0 and 1 in IR2.) + // + + HalpNoritakePciInterrupt1Mask = 0x1; + WRITE_PORT_USHORT( (PUSHORT)HalpNoritakePciImr1Qva, + HalpNoritakePciInterrupt1Mask ); + + HalpNoritakePciInterrupt2Mask = 0x3; + WRITE_PORT_USHORT( (PUSHORT)HalpNoritakePciImr2Qva, + HalpNoritakePciInterrupt2Mask ); + + HalpNoritakePciInterrupt3Mask = 0x0; + WRITE_PORT_USHORT( (PUSHORT)HalpNoritakePciImr3Qva, + HalpNoritakePciInterrupt3Mask ); + +} + + +VOID +HalpInitializeCorellePciInterrupts( + VOID + ) + +/*++ + +Routine Description: + + This routine initializes the Corelle PCI interrupts. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + + // + // Initialize the Corelle PCI interrupts. There are 2 interrupt masks + // that permits individual interrupts to be enabled or disabled by + // setting the appropriate bit in the interrupt mask register. We will + // initialize them all to "disabled" except bit 0 of interrupt register 1 + // which is the sum of all interrupts in interrupt register 2. + // + + HalpCorellePciInterrupt1Mask = 0x1; + WRITE_PORT_USHORT( (PUSHORT)HalpCorellePciImr1Qva, + HalpCorellePciInterrupt1Mask ); + + HalpCorellePciInterrupt2Mask = 0x0; + WRITE_PORT_USHORT( (PUSHORT)HalpCorellePciImr2Qva, + HalpCorellePciInterrupt2Mask ); + +} + + +VOID +HalpDisableMikasaPciInterrupt( + IN ULONG Vector + ) + +/*++ + +Routine Description: + + This function disables the PCI interrupt specified by Vector. + +Arguments: + + Vector - Supplies the vector of the PCI interrupt that is disabled. + +Return Value: + + None. + +--*/ + +{ + + // + // Calculate the PCI interrupt vector, relative to 0, offset by one. + // + + Vector -= PCI_VECTORS + 1; + + // + // Get the current state of the interrupt mask register, then set + // the bit corresponding to the adjusted value of Vector to zero, + // to disable that PCI interrupt. + // + + HalpMikasaPciInterruptMask = + READ_PORT_USHORT( (PUSHORT)HalpMikasaPciImrQva ); + HalpMikasaPciInterruptMask &= (USHORT) ~(1 << Vector); + WRITE_PORT_USHORT( (PUSHORT)HalpMikasaPciImrQva, + HalpMikasaPciInterruptMask ); + +} + + +VOID +HalpDisableNoritakePciInterrupt( + IN ULONG Vector + ) + +/*++ + +Routine Description: + + This function disables the PCI interrupt specified by Vector. + +Arguments: + + Vector - Supplies the vector of the PCI interrupt that is disabled. + +Return Value: + + None. + +--*/ + +{ + // + // Calculate the PCI interrupt vector, relative to 0. + // + + Vector -= PCI_VECTORS; + + // + // First we must determine which interrupt register the interrupt is in. + // In each case, subtract the register offset to get the bit position in + // the interrupt register. Then, get the current state of the interrupt + // mask register. Finally, set the bit corresponding to the adjusted value + // of Vector to zero, to disable that PCI interrupt. + // + + if( Vector >= REGISTER_2_VECTOR_OFFSET ) { + + if( Vector >= REGISTER_3_VECTOR_OFFSET ) { + + // + // The interrupt is in Interrupt Register 3. + // + + Vector -= REGISTER_3_VECTOR_OFFSET; + + HalpNoritakePciInterrupt3Mask = READ_PORT_USHORT( + (PUSHORT)HalpNoritakePciImr3Qva ); + HalpNoritakePciInterrupt3Mask &= (USHORT) ~(1 << Vector); + WRITE_PORT_USHORT( (PUSHORT)HalpNoritakePciImr3Qva, + HalpNoritakePciInterrupt3Mask ); + + } else { + + // + // The interrupt is in Interrupt Register 2. + // + + Vector -= REGISTER_2_VECTOR_OFFSET; + + HalpNoritakePciInterrupt2Mask = READ_PORT_USHORT( + (PUSHORT)HalpNoritakePciImr2Qva ); + HalpNoritakePciInterrupt2Mask &= (USHORT) ~(1 << Vector); + WRITE_PORT_USHORT( (PUSHORT)HalpNoritakePciImr2Qva, + HalpNoritakePciInterrupt2Mask ); + + } + + } else { + + // + // The interrupt is in Interrupt Register 1. + // + + Vector -= REGISTER_1_VECTOR_OFFSET; + + HalpNoritakePciInterrupt1Mask = + READ_PORT_USHORT( (PUSHORT)HalpNoritakePciImr1Qva ); + HalpNoritakePciInterrupt1Mask &= (USHORT) ~(1 << Vector); + WRITE_PORT_USHORT( (PUSHORT)HalpNoritakePciImr1Qva, + HalpNoritakePciInterrupt1Mask ); + + } + +} + + +VOID +HalpDisableCorellePciInterrupt( + IN ULONG Vector + ) + +/*++ + +Routine Description: + + This function disables the PCI interrupt specified by Vector. + +Arguments: + + Vector - Supplies the vector of the PCI interrupt that is disabled. + +Return Value: + + None. + +--*/ + +{ + + // + // Calculate the PCI interrupt vector, relative to 0. + // + + Vector -= PCI_VECTORS; + + // + // First we must determine which interrupt register the interrupt is in. + // Then, get the current state of the interrupt mask register. Finally, + // set the bit corresponding to the adjusted value of Vector to zero, to + // disable that PCI interrupt. + // + + if ( Vector >= CORELLE_INTERRUPT2_OFFSET ) { + + // + // The interrupt is in interrupt register 2 + // + + Vector -= CORELLE_INTERRUPT2_OFFSET; + + HalpCorellePciInterrupt2Mask = + READ_PORT_USHORT((PUSHORT)HalpCorellePciImr2Qva ); + HalpCorellePciInterrupt2Mask &= (USHORT) ~(1 << Vector); + WRITE_PORT_USHORT( (PUSHORT)HalpCorellePciImr2Qva, + HalpCorellePciInterrupt2Mask ); + + } else { + + // + // The interrupt is in interrupt register 1 + // + + Vector -= CORELLE_INTERRUPT1_OFFSET; + + HalpCorellePciInterrupt1Mask = + READ_PORT_USHORT( (PUSHORT)HalpCorellePciImr1Qva ); + HalpCorellePciInterrupt1Mask &= (USHORT) ~(1 << Vector); + WRITE_PORT_USHORT( (PUSHORT)HalpCorellePciImr1Qva, + HalpCorellePciInterrupt1Mask ); + + } + +} + + +VOID +HalpEnableMikasaPciInterrupt( + 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 Mikasa PCI interrupts; they're always levels). + +Return Value: + + None. + +--*/ + +{ + + // + // Calculate the PCI interrupt vector, relative to 0, offset by one. + // + + Vector -= PCI_VECTORS + 1; + + // + // Get the current state of the interrupt mask register, then set + // the bit corresponding to the adjusted value of Vector to one, + // to enable that PCI interrupt. + // + + HalpMikasaPciInterruptMask = + READ_PORT_USHORT( (PUSHORT)HalpMikasaPciImrQva ); + HalpMikasaPciInterruptMask |= (USHORT) (1 << Vector); + WRITE_PORT_USHORT( (PUSHORT)HalpMikasaPciImrQva, + HalpMikasaPciInterruptMask ); + +} + + +VOID +HalpEnableNoritakePciInterrupt( + 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 Mikasa PCI interrupts; they're always levels). + +Return Value: + + None. + +--*/ + +{ + + // + // Calculate the PCI interrupt vector, relative to 0. + // + + Vector -= PCI_VECTORS; + + // + // First we must determine which interrupt register the interrupt is in. + // In each case, subtract the register offset to get the bit position in + // the interrupt register. Then, get the current state of the interrupt + // mask register. Finally, set the bit corresponding to the adjusted value + // of Vector to one, to enable that PCI interrupt. + // + + if( Vector >= REGISTER_2_VECTOR_OFFSET ) { + + if( Vector >= REGISTER_3_VECTOR_OFFSET ) { + + // + // The interrupt is in Interrupt Register 3. + // + + Vector -= REGISTER_3_VECTOR_OFFSET; + + HalpNoritakePciInterrupt3Mask = READ_PORT_USHORT( + (PUSHORT)HalpNoritakePciImr3Qva ); + HalpNoritakePciInterrupt3Mask |= (USHORT) (1 << Vector); + WRITE_PORT_USHORT( (PUSHORT)HalpNoritakePciImr3Qva, + HalpNoritakePciInterrupt3Mask ); + + } else { + + // + // The interrupt is in Interrupt Register 2. + // + + Vector -= REGISTER_2_VECTOR_OFFSET; + + HalpNoritakePciInterrupt2Mask = READ_PORT_USHORT( + (PUSHORT)HalpNoritakePciImr2Qva ); + HalpNoritakePciInterrupt2Mask |= (USHORT) (1 << Vector); + WRITE_PORT_USHORT( (PUSHORT)HalpNoritakePciImr2Qva, + HalpNoritakePciInterrupt2Mask ); + + } + + } else { + + // + // The interrupt is in Interrupt Register 1. + // + + Vector -= REGISTER_1_VECTOR_OFFSET; + + HalpNoritakePciInterrupt1Mask = + READ_PORT_USHORT( (PUSHORT)HalpNoritakePciImr1Qva ); + HalpNoritakePciInterrupt1Mask |= (USHORT) (1 << Vector); + WRITE_PORT_USHORT( (PUSHORT)HalpNoritakePciImr1Qva, + HalpNoritakePciInterrupt1Mask ); + + } + +} + + +VOID +HalpEnableCorellePciInterrupt( + 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 Mikasa PCI interrupts; they're always levels). + +Return Value: + + None. + +--*/ + +{ + + // + // Calculate the PCI interrupt vector, relative to 0. + // + + Vector -= PCI_VECTORS; + + // + // First we must determine which interrupt register the interrupt is in. + // Then, get the current state of the interrupt mask register. Finally, + // set the bit corresponding to the adjusted value of Vector to zero, to + // disable that PCI interrupt. + // + + if ( Vector >= CORELLE_INTERRUPT2_OFFSET ) { + + // + // The interrupt is in interrupt register 2 + // + + Vector -= CORELLE_INTERRUPT2_OFFSET; + + HalpCorellePciInterrupt2Mask = + READ_PORT_USHORT((PUSHORT)HalpCorellePciImr2Qva ); + HalpCorellePciInterrupt2Mask |= (USHORT) (1 << Vector); + WRITE_PORT_USHORT( (PUSHORT)HalpCorellePciImr2Qva, + HalpCorellePciInterrupt2Mask ); + + } else { + + // + // The interrupt is in interrupt register 1 + // + + Vector -= CORELLE_INTERRUPT1_OFFSET; + + HalpCorellePciInterrupt1Mask = + READ_PORT_USHORT( (PUSHORT)HalpCorellePciImr1Qva ); + HalpCorellePciInterrupt1Mask |= (USHORT) (1 << Vector); + WRITE_PORT_USHORT( (PUSHORT)HalpCorellePciImr1Qva, + HalpCorellePciInterrupt1Mask ); + + } + +} + + +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; + + // + // Acknowledge interrupt and receive the returned interrupt vector. + // If we got zero back, there were no enabled interrupts, so we + // signal that with a FALSE return, immediately. + // + + if( HalpNoritakePlatform ) { + + PCIVector = HalpAcknowledgeNoritakePciInterrupt(ServiceContext); + + } else if ( HalpCorellePlatform ) { + + PCIVector = HalpAcknowledgeCorellePciInterrupt(ServiceContext); + + } else { + + PCIVector = HalpAcknowledgeMikasaPciInterrupt(ServiceContext); + + } + + if (PCIVector == 0) { + return( FALSE ); + } + + PCRInOffset = PCIVector + PCI_VECTORS; + + returnValue = ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[PCRInOffset])( + PCR->InterruptRoutine[PCRInOffset], + TrapFrame + ); + + return( returnValue ); +} + + + + diff --git a/private/ntos/nthals/halpinna/alpha/pcisup.c b/private/ntos/nthals/halpinna/alpha/pcisup.c new file mode 100644 index 000000000..360919f42 --- /dev/null +++ b/private/ntos/nthals/halpinna/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/halpinna/alpha/pcrtc.c b/private/ntos/nthals/halpinna/alpha/pcrtc.c new file mode 100644 index 000000000..2e57b87d6 --- /dev/null +++ b/private/ntos/nthals/halpinna/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/halpinna/alpha/pcserial.c b/private/ntos/nthals/halpinna/alpha/pcserial.c new file mode 100644 index 000000000..a2f159c48 --- /dev/null +++ b/private/ntos/nthals/halpinna/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/halpinna/alpha/pcspeakr.c b/private/ntos/nthals/halpinna/alpha/pcspeakr.c new file mode 100644 index 000000000..807b6f324 --- /dev/null +++ b/private/ntos/nthals/halpinna/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/halpinna/alpha/perfcntr.c b/private/ntos/nthals/halpinna/alpha/perfcntr.c new file mode 100644 index 000000000..6c0a8f892 --- /dev/null +++ b/private/ntos/nthals/halpinna/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/halpinna/alpha/pinnaerr.c b/private/ntos/nthals/halpinna/alpha/pinnaerr.c new file mode 100644 index 000000000..1e581ff82 --- /dev/null +++ b/private/ntos/nthals/halpinna/alpha/pinnaerr.c @@ -0,0 +1,157 @@ +/*++ + +Copyright (c) 1994 Digital Equipment Corporation + +Module Name: + + alcorerr.c + +Abstract: + + This module implements error handling (machine checks and error + interrupts) for the Mikasa EV5 (Pinnacle) platform. + +Author: + + Joe Notarangelo 27-Jul-1994 + +Environment: + + Kernel mode only. + +Revision History: + + Scott Lee 30-Nov-1995 + + Adapted from Alcor module for Mikasa EV5 (Pinnacle). + +--*/ + +#include "halp.h" +#include "mikasa.h" + +// +// Declare the extern variable UncorrectableError declared in +// inithal.c. +// +extern PERROR_FRAME PUncorrectableError; + +// +// Function prototypes. +// + +VOID +HalpSetMachineCheckEnables( + IN BOOLEAN DisableMachineChecks, + IN BOOLEAN DisableProcessorCorrectables, + IN BOOLEAN DisableSystemCorrectables + ); + +BOOLEAN +HalHandleNMI( + IN PKINTERRUPT Interrupt, + IN PVOID ServiceContext + ); + + +VOID +HalpPinnacleErrorInterrupt( + VOID + ) +/*++ + +Routine Description: + + This routine is the interrupt handler for a PINNACLE machine check interrupt + The function calls HalpCiaReportFatalError() + +Arguments: + + None. + +Return Value: + + None. If a Fatal Error is detected the system is crashed. + +--*/ +{ + + HalAcquireDisplayOwnership(NULL); + + // + // Display the dreaded banner. + // + + HalDisplayString( "\nFatal system hardware error.\n\n" ); + + // + // If this is a CIA uncorrectable error then report the error and + // crash the system. + // + + if( HalpCiaUncorrectableError() == TRUE ){ + + HalpCiaReportFatalError(); + + KeBugCheckEx( DATA_BUS_ERROR, + 0xfacefeed, //jnfix - quick error interrupt id + 0, + 0, + (ULONG) PUncorrectableError ); + + } + + // + // It was not a CIA uncorrectable error, therefore this must be an + // NMI interrupt. + // + + HalHandleNMI( NULL, NULL ); + + return; // never + +} + + +BOOLEAN +HalpPlatformMachineCheck( + IN PEXCEPTION_RECORD ExceptionRecord, + IN PKEXCEPTION_FRAME ExceptionFrame, + IN PKTRAP_FRAME TrapFrame + ) +/*++ + +Routine Description: + + This routine is given control when an hard error is acknowledged + by the CIA chipset. The routine is given the chance to + correct and dismiss the error. + +Arguments: + + ExceptionRecord - Supplies a pointer to the exception record generated + at the point of the exception. + + ExceptionFrame - Supplies a pointer to the exception frame generated + at the point of the exception. + + TrapFrame - Supplies a pointer to the trap frame generated + at the point of the exception. + +Return Value: + + TRUE is returned if the machine check has been handled and dismissed - + indicating that execution can continue. FALSE is return otherwise. + +--*/ +{ + + // + // All machine check handling on Alcor is determined by the CIA. + // + + return( HalpCiaMachineCheck( ExceptionRecord, + ExceptionFrame, + TrapFrame ) ); + +} diff --git a/private/ntos/nthals/halpinna/alpha/pintolin.h b/private/ntos/nthals/halpinna/alpha/pintolin.h new file mode 100644 index 000000000..38e016f36 --- /dev/null +++ b/private/ntos/nthals/halpinna/alpha/pintolin.h @@ -0,0 +1,251 @@ +/*++ + +Copyright (c) 1993 Microsoft Corporation +Copyright (c) 1994 Digital Equipment Corporation + +Module Name: + + pintolin.h + +Abstract: + + This file includes the platform-dependent Pin To Line Table + for Mikasa. + +Author: + +Environment: + + Kernel mode + +Revision History: + + James Livingston (Digital) 10-May-1994 + Extracted Mikasa-specific table from the combined table + of pin-to-line assignments. + + Janet Schneider (Digital) 27-July-1995 + Added support for the Noritake. + + Scott Lee (Digital) 15-July-1996 + Added support for Corelle. + +--*/ + +// +// This table represents the mapping from slot number and interrupt pin +// into a PCI Interrupt Vector. +// +// On platforms that use an interrupt register or registers instead of, +// or in addition to cascaded 85c59s, the Interrupt Vector is one greater +// than the Interrupt Request Register bit, because interrupt vectors +// can't be zero, and bits in a register are numbered from zero. On +// Mikasa, the Interrupt Vector also represents the Interrupt Mask +// Register bit, since the arrangement of its bits is identical to +// that of the Interrupt Read Register. +// +// Formally, these mappings can be expressed as: +// +// PCIPinToLine: +// (SlotNumber.DeviceNumber, InterruptPin) -> InterruptLine +// +// LineToVector: +// InterruptLine -> InterruptVector +// +// VectorToIRRBit: +// InterruptVector -> InterruptRequestRegisterBit + 1 +// +// VectorToIMRBit: +// InterruptVector -> InterruptMaskRegisterBit + 1 +// +// SlotNumberToIDSEL: +// SlotNumber.DeviceNumber -> IDSEL +// +// subject to: +// +// 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 for lookup function is initialized below) +// +// LineToVector(InterruptLine) = PCI_VECTORS + InterruptLine +// +// VectorToIRRBit(InterruptVector) = InterruptVector - 1 +// +// VectorToIMRBit(InterruptVector) [see below] +// +// SlotNumberToIDSEL(SlotNumber.DeviceNumber) = (Slot.DeviceNumber + 11) +// +// where: +// +// SlotNumber.DeviceNumber: +// Alpha AXP Platforms receive interrupts on local PCI buses only, which +// are limited to 16 devices (PCI AD[11]-AD[26]). +// +// InterruptPin: +// Each virtual slot has up to four interrupt pins INTA#, INTB#, INTC#, +// INTD#, per the PCI Spec. V2.0, Section 2.2.6. Devices having one +// interrupt use INTA#; only multifunction devices use INTB#, INTC#, +// INTD#.) +// +// PCI configuration space indicates which interrupt pin a device will use +// in the InterruptPin register, which can have 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. 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 from "downstream" PCI +// slots must somehow be combined to appear on some combination of the +// four interrupt pins belonging to the bridge's slot. +// +// InterruptLine: +// This PCI Configuration register is maintained by software, and holds +// an offset into PCI interrupt vectors. Whenever HalGetBusData or +// HalGetBusDataByOffset is called, HalpPCIPinToLine() computes the +// correct InterruptLine register value by using the mapping in +// HalpPCIPinToLineTable. +// +// InterruptRequestRegisterBit: +// In the table, 0xff is used to mark an invalid cell; this cell cannot +// be used to produce an interrupt request register bit. +// +// InterruptMaskRegisterBit: +// On Mikasa, the pin-to-line table may also be used to write the +// InterruptMaskRegister, via +// +// VectorToIMRBit(InterrruptVector) = InterruptVector - 1 +// +// IDSEL: +// For accessing PCI configuration space on a local PCI bus (as opposed +// to over a PCI-PCI bridge), type 0 configuration cycles must be generated. +// In this case, the IDSEL pin of the device to be accessed is tied to one +// of the PCI Address lines AD[11] - AD[26]. (The function field in the +// PCI address is used, should we be accessing a multifunction device.) +// Virtual slot 0 represents the device with IDSEL = AD[11], and so on. +// +// +// Interrupt Vector Table Mapping for Mikasa. +// +// Mikasa PCI interrupts are mapped to interrupt vectors in the table +// below. The values are a 1-1 map of the bit numbers in the Mikasa +// PCI interrupt register that are connected to PCI devices. +// +// N.B.: there are two other interrupts in the Mikasa IRR/IMR, but they +// are not connected to I/O devices, and have no associated PCI virtual +// slot, so they're not represented in the table. Entries in the table +// are interrupt vector values for the device having the given virtual +// slot and pin number. +// +// Limit init table to 15 entries, which is the +// MAX_PCI_LOCAL_DEVICES_MIKASA. +// +// We won't ever try to set an InterruptLine register of a slot +// greater than Virtual slot 15 = PCI_AD[25]. +// + +PULONG HalpPCIPinToLineTable; + +ULONG MikasaPCIPinToLineTable[][4]= +{ +// Pin 1 Pin 2 Pin 3 Pin 4 +// ----- ----- ----- ----- + { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 0 = PCI_AD[11] + { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 1 = PCI_AD[12] + { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 2 = PCI_AD[13] + { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 3 = PCI_AD[14] + { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 4 = PCI_AD[15] + { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 5 = PCI_AD[16] + { 0xd, 0xff, 0xff, 0xff }, // Virtual Slot 6 = PCI_AD[17] SCSI + { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 7 = PCI_AD[18] ESC + { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 8 = PCI_AD[19] + { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 9 = PCI_AD[20] + { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 10 = PCI_AD[21] + { 0x1, 0x2, 0x3, 0x4 }, // Virtual Slot 11 = PCI_AD[22] Slot #0 + { 0x5, 0x6, 0x7, 0x8 }, // Virtual Slot 12 = PCI_AD[23] Slot #1 + { 0x9, 0xa, 0xb, 0xc }, // Virtual Slot 13 = PCI_AD[24] Slot #2 + { 0xff, 0xff, 0xff, 0xff } // Virtual Slot 14 = PCI_AD[25] +}; + + +// +// Limit init table to 15 entries, which is the MAX_PCI_LOCAL_DEVICES_MIKASA. +// (It is same for Noritake.) +// +// We won't ever try to set an InterruptLine register of a slot +// greater than Virtual slot 14 = PCI_AD[25] on bus 0. +// +// Noritake PCI interrupts will be no lower than 0x11 so that they are disjoint +// from EISA levels. +// + +ULONG NoritakePCIPinToLineTable0[][4]= +{ +// Pin 1 Pin 2 Pin 3 Pin 4 +// ----- ----- ----- ----- + { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 0 = PCI_AD[11] + { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 1 = PCI_AD[12] + { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 2 = PCI_AD[13] + { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 3 = PCI_AD[14] + { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 4 = PCI_AD[15] + { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 5 = PCI_AD[16] + { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 6 = PCI_AD[17] + { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 7 = PCI_AD[18] PCEB + { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 8 = PCI_AD[19] PCI-PCI Bridge + { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 9 = PCI_AD[20] + { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 10 = PCI_AD[21] + { 0x13, 0x14, 0x23, 0x24 }, // Virtual Slot 11 = PCI_AD[22] Slot 0 + { 0x15, 0x16, 0x25, 0x26 }, // Virtual Slot 12 = PCI_AD[23] Slot 1 + { 0x17, 0x18, 0x27, 0x28 }, // Virtual Slot 13 = PCI_AD[24] Slot 2 + { 0xff, 0xff, 0xff, 0xff } // Virtual Slot 14 = PCI_AD[25] +}; + + +ULONG NoritakePCIPinToLineTable1[][4]= +{ +// Pin 1 Pin 2 Pin 3 Pin 4 +// ----- ----- ----- ----- + { 0x12, 0xff, 0xff, 0xff }, // Virtual Slot 0 = PCI_AD[16] QLogic + { 0x19, 0x1a, 0x29, 0x2a }, // Virtual Slot 1 = PCI_AD[17] Slot 3 + { 0x1b, 0x1c, 0x2b, 0x2c }, // Virtual Slot 2 = PCI_AD[18] Slot 4 + { 0x1d, 0x1e, 0x2d, 0x2e }, // Virtual Slot 3 = PCI_AD[19] Slot 5 + { 0x1f, 0x20, 0x2f, 0x30 } // Virtual Slot 4 = PCI_AD[20] Slot 6 +}; + +// +// Define the pintolin table for Corelle. +// + +ULONG CorellePCIPinToLineTable[][4]= +{ +// Pin 1 Pin 2 Pin 3 Pin 4 +// ----- ----- ----- ----- + { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 0 = PCI_AD[11] + { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 1 = PCI_AD[12] + { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 2 = PCI_AD[13] + { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 3 = PCI_AD[14] + { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 4 = PCI_AD[15] + { 0x11, 0xff, 0xff, 0xff }, // Virtual Slot 5 = PCI_AD[16] QLogic + { 0x1a, 0xff, 0xff, 0xff }, // Virtual Slot 6 = PCI_AD[17] S3 Trio 64 + { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 7 = PCI_AD[18] PCEB + { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 8 = PCI_AD[19] + { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 9 = PCI_AD[20] + { 0xff, 0xff, 0xff, 0xff }, // Virtual Slot 10 = PCI_AD[21] + { 0x12, 0x13, 0x22, 0x23 }, // Virtual Slot 11 = PCI_AD[22] Slot #0 + { 0x14, 0x15, 0x24, 0x25 }, // Virtual Slot 12 = PCI_AD[23] Slot #1 + { 0x16, 0x17, 0x26, 0x27 }, // Virtual Slot 13 = PCI_AD[24] Slot #2 + { 0x18, 0x19, 0x28, 0x29 } // Virtual Slot 14 = PCI_AD[25] Slot #3 +}; + + diff --git a/private/ntos/nthals/halpinna/alpha/vga.c b/private/ntos/nthals/halpinna/alpha/vga.c new file mode 100644 index 000000000..764c585af --- /dev/null +++ b/private/ntos/nthals/halpinna/alpha/vga.c @@ -0,0 +1,7 @@ +// +// This file simply includes the source file from the common Alpha +// HAL directory. +// + +#include "..\halalpha\vga.c" + |