Annotation of XNU/iokit/Kernel/IODeviceTreeSupport.cpp, revision 1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.