|
|
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.