2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
26 * Copyright (c) 1998 Apple Computer, Inc. All rights reserved.
29 #include <IOKit/IODeviceTreeSupport.h>
30 #include <libkern/c++/OSContainers.h>
31 #include <IOKit/IODeviceMemory.h>
32 #include <IOKit/IOService.h>
33 #include <IOKit/IOCatalogue.h>
35 #include <IOKit/IOLib.h>
36 #include <IOKit/IOKitKeys.h>
38 #include <DeviceTree.h>
40 #include <machine/machine_routines.h>
41 void DTInit( void * data
);
43 int IODTGetLoaderInfo( char *key
, void **infoAddr
, int *infosize
);
44 void IODTFreeLoaderInfo( char *key
, void *infoAddr
, int infoSize
);
47 #include <IOKit/assert.h>
49 #define IODTSUPPORTDEBUG 0
51 const IORegistryPlane
* gIODTPlane
;
53 static OSArray
* gIODTPHandles
;
54 static OSArray
* gIODTPHandleMap
;
56 const OSSymbol
* gIODTNameKey
;
57 const OSSymbol
* gIODTUnitKey
;
58 const OSSymbol
* gIODTCompatibleKey
;
59 const OSSymbol
* gIODTTypeKey
;
60 const OSSymbol
* gIODTModelKey
;
62 const OSSymbol
* gIODTSizeCellKey
;
63 const OSSymbol
* gIODTAddressCellKey
;
64 const OSSymbol
* gIODTRangeKey
;
66 const OSSymbol
* gIODTPersistKey
;
68 const OSSymbol
* gIODTDefaultInterruptController
;
69 const OSSymbol
* gIODTAAPLInterruptsKey
;
70 const OSSymbol
* gIODTPHandleKey
;
71 const OSSymbol
* gIODTInterruptCellKey
;
72 const OSSymbol
* gIODTInterruptParentKey
;
73 const OSSymbol
* gIODTNWInterruptMappingKey
;
76 static IORegistryEntry
* MakeReferenceTable( DTEntry dtEntry
, bool copy
);
77 static void AddPHandle( IORegistryEntry
* regEntry
);
78 static void FreePhysicalMemory( vm_offset_t
* range
);
81 IODeviceTreeAlloc( void * dtTop
)
83 IORegistryEntry
*parent
;
84 IORegistryEntry
*child
;
85 IORegistryIterator
*regIter
;
97 IOLog("IODeviceTreeSupport ");
99 gIODTPlane
= IORegistryEntry::makePlane( kIODeviceTreePlane
);
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 gIODTPersistKey
= OSSymbol::withCStringNoCopy( "IODTPersist" );
111 assert( gIODTPlane
&& gIODTCompatibleKey
112 && gIODTTypeKey
&& gIODTModelKey
113 && gIODTSizeCellKey
&& gIODTAddressCellKey
&& gIODTRangeKey
114 && gIODTPersistKey
);
116 gIODTDefaultInterruptController
117 = OSSymbol::withCStringNoCopy("IOPrimaryInterruptController");
118 gIODTNWInterruptMappingKey
119 = OSSymbol::withCStringNoCopy("IONWInterrupts");
121 gIODTAAPLInterruptsKey
122 = OSSymbol::withCStringNoCopy("AAPL,interrupts");
124 = OSSymbol::withCStringNoCopy("AAPL,phandle");
126 gIODTInterruptParentKey
127 = OSSymbol::withCStringNoCopy("interrupt-parent");
129 gIODTPHandles
= OSArray::withCapacity( 1 );
130 gIODTPHandleMap
= OSArray::withCapacity( 1 );
132 gIODTInterruptCellKey
133 = OSSymbol::withCStringNoCopy("#interrupt-cells");
135 assert( gIODTDefaultInterruptController
&& gIODTNWInterruptMappingKey
136 && gIODTAAPLInterruptsKey
137 && gIODTPHandleKey
&& gIODTInterruptParentKey
138 && gIODTPHandles
&& gIODTPHandleMap
139 && gIODTInterruptCellKey
142 freeDT
= (kSuccess
== DTLookupEntry( 0, "/chosen/memory-map", &mapEntry
))
143 && (kSuccess
== DTGetProperty( mapEntry
,
144 "DeviceTree", (void **) &dtMap
, &propSize
))
145 && ((2 * sizeof( vm_offset_t
)) == propSize
);
147 parent
= MakeReferenceTable( (DTEntry
)dtTop
, freeDT
);
149 stack
= OSArray::withObjects( & (const OSObject
*) parent
, 1, 10 );
150 DTCreateEntryIterator( (DTEntry
)dtTop
, &iter
);
153 parent
= (IORegistryEntry
*)stack
->getObject( stack
->getCount() - 1);
155 stack
->removeObject( stack
->getCount() - 1);
157 while( kSuccess
== DTIterateEntries( iter
, &dtChild
) ) {
159 child
= MakeReferenceTable( dtChild
, freeDT
);
160 child
->attachToParent( parent
, gIODTPlane
);
164 if( kSuccess
== DTEnterEntry( iter
, dtChild
)) {
165 stack
->setObject( parent
);
168 // only registry holds retain
172 } while( stack
->getCount()
173 && (kSuccess
== DTExitEntry( iter
, &dtChild
)));
176 DTDisposeEntryIterator( iter
);
178 // parent is now root of the created tree
180 // make root name first compatible entry (purely cosmetic)
181 if( (prop
= (OSData
*) parent
->getProperty( gIODTCompatibleKey
))) {
182 parent
->setName( parent
->getName(), gIODTPlane
);
183 parent
->setName( (const char *) prop
->getBytesNoCopy() );
186 // attach tree to meta root
187 parent
->attachToParent( IORegistryEntry::getRegistryRoot(), gIODTPlane
);
191 // free original device tree
193 IODTFreeLoaderInfo( "DeviceTree",
194 (void *)dtMap
[0], round_page_32(dtMap
[1]) );
199 regIter
= IORegistryIterator::iterateOver( gIODTPlane
,
200 kIORegistryIterateRecursively
);
203 while( (child
= regIter
->getNextObject())) {
204 IODTMapInterrupts( child
);
205 if( !intMap
&& child
->getProperty( gIODTInterruptParentKey
))
208 // Look for a "driver,AAPL,MacOSX,PowerPC" property.
209 if( (obj
= child
->getProperty( "driver,AAPL,MacOSX,PowerPC"))) {
210 gIOCatalogue
->addExtensionsFromArchive((OSData
*)obj
);
211 child
->removeProperty( "driver,AAPL,MacOSX,PowerPC");
214 // some gross pruning
215 child
->removeProperty( "lanLib,AAPL,MacOS,PowerPC");
217 if( (obj
= child
->getProperty( "driver,AAPL,MacOS,PowerPC"))) {
219 if( (0 == (prop
= (OSData
*)child
->getProperty( gIODTTypeKey
)))
220 || (strcmp( "display", (char *) prop
->getBytesNoCopy())) ) {
221 child
->removeProperty( "driver,AAPL,MacOS,PowerPC");
229 // set a key in the root to indicate we found NW interrupt mapping
230 parent
->setProperty( gIODTNWInterruptMappingKey
,
231 (OSObject
*) gIODTNWInterruptMappingKey
);
238 int IODTGetLoaderInfo( char *key
, void **infoAddr
, int *infoSize
)
240 IORegistryEntry
*chosen
;
242 unsigned int *propPtr
;
243 unsigned int propSize
;
245 chosen
= IORegistryEntry::fromPath( "/chosen/memory-map", gIODTPlane
);
246 if ( chosen
== 0 ) return -1;
248 propObj
= OSDynamicCast( OSData
, chosen
->getProperty(key
) );
249 if ( propObj
== 0 ) return -1;
251 propSize
= propObj
->getLength();
252 if ( propSize
!= (2 * sizeof(UInt32
)) ) return -1;
254 propPtr
= (unsigned int *)propObj
->getBytesNoCopy();
255 if ( propPtr
== 0 ) return -1;
257 *infoAddr
= (void *)propPtr
[0] ;
258 *infoSize
= (int) propPtr
[1];
263 void IODTFreeLoaderInfo( char *key
, void *infoAddr
, int infoSize
)
265 vm_offset_t range
[2];
266 IORegistryEntry
*chosen
;
268 range
[0] = (vm_offset_t
)infoAddr
;
269 range
[1] = (vm_offset_t
)infoSize
;
270 FreePhysicalMemory( range
);
273 chosen
= IORegistryEntry::fromPath( "/chosen/memory-map", gIODTPlane
);
275 chosen
->removeProperty(key
);
280 static void FreePhysicalMemory( vm_offset_t
* range
)
284 virt
= ml_static_ptovirt( range
[0] );
286 ml_static_mfree( virt
, range
[1] );
290 static IORegistryEntry
*
291 MakeReferenceTable( DTEntry dtEntry
, bool copy
)
293 IORegistryEntry
*regEntry
;
294 OSDictionary
*propTable
;
295 const OSSymbol
*nameKey
;
298 DTPropertyIterator dtIter
;
303 bool noLocation
= true;
305 regEntry
= new IOService
;
307 if( regEntry
&& (false == regEntry
->init())) {
313 (kSuccess
== DTCreatePropertyIterator( dtEntry
, &dtIter
))) {
315 propTable
= regEntry
->getPropertyTable();
317 while( kSuccess
== DTIterateProperties( dtIter
, &name
)) {
319 if( kSuccess
!= DTGetProperty( dtEntry
, name
, &prop
, &propSize
))
323 nameKey
= OSSymbol::withCString(name
);
324 data
= OSData::withBytes(prop
, propSize
);
326 nameKey
= OSSymbol::withCStringNoCopy(name
);
327 data
= OSData::withBytesNoCopy(prop
, propSize
);
329 assert( nameKey
&& data
);
331 propTable
->setObject( nameKey
, data
);
335 if( nameKey
== gIODTNameKey
) {
337 sym
= OSSymbol::withCString( (const char *) prop
);
339 sym
= OSSymbol::withCStringNoCopy( (const char *) prop
);
340 regEntry
->setName( sym
);
343 } else if( nameKey
== gIODTUnitKey
) {
344 // all OF strings are null terminated... except this one
345 if( propSize
>= (int) sizeof( location
))
346 propSize
= sizeof( location
) - 1;
347 strncpy( location
, (const char *) prop
, propSize
);
348 location
[ propSize
] = 0;
349 regEntry
->setLocation( location
);
350 propTable
->removeObject( gIODTUnitKey
);
353 } else if( noLocation
&& (0 == strcmp( name
, "reg"))) {
354 // default location - override later
355 sprintf( location
, "%lX", *((UInt32
*) prop
) );
356 regEntry
->setLocation( location
);
359 DTDisposePropertyIterator( dtIter
);
365 static void AddPHandle( IORegistryEntry
* regEntry
)
369 if( regEntry
->getProperty( gIODTInterruptCellKey
)
370 && (data
= OSDynamicCast( OSData
, regEntry
->getProperty( gIODTPHandleKey
)))) {
371 // a possible interrupt-parent
372 gIODTPHandles
->setObject( data
);
373 gIODTPHandleMap
->setObject( regEntry
);
377 static IORegistryEntry
* FindPHandle( UInt32 phandle
)
380 IORegistryEntry
*regEntry
= 0;
383 for( i
= 0; (data
= (OSData
*)gIODTPHandles
->getObject( i
)); i
++ ) {
384 if( phandle
== *((UInt32
*)data
->getBytesNoCopy())) {
385 regEntry
= (IORegistryEntry
*)
386 gIODTPHandleMap
->getObject( i
);
394 static bool GetUInt32( IORegistryEntry
* regEntry
, const OSSymbol
* name
,
399 if( (data
= OSDynamicCast( OSData
, regEntry
->getProperty( name
)))
400 && (4 == data
->getLength())) {
401 *value
= *((UInt32
*) data
->getBytesNoCopy());
407 IORegistryEntry
* IODTFindInterruptParent( IORegistryEntry
* regEntry
)
409 IORegistryEntry
* parent
;
412 if( GetUInt32( regEntry
, gIODTInterruptParentKey
, &phandle
))
413 parent
= FindPHandle( phandle
);
415 else if( 0 == regEntry
->getProperty( "interrupt-controller"))
416 parent
= regEntry
->getParentEntry( gIODTPlane
);
423 const OSSymbol
* IODTInterruptControllerName( IORegistryEntry
* regEntry
)
430 ok
= GetUInt32( regEntry
, gIODTPHandleKey
, &phandle
);
434 sprintf( buf
, "IOInterruptController%08lX", phandle
);
435 sym
= OSSymbol::withCString( buf
);
442 #define unexpected(a) { kprintf("unexpected %s:%d\n", __FILE__, __LINE__); a; }
444 static void IODTGetICellCounts( IORegistryEntry
* regEntry
,
445 UInt32
* iCellCount
, UInt32
* aCellCount
)
447 if( !GetUInt32( regEntry
, gIODTInterruptCellKey
, iCellCount
))
448 unexpected( *iCellCount
= 1 );
449 if( !GetUInt32( regEntry
, gIODTAddressCellKey
, aCellCount
))
453 UInt32
IODTMapOneInterrupt( IORegistryEntry
* regEntry
, UInt32
* intSpec
,
454 OSData
** spec
, const OSSymbol
** controller
)
456 IORegistryEntry
*parent
= 0;
462 UInt32 acells
, icells
, pacells
, picells
, cell
;
463 UInt32 i
, original_icells
;
464 bool cmp
, ok
= false;
466 parent
= IODTFindInterruptParent( regEntry
);
467 IODTGetICellCounts( parent
, &icells
, &acells
);
470 data
= OSDynamicCast( OSData
, regEntry
->getProperty( "reg" ));
471 if( data
&& (data
->getLength() >= (acells
* sizeof( UInt32
))))
472 addrCmp
= (UInt32
*) data
->getBytesNoCopy();
474 original_icells
= icells
;
479 kprintf ("IODTMapOneInterrupt: current regEntry name %s\n", regEntry
->getName());
480 kprintf ("acells - icells: ");
481 for (i
= 0; i
< acells
; i
++) kprintf ("0x%08X ", addrCmp
[i
]);
483 for (i
= 0; i
< icells
; i
++) kprintf ("0x%08X ", intSpec
[i
]);
487 if( parent
&& (data
= OSDynamicCast( OSData
,
488 regEntry
->getProperty( "interrupt-controller")))) {
489 // found a controller - don't want to follow cascaded controllers
491 *spec
= OSData::withBytesNoCopy( (void *) intSpec
,
492 icells
* sizeof( UInt32
));
493 *controller
= IODTInterruptControllerName( regEntry
);
494 ok
= (*spec
&& *controller
);
495 } else if( parent
&& (data
= OSDynamicCast( OSData
,
496 regEntry
->getProperty( "interrupt-map")))) {
498 map
= (UInt32
*) data
->getBytesNoCopy();
499 endMap
= map
+ (data
->getLength() / sizeof(UInt32
));
500 data
= OSDynamicCast( OSData
, regEntry
->getProperty( "interrupt-map-mask" ));
501 if( data
&& (data
->getLength() >= ((acells
+ icells
) * sizeof( UInt32
))))
502 maskCmp
= (UInt32
*) data
->getBytesNoCopy();
508 kprintf (" maskCmp: ");
509 for (i
= 0; i
< acells
+ icells
; i
++) {
512 kprintf ("0x%08X ", maskCmp
[i
]);
515 kprintf (" masked: ");
516 for (i
= 0; i
< acells
+ icells
; i
++) {
519 kprintf ("0x%08X ", ((i
< acells
) ? addrCmp
[i
] : intSpec
[i
-acells
]) & maskCmp
[i
]);
523 kprintf ("no maskCmp\n");
528 for (i
= 0; i
< acells
+ icells
; i
++) {
531 kprintf ("0x%08X ", map
[i
]);
535 for( i
= 0, cmp
= true; cmp
&& (i
< (acells
+ icells
)); i
++) {
536 cell
= (i
< acells
) ? addrCmp
[i
] : intSpec
[ i
- acells
];
539 cmp
= (cell
== map
[i
]);
542 map
+= acells
+ icells
;
543 if( 0 == (parent
= FindPHandle( *(map
++) )))
546 IODTGetICellCounts( parent
, &picells
, &pacells
);
549 intSpec
= map
+ pacells
;
552 map
+= pacells
+ picells
;
554 } while( !cmp
&& (map
< endMap
) );
560 IODTGetICellCounts( parent
, &icells
, &acells
);
566 return( ok
? original_icells
: 0 );
569 bool IODTMapInterrupts( IORegistryEntry
* regEntry
)
571 IORegistryEntry
*parent
;
578 const OSSymbol
*controller
;
579 OSArray
*controllers
;
583 nw
= (0 == (local
= OSDynamicCast( OSData
,
584 regEntry
->getProperty( gIODTAAPLInterruptsKey
))));
585 if( nw
&& (0 == (local
= OSDynamicCast( OSData
,
586 regEntry
->getProperty( "interrupts")))))
587 return( true ); // nothing to see here
589 if( nw
&& (parent
= regEntry
->getParentEntry( gIODTPlane
))) {
590 // check for bridges on old world
591 if( (local2
= OSDynamicCast( OSData
,
592 parent
->getProperty( gIODTAAPLInterruptsKey
)))) {
598 localBits
= (UInt32
*) local
->getBytesNoCopy();
599 localEnd
= localBits
+ (local
->getLength() / sizeof( UInt32
));
600 mapped
= OSArray::withCapacity( 1 );
601 controllers
= OSArray::withCapacity( 1 );
603 ok
= (mapped
&& controllers
);
607 skip
= IODTMapOneInterrupt( regEntry
, localBits
, &map
, &controller
);
609 IOLog("%s: error mapping interrupt[%d]\n",
610 regEntry
->getName(), mapped
->getCount());
614 map
= OSData::withData( local
, mapped
->getCount() * sizeof( UInt32
),
616 controller
= gIODTDefaultInterruptController
;
617 controller
->retain();
621 mapped
->setObject( map
);
623 controllers
->setObject( (OSObject
*) controller
);
624 controller
->release();
626 } while( localBits
< localEnd
);
628 ok
&= (localBits
== localEnd
);
632 ok
= regEntry
->setProperty( gIOInterruptControllersKey
, controllers
);
633 ok
&= regEntry
->setProperty( gIOInterruptSpecifiersKey
, mapped
);
637 controllers
->release();
648 CompareKey( OSString
* key
,
649 const IORegistryEntry
* table
, const OSSymbol
* propName
)
657 const char *lastName
;
660 const char *result
= 0;
662 if( 0 == (prop
= table
->getProperty( propName
)))
665 if( (data
= OSDynamicCast( OSData
, prop
))) {
666 names
= (const char *) data
->getBytesNoCopy();
667 lastName
= names
+ data
->getLength();
668 } else if( (string
= OSDynamicCast( OSString
, prop
))) {
669 names
= string
->getCStringNoCopy();
670 lastName
= names
+ string
->getLength() + 1;
674 ckey
= key
->getCStringNoCopy();
675 keyLen
= key
->getLength();
676 wild
= ('*' == key
->getChar( keyLen
- 1 ));
679 // for each name in the property
681 matched
= (0 == strncmp( ckey
, names
, keyLen
- 1 ));
683 matched
= (keyLen
== strlen( names
))
684 && (0 == strncmp( ckey
, names
, keyLen
));
689 names
= names
+ strlen( names
) + 1;
691 } while( (names
< lastName
) && (false == matched
));
697 bool IODTCompareNubName( const IORegistryEntry
* regEntry
,
698 OSString
* name
, OSString
** matchingName
)
703 matched
= (0 != (result
= CompareKey( name
, regEntry
, gIODTNameKey
)))
704 || (0 != (result
= CompareKey( name
, regEntry
, gIODTCompatibleKey
)))
705 || (0 != (result
= CompareKey( name
, regEntry
, gIODTTypeKey
)))
706 || (0 != (result
= CompareKey( name
, regEntry
, gIODTModelKey
)));
708 if( result
&& matchingName
)
709 *matchingName
= OSString::withCString( result
);
711 return( result
!= 0 );
714 bool IODTMatchNubWithKeys( IORegistryEntry
* regEntry
,
720 obj
= OSUnserialize( keys
, 0 );
723 result
= regEntry
->compareNames( obj
);
727 else IOLog("Couldn't unserialize %s\n", keys
);
733 OSCollectionIterator
* IODTFindMatchingEntries( IORegistryEntry
* from
,
734 IOOptionBits options
, const char * keys
)
737 IORegistryEntry
*next
;
738 IORegistryIterator
*iter
;
739 OSCollectionIterator
*cIter
;
741 bool minus
= options
& kIODTExclusive
;
744 iter
= IORegistryIterator::iterateOver( from
, gIODTPlane
,
745 (options
& kIODTRecursive
) ? kIORegistryIterateRecursively
: 0 );
752 result
= OSSet::withCapacity( 3 );
757 while( (next
= iter
->getNextObject())) {
759 // Look for existence of a debug property to skip
760 if( next
->getProperty("AAPL,ignore"))
764 cmp
= IODTMatchNubWithKeys( next
, keys
);
765 if( (minus
&& (false == cmp
))
766 || ((false == minus
) && (false != cmp
)) )
767 result
->setObject( next
);
769 result
->setObject( next
);
771 } while( !iter
->isValid());
776 cIter
= OSCollectionIterator::withCollection( result
);
783 struct IODTPersistent
{
784 IODTCompareAddressCellFunc compareFunc
;
785 IODTNVLocationFunc locationFunc
;
788 void IODTSetResolving( IORegistryEntry
* regEntry
,
789 IODTCompareAddressCellFunc compareFunc
,
790 IODTNVLocationFunc locationFunc
)
792 IODTPersistent persist
;
795 persist
.compareFunc
= compareFunc
;
796 persist
.locationFunc
= locationFunc
;
797 prop
= OSData::withBytes( &persist
, sizeof( persist
));
801 regEntry
->setProperty( gIODTPersistKey
, prop
);
806 static SInt32
DefaultCompare( UInt32 cellCount
, UInt32 left
[], UInt32 right
[] )
809 return( left
[ cellCount
] - right
[ cellCount
] );
813 void IODTGetCellCounts( IORegistryEntry
* regEntry
,
814 UInt32
* sizeCount
, UInt32
* addressCount
)
816 if( !GetUInt32( regEntry
, gIODTSizeCellKey
, sizeCount
))
818 if( !GetUInt32( regEntry
, gIODTAddressCellKey
, addressCount
))
823 // Given addr & len cells from our child, find it in our ranges property, then
824 // look in our parent to resolve the base of the range for us.
826 // Range[]: child-addr our-addr child-len
827 // #cells: child ours child
829 bool IODTResolveAddressCell( IORegistryEntry
* regEntry
,
831 IOPhysicalAddress
* phys
, IOPhysicalLength
* len
)
833 IORegistryEntry
*parent
;
835 // cells in addresses at regEntry
836 UInt32 sizeCells
, addressCells
;
837 // cells in addresses below regEntry
838 UInt32 childSizeCells
, childAddressCells
;
840 UInt32 cell
[ 5 ], offset
= 0, length
;
846 IODTPersistent
*persist
;
847 IODTCompareAddressCellFunc compare
;
849 IODTGetCellCounts( regEntry
, &childSizeCells
, &childAddressCells
);
850 childCells
= childAddressCells
+ childSizeCells
;
852 bcopy( cellsIn
, cell
, 4 * childCells
);
853 if( childSizeCells
> 1)
854 *len
= IOPhysical32( cellsIn
[ childAddressCells
],
855 cellsIn
[ childAddressCells
+ 1 ] );
857 *len
= IOPhysical32( 0, cellsIn
[ childAddressCells
] );
860 prop
= OSDynamicCast( OSData
, regEntry
->getProperty( gIODTRangeKey
));
862 /* end of the road */
863 *phys
= IOPhysical32( 0, cell
[ childAddressCells
- 1 ] + offset
);
867 parent
= regEntry
->getParentEntry( gIODTPlane
);
868 IODTGetCellCounts( parent
, &sizeCells
, &addressCells
);
870 if( (length
= prop
->getLength())) {
872 range
= (UInt32
*) prop
->getBytesNoCopy();
873 endRanges
= range
+ (length
/ 4);
875 prop
= (OSData
*) regEntry
->getProperty( gIODTPersistKey
);
877 persist
= (IODTPersistent
*) prop
->getBytesNoCopy();
878 compare
= persist
->compareFunc
;
880 compare
= DefaultCompare
;
884 range
+= (childCells
+ addressCells
) ) {
886 // is cell >= range start?
887 diff
= (*compare
)( childAddressCells
, cell
, range
);
891 // is cell + size <= range end?
892 if( (diff
+ cell
[ childCells
- 1 ])
893 > range
[ childCells
+ addressCells
- 1 ])
901 // Get the physical start of the range from our parent
902 bcopy( range
+ childAddressCells
, cell
, 4 * addressCells
);
903 bzero( cell
+ addressCells
, 4 * sizeCells
);
905 } /* else zero length range => pass thru to parent */
908 childSizeCells
= sizeCells
;
909 childAddressCells
= addressCells
;
910 childCells
= childAddressCells
+ childSizeCells
;
912 } while( ok
&& regEntry
);
918 OSArray
* IODTResolveAddressing( IORegistryEntry
* regEntry
,
919 const char * addressPropertyName
,
920 IODeviceMemory
* parent
)
922 IORegistryEntry
*parentEntry
;
923 OSData
*addressProperty
;
924 UInt32 sizeCells
, addressCells
, cells
;
927 IOPhysicalAddress phys
;
928 IOPhysicalLength len
;
930 IODeviceMemory
*range
;
932 parentEntry
= regEntry
->getParentEntry( gIODTPlane
);
933 addressProperty
= (OSData
*) regEntry
->getProperty( addressPropertyName
);
934 if( (0 == addressProperty
) || (0 == parentEntry
))
937 IODTGetCellCounts( parentEntry
, &sizeCells
, &addressCells
);
941 cells
= sizeCells
+ addressCells
;
942 reg
= (UInt32
*) addressProperty
->getBytesNoCopy();
943 num
= addressProperty
->getLength() / (4 * cells
);
945 array
= OSArray::withCapacity( 1 );
949 for( i
= 0; i
< num
; i
++) {
950 if( IODTResolveAddressCell( parentEntry
, reg
, &phys
, &len
)) {
953 range
= IODeviceMemory::withSubRange( parent
,
954 phys
- parent
->getPhysicalAddress(), len
);
956 range
= IODeviceMemory::withRange( phys
, len
);
958 array
->setObject( range
);
963 regEntry
->setProperty( gIODeviceMemoryKey
, array
);
964 array
->release(); /* ??? */
969 static void IODTGetNVLocation(
970 IORegistryEntry
* parent
,
971 IORegistryEntry
* regEntry
,
972 UInt8
* busNum
, UInt8
* deviceNum
, UInt8
* functionNum
)
976 IODTPersistent
*persist
;
979 prop
= (OSData
*) parent
->getProperty( gIODTPersistKey
);
981 persist
= (IODTPersistent
*) prop
->getBytesNoCopy();
982 (*persist
->locationFunc
)( regEntry
, busNum
, deviceNum
, functionNum
);
984 prop
= (OSData
*) regEntry
->getProperty( "reg" );
987 cell
= (UInt32
*) prop
->getBytesNoCopy();
989 *deviceNum
= 0x1f & (cell
[ 0 ] >> 24);
999 * Try to make the same messed up descriptor as Mac OS
1002 IOReturn
IODTMakeNVDescriptor( IORegistryEntry
* regEntry
,
1003 IONVRAMDescriptor
* hdr
)
1005 IORegistryEntry
*parent
;
1007 UInt32 bridgeDevices
;
1015 for(level
= 0, bridgeDevices
= 0;
1016 (parent
= regEntry
->getParentEntry( gIODTPlane
)) && (level
< 7); level
++ ) {
1018 IODTGetNVLocation( parent
, regEntry
,
1019 &busNum
, &deviceNum
, &functionNum
);
1021 bridgeDevices
|= ((deviceNum
& 0x1f) << ((level
- 1) * 5));
1023 hdr
->busNum
= busNum
;
1024 hdr
->deviceNum
= deviceNum
;
1025 hdr
->functionNum
= functionNum
;
1029 hdr
->bridgeCount
= level
- 2;
1030 hdr
->bridgeDevices
= bridgeDevices
;
1032 return( kIOReturnSuccess
);
1035 OSData
* IODTFindSlotName( IORegistryEntry
* regEntry
, UInt32 deviceNumber
)
1037 IORegistryEntry
*parent
;
1046 data
= (OSData
*) regEntry
->getProperty("AAPL,slot-name");
1049 parent
= regEntry
->getParentEntry( gIODTPlane
);
1052 data
= OSDynamicCast( OSData
, parent
->getProperty("slot-names"));
1055 if( data
->getLength() <= 4)
1058 bits
= (UInt32
*) data
->getBytesNoCopy();
1060 if( (0 == (mask
& (1 << deviceNumber
))))
1063 names
= (char *)(bits
+ 1);
1064 lastName
= names
+ (data
->getLength() - 4);
1066 for( i
= 0; (i
<= deviceNumber
) && (names
< lastName
); i
++ ) {
1068 if( mask
& (1 << i
)) {
1069 if( i
== deviceNumber
) {
1070 data
= OSData::withBytesNoCopy( names
, 1 + strlen( names
));
1072 regEntry
->setProperty("AAPL,slot-name", data
);
1077 names
+= 1 + strlen( names
);