Ejemplo n.º 1
0
IORegistryEntry *
IODeviceTreeAlloc( void * dtTop )
{
    IORegistryEntry *		parent;
    IORegistryEntry *		child;
    IORegistryIterator *	regIter;
    DTEntryIterator		iter;
    DTEntry			dtChild;
    DTEntry			mapEntry;
    OSArray *			stack;
    OSData *			prop;
    OSDictionary *		allInts;
    vm_offset_t *		dtMap;
    unsigned int		propSize;
    bool			intMap;
    bool			freeDT;

    gIODTPlane = IORegistryEntry::makePlane( kIODeviceTreePlane );

    gIODTNameKey 		= OSSymbol::withCStringNoCopy( "name" );
    gIODTUnitKey 		= OSSymbol::withCStringNoCopy( "AAPL,unit-string" );
    gIODTCompatibleKey 	= OSSymbol::withCStringNoCopy( "compatible" );
    gIODTTypeKey 		= OSSymbol::withCStringNoCopy( "device_type" );
    gIODTModelKey 		= OSSymbol::withCStringNoCopy( "model" );
    gIODTSizeCellKey 	= OSSymbol::withCStringNoCopy( "#size-cells" );
    gIODTAddressCellKey = OSSymbol::withCStringNoCopy( "#address-cells" );
    gIODTRangeKey 		= OSSymbol::withCStringNoCopy( "ranges" );
    gIODTPersistKey		= OSSymbol::withCStringNoCopy( "IODTPersist" );

    assert(    gIODTPlane && gIODTCompatibleKey
            && gIODTTypeKey && gIODTModelKey
            && gIODTSizeCellKey && gIODTAddressCellKey && gIODTRangeKey
            && gIODTPersistKey );

    gIODTDefaultInterruptController
		= OSSymbol::withCStringNoCopy("IOPrimaryInterruptController");
    gIODTNWInterruptMappingKey
		= OSSymbol::withCStringNoCopy("IONWInterrupts");

    gIODTAAPLInterruptsKey
		= OSSymbol::withCStringNoCopy("AAPL,interrupts");
    gIODTPHandleKey
		= OSSymbol::withCStringNoCopy("AAPL,phandle");

    gIODTInterruptParentKey
		= OSSymbol::withCStringNoCopy("interrupt-parent");

    gIODTPHandles	= OSArray::withCapacity( 1 );
    gIODTPHandleMap	= OSArray::withCapacity( 1 );

    gIODTInterruptCellKey
		= OSSymbol::withCStringNoCopy("#interrupt-cells");

    assert(    gIODTDefaultInterruptController && gIODTNWInterruptMappingKey 
	    && gIODTAAPLInterruptsKey
	    && gIODTPHandleKey && gIODTInterruptParentKey
	    && gIODTPHandles && gIODTPHandleMap
            && gIODTInterruptCellKey
	 );

    freeDT = (kSuccess == DTLookupEntry( 0, "/chosen/memory-map", &mapEntry ))
	  && (kSuccess == DTGetProperty( mapEntry,
                "DeviceTree", (void **) &dtMap, &propSize ))
	  && ((2 * sizeof(uint32_t)) == propSize);

    parent = MakeReferenceTable( (DTEntry)dtTop, freeDT );

    stack = OSArray::withObjects( (const OSObject **) &parent, 1, 10 );
    DTCreateEntryIterator( (DTEntry)dtTop, &iter );

    do {
        parent = (IORegistryEntry *)stack->getObject( stack->getCount() - 1);
        //parent->release();
        stack->removeObject( stack->getCount() - 1);

        while( kSuccess == DTIterateEntries( iter, &dtChild) ) {

            child = MakeReferenceTable( dtChild, freeDT );
            child->attachToParent( parent, gIODTPlane);

            AddPHandle( child );

            if( kSuccess == DTEnterEntry( iter, dtChild)) {
                stack->setObject( parent);
                parent = child;
            }
            // only registry holds retain
            child->release();
        }

    } while( stack->getCount()
		&& (kSuccess == DTExitEntry( iter, &dtChild)));

    stack->release();
    DTDisposeEntryIterator( iter);

    // parent is now root of the created tree

    // make root name first compatible entry (purely cosmetic)
    if( (prop = (OSData *) parent->getProperty( gIODTCompatibleKey))) {
        parent->setName( parent->getName(), gIODTPlane );
        parent->setName( (const char *) prop->getBytesNoCopy() );
    }

    // attach tree to meta root
    parent->attachToParent( IORegistryEntry::getRegistryRoot(), gIODTPlane);
    parent->release();

    if( freeDT ) {
        // free original device tree
        DTInit(0);
        IODTFreeLoaderInfo( "DeviceTree",
			    (void *)dtMap[0], (int) round_page(dtMap[1]) );
    }

    // adjust tree

    gIODTSharedInterrupts = OSDictionary::withCapacity(4);
    allInts = OSDictionary::withCapacity(4);
    intMap = false;
    regIter = IORegistryIterator::iterateOver( gIODTPlane,
						kIORegistryIterateRecursively );
    assert( regIter && allInts && gIODTSharedInterrupts );
    if( regIter && allInts && gIODTSharedInterrupts ) {
        while( (child = regIter->getNextObject())) {
            IODTMapInterruptsSharing( child, allInts );
            if( !intMap && child->getProperty( gIODTInterruptParentKey))
                intMap = true;

        }
        regIter->release();
    }

#if IODTSUPPORTDEBUG
    parent->setProperty("allInts", allInts);
    parent->setProperty("sharedInts", gIODTSharedInterrupts);

    regIter = IORegistryIterator::iterateOver( gIODTPlane,
						kIORegistryIterateRecursively );
    if (regIter) {
        while( (child = regIter->getNextObject())) {
	    OSArray *
	    array = OSDynamicCast(OSArray, child->getProperty( gIOInterruptSpecifiersKey ));
	    for( UInt32 i = 0; array && (i < array->getCount()); i++)
	    {
		IOOptionBits options;
		IOReturn ret = IODTGetInterruptOptions( child, i, &options );
		if( (ret != kIOReturnSuccess) || options)
		    IOLog("%s[%ld] %ld (%x)\n", child->getName(), i, options, ret);
	    }
	}
        regIter->release();
    }
#endif

    allInts->release();

    if( intMap)
        // set a key in the root to indicate we found NW interrupt mapping
        parent->setProperty( gIODTNWInterruptMappingKey,
                (OSObject *) gIODTNWInterruptMappingKey );

    return( parent);
}
static void createNubs(IOService *provider) {
	const char nameID[2][8] = {"@0,name", "@1,name"};
	const char name[11] = "Aty,Radeon";
	const char typeID[2][15] = {"@0,device_type", "@1,device_type"};
	const char type[] = "display";
	OSObject *tempObj;
	
	int i;
	
	if (provider->getProperty(kIONDRVIgnoreKey)) return;
	provider->setProperty(kIONDRVIgnoreKey, kOSBooleanTrue);	//prevent IONDRVFramebuffer from match
	
	LOG("createNubs\n");
	
	if (!provider->getProperty("@0,name") && !provider->getProperty("@1,name")) {
		for (i = 0;i < 2;i++) {	// Debug
			tempObj = OSData::withBytes(name, 11);
			provider->setProperty(nameID[i], tempObj);
			tempObj->release();
			tempObj = OSData::withBytes(type, 8);
			provider->setProperty(typeID[i], tempObj);
			tempObj->release();
		}
	}
	// have to move below part from IONDRVFramebuffer to make it work
	IORegistryIterator * iter;
	IORegistryEntry *    next;
	IOService *          newNub;
	OSArray *            toDo = 0;
	bool                 firstLevel;
    OSData *            data;
	
	if (provider->getProperty("@0,name"))
	{
		OSDictionary *         dict;
		OSCollectionIterator * keys;
		const OSSymbol *       key;
		char                   buffer[80];
		const char *           keyChrs;
		size_t                 len;
		char                   c;
		
		dict = provider->dictionaryWithProperties();
		keys = OSCollectionIterator::withCollection(dict);
		if (dict)
			dict->release();
		if (keys)
		{
			while ((key = OSDynamicCast(OSSymbol, keys->getNextObject())))
			{
				keyChrs = key->getCStringNoCopy();
				if ('@' != keyChrs[0])
					continue;
				
				len = 0;
				do
				{
					c = keyChrs[len];
					if (!c || (c == ','))
						break;
					buffer[len] = c;
					len++;
				}
				while (len < (sizeof(buffer) - 1));
				if (!c)
					continue;
				
				buffer[len] = 0;
				keyChrs += len + 1;
				
				next = provider->childFromPath(buffer, gIODTPlane);
				if (!next)
				{
					next = new IOService;
					if (next && !next->init())
					{
						next->release();
						next = 0;
					}
					if (!next)
						continue;
					next->setLocation(&buffer[1]);
					if (!next->attachToParent(provider, gIODTPlane))
						continue;
				}
				
				OSObject * obj = dict->getObject(key);
				next->setProperty(keyChrs, dict->getObject(key));
				if (!strcmp(keyChrs, "name"))
				{
					OSData * data = OSDynamicCast(OSData, obj);
					if (data)
						next->setName((const char *) data->getBytesNoCopy());
				}
				next->release();
				provider->removeProperty(key);
			}
			keys->release();
		}
	}
	
	iter = IORegistryIterator::iterateOver( provider, gIODTPlane, 0 );
	toDo = OSArray::withCapacity(2);
	
	if (iter && toDo)
	{
		bool haveDoneLibInit = false;
		UInt32 index = 0;
		do
		{
			while ((next = (IORegistryEntry *) iter->getNextObject()))
			{
				firstLevel = (provider == next->getParentEntry(gIODTPlane));
				if (firstLevel)
				{
					data = OSDynamicCast( OSData, next->getProperty("device_type"));
					if (!data || (0 != strcmp("display", (char *) data->getBytesNoCopy())))
						continue;
					
					if (!haveDoneLibInit)
					{
						haveDoneLibInit = (kIOReturnSuccess == _IONDRVLibrariesInitialize(provider));
						if (!haveDoneLibInit)
							continue;
					}
					next->setProperty( kIOFBDependentIDKey, (uintptr_t) provider, 64 );
					next->setProperty( kIOFBDependentIndexKey, index, 32 );
					next->setProperty( kIONDRVIgnoreKey, kOSBooleanTrue );
					index++;
				}
				
				toDo->setObject( next );
				iter->enterEntry();
			}
		}
		while (iter->exitEntry());
	}
	if (iter)
		iter->release();
	
	if (toDo)
	{
		OSObject * obj;
		OSArray  * deviceMemory;
		obj = provider->copyProperty(gIODeviceMemoryKey);
		deviceMemory = OSDynamicCast(OSArray, obj);
		
		for (unsigned int i = 0;
			 (next = (IORegistryEntry *) toDo->getObject(i));
			 i++)
		{
			newNub = new IONDRVDevice;
			if (!newNub)
				continue;
			if (!newNub->init(next, gIODTPlane))
			{
				newNub->free();
				newNub = 0;
				continue;
			}
			if (deviceMemory)
				newNub->setDeviceMemory(deviceMemory);
			newNub->attach(provider);
			newNub->registerService(kIOServiceSynchronous);
		}
		if (obj)
			obj->release();
		toDo->release();
	}
}