|
|
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\";"
1.1.1.2 ! root 177: "\"Matching\" = \"bandit uni-north\";"
1.1 root 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.