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 * 12 Nov 98 sdouglas created.
30 #include <IOKit/IORegistryEntry.h>
31 #include <libkern/c++/OSContainers.h>
32 #include <IOKit/IOService.h>
33 #include <IOKit/IOKitKeys.h>
35 #include <IOKit/IOLib.h>
37 #include <IOKit/assert.h>
39 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
41 #define super OSObject
43 OSDefineMetaClassAndStructors(IORegistryEntry
, OSObject
)
45 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
47 static IORegistryEntry
* gRegistryRoot
;
48 static OSDictionary
* gIORegistryPlanes
;
50 const OSSymbol
* gIONameKey
;
51 const OSSymbol
* gIOLocationKey
;
62 class IORegistryPlane
: public OSObject
{
64 friend IORegistryEntry
;
66 OSDeclareAbstractStructors(IORegistryPlane
)
68 const OSSymbol
* nameKey
;
69 const OSSymbol
* keys
[ kNumSetIndex
];
70 const OSSymbol
* pathNameKey
;
71 const OSSymbol
* pathLocationKey
;
75 virtual bool serialize(OSSerialize
*s
) const;
78 OSDefineMetaClassAndStructors(IORegistryPlane
, OSObject
)
81 static IORecursiveLock
* gPropertiesLock
;
82 static SInt32 gIORegistryGenerationCount
;
84 #define UNLOCK s_lock_done( &gIORegistryLock )
85 #define RLOCK s_lock_read( &gIORegistryLock )
86 #define WLOCK s_lock_write( &gIORegistryLock ); \
87 gIORegistryGenerationCount++
90 #define PUNLOCK IORecursiveLockUnlock( gPropertiesLock )
91 #define PLOCK IORecursiveLockLock( gPropertiesLock )
93 #define IOREGSPLITTABLES
95 #ifdef IOREGSPLITTABLES
96 #define registryTable() fRegistryTable
98 #define registryTable() fPropertyTable
101 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
104 decl_simple_lock_data(,interlock
) /* "hardware" interlock field */
105 volatile unsigned int
106 read_count
:16, /* No. of accepted readers */
107 want_upgrade
:1, /* Read-to-write upgrade waiting */
108 want_write
:1, /* Writer is waiting, or
110 waiting
:1, /* Someone is sleeping on lock */
111 can_sleep
:1; /* Can attempts to lock go to sleep? */
114 static struct s_lock_t gIORegistryLock
;
116 /* Time we loop without holding the interlock.
117 * The former is for when we cannot sleep, the latter
118 * for when our thread can go to sleep (loop less)
119 * we shouldn't retake the interlock at all frequently
120 * if we cannot go to sleep, since it interferes with
121 * any other processors. In particular, 100 is too small
122 * a number for powerpc MP systems because of cache
123 * coherency issues and differing lock fetch times between
126 static unsigned int lock_wait_time
[2] = { (unsigned int)-1, 100 } ;
133 (void) memset((void *) l
, 0, sizeof(s_lock_t
));
135 simple_lock_init(&l
->interlock
, 0);
136 l
->want_write
= FALSE
;
137 l
->want_upgrade
= FALSE
;
139 l
->can_sleep
= can_sleep
;
144 register s_lock_t
* l
)
148 simple_lock(&l
->interlock
);
151 * Try to acquire the want_write bit.
153 while (l
->want_write
) {
155 i
= lock_wait_time
[l
->can_sleep
? 1 : 0];
157 simple_unlock(&l
->interlock
);
158 while (--i
!= 0 && l
->want_write
)
160 simple_lock(&l
->interlock
);
163 if (l
->can_sleep
&& l
->want_write
) {
165 thread_sleep_simple_lock((event_t
) l
,
166 simple_lock_addr(l
->interlock
), FALSE
);
167 simple_lock(&l
->interlock
);
170 l
->want_write
= TRUE
;
172 /* Wait for readers (and upgrades) to finish */
174 while ((l
->read_count
!= 0) || l
->want_upgrade
) {
176 i
= lock_wait_time
[l
->can_sleep
? 1 : 0];
178 simple_unlock(&l
->interlock
);
179 while (--i
!= 0 && (l
->read_count
!= 0 ||
182 simple_lock(&l
->interlock
);
185 if (l
->can_sleep
&& (l
->read_count
!= 0 || l
->want_upgrade
)) {
187 thread_sleep_simple_lock((event_t
) l
,
188 simple_lock_addr(l
->interlock
), FALSE
);
189 simple_lock(&l
->interlock
);
193 simple_unlock(&l
->interlock
);
198 register s_lock_t
* l
)
200 boolean_t do_wakeup
= FALSE
;
202 simple_lock(&l
->interlock
);
204 if (l
->read_count
!= 0) {
208 if (l
->want_upgrade
) {
209 l
->want_upgrade
= FALSE
;
212 l
->want_write
= FALSE
;
217 * There is no reason to wakeup a waiting thread
218 * if the read-count is non-zero. Consider:
219 * we must be dropping a read lock
220 * threads are waiting only if one wants a write lock
221 * if there are still readers, they can't proceed
223 if (l
->waiting
&& (l
->read_count
== 0)) {
228 simple_unlock(&l
->interlock
);
231 thread_wakeup((event_t
) l
);
236 register s_lock_t
* l
)
240 simple_lock(&l
->interlock
);
242 while ( l
->want_upgrade
|| ((0 == l
->read_count
) && l
->want_write
)) {
244 i
= lock_wait_time
[l
->can_sleep
? 1 : 0];
247 simple_unlock(&l
->interlock
);
249 (l
->want_upgrade
|| ((0 == l
->read_count
) && l
->want_write
)))
251 simple_lock(&l
->interlock
);
255 (l
->want_upgrade
|| ((0 == l
->read_count
) && l
->want_write
))) {
257 thread_sleep_simple_lock((event_t
) l
,
258 simple_lock_addr(l
->interlock
), FALSE
);
259 simple_lock(&l
->interlock
);
264 simple_unlock(&l
->interlock
);
268 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
270 IORegistryEntry
* IORegistryEntry::initialize( void )
274 if( !gRegistryRoot
) {
276 s_lock_init( &gIORegistryLock
, true );
277 gRegistryRoot
= new IORegistryEntry
;
278 gPropertiesLock
= IORecursiveLockAlloc();
279 gIORegistryPlanes
= OSDictionary::withCapacity( 1 );
281 assert( gRegistryRoot
&& gPropertiesLock
282 && gIORegistryPlanes
);
283 ok
= gRegistryRoot
->init();
285 gIONameKey
= OSSymbol::withCStringNoCopy( "IOName" );
286 gIOLocationKey
= OSSymbol::withCStringNoCopy( "IOLocation" );
288 assert( ok
&& gIONameKey
&& gIOLocationKey
);
290 gRegistryRoot
->setName( "Root" );
291 gRegistryRoot
->setProperty( kIORegistryPlanesKey
, gIORegistryPlanes
);
294 return( gRegistryRoot
);
297 IORegistryEntry
* IORegistryEntry::getRegistryRoot( void )
299 return( gRegistryRoot
);
302 SInt32
IORegistryEntry::getGenerationCount( void )
304 return( gIORegistryGenerationCount
);
308 const IORegistryPlane
* IORegistryEntry::makePlane( const char * name
)
310 IORegistryPlane
* plane
;
311 const OSSymbol
* nameKey
;
312 const OSSymbol
* parentKey
;
313 const OSSymbol
* childKey
;
314 const OSSymbol
* pathNameKey
;
315 const OSSymbol
* pathLocationKey
;
316 char key
[ kIOMaxPlaneName
+ 16 ];
319 strncpy( key
, name
, kIOMaxPlaneName
);
320 key
[ kIOMaxPlaneName
] = 0;
321 end
= key
+ strlen( name
);
323 nameKey
= OSSymbol::withCString( key
);
325 strcpy( end
, "ParentLinks" );
326 parentKey
= OSSymbol::withCString( key
);
328 strcpy( end
, "ChildLinks" );
329 childKey
= OSSymbol::withCString( key
);
331 strcpy( end
, "Name" );
332 pathNameKey
= OSSymbol::withCString( key
);
334 strcpy( end
, "Location" );
335 pathLocationKey
= OSSymbol::withCString( key
);
337 plane
= new IORegistryPlane
;
339 if( plane
&& plane
->init()
340 && nameKey
&& parentKey
&& childKey
341 && pathNameKey
&& pathLocationKey
) {
343 plane
->nameKey
= nameKey
;
344 plane
->keys
[ kParentSetIndex
] = parentKey
;
345 plane
->keys
[ kChildSetIndex
] = childKey
;
346 plane
->pathNameKey
= pathNameKey
;
347 plane
->pathLocationKey
= pathLocationKey
;
350 gIORegistryPlanes
->setObject( nameKey
, plane
);
358 pathLocationKey
->release();
360 pathNameKey
->release();
362 parentKey
->release();
373 const IORegistryPlane
* IORegistryEntry::getPlane( const char * name
)
375 const IORegistryPlane
* plane
;
378 plane
= (const IORegistryPlane
*) gIORegistryPlanes
->getObject( name
);
384 bool IORegistryPlane::serialize(OSSerialize
*s
) const
386 return( nameKey
->serialize(s
) );
389 enum { kIORegCapacityIncrement
= 4 };
391 bool IORegistryEntry::init( OSDictionary
* dict
= 0 )
400 fPropertyTable
= dict
;
403 fPropertyTable
= OSDictionary::withCapacity( kIORegCapacityIncrement
);
405 fPropertyTable
->setCapacityIncrement( kIORegCapacityIncrement
);
411 #ifdef IOREGSPLITTABLES
412 fRegistryTable
= OSDictionary::withCapacity( kIORegCapacityIncrement
);
414 fRegistryTable
->setCapacityIncrement( kIORegCapacityIncrement
);
416 if( (prop
= OSDynamicCast( OSString
, getProperty( gIONameKey
)))) {
417 OSSymbol
* sym
= (OSSymbol
*)OSSymbol::withString( prop
);
418 // ok for OSSymbol too
423 #endif /* IOREGSPLITTABLES */
428 bool IORegistryEntry::init( IORegistryEntry
* old
,
429 const IORegistryPlane
* plane
)
432 IORegistryEntry
* next
;
440 fPropertyTable
= old
->getPropertyTable();
441 old
->fPropertyTable
= 0;
442 #ifdef IOREGSPLITTABLES
443 fRegistryTable
= old
->fRegistryTable
;
444 old
->fRegistryTable
= 0;
445 #endif /* IOREGSPLITTABLES */
447 all
= getParentSetReference( plane
);
448 if( all
) for( index
= 0;
449 (next
= (IORegistryEntry
*) all
->getObject(index
));
451 next
->makeLink( this, kChildSetIndex
, plane
);
452 next
->breakLink( old
, kChildSetIndex
, plane
);
455 all
= getChildSetReference( plane
);
456 if( all
) for( index
= 0;
457 (next
= (IORegistryEntry
*) all
->getObject(index
));
459 next
->makeLink( this, kParentSetIndex
, plane
);
460 next
->breakLink( old
, kParentSetIndex
, plane
);
468 void IORegistryEntry::free( void )
473 const OSSymbol
* key
;
474 const IORegistryPlane
* plane
;
475 OSCollectionIterator
* iter
;
477 if( registryTable()) {
478 iter
= OSCollectionIterator::withCollection( gIORegistryPlanes
);
480 while( (key
= (const OSSymbol
*) iter
->getNextObject())) {
481 if( 0 == (plane
= (const IORegistryPlane
*)
482 OSDynamicCast( IORegistryPlane
,
483 gIORegistryPlanes
->getObject( key
))))
485 if( (links
= getParentSetReference( plane
))
486 || (links
= getChildSetReference( plane
)) ) {
488 IOLog("%s: Still attached in %s at free()\n",
489 getName(), plane
->nameKey
->getCStringNoCopy());
497 if( getPropertyTable())
498 getPropertyTable()->release();
500 #ifdef IOREGSPLITTABLES
502 registryTable()->release();
503 #endif /* IOREGSPLITTABLES */
508 void IORegistryEntry::setPropertyTable( OSDictionary
* dict
)
511 fPropertyTable
->release();
514 fPropertyTable
= dict
;
517 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
519 /* Wrappers to synchronize property table */
521 #define wrap1(func,type,constant) \
523 IORegistryEntry::func ## Property( type * aKey) constant \
528 obj = getPropertyTable()->func ## Object( aKey ); \
534 #define wrap2(type,constant) \
536 IORegistryEntry::copyProperty( type * aKey) constant \
541 obj = getPropertyTable()->getObject( aKey ); \
549 #define wrap3(func,type,constant) \
551 IORegistryEntry::func ## Property( type * aKey) constant \
554 getPropertyTable()->func ## Object( aKey ); \
558 #define wrap4(type,constant) \
560 IORegistryEntry::getProperty( type * aKey, \
561 const IORegistryPlane * plane, \
562 IOOptionBits options ) constant \
564 OSObject * obj = getProperty( aKey ); \
566 if ( (0 == obj) && (options & kIORegistryIterateRecursively) ) { \
567 IORegistryEntry * entry = (IORegistryEntry *) this; \
568 IORegistryIterator * iter; \
569 iter = IORegistryIterator::iterateOver( entry, plane, options ); \
571 while ( (0 == obj) && (entry = iter->getNextObject()) ) { \
572 obj = entry->getProperty( aKey ); \
580 bool IORegistryEntry::serializeProperties( OSSerialize
* s
) const
584 // setProperty( getRetainCount(), 32, "__retain" );
587 ok
= getPropertyTable()->serialize( s
);
593 OSDictionary
* IORegistryEntry::dictionaryWithProperties( void ) const
598 dict
= OSDictionary::withDictionary( getPropertyTable(),
599 getPropertyTable()->getCapacity() );
605 IOReturn
IORegistryEntry::setProperties( OSObject
* properties
)
607 return( kIOReturnUnsupported
);
610 wrap1(get
, const OSSymbol
, const) // getProperty() definition
611 wrap1(get
, const OSString
, const) // getProperty() definition
612 wrap1(get
, const char, const) // getProperty() definition
614 wrap2(const OSSymbol
, const) // copyProperty() definition
615 wrap2(const OSString
, const) // copyProperty() definition
616 wrap2(const char, const) // copyProperty() definition
618 wrap3(remove
, const OSSymbol
,) // removeProperty() definition
619 wrap3(remove
, const OSString
,) // removeProperty() definition
620 wrap3(remove
, const char,) // removeProperty() definition
622 wrap4(const OSSymbol
, const) // getProperty() w/plane definition
623 wrap4(const OSString
, const) // getProperty() w/plane definition
624 wrap4(const char, const) // getProperty() w/plane definition
627 IORegistryEntry::setProperty( const OSSymbol
* aKey
, OSObject
* anObject
)
631 ret
= getPropertyTable()->setObject( aKey
, anObject
);
638 IORegistryEntry::setProperty( const OSString
* aKey
, OSObject
* anObject
)
642 ret
= getPropertyTable()->setObject( aKey
, anObject
);
649 IORegistryEntry::setProperty( const char * aKey
, OSObject
* anObject
)
653 ret
= getPropertyTable()->setObject( aKey
, anObject
);
660 IORegistryEntry::setProperty(const char * aKey
, const char * aString
)
663 OSSymbol
* aSymbol
= (OSSymbol
*) OSSymbol::withCString( aString
);
667 ret
= getPropertyTable()->setObject( aKey
, aSymbol
);
675 IORegistryEntry::setProperty(const char * aKey
, bool aBoolean
)
678 OSBoolean
* aBooleanObj
= OSBoolean::withBoolean( aBoolean
);
682 ret
= getPropertyTable()->setObject( aKey
, aBooleanObj
);
684 aBooleanObj
->release();
690 IORegistryEntry::setProperty( const char * aKey
,
691 unsigned long long aValue
,
692 unsigned int aNumberOfBits
)
695 OSNumber
* anOffset
= OSNumber::withNumber( aValue
, aNumberOfBits
);
699 ret
= getPropertyTable()->setObject( aKey
, anOffset
);
707 IORegistryEntry::setProperty( const char * aKey
,
712 OSData
* data
= OSData::withBytes( bytes
, length
);
716 ret
= getPropertyTable()->setObject( aKey
, data
);
723 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
725 /* Name, location, paths */
727 const char * IORegistryEntry::getName( const IORegistryPlane
* plane
= 0 ) const
733 sym
= (OSSymbol
*) registryTable()->getObject( plane
->pathNameKey
);
735 sym
= (OSSymbol
*) registryTable()->getObject( gIONameKey
);
739 return( sym
->getCStringNoCopy());
741 return( (getMetaClass())->getClassName());
744 const OSSymbol
* IORegistryEntry::copyName(
745 const IORegistryPlane
* plane
= 0 ) const
751 sym
= (OSSymbol
*) registryTable()->getObject( plane
->pathNameKey
);
753 sym
= (OSSymbol
*) registryTable()->getObject( gIONameKey
);
761 return( OSSymbol::withCString((getMetaClass())->getClassName()) );
764 const OSSymbol
* IORegistryEntry::copyLocation(
765 const IORegistryPlane
* plane
= 0 ) const
771 sym
= (OSSymbol
*) registryTable()->getObject( plane
->pathLocationKey
);
773 sym
= (OSSymbol
*) registryTable()->getObject( gIOLocationKey
);
781 const char * IORegistryEntry::getLocation( const IORegistryPlane
* plane
= 0 ) const
783 const OSSymbol
* sym
= copyLocation( plane
);
784 const char * result
= 0;
787 result
= sym
->getCStringNoCopy();
794 void IORegistryEntry::setName( const OSSymbol
* name
,
795 const IORegistryPlane
* plane
= 0 )
797 const OSSymbol
* key
;
801 key
= plane
->pathNameKey
;
806 registryTable()->setObject( key
, (OSObject
*) name
);
811 void IORegistryEntry::setName( const char * name
,
812 const IORegistryPlane
* plane
= 0 )
814 OSSymbol
* sym
= (OSSymbol
*)OSSymbol::withCString( name
);
816 setName( sym
, plane
);
821 void IORegistryEntry::setLocation( const OSSymbol
* location
,
822 const IORegistryPlane
* plane
= 0 )
824 const OSSymbol
* key
;
828 key
= plane
->pathLocationKey
;
830 key
= gIOLocationKey
;
833 registryTable()->setObject( key
, (OSObject
*) location
);
838 void IORegistryEntry::setLocation( const char * location
,
839 const IORegistryPlane
* plane
= 0 )
841 OSSymbol
* sym
= (OSSymbol
*)OSSymbol::withCString( location
);
843 setLocation( sym
, plane
);
849 IORegistryEntry::compareName( OSString
* name
, OSString
** matched
= 0 ) const
851 const OSSymbol
* sym
= copyName();
854 isEqual
= sym
->isEqualTo( name
);
856 if( isEqual
&& matched
) {
868 IORegistryEntry::compareNames( OSObject
* names
, OSString
** matched
= 0 ) const
871 OSCollection
* collection
;
872 OSIterator
* iter
= 0;
875 if( (collection
= OSDynamicCast( OSCollection
, names
))) {
876 iter
= OSCollectionIterator::withCollection( collection
);
879 string
= OSDynamicCast( OSString
, names
);
883 result
= compareName( string
, matched
);
885 } while( (false == result
)
886 && iter
&& (string
= OSDynamicCast( OSString
, iter
->getNextObject())));
895 bool IORegistryEntry::getPath( char * path
, int * length
,
896 const IORegistryPlane
* plane
) const
899 IORegistryEntry
* root
;
900 const IORegistryEntry
* entry
;
901 IORegistryEntry
* parent
;
902 const OSSymbol
* alias
;
904 int len
, maxLength
, compLen
;
908 if( !path
|| !length
|| !plane
)
912 maxLength
= *length
- 2;
915 len
= plane
->nameKey
->getLength();
916 if( len
>= maxLength
)
918 strcpy( nextComp
, plane
->nameKey
->getCStringNoCopy());
919 nextComp
[ len
++ ] = ':';
922 if( (alias
= hasAlias( plane
))) {
923 len
+= alias
->getLength();
924 ok
= (maxLength
> len
);
927 strcpy( nextComp
, alias
->getCStringNoCopy());
932 parent
= entry
->getParentEntry( plane
);
934 // Error if not attached in plane
937 stack
= OSArray::withCapacity( getDepth( plane
));
943 root
= gRegistryRoot
->getChildEntry( plane
);
944 while( parent
&& (entry
!= root
)) {
946 stack
->setObject( (OSObject
*) entry
);
948 parent
= entry
->getParentEntry( plane
);
951 index
= stack
->getCount();
960 } else while( ok
&& ((--index
) >= 0)) {
962 entry
= (IORegistryEntry
*) stack
->getObject((unsigned int) index
);
965 if( (alias
= entry
->hasAlias( plane
))) {
966 len
= plane
->nameKey
->getLength() + 1;
967 nextComp
= path
+ len
;
969 compLen
= alias
->getLength();
970 ok
= (maxLength
> len
+ compLen
);
972 strcpy( nextComp
, alias
->getCStringNoCopy());
974 compLen
= maxLength
- len
;
975 ok
= entry
->getPathComponent( nextComp
+ 1, &compLen
, plane
);
997 bool IORegistryEntry::getPathComponent( char * path
, int * length
,
998 const IORegistryPlane
* plane
) const
1000 int len
, locLen
, maxLength
;
1001 const char * compName
;
1005 maxLength
= *length
;
1007 compName
= getName( plane
);
1008 len
= strlen( compName
);
1009 if( (loc
= getLocation( plane
)))
1010 locLen
= 1 + strlen( loc
);
1014 ok
= ((len
+ locLen
) < maxLength
);
1016 strcpy( path
, compName
);
1021 strcpy( path
, loc
);
1029 const char * IORegistryEntry::matchPathLocation( const char * cmp
,
1030 const IORegistryPlane
* plane
)
1033 const char * result
= 0;
1037 str
= getLocation( plane
);
1041 num1
= strtoul( cmp
, (char **) &cmp
, 16 );
1043 num2
= strtoul( str
, (char **) &str
, 16 );
1053 if( (c2
== ':') && (c2
== c1
)) {
1075 IORegistryEntry
* IORegistryEntry::getChildFromComponent( const char ** opath
,
1076 const IORegistryPlane
* plane
)
1078 IORegistryEntry
* entry
= 0;
1082 const char * cmp
= 0;
1086 set
= getChildSetReference( plane
);
1092 (entry
= (IORegistryEntry
*) set
->getObject(index
));
1098 str
= entry
->getName( plane
);
1099 len
= strlen( str
);
1100 if( strncmp( str
, cmp
, len
))
1107 if( (cmp
= entry
->matchPathLocation( cmp
, plane
)))
1117 const OSSymbol
* IORegistryEntry::hasAlias( const IORegistryPlane
* plane
,
1118 char * opath
= 0, int * length
= 0 ) const
1120 IORegistryEntry
* entry
;
1121 IORegistryEntry
* entry2
;
1122 const OSSymbol
* key
;
1123 const OSSymbol
* bestKey
= 0;
1126 const char * path
= "/aliases";
1128 entry
= IORegistryEntry::fromPath( path
, plane
);
1131 if( (iter
= OSCollectionIterator::withCollection(
1132 entry
->getPropertyTable() ))) {
1134 while( (key
= (OSSymbol
*) iter
->getNextObject())) {
1136 data
= (OSData
*) entry
->getProperty( key
);
1137 path
= (const char *) data
->getBytesNoCopy();
1138 if( (entry2
= IORegistryEntry::fromPath( path
, plane
,
1140 if( this == entry2
) {
1142 || (bestKey
->getLength() > key
->getLength()))
1143 // pick the smallest alias
1157 const char * IORegistryEntry::dealiasPath(
1158 const char ** opath
,
1159 const IORegistryPlane
* plane
)
1161 IORegistryEntry
* entry
;
1163 const char * path
= *opath
;
1164 const char * rpath
= 0;
1167 char temp
[ kIOMaxPlaneName
+ 1 ];
1174 while( (c
= *end
++) && (c
!= '/') && (c
!= ':'))
1177 if( (end
- path
) < kIOMaxPlaneName
) {
1178 strncpy( temp
, path
, end
- path
);
1179 temp
[ end
- path
] = 0;
1182 entry
= IORegistryEntry::fromPath( "/aliases", plane
);
1184 data
= (OSData
*) entry
->getProperty( temp
);
1186 rpath
= (const char *) data
->getBytesNoCopy();
1198 IORegistryEntry
* IORegistryEntry::fromPath(
1200 const IORegistryPlane
* plane
= 0,
1203 IORegistryEntry
* fromEntry
= 0 )
1205 IORegistryEntry
* where
= 0;
1206 IORegistryEntry
* next
;
1212 char temp
[ kIOMaxPlaneName
+ 1 ];
1219 end
= strchr( path
, ':' );
1220 if( end
&& ((end
- path
) < kIOMaxPlaneName
)) {
1221 strncpy( temp
, path
, end
- path
);
1222 temp
[ end
- path
] = 0;
1223 plane
= getPlane( temp
);
1232 if( (alias
= dealiasPath( &end
, plane
))) {
1235 where
= IORegistryEntry::fromPath( alias
, plane
,
1236 opath
, &len
, fromEntry
);
1247 if( (0 == fromEntry
) && (*path
++ == '/'))
1248 fromEntry
= gRegistryRoot
->getChildEntry( plane
);
1255 if( c
&& (c
!= ':')) // check valid terminator
1260 next
= where
->getChildFromComponent( &path
, plane
);
1266 // check residual path
1267 if( where
!= fromEntry
)
1270 if( opath
&& length
) {
1271 // copy out residual path
1272 len2
= len
+ strlen( path
);
1274 strcpy( opath
+ len
, path
);
1278 // no residual path => must be no tail for success
1290 IORegistryEntry
* IORegistryEntry::childFromPath(
1292 const IORegistryPlane
* plane
= 0,
1296 return( IORegistryEntry::fromPath( path
, plane
, opath
, len
, this ));
1299 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1301 #define IOLinkIterator OSCollectionIterator
1304 #define super OSObject
1306 inline bool IORegistryEntry::arrayMember( OSArray
* set
,
1307 const IORegistryEntry
* member
,
1308 unsigned int * index
= 0 ) const
1311 OSObject
* probeObject
;
1313 for( i
= 0; (probeObject
= set
->getObject(i
)); i
++) {
1314 if (probeObject
== (OSObject
*) member
) {
1323 bool IORegistryEntry::makeLink( IORegistryEntry
* to
,
1324 unsigned int relation
,
1325 const IORegistryPlane
* plane
) const
1328 bool result
= false;
1330 if( (links
= (OSArray
*)
1331 registryTable()->getObject( plane
->keys
[ relation
] ))) {
1333 result
= arrayMember( links
, to
);
1335 result
= links
->setObject( to
);
1339 links
= OSArray::withObjects( & (const OSObject
*) to
, 1, 1 );
1340 result
= (links
!= 0);
1342 result
= registryTable()->setObject( plane
->keys
[ relation
],
1351 void IORegistryEntry::breakLink( IORegistryEntry
* to
,
1352 unsigned int relation
,
1353 const IORegistryPlane
* plane
) const
1358 if( (links
= (OSArray
*)
1359 registryTable()->getObject( plane
->keys
[ relation
]))) {
1361 if( arrayMember( links
, to
, &index
)) {
1362 links
->removeObject( index
);
1363 if( 0 == links
->getCount())
1364 registryTable()->removeObject( plane
->keys
[ relation
]);
1370 OSArray
* IORegistryEntry::getParentSetReference(
1371 const IORegistryPlane
* plane
) const
1374 return( (OSArray
*) registryTable()->getObject(
1375 plane
->keys
[ kParentSetIndex
]));
1380 OSIterator
* IORegistryEntry::getParentIterator(
1381 const IORegistryPlane
* plane
) const
1390 links
= getParentSetReference( plane
);
1392 links
= OSArray::withCapacity( 1 );
1394 links
= OSArray::withArray( links
, links
->getCount() );
1397 iter
= IOLinkIterator::withCollection( links
);
1405 IORegistryEntry
* IORegistryEntry::getParentEntry( const IORegistryPlane
* plane
) const
1407 IORegistryEntry
* entry
= 0;
1412 if( (links
= getParentSetReference( plane
)))
1413 entry
= (IORegistryEntry
*) links
->getObject( 0 );
1420 OSArray
* IORegistryEntry::getChildSetReference( const IORegistryPlane
* plane
) const
1423 return( (OSArray
*) registryTable()->getObject(
1424 plane
->keys
[ kChildSetIndex
]));
1429 OSIterator
* IORegistryEntry::getChildIterator( const IORegistryPlane
* plane
) const
1438 links
= getChildSetReference( plane
);
1440 links
= OSArray::withCapacity( 1 );
1442 links
= OSArray::withArray( links
, links
->getCount() );
1445 iter
= IOLinkIterator::withCollection( links
);
1454 IORegistryEntry
* IORegistryEntry::getChildEntry(
1455 const IORegistryPlane
* plane
) const
1457 IORegistryEntry
* entry
= 0;
1462 if( (links
= getChildSetReference( plane
)))
1463 entry
= (IORegistryEntry
*) links
->getObject( 0 );
1470 void IORegistryEntry::applyToChildren( IORegistryEntryApplierFunction applier
,
1472 const IORegistryPlane
* plane
) const
1476 IORegistryEntry
* next
;
1482 array
= OSArray::withArray( getChildSetReference( plane
));
1486 (next
= (IORegistryEntry
*) array
->getObject( index
));
1488 (*applier
)(next
, context
);
1493 void IORegistryEntry::applyToParents( IORegistryEntryApplierFunction applier
,
1495 const IORegistryPlane
* plane
) const
1499 IORegistryEntry
* next
;
1505 array
= OSArray::withArray( getParentSetReference( plane
));
1509 (next
= (IORegistryEntry
*) array
->getObject( index
));
1511 (*applier
)(next
, context
);
1516 bool IORegistryEntry::isChild( IORegistryEntry
* child
,
1517 const IORegistryPlane
* plane
,
1518 bool onlyChild
= false ) const
1525 if( (links
= getChildSetReference( plane
))) {
1526 if( (!onlyChild
) || (1 == links
->getCount()))
1527 ret
= arrayMember( links
, child
);
1529 if( ret
&& (links
= child
->getParentSetReference( plane
)))
1530 ret
= arrayMember( links
, this );
1537 bool IORegistryEntry::isParent( IORegistryEntry
* parent
,
1538 const IORegistryPlane
* plane
,
1539 bool onlyParent
= false ) const
1547 if( (links
= getParentSetReference( plane
))) {
1548 if( (!onlyParent
) || (1 == links
->getCount()))
1549 ret
= arrayMember( links
, parent
);
1551 if( ret
&& (links
= parent
->getChildSetReference( plane
)))
1552 ret
= arrayMember( links
, this );
1559 bool IORegistryEntry::inPlane( const IORegistryPlane
* plane
) const
1565 ret
= (0 != getParentSetReference( plane
));
1572 bool IORegistryEntry::attachToParent( IORegistryEntry
* parent
,
1573 const IORegistryPlane
* plane
)
1584 ret
= makeLink( parent
, kParentSetIndex
, plane
);
1586 if( (links
= parent
->getChildSetReference( plane
)))
1587 needParent
= (false == arrayMember( links
, this ));
1591 // ret &= parent->makeLink( this, kChildSetIndex, plane );
1596 ret
&= parent
->attachToChild( this, plane
);
1601 bool IORegistryEntry::attachToChild( IORegistryEntry
* child
,
1602 const IORegistryPlane
* plane
)
1613 ret
= makeLink( child
, kChildSetIndex
, plane
);
1615 if( (links
= child
->getParentSetReference( plane
)))
1616 needChild
= (false == arrayMember( links
, this ));
1623 ret
&= child
->attachToParent( this, plane
);
1628 void IORegistryEntry::detachFromParent( IORegistryEntry
* parent
,
1629 const IORegistryPlane
* plane
)
1638 breakLink( parent
, kParentSetIndex
, plane
);
1640 if( (links
= parent
->getChildSetReference( plane
)))
1641 needParent
= arrayMember( links
, this );
1645 // parent->breakLink( this, kChildSetIndex, plane );
1650 parent
->detachFromChild( this, plane
);
1655 void IORegistryEntry::detachFromChild( IORegistryEntry
* child
,
1656 const IORegistryPlane
* plane
)
1665 breakLink( child
, kChildSetIndex
, plane
);
1667 if( (links
= child
->getParentSetReference( plane
)))
1668 needChild
= arrayMember( links
, this );
1675 child
->detachFromParent( this, plane
);
1680 void IORegistryEntry::detachAbove( const IORegistryPlane
* plane
)
1682 IORegistryEntry
* parent
;
1685 while( (parent
= getParentEntry( plane
)))
1686 detachFromParent( parent
, plane
);
1690 void IORegistryEntry::detachAll( const IORegistryPlane
* plane
)
1693 IORegistryEntry
* next
;
1694 IORegistryIterator
* regIter
;
1696 regIter
= IORegistryIterator::iterateOver( this, plane
, true );
1699 all
= regIter
->iterateAll();
1702 detachAbove( plane
);
1704 while( (next
= (IORegistryEntry
*) all
->getLastObject())) {
1707 all
->removeObject(next
);
1709 next
->detachAbove( plane
);
1716 unsigned int IORegistryEntry::getDepth( const IORegistryPlane
* plane
) const
1718 unsigned int depth
= 1;
1720 unsigned int oneDepth
, maxParentDepth
, count
;
1721 IORegistryEntry
* one
;
1722 const IORegistryEntry
* next
;
1728 while( (parents
= next
->getParentSetReference( plane
))) {
1730 count
= parents
->getCount();
1735 next
= (IORegistryEntry
*) parents
->getObject( 0 );
1740 (one
= (IORegistryEntry
*) parents
->getObject( index
));
1742 oneDepth
= one
->getDepth( plane
);
1743 if( oneDepth
> maxParentDepth
)
1744 maxParentDepth
= oneDepth
;
1746 depth
+= maxParentDepth
;
1756 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1759 #define super OSIterator
1761 OSDefineMetaClassAndStructors(IORegistryIterator
, OSIterator
)
1763 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1765 IORegistryIterator
*
1766 IORegistryIterator::iterateOver( IORegistryEntry
* root
,
1767 const IORegistryPlane
* plane
,
1768 IOOptionBits options
= 0 )
1770 IORegistryIterator
* create
;
1777 create
= new IORegistryIterator
;
1779 if( create
->init()) {
1782 create
->root
= root
;
1783 create
->where
= &create
->start
;
1784 create
->start
.current
= root
;
1785 create
->plane
= plane
;
1786 create
->options
= options
;
1796 IORegistryIterator
*
1797 IORegistryIterator::iterateOver( const IORegistryPlane
* plane
,
1798 IOOptionBits options
= 0 )
1800 return( iterateOver( gRegistryRoot
, plane
, options
));
1803 bool IORegistryIterator::isValid( void )
1812 while( ok
&& next
) {
1814 ok
= where
->iter
->isValid();
1822 void IORegistryIterator::enterEntry( const IORegistryPlane
* enterPlane
)
1827 where
= (IORegCursor
*) IOMalloc( sizeof( IORegCursor
));
1833 where
->current
= prev
->current
;
1838 void IORegistryIterator::enterEntry( void )
1840 enterEntry( plane
);
1843 bool IORegistryIterator::exitEntry( void )
1848 where
->iter
->release();
1850 if( where
->current
)// && (where != &start))
1851 where
->current
->release();
1854 if( where
!= &start
) {
1857 IOFree( gone
, sizeof( IORegCursor
));
1864 void IORegistryIterator::reset( void )
1874 where
->current
= root
;
1877 void IORegistryIterator::free( void )
1888 IORegistryEntry
* IORegistryIterator::getNextObjectFlat( void )
1890 IORegistryEntry
* next
= 0;
1891 OSArray
* links
= 0;
1895 if( (0 == where
->iter
)) {
1896 // just entered - create new iter
1899 && (links
= ( (options
& kIORegistryIterateParents
) ?
1900 where
->current
->getParentSetReference( plane
) :
1901 where
->current
->getChildSetReference( plane
) )) )
1903 where
->iter
= OSCollectionIterator::withCollection( links
);
1906 // next sibling - release current
1908 where
->current
->release();
1911 next
= (IORegistryEntry
*) where
->iter
->getNextObject();
1916 where
->current
= next
;
1923 IORegistryEntry
* IORegistryIterator::getNextObjectRecursive( void )
1925 IORegistryEntry
* next
;
1928 next
= getNextObjectFlat();
1929 while( (0 == next
) && exitEntry());
1933 done
= OSOrderedSet::withCapacity( 10 );
1934 if( done
->setObject((OSObject
*) next
)) {
1935 // done set didn't contain this one, so recurse
1942 IORegistryEntry
* IORegistryIterator::getNextObject( void )
1944 if( options
& kIORegistryIterateRecursively
)
1945 return( getNextObjectRecursive());
1947 return( getNextObjectFlat());
1950 IORegistryEntry
* IORegistryIterator::getCurrentEntry( void )
1953 return( where
->current
);
1958 OSOrderedSet
* IORegistryIterator::iterateAll( void )
1961 while( getNextObjectRecursive())
1968 OSMetaClassDefineReservedUnused(IORegistryEntry
, 0);
1969 OSMetaClassDefineReservedUnused(IORegistryEntry
, 1);
1970 OSMetaClassDefineReservedUnused(IORegistryEntry
, 2);
1971 OSMetaClassDefineReservedUnused(IORegistryEntry
, 3);
1972 OSMetaClassDefineReservedUnused(IORegistryEntry
, 4);
1973 OSMetaClassDefineReservedUnused(IORegistryEntry
, 5);
1974 OSMetaClassDefineReservedUnused(IORegistryEntry
, 6);
1975 OSMetaClassDefineReservedUnused(IORegistryEntry
, 7);
1976 OSMetaClassDefineReservedUnused(IORegistryEntry
, 8);
1977 OSMetaClassDefineReservedUnused(IORegistryEntry
, 9);
1978 OSMetaClassDefineReservedUnused(IORegistryEntry
, 10);
1979 OSMetaClassDefineReservedUnused(IORegistryEntry
, 11);
1980 OSMetaClassDefineReservedUnused(IORegistryEntry
, 12);
1981 OSMetaClassDefineReservedUnused(IORegistryEntry
, 13);
1982 OSMetaClassDefineReservedUnused(IORegistryEntry
, 14);
1983 OSMetaClassDefineReservedUnused(IORegistryEntry
, 15);
1984 OSMetaClassDefineReservedUnused(IORegistryEntry
, 16);
1985 OSMetaClassDefineReservedUnused(IORegistryEntry
, 17);
1986 OSMetaClassDefineReservedUnused(IORegistryEntry
, 18);
1987 OSMetaClassDefineReservedUnused(IORegistryEntry
, 19);
1988 OSMetaClassDefineReservedUnused(IORegistryEntry
, 20);
1989 OSMetaClassDefineReservedUnused(IORegistryEntry
, 21);
1990 OSMetaClassDefineReservedUnused(IORegistryEntry
, 22);
1991 OSMetaClassDefineReservedUnused(IORegistryEntry
, 23);
1992 OSMetaClassDefineReservedUnused(IORegistryEntry
, 24);
1993 OSMetaClassDefineReservedUnused(IORegistryEntry
, 25);
1994 OSMetaClassDefineReservedUnused(IORegistryEntry
, 26);
1995 OSMetaClassDefineReservedUnused(IORegistryEntry
, 27);
1996 OSMetaClassDefineReservedUnused(IORegistryEntry
, 28);
1997 OSMetaClassDefineReservedUnused(IORegistryEntry
, 29);
1998 OSMetaClassDefineReservedUnused(IORegistryEntry
, 30);
1999 OSMetaClassDefineReservedUnused(IORegistryEntry
, 31);