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
103 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
106 decl_simple_lock_data(,interlock
) /* "hardware" interlock field */
107 volatile unsigned int
108 read_count
:16, /* No. of accepted readers */
109 want_upgrade
:1, /* Read-to-write upgrade waiting */
110 want_write
:1, /* Writer is waiting, or
112 waiting
:1, /* Someone is sleeping on lock */
113 can_sleep
:1; /* Can attempts to lock go to sleep? */
116 static struct s_lock_t gIORegistryLock
;
118 /* Time we loop without holding the interlock.
119 * The former is for when we cannot sleep, the latter
120 * for when our thread can go to sleep (loop less)
121 * we shouldn't retake the interlock at all frequently
122 * if we cannot go to sleep, since it interferes with
123 * any other processors. In particular, 100 is too small
124 * a number for powerpc MP systems because of cache
125 * coherency issues and differing lock fetch times between
128 static unsigned int lock_wait_time
[2] = { (unsigned int)-1, 100 } ;
135 (void) memset((void *) l
, 0, sizeof(s_lock_t
));
137 simple_lock_init(&l
->interlock
, 0);
138 l
->want_write
= FALSE
;
139 l
->want_upgrade
= FALSE
;
141 l
->can_sleep
= can_sleep
;
146 register s_lock_t
* l
)
150 simple_lock(&l
->interlock
);
153 * Try to acquire the want_write bit.
155 while (l
->want_write
) {
157 i
= lock_wait_time
[l
->can_sleep
? 1 : 0];
159 simple_unlock(&l
->interlock
);
160 while (--i
!= 0 && l
->want_write
)
162 simple_lock(&l
->interlock
);
165 if (l
->can_sleep
&& l
->want_write
) {
167 thread_sleep_simple_lock((event_t
) l
,
168 simple_lock_addr(l
->interlock
), FALSE
);
169 simple_lock(&l
->interlock
);
172 l
->want_write
= TRUE
;
174 /* Wait for readers (and upgrades) to finish */
176 while ((l
->read_count
!= 0) || l
->want_upgrade
) {
178 i
= lock_wait_time
[l
->can_sleep
? 1 : 0];
180 simple_unlock(&l
->interlock
);
181 while (--i
!= 0 && (l
->read_count
!= 0 ||
184 simple_lock(&l
->interlock
);
187 if (l
->can_sleep
&& (l
->read_count
!= 0 || l
->want_upgrade
)) {
189 thread_sleep_simple_lock((event_t
) l
,
190 simple_lock_addr(l
->interlock
), FALSE
);
191 simple_lock(&l
->interlock
);
195 simple_unlock(&l
->interlock
);
200 register s_lock_t
* l
)
202 boolean_t do_wakeup
= FALSE
;
204 simple_lock(&l
->interlock
);
206 if (l
->read_count
!= 0) {
210 if (l
->want_upgrade
) {
211 l
->want_upgrade
= FALSE
;
214 l
->want_write
= FALSE
;
219 * There is no reason to wakeup a waiting thread
220 * if the read-count is non-zero. Consider:
221 * we must be dropping a read lock
222 * threads are waiting only if one wants a write lock
223 * if there are still readers, they can't proceed
225 if (l
->waiting
&& (l
->read_count
== 0)) {
230 simple_unlock(&l
->interlock
);
233 thread_wakeup((event_t
) l
);
238 register s_lock_t
* l
)
242 simple_lock(&l
->interlock
);
244 while ( l
->want_upgrade
|| ((0 == l
->read_count
) && l
->want_write
)) {
246 i
= lock_wait_time
[l
->can_sleep
? 1 : 0];
249 simple_unlock(&l
->interlock
);
251 (l
->want_upgrade
|| ((0 == l
->read_count
) && l
->want_write
)))
253 simple_lock(&l
->interlock
);
257 (l
->want_upgrade
|| ((0 == l
->read_count
) && l
->want_write
))) {
259 thread_sleep_simple_lock((event_t
) l
,
260 simple_lock_addr(l
->interlock
), FALSE
);
261 simple_lock(&l
->interlock
);
266 simple_unlock(&l
->interlock
);
270 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
272 IORegistryEntry
* IORegistryEntry::initialize( void )
276 if( !gRegistryRoot
) {
278 s_lock_init( &gIORegistryLock
, true );
279 gRegistryRoot
= new IORegistryEntry
;
280 gPropertiesLock
= IORecursiveLockAlloc();
281 gIORegistryPlanes
= OSDictionary::withCapacity( 1 );
283 assert( gRegistryRoot
&& gPropertiesLock
284 && gIORegistryPlanes
);
285 ok
= gRegistryRoot
->init();
287 gIONameKey
= OSSymbol::withCStringNoCopy( "IOName" );
288 gIOLocationKey
= OSSymbol::withCStringNoCopy( "IOLocation" );
290 assert( ok
&& gIONameKey
&& gIOLocationKey
);
292 gRegistryRoot
->setName( "Root" );
293 gRegistryRoot
->setProperty( kIORegistryPlanesKey
, gIORegistryPlanes
);
296 return( gRegistryRoot
);
299 IORegistryEntry
* IORegistryEntry::getRegistryRoot( void )
301 return( gRegistryRoot
);
304 SInt32
IORegistryEntry::getGenerationCount( void )
306 return( gIORegistryGenerationCount
);
310 const IORegistryPlane
* IORegistryEntry::makePlane( const char * name
)
312 IORegistryPlane
* plane
;
313 const OSSymbol
* nameKey
;
314 const OSSymbol
* parentKey
;
315 const OSSymbol
* childKey
;
316 const OSSymbol
* pathNameKey
;
317 const OSSymbol
* pathLocationKey
;
318 char key
[ kIOMaxPlaneName
+ 16 ];
321 strncpy( key
, name
, kIOMaxPlaneName
);
322 key
[ kIOMaxPlaneName
] = 0;
323 end
= key
+ strlen( name
);
325 nameKey
= OSSymbol::withCString( key
);
327 strcpy( end
, "ParentLinks" );
328 parentKey
= OSSymbol::withCString( key
);
330 strcpy( end
, "ChildLinks" );
331 childKey
= OSSymbol::withCString( key
);
333 strcpy( end
, "Name" );
334 pathNameKey
= OSSymbol::withCString( key
);
336 strcpy( end
, "Location" );
337 pathLocationKey
= OSSymbol::withCString( key
);
339 plane
= new IORegistryPlane
;
341 if( plane
&& plane
->init()
342 && nameKey
&& parentKey
&& childKey
343 && pathNameKey
&& pathLocationKey
) {
345 plane
->nameKey
= nameKey
;
346 plane
->keys
[ kParentSetIndex
] = parentKey
;
347 plane
->keys
[ kChildSetIndex
] = childKey
;
348 plane
->pathNameKey
= pathNameKey
;
349 plane
->pathLocationKey
= pathLocationKey
;
352 gIORegistryPlanes
->setObject( nameKey
, plane
);
360 pathLocationKey
->release();
362 pathNameKey
->release();
364 parentKey
->release();
375 const IORegistryPlane
* IORegistryEntry::getPlane( const char * name
)
377 const IORegistryPlane
* plane
;
380 plane
= (const IORegistryPlane
*) gIORegistryPlanes
->getObject( name
);
386 bool IORegistryPlane::serialize(OSSerialize
*s
) const
388 return( nameKey
->serialize(s
) );
391 enum { kIORegCapacityIncrement
= 4 };
393 bool IORegistryEntry::init( OSDictionary
* dict
= 0 )
402 fPropertyTable
= dict
;
405 fPropertyTable
= OSDictionary::withCapacity( kIORegCapacityIncrement
);
407 fPropertyTable
->setCapacityIncrement( kIORegCapacityIncrement
);
413 #ifdef IOREGSPLITTABLES
414 fRegistryTable
= OSDictionary::withCapacity( kIORegCapacityIncrement
);
416 fRegistryTable
->setCapacityIncrement( kIORegCapacityIncrement
);
418 if( (prop
= OSDynamicCast( OSString
, getProperty( gIONameKey
)))) {
419 OSSymbol
* sym
= (OSSymbol
*)OSSymbol::withString( prop
);
420 // ok for OSSymbol too
425 #endif /* IOREGSPLITTABLES */
430 bool IORegistryEntry::init( IORegistryEntry
* old
,
431 const IORegistryPlane
* plane
)
434 IORegistryEntry
* next
;
442 fPropertyTable
= old
->getPropertyTable();
443 fPropertyTable
->retain();
444 #ifdef IOREGSPLITTABLES
445 fRegistryTable
= old
->fRegistryTable
;
446 old
->fRegistryTable
= OSDictionary::withDictionary( fRegistryTable
);
447 #endif /* IOREGSPLITTABLES */
449 old
->registryTable()->removeObject( plane
->keys
[ kParentSetIndex
] );
450 old
->registryTable()->removeObject( plane
->keys
[ kChildSetIndex
] );
452 all
= getParentSetReference( plane
);
453 if( all
) for( index
= 0;
454 (next
= (IORegistryEntry
*) all
->getObject(index
));
456 next
->makeLink( this, kChildSetIndex
, plane
);
457 next
->breakLink( old
, kChildSetIndex
, plane
);
460 all
= getChildSetReference( plane
);
461 if( all
) for( index
= 0;
462 (next
= (IORegistryEntry
*) all
->getObject(index
));
464 next
->makeLink( this, kParentSetIndex
, plane
);
465 next
->breakLink( old
, kParentSetIndex
, plane
);
473 void IORegistryEntry::free( void )
477 #define msg ": attached at free()"
478 char buf
[ strlen(msg
) + 40 ];
480 if( registryTable() && gIOServicePlane
) {
481 if( getParentSetReference( gIOServicePlane
)
482 || getChildSetReference( gIOServicePlane
)) {
484 strncpy( buf
, getName(), 32);
492 if( getPropertyTable())
493 getPropertyTable()->release();
495 #ifdef IOREGSPLITTABLES
497 registryTable()->release();
498 #endif /* IOREGSPLITTABLES */
503 void IORegistryEntry::setPropertyTable( OSDictionary
* dict
)
506 fPropertyTable
->release();
509 fPropertyTable
= dict
;
512 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
514 /* Wrappers to synchronize property table */
516 #define wrap1(func,type,constant) \
518 IORegistryEntry::func ## Property( type * aKey) constant \
523 obj = getPropertyTable()->func ## Object( aKey ); \
529 #define wrap2(type,constant) \
531 IORegistryEntry::copyProperty( type * aKey) constant \
536 obj = getPropertyTable()->getObject( aKey ); \
544 #define wrap3(func,type,constant) \
546 IORegistryEntry::func ## Property( type * aKey) constant \
549 getPropertyTable()->func ## Object( aKey ); \
553 #define wrap4(type,constant) \
555 IORegistryEntry::getProperty( type * aKey, \
556 const IORegistryPlane * plane, \
557 IOOptionBits options ) constant \
559 OSObject * obj = getProperty( aKey ); \
561 if ( (0 == obj) && plane && (options & kIORegistryIterateRecursively) ) { \
562 IORegistryEntry * entry = (IORegistryEntry *) this; \
563 IORegistryIterator * iter; \
564 iter = IORegistryIterator::iterateOver( entry, plane, options ); \
567 while ( (0 == obj) && (entry = iter->getNextObject()) ) { \
568 obj = entry->getProperty( aKey ); \
577 #define wrap5(type,constant) \
579 IORegistryEntry::copyProperty( type * aKey, \
580 const IORegistryPlane * plane, \
581 IOOptionBits options ) constant \
583 OSObject * obj = copyProperty( aKey ); \
585 if ( (0 == obj) && plane && (options & kIORegistryIterateRecursively) ) { \
586 IORegistryEntry * entry = (IORegistryEntry *) this; \
587 IORegistryIterator * iter; \
588 iter = IORegistryIterator::iterateOver( entry, plane, options ); \
591 while ( (0 == obj) && (entry = iter->getNextObject()) ) { \
592 obj = entry->copyProperty( aKey ); \
601 bool IORegistryEntry::serializeProperties( OSSerialize
* s
) const
605 // setProperty( getRetainCount(), 32, "__retain" );
608 ok
= getPropertyTable()->serialize( s
);
614 OSDictionary
* IORegistryEntry::dictionaryWithProperties( void ) const
619 dict
= OSDictionary::withDictionary( getPropertyTable(),
620 getPropertyTable()->getCapacity() );
626 IOReturn
IORegistryEntry::setProperties( OSObject
* properties
)
628 return( kIOReturnUnsupported
);
631 wrap1(get
, const OSSymbol
, const) // getProperty() definition
632 wrap1(get
, const OSString
, const) // getProperty() definition
633 wrap1(get
, const char, const) // getProperty() definition
635 wrap2(const OSSymbol
, const) // copyProperty() definition
636 wrap2(const OSString
, const) // copyProperty() definition
637 wrap2(const char, const) // copyProperty() definition
639 wrap3(remove
, const OSSymbol
,) // removeProperty() definition
640 wrap3(remove
, const OSString
,) // removeProperty() definition
641 wrap3(remove
, const char,) // removeProperty() definition
643 wrap4(const OSSymbol
, const) // getProperty() w/plane definition
644 wrap4(const OSString
, const) // getProperty() w/plane definition
645 wrap4(const char, const) // getProperty() w/plane definition
647 wrap5(const OSSymbol
, const) // copyProperty() w/plane definition
648 wrap5(const OSString
, const) // copyProperty() w/plane definition
649 wrap5(const char, const) // copyProperty() w/plane definition
653 IORegistryEntry::setProperty( const OSSymbol
* aKey
, OSObject
* anObject
)
657 ret
= getPropertyTable()->setObject( aKey
, anObject
);
664 IORegistryEntry::setProperty( const OSString
* aKey
, OSObject
* anObject
)
668 ret
= getPropertyTable()->setObject( aKey
, anObject
);
675 IORegistryEntry::setProperty( const char * aKey
, OSObject
* anObject
)
679 ret
= getPropertyTable()->setObject( aKey
, anObject
);
686 IORegistryEntry::setProperty(const char * aKey
, const char * aString
)
689 OSSymbol
* aSymbol
= (OSSymbol
*) OSSymbol::withCString( aString
);
693 ret
= getPropertyTable()->setObject( aKey
, aSymbol
);
701 IORegistryEntry::setProperty(const char * aKey
, bool aBoolean
)
704 OSBoolean
* aBooleanObj
= OSBoolean::withBoolean( aBoolean
);
708 ret
= getPropertyTable()->setObject( aKey
, aBooleanObj
);
710 aBooleanObj
->release();
716 IORegistryEntry::setProperty( const char * aKey
,
717 unsigned long long aValue
,
718 unsigned int aNumberOfBits
)
721 OSNumber
* anOffset
= OSNumber::withNumber( aValue
, aNumberOfBits
);
725 ret
= getPropertyTable()->setObject( aKey
, anOffset
);
733 IORegistryEntry::setProperty( const char * aKey
,
738 OSData
* data
= OSData::withBytes( bytes
, length
);
742 ret
= getPropertyTable()->setObject( aKey
, data
);
749 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
751 /* Name, location, paths */
753 const char * IORegistryEntry::getName( const IORegistryPlane
* plane
= 0 ) const
759 sym
= (OSSymbol
*) registryTable()->getObject( plane
->pathNameKey
);
761 sym
= (OSSymbol
*) registryTable()->getObject( gIONameKey
);
765 return( sym
->getCStringNoCopy());
767 return( (getMetaClass())->getClassName());
770 const OSSymbol
* IORegistryEntry::copyName(
771 const IORegistryPlane
* plane
= 0 ) const
777 sym
= (OSSymbol
*) registryTable()->getObject( plane
->pathNameKey
);
779 sym
= (OSSymbol
*) registryTable()->getObject( gIONameKey
);
787 return( OSSymbol::withCString((getMetaClass())->getClassName()) );
790 const OSSymbol
* IORegistryEntry::copyLocation(
791 const IORegistryPlane
* plane
= 0 ) const
797 sym
= (OSSymbol
*) registryTable()->getObject( plane
->pathLocationKey
);
799 sym
= (OSSymbol
*) registryTable()->getObject( gIOLocationKey
);
807 const char * IORegistryEntry::getLocation( const IORegistryPlane
* plane
= 0 ) const
809 const OSSymbol
* sym
= copyLocation( plane
);
810 const char * result
= 0;
813 result
= sym
->getCStringNoCopy();
820 void IORegistryEntry::setName( const OSSymbol
* name
,
821 const IORegistryPlane
* plane
= 0 )
823 const OSSymbol
* key
;
827 key
= plane
->pathNameKey
;
832 registryTable()->setObject( key
, (OSObject
*) name
);
837 void IORegistryEntry::setName( const char * name
,
838 const IORegistryPlane
* plane
= 0 )
840 OSSymbol
* sym
= (OSSymbol
*)OSSymbol::withCString( name
);
842 setName( sym
, plane
);
847 void IORegistryEntry::setLocation( const OSSymbol
* location
,
848 const IORegistryPlane
* plane
= 0 )
850 const OSSymbol
* key
;
854 key
= plane
->pathLocationKey
;
856 key
= gIOLocationKey
;
859 registryTable()->setObject( key
, (OSObject
*) location
);
864 void IORegistryEntry::setLocation( const char * location
,
865 const IORegistryPlane
* plane
= 0 )
867 OSSymbol
* sym
= (OSSymbol
*)OSSymbol::withCString( location
);
869 setLocation( sym
, plane
);
875 IORegistryEntry::compareName( OSString
* name
, OSString
** matched
= 0 ) const
877 const OSSymbol
* sym
= copyName();
880 isEqual
= sym
->isEqualTo( name
);
882 if( isEqual
&& matched
) {
894 IORegistryEntry::compareNames( OSObject
* names
, OSString
** matched
= 0 ) const
897 OSCollection
* collection
;
898 OSIterator
* iter
= 0;
901 if( (collection
= OSDynamicCast( OSCollection
, names
))) {
902 iter
= OSCollectionIterator::withCollection( collection
);
905 string
= OSDynamicCast( OSString
, names
);
909 result
= compareName( string
, matched
);
911 } while( (false == result
)
912 && iter
&& (string
= OSDynamicCast( OSString
, iter
->getNextObject())));
921 bool IORegistryEntry::getPath( char * path
, int * length
,
922 const IORegistryPlane
* plane
) const
925 IORegistryEntry
* root
;
926 const IORegistryEntry
* entry
;
927 IORegistryEntry
* parent
;
928 const OSSymbol
* alias
;
930 int len
, maxLength
, compLen
;
934 if( !path
|| !length
|| !plane
)
938 maxLength
= *length
- 2;
941 len
= plane
->nameKey
->getLength();
942 if( len
>= maxLength
)
944 strcpy( nextComp
, plane
->nameKey
->getCStringNoCopy());
945 nextComp
[ len
++ ] = ':';
948 if( (alias
= hasAlias( plane
))) {
949 len
+= alias
->getLength();
950 ok
= (maxLength
> len
);
953 strcpy( nextComp
, alias
->getCStringNoCopy());
958 parent
= entry
->getParentEntry( plane
);
960 // Error if not attached in plane
963 stack
= OSArray::withCapacity( getDepth( plane
));
969 root
= gRegistryRoot
->getChildEntry( plane
);
970 while( parent
&& (entry
!= root
)) {
972 stack
->setObject( (OSObject
*) entry
);
974 parent
= entry
->getParentEntry( plane
);
977 index
= stack
->getCount();
986 } else while( ok
&& ((--index
) >= 0)) {
988 entry
= (IORegistryEntry
*) stack
->getObject((unsigned int) index
);
991 if( (alias
= entry
->hasAlias( plane
))) {
992 len
= plane
->nameKey
->getLength() + 1;
993 nextComp
= path
+ len
;
995 compLen
= alias
->getLength();
996 ok
= (maxLength
> len
+ compLen
);
998 strcpy( nextComp
, alias
->getCStringNoCopy());
1000 compLen
= maxLength
- len
;
1001 ok
= entry
->getPathComponent( nextComp
+ 1, &compLen
, plane
);
1003 if( ok
&& compLen
) {
1011 nextComp
+= compLen
;
1023 bool IORegistryEntry::getPathComponent( char * path
, int * length
,
1024 const IORegistryPlane
* plane
) const
1026 int len
, locLen
, maxLength
;
1027 const char * compName
;
1031 maxLength
= *length
;
1033 compName
= getName( plane
);
1034 len
= strlen( compName
);
1035 if( (loc
= getLocation( plane
)))
1036 locLen
= 1 + strlen( loc
);
1040 ok
= ((len
+ locLen
) < maxLength
);
1042 strcpy( path
, compName
);
1047 strcpy( path
, loc
);
1055 const char * IORegistryEntry::matchPathLocation( const char * cmp
,
1056 const IORegistryPlane
* plane
)
1059 const char * result
= 0;
1060 u_quad_t num1
, num2
;
1063 str
= getLocation( plane
);
1067 num1
= strtouq( cmp
, (char **) &cmp
, 16 );
1069 num2
= strtouq( str
, (char **) &str
, 16 );
1079 if( (c2
== ':') && (c2
== c1
)) {
1101 IORegistryEntry
* IORegistryEntry::getChildFromComponent( const char ** opath
,
1102 const IORegistryPlane
* plane
)
1104 IORegistryEntry
* entry
= 0;
1108 const char * cmp
= 0;
1113 set
= getChildSetReference( plane
);
1119 (entry
= (IORegistryEntry
*) set
->getObject(index
));
1125 str
= entry
->getName( plane
);
1126 len
= strlen( str
);
1127 if( strncmp( str
, cmp
, len
))
1132 if( (c
== 0) || (c
== '/') || (c
== ':'))
1138 if( (cmp
= entry
->matchPathLocation( cmp
, plane
)))
1148 const OSSymbol
* IORegistryEntry::hasAlias( const IORegistryPlane
* plane
,
1149 char * opath
= 0, int * length
= 0 ) const
1151 IORegistryEntry
* entry
;
1152 IORegistryEntry
* entry2
;
1153 const OSSymbol
* key
;
1154 const OSSymbol
* bestKey
= 0;
1157 const char * path
= "/aliases";
1159 entry
= IORegistryEntry::fromPath( path
, plane
);
1162 if( (iter
= OSCollectionIterator::withCollection(
1163 entry
->getPropertyTable() ))) {
1165 while( (key
= (OSSymbol
*) iter
->getNextObject())) {
1167 data
= (OSData
*) entry
->getProperty( key
);
1168 path
= (const char *) data
->getBytesNoCopy();
1169 if( (entry2
= IORegistryEntry::fromPath( path
, plane
,
1171 if( this == entry2
) {
1173 || (bestKey
->getLength() > key
->getLength()))
1174 // pick the smallest alias
1188 const char * IORegistryEntry::dealiasPath(
1189 const char ** opath
,
1190 const IORegistryPlane
* plane
)
1192 IORegistryEntry
* entry
;
1194 const char * path
= *opath
;
1195 const char * rpath
= 0;
1198 char temp
[ kIOMaxPlaneName
+ 1 ];
1205 while( (c
= *end
++) && (c
!= '/') && (c
!= ':'))
1208 if( (end
- path
) < kIOMaxPlaneName
) {
1209 strncpy( temp
, path
, end
- path
);
1210 temp
[ end
- path
] = 0;
1213 entry
= IORegistryEntry::fromPath( "/aliases", plane
);
1215 data
= (OSData
*) entry
->getProperty( temp
);
1217 rpath
= (const char *) data
->getBytesNoCopy();
1229 IORegistryEntry
* IORegistryEntry::fromPath(
1231 const IORegistryPlane
* plane
= 0,
1234 IORegistryEntry
* fromEntry
= 0 )
1236 IORegistryEntry
* where
= 0;
1237 IORegistryEntry
* next
;
1243 char temp
[ kIOMaxPlaneName
+ 1 ];
1250 end
= strchr( path
, ':' );
1251 if( end
&& ((end
- path
) < kIOMaxPlaneName
)) {
1252 strncpy( temp
, path
, end
- path
);
1253 temp
[ end
- path
] = 0;
1254 plane
= getPlane( temp
);
1263 if( (alias
= dealiasPath( &end
, plane
))) {
1266 where
= IORegistryEntry::fromPath( alias
, plane
,
1267 opath
, &len
, fromEntry
);
1278 if( (0 == fromEntry
) && (*path
++ == '/'))
1279 fromEntry
= gRegistryRoot
->getChildEntry( plane
);
1286 if( c
&& (c
!= ':')) // check valid terminator
1291 next
= where
->getChildFromComponent( &path
, plane
);
1297 // check residual path
1298 if( where
!= fromEntry
)
1301 if( opath
&& length
) {
1302 // copy out residual path
1303 len2
= len
+ strlen( path
);
1305 strcpy( opath
+ len
, path
);
1309 // no residual path => must be no tail for success
1321 IORegistryEntry
* IORegistryEntry::childFromPath(
1323 const IORegistryPlane
* plane
= 0,
1327 return( IORegistryEntry::fromPath( path
, plane
, opath
, len
, this ));
1330 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1332 #define IOLinkIterator OSCollectionIterator
1335 #define super OSObject
1337 inline bool IORegistryEntry::arrayMember( OSArray
* set
,
1338 const IORegistryEntry
* member
,
1339 unsigned int * index
= 0 ) const
1342 OSObject
* probeObject
;
1344 for( i
= 0; (probeObject
= set
->getObject(i
)); i
++) {
1345 if (probeObject
== (OSObject
*) member
) {
1354 bool IORegistryEntry::makeLink( IORegistryEntry
* to
,
1355 unsigned int relation
,
1356 const IORegistryPlane
* plane
) const
1359 bool result
= false;
1361 if( (links
= (OSArray
*)
1362 registryTable()->getObject( plane
->keys
[ relation
] ))) {
1364 result
= arrayMember( links
, to
);
1366 result
= links
->setObject( to
);
1370 links
= OSArray::withObjects( & (const OSObject
*) to
, 1, 1 );
1371 result
= (links
!= 0);
1373 result
= registryTable()->setObject( plane
->keys
[ relation
],
1382 void IORegistryEntry::breakLink( IORegistryEntry
* to
,
1383 unsigned int relation
,
1384 const IORegistryPlane
* plane
) const
1389 if( (links
= (OSArray
*)
1390 registryTable()->getObject( plane
->keys
[ relation
]))) {
1392 if( arrayMember( links
, to
, &index
)) {
1393 links
->removeObject( index
);
1394 if( 0 == links
->getCount())
1395 registryTable()->removeObject( plane
->keys
[ relation
]);
1401 OSArray
* IORegistryEntry::getParentSetReference(
1402 const IORegistryPlane
* plane
) const
1405 return( (OSArray
*) registryTable()->getObject(
1406 plane
->keys
[ kParentSetIndex
]));
1411 OSIterator
* IORegistryEntry::getParentIterator(
1412 const IORegistryPlane
* plane
) const
1421 links
= getParentSetReference( plane
);
1423 links
= OSArray::withCapacity( 1 );
1425 links
= OSArray::withArray( links
, links
->getCount() );
1428 iter
= IOLinkIterator::withCollection( links
);
1436 IORegistryEntry
* IORegistryEntry::copyParentEntry( const IORegistryPlane
* plane
) const
1438 IORegistryEntry
* entry
= 0;
1443 if( (links
= getParentSetReference( plane
))) {
1444 entry
= (IORegistryEntry
*) links
->getObject( 0 );
1453 IORegistryEntry
* IORegistryEntry::getParentEntry( const IORegistryPlane
* plane
) const
1455 IORegistryEntry
* entry
;
1457 entry
= copyParentEntry( plane
);
1464 OSArray
* IORegistryEntry::getChildSetReference( const IORegistryPlane
* plane
) const
1467 return( (OSArray
*) registryTable()->getObject(
1468 plane
->keys
[ kChildSetIndex
]));
1473 OSIterator
* IORegistryEntry::getChildIterator( const IORegistryPlane
* plane
) const
1482 links
= getChildSetReference( plane
);
1484 links
= OSArray::withCapacity( 1 );
1486 links
= OSArray::withArray( links
, links
->getCount() );
1489 iter
= IOLinkIterator::withCollection( links
);
1498 IORegistryEntry
* IORegistryEntry::copyChildEntry(
1499 const IORegistryPlane
* plane
) const
1501 IORegistryEntry
* entry
= 0;
1506 if( (links
= getChildSetReference( plane
))) {
1507 entry
= (IORegistryEntry
*) links
->getObject( 0 );
1516 IORegistryEntry
* IORegistryEntry::getChildEntry(
1517 const IORegistryPlane
* plane
) const
1519 IORegistryEntry
* entry
;
1521 entry
= copyChildEntry( plane
);
1528 void IORegistryEntry::applyToChildren( IORegistryEntryApplierFunction applier
,
1530 const IORegistryPlane
* plane
) const
1534 IORegistryEntry
* next
;
1540 array
= OSArray::withArray( getChildSetReference( plane
));
1544 (next
= (IORegistryEntry
*) array
->getObject( index
));
1546 (*applier
)(next
, context
);
1551 void IORegistryEntry::applyToParents( IORegistryEntryApplierFunction applier
,
1553 const IORegistryPlane
* plane
) const
1557 IORegistryEntry
* next
;
1563 array
= OSArray::withArray( getParentSetReference( plane
));
1567 (next
= (IORegistryEntry
*) array
->getObject( index
));
1569 (*applier
)(next
, context
);
1574 bool IORegistryEntry::isChild( IORegistryEntry
* child
,
1575 const IORegistryPlane
* plane
,
1576 bool onlyChild
= false ) const
1583 if( (links
= getChildSetReference( plane
))) {
1584 if( (!onlyChild
) || (1 == links
->getCount()))
1585 ret
= arrayMember( links
, child
);
1587 if( ret
&& (links
= child
->getParentSetReference( plane
)))
1588 ret
= arrayMember( links
, this );
1595 bool IORegistryEntry::isParent( IORegistryEntry
* parent
,
1596 const IORegistryPlane
* plane
,
1597 bool onlyParent
= false ) const
1605 if( (links
= getParentSetReference( plane
))) {
1606 if( (!onlyParent
) || (1 == links
->getCount()))
1607 ret
= arrayMember( links
, parent
);
1609 if( ret
&& (links
= parent
->getChildSetReference( plane
)))
1610 ret
= arrayMember( links
, this );
1617 bool IORegistryEntry::inPlane( const IORegistryPlane
* plane
) const
1623 ret
= (0 != getParentSetReference( plane
));
1630 bool IORegistryEntry::attachToParent( IORegistryEntry
* parent
,
1631 const IORegistryPlane
* plane
)
1642 ret
= makeLink( parent
, kParentSetIndex
, plane
);
1644 if( (links
= parent
->getChildSetReference( plane
)))
1645 needParent
= (false == arrayMember( links
, this ));
1649 // ret &= parent->makeLink( this, kChildSetIndex, plane );
1654 ret
&= parent
->attachToChild( this, plane
);
1659 bool IORegistryEntry::attachToChild( IORegistryEntry
* child
,
1660 const IORegistryPlane
* plane
)
1671 ret
= makeLink( child
, kChildSetIndex
, plane
);
1673 if( (links
= child
->getParentSetReference( plane
)))
1674 needChild
= (false == arrayMember( links
, this ));
1681 ret
&= child
->attachToParent( this, plane
);
1686 void IORegistryEntry::detachFromParent( IORegistryEntry
* parent
,
1687 const IORegistryPlane
* plane
)
1696 breakLink( parent
, kParentSetIndex
, plane
);
1698 if( (links
= parent
->getChildSetReference( plane
)))
1699 needParent
= arrayMember( links
, this );
1703 // parent->breakLink( this, kChildSetIndex, plane );
1708 parent
->detachFromChild( this, plane
);
1713 void IORegistryEntry::detachFromChild( IORegistryEntry
* child
,
1714 const IORegistryPlane
* plane
)
1723 breakLink( child
, kChildSetIndex
, plane
);
1725 if( (links
= child
->getParentSetReference( plane
)))
1726 needChild
= arrayMember( links
, this );
1733 child
->detachFromParent( this, plane
);
1738 void IORegistryEntry::detachAbove( const IORegistryPlane
* plane
)
1740 IORegistryEntry
* parent
;
1743 while( (parent
= getParentEntry( plane
)))
1744 detachFromParent( parent
, plane
);
1748 void IORegistryEntry::detachAll( const IORegistryPlane
* plane
)
1751 IORegistryEntry
* next
;
1752 IORegistryIterator
* regIter
;
1754 regIter
= IORegistryIterator::iterateOver( this, plane
, true );
1757 all
= regIter
->iterateAll();
1760 detachAbove( plane
);
1762 while( (next
= (IORegistryEntry
*) all
->getLastObject())) {
1765 all
->removeObject(next
);
1767 next
->detachAbove( plane
);
1774 unsigned int IORegistryEntry::getDepth( const IORegistryPlane
* plane
) const
1776 unsigned int depth
= 1;
1778 unsigned int oneDepth
, maxParentDepth
, count
;
1779 IORegistryEntry
* one
;
1780 const IORegistryEntry
* next
;
1786 while( (parents
= next
->getParentSetReference( plane
))) {
1788 count
= parents
->getCount();
1793 next
= (IORegistryEntry
*) parents
->getObject( 0 );
1798 (one
= (IORegistryEntry
*) parents
->getObject( index
));
1800 oneDepth
= one
->getDepth( plane
);
1801 if( oneDepth
> maxParentDepth
)
1802 maxParentDepth
= oneDepth
;
1804 depth
+= maxParentDepth
;
1814 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1817 #define super OSIterator
1819 OSDefineMetaClassAndStructors(IORegistryIterator
, OSIterator
)
1821 enum { kIORegistryIteratorInvalidFlag
= 0x80000000 };
1823 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1825 IORegistryIterator
*
1826 IORegistryIterator::iterateOver( IORegistryEntry
* root
,
1827 const IORegistryPlane
* plane
,
1828 IOOptionBits options
= 0 )
1830 IORegistryIterator
* create
;
1837 create
= new IORegistryIterator
;
1839 if( create
->init()) {
1842 create
->root
= root
;
1843 create
->where
= &create
->start
;
1844 create
->start
.current
= root
;
1845 create
->plane
= plane
;
1846 create
->options
= options
& ~kIORegistryIteratorInvalidFlag
;
1856 IORegistryIterator
*
1857 IORegistryIterator::iterateOver( const IORegistryPlane
* plane
,
1858 IOOptionBits options
= 0 )
1860 return( iterateOver( gRegistryRoot
, plane
, options
));
1863 bool IORegistryIterator::isValid( void )
1872 ok
= (0 == (kIORegistryIteratorInvalidFlag
& options
));
1874 while( ok
&& next
) {
1876 ok
= where
->iter
->isValid();
1884 void IORegistryIterator::enterEntry( const IORegistryPlane
* enterPlane
)
1889 where
= (IORegCursor
*) IOMalloc( sizeof( IORegCursor
));
1895 where
->current
= prev
->current
;
1900 void IORegistryIterator::enterEntry( void )
1902 enterEntry( plane
);
1905 bool IORegistryIterator::exitEntry( void )
1910 where
->iter
->release();
1912 if( where
->current
)// && (where != &start))
1913 where
->current
->release();
1916 if( where
!= &start
) {
1919 IOFree( gone
, sizeof( IORegCursor
));
1926 void IORegistryIterator::reset( void )
1936 where
->current
= root
;
1937 options
&= ~kIORegistryIteratorInvalidFlag
;
1940 void IORegistryIterator::free( void )
1951 IORegistryEntry
* IORegistryIterator::getNextObjectFlat( void )
1953 IORegistryEntry
* next
= 0;
1954 OSArray
* links
= 0;
1958 if( (0 == where
->iter
)) {
1959 // just entered - create new iter
1962 && (links
= ( (options
& kIORegistryIterateParents
) ?
1963 where
->current
->getParentSetReference( plane
) :
1964 where
->current
->getChildSetReference( plane
) )) )
1966 where
->iter
= OSCollectionIterator::withCollection( links
);
1969 // next sibling - release current
1971 where
->current
->release();
1975 next
= (IORegistryEntry
*) where
->iter
->getNextObject();
1979 else if( !where
->iter
->isValid())
1980 options
|= kIORegistryIteratorInvalidFlag
;
1983 where
->current
= next
;
1990 IORegistryEntry
* IORegistryIterator::getNextObjectRecursive( void )
1992 IORegistryEntry
* next
;
1995 next
= getNextObjectFlat();
1996 while( (0 == next
) && exitEntry());
2000 done
= OSOrderedSet::withCapacity( 10 );
2001 if( done
->setObject((OSObject
*) next
)) {
2002 // done set didn't contain this one, so recurse
2009 IORegistryEntry
* IORegistryIterator::getNextObject( void )
2011 if( options
& kIORegistryIterateRecursively
)
2012 return( getNextObjectRecursive());
2014 return( getNextObjectFlat());
2017 IORegistryEntry
* IORegistryIterator::getCurrentEntry( void )
2020 return( where
->current
);
2025 OSOrderedSet
* IORegistryIterator::iterateAll( void )
2028 while( getNextObjectRecursive())
2035 OSMetaClassDefineReservedUsed(IORegistryEntry
, 0);
2036 OSMetaClassDefineReservedUsed(IORegistryEntry
, 1);
2037 OSMetaClassDefineReservedUsed(IORegistryEntry
, 2);
2038 OSMetaClassDefineReservedUsed(IORegistryEntry
, 3);
2039 OSMetaClassDefineReservedUsed(IORegistryEntry
, 4);
2041 OSMetaClassDefineReservedUnused(IORegistryEntry
, 5);
2042 OSMetaClassDefineReservedUnused(IORegistryEntry
, 6);
2043 OSMetaClassDefineReservedUnused(IORegistryEntry
, 7);
2044 OSMetaClassDefineReservedUnused(IORegistryEntry
, 8);
2045 OSMetaClassDefineReservedUnused(IORegistryEntry
, 9);
2046 OSMetaClassDefineReservedUnused(IORegistryEntry
, 10);
2047 OSMetaClassDefineReservedUnused(IORegistryEntry
, 11);
2048 OSMetaClassDefineReservedUnused(IORegistryEntry
, 12);
2049 OSMetaClassDefineReservedUnused(IORegistryEntry
, 13);
2050 OSMetaClassDefineReservedUnused(IORegistryEntry
, 14);
2051 OSMetaClassDefineReservedUnused(IORegistryEntry
, 15);
2052 OSMetaClassDefineReservedUnused(IORegistryEntry
, 16);
2053 OSMetaClassDefineReservedUnused(IORegistryEntry
, 17);
2054 OSMetaClassDefineReservedUnused(IORegistryEntry
, 18);
2055 OSMetaClassDefineReservedUnused(IORegistryEntry
, 19);
2056 OSMetaClassDefineReservedUnused(IORegistryEntry
, 20);
2057 OSMetaClassDefineReservedUnused(IORegistryEntry
, 21);
2058 OSMetaClassDefineReservedUnused(IORegistryEntry
, 22);
2059 OSMetaClassDefineReservedUnused(IORegistryEntry
, 23);
2060 OSMetaClassDefineReservedUnused(IORegistryEntry
, 24);
2061 OSMetaClassDefineReservedUnused(IORegistryEntry
, 25);
2062 OSMetaClassDefineReservedUnused(IORegistryEntry
, 26);
2063 OSMetaClassDefineReservedUnused(IORegistryEntry
, 27);
2064 OSMetaClassDefineReservedUnused(IORegistryEntry
, 28);
2065 OSMetaClassDefineReservedUnused(IORegistryEntry
, 29);
2066 OSMetaClassDefineReservedUnused(IORegistryEntry
, 30);
2067 OSMetaClassDefineReservedUnused(IORegistryEntry
, 31);