bool IOPlatformExpert::start( IOService * provider ) { IORangeAllocator * physicalRanges; OSData * busFrequency; if (!super::start(provider)) return false; // Register the presence or lack thereof a system // PCI address mapper with the IOMapper class #if 1 IORegistryEntry * regEntry = IORegistryEntry::fromPath("/u3/dart", gIODTPlane); if (!regEntry) regEntry = IORegistryEntry::fromPath("/dart", gIODTPlane); if (regEntry) { int debugFlags; if (!PE_parse_boot_arg("dart", &debugFlags) || debugFlags) setProperty(kIOPlatformMapperPresentKey, kOSBooleanTrue); regEntry->release(); } #endif IOMapper::setMapperRequired(0 != getProperty(kIOPlatformMapperPresentKey)); gIOInterruptControllers = OSDictionary::withCapacity(1); gIOInterruptControllersLock = IOLockAlloc(); // Correct the bus frequency in the device tree. busFrequency = OSData::withBytesNoCopy((void *)&gPEClockFrequencyInfo.bus_clock_rate_hz, 4); provider->setProperty("clock-frequency", busFrequency); busFrequency->release(); gPlatformInterruptControllerName = (OSSymbol *)OSSymbol::withCStringNoCopy("IOPlatformInterruptController"); physicalRanges = IORangeAllocator::withRange(0xffffffff, 1, 16, IORangeAllocator::kLocking); assert(physicalRanges); setProperty("Platform Memory Ranges", physicalRanges); setPlatform( this ); gIOPlatform = this; PMInstantiatePowerDomains(); // Parse the serial-number data and publish a user-readable string OSData* mydata = (OSData*) (provider->getProperty("serial-number")); if (mydata != NULL) { OSString *serNoString = createSystemSerialNumberString(mydata); if (serNoString != NULL) { provider->setProperty(kIOPlatformSerialNumberKey, serNoString); serNoString->release(); } } return( configure(provider) ); }
IOService *NullCPUPowerManagement::probe(IOService *provider, SInt32 *score) { if(IOService::probe(provider, score) == NULL) return NULL; #if 0 // If the hpet's invalid then succeed probe if(hpetIsInvalid()) { IOLog("NullCPUPowerManagement::probe: Claiming match category with probe score %ld.\n", score!=NULL?*score:-1); return this; } #endif char crap[20]; if(PE_parse_boot_arg("-allowAppleCPUPM", crap)) { IOLog("NullCPUPowerManagement is respecting the -allowAppleCPUPM flag.\n"); return NULL; } // Always succeed until we can figure out a better way of detecting a valid HPET. return this; }
/* * Initialize the framework; this is currently called as part of BSD init. */ __private_extern__ void mcache_init(void) { mcache_bkttype_t *btp; unsigned int i; char name[32]; ncpu = ml_get_max_cpus(); mcache_llock_grp_attr = lck_grp_attr_alloc_init(); mcache_llock_grp = lck_grp_alloc_init("mcache.list", mcache_llock_grp_attr); mcache_llock_attr = lck_attr_alloc_init(); mcache_llock = lck_mtx_alloc_init(mcache_llock_grp, mcache_llock_attr); mcache_zone = zinit(MCACHE_ALLOC_SIZE, 256 * MCACHE_ALLOC_SIZE, PAGE_SIZE, "mcache"); if (mcache_zone == NULL) panic("mcache_init: failed to allocate mcache zone\n"); LIST_INIT(&mcache_head); for (i = 0; i < sizeof (mcache_bkttype) / sizeof (*btp); i++) { btp = &mcache_bkttype[i]; (void) snprintf(name, sizeof (name), "bkt_%d", btp->bt_bktsize); btp->bt_cache = mcache_create(name, (btp->bt_bktsize + 1) * sizeof (void *), 0, 0, MCR_SLEEP); } PE_parse_boot_arg("mcache_flags", &mcache_flags); mcache_flags &= MCF_FLAGS_MASK; mcache_audit_cache = mcache_create("audit", sizeof (mcache_audit_t), 0, 0, MCR_SLEEP); mcache_reap_interval = 15 * hz; mcache_applyall(mcache_cache_bkt_enable); mcache_ready = 1; }
bool MacRISC2CPU::start(IOService *provider) { kern_return_t result; IORegistryEntry *cpusRegEntry, *uniNRegEntry, *mpicRegEntry, *devicetreeRegEntry; OSIterator *cpusIterator; OSData *tmpData; IOService *service; const OSSymbol *interruptControllerName; OSData *interruptData; OSArray *tmpArray; UInt32 maxCPUs, uniNVersion, physCPU; ml_processor_info_t processor_info; #if enableUserClientInterface DFScontMode = 0; fWorkLoop = 0; DFS_Status = false; GPU_Status = kGPUHigh; vStepped = false; #endif // callPlatformFunction symbols mpic_getProvider = OSSymbol::withCString("mpic_getProvider"); mpic_getIPIVector= OSSymbol::withCString("mpic_getIPIVector"); mpic_setCurrentTaskPriority = OSSymbol::withCString("mpic_setCurrentTaskPriority"); mpic_setUpForSleep = OSSymbol::withCString("mpic_setUpForSleep"); mpic_dispatchIPI = OSSymbol::withCString("mpic_dispatchIPI"); keyLargo_restoreRegisterState = OSSymbol::withCString("keyLargo_restoreRegisterState"); keyLargo_syncTimeBase = OSSymbol::withCString("keyLargo_syncTimeBase"); keyLargo_saveRegisterState = OSSymbol::withCString("keyLargo_saveRegisterState"); keyLargo_turnOffIO = OSSymbol::withCString("keyLargo_turnOffIO"); keyLargo_writeRegUInt8 = OSSymbol::withCString("keyLargo_writeRegUInt8"); keyLargo_getHostKeyLargo = OSSymbol::withCString("keyLargo_getHostKeyLargo"); keyLargo_setPowerSupply = OSSymbol::withCString("setPowerSupply"); uniN_setPowerState = OSSymbol::withCString(kUniNSetPowerState); uniN_setAACKDelay = OSSymbol::withCString(kUniNSetAACKDelay); pmu_cpuReset = OSSymbol::withCString("cpuReset"); ati_prepareDMATransaction = OSSymbol::withCString(kIOFBPrepareDMAValueKey); ati_performDMATransaction = OSSymbol::withCString(kIOFBPerformDMAValueKey); macRISC2PE = OSDynamicCast(MacRISC2PE, getPlatform()); if (macRISC2PE == 0) return false; if (!super::start(provider)) return false; // Get the Uni-N Version. uniNRegEntry = fromPath("/uni-n", gIODTPlane); if (uniNRegEntry == 0) return false; tmpData = OSDynamicCast(OSData, uniNRegEntry->getProperty("device-rev")); if (tmpData == 0) return false; uniNVersion = *(long *)tmpData->getBytesNoCopy(); // Find out if this is the boot CPU. bootCPU = false; tmpData = OSDynamicCast(OSData, provider->getProperty("state")); if (tmpData == 0) return false; if (!strcmp((char *)tmpData->getBytesNoCopy(), "running")) bootCPU = true; // Count the CPUs. numCPUs = 0; cpusRegEntry = fromPath("/cpus", gIODTPlane); if (cpusRegEntry == 0) return false; cpusIterator = cpusRegEntry->getChildIterator(gIODTPlane); while (cpusIterator->getNextObject()) numCPUs++; cpusIterator->release(); // [3830950] - The bootCPU driver inits globals for all instances (like gCPUIC) so if we're not the // boot CPU driver we wait here for that driver to finish its initialization if ((numCPUs > 1) && !bootCPU) // Wait for bootCPU driver to say it's up and running (void) waitForService (resourceMatching ("BootCPU")); // Limit the number of CPUs to one if uniNVersion is 1.0.7 or less. if (uniNVersion < kUniNVersion107) numCPUs = 1; // Limit the number of CPUs by the cpu=# boot arg. if (PE_parse_boot_arg("cpus", &maxCPUs)) { if (numCPUs > maxCPUs) numCPUs = maxCPUs; } ignoreSpeedChange = false; doSleep = false; topLevelPCIBridgeCount = 0; // Get the "flush-on-lock" property from the first cpu node. flushOnLock = false; cpusRegEntry = fromPath("/cpus/@0", gIODTPlane); if (cpusRegEntry == 0) return false; if (cpusRegEntry->getProperty("flush-on-lock") != 0) flushOnLock = true; // Set flushOnLock when numCPUs is not one. if (numCPUs != 1) flushOnLock = true; // If system is PowerMac3,5 (TowerG4), then set flushOnLock to disable nap devicetreeRegEntry = fromPath("/", gIODTPlane); tmpData = OSDynamicCast(OSData, devicetreeRegEntry->getProperty("model")); if (tmpData == 0) return false; #if 0 if(!strcmp((char *)tmpData->getBytesNoCopy(), "PowerMac3,5")) flushOnLock = true; #endif // Get the physical CPU number from the "reg" property. tmpData = OSDynamicCast(OSData, provider->getProperty("reg")); if (tmpData == 0) return false; physCPU = *(long *)tmpData->getBytesNoCopy(); setCPUNumber(physCPU); // Get the gpio offset for soft reset from the "soft-reset" property. tmpData = OSDynamicCast(OSData, provider->getProperty("soft-reset")); if (tmpData == 0) { if (physCPU == 0) soft_reset_offset = 0x5B; else soft_reset_offset = 0x5C; } else soft_reset_offset = *(long *)tmpData->getBytesNoCopy(); // Get the gpio offset for timebase enable from the "timebase-enable" property. tmpData = OSDynamicCast(OSData, provider->getProperty("timebase-enable")); if (tmpData == 0) timebase_enable_offset = 0x73; else timebase_enable_offset = *(long *)tmpData->getBytesNoCopy(); // See if reset is needed on wake resetOnWake = (provider->getProperty ("reset-on-wake") != NULL); if (resetOnWake) { vm_address_t reserveMem; reserveMem = (vm_address_t)IOMallocAligned (PAGE_SIZE, PAGE_SIZE); // Get one page (which we keep forever) if (reserveMem) { // map it reserveMemDesc = IOMemoryDescriptor::withAddress (reserveMem, PAGE_SIZE, kIODirectionNone, NULL); if (reserveMemDesc) { // get the physical address reserveMemPhys = reserveMemDesc->getPhysicalAddress(); } } } // On machines with a 'vmin' property in the CPU Node we need to make sure to tell the kernel to // ml_set_processor_voltage on needed processors. needVSetting = (provider->getProperty( "vmin" ) != 0); // While techincally the Apollo7PM machines do need AACK delay, it is already set in the bootROM // since we boot slow. We don't want the machine to switch AACKdelay off when we run DFS high so // setting this to false will take care of the issue. needAACKDelay = false; if (bootCPU) { gCPUIC = new IOCPUInterruptController; if (gCPUIC == 0) return false; if (gCPUIC->initCPUInterruptController(numCPUs) != kIOReturnSuccess) return false; gCPUIC->attach(this); gCPUIC->registerCPUInterruptController(); } // Get the l2cr value from the property list. tmpData = OSDynamicCast(OSData, provider->getProperty("l2cr")); if (tmpData != 0) { l2crValue = *(long *)tmpData->getBytesNoCopy() & 0x7FFFFFFF; } else { l2crValue = mfl2cr() & 0x7FFFFFFF; } // Wait for KeyLargo to show up. keyLargo = waitForService(serviceMatching("KeyLargo")); if (keyLargo == 0) return false; keyLargo->callPlatformFunction (keyLargo_getHostKeyLargo, false, &keyLargo, 0, 0, 0); if (keyLargo == 0) { kprintf ("MacRISC2CPU::start - getHostKeyLargo returned nil\n"); return false; } // Wait for MPIC to show up. mpic = waitForService(serviceMatching("AppleMPICInterruptController")); if (mpic == 0) return false; // Set the Interrupt Properties for this cpu. mpic->callPlatformFunction(mpic_getProvider, false, (void *)&mpicRegEntry, 0, 0, 0); interruptControllerName = IODTInterruptControllerName(mpicRegEntry); mpic->callPlatformFunction(mpic_getIPIVector, false, (void *)&physCPU, (void *)&interruptData, 0, 0); if ((interruptControllerName == 0) || (interruptData == 0)) return false; tmpArray = OSArray::withCapacity(1); tmpArray->setObject(interruptControllerName); cpuNub->setProperty(gIOInterruptControllersKey, tmpArray); tmpArray->release(); tmpArray = OSArray::withCapacity(1); tmpArray->setObject(interruptData); cpuNub->setProperty(gIOInterruptSpecifiersKey, tmpArray); tmpArray->release(); setCPUState(kIOCPUStateUninitalized); // necessary bootCPU initialization is done, so release other CPU drivers to do their thing // other drivers need to be unblocked *before* we call processor_start otherwise we deadlock if (bootCPU) publishResource ("BootCPU", this); if (physCPU < numCPUs) { processor_info.cpu_id = (cpu_id_t)this; processor_info.boot_cpu = bootCPU; processor_info.start_paddr = 0x0100; processor_info.l2cr_value = l2crValue; processor_info.supports_nap = !flushOnLock; processor_info.time_base_enable = OSMemberFunctionCast(time_base_enable_t, this, &MacRISC2CPU::enableCPUTimeBase); // [4091924] // Register this CPU with mach. result = ml_processor_register(&processor_info, &machProcessor, &ipi_handler); if (result == KERN_FAILURE) return false; processor_start(machProcessor); } // Before to go to sleep we wish to disable the napping mode so that the PMU // will not shutdown the system while going to sleep: service = waitForService(serviceMatching("IOPMrootDomain")); pmRootDomain = OSDynamicCast(IOPMrootDomain, service); if (pmRootDomain != 0) { kprintf("Register MacRISC2CPU %ld to acknowledge power changes\n", getCPUNumber()); pmRootDomain->registerInterestedDriver(this); // Join the Power Management Tree to receive setAggressiveness calls. PMinit(); provider->joinPMtree(this); } // Finds PMU and UniN so in quiesce we can put the machine to sleep. // I can not put these calls there because quiesce runs in interrupt // context and waitForService may block. pmu = waitForService(serviceMatching("ApplePMU")); uniN = waitForService(serviceMatching("AppleUniN")); if ((pmu == 0) || (uniN == 0)) return false; if (macRISC2PE->hasPMon) { // Find the platform monitor, if present service = waitForService(resourceMatching("IOPlatformMonitor")); ioPMon = OSDynamicCast (IOPlatformMonitor, service->getProperty("IOPlatformMonitor")); if (!ioPMon) return false; ioPMonDict = OSDictionary::withCapacity(2); if (!ioPMonDict) { ioPMon = NULL; } else { ioPMonDict->setObject (kIOPMonTypeKey, OSSymbol::withCString (kIOPMonTypeCPUCon)); ioPMonDict->setObject (kIOPMonCPUIDKey, OSNumber::withNumber ((long long)getCPUNumber(), 32)); if (messageClient (kIOPMonMessageRegister, ioPMon, (void *)ioPMonDict) != kIOReturnSuccess) { // IOPMon doesn't need to know about us, so don't bother with it IOLog ("MacRISC2CPU::start - failed to register cpu with IOPlatformMonitor\n"); ioPMonDict->release(); ioPMon = NULL; } } } if (macRISC2PE->hasPPlugin) { IOService *ioPPlugin; OSDictionary *ioPPluginDict; // Find the platform plugin, if present service = waitForService(resourceMatching("IOPlatformPlugin")); ioPPlugin = OSDynamicCast (IOService, service->getProperty("IOPlatformPlugin")); if (!ioPPlugin) return false; ioPPluginDict = OSDictionary::withCapacity(2); if (ioPPluginDict) { ioPPluginDict->setObject ("cpu-id", OSNumber::withNumber ((long long)getCPUNumber(), 32)); // Register with the plugin - same API as for platform monitor if (messageClient (kIOPMonMessageRegister, ioPPlugin, (void *)ioPPluginDict) != kIOReturnSuccess) { // ioPPlugin doesn't need to know about us, so don't bother with it IOLog ("MacRISC2CPU::start - failed to register cpu with IOPlatformPlugin\n"); } ioPPluginDict->release(); // Not needed any more } } #if enableUserClientInterface // // UserClient stuff... // fWorkLoop = getWorkLoop(); if(!fWorkLoop) { IOLog("MacRISC2CPU::start ERROR: failed to find a fWorkLoop\n"); } if(!initTimers()) { IOLog("MacRISC2CPU::start ERROR: failed to init the timers\n"); } #endif registerService(); return true; }
void StartIOKit( void * p1, void * p2, void * p3, void * p4 ) { IOPlatformExpertDevice * rootNub; int debugFlags; IORegistryEntry * root; OSObject * obj; extern const char * gIOKernelKmods; OSString * errorString = NULL; // must release OSDictionary * fakeKmods; // must release OSCollectionIterator * kmodIter; // must release OSString * kmodName; // don't release IOLog( iokit_version ); if( PE_parse_boot_arg( "io", &debugFlags )) gIOKitDebug = debugFlags; // Check for the log synchronous bit set in io if (gIOKitDebug & kIOLogSynchronous) debug_mode = true; // // Have to start IOKit environment before we attempt to start // the C++ runtime environment. At some stage we have to clean up // the initialisation path so that OS C++ can initialise independantly // of iokit basic service initialisation, or better we have IOLib stuff // initialise as basic OS services. // IOLibInit(); OSlibkernInit(); /***** * Declare the fake kmod_info structs for built-in components * that must be tracked as independent units for dependencies. */ fakeKmods = OSDynamicCast(OSDictionary, OSUnserialize(gIOKernelKmods, &errorString)); if (!fakeKmods) { if (errorString) { panic("Kernel kmod list syntax error: %s\n", errorString->getCStringNoCopy()); errorString->release(); } else { panic("Error loading kernel kmod list.\n"); } } kmodIter = OSCollectionIterator::withCollection(fakeKmods); if (!kmodIter) { panic("Can't declare in-kernel kmods.\n"); } while ((kmodName = OSDynamicCast(OSString, kmodIter->getNextObject()))) { OSString * kmodVersion = OSDynamicCast(OSString, fakeKmods->getObject(kmodName)); if (!kmodVersion) { panic("Can't declare in-kernel kmod; \"%s\" has " "an invalid version.\n", kmodName->getCStringNoCopy()); } if (KERN_SUCCESS != kmod_create_fake(kmodName->getCStringNoCopy(), kmodVersion->getCStringNoCopy())) { panic("Failure declaring in-kernel kmod \"%s\".\n", kmodName->getCStringNoCopy()); } } kmodIter->release(); fakeKmods->release(); root = IORegistryEntry::initialize(); assert( root ); IOService::initialize(); IOCatalogue::initialize(); IOUserClient::initialize(); IOMemoryDescriptor::initialize(); obj = OSString::withCString( iokit_version ); assert( obj ); if( obj ) { root->setProperty( kIOKitBuildVersionKey, obj ); obj->release(); } obj = IOKitDiagnostics::diagnostics(); if( obj ) { root->setProperty( kIOKitDiagnosticsKey, obj ); obj->release(); } rootNub = new IOPlatformExpertDevice; if( rootNub && rootNub->initWithArgs( p1, p2, p3, p4)) { rootNub->attach( 0 ); /* Enter into the catalogue the drivers * provided by BootX. */ gIOCatalogue->recordStartupExtensions(); rootNub->registerService(); } }