|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24: /*
25: * Copyright (c) 1997 Apple Computer, Inc.
26: *
27: *
28: * HISTORY
29: *
30: * Simon Douglas 22 Oct 97
31: * - first checked in. Some stuff from ExpMgr in MacOS.
32: */
33:
34:
35: #import <mach/mach_types.h>
36: #import <machdep/ppc/DeviceTree.h>
37:
38: #import <driverkit/KernDeviceDescription.h>
39: #import <driverkit/ppc/PPCKernBus.h>
40:
41: #import <driverkit/ppc/IOPPCDeviceDescription.h>
42: #import <driverkit/ppc/IOPPCDeviceDescriptionPriv.h>
43: #import <driverkit/IODeviceDescriptionPrivate.h>
44: #import <driverkit/ppc/directDevice.h>
45: #import <string.h>
46:
47: #import <driverkit/ppc/IODeviceTreeBus.h>
48:
49: /* DK calls this for PExpert to change DT entries */
50: extern int PEEditDTEntry( DTEntry dtEntry, char * nodeName, int index,
51: char ** propName , void ** propData, int * propSize);
52:
53: static const char * device_type = "device_type";
54:
55: @implementation IODeviceTreeBus
56:
57: static IOPropertyTable *
58: MakeReferenceTable( DTEntry dtEntry )
59: {
60: IOReturn err;
61: IOPropertyTable * propTable;
62: DTPropertyIterator dtIter;
63: void * prop;
64: int propSize;
65: char * name;
66: char * nodeName = NULL;
67: int index;
68:
69: propTable = [[IOPropertyTable alloc] init];
70: err = DTCreatePropertyIterator( dtEntry, &dtIter);
71:
72: if( err == kSuccess) {
73: while( kSuccess == DTIterateProperties( dtIter, &name)) {
74: err = DTGetProperty( dtEntry, name, &prop, &propSize );
75: if( err != kSuccess)
76: continue;
77:
78: if( 0 == strcmp( name, "name"))
79: nodeName = (char *) prop;
80:
81: err = [propTable createProperty:name flags:kReferenceProperty value:prop length:propSize];
82: }
83: DTDisposePropertyIterator( dtIter);
84: }
85:
86: index = 0;
87: do {
88: err = PEEditDTEntry( dtEntry, nodeName, index++, &name, &prop, &propSize);
89: if( err)
90: continue;
91:
92: [propTable deleteProperty:name];
93: if( prop)
94: err = [propTable createProperty:name flags:kReferenceProperty value:prop length:propSize];
95:
96: } while( err == noErr);
97:
98: return( propTable);
99: }
100:
101:
102: + (BOOL)probe:deviceDescription
103: {
104: id inst;
105:
106: // Create an instance and initialize some basic instance variables.
107: inst = [[self alloc] initFromDeviceDescription:deviceDescription];
108: if (inst == nil)
109: return NO;
110:
111: [inst setDeviceKind:"Bus"];
112:
113: [inst registerDevice];
114:
115: [inst probeBus];
116:
117: return( YES);
118: }
119:
120: - initFromDeviceDescription:(IOTreeDevice *)deviceDescription
121: {
122: void * prop;
123: UInt32 propSize;
124: IOReturn err;
125: char nameBuf[ 64 ];
126:
127: if ([super initFromDeviceDescription:deviceDescription] == nil)
128: return [super free];
129:
130: myDevice = deviceDescription;
131: myParent = [deviceDescription parent];
132: propTable = [deviceDescription propertyTable];
133: myEntry = [deviceDescription getRef];
134:
135: [self setUnit:0];
136: [myDevice getDevicePath:nameBuf maxLength:sizeof( nameBuf) useAlias:NO];
137: [self setName:nameBuf];
138:
139: prop = &childSizeCells;
140: propSize = 4;
141: err = [propTable getProperty:"#size-cells" flags:0
142: value:(void **) &prop length:&propSize];
143: if( err || (propSize < sizeof(int)))
144: childSizeCells = 1;
145:
146: prop = &childAddrCells;
147: propSize = 4;
148: err = [propTable getProperty:"#address-cells" flags:0
149: value:(void **) &prop length:&propSize];
150: if( err || (propSize < sizeof(int)))
151: childAddrCells = 2;
152:
153: myAddrCells = [deviceDescription addressCells];
154: mySizeCells = [deviceDescription sizeCells];
155:
156: return( self);
157: }
158:
159:
160: - probeBus
161: {
162: IOReturn err;
163: IOPropertyTable * table;
164: DTEntryIterator iter;
165: DTEntry child;
166: void * prop;
167: UInt32 propSize;
168: id dev;
169:
170: DTCreateEntryIterator( (DTEntry) myEntry, &iter );
171:
172: while( kSuccess == DTIterateEntries( iter, &child) ) {
173:
174: table = MakeReferenceTable( child);
175:
176: // Look for existence of a debug property to skip
177: if( [table getProperty:"AAPL,ignore" flags:kReferenceProperty
178: value:&prop length:&propSize])
179: dev = [self createDevice:table ref:(id)child];
180: else
181: dev = nil;
182:
183: if( nil == dev)
184: [table free];
185:
186: }
187: DTDisposeEntryIterator( iter);
188:
189: return( self);
190: }
191:
192:
193: - createDevice:(IOPropertyTable *)newTable ref:ref
194: {
195: id newDev;
196:
197: newDev = [[IOTreeDevice alloc] initAt:newTable parent:self ref:ref];
198:
199: return( [newDev publish] );
200: }
201:
202: static BOOL CompareName( const char * keys, const char * nameList, IOPropertyTable * table)
203: {
204: BOOL matched;
205: UInt32 keyLen, nameLen;
206: const char * nextKey;
207: const char * names;
208: const char * nextName;
209: BOOL wild;
210:
211: do {
212: // for each key
213:
214: nextKey = strchr( keys, ' ');
215: if( nextKey)
216: keyLen = nextKey - keys;
217: else
218: keyLen = strlen( keys);
219: wild = (keys[ keyLen - 1 ] == '*');
220:
221: names = nameList;
222: do {
223: // for each name
224:
225: nextName = strchr( names, ' ');
226: if( nextName)
227: nameLen = nextName - names;
228: else
229: nameLen = strlen( names);
230:
231: if( wild)
232: matched = (0 == strncmp( keys, names, keyLen - 1 ));
233: else
234: matched = ((nameLen == keyLen)
235: && (0 == strncmp( keys, names, keyLen )));
236:
237: if( matched)
238: [table createProperty:"AAPL,matched-on" flags:0
239: value:names length:nameLen];
240:
241: names = nextName + 1;
242:
243: } while( nextName && (NO == matched));
244:
245: keys = nextKey + 1;
246:
247: } while( nextKey && (NO == matched));
248:
249: return( matched);
250: }
251:
252: - (BOOL) match:(IOTreeDevice *)device key:(const char *)keys location:(const char *)location
253: {
254: UInt32 propSize, i;
255: IOPropertyTable * table;
256: const char * nodeName;
257: char * compat;
258: char * tail;
259: const char * devType;
260: const char * model;
261: BOOL matched;
262:
263: table = [device propertyTable];
264:
265: if( 0 == strcmp( keys, "device-tree")) {
266:
267: // match ourselves to anything looking like a bus
268: return(
269: (noErr == [table getProperty:"ranges" flags:kReferenceProperty
270: value:NULL length:&propSize]) );
271: }
272:
273: nodeName = [device nodeName];
274:
275: if( [table getProperty:device_type flags:kReferenceProperty
276: value:(void **)&devType length:&propSize])
277: devType = NULL;
278:
279: if( [table getProperty:"model" flags:kReferenceProperty
280: value:(void **)&model length:&propSize])
281: model = NULL;
282:
283: if( [table getProperty:"compatible" flags:kReferenceProperty
284: value:(void **)&compat length:&propSize])
285: compat = NULL;
286: else {
287: // convert separators from null to blanks. Blech.
288: compat = (char *)IOMalloc( propSize);
289: [table getProperty:"compatible" flags:0
290: value:(void **)&compat length:&propSize];
291: for( i = 0; i < propSize - 1; i++)
292: if( compat[ i ] == 0)
293: compat[ i ] = ' ';
294: }
295:
296: // Is this enough ordering?
297: matched = (model && CompareName( keys, model, table))
298: || (compat && CompareName( keys, compat, table))
299: || (nodeName && CompareName( keys, nodeName, table))
300: || (devType && CompareName( keys, devType, table));
301:
302: if( compat)
303: IOFree( compat, propSize);
304:
305: if( matched && location)
306: matched = ((tail = [device matchDevicePath:location]) && (tail[0] == 0));
307:
308: return( matched );
309: }
310:
311: + probeTree
312: {
313: IOPropertyTable * table;
314: id root;
315: DTEntry rootEntry;
316:
317: DTLookupEntry( (DTEntry) 0, "/", &rootEntry );
318: table = MakeReferenceTable( rootEntry);
319:
320: root = [[IORootDevice alloc] initAt:table ref:(id)rootEntry];
321: if( nil == root)
322: return( [table free]);
323: else
324: return( [root publish]);
325: }
326:
327: void DeviceTreeProbe( void )
328: {
329: [IODeviceTreeBus probeTree];
330: }
331:
332: // Cells in child nodes
333: - (ItemCount) sizeCells
334: {
335: return( childSizeCells );
336: }
337: - (ItemCount) addressCells
338: {
339: return( childAddrCells );
340: }
341:
342: // Given an addr-len cell from our child, find it in our ranges property, then
343: // recurse to our parent to resolve the base of the range for us.
344:
345: // Range[]: child-addr our-addr child-len
346: // #cells: child ours child
347:
348: - (IOReturn) resolveAddressCell:(UInt32 *)cell physicalAddress:(PhysicalAddress *)phys
349: {
350: IOReturn err;
351: UInt32 * nextRange;
352: UInt32 * endRanges;
353: UInt32 start, rangeStart;
354: UInt32 rangeAddr[ 5 ];
355: UInt32 childCells;
356: UInt32 propSize;
357: UInt32 result;
358:
359: childCells = childAddrCells + childSizeCells;
360:
361: err = [propTable getProperty:"ranges" flags:kReferenceProperty
362: value:(void **) &nextRange length:&propSize];
363:
364: if( err) {
365: // 1-1 map at root
366: *phys = (PhysicalAddress) cell[ childAddrCells - 1 ];
367: return( noErr);
368: }
369:
370: if( propSize == 0)
371: return( [myDevice resolveAddressCell:cell
372: physicalAddress:(PhysicalAddress *)phys] );
373:
374: if( propSize < (sizeof(int) * (childCells + myAddrCells)) )
375: return( IO_R_NO_MEMORY);
376:
377: err = IO_R_NO_MEMORY;
378: endRanges = nextRange + (propSize / sizeof(int));
379:
380: for( ;
381: nextRange < endRanges;
382: nextRange += (childCells + myAddrCells)) {
383:
384: // how is the address compare really supposed to be done?
385: if( childAddrCells > 1) {
386: UInt32 space1, space2;
387: // treat 64-bit memory spaces as 32-bit
388: space1 = (nextRange[ 0 ] >> 24) & 0x03;
389: space2 = (cell[ 0 ] >> 24) & 0x03;
390: if( space1 == 3)
391: space1 = 2;
392: if( space2 == 3)
393: space2 = 2;
394: if( space1 != space2)
395: continue;
396: }
397:
398: rangeStart = nextRange[ childAddrCells - 1 ];
399: start = cell[ childAddrCells - 1 ];
400:
401: if( (rangeStart <= start)
402: && ( (start + cell[ childCells - 1 ])
403: <= (rangeStart + nextRange[ childCells + myAddrCells - 1 ]) )) {
404:
405: // Get the physical start of the range from our parent
406: bcopy( nextRange + childAddrCells, rangeAddr, 4 * myAddrCells );
407: bzero( rangeAddr + myAddrCells, 4 * mySizeCells );
408: err = [myDevice resolveAddressCell:rangeAddr
409: physicalAddress:(PhysicalAddress *)&result];
410: if( err)
411: continue;
412: *phys = (PhysicalAddress) (result + start - rangeStart);
413: break;
414: }
415: }
416: return( err);
417: }
418:
419: // Find interrupt addressing info
420:
421: - (IOReturn) interruptSpecCells:(UInt32)handle count:(UInt32 *)count
422: {
423: IOReturn err;
424: UInt32 cells;
425: UInt32 * prop;
426: UInt32 propSize;
427:
428: err = [propTable getProperty:"AAPL,phandle"
429: flags:kReferenceProperty
430: value:(void **)&prop length:&propSize];
431: if( err)
432: return( err);
433:
434: if( handle && (handle != *prop)) {
435: // This is a hack - a non-DT-parent interrupt parent
436: // is assumed the root controller.
437: *count = 1;
438: return( noErr );
439: }
440:
441: err = [propTable getProperty:"#interrupt-cells"
442: flags:kReferenceProperty
443: value:(void **)&prop length:&propSize];
444:
445: cells = childAddrCells;
446: if( err == noErr)
447: cells += *prop;
448: *count = cells;
449:
450: return( noErr);
451: }
452:
453: // Map one 'unit interrupt specifier' to platform interrupt
454:
455: - (IOReturn) mapUnitInterrupt:(UInt32 *)interruptSpec
456: toInterrupt:(UInt32 **)mapped
457: parentHandle:(UInt32)handle
458: {
459: IOReturn err;
460: UInt32 * map;
461: UInt32 * mapEnd;
462: UInt32 propSize;
463: UInt32 * mask;
464: UInt32 myICells, parentICells;
465: UInt32 iParent;
466: int i;
467:
468: err = [self interruptSpecCells:handle count:&myICells];
469: if( err)
470: return( err);
471:
472: if( 1 == myICells) {
473: *mapped = interruptSpec;
474: return( noErr);
475: }
476:
477: err = [propTable getProperty:"interrupt-map-mask"
478: flags:kReferenceProperty
479: value:(void **)&mask length:&propSize];
480: if( err)
481: return( err);
482: if( propSize != (4 * myICells))
483: return( IO_R_INVALID_ARG);
484:
485: err = [propTable getProperty:"interrupt-map"
486: flags:kReferenceProperty
487: value:(void **)&map length:&propSize];
488: if( err)
489: return( err);
490:
491: mapEnd = map + (propSize / 4);
492:
493: while( map < mapEnd) {
494:
495: for( i = 0; i < myICells; i++) {
496: if( (interruptSpec[ i ] & mask[ i ]) != map[ i ])
497: break;
498: }
499:
500: iParent = map[ myICells ];
501:
502: if( i == myICells) {
503: // it matched
504: err = [myParent mapUnitInterrupt:(map + myICells + 1)
505: toInterrupt:mapped
506: parentHandle:iParent];
507: break;
508: }
509:
510: // skip this controller's stuff & loop
511: err = [myParent interruptSpecCells:iParent count:&parentICells];
512: if( err == noErr)
513: map += myICells + parentICells + 1;
514: else
515: break;
516: }
517:
518: return( err);
519: }
520:
521: // Create platform interrupts for a child device
522:
523: - (IOReturn) mapInterrupts:(IOTreeDevice *)device
524: interrupts:(UInt32 *)interrupts num:(UInt32 *)count
525: {
526: IOReturn err;
527: UInt32 * prop;
528: UInt32 propSize;
529: UInt32 iParent = 0;
530: UInt32 intSpec[ 5 ];
531: UInt32 myICells;
532: UInt32 * mapped;
533: int i, num;
534:
535: do {
536: propSize = *count * 4;
537: err = [[device propertyTable] getProperty:"interrupts" flags:0
538: value:(void **)&interrupts length:&propSize];
539: if( err)
540: continue;
541: num = propSize / 4;
542: *count = num;
543:
544: err = [[device propertyTable] getProperty:"interrupt-parent"
545: flags:kReferenceProperty
546: value:(void **)&prop length:&propSize];
547: if( err == noErr)
548: iParent = *prop;
549:
550: err = [self interruptSpecCells:iParent count:&myICells];
551: if( err)
552: continue;
553: if( 1 == myICells)
554: continue;
555:
556: err = [[device propertyTable] getProperty:"reg"
557: flags:kReferenceProperty
558: value:(void **)&prop length:&propSize];
559: if( err)
560: continue;
561: bcopy( prop, intSpec, childAddrCells * 4);
562:
563: for( i = 0; (err == noErr) && (i < num); i++ ) {
564: // assuming #interrupt-cell == 1
565: intSpec[ childAddrCells ] = interrupts[ i ];
566: err = [self mapUnitInterrupt:intSpec
567: toInterrupt:&mapped
568: parentHandle:iParent];
569: interrupts[ i ] = *mapped;
570: }
571:
572: } while( NO);
573:
574: return( err);
575: }
576:
577: // Create an AAPL,slot-name property from parent's slot-names
578:
579: - getSlotName:(IOTreeDevice *) device index:(UInt32)deviceNum
580: {
581: IOReturn err;
582: UInt32 * prop;
583: UInt32 propSize;
584: int i;
585: char * names;
586: char * lastName;
587: UInt32 mask;
588:
589: err = [propTable getProperty:"slot-names"
590: flags:kReferenceProperty
591: value:(void **) &prop
592: length:&propSize];
593:
594: if( err == noErr) {
595: mask = *prop;
596: names = (char *)(prop + 1);
597: lastName = names + (propSize - 4);
598:
599: for( i = 0;
600: (i <= deviceNum) && (names < lastName);
601: i++ ) {
602:
603: if( mask & (1 << i)) {
604: if( i == deviceNum) {
605: err = [[device propertyTable]
606: createProperty:"AAPL,slot-name" flags:0
607: value:(void *)names
608: length:(1 + strlen( names))];
609: } else
610: names += 1 + strlen( names);
611: }
612: }
613: }
614:
615: return( self);
616: }
617:
618:
619: // Set the NVRAM description for the child device, which could be a bridge
620: // as this recurses up the tree.
621:
622: - makeNVRAMDescriptor:(IOTreeDevice *)device
623: descriptor:(NVRAMDescriptor *)propHdr
624: {
625: UInt8 busNum, deviceNum, functionNum;
626:
627: [device getLocation:&busNum device:&deviceNum function:&functionNum];
628:
629: if( propHdr->format == 0) {
630: propHdr->format = 0x1;
631: propHdr->busNum = busNum;
632: propHdr->functionNum = functionNum;
633: propHdr->deviceNum = deviceNum;
634:
635: } else if( propHdr->bridgeCount < 6) {
636: propHdr->bridgeDevices |= (deviceNum << (propHdr->bridgeCount * 5));
637: propHdr->bridgeCount++;
638: }
639:
640: if( myParent)
641: return( [myParent makeNVRAMDescriptor:myDevice descriptor:propHdr] );
642:
643: return( self);
644: }
645:
646: - getDevicePath:(IOTreeDevice *)device path:(char *)path maxLength:(int)maxLen
647: {
648: IOReturn err = noErr;
649: int len;
650: ByteCount propSize;
651: char * nextComp;
652:
653: if( myParent)
654: if( nil == [myParent getDevicePath:myDevice path:path maxLength:maxLen])
655: return( nil);
656:
657: len = strlen( path);
658: maxLen--;
659: nextComp = path + len;
660:
661: len++;
662: if( len < maxLen) {
663: *(nextComp++) = '/';
664: len += strlen( [device nodeName]);
665: if( len < maxLen) {
666: strcpy( nextComp, [device nodeName] );
667: nextComp = path + len;
668: len++;
669: if( len < maxLen) {
670: *(nextComp++) = '@';
671: if( [self getDeviceUnitStr:device name:nextComp maxLength:(maxLen - len)])
672: return( self);
673: }
674: }
675: }
676: // failed
677: *path = 0;
678: return( nil);
679: }
680:
681: - getDeviceUnitStr:(IOTreeDevice *)device name:(char *)name maxLength:(int)len
682: {
683: IOReturn err;
684: UInt32 * regProp;
685: ByteCount propSize;
686: char unitStr[ 10 ] = "0"; // lame default for no reg, just like OF
687:
688: err = [[device propertyTable] getProperty:"reg" flags:kReferenceProperty
689: value:(void **) ®Prop length:&propSize];
690: if( err == noErr)
691: sprintf( unitStr, "%lx", regProp[ childAddrCells - 1 ]);
692:
693: if( strlen( unitStr) < len) {
694: strcpy( name, unitStr);
695: return( self);
696: }
697: // failed
698: return( nil);
699: }
700:
701: - registerLoudly
702: {
703: return( nil);
704: }
705:
706: @end
707:
708:
709:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.