Пример #1
0
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;
}
Пример #3
0
/*
 * 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;
}
Пример #4
0
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;
}
Пример #5
0
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();
    }
}