2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
23 #include <IOKit/IODeviceTreeSupport.h>
24 #include <libkern/c++/OSContainers.h>
25 #include <IOKit/IODeviceMemory.h>
26 #include <IOKit/IOService.h>
27 #include <IOKit/IOCatalogue.h>
29 #include <IOKit/IOLib.h>
30 #include <IOKit/IOKitKeys.h>
32 #include <pexpert/device_tree.h>
35 #include <machine/machine_routines.h>
36 void DTInit( void * data
);
38 int IODTGetLoaderInfo( char *key
, void **infoAddr
, int *infosize
);
39 void IODTFreeLoaderInfo( char *key
, void *infoAddr
, int infoSize
);
42 #include <IOKit/assert.h>
44 #define IODTSUPPORTDEBUG 0
46 const IORegistryPlane
* gIODTPlane
;
48 static OSArray
* gIODTPHandles
;
49 static OSArray
* gIODTPHandleMap
;
51 const OSSymbol
* gIODTNameKey
;
52 const OSSymbol
* gIODTUnitKey
;
53 const OSSymbol
* gIODTCompatibleKey
;
54 const OSSymbol
* gIODTTypeKey
;
55 const OSSymbol
* gIODTModelKey
;
57 const OSSymbol
* gIODTSizeCellKey
;
58 const OSSymbol
* gIODTAddressCellKey
;
59 const OSSymbol
* gIODTRangeKey
;
61 const OSSymbol
* gIODTPersistKey
;
63 const OSSymbol
* gIODTDefaultInterruptController
;
64 const OSSymbol
* gIODTAAPLInterruptsKey
;
65 const OSSymbol
* gIODTPHandleKey
;
66 const OSSymbol
* gIODTInterruptCellKey
;
67 const OSSymbol
* gIODTInterruptParentKey
;
68 const OSSymbol
* gIODTNWInterruptMappingKey
;
70 OSDictionary
* gIODTSharedInterrupts
;
72 static IORegistryEntry
* MakeReferenceTable( DTEntry dtEntry
, bool copy
);
73 static void AddPHandle( IORegistryEntry
* regEntry
);
74 static void FreePhysicalMemory( vm_offset_t
* range
);
75 static bool IODTMapInterruptsSharing( IORegistryEntry
* regEntry
, OSDictionary
* allInts
);
78 IODeviceTreeAlloc( void * dtTop
)
80 IORegistryEntry
* parent
;
81 IORegistryEntry
* child
;
82 IORegistryIterator
* regIter
;
89 OSDictionary
* allInts
;
95 gIODTPlane
= IORegistryEntry::makePlane( kIODeviceTreePlane
);
97 gIODTNameKey
= OSSymbol::withCStringNoCopy( "name" );
98 gIODTUnitKey
= OSSymbol::withCStringNoCopy( "AAPL,unit-string" );
99 gIODTCompatibleKey
= OSSymbol::withCStringNoCopy( "compatible" );
100 gIODTTypeKey
= OSSymbol::withCStringNoCopy( "device_type" );
101 gIODTModelKey
= OSSymbol::withCStringNoCopy( "model" );
102 gIODTSizeCellKey
= OSSymbol::withCStringNoCopy( "#size-cells" );
103 gIODTAddressCellKey
= OSSymbol::withCStringNoCopy( "#address-cells" );
104 gIODTRangeKey
= OSSymbol::withCStringNoCopy( "ranges" );
105 gIODTPersistKey
= OSSymbol::withCStringNoCopy( "IODTPersist" );
107 assert( gIODTPlane
&& gIODTCompatibleKey
108 && gIODTTypeKey
&& gIODTModelKey
109 && gIODTSizeCellKey
&& gIODTAddressCellKey
&& gIODTRangeKey
110 && gIODTPersistKey
);
112 gIODTDefaultInterruptController
113 = OSSymbol::withCStringNoCopy("IOPrimaryInterruptController");
114 gIODTNWInterruptMappingKey
115 = OSSymbol::withCStringNoCopy("IONWInterrupts");
117 gIODTAAPLInterruptsKey
118 = OSSymbol::withCStringNoCopy("AAPL,interrupts");
120 = OSSymbol::withCStringNoCopy("AAPL,phandle");
122 gIODTInterruptParentKey
123 = OSSymbol::withCStringNoCopy("interrupt-parent");
125 gIODTPHandles
= OSArray::withCapacity( 1 );
126 gIODTPHandleMap
= OSArray::withCapacity( 1 );
128 gIODTInterruptCellKey
129 = OSSymbol::withCStringNoCopy("#interrupt-cells");
131 assert( gIODTDefaultInterruptController
&& gIODTNWInterruptMappingKey
132 && gIODTAAPLInterruptsKey
133 && gIODTPHandleKey
&& gIODTInterruptParentKey
134 && gIODTPHandles
&& gIODTPHandleMap
135 && gIODTInterruptCellKey
138 freeDT
= (kSuccess
== DTLookupEntry( 0, "/chosen/memory-map", &mapEntry
))
139 && (kSuccess
== DTGetProperty( mapEntry
,
140 "DeviceTree", (void **) &dtMap
, &propSize
))
141 && ((2 * sizeof( vm_offset_t
)) == propSize
);
143 parent
= MakeReferenceTable( (DTEntry
)dtTop
, freeDT
);
145 stack
= OSArray::withObjects( (const OSObject
**) &parent
, 1, 10 );
146 DTCreateEntryIterator( (DTEntry
)dtTop
, &iter
);
149 parent
= (IORegistryEntry
*)stack
->getObject( stack
->getCount() - 1);
151 stack
->removeObject( stack
->getCount() - 1);
153 while( kSuccess
== DTIterateEntries( iter
, &dtChild
) ) {
155 child
= MakeReferenceTable( dtChild
, freeDT
);
156 child
->attachToParent( parent
, gIODTPlane
);
160 if( kSuccess
== DTEnterEntry( iter
, dtChild
)) {
161 stack
->setObject( parent
);
164 // only registry holds retain
168 } while( stack
->getCount()
169 && (kSuccess
== DTExitEntry( iter
, &dtChild
)));
172 DTDisposeEntryIterator( iter
);
174 // parent is now root of the created tree
176 // make root name first compatible entry (purely cosmetic)
177 if( (prop
= (OSData
*) parent
->getProperty( gIODTCompatibleKey
))) {
178 parent
->setName( parent
->getName(), gIODTPlane
);
179 parent
->setName( (const char *) prop
->getBytesNoCopy() );
182 // attach tree to meta root
183 parent
->attachToParent( IORegistryEntry::getRegistryRoot(), gIODTPlane
);
187 // free original device tree
189 IODTFreeLoaderInfo( "DeviceTree",
190 (void *)dtMap
[0], round_page_32(dtMap
[1]) );
195 gIODTSharedInterrupts
= OSDictionary::withCapacity(4);
196 allInts
= OSDictionary::withCapacity(4);
198 regIter
= IORegistryIterator::iterateOver( gIODTPlane
,
199 kIORegistryIterateRecursively
);
200 assert( regIter
&& allInts
&& gIODTSharedInterrupts
);
201 if( regIter
&& allInts
&& gIODTSharedInterrupts
) {
202 while( (child
= regIter
->getNextObject())) {
203 IODTMapInterruptsSharing( child
, allInts
);
204 if( !intMap
&& child
->getProperty( gIODTInterruptParentKey
))
207 // Look for a "driver,AAPL,MacOSX,PowerPC" property.
208 if( (obj
= child
->getProperty( "driver,AAPL,MacOSX,PowerPC"))) {
209 gIOCatalogue
->addExtensionsFromArchive((OSData
*)obj
);
210 child
->removeProperty( "driver,AAPL,MacOSX,PowerPC");
213 // some gross pruning
214 child
->removeProperty( "lanLib,AAPL,MacOS,PowerPC");
216 if( (obj
= child
->getProperty( "driver,AAPL,MacOS,PowerPC"))) {
218 if( (0 == (prop
= (OSData
*)child
->getProperty( gIODTTypeKey
)))
219 || (strcmp( "display", (char *) prop
->getBytesNoCopy())) ) {
220 child
->removeProperty( "driver,AAPL,MacOS,PowerPC");
228 parent
->setProperty("allInts", allInts
);
229 parent
->setProperty("sharedInts", gIODTSharedInterrupts
);
231 regIter
= IORegistryIterator::iterateOver( gIODTPlane
,
232 kIORegistryIterateRecursively
);
234 while( (child
= regIter
->getNextObject())) {
236 array
= OSDynamicCast(OSArray
, child
->getProperty( gIOInterruptSpecifiersKey
));
237 for( UInt32 i
= 0; array
&& (i
< array
->getCount()); i
++)
239 IOOptionBits options
;
240 IOReturn ret
= IODTGetInterruptOptions( child
, i
, &options
);
241 if( (ret
!= kIOReturnSuccess
) || options
)
242 IOLog("%s[%ld] %ld (%x)\n", child
->getName(), i
, options
, ret
);
252 // set a key in the root to indicate we found NW interrupt mapping
253 parent
->setProperty( gIODTNWInterruptMappingKey
,
254 (OSObject
*) gIODTNWInterruptMappingKey
);
259 int IODTGetLoaderInfo( char *key
, void **infoAddr
, int *infoSize
)
261 IORegistryEntry
*chosen
;
263 unsigned int *propPtr
;
264 unsigned int propSize
;
266 chosen
= IORegistryEntry::fromPath( "/chosen/memory-map", gIODTPlane
);
267 if ( chosen
== 0 ) return -1;
269 propObj
= OSDynamicCast( OSData
, chosen
->getProperty(key
) );
270 if ( propObj
== 0 ) return -1;
272 propSize
= propObj
->getLength();
273 if ( propSize
!= (2 * sizeof(UInt32
)) ) return -1;
275 propPtr
= (unsigned int *)propObj
->getBytesNoCopy();
276 if ( propPtr
== 0 ) return -1;
278 *infoAddr
= (void *)propPtr
[0] ;
279 *infoSize
= (int) propPtr
[1];
284 void IODTFreeLoaderInfo( char *key
, void *infoAddr
, int infoSize
)
286 vm_offset_t range
[2];
287 IORegistryEntry
*chosen
;
289 range
[0] = (vm_offset_t
)infoAddr
;
290 range
[1] = (vm_offset_t
)infoSize
;
291 FreePhysicalMemory( range
);
294 chosen
= IORegistryEntry::fromPath( "/chosen/memory-map", gIODTPlane
);
296 chosen
->removeProperty(key
);
301 static void FreePhysicalMemory( vm_offset_t
* range
)
305 #if defined (__i386__)
306 virt
= ml_boot_ptovirt( range
[0] );
308 virt
= ml_static_ptovirt( range
[0] );
311 ml_static_mfree( virt
, range
[1] );
315 static IORegistryEntry
*
316 MakeReferenceTable( DTEntry dtEntry
, bool copy
)
318 IORegistryEntry
*regEntry
;
319 OSDictionary
*propTable
;
320 const OSSymbol
*nameKey
;
323 DTPropertyIterator dtIter
;
328 bool noLocation
= true;
330 regEntry
= new IOService
;
332 if( regEntry
&& (false == regEntry
->init())) {
338 (kSuccess
== DTCreatePropertyIterator( dtEntry
, &dtIter
))) {
340 propTable
= regEntry
->getPropertyTable();
342 while( kSuccess
== DTIterateProperties( dtIter
, &name
)) {
344 if( kSuccess
!= DTGetProperty( dtEntry
, name
, &prop
, &propSize
))
348 nameKey
= OSSymbol::withCString(name
);
349 data
= OSData::withBytes(prop
, propSize
);
351 nameKey
= OSSymbol::withCStringNoCopy(name
);
352 data
= OSData::withBytesNoCopy(prop
, propSize
);
354 assert( nameKey
&& data
);
356 propTable
->setObject( nameKey
, data
);
360 if( nameKey
== gIODTNameKey
) {
362 sym
= OSSymbol::withCString( (const char *) prop
);
364 sym
= OSSymbol::withCStringNoCopy( (const char *) prop
);
365 regEntry
->setName( sym
);
368 } else if( nameKey
== gIODTUnitKey
) {
369 // all OF strings are null terminated... except this one
370 if( propSize
>= (int) sizeof( location
))
371 propSize
= sizeof( location
) - 1;
372 strncpy( location
, (const char *) prop
, propSize
);
373 location
[ propSize
] = 0;
374 regEntry
->setLocation( location
);
375 propTable
->removeObject( gIODTUnitKey
);
378 } else if( noLocation
&& (0 == strcmp( name
, "reg"))) {
379 // default location - override later
380 sprintf( location
, "%lX", *((UInt32
*) prop
) );
381 regEntry
->setLocation( location
);
384 DTDisposePropertyIterator( dtIter
);
390 static void AddPHandle( IORegistryEntry
* regEntry
)
394 if( regEntry
->getProperty( gIODTInterruptCellKey
)
395 && (data
= OSDynamicCast( OSData
, regEntry
->getProperty( gIODTPHandleKey
)))) {
396 // a possible interrupt-parent
397 gIODTPHandles
->setObject( data
);
398 gIODTPHandleMap
->setObject( regEntry
);
402 static IORegistryEntry
* FindPHandle( UInt32 phandle
)
405 IORegistryEntry
*regEntry
= 0;
408 for( i
= 0; (data
= (OSData
*)gIODTPHandles
->getObject( i
)); i
++ ) {
409 if( phandle
== *((UInt32
*)data
->getBytesNoCopy())) {
410 regEntry
= (IORegistryEntry
*)
411 gIODTPHandleMap
->getObject( i
);
419 static bool GetUInt32( IORegistryEntry
* regEntry
, const OSSymbol
* name
,
424 if( (data
= OSDynamicCast( OSData
, regEntry
->getProperty( name
)))
425 && (4 == data
->getLength())) {
426 *value
= *((UInt32
*) data
->getBytesNoCopy());
432 IORegistryEntry
* IODTFindInterruptParent( IORegistryEntry
* regEntry
)
434 IORegistryEntry
* parent
;
437 if( GetUInt32( regEntry
, gIODTInterruptParentKey
, &phandle
))
438 parent
= FindPHandle( phandle
);
440 else if( 0 == regEntry
->getProperty( "interrupt-controller"))
441 parent
= regEntry
->getParentEntry( gIODTPlane
);
448 const OSSymbol
* IODTInterruptControllerName( IORegistryEntry
* regEntry
)
455 ok
= GetUInt32( regEntry
, gIODTPHandleKey
, &phandle
);
459 sprintf( buf
, "IOInterruptController%08lX", phandle
);
460 sym
= OSSymbol::withCString( buf
);
467 #define unexpected(a) { kprintf("unexpected %s:%d\n", __FILE__, __LINE__); a; }
469 static void IODTGetICellCounts( IORegistryEntry
* regEntry
,
470 UInt32
* iCellCount
, UInt32
* aCellCount
)
472 if( !GetUInt32( regEntry
, gIODTInterruptCellKey
, iCellCount
))
473 unexpected( *iCellCount
= 1 );
474 if( !GetUInt32( regEntry
, gIODTAddressCellKey
, aCellCount
))
478 UInt32
IODTMapOneInterrupt( IORegistryEntry
* regEntry
, UInt32
* intSpec
,
479 OSData
** spec
, const OSSymbol
** controller
)
481 IORegistryEntry
*parent
= 0;
487 UInt32 acells
, icells
, pacells
, picells
, cell
;
488 UInt32 i
, original_icells
;
489 bool cmp
, ok
= false;
491 parent
= IODTFindInterruptParent( regEntry
);
492 IODTGetICellCounts( parent
, &icells
, &acells
);
495 data
= OSDynamicCast( OSData
, regEntry
->getProperty( "reg" ));
496 if( data
&& (data
->getLength() >= (acells
* sizeof( UInt32
))))
497 addrCmp
= (UInt32
*) data
->getBytesNoCopy();
499 original_icells
= icells
;
504 kprintf ("IODTMapOneInterrupt: current regEntry name %s\n", regEntry
->getName());
505 kprintf ("acells - icells: ");
506 for (i
= 0; i
< acells
; i
++) kprintf ("0x%08X ", addrCmp
[i
]);
508 for (i
= 0; i
< icells
; i
++) kprintf ("0x%08X ", intSpec
[i
]);
512 if( parent
&& (data
= OSDynamicCast( OSData
,
513 regEntry
->getProperty( "interrupt-controller")))) {
514 // found a controller - don't want to follow cascaded controllers
516 *spec
= OSData::withBytesNoCopy( (void *) intSpec
,
517 icells
* sizeof( UInt32
));
518 *controller
= IODTInterruptControllerName( regEntry
);
519 ok
= (*spec
&& *controller
);
520 } else if( parent
&& (data
= OSDynamicCast( OSData
,
521 regEntry
->getProperty( "interrupt-map")))) {
523 map
= (UInt32
*) data
->getBytesNoCopy();
524 endMap
= map
+ (data
->getLength() / sizeof(UInt32
));
525 data
= OSDynamicCast( OSData
, regEntry
->getProperty( "interrupt-map-mask" ));
526 if( data
&& (data
->getLength() >= ((acells
+ icells
) * sizeof( UInt32
))))
527 maskCmp
= (UInt32
*) data
->getBytesNoCopy();
533 kprintf (" maskCmp: ");
534 for (i
= 0; i
< acells
+ icells
; i
++) {
537 kprintf ("0x%08X ", maskCmp
[i
]);
540 kprintf (" masked: ");
541 for (i
= 0; i
< acells
+ icells
; i
++) {
544 kprintf ("0x%08X ", ((i
< acells
) ? addrCmp
[i
] : intSpec
[i
-acells
]) & maskCmp
[i
]);
548 kprintf ("no maskCmp\n");
553 for (i
= 0; i
< acells
+ icells
; i
++) {
556 kprintf ("0x%08X ", map
[i
]);
560 for( i
= 0, cmp
= true; cmp
&& (i
< (acells
+ icells
)); i
++) {
561 cell
= (i
< acells
) ? addrCmp
[i
] : intSpec
[ i
- acells
];
564 cmp
= (cell
== map
[i
]);
567 map
+= acells
+ icells
;
568 if( 0 == (parent
= FindPHandle( *(map
++) )))
571 IODTGetICellCounts( parent
, &picells
, &pacells
);
574 intSpec
= map
+ pacells
;
577 map
+= pacells
+ picells
;
579 } while( !cmp
&& (map
< endMap
) );
585 IODTGetICellCounts( parent
, &icells
, &acells
);
591 return( ok
? original_icells
: 0 );
594 IOReturn
IODTGetInterruptOptions( IORegistryEntry
* regEntry
, int source
, IOOptionBits
* options
)
596 OSArray
* controllers
;
597 OSArray
* specifiers
;
604 controllers
= OSDynamicCast(OSArray
, regEntry
->getProperty(gIOInterruptControllersKey
));
605 specifiers
= OSDynamicCast(OSArray
, regEntry
->getProperty(gIOInterruptSpecifiersKey
));
607 if( !controllers
|| !specifiers
)
608 return (kIOReturnNoInterrupt
);
610 shared
= (OSArray
*) gIODTSharedInterrupts
->getObject(
611 (const OSSymbol
*) controllers
->getObject(source
) );
613 return (kIOReturnSuccess
);
615 spec
= specifiers
->getObject(source
);
617 return (kIOReturnNoInterrupt
);
619 for (unsigned int i
= 0;
620 (oneSpec
= shared
->getObject(i
))
621 && (!oneSpec
->isEqualTo(spec
));
625 *options
= kIODTInterruptShared
;
627 return (kIOReturnSuccess
);
630 static bool IODTMapInterruptsSharing( IORegistryEntry
* regEntry
, OSDictionary
* allInts
)
632 IORegistryEntry
* parent
;
640 OSArray
* controllerInts
;
641 const OSSymbol
* controller
;
642 OSArray
* controllers
;
646 nw
= (0 == (local
= OSDynamicCast( OSData
,
647 regEntry
->getProperty( gIODTAAPLInterruptsKey
))));
648 if( nw
&& (0 == (local
= OSDynamicCast( OSData
,
649 regEntry
->getProperty( "interrupts")))))
650 return( true ); // nothing to see here
652 if( nw
&& (parent
= regEntry
->getParentEntry( gIODTPlane
))) {
653 // check for bridges on old world
654 if( (local2
= OSDynamicCast( OSData
,
655 parent
->getProperty( gIODTAAPLInterruptsKey
)))) {
661 localBits
= (UInt32
*) local
->getBytesNoCopy();
662 localEnd
= localBits
+ (local
->getLength() / sizeof( UInt32
));
663 mapped
= OSArray::withCapacity( 1 );
664 controllers
= OSArray::withCapacity( 1 );
666 ok
= (mapped
&& controllers
);
670 skip
= IODTMapOneInterrupt( regEntry
, localBits
, &map
, &controller
);
672 IOLog("%s: error mapping interrupt[%d]\n",
673 regEntry
->getName(), mapped
->getCount());
677 map
= OSData::withData( local
, mapped
->getCount() * sizeof( UInt32
),
679 controller
= gIODTDefaultInterruptController
;
680 controller
->retain();
684 mapped
->setObject( map
);
685 controllers
->setObject( controller
);
689 controllerInts
= (OSArray
*) allInts
->getObject( controller
);
692 for (unsigned int i
= 0; (oneMap
= controllerInts
->getObject(i
)); i
++)
694 if (map
->isEqualTo(oneMap
))
696 controllerInts
= (OSArray
*) gIODTSharedInterrupts
->getObject( controller
);
698 controllerInts
->setObject(map
);
701 controllerInts
= OSArray::withObjects( (const OSObject
**) &map
, 1, 4 );
704 gIODTSharedInterrupts
->setObject( controller
, controllerInts
);
705 controllerInts
->release();
712 controllerInts
->setObject(map
);
716 controllerInts
= OSArray::withObjects( (const OSObject
**) &map
, 1, 16 );
719 allInts
->setObject( controller
, controllerInts
);
720 controllerInts
->release();
726 controller
->release();
728 } while( localBits
< localEnd
);
730 ok
&= (localBits
== localEnd
);
734 ok
= regEntry
->setProperty( gIOInterruptControllersKey
, controllers
);
735 ok
&= regEntry
->setProperty( gIOInterruptSpecifiersKey
, mapped
);
739 controllers
->release();
746 bool IODTMapInterrupts( IORegistryEntry
* regEntry
)
748 return( IODTMapInterruptsSharing( regEntry
, 0 ));
755 CompareKey( OSString
* key
,
756 const IORegistryEntry
* table
, const OSSymbol
* propName
)
764 const char *lastName
;
767 const char *result
= 0;
769 if( 0 == (prop
= table
->getProperty( propName
)))
772 if( (data
= OSDynamicCast( OSData
, prop
))) {
773 names
= (const char *) data
->getBytesNoCopy();
774 lastName
= names
+ data
->getLength();
775 } else if( (string
= OSDynamicCast( OSString
, prop
))) {
776 names
= string
->getCStringNoCopy();
777 lastName
= names
+ string
->getLength() + 1;
781 ckey
= key
->getCStringNoCopy();
782 keyLen
= key
->getLength();
783 wild
= ('*' == key
->getChar( keyLen
- 1 ));
786 // for each name in the property
788 matched
= (0 == strncmp( ckey
, names
, keyLen
- 1 ));
790 matched
= (keyLen
== strlen( names
))
791 && (0 == strncmp( ckey
, names
, keyLen
));
796 names
= names
+ strlen( names
) + 1;
798 } while( (names
< lastName
) && (false == matched
));
804 bool IODTCompareNubName( const IORegistryEntry
* regEntry
,
805 OSString
* name
, OSString
** matchingName
)
810 matched
= (0 != (result
= CompareKey( name
, regEntry
, gIODTNameKey
)))
811 || (0 != (result
= CompareKey( name
, regEntry
, gIODTCompatibleKey
)))
812 || (0 != (result
= CompareKey( name
, regEntry
, gIODTTypeKey
)))
813 || (0 != (result
= CompareKey( name
, regEntry
, gIODTModelKey
)));
815 if( result
&& matchingName
)
816 *matchingName
= OSString::withCString( result
);
818 return( result
!= 0 );
821 bool IODTMatchNubWithKeys( IORegistryEntry
* regEntry
,
827 obj
= OSUnserialize( keys
, 0 );
830 result
= regEntry
->compareNames( obj
);
834 else IOLog("Couldn't unserialize %s\n", keys
);
840 OSCollectionIterator
* IODTFindMatchingEntries( IORegistryEntry
* from
,
841 IOOptionBits options
, const char * keys
)
844 IORegistryEntry
*next
;
845 IORegistryIterator
*iter
;
846 OSCollectionIterator
*cIter
;
848 bool minus
= options
& kIODTExclusive
;
851 iter
= IORegistryIterator::iterateOver( from
, gIODTPlane
,
852 (options
& kIODTRecursive
) ? kIORegistryIterateRecursively
: 0 );
859 result
= OSSet::withCapacity( 3 );
864 while( (next
= iter
->getNextObject())) {
866 // Look for existence of a debug property to skip
867 if( next
->getProperty("AAPL,ignore"))
871 cmp
= IODTMatchNubWithKeys( next
, keys
);
872 if( (minus
&& (false == cmp
))
873 || ((false == minus
) && (false != cmp
)) )
874 result
->setObject( next
);
876 result
->setObject( next
);
878 } while( !iter
->isValid());
883 cIter
= OSCollectionIterator::withCollection( result
);
890 struct IODTPersistent
{
891 IODTCompareAddressCellFunc compareFunc
;
892 IODTNVLocationFunc locationFunc
;
895 void IODTSetResolving( IORegistryEntry
* regEntry
,
896 IODTCompareAddressCellFunc compareFunc
,
897 IODTNVLocationFunc locationFunc
)
899 IODTPersistent persist
;
902 persist
.compareFunc
= compareFunc
;
903 persist
.locationFunc
= locationFunc
;
904 prop
= OSData::withBytes( &persist
, sizeof( persist
));
908 regEntry
->setProperty( gIODTPersistKey
, prop
);
913 static SInt32
DefaultCompare( UInt32 cellCount
, UInt32 left
[], UInt32 right
[] )
916 return( left
[ cellCount
] - right
[ cellCount
] );
919 void IODTGetCellCounts( IORegistryEntry
* regEntry
,
920 UInt32
* sizeCount
, UInt32
* addressCount
)
922 if( !GetUInt32( regEntry
, gIODTSizeCellKey
, sizeCount
))
924 if( !GetUInt32( regEntry
, gIODTAddressCellKey
, addressCount
))
929 // Given addr & len cells from our child, find it in our ranges property, then
930 // look in our parent to resolve the base of the range for us.
932 // Range[]: child-addr our-addr child-len
933 // #cells: child ours child
935 bool IODTResolveAddressCell( IORegistryEntry
* regEntry
,
937 IOPhysicalAddress
* phys
, IOPhysicalLength
* len
)
939 IORegistryEntry
*parent
;
941 // cells in addresses at regEntry
942 UInt32 sizeCells
, addressCells
;
943 // cells in addresses below regEntry
944 UInt32 childSizeCells
, childAddressCells
;
946 UInt32 cell
[ 5 ], offset
= 0, length
;
953 SInt32 diff
, endDiff
;
955 IODTPersistent
*persist
;
956 IODTCompareAddressCellFunc compare
;
958 IODTGetCellCounts( regEntry
, &childSizeCells
, &childAddressCells
);
959 childCells
= childAddressCells
+ childSizeCells
;
961 bcopy( cellsIn
, cell
, 4 * childCells
);
962 if( childSizeCells
> 1)
963 *len
= IOPhysical32( cellsIn
[ childAddressCells
],
964 cellsIn
[ childAddressCells
+ 1 ] );
966 *len
= IOPhysical32( 0, cellsIn
[ childAddressCells
] );
970 prop
= OSDynamicCast( OSData
, regEntry
->getProperty( gIODTRangeKey
));
972 /* end of the road */
973 *phys
= IOPhysical32( 0, cell
[ childAddressCells
- 1 ] + offset
);
977 parent
= regEntry
->getParentEntry( gIODTPlane
);
978 IODTGetCellCounts( parent
, &sizeCells
, &addressCells
);
980 if( (length
= prop
->getLength())) {
982 startRange
= (UInt32
*) prop
->getBytesNoCopy();
984 endRanges
= range
+ (length
/ 4);
986 prop
= (OSData
*) regEntry
->getProperty( gIODTPersistKey
);
988 persist
= (IODTPersistent
*) prop
->getBytesNoCopy();
989 compare
= persist
->compareFunc
;
991 compare
= DefaultCompare
;
995 range
+= (childCells
+ addressCells
) ) {
997 // is cell start >= range start?
998 diff
= (*compare
)( childAddressCells
, cell
, range
);
1002 ok
= (0 == cell
[childCells
- 1]);
1005 // search for cell end
1006 bcopy(cell
, endCell
, childAddressCells
* sizeof(UInt32
));
1007 endCell
[childAddressCells
- 1] += cell
[childCells
- 1] - 1;
1008 lookRange
= startRange
;
1010 lookRange
< endRanges
;
1011 lookRange
+= (childCells
+ addressCells
) )
1013 // is cell >= range start?
1014 endDiff
= (*compare
)( childAddressCells
, endCell
, lookRange
);
1017 if ((endDiff
- cell
[childCells
- 1] + 1 + lookRange
[childAddressCells
+ addressCells
- 1])
1018 == (diff
+ range
[childAddressCells
+ addressCells
- 1]))
1031 // Get the physical start of the range from our parent
1032 bcopy( range
+ childAddressCells
, cell
, 4 * addressCells
);
1033 bzero( cell
+ addressCells
, 4 * sizeCells
);
1035 } /* else zero length range => pass thru to parent */
1038 childSizeCells
= sizeCells
;
1039 childAddressCells
= addressCells
;
1040 childCells
= childAddressCells
+ childSizeCells
;
1042 while( ok
&& regEntry
);
1048 OSArray
* IODTResolveAddressing( IORegistryEntry
* regEntry
,
1049 const char * addressPropertyName
,
1050 IODeviceMemory
* parent
)
1052 IORegistryEntry
*parentEntry
;
1053 OSData
*addressProperty
;
1054 UInt32 sizeCells
, addressCells
, cells
;
1057 IOPhysicalAddress phys
;
1058 IOPhysicalLength len
;
1060 IODeviceMemory
*range
;
1062 parentEntry
= regEntry
->getParentEntry( gIODTPlane
);
1063 addressProperty
= (OSData
*) regEntry
->getProperty( addressPropertyName
);
1064 if( (0 == addressProperty
) || (0 == parentEntry
))
1067 IODTGetCellCounts( parentEntry
, &sizeCells
, &addressCells
);
1071 cells
= sizeCells
+ addressCells
;
1072 reg
= (UInt32
*) addressProperty
->getBytesNoCopy();
1073 num
= addressProperty
->getLength() / (4 * cells
);
1075 array
= OSArray::withCapacity( 1 );
1079 for( i
= 0; i
< num
; i
++) {
1080 if( IODTResolveAddressCell( parentEntry
, reg
, &phys
, &len
)) {
1083 range
= IODeviceMemory::withSubRange( parent
,
1084 phys
- parent
->getPhysicalAddress(), len
);
1086 range
= IODeviceMemory::withRange( phys
, len
);
1088 array
->setObject( range
);
1093 regEntry
->setProperty( gIODeviceMemoryKey
, array
);
1094 array
->release(); /* ??? */
1099 static void IODTGetNVLocation(
1100 IORegistryEntry
* parent
,
1101 IORegistryEntry
* regEntry
,
1102 UInt8
* busNum
, UInt8
* deviceNum
, UInt8
* functionNum
)
1106 IODTPersistent
*persist
;
1109 prop
= (OSData
*) parent
->getProperty( gIODTPersistKey
);
1111 persist
= (IODTPersistent
*) prop
->getBytesNoCopy();
1112 (*persist
->locationFunc
)( regEntry
, busNum
, deviceNum
, functionNum
);
1114 prop
= (OSData
*) regEntry
->getProperty( "reg" );
1117 cell
= (UInt32
*) prop
->getBytesNoCopy();
1119 *deviceNum
= 0x1f & (cell
[ 0 ] >> 24);
1129 * Try to make the same messed up descriptor as Mac OS
1132 IOReturn
IODTMakeNVDescriptor( IORegistryEntry
* regEntry
,
1133 IONVRAMDescriptor
* hdr
)
1135 IORegistryEntry
*parent
;
1137 UInt32 bridgeDevices
;
1145 for(level
= 0, bridgeDevices
= 0;
1146 (parent
= regEntry
->getParentEntry( gIODTPlane
)) && (level
< 7); level
++ ) {
1148 IODTGetNVLocation( parent
, regEntry
,
1149 &busNum
, &deviceNum
, &functionNum
);
1151 bridgeDevices
|= ((deviceNum
& 0x1f) << ((level
- 1) * 5));
1153 hdr
->busNum
= busNum
;
1154 hdr
->deviceNum
= deviceNum
;
1155 hdr
->functionNum
= functionNum
;
1159 hdr
->bridgeCount
= level
- 2;
1160 hdr
->bridgeDevices
= bridgeDevices
;
1162 return( kIOReturnSuccess
);
1165 OSData
* IODTFindSlotName( IORegistryEntry
* regEntry
, UInt32 deviceNumber
)
1167 IORegistryEntry
*parent
;
1176 data
= (OSData
*) regEntry
->getProperty("AAPL,slot-name");
1179 parent
= regEntry
->getParentEntry( gIODTPlane
);
1182 data
= OSDynamicCast( OSData
, parent
->getProperty("slot-names"));
1185 if( data
->getLength() <= 4)
1188 bits
= (UInt32
*) data
->getBytesNoCopy();
1190 if( (0 == (mask
& (1 << deviceNumber
))))
1193 names
= (char *)(bits
+ 1);
1194 lastName
= names
+ (data
->getLength() - 4);
1196 for( i
= 0; (i
<= deviceNumber
) && (names
< lastName
); i
++ ) {
1198 if( mask
& (1 << i
)) {
1199 if( i
== deviceNumber
) {
1200 data
= OSData::withBytesNoCopy( names
, 1 + strlen( names
));
1202 regEntry
->setProperty("AAPL,slot-name", data
);
1207 names
+= 1 + strlen( names
);
1214 extern "C" IOReturn
IONDRVLibrariesInitialize( IOService
* provider
)
1216 return( kIOReturnUnsupported
);