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