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 * Copyright (c) 1998 Apple Computer, Inc. All rights reserved.
26 * 23 Nov 98 sdouglas, created from IODeviceTreeBus.m, & MacOS exp mgr.
27 * 05 Apr 99 sdouglas, add interrupt mapping.
31 #include <IOKit/IODeviceTreeSupport.h>
32 #include <libkern/c++/OSContainers.h>
33 #include <IOKit/IODeviceMemory.h>
34 #include <IOKit/IOService.h>
35 #include <IOKit/IOCatalogue.h>
37 #include <IOKit/IOLib.h>
38 #include <IOKit/IOKitKeys.h>
40 #include <DeviceTree.h>
42 #include <machine/machine_routines.h>
43 void DTInit( void * data
);
45 int IODTGetLoaderInfo( char *key
, void **infoAddr
, int *infosize
);
46 void IODTFreeLoaderInfo( char *key
, void *infoAddr
, int infoSize
);
49 #include <IOKit/assert.h>
52 const IORegistryPlane
* gIODTPlane
;
54 static OSArray
* gIODTPHandles
;
55 static OSArray
* gIODTPHandleMap
;
57 const OSSymbol
* gIODTNameKey
;
58 const OSSymbol
* gIODTUnitKey
;
59 const OSSymbol
* gIODTCompatibleKey
;
60 const OSSymbol
* gIODTTypeKey
;
61 const OSSymbol
* gIODTModelKey
;
63 const OSSymbol
* gIODTSizeCellKey
;
64 const OSSymbol
* gIODTAddressCellKey
;
65 const OSSymbol
* gIODTRangeKey
;
67 const OSSymbol
* gIODTPersistKey
;
69 const OSSymbol
* gIODTDefaultInterruptController
;
70 const OSSymbol
* gIODTAAPLInterruptsKey
;
71 const OSSymbol
* gIODTPHandleKey
;
72 const OSSymbol
* gIODTInterruptCellKey
;
73 const OSSymbol
* gIODTInterruptParentKey
;
74 const OSSymbol
* gIODTNWInterruptMappingKey
;
77 static IORegistryEntry
* MakeReferenceTable( DTEntry dtEntry
, bool copy
);
78 static void AddPHandle( IORegistryEntry
* regEntry
);
79 static void FreePhysicalMemory( vm_offset_t
* range
);
82 IODeviceTreeAlloc( void * dtTop
)
84 IORegistryEntry
* parent
;
85 IORegistryEntry
* child
;
86 IORegistryIterator
* regIter
;
98 IOLog("IODeviceTreeSupport ");
100 gIODTPlane
= IORegistryEntry::makePlane( kIODeviceTreePlane
);
102 gIODTNameKey
= OSSymbol::withCStringNoCopy( "name" );
103 gIODTUnitKey
= OSSymbol::withCStringNoCopy( "AAPL,unit-string" );
104 gIODTCompatibleKey
= OSSymbol::withCStringNoCopy( "compatible" );
105 gIODTTypeKey
= OSSymbol::withCStringNoCopy( "device_type" );
106 gIODTModelKey
= OSSymbol::withCStringNoCopy( "model" );
107 gIODTSizeCellKey
= OSSymbol::withCStringNoCopy( "#size-cells" );
108 gIODTAddressCellKey
= OSSymbol::withCStringNoCopy( "#address-cells" );
109 gIODTRangeKey
= OSSymbol::withCStringNoCopy( "ranges" );
111 gIODTPersistKey
= OSSymbol::withCStringNoCopy( "IODTPersist" );
113 assert( gIODTPlane
&& gIODTCompatibleKey
114 && gIODTTypeKey
&& gIODTModelKey
115 && gIODTSizeCellKey
&& gIODTAddressCellKey
&& gIODTRangeKey
116 && gIODTPersistKey
);
118 gIODTDefaultInterruptController
119 = OSSymbol::withCStringNoCopy("IOPrimaryInterruptController");
120 gIODTNWInterruptMappingKey
121 = OSSymbol::withCStringNoCopy("IONWInterrupts");
123 gIODTAAPLInterruptsKey
124 = OSSymbol::withCStringNoCopy("AAPL,interrupts");
126 = OSSymbol::withCStringNoCopy("AAPL,phandle");
128 gIODTInterruptParentKey
129 = OSSymbol::withCStringNoCopy("interrupt-parent");
131 gIODTPHandles
= OSArray::withCapacity( 1 );
132 gIODTPHandleMap
= OSArray::withCapacity( 1 );
134 gIODTInterruptCellKey
135 = OSSymbol::withCStringNoCopy("#interrupt-cells");
137 assert( gIODTDefaultInterruptController
&& gIODTNWInterruptMappingKey
138 && gIODTAAPLInterruptsKey
139 && gIODTPHandleKey
&& gIODTInterruptParentKey
140 && gIODTPHandles
&& gIODTPHandleMap
141 && gIODTInterruptCellKey
144 freeDT
= (kSuccess
== DTLookupEntry( 0, "/chosen/memory-map", &mapEntry
))
145 && (kSuccess
== DTGetProperty( mapEntry
,
146 "DeviceTree", (void **) &dtMap
, &propSize
))
147 && ((2 * sizeof( vm_offset_t
)) == propSize
);
149 parent
= MakeReferenceTable( (DTEntry
)dtTop
, freeDT
);
151 stack
= OSArray::withObjects( & (const OSObject
*) parent
, 1, 10 );
152 DTCreateEntryIterator( (DTEntry
)dtTop
, &iter
);
155 parent
= (IORegistryEntry
*)stack
->getObject( stack
->getCount() - 1);
157 stack
->removeObject( stack
->getCount() - 1);
159 while( kSuccess
== DTIterateEntries( iter
, &dtChild
) ) {
161 child
= MakeReferenceTable( dtChild
, freeDT
);
162 child
->attachToParent( parent
, gIODTPlane
);
166 if( kSuccess
== DTEnterEntry( iter
, dtChild
)) {
167 stack
->setObject( parent
);
170 // only registry holds retain
174 } while( stack
->getCount()
175 && (kSuccess
== DTExitEntry( iter
, &dtChild
)));
178 DTDisposeEntryIterator( iter
);
180 // parent is now root of the created tree
182 // make root name first compatible entry (purely cosmetic)
183 if( (prop
= (OSData
*) parent
->getProperty( gIODTCompatibleKey
))) {
184 parent
->setName( parent
->getName(), gIODTPlane
);
185 parent
->setName( (const char *) prop
->getBytesNoCopy() );
188 // attach tree to meta root
189 parent
->attachToParent( IORegistryEntry::getRegistryRoot(), gIODTPlane
);
193 // free original device tree
195 IODTFreeLoaderInfo( "DeviceTree",
196 (void *)dtMap
[0], round_page(dtMap
[1]) );
201 regIter
= IORegistryIterator::iterateOver( gIODTPlane
,
202 kIORegistryIterateRecursively
);
205 while( (child
= regIter
->getNextObject())) {
206 IODTMapInterrupts( child
);
207 if( !intMap
&& child
->getProperty( gIODTInterruptParentKey
))
210 // Look for a "driver,AAPL,MacOSX,PowerPC" property.
211 if( (obj
= child
->getProperty( "driver,AAPL,MacOSX,PowerPC"))) {
212 gIOCatalogue
->addExtensionsFromArchive((OSData
*)obj
);
214 child
->removeProperty( "driver,AAPL,MacOSX,PowerPC");
217 // some gross pruning
218 child
->removeProperty( "lanLib,AAPL,MacOS,PowerPC");
220 if( (obj
= child
->getProperty( "driver,AAPL,MacOS,PowerPC"))) {
222 if( (0 == (prop
= (OSData
*)child
->getProperty( gIODTTypeKey
)))
223 || (strcmp( "display", (char *) prop
->getBytesNoCopy())) ) {
225 child
->removeProperty( "driver,AAPL,MacOS,PowerPC");
233 // set a key in the root to indicate we found NW interrupt mapping
234 parent
->setProperty( gIODTNWInterruptMappingKey
,
235 (OSObject
*) gIODTNWInterruptMappingKey
);
242 int IODTGetLoaderInfo( char *key
, void **infoAddr
, int *infoSize
)
244 IORegistryEntry
*chosen
;
246 unsigned int *propPtr
;
247 unsigned int propSize
;
249 chosen
= IORegistryEntry::fromPath( "/chosen/memory-map", gIODTPlane
);
250 if ( chosen
== 0 ) return -1;
252 propObj
= OSDynamicCast( OSData
, chosen
->getProperty(key
) );
253 if ( propObj
== 0 ) return -1;
255 propSize
= propObj
->getLength();
256 if ( propSize
!= (2 * sizeof(UInt32
)) ) return -1;
258 propPtr
= (unsigned int *)propObj
->getBytesNoCopy();
259 if ( propPtr
== 0 ) return -1;
261 *infoAddr
= (void *)propPtr
[0] ;
262 *infoSize
= (int) propPtr
[1];
267 void IODTFreeLoaderInfo( char *key
, void *infoAddr
, int infoSize
)
269 vm_offset_t range
[2];
270 IORegistryEntry
*chosen
;
272 range
[0] = (vm_offset_t
)infoAddr
;
273 range
[1] = (vm_offset_t
)infoSize
;
274 FreePhysicalMemory( range
);
277 chosen
= IORegistryEntry::fromPath( "/chosen/memory-map", gIODTPlane
);
279 chosen
->removeProperty(key
);
284 static void FreePhysicalMemory( vm_offset_t
* range
)
288 virt
= ml_static_ptovirt( range
[0] );
290 ml_static_mfree( virt
, range
[1] );
294 static IORegistryEntry
*
295 MakeReferenceTable( DTEntry dtEntry
, bool copy
)
297 IORegistryEntry
* regEntry
;
298 OSDictionary
* propTable
;
299 const OSSymbol
* nameKey
;
301 const OSSymbol
* sym
;
302 DTPropertyIterator dtIter
;
307 bool noLocation
= true;
309 regEntry
= new IOService
;
311 if( regEntry
&& (false == regEntry
->init())) {
317 (kSuccess
== DTCreatePropertyIterator( dtEntry
, &dtIter
))) {
319 propTable
= regEntry
->getPropertyTable();
321 while( kSuccess
== DTIterateProperties( dtIter
, &name
)) {
323 if( kSuccess
!= DTGetProperty( dtEntry
, name
, &prop
, &propSize
))
327 nameKey
= OSSymbol::withCString(name
);
328 data
= OSData::withBytes(prop
, propSize
);
330 nameKey
= OSSymbol::withCStringNoCopy(name
);
331 data
= OSData::withBytesNoCopy(prop
, propSize
);
333 assert( nameKey
&& data
);
335 propTable
->setObject( nameKey
, data
);
339 if( nameKey
== gIODTNameKey
) {
341 sym
= OSSymbol::withCString( (const char *) prop
);
343 sym
= OSSymbol::withCStringNoCopy( (const char *) prop
);
344 regEntry
->setName( sym
);
347 } else if( nameKey
== gIODTUnitKey
) {
348 // all OF strings are null terminated... except this one
349 if( propSize
>= (int) sizeof( location
))
350 propSize
= sizeof( location
) - 1;
351 strncpy( location
, (const char *) prop
, propSize
);
352 location
[ propSize
] = 0;
353 regEntry
->setLocation( location
);
354 propTable
->removeObject( gIODTUnitKey
);
357 } else if( noLocation
&& (0 == strcmp( name
, "reg"))) {
358 // default location - override later
359 sprintf( location
, "%lX", *((UInt32
*) prop
) );
360 regEntry
->setLocation( location
);
363 DTDisposePropertyIterator( dtIter
);
369 static void AddPHandle( IORegistryEntry
* regEntry
)
373 if( regEntry
->getProperty( gIODTInterruptCellKey
)
374 && (data
= OSDynamicCast( OSData
, regEntry
->getProperty( gIODTPHandleKey
)))) {
375 // a possible interrupt-parent
376 gIODTPHandles
->setObject( data
);
377 gIODTPHandleMap
->setObject( regEntry
);
381 static IORegistryEntry
* FindPHandle( UInt32 phandle
)
384 IORegistryEntry
* regEntry
= 0;
388 (data
= (OSData
*)gIODTPHandles
->getObject( i
));
390 if( phandle
== *((UInt32
*)data
->getBytesNoCopy())) {
391 regEntry
= (IORegistryEntry
*)
392 gIODTPHandleMap
->getObject( i
);
400 static bool GetUInt32( IORegistryEntry
* regEntry
, const OSSymbol
* name
,
405 if( (data
= OSDynamicCast( OSData
, regEntry
->getProperty( name
)))
406 && (4 == data
->getLength())) {
407 *value
= *((UInt32
*) data
->getBytesNoCopy());
413 IORegistryEntry
* IODTFindInterruptParent( IORegistryEntry
* regEntry
)
415 IORegistryEntry
* parent
;
418 if( GetUInt32( regEntry
, gIODTInterruptParentKey
, &phandle
))
419 parent
= FindPHandle( phandle
);
421 else if( 0 == regEntry
->getProperty( "interrupt-controller"))
422 parent
= regEntry
->getParentEntry( gIODTPlane
);
429 const OSSymbol
* IODTInterruptControllerName( IORegistryEntry
* regEntry
)
431 const OSSymbol
* sym
;
436 ok
= GetUInt32( regEntry
, gIODTPHandleKey
, &phandle
);
440 sprintf( buf
, "IOInterruptController%08lX", phandle
);
441 sym
= OSSymbol::withCString( buf
);
448 #define unexpected(a) { kprintf("unexpected %s:%d\n", __FILE__, __LINE__); a; }
450 static void IODTGetICellCounts( IORegistryEntry
* regEntry
,
451 UInt32
* iCellCount
, UInt32
* aCellCount
)
453 if( !GetUInt32( regEntry
, gIODTInterruptCellKey
, iCellCount
))
454 unexpected( *iCellCount
= 1 );
455 if( !GetUInt32( regEntry
, gIODTAddressCellKey
, aCellCount
))
459 UInt32
IODTMapOneInterrupt( IORegistryEntry
* regEntry
, UInt32
* intSpec
,
460 OSData
** spec
, const OSSymbol
** controller
)
462 IORegistryEntry
* parent
= 0;
468 UInt32 acells
, icells
, pacells
, picells
, cell
;
470 bool cmp
, ok
= false;
473 if( parent
&& (data
= OSDynamicCast( OSData
,
474 regEntry
->getProperty( "interrupt-controller")))) {
475 // found a controller - don't want to follow cascaded controllers
477 *spec
= OSData::withBytesNoCopy( (void *) intSpec
,
478 icells
* sizeof( UInt32
));
479 *controller
= IODTInterruptControllerName( regEntry
);
480 ok
= (*spec
&& *controller
);
482 } else if( parent
&& (data
= OSDynamicCast( OSData
,
483 regEntry
->getProperty( "interrupt-map")))) {
485 map
= (UInt32
*) data
->getBytesNoCopy();
486 endMap
= map
+ (data
->getLength() / sizeof(UInt32
));
487 data
= OSDynamicCast( OSData
, regEntry
->getProperty( "interrupt-map-mask" ));
488 if( data
&& (data
->getLength() >= ((acells
+ icells
) * sizeof( UInt32
))))
489 maskCmp
= (UInt32
*) data
->getBytesNoCopy();
494 for( i
= 0, cmp
= true;
495 cmp
&& (i
< (acells
+ icells
));
497 cell
= (i
< acells
) ? addrCmp
[i
] : intSpec
[ i
- acells
];
500 cmp
= (cell
== map
[i
]);
503 map
+= acells
+ icells
;
504 if( 0 == (parent
= FindPHandle( *(map
++) )))
510 IODTGetICellCounts( parent
, &picells
, &pacells
);
511 map
+= pacells
+ picells
;
514 } while( !cmp
&& (map
< endMap
) );
517 // first time (usually)
518 parent
= IODTFindInterruptParent( regEntry
);
521 IODTGetICellCounts( parent
, &icells
, &acells
);
524 data
= OSDynamicCast( OSData
, regEntry
->getProperty( "reg" ));
525 if( data
&& (data
->getLength() >= (acells
* sizeof( UInt32
))))
526 addrCmp
= (UInt32
*) data
->getBytesNoCopy();
540 bool IODTMapInterrupts( IORegistryEntry
* regEntry
)
542 IORegistryEntry
* parent
;
549 const OSSymbol
* controller
;
550 OSArray
* controllers
;
554 nw
= (0 == (local
= OSDynamicCast( OSData
,
555 regEntry
->getProperty( gIODTAAPLInterruptsKey
))));
557 && (0 == (local
= OSDynamicCast( OSData
,
558 regEntry
->getProperty( "interrupts")))))
559 return( true ); // nothing to see here
561 if( nw
&& (parent
= regEntry
->getParentEntry( gIODTPlane
))) {
562 // check for bridges on old world
563 if( (local2
= OSDynamicCast( OSData
,
564 parent
->getProperty( gIODTAAPLInterruptsKey
)))) {
570 localBits
= (UInt32
*) local
->getBytesNoCopy();
571 localEnd
= localBits
+ (local
->getLength() / sizeof( UInt32
));
572 mapped
= OSArray::withCapacity( 1 );
573 controllers
= OSArray::withCapacity( 1 );
575 ok
= (mapped
&& controllers
);
579 skip
= IODTMapOneInterrupt( regEntry
, localBits
, &map
, &controller
);
581 IOLog("%s: error mapping interrupt[%d]\n",
582 regEntry
->getName(), mapped
->getCount());
586 map
= OSData::withData( local
, mapped
->getCount() * sizeof( UInt32
),
588 controller
= gIODTDefaultInterruptController
;
592 mapped
->setObject( map
);
594 controllers
->setObject( (OSObject
*) controller
);
595 controller
->release();
597 } while( localBits
< localEnd
);
599 ok
&= (localBits
== localEnd
);
603 ok
= regEntry
->setProperty( gIOInterruptControllersKey
, controllers
);
604 ok
&= regEntry
->setProperty( gIOInterruptSpecifiersKey
, mapped
);
608 controllers
->release();
619 CompareKey( OSString
* key
,
620 const IORegistryEntry
* table
, const OSSymbol
* propName
)
628 const char * lastName
;
631 const char * result
= 0;
633 if( 0 == (prop
= table
->getProperty( propName
)))
636 if( (data
= OSDynamicCast( OSData
, prop
))) {
637 names
= (const char *) data
->getBytesNoCopy();
638 lastName
= names
+ data
->getLength();
640 } else if( (string
= OSDynamicCast( OSString
, prop
))) {
641 names
= string
->getCStringNoCopy();
642 lastName
= names
+ string
->getLength() + 1;
647 ckey
= key
->getCStringNoCopy();
648 keyLen
= key
->getLength();
649 wild
= ('*' == key
->getChar( keyLen
- 1 ));
652 // for each name in the property
654 matched
= (0 == strncmp( ckey
, names
, keyLen
- 1 ));
656 matched
= (keyLen
== strlen( names
))
657 && (0 == strncmp( ckey
, names
, keyLen
));
662 names
= names
+ strlen( names
) + 1;
664 } while( (names
< lastName
) && (false == matched
));
670 bool IODTCompareNubName( const IORegistryEntry
* regEntry
,
671 OSString
* name
, OSString
** matchingName
)
676 matched
= (0 != (result
= CompareKey( name
, regEntry
, gIODTNameKey
)))
677 || (0 != (result
= CompareKey( name
, regEntry
, gIODTCompatibleKey
)))
678 || (0 != (result
= CompareKey( name
, regEntry
, gIODTTypeKey
)))
679 || (0 != (result
= CompareKey( name
, regEntry
, gIODTModelKey
)));
681 if( result
&& matchingName
)
682 *matchingName
= OSString::withCString( result
);
684 return( result
!= 0 );
687 bool IODTMatchNubWithKeys( IORegistryEntry
* regEntry
,
693 obj
= OSUnserialize( keys
, 0 );
696 result
= regEntry
->compareNames( obj
);
700 else IOLog("Couldn't unserialize %s\n", keys
);
706 OSCollectionIterator
* IODTFindMatchingEntries( IORegistryEntry
* from
,
707 IOOptionBits options
, const char * keys
)
710 IORegistryEntry
* next
;
711 IORegistryIterator
* iter
;
712 OSCollectionIterator
* cIter
;
714 bool minus
= options
& kIODTExclusive
;
716 result
= OSSet::withCapacity( 3 );
720 iter
= IORegistryIterator::iterateOver( from
, gIODTPlane
,
721 (options
& kIODTRecursive
) ? kIORegistryIterateRecursively
: 0 );
723 while( (next
= iter
->getNextObject())) {
725 // Look for existence of a debug property to skip
726 if( next
->getProperty("AAPL,ignore"))
730 cmp
= IODTMatchNubWithKeys( next
, keys
);
731 if( (minus
&& (false == cmp
))
732 || ((false == minus
) && (false != cmp
)) )
733 result
->setObject( next
);
735 result
->setObject( next
);
740 cIter
= OSCollectionIterator::withCollection( result
);
747 struct IODTPersistent
{
748 IODTCompareAddressCellFunc compareFunc
;
749 IODTNVLocationFunc locationFunc
;
752 void IODTSetResolving( IORegistryEntry
* regEntry
,
753 IODTCompareAddressCellFunc compareFunc
,
754 IODTNVLocationFunc locationFunc
)
756 IODTPersistent persist
;
759 persist
.compareFunc
= compareFunc
;
760 persist
.locationFunc
= locationFunc
;
761 prop
= OSData::withBytes( &persist
, sizeof( persist
));
765 regEntry
->setProperty( gIODTPersistKey
, prop
);
769 static SInt32
DefaultCompare( UInt32 cellCount
, UInt32 left
[], UInt32 right
[] )
772 return( left
[ cellCount
] - right
[ cellCount
] );
776 void IODTGetCellCounts( IORegistryEntry
* regEntry
,
777 UInt32
* sizeCount
, UInt32
* addressCount
)
779 if( !GetUInt32( regEntry
, gIODTSizeCellKey
, sizeCount
))
781 if( !GetUInt32( regEntry
, gIODTAddressCellKey
, addressCount
))
785 // Given addr & len cells from our child, find it in our ranges property, then
786 // look in our parent to resolve the base of the range for us.
788 // Range[]: child-addr our-addr child-len
789 // #cells: child ours child
791 bool IODTResolveAddressCell( IORegistryEntry
* regEntry
,
793 IOPhysicalAddress
* phys
, IOPhysicalLength
* len
)
795 IORegistryEntry
* parent
;
797 // cells in addresses at regEntry
798 UInt32 sizeCells
, addressCells
;
799 // cells in addresses below regEntry
800 UInt32 childSizeCells
, childAddressCells
;
802 UInt32 cell
[ 5 ], offset
= 0, length
;
808 IODTPersistent
* persist
;
809 IODTCompareAddressCellFunc compare
;
811 IODTGetCellCounts( regEntry
, &childSizeCells
, &childAddressCells
);
812 childCells
= childAddressCells
+ childSizeCells
;
814 bcopy( cellsIn
, cell
, 4 * childCells
);
815 if( childSizeCells
> 1)
816 *len
= IOPhysical32( cellsIn
[ childAddressCells
],
817 cellsIn
[ childAddressCells
+ 1 ] );
819 *len
= IOPhysical32( 0, cellsIn
[ childAddressCells
] );
822 prop
= OSDynamicCast( OSData
, regEntry
->getProperty( gIODTRangeKey
));
824 /* end of the road */
825 *phys
= IOPhysical32( 0, cell
[ childAddressCells
- 1 ] + offset
);
829 parent
= regEntry
->getParentEntry( gIODTPlane
);
830 IODTGetCellCounts( parent
, &sizeCells
, &addressCells
);
832 if( (length
= prop
->getLength())) {
834 range
= (UInt32
*) prop
->getBytesNoCopy();
835 endRanges
= range
+ (length
/ 4);
837 prop
= (OSData
*) regEntry
->getProperty( gIODTPersistKey
);
839 persist
= (IODTPersistent
*) prop
->getBytesNoCopy();
840 compare
= persist
->compareFunc
;
842 compare
= DefaultCompare
;
846 range
+= (childCells
+ addressCells
) ) {
848 // is cell >= range start?
849 diff
= (*compare
)( childAddressCells
, cell
, range
);
852 // is cell + size <= range end?
853 if( (diff
+ cell
[ childCells
- 1 ])
854 > range
[ childCells
+ addressCells
- 1 ])
862 // Get the physical start of the range from our parent
863 bcopy( range
+ childAddressCells
, cell
, 4 * addressCells
);
864 bzero( cell
+ addressCells
, 4 * sizeCells
);
866 } /* else zero length range => pass thru to parent */
869 childSizeCells
= sizeCells
;
870 childAddressCells
= addressCells
;
871 childCells
= childAddressCells
+ childSizeCells
;
873 } while( ok
&& regEntry
);
879 OSArray
* IODTResolveAddressing( IORegistryEntry
* regEntry
,
880 const char * addressPropertyName
,
881 IODeviceMemory
* parent
)
883 IORegistryEntry
* parentEntry
;
884 OSData
* addressProperty
;
885 UInt32 sizeCells
, addressCells
, cells
;
888 IOPhysicalAddress phys
;
889 IOPhysicalLength len
;
891 IODeviceMemory
* range
;
893 parentEntry
= regEntry
->getParentEntry( gIODTPlane
);
894 addressProperty
= (OSData
*) regEntry
->getProperty( addressPropertyName
);
895 if( (0 == addressProperty
) || (0 == parentEntry
))
898 IODTGetCellCounts( parentEntry
, &sizeCells
, &addressCells
);
902 cells
= sizeCells
+ addressCells
;
903 reg
= (UInt32
*) addressProperty
->getBytesNoCopy();
904 num
= addressProperty
->getLength() / (4 * cells
);
906 array
= OSArray::withCapacity( 1 );
910 for( i
= 0; i
< num
; i
++) {
912 if( IODTResolveAddressCell( parentEntry
, reg
, &phys
, &len
)) {
916 range
= IODeviceMemory::withSubRange( parent
,
917 phys
- parent
->getPhysicalAddress(), len
);
919 range
= IODeviceMemory::withRange( phys
, len
);
921 array
->setObject( range
);
926 regEntry
->setProperty( gIODeviceMemoryKey
, array
);
927 array
->release(); /* ??? */
932 static void IODTGetNVLocation(
933 IORegistryEntry
* parent
,
934 IORegistryEntry
* regEntry
,
935 UInt8
* busNum
, UInt8
* deviceNum
, UInt8
* functionNum
)
939 IODTPersistent
* persist
;
942 prop
= (OSData
*) parent
->getProperty( gIODTPersistKey
);
944 persist
= (IODTPersistent
*) prop
->getBytesNoCopy();
945 (*persist
->locationFunc
)( regEntry
, busNum
, deviceNum
, functionNum
);
948 prop
= (OSData
*) regEntry
->getProperty( "reg" );
951 cell
= (UInt32
*) prop
->getBytesNoCopy();
953 if( (regHi
& 0xf0000000) != 0xf0000000) {
954 *bus
= 0x03 & (regHi
>> 16);
955 *function
= 0x07 & (regHi
>> 8);
956 *device
= 0x1f & (regHi
>> 11);
959 *deviceNum
= 0x1f & (cell
[ 0 ] >> 24);
968 * Try to make the same messed up descriptor as Mac OS
971 IOReturn
IODTMakeNVDescriptor( IORegistryEntry
* regEntry
,
972 IONVRAMDescriptor
* hdr
)
974 IORegistryEntry
* parent
;
976 UInt32 bridgeDevices
;
985 level
= 0, bridgeDevices
= 0;
986 (parent
= regEntry
->getParentEntry( gIODTPlane
))
990 IODTGetNVLocation( parent
, regEntry
,
991 &busNum
, &deviceNum
, &functionNum
);
993 bridgeDevices
|= ((deviceNum
& 0x1f) << ((level
- 1) * 5));
995 hdr
->busNum
= busNum
;
996 hdr
->deviceNum
= deviceNum
;
997 hdr
->functionNum
= functionNum
;
1001 hdr
->bridgeCount
= level
- 2;
1002 hdr
->bridgeDevices
= bridgeDevices
;
1004 return( kIOReturnSuccess
);
1007 OSData
* IODTFindSlotName( IORegistryEntry
* regEntry
, UInt32 deviceNumber
)
1009 IORegistryEntry
* parent
;
1018 data
= (OSData
*) regEntry
->getProperty("AAPL,slot-name");
1021 parent
= regEntry
->getParentEntry( gIODTPlane
);
1024 data
= OSDynamicCast( OSData
, parent
->getProperty("slot-names"));
1027 if( data
->getLength() <= 4)
1030 bits
= (UInt32
*) data
->getBytesNoCopy();
1032 if( (0 == (mask
& (1 << deviceNumber
))))
1035 names
= (char *)(bits
+ 1);
1036 lastName
= names
+ (data
->getLength() - 4);
1039 (i
<= deviceNumber
) && (names
< lastName
);
1042 if( mask
& (1 << i
)) {
1043 if( i
== deviceNumber
) {
1044 data
= OSData::withBytesNoCopy( names
, 1 + strlen( names
));
1046 regEntry
->setProperty("AAPL,slot-name", data
);
1051 names
+= 1 + strlen( names
);