Annotation of kernel/driverkit/ppc/autoconf_ppc.m, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.