|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * Copyright (c) 1998 Apple Computer, Inc. All rights reserved. ! 24: * ! 25: * HISTORY ! 26: * 23 Nov 98 sdouglas, created from IODeviceTreeBus.m, & MacOS exp mgr. ! 27: * 05 Apr 99 sdouglas, add interrupt mapping. ! 28: * ! 29: */ ! 30: ! 31: #include <IOKit/IODeviceTreeSupport.h> ! 32: #include <libkern/c++/OSContainers.h> ! 33: #include <IOKit/IODeviceMemory.h> ! 34: #include <IOKit/IOService.h> ! 35: ! 36: #include <IOKit/IOLib.h> ! 37: #include <IOKit/IOKitKeys.h> ! 38: ! 39: #include <DeviceTree.h> ! 40: extern "C" { ! 41: #include <machine/machine_routines.h> ! 42: void DTInit( void * data ); ! 43: ! 44: int IODTGetLoaderInfo( char *key, void **infoAddr, int *infosize ); ! 45: void IODTFreeLoaderInfo( char *key, void *infoAddr, int infoSize ); ! 46: } ! 47: ! 48: #include <IOKit/assert.h> ! 49: ! 50: ! 51: const IORegistryPlane * gIODTPlane; ! 52: ! 53: static OSArray * gIODTPHandles; ! 54: static OSArray * gIODTPHandleMap; ! 55: ! 56: const OSSymbol * gIODTNameKey; ! 57: const OSSymbol * gIODTUnitKey; ! 58: const OSSymbol * gIODTCompatibleKey; ! 59: const OSSymbol * gIODTTypeKey; ! 60: const OSSymbol * gIODTModelKey; ! 61: ! 62: const OSSymbol * gIODTSizeCellKey; ! 63: const OSSymbol * gIODTAddressCellKey; ! 64: const OSSymbol * gIODTRangeKey; ! 65: ! 66: const OSSymbol * gIODTPersistKey; ! 67: ! 68: const OSSymbol * gIODTDefaultInterruptController; ! 69: const OSSymbol * gIODTAAPLInterruptsKey; ! 70: const OSSymbol * gIODTPHandleKey; ! 71: const OSSymbol * gIODTInterruptCellKey; ! 72: const OSSymbol * gIODTInterruptParentKey; ! 73: const OSSymbol * gIODTNWInterruptMappingKey; ! 74: ! 75: ! 76: static IORegistryEntry * MakeReferenceTable( DTEntry dtEntry, bool copy ); ! 77: static void AddPHandle( IORegistryEntry * regEntry ); ! 78: static void FreePhysicalMemory( vm_offset_t * range ); ! 79: ! 80: IORegistryEntry * ! 81: IODeviceTreeAlloc( void * dtTop ) ! 82: { ! 83: IORegistryEntry * parent; ! 84: IORegistryEntry * child; ! 85: IORegistryIterator * regIter; ! 86: DTEntryIterator iter; ! 87: DTEntry dtChild; ! 88: DTEntry mapEntry; ! 89: OSArray * stack; ! 90: OSData * prop; ! 91: OSObject * obj; ! 92: vm_offset_t * dtMap; ! 93: int propSize; ! 94: bool intMap; ! 95: bool freeDT; ! 96: ! 97: IOLog("IODeviceTreeSupport "); ! 98: ! 99: gIODTPlane = IORegistryEntry::makePlane( kIODeviceTreePlane ); ! 100: ! 101: gIODTNameKey = OSSymbol::withCStringNoCopy( "name" ); ! 102: gIODTUnitKey = OSSymbol::withCStringNoCopy( "AAPL,unit-string" ); ! 103: gIODTCompatibleKey = OSSymbol::withCStringNoCopy( "compatible" ); ! 104: gIODTTypeKey = OSSymbol::withCStringNoCopy( "device_type" ); ! 105: gIODTModelKey = OSSymbol::withCStringNoCopy( "model" ); ! 106: gIODTSizeCellKey = OSSymbol::withCStringNoCopy( "#size-cells" ); ! 107: gIODTAddressCellKey = OSSymbol::withCStringNoCopy( "#address-cells" ); ! 108: gIODTRangeKey = OSSymbol::withCStringNoCopy( "ranges" ); ! 109: ! 110: gIODTPersistKey = OSSymbol::withCStringNoCopy( "IODTPersist" ); ! 111: ! 112: assert( gIODTPlane && gIODTCompatibleKey ! 113: && gIODTTypeKey && gIODTModelKey ! 114: && gIODTSizeCellKey && gIODTAddressCellKey && gIODTRangeKey ! 115: && gIODTPersistKey ); ! 116: ! 117: gIODTDefaultInterruptController ! 118: = OSSymbol::withCStringNoCopy("IOPrimaryInterruptController"); ! 119: gIODTNWInterruptMappingKey ! 120: = OSSymbol::withCStringNoCopy("IONWInterrupts"); ! 121: ! 122: gIODTAAPLInterruptsKey ! 123: = OSSymbol::withCStringNoCopy("AAPL,interrupts"); ! 124: gIODTPHandleKey ! 125: = OSSymbol::withCStringNoCopy("AAPL,phandle"); ! 126: ! 127: gIODTInterruptParentKey ! 128: = OSSymbol::withCStringNoCopy("interrupt-parent"); ! 129: ! 130: gIODTPHandles = OSArray::withCapacity( 1 ); ! 131: gIODTPHandleMap = OSArray::withCapacity( 1 ); ! 132: ! 133: gIODTInterruptCellKey ! 134: = OSSymbol::withCStringNoCopy("#interrupt-cells"); ! 135: ! 136: assert( gIODTDefaultInterruptController && gIODTNWInterruptMappingKey ! 137: && gIODTAAPLInterruptsKey ! 138: && gIODTPHandleKey && gIODTInterruptParentKey ! 139: && gIODTPHandles && gIODTPHandleMap ! 140: && gIODTInterruptCellKey ! 141: ); ! 142: ! 143: freeDT = (kSuccess == DTLookupEntry( 0, "/chosen/memory-map", &mapEntry )) ! 144: && (kSuccess == DTGetProperty( mapEntry, ! 145: "DeviceTree", (void **) &dtMap, &propSize )) ! 146: && ((2 * sizeof( vm_offset_t)) == propSize); ! 147: ! 148: parent = MakeReferenceTable( (DTEntry)dtTop, freeDT ); ! 149: ! 150: stack = OSArray::withObjects( (OSObject **)&parent, 1, 10 ); ! 151: DTCreateEntryIterator( (DTEntry)dtTop, &iter ); ! 152: ! 153: do { ! 154: parent = (IORegistryEntry *)stack->getObject( stack->getCount() - 1); ! 155: //parent->release(); ! 156: stack->removeObject( stack->getCount() - 1); ! 157: ! 158: while( kSuccess == DTIterateEntries( iter, &dtChild) ) { ! 159: ! 160: child = MakeReferenceTable( dtChild, freeDT ); ! 161: child->attachToParent( parent, gIODTPlane); ! 162: ! 163: AddPHandle( child ); ! 164: ! 165: if( kSuccess == DTEnterEntry( iter, dtChild)) { ! 166: stack->setObject( parent); ! 167: parent = child; ! 168: } ! 169: // only registry holds retain ! 170: child->release(); ! 171: } ! 172: ! 173: } while( stack->getCount() ! 174: && (kSuccess == DTExitEntry( iter, &dtChild))); ! 175: ! 176: stack->release(); ! 177: DTDisposeEntryIterator( iter); ! 178: ! 179: // parent is now root of the created tree ! 180: ! 181: // make root name first compatible entry (purely cosmetic) ! 182: if( (prop = (OSData *) parent->getProperty( gIODTCompatibleKey))) { ! 183: parent->setName( parent->getName(), gIODTPlane ); ! 184: parent->setName( (const char *) prop->getBytesNoCopy() ); ! 185: } ! 186: ! 187: // attach tree to meta root ! 188: parent->attachToParent( IORegistryEntry::getRegistryRoot(), gIODTPlane); ! 189: parent->release(); ! 190: ! 191: if( freeDT ) { ! 192: // free original device tree ! 193: DTInit(0); ! 194: IODTFreeLoaderInfo( "DeviceTree", ! 195: (void *)dtMap[0], round_page(dtMap[1]) ); ! 196: } ! 197: ! 198: // adjust tree ! 199: intMap = false; ! 200: regIter = IORegistryIterator::iterateOver( gIODTPlane, ! 201: kIORegistryIterateRecursively ); ! 202: assert( regIter ); ! 203: if( regIter) { ! 204: while( (child = regIter->getNextObject())) { ! 205: IODTMapInterrupts( child ); ! 206: if( !intMap && child->getProperty( gIODTInterruptParentKey)) ! 207: intMap = true; ! 208: ! 209: // some gross pruning ! 210: child->removeProperty( "lanLib,AAPL,MacOS,PowerPC"); ! 211: ! 212: if( (obj = child->getProperty( "driver,AAPL,MacOS,PowerPC"))) { ! 213: ! 214: if( (0 == (prop = (OSData *)child->getProperty( gIODTTypeKey ))) ! 215: || (strcmp( "display", (char *) prop->getBytesNoCopy())) ) { ! 216: ! 217: child->removeProperty( "driver,AAPL,MacOS,PowerPC"); ! 218: } ! 219: } ! 220: } ! 221: regIter->release(); ! 222: } ! 223: ! 224: if( intMap) ! 225: // set a key in the root to indicate we found NW interrupt mapping ! 226: parent->setProperty( gIODTNWInterruptMappingKey, ! 227: (OSObject *) gIODTNWInterruptMappingKey ); ! 228: ! 229: IOLog("done\n"); ! 230: ! 231: return( parent); ! 232: } ! 233: ! 234: int IODTGetLoaderInfo( char *key, void **infoAddr, int *infoSize ) ! 235: { ! 236: IORegistryEntry *chosen; ! 237: OSData *propObj; ! 238: unsigned int *propPtr; ! 239: unsigned int propSize; ! 240: ! 241: chosen = IORegistryEntry::fromPath( "/chosen/memory-map", gIODTPlane ); ! 242: if ( chosen == 0 ) return -1; ! 243: ! 244: propObj = OSDynamicCast( OSData, chosen->getProperty(key) ); ! 245: if ( propObj == 0 ) return -1; ! 246: ! 247: propSize = propObj->getLength(); ! 248: if ( propSize != (2 * sizeof(UInt32)) ) return -1; ! 249: ! 250: propPtr = (unsigned int *)propObj->getBytesNoCopy(); ! 251: if ( propPtr == 0 ) return -1; ! 252: ! 253: *infoAddr = (void *)propPtr[0] ; ! 254: *infoSize = (int) propPtr[1]; ! 255: ! 256: return 0; ! 257: } ! 258: ! 259: void IODTFreeLoaderInfo( char *key, void *infoAddr, int infoSize ) ! 260: { ! 261: vm_offset_t range[2]; ! 262: IORegistryEntry *chosen; ! 263: ! 264: range[0] = (vm_offset_t)infoAddr; ! 265: range[1] = (vm_offset_t)infoSize; ! 266: FreePhysicalMemory( range ); ! 267: ! 268: if ( key != 0 ) { ! 269: chosen = IORegistryEntry::fromPath( "/chosen/memory-map", gIODTPlane ); ! 270: if ( chosen != 0 ) { ! 271: chosen->removeProperty(key); ! 272: } ! 273: } ! 274: } ! 275: ! 276: static void FreePhysicalMemory( vm_offset_t * range ) ! 277: { ! 278: vm_offset_t virt; ! 279: ! 280: virt = ml_static_ptovirt( range[0] ); ! 281: if( virt) { ! 282: ml_static_mfree( virt, range[1] ); ! 283: } ! 284: } ! 285: ! 286: static IORegistryEntry * ! 287: MakeReferenceTable( DTEntry dtEntry, bool copy ) ! 288: { ! 289: IORegistryEntry * regEntry; ! 290: OSDictionary * propTable; ! 291: const OSSymbol * nameKey; ! 292: OSData * data; ! 293: const OSSymbol * sym; ! 294: DTPropertyIterator dtIter; ! 295: void * prop; ! 296: int propSize; ! 297: char * name; ! 298: char location[ 32 ]; ! 299: bool noLocation = true; ! 300: ! 301: regEntry = new IOService; ! 302: ! 303: if( regEntry && (false == regEntry->init())) { ! 304: regEntry->release(); ! 305: regEntry = 0; ! 306: } ! 307: ! 308: if( regEntry && ! 309: (kSuccess == DTCreatePropertyIterator( dtEntry, &dtIter))) { ! 310: ! 311: propTable = regEntry->getPropertyTable(); ! 312: ! 313: while( kSuccess == DTIterateProperties( dtIter, &name)) { ! 314: ! 315: if( kSuccess != DTGetProperty( dtEntry, name, &prop, &propSize )) ! 316: continue; ! 317: ! 318: if( copy) { ! 319: nameKey = OSSymbol::withCString(name); ! 320: data = OSData::withBytes(prop, propSize); ! 321: } else { ! 322: nameKey = OSSymbol::withCStringNoCopy(name); ! 323: data = OSData::withBytesNoCopy(prop, propSize); ! 324: } ! 325: assert( nameKey && data ); ! 326: ! 327: propTable->setObject( nameKey, data); ! 328: data->release(); ! 329: nameKey->release(); ! 330: ! 331: if( nameKey == gIODTNameKey ) { ! 332: if( copy) ! 333: sym = OSSymbol::withCString( (const char *) prop); ! 334: else ! 335: sym = OSSymbol::withCStringNoCopy( (const char *) prop); ! 336: regEntry->setName( sym ); ! 337: sym->release(); ! 338: ! 339: } else if( nameKey == gIODTUnitKey ) { ! 340: // all OF strings are null terminated... except this one ! 341: if( propSize >= (int) sizeof( location)) ! 342: propSize = sizeof( location) - 1; ! 343: strncpy( location, (const char *) prop, propSize ); ! 344: location[ propSize ] = 0; ! 345: regEntry->setLocation( location ); ! 346: propTable->removeObject( gIODTUnitKey ); ! 347: noLocation = false; ! 348: ! 349: } else if( noLocation && (0 == strcmp( name, "reg"))) { ! 350: // default location - override later ! 351: sprintf( location, "%lX", *((UInt32 *) prop) ); ! 352: regEntry->setLocation( location ); ! 353: } ! 354: } ! 355: DTDisposePropertyIterator( dtIter); ! 356: } ! 357: ! 358: return( regEntry); ! 359: } ! 360: ! 361: static void AddPHandle( IORegistryEntry * regEntry ) ! 362: { ! 363: OSData * data; ! 364: ! 365: if( regEntry->getProperty( gIODTInterruptCellKey) ! 366: && (data = OSDynamicCast( OSData, regEntry->getProperty( gIODTPHandleKey )))) { ! 367: // a possible interrupt-parent ! 368: gIODTPHandles->setObject( data ); ! 369: gIODTPHandleMap->setObject( regEntry ); ! 370: } ! 371: } ! 372: ! 373: static IORegistryEntry * FindPHandle( UInt32 phandle ) ! 374: { ! 375: OSData * data; ! 376: IORegistryEntry * regEntry = 0; ! 377: int i; ! 378: ! 379: for( i = 0; ! 380: (data = (OSData *)gIODTPHandles->getObject( i )); ! 381: i++ ) { ! 382: if( phandle == *((UInt32 *)data->getBytesNoCopy())) { ! 383: regEntry = (IORegistryEntry *) ! 384: gIODTPHandleMap->getObject( i ); ! 385: break; ! 386: } ! 387: } ! 388: ! 389: return( regEntry ); ! 390: } ! 391: ! 392: static bool GetUInt32( IORegistryEntry * regEntry, const OSSymbol * name, ! 393: UInt32 * value ) ! 394: { ! 395: OSData * data; ! 396: ! 397: if( (data = OSDynamicCast( OSData, regEntry->getProperty( name ))) ! 398: && (4 == data->getLength())) { ! 399: *value = *((UInt32 *) data->getBytesNoCopy()); ! 400: return( true ); ! 401: } else ! 402: return( false ); ! 403: } ! 404: ! 405: IORegistryEntry * IODTFindInterruptParent( IORegistryEntry * regEntry ) ! 406: { ! 407: IORegistryEntry * parent; ! 408: UInt32 phandle; ! 409: ! 410: if( GetUInt32( regEntry, gIODTInterruptParentKey, &phandle)) ! 411: parent = FindPHandle( phandle ); ! 412: ! 413: else if( 0 == regEntry->getProperty( "interrupt-controller")) ! 414: parent = regEntry->getParentEntry( gIODTPlane); ! 415: else ! 416: parent = 0; ! 417: ! 418: return( parent ); ! 419: } ! 420: ! 421: const OSSymbol * IODTInterruptControllerName( IORegistryEntry * regEntry ) ! 422: { ! 423: const OSSymbol * sym; ! 424: UInt32 phandle; ! 425: bool ok; ! 426: char buf[48]; ! 427: ! 428: ok = GetUInt32( regEntry, gIODTPHandleKey, &phandle); ! 429: assert( ok ); ! 430: ! 431: if( ok) { ! 432: sprintf( buf, "IOInterruptController%08lX", phandle); ! 433: sym = OSSymbol::withCString( buf ); ! 434: } else ! 435: sym = 0; ! 436: ! 437: return( sym ); ! 438: } ! 439: ! 440: #define unexpected(a) { kprintf("unexpected %s:%d\n", __FILE__, __LINE__); a; } ! 441: ! 442: static void IODTGetICellCounts( IORegistryEntry * regEntry, ! 443: UInt32 * iCellCount, UInt32 * aCellCount) ! 444: { ! 445: if( !GetUInt32( regEntry, gIODTInterruptCellKey, iCellCount)) ! 446: unexpected( *iCellCount = 1 ); ! 447: if( !GetUInt32( regEntry, gIODTAddressCellKey, aCellCount)) ! 448: *aCellCount = 0; ! 449: } ! 450: ! 451: UInt32 IODTMapOneInterrupt( IORegistryEntry * regEntry, UInt32 * intSpec, ! 452: OSData ** spec, const OSSymbol ** controller ) ! 453: { ! 454: IORegistryEntry * parent = 0; ! 455: OSData * data; ! 456: UInt32 * addrCmp; ! 457: UInt32 * maskCmp; ! 458: UInt32 * map; ! 459: UInt32 * endMap; ! 460: UInt32 acells, icells, pacells, picells, cell; ! 461: UInt32 i, skip = 0; ! 462: bool cmp, ok = false; ! 463: ! 464: do { ! 465: if( parent && (data = OSDynamicCast( OSData, ! 466: regEntry->getProperty( "interrupt-controller")))) { ! 467: // found a controller - don't want to follow cascaded controllers ! 468: parent = 0; ! 469: *spec = OSData::withBytesNoCopy( (void *) intSpec, ! 470: icells * sizeof( UInt32)); ! 471: *controller = IODTInterruptControllerName( regEntry ); ! 472: ok = (*spec && *controller); ! 473: ! 474: } else if( parent && (data = OSDynamicCast( OSData, ! 475: regEntry->getProperty( "interrupt-map")))) { ! 476: // interrupt-map ! 477: map = (UInt32 *) data->getBytesNoCopy(); ! 478: endMap = map + (data->getLength() / sizeof(UInt32)); ! 479: data = OSDynamicCast( OSData, regEntry->getProperty( "interrupt-map-mask" )); ! 480: if( data && (data->getLength() >= ((acells + icells) * sizeof( UInt32)))) ! 481: maskCmp = (UInt32 *) data->getBytesNoCopy(); ! 482: else ! 483: maskCmp = 0; ! 484: ! 485: do { ! 486: for( i = 0, cmp = true; ! 487: cmp && (i < (acells + icells)); ! 488: i++) { ! 489: cell = (i < acells) ? addrCmp[i] : intSpec[ i - acells ]; ! 490: if( maskCmp) ! 491: cell &= maskCmp[i]; ! 492: cmp = (cell == map[i]); ! 493: } ! 494: ! 495: map += acells + icells; ! 496: if( 0 == (parent = FindPHandle( *(map++) ))) ! 497: unexpected(break); ! 498: ! 499: if( cmp) ! 500: intSpec = map; ! 501: else { ! 502: IODTGetICellCounts( parent, &picells, &pacells ); ! 503: map += pacells + picells; ! 504: parent = 0; ! 505: } ! 506: } while( !cmp && (map < endMap) ); ! 507: ! 508: } else ! 509: // first time (usually) ! 510: parent = IODTFindInterruptParent( regEntry ); ! 511: ! 512: if( parent) { ! 513: IODTGetICellCounts( parent, &icells, &acells ); ! 514: addrCmp = 0; ! 515: if( acells) { ! 516: data = OSDynamicCast( OSData, regEntry->getProperty( "reg" )); ! 517: if( data && (data->getLength() >= (acells * sizeof( UInt32)))) ! 518: addrCmp = (UInt32 *) data->getBytesNoCopy(); ! 519: } ! 520: regEntry = parent; ! 521: if( !skip) ! 522: skip = icells; ! 523: } ! 524: } while( parent); ! 525: ! 526: if( ok) ! 527: return( skip ); ! 528: else ! 529: return( 0 ); ! 530: } ! 531: ! 532: bool IODTMapInterrupts( IORegistryEntry * regEntry ) ! 533: { ! 534: IORegistryEntry * parent; ! 535: OSData * local; ! 536: OSData * local2; ! 537: UInt32 * localBits; ! 538: UInt32 * localEnd; ! 539: OSData * map; ! 540: OSArray * mapped; ! 541: const OSSymbol * controller; ! 542: OSArray * controllers; ! 543: UInt32 skip = 1; ! 544: bool ok, nw; ! 545: ! 546: nw = (0 == (local = OSDynamicCast( OSData, ! 547: regEntry->getProperty( gIODTAAPLInterruptsKey)))); ! 548: if( nw ! 549: && (0 == (local = OSDynamicCast( OSData, ! 550: regEntry->getProperty( "interrupts"))))) ! 551: return( true ); // nothing to see here ! 552: ! 553: if( nw && (parent = regEntry->getParentEntry( gIODTPlane))) { ! 554: // check for bridges on old world ! 555: if( (local2 = OSDynamicCast( OSData, ! 556: parent->getProperty( gIODTAAPLInterruptsKey)))) { ! 557: local = local2; ! 558: nw = false; ! 559: } ! 560: } ! 561: ! 562: localBits = (UInt32 *) local->getBytesNoCopy(); ! 563: localEnd = localBits + (local->getLength() / sizeof( UInt32)); ! 564: mapped = OSArray::withCapacity( 1 ); ! 565: controllers = OSArray::withCapacity( 1 ); ! 566: ! 567: ok = (mapped && controllers); ! 568: ! 569: if( ok) do { ! 570: if( nw) { ! 571: skip = IODTMapOneInterrupt( regEntry, localBits, &map, &controller ); ! 572: if( 0 == skip) { ! 573: IOLog("%s: error mapping interrupt[%d]\n", ! 574: regEntry->getName(), mapped->getCount()); ! 575: break; ! 576: } ! 577: } else { ! 578: map = OSData::withData( local, mapped->getCount() * sizeof( UInt32), ! 579: sizeof( UInt32)); ! 580: controller = gIODTDefaultInterruptController; ! 581: } ! 582: ! 583: localBits += skip; ! 584: mapped->setObject( map ); ! 585: map->release(); ! 586: controllers->setObject( (OSObject *) controller ); ! 587: controller->release(); ! 588: ! 589: } while( localBits < localEnd); ! 590: ! 591: ok &= (localBits == localEnd); ! 592: ! 593: if( ok ) { ! 594: // store results ! 595: ok = regEntry->setProperty( gIOInterruptControllersKey, controllers); ! 596: ok &= regEntry->setProperty( gIOInterruptSpecifiersKey, mapped); ! 597: } ! 598: ! 599: if( controllers) ! 600: controllers->release(); ! 601: if( mapped) ! 602: mapped->release(); ! 603: ! 604: return( ok ); ! 605: } ! 606: ! 607: /* ! 608: */ ! 609: ! 610: static const char * ! 611: CompareKey( OSString * key, ! 612: const IORegistryEntry * table, const OSSymbol * propName ) ! 613: { ! 614: OSObject * prop; ! 615: OSData * data; ! 616: OSString * string; ! 617: const char * ckey; ! 618: UInt32 keyLen; ! 619: const char * names; ! 620: const char * lastName; ! 621: bool wild; ! 622: bool matched; ! 623: const char * result = 0; ! 624: ! 625: if( 0 == (prop = table->getProperty( propName ))) ! 626: return( 0 ); ! 627: ! 628: if( (data = OSDynamicCast( OSData, prop ))) { ! 629: names = (const char *) data->getBytesNoCopy(); ! 630: lastName = names + data->getLength(); ! 631: ! 632: } else if( (string = OSDynamicCast( OSString, prop ))) { ! 633: names = string->getCStringNoCopy(); ! 634: lastName = names + string->getLength() + 1; ! 635: ! 636: } else ! 637: return( 0 ); ! 638: ! 639: ckey = key->getCStringNoCopy(); ! 640: keyLen = key->getLength(); ! 641: wild = ('*' == key->getChar( keyLen )); ! 642: ! 643: do { ! 644: // for each name in the property ! 645: if( wild) ! 646: matched = (0 == strncmp( ckey, names, keyLen - 1 )); ! 647: else ! 648: matched = (keyLen == strlen( names )) ! 649: && (0 == strncmp( ckey, names, keyLen )); ! 650: ! 651: if( matched) ! 652: result = names; ! 653: ! 654: names = names + strlen( names) + 1; ! 655: ! 656: } while( (names < lastName) && (false == matched)); ! 657: ! 658: return( result); ! 659: } ! 660: ! 661: ! 662: bool IODTCompareNubName( const IORegistryEntry * regEntry, ! 663: OSString * name, OSString ** matchingName ) ! 664: { ! 665: const char * result; ! 666: bool matched; ! 667: ! 668: matched = (0 != (result = CompareKey( name, regEntry, gIODTNameKey))) ! 669: || (0 != (result = CompareKey( name, regEntry, gIODTCompatibleKey))) ! 670: || (0 != (result = CompareKey( name, regEntry, gIODTTypeKey))) ! 671: || (0 != (result = CompareKey( name, regEntry, gIODTModelKey))); ! 672: ! 673: if( result && matchingName) ! 674: *matchingName = OSString::withCString( result ); ! 675: ! 676: return( result != 0 ); ! 677: } ! 678: ! 679: bool IODTMatchNubWithKeys( IORegistryEntry * regEntry, ! 680: const char * keys ) ! 681: { ! 682: OSObject * obj; ! 683: bool result = false; ! 684: ! 685: obj = OSUnserialize( keys, 0 ); ! 686: ! 687: if( obj) { ! 688: result = regEntry->compareNames( obj ); ! 689: obj->release(); ! 690: } ! 691: #ifdef DEBUG ! 692: else IOLog("Couldn't unserialize %s\n", keys ); ! 693: #endif ! 694: ! 695: return( result ); ! 696: } ! 697: ! 698: OSCollectionIterator * IODTFindMatchingEntries( IORegistryEntry * from, ! 699: IOOptionBits options, const char * keys ) ! 700: { ! 701: OSSet * result; ! 702: IORegistryEntry * next; ! 703: IORegistryIterator * iter; ! 704: OSCollectionIterator * cIter; ! 705: bool cmp; ! 706: bool minus = options & kIODTExclusive; ! 707: ! 708: result = OSSet::withCapacity( 3 ); ! 709: if( !result) ! 710: return( 0); ! 711: ! 712: iter = IORegistryIterator::iterateOver( from, gIODTPlane, ! 713: (options & kIODTRecursive) ? kIORegistryIterateRecursively : 0 ); ! 714: if( iter) { ! 715: while( (next = iter->getNextObject())) { ! 716: ! 717: // Look for existence of a debug property to skip ! 718: if( next->getProperty("AAPL,ignore")) ! 719: continue; ! 720: ! 721: if( keys) { ! 722: cmp = IODTMatchNubWithKeys( next, keys ); ! 723: if( (minus && (false == cmp)) ! 724: || ((false == minus) && (false != cmp)) ) ! 725: result->setObject( next); ! 726: } else ! 727: result->setObject( next); ! 728: } ! 729: iter->release(); ! 730: } ! 731: ! 732: cIter = OSCollectionIterator::withCollection( result); ! 733: result->release(); ! 734: ! 735: return( cIter); ! 736: } ! 737: ! 738: ! 739: struct IODTPersistent { ! 740: IODTCompareAddressCellFunc compareFunc; ! 741: IODTNVLocationFunc locationFunc; ! 742: }; ! 743: ! 744: void IODTSetResolving( IORegistryEntry * regEntry, ! 745: IODTCompareAddressCellFunc compareFunc, ! 746: IODTNVLocationFunc locationFunc ) ! 747: { ! 748: IODTPersistent persist; ! 749: OSData * prop; ! 750: ! 751: persist.compareFunc = compareFunc; ! 752: persist.locationFunc = locationFunc; ! 753: prop = OSData::withBytes( &persist, sizeof( persist)); ! 754: if( !prop) ! 755: return; ! 756: ! 757: regEntry->setProperty( gIODTPersistKey, prop); ! 758: prop->release(); ! 759: } ! 760: ! 761: static SInt32 DefaultCompare( UInt32 cellCount, UInt32 left[], UInt32 right[] ) ! 762: { ! 763: cellCount--; ! 764: return( left[ cellCount ] - right[ cellCount ] ); ! 765: } ! 766: ! 767: ! 768: void IODTGetCellCounts( IORegistryEntry * regEntry, ! 769: UInt32 * sizeCount, UInt32 * addressCount) ! 770: { ! 771: if( !GetUInt32( regEntry, gIODTSizeCellKey, sizeCount)) ! 772: *sizeCount = 1; ! 773: if( !GetUInt32( regEntry, gIODTAddressCellKey, addressCount)) ! 774: *addressCount = 2; ! 775: } ! 776: ! 777: // Given addr & len cells from our child, find it in our ranges property, then ! 778: // look in our parent to resolve the base of the range for us. ! 779: ! 780: // Range[]: child-addr our-addr child-len ! 781: // #cells: child ours child ! 782: ! 783: bool IODTResolveAddressCell( IORegistryEntry * regEntry, ! 784: UInt32 cellsIn[], ! 785: IOPhysicalAddress * phys, IOPhysicalLength * len ) ! 786: { ! 787: IORegistryEntry * parent; ! 788: OSData * prop; ! 789: // cells in addresses at regEntry ! 790: UInt32 sizeCells, addressCells; ! 791: // cells in addresses below regEntry ! 792: UInt32 childSizeCells, childAddressCells; ! 793: UInt32 childCells; ! 794: UInt32 cell[ 5 ], offset = 0, length; ! 795: UInt32 * range; ! 796: UInt32 * endRanges; ! 797: bool ok = true; ! 798: SInt32 diff; ! 799: ! 800: IODTPersistent * persist; ! 801: IODTCompareAddressCellFunc compare; ! 802: ! 803: IODTGetCellCounts( regEntry, &childSizeCells, &childAddressCells ); ! 804: childCells = childAddressCells + childSizeCells; ! 805: ! 806: bcopy( cellsIn, cell, 4 * childCells ); ! 807: if( childSizeCells > 1) ! 808: *len = IOPhysical32( cellsIn[ childAddressCells ], ! 809: cellsIn[ childAddressCells + 1 ] ); ! 810: else ! 811: *len = IOPhysical32( 0, cellsIn[ childAddressCells ] ); ! 812: ! 813: do { ! 814: prop = OSDynamicCast( OSData, regEntry->getProperty( gIODTRangeKey )); ! 815: if( 0 == prop) { ! 816: /* end of the road */ ! 817: *phys = IOPhysical32( 0, cell[ childAddressCells - 1 ] + offset); ! 818: break; ! 819: } ! 820: ! 821: parent = regEntry->getParentEntry( gIODTPlane ); ! 822: IODTGetCellCounts( parent, &sizeCells, &addressCells ); ! 823: ! 824: if( (length = prop->getLength())) { ! 825: // search ! 826: range = (UInt32 *) prop->getBytesNoCopy(); ! 827: endRanges = range + (length / 4); ! 828: ! 829: prop = (OSData *) regEntry->getProperty( gIODTPersistKey ); ! 830: if( prop) { ! 831: persist = (IODTPersistent *) prop->getBytesNoCopy(); ! 832: compare = persist->compareFunc; ! 833: } else ! 834: compare = DefaultCompare; ! 835: ! 836: for( ok = false; ! 837: range < endRanges; ! 838: range += (childCells + addressCells) ) { ! 839: ! 840: // is cell >= range start? ! 841: diff = (*compare)( childAddressCells, cell, range ); ! 842: if( diff < 0) ! 843: continue; ! 844: // is cell + size <= range end? ! 845: if( (diff + cell[ childCells - 1 ]) ! 846: > range[ childCells + addressCells - 1 ]) ! 847: continue; ! 848: ! 849: offset += diff; ! 850: ok = true; ! 851: break; ! 852: } ! 853: ! 854: // Get the physical start of the range from our parent ! 855: bcopy( range + childAddressCells, cell, 4 * addressCells ); ! 856: bzero( cell + addressCells, 4 * sizeCells ); ! 857: ! 858: } /* else zero length range => pass thru to parent */ ! 859: ! 860: regEntry = parent; ! 861: childSizeCells = sizeCells; ! 862: childAddressCells = addressCells; ! 863: childCells = childAddressCells + childSizeCells; ! 864: ! 865: } while( ok && regEntry); ! 866: ! 867: return( ok); ! 868: } ! 869: ! 870: ! 871: OSArray * IODTResolveAddressing( IORegistryEntry * regEntry, ! 872: const char * addressPropertyName, ! 873: IODeviceMemory * parent ) ! 874: { ! 875: IORegistryEntry * parentEntry; ! 876: OSData * addressProperty; ! 877: UInt32 sizeCells, addressCells, cells; ! 878: int i, num; ! 879: UInt32 * reg; ! 880: IOPhysicalAddress phys; ! 881: IOPhysicalLength len; ! 882: OSArray * array; ! 883: IODeviceMemory * range; ! 884: ! 885: parentEntry = regEntry->getParentEntry( gIODTPlane ); ! 886: addressProperty = (OSData *) regEntry->getProperty( addressPropertyName ); ! 887: if( (0 == addressProperty) || (0 == parentEntry)) ! 888: return( 0); ! 889: ! 890: IODTGetCellCounts( parentEntry, &sizeCells, &addressCells ); ! 891: if( 0 == sizeCells) ! 892: return( 0); ! 893: ! 894: cells = sizeCells + addressCells; ! 895: reg = (UInt32 *) addressProperty->getBytesNoCopy(); ! 896: num = addressProperty->getLength() / (4 * cells); ! 897: ! 898: array = OSArray::withCapacity( 1 ); ! 899: if( 0 == array) ! 900: return( 0); ! 901: ! 902: for( i = 0; i < num; i++) { ! 903: ! 904: if( IODTResolveAddressCell( parentEntry, reg, &phys, &len )) { ! 905: ! 906: range = 0; ! 907: if( parent) ! 908: range = IODeviceMemory::withSubRange( parent, ! 909: phys - parent->getPhysicalAddress(), len ); ! 910: if( 0 == range) ! 911: range = IODeviceMemory::withRange( phys, len ); ! 912: if( range) ! 913: array->setObject( range ); ! 914: } ! 915: reg += cells; ! 916: } ! 917: ! 918: regEntry->setProperty( gIODeviceMemoryKey, array); ! 919: array->release(); /* ??? */ ! 920: ! 921: return( array); ! 922: } ! 923: ! 924: static void IODTGetNVLocation( ! 925: IORegistryEntry * parent, ! 926: IORegistryEntry * regEntry, ! 927: UInt8 * busNum, UInt8 * deviceNum, UInt8 * functionNum ) ! 928: { ! 929: ! 930: OSData * prop; ! 931: IODTPersistent * persist; ! 932: UInt32 * cell; ! 933: ! 934: prop = (OSData *) parent->getProperty( gIODTPersistKey ); ! 935: if( prop) { ! 936: persist = (IODTPersistent *) prop->getBytesNoCopy(); ! 937: (*persist->locationFunc)( regEntry, busNum, deviceNum, functionNum ); ! 938: ! 939: } else { ! 940: prop = (OSData *) regEntry->getProperty( "reg" ); ! 941: *functionNum = 0; ! 942: if( prop) { ! 943: cell = (UInt32 *) prop->getBytesNoCopy(); ! 944: #if 0 ! 945: if( (regHi & 0xf0000000) != 0xf0000000) { ! 946: *bus = 0x03 & (regHi >> 16); ! 947: *function = 0x07 & (regHi >> 8); ! 948: *device = 0x1f & (regHi >> 11); ! 949: #endif ! 950: *busNum = 3; ! 951: *deviceNum = 0x1f & (cell[ 0 ] >> 24); ! 952: } else { ! 953: *busNum = 0; ! 954: *deviceNum = 0; ! 955: } ! 956: } ! 957: } ! 958: ! 959: /* ! 960: * Try to make the same messed up descriptor as Mac OS ! 961: */ ! 962: ! 963: IOReturn IODTMakeNVDescriptor( IORegistryEntry * regEntry, ! 964: IONVRAMDescriptor * hdr ) ! 965: { ! 966: IORegistryEntry * parent; ! 967: UInt32 level; ! 968: UInt32 bridgeDevices; ! 969: UInt8 busNum; ! 970: UInt8 deviceNum; ! 971: UInt8 functionNum; ! 972: ! 973: hdr->format = 1; ! 974: hdr->marker = 0; ! 975: ! 976: for( ! 977: level = 0, bridgeDevices = 0; ! 978: (parent = regEntry->getParentEntry( gIODTPlane )) ! 979: && (level < 7); ! 980: level++ ) { ! 981: ! 982: IODTGetNVLocation( parent, regEntry, ! 983: &busNum, &deviceNum, &functionNum ); ! 984: if( level) ! 985: bridgeDevices |= ((deviceNum & 0x1f) << ((level - 1) * 5)); ! 986: else { ! 987: hdr->busNum = busNum; ! 988: hdr->deviceNum = deviceNum; ! 989: hdr->functionNum = functionNum; ! 990: } ! 991: regEntry = parent; ! 992: } ! 993: hdr->bridgeCount = level - 2; ! 994: hdr->bridgeDevices = bridgeDevices; ! 995: ! 996: return( kIOReturnSuccess ); ! 997: } ! 998: ! 999: OSData * IODTFindSlotName( IORegistryEntry * regEntry, UInt32 deviceNumber ) ! 1000: { ! 1001: IORegistryEntry * parent; ! 1002: OSData * data; ! 1003: OSData * ret = 0; ! 1004: UInt32 * bits; ! 1005: UInt32 i; ! 1006: char * names; ! 1007: char * lastName; ! 1008: UInt32 mask; ! 1009: ! 1010: data = (OSData *) regEntry->getProperty("AAPL,slot-name"); ! 1011: if( data) ! 1012: return( data); ! 1013: parent = regEntry->getParentEntry( gIODTPlane ); ! 1014: if( !parent) ! 1015: return( 0 ); ! 1016: data = OSDynamicCast( OSData, parent->getProperty("slot-names")); ! 1017: if( !data) ! 1018: return( 0 ); ! 1019: if( data->getLength() <= 4) ! 1020: return( 0 ); ! 1021: ! 1022: bits = (UInt32 *) data->getBytesNoCopy(); ! 1023: mask = *bits; ! 1024: if( (0 == (mask & (1 << deviceNumber)))) ! 1025: return( 0 ); ! 1026: ! 1027: names = (char *)(bits + 1); ! 1028: lastName = names + (data->getLength() - 4); ! 1029: ! 1030: for( i = 0; ! 1031: (i <= deviceNumber) && (names < lastName); ! 1032: i++ ) { ! 1033: ! 1034: if( mask & (1 << i)) { ! 1035: if( i == deviceNumber) { ! 1036: data = OSData::withBytesNoCopy( names, 1 + strlen( names)); ! 1037: if( data) { ! 1038: regEntry->setProperty("AAPL,slot-name", data); ! 1039: ret = data; ! 1040: data->release(); ! 1041: } ! 1042: } else ! 1043: names += 1 + strlen( names); ! 1044: } ! 1045: } ! 1046: ! 1047: return( ret ); ! 1048: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.