Annotation of driverkit/Config/Config.c.test, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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