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