]> git.saurik.com Git - apple/xnu.git/blame - iokit/Kernel/IORegistryEntry.cpp
xnu-124.13.tar.gz
[apple/xnu.git] / iokit / Kernel / IORegistryEntry.cpp
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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.
11 *
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
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22/*
23 * Copyright (c) 1998 Apple Computer, Inc. All rights reserved.
24 *
25 * HISTORY
26 * 12 Nov 98 sdouglas created.
27 *
28 */
29
30#include <IOKit/IORegistryEntry.h>
31#include <libkern/c++/OSContainers.h>
32#include <IOKit/IOService.h>
33#include <IOKit/IOKitKeys.h>
34
35#include <IOKit/IOLib.h>
36
37#include <IOKit/assert.h>
38
39/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
40
41#define super OSObject
42
43OSDefineMetaClassAndStructors(IORegistryEntry, OSObject)
44
45/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
46
47static IORegistryEntry * gRegistryRoot;
48static OSDictionary * gIORegistryPlanes;
49
50const OSSymbol * gIONameKey;
51const OSSymbol * gIOLocationKey;
52
53enum {
54 kParentSetIndex = 0,
55 kChildSetIndex = 1,
56 kNumSetIndex
57};
58enum {
59 kIOMaxPlaneName = 32
60};
61
62class IORegistryPlane : public OSObject {
63
64 friend IORegistryEntry;
65
66 OSDeclareAbstractStructors(IORegistryPlane)
67
68 const OSSymbol * nameKey;
69 const OSSymbol * keys[ kNumSetIndex ];
70 const OSSymbol * pathNameKey;
71 const OSSymbol * pathLocationKey;
72 int reserved[2];
73
74public:
75 virtual bool serialize(OSSerialize *s) const;
76};
77
78OSDefineMetaClassAndStructors(IORegistryPlane, OSObject)
79
80
81static IORecursiveLock * gPropertiesLock;
82static SInt32 gIORegistryGenerationCount;
83
84#define UNLOCK s_lock_done( &gIORegistryLock )
85#define RLOCK s_lock_read( &gIORegistryLock )
86#define WLOCK s_lock_write( &gIORegistryLock ); \
87 gIORegistryGenerationCount++
88 // make atomic
89
90#define PUNLOCK IORecursiveLockUnlock( gPropertiesLock )
91#define PLOCK IORecursiveLockLock( gPropertiesLock )
92
93#define IOREGSPLITTABLES
94
95#ifdef IOREGSPLITTABLES
96#define registryTable() fRegistryTable
97#else
98#define registryTable() fPropertyTable
99#endif
100
101/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
102
103struct s_lock_t {
104 decl_simple_lock_data(,interlock) /* "hardware" interlock field */
105 volatile unsigned int
106 read_count:16, /* No. of accepted readers */
107 want_upgrade:1, /* Read-to-write upgrade waiting */
108 want_write:1, /* Writer is waiting, or
109 locked for write */
110 waiting:1, /* Someone is sleeping on lock */
111 can_sleep:1; /* Can attempts to lock go to sleep? */
112};
113
114static struct s_lock_t gIORegistryLock;
115
116/* Time we loop without holding the interlock.
117 * The former is for when we cannot sleep, the latter
118 * for when our thread can go to sleep (loop less)
119 * we shouldn't retake the interlock at all frequently
120 * if we cannot go to sleep, since it interferes with
121 * any other processors. In particular, 100 is too small
122 * a number for powerpc MP systems because of cache
123 * coherency issues and differing lock fetch times between
124 * the processors
125 */
126static unsigned int lock_wait_time[2] = { (unsigned int)-1, 100 } ;
127
128static void
129s_lock_init(
130 s_lock_t *l,
131 boolean_t can_sleep)
132{
133 (void) memset((void *) l, 0, sizeof(s_lock_t));
134
135 simple_lock_init(&l->interlock, 0);
136 l->want_write = FALSE;
137 l->want_upgrade = FALSE;
138 l->read_count = 0;
139 l->can_sleep = can_sleep;
140}
141
142static void
143s_lock_write(
144 register s_lock_t * l)
145{
146 register int i;
147
148 simple_lock(&l->interlock);
149
150 /*
151 * Try to acquire the want_write bit.
152 */
153 while (l->want_write) {
154
155 i = lock_wait_time[l->can_sleep ? 1 : 0];
156 if (i != 0) {
157 simple_unlock(&l->interlock);
158 while (--i != 0 && l->want_write)
159 continue;
160 simple_lock(&l->interlock);
161 }
162
163 if (l->can_sleep && l->want_write) {
164 l->waiting = TRUE;
165 thread_sleep_simple_lock((event_t) l,
166 simple_lock_addr(l->interlock), FALSE);
167 simple_lock(&l->interlock);
168 }
169 }
170 l->want_write = TRUE;
171
172 /* Wait for readers (and upgrades) to finish */
173
174 while ((l->read_count != 0) || l->want_upgrade) {
175
176 i = lock_wait_time[l->can_sleep ? 1 : 0];
177 if (i != 0) {
178 simple_unlock(&l->interlock);
179 while (--i != 0 && (l->read_count != 0 ||
180 l->want_upgrade))
181 continue;
182 simple_lock(&l->interlock);
183 }
184
185 if (l->can_sleep && (l->read_count != 0 || l->want_upgrade)) {
186 l->waiting = TRUE;
187 thread_sleep_simple_lock((event_t) l,
188 simple_lock_addr(l->interlock), FALSE);
189 simple_lock(&l->interlock);
190 }
191 }
192
193 simple_unlock(&l->interlock);
194}
195
196static void
197s_lock_done(
198 register s_lock_t * l)
199{
200 boolean_t do_wakeup = FALSE;
201
202 simple_lock(&l->interlock);
203
204 if (l->read_count != 0) {
205 l->read_count -= 1;
206 }
207 else {
208 if (l->want_upgrade) {
209 l->want_upgrade = FALSE;
210 }
211 else {
212 l->want_write = FALSE;
213 }
214 }
215
216 /*
217 * There is no reason to wakeup a waiting thread
218 * if the read-count is non-zero. Consider:
219 * we must be dropping a read lock
220 * threads are waiting only if one wants a write lock
221 * if there are still readers, they can't proceed
222 */
223 if (l->waiting && (l->read_count == 0)) {
224 l->waiting = FALSE;
225 do_wakeup = TRUE;
226 }
227
228 simple_unlock(&l->interlock);
229
230 if (do_wakeup)
231 thread_wakeup((event_t) l);
232}
233
234static void
235s_lock_read(
236 register s_lock_t * l)
237{
238 register int i;
239
240 simple_lock(&l->interlock);
241
242 while ( l->want_upgrade || ((0 == l->read_count) && l->want_write )) {
243
244 i = lock_wait_time[l->can_sleep ? 1 : 0];
245
246 if (i != 0) {
247 simple_unlock(&l->interlock);
248 while (--i != 0 &&
249 (l->want_upgrade || ((0 == l->read_count) && l->want_write )))
250 continue;
251 simple_lock(&l->interlock);
252 }
253
254 if (l->can_sleep &&
255 (l->want_upgrade || ((0 == l->read_count) && l->want_write ))) {
256 l->waiting = TRUE;
257 thread_sleep_simple_lock((event_t) l,
258 simple_lock_addr(l->interlock), FALSE);
259 simple_lock(&l->interlock);
260 }
261 }
262
263 l->read_count += 1;
264 simple_unlock(&l->interlock);
265
266}
267
268/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
269
270IORegistryEntry * IORegistryEntry::initialize( void )
271{
272 bool ok;
273
274 if( !gRegistryRoot) {
275
276 s_lock_init( &gIORegistryLock, true );
277 gRegistryRoot = new IORegistryEntry;
278 gPropertiesLock = IORecursiveLockAlloc();
279 gIORegistryPlanes = OSDictionary::withCapacity( 1 );
280
281 assert( gRegistryRoot && gPropertiesLock
282 && gIORegistryPlanes );
283 ok = gRegistryRoot->init();
284
285 gIONameKey = OSSymbol::withCStringNoCopy( "IOName" );
286 gIOLocationKey = OSSymbol::withCStringNoCopy( "IOLocation" );
287
288 assert( ok && gIONameKey && gIOLocationKey );
289
290 gRegistryRoot->setName( "Root" );
291 gRegistryRoot->setProperty( kIORegistryPlanesKey, gIORegistryPlanes );
292 }
293
294 return( gRegistryRoot );
295}
296
297IORegistryEntry * IORegistryEntry::getRegistryRoot( void )
298{
299 return( gRegistryRoot );
300}
301
302SInt32 IORegistryEntry::getGenerationCount( void )
303{
304 return( gIORegistryGenerationCount );
305}
306
307
308const IORegistryPlane * IORegistryEntry::makePlane( const char * name )
309{
310 IORegistryPlane * plane;
311 const OSSymbol * nameKey;
312 const OSSymbol * parentKey;
313 const OSSymbol * childKey;
314 const OSSymbol * pathNameKey;
315 const OSSymbol * pathLocationKey;
316 char key[ kIOMaxPlaneName + 16 ];
317 char * end;
318
319 strncpy( key, name, kIOMaxPlaneName );
320 key[ kIOMaxPlaneName ] = 0;
321 end = key + strlen( name );
322
323 nameKey = OSSymbol::withCString( key);
324
325 strcpy( end, "ParentLinks" );
326 parentKey = OSSymbol::withCString( key);
327
328 strcpy( end, "ChildLinks" );
329 childKey = OSSymbol::withCString( key);
330
331 strcpy( end, "Name" );
332 pathNameKey = OSSymbol::withCString( key);
333
334 strcpy( end, "Location" );
335 pathLocationKey = OSSymbol::withCString( key);
336
337 plane = new IORegistryPlane;
338
339 if( plane && plane->init()
340 && nameKey && parentKey && childKey
341 && pathNameKey && pathLocationKey ) {
342
343 plane->nameKey = nameKey;
344 plane->keys[ kParentSetIndex ] = parentKey;
345 plane->keys[ kChildSetIndex ] = childKey;
346 plane->pathNameKey = pathNameKey;
347 plane->pathLocationKey = pathLocationKey;
348
349 WLOCK;
350 gIORegistryPlanes->setObject( nameKey, plane );
351 UNLOCK;
352
353 } else {
354
355 if( plane)
356 plane->release();
357 if( pathLocationKey)
358 pathLocationKey->release();
359 if( pathNameKey)
360 pathNameKey->release();
361 if( parentKey)
362 parentKey->release();
363 if( childKey)
364 childKey->release();
365 if( nameKey)
366 nameKey->release();
367 plane = 0;
368 }
369
370 return( plane);
371}
372
373const IORegistryPlane * IORegistryEntry::getPlane( const char * name )
374{
375 const IORegistryPlane * plane;
376
377 RLOCK;
378 plane = (const IORegistryPlane *) gIORegistryPlanes->getObject( name );
379 UNLOCK;
380
381 return( plane );
382}
383
384bool IORegistryPlane::serialize(OSSerialize *s) const
385{
386 return( nameKey->serialize(s) );
387}
388
389enum { kIORegCapacityIncrement = 4 };
390
391bool IORegistryEntry::init( OSDictionary * dict = 0 )
392{
393 OSString * prop;
394
395 if( !super::init())
396 return( false);
397
398 if( dict) {
399 dict->retain();
400 fPropertyTable = dict;
401
402 } else {
403 fPropertyTable = OSDictionary::withCapacity( kIORegCapacityIncrement );
404 if( fPropertyTable)
405 fPropertyTable->setCapacityIncrement( kIORegCapacityIncrement );
406 }
407
408 if( !fPropertyTable)
409 return( false);
410
411#ifdef IOREGSPLITTABLES
412 fRegistryTable = OSDictionary::withCapacity( kIORegCapacityIncrement );
413 if( fRegistryTable)
414 fRegistryTable->setCapacityIncrement( kIORegCapacityIncrement );
415
416 if( (prop = OSDynamicCast( OSString, getProperty( gIONameKey)))) {
417 OSSymbol * sym = (OSSymbol *)OSSymbol::withString( prop);
418 // ok for OSSymbol too
419 setName( sym);
420 sym->release();
421 }
422
423#endif /* IOREGSPLITTABLES */
424
425 return( true);
426}
427
428bool IORegistryEntry::init( IORegistryEntry * old,
429 const IORegistryPlane * plane )
430{
431 OSArray * all;
432 IORegistryEntry * next;
433 unsigned int index;
434
435 if( !super::init())
436 return( false);
437
438 WLOCK;
439
440 fPropertyTable = old->getPropertyTable();
441 old->fPropertyTable = 0;
442#ifdef IOREGSPLITTABLES
443 fRegistryTable = old->fRegistryTable;
444 old->fRegistryTable = 0;
445#endif /* IOREGSPLITTABLES */
446
447 all = getParentSetReference( plane );
448 if( all) for( index = 0;
449 (next = (IORegistryEntry *) all->getObject(index));
450 index++ ) {
451 next->makeLink( this, kChildSetIndex, plane );
452 next->breakLink( old, kChildSetIndex, plane );
453 }
454
455 all = getChildSetReference( plane );
456 if( all) for( index = 0;
457 (next = (IORegistryEntry *) all->getObject(index));
458 index++ ) {
459 next->makeLink( this, kParentSetIndex, plane );
460 next->breakLink( old, kParentSetIndex, plane );
461 }
462
463 UNLOCK;
464
465 return( true );
466}
467
468void IORegistryEntry::free( void )
469{
470
471#ifdef DEBUG
472 OSArray * links;
473 const OSSymbol * key;
474 const IORegistryPlane * plane;
475 OSCollectionIterator * iter;
476
477 if( registryTable()) {
478 iter = OSCollectionIterator::withCollection( gIORegistryPlanes );
479 if( iter) {
480 while( (key = (const OSSymbol *) iter->getNextObject())) {
481 if( 0 == (plane = (const IORegistryPlane *)
482 OSDynamicCast( IORegistryPlane,
483 gIORegistryPlanes->getObject( key ))))
484 continue;
485 if( (links = getParentSetReference( plane ))
486 || (links = getChildSetReference( plane )) ) {
487
488 IOLog("%s: Still attached in %s at free()\n",
489 getName(), plane->nameKey->getCStringNoCopy());
490 }
491 }
492 iter->release();
493 }
494 }
495#endif
496
497 if( getPropertyTable())
498 getPropertyTable()->release();
499
500#ifdef IOREGSPLITTABLES
501 if( registryTable())
502 registryTable()->release();
503#endif /* IOREGSPLITTABLES */
504
505 super::free();
506}
507
508void IORegistryEntry::setPropertyTable( OSDictionary * dict )
509{
510 if( fPropertyTable)
511 fPropertyTable->release();
512 if( dict)
513 dict->retain();
514 fPropertyTable = dict;
515}
516
517/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
518
519/* Wrappers to synchronize property table */
520
521#define wrap1(func,type,constant) \
522OSObject * \
523IORegistryEntry::func ## Property( type * aKey) constant \
524{ \
525 OSObject * obj; \
526 \
527 PLOCK; \
528 obj = getPropertyTable()->func ## Object( aKey ); \
529 PUNLOCK; \
530 \
531 return( obj ); \
532}
533
534#define wrap2(type,constant) \
535OSObject * \
536IORegistryEntry::copyProperty( type * aKey) constant \
537{ \
538 OSObject * obj; \
539 \
540 PLOCK; \
541 obj = getPropertyTable()->getObject( aKey ); \
542 if( obj) \
543 obj->retain(); \
544 PUNLOCK; \
545 \
546 return( obj ); \
547}
548
549#define wrap3(func,type,constant) \
550void \
551IORegistryEntry::func ## Property( type * aKey) constant \
552{ \
553 PLOCK; \
554 getPropertyTable()->func ## Object( aKey ); \
555 PUNLOCK; \
556}
557
558#define wrap4(type,constant) \
559OSObject * \
560IORegistryEntry::getProperty( type * aKey, \
561 const IORegistryPlane * plane, \
562 IOOptionBits options ) constant \
563{ \
564 OSObject * obj = getProperty( aKey ); \
565 \
566 if ( (0 == obj) && (options & kIORegistryIterateRecursively) ) { \
567 IORegistryEntry * entry = (IORegistryEntry *) this; \
568 IORegistryIterator * iter; \
569 iter = IORegistryIterator::iterateOver( entry, plane, options ); \
570 \
571 while ( (0 == obj) && (entry = iter->getNextObject()) ) { \
572 obj = entry->getProperty( aKey ); \
573 } \
574 iter->release(); \
575 } \
576 \
577 return( obj ); \
578}
579
580bool IORegistryEntry::serializeProperties( OSSerialize * s ) const
581{
582 bool ok;
583
584// setProperty( getRetainCount(), 32, "__retain" );
585
586 PLOCK;
587 ok = getPropertyTable()->serialize( s );
588 PUNLOCK;
589
590 return( ok );
591}
592
593OSDictionary * IORegistryEntry::dictionaryWithProperties( void ) const
594{
595 OSDictionary * dict;
596
597 PLOCK;
598 dict = OSDictionary::withDictionary( getPropertyTable(),
599 getPropertyTable()->getCapacity() );
600 PUNLOCK;
601
602 return( dict );
603}
604
605IOReturn IORegistryEntry::setProperties( OSObject * properties )
606{
607 return( kIOReturnUnsupported );
608}
609
610wrap1(get, const OSSymbol, const) // getProperty() definition
611wrap1(get, const OSString, const) // getProperty() definition
612wrap1(get, const char, const) // getProperty() definition
613
614wrap2(const OSSymbol, const) // copyProperty() definition
615wrap2(const OSString, const) // copyProperty() definition
616wrap2(const char, const) // copyProperty() definition
617
618wrap3(remove, const OSSymbol,) // removeProperty() definition
619wrap3(remove, const OSString,) // removeProperty() definition
620wrap3(remove, const char,) // removeProperty() definition
621
622wrap4(const OSSymbol, const) // getProperty() w/plane definition
623wrap4(const OSString, const) // getProperty() w/plane definition
624wrap4(const char, const) // getProperty() w/plane definition
625
626bool
627IORegistryEntry::setProperty( const OSSymbol * aKey, OSObject * anObject)
628{
629 bool ret = false;
630 PLOCK;
631 ret = getPropertyTable()->setObject( aKey, anObject );
632 PUNLOCK;
633
634 return ret;
635}
636
637bool
638IORegistryEntry::setProperty( const OSString * aKey, OSObject * anObject)
639{
640 bool ret = false;
641 PLOCK;
642 ret = getPropertyTable()->setObject( aKey, anObject );
643 PUNLOCK;
644
645 return ret;
646}
647
648bool
649IORegistryEntry::setProperty( const char * aKey, OSObject * anObject)
650{
651 bool ret = false;
652 PLOCK;
653 ret = getPropertyTable()->setObject( aKey, anObject );
654 PUNLOCK;
655
656 return ret;
657}
658
659bool
660IORegistryEntry::setProperty(const char * aKey, const char * aString)
661{
662 bool ret = false;
663 OSSymbol * aSymbol = (OSSymbol *) OSSymbol::withCString( aString );
664
665 if( aSymbol) {
666 PLOCK;
667 ret = getPropertyTable()->setObject( aKey, aSymbol );
668 PUNLOCK;
669 aSymbol->release();
670 }
671 return( ret );
672}
673
674bool
675IORegistryEntry::setProperty(const char * aKey, bool aBoolean)
676{
677 bool ret = false;
678 OSBoolean * aBooleanObj = OSBoolean::withBoolean( aBoolean );
679
680 if( aBooleanObj) {
681 PLOCK;
682 ret = getPropertyTable()->setObject( aKey, aBooleanObj );
683 PUNLOCK;
684 aBooleanObj->release();
685 }
686 return( ret );
687}
688
689bool
690IORegistryEntry::setProperty( const char * aKey,
691 unsigned long long aValue,
692 unsigned int aNumberOfBits)
693{
694 bool ret = false;
695 OSNumber * anOffset = OSNumber::withNumber( aValue, aNumberOfBits );
696
697 if( anOffset) {
698 PLOCK;
699 ret = getPropertyTable()->setObject( aKey, anOffset );
700 PUNLOCK;
701 anOffset->release();
702 }
703 return( ret );
704}
705
706bool
707IORegistryEntry::setProperty( const char * aKey,
708 void * bytes,
709 unsigned int length)
710{
711 bool ret = false;
712 OSData * data = OSData::withBytes( bytes, length );
713
714 if( data) {
715 PLOCK;
716 ret = getPropertyTable()->setObject( aKey, data );
717 PUNLOCK;
718 data->release();
719 }
720 return( ret );
721}
722
723/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
724
725/* Name, location, paths */
726
727const char * IORegistryEntry::getName( const IORegistryPlane * plane = 0 ) const
728{
729 OSSymbol * sym = 0;
730
731 RLOCK;
732 if( plane)
733 sym = (OSSymbol *) registryTable()->getObject( plane->pathNameKey );
734 if( !sym)
735 sym = (OSSymbol *) registryTable()->getObject( gIONameKey );
736 UNLOCK;
737
738 if( sym)
739 return( sym->getCStringNoCopy());
740 else
741 return( (getMetaClass())->getClassName());
742}
743
744const OSSymbol * IORegistryEntry::copyName(
745 const IORegistryPlane * plane = 0 ) const
746{
747 OSSymbol * sym = 0;
748
749 RLOCK;
750 if( plane)
751 sym = (OSSymbol *) registryTable()->getObject( plane->pathNameKey );
752 if( !sym)
753 sym = (OSSymbol *) registryTable()->getObject( gIONameKey );
754 if( sym)
755 sym->retain();
756 UNLOCK;
757
758 if( sym)
759 return( sym );
760 else
761 return( OSSymbol::withCString((getMetaClass())->getClassName()) );
762}
763
764const OSSymbol * IORegistryEntry::copyLocation(
765 const IORegistryPlane * plane = 0 ) const
766{
767 OSSymbol * sym = 0;
768
769 RLOCK;
770 if( plane)
771 sym = (OSSymbol *) registryTable()->getObject( plane->pathLocationKey );
772 if( !sym)
773 sym = (OSSymbol *) registryTable()->getObject( gIOLocationKey );
774 if( sym)
775 sym->retain();
776 UNLOCK;
777
778 return( sym );
779}
780
781const char * IORegistryEntry::getLocation( const IORegistryPlane * plane = 0 ) const
782{
783 const OSSymbol * sym = copyLocation( plane );
784 const char * result = 0;
785
786 if( sym) {
787 result = sym->getCStringNoCopy();
788 sym->release();
789 }
790
791 return( result );
792}
793
794void IORegistryEntry::setName( const OSSymbol * name,
795 const IORegistryPlane * plane = 0 )
796{
797 const OSSymbol * key;
798
799 if( name) {
800 if( plane)
801 key = plane->pathNameKey;
802 else
803 key = gIONameKey;
804
805 WLOCK;
806 registryTable()->setObject( key, (OSObject *) name);
807 UNLOCK;
808 }
809}
810
811void IORegistryEntry::setName( const char * name,
812 const IORegistryPlane * plane = 0 )
813{
814 OSSymbol * sym = (OSSymbol *)OSSymbol::withCString( name );
815 if ( sym ) {
816 setName( sym, plane );
817 sym->release();
818 }
819}
820
821void IORegistryEntry::setLocation( const OSSymbol * location,
822 const IORegistryPlane * plane = 0 )
823{
824 const OSSymbol * key;
825
826 if( location) {
827 if( plane)
828 key = plane->pathLocationKey;
829 else
830 key = gIOLocationKey;
831
832 WLOCK;
833 registryTable()->setObject( key, (OSObject *) location);
834 UNLOCK;
835 }
836}
837
838void IORegistryEntry::setLocation( const char * location,
839 const IORegistryPlane * plane = 0 )
840{
841 OSSymbol * sym = (OSSymbol *)OSSymbol::withCString( location );
842 if ( sym ) {
843 setLocation( sym, plane );
844 sym->release();
845 }
846}
847
848bool
849IORegistryEntry::compareName( OSString * name, OSString ** matched = 0 ) const
850{
851 const OSSymbol * sym = copyName();
852 bool isEqual;
853
854 isEqual = sym->isEqualTo( name );
855
856 if( isEqual && matched) {
857 name->retain();
858 *matched = name;
859 }
860
861 if( sym)
862 sym->release();
863
864 return( isEqual );
865}
866
867bool
868IORegistryEntry::compareNames( OSObject * names, OSString ** matched = 0 ) const
869{
870 OSString * string;
871 OSCollection * collection;
872 OSIterator * iter = 0;
873 bool result = false;
874
875 if( (collection = OSDynamicCast( OSCollection, names))) {
876 iter = OSCollectionIterator::withCollection( collection );
877 string = 0;
878 } else
879 string = OSDynamicCast( OSString, names);
880
881 do {
882 if( string)
883 result = compareName( string, matched );
884
885 } while( (false == result)
886 && iter && (string = OSDynamicCast( OSString, iter->getNextObject())));
887
888 if( iter)
889 iter->release();
890
891 return( result);
892}
893
894
895bool IORegistryEntry::getPath( char * path, int * length,
896 const IORegistryPlane * plane ) const
897{
898 OSArray * stack;
899 IORegistryEntry * root;
900 const IORegistryEntry * entry;
901 IORegistryEntry * parent;
902 const OSSymbol * alias;
903 int index;
904 int len, maxLength, compLen;
905 char * nextComp;
906 bool ok;
907
908 if( !path || !length || !plane)
909 return( false);
910
911 len = 0;
912 maxLength = *length - 2;
913 nextComp = path;
914
915 len = plane->nameKey->getLength();
916 if( len >= maxLength)
917 return( false);
918 strcpy( nextComp, plane->nameKey->getCStringNoCopy());
919 nextComp[ len++ ] = ':';
920 nextComp += len;
921
922 if( (alias = hasAlias( plane ))) {
923 len += alias->getLength();
924 ok = (maxLength > len);
925 *length = len;
926 if( ok)
927 strcpy( nextComp, alias->getCStringNoCopy());
928 return( ok );
929 }
930
931 entry = this;
932 parent = entry->getParentEntry( plane );
933 if( !parent)
934 // Error if not attached in plane
935 return( false);
936
937 stack = OSArray::withCapacity( getDepth( plane ));
938 if( !stack)
939 return( false);
940
941 RLOCK;
942
943 root = gRegistryRoot->getChildEntry( plane );
944 while( parent && (entry != root)) {
945 // stop below root
946 stack->setObject( (OSObject *) entry );
947 entry = parent;
948 parent = entry->getParentEntry( plane );
949 }
950
951 index = stack->getCount();
952 ok = true;
953
954 if( 0 == index) {
955
956 *nextComp++ = '/';
957 *nextComp = 0;
958 len++;
959
960 } else while( ok && ((--index) >= 0)) {
961
962 entry = (IORegistryEntry *) stack->getObject((unsigned int) index );
963 assert( entry );
964
965 if( (alias = entry->hasAlias( plane ))) {
966 len = plane->nameKey->getLength() + 1;
967 nextComp = path + len;
968
969 compLen = alias->getLength();
970 ok = (maxLength > len + compLen);
971 if( ok)
972 strcpy( nextComp, alias->getCStringNoCopy());
973 } else {
974 compLen = maxLength - len;
975 ok = entry->getPathComponent( nextComp + 1, &compLen, plane );
976
977 if( ok && compLen) {
978 compLen++;
979 *nextComp = '/';
980 }
981 }
982
983 if( ok) {
984 len += compLen;
985 nextComp += compLen;
986 }
987 }
988 *length = len;
989
990 UNLOCK;
991
992 stack->release();
993
994 return( ok );
995}
996
997bool IORegistryEntry::getPathComponent( char * path, int * length,
998 const IORegistryPlane * plane ) const
999{
1000 int len, locLen, maxLength;
1001 const char * compName;
1002 const char * loc;
1003 bool ok;
1004
1005 maxLength = *length;
1006
1007 compName = getName( plane );
1008 len = strlen( compName );
1009 if( (loc = getLocation( plane )))
1010 locLen = 1 + strlen( loc );
1011 else
1012 locLen = 0;
1013
1014 ok = ((len + locLen) < maxLength);
1015 if( ok) {
1016 strcpy( path, compName );
1017 if( loc) {
1018 path += len;
1019 len += locLen;
1020 *path++ = '@';
1021 strcpy( path, loc );
1022 }
1023 *length = len;
1024 }
1025
1026 return( ok );
1027}
1028
1029const char * IORegistryEntry::matchPathLocation( const char * cmp,
1030 const IORegistryPlane * plane )
1031{
1032 const char * str;
1033 const char * result = 0;
1034 int num1, num2;
1035 char c1, c2;
1036
1037 str = getLocation( plane );
1038 if( str) {
1039 c2 = str[0];
1040 do {
1041 num1 = strtoul( cmp, (char **) &cmp, 16 );
1042 if( c2) {
1043 num2 = strtoul( str, (char **) &str, 16 );
1044 c2 = str[0];
1045 } else
1046 num2 = 0;
1047
1048 if( num1 != num2)
1049 break;
1050
1051 c1 = *cmp++;
1052
1053 if( (c2 == ':') && (c2 == c1)) {
1054 str++;
1055 continue;
1056 }
1057
1058 if( ',' != c1) {
1059 result = cmp - 1;
1060 break;
1061 }
1062
1063 if( c2) {
1064 if( c2 != ',')
1065 break;
1066 str++;
1067 }
1068
1069 } while( true);
1070 }
1071
1072 return( result );
1073}
1074
1075IORegistryEntry * IORegistryEntry::getChildFromComponent( const char ** opath,
1076 const IORegistryPlane * plane )
1077{
1078 IORegistryEntry * entry = 0;
1079 OSArray * set;
1080 unsigned int index;
1081 const char * path;
1082 const char * cmp = 0;
1083 size_t len;
1084 const char * str;
1085
1086 set = getChildSetReference( plane );
1087 if( set) {
1088
1089 path = *opath;
1090
1091 for( index = 0;
1092 (entry = (IORegistryEntry *) set->getObject(index));
1093 index++ ) {
1094
1095 cmp = path;
1096
1097 if( *cmp != '@') {
1098 str = entry->getName( plane );
1099 len = strlen( str );
1100 if( strncmp( str, cmp, len ))
1101 continue;
1102 cmp += len;
1103 if( *cmp != '@' )
1104 break;
1105 }
1106 cmp++;
1107 if( (cmp = entry->matchPathLocation( cmp, plane )))
1108 break;
1109 }
1110 if( entry)
1111 *opath = cmp;
1112 }
1113
1114 return( entry );
1115}
1116
1117const OSSymbol * IORegistryEntry::hasAlias( const IORegistryPlane * plane,
1118 char * opath = 0, int * length = 0 ) const
1119{
1120 IORegistryEntry * entry;
1121 IORegistryEntry * entry2;
1122 const OSSymbol * key;
1123 const OSSymbol * bestKey = 0;
1124 OSIterator * iter;
1125 OSData * data;
1126 const char * path = "/aliases";
1127
1128 entry = IORegistryEntry::fromPath( path, plane );
1129 if( entry) {
1130 RLOCK;
1131 if( (iter = OSCollectionIterator::withCollection(
1132 entry->getPropertyTable() ))) {
1133
1134 while( (key = (OSSymbol *) iter->getNextObject())) {
1135
1136 data = (OSData *) entry->getProperty( key );
1137 path = (const char *) data->getBytesNoCopy();
1138 if( (entry2 = IORegistryEntry::fromPath( path, plane,
1139 opath, length ))) {
1140 if( this == entry2) {
1141 if( !bestKey
1142 || (bestKey->getLength() > key->getLength()))
1143 // pick the smallest alias
1144 bestKey = key;
1145 }
1146 entry2->release();
1147 }
1148 }
1149 iter->release();
1150 }
1151 entry->release();
1152 UNLOCK;
1153 }
1154 return( bestKey );
1155}
1156
1157const char * IORegistryEntry::dealiasPath(
1158 const char ** opath,
1159 const IORegistryPlane * plane )
1160{
1161 IORegistryEntry * entry;
1162 OSData * data;
1163 const char * path = *opath;
1164 const char * rpath = 0;
1165 const char * end;
1166 char c;
1167 char temp[ kIOMaxPlaneName + 1 ];
1168
1169 if( path[0] == '/')
1170 return( rpath );
1171
1172 // check for alias
1173 end = path;
1174 while( (c = *end++) && (c != '/') && (c != ':'))
1175 {}
1176 end--;
1177 if( (end - path) < kIOMaxPlaneName) {
1178 strncpy( temp, path, end - path );
1179 temp[ end - path ] = 0;
1180
1181 RLOCK;
1182 entry = IORegistryEntry::fromPath( "/aliases", plane );
1183 if( entry) {
1184 data = (OSData *) entry->getProperty( temp );
1185 if( data ) {
1186 rpath = (const char *) data->getBytesNoCopy();
1187 if( rpath)
1188 *opath = end;
1189 }
1190 entry->release();
1191 }
1192 UNLOCK;
1193 }
1194
1195 return( rpath );
1196}
1197
1198IORegistryEntry * IORegistryEntry::fromPath(
1199 const char * path,
1200 const IORegistryPlane * plane = 0,
1201 char * opath = 0,
1202 int * length = 0,
1203 IORegistryEntry * fromEntry = 0 )
1204{
1205 IORegistryEntry * where = 0;
1206 IORegistryEntry * next;
1207 const char * alias;
1208 const char * end;
1209 int len = 0;
1210 int len2;
1211 char c;
1212 char temp[ kIOMaxPlaneName + 1 ];
1213
1214 if( 0 == path)
1215 return( 0 );
1216
1217 if( 0 == plane) {
1218 // get plane name
1219 end = strchr( path, ':' );
1220 if( end && ((end - path) < kIOMaxPlaneName)) {
1221 strncpy( temp, path, end - path );
1222 temp[ end - path ] = 0;
1223 plane = getPlane( temp );
1224 path = end + 1;
1225 }
1226 }
1227 if( 0 == plane)
1228 return( 0 );
1229
1230 // check for alias
1231 end = path;
1232 if( (alias = dealiasPath( &end, plane))) {
1233 if( length)
1234 len = *length;
1235 where = IORegistryEntry::fromPath( alias, plane,
1236 opath, &len, fromEntry );
1237 if( where)
1238 path = end;
1239 else
1240 len = 0;
1241 }
1242
1243 RLOCK;
1244
1245 do {
1246 if( 0 == where) {
1247 if( (0 == fromEntry) && (*path++ == '/'))
1248 fromEntry = gRegistryRoot->getChildEntry( plane );
1249 where = fromEntry;
1250 if( 0 == where)
1251 break;
1252 } else {
1253 c = *path++;
1254 if( c != '/') {
1255 if( c && (c != ':')) // check valid terminator
1256 where = 0;
1257 break;
1258 }
1259 }
1260 next = where->getChildFromComponent( &path, plane );
1261 if( next)
1262 where = next;
1263 } while( next );
1264
1265 if( where) {
1266 // check residual path
1267 if( where != fromEntry)
1268 path--;
1269
1270 if( opath && length) {
1271 // copy out residual path
1272 len2 = len + strlen( path );
1273 if( len2 < *length)
1274 strcpy( opath + len, path );
1275 *length = len2;
1276
1277 } else if( path[0])
1278 // no residual path => must be no tail for success
1279 where = 0;
1280 }
1281
1282 if( where)
1283 where->retain();
1284
1285 UNLOCK;
1286
1287 return( where );
1288}
1289
1290IORegistryEntry * IORegistryEntry::childFromPath(
1291 const char * path,
1292 const IORegistryPlane * plane = 0,
1293 char * opath = 0,
1294 int * len = 0 )
1295{
1296 return( IORegistryEntry::fromPath( path, plane, opath, len, this ));
1297}
1298
1299/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1300
1301#define IOLinkIterator OSCollectionIterator
1302
1303#undef super
1304#define super OSObject
1305
1306inline bool IORegistryEntry::arrayMember( OSArray * set,
1307 const IORegistryEntry * member,
1308 unsigned int * index = 0 ) const
1309{
1310 int i;
1311 OSObject * probeObject;
1312
1313 for( i = 0; (probeObject = set->getObject(i)); i++) {
1314 if (probeObject == (OSObject *) member) {
1315 if( index)
1316 *index = i;
1317 return( true );
1318 }
1319 }
1320 return( false );
1321}
1322
1323bool IORegistryEntry::makeLink( IORegistryEntry * to,
1324 unsigned int relation,
1325 const IORegistryPlane * plane ) const
1326{
1327 OSArray * links;
1328 bool result = false;
1329
1330 if( (links = (OSArray *)
1331 registryTable()->getObject( plane->keys[ relation ] ))) {
1332
1333 result = arrayMember( links, to );
1334 if( !result)
1335 result = links->setObject( to );
1336
1337 } else {
1338
1339 links = OSArray::withObjects( & (const OSObject *) to, 1, 1 );
1340 result = (links != 0);
1341 if( result) {
1342 result = registryTable()->setObject( plane->keys[ relation ],
1343 links );
1344 links->release();
1345 }
1346 }
1347
1348 return( result);
1349}
1350
1351void IORegistryEntry::breakLink( IORegistryEntry * to,
1352 unsigned int relation,
1353 const IORegistryPlane * plane ) const
1354{
1355 OSArray * links;
1356 unsigned int index;
1357
1358 if( (links = (OSArray *)
1359 registryTable()->getObject( plane->keys[ relation ]))) {
1360
1361 if( arrayMember( links, to, &index )) {
1362 links->removeObject( index );
1363 if( 0 == links->getCount())
1364 registryTable()->removeObject( plane->keys[ relation ]);
1365 }
1366 }
1367}
1368
1369
1370OSArray * IORegistryEntry::getParentSetReference(
1371 const IORegistryPlane * plane ) const
1372{
1373 if( plane)
1374 return( (OSArray *) registryTable()->getObject(
1375 plane->keys[ kParentSetIndex ]));
1376 else
1377 return( 0 );
1378}
1379
1380OSIterator * IORegistryEntry::getParentIterator(
1381 const IORegistryPlane * plane ) const
1382{
1383 OSArray * links;
1384 OSIterator * iter;
1385
1386 if( !plane)
1387 return( 0 );
1388
1389 RLOCK;
1390 links = getParentSetReference( plane );
1391 if( 0 == links)
1392 links = OSArray::withCapacity( 1 );
1393 else
1394 links = OSArray::withArray( links, links->getCount() );
1395 UNLOCK;
1396
1397 iter = IOLinkIterator::withCollection( links );
1398
1399 if( links)
1400 links->release();
1401
1402 return( iter );
1403}
1404
1405IORegistryEntry * IORegistryEntry::getParentEntry( const IORegistryPlane * plane ) const
1406{
1407 IORegistryEntry * entry = 0;
1408 OSArray * links;
1409
1410 RLOCK;
1411
1412 if( (links = getParentSetReference( plane )))
1413 entry = (IORegistryEntry *) links->getObject( 0 );
1414
1415 UNLOCK;
1416
1417 return( entry);
1418}
1419
1420OSArray * IORegistryEntry::getChildSetReference( const IORegistryPlane * plane ) const
1421{
1422 if( plane)
1423 return( (OSArray *) registryTable()->getObject(
1424 plane->keys[ kChildSetIndex ]));
1425 else
1426 return( 0 );
1427}
1428
1429OSIterator * IORegistryEntry::getChildIterator( const IORegistryPlane * plane ) const
1430{
1431 OSArray * links;
1432 OSIterator * iter;
1433
1434 if( !plane)
1435 return( 0 );
1436
1437 RLOCK;
1438 links = getChildSetReference( plane );
1439 if( 0 == links)
1440 links = OSArray::withCapacity( 1 );
1441 else
1442 links = OSArray::withArray( links, links->getCount() );
1443 UNLOCK;
1444
1445 iter = IOLinkIterator::withCollection( links );
1446
1447 if( links)
1448 links->release();
1449
1450 return( iter );
1451}
1452
1453
1454IORegistryEntry * IORegistryEntry::getChildEntry(
1455 const IORegistryPlane * plane ) const
1456{
1457 IORegistryEntry * entry = 0;
1458 OSArray * links;
1459
1460 RLOCK;
1461
1462 if( (links = getChildSetReference( plane )))
1463 entry = (IORegistryEntry *) links->getObject( 0 );
1464
1465 UNLOCK;
1466
1467 return( entry);
1468}
1469
1470void IORegistryEntry::applyToChildren( IORegistryEntryApplierFunction applier,
1471 void * context,
1472 const IORegistryPlane * plane ) const
1473{
1474 OSArray * array;
1475 unsigned int index;
1476 IORegistryEntry * next;
1477
1478 if( !plane)
1479 return;
1480
1481 RLOCK;
1482 array = OSArray::withArray( getChildSetReference( plane ));
1483 UNLOCK;
1484 if( array) {
1485 for( index = 0;
1486 (next = (IORegistryEntry *) array->getObject( index ));
1487 index++)
1488 (*applier)(next, context);
1489 array->release();
1490 }
1491}
1492
1493void IORegistryEntry::applyToParents( IORegistryEntryApplierFunction applier,
1494 void * context,
1495 const IORegistryPlane * plane ) const
1496{
1497 OSArray * array;
1498 unsigned int index;
1499 IORegistryEntry * next;
1500
1501 if( !plane)
1502 return;
1503
1504 RLOCK;
1505 array = OSArray::withArray( getParentSetReference( plane ));
1506 UNLOCK;
1507 if( array) {
1508 for( index = 0;
1509 (next = (IORegistryEntry *) array->getObject( index ));
1510 index++)
1511 (*applier)(next, context);
1512 array->release();
1513 }
1514}
1515
1516bool IORegistryEntry::isChild( IORegistryEntry * child,
1517 const IORegistryPlane * plane,
1518 bool onlyChild = false ) const
1519{
1520 OSArray * links;
1521 bool ret = false;
1522
1523 RLOCK;
1524
1525 if( (links = getChildSetReference( plane ))) {
1526 if( (!onlyChild) || (1 == links->getCount()))
1527 ret = arrayMember( links, child );
1528 }
1529 if( ret && (links = child->getParentSetReference( plane )))
1530 ret = arrayMember( links, this );
1531
1532 UNLOCK;
1533
1534 return( ret);
1535}
1536
1537bool IORegistryEntry::isParent( IORegistryEntry * parent,
1538 const IORegistryPlane * plane,
1539 bool onlyParent = false ) const
1540
1541{
1542 OSArray * links;
1543 bool ret = false;
1544
1545 RLOCK;
1546
1547 if( (links = getParentSetReference( plane ))) {
1548 if( (!onlyParent) || (1 == links->getCount()))
1549 ret = arrayMember( links, parent );
1550 }
1551 if( ret && (links = parent->getChildSetReference( plane )))
1552 ret = arrayMember( links, this );
1553
1554 UNLOCK;
1555
1556 return( ret);
1557}
1558
1559bool IORegistryEntry::inPlane( const IORegistryPlane * plane ) const
1560{
1561 bool ret;
1562
1563 RLOCK;
1564
1565 ret = (0 != getParentSetReference( plane ));
1566
1567 UNLOCK;
1568
1569 return( ret );
1570}
1571
1572bool IORegistryEntry::attachToParent( IORegistryEntry * parent,
1573 const IORegistryPlane * plane )
1574{
1575 OSArray * links;
1576 bool ret;
1577 bool needParent;
1578
1579 if( this == parent)
1580 return( false );
1581
1582 WLOCK;
1583
1584 ret = makeLink( parent, kParentSetIndex, plane );
1585
1586 if( (links = parent->getChildSetReference( plane )))
1587 needParent = (false == arrayMember( links, this ));
1588 else
1589 needParent = true;
1590
1591// ret &= parent->makeLink( this, kChildSetIndex, plane );
1592
1593 UNLOCK;
1594
1595 if( needParent)
1596 ret &= parent->attachToChild( this, plane );
1597
1598 return( ret );
1599}
1600
1601bool IORegistryEntry::attachToChild( IORegistryEntry * child,
1602 const IORegistryPlane * plane )
1603{
1604 OSArray * links;
1605 bool ret;
1606 bool needChild;
1607
1608 if( this == child)
1609 return( false );
1610
1611 WLOCK;
1612
1613 ret = makeLink( child, kChildSetIndex, plane );
1614
1615 if( (links = child->getParentSetReference( plane )))
1616 needChild = (false == arrayMember( links, this ));
1617 else
1618 needChild = true;
1619
1620 UNLOCK;
1621
1622 if( needChild)
1623 ret &= child->attachToParent( this, plane );
1624
1625 return( ret );
1626}
1627
1628void IORegistryEntry::detachFromParent( IORegistryEntry * parent,
1629 const IORegistryPlane * plane )
1630{
1631 OSArray * links;
1632 bool needParent;
1633
1634 WLOCK;
1635
1636 parent->retain();
1637
1638 breakLink( parent, kParentSetIndex, plane );
1639
1640 if( (links = parent->getChildSetReference( plane )))
1641 needParent = arrayMember( links, this );
1642 else
1643 needParent = false;
1644
1645// parent->breakLink( this, kChildSetIndex, plane );
1646
1647 UNLOCK;
1648
1649 if( needParent)
1650 parent->detachFromChild( this, plane );
1651
1652 parent->release();
1653}
1654
1655void IORegistryEntry::detachFromChild( IORegistryEntry * child,
1656 const IORegistryPlane * plane )
1657{
1658 OSArray * links;
1659 bool needChild;
1660
1661 WLOCK;
1662
1663 child->retain();
1664
1665 breakLink( child, kChildSetIndex, plane );
1666
1667 if( (links = child->getParentSetReference( plane )))
1668 needChild = arrayMember( links, this );
1669 else
1670 needChild = false;
1671
1672 UNLOCK;
1673
1674 if( needChild)
1675 child->detachFromParent( this, plane );
1676
1677 child->release();
1678}
1679
1680void IORegistryEntry::detachAbove( const IORegistryPlane * plane )
1681{
1682 IORegistryEntry * parent;
1683
1684 retain();
1685 while( (parent = getParentEntry( plane )))
1686 detachFromParent( parent, plane );
1687 release();
1688}
1689
1690void IORegistryEntry::detachAll( const IORegistryPlane * plane )
1691{
1692 OSOrderedSet * all;
1693 IORegistryEntry * next;
1694 IORegistryIterator * regIter;
1695
1696 regIter = IORegistryIterator::iterateOver( this, plane, true );
1697 if( 0 == regIter)
1698 return;
1699 all = regIter->iterateAll();
1700 regIter->release();
1701
1702 detachAbove( plane );
1703 if( all) {
1704 while( (next = (IORegistryEntry *) all->getLastObject())) {
1705
1706 next->retain();
1707 all->removeObject(next);
1708
1709 next->detachAbove( plane );
1710 next->release();
1711 }
1712 all->release();
1713 }
1714}
1715
1716unsigned int IORegistryEntry::getDepth( const IORegistryPlane * plane ) const
1717{
1718 unsigned int depth = 1;
1719 OSArray * parents;
1720 unsigned int oneDepth, maxParentDepth, count;
1721 IORegistryEntry * one;
1722 const IORegistryEntry * next;
1723 unsigned int index;
1724
1725 RLOCK;
1726
1727 next = this;
1728 while( (parents = next->getParentSetReference( plane ))) {
1729
1730 count = parents->getCount();
1731 if( 0 == count)
1732 break;
1733 if( 1 == count) {
1734 depth++;
1735 next = (IORegistryEntry *) parents->getObject( 0 );
1736 } else {
1737 // painful
1738 maxParentDepth = 0;
1739 for( index = 0;
1740 (one = (IORegistryEntry *) parents->getObject( index ));
1741 index++ ) {
1742 oneDepth = one->getDepth( plane );
1743 if( oneDepth > maxParentDepth)
1744 maxParentDepth = oneDepth;
1745 }
1746 depth += maxParentDepth;
1747 break;
1748 }
1749 }
1750
1751 UNLOCK;
1752
1753 return( depth);
1754}
1755
1756/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1757
1758#undef super
1759#define super OSIterator
1760
1761OSDefineMetaClassAndStructors(IORegistryIterator, OSIterator)
1762
1763/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1764
1765IORegistryIterator *
1766IORegistryIterator::iterateOver( IORegistryEntry * root,
1767 const IORegistryPlane * plane,
1768 IOOptionBits options = 0 )
1769{
1770 IORegistryIterator * create;
1771
1772 if( 0 == root)
1773 return( 0);
1774 if( 0 == plane)
1775 return( 0);
1776
1777 create = new IORegistryIterator;
1778 if( create) {
1779 if( create->init()) {
1780
1781 root->retain();
1782 create->root = root;
1783 create->where = &create->start;
1784 create->start.current = root;
1785 create->plane = plane;
1786 create->options = options;
1787
1788 } else {
1789 create->release();
1790 create = 0;
1791 }
1792 }
1793 return( create);
1794}
1795
1796IORegistryIterator *
1797IORegistryIterator::iterateOver( const IORegistryPlane * plane,
1798 IOOptionBits options = 0 )
1799{
1800 return( iterateOver( gRegistryRoot, plane, options ));
1801}
1802
1803bool IORegistryIterator::isValid( void )
1804{
1805 bool ok;
1806 IORegCursor * next;
1807
1808 ok = true;
1809 next = where;
1810
1811 RLOCK;
1812 while( ok && next) {
1813 if( where->iter)
1814 ok = where->iter->isValid();
1815 next = next->next;
1816 }
1817 UNLOCK;
1818
1819 return( ok);
1820}
1821
1822void IORegistryIterator::enterEntry( const IORegistryPlane * enterPlane )
1823{
1824 IORegCursor * prev;
1825
1826 prev = where;
1827 where = (IORegCursor *) IOMalloc( sizeof( IORegCursor));
1828 assert( where);
1829
1830 if( where) {
1831 where->iter = 0;
1832 where->next = prev;
1833 where->current = prev->current;
1834 plane = enterPlane;
1835 }
1836}
1837
1838void IORegistryIterator::enterEntry( void )
1839{
1840 enterEntry( plane );
1841}
1842
1843bool IORegistryIterator::exitEntry( void )
1844{
1845 IORegCursor * gone;
1846
1847 if( where->iter) {
1848 where->iter->release();
1849 where->iter = 0;
1850 if( where->current)// && (where != &start))
1851 where->current->release();
1852 }
1853
1854 if( where != &start) {
1855 gone = where;
1856 where = gone->next;
1857 IOFree( gone, sizeof( IORegCursor));
1858 return( true);
1859
1860 } else
1861 return( false);
1862}
1863
1864void IORegistryIterator::reset( void )
1865{
1866 while( exitEntry())
1867 {}
1868
1869 if( done) {
1870 done->release();
1871 done = 0;
1872 }
1873
1874 where->current = root;
1875}
1876
1877void IORegistryIterator::free( void )
1878{
1879 reset();
1880
1881 if( root)
1882 root->release();
1883
1884 super::free();
1885}
1886
1887
1888IORegistryEntry * IORegistryIterator::getNextObjectFlat( void )
1889{
1890 IORegistryEntry * next = 0;
1891 OSArray * links = 0;
1892
1893 RLOCK;
1894
1895 if( (0 == where->iter)) {
1896 // just entered - create new iter
1897 if( isValid()
1898 && where->current
1899 && (links = ( (options & kIORegistryIterateParents) ?
1900 where->current->getParentSetReference( plane ) :
1901 where->current->getChildSetReference( plane ) )) )
1902
1903 where->iter = OSCollectionIterator::withCollection( links );
1904
1905 } else
1906 // next sibling - release current
1907 if( where->current)
1908 where->current->release();
1909
1910 if( where->iter)
1911 next = (IORegistryEntry *) where->iter->getNextObject();
1912
1913 if( next)
1914 next->retain();
1915
1916 where->current = next;
1917
1918 UNLOCK;
1919
1920 return( next);
1921}
1922
1923IORegistryEntry * IORegistryIterator::getNextObjectRecursive( void )
1924{
1925 IORegistryEntry * next;
1926
1927 do
1928 next = getNextObjectFlat();
1929 while( (0 == next) && exitEntry());
1930
1931 if( next) {
1932 if( 0 == done)
1933 done = OSOrderedSet::withCapacity( 10 );
1934 if( done->setObject((OSObject *) next)) {
1935 // done set didn't contain this one, so recurse
1936 enterEntry();
1937 }
1938 }
1939 return( next);
1940}
1941
1942IORegistryEntry * IORegistryIterator::getNextObject( void )
1943{
1944 if( options & kIORegistryIterateRecursively)
1945 return( getNextObjectRecursive());
1946 else
1947 return( getNextObjectFlat());
1948}
1949
1950IORegistryEntry * IORegistryIterator::getCurrentEntry( void )
1951{
1952 if( isValid())
1953 return( where->current);
1954 else
1955 return( 0);
1956}
1957
1958OSOrderedSet * IORegistryIterator::iterateAll( void )
1959{
1960 reset();
1961 while( getNextObjectRecursive())
1962 {}
1963 if( done)
1964 done->retain();
1965 return( done);
1966}
1967
1968OSMetaClassDefineReservedUnused(IORegistryEntry, 0);
1969OSMetaClassDefineReservedUnused(IORegistryEntry, 1);
1970OSMetaClassDefineReservedUnused(IORegistryEntry, 2);
1971OSMetaClassDefineReservedUnused(IORegistryEntry, 3);
1972OSMetaClassDefineReservedUnused(IORegistryEntry, 4);
1973OSMetaClassDefineReservedUnused(IORegistryEntry, 5);
1974OSMetaClassDefineReservedUnused(IORegistryEntry, 6);
1975OSMetaClassDefineReservedUnused(IORegistryEntry, 7);
1976OSMetaClassDefineReservedUnused(IORegistryEntry, 8);
1977OSMetaClassDefineReservedUnused(IORegistryEntry, 9);
1978OSMetaClassDefineReservedUnused(IORegistryEntry, 10);
1979OSMetaClassDefineReservedUnused(IORegistryEntry, 11);
1980OSMetaClassDefineReservedUnused(IORegistryEntry, 12);
1981OSMetaClassDefineReservedUnused(IORegistryEntry, 13);
1982OSMetaClassDefineReservedUnused(IORegistryEntry, 14);
1983OSMetaClassDefineReservedUnused(IORegistryEntry, 15);
1984OSMetaClassDefineReservedUnused(IORegistryEntry, 16);
1985OSMetaClassDefineReservedUnused(IORegistryEntry, 17);
1986OSMetaClassDefineReservedUnused(IORegistryEntry, 18);
1987OSMetaClassDefineReservedUnused(IORegistryEntry, 19);
1988OSMetaClassDefineReservedUnused(IORegistryEntry, 20);
1989OSMetaClassDefineReservedUnused(IORegistryEntry, 21);
1990OSMetaClassDefineReservedUnused(IORegistryEntry, 22);
1991OSMetaClassDefineReservedUnused(IORegistryEntry, 23);
1992OSMetaClassDefineReservedUnused(IORegistryEntry, 24);
1993OSMetaClassDefineReservedUnused(IORegistryEntry, 25);
1994OSMetaClassDefineReservedUnused(IORegistryEntry, 26);
1995OSMetaClassDefineReservedUnused(IORegistryEntry, 27);
1996OSMetaClassDefineReservedUnused(IORegistryEntry, 28);
1997OSMetaClassDefineReservedUnused(IORegistryEntry, 29);
1998OSMetaClassDefineReservedUnused(IORegistryEntry, 30);
1999OSMetaClassDefineReservedUnused(IORegistryEntry, 31);