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