diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/nthals/halvict | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to 'private/ntos/nthals/halvict')
51 files changed, 7712 insertions, 0 deletions
diff --git a/private/ntos/nthals/halvict/hal.rc b/private/ntos/nthals/halvict/hal.rc new file mode 100644 index 000000000..3cba4ad89 --- /dev/null +++ b/private/ntos/nthals/halvict/hal.rc @@ -0,0 +1,11 @@ +#include <windows.h> + +#include <ntverp.h> + +#define VER_FILETYPE VFT_DLL +#define VER_FILESUBTYPE VFT2_UNKNOWN +#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL" +#define VER_INTERNALNAME_STR "hal.dll" + +#include "common.ver" + diff --git a/private/ntos/nthals/halvict/makefile b/private/ntos/nthals/halvict/makefile new file mode 100644 index 000000000..6ee4f43fa --- /dev/null +++ b/private/ntos/nthals/halvict/makefile @@ -0,0 +1,6 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/private/ntos/nthals/halvict/ppc/fwnvr.c b/private/ntos/nthals/halvict/ppc/fwnvr.c new file mode 100644 index 000000000..74d30689e --- /dev/null +++ b/private/ntos/nthals/halvict/ppc/fwnvr.c @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\fwnvr.c> diff --git a/private/ntos/nthals/halvict/ppc/pxbbl.c b/private/ntos/nthals/halvict/ppc/pxbbl.c new file mode 100644 index 000000000..5466a07f1 --- /dev/null +++ b/private/ntos/nthals/halvict/ppc/pxbbl.c @@ -0,0 +1,2 @@ +#include "..\..\halppc\ppc\pxbbl.c" + diff --git a/private/ntos/nthals/halvict/ppc/pxbeep.c b/private/ntos/nthals/halvict/ppc/pxbeep.c new file mode 100644 index 000000000..cb3db8ccc --- /dev/null +++ b/private/ntos/nthals/halvict/ppc/pxbeep.c @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxbeep.c> diff --git a/private/ntos/nthals/halvict/ppc/pxbl.c b/private/ntos/nthals/halvict/ppc/pxbl.c new file mode 100644 index 000000000..c80af0ce0 --- /dev/null +++ b/private/ntos/nthals/halvict/ppc/pxbl.c @@ -0,0 +1,2 @@ +#include "..\..\halppc\ppc\pxbl.c" + diff --git a/private/ntos/nthals/halvict/ppc/pxbusdat.c b/private/ntos/nthals/halvict/ppc/pxbusdat.c new file mode 100644 index 000000000..88573c58d --- /dev/null +++ b/private/ntos/nthals/halvict/ppc/pxbusdat.c @@ -0,0 +1,281 @@ +/*++ + + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + pxhwsup.c + +Abstract: + + This module contains the IoXxx routines for the NT I/O system that + are hardware dependent. Were these routines not hardware dependent, + they would reside in the iosubs.c module. + +Author: + + Ken Reneris (kenr) July-28-1994 + +Environment: + + Kernel mode + +Revision History: + + Jim Wooldridge Ported to PowerPC + + Chris P. Karamatas (ckaramatas@vnet.ibm.com) 2.96 - Merged for common HAL + +--*/ + +#include "halp.h" +#include "ibmppc.h" + +VOID HalpInitOtherBuses (VOID); + + +ULONG +HalpNoBusData ( + IN PVOID BusHandler, + IN PVOID RootHandler, + IN ULONG SlotNumber, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ); + + +// +// Prototype for system bus handlers +// + + +NTSTATUS +HalpAdjustIsaResourceList ( + IN PVOID BusHandler, + IN PVOID RootHandler, + IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList + ); + +ULONG +HalpGetSystemInterruptVector ( + IN PVOID BusHandler, + IN PVOID RootHandler, + IN ULONG BusInterruptLevel, + IN ULONG BusInterruptVector, + OUT PKIRQL Irql, + OUT PKAFFINITY Affinity + ); + +ULONG +HalpGetIsaInterruptVector ( + IN PVOID BusHandler, + IN PVOID RootHandler, + IN ULONG BusInterruptLevel, + IN ULONG BusInterruptVector, + OUT PKIRQL Irql, + OUT PKAFFINITY Affinity + ); + +BOOLEAN +HalpTranslateSystemBusAddress ( + IN PVOID BusHandler, + IN PVOID RootHandler, + IN PHYSICAL_ADDRESS BusAddress, + IN OUT PULONG AddressSpace, + OUT PPHYSICAL_ADDRESS TranslatedAddress + ); + +VOID +HalpRegisterInternalBusHandlers ( + VOID + ); + + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(INIT,HalpRegisterInternalBusHandlers) +#pragma alloc_text(INIT,HalpAllocateBusHandler) +#endif + + +VOID +HalpRegisterInternalBusHandlers ( + VOID + ) +{ + PBUS_HANDLER Bus; + + if (KeGetCurrentPrcb()->Number) { + // only need to do this once + return ; + } + + // + // Initalize BusHandler data before registering any handlers + // + + HalpInitBusHandler (); + + // + // Build internal-bus 0, or system level bus + // + Bus = HalpAllocateBusHandler (Internal, -1, 0, -1, 0, 0); + Bus->GetInterruptVector = HalpGetSystemInterruptVector; + Bus->TranslateBusAddress = HalpTranslateSystemBusAddress; + + // + // Build Isa bus 0 + + Bus = HalpAllocateBusHandler (Isa, -1, 0, Internal, 0, 0); + Bus->GetBusData = HalpNoBusData; + Bus->GetInterruptVector = HalpGetIsaInterruptVector; + Bus->AdjustResourceList = HalpAdjustIsaResourceList; + + + HalpInitOtherBuses (); +} + + + +PBUS_HANDLER +HalpAllocateBusHandler ( + IN INTERFACE_TYPE InterfaceType, + IN BUS_DATA_TYPE BusDataType, + IN ULONG BusNumber, + IN INTERFACE_TYPE ParentBusInterfaceType, + IN ULONG ParentBusNumber, + IN ULONG BusSpecificData + ) +/*++ + +Routine Description: + + Stub function to map old style code into new HalRegisterBusHandler code. + + Note we can add our specific bus handler functions after this bus + handler structure has been added since this is being done during + hal initialization. + +--*/ +{ + PBUS_HANDLER Bus; + + extern UCHAR HalpEpciMin; + extern UCHAR HalpEpciMax; + + // + // Create bus handler - new style + // + + HaliRegisterBusHandler( + InterfaceType, + BusDataType, + BusNumber, + ParentBusInterfaceType, + ParentBusNumber, + BusSpecificData, + NULL, + &Bus + ); + + if (InterfaceType != InterfaceTypeUndefined) { + Bus->BusAddresses = ExAllocatePool(SPRANGEPOOL, sizeof(SUPPORTED_RANGES)); + RtlZeroMemory(Bus->BusAddresses, sizeof(SUPPORTED_RANGES)); + Bus->BusAddresses->Version = BUS_SUPPORTED_RANGE_VERSION; + Bus->BusAddresses->Dma.Limit = 7; + Bus->BusAddresses->PrefetchMemory.Base = 1; + + switch (InterfaceType) { + case Internal: + // + // This is a logical mapping of the 60X bus. + // + Bus->BusAddresses->Memory.Limit = 0xFEFFFFFF; + Bus->BusAddresses->Memory.SystemAddressSpace = 0; + Bus->BusAddresses->Memory.SystemBase = 0; + Bus->BusAddresses->IO.SystemBase = 0x80000000; + Bus->BusAddresses->IO.Limit = 0x3F7FFFFF; + Bus->BusAddresses->IO.SystemAddressSpace = 0; + + break; + + case PCIBus: + + if (HalpSystemType == IBM_DORAL) { + + // + // DORAL Cpu to PCI Addressing model. (See Doral spec, + // PCI Bridge Function). + // + // CPU Address PCI I/O PCI MEM EPCI I/O EPCI MEM + // Addr Addr Addr Addr + // + // 0x80000000 0 + // 0x9fffffff 1fffffff + // 0xa0000000 20000000 + // 0xafffffff 2fffffff + // 0xb0000000 + // 0xbfffffff + // 0xc0000000 0 + // 0xdfffffff 1fffffff + // 0xe0000000 20000000 + // 0xfeffffff 3effffff * + // + // * This is 4GB - 16MB (-1), which is unclear from the spec but + // required. + // + + if ( (BusNumber < HalpEpciMin) || (BusNumber > HalpEpciMax) ) { + // + // PCI bus. + // + Bus->BusAddresses->IO.SystemBase = 0x80000000; + Bus->BusAddresses->IO.SystemAddressSpace = 0x00000000; + Bus->BusAddresses->IO.Limit = 0x1fffffff; + + Bus->BusAddresses->Memory.SystemBase = 0xc0000000; + Bus->BusAddresses->Memory.SystemAddressSpace = 0x00000000; + Bus->BusAddresses->Memory.Limit = 0x1fffffff; + } else { + // + // EPCI bus. + // + Bus->BusAddresses->IO.SystemBase = 0x80000000; + Bus->BusAddresses->IO.Base = 0x20000000; + Bus->BusAddresses->IO.SystemAddressSpace = 0x00000000; + Bus->BusAddresses->IO.Limit = 0x2fffffff; + + Bus->BusAddresses->Memory.SystemBase = 0xc0000000; + Bus->BusAddresses->Memory.Base = 0x20000000; + Bus->BusAddresses->Memory.SystemAddressSpace = 0x00000000; + Bus->BusAddresses->Memory.Limit = 0x3effffff; + } + + } else { // All other (NON-Doral) IBM PPC's Fall through here + + Bus->BusAddresses->Memory.Limit = 0x3EFFFFFF; + Bus->BusAddresses->Memory.SystemAddressSpace = 0; + Bus->BusAddresses->Memory.SystemBase = PCI_MEMORY_PHYSICAL_BASE; + Bus->BusAddresses->IO.SystemBase = 0x80000000; + Bus->BusAddresses->IO.Limit = 0x3F7FFFFF; + Bus->BusAddresses->IO.SystemAddressSpace = 0; + + } + break; + + default: + // EISA, ISA, PCMCIA... + Bus->BusAddresses->Memory.Limit = 0x3EFFFFFF; + Bus->BusAddresses->Memory.SystemAddressSpace = 0; + Bus->BusAddresses->Memory.SystemBase = PCI_MEMORY_PHYSICAL_BASE; + Bus->BusAddresses->IO.SystemBase = 0x80000000; + Bus->BusAddresses->IO.Limit = 0x3F7FFFFF; + Bus->BusAddresses->IO.SystemAddressSpace = 0; + + } + } + + return Bus; +} + diff --git a/private/ntos/nthals/halvict/ppc/pxcache.s b/private/ntos/nthals/halvict/ppc/pxcache.s new file mode 100644 index 000000000..2c5630a60 --- /dev/null +++ b/private/ntos/nthals/halvict/ppc/pxcache.s @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxcache.s> diff --git a/private/ntos/nthals/halvict/ppc/pxcalstl.c b/private/ntos/nthals/halvict/ppc/pxcalstl.c new file mode 100644 index 000000000..3d972b02b --- /dev/null +++ b/private/ntos/nthals/halvict/ppc/pxcalstl.c @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxcalstl.c> diff --git a/private/ntos/nthals/halvict/ppc/pxclksup.s b/private/ntos/nthals/halvict/ppc/pxclksup.s new file mode 100644 index 000000000..8452d5e05 --- /dev/null +++ b/private/ntos/nthals/halvict/ppc/pxclksup.s @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxclksup.s> diff --git a/private/ntos/nthals/halvict/ppc/pxclock.c b/private/ntos/nthals/halvict/ppc/pxclock.c new file mode 100644 index 000000000..16cb61886 --- /dev/null +++ b/private/ntos/nthals/halvict/ppc/pxclock.c @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxclock.c> diff --git a/private/ntos/nthals/halvict/ppc/pxdat.c b/private/ntos/nthals/halvict/ppc/pxdat.c new file mode 100644 index 000000000..978438ac0 --- /dev/null +++ b/private/ntos/nthals/halvict/ppc/pxdat.c @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxdat.c> diff --git a/private/ntos/nthals/halvict/ppc/pxdisp.c b/private/ntos/nthals/halvict/ppc/pxdisp.c new file mode 100644 index 000000000..103883cc6 --- /dev/null +++ b/private/ntos/nthals/halvict/ppc/pxdisp.c @@ -0,0 +1,2 @@ +#include "..\..\halppc\ppc\pxdisp.c" + diff --git a/private/ntos/nthals/halvict/ppc/pxenviro.c b/private/ntos/nthals/halvict/ppc/pxenviro.c new file mode 100644 index 000000000..0f822c840 --- /dev/null +++ b/private/ntos/nthals/halvict/ppc/pxenviro.c @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxenviro.c> diff --git a/private/ntos/nthals/halvict/ppc/pxfirsup.c b/private/ntos/nthals/halvict/ppc/pxfirsup.c new file mode 100644 index 000000000..5fd3db1f2 --- /dev/null +++ b/private/ntos/nthals/halvict/ppc/pxfirsup.c @@ -0,0 +1,2 @@ +#include "..\..\halppc\ppc\pxfirsup.c" + diff --git a/private/ntos/nthals/halvict/ppc/pxflshbf.s b/private/ntos/nthals/halvict/ppc/pxflshbf.s new file mode 100644 index 000000000..b2e4b591d --- /dev/null +++ b/private/ntos/nthals/halvict/ppc/pxflshbf.s @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxflshbf.s> diff --git a/private/ntos/nthals/halvict/ppc/pxflshio.c b/private/ntos/nthals/halvict/ppc/pxflshio.c new file mode 100644 index 000000000..5817b14f5 --- /dev/null +++ b/private/ntos/nthals/halvict/ppc/pxflshio.c @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxflshio.c> diff --git a/private/ntos/nthals/halvict/ppc/pxhwsup.c b/private/ntos/nthals/halvict/ppc/pxhwsup.c new file mode 100644 index 000000000..9164059ae --- /dev/null +++ b/private/ntos/nthals/halvict/ppc/pxhwsup.c @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxhwsup.c> diff --git a/private/ntos/nthals/halvict/ppc/pxidle.c b/private/ntos/nthals/halvict/ppc/pxidle.c new file mode 100644 index 000000000..55114b480 --- /dev/null +++ b/private/ntos/nthals/halvict/ppc/pxidle.c @@ -0,0 +1,85 @@ +/*++ +TITLE("Processor Idle") + + +Copyright (c) 1994 Microsoft Corporation + +Module Name: + + pxidle.c + +abstract: + + This module implements system platform dependent power management + support. + +Author: + + Jim Wooldridge + +Environment: + + Kernel mode only. + +Revision History: + +--*/ + +#include "halp.h" +#include "pxmp.h" + + +VOID +HalProcessorIdle( + VOID + ) + +/*++ + + Routine Description: + + This function is called when the current processor is idle with + interrupts disabled. There is no thread active and there are no + DPCs to process. Therefore, power can be switched to a standby + mode until the the next interrupt occurs on the current processor. + + N.B. This routine is entered with EE in MSR clear. This routine + must do any power management enabling necessary, set the EE + bit in MSR, then either return or wait for an interrupt. + + Arguments: + + None. + + Return Value: + + None. + + +--*/ + +{ + // + // If this processor is newly IDLE, drop the MPIC TaskPriority register + // for this processor to 0 to make it a desirable target for interrupts. + // + + if ( HALPCR->HardPriority ) { + HALPCR->MpicProcessorBase->TaskPriority = 0; + HALPCR->HardPriority = 0; + } + +#ifdef POWER_MANAGEMENT + + if(HalpProcessorIdleEx != NULL) { + HalpProcessorIdleEx(); + } else { + HalpProcessorIdle(); + } + +#else + + HalpEnableInterrupts(); + +#endif // POWER_MANAGEMENT +} diff --git a/private/ntos/nthals/halvict/ppc/pxinfo.c b/private/ntos/nthals/halvict/ppc/pxinfo.c new file mode 100644 index 000000000..812bd48b4 --- /dev/null +++ b/private/ntos/nthals/halvict/ppc/pxinfo.c @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxinfo.c> diff --git a/private/ntos/nthals/halvict/ppc/pxinithl.c b/private/ntos/nthals/halvict/ppc/pxinithl.c new file mode 100644 index 000000000..ed0de708b --- /dev/null +++ b/private/ntos/nthals/halvict/ppc/pxinithl.c @@ -0,0 +1,506 @@ +/*++ + +Copyright (c) 1991-1993 Microsoft Corporation + +Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file +contains copyrighted material. Use of this file is restricted +by the provisions of a Motorola Software License Agreement. + +Copyright (c) 1993-1996 International Business Machines Corporation + +Module Name: + + pxinithl.c + +Abstract: + + + This module implements the initialization of the system dependent + functions that define the Hardware Architecture Layer (HAL) for a + Power PC system. + + +Author: + + David N. Cutler (davec) 25-Apr-1991 + +Environment: + + Kernel mode only. + +Revision History: + + Jim Wooldridge (jimw@austin.ibm.com) Initial Power PC port + + Removed call to HalpMapFixedTbEntries, the PPC port + maps all memory via calls to MmMapIoSpace(). + Removed call to HalpInializeInterrupts - 8259 initialized in phase 1 + Removed Cache error handler - 601 has no cache error interrupt + Removed call to HalpCreateDmaSturctures - it supports internal DMA + internal DMA contoller. + + Jake Oshins + Support Victory machines + + Chris Karamatas (ckaramatas@vnet.ibm.com) 2.96 + Unification + +--*/ + +#include "halp.h" +#include "pxmemctl.h" +#include "pxmp.h" +#include "ibmppc.h" + +#if _MSC_VER < 1000 + +#define UNIQUE_PCR ((KPCR *)__builtin_get_sprg1()) + +#else + +#define UNIQUE_PCR ((KPCR *)__sregister_get(273)) + +#endif + +extern ADDRESS_USAGE HalpDefaultIoSpace; + +extern VOID HalpCopyOEMFontFile(); + +VOID +HalpSynchronizeExecution( + VOID + ); + +VOID +HalpConnectFixedInterrupts( + VOID + ); + +VOID +HalpMapMpicProcessorRegisters( + VOID + ); + +ULONG +HalpGetPhysicalProcessorNumber( + VOID + ); + +IBM_SYSTEM_TYPE +HalpSetSystemType( + PLOADER_PARAMETER_BLOCK + ); + +// +// Put all code for HAL initialization in the INIT section. It will be +// deallocated by memory management when phase 1 initialization is +// completed. +// + +#if defined(ALLOC_PRAGMA) + +#pragma alloc_text(INIT, HalpSetSystemType) +#pragma alloc_text(INIT, HalInitSystem) +#pragma alloc_text(INIT, HalInitializeProcessor) + +#endif + +PVOID HalpIoControlBase = (PVOID) 0; +PVOID HalpIoMemoryBase = (PVOID) 0; + +ULONG HalpInitPhase; +ULONG HalpPhysicalIpiMask[MAXIMUM_PROCESSORS]; + +IBM_SYSTEM_TYPE HalpSystemType; + +VOID +HalpInitBusHandlers ( + VOID + ); + +VOID +HalpInitializePciAccess ( + VOID + ); + +VOID +HalpRegisterInternalBusHandlers ( + VOID + ); + + + +// +// Define global spin locks used to synchronize various HAL operations. +// + +KSPIN_LOCK HalpBeepLock; +KSPIN_LOCK HalpDisplayAdapterLock; +KSPIN_LOCK HalpSystemInterruptLock; + + +IBM_SYSTEM_TYPE +HalpSetSystemType( + PLOADER_PARAMETER_BLOCK LoaderBlock + ) + +/*++ + +Routine Description: + + Sets the global variable HalpSystemType according to the type + of system we are running on. Also sets pointers to various + tables accordingly. + +Arguments: + + None. + +Return Value: + + Returns the value assigned to HalpSystemType. N.B. A value + of IBM_UNKNOWN indicates failure. + +--*/ + +{ + PCONFIGURATION_COMPONENT_DATA ConfigurationEntry; + ULONG MatchKey; + UCHAR *ptr; + +#define SYSTEM_IS(x) \ + (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,(x))) + +#define SYSTEM_ID_STARTS(x) \ + (!strncmp(ConfigurationEntry->ComponentEntry.Identifier, \ + (x), \ + strlen(x))) + + MatchKey = 0; + ConfigurationEntry=KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot, + SystemClass, + ArcSystem, + &MatchKey); + + HalpSystemType = IBM_UNKNOWN; + + if (ConfigurationEntry != NULL) { + +#if DBG + + DbgPrint("HAL: System configuration = %s\n", + ConfigurationEntry->ComponentEntry.Identifier); + +#endif + + if ( SYSTEM_IS(SID_IBM_TIGER) ) { + HalpSystemType = IBM_TIGER; + } else if ( SYSTEM_IS(SID_IBM_VICTORY) ) { + HalpSystemType = IBM_VICTORY; + } else if ( SYSTEM_IS(SID_IBM_DORAL) || + SYSTEM_IS(SID_IBM_TERLINGUA) || + SYSTEM_ID_STARTS(SID_IBM_DORAL_START) || + SYSTEM_ID_STARTS(SID_IBM_TERLINGUA_START) ) { + HalpSystemType = IBM_DORAL; + } else { + DbgPrint("HAL: UNKNOWN SYSTEM: %s\n", ConfigurationEntry->ComponentEntry.Identifier); + } + } else { + DbgPrint("HAL: No SYSTEM Entry in Loader Block\n"); + } + return HalpSystemType; + +#undef SYSTEM_IS +} + +BOOLEAN +HalInitSystem ( + IN ULONG Phase, + IN PLOADER_PARAMETER_BLOCK LoaderBlock + ) + +/*++ + +Routine Description: + + This function initializes the Hardware Architecture Layer (HAL) for a + Power PC system. + +Arguments: + + Phase - Supplies the initialization phase (zero or one). + + LoaderBlock - Supplies a pointer to a loader parameter block. + +Return Value: + + A value of TRUE is returned is the initialization was successfully + complete. Otherwise a value of FALSE is returend. + +--*/ + +{ + + PKPRCB Prcb; + ULONG BuildType = 0; + ULONG ProcessorNumber; + + + // + // Initialize the HAL components based on the phase of initialization + // and the processor number. + // + + HalpInitPhase = Phase; + + Prcb = PCR->Prcb; + if ((Phase == 0) || (Prcb->Number != 0)) { + + // + // Phase 0 initialization. + // + // N.B. Phase 0 initialization is executed on all processors. + // + // + // Get access to I/O space, check if I/O space has already been + // mapped by debbuger initialization. + // + + + if (HalpIoControlBase == NULL) { + + HalpIoControlBase = (PVOID)KePhase0MapIo(IO_CONTROL_PHYSICAL_BASE, + 0x20000 + ); + if ( !HalpIoControlBase ) { + return FALSE; + } + } + + // Verify that the processor block major version number conform + // to the system that is being loaded. + // + + if (Prcb->MajorVersion != PRCB_MAJOR_VERSION) { + KeBugCheck(MISMATCHED_HAL); + } + + // + // Every processor needs to determine its PHYSICAL processor + // number (Prcb->Number is a logical s/w concept) and record + // it in the PER Cpu data (HAL reserved space in the PCR). + // + // Get the physical number from the processor's PIR register + // (Processor Id Register). + // + + ProcessorNumber = HalpGetPhysicalProcessorNumber(); + HALPCR->PhysicalProcessor = ProcessorNumber; + HalpPhysicalIpiMask[Prcb->Number] = 1 << ProcessorNumber; + + // + // If processor 0 is being initialized, then initialize various + // variables, spin locks, and the display adapter. + // + + if (Prcb->Number == 0) { + + if ( !HalpSetSystemType(LoaderBlock) ) { + KeBugCheck(BAD_SYSTEM_CONFIG_INFO); + } + + // + // Get access to PCI Configuration Address and Data + // registers. + // + + HalpInitializePciAccess(); + + // + // Do very early planar initialization, for example, + // get access to the memory controller error status + // registers. + // + + HalpInitPlanar(); + + // + // Set the interval clock increment value. + // + + HalpCurrentTimeIncrement = MAXIMUM_INCREMENT; + HalpNewTimeIncrement = MAXIMUM_INCREMENT; + KeSetTimeIncrement(MAXIMUM_INCREMENT, MINIMUM_INCREMENT); + + // + // Initialize all spin locks. + // + + KeInitializeSpinLock(&HalpBeepLock); + KeInitializeSpinLock(&HalpDisplayAdapterLock); + KeInitializeSpinLock(&HalpSystemInterruptLock); + +#ifdef POWER_MANAGEMENT + // + // Fill in handlers for APIs which this hal supports + // + + HalSuspendHibernateSystem = HaliSuspendHibernateSystem; + HalQuerySystemInformation = HaliQuerySystemInformation; + HalSetSystemInformation = HaliSetSystemInformation; + HalRegisterBusHandler = HaliRegisterBusHandler; + HalHandlerForBus = HaliHandlerForBus; + HalHandlerForConfigSpace = HaliHandlerForConfigSpace; + HalQueryBusSlots = HaliQueryBusSlots; + HalSlotControl = HaliSlotControl; + HalCompleteSlotControl = HaliCompleteSlotControl; +#endif // POWER_MANAGEMENT + + HalpRegisterAddressUsage (&HalpDefaultIoSpace); + + // + // initialize HalpPciMaxBuses (not really used YET) + // + + HalpPhase0DiscoverPciBuses(LoaderBlock->ConfigurationRoot); + + // + // Initialize the display adapter. + // + + if (!HalpInitializeDisplay(LoaderBlock)) { + return FALSE; + } + + // + // Initialize per Machine (as opposed to per Processor) + // Interrupt Hardware. + // + + if (!HalpInitializeInterrupts()) { + return FALSE; + } + } else { + + // + // Processor is not 0. + // + + HalpMapMpicProcessorRegisters(); + HalpConnectFixedInterrupts(); + } + + // + // Calibrate execution stall + // + + HalpCalibrateStall(); + + // + // return success + // + + return TRUE; + + + } else { + + if (Phase != 1) + return(FALSE); + + + // + // Phase 1 initialization. + // + // N.B. Phase 1 initialization is only executed on processor 0. + // + + + HalpRegisterInternalBusHandlers (); + + + if (!HalpAllocateMapBuffer()) { + return FALSE; + } + + + // + // Map I/O space and create ISA data structures. + // + + if (!HalpMapIoSpace()) { + return FALSE; + } + + if (!HalpCreateSioStructures()) { + return FALSE; + } + + // + // retain the OEM Font File for later use + // + + HalpCopyOEMFontFile(); + HalpCopyBiosShadow(); + + return TRUE; + + } +} + +VOID +HalInitializeProcessor ( + IN ULONG Number + ) + +/*++ + +Routine Description: + + This function is called early in the initialization of the kernel + to perform platform dependent initialization for each processor + before the HAL Is fully functional. + + N.B. When this routine is called, the PCR is present but is not + fully initialized. + +Arguments: + + Number - Supplies the number of the processor to initialize. + +Return Value: + + None. + +--*/ + +{ + // + // Define a static structure that KeRaise/LowerIrql can use + // until access to the MPIC is initialized. + // + static MPIC_PER_PROCESSOR_REGS DummyMpicRegs; + + // + // If this is the first processor to do so, initialize the cache + // sweeping routines depending on type of processor. + // + + if ( Number == 0 ) { + if ( HalpCacheSweepSetup() ) { + KeBugCheck(MISMATCHED_HAL); + } + } + + // + // Set HAL per processor data MpicProcessorBase pointing + // to the above structure. This pointer will be overwritten + // once access to the MPIC itself is available. + // Note: We don't have real access to the PCR yet. + // + + ((PPER_PROCESSOR_DATA)&UNIQUE_PCR->HalReserved)->MpicProcessorBase = &DummyMpicRegs; + + return; +} + diff --git a/private/ntos/nthals/halvict/ppc/pxintrpt.c b/private/ntos/nthals/halvict/ppc/pxintrpt.c new file mode 100644 index 000000000..4cd20cab5 --- /dev/null +++ b/private/ntos/nthals/halvict/ppc/pxintrpt.c @@ -0,0 +1,1505 @@ +/*++ + +Copyright (c) 1996 International Business Machines Corporation +Copyright (c) 1996 Microsoft Corporation + +Module Name: + + pxintrpt.c + +Abstract: + + This module implements machine specific interrupt functions + for IBM's PowerPC Machines. + + Code in this module was largely gathered from other modules + in earlier versions of the HAL. + +Author: + + Peter Johnston (plj@vnet.ibm.com) Oct 1995. + +Environment: + + Kernel mode. + +Revision History: + + Jake Oshins + Made it support Victory machines + Chris Karamatas + Merged Victory/Doral/Tiger. + + +--*/ + +#include "halp.h" +#include "eisa.h" +#include "pxfirsup.h" +#include "pci.h" +#include "pcip.h" +#include "pxmp.h" +#include "pxmpic2.h" +#include "ibmppc.h" +#include "pxintrpt.h" + +#if _MSC_VER >= 1000 + +// +// VC++ doesn't have the same intrinsics as MCL. +// +// Although the MSR is not strictly a SPR, the compiler recognizes +// all ones (~0) as being the MSR and emits the appropriate code. +// + +#define __builtin_set_msr(x) __sregister_set(_PPC_MSR_,x) + +#endif + +// +// Define the context structure for use by the interrupt routine. +// + + +typedef BOOLEAN (*PSECONDARY_DISPATCH)( + PVOID InterruptRoutine, + PVOID ServiceContext, + PVOID TrapFrame + ); + + +extern ADDRESS_USAGE HalpMpicSpace; + +// +// The following function is called when a machine check occurs. +// + +BOOLEAN +HalpHandleMachineCheck( + IN PKINTERRUPT Interrupt, + IN PVOID ServiceContext + ); + +// +// Provide prototype for Decrementer Interrupts on processors other +// than 0. +// + +BOOLEAN +HalpHandleDecrementerInterrupt1 ( + IN PKINTERRUPT Interrupt, + IN PVOID ServiceContext, + IN PVOID TrapFrame + ); + +BOOLEAN +HalpHandleIpi( + IN PVOID Unused0, + IN PVOID Unused1, + IN PVOID TrapFrame + ); + +VOID +HalpMapMpicProcessorRegisters( + VOID + ); + +VOID +HalpMapMpicSpace( + VOID + ); + +ULONG +HalpGetSystemInterruptVector( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN ULONG BusInterruptLevel, + IN ULONG BusInterruptVector, + OUT PKIRQL Irql, + OUT PKAFFINITY Affinity + ); + +VOID +HalpConnectFixedInterrupts( + VOID + ); + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(INIT,HalpConnectFixedInterrupts) +#pragma alloc_text(PAGE,HalpGetPCIIrq) +#pragma alloc_text(PAGE,HalpGetSystemInterruptVector) +#pragma alloc_text(INIT,HalpMapMpicProcessorRegisters) +#pragma alloc_text(INIT,HalpMapMpicSpace) +#endif + + +// +// ERRATA: MPIC2 Ipi SelectProcessor registers need their addresses +// munged. +// + +ULONG Mpic2IpiBugFix; + +// +// ERRATA end. +// + +// +// Define globals for the pointers to MPIC Global and Interrupt Source +// address spaces. +// + +PMPIC_GLOBAL_REGS HalpMpicGlobal; +PMPIC_INTERRUPT_SOURCE_REGS HalpMpicInterruptSource; +ULONG HalpMpicBasePhysicalAddress; +ULONG HalpMpicSupportedInts; +ULONG HalpMpicMaxVector; + + +PVOID +HalpAssignReservedVirtualSpace( + ULONG BasePage, + ULONG LengthInPages + ); + + +#if defined(SOFT_HDD_LAMP) + +// +// On PowerPC machines the HDD lamp is software driven. We +// turn it on any time we take an interrupt from a Mass Storage +// Controller (assuming it isn't already on) and turn it off the 2nd +// clock tick after we turn it on if we have not received +// any more MSC interrupts since the first clock tick. +// + +HDD_LAMP_STATUS HalpHddLamp; + +ULONG HalpMassStorageControllerVectors; + +#endif + +extern UCHAR IrqlToTaskPriority[]; // in pxirql.c + +// +// Save area for ISA interrupt mask resiters and level\edge control +// registers. (Declared in pxfirsup.c). +// + +extern UCHAR HalpSioInterrupt1Mask; +extern UCHAR HalpSioInterrupt2Mask; +extern UCHAR HalpSioInterrupt1Level; +extern UCHAR HalpSioInterrupt2Level; + + +VOID +HalpMapMpicProcessorRegisters( + VOID + ) + +/*++ + +Routine Description: + + + Map MPIC per-processor registers for this processor. Note + that although the logical processor Prcb->Number, may not be + the physical processor bt the same number. We must map the + registers appropriate to this physical processor. + Also, the VA of this space will only ever be used by THIS + processor so we will use HAL reserved space rather than an + address assigned by MmMapIoSpace, the only reason for this + is to save the system a page per processor (not a big deal). + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + ULONG PerProcessorRegs; + ULONG i; + PerProcessorRegs = HalpMpicBasePhysicalAddress + MPIC_PROCESSOR_0_OFFSET + + (HALPCR->PhysicalProcessor * MPIC_PROCESSOR_REGS_SIZE); + + HALPCR->MpicProcessorBase = HalpAssignReservedVirtualSpace( + PerProcessorRegs >> PAGE_SHIFT, + 1); + + if ( !HALPCR->MpicProcessorBase ) { + KeBugCheck(MISMATCHED_HAL); + } + + // + // Set priority for this processor to mask ALL interrupts. + // + + HALPCR->MpicProcessorBase->TaskPriority = MPIC_MAX_PRIORITY; + HALPCR->HardPriority = MPIC_MAX_PRIORITY; + HALPCR->PendingInterrupts = 0; + MPIC_SYNC(); + + // + // Reading the Acknowledge register now would give us the spurious + // vector,... but,... clear the In-Service Register just in case + // there's something still in it. This is done by writing to the + // EOI register. + // + // There could potentially be one in service interrupt for each + // level the MPIC supports, so do it that many times. + // + + for ( i = 0 ; i < MPIC_SUPPORTED_IPI ; i++ ) { + HALPCR->MpicProcessorBase->EndOfInterrupt = 0; + MPIC_SYNC(); + } +} + + +VOID +HalpMapMpicSpace( + VOID + ) + +/*++ + +Routine Description: + + Locate and map the MPIC 2 (or 2A) controller. Initialize + all interrupts disabled. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + ULONG MpicBasePhysicalAddress = 0; + ULONG DeviceVendor; + ULONG i; + ULONG SlotNumber; + MPIC_ISVP InterruptSource; + MPIC_IPIVP IpiSource; + + // + // Find the MPIC controller. + // This should probably be passed in in the h/w config, but + // neither the configuration nor the PCI bus have been initialized + // yet. So, search for it using Phase 0 routines. + // + + for ( SlotNumber = 0; SlotNumber < 32 ; SlotNumber++ ) { + HalpPhase0GetPciDataByOffset( + 0, + SlotNumber, + &DeviceVendor, + FIELD_OFFSET(PCI_COMMON_CONFIG, VendorID), + sizeof(DeviceVendor) + ); + if ( (DeviceVendor == MPIC2_PCI_VENDOR_DEVICE) || + (DeviceVendor == MPIC2A_PCI_VENDOR_DEVICE) || + (DeviceVendor == HYDRA_PCI_VENDOR_DEVICE ) ) { + HalpPhase0GetPciDataByOffset( + 0, + SlotNumber, + &MpicBasePhysicalAddress, + FIELD_OFFSET(PCI_COMMON_CONFIG, u.type0.BaseAddresses[0]), + sizeof(MpicBasePhysicalAddress) + ); + break; + } + } + + + // + // Assert that (a) we found it, and (b) if MPIC2, its I/O space + // really is I/O space, or, if MPIC2A, its I/O space is PCI + // memory space. + // + + if ( !MpicBasePhysicalAddress) { + KeBugCheck(MISMATCHED_HAL); + } + + // Default to standard MPIC + HalpMpicSupportedInts = MPIC_SUPPORTED_INTS; + + switch ( DeviceVendor ) { + + case MPIC2_PCI_VENDOR_DEVICE: + if ( !(MpicBasePhysicalAddress & 0x1) ) { + KeBugCheck(MISMATCHED_HAL); + } + MpicBasePhysicalAddress |= 0x80000000; + + // + // ERRATA: MPIC2 bug, the IPI SelectProcessor registers need to be + // munged. + // + + Mpic2IpiBugFix = 0x2; + + // + // ERRATA end. + // + break; + + case HYDRA_PCI_VENDOR_DEVICE: + // + // For Tiger: MPIC is within Hydra, so we add 0x40000 to Hydra Base to + // reach MPIC space - IBMCPK + // + MpicBasePhysicalAddress += 0x40000; + + HalpMpicSupportedInts = HYDRA_MPIC_SUPPORTED_INTS; + + // Fall thru. + + case MPIC2A_PCI_VENDOR_DEVICE: + if ( MpicBasePhysicalAddress & 0x1 ) { + KeBugCheck(MISMATCHED_HAL); + } + MpicBasePhysicalAddress |= 0xc0000000; + break; + + default: + KeBugCheck(MISMATCHED_HAL); + } + + // + // Remove lower 2 bits, (I/O space indicator and "reserved"). + // + + MpicBasePhysicalAddress &= ~0x3; + + HalpMpicBasePhysicalAddress = MpicBasePhysicalAddress; + + // + // Map MPIC Global Registers and Interrupt Source Configuration + // registers. + + HalpMpicGlobal = HalpAssignReservedVirtualSpace( + (MpicBasePhysicalAddress + MPIC_GLOBAL_OFFSET) >> PAGE_SHIFT, + 1); + if ( !HalpMpicGlobal ) { + KeBugCheck(MISMATCHED_HAL); + } + + HalpMpicInterruptSource = HalpAssignReservedVirtualSpace( + (MpicBasePhysicalAddress + MPIC_INTERRUPT_SOURCE_OFFSET) >> PAGE_SHIFT, + 1); + + if ( !HalpMpicInterruptSource ) { + KeBugCheck(MISMATCHED_HAL); + } + + HalpMpicGlobal->Configuration.Mode = MPIC_MIXED_MODE; + + if ( DeviceVendor == HYDRA_PCI_VENDOR_DEVICE ) { + // + // Set Hydra Feature Register bit MpicIsMaster (bit 8). + // + + PVOID HydraBase = HalpAssignReservedVirtualSpace( + (MpicBasePhysicalAddress - 0x40000) >> PAGE_SHIFT, + 1); + PULONG HydraFeatureRegister = (PULONG)((ULONG)HydraBase + 0x38); + if ( !HydraBase ) { + KeBugCheck(MISMATCHED_HAL); + } + + *HydraFeatureRegister |= 0x100; + + HalpReleaseReservedVirtualSpace(HydraBase, 1); + } + + // + // Disable all interrupt sources. + // + + *(PULONG)&InterruptSource = 0; + + InterruptSource.Priority = 0; + InterruptSource.Sense = 1; + InterruptSource.Polarity = 0; + + for ( i = 0 ; i < HalpMpicSupportedInts ; i++ ) { + InterruptSource.Vector = i + MPIC_BASE_VECTOR; + MPIC_WAIT_SOURCE(i); + HalpMpicInterruptSource->Int[i].VectorPriority = InterruptSource; + MPIC_WAIT_SOURCE(i); + HalpMpicInterruptSource->Int[i].SelectProcessor = 0; + } + + MPIC_SYNC(); + + // + // Set source 0 (the 8259) to Active High, Level Triggered. + // + + MPIC_WAIT_SOURCE(0); + HalpMpicInterruptSource->Int[0].VectorPriority.Polarity = 1; + MPIC_SYNC(); + + + // + // Set IPI Vector/Priority. 0 is the only one we really + // use. However, we set 3 to the MAX and NMI so we can + // use it to wake the dead when debugging (maybe). + // + // Set IPI 0 to overload vector 30 which is one of the reserved + // vectors on DORAL. + // Set IPI 1 & 2 to do nothing. + // Set IPI 3 to overload vector 29 which is reserved on DORAL. ALSO, + // set IPI 3 NMI. (Priority is irrelevant). + // + + *(PULONG)&IpiSource = 0; + + IpiSource.Vector = MPIC_IPI0_VECTOR; + IpiSource.Priority = 14; + MPIC_WAIT_IPI_SOURCE(0); + HalpMpicGlobal->Ipi[0].VectorPriority = IpiSource; + + IpiSource.Vector = MPIC_IPI1_VECTOR; + IpiSource.Priority = 0; + MPIC_WAIT_IPI_SOURCE(1); + HalpMpicGlobal->Ipi[1].VectorPriority = IpiSource; + + IpiSource.Vector = MPIC_IPI2_VECTOR; + MPIC_WAIT_IPI_SOURCE(2); + HalpMpicGlobal->Ipi[2].VectorPriority = IpiSource; + + IpiSource.Vector = MPIC_IPI3_VECTOR; + IpiSource.NMI = 1; + MPIC_WAIT_IPI_SOURCE(3); + HalpMpicGlobal->Ipi[3].VectorPriority = IpiSource; + MPIC_SYNC(); + + // + // Initialize per processor registers for this processor. + // + + HalpMapMpicProcessorRegisters(); + + // + // Register this I/O space as in-use. + // + + MpicBasePhysicalAddress &= 0x7FFFFFFF; // Get bus-relative address + + // Length can only be a USHORT, so we do this four times + HalpMpicSpace.Element[0].Start = MpicBasePhysicalAddress; + HalpMpicSpace.Element[0].Length = 0xFFFF; + HalpMpicSpace.Element[1].Start = MpicBasePhysicalAddress + 0x10000; + HalpMpicSpace.Element[1].Length = 0xFFFF; + HalpMpicSpace.Element[2].Start = MpicBasePhysicalAddress + 0x20000; + HalpMpicSpace.Element[2].Length = 0xFFFF; + HalpMpicSpace.Element[3].Start = MpicBasePhysicalAddress + 0x30000; + HalpMpicSpace.Element[3].Length = 0xFFFF; + + switch ( DeviceVendor ) { + case MPIC2_PCI_VENDOR_DEVICE: + + HalpMpicSpace.Type = CmResourceTypePort; + break; + + case HYDRA_PCI_VENDOR_DEVICE: + case MPIC2A_PCI_VENDOR_DEVICE: + + HalpMpicSpace.Type = CmResourceTypeMemory; + break; + } + + HalpRegisterAddressUsage(&HalpMpicSpace); +} + + +VOID +HalpConnectFixedInterrupts( + VOID + ) + +/*++ + +Routine Description: + + Set required interrupt vectors in the PCR, called once on each + processor in the system. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + // + // Connect the machine check handler + // + + PCR->InterruptRoutine[MACHINE_CHECK_VECTOR] = + (PKINTERRUPT_ROUTINE)HalpHandleMachineCheck; + + // + // Connect the external interrupt handler + // + + PCR->InterruptRoutine[EXTERNAL_INTERRUPT_VECTOR] = + (PKINTERRUPT_ROUTINE)HalpHandleExternalInterrupt; + + + // + // Connect directly to the decrementer handler. Processor 0 uses + // HalpHandleDecrementerInterrupt, other processors use + // HalpHandleDecrementerInterrupt1. + // + + PCR->InterruptRoutine[DECREMENT_VECTOR] = + (PKINTERRUPT_ROUTINE)HalpHandleDecrementerInterrupt1; + + // + // Connect the Inter-Processor Interrupt (IPI) handler. + // + + PCR->InterruptRoutine[MPIC_IPI0_VECTOR + DEVICE_VECTORS] = + (PKINTERRUPT_ROUTINE)HalpHandleIpi; + + // + // Connect the Profile interrupt (Timer 1 IRQ0) handler. + // + + PCR->InterruptRoutine[PROFILE_LEVEL] = + (PKINTERRUPT_ROUTINE)HalpHandleProfileInterrupt; + + // + // Enable the clock interrupt + // + + HalpUpdateDecrementer(1000); // Get those decrementer ticks going + + +} + +BOOLEAN +HalpHandleExternalInterrupt( + IN PKINTERRUPT Interrupt, + IN PVOID ServiceContext, + IN PVOID TrapFrame + ) + +/*++ + +Routine Description: + + This routine is entered as the result of an interrupt being generated + via the vector that is connected to an interrupt object that describes + the SIO device interrupts. Its function is to call the second + level interrupt dispatch routine and acknowledge the interrupt at the SIO + controller. + + N.B. This routine in entered and left with external interrupts disabled. + + +Arguments: + + Interrupt - Supplies a pointer to the interrupt object. + + ServiceContext - Supplies a pointer to the SIO interrupt acknowledge + register. + + None. + +Return Value: + + Returns the value returned from the second level routine. + +--*/ + +{ + PSECONDARY_DISPATCH SioHandler; + PKINTERRUPT SioInterrupt; + USHORT Vector; + BOOLEAN returnValue; + UCHAR OldIrql; + USHORT Isr; + ULONG TaskPriority; + + // + // Read the MPIC interrupt vector. + // + + Vector = (USHORT)(HALPCR->MpicProcessorBase->Acknowledge & 0xff); + + // + // Check for cancelled (spurious) interrupts. + // + + if ( Vector == 0xff ) { + return 0; + } + + // + // Check for 8259 interrupt. + // + + if ( Vector == MPIC_8259_VECTOR ) { + + // + // Read the 8259 interrupt vector. + // + + Vector = READ_REGISTER_UCHAR(HalpInterruptBase); + + // + // Acknowledge this interrupt immediately in the MPIC2 + // controller so higher priority 8259 interrupts can be + // delivered. + // + + HALPCR->MpicProcessorBase->EndOfInterrupt = 0; + + // + // Check for NMI interrupt before we raise irql since we would + // raise to a bogus level. + // + + if (Vector == 0xFF) { + + HalpHandleMachineCheck(NULL, NULL); + } + + // + // check for spurious interrupt + // + + if (Vector == SPURIOUS_VECTOR) { + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL)HalpIoControlBase)->Interrupt1ControlPort0, + 0x0B); + Isr = READ_REGISTER_UCHAR( + &((PEISA_CONTROL)HalpIoControlBase)->Interrupt1ControlPort0); + + if (!(Isr & 0x80)) { + + // + // Spurious interrupt + // + + return 0; + } + } + +#if defined(SOFT_HDD_LAMP) + + } else if ( HalpMassStorageControllerVectors & ( 1 << Vector) ) { + // + // On any Mass Storage Controller interrupt, light the HDD lamp. + // The system timer routines will turn it off again in a little + // while. + // + + if ( !HalpHddLamp.Count ) { + *(PUCHAR)((PUCHAR)HalpIoControlBase + HDD_LAMP_PORT) = 1; + } + HalpHddLamp.Count = 10; + +#endif + + } + + // + // Raise IRQL - We rely on the MPIC and 8259 controllers to + // hold off any lower or equal priority interrupts. Therefore + // all we need do is update the PCRs notion of IRQL and re + // enable interrupts. + // + + OldIrql = PCR->CurrentIrql; + PCR->CurrentIrql = HalpVectorToIrql[Vector]; + HalpEnableInterrupts(); + + // + // Dispatch to the secondary interrupt service routine. + // + + SioHandler = (PSECONDARY_DISPATCH) + PCR->InterruptRoutine[DEVICE_VECTORS + Vector]; + SioInterrupt = CONTAINING_RECORD(SioHandler, + KINTERRUPT, + DispatchCode[0]); + + returnValue = SioHandler(SioInterrupt, + SioInterrupt->ServiceContext, + TrapFrame + ); + + // + // Clear the interrupt in the appropriate controller. To + // avoid the possibility of being drowned with interrupts + // at this level, disable interrupts first (we need to + // return to our caller with interrupts disabled anyway). + // + + HalpDisableInterrupts(); + + if ( Vector < MPIC_8259_VECTOR ) { + // + // Dismiss the interrupt in the SIO interrupt controllers. + // + // If this is a cascaded interrupt then the interrupt must + // be dismissed in both controllers. + // + + if (Vector & 0x08) { + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort0, + NONSPECIFIC_END_OF_INTERRUPT + ); + + } + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort0, + NONSPECIFIC_END_OF_INTERRUPT + ); + + + } else { + + HALPCR->MpicProcessorBase->EndOfInterrupt = 0; + } + + // + // Lower IRQL without enabling external interrupts. It is + // possible that Irql was raised above this level and lowered + // back to this level in the mean time. If so, the TaskPriority + // will have been adjusted and we need to adjust it downwards. + // + + PCR->CurrentIrql = OldIrql; + + TaskPriority = IrqlToTaskPriority[OldIrql]; + + if ( TaskPriority < HALPCR->HardPriority ) { + HALPCR->MpicProcessorBase->TaskPriority = TaskPriority; + HALPCR->HardPriority = TaskPriority; + } + + return returnValue; +} + + +VOID +HalpEnableSioInterrupt( + IN ULONG Vector, + IN KINTERRUPT_MODE InterruptMode + ) + +/*++ + +Routine Description: + + This function enables the SIO interrupt and sets + the level/edge register to the requested value. + +Arguments: + + Vector - Supplies the vector of the interrupt that is enabled. + + InterruptMode - Supplies the mode of the interrupt; LevelSensitive or + Latched. + +Return Value: + + None. + +--*/ + +{ + + // + // Calculate the SIO interrupt vector. + // + + Vector -= DEVICE_VECTORS; + + // + // Determine if this vector is for interrupt controller 1 or 2. + // + + if (Vector & 0x08) { + + // + // The interrupt is in controller 2. + // + + Vector &= 0x7; + + HalpSioInterrupt2Mask &= (UCHAR) ~(1 << Vector); + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1, + HalpSioInterrupt2Mask + ); + + // + // Set the level/edge control register. + // + + if (InterruptMode == LevelSensitive) { + + HalpSioInterrupt2Level |= (UCHAR) (1 << Vector); + + } else { + + HalpSioInterrupt2Level &= (UCHAR) ~(1 << Vector); + + } + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2EdgeLevel, + HalpSioInterrupt2Level + ); + + } else { + + // + // The interrupt is in controller 1. + // + + Vector &= 0x7; + + HalpSioInterrupt1Mask &= (UCHAR) ~(1 << Vector); + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1, + HalpSioInterrupt1Mask + ); + + // + // Set the level/edge control register. + // + + if (InterruptMode == LevelSensitive) { + + HalpSioInterrupt1Level |= (UCHAR) (1 << Vector); + + } else { + + HalpSioInterrupt1Level &= (UCHAR) ~(1 << Vector); + + } + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1EdgeLevel, + HalpSioInterrupt1Level + ); + } + +} + +VOID +HalpDisableSioInterrupt( + IN ULONG Vector + ) + +/*++ + +Routine Description: + + This function Disables the SIO interrupt. + +Arguments: + + Vector - Supplies the vector of the EISA interrupt that is Disabled. + +Return Value: + + None. + +--*/ + +{ + + // + // Calculate the SIO interrupt vector. + // + + Vector -= DEVICE_VECTORS; + + // + // Determine if this vector is for interrupt controller 1 or 2. + // + + if (Vector & 0x08) { + + // + // The interrupt is in controller 2. + // + + Vector &= 0x7; + + HalpSioInterrupt2Mask |= (UCHAR) 1 << Vector; + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1, + HalpSioInterrupt2Mask + ); + + } else { + + // + // The interrupt is in controller 1. + // + + Vector &= 0x7; + + HalpSioInterrupt1Mask |= (ULONG) 1 << Vector; + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1, + HalpSioInterrupt1Mask + ); + + } + +} + +VOID +HalpEnableMpicInterrupt( + IN ULONG Vector + ) + +/*++ + +Routine Description: + + This function enables the MPIC interrupt at the source. + +Arguments: + + Vector - Supplies the vector of the interrupt that is enabled. + +Return Value: + + None. + +--*/ + +{ + MPIC_ISVP VectorPriority; + + // + // Calculate the MPIC source. + // + + ULONG Source = Vector - (DEVICE_VECTORS + MPIC_BASE_VECTOR); + + MPIC_WAIT_SOURCE(Source); + + VectorPriority = HalpMpicInterruptSource->Int[Source].VectorPriority; + + if (Source == 0) { // special 8259 case + VectorPriority.Priority = 2; + } else if (Source < MPIC_SUPPORTED_INTS) { + VectorPriority.Priority = (Source / 2) + 3; + } else { + // Extra hydra poles get the same (highest) priority + VectorPriority.Priority = 10; + } + HalpMpicInterruptSource->Int[Source].VectorPriority = VectorPriority; + + + MPIC_WAIT_SOURCE(Source); + + HalpMpicInterruptSource->Int[Source].SelectProcessor = + 1 << HALPCR->PhysicalProcessor; +} + +VOID +HalpDisableMpicInterrupt( + IN ULONG Vector + ) + +/*++ + +Routine Description: + + This function Disables the SIO interrupt. + +Arguments: + + Vector - Supplies the vector of the ESIA interrupt that is Disabled. + +Return Value: + + None. + +--*/ + +{ + MPIC_ISVP VectorPriority; + // + // Calculate the MPIC source. + // + + ULONG Source = Vector - (DEVICE_VECTORS + MPIC_BASE_VECTOR); + + MPIC_WAIT_SOURCE(Source); + + VectorPriority = HalpMpicInterruptSource->Int[Source].VectorPriority; + VectorPriority.Priority = 0; + HalpMpicInterruptSource->Int[Source].VectorPriority = VectorPriority; + + if (HalpSystemType == IBM_DORAL) { + + MPIC_WAIT_SOURCE(Source); + + HalpMpicInterruptSource->Int[Source].SelectProcessor = 0; + + } +} + +BOOLEAN +HalpInitializeInterrupts ( + VOID + ) + +/*++ + +Routine Description: + + This routine is called from phase 0 initialization, it initializes the + 8259 interrupt controller ( currently it masks all 8259 interrupts). + + +Arguments: + + None. + +Return Value: + + +--*/ + +{ + ULONG Vector; + + // + // Mask all 8259 interrupts (except the cascade interrupt) + // + + for (Vector=0;Vector<16;Vector++) { + if (Vector == 2) + continue; + HalpDisableSioInterrupt(Vector + DEVICE_VECTORS); + } + + // + // Map MPIC space and mask interrupts. + // + + HalpMapMpicSpace(); + + // + // Set appropriate Interrupt Vector to Irql mapping for this + // machine. + // + + HalpMpicMaxVector = MPIC_BASE_VECTOR + DEVICE_VECTORS + + HalpMpicSupportedInts - 1; + + // + // Reserve the external interrupt vector for exclusive use by the HAL. + // + + PCR->ReservedVectors |= (1 << EXTERNAL_INTERRUPT_VECTOR); + + return TRUE; + +} + + +KINTERRUPT_MODE +HalpGetInterruptMode ( + IN ULONG Vector, + IN KIRQL Irql, + IN KINTERRUPT_MODE InterruptMode + ) +/*++ + +Routine Description: + + Force interrupt mode for (machine specific) interrupt vectors. + If the vector is not one of those hardwired, return the caller's + requested mode. + + On Doral, all ISA style interrupts (8259) except 13 (Power + Management) are edge sensitive. 13 is level sensitive. + +Arguments: + + Vector - Vector for which translation is being requested. + Irql - Not used. + InterruptMode - Requested mode. + +Return Value: + + Interrupt mode for this vector. + +--*/ + + +{ + if ((HalpSystemType == IBM_TIGER) && + (Vector == DEVICE_VECTORS + 15)) { + return LevelSensitive; + } else if ( Vector == (DEVICE_VECTORS + 13) ) { + return LevelSensitive; + } else { + return Latched; + } +} + +VOID +HalpSetInterruptMode ( + IN ULONG Vector, + IN KIRQL Irql + ) +/*++ + +Routine Description: + + Correct the interrupt mode for a given vector. This is a no-op + as the correct interrupt mode was assigned in HalpGetInterruptMode. + +Arguments: + + Vector - Vector to correct. (Not used). + Irql - Not used. + +Return Value: + + None. + +--*/ + +{ + return; +} + + +ULONG +HalpGetSystemInterruptVector( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN ULONG BusInterruptLevel, + IN ULONG BusInterruptVector, + OUT PKIRQL Irql, + OUT PKAFFINITY Affinity + ) + +/*++ + +Routine Description: + +Arguments: + + BusInterruptLevel - Supplies the bus specific interrupt level. + + BusInterruptVector - Supplies the bus specific interrupt vector. + + Irql - Returns the system request priority. + + Affinity - Returns the system wide irq affinity. + +Return Value: + + Returns the system interrupt vector corresponding to the specified device. + +--*/ +{ + + UNREFERENCED_PARAMETER( BusHandler ); + UNREFERENCED_PARAMETER( RootHandler ); + + *Affinity = 1; + + // + // Set the IRQL level. Map the interrupt controllers priority scheme to + // NT irql values. The SIO prioritizes irq's as follows: + // + // irq0, irq1, irq8, irq9 ... irq15, irq3, irq4 ... irq7. + // + // The MPIC is a straight mapping. + // + + *Irql = HalpVectorToIrql[BusInterruptLevel]; + + + // + // The vector is equal to the specified bus level plus the DEVICE_VECTORS. + // + + return(BusInterruptLevel + DEVICE_VECTORS); + +} + +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 and acquire device enable spinlock. + // + + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + KiAcquireSpinLock(&HalpSystemInterruptLock); + + if (Vector >= DEVICE_VECTORS ) { + if ( Vector < DEVICE_VECTORS + MPIC_BASE_VECTOR ) { + + HalpDisableSioInterrupt(Vector); + + } else if ( Vector <= HalpMpicMaxVector ) { + + HalpDisableMpicInterrupt(Vector); + } + } + + // + // Release the device enable spin lock and lower IRQL to the previous level. + // + + KiReleaseSpinLock(&HalpSystemInterruptLock); + KeLowerIrql(OldIrql); + return; +} + +BOOLEAN +HalEnableSystemInterrupt ( + IN ULONG Vector, + IN KIRQL Irql, + IN KINTERRUPT_MODE InterruptMode + ) + +/*++ + +Routine Description: + + This routine enables the specified system interrupt. + +Arguments: + + Vector - Supplies the vector of the system interrupt that is enabled. + + Irql - Supplies the IRQL of the interrupting source. + + InterruptMode - Supplies the mode of the interrupt; LevelSensitive or + Latched. + +Return Value: + + TRUE if the system interrupt was enabled + +--*/ + +{ + + KIRQL OldIrql; + KINTERRUPT_MODE TranslatedInterruptMode; + + // + // Raise IRQL to the highest level and acquire device enable spinlock. + // + + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + KiAcquireSpinLock(&HalpSystemInterruptLock); + + if ( Vector >= DEVICE_VECTORS ) { + if ( Vector < DEVICE_VECTORS + MPIC_BASE_VECTOR ) { + + // + // It's an 8259 vector. + // + // Get translated interrupt mode + // + + + TranslatedInterruptMode = HalpGetInterruptMode(Vector, + Irql, + InterruptMode); + + + HalpEnableSioInterrupt(Vector, TranslatedInterruptMode); + + } else if ( Vector <= HalpMpicMaxVector ) { + + HalpEnableMpicInterrupt(Vector); + } + } + + // + // Release the device enable spin lock and lower IRQL to the previous level. + // + + KiReleaseSpinLock(&HalpSystemInterruptLock); + KeLowerIrql(OldIrql); + return TRUE; +} + +VOID +HalRequestIpi ( + IN ULONG Mask + ) + +/*++ + +Routine Description: + + This routine requests an interprocessor interrupt on a set of processors. + +Arguments: + + Mask - Supplies the set of processors that are sent an interprocessor + interrupt. + +Return Value: + + None. + +--*/ + +{ + extern ULONG Mpic2IpiBugFix; + extern ULONG HalpPhysicalIpiMask[]; + ULONG BugFix = Mpic2IpiBugFix; + ULONG PhysicalMask = 0; + PULONG PhysicalIpiMask = HalpPhysicalIpiMask; + ULONG OldMsr = __builtin_get_msr(); + + // + // Request an interprocessor interrupt on each of the specified target + // processors. + // + + __builtin_set_msr(OldMsr & 0xffff7fff); // Disable Interrupts + + // + // Mask is a mask of logical CPUs. Convert it to a mask of + // Physical CPUs so the IPI requests will be distributed + // properly. + // + + do { + if ( Mask & 1 ) { + PhysicalMask |= *PhysicalIpiMask; + } + PhysicalIpiMask++; + Mask >>= 1; + } while ( Mask ); + + // + // Send the IPI interrupt(s). + // + + HALPCR->MpicProcessorBase->Ipi[0 ^ BugFix].SelectProcessor = PhysicalMask; + + __builtin_set_msr(OldMsr); // Restore previous interrupt + // setting. + return; +} + +BOOLEAN +HalAcknowledgeIpi (VOID) + +/*++ + +Routine Description: + + This routine aknowledges an interprocessor interrupt on a set of + processors. + +Arguments: + + None + +Return Value: + + TRUE if the IPI is valid; otherwise FALSE is returned. + +--*/ + +{ + return (TRUE); +} + +BOOLEAN +HalpHandleIpi( + IN PVOID Unused0, + IN PVOID Unused1, + IN PVOID TrapFrame + ) + +/*++ + +Routine Description: + + This routine is entered as the result of an Inter-Processor Interrupt + being received by this processor. It passes the request onto the + kernel. + +Arguments: + + Unused0 - Not used. + Unused1 - Not used. + TrapFrame - Volatile context at time interrupt occured. + +Return Value: + + Returns TRUE (this routine always succeeds). + +--*/ + +{ + KeIpiInterrupt(TrapFrame); + + return TRUE; +} diff --git a/private/ntos/nthals/halvict/ppc/pxintrpt.h b/private/ntos/nthals/halvict/ppc/pxintrpt.h new file mode 100644 index 000000000..e75201f14 --- /dev/null +++ b/private/ntos/nthals/halvict/ppc/pxintrpt.h @@ -0,0 +1,103 @@ +/*++ + +Copyright (c) 1995 International Business Machines Corporation +Copyright (c) 1995 Microsoft Corporation + +Module Name: + + vectirql.h + +Abstract: + + This module implements machine specific interrupt functions + for IBM's PowerPC Machines. + + Code in this module was largely gathered from other modules + in earlier versions of the HAL. + +Author: + + Chris Karamatas - Collected VectorToIrql Tables into one file. + +Environment: + + Kernel mode. + +Revision History: + + +--*/ + + +// +// The following table maps Interrupt Vectors to the appropriate +// IRQL. The MPIC is initialized to assign vectors 16 thru 31 +// to its sources 0 thru 15. The 8259 gives us vectors 0 thru 15. +// +// It is possible that we are actually dealing with a Hydra, which +// is an MPIC with sources 0 through 19, so we have extra entries +// in the table. +// +// The MPIC is also programmed with priority in ascending order by +// vector (and source). +// +// This table should reflect the real mapping of vector to device +// priority. This implementation assumes that all MPIC sources +// are at a higher priority than 8259 sources. +// + +UCHAR HalpVectorToIrql[40] = { + + // 8259 Master, Priority 1 - 2 + + 18, // 0 Timer 1 Counter 0 + 17, // 1 Keyboard + 16, // 2 Cascade (not translated) + + 7, // 3 Com 2 + 6, // 4 Com 1 + 5, // 5 Audio + 4, // 6 Floppy + 3, // 7 Parallel Port + + // 8259 Slave, Priority 3-10 + + 15, // 8 RTC + 14, // 9 Audio (MIDI), ISA Slots pin B04 + 13, // 10 ISA Slots pin D03 + 12, // 11 ISA Slots pin D04 + 11, // 12 Mouse, ISA Slots pin D05 + 10, // 13 Power Management Interrupt + 9, // 14 ISA Slots pin D07 + 8, // 15 ISA Slots pin D06 + + // MPIC Sources - The following values are chosen arbitarily. Support + // should be added to reprogram the MPIC and this table + // once the device configuration is known. + + 0, // 0 8259 interrupt, will get from above + 19, // 1 + 20, // 2 + 20, // 3 + 21, // 4 + 21, // 5 + 22, // 6 + 22, // 7 + 23, // 8 + 23, // 9 + 24, // 10 + 24, // 11 + 25, // 12 + 25, // 13 + 26, // 14 + 26, // 15 + 26, // 16 Possible Hydra interrupt source + 26, // 17 Hydra + 26, // 18 Hydra + 26, // 19 Hydra + IPI_LEVEL, // 36 Reserved, PLUS IPI[0] + IPI_LEVEL, // 37 Reserved, PLUS IPI[1] + IPI_LEVEL, // 38 Reserved, PLUS IPI[2] + IPI_LEVEL, // 39 Reserved, PLUS IPI[3] +}; + diff --git a/private/ntos/nthals/halvict/ppc/pxirql.c b/private/ntos/nthals/halvict/ppc/pxirql.c new file mode 100644 index 000000000..de9a694e0 --- /dev/null +++ b/private/ntos/nthals/halvict/ppc/pxirql.c @@ -0,0 +1,337 @@ +// TITLE("Manipulate Interrupt Request Level") +//++ +// +// Copyright (c) 1990 Microsoft Corporation +// Copyright (c) 1995 International Business Machines Corporation +// +// Module Name: +// +// PXIRQL.C +// +// Abstract: +// +// This module implements the code necessary to lower and raise the current +// Interrupt Request Level (IRQL). +// +// +// Author: +// +// Jim Wooldridge (IBM) +// +// Environment: +// +// Kernel mode only. +// +// Revision History: +// +// Peter L Johnston (plj@vnet.ibm.com) August 1995. +// Rewrote for Lazy IRQL based on MPIC2. +// +// Jake Oshins (joshins@vnet.ibm.com) +// Support Victory machines +// +//-- + +#include "halp.h" +#include "pxmp.h" + +#define ISA_CONTROL ((PEISA_CONTROL) HalpIoControlBase) +extern UCHAR HalpSioInterrupt1Mask; +extern UCHAR HalpSioInterrupt2Mask; +extern BOOLEAN HalpProfilingActive; + +#if 0 +// +// The following is not used with Lazy IRQL/MPIC2 but the informationed +// contained herein is useful. +// +// VICTORY 8259 Interrupt assignments. +// +// IRQ Mask Device +// +// 0 0001 Timer 1 Counter 0 +// 1 0002 Keyboard +// 2 0004 2nd 8259 Cascade +// 3 0008 Serial Port 2, EISA IRQ3 +// 4 0010 Serial Port 1, EISA IRQ4 +// 5 0020 EISA IRQ5 +// 6 0040 Floppy Disk +// 7 0080 Parallel Port, ISA Slots pin B21 +// 8 0100 Real Time Clock +// 9 0200 EISA IRQ9 +// 10 0400 EISA IRQ10 +// 11 0800 EISA IRQ11 +// 12 1000 Mouse +// 13 2000 Power Management Interrupt (also SCSI) +// 14 4000 EISA IRQ14 (Mini-SP) +// 15 8000 EISA IRQ15 +// +// DORAL 8259 Interrupt assignments. +// +// IRQ Mask Device +// +// 0 0001 Timer 1 Counter 0 +// 1 0002 Keyboard +// 2 0004 2nd 8259 Cascade +// 3 0008 Serial Port 2, ISA Slots pin B25 +// 4 0010 Serial Port 1, ISA Slots pin B24 +// 5 0020 Audio, ISA Slots pin B23 +// 6 0040 Floppy Disk +// 7 0080 Parallel Port, ISA Slots pin B21 +// 8 0100 Real Time Clock +// 9 0200 Audio (MIDI), ISA Slots pin B04 +// 10 0400 ISA Slots pin D03 +// 11 0800 ISA Slots pin D04 +// 12 1000 Mouse, ISA Slots pin D05 +// 13 2000 Power Management Interrupt +// 14 4000 ISA Slots pin D07 +// 15 8000 ISA Slots pin D06 +// +// +// Victory MPIC2 IRQ assignments: +// Level Source +// 0 EISA 8259 Cascade +// 1 On-board SCSI +// 2 PCI Slot 1 A&C +// 3 PCI Slot 1 B&D +// 4 PCI Slot 2 A&C +// 5 PCI Slot 2 B&D +// 6 PCI Slot 3 A&C // this slot doesn't exist on some machines +// 7 PCI Slot 3 B&D +// 8 PCI Slot 4 A&C // beginning of secondary PCI bus +// 9 PCI Slot 4 B&D +// 10 PCI Slot 5 A&C +// 11 PCI Slot 5 B&D +// 12 PCI Slot 6 A&C +// 13 PCI Slot 6 B&D +// 14 PCI Slot 7 A&C +// 15 PCI Slot 7 B&D + +// +// Initialize the 8259 irql mask table. +// + +USHORT Halp8259MaskTable[] = { 0x0000, // irql0 Low level + 0x0000, // irql1 APC + 0x0000, // irql2 Dispatch + 0x0080, // irql3 parallel + 0x00c0, // irql4 floppy + 0x00e0, // irql5 audio + 0x00f0, // irql6 com 1 + 0x00f8, // irql7 com 2 + 0x80f8, // irql8 isa pin D06 + 0xc0f8, // irql9 isa pin D07 + 0xe0f8, // irql10 pow + 0xf0f8, // irql11 mouse, isa pin D05 + 0xf8f8, // irql12 isa pin D04 + 0xfcf8, // irql13 isa pin D03 + 0xfef8, // irql14 audio (MIDI), isa B04 + 0xfff8, // irql15 rtc + 0xfff8, // irql16 cascade + 0xfffa, // irql17 kb + 0xfffb, // irql18 timer 1/ profile + 0xffff, // irql19 clock level + 0xffff, // irql20 + 0xffff, // irql21 + 0xffff, // irql22 + 0xffff, // irql23 + 0xffff, // irql24 + 0xffff, // irql25 + 0xffff, // irql26 + 0xffff, // irql27 + 0xffff, // irql28 + 0xffff, // irql29 IPI Level + 0xffff, // irql30 + 0xffff // irql31 High level + }; +#endif + +// +// Map IRQL to MPIC2 TaskPriority. We are somewhat lazy here in that +// all 8259 interrupts are considered to be at the same level. This +// is so we can avoid setting the 8259 mask registers for the majority +// of Raise/Lower Irqls. +// + +UCHAR IrqlToTaskPriority[32] = { + + // User, APC and DISPATCH level all get TaskPriority of 1. + // (TaskPriority of 0 is for the IDLE loop). + + 1, // 0 + 1, // 1 + 1, // 2 + + // 8259 - mask source 0 (at priority 2) in the MPIC + + 2, // 3 - 18 + 2, // + 2, // + 2, // + 2, // + 2, // + 2, // + 2, // + 2, // + 2, // + 2, // + 2, // + 2, // + 2, // + 2, // + 2, // + + // MPIC source 1 (priority 3) + + // Spread this across the Victory + // PCI slots, with emphasis on the + // secondary PCI bus. + 3, // 19 + 4, // 20 + 5, // 21 + 6, // 22 + 7, // 23 + 8, // 24 + 9, // 25 + 10, // 26 + + // The following, except HIGH_LEVEL aren't used by Victory. + // Doral needs them. + + 11, // 27 + 12, // 28 DECREMENTER_LEVEL + 14, // 29 IPI_LEVEL + + // MPIC source 15, Power Fail. + + 15, // 30 POWER_LEVEL + 15 // 31 HIGH_LEVEL +}; + + + + +VOID +KiDispatchSoftwareInterrupt( + VOID + ); + + +VOID +KeLowerIrql( + KIRQL NewIrql + ) + +//++ +// +// VOID +// KeLowerIrql ( +// KIRQL NewIrql +// ) +// +// Routine Description: +// +// This function lowers the current IRQL to the specified value. +// +// Arguments: +// +// NewIrql - Supplies the new IRQL value. +// +// Return Value: +// +// None. +// +//-- + +{ + KIRQL OldIrql; + PUCHAR PIC_Address; + UCHAR PIC_Mask; + + + OldIrql = PCR->CurrentIrql; + + // + // If this is a software to software transition don't change hardware + // interrupt state + // + + if (OldIrql > DISPATCH_LEVEL) { + + ULONG TaskPriority = IrqlToTaskPriority[NewIrql]; + + HalpDisableInterrupts(); + HALPCR->MpicProcessorBase->TaskPriority = TaskPriority; + PCR->CurrentIrql = NewIrql; + HALPCR->HardPriority = TaskPriority; + + if ( NewIrql <= IPI_LEVEL ) { + + HalpEnableInterrupts(); + } + } else { + PCR->CurrentIrql = NewIrql; + } + + // + // check for DPC's + // + + if ((NewIrql < DISPATCH_LEVEL) && PCR->SoftwareInterrupt) { + KiDispatchSoftwareInterrupt(); + } +} + +/*************************************************************************/ + +// +// VOID KeRaiseIrql ( +// KIRQL NewIrql, +// PKIRQL OldIrql +// ) +// +// Routine Description: +// +// This function raises the current IRQL to the specified value and returns +// the old IRQL value. +// +// Arguments: +// +// NewIrql - Supplies the new IRQL value. +// +// OldIrql - Supplies a pointer to a variable that recieves the old +// IRQL value. +// + +VOID +KeRaiseIrql( + IN KIRQL NewIrql, + OUT PKIRQL OldIrql + ) + +{ + // + // If this is a software to software transition don't change hardware + // interrupt state + // + + if (NewIrql > DISPATCH_LEVEL) { + + ULONG TaskPriority = IrqlToTaskPriority[NewIrql]; + + HalpDisableInterrupts(); + + HALPCR->MpicProcessorBase->TaskPriority = TaskPriority; + *OldIrql = PCR->CurrentIrql; + PCR->CurrentIrql = NewIrql; + HALPCR->HardPriority = TaskPriority; + + if ( NewIrql <= IPI_LEVEL ) { + + HalpEnableInterrupts(); + } + } else { + *OldIrql = PCR->CurrentIrql; + PCR->CurrentIrql = NewIrql; + } +} diff --git a/private/ntos/nthals/halvict/ppc/pxisabus.c b/private/ntos/nthals/halvict/ppc/pxisabus.c new file mode 100644 index 000000000..a38788df8 --- /dev/null +++ b/private/ntos/nthals/halvict/ppc/pxisabus.c @@ -0,0 +1,2 @@ +#include "..\..\halppc\ppc\pxisabus.c" + diff --git a/private/ntos/nthals/halvict/ppc/pxmapio.c b/private/ntos/nthals/halvict/ppc/pxmapio.c new file mode 100644 index 000000000..38b6ef09e --- /dev/null +++ b/private/ntos/nthals/halvict/ppc/pxmapio.c @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxmapio.c> diff --git a/private/ntos/nthals/halvict/ppc/pxmemctl.c b/private/ntos/nthals/halvict/ppc/pxmemctl.c new file mode 100644 index 000000000..b3ada428d --- /dev/null +++ b/private/ntos/nthals/halvict/ppc/pxmemctl.c @@ -0,0 +1,706 @@ + +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file +contains copyrighted material. Use of this file is restricted +by the provisions of a Motorola Software License Agreement. + +Copyright (c) 1996 International Business Machines Corporation + +Module Name: + + pxmemctl.c + +Abstract: + + The module initializes any planar registers. + This module also implements machince check parity error handling. + +Author: + + Jim Wooldridge (jimw@austin.vnet.ibm.com) + + +Revision History: + + Jake Oshins (joshins@vnet.ibm.com) + Support newer Victory machines, (Lightning-2, Thunderbolt) + Peter L Johnston (plj@vnet.ibm.com) Handle UNION (aka Doral/Terlingua) + +--*/ + + + +#include "halp.h" +#include "pxmemctl.h" +#include "pxdakota.h" +#include "pci.h" +#include "pcip.h" +// #include "pxmp.h" +#include "ibmppc.h" + +#define BYTE_SWAP(x) ((((x) & 0x000000ff) << 24) | \ + (((x) & 0x0000ff00) << 8 ) | \ + (((x) & 0x00ff0000) >> 8 ) | \ + (((x) & 0xff000000) >> 24)) + +// +// Device ID/Vendor ID for IBM PCI Host Bridge (in UNION). +// + +#define IBMUNIONPCIBRIDGE 0x003a1014 + +// +// Prototype routines to be discarded at end of phase 1. +// + +BOOLEAN +HalpInitPlanar ( + VOID + ); + +BOOLEAN +HalpMapPlanarSpace ( + VOID + ); + +BOOLEAN +HalpMapBusConfigSpace ( + VOID + ); + +BOOLEAN +HalpPhase0MapBusConfigSpace ( + VOID + ); + +VOID +HalpPhase0UnMapBusConfigSpace ( + VOID + ); + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(INIT,HalpInitPlanar) +#pragma alloc_text(INIT,HalpMapPlanarSpace) +#pragma alloc_text(INIT,HalpMapBusConfigSpace) +#pragma alloc_text(INIT,HalpPhase0MapBusConfigSpace) +#pragma alloc_text(INIT,HalpPhase0UnMapBusConfigSpace) +#endif + + +// +// Virtual address of UNION System Control Registers (page). +// + +PVOID HalpUnionControlRegs; + +BOOLEAN +HalpInitPlanar ( + VOID + ) + +{ + + ULONG pcidata; + static Pass = 0; + + if ( Pass++ == 0 ) { + // + // This would be an error,... + // + return TRUE; + } + + switch (HalpSystemType) { + case IBM_VICTORY: + + // Write NMI status and control register NMISC + WRITE_PORT_UCHAR((PUCHAR)HalpIoControlBase + 0x61, 0x04); + + // Write Mode select register PCI-Eisa bridge + WRITE_PORT_UCHAR((PUCHAR)HalpIoControlBase + 0x22, 0x40); + WRITE_PORT_UCHAR((PUCHAR)HalpIoControlBase + 0x23, 0x40); + + + // Set it so that the memory controller (montana/nevada + // will not cause a machine check when he is the initiator + // of a transaction when a pci parity error takes place + // won't cause a machine check. A server should probably + // do things like parity checking + // on the PCI bus, but there are lots of broken adapters + // out there that don't generate PCI bus parity. + + // Read Montana Enable detection register (and surrounding bytes) + + HalpPhase0GetPciDataByOffset(0, // primary PCI bus + 0, // location of Montana/Nevada + &pcidata, + 0xc0, + 4); + + pcidata &= ~(1 << 5); + + // Now write back Montana Enable detection register + + HalpPhase0SetPciDataByOffset(0, // primary PCI bus + 0, // location of Montana/Nevada + &pcidata, + 0xc0, + 4); + break; + case IBM_DORAL: + HalpUnionControlRegs = HalpAssignReservedVirtualSpace( + UNION_SYSTEM_CONTROL_REG_BASE >> PAGE_SHIFT, + 1); + // + // If the above failed, there's nothing we can do about it now + // anyway. + // + break; + case IBM_TIGER: + // + // CPK? What goes here? + // + break; + } + return TRUE; +} + +BOOLEAN +HalpMapPlanarSpace ( + VOID + ) + +/*++ + +Routine Description: + + This routine maps the interrupt acknowledge register for the 8259. + +Arguments: + + None. + +Return Value: + + If the initialization is successfully completed, than a value of TRUE + is returned. Otherwise, a value of FALSE is returned. + +--*/ + +{ + PHYSICAL_ADDRESS physicalAddress; + + // + // Map 8259 interrupt control space. + // + + physicalAddress.HighPart = 0; + switch (HalpSystemType) { + case IBM_DORAL: + physicalAddress.LowPart = UNION_INTERRUPT_PHYSICAL_BASE; + break; + case IBM_VICTORY: + case IBM_TIGER: + physicalAddress.LowPart = INTERRUPT_PHYSICAL_BASE; + break; + } + HalpInterruptBase = MmMapIoSpace(physicalAddress, + PAGE_SIZE, + FALSE); + return TRUE; +} + +BOOLEAN +HalpMapBusConfigSpace ( + VOID + ) + +/*++ + +Routine Description: + + Access to the PCI Configuration and Data registers has already been + obtained. This routine does nothing. + +Arguments: + + None. + +Return Value: + + Returns TRUE. + +--*/ + +{ + return TRUE; +} + +BOOLEAN +HalpPhase0MapBusConfigSpace ( + VOID + ) + +/*++ + +Routine Description: + + Access to the PCI Configuration and Data registers has already been + obtained. This routine does nothing. + +Arguments: + + None. + +Return Value: + + Returns TRUE. + +--*/ + +{ + return TRUE; +} + +VOID +HalpPhase0UnMapBusConfigSpace ( + VOID + ) + +/*++ + +Routine Description: + + Return the space mapped above. Except we didn't actually map + anything above, so do nothing. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + return; +} + +VOID +HalpDisplayRegister( + PUCHAR RegHex, + ULONG Bytes + ) + +/*++ + +Routine Description: + + Displays (via HalDisplayString) a new-line terminated + string of hex digits representing the input value. The + input value is pointed to by the first argument is + from 1 to 4 bytes in length. + +Arguments: + + RegHex Pointer to the value to be displayed. + Bytes Length of input value in bytes (1-4). + +Return Value: + + None. + +--*/ + +{ +#define DISP_MAX 4 + + UCHAR RegString[(DISP_MAX * 2) + 2]; + UCHAR Num, High, Low; + PUCHAR Byte = &RegString[(DISP_MAX * 2) + 1]; + + *Byte = '\0'; + *--Byte = '\n'; + + if ( (unsigned)Bytes > DISP_MAX ) { + Bytes = DISP_MAX; + } + + while (Bytes--) { + Num = *RegHex++; + High = (Num >> 4) + '0'; + Low = (Num & 0xf) + '0'; + if ( High > '9' ) { + High += ('A' - '0' - 0xA); + } + if ( Low > '9' ) { + Low += ('A' - '0' - 0xA); + } + *--Byte = Low; + *--Byte = High; + } + HalDisplayString(Byte); +} + +VOID +HalpHandleVictoryMemoryError( + VOID + ) +{ + UCHAR StatusByte; + ULONG ErrorAddress; + + // + // Read the error address register first + // + + + ErrorAddress = READ_PORT_ULONG(HalpErrorAddressRegister); + + // + // Check TEA conditions + // + + StatusByte = READ_PORT_UCHAR(&((PDAKOTA_CONTROL) + HalpIoControlBase)->MemoryParityErrorStatus); + + if (!(StatusByte & 0x01)) { + HalDisplayString("TEA: Memory Parity Error at Address "); + HalpDisplayRegister((PUCHAR)&ErrorAddress, sizeof(ErrorAddress)); + } + + StatusByte = READ_PORT_UCHAR(&((PDAKOTA_CONTROL) + HalpIoControlBase)->L2CacheErrorStatus); + + if (!(StatusByte & 0x01)) { + HalDisplayString ("TEA: L2 Cache Parity Error\n"); + } + + StatusByte = READ_PORT_UCHAR(&((PDAKOTA_CONTROL) + HalpIoControlBase)->TransferErrorStatus); + + if (!(StatusByte & 0x01)) { + HalDisplayString ("TEA: Transfer Error at Address "); + HalpDisplayRegister((PUCHAR)&ErrorAddress, sizeof(ErrorAddress)); + } +} + +VOID +HalpHandleTigerMemoryError( + VOID + ) +{ + // CPK: Your turn. (plj). +} + +VOID +HalpHandleDoralMemoryError( + VOID + ) + +{ + static ULONG RecursionLevel = 0; + ULONG Status; + ULONG Address; + ULONG PciCsr0; + ULONG PciCsr1; + ULONG PciPlssr0; + ULONG PciPlssr1; + ULONG MemErrorStatus; + ULONG MemErrorAddress; + ULONG OldPciConfigAddress; + ULONG HostBridgePciAddress = 0x80000000; + ULONG PciConfigData; + ULONG PciBridgeFound = 0; + UCHAR Syndrome = 0; + PCHAR PciBusString; + extern KSPIN_LOCK HalpPCIConfigLock; + extern PVOID HalpPciConfigAddr[]; + extern PVOID HalpPciConfigData[]; + extern UCHAR HalpEpciMin; + + switch ( ++RecursionLevel ) { + case 1: + // + // Read the System Error Status Register and try to display + // something reasonable based on what's in there. + // + + Status = *(PULONG)((ULONG)HalpUnionControlRegs + UNION_SESR); + Status = BYTE_SWAP(Status); + + // + // Before calling HalDisplayString which will interact with + // the PCI bus, try to gather all the pertinent info. + // + PciCsr0 = *((PULONG)HalpPciConfigAddr[0] + UNION_PCI_CSR_OFFSET); + PciCsr1 = *((PULONG)HalpPciConfigAddr[1] + UNION_PCI_CSR_OFFSET); + PciPlssr0 = *((PULONG)HalpPciConfigAddr[0] + UNION_PCI_PLSSR_OFFSET); + PciPlssr1 = *((PULONG)HalpPciConfigAddr[1] + UNION_PCI_PLSSR_OFFSET); + + if ( Status & ~(UNION_SEAR_NOT_SET) ) { + // + // Status Error Address Register contains valid data, + // display it also. + // + Address = *(PULONG)((ULONG)HalpUnionControlRegs + UNION_SEAR); + Address = BYTE_SWAP(Address); + + } else if ( Status & + (UNION_SESR_PCI32_BUS_MASTER | UNION_SESR_PCI64_BUS_MASTER) ) { + + ULONG i = 0; + PciBusString = "on the 32 bit PCI bus.\n"; + if ( Status & UNION_SESR_PCI64_BUS_MASTER ) { + i = 1; + PciBusString = "on the 64 bit PCI bus.\n"; + } + + // + // The error was a PCI error. It is possible we are still + // holding the PCI config access lock, so, unconditionally + // blow it away. + // + // However, we need to access the PCI config space for the + // bridge, so we need the lock but cannot acquire it in the + // usual way, (a) because it may already be locked, and (b) + // KeAcquireSpinLock will change IRQL. + // + // WARNING: Arcane knowledge about what a KSPIN_LOCK really + // is! + // + + HalpPCIConfigLock = 0xdeaddead; + __builtin_isync(); + + // + // Get current value of this bridge's PCI CONFIG ADDRESS + // register. + // + + OldPciConfigAddress = *(PULONG)(HalpPciConfigAddr[i]); + __builtin_sync(); + + // + // Set address for access to the host PCI bridge's config + // space. + // + + if ( i != 0 ) { + // + // EPCI Bridge. + // + + HostBridgePciAddress |= HalpEpciMin << 16; + } + + *(PULONG)(HalpPciConfigAddr[i]) = HostBridgePciAddress; + __builtin_sync(); + + PciConfigData = *(PULONG)(HalpPciConfigData[i]); + + if ( PciConfigData == IBMUNIONPCIBRIDGE ) { + PciBridgeFound = 1; + *(PULONG)(HalpPciConfigAddr[i]) = HostBridgePciAddress + 4; + __builtin_sync(); + + PciConfigData = *(PULONG)(HalpPciConfigData[i]); + } + + // + // Release spin lock. + // + + HalpPCIConfigLock = 0; + } + + if ( Status & UNION_SESR_CPU_MEMORY_ACCESS ) { + // + // Memory Error. Read the Memory Error Status and + // Memory Error Address registers as well. + // + MemErrorStatus = *(PULONG) + ((ULONG)HalpUnionControlRegs + UNION_MESR); + MemErrorStatus = BYTE_SWAP(MemErrorStatus); + MemErrorAddress = *(PULONG) + ((ULONG)HalpUnionControlRegs + UNION_MEAR); + MemErrorAddress = BYTE_SWAP(MemErrorAddress); + Syndrome = (UCHAR)(MemErrorStatus & 0xff); + } + + HalDisplayString("Machine Check : System Error Status = 0x"); + HalpDisplayRegister((PUCHAR)&Status, sizeof(Status)); + + if ( Status & ~(UNION_SEAR_NOT_SET) ) { + HalDisplayString(" System Error Address = 0x"); + HalpDisplayRegister((PUCHAR)&Address, sizeof(Address)); + } + + // + // The following strangness is just in case it is possible + // for more than one bit to be set. + // + + if ( Status & UNION_SESR_CHECKSTOP ) { + HalDisplayString("UNION initiated checkstop.\n"); + } + + if ( Status & UNION_SESR_FLASH_WRITE ) { + HalDisplayString("FLASH Write Error. A write to flash\n"); + HalDisplayString("memory was attempted but is not enabled.\n"); + } + + if ( Status & UNION_SESR_IGMC_ACCESS ) { + HalDisplayString("Access performed to IGMC when not enabled.\n"); + } + + if ( Status & UNION_SESR_DISABLED_ADDRESS ) { + HalDisplayString("Access performed to system I/O\n"); + HalDisplayString("address space that is not enabled.\n"); + } + + if ( Status & UNION_SESR_T1_ACCESS ) { + HalDisplayString( + "T = 1 Access Error, a T = 1 PIO cycle was detected.\n"); + } + + if ( Status & UNION_SESR_ADDRESS_BUS_PARITY ) { + HalDisplayString("Address bus parity error.\n"); + } + + if ( Status & UNION_SESR_DATA_BUS_PARITY ) { + HalDisplayString("Data bus parity error.\n"); + } + + if ( Status & UNION_SESR_NO_L2_HIT_ACCESS ) { + HalDisplayString( + "L2_HIT_signal not active after AACK_; Addressing error.\n"); + } + + if ( Status & UNION_SESR_CPU_TO_PCI_ACCESS ) { + HalDisplayString( + "An error occurred on PCI bus while processing a load/store request.\n"); + } + + if ( Status & + (UNION_SESR_PCI32_BUS_MASTER | UNION_SESR_PCI64_BUS_MASTER) ) { + HalDisplayString( + "An error occurred during a PCI master initiated operation\n"); + HalDisplayString(PciBusString); + HalDisplayString("Last PCI Configuration Address = 0x"); + HalpDisplayRegister((PUCHAR)&OldPciConfigAddress, + sizeof(OldPciConfigAddress)); + if ( PciBridgeFound ) { + HalDisplayString("PCI Bridge Status/Command = 0x"); + HalpDisplayRegister((PUCHAR)&PciConfigData, + sizeof(PciConfigData)); + } + } + if ( PciCsr0 ) { + HalDisplayString("Channel Status [32 bit bus] = 0x"); + HalpDisplayRegister((PUCHAR)&PciCsr0, sizeof(PciCsr0)); + } + if ( PciPlssr0 ) { + HalDisplayString("Processor Load/Store Status [32 bit bus] = 0x"); + HalpDisplayRegister((PUCHAR)&PciPlssr0, sizeof(PciPlssr0)); + } + if ( PciCsr1 ) { + HalDisplayString("Channel Status [64 bit bus] = 0x"); + HalpDisplayRegister((PUCHAR)&PciCsr1, sizeof(PciCsr1)); + } + if ( PciPlssr1 ) { + HalDisplayString("Processor Load/Store Status [32 bit bus] = 0x"); + HalpDisplayRegister((PUCHAR)&PciPlssr1, sizeof(PciPlssr1)); + } + + if ( Status & UNION_SESR_XFERDATA ) { + HalDisplayString( + "An error occured during an operation in the memory\n"); + HalDisplayString("controller's XferData unit.\n"); + } + + if ( Status & UNION_SESR_DATA_BUS_TIMEOUT ) { + // + // N.B. This error cannot be detected except via JTAG logic + // as UNION will checkstop rather than machine check in this + // case. This error indicates that the 60x bus did not + // respond in 8ms. + // + HalDisplayString("Data bus timeout.\n"); + } + + if ( Status & UNION_SESR_CPU_MEMORY_ACCESS ) { + HalDisplayString( + "An error occurred during a memory access by the CPU.\n"); + HalDisplayString("Memory Error Status Register = 0x"); + HalpDisplayRegister((PUCHAR)&MemErrorStatus, + sizeof(MemErrorStatus)); + HalDisplayString("Memory Error Address Register = 0x"); + HalpDisplayRegister((PUCHAR)&MemErrorAddress, + sizeof(MemErrorAddress)); + + if ( MemErrorStatus & UNION_MESR_DOUBLE_BIT ) { + HalDisplayString( + "bit 0 - A double bit memory error was detected.\n"); + HalDisplayString( + " Syndrome bits = 0x"); + HalpDisplayRegister(&Syndrome, sizeof(UCHAR)); + } + + if ( MemErrorStatus & UNION_MESR_SINGLE_BIT ) { + HalDisplayString( + "bit 1 - A single bit memory error was detected/corrected.\n"); + if ( !(MemErrorStatus & UNION_MESR_SINGLE_BIT) ) { + HalDisplayString( + " Syndrome bits = 0x"); + HalpDisplayRegister(&Syndrome, sizeof(UCHAR)); + } else { + HalDisplayString( + " Error Address and Syndrome are for the Double bit error only.\n"); + } + } + + if ( MemErrorStatus & UNION_MESR_OVERLAPPED_MEM_EXT ) { + HalDisplayString( + "bit 3 - An access to an address that is mapped in two different memory\n"); + HalDisplayString( + " extents was detected. This is a System Software error.\n"); + } + } + break; + case 2: + HalDisplayString( + "Machine Check while trying to report Machine Check\n"); + default: + // + // If we get here we took a second machine check while processing + // the first. Just hang. + // + for (;;); + } +} + +VOID +HalpHandleMemoryError( + VOID + ) + +{ + switch (HalpSystemType) { + case IBM_VICTORY: + HalpHandleVictoryMemoryError(); + return; + case IBM_DORAL: + HalpHandleDoralMemoryError(); + return; + case IBM_TIGER: + HalpHandleTigerMemoryError(); + return; + } + return; +} diff --git a/private/ntos/nthals/halvict/ppc/pxmemctl.h b/private/ntos/nthals/halvict/ppc/pxmemctl.h new file mode 100644 index 000000000..569bae171 --- /dev/null +++ b/private/ntos/nthals/halvict/ppc/pxmemctl.h @@ -0,0 +1,143 @@ +/*++ BUILD Version: 0001 // Increment this if a change has global effects + +Copyright (c) 1996 International Business Machines Corporation + + +Module Name: + + pxmemctl.h + +Abstract: + + This header file defines the structures for the planar registers + for an Idaho memory controller. + + + + +Author: + + Jim Wooldridge + + +Revision History: + + Peter L Johnston (plj@vnet.ibm.com) August 1995. + Doral. + +--*/ + + +// +// define physical base addresses of planar registers (non UNION) +// + +#define INTERRUPT_PHYSICAL_BASE 0xbffffff0 // physical base of interrupt source +#define ERROR_ADDRESS_REGISTER 0xbfffeff0 + +// +// define physical base addresses of UNION planar registers +// + +// +// 8259 Interrupt Source (DORAL) +// + +#define UNION_INTERRUPT_PHYSICAL_BASE 0xbfff7700 + +// +// IO Space (ISA) +// + +#define IO_CONTROL_PHYSICAL_BASE 0x80000000 + +// +// UNION System Control Registers +// + +#define UNION_SYSTEM_CONTROL_REG_BASE 0xff001000 + +// +// System Error Control Register (offset from UNION_SYSTEM_CONTROL_REG_BASE) +// + +#define UNION_SECR 0x50 + +// +// System Error Status Register (offset) +// + +#define UNION_SESR 0x60 + +// +// System Error Address Register (offset) +// + +#define UNION_SEAR 0x70 + +// +// Memory Error Status Register (offset) +// + +#define UNION_MESR 0x120 + +// +// Memory Error Address Register (offset) +// + +#define UNION_MEAR 0x130 + +// +// System Error Status Register bit definitions. +// + +// Reserved 0xe0000000 +#define UNION_SESR_CHECKSTOP 0x20000000 +#define UNION_SESR_FLASH_WRITE 0x10000000 +#define UNION_SESR_IGMC_ACCESS 0x08000000 +#define UNION_SESR_DISABLED_ADDRESS 0x04000000 +// Reserved 0x03f00000 +#define UNION_SESR_T1_ACCESS 0x00080000 +#define UNION_SESR_ADDRESS_BUS_PARITY 0x00040000 +#define UNION_SESR_DATA_BUS_PARITY 0x00020000 +#define UNION_SESR_NO_L2_HIT_ACCESS 0x00010000 +#define UNION_SESR_CPU_TO_PCI_ACCESS 0x00008000 +#define UNION_SESR_PCI32_BUS_MASTER 0x00004000 +#define UNION_SESR_PCI64_BUS_MASTER 0x00002000 +#define UNION_SESR_XFERDATA 0x00001000 +#define UNION_SESR_DATA_BUS_TIMEOUT 0x00000800 +#define UNION_SESR_CPU_MEMORY_ACCESS 0x00000400 +// Reserved 0x000003ff + +// +// Bits 17, 18 and 19 above represent PCI initiated errors and +// the System Error Address Register is not updated. In these +// cases the PCI bridges or xferdata logic must be interogated +// to determine the cause of the error. Bit 16 also requires +// bridge interrogation. +// + +#define UNION_SEAR_NOT_SET (UNION_SESR_PCI32_BUS_MASTER | \ + UNION_SESR_PCI64_BUS_MASTER | \ + UNION_SESR_XFERDATA) + +// +// Memory Error Status Register bit definitions +// + +#define UNION_MESR_DOUBLE_BIT 0x80000000 +#define UNION_MESR_SINGLE_BIT 0x40000000 +#define UNION_MESR_ADDRESS 0x20000000 +#define UNION_MESR_OVERLAPPED_MEM_EXT 0x10000000 +//reserved 0x0fffff00 +#define UNION_MESR_SYNDROME 0x000000ff + +// +// UNION Channel Status Register is at offset 0x1800 from the PCI Config +// Address register. Processor Load/Store Status Register is at offset +// 0x1810. +// + +#define UNION_PCI_CSR_OFFSET 0x1800 +#define UNION_PCI_PLSSR_OFFSET 0x1810 + diff --git a/private/ntos/nthals/halvict/ppc/pxmisc.s b/private/ntos/nthals/halvict/ppc/pxmisc.s new file mode 100644 index 000000000..2afe3e6da --- /dev/null +++ b/private/ntos/nthals/halvict/ppc/pxmisc.s @@ -0,0 +1,2 @@ +#include "..\..\halppc\ppc\pxmisc.s" + diff --git a/private/ntos/nthals/halvict/ppc/pxnatsup.c b/private/ntos/nthals/halvict/ppc/pxnatsup.c new file mode 100644 index 000000000..45b71d905 --- /dev/null +++ b/private/ntos/nthals/halvict/ppc/pxnatsup.c @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxnatsup.c> diff --git a/private/ntos/nthals/halvict/ppc/pxp91.c b/private/ntos/nthals/halvict/ppc/pxp91.c new file mode 100644 index 000000000..0427a3f5f --- /dev/null +++ b/private/ntos/nthals/halvict/ppc/pxp91.c @@ -0,0 +1,2 @@ +#include "..\..\halppc\ppc\pxp91.c" + diff --git a/private/ntos/nthals/halvict/ppc/pxpcibrd.c b/private/ntos/nthals/halvict/ppc/pxpcibrd.c new file mode 100644 index 000000000..d10d244dd --- /dev/null +++ b/private/ntos/nthals/halvict/ppc/pxpcibrd.c @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxpcibrd.c> diff --git a/private/ntos/nthals/halvict/ppc/pxpcibus.c b/private/ntos/nthals/halvict/ppc/pxpcibus.c new file mode 100644 index 000000000..ae07be2d7 --- /dev/null +++ b/private/ntos/nthals/halvict/ppc/pxpcibus.c @@ -0,0 +1,2318 @@ +/*++ + + +Copyright (c) 1989 Microsoft Corporation + +Copyright (c) 1996 International Business Machines Corporation + +Module Name: + + pxpcidat.c + +Abstract: + + Get/Set bus data routines for the PCI bus + +Author: + + Ken Reneris (kenr) 14-June-1994 + Jim Wooldridge Port to PowerPC + +Environment: + + Kernel mode + +Revision History: + + Chris Karamatas (ckaramatas@vnet.ibm.com) - Updated and merged support for various PPC boxes. + Jake Oshins (joshins@vnet.ibm.com) -- Further merging and generalization, support for more boxes. + +--*/ + +#include "halp.h" +#include "pci.h" +#include "pcip.h" +#include "ibmppc.h" + +#define PCI_DISPLAY_CONTROLLER 0x03 +#define PCI_PRE_REV_2 0x0 +#define IsVideoDevice(a) \ + (((a->BaseClass == PCI_DISPLAY_CONTROLLER) && \ + (a->SubClass == 0)) || \ + (((a->BaseClass == PCI_PRE_REV_2) && \ + (a->SubClass == 1)))) + +extern WCHAR rgzMultiFunctionAdapter[]; +extern WCHAR rgzConfigurationData[]; +extern WCHAR rgzIdentifier[]; +extern WCHAR rgzPCIIdentifier[]; + +ULONG HalpPciMaxBuses = 0; +extern ULONG HalpPciMaxSlots; +extern PVOID HalpPciConfigAddr[]; +extern PVOID HalpPciConfigData[]; +extern UCHAR HalpEpciMin; +extern UCHAR HalpEpciMax; + +typedef ULONG (*FncConfigIO) ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +typedef VOID (*FncSync) ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PKIRQL Irql, + IN PVOID State + ); + +typedef VOID (*FncReleaseSync) ( + IN PBUS_HANDLER BusHandler, + IN KIRQL Irql + ); + +typedef struct _PCI_CONFIG_HANDLER { + FncSync Synchronize; + FncReleaseSync ReleaseSynchronzation; + FncConfigIO ConfigRead[3]; + FncConfigIO ConfigWrite[3]; +} PCI_CONFIG_HANDLER, *PPCI_CONFIG_HANDLER; + +// +// Prototypes +// + +ULONG +HalpGetPCIData ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER SlotNumber, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ); + +ULONG +HalpSetPCIData ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER SlotNumber, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ); + +NTSTATUS +HalpAssignPCISlotResources ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PUNICODE_STRING RegistryPath, + IN PUNICODE_STRING DriverClassName OPTIONAL, + IN PDRIVER_OBJECT DriverObject, + IN PDEVICE_OBJECT DeviceObject OPTIONAL, + IN ULONG SlotNumber, + IN OUT PCM_RESOURCE_LIST *AllocatedResources + ); + +BOOLEAN +HalpIsValidPCIDevice ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot + ); + +BOOLEAN +HalpValidPCISlot ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot + ); + +//------------------------------------------------- + +VOID HalpPCISynchronizeType1 ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PKIRQL Irql, + IN PVOID State + ); + +VOID HalpPCIReleaseSynchronzationType1 ( + IN PBUS_HANDLER BusHandler, + IN KIRQL Irql + ); + +ULONG HalpPCIReadUlongType1 ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +ULONG HalpPCIReadUcharType1 ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +ULONG HalpPCIReadUshortType1 ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +ULONG HalpPCIWriteUlongType1 ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +ULONG HalpPCIWriteUcharType1 ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +ULONG HalpPCIWriteUshortType1 ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +VOID HalpPCISynchronizeType2 ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PKIRQL Irql, + IN PVOID State + ); + +VOID HalpPCIReleaseSynchronzationType2 ( + IN PBUS_HANDLER BusHandler, + IN KIRQL Irql + ); + +ULONG HalpPCIReadUlongType2 ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +ULONG HalpPCIReadUcharType2 ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +ULONG HalpPCIReadUshortType2 ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +ULONG HalpPCIWriteUlongType2 ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +ULONG HalpPCIWriteUcharType2 ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +ULONG HalpPCIWriteUshortType2 ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + + +// +// Globals +// + +KSPIN_LOCK HalpPCIConfigLock; + +PCI_CONFIG_HANDLER PCIConfigHandler; + +PCI_CONFIG_HANDLER PCIConfigHandlerType1 = { + HalpPCISynchronizeType1, + HalpPCIReleaseSynchronzationType1, + { + HalpPCIReadUlongType1, // 0 + HalpPCIReadUcharType1, // 1 + HalpPCIReadUshortType1 // 2 + }, + { + HalpPCIWriteUlongType1, // 0 + HalpPCIWriteUcharType1, // 1 + HalpPCIWriteUshortType1 // 2 + } +}; + +PCI_CONFIG_HANDLER PCIConfigHandlerType2 = { + HalpPCISynchronizeType2, + HalpPCIReleaseSynchronzationType2, + { + HalpPCIReadUlongType2, // 0 + HalpPCIReadUcharType2, // 1 + HalpPCIReadUshortType2 // 2 + }, + { + HalpPCIWriteUlongType2, // 0 + HalpPCIWriteUcharType2, // 1 + HalpPCIWriteUshortType2 // 2 + } +}; + +UCHAR PCIDeref[4][4] = { {0,1,2,2},{1,1,1,1},{2,1,2,2},{1,1,1,1} }; + +VOID +HalpPCIConfig ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PUCHAR Buffer, + IN ULONG Offset, + IN ULONG Length, + IN FncConfigIO *ConfigIO + ); + +#if DBG +#define DBGMSG(a) DbgPrint(a) +VOID +HalpTestPci ( + ULONG + ); +#else +#define DBGMSG(a) +#endif + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(INIT,HalpInitializePciBus) +#pragma alloc_text(INIT,HalpAllocateAndInitPciBusHandler) +#pragma alloc_text(INIT,HalpIsValidPCIDevice) +#pragma alloc_text(PAGE,HalpAssignPCISlotResources) +#endif + + + +VOID +HalpInitializePciBus ( + VOID + ) +{ + PPCI_REGISTRY_INFO PCIRegInfo; + UNICODE_STRING unicodeString, ConfigName, IdentName; + OBJECT_ATTRIBUTES objectAttributes; + HANDLE hMFunc, hBus; + NTSTATUS status; + UCHAR buffer [sizeof(PPCI_REGISTRY_INFO) + 99]; + PWSTR p; + WCHAR wstr[8]; + ULONG i, d, junk, HwType, BusNo, f; + PBUS_HANDLER BusHandler; + PCI_SLOT_NUMBER SlotNumber; + PPCI_COMMON_CONFIG PciData; + UCHAR iBuffer[PCI_COMMON_HDR_LENGTH]; + PKEY_VALUE_FULL_INFORMATION ValueInfo; + PCM_FULL_RESOURCE_DESCRIPTOR Desc; + PCM_PARTIAL_RESOURCE_DESCRIPTOR PDesc; + + // + // Search the hardware description looking for any reported + // PCI bus. The first ARC entry for a PCI bus will contain + // the PCI_REGISTRY_INFO. + + // + RtlInitUnicodeString (&unicodeString, rgzMultiFunctionAdapter); + InitializeObjectAttributes ( + &objectAttributes, + &unicodeString, + OBJ_CASE_INSENSITIVE, + NULL, // handle + NULL); + + + status = ZwOpenKey (&hMFunc, KEY_READ, &objectAttributes); + if (!NT_SUCCESS(status)) { + return ; + } + + unicodeString.Buffer = wstr; + unicodeString.MaximumLength = sizeof (wstr); + + RtlInitUnicodeString (&ConfigName, rgzConfigurationData); + RtlInitUnicodeString (&IdentName, rgzIdentifier); + + ValueInfo = (PKEY_VALUE_FULL_INFORMATION) buffer; + + for (i=0; TRUE; i++) { + RtlIntegerToUnicodeString (i, 10, &unicodeString); + InitializeObjectAttributes ( + &objectAttributes, + &unicodeString, + OBJ_CASE_INSENSITIVE, + hMFunc, + NULL); + + status = ZwOpenKey (&hBus, KEY_READ, &objectAttributes); + if (!NT_SUCCESS(status)) { + // + // Out of Multifunction adapter entries... + // + + ZwClose (hMFunc); + return ; + } + + // + // Check the Indentifier to see if this is a PCI entry + // + + status = ZwQueryValueKey ( + hBus, + &IdentName, + KeyValueFullInformation, + ValueInfo, + sizeof (buffer), + &junk + ); + + if (!NT_SUCCESS (status)) { + ZwClose (hBus); + continue; + } + + p = (PWSTR) ((PUCHAR) ValueInfo + ValueInfo->DataOffset); + if (p[0] != L'P' || p[1] != L'C' || p[2] != L'I' || p[3] != 0) { + ZwClose (hBus); + continue; + } + + // + // The first PCI entry has the PCI_REGISTRY_INFO structure + // attached to it. + // + + status = ZwQueryValueKey ( + hBus, + &ConfigName, + KeyValueFullInformation, + ValueInfo, + sizeof (buffer), + &junk + ); + + ZwClose (hBus); + if (!NT_SUCCESS(status)) { + continue ; + } + + Desc = (PCM_FULL_RESOURCE_DESCRIPTOR) ((PUCHAR) + ValueInfo + ValueInfo->DataOffset); + PDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) ((PUCHAR) + Desc->PartialResourceList.PartialDescriptors); + + if (PDesc->Type == CmResourceTypeDeviceSpecific) { + // got it.. + PCIRegInfo = (PPCI_REGISTRY_INFO) (PDesc+1); + break; + } + } + + // + // Initialize spinlock for synchronizing access to PCI space + // + + KeInitializeSpinLock (&HalpPCIConfigLock); + PciData = (PPCI_COMMON_CONFIG) iBuffer; + + // + // PCIRegInfo describes the system's PCI support as indicated by the BIOS. + // + + HwType = PCIRegInfo->HardwareMechanism & 0xf; + + // + // For each PCI bus present, allocate a handler structure and + // fill in the dispatch functions + // + + do { + for (i=0; i < PCIRegInfo->NoBuses; i++) { + + // + // If handler not already built, do it now + // + + if (!HalpHandlerForBus (PCIBus, i)) { + HalpAllocateAndInitPciBusHandler (HwType, i, FALSE); + } + } + + // + // Bus handlers for all PCI buses have been allocated, go collect + // pci bridge information. + // + + } while (HalpGetPciBridgeConfig (HwType, &PCIRegInfo->NoBuses)) ; + + // + // Fixup SUPPORTED_RANGES + // + + HalpFixupPciSupportedRanges (PCIRegInfo->NoBuses); + + // + // Look for PCI controllers which have known work-arounds, and make + // sure they are applied. + // + + SlotNumber.u.bits.Reserved = 0; + for (BusNo=0; BusNo < PCIRegInfo->NoBuses; BusNo++) { + BusHandler = HalpHandlerForBus (PCIBus, BusNo); + + for (d = 0; d < PCI_MAX_DEVICES; d++) { + SlotNumber.u.bits.DeviceNumber = d; + + for (f = 0; f < PCI_MAX_FUNCTION; f++) { + SlotNumber.u.bits.FunctionNumber = f; + + // + // Read PCI configuration information + // + + HalpReadPCIConfig (BusHandler, SlotNumber, PciData, 0, PCI_COMMON_HDR_LENGTH); + + // + // Check for chips with known work-arounds to apply + // + + if (PciData->VendorID == 0x8086 && + PciData->DeviceID == 0x04A3 && + PciData->RevisionID < 0x11) { + + // + // 82430 PCMC controller + // + + HalpReadPCIConfig (BusHandler, SlotNumber, buffer, 0x53, 2); + + buffer[0] &= ~0x08; // turn off bit 3 register 0x53 + + if (PciData->RevisionID == 0x10) { // on rev 0x10, also turn + buffer[1] &= ~0x01; // bit 0 register 0x54 + } + + HalpWritePCIConfig (BusHandler, SlotNumber, buffer, 0x53, 2); + } + + if (PciData->VendorID == 0x8086 && + PciData->DeviceID == 0x0484 && + PciData->RevisionID <= 3) { + + // + // 82378 ISA bridge & SIO + // + + HalpReadPCIConfig (BusHandler, SlotNumber, buffer, 0x41, 1); + + buffer[0] &= ~0x1; // turn off bit 0 register 0x41 + + HalpWritePCIConfig (BusHandler, SlotNumber, buffer, 0x41, 1); + } + + } // next function + } // next device + } // next bus + +#if DBG + HalpTestPci (0); +#endif +} + + +PBUS_HANDLER +HalpAllocateAndInitPciBusHandler ( + IN ULONG HwType, + IN ULONG BusNo, + IN BOOLEAN TestAllocation + ) +{ + PBUS_HANDLER Bus; + PPCIPBUSDATA BusData; + ULONG UnionBridge; + + Bus = HalpAllocateBusHandler ( + PCIBus, // Interface type + PCIConfiguration, // Has this configuration space + BusNo, // bus # + Internal, // child of this bus + 0, // and number + sizeof (PCIPBUSDATA) // sizeof bus specific buffer + ); + + // + // Fill in PCI handlers + // + + Bus->GetBusData = (PGETSETBUSDATA) HalpGetPCIData; + Bus->SetBusData = (PGETSETBUSDATA) HalpSetPCIData; + Bus->GetInterruptVector = (PGETINTERRUPTVECTOR) HalpGetPCIIntOnISABus; + Bus->AdjustResourceList = (PADJUSTRESOURCELIST) HalpAdjustPCIResourceList; + Bus->AssignSlotResources = (PASSIGNSLOTRESOURCES) HalpAssignPCISlotResources; + Bus->BusAddresses->Dma.Limit = 0; + + BusData = (PPCIPBUSDATA) Bus->BusData; + + // + // Fill in common PCI data + // + + BusData->CommonData.Tag = PCI_DATA_TAG; + BusData->CommonData.Version = PCI_DATA_VERSION; + BusData->CommonData.ReadConfig = (PciReadWriteConfig) HalpReadPCIConfig; + BusData->CommonData.WriteConfig = (PciReadWriteConfig) HalpWritePCIConfig; + BusData->CommonData.Pin2Line = (PciPin2Line) HalpPCIPin2ISALine; + BusData->CommonData.Line2Pin = (PciLine2Pin) HalpPCIISALine2Pin; + + // set defaults + + BusData->GetIrqRange = (PciIrqRange) HalpGetPCIIrq; + + + RtlInitializeBitMap (&BusData->DeviceConfigured, + BusData->ConfiguredBits, 256); + + switch (HwType) { + case 1: + // + // Initialize access port information for Type1 handlers + // + + RtlCopyMemory (&PCIConfigHandler, + &PCIConfigHandlerType1, + sizeof (PCIConfigHandler)); + + BusData->MaxDevice = HalpPciMaxSlots; + break; + + case 2: + // + // Initialize access port information for Type2 handlers + // + + RtlCopyMemory (&PCIConfigHandler, + &PCIConfigHandlerType2, + sizeof (PCIConfigHandler)); + + // + // If BusNo is in the range of busses supported on UNION's + // EPCI bus, initialize the BusData for the appropriate + // bridge. + // + // N.B. Initialization is such that non-UNION machines + // correct values are obtained. + // + if ( (BusNo < HalpEpciMin) || (BusNo > HalpEpciMax) ) { + UnionBridge = 0; + } else { + UnionBridge = 1; + } + BusData->Config.Type2.Address = + HalpPciConfigAddr[UnionBridge]; + BusData->Config.Type2.Data = + HalpPciConfigData[UnionBridge]; + + // + // Early PCI machines didn't decode the last bit of + // the device id. Shrink type 2 support max device. + // + BusData->MaxDevice = HalpPciMaxSlots; + + break; + + default: + // unsupport type + DBGMSG ("HAL: Unkown PCI type\n"); + } + + if (!TestAllocation) { +#ifdef SUBCLASSPCI + HalpSubclassPCISupport (Bus, HwType); +#endif + } + + return Bus; +} + +BOOLEAN +HalpIsValidPCIDevice ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot + ) +/*++ + +Routine Description: + + Reads the device configuration data for the given slot and + returns TRUE if the configuration data appears to be valid for + a PCI device; otherwise returns FALSE. + +Arguments: + + BusHandler - Bus to check + Slot - Slot to check + +--*/ + +{ + PPCI_COMMON_CONFIG PciData; + UCHAR iBuffer[PCI_COMMON_HDR_LENGTH]; + ULONG i, j; + + + PciData = (PPCI_COMMON_CONFIG) iBuffer; + + // + // Read device common header + // + + HalpReadPCIConfig (BusHandler, Slot, PciData, 0, PCI_COMMON_HDR_LENGTH); + + // + // Valid device header? + // + + if (PciData->VendorID == PCI_INVALID_VENDORID || + PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) { + + return FALSE; + } + + // + // Check fields for reasonable values + // + + if ((PciData->u.type0.InterruptPin && PciData->u.type0.InterruptPin > 4) || + (PciData->u.type0.InterruptLine & 0x70)) { + return FALSE; + } + + for (i=0; i < PCI_TYPE0_ADDRESSES; i++) { + j = PciData->u.type0.BaseAddresses[i]; + + if (j & PCI_ADDRESS_IO_SPACE) { + if (j > 0xffff) { + // IO port > 64k? + return FALSE; + } + } else { + if (j > 0xf && j < 0x80000) { + // Mem address < 0x8000h? + return FALSE; + } + } + + if (Is64BitBaseAddress(j)) { + i += 1; + } + } + + // + // Guess it's a valid device.. + // + + return TRUE; +} + + +ULONG +HalpGetPCIData ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER Slot, + IN PUCHAR Buffer, + IN ULONG Offset, + IN ULONG Length + ) +/*++ + +Routine Description: + + The function returns the Pci bus data for a device. + +Arguments: + + BusNumber - Indicates which bus. + + VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word) + + Buffer - Supplies the space to store the data. + + Length - Supplies a count in bytes of the maximum amount to return. + +Return Value: + + Returns the amount of data stored into the buffer. + + If this PCI slot has never been set, then the configuration information + returned is zeroed. + + +--*/ +{ + PPCI_COMMON_CONFIG PciData; + UCHAR iBuffer[PCI_COMMON_HDR_LENGTH]; + PPCIPBUSDATA BusData; + ULONG Len; + ULONG i, bit; + + if (Length > sizeof (PCI_COMMON_CONFIG)) { + Length = sizeof (PCI_COMMON_CONFIG); + } + + Len = 0; + PciData = (PPCI_COMMON_CONFIG) iBuffer; + + if (Offset >= PCI_COMMON_HDR_LENGTH) { + // + // The user did not request any data from the common + // header. Verify the PCI device exists, then continue + // in the device specific area. + // + + HalpReadPCIConfig (BusHandler, Slot, PciData, 0, sizeof(ULONG)); + + if (PciData->VendorID == PCI_INVALID_VENDORID) { + return 0; + } + + } else { + + // + // Caller requested at least some data within the + // common header. Read the whole header, effect the + // fields we need to and then copy the user's requested + // bytes from the header + // + + BusData = (PPCIPBUSDATA) BusHandler->BusData; + + // + // Read this PCI devices slot data + // + + Len = PCI_COMMON_HDR_LENGTH; + HalpReadPCIConfig (BusHandler, Slot, PciData, 0, Len); + + if (PciData->VendorID == PCI_INVALID_VENDORID || + PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) { + PciData->VendorID = PCI_INVALID_VENDORID; + Len = 2; // only return invalid id + + } else { + + BusData->CommonData.Pin2Line (BusHandler, RootHandler, Slot, PciData); + } + + // + // Copy whatever data overlaps into the callers buffer + // + + if (Len < Offset) { + // no data at caller's buffer + return 0; + } + + Len -= Offset; + if (Len > Length) { + Len = Length; + } + + RtlMoveMemory(Buffer, iBuffer + Offset, Len); + + Offset += Len; + Buffer += Len; + Length -= Len; + } + + if (Length) { + if (Offset >= PCI_COMMON_HDR_LENGTH) { + // + // The remaining Buffer comes from the Device Specific + // area - put on the kitten gloves and read from it. + // + // Specific read/writes to the PCI device specific area + // are guarenteed: + // + // Not to read/write any byte outside the area specified + // by the caller. (this may cause WORD or BYTE references + // to the area in order to read the non-dword aligned + // ends of the request) + // + // To use a WORD access if the requested length is exactly + // a WORD long. + // + // To use a BYTE access if the requested length is exactly + // a BYTE long. + // + + HalpReadPCIConfig (BusHandler, Slot, Buffer, Offset, Length); + Len += Length; + } + } + + return Len; +} + +ULONG +HalpSetPCIData ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER Slot, + IN PUCHAR Buffer, + IN ULONG Offset, + IN ULONG Length + ) +/*++ + +Routine Description: + + The function returns the Pci bus data for a device. + +Arguments: + + + VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word) + + Buffer - Supplies the space to store the data. + + Length - Supplies a count in bytes of the maximum amount to return. + +Return Value: + + Returns the amount of data stored into the buffer. + +--*/ +{ + PPCI_COMMON_CONFIG PciData, PciData2; + UCHAR iBuffer[PCI_COMMON_HDR_LENGTH]; + UCHAR iBuffer2[PCI_COMMON_HDR_LENGTH]; + PPCIPBUSDATA BusData; + ULONG Len, cnt; + + + if (Length > sizeof (PCI_COMMON_CONFIG)) { + Length = sizeof (PCI_COMMON_CONFIG); + } + + + Len = 0; + PciData = (PPCI_COMMON_CONFIG) iBuffer; + PciData2 = (PPCI_COMMON_CONFIG) iBuffer2; + + + if (Offset >= PCI_COMMON_HDR_LENGTH) { + // + // The user did not request any data from the common + // header. Verify the PCI device exists, then continue in + // the device specific area. + // + + HalpReadPCIConfig (BusHandler, Slot, PciData, 0, sizeof(ULONG)); + + if (PciData->VendorID == PCI_INVALID_VENDORID) { + return 0; + } + + } else { + + // + // Caller requested to set at least some data within the + // common header. + // + + Len = PCI_COMMON_HDR_LENGTH; + HalpReadPCIConfig (BusHandler, Slot, PciData, 0, Len); + if (PciData->VendorID == PCI_INVALID_VENDORID || + PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) { + + // no device, or header type unkown + return 0; + } + + + // + // Set this device as configured + // + + BusData = (PPCIPBUSDATA) BusHandler->BusData; +#if DBG + cnt = PciBitIndex(Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber); + RtlSetBits (&BusData->DeviceConfigured, cnt, 1); +#endif + // + // Copy COMMON_HDR values to buffer2, then overlay callers changes. + // + + RtlMoveMemory (iBuffer2, iBuffer, Len); + BusData->CommonData.Pin2Line (BusHandler, RootHandler, Slot, PciData2); + + Len -= Offset; + if (Len > Length) { + Len = Length; + } + + RtlMoveMemory (iBuffer2+Offset, Buffer, Len); + + // in case interrupt line or pin was editted + BusData->CommonData.Line2Pin (BusHandler, RootHandler, Slot, PciData2, PciData); + +#if DBG + // + // Verify R/O fields haven't changed + // + if (PciData2->VendorID != PciData->VendorID || + PciData2->DeviceID != PciData->DeviceID || + PciData2->RevisionID != PciData->RevisionID || + PciData2->ProgIf != PciData->ProgIf || + PciData2->SubClass != PciData->SubClass || + PciData2->BaseClass != PciData->BaseClass || + PciData2->HeaderType != PciData->HeaderType || + PciData2->BaseClass != PciData->BaseClass || + PciData2->u.type0.MinimumGrant != PciData->u.type0.MinimumGrant || + PciData2->u.type0.MaximumLatency != PciData->u.type0.MaximumLatency) { + DbgPrint ("PCI SetBusData: Read-Only configuration value changed\n"); +// DbgBreakPoint (); + } +#endif + // + // Set new PCI configuration + // + + HalpWritePCIConfig (BusHandler, Slot, iBuffer2+Offset, Offset, Len); + + Offset += Len; + Buffer += Len; + Length -= Len; + } + + if (Length) { + if (Offset >= PCI_COMMON_HDR_LENGTH) { + // + // The remaining Buffer comes from the Device Specific + // area - put on the kitten gloves and write it + // + // Specific read/writes to the PCI device specific area + // are guarenteed: + // + // Not to read/write any byte outside the area specified + // by the caller. (this may cause WORD or BYTE references + // to the area in order to read the non-dword aligned + // ends of the request) + // + // To use a WORD access if the requested length is exactly + // a WORD long. + // + // To use a BYTE access if the requested length is exactly + // a BYTE long. + // + + HalpWritePCIConfig (BusHandler, Slot, Buffer, Offset, Length); + Len += Length; + } + } + + return Len; +} + +VOID +HalpReadPCIConfig ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ) +{ + if (!HalpValidPCISlot (BusHandler, Slot)) { + // + // Invalid SlotID return no data + // + + RtlFillMemory (Buffer, Length, (UCHAR) -1); + return ; + } + + HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length, + PCIConfigHandler.ConfigRead); +} + +VOID +HalpWritePCIConfig ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ) +{ + if (!HalpValidPCISlot (BusHandler, Slot)) { + // + // Invalid SlotID do nothing + // + return ; + } + + HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length, + PCIConfigHandler.ConfigWrite); +} + +BOOLEAN +HalpValidPCISlot ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot + ) +{ + PCI_SLOT_NUMBER Slot2; + PPCIPBUSDATA BusData; + UCHAR HeaderType; + ULONG i; + + + BusData = (PPCIPBUSDATA) BusHandler->BusData; + + if (Slot.u.bits.Reserved != 0) { + return FALSE; + } + + if (Slot.u.bits.DeviceNumber >= BusData->MaxDevice) { //IBMCPK: added = + return FALSE; + } + + if (Slot.u.bits.FunctionNumber == 0) { + return TRUE; + } + + // + // Sandalfoot doesn't support Multifunction adapters + // + +// return FALSE; + + // + // Non zero function numbers are only supported if the + // device has the PCI_MULTIFUNCTION bit set in it's header + // + + i = Slot.u.bits.DeviceNumber; + + // + // Read DeviceNumber, Function zero, to determine if the + // PCI supports multifunction devices + // + + Slot2 = Slot; + Slot2.u.bits.FunctionNumber = 0; + + HalpReadPCIConfig ( + BusHandler, + Slot2, + &HeaderType, + FIELD_OFFSET (PCI_COMMON_CONFIG, HeaderType), + sizeof (UCHAR) + ); + + if (!(HeaderType & PCI_MULTIFUNCTION) || HeaderType == 0xFF) { + // this device doesn't exists or doesn't support MULTIFUNCTION types + return FALSE; + } + + return TRUE; +} + + +VOID +HalpPCIConfig ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PUCHAR Buffer, + IN ULONG Offset, + IN ULONG Length, + IN FncConfigIO *ConfigIO + ) +{ + KIRQL OldIrql; + ULONG i; + UCHAR State[20]; + PPCIPBUSDATA BusData; + + BusData = (PPCIPBUSDATA) BusHandler->BusData; + PCIConfigHandler.Synchronize (BusHandler, Slot, &OldIrql, State); + + while (Length) { + i = PCIDeref[Offset % sizeof(ULONG)][Length % sizeof(ULONG)]; + i = ConfigIO[i] (BusData, State, Buffer, Offset); + + Offset += i; + Buffer += i; + Length -= i; + } + + PCIConfigHandler.ReleaseSynchronzation (BusHandler, OldIrql); +} + +VOID HalpPCISynchronizeType1 ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PKIRQL Irql, + IN PPCI_TYPE1_CFG_BITS PciCfg1 + ) +{ + // + // Initialize PciCfg1 + // + + PciCfg1->u.AsULONG = HalpTranslatePciSlotNumber(BusHandler->BusNumber, Slot.u.AsULONG); + + +} + +VOID HalpPCIReleaseSynchronzationType1 ( + IN PBUS_HANDLER BusHandler, + IN KIRQL Irql + ) +{ + + +} + + +ULONG +HalpPCIReadUcharType1 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE1_CFG_BITS PciCfg1, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + ULONG i; + + i = Offset % sizeof(ULONG); + PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG); + + *Buffer = READ_PORT_UCHAR ((PUCHAR)(PciCfg1->u.AsULONG + i)); + return sizeof (UCHAR); +} + +ULONG +HalpPCIReadUshortType1 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE1_CFG_BITS PciCfg1, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + ULONG i; + + i = Offset % sizeof(ULONG); + PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG); + + *((PUSHORT) Buffer) = READ_PORT_USHORT ((PUSHORT)(PciCfg1->u.AsULONG + i)); + return sizeof (USHORT); +} + +ULONG +HalpPCIReadUlongType1 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE1_CFG_BITS PciCfg1, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG); + + *((PULONG) Buffer) = READ_PORT_ULONG ((PULONG) (PciCfg1->u.AsULONG)); + return sizeof (ULONG); +} + + +ULONG +HalpPCIWriteUcharType1 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE1_CFG_BITS PciCfg1, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + ULONG i; + + i = Offset % sizeof(ULONG); + PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG); + + WRITE_PORT_UCHAR (PciCfg1->u.AsULONG + i, *Buffer ); + return sizeof (UCHAR); +} + +ULONG +HalpPCIWriteUshortType1 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE1_CFG_BITS PciCfg1, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + ULONG i; + + i = Offset % sizeof(ULONG); + PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG); + + WRITE_PORT_USHORT (PciCfg1->u.AsULONG + i, *((PUSHORT) Buffer) ); + return sizeof (USHORT); +} + +ULONG +HalpPCIWriteUlongType1 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE1_CFG_BITS PciCfg1, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG); + + WRITE_PORT_ULONG (PciCfg1->u.AsULONG, *((PULONG) Buffer) ); + return sizeof (ULONG); +} + +VOID HalpPCISynchronizeType2 ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PKIRQL Irql, + IN PPCI_TYPE1_CFG_BITS PciCfg1 + ) +{ + + // + // Initialize PciCfg1 + // + + PciCfg1->u.AsULONG = HalpTranslatePciSlotNumber(BusHandler->BusNumber, Slot.u.AsULONG); + + KeRaiseIrql (PROFILE_LEVEL, Irql); + KiAcquireSpinLock (&HalpPCIConfigLock); + + + +} + + +VOID HalpPCIReleaseSynchronzationType2 ( + IN PBUS_HANDLER BusHandler, + IN KIRQL Irql + ) +{ + + KiReleaseSpinLock (&HalpPCIConfigLock); + KeLowerIrql (Irql); + +} + + +ULONG +HalpPCIReadUcharType2 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE1_CFG_BITS PciCfg1, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + ULONG i; + union { + ULONG All; + UCHAR Bytes[4]; + } Tmp; + + i = Offset % sizeof(ULONG); + PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG); + + WRITE_PORT_ULONG(BusData->Config.Type2.Address, PciCfg1->u.AsULONG); + Tmp.All = READ_PORT_ULONG(BusData->Config.Type2.Data); + *Buffer = Tmp.Bytes[i]; + + return sizeof (UCHAR); +} + +ULONG +HalpPCIReadUshortType2 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE1_CFG_BITS PciCfg1, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + ULONG i; + union { + ULONG All; + UCHAR Bytes[4]; + } Tmp; + + i = Offset % sizeof(ULONG); + PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG); + + WRITE_PORT_ULONG(BusData->Config.Type2.Address, PciCfg1->u.AsULONG); + Tmp.All = READ_PORT_ULONG(BusData->Config.Type2.Data); + *Buffer++ = Tmp.Bytes[i++]; + if ( i == sizeof(ULONG) ) { + PciCfg1->u.bits.RegisterNumber++; + WRITE_PORT_ULONG(BusData->Config.Type2.Address, PciCfg1->u.AsULONG); + Tmp.All = READ_PORT_ULONG(BusData->Config.Type2.Data); + i = 0; + } + *Buffer = Tmp.Bytes[i]; + + return sizeof (USHORT); +} + +ULONG +HalpPCIReadUlongType2 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE1_CFG_BITS PciCfg1, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG); + + WRITE_PORT_ULONG(BusData->Config.Type2.Address, PciCfg1->u.AsULONG); + *((PULONG) Buffer) = READ_PORT_ULONG(BusData->Config.Type2.Data); + + return sizeof(ULONG); +} + + +ULONG +HalpPCIWriteUcharType2 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE1_CFG_BITS PciCfg1, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + ULONG i; + union { + ULONG All; + UCHAR Bytes[4]; + } Tmp; + + i = Offset % sizeof(ULONG); + PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG); + + WRITE_PORT_ULONG(BusData->Config.Type2.Address, PciCfg1->u.AsULONG); + Tmp.All = READ_PORT_ULONG(BusData->Config.Type2.Data); + Tmp.Bytes[i] = *Buffer; + WRITE_PORT_ULONG(BusData->Config.Type2.Data, Tmp.All); + + return sizeof (UCHAR); +} + +ULONG +HalpPCIWriteUshortType2 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE1_CFG_BITS PciCfg1, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + ULONG i; + union { + ULONG All; + UCHAR Bytes[4]; + } Tmp; + + i = Offset % sizeof(ULONG); + PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG); + + WRITE_PORT_ULONG(BusData->Config.Type2.Address, PciCfg1->u.AsULONG); + Tmp.All = READ_PORT_ULONG(BusData->Config.Type2.Data); + Tmp.Bytes[i++] = *Buffer++; + if ( i == sizeof(ULONG) ) { + WRITE_PORT_ULONG(BusData->Config.Type2.Data, Tmp.All); + PciCfg1->u.bits.RegisterNumber++; + WRITE_PORT_ULONG(BusData->Config.Type2.Address, PciCfg1->u.AsULONG); + Tmp.All = READ_PORT_ULONG(BusData->Config.Type2.Data); + i = 0; + } + Tmp.Bytes[i] = *Buffer; + WRITE_PORT_ULONG(BusData->Config.Type2.Data, Tmp.All); + + return sizeof (USHORT); +} + +ULONG +HalpPCIWriteUlongType2 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE1_CFG_BITS PciCfg1, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG); + + WRITE_PORT_ULONG(BusData->Config.Type2.Address, PciCfg1->u.AsULONG); + WRITE_PORT_ULONG(BusData->Config.Type2.Data, *((PULONG)Buffer)); + + return sizeof(ULONG); +} + +NTSTATUS +HalpAssignPCISlotResources ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PUNICODE_STRING RegistryPath, + IN PUNICODE_STRING DriverClassName OPTIONAL, + IN PDRIVER_OBJECT DriverObject, + IN PDEVICE_OBJECT DeviceObject OPTIONAL, + IN ULONG Slot, + IN OUT PCM_RESOURCE_LIST *pAllocatedResources + ) +/*++ + +Routine Description: + + Reads the targeted device to determine it's required resources. + Calls IoAssignResources to allocate them. + Sets the targeted device with it's assigned resources + and returns the assignments to the caller. + +Arguments: + +Return Value: + + STATUS_SUCCESS or error + +--*/ +{ + NTSTATUS status; + PUCHAR WorkingPool; + PPCI_COMMON_CONFIG PciData, PciOrigData, PciData2; + PCI_SLOT_NUMBER PciSlot; + PPCIPBUSDATA BusData; + PIO_RESOURCE_REQUIREMENTS_LIST CompleteList; + PIO_RESOURCE_DESCRIPTOR Descriptor; + PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor; + ULONG BusNumber; + ULONG i, j, m, length, memtype; + ULONG NoBaseAddress, RomIndex, Option; + PULONG BaseAddress[PCI_TYPE0_ADDRESSES + 1]; + PULONG OrigAddress[PCI_TYPE0_ADDRESSES + 1]; + BOOLEAN Match, EnableRomBase; + + + *pAllocatedResources = NULL; + PciSlot = *((PPCI_SLOT_NUMBER) &Slot); + BusNumber = BusHandler->BusNumber; + BusData = (PPCIPBUSDATA) BusHandler->BusData; + + // + // Allocate some pool for working space + // + + i = sizeof (IO_RESOURCE_REQUIREMENTS_LIST) + + sizeof (IO_RESOURCE_DESCRIPTOR) * (PCI_TYPE0_ADDRESSES + 2) * 2 + + PCI_COMMON_HDR_LENGTH * 3; + + WorkingPool = (PUCHAR) ExAllocatePool (PagedPool, i); + if (!WorkingPool) { + return STATUS_INSUFFICIENT_RESOURCES; + } + + // + // Zero initialize pool, and get pointers into memory + // + + RtlZeroMemory (WorkingPool, i); + CompleteList = (PIO_RESOURCE_REQUIREMENTS_LIST) WorkingPool; + PciData = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 3); + PciData2 = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 2); + PciOrigData = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 1); + + // + // Read the PCI device's configuration + // + + HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH); + if (PciData->VendorID == PCI_INVALID_VENDORID) { + ExFreePool (WorkingPool); + return STATUS_NO_SUCH_DEVICE; + } + + // + // Make a copy of the device's current settings + // + + RtlMoveMemory (PciOrigData, PciData, PCI_COMMON_HDR_LENGTH); + + // + // Initialize base addresses base on configuration data type + // + + switch (PCI_CONFIG_TYPE(PciData)) { + case 0 : + NoBaseAddress = PCI_TYPE0_ADDRESSES+1; + for (j=0; j < PCI_TYPE0_ADDRESSES; j++) { + BaseAddress[j] = &PciData->u.type0.BaseAddresses[j]; + OrigAddress[j] = &PciOrigData->u.type0.BaseAddresses[j]; + } + BaseAddress[j] = &PciData->u.type0.ROMBaseAddress; + OrigAddress[j] = &PciOrigData->u.type0.ROMBaseAddress; + RomIndex = j; + break; + case 1: + NoBaseAddress = PCI_TYPE1_ADDRESSES+1; + for (j=0; j < PCI_TYPE1_ADDRESSES; j++) { + BaseAddress[j] = &PciData->u.type1.BaseAddresses[j]; + OrigAddress[j] = &PciOrigData->u.type1.BaseAddresses[j]; + } + BaseAddress[j] = &PciData->u.type1.ROMBaseAddress; + OrigAddress[j] = &PciOrigData->u.type1.ROMBaseAddress; + RomIndex = j; + break; + + default: + ExFreePool (WorkingPool); + return STATUS_NO_SUCH_DEVICE; + } + + // + // If the BIOS doesn't have the device's ROM enabled, then we won't + // enable it either. Remove it from the list. + // + + EnableRomBase = TRUE; + if (!(*BaseAddress[RomIndex] & PCI_ROMADDRESS_ENABLED)) { + ASSERT (RomIndex+1 == NoBaseAddress); + EnableRomBase = FALSE; + NoBaseAddress -= 1; + } + + // + // Set resources to all bits on to see what type of resources + // are required. + // + + for (j=0; j < NoBaseAddress; j++) { + *BaseAddress[j] = 0xFFFFFFFF; + } + + PciData->Command &= ~(PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE); + *BaseAddress[RomIndex] &= ~PCI_ROMADDRESS_ENABLED; + HalpWritePCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH); + HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH); + + // note type0 & type1 overlay ROMBaseAddress, InterruptPin, and InterruptLine + BusData->CommonData.Pin2Line (BusHandler, RootHandler, PciSlot, PciData); + + // + // Build an IO_RESOURCE_REQUIREMENTS_LIST for the PCI device + // + + CompleteList->InterfaceType = PCIBus; + CompleteList->BusNumber = BusNumber; + CompleteList->SlotNumber = Slot; + CompleteList->AlternativeLists = 1; + + CompleteList->List[0].Version = 1; + CompleteList->List[0].Revision = 1; + + Descriptor = CompleteList->List[0].Descriptors; + + // + // If PCI device has an interrupt resource, add it + // + + if (PciData->u.type0.InterruptPin) { + CompleteList->List[0].Count++; + + Descriptor->Option = 0; + Descriptor->Type = CmResourceTypeInterrupt; + Descriptor->ShareDisposition = CmResourceShareShared; + Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE; + + // Fill in any vector here - we'll pick it back up in + // HalAdjustResourceList and adjust it to it's allowed settings + Descriptor->u.Interrupt.MinimumVector = 0; + Descriptor->u.Interrupt.MaximumVector = 0xff; + Descriptor++; + } + + // + // Add a memory/port resource for each PCI resource + // + + // Clear ROM reserved bits + + *BaseAddress[RomIndex] &= ~0x7FF; + + for (j=0; j < NoBaseAddress; j++) { + if (*BaseAddress[j]) { + i = *BaseAddress[j]; + + // scan for first set bit, that's the length & alignment + length = 1 << (i & PCI_ADDRESS_IO_SPACE ? 2 : 4); + while (!(i & length) && length) { + length <<= 1; + } + + // scan for last set bit, that's the maxaddress + 1 + for (m = length; i & m; m <<= 1) ; + m--; + + // check for hosed PCI configuration requirements + if (length & ~m) { +#if DBG + DbgPrint ("PCI: defective device! Bus %d, Slot %d, Function %d\n", + BusNumber, + PciSlot.u.bits.DeviceNumber, + PciSlot.u.bits.FunctionNumber + ); + + DbgPrint ("PCI: BaseAddress[%d] = %08lx\n", j, i); +#endif + // the device is in error - punt. don't allow this + // resource any option - it either gets set to whatever + // bits it was able to return, or it doesn't get set. + + if (i & PCI_ADDRESS_IO_SPACE) { + m = i & ~0x3; + Descriptor->u.Port.MinimumAddress.LowPart = m; + } else { + m = i & ~0xf; + Descriptor->u.Memory.MinimumAddress.LowPart = m; + } + + m += length; // max address is min address + length + } + + // + // Add requested resource + // + + Descriptor->Option = 0; + if (i & PCI_ADDRESS_IO_SPACE) { + memtype = 0; + + if (!Is64BitBaseAddress(i) && + PciOrigData->Command & PCI_ENABLE_IO_SPACE) { + + // + // The IO range is/was already enabled at some + // location, add that as it's preferred setting. + // + + Descriptor->Type = CmResourceTypePort; + Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; + Descriptor->Flags = CM_RESOURCE_PORT_IO; + Descriptor->Option = IO_RESOURCE_PREFERRED; + + Descriptor->u.Port.Length = length; + Descriptor->u.Port.Alignment = length; + Descriptor->u.Port.MinimumAddress.LowPart = *OrigAddress[j] & ~0x3; + Descriptor->u.Port.MaximumAddress.LowPart = + Descriptor->u.Port.MinimumAddress.LowPart + length - 1; //IBMCPK:added -1 + + CompleteList->List[0].Count++; + Descriptor++; + + Descriptor->Option = IO_RESOURCE_ALTERNATIVE; + } + + // + // Add this IO range + // + + Descriptor->Type = CmResourceTypePort; + Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; + Descriptor->Flags = CM_RESOURCE_PORT_IO; + + Descriptor->u.Port.Length = length; + Descriptor->u.Port.Alignment = length; + Descriptor->u.Port.MaximumAddress.LowPart = m; + + } else { + + memtype = i & PCI_ADDRESS_MEMORY_TYPE_MASK; + + Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE; + if (j == RomIndex) { + // this is a ROM address + Descriptor->Flags = CM_RESOURCE_MEMORY_READ_ONLY; + } + + if (i & PCI_ADDRESS_MEMORY_PREFETCHABLE) { + Descriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; + } + + if (!Is64BitBaseAddress(i) && + (j == RomIndex || + PciOrigData->Command & PCI_ENABLE_MEMORY_SPACE)) { + + // + // The memory range is/was already enabled at some location, add that + // as it's preferred setting. + // + + Descriptor->Type = CmResourceTypeMemory; + Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; + Descriptor->Option = IO_RESOURCE_PREFERRED; + + Descriptor->u.Port.Length = length; + Descriptor->u.Port.Alignment = length; + Descriptor->u.Port.MinimumAddress.LowPart = *OrigAddress[j] & ~0xF; + Descriptor->u.Port.MaximumAddress.LowPart = + Descriptor->u.Port.MinimumAddress.LowPart + length - 1; //IBMCPK: added -1 + + CompleteList->List[0].Count++; + Descriptor++; + + Descriptor->Flags = Descriptor[-1].Flags; + Descriptor->Option = IO_RESOURCE_ALTERNATIVE; + } + + // + // Add this memory range + // + + Descriptor->Type = CmResourceTypeMemory; + Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; + + Descriptor->u.Memory.Length = length; + Descriptor->u.Memory.Alignment = length; + Descriptor->u.Memory.MaximumAddress.LowPart = m; + + if (memtype == PCI_TYPE_20BIT && m > 0xFFFFF) { + // limit to 20 bit address + Descriptor->u.Memory.MaximumAddress.LowPart = 0xFFFFF; + } + + } + + CompleteList->List[0].Count++; + Descriptor++; + + + if (Is64BitBaseAddress(i)) { + // skip upper half of 64 bit address since this processor + // only supports 32 bits of address space + j++; + } + } + } + + CompleteList->ListSize = (ULONG) + ((PUCHAR) Descriptor - (PUCHAR) CompleteList); + + // + // Restore the device settings as we found them, enable memory + // and io decode after setting base addresses. This is done in + // case HalAdjustResourceList wants to read the current settings + // in the device. + // + + HalpWritePCIConfig ( + BusHandler, + PciSlot, + &PciOrigData->Status, + FIELD_OFFSET (PCI_COMMON_CONFIG, Status), + PCI_COMMON_HDR_LENGTH - FIELD_OFFSET (PCI_COMMON_CONFIG, Status) + ); + + HalpWritePCIConfig ( + BusHandler, + PciSlot, + PciOrigData, + 0, + FIELD_OFFSET (PCI_COMMON_CONFIG, Status) + ); + + // + // Have the IO system allocate resource assignments + // + + status = IoAssignResources ( + RegistryPath, + DriverClassName, + DriverObject, + DeviceObject, + CompleteList, + pAllocatedResources + ); + + if (!NT_SUCCESS(status)) { + goto CleanUp; + } + + // + // Slurp the assigments back into the PciData structure and + // perform them + // + + CmDescriptor = (*pAllocatedResources)->List[0].PartialResourceList.PartialDescriptors; + + // + // If PCI device has an interrupt resource then that was + // passed in as the first requested resource + // + + if (PciData->u.type0.InterruptPin) { + PciData->u.type0.InterruptLine = (UCHAR) CmDescriptor->u.Interrupt.Vector; + BusData->CommonData.Line2Pin (BusHandler, RootHandler, PciSlot, PciData, PciOrigData); + CmDescriptor++; + } + + // + // Pull out resources in the order they were passed to IoAssignResources + // + + for (j=0; j < NoBaseAddress; j++) { + i = *BaseAddress[j]; + if (i) { + if (i & PCI_ADDRESS_IO_SPACE) { + *BaseAddress[j] = CmDescriptor->u.Port.Start.LowPart; + } else { + *BaseAddress[j] = CmDescriptor->u.Memory.Start.LowPart; + } + CmDescriptor++; + } + + if (Is64BitBaseAddress(i)) { + // skip upper 32 bits + j++; + } + } + + // + // Turn off decodes, then set new addresses + // + + HalpWritePCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH); + + // + // Read configuration back and verify address settings took + // + + HalpReadPCIConfig(BusHandler, PciSlot, PciData2, 0, PCI_COMMON_HDR_LENGTH); + + Match = TRUE; + if (PciData->u.type0.InterruptLine != PciData2->u.type0.InterruptLine || + PciData->u.type0.InterruptPin != PciData2->u.type0.InterruptPin || + PciData->u.type0.ROMBaseAddress != PciData2->u.type0.ROMBaseAddress) { + Match = FALSE; + } + + for (j=0; j < NoBaseAddress; j++) { + if (*BaseAddress[j]) { + if (*BaseAddress[j] & PCI_ADDRESS_IO_SPACE) { + i = (ULONG) ~0x3; + } else { + i = (ULONG) ~0xF; + } + + if ((*BaseAddress[j] & i) != + *((PULONG) ((PUCHAR) BaseAddress[j] - + (PUCHAR) PciData + + (PUCHAR) PciData2)) & i) { + + Match = FALSE; + } + + if (Is64BitBaseAddress(*BaseAddress[j])) { + // skip upper 32 bits + j++; + } + } + } + + if (!Match) { +#if DBG + DbgPrint ("PCI: defective device! Bus %d, Slot %d, Function %d\n", + BusNumber, + PciSlot.u.bits.DeviceNumber, + PciSlot.u.bits.FunctionNumber + ); +#endif + status = STATUS_DEVICE_PROTOCOL_ERROR; + goto CleanUp; + } + + // + // Settings took - turn on the appropiate decodes + // + + if (EnableRomBase && *BaseAddress[RomIndex]) { + // a rom address was allocated and should be enabled + *BaseAddress[RomIndex] |= PCI_ROMADDRESS_ENABLED; + HalpWritePCIConfig ( + BusHandler, + PciSlot, + BaseAddress[RomIndex], + (ULONG) ((PUCHAR) BaseAddress[RomIndex] - (PUCHAR) PciData), + sizeof (ULONG) + ); + } + + // + // Enable IO, Memory, and BUS_MASTER decodes + // (use HalSetBusData since valid settings now set) + // + // But don't change video devices, they will be enabled or + // disabled by HalpInitializeDisplay() + // + // (For the moment, that means we are shutting off the + // S3 chip so that a plug-in Weitek card can get a chance + // to talk to GDI. + + if (!(IsVideoDevice(PciData))) { + + PciData->Command |= PCI_ENABLE_IO_SPACE | + PCI_ENABLE_MEMORY_SPACE | + PCI_ENABLE_BUS_MASTER; + } else { + + PciData->Command = PciOrigData->Command; + } + + HalSetBusDataByOffset ( + PCIConfiguration, + BusHandler->BusNumber, + PciSlot.u.AsULONG, + &PciData->Command, + FIELD_OFFSET (PCI_COMMON_CONFIG, Command), + sizeof (PciData->Command) + ); + +CleanUp: + if (!NT_SUCCESS(status)) { + + // + // Failure, if there are any allocated resources free them + // + + if (*pAllocatedResources) { + IoAssignResources ( + RegistryPath, + DriverClassName, + DriverObject, + DeviceObject, + NULL, + NULL + ); + + ExFreePool (*pAllocatedResources); + *pAllocatedResources = NULL; + } + + // + // Restore the device settings as we found them, enable memory + // and io decode after setting base addresses + // + + HalpWritePCIConfig ( + BusHandler, + PciSlot, + &PciOrigData->Status, + FIELD_OFFSET (PCI_COMMON_CONFIG, Status), + PCI_COMMON_HDR_LENGTH - FIELD_OFFSET (PCI_COMMON_CONFIG, Status) + ); + + HalpWritePCIConfig ( + BusHandler, + PciSlot, + PciOrigData, + 0, + FIELD_OFFSET (PCI_COMMON_CONFIG, Status) + ); + } + + ExFreePool (WorkingPool); + return status; +} + +VOID +HalpPhase0DiscoverPciBuses( + IN PCONFIGURATION_COMPONENT_DATA Component + ) +/* + This function looks down the LoaderBlock looking for nodes that + correspond to PCI buses. When it has found them all, it sets + HalpPciMaxBuses. +*/ +{ + // Check to see if this component would look like a "multi(x)" + // entry in ARC. + if ((Component->ComponentEntry.Class == AdapterClass) && + (Component->ComponentEntry.Type == MultiFunctionAdapter)) { + + // + // First check to see if Identifier is valid, then + // check the string it points to. + // + if (Component->ComponentEntry.Identifier) { + + if ((Component->ComponentEntry.Identifier[0] == 'P') && + (Component->ComponentEntry.Identifier[1] == 'C') && + (Component->ComponentEntry.Identifier[2] == 'I')) { + + HalpPciMaxBuses++; // Increment the number of PCI buses + + } + } + } + + // + // Look at the Siblings of this component + // + if (Component->Sibling) { + HalpPhase0DiscoverPciBuses(Component->Sibling); + } + + // + // Look at the Children of this component + // + if (Component->Child) { + HalpPhase0DiscoverPciBuses(Component->Child); + } + + +} + +#if DBG +VOID +HalpTestPci (ULONG flag2) +{ + PCI_SLOT_NUMBER SlotNumber; + PCI_COMMON_CONFIG PciData, OrigData; + ULONG i, f, j, k, bus; + BOOLEAN flag; + + + if (!flag2) { + return ; + } + + DbgBreakPoint (); + SlotNumber.u.bits.Reserved = 0; + + // + // Read every possible PCI Device/Function and display it's + // default info. + // + // (note this destories it's current settings) + // + + flag = TRUE; + for (bus = 0; flag; bus++) { + + for (i = 0; i < PCI_MAX_DEVICES; i++) { + SlotNumber.u.bits.DeviceNumber = i; + + for (f = 0; f < PCI_MAX_FUNCTION; f++) { + SlotNumber.u.bits.FunctionNumber = f; + + // + // Note: This is reading the DeviceSpecific area of + // the device's configuration - normally this should + // only be done on device for which the caller understands. + // I'm doing it here only for debugging. + // + + j = HalGetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + sizeof (PciData) + ); + + if (j == 0) { + // out of buses + flag = FALSE; + break; + } + + if (j < PCI_COMMON_HDR_LENGTH) { + continue; + } + + HalSetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + 1 + ); + + HalGetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + sizeof (PciData) + ); + + memcpy (&OrigData, &PciData, sizeof PciData); + + for (j=0; j < PCI_TYPE0_ADDRESSES; j++) { + PciData.u.type0.BaseAddresses[j] = 0xFFFFFFFF; + } + + PciData.u.type0.ROMBaseAddress = 0xFFFFFFFF; + + HalSetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + sizeof (PciData) + ); + + HalGetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + sizeof (PciData) + ); + + DbgPrint ("PCI Bus %d Slot %2d %2d ID:%04lx-%04lx Rev:%04lx", + bus, i, f, PciData.VendorID, PciData.DeviceID, + PciData.RevisionID); + + + if (PciData.u.type0.InterruptPin) { + DbgPrint (" IntPin:%x", PciData.u.type0.InterruptPin); + } + + if (PciData.u.type0.InterruptLine) { + DbgPrint (" IntLine:%x", PciData.u.type0.InterruptLine); + } + + if (PciData.u.type0.ROMBaseAddress) { + DbgPrint (" ROM:%08lx", PciData.u.type0.ROMBaseAddress); + } + + DbgPrint ("\n Cmd:%04x Status:%04x ProgIf:%04x SubClass:%04x BaseClass:%04lx\n", + PciData.Command, PciData.Status, PciData.ProgIf, + PciData.SubClass, PciData.BaseClass); + + k = 0; + for (j=0; j < PCI_TYPE0_ADDRESSES; j++) { + if (PciData.u.type0.BaseAddresses[j]) { + DbgPrint (" Ad%d:%08lx", j, PciData.u.type0.BaseAddresses[j]); + k = 1; + } + } + + if (PciData.u.type0.ROMBaseAddress == 0xC08001) { + + PciData.u.type0.ROMBaseAddress = 0xC00001; + HalSetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + sizeof (PciData) + ); + + HalGetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + sizeof (PciData) + ); + + DbgPrint ("\n Bogus rom address, edit yields:%08lx", + PciData.u.type0.ROMBaseAddress); + } + + if (k) { + DbgPrint ("\n"); + } + + if (PciData.VendorID == 0x8086) { + // dump complete buffer + DbgPrint ("Command %x, Status %x, BIST %x\n", + PciData.Command, PciData.Status, + PciData.BIST + ); + + DbgPrint ("CacheLineSz %x, LatencyTimer %x", + PciData.CacheLineSize, PciData.LatencyTimer + ); + + for (j=0; j < 192; j++) { + if ((j & 0xf) == 0) { + DbgPrint ("\n%02x: ", j + 0x40); + } + DbgPrint ("%02x ", PciData.DeviceSpecific[j]); + } + DbgPrint ("\n"); + } + + + // + // now print original data + // + + if (OrigData.u.type0.ROMBaseAddress) { + DbgPrint (" oROM:%08lx", OrigData.u.type0.ROMBaseAddress); + } + + DbgPrint ("\n"); + k = 0; + for (j=0; j < PCI_TYPE0_ADDRESSES; j++) { + if (OrigData.u.type0.BaseAddresses[j]) { + DbgPrint (" oAd%d:%08lx", j, OrigData.u.type0.BaseAddresses[j]); + k = 1; + } + } + + // + // Restore original settings + // + + HalSetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &OrigData, + sizeof (PciData) + ); + + // + // Next + // + + if (k) { + DbgPrint ("\n\n"); + } + } + } + } + DbgBreakPoint (); +} +#endif diff --git a/private/ntos/nthals/halvict/ppc/pxpciint.c b/private/ntos/nthals/halvict/ppc/pxpciint.c new file mode 100644 index 000000000..6e7fd7ab8 --- /dev/null +++ b/private/ntos/nthals/halvict/ppc/pxpciint.c @@ -0,0 +1,290 @@ +/*++ + + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + ixpciint.c + +Abstract: + + All PCI bus interrupt mapping is in this module, so that a real + system which doesn't have all the limitations which PC PCI + systems have can replaced this code easly. + (bus memory & i/o address mappings can also be fix here) + +Author: + + Ken Reneris + Jim Wooldridge - Ported to PowerPC + +Environment: + + Kernel mode + +Revision History: + + +--*/ + +#include "halp.h" +#include "pci.h" +#include "pcip.h" +#include "ibmppc.h" + + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE,HalpGetPCIIntOnISABus) +#pragma alloc_text(PAGE,HalpAdjustPCIResourceList) +#endif + +#define PCI_DISPLAY_CONTROLLER 0x03 +#define PCI_PRE_REV_2 0x0 +#define IsVideoDevice(a) \ + (((a->BaseClass == PCI_DISPLAY_CONTROLLER) && \ + (a->SubClass == 0)) || \ + (((a->BaseClass == PCI_PRE_REV_2) && \ + (a->SubClass == 1)))) + +#define P91_DEVICE_ID 0x9100100E +extern PHYSICAL_ADDRESS HalpP9CoprocPhysicalAddress; // in pxp91.c + +ULONG +HalpGetPCIData ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER SlotNumber, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ); + +ULONG +HalpGetPCIIntOnISABus ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN ULONG BusInterruptLevel, + IN ULONG BusInterruptVector, + OUT PKIRQL Irql, + OUT PKAFFINITY Affinity + ) +{ + if (BusInterruptLevel < 1) { + // bogus bus level + return 0; + } + + + // + // Current PCI buses just map their IRQs ontop of the ISA space, + // so foreward this to the isa handler for the isa vector + // (the isa vector was saved away at either HalSetBusData or + // IoAssignReosurces time - if someone is trying to connect a + // PCI interrupt without performing one of those operations first, + // they are broken). + // + + return HalGetInterruptVector ( + Internal, 0, + BusInterruptLevel, + BusInterruptVector, + Irql, + Affinity + ); +} + + +VOID +HalpPCIPin2ISALine ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER SlotNumber, + IN PPCI_COMMON_CONFIG PciData + ) +/*++ + +// This function maps the device's InterruptPin to an InterruptLine +// value. +// +// On Sandalfoot and Polo machines PCI interrupts are statically routed +// via slot number. This routine just returns and the static routing +// is done in HalpGetIsaFixedPCIIrq +// + +--*/ +{ + + +} + + + +VOID +HalpPCIISALine2Pin ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER SlotNumber, + IN PPCI_COMMON_CONFIG PciNewData, + IN PPCI_COMMON_CONFIG PciOldData + ) +/*++ + + This functions maps the device's InterruptLine to it's + device specific InterruptPin value. + + +--*/ +{ +} + +NTSTATUS +HalpAdjustPCIResourceList ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList + ) +/*++ + Rewrite the callers requested resource list to fit within + the supported ranges of this bus +--*/ +{ + NTSTATUS Status; + PPCIPBUSDATA BusData; + PCI_SLOT_NUMBER PciSlot; + PSUPPORTED_RANGE Interrupt; + PPCI_COMMON_CONFIG PciData; + UCHAR iBuffer[PCI_COMMON_HDR_LENGTH]; + ULONG cnt; + + BusData = (PPCIPBUSDATA) BusHandler->BusData; + PciSlot = *((PPCI_SLOT_NUMBER) &(*pResourceList)->SlotNumber); + + PciData = (PPCI_COMMON_CONFIG) iBuffer; + + // + // Determine PCI device's interrupt restrictions + // + + Status = BusData->GetIrqRange(BusHandler, RootHandler, PciSlot, &Interrupt); + + if (!NT_SUCCESS(Status)) { + DbgPrint("Bad IRQ range\n"); + return Status; + } + + // + // Adjust resources + // + + Status = HaliAdjustResourceListRange ( + BusHandler->BusAddresses, + Interrupt, + pResourceList + ); + + ExFreePool (Interrupt); + + if (!NT_SUCCESS(Status)) { + DbgPrint("Bad HaliAdjustResourceListRange\n"); + return Status; + } + + // + // This next part is a major HACK. The Weitek video + // adapter (which is one of IBM's favorites) needs + // to have its frame buffer enabled by the HAL so + // that the HAL can write to the screen. The device + // driver for this card needs to touch the frame buffer + // during its initialization phase, which overlaps with + // the period of time that the HAL is writing to the + // screen. So, to avoid breaking one or the other, + // we need to force the device driver to use the + // same I/O space for the frame buffer that the HAL + // was using. Unfortunately, this is the only place + // to do it. -- Jake Oshins 1/2/96 + + HalpGetPCIData(BusHandler, + RootHandler, + PciSlot, + PciData, + 0, + PCI_COMMON_HDR_LENGTH + ); + + // + // We want to do this only for video devices that are + // already decoding a range of memory. + // + if ((IsVideoDevice(PciData)) && + (PciData->u.type0.BaseAddresses[0] & 0xfffffffe)) + { + for (cnt = (*pResourceList)->List->Count; cnt; cnt--) { + switch ((*pResourceList)->List->Descriptors->Type) { + case CmResourceTypeInterrupt: + case CmResourceTypePort: + case CmResourceTypeDma: + break; + + case CmResourceTypeMemory: + + // + // Set the bottom of the range to the value in the Base Address Register + // + (*pResourceList)->List->Descriptors->u.Memory.MinimumAddress.LowPart = + PciData->u.type0.BaseAddresses[0]; + + // + // Set the top of the range to the BAR plus the requested length + // + (*pResourceList)->List->Descriptors->u.Memory.MaximumAddress.LowPart = + PciData->u.type0.BaseAddresses[0] + + (*pResourceList)->List->Descriptors->u.Memory.Length; + } + } + + } + + // JAKETEMP pull this out when reworking Baby Blue code!!!! + + // Yet another MAJOR HACK! + // + // If this is a Doral/Terlingua, then space on the primary PCI bus is + // limited. The Baby Blue card, if it is plugged in, will require the + // entire upper half. Although this is ridiculous, we want to support + // it. And since all boot devices initialize before video, we have to + // make sure that nothing has claimed the upper half of the bus' + // address space. -- Jake Oshins 3/7/96 + + if ((HalpSystemType == IBM_DORAL) && (BusHandler->BusNumber == 0)) { + for (cnt = (*pResourceList)->List->Count; cnt; cnt--) { + switch ((*pResourceList)->List->Descriptors->Type) { + case CmResourceTypeInterrupt: + case CmResourceTypePort: + case CmResourceTypeDma: + break; + + case CmResourceTypeMemory: + + // + // If the requested range maximum is above the first 256MB of + // memory space, then the requested maximum is 256MB and the + // minimum is 0. (i.e. Let IoAssignResources place it anywhere + // in the first 256MB. + // + + if ((*pResourceList)->List->Descriptors->u.Memory.MaximumAddress.LowPart > 0x0fffffff) { + (*pResourceList)->List->Descriptors->u.Memory.MinimumAddress.LowPart = 0x0; + (*pResourceList)->List->Descriptors->u.Memory.MaximumAddress.LowPart = 0x0fffffff; + + } + + } + + } + } + return Status; + +} + + diff --git a/private/ntos/nthals/halvict/ppc/pxpcisup.c b/private/ntos/nthals/halvict/ppc/pxpcisup.c new file mode 100644 index 000000000..14cb7ba41 --- /dev/null +++ b/private/ntos/nthals/halvict/ppc/pxpcisup.c @@ -0,0 +1,708 @@ + + +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file +contains copyrighted material. Use of this file is restricted +by the provisions of a Motorola Software License Agreement. + +Module Name: + + pxmemctl.c + +Abstract: + + The module initializes any planar registers. + This module also implements machince check parity error handling. + +Author: + + Jim Wooldridge (jimw@austin.vnet.ibm.com) + + +Revision History: + + Jake Oshins + Support Victory machines + Peter Johnston + Merge Victory/Doral versions. + + +--*/ + +#include "halp.h" +#include "pci.h" +#include "pcip.h" +#include "pxmpic2.h" +#include "ibmppc.h" + +#define IsPciBridge(a) \ + (a->VendorID != PCI_INVALID_VENDORID && \ + PCI_CONFIG_TYPE(a) == PCI_BRIDGE_TYPE && \ + a->SubClass == 4 && a->BaseClass == 6) + +// +// UNION has two top level PCI busses. +// + +#define UNION_PCI_BASE_0 0xbfff8000 +#define UNION_PCI_BASE_1 0xbfef8000 + +PVOID HalpPciConfigAddr[2]; +PVOID HalpPciConfigData[2]; +UCHAR HalpEpciMin = 0xff; +UCHAR HalpEpciMax = 0xff; + +ULONG HalpPciMaxSlots = PCI_MAX_DEVICES; + +typedef struct _PCI_BUS_NODE { + struct _PCI_BUS_NODE *Sibling; + struct _PCI_BUS_NODE *Child; + ULONG BusNumber; // logical bus number + ULONG BaseBus; // number of the root bus + ULONG BaseSlot; // slot in the base bus that these PPBs are plugged into +} PCI_BUS_NODE, *PPCI_BUS_NODE; + +PPCI_BUS_NODE HalpPciBusTree = NULL; + +UCHAR +HalpSearchPciBridgeMap( + IN PPCI_BUS_NODE Node, + IN ULONG BusNumber, + IN PCI_SLOT_NUMBER PciSlot, + IN UCHAR InterruptPin + ); + +VOID +HalpInitializePciAccess ( + VOID + ); + +ULONG +HalpPhase0SetPciDataByOffset ( + ULONG BusNumber, + ULONG SlotNumber, + PVOID Buffer, + ULONG Offset, + ULONG Length + ); + +ULONG +HalpPhase0GetPciDataByOffset ( + ULONG BusNumber, + ULONG SlotNumber, + PVOID Buffer, + ULONG Offset, + ULONG Length + ); + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE,HalpGetPCIIrq) +#pragma alloc_text(INIT,HalpInitializePciAccess) +#pragma alloc_text(INIT,HalpPhase0GetPciDataByOffset) +#pragma alloc_text(INIT,HalpPhase0SetPciDataByOffset) +#pragma alloc_text(PAGE,HalpSearchPciBridgeMap) +#endif + + + + +VOID +HalpInitializePciAccess ( + VOID + ) +/*++ + +Routine Description: + + Fill the HalpPciConfigAddr and HalpPciConfigData arrays with + virtual addresses used to access the various top level PCI + busses on this machine. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + if ( HalpSystemType != IBM_DORAL ) { + HalpPciConfigAddr[0] = (PVOID)((ULONG)HalpIoControlBase + 0xcf8); + HalpPciConfigData[0] = (PVOID)((ULONG)HalpIoControlBase + 0xcfc); + + return; + } + + // + // UNION based systems (eg Doral) + // + + HalpPciConfigAddr[0] = HalpAssignReservedVirtualSpace( + UNION_PCI_BASE_0 >> PAGE_SHIFT, + 2); + HalpPciConfigData[0] = (PVOID)((ULONG)HalpPciConfigAddr[0] + 0x10); + + HalpPciConfigAddr[1] = HalpAssignReservedVirtualSpace( + UNION_PCI_BASE_1 >> PAGE_SHIFT, + 2); + HalpPciConfigData[1] = (PVOID)((ULONG)HalpPciConfigAddr[1] + 0x10); + + if ( !HalpPciConfigAddr[0] || + !HalpPciConfigAddr[1] ) { + KeBugCheck(HAL_INITIALIZATION_FAILED); + } + +#define EPCI_KLUDGE +#if defined(EPCI_KLUDGE) +#define IBMHOSTPCIBRIDGE 0x003a1014 + // + // The EPCI bus on doral is initialized with a bus number of 0x80 + // for reasons unclear. Reset it so it is the next logical bus + // following the max PCI bus. + // + // The following code is really grungy, we should use PCI + // access routines to do it,.... the gist of it is + // + // (1) Check that we have an IBM Host/PCI bridge. + // (2) Check that it thinks it's bus 80 and subordinate + // bus 80 also (ie no subordinate busses). + // (3) Change to bus 0 subordinate bus 0. + // + + { + ULONG BusInfo; + PULONG PciAddr = (PULONG)(HalpPciConfigAddr[0]); + PULONG PciData = (PULONG)(HalpPciConfigData[0]); + PULONG EpciAddr = (PULONG)(HalpPciConfigAddr[1]); + PULONG EpciData = (PULONG)(HalpPciConfigData[1]); + ULONG BusNo; + ULONG Found = 0; + + // + // First, locate the host bridge on the PCI bus. Hopefully + // it's on bus 0. + // + + *PciAddr = 0x80000000; + __builtin_eieio(); + BusInfo = *PciData; + + if ( BusInfo == IBMHOSTPCIBRIDGE ) { + // + // Have bridge, see what the bus range is. + // + *PciAddr = 0x80000040; + __builtin_eieio(); + BusInfo = *PciData; + HalpEpciMin = (UCHAR)(((BusInfo >> 8) & 0xff) + 1); + // + // Now, find bridge on EPCI bus. Scan for it. + // + for ( BusNo = 0 ; BusNo < 0x100 ; BusNo++ ) { + *EpciAddr = 0x80000000 | (BusNo << 16); + __builtin_eieio(); + BusInfo = *EpciData; + if ( BusInfo == IBMHOSTPCIBRIDGE ) { + *EpciAddr = 0x80000000 | (BusNo << 16) | 0x40; + __builtin_eieio(); + BusInfo = *EpciData; + + // Subordinate bus number - Primary bus number + HalpEpciMax = (UCHAR)(((BusInfo >> 8) & 0xff) - (BusInfo & 0xff)); + HalpEpciMax += HalpEpciMin; + + BusInfo &= 0xffff0000; + BusInfo |= (HalpEpciMax << 8) | HalpEpciMin; + *EpciData = BusInfo; + Found = 1; + break; + } + } + if ( !Found ) { + // + // No bridge on EPCI bus? + // + HalpEpciMin = HalpEpciMax = 0xff; + } + } + } + +#endif + +#define AMD_KLUDGE +#if defined(AMD_KLUDGE) +#define AMDPCIETHERNET 0x20001022 + // + // Open firmware is configuring the AMD chip in a way we cannot + // deal with. It is possible to issue a hard reset on Doral/Terlingua + // so that's what we do here. + // + + { + PULONG PciAddr = (PULONG)(HalpPciConfigAddr[0]); + PULONG PciData = (PULONG)(HalpPciConfigData[0]); + PVOID CRRBase; + ULONG CfgSpace[16]; + ULONG Slot; + ULONG i; + + for ( Slot = 0 ; Slot < 32 ; Slot++ ) { + HalpPhase0GetPciDataByOffset(0, + Slot, + CfgSpace, + 0, + 64); + if ( CfgSpace[0] == AMDPCIETHERNET ) { + // + // Change the command (and status) of this puppy + // so that when we write it back it's disabled. + // + CfgSpace[1] = 0; + + // + // Ok, now we need to write to UNION's Component + // Reset Register for this bridge. Bits of interest + // are 0 thru 5 correcponding to devices 1 thru 6 + // (spec says 0 thru 5 but they seem to want you + // to skip the memory controller before you start + // counting). + // + // Also, this register isn't byte reversed so we hit + // bits 24 thru 31 instead,... note that setting to + // 1 means leave it alone, setting to 0 resets. + // + // This register is at xxxf7ef0 which isn't mapped. + // This is the PCI bridge (not EPCI) so xxx in this + // case is bff. + // + CRRBase = HalpAssignReservedVirtualSpace(0xbfff7, 1); + + if ( !CRRBase ) { + // + // Bad things happened, give up. + // + break; + } + + *(PULONG)((ULONG)CRRBase + 0xef0) = 0xfc ^ (0x80 >> (Slot - 1)); + // + // Wait a while then unset the reset bit. + // + for ( i = 0 ; i < 1000000 ; i++ ) { + __builtin_eieio(); + } + *(PULONG)((ULONG)CRRBase + 0xef0) = 0xfc; + // + // Wait a while longer then write back the config space. + // + for ( i = 0 ; i < 1000000 ; i++ ) { + __builtin_eieio(); + } + HalpReleaseReservedVirtualSpace(CRRBase, 1); + HalpPhase0SetPciDataByOffset(0, + Slot, + CfgSpace, + 0, + 64); + // + // Assume there's only one. + // + break; + } + } + } + +#endif + + +} + +ULONG +HalpTranslatePciSlotNumber ( + ULONG BusNumber, + ULONG SlotNumber + ) +/*++ + +Routine Description: + + This routine translate a PCI slot number to a PCI device number. + +Arguments: + + None. + +Return Value: + + Returns length of data written. + +--*/ + +{ + // + // Sandalfoot only has 1 PCI bus so bus number is unused + // + + PCI_TYPE1_CFG_BITS PciConfig; + PCI_SLOT_NUMBER PciSlotNumber; + + PciSlotNumber.u.AsULONG = SlotNumber; + + PciConfig.u.AsULONG = 0; + PciConfig.u.bits.DeviceNumber = PciSlotNumber.u.bits.DeviceNumber; + PciConfig.u.bits.FunctionNumber = PciSlotNumber.u.bits.FunctionNumber; + PciConfig.u.bits.BusNumber = BusNumber; + PciConfig.u.bits.Enable = TRUE; + + return (PciConfig.u.AsULONG); +} + +ULONG +HalpPhase0SetPciDataByOffset ( + ULONG BusNumber, + ULONG SlotNumber, + PVOID Buffer, + ULONG Offset, + ULONG Length + ) + +/*++ + +Routine Description: + + This routine writes to PCI configuration space prior to bus handler + installation. + +Arguments: + + BusNumber PCI Bus Number. This is the 8 bit BUS Number which is + bits 23-16 of the Configuration Address. In support of + multiple top level busses, the upper 24 bits of this + argument will supply the index into the table of + configuration address registers. + SlotNumber PCI Slot Number, 8 bits composed of the 5 bit device + number (bits 15-11 of the configuration address) and + the 3 bit function number (10-8). + Buffer Address of source data. + Offset Number of bytes to skip from base of PCI config area. + Length Number of bytes to write + +Return Value: + + Returns length of data written. + +--*/ + +{ + PCI_TYPE1_CFG_BITS ConfigAddress; + ULONG ReturnLength; + PVOID ConfigAddressRegister; + PVOID ConfigDataRegister; + PUCHAR Bfr = (PUCHAR)Buffer; + + if ( BusNumber < HalpEpciMin ) { + ConfigAddressRegister = HalpPciConfigAddr[0]; + ConfigDataRegister = HalpPciConfigData[0]; + } else { + ConfigAddressRegister = HalpPciConfigAddr[1]; + ConfigDataRegister = HalpPciConfigData[1]; + } + + ASSERT(!(Offset & ~0xff)); + ASSERT(Length); + ASSERT((Offset + Length) <= 256); + + if ( Length + Offset > 256 ) { + if ( Offset > 256 ) { + return 0; + } + Length = 256 - Offset; + } + + ReturnLength = Length; + + ConfigAddress.u.AsULONG = HalpTranslatePciSlotNumber(BusNumber, + SlotNumber); + ConfigAddress.u.bits.RegisterNumber = (Offset & 0xfc) >> 2; + + if ( Offset & 0x3 ) { + // + // Access begins at a non-register boundary in the config + // space. We need to read the register containing the data + // and rewrite only the changed data. (I wonder if this + // ever really happens?) + // + ULONG SubOffset = Offset & 0x3; + ULONG SubLength = 4 - SubOffset; + union { + ULONG All; + UCHAR Bytes[4]; + } Tmp; + + if ( SubLength > Length ) { + SubLength = Length; + } + + // + // Adjust Length (remaining) and (new) Offset bu amount covered + // in this first word. + // + Length -= SubLength; + Offset += SubLength; + + // + // Get the first word (register), replace only those bytes that + // need to be changed, then write the whole thing back out again. + // + WRITE_PORT_ULONG(ConfigAddressRegister, ConfigAddress.u.AsULONG); + Tmp.All = READ_PORT_ULONG(ConfigDataRegister); + + while ( SubLength-- ) { + Tmp.Bytes[SubOffset++] = *Bfr++; + } + + WRITE_PORT_ULONG(ConfigDataRegister, Tmp.All); + + // + // Aim ConfigAddressRegister at the next word (register). + // + ConfigAddress.u.bits.RegisterNumber++; + } + + // + // Do the majority of the transfer 4 bytes at a time. + // + while ( Length > sizeof(ULONG) ) { + ULONG Tmp = *(UNALIGNED PULONG)Bfr; + WRITE_PORT_ULONG(ConfigAddressRegister, ConfigAddress.u.AsULONG); + WRITE_PORT_ULONG(ConfigDataRegister, Tmp); + ConfigAddress.u.bits.RegisterNumber++; + Bfr += sizeof(ULONG); + Length -= sizeof(ULONG); + + } + + // + // Do bytes in last register. + // + if ( Length ) { + union { + ULONG All; + UCHAR Bytes[4]; + } Tmp; + ULONG i = 0; + WRITE_PORT_ULONG(ConfigAddressRegister, ConfigAddress.u.AsULONG); + Tmp.All = READ_PORT_ULONG(ConfigDataRegister); + + while ( Length-- ) { + Tmp.Bytes[i++] = *(PUCHAR)Bfr++; + } + WRITE_PORT_ULONG(ConfigDataRegister, Tmp.All); + } + + return ReturnLength; +} + +ULONG +HalpPhase0GetPciDataByOffset ( + ULONG BusNumber, + ULONG SlotNumber, + PVOID Buffer, + ULONG Offset, + ULONG Length + ) + +/*++ + +Routine Description: + + This routine reads PCI config space prior to bus handlder installation. + +Arguments: + + BusNumber PCI Bus Number. This is the 8 bit BUS Number which is + bits 23-16 of the Configuration Address. In support of + multiple top level busses, the upper 24 bits of this + argument will supply the index into the table of + configuration address registers. + SlotNumber PCI Slot Number, 8 bits composed of the 5 bit device + number (bits 15-11 of the configuration address) and + the 3 bit function number (10-8). + Buffer Address of source data. + Offset Number of bytes to skip from base of PCI config area. + Length Number of bytes to write + +Return Value: + + Amount of data read. + +--*/ + +{ + PCI_TYPE1_CFG_BITS ConfigAddress; + PCI_TYPE1_CFG_BITS ConfigAddressTemp; + ULONG ReturnLength; + ULONG i; + union { + ULONG All; + UCHAR Bytes[4]; + } Tmp; + PVOID ConfigAddressRegister; + PVOID ConfigDataRegister; + + if ( BusNumber < HalpEpciMin ) { + ConfigAddressRegister = HalpPciConfigAddr[0]; + ConfigDataRegister = HalpPciConfigData[0]; + } else { + ConfigAddressRegister = HalpPciConfigAddr[1]; + ConfigDataRegister = HalpPciConfigData[1]; + } + + ASSERT(!(Offset & ~0xff)); + ASSERT(Length); + ASSERT((Offset + Length) <= 256); + + if ( Length + Offset > 256 ) { + if ( Offset > 256 ) { + return 0; + } + Length = 256 - Offset; + } + + ReturnLength = Length; + + ConfigAddress.u.AsULONG = HalpTranslatePciSlotNumber(BusNumber, + SlotNumber); + ConfigAddress.u.bits.RegisterNumber = (Offset & 0xfc) >> 2; + + // + // If we are being asked to read data when function != 0, check + // first to see if this device decares itself as a multi-function + // device. If it doesn't, don't do this read. + // + if (ConfigAddress.u.bits.FunctionNumber != 0) { + + ConfigAddressTemp.u.bits.RegisterNumber = 3; // contains header type + ConfigAddressTemp.u.bits.FunctionNumber = 0; // look at base package + ConfigAddressTemp.u.bits.DeviceNumber = ConfigAddress.u.bits.DeviceNumber; + ConfigAddressTemp.u.bits.BusNumber = ConfigAddress.u.bits.BusNumber; + ConfigAddressTemp.u.bits.Enable = TRUE; + + WRITE_PORT_ULONG(ConfigAddressRegister, ConfigAddressTemp.u.AsULONG); + Tmp.All = READ_PORT_ULONG(ConfigDataRegister); + + if (!(Tmp.Bytes[2] & 0x80)) { // if the Header type field's multi-function bit is not set + + for (i = 0; i < Length; i++) { + *((PUCHAR)Buffer)++ = 0xff; // Make this read as if the device isn't populated + } + + return Length; + } + } + + i = Offset & 0x3; + + while ( Length ) { + WRITE_PORT_ULONG(ConfigAddressRegister, ConfigAddress.u.AsULONG); + Tmp.All = READ_PORT_ULONG(ConfigDataRegister); + while ( (i < 4) && Length) { + *((PUCHAR)Buffer)++ = Tmp.Bytes[i]; + i++; + Length--; + } + i = 0; + ConfigAddress.u.bits.RegisterNumber++; + } + return ReturnLength; +} + +NTSTATUS +HalpGetPCIIrq ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER PciSlot, + OUT PSUPPORTED_RANGE *Interrupt + ) +{ + UCHAR buffer[PCI_COMMON_HDR_LENGTH]; + PPCI_COMMON_CONFIG PciData; + UCHAR InterruptPin; + UCHAR BaseLimit = 0; + UCHAR Class; + + PciData = (PPCI_COMMON_CONFIG) buffer; + HalGetBusData ( + PCIConfiguration, + BusHandler->BusNumber, + PciSlot.u.AsULONG, + PciData, + PCI_COMMON_HDR_LENGTH + ); + + if (PciData->VendorID == PCI_INVALID_VENDORID || + PCI_CONFIG_TYPE (PciData) != 0) { + return STATUS_UNSUCCESSFUL; + } + + *Interrupt = ExAllocatePool (PagedPool, sizeof (SUPPORTED_RANGE)); + if (!*Interrupt) { + return STATUS_INSUFFICIENT_RESOURCES; + } + + RtlZeroMemory (*Interrupt, sizeof (SUPPORTED_RANGE)); + + InterruptPin = PciData->u.type0.InterruptPin; + Class = PciData->BaseClass; + + if (InterruptPin == 0) { // Device doesn't implement an interrupt + return STATUS_UNSUCCESSFUL; + } + + BaseLimit = PciData->u.type0.InterruptLine + MPIC_BASE_VECTOR; + + (*Interrupt)->Base = BaseLimit; + (*Interrupt)->Limit = BaseLimit; + +#if DBG + DbgPrint("Interrupt line, by the hardware: 0x%x\n", + PciData->u.type0.InterruptLine + MPIC_BASE_VECTOR); +#endif + + if ( BaseLimit != NOT_MPIC) { + +#if defined(SOFT_HDD_LAMP) + + if ( Class == 1 ) { + // + // This device is a Mass Storage Controller, set flag to + // turn on the HDD Lamp when interrupts come in on this + // vector. + // + // (Shouldn't there be a constant defined somewhere for + // the Class? (plj)). + // + + extern ULONG HalpMassStorageControllerVectors; + + HalpMassStorageControllerVectors |= 1 << BaseLimit; + } + +#endif + + return STATUS_SUCCESS; + } + + ASSERT(!(BaseLimit == NOT_MPIC)); // We should never hit this because + // there should never be a device + // with an interrupt pin != 0 that + // has no valid mapping to the MPIC + return STATUS_UNSUCCESSFUL; +} + diff --git a/private/ntos/nthals/halvict/ppc/pxport.c b/private/ntos/nthals/halvict/ppc/pxport.c new file mode 100644 index 000000000..19c0841dc --- /dev/null +++ b/private/ntos/nthals/halvict/ppc/pxport.c @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxport.c> diff --git a/private/ntos/nthals/halvict/ppc/pxpower.s b/private/ntos/nthals/halvict/ppc/pxpower.s new file mode 100644 index 000000000..39dc14e06 --- /dev/null +++ b/private/ntos/nthals/halvict/ppc/pxpower.s @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxpower.s> diff --git a/private/ntos/nthals/halvict/ppc/pxproc.c b/private/ntos/nthals/halvict/ppc/pxproc.c new file mode 100644 index 000000000..5a8ee0570 --- /dev/null +++ b/private/ntos/nthals/halvict/ppc/pxproc.c @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxproc.c> diff --git a/private/ntos/nthals/halvict/ppc/pxprof.c b/private/ntos/nthals/halvict/ppc/pxprof.c new file mode 100644 index 000000000..5e9e3dc20 --- /dev/null +++ b/private/ntos/nthals/halvict/ppc/pxprof.c @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxprof.c> diff --git a/private/ntos/nthals/halvict/ppc/pxreset.s b/private/ntos/nthals/halvict/ppc/pxreset.s new file mode 100644 index 000000000..0b6c055f7 --- /dev/null +++ b/private/ntos/nthals/halvict/ppc/pxreset.s @@ -0,0 +1,557 @@ +//++ +// +// Copyright (c) 1993, 94, 95, 96 IBM Corporation +// +// Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file +// contains copyrighted material. Use of this file is restricted +// by the provisions of a Motorola Software License Agreement. +// +// Module Name: +// +// pxreset.s +// +// Abstract: +// +// This module implements the routine HalpPowerPcReset, which can be +// used to return the PowerPC to Big Endian with cache flushed and +// branches to the rom based machine reset handler. +// +// Author: +// +// Peter L. Johnston (plj@vnet.ibm.com) September 1993 +// +// Environment: +// +// Kernel mode only. +// +// Revision History: +// +// plj Feb 1995 Zap TLB before resetting, add 603+ +// and 604+ support. +// +// jlw Added eagle memory controller support +// plj Aug 1995 MP version (UNION dependent). +// +// +//-- + +#include "kxppc.h" + +#define HPT_LOCK 0x4fc + + + .set C_LINE_SZ, 64 + .set C_LINE_CNT, 64 + .set C_SETS, 8 + + .set C_SIZE, C_LINE_SZ * C_LINE_CNT * C_SETS + + .set HID0, 1008 + .set DISABLES, MASK_SPR(MSR_DR,1) | MASK_SPR(MSR_IR,1) + + + .set H0_603_DCE, 0x4000 // 603 Data Cache Enable + .set H0_603_ICE, 0x8000 // 603 Instruction Cache Enable + .set H0_603_ICFI, 0x0800 // 603 I-Cache Flash Invalidate + + .set H0_604_DCE, 0x4000 // 604 Data Cache Enable + .set H0_604_ICE, 0x8000 // 604 Instruction Cache Enable + .set H0_604_DCIA, 0x0400 // 604 I-Cache Invalidate All + .set H0_604_ICIA, 0x0800 // 604 I-Cache Invalidate All + + .set TLB_CLASSES_601, 128 // 601 tlb has 128 congruence classes + .set TLB_CLASSES_603, 32 // 603 tlb has 32 congruence classes + .set TLB_CLASSES_604, 64 // 604 tlb has 64 congruence classes + + + LEAF_ENTRY(HalpPowerPcReset) + li r.6, -1 + mtdec r.6 + isync + + bl ..HalpResetHelper +here: + mflr r.9 // r.9 = &here + + LWI(r.4, 0xfff00100) // address of rom reset handler + LWI(r.7, 0x80000092) // address of MEM CTLR endian sw + li r.6, 0 + + bne not_601 // jif processor is not a 601 + + // + // processor is a 601 + // + + rlwinm r.5, r.5, 0, ~(0x0008) // turn off little endian + + // + // disable instruction and data relocation and switch + // interrupt prefix to fetch from ROM + // + + andi. r.8, r.8, ~DISABLES & 0xffff + ori r.8, r.8, MASK_SPR(MSR_IP,1) + mtsrr1 r.8 // this will also be target state + nop // for rfi + +// +// Ensure all code from 'cachem' to 'end_little' is in cache by loading a +// byte in each address line in that range. + + addi r.9, r.9, cachem-here // (r.9) = physical &cachem + + // r.9 now contains the physical address of cachem. (assuming + // this code was loaded as part of kernel which is loaded at + // physical 0 = virtual 0x80000000). We effect the switch to + // physical addressing thru an rfi with the target state set + // to resume at cachem with relocation and interrupts disabled. + + mtsrr0 r.9 // address of cachem for rfi + addi r.10, r.9, end_little-cachem // (r.10) = &end_little + addi r.11, r.9, HalpPowerPcReset.end-cachem // (r.11) = &reset_end + + addi r.12, r.9, -C_LINE_SZ // bias addr for 1st iteration by + // amount added by lbzu prior to load + + rfi // switch +cachem: + lbzu r.13, C_LINE_SZ(r.12) // get byte at (r.13)+C_LINE_SZ + cmplw r.12, r.10 // bumping r.12 by C_LINE_SZ + addi r.13, r.13, 1 // ensure load completed. + blt cachem // get all in range here-end_little. + + isync + mtsrr0 r.4 // set rom reset target for next rfi + lis r.9, 0x87f0 // Segment register base 0x87f00000 + li r.10, 0xf // Set all 16 segment registers + + li r.11, 0 + mtibatl 0, r.6 // zero bat 0-3 upper and lower + mtibatu 0, r.6 + mtibatl 1, r.6 + + mtibatu 1, r.6 + mtibatl 2, r.6 + mtibatu 2, r.6 + mtibatl 3, r.6 + + mtibatu 3, r.6 +setsr: rlwimi r.11, r.10, 28, 0, 3 // Shift segment reg. # to bits 0-3 + or r.12, r.9, r.10 // Segment register value 0x87f000sr + mtsrin r.12, r.11 + + addic. r.10, r.10, -1 // Next segment register + bne setsr + nop + nop + + nop + nop + nop + nop + + nop + sync // quiet the machine down + sync + sync + + sync + stb r.6, 0(r.7) // switch memory + eieio // flush io + sync + + sync + sync + sync + mtspr HID0, r.5 // switch ends on the cpu + + sync + sync + sync + addi r.0, r.1, 0x138 // same both ways + + addi r.0, r.1, 0x138 // same both ways + addi r.0, r.1, 0x138 // same both ways + addi r.0, r.1, 0x138 // same both ways + addi r.0, r.1, 0x138 // same both ways + + addi r.0, r.1, 0x138 // same both ways + addi r.0, r.1, 0x138 // same both ways + addi r.0, r.1, 0x138 // same both ways + addi r.0, r.1, 0x138 // same both ways + + addi r.0, r.1, 0x138 // same both ways + addi r.0, r.1, 0x138 // same both ways + addi r.0, r.1, 0x138 // same both ways + addi r.0, r.1, 0x138 // same both ways + + addi r.0, r.1, 0x138 // same both ways + addi r.0, r.1, 0x138 // same both ways + addi r.0, r.1, 0x138 // same both ways + mtsr 0, r.9 // Set the last segment register + + rfi // head off into the reset handler + rfi + addi r.0, r.1, 0x138 // we never get here + oris r.0, r.0, 0x4c // rfi (big-endian) +end_little: + + b $ + +// +// For the 603 (and hopefully other) processor(s) things are a little +// easier because little-endianness is controlled by the MSR. We still +// have to change memory seperately so we still want code from the memory +// switch thru the cpu switch in cache. +// +// When we get here +// r.4 contains the address of the ROM resident Machine Reset +// handler. +// r.6 contains 0. +// r.7 contains the port address (real) used to switch memory +// endianness. +// r.8 contains MSR present value. +// r.9 contains the address of "here". +// r.31 contains the processor type + + +not_601: + +// +// MSR bits ILE and POW must be disabled via mtmsr as rfi only moves +// the least significant 16 bits into the MSR. +// + + rlwinm r.8, r.8, 0, ~MASK_SPR(MSR_POW,1) // -= Power Management + rlwinm r.8, r.8, 0, ~MASK_SPR(MSR_ILE,1) // -= Interrupt Little Endian + sync + mtmsr r.8 + isync + +// +// Use an rfi to switch to big-endian, untranslated, interrupt prefix on +// with a target address in the nice harmless pallindromic code below. +// use another rfi to branch to the rom resident reset handler. +// + + li r.8, MASK_SPR(MSR_ME,1) | MASK_SPR(MSR_IP,1) + addi r.9, r.9, uncached_6034-here + mtsrr1 r.8 // state = Machine Check Enabled + bl here2 +here2: mflr r.28 + rlwinm r.28, r.28, 0, 0x7fffffff // convert address to physical + lwz r.29, endofroutine - here2(r.28) + mtsrr0 r.9 // rfi to uncached_6034 + b jumpswap + +memoryswap: + ori r.8, r.28, 0 + addi r.8, r.8, uncached_6034-here2 + addi r.9, 0, 0 + li r.15, swapend - uncached_6034 + addis r.14, 0, 0 + addi r.14, 0, 4 +swaploop: + lwz r.11, 0(r.8) + lwz r.12, 4(r.8) + stwbrx r.11, r.14, r.8 + stwbrx r.12, 0, r.8 + addi r.8, r.8, 8 + subi r.15, r.15, 8 + cmpi 0, 0, r.15, 0 + bgt swaploop + +jumpswap: + +// +// The following bizzareness is to ensure that the memory switch thru +// the disabling of cache is in cache. There is less than 32 bytes so +// they must be part of either the cache line we are currently in, or +// the one at the target of the branch. Therefore, branching over them, +// doing a little and branching back to them should be enough to enure +// they're cache resident. +// + + b fill_icache +goto_bigendian: + sync + stb r.6, 0(r.7) // switch memory + sync + lwz r.30, endofroutine - here2(r.28) + cmp 0, 0, r.29, r.30 + beq memoryswap + rfi +fill_icache: + isync + sync // complete everything! + b goto_bigendian + + .align 5 + +uncached_6034: + .big_endian // out of cache fetches must be + // assembled in same mode as processor + addi r.0, r.1, 0x138 // same both ways + addi r.0, r.1, 0x138 // same both ways + addi r.0, r.1, 0x138 // same both ways + addi r.0, r.1, 0x138 // same both ways + + addi r.0, r.1, 0x138 // same both ways + addi r.0, r.1, 0x138 // same both ways + addi r.0, r.1, 0x138 // same both ways + addi r.0, r.1, 0x138 // same both ways + + addi r.0, r.1, 0x138 // same both ways + addi r.0, r.1, 0x138 // same both ways + addi r.0, r.1, 0x138 // same both ways + addi r.0, r.1, 0x138 // same both ways + + addi r.0, r.1, 0x138 // same both ways + addi r.0, r.1, 0x138 // same both ways + addi r.0, r.1, 0x138 // same both ways + addi r.0, r.1, 0x138 // same both ways + + addi r.0, r.1, 0x138 // same both ways + addi r.0, r.1, 0x138 // same both ways + addi r.0, r.1, 0x138 // same both ways + addi r.0, r.1, 0x138 // same both ways + + addi r.0, r.1, 0x138 // same both ways + addi r.0, r.1, 0x138 // same both ways + mtsrr0 r.4 // rfi target = 0xfff00100 + mtspr HID0, r.10 // DISABLE CACHING + + mtibatl 0, r.6 // invalidate/clear all bats + mtibatu 0, r.6 + mtibatl 1, r.6 + mtibatu 1, r.6 + + mtibatl 2, r.6 + mtibatu 2, r.6 + mtibatl 3, r.6 + mtibatu 3, r.6 + + mtdbatl 0, r.6 + mtdbatu 0, r.6 + mtdbatl 1, r.6 + mtdbatu 1, r.6 + + mtdbatl 2, r.6 + mtdbatu 2, r.6 + mtdbatl 3, r.6 + mtdbatu 3, r.6 + + mtsr 0, r.6 + mtsr 1, r.6 + mtsr 2, r.6 + mtsr 3, r.6 + + mtsr 4, r.6 + mtsr 5, r.6 + mtsr 6, r.6 + mtsr 7, r.6 + + mtsr 8, r.6 + mtsr 9, r.6 + mtsr 10, r.6 + mtsr 11, r.6 + + mtsr 12, r.6 + mtsr 13, r.6 + mtsr 14, r.6 + mtsr 15, r.6 + + rfi // go to machine reset handler + // never get here + rfi // previous rfi on a dword boundary + // allow for word swap + .little_endian +endofroutine: + sync + .globl swapend + .long swapend +swapend: + + LEAF_EXIT(HalpPowerPcReset) + + LEAF_ENTRY(HalpResetUnion) + + bl ..HalpResetHelper + +// +// Union has a Software Power on Reset control register. Any write to +// this register will send a hard reset to all processors and I/O devices +// and the memory controller (Union) itself. +// + + li r.0, -1 // something to write + isync + lis r.8, 0xff00 // get address of S/R POR reg + stw r.0, 0xe8(r.8) // should never get here. + sync + sync + sync + sync + isync + + LEAF_EXIT(HalpResetUnion) + +//++ +// +// HalpResetHelper +// +// This routine locks the HPT, invalidates the TLB, disables the caches +// and returns to the caller in REAL mode. +// +// On entry, interrupts are expected to be disabled. +// +// Arguments: +// +// None. +// +// Return Value: +// +// cr.0 EQ if processor is a 601 +// r.5 contains HID0 present value. +// r.8 contains MSR present value. +// r.31 contains PVR >> 16. +// +//-- + + LEAF_ENTRY(HalpResetHelper) + + mfspr r.5, HID0 + mfpvr r.31 // determine processor type + mfmsr r.8 + rlwinm r.8, r.8, 0, ~MASK_SPR(MSR_EE,1) // disable interrupts + mtmsr r.8 + rlwinm r.8, r.8, 0, ~MASK_SPR(MSR_DR,1) // -= Data Relocation + rlwinm r.8, r.8, 0, ~MASK_SPR(MSR_IR,1) // -= Inst Relocation + mtsrr1 r.8 // rfi target state + mflr r.9 // (r.9) = return address + rlwinm r.9, r.9, 0, 0x7fffffff // convert address to physical + + // + // Get the processor into real mode. The following assumes + // physical = (virtual & 0x7fffffff) for this code. If this + // assumption cannot be guaranteed (this code has been paged?) + // then we should copy it to low memory,.... we are at high + // IRQL so we can't page fault but has it always been locked? + // (This question arises as more or the kernel and hal are made + // pageable and moved out of BAT protection). + // + bl almost_real +almost_real: + mflr r.3 // r.3 = &almost_real + addi r.3, r.3, real-almost_real + rlwinm r.3, r.3, 0, 0x7fffffff // convert address to physical + mtsrr0 r.3 // set target address + rfi +real: + + // + // The processor is now executing in REAL mode. + // + mtlr r.9 // set real return address + + // + // Attempt to get the HPT lock. If attempt fails 1024 * 1024 + // times, just take it anyway (the other processor(s) is + // probably dead) or this processor already has it. + // + + li r.3, HPT_LOCK // get address of HPT LOCK + lis r.9, 0x10 // retry count (1024 * 1024) + mtctr r.9 + li r.9, 1 // lock value + +lockhpt: + lwarx r.10, 0, r.3 // get current lock value + cmpwi r.10, 0 + bne lockretry + stwcx. r.9, 0, r.3 + beq lockedhpt +lockretry: + bdnz lockhpt + + // + // Failed to obtain lock. Forcibly lock it. + // + + stw r.9, 0(r.3) + +lockedhpt: + + // + // invalidate all tlb entries + // + + li r.3, TLB_CLASSES_601 // use largest known number of + // congruence classes + mtctr r.3 // number of classes = iteration count +zaptlb: tlbie r.3 // invalidate tlb congruence class + addi r.3, r.3, 4096 // increment to next class address + bdnz zaptlb // loop through all classes + sync + + srwi r.31, r.31, 16 // isolate processor type + cmpwi r.31, 1 // is 601? + + beqlr // return if 601 (no cache control) + + cmpwi cr.0, r.31, 3 // is 603? + cmpwi cr.4, r.31, 7 // is 603ev? + cmpwi cr.1, r.31, 6 // is 603e? + cmpwi cr.2, r.31, 4 // is 604? + cmpwi cr.3, r.31, 9 // is 604e? + beq cr.0, is_603 + beq cr.4, is_603 + bne cr.1, not_603 + +// +// 603 I-Cache is invalidated by setting ICFI in HID0. Unlike +// the 604, this bit is not self clearing. +// + +is_603: rlwinm r.5, r.5, 0, ~H0_603_DCE// turn off D-cache + rlwinm r.10, r.5, 0, ~H0_603_ICE// turn off I-cache + ori r.10, r.10, H0_603_ICFI // I-Cache Flash Invalidate + ori r.5, r.5, H0_603_ICE // I-cache enable + isync + mtspr HID0, r.10 // invalidate/disable + mtspr HID0, r.5 // enable + blr // return + +not_603: + beq cr.2, is_604 +// bne not_604 + +// Note: the above branch is commented out because we don't +// currently have any other options,... 620 will probably +// be different. + + +is_604: tlbsync // wait all processor tlb invalidate + sync + +// +// 604 caches must be enabled in order to be invalidated. It +// is acceptable to enable and invalidate with the same move +// to hid0. The data cache will be left disabled, the instruction +// cache enabled. +// + + ori r.5, r.5, H0_604_DCE | H0_604_ICE + ori r.10, r.5, H0_604_DCIA | H0_604_ICIA + + rlwinm r.5, r.5, 0, ~H0_604_DCE + rlwinm r.5, r.5, 0, ~H0_604_DCIA + rlwinm r.5, r.5, 0, ~H0_604_ICIA + + mtspr HID0, r.10 // enable + invalidate + mtspr HID0, r.5 // disable data cache + + rlwinm r.10, r.5, 0, ~H0_604_ICE // disable i-cache later + + LEAF_EXIT(HalpResetHelper) diff --git a/private/ntos/nthals/halvict/ppc/pxreturn.c b/private/ntos/nthals/halvict/ppc/pxreturn.c new file mode 100644 index 000000000..8181c91f7 --- /dev/null +++ b/private/ntos/nthals/halvict/ppc/pxreturn.c @@ -0,0 +1,2 @@ +#include "..\..\halppc\ppc\pxreturn.c" + diff --git a/private/ntos/nthals/halvict/ppc/pxs3.c b/private/ntos/nthals/halvict/ppc/pxs3.c new file mode 100644 index 000000000..0b7211142 --- /dev/null +++ b/private/ntos/nthals/halvict/ppc/pxs3.c @@ -0,0 +1,2 @@ +#include "..\..\halppc\ppc\pxs3.c" + diff --git a/private/ntos/nthals/halvict/ppc/pxshadbf.s b/private/ntos/nthals/halvict/ppc/pxshadbf.s new file mode 100644 index 000000000..d637a3763 --- /dev/null +++ b/private/ntos/nthals/halvict/ppc/pxshadbf.s @@ -0,0 +1,2 @@ +#include <..\..\halppc\ppc\pxshadbf.s> + diff --git a/private/ntos/nthals/halvict/ppc/pxstall.s b/private/ntos/nthals/halvict/ppc/pxstall.s new file mode 100644 index 000000000..50d947500 --- /dev/null +++ b/private/ntos/nthals/halvict/ppc/pxstall.s @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxstall.s> diff --git a/private/ntos/nthals/halvict/ppc/pxsysbus.c b/private/ntos/nthals/halvict/ppc/pxsysbus.c new file mode 100644 index 000000000..bbc98ee76 --- /dev/null +++ b/private/ntos/nthals/halvict/ppc/pxsysbus.c @@ -0,0 +1,2 @@ +#include "..\..\halppc\ppc\pxsysbus.c" + diff --git a/private/ntos/nthals/halvict/ppc/pxtime.c b/private/ntos/nthals/halvict/ppc/pxtime.c new file mode 100644 index 000000000..5fe5a500a --- /dev/null +++ b/private/ntos/nthals/halvict/ppc/pxtime.c @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxtime.c> diff --git a/private/ntos/nthals/halvict/ppc/pxusage.c b/private/ntos/nthals/halvict/ppc/pxusage.c new file mode 100644 index 000000000..3be115176 --- /dev/null +++ b/private/ntos/nthals/halvict/ppc/pxusage.c @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxusage.c> diff --git a/private/ntos/nthals/halvict/ppc/pxvm.c b/private/ntos/nthals/halvict/ppc/pxvm.c new file mode 100644 index 000000000..d515cb51f --- /dev/null +++ b/private/ntos/nthals/halvict/ppc/pxvm.c @@ -0,0 +1,2 @@ +#include "..\..\halppc\ppc\pxvm.c" + diff --git a/private/ntos/nthals/halvict/ppc/pxwd.c b/private/ntos/nthals/halvict/ppc/pxwd.c new file mode 100644 index 000000000..bcfc1f5e9 --- /dev/null +++ b/private/ntos/nthals/halvict/ppc/pxwd.c @@ -0,0 +1,2 @@ +#include "..\..\halppc\ppc\pxwd.c" + diff --git a/private/ntos/nthals/halvict/ppc/x86bios.c b/private/ntos/nthals/halvict/ppc/x86bios.c new file mode 100644 index 000000000..ba7969c5d --- /dev/null +++ b/private/ntos/nthals/halvict/ppc/x86bios.c @@ -0,0 +1 @@ +#include "..\..\halppc\ppc\x86bios.c" diff --git a/private/ntos/nthals/halvict/sources b/private/ntos/nthals/halvict/sources new file mode 100644 index 000000000..5985d56c0 --- /dev/null +++ b/private/ntos/nthals/halvict/sources @@ -0,0 +1,107 @@ +!IF 0 + +Copyright (c) 1993 Microsoft Corporation + +Module Name: + + sources. + +Abstract: + + This file specifies the target component being built and the list of + sources files needed to build that component. Also specifies optional + compiler switches and libraries that are unique for the component being + built. + + + +Author: + + David N. Cutler (davec) 8-Apr-1993 + +Revision Histoy: + + Jim Wooldridge (jimw@austin.vnet.ibm.com) Power PC port + +NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl + +!ENDIF + +MAJORCOMP=ntos +MINORCOMP=hal + +TARGETNAME=halvict +TARGETPATH=$(BASEDIR)\public\sdk\lib +TARGETLIBS=..\x86new\obj\*\x86new.lib \ + $(BASEDIR)\public\sdk\lib\*\libc.lib + + +!IF $(PPC) + +TARGETTYPE=HAL + +!ELSE + +TARGETTYPE=DRIVER + +!ENDIF + +C_DEFINES=-D_MP_PPC_ -DDAKOTA -DVICTORY -DSOFT_HDD_LAMP -D_HALNVR_ + +INCLUDES=..\halppc\ppc;..\x86new;$(BASEDIR)\private\ntos\inc + +SOURCES= + +PPC_SOURCES=hal.rc \ + drivesup.c \ + bushnd.c \ + rangesup.c \ + ppc\pxbeep.c \ + ppc\pxnatsup.c \ + ppc\pxfirsup.c \ + ppc\pxmemctl.c \ + ppc\pxpcisup.c \ + ppc\pxdisp.c \ + ppc\pxp91.c \ + ppc\pxwd.c \ + ppc\pxs3.c \ + ppc\pxbbl.c \ + ppc\pxbl.c \ + ppc\pxshadbf.s \ + ppc\pxstall.s \ + ppc\pxcache.s \ + ppc\pxclock.c \ + ppc\pxcalstl.c \ + ppc\pxclksup.s \ + ppc\pxflshbf.s \ + ppc\pxhwsup.c \ + ppc\pxprof.c \ + ppc\pxenviro.c \ + ppc\pxmapio.c \ + ppc\pxtime.c \ + ppc\pxreset.s \ + ppc\pxreturn.c \ + ppc\pxinithl.c \ + ppc\pxport.c \ + ppc\pxirql.c \ + ppc\pxusage.c \ + ppc\pxbusdat.c \ + ppc\pxpcibus.c \ + ppc\pxpciint.c \ + ppc\pxisabus.c \ + ppc\pxidle.c \ + ppc\pxsysbus.c \ + ppc\pxproc.c \ + ppc\pxdat.c \ + ppc\fwnvr.c \ + ppc\pxflshio.c \ + ppc\pxinfo.c \ + ppc\pxpcibrd.c \ + ppc\pxvm.c \ + ppc\pxpower.s \ + ppc\pxintrpt.c \ + ppc\pxmisc.s \ + ppc\x86bios.c + +DLLDEF=obj\*\hal.def + |