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