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