|
|
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.