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 class 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
),
170 /* interlock relocked */
173 l
->want_write
= TRUE
;
175 /* Wait for readers (and upgrades) to finish */
177 while ((l
->read_count
!= 0) || l
->want_upgrade
) {
179 i
= lock_wait_time
[l
->can_sleep
? 1 : 0];
181 simple_unlock(&l
->interlock
);
182 while (--i
!= 0 && (l
->read_count
!= 0 ||
185 simple_lock(&l
->interlock
);
188 if (l
->can_sleep
&& (l
->read_count
!= 0 || l
->want_upgrade
)) {
190 thread_sleep_simple_lock((event_t
) l
,
191 simple_lock_addr(l
->interlock
),
193 /* interlock relocked */
197 simple_unlock(&l
->interlock
);
202 register s_lock_t
* l
)
204 boolean_t do_wakeup
= FALSE
;
206 simple_lock(&l
->interlock
);
208 if (l
->read_count
!= 0) {
212 if (l
->want_upgrade
) {
213 l
->want_upgrade
= FALSE
;
216 l
->want_write
= FALSE
;
221 * There is no reason to wakeup a waiting thread
222 * if the read-count is non-zero. Consider:
223 * we must be dropping a read lock
224 * threads are waiting only if one wants a write lock
225 * if there are still readers, they can't proceed
227 if (l
->waiting
&& (l
->read_count
== 0)) {
232 simple_unlock(&l
->interlock
);
235 thread_wakeup((event_t
) l
);
240 register s_lock_t
* l
)
244 simple_lock(&l
->interlock
);
246 while ( l
->want_upgrade
|| ((0 == l
->read_count
) && l
->want_write
)) {
248 i
= lock_wait_time
[l
->can_sleep
? 1 : 0];
251 simple_unlock(&l
->interlock
);
253 (l
->want_upgrade
|| ((0 == l
->read_count
) && l
->want_write
)))
255 simple_lock(&l
->interlock
);
259 (l
->want_upgrade
|| ((0 == l
->read_count
) && l
->want_write
))) {
261 thread_sleep_simple_lock((event_t
) l
,
262 simple_lock_addr(l
->interlock
),
264 /* interlock relocked */
269 simple_unlock(&l
->interlock
);
273 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
275 IORegistryEntry
* IORegistryEntry::initialize( void )
279 if( !gRegistryRoot
) {
281 s_lock_init( &gIORegistryLock
, true );
282 gRegistryRoot
= new IORegistryEntry
;
283 gPropertiesLock
= IORecursiveLockAlloc();
284 gIORegistryPlanes
= OSDictionary::withCapacity( 1 );
286 assert( gRegistryRoot
&& gPropertiesLock
287 && gIORegistryPlanes
);
288 ok
= gRegistryRoot
->init();
290 gIONameKey
= OSSymbol::withCStringNoCopy( "IOName" );
291 gIOLocationKey
= OSSymbol::withCStringNoCopy( "IOLocation" );
293 assert( ok
&& gIONameKey
&& gIOLocationKey
);
295 gRegistryRoot
->setName( "Root" );
296 gRegistryRoot
->setProperty( kIORegistryPlanesKey
, gIORegistryPlanes
);
299 return( gRegistryRoot
);
302 IORegistryEntry
* IORegistryEntry::getRegistryRoot( void )
304 return( gRegistryRoot
);
307 SInt32
IORegistryEntry::getGenerationCount( void )
309 return( gIORegistryGenerationCount
);
313 const IORegistryPlane
* IORegistryEntry::makePlane( const char * name
)
315 IORegistryPlane
* plane
;
316 const OSSymbol
* nameKey
;
317 const OSSymbol
* parentKey
;
318 const OSSymbol
* childKey
;
319 const OSSymbol
* pathNameKey
;
320 const OSSymbol
* pathLocationKey
;
321 char key
[ kIOMaxPlaneName
+ 16 ];
324 strncpy( key
, name
, kIOMaxPlaneName
);
325 key
[ kIOMaxPlaneName
] = 0;
326 end
= key
+ strlen( name
);
328 nameKey
= OSSymbol::withCString( key
);
330 strcpy( end
, "ParentLinks" );
331 parentKey
= OSSymbol::withCString( key
);
333 strcpy( end
, "ChildLinks" );
334 childKey
= OSSymbol::withCString( key
);
336 strcpy( end
, "Name" );
337 pathNameKey
= OSSymbol::withCString( key
);
339 strcpy( end
, "Location" );
340 pathLocationKey
= OSSymbol::withCString( key
);
342 plane
= new IORegistryPlane
;
344 if( plane
&& plane
->init()
345 && nameKey
&& parentKey
&& childKey
346 && pathNameKey
&& pathLocationKey
) {
348 plane
->nameKey
= nameKey
;
349 plane
->keys
[ kParentSetIndex
] = parentKey
;
350 plane
->keys
[ kChildSetIndex
] = childKey
;
351 plane
->pathNameKey
= pathNameKey
;
352 plane
->pathLocationKey
= pathLocationKey
;
355 gIORegistryPlanes
->setObject( nameKey
, plane
);
363 pathLocationKey
->release();
365 pathNameKey
->release();
367 parentKey
->release();
378 const IORegistryPlane
* IORegistryEntry::getPlane( const char * name
)
380 const IORegistryPlane
* plane
;
383 plane
= (const IORegistryPlane
*) gIORegistryPlanes
->getObject( name
);
389 bool IORegistryPlane::serialize(OSSerialize
*s
) const
391 return( nameKey
->serialize(s
) );
394 enum { kIORegCapacityIncrement
= 4 };
396 bool IORegistryEntry::init( OSDictionary
* dict
)
406 fPropertyTable
->release();
407 fPropertyTable
= dict
;
409 } else if( !fPropertyTable
) {
410 fPropertyTable
= OSDictionary::withCapacity( kIORegCapacityIncrement
);
412 fPropertyTable
->setCapacityIncrement( kIORegCapacityIncrement
);
418 #ifdef IOREGSPLITTABLES
419 if( !fRegistryTable
) {
420 fRegistryTable
= OSDictionary::withCapacity( kIORegCapacityIncrement
);
422 fRegistryTable
->setCapacityIncrement( kIORegCapacityIncrement
);
425 if( (prop
= OSDynamicCast( OSString
, getProperty( gIONameKey
)))) {
426 OSSymbol
* sym
= (OSSymbol
*)OSSymbol::withString( prop
);
427 // ok for OSSymbol too
432 #endif /* IOREGSPLITTABLES */
437 bool IORegistryEntry::init( IORegistryEntry
* old
,
438 const IORegistryPlane
* plane
)
441 IORegistryEntry
* next
;
449 fPropertyTable
= old
->getPropertyTable();
450 fPropertyTable
->retain();
451 #ifdef IOREGSPLITTABLES
452 fRegistryTable
= old
->fRegistryTable
;
453 old
->fRegistryTable
= OSDictionary::withDictionary( fRegistryTable
);
454 #endif /* IOREGSPLITTABLES */
456 old
->registryTable()->removeObject( plane
->keys
[ kParentSetIndex
] );
457 old
->registryTable()->removeObject( plane
->keys
[ kChildSetIndex
] );
459 all
= getParentSetReference( plane
);
460 if( all
) for( index
= 0;
461 (next
= (IORegistryEntry
*) all
->getObject(index
));
463 next
->makeLink( this, kChildSetIndex
, plane
);
464 next
->breakLink( old
, kChildSetIndex
, plane
);
467 all
= getChildSetReference( plane
);
468 if( all
) for( index
= 0;
469 (next
= (IORegistryEntry
*) all
->getObject(index
));
471 next
->makeLink( this, kParentSetIndex
, plane
);
472 next
->breakLink( old
, kParentSetIndex
, plane
);
480 void IORegistryEntry::free( void )
484 #define msg ": attached at free()"
485 char buf
[ strlen(msg
) + 40 ];
487 if( registryTable() && gIOServicePlane
) {
488 if( getParentSetReference( gIOServicePlane
)
489 || getChildSetReference( gIOServicePlane
)) {
491 strncpy( buf
, getName(), 32);
499 if( getPropertyTable())
500 getPropertyTable()->release();
502 #ifdef IOREGSPLITTABLES
504 registryTable()->release();
505 #endif /* IOREGSPLITTABLES */
510 void IORegistryEntry::setPropertyTable( OSDictionary
* dict
)
513 fPropertyTable
->release();
516 fPropertyTable
= dict
;
519 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
521 /* Wrappers to synchronize property table */
523 #define wrap2(type, constant) \
525 IORegistryEntry::copyProperty( type * aKey) constant \
530 obj = getProperty( aKey ); \
538 #define wrap4(type,constant) \
540 IORegistryEntry::getProperty( type * aKey, \
541 const IORegistryPlane * plane, \
542 IOOptionBits options ) constant \
544 OSObject * obj = getProperty( aKey ); \
546 if ( (0 == obj) && plane && (options & kIORegistryIterateRecursively) ) { \
547 IORegistryEntry * entry = (IORegistryEntry *) this; \
548 IORegistryIterator * iter; \
549 iter = IORegistryIterator::iterateOver( entry, plane, options ); \
552 while ( (0 == obj) && (entry = iter->getNextObject()) ) { \
553 obj = entry->getProperty( aKey ); \
562 #define wrap5(type,constant) \
564 IORegistryEntry::copyProperty( type * aKey, \
565 const IORegistryPlane * plane, \
566 IOOptionBits options ) constant \
568 OSObject * obj = copyProperty( aKey ); \
570 if ( (0 == obj) && plane && (options & kIORegistryIterateRecursively) ) { \
571 IORegistryEntry * entry = (IORegistryEntry *) this; \
572 IORegistryIterator * iter; \
573 iter = IORegistryIterator::iterateOver( entry, plane, options ); \
576 while ( (0 == obj) && (entry = iter->getNextObject()) ) { \
577 obj = entry->copyProperty( aKey ); \
586 bool IORegistryEntry::serializeProperties( OSSerialize
* s
) const
590 // setProperty( getRetainCount(), 32, "__retain" );
593 ok
= getPropertyTable()->serialize( s
);
599 OSDictionary
* IORegistryEntry::dictionaryWithProperties( void ) const
604 dict
= OSDictionary::withDictionary( getPropertyTable(),
605 getPropertyTable()->getCapacity() );
611 IOReturn
IORegistryEntry::setProperties( OSObject
* properties
)
613 return( kIOReturnUnsupported
);
616 wrap2(const OSSymbol
, const) // copyProperty() definition
617 wrap2(const OSString
, const) // copyProperty() definition
618 wrap2(const char, const) // copyProperty() definition
620 wrap4(const OSSymbol
, const) // getProperty() w/plane definition
621 wrap4(const OSString
, const) // getProperty() w/plane definition
622 wrap4(const char, const) // getProperty() w/plane definition
624 wrap5(const OSSymbol
, const) // copyProperty() w/plane definition
625 wrap5(const OSString
, const) // copyProperty() w/plane definition
626 wrap5(const char, const) // copyProperty() w/plane definition
630 IORegistryEntry::getProperty( const OSSymbol
* aKey
) const
635 obj
= getPropertyTable()->getObject( aKey
);
642 IORegistryEntry::getProperty( const OSString
* aKey
) const
644 const OSSymbol
* tmpKey
= OSSymbol::withString( aKey
);
645 OSObject
* obj
= getProperty( tmpKey
);
652 IORegistryEntry::getProperty( const char * aKey
) const
654 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
655 OSObject
* obj
= getProperty( tmpKey
);
662 IORegistryEntry::removeProperty( const OSSymbol
* aKey
)
665 getPropertyTable()->removeObject( aKey
);
670 IORegistryEntry::removeProperty( const OSString
* aKey
)
672 const OSSymbol
* tmpKey
= OSSymbol::withString( aKey
);
673 removeProperty( tmpKey
);
678 IORegistryEntry::removeProperty( const char * aKey
)
680 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
681 removeProperty( tmpKey
);
686 IORegistryEntry::setProperty( const OSSymbol
* aKey
, OSObject
* anObject
)
690 ret
= getPropertyTable()->setObject( aKey
, anObject
);
697 IORegistryEntry::setProperty( const OSString
* aKey
, OSObject
* anObject
)
699 const OSSymbol
* tmpKey
= OSSymbol::withString( aKey
);
700 bool ret
= setProperty( tmpKey
, anObject
);
707 IORegistryEntry::setProperty( const char * aKey
, OSObject
* anObject
)
709 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
710 bool ret
= setProperty( tmpKey
, anObject
);
717 IORegistryEntry::setProperty(const char * aKey
, const char * aString
)
720 OSSymbol
* aSymbol
= (OSSymbol
*) OSSymbol::withCString( aString
);
723 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
724 ret
= setProperty( tmpKey
, aSymbol
);
733 IORegistryEntry::setProperty(const char * aKey
, bool aBoolean
)
736 OSBoolean
* aBooleanObj
= OSBoolean::withBoolean( aBoolean
);
739 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
740 ret
= setProperty( tmpKey
, aBooleanObj
);
743 aBooleanObj
->release();
749 IORegistryEntry::setProperty( const char * aKey
,
750 unsigned long long aValue
,
751 unsigned int aNumberOfBits
)
754 OSNumber
* anOffset
= OSNumber::withNumber( aValue
, aNumberOfBits
);
757 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
758 ret
= setProperty( tmpKey
, anOffset
);
767 IORegistryEntry::setProperty( const char * aKey
,
772 OSData
* data
= OSData::withBytes( bytes
, length
);
775 const OSSymbol
* tmpKey
= OSSymbol::withCString( aKey
);
776 ret
= setProperty( tmpKey
, data
);
784 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
786 /* Name, location, paths */
788 const char * IORegistryEntry::getName( const IORegistryPlane
* plane
) const
794 sym
= (OSSymbol
*) registryTable()->getObject( plane
->pathNameKey
);
796 sym
= (OSSymbol
*) registryTable()->getObject( gIONameKey
);
800 return( sym
->getCStringNoCopy());
802 return( (getMetaClass())->getClassName());
805 const OSSymbol
* IORegistryEntry::copyName(
806 const IORegistryPlane
* plane
) const
812 sym
= (OSSymbol
*) registryTable()->getObject( plane
->pathNameKey
);
814 sym
= (OSSymbol
*) registryTable()->getObject( gIONameKey
);
822 return( OSSymbol::withCString((getMetaClass())->getClassName()) );
825 const OSSymbol
* IORegistryEntry::copyLocation(
826 const IORegistryPlane
* plane
) const
832 sym
= (OSSymbol
*) registryTable()->getObject( plane
->pathLocationKey
);
834 sym
= (OSSymbol
*) registryTable()->getObject( gIOLocationKey
);
842 const char * IORegistryEntry::getLocation( const IORegistryPlane
* plane
) const
844 const OSSymbol
* sym
= copyLocation( plane
);
845 const char * result
= 0;
848 result
= sym
->getCStringNoCopy();
855 void IORegistryEntry::setName( const OSSymbol
* name
,
856 const IORegistryPlane
* plane
)
858 const OSSymbol
* key
;
862 key
= plane
->pathNameKey
;
867 registryTable()->setObject( key
, (OSObject
*) name
);
872 void IORegistryEntry::setName( const char * name
,
873 const IORegistryPlane
* plane
)
875 OSSymbol
* sym
= (OSSymbol
*)OSSymbol::withCString( name
);
877 setName( sym
, plane
);
882 void IORegistryEntry::setLocation( const OSSymbol
* location
,
883 const IORegistryPlane
* plane
)
885 const OSSymbol
* key
;
889 key
= plane
->pathLocationKey
;
891 key
= gIOLocationKey
;
894 registryTable()->setObject( key
, (OSObject
*) location
);
899 void IORegistryEntry::setLocation( const char * location
,
900 const IORegistryPlane
* plane
)
902 OSSymbol
* sym
= (OSSymbol
*)OSSymbol::withCString( location
);
904 setLocation( sym
, plane
);
910 IORegistryEntry::compareName( OSString
* name
, OSString
** matched
) const
912 const OSSymbol
* sym
= copyName();
915 isEqual
= sym
->isEqualTo( name
);
917 if( isEqual
&& matched
) {
929 IORegistryEntry::compareNames( OSObject
* names
, OSString
** matched
) const
932 OSCollection
* collection
;
933 OSIterator
* iter
= 0;
936 if( (collection
= OSDynamicCast( OSCollection
, names
))) {
937 iter
= OSCollectionIterator::withCollection( collection
);
940 string
= OSDynamicCast( OSString
, names
);
944 result
= compareName( string
, matched
);
946 } while( (false == result
)
947 && iter
&& (string
= OSDynamicCast( OSString
, iter
->getNextObject())));
956 bool IORegistryEntry::getPath( char * path
, int * length
,
957 const IORegistryPlane
* plane
) const
960 IORegistryEntry
* root
;
961 const IORegistryEntry
* entry
;
962 IORegistryEntry
* parent
;
963 const OSSymbol
* alias
;
965 int len
, maxLength
, compLen
;
969 if( !path
|| !length
|| !plane
)
973 maxLength
= *length
- 2;
976 len
= plane
->nameKey
->getLength();
977 if( len
>= maxLength
)
979 strcpy( nextComp
, plane
->nameKey
->getCStringNoCopy());
980 nextComp
[ len
++ ] = ':';
983 if( (alias
= hasAlias( plane
))) {
984 len
+= alias
->getLength();
985 ok
= (maxLength
> len
);
988 strcpy( nextComp
, alias
->getCStringNoCopy());
993 parent
= entry
->getParentEntry( plane
);
995 // Error if not attached in plane
998 stack
= OSArray::withCapacity( getDepth( plane
));
1004 root
= gRegistryRoot
->getChildEntry( plane
);
1005 while( parent
&& (entry
!= root
)) {
1007 stack
->setObject( (OSObject
*) entry
);
1009 parent
= entry
->getParentEntry( plane
);
1012 index
= stack
->getCount();
1021 } else while( ok
&& ((--index
) >= 0)) {
1023 entry
= (IORegistryEntry
*) stack
->getObject((unsigned int) index
);
1026 if( (alias
= entry
->hasAlias( plane
))) {
1027 len
= plane
->nameKey
->getLength() + 1;
1028 nextComp
= path
+ len
;
1030 compLen
= alias
->getLength();
1031 ok
= (maxLength
> len
+ compLen
);
1033 strcpy( nextComp
, alias
->getCStringNoCopy());
1035 compLen
= maxLength
- len
;
1036 ok
= entry
->getPathComponent( nextComp
+ 1, &compLen
, plane
);
1038 if( ok
&& compLen
) {
1046 nextComp
+= compLen
;
1058 bool IORegistryEntry::getPathComponent( char * path
, int * length
,
1059 const IORegistryPlane
* plane
) const
1061 int len
, locLen
, maxLength
;
1062 const char * compName
;
1066 maxLength
= *length
;
1068 compName
= getName( plane
);
1069 len
= strlen( compName
);
1070 if( (loc
= getLocation( plane
)))
1071 locLen
= 1 + strlen( loc
);
1075 ok
= ((len
+ locLen
) < maxLength
);
1077 strcpy( path
, compName
);
1082 strcpy( path
, loc
);
1090 const char * IORegistryEntry::matchPathLocation( const char * cmp
,
1091 const IORegistryPlane
* plane
)
1094 const char * result
= 0;
1095 u_quad_t num1
, num2
;
1096 char lastPathChar
, lastLocationChar
;
1098 str
= getLocation( plane
);
1100 lastPathChar
= cmp
[0];
1101 lastLocationChar
= str
[0];
1104 num1
= strtouq( cmp
, (char **) &cmp
, 16 );
1105 lastPathChar
= *cmp
++;
1109 if( lastLocationChar
) {
1110 num2
= strtouq( str
, (char **) &str
, 16 );
1111 lastLocationChar
= *str
++;
1118 if (!lastPathChar
&& !lastLocationChar
) {
1123 if( (',' != lastPathChar
) && (':' != lastPathChar
))
1126 if (lastPathChar
&& lastLocationChar
&& (lastPathChar
!= lastLocationChar
))
1135 IORegistryEntry
* IORegistryEntry::getChildFromComponent( const char ** opath
,
1136 const IORegistryPlane
* plane
)
1138 IORegistryEntry
* entry
= 0;
1142 const char * cmp
= 0;
1147 set
= getChildSetReference( plane
);
1153 (entry
= (IORegistryEntry
*) set
->getObject(index
));
1159 str
= entry
->getName( plane
);
1160 len
= strlen( str
);
1161 if( strncmp( str
, cmp
, len
))
1166 if( (c
== 0) || (c
== '/') || (c
== ':'))
1172 if( (cmp
= entry
->matchPathLocation( cmp
, plane
)))
1182 const OSSymbol
* IORegistryEntry::hasAlias( const IORegistryPlane
* plane
,
1183 char * opath
, int * length
) const
1185 IORegistryEntry
* entry
;
1186 IORegistryEntry
* entry2
;
1187 const OSSymbol
* key
;
1188 const OSSymbol
* bestKey
= 0;
1191 const char * path
= "/aliases";
1193 entry
= IORegistryEntry::fromPath( path
, plane
);
1196 if( (iter
= OSCollectionIterator::withCollection(
1197 entry
->getPropertyTable() ))) {
1199 while( (key
= (OSSymbol
*) iter
->getNextObject())) {
1201 data
= (OSData
*) entry
->getProperty( key
);
1202 path
= (const char *) data
->getBytesNoCopy();
1203 if( (entry2
= IORegistryEntry::fromPath( path
, plane
,
1205 if( this == entry2
) {
1207 || (bestKey
->getLength() > key
->getLength()))
1208 // pick the smallest alias
1222 const char * IORegistryEntry::dealiasPath(
1223 const char ** opath
,
1224 const IORegistryPlane
* plane
)
1226 IORegistryEntry
* entry
;
1228 const char * path
= *opath
;
1229 const char * rpath
= 0;
1232 char temp
[ kIOMaxPlaneName
+ 1 ];
1239 while( (c
= *end
++) && (c
!= '/') && (c
!= ':'))
1242 if( (end
- path
) < kIOMaxPlaneName
) {
1243 strncpy( temp
, path
, end
- path
);
1244 temp
[ end
- path
] = 0;
1247 entry
= IORegistryEntry::fromPath( "/aliases", plane
);
1249 data
= (OSData
*) entry
->getProperty( temp
);
1251 rpath
= (const char *) data
->getBytesNoCopy();
1263 IORegistryEntry
* IORegistryEntry::fromPath(
1265 const IORegistryPlane
* plane
,
1268 IORegistryEntry
* fromEntry
)
1270 IORegistryEntry
* where
= 0;
1271 IORegistryEntry
* aliasEntry
= 0;
1272 IORegistryEntry
* next
;
1278 char temp
[ kIOMaxPlaneName
+ 1 ];
1285 end
= strchr( path
, ':' );
1286 if( end
&& ((end
- path
) < kIOMaxPlaneName
)) {
1287 strncpy( temp
, path
, end
- path
);
1288 temp
[ end
- path
] = 0;
1289 plane
= getPlane( temp
);
1298 if( (alias
= dealiasPath( &end
, plane
))) {
1301 aliasEntry
= IORegistryEntry::fromPath( alias
, plane
,
1302 opath
, &len
, fromEntry
);
1314 if( (0 == fromEntry
) && (*path
++ == '/'))
1315 fromEntry
= gRegistryRoot
->getChildEntry( plane
);
1322 if( c
&& (c
!= ':')) // check valid terminator
1327 next
= where
->getChildFromComponent( &path
, plane
);
1333 // check residual path
1334 if( where
!= fromEntry
)
1337 if( opath
&& length
) {
1338 // copy out residual path
1339 len2
= len
+ strlen( path
);
1341 strcpy( opath
+ len
, path
);
1345 // no residual path => must be no tail for success
1352 aliasEntry
->release();
1359 IORegistryEntry
* IORegistryEntry::childFromPath(
1361 const IORegistryPlane
* plane
,
1365 return( IORegistryEntry::fromPath( path
, plane
, opath
, len
, this ));
1368 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1370 #define IOLinkIterator OSCollectionIterator
1373 #define super OSObject
1375 inline bool IORegistryEntry::arrayMember( OSArray
* set
,
1376 const IORegistryEntry
* member
,
1377 unsigned int * index
) const
1380 OSObject
* probeObject
;
1382 for( i
= 0; (probeObject
= set
->getObject(i
)); i
++) {
1383 if (probeObject
== (OSObject
*) member
) {
1392 bool IORegistryEntry::makeLink( IORegistryEntry
* to
,
1393 unsigned int relation
,
1394 const IORegistryPlane
* plane
) const
1397 bool result
= false;
1399 if( (links
= (OSArray
*)
1400 registryTable()->getObject( plane
->keys
[ relation
] ))) {
1402 result
= arrayMember( links
, to
);
1404 result
= links
->setObject( to
);
1408 links
= OSArray::withObjects( (const OSObject
**) &to
, 1, 1 );
1409 result
= (links
!= 0);
1411 result
= registryTable()->setObject( plane
->keys
[ relation
],
1420 void IORegistryEntry::breakLink( IORegistryEntry
* to
,
1421 unsigned int relation
,
1422 const IORegistryPlane
* plane
) const
1427 if( (links
= (OSArray
*)
1428 registryTable()->getObject( plane
->keys
[ relation
]))) {
1430 if( arrayMember( links
, to
, &index
)) {
1431 links
->removeObject( index
);
1432 if( 0 == links
->getCount())
1433 registryTable()->removeObject( plane
->keys
[ relation
]);
1439 OSArray
* IORegistryEntry::getParentSetReference(
1440 const IORegistryPlane
* plane
) const
1443 return( (OSArray
*) registryTable()->getObject(
1444 plane
->keys
[ kParentSetIndex
]));
1449 OSIterator
* IORegistryEntry::getParentIterator(
1450 const IORegistryPlane
* plane
) const
1459 links
= getParentSetReference( plane
);
1461 links
= OSArray::withCapacity( 1 );
1463 links
= OSArray::withArray( links
, links
->getCount() );
1466 iter
= IOLinkIterator::withCollection( links
);
1474 IORegistryEntry
* IORegistryEntry::copyParentEntry( const IORegistryPlane
* plane
) const
1476 IORegistryEntry
* entry
= 0;
1481 if( (links
= getParentSetReference( plane
))) {
1482 entry
= (IORegistryEntry
*) links
->getObject( 0 );
1491 IORegistryEntry
* IORegistryEntry::getParentEntry( const IORegistryPlane
* plane
) const
1493 IORegistryEntry
* entry
;
1495 entry
= copyParentEntry( plane
);
1502 OSArray
* IORegistryEntry::getChildSetReference( const IORegistryPlane
* plane
) const
1505 return( (OSArray
*) registryTable()->getObject(
1506 plane
->keys
[ kChildSetIndex
]));
1511 OSIterator
* IORegistryEntry::getChildIterator( const IORegistryPlane
* plane
) const
1520 links
= getChildSetReference( plane
);
1522 links
= OSArray::withCapacity( 1 );
1524 links
= OSArray::withArray( links
, links
->getCount() );
1527 iter
= IOLinkIterator::withCollection( links
);
1536 IORegistryEntry
* IORegistryEntry::copyChildEntry(
1537 const IORegistryPlane
* plane
) const
1539 IORegistryEntry
* entry
= 0;
1544 if( (links
= getChildSetReference( plane
))) {
1545 entry
= (IORegistryEntry
*) links
->getObject( 0 );
1554 IORegistryEntry
* IORegistryEntry::getChildEntry(
1555 const IORegistryPlane
* plane
) const
1557 IORegistryEntry
* entry
;
1559 entry
= copyChildEntry( plane
);
1566 void IORegistryEntry::applyToChildren( IORegistryEntryApplierFunction applier
,
1568 const IORegistryPlane
* plane
) const
1572 IORegistryEntry
* next
;
1578 array
= OSArray::withArray( getChildSetReference( plane
));
1582 (next
= (IORegistryEntry
*) array
->getObject( index
));
1584 (*applier
)(next
, context
);
1589 void IORegistryEntry::applyToParents( IORegistryEntryApplierFunction applier
,
1591 const IORegistryPlane
* plane
) const
1595 IORegistryEntry
* next
;
1601 array
= OSArray::withArray( getParentSetReference( plane
));
1605 (next
= (IORegistryEntry
*) array
->getObject( index
));
1607 (*applier
)(next
, context
);
1612 bool IORegistryEntry::isChild( IORegistryEntry
* child
,
1613 const IORegistryPlane
* plane
,
1614 bool onlyChild
) const
1621 if( (links
= getChildSetReference( plane
))) {
1622 if( (!onlyChild
) || (1 == links
->getCount()))
1623 ret
= arrayMember( links
, child
);
1625 if( ret
&& (links
= child
->getParentSetReference( plane
)))
1626 ret
= arrayMember( links
, this );
1633 bool IORegistryEntry::isParent( IORegistryEntry
* parent
,
1634 const IORegistryPlane
* plane
,
1635 bool onlyParent
) const
1643 if( (links
= getParentSetReference( plane
))) {
1644 if( (!onlyParent
) || (1 == links
->getCount()))
1645 ret
= arrayMember( links
, parent
);
1647 if( ret
&& (links
= parent
->getChildSetReference( plane
)))
1648 ret
= arrayMember( links
, this );
1655 bool IORegistryEntry::inPlane( const IORegistryPlane
* plane
) const
1661 ret
= (0 != getParentSetReference( plane
));
1668 bool IORegistryEntry::attachToParent( IORegistryEntry
* parent
,
1669 const IORegistryPlane
* plane
)
1680 ret
= makeLink( parent
, kParentSetIndex
, plane
);
1682 if( (links
= parent
->getChildSetReference( plane
)))
1683 needParent
= (false == arrayMember( links
, this ));
1687 // ret &= parent->makeLink( this, kChildSetIndex, plane );
1692 ret
&= parent
->attachToChild( this, plane
);
1697 bool IORegistryEntry::attachToChild( IORegistryEntry
* child
,
1698 const IORegistryPlane
* plane
)
1709 ret
= makeLink( child
, kChildSetIndex
, plane
);
1711 if( (links
= child
->getParentSetReference( plane
)))
1712 needChild
= (false == arrayMember( links
, this ));
1719 ret
&= child
->attachToParent( this, plane
);
1724 void IORegistryEntry::detachFromParent( IORegistryEntry
* parent
,
1725 const IORegistryPlane
* plane
)
1734 breakLink( parent
, kParentSetIndex
, plane
);
1736 if( (links
= parent
->getChildSetReference( plane
)))
1737 needParent
= arrayMember( links
, this );
1741 // parent->breakLink( this, kChildSetIndex, plane );
1746 parent
->detachFromChild( this, plane
);
1751 void IORegistryEntry::detachFromChild( IORegistryEntry
* child
,
1752 const IORegistryPlane
* plane
)
1761 breakLink( child
, kChildSetIndex
, plane
);
1763 if( (links
= child
->getParentSetReference( plane
)))
1764 needChild
= arrayMember( links
, this );
1771 child
->detachFromParent( this, plane
);
1776 void IORegistryEntry::detachAbove( const IORegistryPlane
* plane
)
1778 IORegistryEntry
* parent
;
1781 while( (parent
= getParentEntry( plane
)))
1782 detachFromParent( parent
, plane
);
1786 void IORegistryEntry::detachAll( const IORegistryPlane
* plane
)
1789 IORegistryEntry
* next
;
1790 IORegistryIterator
* regIter
;
1792 regIter
= IORegistryIterator::iterateOver( this, plane
, true );
1795 all
= regIter
->iterateAll();
1798 detachAbove( plane
);
1800 while( (next
= (IORegistryEntry
*) all
->getLastObject())) {
1803 all
->removeObject(next
);
1805 next
->detachAbove( plane
);
1812 unsigned int IORegistryEntry::getDepth( const IORegistryPlane
* plane
) const
1814 unsigned int depth
= 1;
1816 unsigned int oneDepth
, maxParentDepth
, count
;
1817 IORegistryEntry
* one
;
1818 const IORegistryEntry
* next
;
1824 while( (parents
= next
->getParentSetReference( plane
))) {
1826 count
= parents
->getCount();
1831 next
= (IORegistryEntry
*) parents
->getObject( 0 );
1836 (one
= (IORegistryEntry
*) parents
->getObject( index
));
1838 oneDepth
= one
->getDepth( plane
);
1839 if( oneDepth
> maxParentDepth
)
1840 maxParentDepth
= oneDepth
;
1842 depth
+= maxParentDepth
;
1852 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1855 #define super OSIterator
1857 OSDefineMetaClassAndStructors(IORegistryIterator
, OSIterator
)
1859 enum { kIORegistryIteratorInvalidFlag
= 0x80000000 };
1861 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1863 IORegistryIterator
*
1864 IORegistryIterator::iterateOver( IORegistryEntry
* root
,
1865 const IORegistryPlane
* plane
,
1866 IOOptionBits options
)
1868 IORegistryIterator
* create
;
1875 create
= new IORegistryIterator
;
1877 if( create
->init()) {
1880 create
->root
= root
;
1881 create
->where
= &create
->start
;
1882 create
->start
.current
= root
;
1883 create
->plane
= plane
;
1884 create
->options
= options
& ~kIORegistryIteratorInvalidFlag
;
1894 IORegistryIterator
*
1895 IORegistryIterator::iterateOver( const IORegistryPlane
* plane
,
1896 IOOptionBits options
)
1898 return( iterateOver( gRegistryRoot
, plane
, options
));
1901 bool IORegistryIterator::isValid( void )
1910 ok
= (0 == (kIORegistryIteratorInvalidFlag
& options
));
1912 while( ok
&& next
) {
1914 ok
= where
->iter
->isValid();
1922 void IORegistryIterator::enterEntry( const IORegistryPlane
* enterPlane
)
1927 where
= (IORegCursor
*) IOMalloc( sizeof( IORegCursor
));
1933 where
->current
= prev
->current
;
1938 void IORegistryIterator::enterEntry( void )
1940 enterEntry( plane
);
1943 bool IORegistryIterator::exitEntry( void )
1948 where
->iter
->release();
1950 if( where
->current
)// && (where != &start))
1951 where
->current
->release();
1954 if( where
!= &start
) {
1957 IOFree( gone
, sizeof( IORegCursor
));
1964 void IORegistryIterator::reset( void )
1974 where
->current
= root
;
1975 options
&= ~kIORegistryIteratorInvalidFlag
;
1978 void IORegistryIterator::free( void )
1989 IORegistryEntry
* IORegistryIterator::getNextObjectFlat( void )
1991 IORegistryEntry
* next
= 0;
1992 OSArray
* links
= 0;
1996 if( (0 == where
->iter
)) {
1997 // just entered - create new iter
2000 && (links
= ( (options
& kIORegistryIterateParents
) ?
2001 where
->current
->getParentSetReference( plane
) :
2002 where
->current
->getChildSetReference( plane
) )) )
2004 where
->iter
= OSCollectionIterator::withCollection( links
);
2007 // next sibling - release current
2009 where
->current
->release();
2013 next
= (IORegistryEntry
*) where
->iter
->getNextObject();
2017 else if( !where
->iter
->isValid())
2018 options
|= kIORegistryIteratorInvalidFlag
;
2021 where
->current
= next
;
2028 IORegistryEntry
* IORegistryIterator::getNextObjectRecursive( void )
2030 IORegistryEntry
* next
;
2033 next
= getNextObjectFlat();
2034 while( (0 == next
) && exitEntry());
2038 done
= OSOrderedSet::withCapacity( 10 );
2039 if( done
->setObject((OSObject
*) next
)) {
2040 // done set didn't contain this one, so recurse
2047 IORegistryEntry
* IORegistryIterator::getNextObject( void )
2049 if( options
& kIORegistryIterateRecursively
)
2050 return( getNextObjectRecursive());
2052 return( getNextObjectFlat());
2055 IORegistryEntry
* IORegistryIterator::getCurrentEntry( void )
2058 return( where
->current
);
2063 OSOrderedSet
* IORegistryIterator::iterateAll( void )
2066 while( getNextObjectRecursive())
2073 OSMetaClassDefineReservedUsed(IORegistryEntry
, 0);
2074 OSMetaClassDefineReservedUsed(IORegistryEntry
, 1);
2075 OSMetaClassDefineReservedUsed(IORegistryEntry
, 2);
2076 OSMetaClassDefineReservedUsed(IORegistryEntry
, 3);
2077 OSMetaClassDefineReservedUsed(IORegistryEntry
, 4);
2079 OSMetaClassDefineReservedUnused(IORegistryEntry
, 5);
2080 OSMetaClassDefineReservedUnused(IORegistryEntry
, 6);
2081 OSMetaClassDefineReservedUnused(IORegistryEntry
, 7);
2082 OSMetaClassDefineReservedUnused(IORegistryEntry
, 8);
2083 OSMetaClassDefineReservedUnused(IORegistryEntry
, 9);
2084 OSMetaClassDefineReservedUnused(IORegistryEntry
, 10);
2085 OSMetaClassDefineReservedUnused(IORegistryEntry
, 11);
2086 OSMetaClassDefineReservedUnused(IORegistryEntry
, 12);
2087 OSMetaClassDefineReservedUnused(IORegistryEntry
, 13);
2088 OSMetaClassDefineReservedUnused(IORegistryEntry
, 14);
2089 OSMetaClassDefineReservedUnused(IORegistryEntry
, 15);
2090 OSMetaClassDefineReservedUnused(IORegistryEntry
, 16);
2091 OSMetaClassDefineReservedUnused(IORegistryEntry
, 17);
2092 OSMetaClassDefineReservedUnused(IORegistryEntry
, 18);
2093 OSMetaClassDefineReservedUnused(IORegistryEntry
, 19);
2094 OSMetaClassDefineReservedUnused(IORegistryEntry
, 20);
2095 OSMetaClassDefineReservedUnused(IORegistryEntry
, 21);
2096 OSMetaClassDefineReservedUnused(IORegistryEntry
, 22);
2097 OSMetaClassDefineReservedUnused(IORegistryEntry
, 23);
2098 OSMetaClassDefineReservedUnused(IORegistryEntry
, 24);
2099 OSMetaClassDefineReservedUnused(IORegistryEntry
, 25);
2100 OSMetaClassDefineReservedUnused(IORegistryEntry
, 26);
2101 OSMetaClassDefineReservedUnused(IORegistryEntry
, 27);
2102 OSMetaClassDefineReservedUnused(IORegistryEntry
, 28);
2103 OSMetaClassDefineReservedUnused(IORegistryEntry
, 29);
2104 OSMetaClassDefineReservedUnused(IORegistryEntry
, 30);
2105 OSMetaClassDefineReservedUnused(IORegistryEntry
, 31);
2107 /* inline function implementation */
2108 OSDictionary
* IORegistryEntry::getPropertyTable( void ) const
2109 { return(fPropertyTable
); }