]> git.saurik.com Git - apple/xnu.git/blame - iokit/Kernel/IODeviceTreeSupport.cpp
xnu-2422.115.4.tar.gz
[apple/xnu.git] / iokit / Kernel / IODeviceTreeSupport.cpp
CommitLineData
1c79356b 1/*
2d21ac55 2 * Copyright (c) 1998-2006 Apple Computer, Inc. All rights reserved.
1c79356b 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 5 *
2d21ac55
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
8f6c56a5 14 *
2d21ac55
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
8f6c56a5 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b 27 */
1c79356b
A
28
29#include <IOKit/IODeviceTreeSupport.h>
30#include <libkern/c++/OSContainers.h>
31#include <IOKit/IODeviceMemory.h>
32#include <IOKit/IOService.h>
33#include <IOKit/IOCatalogue.h>
34
35#include <IOKit/IOLib.h>
36#include <IOKit/IOKitKeys.h>
37
55e303ae
A
38#include <pexpert/device_tree.h>
39
6d2010ae
A
40#include <machine/machine_routines.h>
41
1c79356b 42extern "C" {
1c79356b 43
6d2010ae
A
44int IODTGetLoaderInfo( const char *key, void **infoAddr, int *infosize );
45void IODTFreeLoaderInfo( const char *key, void *infoAddr, int infoSize );
46int IODTGetDefault(const char *key, void *infoAddr, unsigned int infoSize );
47
1c79356b
A
48}
49
50#include <IOKit/assert.h>
51
0b4e3aa0 52#define IODTSUPPORTDEBUG 0
1c79356b
A
53
54const IORegistryPlane * gIODTPlane;
55
56static OSArray * gIODTPHandles;
57static OSArray * gIODTPHandleMap;
58
59const OSSymbol * gIODTNameKey;
60const OSSymbol * gIODTUnitKey;
61const OSSymbol * gIODTCompatibleKey;
62const OSSymbol * gIODTTypeKey;
63const OSSymbol * gIODTModelKey;
64
65const OSSymbol * gIODTSizeCellKey;
66const OSSymbol * gIODTAddressCellKey;
67const OSSymbol * gIODTRangeKey;
68
69const OSSymbol * gIODTPersistKey;
70
71const OSSymbol * gIODTDefaultInterruptController;
72const OSSymbol * gIODTAAPLInterruptsKey;
73const OSSymbol * gIODTPHandleKey;
74const OSSymbol * gIODTInterruptCellKey;
75const OSSymbol * gIODTInterruptParentKey;
76const OSSymbol * gIODTNWInterruptMappingKey;
77
91447636 78OSDictionary * gIODTSharedInterrupts;
1c79356b
A
79
80static IORegistryEntry * MakeReferenceTable( DTEntry dtEntry, bool copy );
81static void AddPHandle( IORegistryEntry * regEntry );
82static void FreePhysicalMemory( vm_offset_t * range );
91447636 83static bool IODTMapInterruptsSharing( IORegistryEntry * regEntry, OSDictionary * allInts );
1c79356b
A
84
85IORegistryEntry *
86IODeviceTreeAlloc( void * dtTop )
87{
91447636
A
88 IORegistryEntry * parent;
89 IORegistryEntry * child;
90 IORegistryIterator * regIter;
0b4e3aa0 91 DTEntryIterator iter;
91447636
A
92 DTEntry dtChild;
93 DTEntry mapEntry;
94 OSArray * stack;
95 OSData * prop;
91447636
A
96 OSDictionary * allInts;
97 vm_offset_t * dtMap;
2d21ac55 98 unsigned int propSize;
91447636
A
99 bool intMap;
100 bool freeDT;
1c79356b 101
1c79356b
A
102 gIODTPlane = IORegistryEntry::makePlane( kIODeviceTreePlane );
103
0b4e3aa0
A
104 gIODTNameKey = OSSymbol::withCStringNoCopy( "name" );
105 gIODTUnitKey = OSSymbol::withCStringNoCopy( "AAPL,unit-string" );
1c79356b 106 gIODTCompatibleKey = OSSymbol::withCStringNoCopy( "compatible" );
0b4e3aa0
A
107 gIODTTypeKey = OSSymbol::withCStringNoCopy( "device_type" );
108 gIODTModelKey = OSSymbol::withCStringNoCopy( "model" );
1c79356b
A
109 gIODTSizeCellKey = OSSymbol::withCStringNoCopy( "#size-cells" );
110 gIODTAddressCellKey = OSSymbol::withCStringNoCopy( "#address-cells" );
0b4e3aa0
A
111 gIODTRangeKey = OSSymbol::withCStringNoCopy( "ranges" );
112 gIODTPersistKey = OSSymbol::withCStringNoCopy( "IODTPersist" );
1c79356b
A
113
114 assert( gIODTPlane && gIODTCompatibleKey
115 && gIODTTypeKey && gIODTModelKey
116 && gIODTSizeCellKey && gIODTAddressCellKey && gIODTRangeKey
117 && gIODTPersistKey );
118
119 gIODTDefaultInterruptController
0b4e3aa0 120 = OSSymbol::withCStringNoCopy("IOPrimaryInterruptController");
1c79356b 121 gIODTNWInterruptMappingKey
0b4e3aa0 122 = OSSymbol::withCStringNoCopy("IONWInterrupts");
1c79356b
A
123
124 gIODTAAPLInterruptsKey
0b4e3aa0 125 = OSSymbol::withCStringNoCopy("AAPL,interrupts");
1c79356b 126 gIODTPHandleKey
0b4e3aa0 127 = OSSymbol::withCStringNoCopy("AAPL,phandle");
1c79356b
A
128
129 gIODTInterruptParentKey
0b4e3aa0 130 = OSSymbol::withCStringNoCopy("interrupt-parent");
1c79356b
A
131
132 gIODTPHandles = OSArray::withCapacity( 1 );
133 gIODTPHandleMap = OSArray::withCapacity( 1 );
134
135 gIODTInterruptCellKey
0b4e3aa0 136 = OSSymbol::withCStringNoCopy("#interrupt-cells");
1c79356b
A
137
138 assert( gIODTDefaultInterruptController && gIODTNWInterruptMappingKey
139 && gIODTAAPLInterruptsKey
140 && gIODTPHandleKey && gIODTInterruptParentKey
141 && gIODTPHandles && gIODTPHandleMap
142 && gIODTInterruptCellKey
143 );
144
145 freeDT = (kSuccess == DTLookupEntry( 0, "/chosen/memory-map", &mapEntry ))
146 && (kSuccess == DTGetProperty( mapEntry,
147 "DeviceTree", (void **) &dtMap, &propSize ))
b0d623f7 148 && ((2 * sizeof(uint32_t)) == propSize);
1c79356b
A
149
150 parent = MakeReferenceTable( (DTEntry)dtTop, freeDT );
151
55e303ae 152 stack = OSArray::withObjects( (const OSObject **) &parent, 1, 10 );
1c79356b
A
153 DTCreateEntryIterator( (DTEntry)dtTop, &iter );
154
155 do {
156 parent = (IORegistryEntry *)stack->getObject( stack->getCount() - 1);
9bccf70c 157 //parent->release();
1c79356b
A
158 stack->removeObject( stack->getCount() - 1);
159
160 while( kSuccess == DTIterateEntries( iter, &dtChild) ) {
161
162 child = MakeReferenceTable( dtChild, freeDT );
163 child->attachToParent( parent, gIODTPlane);
164
9bccf70c 165 AddPHandle( child );
1c79356b
A
166
167 if( kSuccess == DTEnterEntry( iter, dtChild)) {
168 stack->setObject( parent);
169 parent = child;
170 }
9bccf70c
A
171 // only registry holds retain
172 child->release();
1c79356b
A
173 }
174
175 } while( stack->getCount()
0b4e3aa0 176 && (kSuccess == DTExitEntry( iter, &dtChild)));
1c79356b
A
177
178 stack->release();
179 DTDisposeEntryIterator( iter);
180
181 // parent is now root of the created tree
182
183 // make root name first compatible entry (purely cosmetic)
184 if( (prop = (OSData *) parent->getProperty( gIODTCompatibleKey))) {
9bccf70c
A
185 parent->setName( parent->getName(), gIODTPlane );
186 parent->setName( (const char *) prop->getBytesNoCopy() );
1c79356b
A
187 }
188
189 // attach tree to meta root
190 parent->attachToParent( IORegistryEntry::getRegistryRoot(), gIODTPlane);
191 parent->release();
192
193 if( freeDT ) {
9bccf70c 194 // free original device tree
1c79356b
A
195 DTInit(0);
196 IODTFreeLoaderInfo( "DeviceTree",
b0d623f7 197 (void *)dtMap[0], (int) round_page(dtMap[1]) );
1c79356b
A
198 }
199
200 // adjust tree
91447636
A
201
202 gIODTSharedInterrupts = OSDictionary::withCapacity(4);
203 allInts = OSDictionary::withCapacity(4);
1c79356b
A
204 intMap = false;
205 regIter = IORegistryIterator::iterateOver( gIODTPlane,
206 kIORegistryIterateRecursively );
91447636
A
207 assert( regIter && allInts && gIODTSharedInterrupts );
208 if( regIter && allInts && gIODTSharedInterrupts ) {
9bccf70c 209 while( (child = regIter->getNextObject())) {
91447636 210 IODTMapInterruptsSharing( child, allInts );
9bccf70c
A
211 if( !intMap && child->getProperty( gIODTInterruptParentKey))
212 intMap = true;
213
9bccf70c
A
214 }
215 regIter->release();
1c79356b
A
216 }
217
91447636
A
218#if IODTSUPPORTDEBUG
219 parent->setProperty("allInts", allInts);
220 parent->setProperty("sharedInts", gIODTSharedInterrupts);
221
222 regIter = IORegistryIterator::iterateOver( gIODTPlane,
223 kIORegistryIterateRecursively );
224 if (regIter) {
225 while( (child = regIter->getNextObject())) {
226 OSArray *
227 array = OSDynamicCast(OSArray, child->getProperty( gIOInterruptSpecifiersKey ));
228 for( UInt32 i = 0; array && (i < array->getCount()); i++)
229 {
230 IOOptionBits options;
231 IOReturn ret = IODTGetInterruptOptions( child, i, &options );
232 if( (ret != kIOReturnSuccess) || options)
233 IOLog("%s[%ld] %ld (%x)\n", child->getName(), i, options, ret);
234 }
235 }
236 regIter->release();
237 }
238#endif
239
240 allInts->release();
241
1c79356b 242 if( intMap)
9bccf70c
A
243 // set a key in the root to indicate we found NW interrupt mapping
244 parent->setProperty( gIODTNWInterruptMappingKey,
245 (OSObject *) gIODTNWInterruptMappingKey );
1c79356b 246
1c79356b
A
247 return( parent);
248}
249
6d2010ae 250int IODTGetLoaderInfo( const char *key, void **infoAddr, int *infoSize )
1c79356b
A
251{
252 IORegistryEntry *chosen;
0b4e3aa0 253 OSData *propObj;
1c79356b
A
254 unsigned int *propPtr;
255 unsigned int propSize;
256
257 chosen = IORegistryEntry::fromPath( "/chosen/memory-map", gIODTPlane );
258 if ( chosen == 0 ) return -1;
259
260 propObj = OSDynamicCast( OSData, chosen->getProperty(key) );
261 if ( propObj == 0 ) return -1;
262
263 propSize = propObj->getLength();
264 if ( propSize != (2 * sizeof(UInt32)) ) return -1;
265
266 propPtr = (unsigned int *)propObj->getBytesNoCopy();
267 if ( propPtr == 0 ) return -1;
268
39236c6e
A
269 *infoAddr = (void *)(uintptr_t) (propPtr[0]);
270 *infoSize = (int) (propPtr[1]);
1c79356b
A
271
272 return 0;
273}
274
6d2010ae 275void IODTFreeLoaderInfo( const char *key, void *infoAddr, int infoSize )
1c79356b
A
276{
277 vm_offset_t range[2];
278 IORegistryEntry *chosen;
279
280 range[0] = (vm_offset_t)infoAddr;
281 range[1] = (vm_offset_t)infoSize;
282 FreePhysicalMemory( range );
283
284 if ( key != 0 ) {
285 chosen = IORegistryEntry::fromPath( "/chosen/memory-map", gIODTPlane );
286 if ( chosen != 0 ) {
287 chosen->removeProperty(key);
288 }
289 }
290}
291
6d2010ae
A
292int IODTGetDefault(const char *key, void *infoAddr, unsigned int infoSize )
293{
294 IORegistryEntry *defaults;
295 OSData *defaultObj;
296 unsigned int defaultSize;
297
298 defaults = IORegistryEntry::fromPath( "/defaults", gIODTPlane );
299 if ( defaults == 0 ) return -1;
300
301 defaultObj = OSDynamicCast( OSData, defaults->getProperty(key) );
302 if ( defaultObj == 0 ) return -1;
303
304 defaultSize = defaultObj->getLength();
305 if ( defaultSize > infoSize) return -1;
306
307 memcpy( infoAddr, defaultObj->getBytesNoCopy(), defaultSize );
308
309 return 0;
310}
311
1c79356b
A
312static void FreePhysicalMemory( vm_offset_t * range )
313{
314 vm_offset_t virt;
315
316 virt = ml_static_ptovirt( range[0] );
317 if( virt) {
318 ml_static_mfree( virt, range[1] );
319 }
320}
321
322static IORegistryEntry *
323MakeReferenceTable( DTEntry dtEntry, bool copy )
324{
0b4e3aa0
A
325 IORegistryEntry *regEntry;
326 OSDictionary *propTable;
327 const OSSymbol *nameKey;
328 OSData *data;
329 const OSSymbol *sym;
1c79356b 330 DTPropertyIterator dtIter;
0b4e3aa0 331 void *prop;
2d21ac55 332 unsigned int propSize;
0b4e3aa0
A
333 char *name;
334 char location[ 32 ];
335 bool noLocation = true;
1c79356b
A
336
337 regEntry = new IOService;
338
339 if( regEntry && (false == regEntry->init())) {
9bccf70c
A
340 regEntry->release();
341 regEntry = 0;
1c79356b
A
342 }
343
344 if( regEntry &&
9bccf70c 345 (kSuccess == DTCreatePropertyIterator( dtEntry, &dtIter))) {
1c79356b
A
346
347 propTable = regEntry->getPropertyTable();
348
9bccf70c
A
349 while( kSuccess == DTIterateProperties( dtIter, &name)) {
350
351 if( kSuccess != DTGetProperty( dtEntry, name, &prop, &propSize ))
352 continue;
353
354 if( copy) {
355 nameKey = OSSymbol::withCString(name);
356 data = OSData::withBytes(prop, propSize);
357 } else {
358 nameKey = OSSymbol::withCStringNoCopy(name);
359 data = OSData::withBytesNoCopy(prop, propSize);
360 }
361 assert( nameKey && data );
362
363 propTable->setObject( nameKey, data);
364 data->release();
365 nameKey->release();
366
367 if( nameKey == gIODTNameKey ) {
368 if( copy)
369 sym = OSSymbol::withCString( (const char *) prop);
370 else
371 sym = OSSymbol::withCStringNoCopy( (const char *) prop);
372 regEntry->setName( sym );
373 sym->release();
374
375 } else if( nameKey == gIODTUnitKey ) {
376 // all OF strings are null terminated... except this one
2d21ac55
A
377 if( propSize >= (int) sizeof(location))
378 propSize = sizeof(location) - 1;
9bccf70c
A
379 strncpy( location, (const char *) prop, propSize );
380 location[ propSize ] = 0;
381 regEntry->setLocation( location );
382 propTable->removeObject( gIODTUnitKey );
383 noLocation = false;
384
2d21ac55 385 } else if(noLocation && (!strncmp(name, "reg", sizeof("reg")))) {
9bccf70c 386 // default location - override later
b0d623f7 387 snprintf(location, sizeof(location), "%X", *((uint32_t *) prop));
9bccf70c
A
388 regEntry->setLocation( location );
389 }
390 }
391 DTDisposePropertyIterator( dtIter);
1c79356b
A
392 }
393
394 return( regEntry);
395}
396
397static void AddPHandle( IORegistryEntry * regEntry )
398{
399 OSData * data;
400
401 if( regEntry->getProperty( gIODTInterruptCellKey)
9bccf70c
A
402 && (data = OSDynamicCast( OSData, regEntry->getProperty( gIODTPHandleKey )))) {
403 // a possible interrupt-parent
404 gIODTPHandles->setObject( data );
405 gIODTPHandleMap->setObject( regEntry );
1c79356b
A
406 }
407}
408
409static IORegistryEntry * FindPHandle( UInt32 phandle )
410{
0b4e3aa0
A
411 OSData *data;
412 IORegistryEntry *regEntry = 0;
413 int i;
414
415 for( i = 0; (data = (OSData *)gIODTPHandles->getObject( i )); i++ ) {
9bccf70c
A
416 if( phandle == *((UInt32 *)data->getBytesNoCopy())) {
417 regEntry = (IORegistryEntry *)
418 gIODTPHandleMap->getObject( i );
419 break;
1c79356b
A
420 }
421 }
422
423 return( regEntry );
424}
425
426static bool GetUInt32( IORegistryEntry * regEntry, const OSSymbol * name,
427 UInt32 * value )
428{
0b4e3aa0 429 OSData *data;
1c79356b
A
430
431 if( (data = OSDynamicCast( OSData, regEntry->getProperty( name )))
9bccf70c 432 && (4 == data->getLength())) {
1c79356b 433 *value = *((UInt32 *) data->getBytesNoCopy());
9bccf70c 434 return( true );
1c79356b 435 } else
9bccf70c 436 return( false );
1c79356b
A
437}
438
4a3eedf9 439static IORegistryEntry * IODTFindInterruptParent( IORegistryEntry * regEntry, IOItemCount index )
1c79356b
A
440{
441 IORegistryEntry * parent;
442 UInt32 phandle;
4a3eedf9
A
443 OSData * data;
444 unsigned int len;
1c79356b 445
4a3eedf9
A
446 if( (data = OSDynamicCast( OSData, regEntry->getProperty( gIODTInterruptParentKey )))
447 && (sizeof(UInt32) <= (len = data->getLength()))) {
448 if (((index + 1) * sizeof(UInt32)) > len)
449 index = 0;
450 phandle = ((UInt32 *) data->getBytesNoCopy())[index];
451 parent = FindPHandle( phandle );
1c79356b 452
4a3eedf9 453 } else if( 0 == regEntry->getProperty( "interrupt-controller"))
9bccf70c 454 parent = regEntry->getParentEntry( gIODTPlane);
1c79356b 455 else
9bccf70c 456 parent = 0;
1c79356b
A
457
458 return( parent );
459}
460
461const OSSymbol * IODTInterruptControllerName( IORegistryEntry * regEntry )
462{
0b4e3aa0 463 const OSSymbol *sym;
9bccf70c
A
464 UInt32 phandle;
465 bool ok;
466 char buf[48];
1c79356b
A
467
468 ok = GetUInt32( regEntry, gIODTPHandleKey, &phandle);
469 assert( ok );
470
471 if( ok) {
b0d623f7 472 snprintf(buf, sizeof(buf), "IOInterruptController%08X", (uint32_t)phandle);
1c79356b
A
473 sym = OSSymbol::withCString( buf );
474 } else
9bccf70c 475 sym = 0;
1c79356b
A
476
477 return( sym );
478}
479
480#define unexpected(a) { kprintf("unexpected %s:%d\n", __FILE__, __LINE__); a; }
481
482static void IODTGetICellCounts( IORegistryEntry * regEntry,
483 UInt32 * iCellCount, UInt32 * aCellCount)
484{
485 if( !GetUInt32( regEntry, gIODTInterruptCellKey, iCellCount))
486 unexpected( *iCellCount = 1 );
487 if( !GetUInt32( regEntry, gIODTAddressCellKey, aCellCount))
488 *aCellCount = 0;
489}
490
4a3eedf9
A
491static UInt32 IODTMapOneInterrupt( IORegistryEntry * regEntry, UInt32 * intSpec, UInt32 index,
492 OSData ** spec, const OSSymbol ** controller )
1c79356b 493{
0b4e3aa0
A
494 IORegistryEntry *parent = 0;
495 OSData *data;
496 UInt32 *addrCmp;
497 UInt32 *maskCmp;
498 UInt32 *map;
499 UInt32 *endMap;
500 UInt32 acells, icells, pacells, picells, cell;
501 UInt32 i, original_icells;
502 bool cmp, ok = false;
503
4a3eedf9 504 parent = IODTFindInterruptParent( regEntry, index );
0b4e3aa0
A
505 IODTGetICellCounts( parent, &icells, &acells );
506 addrCmp = 0;
507 if( acells) {
9bccf70c 508 data = OSDynamicCast( OSData, regEntry->getProperty( "reg" ));
2d21ac55 509 if( data && (data->getLength() >= (acells * sizeof(UInt32))))
9bccf70c 510 addrCmp = (UInt32 *) data->getBytesNoCopy();
0b4e3aa0
A
511 }
512 original_icells = icells;
513 regEntry = parent;
514
9bccf70c 515 do {
0b4e3aa0 516#if IODTSUPPORTDEBUG
9bccf70c
A
517 kprintf ("IODTMapOneInterrupt: current regEntry name %s\n", regEntry->getName());
518 kprintf ("acells - icells: ");
519 for (i = 0; i < acells; i++) kprintf ("0x%08X ", addrCmp[i]);
520 kprintf ("- ");
521 for (i = 0; i < icells; i++) kprintf ("0x%08X ", intSpec[i]);
522 kprintf ("\n");
0b4e3aa0 523#endif
1c79356b 524
9bccf70c
A
525 if( parent && (data = OSDynamicCast( OSData,
526 regEntry->getProperty( "interrupt-controller")))) {
527 // found a controller - don't want to follow cascaded controllers
1c79356b
A
528 parent = 0;
529 *spec = OSData::withBytesNoCopy( (void *) intSpec,
2d21ac55 530 icells * sizeof(UInt32));
1c79356b 531 *controller = IODTInterruptControllerName( regEntry );
9bccf70c
A
532 ok = (*spec && *controller);
533 } else if( parent && (data = OSDynamicCast( OSData,
534 regEntry->getProperty( "interrupt-map")))) {
1c79356b
A
535 // interrupt-map
536 map = (UInt32 *) data->getBytesNoCopy();
537 endMap = map + (data->getLength() / sizeof(UInt32));
538 data = OSDynamicCast( OSData, regEntry->getProperty( "interrupt-map-mask" ));
2d21ac55 539 if( data && (data->getLength() >= ((acells + icells) * sizeof(UInt32))))
1c79356b 540 maskCmp = (UInt32 *) data->getBytesNoCopy();
9bccf70c
A
541 else
542 maskCmp = 0;
0b4e3aa0
A
543
544#if IODTSUPPORTDEBUG
9bccf70c
A
545 if (maskCmp) {
546 kprintf (" maskCmp: ");
547 for (i = 0; i < acells + icells; i++) {
548 if (i == acells)
549 kprintf ("- ");
550 kprintf ("0x%08X ", maskCmp[i]);
551 }
552 kprintf ("\n");
553 kprintf (" masked: ");
554 for (i = 0; i < acells + icells; i++) {
555 if (i == acells)
556 kprintf ("- ");
557 kprintf ("0x%08X ", ((i < acells) ? addrCmp[i] : intSpec[i-acells]) & maskCmp[i]);
558 }
559 kprintf ("\n");
560 } else
561 kprintf ("no maskCmp\n");
0b4e3aa0 562#endif
9bccf70c 563 do {
0b4e3aa0 564#if IODTSUPPORTDEBUG
9bccf70c
A
565 kprintf (" map: ");
566 for (i = 0; i < acells + icells; i++) {
567 if (i == acells)
568 kprintf ("- ");
569 kprintf ("0x%08X ", map[i]);
570 }
571 kprintf ("\n");
0b4e3aa0 572#endif
9bccf70c 573 for( i = 0, cmp = true; cmp && (i < (acells + icells)); i++) {
1c79356b
A
574 cell = (i < acells) ? addrCmp[i] : intSpec[ i - acells ];
575 if( maskCmp)
576 cell &= maskCmp[i];
577 cmp = (cell == map[i]);
578 }
579
580 map += acells + icells;
581 if( 0 == (parent = FindPHandle( *(map++) )))
582 unexpected(break);
583
9bccf70c 584 IODTGetICellCounts( parent, &picells, &pacells );
0b4e3aa0
A
585 if( cmp) {
586 addrCmp = map;
587 intSpec = map + pacells;
588 regEntry = parent;
9bccf70c 589 } else {
1c79356b 590 map += pacells + picells;
9bccf70c 591 }
1c79356b 592 } while( !cmp && (map < endMap) );
0b4e3aa0 593 if (!cmp)
9bccf70c
A
594 parent = 0;
595 }
1c79356b 596
9bccf70c 597 if( parent) {
1c79356b 598 IODTGetICellCounts( parent, &icells, &acells );
9bccf70c
A
599 regEntry = parent;
600 }
601
602 } while( parent);
0b4e3aa0
A
603
604 return( ok ? original_icells : 0 );
1c79356b
A
605}
606
91447636 607IOReturn IODTGetInterruptOptions( IORegistryEntry * regEntry, int source, IOOptionBits * options )
1c79356b 608{
91447636
A
609 OSArray * controllers;
610 OSArray * specifiers;
611 OSArray * shared;
612 OSObject * spec;
613 OSObject * oneSpec;
614
615 *options = 0;
616
617 controllers = OSDynamicCast(OSArray, regEntry->getProperty(gIOInterruptControllersKey));
618 specifiers = OSDynamicCast(OSArray, regEntry->getProperty(gIOInterruptSpecifiersKey));
619
620 if( !controllers || !specifiers)
621 return (kIOReturnNoInterrupt);
622
623 shared = (OSArray *) gIODTSharedInterrupts->getObject(
624 (const OSSymbol *) controllers->getObject(source) );
625 if (!shared)
626 return (kIOReturnSuccess);
627
628 spec = specifiers->getObject(source);
629 if (!spec)
630 return (kIOReturnNoInterrupt);
631
632 for (unsigned int i = 0;
633 (oneSpec = shared->getObject(i))
634 && (!oneSpec->isEqualTo(spec));
635 i++ ) {}
636
637 if (oneSpec)
638 *options = kIODTInterruptShared;
639
640 return (kIOReturnSuccess);
641}
642
643static bool IODTMapInterruptsSharing( IORegistryEntry * regEntry, OSDictionary * allInts )
644{
645 IORegistryEntry * parent;
646 OSData * local;
647 OSData * local2;
648 UInt32 * localBits;
649 UInt32 * localEnd;
4a3eedf9 650 IOItemCount index;
91447636
A
651 OSData * map;
652 OSObject * oneMap;
653 OSArray * mapped;
654 OSArray * controllerInts;
4a3eedf9 655 const OSSymbol * controller = 0;
91447636
A
656 OSArray * controllers;
657 UInt32 skip = 1;
658 bool ok, nw;
1c79356b
A
659
660 nw = (0 == (local = OSDynamicCast( OSData,
9bccf70c 661 regEntry->getProperty( gIODTAAPLInterruptsKey))));
0b4e3aa0 662 if( nw && (0 == (local = OSDynamicCast( OSData,
9bccf70c
A
663 regEntry->getProperty( "interrupts")))))
664 return( true ); // nothing to see here
1c79356b
A
665
666 if( nw && (parent = regEntry->getParentEntry( gIODTPlane))) {
9bccf70c
A
667 // check for bridges on old world
668 if( (local2 = OSDynamicCast( OSData,
669 parent->getProperty( gIODTAAPLInterruptsKey)))) {
670 local = local2;
671 nw = false;
672 }
1c79356b
A
673 }
674
675 localBits = (UInt32 *) local->getBytesNoCopy();
2d21ac55 676 localEnd = localBits + (local->getLength() / sizeof(UInt32));
4a3eedf9 677 index = 0;
1c79356b
A
678 mapped = OSArray::withCapacity( 1 );
679 controllers = OSArray::withCapacity( 1 );
680
681 ok = (mapped && controllers);
682
683 if( ok) do {
684 if( nw) {
4a3eedf9 685 skip = IODTMapOneInterrupt( regEntry, localBits, index, &map, &controller );
1c79356b
A
686 if( 0 == skip) {
687 IOLog("%s: error mapping interrupt[%d]\n",
9bccf70c 688 regEntry->getName(), mapped->getCount());
1c79356b
A
689 break;
690 }
691 } else {
2d21ac55
A
692 map = OSData::withData( local, mapped->getCount() * sizeof(UInt32),
693 sizeof(UInt32));
1c79356b 694 controller = gIODTDefaultInterruptController;
fa4905b1 695 controller->retain();
1c79356b
A
696 }
697
4a3eedf9 698 index++;
1c79356b
A
699 localBits += skip;
700 mapped->setObject( map );
91447636
A
701 controllers->setObject( controller );
702
703 if (allInts)
704 {
705 controllerInts = (OSArray *) allInts->getObject( controller );
706 if (controllerInts)
707 {
708 for (unsigned int i = 0; (oneMap = controllerInts->getObject(i)); i++)
709 {
710 if (map->isEqualTo(oneMap))
711 {
712 controllerInts = (OSArray *) gIODTSharedInterrupts->getObject( controller );
713 if (controllerInts)
714 controllerInts->setObject(map);
715 else
716 {
717 controllerInts = OSArray::withObjects( (const OSObject **) &map, 1, 4 );
718 if (controllerInts)
719 {
720 gIODTSharedInterrupts->setObject( controller, controllerInts );
721 controllerInts->release();
722 }
723 }
724 break;
725 }
726 }
727 if (!oneMap)
728 controllerInts->setObject(map);
729 }
730 else
731 {
732 controllerInts = OSArray::withObjects( (const OSObject **) &map, 1, 16 );
733 if (controllerInts)
734 {
735 allInts->setObject( controller, controllerInts );
736 controllerInts->release();
737 }
738 }
739 }
740
1c79356b 741 map->release();
1c79356b
A
742 controller->release();
743
744 } while( localBits < localEnd);
745
746 ok &= (localBits == localEnd);
747
748 if( ok ) {
9bccf70c 749 // store results
1c79356b
A
750 ok = regEntry->setProperty( gIOInterruptControllersKey, controllers);
751 ok &= regEntry->setProperty( gIOInterruptSpecifiersKey, mapped);
752 }
753
754 if( controllers)
755 controllers->release();
756 if( mapped)
757 mapped->release();
758
759 return( ok );
760}
761
91447636
A
762bool IODTMapInterrupts( IORegistryEntry * regEntry )
763{
764 return( IODTMapInterruptsSharing( regEntry, 0 ));
765}
766
1c79356b
A
767/*
768 */
769
770static const char *
771CompareKey( OSString * key,
772 const IORegistryEntry * table, const OSSymbol * propName )
773{
0b4e3aa0
A
774 OSObject *prop;
775 OSData *data;
776 OSString *string;
777 const char *ckey;
778 UInt32 keyLen;
779 const char *names;
780 const char *lastName;
781 bool wild;
782 bool matched;
783 const char *result = 0;
1c79356b
A
784
785 if( 0 == (prop = table->getProperty( propName )))
786 return( 0 );
787
788 if( (data = OSDynamicCast( OSData, prop ))) {
789 names = (const char *) data->getBytesNoCopy();
790 lastName = names + data->getLength();
1c79356b
A
791 } else if( (string = OSDynamicCast( OSString, prop ))) {
792 names = string->getCStringNoCopy();
793 lastName = names + string->getLength() + 1;
1c79356b 794 } else
0b4e3aa0 795 return( 0 );
1c79356b
A
796
797 ckey = key->getCStringNoCopy();
798 keyLen = key->getLength();
799 wild = ('*' == key->getChar( keyLen - 1 ));
800
801 do {
802 // for each name in the property
803 if( wild)
804 matched = (0 == strncmp( ckey, names, keyLen - 1 ));
805 else
806 matched = (keyLen == strlen( names ))
807 && (0 == strncmp( ckey, names, keyLen ));
808
809 if( matched)
810 result = names;
811
812 names = names + strlen( names) + 1;
813
814 } while( (names < lastName) && (false == matched));
815
816 return( result);
817}
818
819
820bool IODTCompareNubName( const IORegistryEntry * regEntry,
821 OSString * name, OSString ** matchingName )
822{
0b4e3aa0
A
823 const char *result;
824 bool matched;
1c79356b
A
825
826 matched = (0 != (result = CompareKey( name, regEntry, gIODTNameKey)))
827 || (0 != (result = CompareKey( name, regEntry, gIODTCompatibleKey)))
828 || (0 != (result = CompareKey( name, regEntry, gIODTTypeKey)))
829 || (0 != (result = CompareKey( name, regEntry, gIODTModelKey)));
830
831 if( result && matchingName)
832 *matchingName = OSString::withCString( result );
833
834 return( result != 0 );
835}
836
837bool IODTMatchNubWithKeys( IORegistryEntry * regEntry,
838 const char * keys )
839{
0b4e3aa0 840 OSObject *obj;
1c79356b
A
841 bool result = false;
842
843 obj = OSUnserialize( keys, 0 );
844
845 if( obj) {
846 result = regEntry->compareNames( obj );
0b4e3aa0 847 obj->release();
1c79356b 848 }
b0d623f7 849#if DEBUG
9bccf70c 850 else IOLog("Couldn't unserialize %s\n", keys );
1c79356b
A
851#endif
852
853 return( result );
854}
855
856OSCollectionIterator * IODTFindMatchingEntries( IORegistryEntry * from,
857 IOOptionBits options, const char * keys )
858{
fa4905b1 859 OSSet *result = 0;
0b4e3aa0
A
860 IORegistryEntry *next;
861 IORegistryIterator *iter;
862 OSCollectionIterator *cIter;
863 bool cmp;
864 bool minus = options & kIODTExclusive;
1c79356b 865
1c79356b
A
866
867 iter = IORegistryIterator::iterateOver( from, gIODTPlane,
0b4e3aa0 868 (options & kIODTRecursive) ? kIORegistryIterateRecursively : 0 );
1c79356b 869 if( iter) {
9bccf70c 870
fa4905b1 871 do {
1c79356b 872
fa4905b1
A
873 if( result)
874 result->release();
875 result = OSSet::withCapacity( 3 );
876 if( !result)
877 break;
1c79356b 878
fa4905b1
A
879 iter->reset();
880 while( (next = iter->getNextObject())) {
881
882 // Look for existence of a debug property to skip
883 if( next->getProperty("AAPL,ignore"))
9bccf70c 884 continue;
fa4905b1 885
9bccf70c 886 if( keys) {
fa4905b1
A
887 cmp = IODTMatchNubWithKeys( next, keys );
888 if( (minus && (false == cmp))
889 || ((false == minus) && (false != cmp)) )
890 result->setObject( next);
9bccf70c 891 } else
1c79356b 892 result->setObject( next);
fa4905b1
A
893 }
894 } while( !iter->isValid());
9bccf70c 895
1c79356b
A
896 iter->release();
897 }
898
899 cIter = OSCollectionIterator::withCollection( result);
900 result->release();
901
902 return( cIter);
903}
904
905
906struct IODTPersistent {
907 IODTCompareAddressCellFunc compareFunc;
908 IODTNVLocationFunc locationFunc;
909};
910
911void IODTSetResolving( IORegistryEntry * regEntry,
912 IODTCompareAddressCellFunc compareFunc,
913 IODTNVLocationFunc locationFunc )
914{
915 IODTPersistent persist;
0b4e3aa0 916 OSData *prop;
1c79356b
A
917
918 persist.compareFunc = compareFunc;
919 persist.locationFunc = locationFunc;
2d21ac55 920 prop = OSData::withBytes( &persist, sizeof(persist));
1c79356b 921 if( !prop)
9bccf70c 922 return;
1c79356b 923
316670eb 924 prop->setSerializable(false);
1c79356b
A
925 regEntry->setProperty( gIODTPersistKey, prop);
926 prop->release();
0b4e3aa0 927 return;
1c79356b
A
928}
929
39236c6e 930#if defined(__arm__) || defined(__i386__) || defined(__x86_64__)
1c79356b
A
931static SInt32 DefaultCompare( UInt32 cellCount, UInt32 left[], UInt32 right[] )
932{
316670eb
A
933 cellCount--;
934 return( left[ cellCount ] - right[ cellCount ] );
1c79356b 935}
39236c6e
A
936#else
937#error Unknown architecture.
938#endif
939
940static void AddLengthToCells( UInt32 numCells, UInt32 *cells, UInt64 offset)
941{
942 if (numCells == 1)
943 {
944 cells[0] += (UInt32)offset;
945 }
946 else {
947 UInt64 sum = cells[numCells - 1] + offset;
948 cells[numCells - 1] = (UInt32)sum;
949 if (sum > UINT32_MAX) {
950 cells[numCells - 2] += (UInt32)(sum >> 32);
951 }
952 }
953}
954
955static IOPhysicalAddress CellsValue( UInt32 numCells, UInt32 *cells)
956{
957 if (numCells == 1) {
958 return IOPhysical32( 0, cells[0] );
959 } else {
960 return IOPhysical32( cells[numCells - 2], cells[numCells - 1] );
961 }
962}
1c79356b 963
1c79356b
A
964void IODTGetCellCounts( IORegistryEntry * regEntry,
965 UInt32 * sizeCount, UInt32 * addressCount)
966{
967 if( !GetUInt32( regEntry, gIODTSizeCellKey, sizeCount))
968 *sizeCount = 1;
969 if( !GetUInt32( regEntry, gIODTAddressCellKey, addressCount))
970 *addressCount = 2;
9bccf70c 971 return;
1c79356b
A
972}
973
974// Given addr & len cells from our child, find it in our ranges property, then
975// look in our parent to resolve the base of the range for us.
976
977// Range[]: child-addr our-addr child-len
978// #cells: child ours child
979
980bool IODTResolveAddressCell( IORegistryEntry * regEntry,
981 UInt32 cellsIn[],
39236c6e 982 IOPhysicalAddress * phys, IOPhysicalLength * lenOut )
1c79356b 983{
9bccf70c
A
984 IORegistryEntry *parent;
985 OSData *prop;
1c79356b 986 // cells in addresses at regEntry
9bccf70c 987 UInt32 sizeCells, addressCells;
1c79356b 988 // cells in addresses below regEntry
9bccf70c
A
989 UInt32 childSizeCells, childAddressCells;
990 UInt32 childCells;
39236c6e 991 UInt32 cell[ 8 ], propLen;
316670eb
A
992 UInt64 offset = 0;
993 UInt32 endCell[ 8 ];
9bccf70c 994 UInt32 *range;
3a60a9f5
A
995 UInt32 *lookRange;
996 UInt32 *startRange;
9bccf70c
A
997 UInt32 *endRanges;
998 bool ok = true;
316670eb 999 SInt64 diff, diff2, endDiff;
39236c6e 1000 UInt64 len, rangeLen;
9bccf70c
A
1001
1002 IODTPersistent *persist;
1c79356b
A
1003 IODTCompareAddressCellFunc compare;
1004
1005 IODTGetCellCounts( regEntry, &childSizeCells, &childAddressCells );
1006 childCells = childAddressCells + childSizeCells;
1007
316670eb
A
1008 if (childCells > sizeof(cell)/sizeof(cell[0]))
1009 panic("IODTResolveAddressCell: Invalid device tree (%u,%u)", (uint32_t)childAddressCells, (uint32_t)childSizeCells);
1010
2d21ac55 1011 bcopy( cellsIn, cell, sizeof(UInt32) * childCells );
39236c6e 1012 *lenOut = CellsValue( childSizeCells, cellsIn + childAddressCells );
1c79356b 1013
3a60a9f5
A
1014 do
1015 {
39236c6e
A
1016 prop = OSDynamicCast( OSData, regEntry->getProperty( gIODTRangeKey ));
1017 if( 0 == prop) {
316670eb 1018 /* end of the road */
39236c6e 1019 *phys = CellsValue( childAddressCells, cell );
316670eb 1020 *phys += offset;
39236c6e
A
1021 break;
1022 }
1c79356b 1023
39236c6e
A
1024 parent = regEntry->getParentEntry( gIODTPlane );
1025 IODTGetCellCounts( parent, &sizeCells, &addressCells );
1026
1027 if( (propLen = prop->getLength())) {
1028 // search
1029 startRange = (UInt32 *) prop->getBytesNoCopy();
1030 range = startRange;
1031 endRanges = range + (propLen / sizeof(UInt32));
1032
1033 prop = (OSData *) regEntry->getProperty( gIODTPersistKey );
1034 if( prop) {
1035 persist = (IODTPersistent *) prop->getBytesNoCopy();
1036 compare = persist->compareFunc;
1037 } else if (addressCells == childAddressCells) {
1038 compare = DefaultCompare;
1039 } else {
1040 panic("There is no mixed comparison function yet...");
1041 }
3a60a9f5 1042
39236c6e
A
1043 for( ok = false;
1044 range < endRanges;
1045 range += (childCells + addressCells) ) {
1046
1047 // is cell start within range?
1048 diff = (*compare)( childAddressCells, cell, range );
1049
1050 if (childAddressCells > sizeof(endCell)/sizeof(endCell[0]))
1051 panic("IODTResolveAddressCell: Invalid device tree (%u)", (uint32_t)childAddressCells);
1052
1053 bcopy(range, endCell, childAddressCells * sizeof(UInt32));
1054
1055 rangeLen = CellsValue(childSizeCells, range + childAddressCells + addressCells);
1056 AddLengthToCells(childAddressCells, endCell, rangeLen);
1057
1058 diff2 = (*compare)( childAddressCells, cell, endCell );
1059
1060 // if start of cell < start of range, or end of range >= start of cell, skip
1061 if ((diff < 0) || (diff2 >= 0))
1062 continue;
1063
1064 len = CellsValue(childSizeCells, cell + childAddressCells);
1065 ok = (0 == len);
1066
1067 if (!ok)
1068 {
1069 // search for cell end
1070 bcopy(cell, endCell, childAddressCells * sizeof(UInt32));
1071
1072 AddLengthToCells(childAddressCells, endCell, len - 1);
1073
1074 for( lookRange = startRange;
1075 lookRange < endRanges;
1076 lookRange += (childCells + addressCells) )
1077 {
1078 // make sure end of cell >= range start
1079 endDiff = (*compare)( childAddressCells, endCell, lookRange );
1080 if( endDiff < 0)
1081 continue;
1082
1083 UInt64 rangeStart = CellsValue(addressCells, range + childAddressCells);
1084 UInt64 lookRangeStart = CellsValue(addressCells, lookRange + childAddressCells);
1085 if ((endDiff - len + 1 + lookRangeStart) == (diff + rangeStart))
1086 {
1087 ok = true;
1088 break;
1089 }
1090 }
1091 if (!ok)
1092 continue;
1093 }
1094 offset += diff;
1095 break;
1096 }
1c79356b 1097
39236c6e
A
1098 if (addressCells + sizeCells > sizeof(cell)/sizeof(cell[0]))
1099 panic("IODTResolveAddressCell: Invalid device tree (%u, %u)", (uint32_t)addressCells, (uint32_t)sizeCells);
316670eb 1100
39236c6e
A
1101 // Get the physical start of the range from our parent
1102 bcopy( range + childAddressCells, cell, sizeof(UInt32) * addressCells );
1103 bzero( cell + addressCells, sizeof(UInt32) * sizeCells );
1c79356b 1104
39236c6e 1105 } /* else zero length range => pass thru to parent */
1c79356b 1106
39236c6e
A
1107 regEntry = parent;
1108 childSizeCells = sizeCells;
1109 childAddressCells = addressCells;
1110 childCells = childAddressCells + childSizeCells;
3a60a9f5
A
1111 }
1112 while( ok && regEntry);
1c79356b
A
1113
1114 return( ok);
1115}
1116
1117
1118OSArray * IODTResolveAddressing( IORegistryEntry * regEntry,
1119 const char * addressPropertyName,
1120 IODeviceMemory * parent )
1121{
0b4e3aa0
A
1122 IORegistryEntry *parentEntry;
1123 OSData *addressProperty;
1124 UInt32 sizeCells, addressCells, cells;
1125 int i, num;
1126 UInt32 *reg;
1c79356b
A
1127 IOPhysicalAddress phys;
1128 IOPhysicalLength len;
0b4e3aa0
A
1129 OSArray *array;
1130 IODeviceMemory *range;
1c79356b
A
1131
1132 parentEntry = regEntry->getParentEntry( gIODTPlane );
1133 addressProperty = (OSData *) regEntry->getProperty( addressPropertyName );
1134 if( (0 == addressProperty) || (0 == parentEntry))
9bccf70c 1135 return( 0);
1c79356b
A
1136
1137 IODTGetCellCounts( parentEntry, &sizeCells, &addressCells );
1138 if( 0 == sizeCells)
9bccf70c 1139 return( 0);
1c79356b
A
1140
1141 cells = sizeCells + addressCells;
1142 reg = (UInt32 *) addressProperty->getBytesNoCopy();
1143 num = addressProperty->getLength() / (4 * cells);
1144
1145 array = OSArray::withCapacity( 1 );
1146 if( 0 == array)
9bccf70c 1147 return( 0);
1c79356b
A
1148
1149 for( i = 0; i < num; i++) {
9bccf70c
A
1150 if( IODTResolveAddressCell( parentEntry, reg, &phys, &len )) {
1151 range = 0;
1152 if( parent)
1153 range = IODeviceMemory::withSubRange( parent,
b0d623f7 1154 phys - parent->getPhysicalSegment(0, 0, kIOMemoryMapperNone), len );
9bccf70c
A
1155 if( 0 == range)
1156 range = IODeviceMemory::withRange( phys, len );
1157 if( range)
1158 array->setObject( range );
1159 }
1160 reg += cells;
1c79356b
A
1161 }
1162
1163 regEntry->setProperty( gIODeviceMemoryKey, array);
1164 array->release(); /* ??? */
1165
1166 return( array);
1167}
1168
1169static void IODTGetNVLocation(
1170 IORegistryEntry * parent,
1171 IORegistryEntry * regEntry,
1172 UInt8 * busNum, UInt8 * deviceNum, UInt8 * functionNum )
1173{
1174
0b4e3aa0
A
1175 OSData *prop;
1176 IODTPersistent *persist;
1177 UInt32 *cell;
1c79356b
A
1178
1179 prop = (OSData *) parent->getProperty( gIODTPersistKey );
1180 if( prop) {
1181 persist = (IODTPersistent *) prop->getBytesNoCopy();
9bccf70c 1182 (*persist->locationFunc)( regEntry, busNum, deviceNum, functionNum );
1c79356b
A
1183 } else {
1184 prop = (OSData *) regEntry->getProperty( "reg" );
1185 *functionNum = 0;
1186 if( prop) {
1187 cell = (UInt32 *) prop->getBytesNoCopy();
1c79356b
A
1188 *busNum = 3;
1189 *deviceNum = 0x1f & (cell[ 0 ] >> 24);
1190 } else {
1191 *busNum = 0;
1192 *deviceNum = 0;
9bccf70c 1193 }
1c79356b 1194 }
0b4e3aa0 1195 return;
1c79356b
A
1196}
1197
1198/*
1199 * Try to make the same messed up descriptor as Mac OS
1200 */
1201
1202IOReturn IODTMakeNVDescriptor( IORegistryEntry * regEntry,
1203 IONVRAMDescriptor * hdr )
1204{
0b4e3aa0
A
1205 IORegistryEntry *parent;
1206 UInt32 level;
1207 UInt32 bridgeDevices;
1208 UInt8 busNum;
1209 UInt8 deviceNum;
1210 UInt8 functionNum;
1c79356b
A
1211
1212 hdr->format = 1;
1213 hdr->marker = 0;
1214
0b4e3aa0
A
1215 for(level = 0, bridgeDevices = 0;
1216 (parent = regEntry->getParentEntry( gIODTPlane )) && (level < 7); level++ ) {
1c79356b
A
1217
1218 IODTGetNVLocation( parent, regEntry,
0b4e3aa0 1219 &busNum, &deviceNum, &functionNum );
9bccf70c
A
1220 if( level)
1221 bridgeDevices |= ((deviceNum & 0x1f) << ((level - 1) * 5));
1222 else {
1c79356b
A
1223 hdr->busNum = busNum;
1224 hdr->deviceNum = deviceNum;
1225 hdr->functionNum = functionNum;
9bccf70c
A
1226 }
1227 regEntry = parent;
1c79356b
A
1228 }
1229 hdr->bridgeCount = level - 2;
1230 hdr->bridgeDevices = bridgeDevices;
1231
1232 return( kIOReturnSuccess );
1233}
1234
1235OSData * IODTFindSlotName( IORegistryEntry * regEntry, UInt32 deviceNumber )
1236{
0b4e3aa0
A
1237 IORegistryEntry *parent;
1238 OSData *data;
1239 OSData *ret = 0;
1240 UInt32 *bits;
1241 UInt32 i;
1242 char *names;
1243 char *lastName;
1244 UInt32 mask;
1c79356b
A
1245
1246 data = (OSData *) regEntry->getProperty("AAPL,slot-name");
1247 if( data)
9bccf70c 1248 return( data);
1c79356b
A
1249 parent = regEntry->getParentEntry( gIODTPlane );
1250 if( !parent)
9bccf70c 1251 return( 0 );
1c79356b
A
1252 data = OSDynamicCast( OSData, parent->getProperty("slot-names"));
1253 if( !data)
9bccf70c 1254 return( 0 );
1c79356b 1255 if( data->getLength() <= 4)
9bccf70c 1256 return( 0 );
1c79356b
A
1257
1258 bits = (UInt32 *) data->getBytesNoCopy();
1259 mask = *bits;
1260 if( (0 == (mask & (1 << deviceNumber))))
9bccf70c 1261 return( 0 );
1c79356b
A
1262
1263 names = (char *)(bits + 1);
1264 lastName = names + (data->getLength() - 4);
1265
0b4e3aa0 1266 for( i = 0; (i <= deviceNumber) && (names < lastName); i++ ) {
1c79356b 1267
9bccf70c 1268 if( mask & (1 << i)) {
1c79356b 1269 if( i == deviceNumber) {
9bccf70c
A
1270 data = OSData::withBytesNoCopy( names, 1 + strlen( names));
1271 if( data) {
1272 regEntry->setProperty("AAPL,slot-name", data);
1273 ret = data;
1274 data->release();
1275 }
1c79356b 1276 } else
9bccf70c 1277 names += 1 + strlen( names);
1c79356b
A
1278 }
1279 }
1280
1281 return( ret );
1282}
91447636
A
1283
1284extern "C" IOReturn IONDRVLibrariesInitialize( IOService * provider )
1285{
1286 return( kIOReturnUnsupported );
1287}