void ARMCPU::initCPU(bool boot) { IOLog("ARMCPU::initCPU(%p): we are here to serve!\n", this); if(gIC) { gIC->enableCPUInterrupt(this); } setCPUState(kIOCPUStateRunning); }
void ARMCPU::initCPU(bool boot) { PE_LOG("Setting active cpu state\n"); if(gIC) { gIC->enableCPUInterrupt(this); } setCPUState(kIOCPUStateRunning); }
void MacRISC2CPU::haltCPU(void) { OSIterator *childIterator; IORegistryEntry *childEntry, *childDriver; IOPCIBridge *pciDriver; OSData *deviceTypeString; UInt32 i; setCPUState(kIOCPUStateStopped); if (bootCPU) { // Some systems require special handling of Ultra-ATA at sleep. // Call UniN to prepare for that, if necessary uniN->callPlatformFunction ("setupUATAforSleep", false, (void *)0, (void *)0, (void *)0, (void *)0); // Notify our pci children to save their state if (!topLevelPCIBridgeCount) { // First build list of top level bridges - only need to do once as these don't change if ((childIterator = macRISC2PE->getChildIterator (gIOServicePlane)) != NULL) { while ((childEntry = (IORegistryEntry *)(childIterator->getNextObject ())) != NULL) { deviceTypeString = OSDynamicCast( OSData, childEntry->getProperty( "device_type" )); if (deviceTypeString) { if (!strcmp((const char *)deviceTypeString->getBytesNoCopy(), "pci")) { childDriver = childEntry->copyChildEntry(gIOServicePlane); if (childDriver) { pciDriver = OSDynamicCast( IOPCIBridge, childDriver ); if (pciDriver) if (topLevelPCIBridgeCount < kMaxPCIBridges) // Remember this driver topLevelPCIBridges[topLevelPCIBridgeCount++] = pciDriver; else kprintf ("MacRISC2CPU::haltCPU - warning, more than %d PCI bridges - cannot save/restore them all\n", kMaxPCIBridges); childDriver->release(); } } } } childIterator->release(); } } for (i = 0; i < topLevelPCIBridgeCount; i++) if (pciDriver = topLevelPCIBridges[i]) { // Got the driver - send the message pciDriver->setDevicePowerState (NULL, 2); } } kprintf("MacRISC2CPU::haltCPU %ld Here!\n", getCPUNumber()); processor_exit(machProcessor); }
bool AppleI386CPU::startCommon() { if (startCommonCompleted) return true; cpuIC = new AppleI386CPUInterruptController; if (cpuIC == 0) return false; if (cpuIC->initCPUInterruptController(1) != kIOReturnSuccess) return false; cpuIC->attach(this); cpuIC->registerCPUInterruptController(); setCPUState(kIOCPUStateUninitalized); initCPU(true); registerService(); startCommonCompleted = true; return true; }
bool ARMCPU::start(IOService* provider) { IOLog("ARMCPU::start: Starting ARM CPU IOKit provider...\n"); if(!super::start(provider)) { panic("Failed to start super IOCPU provider"); } gIC = new ARMDumbInterruptController; if(!gIC) { panic("Failed to alloc class for dumb interrupt controller, we suck hard"); } gIC->initCPUInterruptController(1); gIC->attach(this); gIC->registerCPUInterruptController(); setCPUState(kIOCPUStateUninitalized); initCPU(true); registerService(); return true; }
bool AppleI386CPU::start(IOService * provider) { // kern_return_t result; if (!super::start(provider)) return false; cpuIC = new AppleI386CPUInterruptController; if (cpuIC == 0) return false; if (cpuIC->initCPUInterruptController(1) != kIOReturnSuccess) return false; cpuIC->attach(this); cpuIC->registerCPUInterruptController(); #ifdef NOTYET // Register this CPU with mach. result = ml_processor_register((cpu_id_t)this, 0, &machProcessor, &ipi_handler, true); if (result == KERN_FAILURE) return false; #endif setCPUState(kIOCPUStateUninitalized); #ifdef NOTYET processor_start(machProcessor); #endif // Hack. Call initCPU() ourself since no one else will. initCPU(true); registerService(); return true; }
void AppleI386CPU::initCPU(bool boot) { cpuIC->enableCPUInterrupt(this); setCPUState(kIOCPUStateRunning); }
void MacRISC2CPU::initCPU(bool boot) { IOPCIBridge *pciDriver; UInt32 i; if (!boot && bootCPU) { // Tell Uni-N to enter normal mode. uniN->callPlatformFunction (uniN_setPowerState, false, (void *)kUniNNormal, (void *)0, (void *)0, (void *)0); if (!processorSpeedChange) { // Notify our pci children to restore their state for (i = 0; i < topLevelPCIBridgeCount; i++) if (pciDriver = topLevelPCIBridges[i]) // Got the driver - send the message pciDriver->setDevicePowerState (NULL, 3); if (resetOnWake && (!gPHibernateState || !*gPHibernateState)) { bool doAGPRecovery; IOReturn result; doAGPRecovery = false; if (macRISC2PE->atiDriver) { // Restore ATI config space macRISC2PE->atiDriver->restoreDeviceState(); if (macRISC2PE->gpuSensor) { // Call ATI through the sensor driver to prep for the DMA transaction result = macRISC2PE->gpuSensor->callPlatformFunction (ati_prepareDMATransaction, false, (void *)reserveMemDesc, 0, 0, 0); if (result == kIOReturnSuccess) { if (macRISC2PE->atiDriver && macRISC2PE->agpBridgeDriver) { // Issue resetAGP to turn on AGP macRISC2PE->atiDriver->resetAGP(); // Turn off GART (turned on by resetAGP) macRISC2PE->agpBridgeDriver->configWrite32(macRISC2PE->agpBridgeDriver->getBridgeSpace(), 0x94, 0); // Call ATI to do the dummy DMA transfer as a test result = macRISC2PE->gpuSensor->callPlatformFunction (ati_performDMATransaction, false, (void *)reserveMemDesc, 0, 0, 0); // Issue resetAGP to turn off AGP (so it's in state later s/w expects) macRISC2PE->atiDriver->resetAGP(); if (result == kIOReturnDMAError) // DMA failed, to the recovery procedure doAGPRecovery = true; } } } } if (doAGPRecovery) { kprintf("MacRISC2CPU::initCPU - AGP recovery required, issuing cpuReset\n"); pmu->callPlatformFunction (pmu_cpuReset, false, 0, 0, 0, 0); while (1) /* spin waiting for restart*/ ; } } // Continue the wake process keyLargo->callPlatformFunction(keyLargo_restoreRegisterState, false, 0, 0, 0, 0); // Enables the interrupts for this CPU. if (macRISC2PE->getMachineType() == kMacRISC2TypePowerMac) { haveSleptMPIC = false; kprintf("MacRISC2CPU::initCPU %ld -> mpic->setUpForSleep off", getCPUNumber()); mpic->callPlatformFunction(mpic_setUpForSleep, false, (void *)false, (void *)getCPUNumber(), 0, 0); } } } kprintf("MacRISC2CPU::initCPU %ld Here!\n", getCPUNumber()); // Set time base. if (bootCPU) keyLargo->callPlatformFunction(keyLargo_syncTimeBase, false, 0, 0, 0, 0); if (boot) { if (gCPUIC) gCPUIC->enableCPUInterrupt(this); else panic ("MacRISC2CPU: gCPUIC uninitialized for CPU %ld\n", getCPUNumber()); // Register and enable IPIs. cpuNub->registerInterrupt(0, this, OSMemberFunctionCast(IOInterruptAction, this, &MacRISC2CPU::ipiHandler), 0); // [4091924] cpuNub->enableInterrupt(0); } // [5376988] - MPIC is no longer automatically setting priority to 0 so now must do this in all cases, not just non-boot case long priority = 0; mpic->callPlatformFunction(mpic_setCurrentTaskPriority, false, (void *)&priority, 0, 0, 0); setCPUState(kIOCPUStateRunning); }
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; }