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