|
|
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: * 486 Driverkit configuration. ! 29: * ! 30: * HISTORY ! 31: * ! 32: * 28 Jan 1993 Brian Pinkerton at NeXT ! 33: * Added support for new, MI autoconf logic, and new driverkit API. ! 34: * 10 Nov 1992 Brian Pinkerton at NeXT ! 35: * Added indirect probe logic. ! 36: * 20 Aug 1992 Joe Pasqua ! 37: * Init intrReq & intrAttached of kern_dev in configure_device_class(). ! 38: * 3 August 1992 ? at NeXT ! 39: * Created. ! 40: */ ! 41: ! 42: #import <mach/mach_types.h> ! 43: #import <kern/mach_header.h> ! 44: ! 45: #import <machkit/NXLock.h> ! 46: #import <driverkit/KernDeviceDescription.h> ! 47: #import <driverkit/KernStringList.h> ! 48: #import <driverkit/i386/IOEISADeviceDescription.h> ! 49: #import <driverkit/IODeviceDescriptionPrivate.h> ! 50: #import <driverkit/IODirectDevice.h> ! 51: #import <driverkit/IODeviceKernPrivate.h> ! 52: #import <driverkit/IODeviceParams.h> ! 53: #import <driverkit/Device_ddm.h> ! 54: #import <driverkit/configTableKern.h> ! 55: #import <driverkit/KernDevice.h> ! 56: #import <driverkit/IOConfigTable.h> ! 57: #import <driverkit/driverTypesPrivate.h> ! 58: #import <driverkit/autoconfCommon.h> ! 59: #import <driverkit/i386/EISAKernBus.h> ! 60: #import <driverkit/i386/PCMCIA.h> ! 61: #import <driverkit/i386/PCMCIAKernBus.h> ! 62: #import <driverkit/i386/PCIKernBus.h> ! 63: ! 64: #import <machdep/i386/kernBootStruct.h> ! 65: ! 66: boolean_t eisa_id(int slot, unsigned int *_id); ! 67: ! 68: static void probe_indirect(const char **indirectNamep, id driverInstance); ! 69: ! 70: static BOOL configureDriver(const char *configData); ! 71: const char *findBootConfigString(int n); ! 72: static void bootDriverInit(void); ! 73: ! 74: id defaultBus, defaultBusClass; ! 75: static BOOL printedPCMCIAMessage; ! 76: ! 77: /* ! 78: * Native indirect driver classes. ! 79: */ ! 80: char *indirectDevList[] = { ! 81: "SCSIDisk", ! 82: "SCSIGeneric", ! 83: "IODiskPartition", ! 84: NULL ! 85: }; ! 86: ! 87: /* ! 88: * Pseudo device list. ! 89: */ ! 90: char *pseudoDevList[] = { ! 91: "EventDriver", ! 92: "kmDevice", ! 93: NULL ! 94: }; ! 95: ! 96: #define SERVER_NAME_KEY "Server Name" ! 97: #define CLASS_NAMES_KEY "Class Names" ! 98: #define DRIVER_NAME_KEY "Driver Name" ! 99: #define BUS_TYPE_KEY "Bus Type" ! 100: #define BUS_CLASS_KEY "Bus Class" ! 101: #define FAMILY_KEY "Family" ! 102: #define BUS_FAMILY "Bus" ! 103: #define KERN_BUS_FORMAT "%sKernBus" ! 104: #define DEVICE_DESCR_FORMAT "IO%sDeviceDescription" ! 105: #define DEFAULT_BUS "EISA" ! 106: #define NAME_BUF_LEN 128 ! 107: ! 108: ! 109: BOOL is_ISA; ! 110: ! 111: static BOOL ! 112: versionIsOK(const char *serverName) ! 113: { ! 114: int version; ! 115: ! 116: /* ! 117: * Right now, if serverName is NULL, that means the driver ! 118: * is compiled into the kernel, so don't check the version. ! 119: * This may change later, however. ! 120: */ ! 121: ! 122: if (serverName != NULL) { ! 123: version = [IODevice ! 124: driverKitVersionForDriverNamed:(char *)serverName]; ! 125: if (version == -1) ! 126: version = 310; ! 127: /* ! 128: * TODO: revisit this policy decision if DriverKit ! 129: * compatibility changes in the future. ! 130: */ ! 131: if (version <= 310) { ! 132: IOLog("WARNING: driver %s uses incompatible DriverKit version %d\n", serverName, version); ! 133: IOLog("Driver %s could not be configured\n", ! 134: serverName); ! 135: return NO; ! 136: } ! 137: } ! 138: return YES; ! 139: } ! 140: ! 141: /* ! 142: * Eventually, this routine will only initialize the boot device(s) per ! 143: * input from the booter via KERNBOOTSTRUCT. ! 144: * For now, configure all native devices enumerated in the various ! 145: * tables in device_configuration.c. ! 146: */ ! 147: void ! 148: probeNativeDevices(void) ! 149: { ! 150: int slot; ! 151: unsigned int _id; ! 152: char **configData; ! 153: int i; ! 154: const char *config; ! 155: IOConfigTable *configTable = nil; ! 156: const char *family, *busName; ! 157: char *nameBuf; ! 158: id busClass; ! 159: ! 160: // ! 161: // Initialize drivers and modules loaded by booter. ! 162: ! 163: bootDriverInit(); ! 164: ! 165: nameBuf = (char *)IOMalloc(NAME_BUF_LEN); ! 166: ! 167: // ! 168: // Find all bus drivers. ! 169: // ! 170: for(i=1; ; i++) { ! 171: config = findBootConfigString(i); ! 172: if(config == NULL) { ! 173: break; ! 174: } ! 175: configTable = [IOConfigTable newForConfigData:config]; ! 176: family = [configTable valueForStringKey:FAMILY_KEY]; ! 177: if (family && strcmp(family, BUS_FAMILY) == 0) { ! 178: busName = [configTable valueForStringKey:BUS_CLASS_KEY]; ! 179: busClass = objc_getClass(busName); ! 180: (void)[busClass probeBus:configTable]; ! 181: } ! 182: if (family) ! 183: [configTable freeString:family]; ! 184: } ! 185: ! 186: defaultBusClass = [KernBus lookupBusClassWithName:DEFAULT_BUS]; // XXX ! 187: if (defaultBusClass == nil) { ! 188: sprintf(nameBuf, "Missing %s kernel bus class", DEFAULT_BUS); ! 189: panic(nameBuf); ! 190: } ! 191: defaultBus = [KernBus lookupBusInstanceWithName:DEFAULT_BUS busId:0]; ! 192: ! 193: /* ! 194: * For now this is the only ! 195: * concession to EISA bus. ! 196: */ ! 197: if (eisa_id(0, &_id)) { ! 198: printf("CPU:\tEISA id %08x\n", _id); ! 199: for (slot = 1; slot <= 0xf; slot++) { ! 200: if (eisa_id(slot, &_id)) ! 201: printf("slot %x:\tEISA id %08x\n", slot, _id); ! 202: } ! 203: led_msg("NeXT"); ! 204: is_ISA = NO; ! 205: } ! 206: else { ! 207: printf("ISA bus\n"); ! 208: is_ISA = YES; ! 209: } ! 210: ! 211: ! 212: printf("DriverKit version %d\n",[IODevice driverKitVersion]); ! 213: ! 214: /* ! 215: * Configure all devices for which the booter has given us config info. ! 216: * The zeroth config string is the system config table. ! 217: */ ! 218: for(i=1; ; i++) { ! 219: config = findBootConfigString(i); ! 220: if(config == NULL) { ! 221: break; ! 222: } ! 223: configureDriver(config); ! 224: } ! 225: IOFree(nameBuf, NAME_BUF_LEN); ! 226: } ! 227: ! 228: ! 229: @protocol OldProbeMethods ! 230: + probe; ! 231: + probe:(int)a deviceMaster:(port_t) b; ! 232: @end ! 233: ! 234: /* ! 235: * Called from MD probeNativeDevices() and from configureThread(), the ! 236: * IOTask version of IOProbeDriver(). ! 237: * ! 238: * Given a class name and an ASCII representation of a config file, ! 239: * create a kern_dev and an IODeviceDescription and probe the class. ! 240: * This is used both at boot time - for the boot device and (temporarily) ! 241: * any native drivers with static config tables - and by IOProbeDriver(). ! 242: * ! 243: * Returns YES if driver was started successfully, else returns NO. ! 244: */ ! 245: static BOOL ! 246: configureDriver( ! 247: const char *configData ! 248: ) ! 249: { ! 250: const char *className, *classNames; ! 251: KernStringList *classNameList = nil; ! 252: const char *serverName = NULL; ! 253: IOConfigTable *configTable = nil; ! 254: Class theClass; ! 255: id deviceDescription = nil; ! 256: id device = nil; ! 257: id ioDeviceDescription = nil; ! 258: IOReturn drtn; ! 259: int index, classesLoaded, version; ! 260: BOOL versionChecked = NO; ! 261: const char *busType, *busTypeString; ! 262: char *nameBuf; ! 263: id busClass, busDescriptionClass; ! 264: ! 265: nameBuf = (char *)IOMalloc(NAME_BUF_LEN); ! 266: ! 267: configTable = [IOConfigTable newForConfigData:configData]; ! 268: ! 269: serverName = [configTable valueForStringKey:SERVER_NAME_KEY]; ! 270: ! 271: classNames = (char *)[configTable valueForStringKey:CLASS_NAMES_KEY]; ! 272: if (classNames == NULL) ! 273: classNames = (char *)[configTable ! 274: valueForStringKey:DRIVER_NAME_KEY]; ! 275: classNameList = [[KernStringList alloc] ! 276: initWithWhitespaceDelimitedString:classNames]; ! 277: IOFree(classNames, strlen(classNames) + 1); ! 278: busTypeString = [configTable valueForStringKey:BUS_TYPE_KEY]; ! 279: if (busTypeString == NULL || *busTypeString == '\0') ! 280: busType = DEFAULT_BUS; ! 281: else ! 282: busType = busTypeString; ! 283: ! 284: sprintf(nameBuf, KERN_BUS_FORMAT, busType); ! 285: busClass = objc_getClass((const char *)nameBuf); ! 286: if (busClass == nil) { ! 287: busClass = defaultBusClass; ! 288: busType = DEFAULT_BUS; ! 289: } ! 290: ! 291: classesLoaded = 0; ! 292: for (index = 0; index < [classNameList count]; index++) { ! 293: className = [classNameList stringAt:index]; ! 294: theClass = objc_getClass(className); ! 295: ! 296: if (theClass == nil) { ! 297: IOLog("configureDriver: " ! 298: "driver class '%s' was not loaded\n", className); ! 299: IOLog("Driver %s could not be configured\n", serverName); ! 300: goto abort; ! 301: } ! 302: ! 303: if (versionChecked == NO) { ! 304: /* ! 305: * Right now, if serverName is NULL, that means the driver ! 306: * is compiled into the kernel, so don't check the version. ! 307: * This may change later, however. ! 308: */ ! 309: ! 310: if (serverName != NULL) { ! 311: if (versionIsOK(serverName) == NO) ! 312: goto abort; ! 313: } ! 314: versionChecked = YES; ! 315: } ! 316: ! 317: /* ! 318: * Check to see if bus wants to configure driver itself. ! 319: */ ! 320: if ([busClass configureDriverWithTable:configTable]) { ! 321: classesLoaded = 1; ! 322: /* Return success. */ ! 323: break; ! 324: } ! 325: ! 326: /* ! 327: * Depending on the deviceStyle, we either make ! 328: * an DeviceDescription or the bus type device description. ! 329: */ ! 330: switch ([theClass deviceStyle]) { ! 331: case IO_DirectDevice: ! 332: deviceDescription = [busClass ! 333: deviceDescriptionFromConfigTable:configTable]; ! 334: ! 335: if (deviceDescription == nil) { ! 336: IOLog("configureDriver: initFromConfigTable " ! 337: "failed for class %s\n", className); ! 338: goto abort; ! 339: } ! 340: ! 341: if ([deviceDescription bus] == nil) { ! 342: [deviceDescription setBus:defaultBus]; ! 343: } ! 344: ! 345: if ([[deviceDescription bus] allocateResourcesForDeviceDescription: ! 346: deviceDescription] == nil) { ! 347: IOLog("configureDriver: could not allocate " ! 348: "resources for class %s\n", className); ! 349: goto abort; ! 350: } ! 351: ! 352: device = [[KernDevice alloc] ! 353: initWithDeviceDescription:deviceDescription]; ! 354: ! 355: if (device == nil) { ! 356: IOLog("configureDriver: initFromDeviceDescription " ! 357: "failed for class %s\n", className); ! 358: goto abort; ! 359: } ! 360: ! 361: [deviceDescription setDevice:device]; ! 362: ! 363: sprintf(nameBuf, "IO%sDeviceDescription", busType); ! 364: busDescriptionClass = objc_getClass((const char *)nameBuf); ! 365: ! 366: ioDeviceDescription = [[busDescriptionClass alloc] ! 367: _initWithDelegate:deviceDescription]; ! 368: ! 369: if (ioDeviceDescription == nil) { ! 370: goto abort; ! 371: } ! 372: ! 373: [ioDeviceDescription ! 374: setDevicePort:create_dev_port(device)]; ! 375: break; ! 376: ! 377: case IO_IndirectDevice: ! 378: case IO_PseudoDevice: ! 379: deviceDescription = [[KernDeviceDescription alloc] ! 380: initFromConfigTable:configTable]; ! 381: if (deviceDescription == nil) { ! 382: goto abort; ! 383: } ! 384: ! 385: ioDeviceDescription = [[IODeviceDescription alloc] ! 386: _initWithDelegate:deviceDescription]; ! 387: ! 388: if (ioDeviceDescription == nil) ! 389: goto abort; ! 390: ! 391: break; ! 392: ! 393: default: ! 394: IOLog("Invalid style for class %s", className); ! 395: goto abort; ! 396: } ! 397: ! 398: /* ! 399: * Now that we have a valid device description for the device, ! 400: * probe the sucker. ! 401: */ ! 402: if (![theClass respondsTo:@selector(probe:)]) { ! 403: IOLog("configureDriver: Class %s does not respond " ! 404: "to probe:\n", className); ! 405: continue; ! 406: } ! 407: ! 408: if ( ! 409: [IODevice addLoadedClass:theClass ! 410: description:ioDeviceDescription] == IO_R_SUCCESS) { ! 411: classesLoaded++; ! 412: } ! 413: } ! 414: ! 415: /* ! 416: * Only free resources if there was a fatal error before ! 417: * addLoadedClass: was called, because the class may cache ! 418: * the device description and config table for later use. ! 419: */ ! 420: IOFree(nameBuf, NAME_BUF_LEN); ! 421: [classNameList free]; ! 422: if (serverName) ! 423: [configTable freeString:serverName]; ! 424: if (busTypeString) ! 425: [configTable freeString:busTypeString]; ! 426: if (classesLoaded) ! 427: return YES; ! 428: else { ! 429: [configTable free]; ! 430: [ioDeviceDescription free]; ! 431: [deviceDescription free]; ! 432: [device free]; ! 433: return NO; ! 434: } ! 435: ! 436: abort: ! 437: if (serverName) ! 438: [configTable freeString:serverName]; ! 439: if (busTypeString) ! 440: [configTable freeString:busTypeString]; ! 441: if (configTable) ! 442: [configTable free]; ! 443: ! 444: if (ioDeviceDescription) { ! 445: [ioDeviceDescription free]; ! 446: } ! 447: if (deviceDescription) { ! 448: [deviceDescription free]; ! 449: } ! 450: if (device) { ! 451: [device free]; ! 452: } ! 453: ! 454: return NO; ! 455: } ! 456: ! 457: ! 458: static boolean_t isEISA=FALSE; ! 459: ! 460: boolean_t ! 461: eisa_present( ! 462: void ! 463: ) ! 464: { ! 465: static boolean_t checked; ! 466: ! 467: if (!checked) { ! 468: if (strncmp((char *)0xfffd9, "EISA", 4) == 0) ! 469: isEISA = TRUE; ! 470: ! 471: checked = TRUE; ! 472: } ! 473: ! 474: return (isEISA); ! 475: } ! 476: ! 477: boolean_t ! 478: eisa_id( ! 479: int slot, ! 480: unsigned int *_id ! 481: ) ! 482: { ! 483: unsigned char *ids = (unsigned char *)_id; ! 484: IOEISAPortAddress port; ! 485: ! 486: if (!eisa_present()) ! 487: return (FALSE); ! 488: ! 489: port = (slot << 12) | 0x0C80; ! 490: ! 491: ids[3] = inb(port); ! 492: ids[2] = inb(++port); ! 493: ids[1] = inb(++port); ! 494: ids[0] = inb(++port); ! 495: ! 496: if (*_id == 0xffffffff) ! 497: return (FALSE); ! 498: ! 499: return (TRUE); ! 500: } ! 501: ! 502: ! 503: /* ! 504: * probe all indirect drivers associated with specified driver. ! 505: * As of mk-149.10, this is only used for IdeDisk. ! 506: */ ! 507: static void ! 508: probe_indirect(const char **indirectNamep, id driverInstance) ! 509: { ! 510: id driverClass; ! 511: ! 512: if(indirectNamep == NULL) { ! 513: return; ! 514: } ! 515: for(; *indirectNamep; indirectNamep++) { ! 516: driverClass = objc_getClass(*indirectNamep); ! 517: if(driverClass == nil) { ! 518: printf("probe_indirect: Class %s does not exist\n", ! 519: *indirectNamep); ! 520: continue; ! 521: } ! 522: if(![driverClass respondsTo:@selector(probe:)]) { ! 523: printf("probe_indirect: Class %s does not respond to" ! 524: " probe:\n", *indirectNamep); ! 525: continue; ! 526: } ! 527: ! 528: [driverClass probe:driverInstance]; ! 529: } ! 530: } ! 531: ! 532: /* ! 533: * Configure a driver based on some config information. This is really just ! 534: * a wrapper around configureDriver that runs in its own thread, and needs to ! 535: * be called in the IOTask context. ! 536: */ ! 537: void ! 538: configureThread(struct probeDriverArgs *args) ! 539: { ! 540: args->rtn = configureDriver(args->configData); ! 541: ! 542: /* ! 543: * Notify parent that we're finished, then terminate. ! 544: */ ! 545: [args->waitLock lock]; ! 546: [args->waitLock unlockWith:YES]; ! 547: IOExitThread(); ! 548: } ! 549: ! 550: /* ! 551: * Perform machine dependent hardware probe/config. ! 552: */ ! 553: void probeHardware(void) ! 554: { ! 555: } ! 556: ! 557: /* ! 558: * Start up all non-native direct drivers. Called after probeHardware(). ! 559: */ ! 560: void probeDirectDevices(void) ! 561: { ! 562: /* nope */ ! 563: } ! 564: ! 565: /* ! 566: * Obtain n'th string in KERNBOOSTRUCT.config[]. Returns pointer to desired ! 567: * string if found, else returns NULL. ! 568: * KERNBOOTSTRUCT.config is a set of contiguous strings, NULL separated. ! 569: * The end of the list is delineated by a double NULL. ! 570: */ ! 571: const char *findBootConfigString(int n) ! 572: { ! 573: KERNBOOTSTRUCT *kernBootStruct = KERNSTRUCT_ADDR; ! 574: int stringsFound; ! 575: const char *cp = kernBootStruct->config; ! 576: int currentIndex = 0; ! 577: int length; ! 578: ! 579: if(*cp == '\0') { ! 580: IOLog("WARNING: No config table in KERNBOOTSTRUCT!\n"); ! 581: return NULL; ! 582: } ! 583: for(stringsFound=0; stringsFound<n; stringsFound++) { ! 584: length = strlen(cp); ! 585: currentIndex += (length + 1); ! 586: cp += (length + 1); ! 587: if( (length == 0) || ! 588: (currentIndex > CONFIG_SIZE) || ! 589: (*cp == '\0')) { ! 590: /* ! 591: * Explicit end of list or beyond boundary. ! 592: */ ! 593: return NULL; ! 594: } ! 595: } ! 596: return cp; ! 597: } ! 598: ! 599: ! 600: static void ! 601: bootDriverInit(void) ! 602: { ! 603: KERNBOOTSTRUCT *bootstruct = KERNSTRUCT_ADDR; ! 604: int i; ! 605: struct section *sp; ! 606: struct mach_header *hdr; ! 607: ! 608: for (i = 0; i < bootstruct->numBootDrivers; i++) { ! 609: hdr = (struct mach_header *)bootstruct->driverConfig[i].address; ! 610: /* Zero out bss */ ! 611: sp = getsectbynamefromheader(hdr,"__DATA","__bss"); ! 612: if (sp) ! 613: bzero(sp->addr, sp->size); ! 614: (void)objc_registerModule(hdr, 0); ! 615: } ! 616: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.