|
|
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: /* ! 26: * Copyright (c) 1993 NeXT Computer, Inc. ! 27: * ! 28: * PPC Driverkit configuration. ! 29: * ! 30: * HISTORY ! 31: * ! 32: * 10 Dec 1998 Adam Wang ! 33: * Added USB matching ! 34: * 27 Oct 1997 Simon Douglas ! 35: * Added support for tree probe, name matching. ! 36: * 28 June 1994 ! 37: * Derived from i386 version. ! 38: * 28 Jan 1993 Brian Pinkerton at NeXT ! 39: * Added support for new, MI autoconf logic, and new driverkit API. ! 40: * 10 Nov 1992 Brian Pinkerton at NeXT ! 41: * Added indirect probe logic. ! 42: * 20 Aug 1992 Joe Pasqua ! 43: * Init intrReq & intrAttached of kern_dev in configure_device_class(). ! 44: * 3 August 1992 ? at NeXT ! 45: * Created. ! 46: */ ! 47: ! 48: #import <mach/mach_types.h> ! 49: ! 50: #import <machkit/NXLock.h> ! 51: #import <objc/List.h> ! 52: #import <driverkit/KernDeviceDescription.h> ! 53: #import <driverkit/KernStringList.h> ! 54: #import <driverkit/ppc/IOPPCDeviceDescription.h> ! 55: #import <driverkit/IODeviceDescriptionPrivate.h> ! 56: #import <driverkit/IODirectDevice.h> ! 57: #import <driverkit/IODeviceKernPrivate.h> ! 58: #import <driverkit/IODeviceParams.h> ! 59: #import <driverkit/Device_ddm.h> ! 60: #import <driverkit/configTableKern.h> ! 61: #import <driverkit/KernDevice.h> ! 62: #import <driverkit/IOConfigTable.h> ! 63: #import <driverkit/driverTypesPrivate.h> ! 64: #import <driverkit/autoconfCommon.h> ! 65: #import <driverkit/ppc/PPCKernBus.h> ! 66: #import <driverkit/ppc/PPCKernBusPrivate.h> ! 67: ! 68: #import <machdep/ppc/kernBootStruct.h> ! 69: #import <machdep/ppc/DeviceTree.h> ! 70: #import <driverkit/ppc/IOTreeDevice.h> ! 71: ! 72: /* Used for machine determination */ ! 73: #import <machdep/ppc/powermac.h> ! 74: #import <machdep/ppc/powermac_gestalt.h> ! 75: #import <string.h> ! 76: ! 77: // config tables passed by booter in /AAPL,loadables dir ! 78: static char ** allConfigTables; ! 79: static int numConfigTables; ! 80: ! 81: #define BUS_LOAD_PRI_PROP "\"Load Priority\" = \"10000\";" ! 82: // for debugging ! 83: #define ENET_LOAD_PRI_PROP "\"Load Priority\" = \"7000\";" ! 84: #define VIA_LOAD_PRI_PROP "\"Load Priority\" = \"6800\";" ! 85: // slightly higher than default so they come before any PCI SCSI ! 86: #define INT_IDE_LOAD_PRI_PROP "\"Load Priority\" = \"5050\";" ! 87: #define INT_SCSI_LOAD_PRI_PROP "\"Load Priority\" = \"5100\";" ! 88: #define EXT_SCSI_LOAD_PRI_PROP "\"Load Priority\" = \"5200\";" ! 89: #define DISPLAY_LOAD_PRI 6000 ! 90: #define DEFAULT_LOAD_PRI 5000 ! 91: #define USBCMD_LOAD_PRI_PROP "\"Load Priority\" = \"4000\";" ! 92: ! 93: static const char * inKernelConfigTables = ! 94: ! 95: "\"Bus Class\" = \"PPCKernBus\";" ! 96: "\"Class Names\" = \"\";" ! 97: "\"Family\" = \"Bus\";" ! 98: "\"Instance\" = \"0\";" ! 99: "\"Version\" = \"5.0\";" ! 100: "\0" ! 101: #if MK_HASDRIVERS ! 102: "\"Driver Name\" = \"BMacEnet\";" ! 103: "\"Matching\" = \"bmac bmac+\";" ! 104: ENET_LOAD_PRI_PROP ! 105: "\0" ! 106: "\"Driver Name\" = \"MaceEnet\";" ! 107: "\"Matching\" = \"mace\";" ! 108: ENET_LOAD_PRI_PROP ! 109: "\0" ! 110: "\"Driver Name\" = \"DECchip21041\";" ! 111: "\"Matching\" = \"pci1011,14\";" ! 112: "\"Share IRQ Levels\" = \"YES\";" ! 113: "\"Network Interface\" = \"AUTO\";" ! 114: ENET_LOAD_PRI_PROP ! 115: "\0" ! 116: "\"Driver Name\" = \"Apple96_SCSI\";" ! 117: "\"Matching\" = \"53c94\";" ! 118: "\"Bus Type\" = \"PPC\";" // why do they look for it? ! 119: EXT_SCSI_LOAD_PRI_PROP ! 120: "\0" ! 121: "\"Driver Name\" = \"AppleMesh_SCSI\";" ! 122: "\"Matching\" = \"mesh\";" ! 123: "\"Bus Type\" = \"PPC\";" // why do they look for it? ! 124: INT_SCSI_LOAD_PRI_PROP ! 125: "\0" ! 126: "\"Family\" = \"Disk\";" ! 127: "\"Driver Name\" = \"EIDE\";" ! 128: "\"Matching\" = \"ide ata ATA pci1095,646\";" ! 129: "\"Class Names\" = \"IdeController AtapiController\";" ! 130: "\"Block Major\" = \"3\";" ! 131: "\"Character Major\" = \"15\";" ! 132: INT_IDE_LOAD_PRI_PROP ! 133: "\0" ! 134: "\"Driver Name\" = \"ApplePMU\";" ! 135: "\"Matching\" = \"via-pmu\";" ! 136: VIA_LOAD_PRI_PROP ! 137: "\0" ! 138: "\"Driver Name\" = \"AppleCuda\";" ! 139: "\"Matching\" = \"via-cuda\";" ! 140: VIA_LOAD_PRI_PROP ! 141: "\0" ! 142: "\"Driver Name\" = \"AppleUSBCMD\";" ! 143: "\"Matching\" = \"pci1095,670\";" ! 144: USBCMD_LOAD_PRI_PROP ! 145: "\0" ! 146: "\"Driver Name\" = \"AppleUSBCMD\";" ! 147: "\"Matching\" = \"pci11c1,5801\";" ! 148: USBCMD_LOAD_PRI_PROP ! 149: "\0" ! 150: "\"Driver Name\" = \"AppleUSBCMD\";" ! 151: "\"Matching\" = \"pciclass,0c0310\";" ! 152: USBCMD_LOAD_PRI_PROP ! 153: "\0" ! 154: "\"Driver Name\" = \"AppleUSBCMD\";" ! 155: "\"Matching\" = \"usb\";" ! 156: USBCMD_LOAD_PRI_PROP ! 157: "\0" ! 158: "\"Driver Name\" = \"AppleOHare\";" ! 159: "\"Matching\" = \"pci106b,7\";" ! 160: BUS_LOAD_PRI_PROP ! 161: "\0" ! 162: "\"Driver Name\" = \"Symbios8xx\";" ! 163: "\"Matching\" = \"apple53C8xx Apple53C875Card\";" ! 164: "\"Class Names\" = \"Sym8xxController\";" ! 165: "\"Bus Type\" = \"PPC\";" ! 166: "\0" ! 167: "\"Driver Name\" = \"AdaptecU2SCSI\";" ! 168: "\"Matching\" = \"ADPT,2940U2B ADPT,3950U2B ADPT,2930CU ADPT,2930U\";" ! 169: "\"Class Names\" = \"AdaptecU2SCSI\";" ! 170: "\"Bus Type\" = \"PPC\";" ! 171: INT_SCSI_LOAD_PRI_PROP ! 172: "\0" ! 173: #endif /* MK_HASDRIVERS */ ! 174: ! 175: #if DK_HASDRIVERS ! 176: "\"Driver Name\" = \"IOMacRiscPCIBridge\";" ! 177: "\"Matching\" = \"bandit\";" ! 178: BUS_LOAD_PRI_PROP ! 179: "\0" ! 180: "\"Driver Name\" = \"IOMacRiscVCIBridge\";" ! 181: "\"Matching\" = \"chaos\";" ! 182: BUS_LOAD_PRI_PROP ! 183: "\0" ! 184: "\"Driver Name\" = \"IOGracklePCIBridge\";" ! 185: "\"Matching\" = \"grackle\";" ! 186: BUS_LOAD_PRI_PROP ! 187: "\0" ! 188: "\"Driver Name\" = \"IOPCIBridge\";" ! 189: "\"Matching\" = \"pci-bridge\";" ! 190: BUS_LOAD_PRI_PROP ! 191: "\0" ! 192: "\"Driver Name\" = \"IONDRVFramebuffer\";" /* shim for ndrv's */ ! 193: "\"Matching\" = \"display\";" /* matches device_type */ ! 194: "\"Load Priority\" = \"6000\";" ! 195: "\0" ! 196: #endif /* DK_HASDRIVERS */ ! 197: "\"Driver Name\" = \"IODeviceTreeBus\";" ! 198: "\"Matching\" = \"cpu cpus l2-cache\";" /* matches device_type */ ! 199: "\0" ! 200: /************ must be last ************/ ! 201: "\"Driver Name\" = \"IODeviceTreeBus\";" ! 202: "\"Matching\" = \"device-tree\";" /* matches any tree "bus" node */ ! 203: BUS_LOAD_PRI_PROP ! 204: "\0" ! 205: "\0" ! 206: ; ! 207: ! 208: void DeviceTreeProbe( void ); ! 209: static int ! 210: MatchDriversForDevice( id ioDevice ); ! 211: static char * ! 212: FindStringKey( const char * config, const char * key, char * value ); ! 213: IOReturn ! 214: PublishDevice( id ioDevice ); ! 215: static BOOL ! 216: StartDriver( IOConfigTable * configTable, id ioDeviceDescription ); ! 217: BOOL ! 218: NewLoadDriver( const char * configData ); ! 219: ! 220: static void probe_indirect(const char **indirectNamep, id driverInstance); ! 221: const char *findBootConfigString(int n); ! 222: static void bootDriverInit(void); ! 223: ! 224: id defaultBus, defaultBusClass; ! 225: id autoConfigTables; ! 226: ! 227: /* ! 228: * Native indirect driver classes. ! 229: */ ! 230: char *indirectDevList[] = { ! 231: "ATADisk", ! 232: "SCSIDisk", ! 233: "SCSIGeneric", ! 234: "IODiskPartition", ! 235: "IOADBBus", ! 236: "PPCKeyboard", ! 237: "PPCMouse", ! 238: NULL ! 239: }; ! 240: ! 241: /* ! 242: * Pseudo device list. ! 243: */ ! 244: char *pseudoDevList[] = { ! 245: "EventDriver", ! 246: "kmDevice", ! 247: NULL ! 248: }; ! 249: ! 250: #define SERVER_NAME_KEY "Server Name" ! 251: #define CLASS_NAMES_KEY "Class Names" ! 252: #define DRIVER_NAME_KEY "Driver Name" ! 253: #define BUS_CLASS_KEY "Bus Class" ! 254: #define BUS_TYPE_KEY "Bus Type" ! 255: #define FAMILY_KEY "Family" ! 256: #define BUS_FAMILY "Bus" ! 257: #define KERN_BUS_FORMAT "%sKernBus" ! 258: #define DEVICE_DESCR_FORMAT "IO%sDeviceDescription" ! 259: #define DEFAULT_BUS "PPC" ! 260: #define NAME_BUF_LEN 128 ! 261: ! 262: ! 263: static BOOL ! 264: versionIsOK(const char *serverName) ! 265: { ! 266: int version; ! 267: ! 268: return YES; ! 269: /* ! 270: * Right now, if serverName is NULL, that means the driver ! 271: * is compiled into the kernel, so don't check the version. ! 272: * This may change later, however. ! 273: */ ! 274: ! 275: if (serverName != NULL) { ! 276: version = [IODevice ! 277: driverKitVersionForDriverNamed:(char *)serverName]; ! 278: if (version == -1) ! 279: version = 310; ! 280: /* ! 281: * TODO: revisit this policy decision if DriverKit ! 282: * compatibility changes in the future. ! 283: */ ! 284: if (version <= 310) { ! 285: IOLog("WARNING: driver %s uses incompatible DriverKit version %d\n", serverName, version); ! 286: IOLog("Driver %s could not be configured\n", ! 287: serverName); ! 288: return NO; ! 289: } ! 290: } ! 291: return YES; ! 292: } ! 293: ! 294: #define BUILTIN_BUS_CLASS "PPCKernBus" // XXX ! 295: ! 296: /* ! 297: * Eventually, this routine will only initialize the boot device(s) per ! 298: * input from the booter via KERNBOOTSTRUCT. ! 299: * For now, configure all native devices enumerated in the various ! 300: * tables in device_configuration.c. ! 301: */ ! 302: ! 303: void ! 304: probeNativeDevices(void) ! 305: { ! 306: int i; ! 307: const char *config; ! 308: IOConfigTable *configTable = nil; ! 309: const char *family, *busName; ! 310: id busClass; ! 311: BOOL gotBuiltinBus = NO; ! 312: ! 313: autoConfigTables = [[List alloc] init]; ! 314: ! 315: // ! 316: // Initialize drivers and modules loaded by booter. ! 317: ! 318: bootDriverInit(); ! 319: ! 320: // ! 321: // Find all bus drivers. ! 322: // ! 323: ! 324: for(i=1; (config = findBootConfigString(i)); i++) { ! 325: ! 326: configTable = [IOConfigTable newForConfigData:config]; ! 327: family = [configTable valueForStringKey:FAMILY_KEY]; ! 328: if (family && strcmp(family, BUS_FAMILY) == 0) { ! 329: busName = [configTable valueForStringKey:BUS_CLASS_KEY]; ! 330: if (!busName) { ! 331: printf("autoconf: missing \"%s\" key\n", ! 332: BUS_CLASS_KEY); ! 333: continue; ! 334: } ! 335: if (strcmp(busName, BUILTIN_BUS_CLASS) == 0) { ! 336: gotBuiltinBus = YES; ! 337: } ! 338: busClass = objc_getClass(busName); ! 339: (void)[busClass probeBus:configTable]; ! 340: [configTable freeString:busName]; ! 341: [configTable freeString:family]; ! 342: } else { ! 343: if (family) ! 344: [configTable freeString:family]; ! 345: [configTable free]; ! 346: } ! 347: } ! 348: ! 349: if (gotBuiltinBus == NO) { // XXX ! 350: busClass = objc_getClass(BUILTIN_BUS_CLASS); ! 351: (void)[busClass probeBus:nil]; ! 352: } ! 353: ! 354: defaultBusClass = [KernBus lookupBusClassWithName:DEFAULT_BUS]; // XXX ! 355: if (defaultBusClass == nil) { ! 356: panic("Missing default kernel bus class"); ! 357: } ! 358: defaultBus = [KernBus lookupBusInstanceWithName:DEFAULT_BUS busId:0]; ! 359: ! 360: /* ! 361: */ ! 362: for( i = 1; (config = findBootConfigString(i)); i++) { ! 363: NewLoadDriver( config ); ! 364: } ! 365: ! 366: /* ! 367: * Probe the device tree ! 368: */ ! 369: DeviceTreeProbe(); ! 370: ! 371: } ! 372: ! 373: ! 374: @protocol OldProbeMethods ! 375: + probe; ! 376: + probe:(int)a deviceMaster:(port_t) b; ! 377: @end ! 378: ! 379: /* ! 380: * Called from MD probeNativeDevices() and from configureThread(), the ! 381: * IOTask version of IOProbeDriver(). ! 382: * ! 383: * Given a class name and an ASCII representation of a config file, ! 384: * create a kern_dev and an IODeviceDescription and probe the class. ! 385: * This is used both at boot time - for the boot device and (temporarily) ! 386: * any native drivers with static config tables - and by IOProbeDriver(). ! 387: * ! 388: * Returns YES if driver was started successfully, else returns NO. ! 389: */ ! 390: ! 391: static BOOL ! 392: StartDriver( IOConfigTable * configTable, id ioDeviceDescription ) ! 393: { ! 394: const char *className, *classNames; ! 395: KernStringList *classNameList = nil; ! 396: const char *serverName = NULL; ! 397: Class theClass; ! 398: id deviceDescription = nil; ! 399: id device = nil; ! 400: id newDescription; ! 401: int index, classesLoaded; ! 402: BOOL versionChecked = NO; ! 403: const char *placeholder; ! 404: const char *busType, *busTypeString; ! 405: char *nameBuf; ! 406: id busClass, busDescriptionClass; ! 407: ! 408: ! 409: nameBuf = (char *)IOMalloc(NAME_BUF_LEN); ! 410: ! 411: serverName = [configTable valueForStringKey:SERVER_NAME_KEY]; ! 412: ! 413: /* ! 414: * Check for a placeholder config table ! 415: * that represents a dynamically configured device. ! 416: * NOTE: this skips the driverkit version check. XXX ! 417: */ ! 418: if ((placeholder = [configTable valueForStringKey:"Dynamic"])) { ! 419: if (*placeholder == 'Y' || *placeholder == 'y') { ! 420: [autoConfigTables addObject:configTable]; ! 421: [configTable freeString:placeholder]; ! 422: return YES; ! 423: } else { ! 424: [configTable freeString:placeholder]; ! 425: } ! 426: } ! 427: ! 428: classNames = (char *)[configTable valueForStringKey:CLASS_NAMES_KEY]; ! 429: if (classNames == NULL) { ! 430: classNames = (char *)[configTable ! 431: valueForStringKey:DRIVER_NAME_KEY]; ! 432: if (classNames == NULL) ! 433: goto abort; ! 434: } ! 435: classNameList = [[KernStringList alloc] ! 436: initWithWhitespaceDelimitedString:classNames]; ! 437: [configTable freeString:classNames]; ! 438: ! 439: busTypeString = [configTable valueForStringKey:BUS_TYPE_KEY]; ! 440: if (busTypeString == NULL || *busTypeString == '\0') ! 441: busType = DEFAULT_BUS; ! 442: else ! 443: busType = busTypeString; ! 444: ! 445: sprintf(nameBuf, KERN_BUS_FORMAT, busType); ! 446: busClass = objc_getClass((const char *)nameBuf); ! 447: if (busClass == nil) ! 448: busClass = defaultBusClass; ! 449: ! 450: classesLoaded = 0; ! 451: for (index = 0; index < [classNameList count]; index++) { ! 452: className = [classNameList stringAt:index]; ! 453: theClass = objc_getClass(className); ! 454: ! 455: if (theClass == nil) { ! 456: IOLog("configureDriver: " ! 457: "driver class '%s' was not loaded\n", className); ! 458: if( serverName) ! 459: IOLog("Driver %s could not be configured\n", serverName); ! 460: goto abort; ! 461: } ! 462: ! 463: #if DEBUG ! 464: if( ioDeviceDescription) ! 465: kprintf("Probing class %s on device %s\n", ! 466: className, [ioDeviceDescription nodeName]); ! 467: #endif ! 468: ! 469: if (versionChecked == NO) { ! 470: /* ! 471: * Right now, if serverName is NULL, that means the driver ! 472: * is compiled into the kernel, so don't check the version. ! 473: * This may change later, however. ! 474: */ ! 475: ! 476: if (serverName != NULL) { ! 477: if (versionIsOK(serverName) == NO) ! 478: goto abort; ! 479: } ! 480: versionChecked = YES; ! 481: } ! 482: ! 483: /* ! 484: * Check to see if bus wants to configure driver itself. ! 485: */ ! 486: if ([busClass configureDriverWithTable:configTable]) { ! 487: classesLoaded = 1; ! 488: /* Return success. */ ! 489: break; ! 490: } ! 491: ! 492: /* ! 493: * Depending on the deviceStyle, we either make ! 494: * an DeviceDescription or an PPCDeviceDescription. ! 495: */ ! 496: ! 497: switch ([theClass deviceStyle]) { ! 498: case IO_DirectDevice: ! 499: deviceDescription = [busClass ! 500: deviceDescriptionFromConfigTable:configTable]; ! 501: ! 502: if (deviceDescription == nil) { ! 503: IOLog("configureDriver: initFromConfigTable " ! 504: "failed for class %s\n", className); ! 505: goto abort; ! 506: } ! 507: ! 508: if ([deviceDescription bus] == nil) { ! 509: [deviceDescription setBus:defaultBus]; ! 510: } ! 511: ! 512: if ([[deviceDescription bus] allocateResourcesForDeviceDescription: ! 513: deviceDescription] == nil) { ! 514: IOLog("configureDriver: could not allocate " ! 515: "resources for class %s\n", className); ! 516: goto abort; ! 517: } ! 518: ! 519: device = [[KernDevice alloc] ! 520: initWithDeviceDescription:deviceDescription]; ! 521: ! 522: if (device == nil) { ! 523: IOLog("configureDriver: initFromDeviceDescription " ! 524: "failed for class %s\n", className); ! 525: goto abort; ! 526: } ! 527: ! 528: [deviceDescription setDevice:device]; ! 529: ! 530: if( nil == ioDeviceDescription) { ! 531: sprintf(nameBuf, "IO%sDeviceDescription", busType); ! 532: busDescriptionClass = objc_getClass((const char *)nameBuf); ! 533: newDescription = [[busDescriptionClass alloc] ! 534: _initWithDelegate:deviceDescription]; ! 535: if (newDescription == nil) ! 536: goto abort; ! 537: } else { ! 538: newDescription = ioDeviceDescription; ! 539: [newDescription setDelegate:deviceDescription]; ! 540: } ! 541: [newDescription setDevicePort:create_dev_port(device)]; ! 542: break; ! 543: ! 544: case IO_IndirectDevice: ! 545: case IO_PseudoDevice: ! 546: ! 547: deviceDescription = [[KernDeviceDescription alloc] ! 548: initFromConfigTable:configTable]; ! 549: if (deviceDescription == nil) { ! 550: goto abort; ! 551: } ! 552: ! 553: newDescription = [[IODeviceDescription alloc] ! 554: _initWithDelegate:deviceDescription]; ! 555: ! 556: if (newDescription == nil) ! 557: goto abort; ! 558: ! 559: break; ! 560: ! 561: default: ! 562: IOLog("Invalid style for class %s", className); ! 563: goto abort; ! 564: } ! 565: ! 566: /* ! 567: * Now that we have a valid device description for the device, ! 568: * probe the sucker. ! 569: */ ! 570: ! 571: if (![theClass respondsTo:@selector(probe:)]) { ! 572: IOLog("configureDriver: Class %s does not respond " ! 573: "to probe:\n", className); ! 574: continue; ! 575: } ! 576: ! 577: if( [IODevice addLoadedClass:theClass ! 578: description:newDescription] == IO_R_SUCCESS) { ! 579: classesLoaded++; ! 580: } ! 581: } ! 582: ! 583: /* ! 584: * Only free resources if there was a fatal error before ! 585: * addLoadedClass: was called, because the class may cache ! 586: * the device description and config table for later use. ! 587: */ ! 588: IOFree(nameBuf, NAME_BUF_LEN); ! 589: [classNameList free]; ! 590: if (serverName) ! 591: [configTable freeString:serverName]; ! 592: if (busTypeString) ! 593: [configTable freeString:busTypeString]; ! 594: if (classesLoaded) { ! 595: return YES; ! 596: } else { ! 597: [deviceDescription free]; ! 598: [device free]; ! 599: return NO; ! 600: } ! 601: ! 602: abort: ! 603: ! 604: if (serverName) ! 605: [configTable freeString:serverName]; ! 606: if (busTypeString) ! 607: [configTable freeString:busTypeString]; ! 608: ! 609: if (deviceDescription) { ! 610: [deviceDescription free]; ! 611: } ! 612: if (device) { ! 613: [device free]; ! 614: } ! 615: ! 616: return NO; ! 617: } ! 618: ! 619: ! 620: ! 621: ! 622: /* ! 623: * probe all indirect drivers associated with specified driver. ! 624: * As of mk-149.10, this is only used for IdeDisk. ! 625: */ ! 626: static void ! 627: probe_indirect(const char **indirectNamep, id driverInstance) ! 628: { ! 629: id driverClass; ! 630: ! 631: if(indirectNamep == NULL) { ! 632: return; ! 633: } ! 634: for(; *indirectNamep; indirectNamep++) { ! 635: driverClass = objc_getClass(*indirectNamep); ! 636: if(driverClass == nil) { ! 637: printf("probe_indirect: Class %s does not exist\n", ! 638: *indirectNamep); ! 639: continue; ! 640: } ! 641: if(![driverClass respondsTo:@selector(probe:)]) { ! 642: printf("probe_indirect: Class %s does not respond to" ! 643: " probe:\n", *indirectNamep); ! 644: continue; ! 645: } ! 646: ! 647: [driverClass probe:driverInstance]; ! 648: } ! 649: } ! 650: ! 651: IOReturn ! 652: PublishDevice( id ioDevice ) ! 653: { ! 654: struct PendingProbe { ! 655: struct PendingProbe * next; ! 656: struct PendingProbe * prev; ! 657: int priority; ! 658: id device; ! 659: }; ! 660: struct PendingProbeQueue { ! 661: struct PendingProbe * head; ! 662: struct PendingProbe * zero; ! 663: struct PendingProbe * tail; ! 664: }; ! 665: int priority; ! 666: struct PendingProbe * newProbe; ! 667: struct PendingProbe * elem; ! 668: static struct PendingProbeQueue probeQueue; ! 669: static int outstanding = 0; ! 670: static probing = 0; ! 671: ! 672: priority = MatchDriversForDevice( ioDevice); ! 673: if( priority < 0) ! 674: return( IO_R_SUCCESS); // no match, no probe now ! 675: ! 676: if( probing) { ! 677: newProbe = IOMalloc( sizeof( struct PendingProbe)); ! 678: if( newProbe == NULL) ! 679: return( IO_R_NO_MEMORY); ! 680: newProbe->device = ioDevice; ! 681: newProbe->priority = priority; ! 682: ! 683: // queue it behind those with same priority ! 684: for( elem = probeQueue.head; ! 685: ( elem->next && (elem->priority >= priority)); ! 686: elem = elem->next ) ! 687: {} ! 688: // queue before elem ! 689: newProbe->next = elem; ! 690: newProbe->prev = elem->prev; ! 691: elem->prev->next = newProbe; ! 692: elem->prev = newProbe; ! 693: outstanding++; ! 694: ! 695: } else { ! 696: ! 697: probing++; ! 698: probeQueue.head = (struct PendingProbe *) &probeQueue.zero; ! 699: probeQueue.tail = (struct PendingProbe *) &probeQueue.head; ! 700: ! 701: StartDriver( [ioDevice configTable], ioDevice ); ! 702: ! 703: while( outstanding) { ! 704: // dequeue highest - must be one ! 705: newProbe = probeQueue.head; ! 706: probeQueue.head = newProbe->next; ! 707: newProbe->next->prev = &probeQueue.head; ! 708: ! 709: outstanding--; ! 710: ioDevice = newProbe->device; ! 711: priority = newProbe->priority; ! 712: IOFree( newProbe, sizeof( struct PendingProbe)); ! 713: ! 714: // start it ! 715: #if DEBUG ! 716: kprintf("---- [%d] Driver probe on device %s\n", priority, [ioDevice nodeName] ); ! 717: #endif ! 718: StartDriver( [ioDevice configTable], ioDevice ); ! 719: } ! 720: probing--; ! 721: } ! 722: ! 723: return( IO_R_SUCCESS); ! 724: } ! 725: ! 726: BOOL ! 727: NewLoadDriver( const char * configData ) ! 728: { ! 729: BOOL ret = NO; ! 730: id ioDevice; ! 731: IOConfigTable * configTable; ! 732: char * tryMatch; ! 733: char * tryLoc; ! 734: char * location; ! 735: enum { kStringSize = 128 }; ! 736: id * failedList = nil; ! 737: int numFailed = 0; ! 738: int i; ! 739: ! 740: tryMatch = IOMalloc( kStringSize * 2); ! 741: if( ! tryMatch) ! 742: return( NO); ! 743: tryLoc = tryMatch + kStringSize; ! 744: ! 745: if( FindStringKey( configData, "\"Location\"", tryLoc) && tryLoc[0] ) ! 746: location = tryLoc; ! 747: else ! 748: location = NULL; ! 749: ! 750: if( FindStringKey( configData, "\"Matching\"", tryMatch)) { ! 751: ! 752: while( (ioDevice = [IOTreeDevice findMatchingDevice:tryMatch location:location]) ) { ! 753: // Start the driver on all matching devices ! 754: [ioDevice taken:YES]; ! 755: [[ioDevice propertyTable] addConfigData:configData]; ! 756: #if DEBUG ! 757: kprintf("---- Driver probe on device %s\n", [ioDevice nodeName] ); ! 758: #endif ! 759: ret = StartDriver( [ioDevice configTable], ioDevice ); ! 760: ! 761: if( NO == ret) { ! 762: numFailed++; ! 763: failedList = realloc( failedList, numFailed * sizeof( id)); ! 764: if( failedList) ! 765: failedList[ numFailed - 1 ] = ioDevice; ! 766: } ! 767: } ! 768: if( failedList) { ! 769: for( i = 0; i < numFailed; i++ ) ! 770: [failedList[ i ] taken:NO]; ! 771: free( failedList ); ! 772: } ! 773: ! 774: } else { ! 775: configTable = [IOConfigTable newForConfigData:configData]; ! 776: if( configTable) { ! 777: ret = StartDriver( configTable, nil ); ! 778: if( ret == NO) ! 779: [configTable free]; ! 780: } ! 781: } ! 782: ! 783: IOFree( tryMatch, kStringSize * 2); ! 784: return( ret); ! 785: } ! 786: ! 787: static int ! 788: MatchDriversForDevice( id ioDevice ) ! 789: { ! 790: int i, propLen; ! 791: void * prop; ! 792: int priority = DEFAULT_LOAD_PRI; ! 793: BOOL found; ! 794: const char * configData; ! 795: IOPropertyTable * propTable = [ioDevice propertyTable]; ! 796: char * tryMatch; ! 797: char * tryLoc; ! 798: char * location; ! 799: enum { kStringSize = 128 }; ! 800: ! 801: tryMatch = IOMalloc( kStringSize * 2); ! 802: if( ! tryMatch) ! 803: return( -1); ! 804: tryLoc = tryMatch + kStringSize; ! 805: ! 806: found = NO; // NDRVForDevice( ioDevice); ! 807: ! 808: // look in tree for priority ! 809: propLen = sizeof( priority); ! 810: prop = &priority; ! 811: if( [propTable getProperty:"AAPL,load-priority" ! 812: flags:0 value:&prop length:&propLen] ) { ! 813: // else defaults - different for ndrv's ! 814: if( found) ! 815: priority = DISPLAY_LOAD_PRI; ! 816: else ! 817: priority = DEFAULT_LOAD_PRI; ! 818: } ! 819: ! 820: // look for a native XXXKit driver... ! 821: for( i = 1; (NO == found) && (configData = findBootConfigString(i)); i++ ) { ! 822: ! 823: if( FindStringKey( configData, "\"Location\"", tryLoc) && tryLoc[0] ) ! 824: location = tryLoc; ! 825: else ! 826: location = NULL; ! 827: ! 828: if( FindStringKey( configData, "\"Matching\"", tryMatch)) { ! 829: if( (found = [ioDevice match:tryMatch location:location])) { ! 830: ! 831: [propTable addConfigData:configData]; ! 832: // look in driver table for priority - overrides tree ! 833: if( FindStringKey( configData, "\"Load Priority\"", tryMatch)) ! 834: priority = strtol( tryMatch, 0, 10); ! 835: } ! 836: } ! 837: } ! 838: if( found) ! 839: [ioDevice taken:YES]; ! 840: ! 841: IOFree( tryMatch, kStringSize * 2); ! 842: return( found ? priority : (-1)); ! 843: } ! 844: ! 845: ! 846: ! 847: /* ! 848: * Configure a driver based on some config information. This is really just ! 849: * a wrapper around configureDriver that runs in its own thread, and needs to ! 850: * be called in the IOTask context. ! 851: */ ! 852: void ! 853: configureThread(struct probeDriverArgs *args) ! 854: { ! 855: ! 856: args->rtn = NewLoadDriver(args->configData); ! 857: ! 858: /* ! 859: * Notify parent that we're finished, then terminate. ! 860: */ ! 861: [args->waitLock lock]; ! 862: [args->waitLock unlockWith:YES]; ! 863: IOExitThread(); ! 864: } ! 865: ! 866: /* ! 867: * Perform machine dependent hardware probe/config. ! 868: */ ! 869: void probeHardware(void) ! 870: { ! 871: /* nope */ ! 872: } ! 873: ! 874: /* ! 875: * Start up all non-native direct drivers. Called after probeHardware(). ! 876: */ ! 877: void probeDirectDevices(void) ! 878: { ! 879: /* nope */ ! 880: } ! 881: ! 882: /* ! 883: * Obtain n'th boot config table. ! 884: */ ! 885: const char *findBootConfigString(int n) ! 886: { ! 887: if( n < numConfigTables) ! 888: return( allConfigTables[ n ]); ! 889: else ! 890: return( NULL); ! 891: } ! 892: ! 893: static char * ! 894: FindStringKey( const char * config, const char * key, char * value ) ! 895: { ! 896: char * match; ! 897: char * prop; ! 898: char * end; ! 899: ! 900: do { ! 901: match = strstr( config, key ); ! 902: if( match == NULL) ! 903: continue; ! 904: prop = strchr( match + strlen( key ), '\"'); ! 905: if( prop == NULL) ! 906: continue; ! 907: prop++; ! 908: end = strchr( prop, '\"'); ! 909: if( end == NULL) ! 910: continue; ! 911: ! 912: strncpy( value, prop, end - prop); ! 913: value[ end - prop ] = 0; ! 914: return( value); ! 915: ! 916: } while( NO); ! 917: ! 918: return( NULL); ! 919: } ! 920: ! 921: ! 922: /* ! 923: * Make a list of config tables in the kernel and loaded by the booter. ! 924: * Register objective-C code loaded by the booter. ! 925: */ ! 926: ! 927: static void ! 928: bootDriverInit(void) ! 929: { ! 930: IOReturn err; ! 931: DTEntry rootEntry, dtEntry; ! 932: DTEntryIterator dtIter; ! 933: int i, size, allocedTables; ! 934: char * prop; ! 935: char * bundleName; ! 936: void ** module; ! 937: char * nextTable; ! 938: ! 939: if( (kSuccess != DTLookupEntry( 0, "/AAPL,loadables", &rootEntry)) ! 940: || (kSuccess != DTCreateEntryIterator ( rootEntry, &dtIter))) ! 941: ! 942: dtIter = NULL; ! 943: ! 944: for( i = 0; i < 2; i++) { ! 945: numConfigTables = 1; // System assumed ! 946: if( dtIter) while( kSuccess == DTIterateEntries( dtIter, &dtEntry)) { ! 947: ! 948: // look for reloc on second pass ! 949: if( allConfigTables ! 950: && (kSuccess == DTGetProperty( dtEntry, "_reloc", &module, &size )) ! 951: && (size == sizeof( void *)) ) { ! 952: ! 953: err = objc_registerModule( *module, 0); ! 954: #if DEBUG ! 955: kprintf("Registered objc @ %x\n", *module); ! 956: #endif ! 957: } ! 958: ! 959: if( kSuccess != DTGetProperty( dtEntry, "name", &bundleName, &size )) ! 960: continue; ! 961: if( (kSuccess != DTGetProperty( dtEntry, "Instance0.table", &prop, &size )) ! 962: && (kSuccess != DTGetProperty( dtEntry, "Default.table", &prop, &size )) ) ! 963: continue; ! 964: ! 965: if( 0 == strcmp( "System", bundleName)) { ! 966: if( allConfigTables) ! 967: allConfigTables[ 0 ] = prop; ! 968: ! 969: } else for( nextTable = prop; ! 970: (nextTable - prop) < size; ! 971: nextTable = nextTable + strlen( nextTable) + 1) { ! 972: if( allConfigTables && (numConfigTables < allocedTables)) ! 973: allConfigTables[ numConfigTables ] = (char *) nextTable; ! 974: numConfigTables++; ! 975: } ! 976: } ! 977: ! 978: // now the linked in kernel tables ! 979: for( nextTable = inKernelConfigTables; ! 980: *nextTable; ! 981: nextTable = nextTable + strlen( nextTable) + 1) { ! 982: if( allConfigTables && (numConfigTables < allocedTables)) ! 983: allConfigTables[ numConfigTables ] = (char *) nextTable; ! 984: numConfigTables++; ! 985: } ! 986: ! 987: // allocate for second pass ! 988: if( nil == allConfigTables) { ! 989: allocedTables = numConfigTables; ! 990: allConfigTables = IOMalloc( allocedTables * sizeof( char *)); ! 991: if( allConfigTables) ! 992: bzero( allConfigTables, allocedTables * sizeof( char *)); ! 993: if( dtIter) ! 994: DTRestartEntryIteration( dtIter); ! 995: } ! 996: } ! 997: if( dtIter) ! 998: DTDisposeEntryIterator( dtIter); ! 999: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.