static IORegistryEntry * MakeReferenceTable( DTEntry dtEntry, bool copy ) { IORegistryEntry *regEntry; OSDictionary *propTable; const OSSymbol *nameKey; OSData *data; const OSSymbol *sym; DTPropertyIterator dtIter; void *prop; unsigned int propSize; char *name; char location[ 32 ]; bool noLocation = true; regEntry = new IOService; if( regEntry && (false == regEntry->init())) { regEntry->release(); regEntry = 0; } if( regEntry && (kSuccess == DTCreatePropertyIterator( dtEntry, &dtIter))) { propTable = regEntry->getPropertyTable(); while( kSuccess == DTIterateProperties( dtIter, &name)) { if( kSuccess != DTGetProperty( dtEntry, name, &prop, &propSize )) continue; if( copy) { nameKey = OSSymbol::withCString(name); data = OSData::withBytes(prop, propSize); } else { nameKey = OSSymbol::withCStringNoCopy(name); data = OSData::withBytesNoCopy(prop, propSize); } assert( nameKey && data ); propTable->setObject( nameKey, data); data->release(); nameKey->release(); if( nameKey == gIODTNameKey ) { if( copy) sym = OSSymbol::withCString( (const char *) prop); else sym = OSSymbol::withCStringNoCopy( (const char *) prop); regEntry->setName( sym ); sym->release(); } else if( nameKey == gIODTUnitKey ) { // all OF strings are null terminated... except this one if( propSize >= (int) sizeof(location)) propSize = sizeof(location) - 1; strncpy( location, (const char *) prop, propSize ); location[ propSize ] = 0; regEntry->setLocation( location ); propTable->removeObject( gIODTUnitKey ); noLocation = false; } else if(noLocation && (!strncmp(name, "reg", sizeof("reg")))) { // default location - override later snprintf(location, sizeof(location), "%X", *((uint32_t *) prop)); regEntry->setLocation( location ); } } DTDisposePropertyIterator( dtIter); } return( regEntry); }
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(); } }