/*++ 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; }