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