Annotation of driverkit/Config/Config.c, 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: /*     Copyright (c) 1991 NeXT Computer, Inc.  All rights reserved. 
                     25:  *
                     26:  * Config.c - Config server.
                     27:  *
                     28:  * HISTORY
                     29:  * 11-Apr-91    Doug Mitchell at NeXT
                     30:  *      Created.
                     31:  */
                     32: 
                     33: #import <bsd/sys/types.h>
                     34: #import <bsd/libc.h>
                     35: #import <mach/mach_types.h>
                     36: #import <driverkit/userConfigServer.h>
                     37: #import <driverkit/generalFuncs.h>
                     38: #import "ConfigPrivate.h"
                     39: #import "ConfigUtils.h"
                     40: #import "ConfigScan.h"
                     41: #import <mach/kern_return.h>
                     42: #import <mach/mach.h>
                     43: #import <servers/netname.h>
                     44: #import <mach/message.h>
                     45: #import <mach/mach_error.h>
                     46: #import <mach/cthreads.h>
                     47: #import <kernserv/queue.h>
                     48: #import <mach/notify.h>
                     49: #import <syslog.h>
                     50: #ifdef DEBUG
                     51: #import "ConfigUfs.h"
                     52: #endif DEBUG
                     53: 
                     54: /*
                     55:  * prototypes for private functions.
                     56:  */
                     57: static void usage(char **argv);
                     58: static void server_loop();
                     59: boolean_t Config_server(msg_header_t *inp, msg_header_t *outp);
                     60: static void config_port_death(msg_header_t *inp);
                     61: 
                     62: /*
                     63:  * Static variables.
                     64:  */
                     65: static port_t config_port;             // we advertise this for all takers
                     66: static port_set_name_t config_port_set;        // the set on which we listen 
                     67: port_t device_master_port;             // used to communicate with kernel
                     68: port_t notify_port;                    // that's ours
                     69: static boolean_t config_in_progress;   // prevents hazardous operations
                     70:                                        //   during initial config
                     71: queue_head_t driver_list;              // list of driver_entry_t's
                     72: mutex_t driver_list_lock;              // protects driver_list during initial
                     73:                                        //   config
                     74: condition_t driver_list_cond;
                     75: boolean_t driver_list_locked;
                     76: 
                     77: extern port_t device_master_self();
                     78: 
                     79: /*
                     80:  * User-specified variables.
                     81:  */
                     82: int verbose = 0;
                     83: 
                     84: void main(int argc, char **argv)
                     85: {
                     86:        int arg;
                     87:        kern_return_t krtn;
                     88:        cthread_t server_thread;
                     89:        
                     90:        if(argc < 1)
                     91:                usage(argv);
                     92:        for(arg=1; arg<argc; arg++) {
                     93:                switch(argv[arg][0]) {
                     94:                    case 'v':
                     95:                        verbose++;
                     96:                        break;
                     97:                    default:
                     98:                        usage(argv);
                     99:                }
                    100:        }
                    101:        
                    102: #ifdef DDM_DEBUG
                    103:        IOInitDDM(200, "ConfigXpr");
                    104:        IOSetDDMMask(XPR_CONFIG_INDEX,
                    105:                XPR_CONFIG | XPR_SERVER | XPR_COMMON | XPR_ERR);
                    106: #endif DDM_DEBUG
                    107: 
                    108:        /*
                    109:         * Initialize global state.
                    110:         */
                    111:        queue_init(&driver_list);
                    112:        driver_list_lock = mutex_alloc();
                    113:        driver_list_cond = condition_alloc();
                    114:        config_in_progress = TRUE;
                    115:        
                    116:        /*
                    117:         * Set up various ports and start the server thread before initial 
                    118:         * autoconfig so device drivers have a place to send messages.
                    119:         *
                    120:         * config_port is how we advertise our exported services to all.
                    121:         */
                    122:        krtn = port_allocate(task_self(), &config_port);
                    123:        if(krtn) {
                    124:                mach_error("port_allocate", krtn);
                    125:                exit(1);
                    126:        }
                    127:        krtn = port_set_allocate(task_self(), &config_port_set);
                    128:        if(krtn) {
                    129:                mach_error("port_set_allocate", krtn);
                    130:                exit(1);
                    131:        }
                    132:        krtn = port_set_add(task_self(), config_port_set, config_port);
                    133:        if(krtn) {
                    134:                mach_error("port_set_add", krtn);
                    135:                exit(1);
                    136:        }
                    137:        
                    138:        /*
                    139:         * we get port death notification on notify_port.
                    140:         */
                    141:        krtn = port_allocate(task_self(), &notify_port);
                    142:        if(krtn) {
                    143:                mach_error("port_allocate", krtn);
                    144:                exit(1);
                    145:        }
                    146:        krtn = task_set_notify_port(task_self(), notify_port);
                    147:        if(krtn) {
                    148:                mach_error("task_set_notify_port", krtn);
                    149:                exit(1);
                    150:        }
                    151:        krtn = port_set_add(task_self(), config_port_set, notify_port);
                    152:        if(krtn) {
                    153:                mach_error("port_set_add", krtn);
                    154:                exit(1);
                    155:        }
                    156:        krtn = netname_check_in(name_server_port,
                    157:                CONFIG_SERVER_NAME,
                    158:                task_self(),
                    159:                config_port);
                    160:        if(krtn) {
                    161:                mach_error("netname_check_in", krtn);
                    162:                exit(1);
                    163:        }
                    164:        device_master_port = device_master_self();
                    165:        if(device_master_port == PORT_NULL) {
                    166:                syslog(LOG_ERR, "Config: Can't get device_master_port\n");
                    167:                exit(1);
                    168:        }
                    169: 
                    170:        server_thread = cthread_fork((cthread_fn_t)server_loop, (any_t)0);      
                    171:        
                    172:        /*
                    173:         * Do initial autoconfig.
                    174:         */
                    175:        config_scan(SCAN_ALL, IO_NULL_SLOT_ID, IO_NULL_DEVICE_TYPE);
                    176:        
                    177:        /*
                    178:         * We're done; let the server_thread take it from here.
                    179:         */
                    180:        config_in_progress = FALSE;
                    181:        cthread_exit(0);
                    182: }
                    183: 
                    184: static void usage(char **argv)
                    185: {
                    186:        printf("usage: %s [options]\n", argv[0]);
                    187:        printf("Options:\n");
                    188:        printf("\tv  verbose mode\n");
                    189:        exit(1);
                    190: }
                    191: 
                    192:        
                    193: /*
                    194:  * Main server loop. This thread starts running before autoconfiguration 
                    195:  * takes place to allow servicing of IORegisterDriver() calls during 
                    196:  * autoconfig. The config_in_progress flag prevents us from servicing any 
                    197:  * hazardous calls during this time - like IORescanDriver(). Such calls will
                    198:  * return a IO_CNF_BUSY status.
                    199:  */                                    
                    200: static void server_loop()
                    201: {
                    202:        msg_header_t *inp, *outp;
                    203:        kern_return_t krtn;
                    204:        boolean_t return_msg;
                    205:        
                    206:        inp = (msg_header_t *)malloc(MSG_SIZE_MAX);
                    207:        outp = (msg_header_t *)malloc(MSG_SIZE_MAX);
                    208:        while (1) {
                    209:                inp->msg_local_port = config_port_set;
                    210:                inp->msg_size = MSG_SIZE_MAX;
                    211:                krtn = msg_receive(inp, MSG_OPTION_NONE, 0);
                    212:                if(krtn) {
                    213:                        mach_error("msg_receive", krtn);
                    214:                        continue;
                    215:                }
                    216:                xpr_server("msg_id %d received\n", inp->msg_id, 2,3,4,5);
                    217:                return_msg = FALSE;
                    218:                if(inp->msg_local_port == config_port) {
                    219:                        Config_server(inp, outp);
                    220:                        return_msg = TRUE;
                    221:                }
                    222:                else if(inp->msg_local_port == notify_port) {
                    223:                        config_port_death(inp);
                    224:                }
                    225:                else {
                    226:                        printf("Config server_loop: Bogus msg_local_port\n");
                    227:                }
                    228:                
                    229:                if(return_msg) {
                    230:                        /*
                    231:                         * Return message to client. We don't deal with 
                    232:                         * backed up port queues for now.
                    233:                         */
                    234:                        krtn = msg_send(outp, SEND_TIMEOUT, 0);
                    235:                        if(krtn) {
                    236:                                mach_error("msg_receive", krtn);
                    237:                                continue;
                    238:                        }
                    239:                }
                    240:        }
                    241:        /* NOT REACHED */
                    242: }
                    243: 
                    244: /*
                    245:  * Handle port death notification. The only ports we're interested in are
                    246:  * driver_ports.
                    247:  */
                    248: static void config_port_death(msg_header_t *inp)
                    249: {
                    250:        notification_t  *msgp = (notification_t *)inp;
                    251:        driver_entry_t  *driver_entry;
                    252:        queue_head_t    dev_list;
                    253:        dev_entry_t     *dev_entry;
                    254:        IOReturn drtn;
                    255:        
                    256:        /*
                    257:         * FIXME: use NOTIFY_PORT_DESTOYED??
                    258:         */
                    259:        if(inp->msg_id != NOTIFY_PORT_DELETED) {
                    260:                xpr_server("config_port_death: weird msg_id (%d)\n",
                    261:                        inp->msg_id, 2,3,4,5);
                    262:                return;
                    263:        }
                    264:        xpr_server("config_port_death: port %d\n", msgp->notify_port, 2,3,4,5);
                    265:        get_driver_list_lock();
                    266:        driver_entry = get_driver_entry(
                    267:                SK_DRIVER_PORT,
                    268:                msgp->notify_port,
                    269:                DEV_NUM_NULL,
                    270:                FID_NULL,
                    271:                IO_NULL_DEVICE_TYPE,
                    272:                IO_NULL_SLOT_ID,
                    273:                NULL);
                    274:        release_driver_list_lock();
                    275:        if(driver_entry == NULL) {
                    276:                xpr_server("config_port_death: not sig port\n", 
                    277:                        1,2,3,4,5);
                    278:                return;
                    279:        }
                    280:        driver_entry->driver_port = PORT_NULL;
                    281:        
                    282:        /*
                    283:         * Shut down all devices associated with this driver.
                    284:         * First, move all of this driver's dev_entry's to our local
                    285:         * queue.
                    286:         */
                    287:        queue_init(&dev_list);
                    288:        while(!queue_empty(&driver_entry->dev_list)) {
                    289:                dev_entry = (dev_entry_t *)
                    290:                        queue_first(&driver_entry->dev_list);
                    291:                queue_remove(&driver_entry->dev_list,
                    292:                        dev_entry,
                    293:                        dev_entry_t *,
                    294:                        link);
                    295:                queue_enter(&dev_list,
                    296:                        dev_entry,
                    297:                        dev_entry_t *,
                    298:                        link);
                    299:        }
                    300:        
                    301:        /*
                    302:         * For each device, destroy the associated device port, then 
                    303:         * create a new one for the same physical device.
                    304:         */
                    305:        while(!queue_empty(&dev_list)) {
                    306:                dev_entry = (dev_entry_t *)queue_first(&dev_list);
                    307:                queue_remove(&dev_list,
                    308:                        dev_entry,
                    309:                        dev_entry_t *,
                    310:                        link);
                    311:                if(dev_entry->dev_port) {
                    312:                        drtn = _IODestroyDevicePort(device_master_port,
                    313:                                dev_entry->dev_port);
                    314:                        if(drtn) {
                    315:                                xpr_common("config_port_death: "
                    316:                                    "_IODestroyDevicePort() returned %s\n", 
                    317:                                    IOFindNameForValue(drtn, dev_returns),
                    318:                                    2,3,4,5);
                    319:                                /* but keep going... */
                    320:                        }
                    321:                }
                    322:                create_dev_entry(driver_entry,
                    323:                        dev_entry->dev_number,
                    324:                        dev_entry->dev_type,
                    325:                        dev_entry->slot_id);
                    326:                        
                    327:                /*
                    328:                 * Our dev_entry is a useless copy...
                    329:                 */
                    330:                free(dev_entry);
                    331:        }
                    332:        
                    333:        /*
                    334:         * Now restart the driver.
                    335:         */
                    336:        xpr_server("config_port_death: restarting driver %s\n", 
                    337:                IOCopyString(driver_entry->filename), 2,3,4,5);
                    338:        if(exec_driver(driver_entry) != IO_CNF_SUCCESS) {
                    339:                /*
                    340:                 * Couldn't exec this driver. Remove from driver_list.
                    341:                 */
                    342:                get_driver_list_lock();
                    343:                free_driver_entry(driver_entry);
                    344:                release_driver_list_lock();
                    345:        }
                    346: }
                    347: 
                    348: /*
                    349:  * These functions are called out from the mig-generated Config_server.
                    350:  */
                    351:  
                    352: /*
                    353:  * Each driver which we exec calls this exactly once. The purpose is to 
                    354:  * register a driver_port for the driver's driver_entry so we can detect the
                    355:  * death of the driver. 
                    356:  */
                    357: IOConfigReturn _IORegisterDriver(
                    358:        port_t dev_config_port,
                    359:        port_t driver_sig_port,
                    360:        port_t driver_port)
                    361: {
                    362:        driver_entry_t *driver_entry;
                    363:        IOConfigReturn rtn = IO_CNF_SUCCESS;
                    364:        
                    365:        xpr_server("driver_register driver_port %d\n", driver_port, 2,3,4,5);
                    366:        get_driver_list_lock();
                    367:        
                    368:        /*
                    369:         * Make sure that this is a new registration for a device we
                    370:         * know about.
                    371:         */
                    372:        driver_entry = get_driver_entry(
                    373:                SK_SIG_PORT,
                    374:                driver_sig_port,
                    375:                DEV_NUM_NULL,
                    376:                FID_NULL,
                    377:                IO_NULL_DEVICE_TYPE,
                    378:                IO_NULL_SLOT_ID,
                    379:                NULL);
                    380:        if(driver_entry == NULL) {
                    381:                xpr_server("device_register: BAD driver_sig_port\n",
                    382:                         1,2,3,4,5);
                    383:                rtn = IO_CNF_NOT_REGISTERED;
                    384:                goto done;
                    385:        }
                    386:        if(driver_entry->driver_port != PORT_NULL) {
                    387:                xpr_server("device_register: REDUNDANT REGISTRATION\n",
                    388:                        1,2,3,4,5);
                    389:                rtn = IO_CNF_REGISTERED;
                    390:                goto done;
                    391:        }
                    392:        driver_entry->driver_port = driver_port;
                    393: done:
                    394:        release_driver_list_lock();
                    395:        return rtn;
                    396: }
                    397: 
                    398: /*
                    399:  * Release all state associated with specified driver. Can only be called 
                    400:  * by drivers we exec. 
                    401:  */
                    402: IOConfigReturn _IODeleteDriver(
                    403:        port_t dev_config_port,
                    404:        port_t driver_sig_port)
                    405: {
                    406:        driver_entry_t *driver_entry;
                    407:        IOConfigReturn rtn = IO_CNF_SUCCESS;
                    408: 
                    409:        xpr_server("driver_delete\n", 1,2,3,4,5);
                    410:        
                    411:        get_driver_list_lock();
                    412:        driver_entry = get_driver_entry(
                    413:                SK_SIG_PORT,
                    414:                driver_sig_port,
                    415:                DEV_NUM_NULL,
                    416:                FID_NULL,
                    417:                IO_NULL_DEVICE_TYPE,
                    418:                IO_NULL_SLOT_ID,
                    419:                NULL);
                    420:        if(driver_entry == NULL) {
                    421:                xpr_server("driver_delete: BAD driver_sig_port\n",
                    422:                         1,2,3,4,5);
                    423:                rtn = IO_CNF_NOT_REGISTERED;
                    424:                goto done;
                    425:        }
                    426:        
                    427:        rtn = free_driver_entry(driver_entry);
                    428: done:
                    429:        release_driver_list_lock();
                    430:        return rtn;
                    431: }
                    432: 
                    433: #if    SUPPORT_DEVICE_DELETE
                    434: /*
                    435:  * Release state associated with one device. Can only be called 
                    436:  * by drivers we exec.
                    437:  *
                    438:  * FIXME:
                    439:  * problem - a driver deletes some ports via device_delete(), then crashes. 
                    440:  * On restart, should it have access to all of the dev_ports it initially 
                    441:  * had? Currently it won't because Config did device_destroy()'s on the 
                    442:  * dev_ports. Those dev_entry's will be missing from the driver_entry's
                    443:  * dev_list...
                    444:  *
                    445:  * Also, how to assign a deleted device to another driver if the deletor 
                    446:  * keeps running? A config_scan() will just add it to that driver's 
                    447:  * dev_list and since that driver's already running, it won't get exec'd. 
                    448:  *
                    449:  * SO...for now we don't support device_delete().
                    450:  */            
                    451: IOConfigReturn _IODeleteDevice(
                    452:        port_t dev_config_port,
                    453:        port_t driver_sig_port,
                    454:        dev_port_t dev_port)
                    455: {
                    456:        driver_entry_t *driver_entry;
                    457:        dev_entry_t *dev_entry;
                    458:        IOConfigReturn rtn = IO_CNF_SUCCESS;
                    459:        
                    460:        xpr_server("device_delete\n", 1,2,3,4,5);
                    461:        get_driver_list_lock();
                    462:        driver_entry = get_driver_entry(
                    463:                SK_DEV_PORT, 
                    464:                dev_port, 
                    465:                DEV_NUM_NULL,
                    466:                FID_NULL,
                    467:                IO_NULL_DEVICE_TYPE,
                    468:                IO_NULL_SLOT_ID,
                    469:                &dev_entry);
                    470:        if(driver_entry == NULL) {
                    471:                rtn = IO_CNF_NOT_REGISTERED;
                    472:                goto done;
                    473:        }
                    474:        if(dev_entry == NULL) {
                    475:                /*
                    476:                 * Huh? This should not happen...
                    477:                 */
                    478:                rtn = IO_CNF_NOT_REGISTERED;
                    479:                goto done;
                    480:        }
                    481:        if(driver_entry->driver_sig_port != driver_sig_port) {
                    482:                rtn = IO_CNF_NOT_REGISTERED;
                    483:                goto done;
                    484:        }
                    485:        rtn = free_dev_entry(dev_entry);
                    486: done:
                    487:        release_driver_list_lock();
                    488:        xpr_server("device_delete: returning %s\n", 
                    489:                reg_text(*rtn, config_returns), 2,3,4,5);
                    490:        return rtn;
                    491: }
                    492: 
                    493: #endif SUPPORT_DEVICE_DELETE
                    494: 
                    495: /*
                    496:  * Do a complete rescan of all potential devices. Exec drivers for the
                    497:  * devices which we don't currently have registered drivers. This can be
                    498:  * called by anyone who can get dev_config_port. We return Busy status if
                    499:  * initial config is still in progress.
                    500:  */
                    501: IOConfigReturn _IORescanDriver(
                    502:        port_t dev_config_port)
                    503: {
                    504:        IOConfigReturn rtn;
                    505:        
                    506:        xpr_server("driver_rescan\n", 1,2,3,4,5);
                    507:        if(config_in_progress) {
                    508:                return(IO_CNF_BUSY);
                    509:        }
                    510:        rtn = config_scan(SCAN_ALL, IO_NULL_SLOT_ID, IO_NULL_DEVICE_TYPE);
                    511:        return rtn;
                    512: }
                    513: 
                    514: /*
                    515:  * Attempt to start a driver for device specified by slot_id and dev_type.
                    516:  * This can be called by anyone who can get dev_config_port. We return 
                    517:  * Busy status if initial config is still in progress. 
                    518:  */
                    519: IOConfigReturn _IOConfigDevice(
                    520:        port_t dev_config_port,
                    521:        IOSlotId slot_id,
                    522:        IODeviceType dev_type)
                    523: {
                    524:        IOConfigReturn rtn;
                    525: 
                    526:        xpr_server("driver_config\n", 1,2,3,4,5);
                    527:        if(config_in_progress) {
                    528:                return(IO_CNF_BUSY);
                    529:        }
                    530:        rtn = config_scan(SCAN_ONE, slot_id, dev_type);
                    531:        return rtn;
                    532: }
                    533: 
                    534: #ifdef DEBUG
                    535: 
                    536: /*
                    537:  * For debugging new drivers. Delete state associated with specified slot_id 
                    538:  * and device_type. 
                    539:  */
                    540: IOConfigReturn _IODeleteDeviceByType(
                    541:        port_t configPort,
                    542:        IOSlotId slot_id,
                    543:        IODeviceType device_type)
                    544: {
                    545:        IOConfigReturn rtn;
                    546:        driver_entry_t *driver_entry;
                    547:        dev_entry_t *dev_entry;
                    548:        
                    549:        xpr_server("IODeleteDeviceByType: slot_id 0x%x device_type 0x%x\n",
                    550:                slot_id, device_type, 3,4,5);
                    551:                
                    552:        /*
                    553:         * Get driver_entry associated with this slotId and deviceType.
                    554:         */
                    555:        get_driver_list_lock();
                    556:        driver_entry = get_driver_entry(
                    557:                SK_DEV_INDEX,
                    558:                PORT_NULL,
                    559:                DEV_NUM_NULL,
                    560:                FID_NULL,
                    561:                device_type,
                    562:                slot_id,
                    563:                &dev_entry);
                    564:        if(driver_entry == NULL) {
                    565:                rtn = IO_CNF_NOT_FOUND;
                    566:                goto done;
                    567:        }
                    568:        
                    569:        rtn = free_driver_entry(driver_entry);
                    570: done:
                    571:        release_driver_list_lock();
                    572:        return rtn;
                    573: 
                    574: }
                    575: #endif DEBUG

unix.superglobalmegacorp.com

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