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 * 12 Nov 98 sdouglas created.
33 #include <IOKit/IORegistryEntry.h>
34 #include <libkern/c++/OSContainers.h>
35 #include <IOKit/IOService.h>
36 #include <IOKit/IOKitKeys.h>
38 #include <IOKit/IOLib.h>
40 #include <IOKit/assert.h>
42 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
44 #define super OSObject
46 OSDefineMetaClassAndStructors(IORegistryEntry
, OSObject
)
48 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
50 static IORegistryEntry
* gRegistryRoot
;
51 static OSDictionary
* gIORegistryPlanes
;
53 const OSSymbol
* gIONameKey
;
54 const OSSymbol
* gIOLocationKey
;
65 class IORegistryPlane
: public OSObject
{
67 friend class IORegistryEntry
;
69 OSDeclareAbstractStructors(IORegistryPlane
)
71 const OSSymbol
* nameKey
;
72 const OSSymbol
* keys
[ kNumSetIndex
];
73 const OSSymbol
* pathNameKey
;
74 const OSSymbol
* pathLocationKey
;
78 virtual bool serialize(OSSerialize
*s
) const;
81 OSDefineMetaClassAndStructors(IORegistryPlane
, OSObject
)
84 static IORecursiveLock
* gPropertiesLock
;
85 static SInt32 gIORegistryGenerationCount
;
87 #define UNLOCK s_lock_done( &gIORegistryLock )
88 #define RLOCK s_lock_read( &gIORegistryLock )
89 #define WLOCK s_lock_write( &gIORegistryLock ); \
90 gIORegistryGenerationCount++
93 #define PUNLOCK IORecursiveLockUnlock( gPropertiesLock )
94 #define PLOCK IORecursiveLockLock( gPropertiesLock )
96 #define IOREGSPLITTABLES
98 #ifdef IOREGSPLITTABLES
99 #define registryTable() fRegistryTable
101 #define registryTable() fPropertyTable
106 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
109 decl_simple_lock_data(,interlock
) /* "hardware" interlock field */
110 volatile unsigned int
111 read_count
:16, /* No. of accepted readers */
112 want_upgrade
:1, /* Read-to-write upgrade waiting */
113 want_write
:1, /* Writer is waiting, or
115 waiting
:1, /* Someone is sleeping on lock */
116 can_sleep
:1; /* Can attempts to lock go to sleep? */
119 static struct s_lock_t gIORegistryLock
;
121 /* Time we loop without holding the interlock.
122 * The former is for when we cannot sleep, the latter
123 * for when our thread can go to sleep (loop less)
124 * we shouldn't retake the interlock at all frequently
125 * if we cannot go to sleep, since it interferes with
126 * any other processors. In particular, 100 is too small
127 * a number for powerpc MP systems because of cache
128 * coherency issues and differing lock fetch times between
131 static unsigned int lock_wait_time
[2] = { (unsigned int)-1, 100 } ;
138 (void) memset((void *) l
, 0, sizeof(s_lock_t
));
140 simple_lock_init(&l
->interlock
, 0);
141 l
->want_write
= FALSE
;
142 l
->want_upgrade
= FALSE
;
144 l
->can_sleep
= can_sleep
;
149 register s_lock_t
* l
)
153 simple_lock(&l
->interlock
);
156 * Try to acquire the want_write bit.
158 while (l
->want_write
) {
160 i
= lock_wait_time
[l
->can_sleep
? 1 : 0];
162 simple_unlock(&l
->interlock
);
163 while (--i
!= 0 && l
->want_write
)
165 simple_lock(&l
->interlock
);
168 if (l
->can_sleep
&& l
->want_write
) {
170 thread_sleep_simple_lock((event_t
) l
,
171 simple_lock_addr(l
->interlock
),
173 /* interlock relocked */
176 l
->want_write
= TRUE
;
178 /* Wait for readers (and upgrades) to finish */
180 while ((l
->read_count
!= 0) || l
->want_upgrade
) {
182 i
= lock_wait_time
[l
->can_sleep
? 1 : 0];
184 simple_unlock(&l
->interlock
);
185 while (--i
!= 0 && (l
->read_count
!= 0 ||
188 simple_lock(&l
->interlock
);
191 if (l
->can_sleep
&& (l
->read_count
!= 0 || l
->want_upgrade
)) {
193 thread_sleep_simple_lock((event_t
) l
,
194 simple_lock_addr(l
->interlock
),
196 /* interlock relocked */
200 simple_unlock(&l
->interlock
);
205 register s_lock_t
* l
)
207 boolean_t do_wakeup
= FALSE
;
209 simple_lock(&l
->interlock
);
211 if (l
->read_count
!= 0) {
215 if (l
->want_upgrade
) {
216 l
->want_upgrade
= FALSE
;
219 l
->want_write
= FALSE
;
224 * There is no reason to wakeup a waiting thread
225 * if the read-count is non-zero. Consider:
226 * we must be dropping a read lock
227 * threads are waiting only if one wants a write lock
228 * if there are still readers, they can't proceed
230 if (l
->waiting
&& (l
->read_count
== 0)) {
235 simple_unlock(&l
->interlock
);
238 thread_wakeup((event_t
) l
);
243 register s_lock_t
* l
)
247 simple_lock(&l
->interlock
);
249 while ( l
->want_upgrade
|| ((0 == l
->read_count
) && l
->want_write
)) {
251 i
= lock_wait_time
[l
->can_sleep
? 1 : 0];
254 simple_unlock(&l
->interlock
);
256 (l
->want_upgrade
|| ((0 == l
->read_count
) && l
->want_write
)))
258 simple_lock(&l
->interlock
);
262 (l
->want_upgrade
|| ((0 == l
->read_count
) && l
->want_write
))) {
264 thread_sleep_simple_lock((event_t
) l
,
265 simple_lock_addr(l
->interlock
),
267 /* interlock relocked */
272 simple_unlock(&l
->interlock
);
276 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
278 IORegistryEntry
* IORegistryEntry::initialize( void )
282 if( !gRegistryRoot
) {
284 s_lock_init( &gIORegistryLock
, true );
285 gRegistryRoot
= new IORegistryEntry
;
286 gPropertiesLock
= IORecursiveLockAlloc();
287 gIORegistryPlanes
= OSDictionary::withCapacity( 1 );
289 assert( gRegistryRoot
&& gPropertiesLock
290 && gIORegistryPlanes
);
291 ok
= gRegistryRoot
->init();
293 gIONameKey
= OSSymbol::withCStringNoCopy( "IOName" );
294 gIOLocationKey
= OSSymbol::withCStringNoCopy( "IOLocation" );
296 assert( ok
&& gIONameKey
&& gIOLocationKey
);
298 gRegistryRoot
->setName( "Root" );
299 gRegistryRoot
->setProperty( kIORegistryPlanesKey
, gIORegistryPlanes
);
302 return( gRegistryRoot
);
305 IORegistryEntry
* IORegistryEntry::getRegistryRoot( void )
307 return( gRegistryRoot
);
310 SInt32
IORegistryEntry::getGenerationCount( void )
312 return( gIORegistryGenerationCount
);
316 const IORegistryPlane
* IORegistryEntry::makePlane( const char * name
)
318 IORegistryPlane
* plane
;
319 const OSSymbol
* nameKey
;
320 const OSSymbol
* parentKey
;
321 const OSSymbol
* childKey
;
322 const OSSymbol
* pathNameKey
;
323 const OSSymbol
* pathLocationKey
;
324 char key
[ kIOMaxPlaneName
+ 16 ];
327 strncpy( key
, name
, kIOMaxPlaneName
);
328 key
[ kIOMaxPlaneName
] = 0;
329 end
= key
+ strlen( name
);
331 nameKey
= OSSymbol::withCString( key
);
333 strcpy( end
, "ParentLinks" );
334 parentKey
= OSSymbol::withCString( key
);
336 strcpy( end
, "ChildLinks" );
337 childKey
= OSSymbol::withCString( key
);
339 strcpy( end
, "Name" );
340 pathNameKey
= OSSymbol::withCString( key
);
342 strcpy( end
, "Location" );
343 pathLocationKey
= OSSymbol::withCString( key
);
345 plane
= new IORegistryPlane
;
347 if( plane
&& plane
->init()
348 && nameKey
&& parentKey
&& childKey
349 && pathNameKey
&& pathLocationKey
) {
351 plane
->nameKey
= nameKey
;
352 plane
->keys
[ kParentSetIndex
] = parentKey
;
353 plane
->keys
[ kChildSetIndex
] = childKey
;
354 plane
->pathNameKey
= pathNameKey
;
355 plane
->pathLocationKey
= pathLocationKey
;
358 gIORegistryPlanes
->setObject( nameKey
, plane
);
366 pathLocationKey
->release();
368 pathNameKey
->release();
370 parentKey
->release();
381 const IORegistryPlane
* IORegistryEntry::getPlane( const char * name
)
383 const IORegistryPlane
* plane
;
386 plane
= (const IORegistryPlane
*) gIORegistryPlanes
->getObject( name
);
392 bool IORegistryPlane::serialize(OSSerialize
*s
) const
394 return( nameKey
->serialize(s
) );
397 enum { kIORegCapacityIncrement
= 4 };
399 bool IORegistryEntry::init( OSDictionary
* dict
= 0 )
409 fPropertyTable
->release();
410 fPropertyTable
= dict
;
412 } else if( !fPropertyTable
) {
413 fPropertyTable
= OSDictionary::withCapacity( kIORegCapacityIncrement
);
415 fPropertyTable
->setCapacityIncrement( kIORegCapacityIncrement
);
421 #ifdef IOREGSPLITTABLES
422 if( !fRegistryTable
) {
423 fRegistryTable
= OSDictionary::withCapacity( kIORegCapacityIncrement
);
425 fRegistryTable
->setCapacityIncrement( kIORegCapacityIncrement
);
428 if( (prop
= OSDynamicCast( OSString
, getProperty( gIONameKey
)))) {
429 OSSymbol
* sym
= (OSSymbol
*)OSSymbol::withString( prop
);
430 // ok for OSSymbol too
435 #endif /* IOREGSPLITTABLES */
440 bool IORegistryEntry::init( IORegistryEntry
* old
,
441 const IORegistryPlane
* plane
)
444 IORegistryEntry
* next
;
452 fPropertyTable
= old
->getPropertyTable();
453 fPropertyTable
->retain();
454 #ifdef IOREGSPLITTABLES
455 fRegistryTable
= old
->fRegistryTable
;
456 old
->fRegistryTable
= OSDictionary::withDictionary( fRegistryTable
);
457 #endif /* IOREGSPLITTABLES */
459 old
->registryTable()->removeObject( plane
->keys
[ kParentSetIndex
] );
460 old
->registryTable()->removeObject( plane
->keys
[ kChildSetIndex
] );
462 all
= getParentSetReference( plane
);
463 if( all
) for( index
= 0;
464 (next
= (IORegistryEntry
*) all
->getObject(index
));
466 next
->makeLink( this, kChildSetIndex
, plane
);
467 next
->breakLink( old
, kChildSetIndex
, plane
);
470 all
= getChildSetReference( plane
);
471 if( all
) for( index
= 0;
472 (next
= (IORegistryEntry
*) all
->getObject(index
));
474 next
->makeLink( this, kParentSetIndex
, plane
);
475 next
->breakLink( old
, kParentSetIndex
, plane
);
483 void IORegistryEntry::free( void )
487 #define msg ": attached at free()"
488 char buf
[ strlen(msg
) + 40 ];
490 if( registryTable() && gIOServicePlane
) {
491 if( getParentSetReference( gIOServicePlane
)
492 || getChildSetReference( gIOServicePlane
)) {
494 strncpy( buf
, getName(), 32);
502 if( getPropertyTable())
503 getPropertyTable()->release();
505 #ifdef IOREGSPLITTABLES
507 registryTable()->release();
508 #endif /* IOREGSPLITTABLES */
513 void IORegistryEntry::setPropertyTable( OSDictionary
* dict
)
516 fPropertyTable
->release();
519 fPropertyTable
= dict
;
522 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
524 /* Wrappers to synchronize property table */
526 #define wrap1(func, type, constant) \
528 IORegistryEntry::func ## Property( type * aKey) constant \
533 obj = getPropertyTable()->func ## Object( aKey ); \
539 #define wrap2(type, constant) \
541 IORegistryEntry::copyProperty( type * aKey) constant \
546 obj = getProperty( aKey ); \
554 #define wrap3(func,type,constant) \
556 IORegistryEntry::func ## Property( type * aKey) constant \
559 getPropertyTable()->func ## Object( aKey ); \
563 #define wrap4(type,constant) \
565 IORegistryEntry::getProperty( type * aKey, \
566 const IORegistryPlane * plane, \
567 IOOptionBits options ) constant \
569 OSObject * obj = getProperty( aKey ); \
571 if ( (0 == obj) && plane && (options & kIORegistryIterateRecursively) ) { \
572 IORegistryEntry * entry = (IORegistryEntry *) this; \
573 IORegistryIterator * iter; \
574 iter = IORegistryIterator::iterateOver( entry, plane, options ); \
577 while ( (0 == obj) && (entry = iter->getNextObject()) ) { \
578 obj = entry->getProperty( aKey ); \
587 #define wrap5(type,constant) \
589 IORegistryEntry::copyProperty( type * aKey, \
590 const IORegistryPlane * plane, \
591 IOOptionBits options ) constant \
593 OSObject * obj = copyProperty( aKey ); \
595 if ( (0 == obj) && plane && (options & kIORegistryIterateRecursively) ) { \
596 IORegistryEntry * entry = (IORegistryEntry *) this; \
597 IORegistryIterator * iter; \
598 iter = IORegistryIterator::iterateOver( entry, plane, options ); \
601 while ( (0 == obj) && (entry = iter->getNextObject()) ) { \
602 obj = entry->copyProperty( aKey ); \
611 bool IORegistryEntry::serializeProperties( OSSerialize
* s
) const
615 // setProperty( getRetainCount(), 32, "__retain" );
618 ok
= getPropertyTable()->serialize( s
);
624 OSDictionary
* IORegistryEntry::dictionaryWithProperties( void ) const
629 dict
= OSDictionary::withDictionary( getPropertyTable(),
630 getPropertyTable()->getCapacity() );
636 IOReturn
IORegistryEntry::setProperties( OSObject
* properties
)
638 return( kIOReturnUnsupported
);
641 wrap1(get
, const OSSymbol
, const) // getProperty() definition
642 wrap1(get
, const OSString
, const) // getProperty() definition
643 wrap1(get
, const char, const) // getProperty() definition
645 wrap2(const OSSymbol
, const) // copyProperty() definition
646 wrap2(const OSString
, const) // copyProperty() definition
647 wrap2(const char, const) // copyProperty() definition
649 wrap3(remove
, const OSSymbol
,) // removeProperty() definition
650 wrap3(remove
, const OSString
,) // removeProperty() definition
651 wrap3(remove
, const char,) // removeProperty() definition
653 wrap4(const OSSymbol
, const) // getProperty() w/plane definition
654 wrap4(const OSString
, const) // getProperty() w/plane definition
655 wrap4(const char, const) // getProperty() w/plane definition
657 wrap5(const OSSymbol
, const) // copyProperty() w/plane definition
658 wrap5(const OSString
, const) // copyProperty() w/plane definition
659 wrap5(const char, const) // copyProperty() w/plane definition
663 IORegistryEntry::setProperty( const OSSymbol
* aKey
, OSObject
* anObject
)
667 ret
= getPropertyTable()->setObject( aKey
, anObject
);
674 IORegistryEntry::setProperty( const OSString
* aKey
, OSObject
* anObject
)
678 ret
= getPropertyTable()->setObject( aKey
, anObject
);
685 IORegistryEntry::setProperty( const char * aKey
, OSObject
* anObject
)
689 ret
= getPropertyTable()->setObject( aKey
, anObject
);
696 IORegistryEntry::setProperty(const char * aKey
, const char * aString
)
699 OSSymbol
* aSymbol
= (OSSymbol
*) OSSymbol::withCString( aString
);
703 ret
= getPropertyTable()->setObject( aKey
, aSymbol
);
711 IORegistryEntry::setProperty(const char * aKey
, bool aBoolean
)
714 OSBoolean
* aBooleanObj
= OSBoolean::withBoolean( aBoolean
);
718 ret
= getPropertyTable()->setObject( aKey
, aBooleanObj
);
720 aBooleanObj
->release();
726 IORegistryEntry::setProperty( const char * aKey
,
727 unsigned long long aValue
,
728 unsigned int aNumberOfBits
)
731 OSNumber
* anOffset
= OSNumber::withNumber( aValue
, aNumberOfBits
);
735 ret
= getPropertyTable()->setObject( aKey
, anOffset
);
743 IORegistryEntry::setProperty( const char * aKey
,
748 OSData
* data
= OSData::withBytes( bytes
, length
);
752 ret
= getPropertyTable()->setObject( aKey
, data
);
759 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
761 /* Name, location, paths */
763 const char * IORegistryEntry::getName( const IORegistryPlane
* plane
= 0 ) const
769 sym
= (OSSymbol
*) registryTable()->getObject( plane
->pathNameKey
);
771 sym
= (OSSymbol
*) registryTable()->getObject( gIONameKey
);
775 return( sym
->getCStringNoCopy());
777 return( (getMetaClass())->getClassName());
780 const OSSymbol
* IORegistryEntry::copyName(
781 const IORegistryPlane
* plane
= 0 ) const
787 sym
= (OSSymbol
*) registryTable()->getObject( plane
->pathNameKey
);
789 sym
= (OSSymbol
*) registryTable()->getObject( gIONameKey
);
797 return( OSSymbol::withCString((getMetaClass())->getClassName()) );
800 const OSSymbol
* IORegistryEntry::copyLocation(
801 const IORegistryPlane
* plane
= 0 ) const
807 sym
= (OSSymbol
*) registryTable()->getObject( plane
->pathLocationKey
);
809 sym
= (OSSymbol
*) registryTable()->getObject( gIOLocationKey
);
817 const char * IORegistryEntry::getLocation( const IORegistryPlane
* plane
= 0 ) const
819 const OSSymbol
* sym
= copyLocation( plane
);
820 const char * result
= 0;
823 result
= sym
->getCStringNoCopy();
830 void IORegistryEntry::setName( const OSSymbol
* name
,
831 const IORegistryPlane
* plane
= 0 )
833 const OSSymbol
* key
;
837 key
= plane
->pathNameKey
;
842 registryTable()->setObject( key
, (OSObject
*) name
);
847 void IORegistryEntry::setName( const char * name
,
848 const IORegistryPlane
* plane
= 0 )
850 OSSymbol
* sym
= (OSSymbol
*)OSSymbol::withCString( name
);
852 setName( sym
, plane
);
857 void IORegistryEntry::setLocation( const OSSymbol
* location
,
858 const IORegistryPlane
* plane
= 0 )
860 const OSSymbol
* key
;
864 key
= plane
->pathLocationKey
;
866 key
= gIOLocationKey
;
869 registryTable()->setObject( key
, (OSObject
*) location
);
874 void IORegistryEntry::setLocation( const char * location
,
875 const IORegistryPlane
* plane
= 0 )
877 OSSymbol
* sym
= (OSSymbol
*)OSSymbol::withCString( location
);
879 setLocation( sym
, plane
);
885 IORegistryEntry::compareName( OSString
* name
, OSString
** matched
= 0 ) const
887 const OSSymbol
* sym
= copyName();
890 isEqual
= sym
->isEqualTo( name
);
892 if( isEqual
&& matched
) {
904 IORegistryEntry::compareNames( OSObject
* names
, OSString
** matched
= 0 ) const
907 OSCollection
* collection
;
908 OSIterator
* iter
= 0;
911 if( (collection
= OSDynamicCast( OSCollection
, names
))) {
912 iter
= OSCollectionIterator::withCollection( collection
);
915 string
= OSDynamicCast( OSString
, names
);
919 result
= compareName( string
, matched
);
921 } while( (false == result
)
922 && iter
&& (string
= OSDynamicCast( OSString
, iter
->getNextObject())));
931 bool IORegistryEntry::getPath( char * path
, int * length
,
932 const IORegistryPlane
* plane
) const
935 IORegistryEntry
* root
;
936 const IORegistryEntry
* entry
;
937 IORegistryEntry
* parent
;
938 const OSSymbol
* alias
;
940 int len
, maxLength
, compLen
;
944 if( !path
|| !length
|| !plane
)
948 maxLength
= *length
- 2;
951 len
= plane
->nameKey
->getLength();
952 if( len
>= maxLength
)
954 strcpy( nextComp
, plane
->nameKey
->getCStringNoCopy());
955 nextComp
[ len
++ ] = ':';
958 if( (alias
= hasAlias( plane
))) {
959 len
+= alias
->getLength();
960 ok
= (maxLength
> len
);
963 strcpy( nextComp
, alias
->getCStringNoCopy());
968 parent
= entry
->getParentEntry( plane
);
970 // Error if not attached in plane
973 stack
= OSArray::withCapacity( getDepth( plane
));
979 root
= gRegistryRoot
->getChildEntry( plane
);
980 while( parent
&& (entry
!= root
)) {
982 stack
->setObject( (OSObject
*) entry
);
984 parent
= entry
->getParentEntry( plane
);
987 index
= stack
->getCount();
996 } else while( ok
&& ((--index
) >= 0)) {
998 entry
= (IORegistryEntry
*) stack
->getObject((unsigned int) index
);
1001 if( (alias
= entry
->hasAlias( plane
))) {
1002 len
= plane
->nameKey
->getLength() + 1;
1003 nextComp
= path
+ len
;
1005 compLen
= alias
->getLength();
1006 ok
= (maxLength
> len
+ compLen
);
1008 strcpy( nextComp
, alias
->getCStringNoCopy());
1010 compLen
= maxLength
- len
;
1011 ok
= entry
->getPathComponent( nextComp
+ 1, &compLen
, plane
);
1013 if( ok
&& compLen
) {
1021 nextComp
+= compLen
;
1033 bool IORegistryEntry::getPathComponent( char * path
, int * length
,
1034 const IORegistryPlane
* plane
) const
1036 int len
, locLen
, maxLength
;
1037 const char * compName
;
1041 maxLength
= *length
;
1043 compName
= getName( plane
);
1044 len
= strlen( compName
);
1045 if( (loc
= getLocation( plane
)))
1046 locLen
= 1 + strlen( loc
);
1050 ok
= ((len
+ locLen
) < maxLength
);
1052 strcpy( path
, compName
);
1057 strcpy( path
, loc
);
1065 const char * IORegistryEntry::matchPathLocation( const char * cmp
,
1066 const IORegistryPlane
* plane
)
1069 const char * result
= 0;
1070 u_quad_t num1
, num2
;
1073 str
= getLocation( plane
);
1077 num1
= strtouq( cmp
, (char **) &cmp
, 16 );
1079 num2
= strtouq( str
, (char **) &str
, 16 );
1089 if( (c2
== ':') && (c2
== c1
)) {
1111 IORegistryEntry
* IORegistryEntry::getChildFromComponent( const char ** opath
,
1112 const IORegistryPlane
* plane
)
1114 IORegistryEntry
* entry
= 0;
1118 const char * cmp
= 0;
1123 set
= getChildSetReference( plane
);
1129 (entry
= (IORegistryEntry
*) set
->getObject(index
));
1135 str
= entry
->getName( plane
);
1136 len
= strlen( str
);
1137 if( strncmp( str
, cmp
, len
))
1142 if( (c
== 0) || (c
== '/') || (c
== ':'))
1148 if( (cmp
= entry
->matchPathLocation( cmp
, plane
)))
1158 const OSSymbol
* IORegistryEntry::hasAlias( const IORegistryPlane
* plane
,
1159 char * opath
= 0, int * length
= 0 ) const
1161 IORegistryEntry
* entry
;
1162 IORegistryEntry
* entry2
;
1163 const OSSymbol
* key
;
1164 const OSSymbol
* bestKey
= 0;
1167 const char * path
= "/aliases";
1169 entry
= IORegistryEntry::fromPath( path
, plane
);
1172 if( (iter
= OSCollectionIterator::withCollection(
1173 entry
->getPropertyTable() ))) {
1175 while( (key
= (OSSymbol
*) iter
->getNextObject())) {
1177 data
= (OSData
*) entry
->getProperty( key
);
1178 path
= (const char *) data
->getBytesNoCopy();
1179 if( (entry2
= IORegistryEntry::fromPath( path
, plane
,
1181 if( this == entry2
) {
1183 || (bestKey
->getLength() > key
->getLength()))
1184 // pick the smallest alias
1198 const char * IORegistryEntry::dealiasPath(
1199 const char ** opath
,
1200 const IORegistryPlane
* plane
)
1202 IORegistryEntry
* entry
;
1204 const char * path
= *opath
;
1205 const char * rpath
= 0;
1208 char temp
[ kIOMaxPlaneName
+ 1 ];
1215 while( (c
= *end
++) && (c
!= '/') && (c
!= ':'))
1218 if( (end
- path
) < kIOMaxPlaneName
) {
1219 strncpy( temp
, path
, end
- path
);
1220 temp
[ end
- path
] = 0;
1223 entry
= IORegistryEntry::fromPath( "/aliases", plane
);
1225 data
= (OSData
*) entry
->getProperty( temp
);
1227 rpath
= (const char *) data
->getBytesNoCopy();
1239 IORegistryEntry
* IORegistryEntry::fromPath(
1241 const IORegistryPlane
* plane
= 0,
1244 IORegistryEntry
* fromEntry
= 0 )
1246 IORegistryEntry
* where
= 0;
1247 IORegistryEntry
* aliasEntry
= 0;
1248 IORegistryEntry
* next
;
1254 char temp
[ kIOMaxPlaneName
+ 1 ];
1261 end
= strchr( path
, ':' );
1262 if( end
&& ((end
- path
) < kIOMaxPlaneName
)) {
1263 strncpy( temp
, path
, end
- path
);
1264 temp
[ end
- path
] = 0;
1265 plane
= getPlane( temp
);
1274 if( (alias
= dealiasPath( &end
, plane
))) {
1277 aliasEntry
= IORegistryEntry::fromPath( alias
, plane
,
1278 opath
, &len
, fromEntry
);
1290 if( (0 == fromEntry
) && (*path
++ == '/'))
1291 fromEntry
= gRegistryRoot
->getChildEntry( plane
);
1298 if( c
&& (c
!= ':')) // check valid terminator
1303 next
= where
->getChildFromComponent( &path
, plane
);
1309 // check residual path
1310 if( where
!= fromEntry
)
1313 if( opath
&& length
) {
1314 // copy out residual path
1315 len2
= len
+ strlen( path
);
1317 strcpy( opath
+ len
, path
);
1321 // no residual path => must be no tail for success
1328 aliasEntry
->release();
1335 IORegistryEntry
* IORegistryEntry::childFromPath(
1337 const IORegistryPlane
* plane
= 0,
1341 return( IORegistryEntry::fromPath( path
, plane
, opath
, len
, this ));
1344 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1346 #define IOLinkIterator OSCollectionIterator
1349 #define super OSObject
1351 inline bool IORegistryEntry::arrayMember( OSArray
* set
,
1352 const IORegistryEntry
* member
,
1353 unsigned int * index
= 0 ) const
1356 OSObject
* probeObject
;
1358 for( i
= 0; (probeObject
= set
->getObject(i
)); i
++) {
1359 if (probeObject
== (OSObject
*) member
) {
1368 bool IORegistryEntry::makeLink( IORegistryEntry
* to
,
1369 unsigned int relation
,
1370 const IORegistryPlane
* plane
) const
1373 bool result
= false;
1375 if( (links
= (OSArray
*)
1376 registryTable()->getObject( plane
->keys
[ relation
] ))) {
1378 result
= arrayMember( links
, to
);
1380 result
= links
->setObject( to
);
1384 links
= OSArray::withObjects( & (const OSObject
*) to
, 1, 1 );
1385 result
= (links
!= 0);
1387 result
= registryTable()->setObject( plane
->keys
[ relation
],
1396 void IORegistryEntry::breakLink( IORegistryEntry
* to
,
1397 unsigned int relation
,
1398 const IORegistryPlane
* plane
) const
1403 if( (links
= (OSArray
*)
1404 registryTable()->getObject( plane
->keys
[ relation
]))) {
1406 if( arrayMember( links
, to
, &index
)) {
1407 links
->removeObject( index
);
1408 if( 0 == links
->getCount())
1409 registryTable()->removeObject( plane
->keys
[ relation
]);
1415 OSArray
* IORegistryEntry::getParentSetReference(
1416 const IORegistryPlane
* plane
) const
1419 return( (OSArray
*) registryTable()->getObject(
1420 plane
->keys
[ kParentSetIndex
]));
1425 OSIterator
* IORegistryEntry::getParentIterator(
1426 const IORegistryPlane
* plane
) const
1435 links
= getParentSetReference( plane
);
1437 links
= OSArray::withCapacity( 1 );
1439 links
= OSArray::withArray( links
, links
->getCount() );
1442 iter
= IOLinkIterator::withCollection( links
);
1450 IORegistryEntry
* IORegistryEntry::copyParentEntry( const IORegistryPlane
* plane
) const
1452 IORegistryEntry
* entry
= 0;
1457 if( (links
= getParentSetReference( plane
))) {
1458 entry
= (IORegistryEntry
*) links
->getObject( 0 );
1467 IORegistryEntry
* IORegistryEntry::getParentEntry( const IORegistryPlane
* plane
) const
1469 IORegistryEntry
* entry
;
1471 entry
= copyParentEntry( plane
);
1478 OSArray
* IORegistryEntry::getChildSetReference( const IORegistryPlane
* plane
) const
1481 return( (OSArray
*) registryTable()->getObject(
1482 plane
->keys
[ kChildSetIndex
]));
1487 OSIterator
* IORegistryEntry::getChildIterator( const IORegistryPlane
* plane
) const
1496 links
= getChildSetReference( plane
);
1498 links
= OSArray::withCapacity( 1 );
1500 links
= OSArray::withArray( links
, links
->getCount() );
1503 iter
= IOLinkIterator::withCollection( links
);
1512 IORegistryEntry
* IORegistryEntry::copyChildEntry(
1513 const IORegistryPlane
* plane
) const
1515 IORegistryEntry
* entry
= 0;
1520 if( (links
= getChildSetReference( plane
))) {
1521 entry
= (IORegistryEntry
*) links
->getObject( 0 );
1530 IORegistryEntry
* IORegistryEntry::getChildEntry(
1531 const IORegistryPlane
* plane
) const
1533 IORegistryEntry
* entry
;
1535 entry
= copyChildEntry( plane
);
1542 void IORegistryEntry::applyToChildren( IORegistryEntryApplierFunction applier
,
1544 const IORegistryPlane
* plane
) const
1548 IORegistryEntry
* next
;
1554 array
= OSArray::withArray( getChildSetReference( plane
));
1558 (next
= (IORegistryEntry
*) array
->getObject( index
));
1560 (*applier
)(next
, context
);
1565 void IORegistryEntry::applyToParents( IORegistryEntryApplierFunction applier
,
1567 const IORegistryPlane
* plane
) const
1571 IORegistryEntry
* next
;
1577 array
= OSArray::withArray( getParentSetReference( plane
));
1581 (next
= (IORegistryEntry
*) array
->getObject( index
));
1583 (*applier
)(next
, context
);
1588 bool IORegistryEntry::isChild( IORegistryEntry
* child
,
1589 const IORegistryPlane
* plane
,
1590 bool onlyChild
= false ) const
1597 if( (links
= getChildSetReference( plane
))) {
1598 if( (!onlyChild
) || (1 == links
->getCount()))
1599 ret
= arrayMember( links
, child
);
1601 if( ret
&& (links
= child
->getParentSetReference( plane
)))
1602 ret
= arrayMember( links
, this );
1609 bool IORegistryEntry::isParent( IORegistryEntry
* parent
,
1610 const IORegistryPlane
* plane
,
1611 bool onlyParent
= false ) const
1619 if( (links
= getParentSetReference( plane
))) {
1620 if( (!onlyParent
) || (1 == links
->getCount()))
1621 ret
= arrayMember( links
, parent
);
1623 if( ret
&& (links
= parent
->getChildSetReference( plane
)))
1624 ret
= arrayMember( links
, this );
1631 bool IORegistryEntry::inPlane( const IORegistryPlane
* plane
) const
1637 ret
= (0 != getParentSetReference( plane
));
1644 bool IORegistryEntry::attachToParent( IORegistryEntry
* parent
,
1645 const IORegistryPlane
* plane
)
1656 ret
= makeLink( parent
, kParentSetIndex
, plane
);
1658 if( (links
= parent
->getChildSetReference( plane
)))
1659 needParent
= (false == arrayMember( links
, this ));
1663 // ret &= parent->makeLink( this, kChildSetIndex, plane );
1668 ret
&= parent
->attachToChild( this, plane
);
1673 bool IORegistryEntry::attachToChild( IORegistryEntry
* child
,
1674 const IORegistryPlane
* plane
)
1685 ret
= makeLink( child
, kChildSetIndex
, plane
);
1687 if( (links
= child
->getParentSetReference( plane
)))
1688 needChild
= (false == arrayMember( links
, this ));
1695 ret
&= child
->attachToParent( this, plane
);
1700 void IORegistryEntry::detachFromParent( IORegistryEntry
* parent
,
1701 const IORegistryPlane
* plane
)
1710 breakLink( parent
, kParentSetIndex
, plane
);
1712 if( (links
= parent
->getChildSetReference( plane
)))
1713 needParent
= arrayMember( links
, this );
1717 // parent->breakLink( this, kChildSetIndex, plane );
1722 parent
->detachFromChild( this, plane
);
1727 void IORegistryEntry::detachFromChild( IORegistryEntry
* child
,
1728 const IORegistryPlane
* plane
)
1737 breakLink( child
, kChildSetIndex
, plane
);
1739 if( (links
= child
->getParentSetReference( plane
)))
1740 needChild
= arrayMember( links
, this );
1747 child
->detachFromParent( this, plane
);
1752 void IORegistryEntry::detachAbove( const IORegistryPlane
* plane
)
1754 IORegistryEntry
* parent
;
1757 while( (parent
= getParentEntry( plane
)))
1758 detachFromParent( parent
, plane
);
1762 void IORegistryEntry::detachAll( const IORegistryPlane
* plane
)
1765 IORegistryEntry
* next
;
1766 IORegistryIterator
* regIter
;
1768 regIter
= IORegistryIterator::iterateOver( this, plane
, true );
1771 all
= regIter
->iterateAll();
1774 detachAbove( plane
);
1776 while( (next
= (IORegistryEntry
*) all
->getLastObject())) {
1779 all
->removeObject(next
);
1781 next
->detachAbove( plane
);
1788 unsigned int IORegistryEntry::getDepth( const IORegistryPlane
* plane
) const
1790 unsigned int depth
= 1;
1792 unsigned int oneDepth
, maxParentDepth
, count
;
1793 IORegistryEntry
* one
;
1794 const IORegistryEntry
* next
;
1800 while( (parents
= next
->getParentSetReference( plane
))) {
1802 count
= parents
->getCount();
1807 next
= (IORegistryEntry
*) parents
->getObject( 0 );
1812 (one
= (IORegistryEntry
*) parents
->getObject( index
));
1814 oneDepth
= one
->getDepth( plane
);
1815 if( oneDepth
> maxParentDepth
)
1816 maxParentDepth
= oneDepth
;
1818 depth
+= maxParentDepth
;
1828 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1831 #define super OSIterator
1833 OSDefineMetaClassAndStructors(IORegistryIterator
, OSIterator
)
1835 enum { kIORegistryIteratorInvalidFlag
= 0x80000000 };
1837 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1839 IORegistryIterator
*
1840 IORegistryIterator::iterateOver( IORegistryEntry
* root
,
1841 const IORegistryPlane
* plane
,
1842 IOOptionBits options
= 0 )
1844 IORegistryIterator
* create
;
1851 create
= new IORegistryIterator
;
1853 if( create
->init()) {
1856 create
->root
= root
;
1857 create
->where
= &create
->start
;
1858 create
->start
.current
= root
;
1859 create
->plane
= plane
;
1860 create
->options
= options
& ~kIORegistryIteratorInvalidFlag
;
1870 IORegistryIterator
*
1871 IORegistryIterator::iterateOver( const IORegistryPlane
* plane
,
1872 IOOptionBits options
= 0 )
1874 return( iterateOver( gRegistryRoot
, plane
, options
));
1877 bool IORegistryIterator::isValid( void )
1886 ok
= (0 == (kIORegistryIteratorInvalidFlag
& options
));
1888 while( ok
&& next
) {
1890 ok
= where
->iter
->isValid();
1898 void IORegistryIterator::enterEntry( const IORegistryPlane
* enterPlane
)
1903 where
= (IORegCursor
*) IOMalloc( sizeof( IORegCursor
));
1909 where
->current
= prev
->current
;
1914 void IORegistryIterator::enterEntry( void )
1916 enterEntry( plane
);
1919 bool IORegistryIterator::exitEntry( void )
1924 where
->iter
->release();
1926 if( where
->current
)// && (where != &start))
1927 where
->current
->release();
1930 if( where
!= &start
) {
1933 IOFree( gone
, sizeof( IORegCursor
));
1940 void IORegistryIterator::reset( void )
1950 where
->current
= root
;
1951 options
&= ~kIORegistryIteratorInvalidFlag
;
1954 void IORegistryIterator::free( void )
1965 IORegistryEntry
* IORegistryIterator::getNextObjectFlat( void )
1967 IORegistryEntry
* next
= 0;
1968 OSArray
* links
= 0;
1972 if( (0 == where
->iter
)) {
1973 // just entered - create new iter
1976 && (links
= ( (options
& kIORegistryIterateParents
) ?
1977 where
->current
->getParentSetReference( plane
) :
1978 where
->current
->getChildSetReference( plane
) )) )
1980 where
->iter
= OSCollectionIterator::withCollection( links
);
1983 // next sibling - release current
1985 where
->current
->release();
1989 next
= (IORegistryEntry
*) where
->iter
->getNextObject();
1993 else if( !where
->iter
->isValid())
1994 options
|= kIORegistryIteratorInvalidFlag
;
1997 where
->current
= next
;
2004 IORegistryEntry
* IORegistryIterator::getNextObjectRecursive( void )
2006 IORegistryEntry
* next
;
2009 next
= getNextObjectFlat();
2010 while( (0 == next
) && exitEntry());
2014 done
= OSOrderedSet::withCapacity( 10 );
2015 if( done
->setObject((OSObject
*) next
)) {
2016 // done set didn't contain this one, so recurse
2023 IORegistryEntry
* IORegistryIterator::getNextObject( void )
2025 if( options
& kIORegistryIterateRecursively
)
2026 return( getNextObjectRecursive());
2028 return( getNextObjectFlat());
2031 IORegistryEntry
* IORegistryIterator::getCurrentEntry( void )
2034 return( where
->current
);
2039 OSOrderedSet
* IORegistryIterator::iterateAll( void )
2042 while( getNextObjectRecursive())
2049 OSMetaClassDefineReservedUsed(IORegistryEntry
, 0);
2050 OSMetaClassDefineReservedUsed(IORegistryEntry
, 1);
2051 OSMetaClassDefineReservedUsed(IORegistryEntry
, 2);
2052 OSMetaClassDefineReservedUsed(IORegistryEntry
, 3);
2053 OSMetaClassDefineReservedUsed(IORegistryEntry
, 4);
2055 OSMetaClassDefineReservedUnused(IORegistryEntry
, 5);
2056 OSMetaClassDefineReservedUnused(IORegistryEntry
, 6);
2057 OSMetaClassDefineReservedUnused(IORegistryEntry
, 7);
2058 OSMetaClassDefineReservedUnused(IORegistryEntry
, 8);
2059 OSMetaClassDefineReservedUnused(IORegistryEntry
, 9);
2060 OSMetaClassDefineReservedUnused(IORegistryEntry
, 10);
2061 OSMetaClassDefineReservedUnused(IORegistryEntry
, 11);
2062 OSMetaClassDefineReservedUnused(IORegistryEntry
, 12);
2063 OSMetaClassDefineReservedUnused(IORegistryEntry
, 13);
2064 OSMetaClassDefineReservedUnused(IORegistryEntry
, 14);
2065 OSMetaClassDefineReservedUnused(IORegistryEntry
, 15);
2066 OSMetaClassDefineReservedUnused(IORegistryEntry
, 16);
2067 OSMetaClassDefineReservedUnused(IORegistryEntry
, 17);
2068 OSMetaClassDefineReservedUnused(IORegistryEntry
, 18);
2069 OSMetaClassDefineReservedUnused(IORegistryEntry
, 19);
2070 OSMetaClassDefineReservedUnused(IORegistryEntry
, 20);
2071 OSMetaClassDefineReservedUnused(IORegistryEntry
, 21);
2072 OSMetaClassDefineReservedUnused(IORegistryEntry
, 22);
2073 OSMetaClassDefineReservedUnused(IORegistryEntry
, 23);
2074 OSMetaClassDefineReservedUnused(IORegistryEntry
, 24);
2075 OSMetaClassDefineReservedUnused(IORegistryEntry
, 25);
2076 OSMetaClassDefineReservedUnused(IORegistryEntry
, 26);
2077 OSMetaClassDefineReservedUnused(IORegistryEntry
, 27);
2078 OSMetaClassDefineReservedUnused(IORegistryEntry
, 28);
2079 OSMetaClassDefineReservedUnused(IORegistryEntry
, 29);
2080 OSMetaClassDefineReservedUnused(IORegistryEntry
, 30);
2081 OSMetaClassDefineReservedUnused(IORegistryEntry
, 31);
2083 /* inline function implementation */
2084 OSDictionary
* IORegistryEntry::getPropertyTable( void ) const
2085 { return(fPropertyTable
); }