Annotation of kernel/bsd/dev/vol.c, revision 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: /*     @(#)vol.c       2.0     03/19/90        (c) 1990 NeXT   */
        !            26: 
        !            27: /* 
        !            28:  * vol.c - volume insertion device
        !            29:  *
        !            30:  * HISTORY
        !            31:  * 03-19-90    Doug Mitchell at NeXT
        !            32:  *     Created.
        !            33:  */ 
        !            34: 
        !            35: #import <sys/types.h>
        !            36: #import <sys/errno.h>
        !            37: #import <sys/ioctl.h>
        !            38: #import <sys/systm.h>
        !            39: #import <sys/disktab.h>
        !            40: #import <kern/kern_port.h>
        !            41: #import <kern/thread.h> 
        !            42: #import <kern/lock.h>
        !            43: #import <kernserv/insertmsg.h>
        !            44: #import <bsd/dev/disk.h>
        !            45: #import <kernserv/prototypes.h>
        !            46: #import <bsd/dev/voldev.h>
        !            47: #import <kern/queue.h>
        !            48: #import <kernserv/kern_notify.h>
        !            49: #import <mach/notify.h>
        !            50: #if    hppa
        !            51: # import <bsd/dev/hppa/sdvol.h>
        !            52: #endif hppa
        !            53: #import "driverkit.h"
        !            54: 
        !            55: /* #define VOL_DEBUG   1       /* */
        !            56: 
        !            57: #ifdef VOL_DEBUG
        !            58: #define vol_debug(x)   printf x
        !            59: #else  VOL_DEBUG
        !            60: #define vol_debug(x)
        !            61: #endif VOL_DEBUG
        !            62: 
        !            63: /*
        !            64:  * Struct used for queueing notifications prior to first DKIOCMNOTIFY
        !            65:  */
        !            66: struct vol_notify_entry {
        !            67:        queue_chain_t           link;
        !            68:        int                     dev_desc;       /* IND_DD_DEV, IND_DD_PORT */
        !            69:        dev_t                   block_dev;      /* for IND_DD_DEV */
        !            70:        dev_t                   raw_dev;        /* ditto */
        !            71:        kern_port_t             dev_port;       /* for IND_DD_PORT */
        !            72:        int                     vol_state;      /* IND_VS_LABEL, etc. */
        !            73:        char                    form_type[FORM_TYPE_LENGTH];
        !            74:        char                    dev_str[OID_DEVSTR_LEN];
        !            75:        int                     flags;
        !            76: };
        !            77: 
        !            78: typedef struct vol_notify_entry *vne_t;
        !            79: 
        !            80: /*
        !            81:  * Struct for maintaining state of panel requests
        !            82:  */
        !            83: 
        !            84: struct vol_panel_entry {
        !            85:        queue_chain_t           link;
        !            86:        int                     tag;
        !            87:        vpt_func                fnc;            /* to be called upon receipt of
        !            88:                                                 * vol_panel_resp message */    
        !            89:        void                    *param;
        !            90: };
        !            91: 
        !            92: typedef struct vol_panel_entry *vpe_t;
        !            93: 
        !            94: 
        !            95: /*
        !            96:  * Local functions.
        !            97:  */
        !            98: static kern_return_t vol_notify_com(int in_dev_desc,   
        !            99:        dev_t block_dev, 
        !           100:        dev_t raw_dev,
        !           101:        kern_port_t dev_port, 
        !           102:        int vol_state,
        !           103:        const char *form_type,
        !           104:        const char *dev_str,
        !           105:        int flags);
        !           106: static void vol_thread();
        !           107: static vpe_t vol_panel_get_entry(int tag);
        !           108: static void vol_port_death(notification_t *nmsg);
        !           109: 
        !           110: /*
        !           111:  * Prototypes for kernel functions.
        !           112:  */
        !           113: msg_return_t msg_send_from_kernel(msg_header_t *msgptr, msg_option_t option, 
        !           114:        msg_timeout_t tout);
        !           115: 
        !           116: int volopen(dev_t dev);
        !           117: int volclose(dev_t dev);
        !           118: int volioctl(dev_t dev, 
        !           119:        int cmd, 
        !           120:        caddr_t data, 
        !           121:        int flag);
        !           122: 
        !           123: /*
        !           124:  * Globals.
        !           125:  */
        !           126: static char vol_dev_open;
        !           127: static char vol_dev_init_flag;
        !           128: static kern_port_t vol_check_port=PORT_NULL;   
        !           129:                                        /* port to which disk insertion 
        !           130:                                         * messages are sent; usually allocated 
        !           131:                                         * by autodiskmount. */
        !           132: kern_port_t panel_req_port=PORT_NULL;
        !           133:                                        /* port to which Panel Requests are
        !           134:                                         * sent. */
        !           135: static kern_port_t vol_local_port=PORT_NULL;   
        !           136:                                        /* port on which vol_thread listens. */
        !           137: static port_t  vol_receive_port = PORT_NULL;
        !           138: static queue_head_t vol_notify_q = {&vol_notify_q, &vol_notify_q};
        !           139:                                        /* hold notifications prior to
        !           140:                                         * first DKIOCMNOTIFY */
        !           141: static lock_data_t vol_notify_lock;    /* protects vol_notify_q */
        !           142: static queue_head_t vol_panel_q = {&vol_panel_q, &vol_panel_q};
        !           143: static int vol_panel_tag;
        !           144: static vol_thread_alive=0;
        !           145: #if    DRIVERKIT
        !           146: static int manual_poll;
        !           147: #endif DRIVERKIT
        !           148: 
        !           149: /*
        !           150:  * message templates.
        !           151:  */
        !           152: static struct insert_notify insert_notify_temp = { 
        !           153:        {                                       /* in_header */
        !           154:                0,                              /* msg_unused */
        !           155:                FALSE,                          /* msg_simple */
        !           156:                0,                              /* msg_size */
        !           157:                MSG_TYPE_NORMAL,                /* msg_type */
        !           158:                PORT_NULL,                      /* msg_local_port */
        !           159:                PORT_NULL,                      /* msg_remote_port */
        !           160:                VOL_CHECK_MSG_ID                /* msg_id */
        !           161:        },
        !           162:        {                                       /* in_vd_type */
        !           163:                MSG_TYPE_INTEGER_32,            /* msg_type_name */
        !           164:                32,                             /* msg_type_size */
        !           165:                2,                              /* msg_type_number */
        !           166:                TRUE,                           /* msg_type_inline */
        !           167:                FALSE,                          /* msg_type_longform */
        !           168:                FALSE,                          /* msg_type_deallocate */
        !           169:        },
        !           170:        0,                                      /* in_vol_state */
        !           171:        0,                                      /* in_dev_desc */
        !           172:        {                                       /* in_flags_type */
        !           173:                MSG_TYPE_INTEGER_32,            /* msg_type_name */
        !           174:                32,                             /* msg_type_size */
        !           175:                1,                              /* msg_type_number */
        !           176:                TRUE,                           /* msg_type_inline */
        !           177:                FALSE,                          /* msg_type_longform */
        !           178:                FALSE,                          /* msg_type_deallocate */
        !           179:        },
        !           180:        0,                                      /* in_flags */
        !           181:        {                                       /* in_form_type */
        !           182:                MSG_TYPE_CHAR,                  /* msg_type_name */
        !           183:                8,                              /* msg_type_size */
        !           184:                FORM_TYPE_LENGTH,               /* msg_type_number */
        !           185:                TRUE,                           /* msg_type_inline */
        !           186:                FALSE,                          /* msg_type_longform */
        !           187:                FALSE,                          /* msg_type_deallocate */
        !           188:        },
        !           189:        NULL                                    /* in_form_type */
        !           190: };
        !           191: 
        !           192: static struct vol_panel_req vol_panel_req_temp = {
        !           193:        {                                       /* pr_header */
        !           194:                0,                              /* msg_unused */
        !           195:                TRUE,                           /* msg_simple */
        !           196:                sizeof(struct vol_panel_req),   /* msg_size */
        !           197:                MSG_TYPE_NORMAL,                /* msg_type */
        !           198:                PORT_NULL,                      /* msg_local_port */
        !           199:                PORT_NULL,                      /* msg_remote_port */
        !           200:                VOL_PANEL_REQ                   /* msg_id */
        !           201:        },
        !           202:        {                                       /* pr_int_desc */
        !           203:                MSG_TYPE_INTEGER_32,            /* msg_type_name */
        !           204:                32,                             /* msg_type_size */
        !           205:                7,                              /* msg_type_number */
        !           206:                TRUE,                           /* msg_type_inline */
        !           207:                FALSE,                          /* msg_type_longform */
        !           208:                FALSE,                          /* msg_type_deallocate */
        !           209:        },
        !           210:        0,                                      /* pr_panel_type */
        !           211:        0,                                      /* pr_resp_type */
        !           212:        0,                                      /* pr_tag */
        !           213:        0,                                      /* p1 */
        !           214:        0,                                      /* p2 */
        !           215:        0,                                      /* p3 */
        !           216:        0,                                      /* p4 */
        !           217:        {                                       /* pr_string_desc */
        !           218:                MSG_TYPE_CHAR,                  /* msg_type_name */
        !           219:                8,                              /* msg_type_size */
        !           220:                2 * VP_STRING_LEN,              /* msg_type_number */
        !           221:                TRUE,                           /* msg_type_inline */
        !           222:                FALSE,                          /* msg_type_longform */
        !           223:                FALSE                           /* msg_type_deallocate */
        !           224:        },
        !           225:        NULL,                                   /* string1 */
        !           226:        NULL                                    /* string2 */
        !           227: };
        !           228: 
        !           229: static struct vol_panel_cancel vol_panel_cancel_temp = {
        !           230:        {                                       /* pc_header */
        !           231:                0,                              /* msg_unused */
        !           232:                TRUE,                           /* msg_simple */
        !           233:                sizeof(struct vol_panel_cancel),/* msg_size */
        !           234:                MSG_TYPE_NORMAL,                /* msg_type */
        !           235:                PORT_NULL,                      /* msg_local_port */
        !           236:                PORT_NULL,                      /* msg_remote_port */
        !           237:                VOL_PANEL_CANCEL                /* msg_id */
        !           238:        },
        !           239:        {                                       /* pc_int_desc */
        !           240:                MSG_TYPE_INTEGER_32,            /* msg_type_name */
        !           241:                32,                             /* msg_type_size */
        !           242:                1,                              /* msg_type_number */
        !           243:                TRUE,                           /* msg_type_inline */
        !           244:                FALSE,                          /* msg_type_longform */
        !           245:                FALSE                           /* msg_type_deallocate */
        !           246:        },
        !           247:        0                                       /* pc_tag */
        !           248: };
        !           249: 
        !           250: int volopen(dev_t dev)
        !           251: {
        !           252:        if(vol_dev_open)
        !           253:                return(EBUSY);
        !           254:        else {
        !           255:                vol_dev_open = 1;
        !           256:                return(0);
        !           257:        }
        !           258: }
        !           259: 
        !           260: int volclose(dev_t dev)
        !           261: {
        !           262:        vol_dev_open = 0;
        !           263:        return(0);
        !           264: }
        !           265: 
        !           266: int volioctl(dev_t dev, 
        !           267:        int cmd, 
        !           268:        caddr_t data, 
        !           269:        int flag)
        !           270: {
        !           271:        int rtn=0;
        !           272:        port_t remote_port;
        !           273:        dev_t mydev;
        !           274:        
        !           275:        switch (cmd) {
        !           276:            case DKIOCMNOTIFY:
        !           277:                /*
        !           278:                 * Send disk insert notification to port specified in *data.
        !           279:                 */
        !           280:                vol_debug(("volioctl: registering NOTIFY port\n"));
        !           281:                remote_port = *(port_t *)data;
        !           282:                if(get_kern_port(current_task(), remote_port, &vol_check_port)) 
        !           283:                        rtn = EINVAL;
        !           284:                else {
        !           285:                        /* 
        !           286:                         * Send notification for each entry in vol_notify_q.
        !           287:                         */
        !           288:                        vne_t vnep, vne_next_p;
        !           289:                        
        !           290:                        lock_write(&vol_notify_lock);
        !           291:                        vnep = (vne_t)queue_first(&vol_notify_q);
        !           292:                        while(!queue_end(&vol_notify_q, (queue_entry_t)vnep)) {
        !           293:                                vne_next_p = (vne_t)vnep->link.next;
        !           294:                                queue_remove(&vol_notify_q,
        !           295:                                        vnep,
        !           296:                                        vne_t,
        !           297:                                        link); 
        !           298:                                if(vnep->block_dev != rootdev) {
        !           299:                                        /*
        !           300:                                         * skip notification for root device 
        !           301:                                         */
        !           302:                                        vol_notify_com(vnep->dev_desc,  
        !           303:                                                vnep->block_dev, 
        !           304:                                                vnep->raw_dev,
        !           305:                                                vnep->dev_port, 
        !           306:                                                vnep->vol_state,
        !           307:                                                vnep->form_type,
        !           308:                                                vnep->dev_str,
        !           309:                                                vnep->flags);
        !           310:                                }
        !           311:                                kfree(vnep, sizeof(struct vol_notify_entry));
        !           312:                                vnep = vne_next_p;
        !           313:                        }
        !           314:                        lock_done(&vol_notify_lock);
        !           315:                }
        !           316:                /*
        !           317:                 * Register this port so we'll know when it dies.
        !           318:                 */
        !           319:                if(rtn == 0) 
        !           320:                        port_request_notification(vol_check_port, 
        !           321:                                vol_local_port);
        !           322:                break;
        !           323: 
        !           324:            case DKIOCPANELPRT:
        !           325:                /*
        !           326:                 * register port to which we send Panel request messages.
        !           327:                 */
        !           328:                vol_debug(("volioctl: registering PANEL port\n"));
        !           329:                remote_port = *(port_t *)data;
        !           330:                if(get_kern_port(current_task(), remote_port, &panel_req_port)) 
        !           331:                        rtn = EINVAL;
        !           332:                /*
        !           333:                 * Register this port so we'll know when it dies.
        !           334:                 */
        !           335:                port_request_notification(panel_req_port, vol_local_port);
        !           336:                break;
        !           337:                
        !           338: #if    DRIVERKIT
        !           339:            case DKIOCCHECKINSERT:
        !           340: #if 0
        !           341: #if    hppa
        !           342:                sd_check_disks(SD_CHECK_DISKS);
        !           343: #endif hppa
        !           344: #endif 0
        !           345:                manual_poll = 1;
        !           346:                break;
        !           347: #endif DRIVERKIT
        !           348: 
        !           349:            case DKIOCCANCELAUTOMOUNT:
        !           350:                mydev = *(dev_t *)data;
        !           351:                vol_notify_cancel(mydev);
        !           352: 
        !           353: /* note: for hppa, if we go with the different vol driver behavior,
        !           354:  * this function needs to be taken from the 3.2 HP kernel
        !           355:  */
        !           356: #if 0
        !           357: #ifdef hppa
        !           358:                sd_ignore_vol(mydev);
        !           359: #endif
        !           360: #endif
        !           361: 
        !           362:                break;
        !           363: 
        !           364:            default:
        !           365:                rtn = EINVAL;
        !           366:                break;
        !           367:        }
        !           368:        return(rtn);
        !           369: } /* volioctl() */
        !           370: 
        !           371: /*
        !           372:  * Any driver may call these functions to notify appropriate user task of disk
        !           373:  * insertion. If no port has been registered via DKIOCMNOTIFY, no action
        !           374:  * is taken.
        !           375:  */
        !           376:  
        !           377: kern_return_t vol_notify_dev(dev_t block_dev, 
        !           378:        dev_t raw_dev,
        !           379:        const char *form_type,
        !           380:        int vol_state,                          /* IND_VS_LABEL, etc. */
        !           381:        const char *dev_str,
        !           382:        int flags)
        !           383: {
        !           384:        return(vol_notify_com(IND_DD_DEV,
        !           385:                block_dev,
        !           386:                raw_dev,
        !           387:                0,
        !           388:                vol_state,
        !           389:                form_type,
        !           390:                dev_str,
        !           391:                flags));
        !           392: }
        !           393: 
        !           394: #if    SUPPORT_PORT_DEVICE
        !           395:        
        !           396: kern_return_t vol_notify_port(kern_port_t dev_port, 
        !           397:        char *const form_type,
        !           398:        int vol_state,                          /* IND_VS_LABEL, etc. */
        !           399:        int flags)
        !           400: {
        !           401:        return(vol_notify_com(IND_DD_PORT,
        !           402:                0,
        !           403:                0,
        !           404:                dev_port,
        !           405:                vol_state,
        !           406:                form_type,
        !           407:                "",
        !           408:                flags));
        !           409: }
        !           410: 
        !           411: #endif SUPPORT_PORT_DEVICE
        !           412: 
        !           413: static kern_return_t vol_notify_com(int in_dev_desc,   
        !           414:        dev_t block_dev, 
        !           415:        dev_t raw_dev,
        !           416:        kern_port_t dev_port, 
        !           417:        int vol_state,                          /* IND_VS_LABEL, etc. */
        !           418:        const char *form_type,
        !           419:        const char *dev_str,
        !           420:        int flags)
        !           421: {
        !           422:        struct insert_notify *notify_msg;
        !           423:        struct of_insert_notify_dev *dev_msg;
        !           424:        struct of_insert_notify_port *port_msg;
        !           425:        int size;       
        !           426:        kern_return_t krtn;
        !           427:        
        !           428:        vol_debug(("vol_notify_com: block_dev=0x%x vol_state=0x%x\n", 
        !           429:                block_dev, vol_state));
        !           430:        if(!vol_dev_init_flag) {
        !           431:                lock_init(&vol_notify_lock, TRUE);
        !           432:                vol_dev_init_flag = TRUE;
        !           433:        }
        !           434:        if(vol_check_port == (kern_port_t)NULL) {
        !           435:                vne_t vnep;
        !           436:                
        !           437:                /* 
        !           438:                 * nobody has registered yet. Queue up this request.
        !           439:                 */
        !           440:                vnep = (vne_t)kalloc(sizeof(struct vol_notify_entry));
        !           441:                vnep->dev_desc = in_dev_desc;
        !           442:                vnep->block_dev = block_dev;
        !           443:                vnep->raw_dev = raw_dev;
        !           444:                vnep->dev_port = dev_port;
        !           445:                vnep->vol_state = vol_state;
        !           446:                vnep->flags = flags;
        !           447:                strcpy(vnep->form_type, form_type);
        !           448:                strcpy(vnep->dev_str, dev_str);
        !           449:                lock_write(&vol_notify_lock);
        !           450:                queue_enter(&vol_notify_q,
        !           451:                        vnep,
        !           452:                        struct vol_notify_entry *,
        !           453:                        link); 
        !           454:                lock_done(&vol_notify_lock);
        !           455:                return(KERN_SUCCESS);
        !           456:        }
        !           457: 
        !           458:        switch(in_dev_desc) {
        !           459:            case IND_DD_DEV:
        !           460:                size = sizeof(struct of_insert_notify_dev);
        !           461:                break;
        !           462:                
        !           463: #if    SUPPORT_PORT_DEVICE
        !           464:            case IND_DD_PORT:
        !           465:                size = sizeof(struct of_insert_notify_port);
        !           466: #endif SUPPORT_PORT_DEVICE
        !           467: 
        !           468:            default:
        !           469:                return(KERN_INVALID_ARGUMENT);
        !           470:        }
        !           471:        notify_msg = (struct insert_notify *)kalloc(size);
        !           472:        *notify_msg = insert_notify_temp;
        !           473:        notify_msg->in_header.msg_simple      = (in_dev_desc == IND_DD_PORT) ? 
        !           474:                                                FALSE : TRUE;
        !           475:        notify_msg->in_header.msg_size        = size;
        !           476:        notify_msg->in_header.msg_remote_port = (port_t)vol_check_port;
        !           477:        notify_msg->in_vol_state              = vol_state;
        !           478:        notify_msg->in_dev_desc               = in_dev_desc;
        !           479:        notify_msg->in_flags                  = flags;
        !           480:        strcpy(notify_msg->in_form_type, form_type);
        !           481: 
        !           482:        /*
        !           483:         * dev or port 
        !           484:         */
        !           485:        switch(in_dev_desc) {
        !           486:            case IND_DD_DEV:
        !           487:                dev_msg = (struct of_insert_notify_dev *)notify_msg;
        !           488:                dev_msg->oid_dev_type.msg_type_name      = MSG_TYPE_INTEGER_32;
        !           489:                dev_msg->oid_dev_type.msg_type_size       = 32;
        !           490:                dev_msg->oid_dev_type.msg_type_number     = 2;
        !           491:                dev_msg->oid_dev_type.msg_type_inline     = TRUE;
        !           492:                dev_msg->oid_dev_type.msg_type_longform   = FALSE;
        !           493:                dev_msg->oid_dev_type.msg_type_deallocate = FALSE;
        !           494:                dev_msg->oid_bdev_t = block_dev;
        !           495:                dev_msg->oid_cdev_t = raw_dev;
        !           496:                dev_msg->oid_ds_type.msg_type_name       = MSG_TYPE_CHAR;
        !           497:                dev_msg->oid_ds_type.msg_type_size       = 8;
        !           498:                dev_msg->oid_ds_type.msg_type_number     = OID_DEVSTR_LEN;
        !           499:                dev_msg->oid_ds_type.msg_type_inline     = TRUE;
        !           500:                dev_msg->oid_ds_type.msg_type_longform   = FALSE;
        !           501:                dev_msg->oid_ds_type.msg_type_deallocate = FALSE;
        !           502:                strcpy(dev_msg->oid_dev_str, dev_str);
        !           503:                break;
        !           504:                
        !           505: #if    SUPPORT_PORT_DEVICE
        !           506: 
        !           507:            case IND_DD_PORT:
        !           508:                port_msg = (struct of_insert_notify_port *)notify_msg;
        !           509:                port_msg->oip_p_type.msg_type_name       = MSG_TYPE_PORT;
        !           510:                port_msg->oip_p_type.msg_type_size       = 32;
        !           511:                port_msg->oip_p_type.msg_type_number     = 1;
        !           512:                port_msg->oip_p_type.msg_type_inline     = TRUE;
        !           513:                port_msg->oip_p_type.msg_type_longform   = FALSE;
        !           514:                port_msg->oip_p_type.msg_type_deallocate = FALSE;
        !           515:                port_msg->oip_port = (port_t)dev_port;
        !           516:                
        !           517: #endif SUPPORT_PORT_DEVICE
        !           518:            default:
        !           519:                break;                  // can't happen, avoid compiler
        !           520:                                        //    warning
        !           521: 
        !           522:        }
        !           523:        krtn = msg_send_from_kernel(&notify_msg->in_header,
        !           524:                SEND_TIMEOUT,
        !           525:                0);                     /* don't block if queue full */
        !           526: #ifdef DEBUG
        !           527:        if(krtn)
        !           528:                printf("vol_check_notify: msg_send returned %d\n", krtn);
        !           529: #endif         DEBUG
        !           530:        return(krtn);
        !           531: } /* vol_check_notify */
        !           532: 
        !           533: /*
        !           534:  * Cancel a (possibly) queued notify message. Normally called when a device
        !           535:  * is mounted.
        !           536:  */
        !           537: void vol_notify_cancel(dev_t device)
        !           538: {
        !           539:        vne_t vnep, vne_next_p;
        !           540:        
        !           541:        /*
        !           542:         * Inserts are always registered for partition a; mounts can be
        !           543:         * on other partitions...
        !           544:         */
        !           545:        device &= ~(NPART - 1);
        !           546:        
        !           547:        if(!vol_dev_init_flag) {
        !           548:                lock_init(&vol_notify_lock, TRUE);
        !           549:                vol_dev_init_flag = TRUE;
        !           550:        }
        !           551: 
        !           552:        lock_write(&vol_notify_lock);
        !           553:        vnep = (vne_t)queue_first(&vol_notify_q);
        !           554:        while(!queue_end(&vol_notify_q, (queue_entry_t)vnep)) {
        !           555:                vne_next_p = (vne_t)vnep->link.next;
        !           556:                if((vnep->block_dev == device) ||
        !           557:                   (vnep->raw_dev == device)) {
        !           558:                        queue_remove(&vol_notify_q,
        !           559:                                vnep,
        !           560:                                vne_t,
        !           561:                                link); 
        !           562:                        kfree(vnep, sizeof(struct vol_notify_entry));
        !           563:                }
        !           564:                vnep = vne_next_p;
        !           565:        }
        !           566:        lock_done(&vol_notify_lock);
        !           567: }
        !           568: 
        !           569: /*
        !           570:  * Functions to request and cancel alert panels via WSM
        !           571:  */
        !           572:  
        !           573: /*
        !           574:  * Generic panel request.
        !           575:  */
        !           576: kern_return_t vol_panel_request(vpt_func fnc,
        !           577:        int panel_type,                         /* PR_PT_DISK_NUM, etc. */
        !           578:        int response_type,                      /* PR_RT_ACK, etc. */
        !           579:        int p1,
        !           580:        int p2,
        !           581:        int p3,
        !           582:        int p4,
        !           583:        char *string1,
        !           584:        char *string2,
        !           585:        void *param,
        !           586:        int *tag) {                             /* RETURNED */
        !           587:        
        !           588:        kern_return_t krtn;
        !           589:        vpe_t vpe;
        !           590:        struct vol_panel_req *panel_msgp;
        !           591:        
        !           592:        vol_debug(("vol_panel_request: panel_type=%d\n", panel_type));
        !           593:        if(panel_req_port == (kern_port_t)NULL) {
        !           594:                char *disk_string;
        !           595:                
        !           596:                /*
        !           597:                 * Nobody registered to deal with these requests yet. Punt
        !           598:                 * and send notification to the console; no ack is possible.
        !           599:                 *
        !           600:                 * For some panels, this switch is meaningless (but harmless).
        !           601:                 */
        !           602:                switch(p2) {
        !           603:                    case PR_DRIVE_FLOPPY:
        !           604:                        disk_string = "Floppy";
        !           605:                        break;
        !           606:                    case PR_DRIVE_OPTICAL:
        !           607:                        disk_string = "Optical";
        !           608:                        break;
        !           609:                    case PR_DRIVE_SCSI:
        !           610:                        disk_string = "SCSI";
        !           611:                        break;
        !           612:                    default: 
        !           613:                        disk_string = "";
        !           614:                        break;
        !           615:                }  
        !           616:                switch(panel_type) {
        !           617:                    case PR_PT_DISK_NUM:
        !           618:                        printf("Please Insert %s Disk %d in Drive %d\n", 
        !           619:                                disk_string, p1, p3);
        !           620:                        break;
        !           621:                    case PR_PT_DISK_LABEL:
        !           622:                        printf("Please Insert %s Disk \'%s\' in Drive %d\n", 
        !           623:                                disk_string, string1, p3);
        !           624:                        break;
        !           625:                    case PR_PT_DISK_NUM_W:
        !           626:                        printf("Wrong Disk: Please Insert %s Disk %d in Drive "
        !           627:                                "%d\n", disk_string, p1, p3);
        !           628:                        break;
        !           629:                    case PR_PT_DISK_LABEL_W:
        !           630:                        printf("Wrong Disk: Please Insert %s Disk \'%s\' in "
        !           631:                                "Drive %d\n", disk_string, string1, p3);
        !           632:                        break;
        !           633:                    case PR_PT_SWAPDEV_FULL:
        !           634:                        printf("***Swap Device Full***\n");
        !           635:                        break;
        !           636:                    case PR_PT_FILESYS_FULL:
        !           637:                        printf("***File System %s Full***\n", string1);
        !           638:                        break;
        !           639:                    case PR_RT_EJECT_REQ:
        !           640:                        printf("Please Eject %s Disk %d\n", disk_string, p3);
        !           641:                        break;
        !           642:                    default:
        !           643:                        /* FIXME: what do we do here? */
        !           644:                        printf("vol_panel_request: bogus panel_type (%d)\n",
        !           645:                                panel_type);
        !           646:                        break;
        !           647:                }
        !           648:                return(0);
        !           649:        }
        !           650:        /*
        !           651:         * Build a panel request message.
        !           652:         */
        !           653:        panel_msgp = (struct vol_panel_req *)kalloc(sizeof(*panel_msgp));
        !           654:        *panel_msgp = vol_panel_req_temp;
        !           655:        panel_msgp->pr_header.msg_local_port    = (port_t)vol_local_port;
        !           656:        panel_msgp->pr_header.msg_remote_port   = (port_t)panel_req_port;
        !           657:        panel_msgp->pr_panel_type               = panel_type;
        !           658:        panel_msgp->pr_resp_type                = response_type;
        !           659:        panel_msgp->pr_tag                      = vol_panel_tag++;
        !           660:        panel_msgp->pr_p1                       = p1;
        !           661:        panel_msgp->pr_p2                       = p2;
        !           662:        panel_msgp->pr_p3                       = p3;
        !           663:        panel_msgp->pr_p4                       = p4;
        !           664:        if(strlen(string1) >= VP_STRING_LEN)
        !           665:                string1[VP_STRING_LEN-1] = '\0';
        !           666:        if(strlen(string2) >= VP_STRING_LEN)
        !           667:                string2[VP_STRING_LEN-1] = '\0';
        !           668:        strcpy(panel_msgp->pr_string1, string1);
        !           669:        strcpy(panel_msgp->pr_string2, string2);
        !           670:        /*
        !           671:         * send the message.
        !           672:         */
        !           673:        krtn = msg_send_from_kernel(&panel_msgp->pr_header,
        !           674:                SEND_TIMEOUT,
        !           675:                0);                     /* don't block if queue full */
        !           676: #ifdef DEBUG
        !           677:        if(krtn)
        !           678:                printf("vol_panel_request: msg_send returned %d\n", krtn);
        !           679: #endif         DEBUG
        !           680:        if(krtn)
        !           681:                return(krtn);
        !           682:        *tag = panel_msgp->pr_tag;
        !           683:        /*
        !           684:         * Enqueue this event on vol_panel_q if we expect an ack 
        !           685:         */
        !           686:        if(response_type == PR_RT_NONE)
        !           687:                return(KERN_SUCCESS);
        !           688:        vpe = (vpe_t)kalloc(sizeof(struct vol_panel_entry));
        !           689:        if(vpe == NULL)
        !           690:                return(KERN_RESOURCE_SHORTAGE);
        !           691:        vpe->tag = panel_msgp->pr_tag;
        !           692:        vpe->fnc = fnc;
        !           693:        vpe->param = param;
        !           694:        queue_enter(&vol_panel_q, vpe, struct vol_panel_entry *, link);
        !           695:        return(KERN_SUCCESS);
        !           696:        
        !           697: } /* vol_panel_request */
        !           698: 
        !           699: /*
        !           700:  * remove an existing panel.
        !           701:  */
        !           702: kern_return_t vol_panel_remove(int tag) {
        !           703:        struct vol_panel_cancel *msgp;
        !           704:        kern_return_t krtn = KERN_SUCCESS;
        !           705:        vpe_t vpe;
        !           706:        
        !           707:        vol_debug(("vol_panel_remove\n"));
        !           708:        if(panel_req_port != (kern_port_t)NULL) {
        !           709:                msgp = (struct vol_panel_cancel *)kalloc(sizeof(*msgp));
        !           710:                *msgp = vol_panel_cancel_temp;
        !           711:                msgp->pc_header.msg_local_port        = (port_t)vol_local_port;
        !           712:                msgp->pc_header.msg_remote_port       = (port_t)panel_req_port;
        !           713:                msgp->pc_tag                          = tag;
        !           714:                krtn = msg_send_from_kernel(&msgp->pc_header,
        !           715:                        SEND_TIMEOUT,
        !           716:                        0);                     /* don't block if queue full */
        !           717:                if(krtn)
        !           718:                        printf("vol_panel_remove: msg_send returned %d\n",
        !           719:                                krtn);
        !           720:        }
        !           721:        /*
        !           722:         * Remove entry in vol_panel_q for this panel.
        !           723:         */
        !           724:        vpe = vol_panel_get_entry(tag);
        !           725:        if(vpe) 
        !           726:                kfree(vpe, sizeof(*vpe));
        !           727:        else {
        !           728:                /*
        !           729:                 * This is not an error; it could happen in a race condition in 
        !           730:                 * which this function were called just after we received a
        !           731:                 * vol_panel_cancel message.
        !           732:                 */
        !           733:                vol_debug(("vol_panel_remove: panel resp, tag not found\n"));
        !           734:        }
        !           735:        return(krtn);
        !           736: }
        !           737: 
        !           738: /*
        !           739:  * Panel requests specifically for disk drivers.
        !           740:  */
        !           741: kern_return_t vol_panel_disk_num(vpt_func fnc,
        !           742:        int volume_num,
        !           743:        int drive_type,                         /* PR_DRIVE_FLOPPY, etc. */
        !           744:        int drive_num,
        !           745:        void *param,
        !           746:        boolean_t wrong_disk,
        !           747:        int *tag) {                             /* RETURNED */
        !           748:        
        !           749:        return(vol_panel_request(fnc,
        !           750:                wrong_disk ? PR_PT_DISK_NUM_W : PR_PT_DISK_NUM,
        !           751:                PR_RT_ACK,
        !           752:                volume_num,
        !           753:                drive_type,
        !           754:                drive_num,
        !           755:                0,
        !           756:                "",
        !           757:                "",
        !           758:                param,
        !           759:                tag));  
        !           760: }
        !           761: 
        !           762: kern_return_t vol_panel_disk_label(vpt_func fnc,
        !           763:        char *label,
        !           764:        int drive_type,                         /* PR_DRIVE_FLOPPY, etc. */
        !           765:        int drive_num,
        !           766:        void *param,
        !           767:        boolean_t wrong_disk,
        !           768:        int *tag) {                             /* RETURNED */
        !           769: 
        !           770:        return(vol_panel_request(fnc,
        !           771:                wrong_disk ? PR_PT_DISK_LABEL_W : PR_PT_DISK_LABEL,
        !           772:                PR_RT_ACK,
        !           773:                0,
        !           774:                drive_type,
        !           775:                drive_num,
        !           776:                0,
        !           777:                label,
        !           778:                "",
        !           779:                param,
        !           780:                tag));  
        !           781: } 
        !           782: 
        !           783: void vol_thread() {
        !           784:        /*
        !           785:         * The job here is to receive and handle two kinds of messages:
        !           786:         *
        !           787:         * -- messages from the Workspace (like vol_panel_resp messages). 
        !           788:         * -- port death messages, forwarded to us from voltask. The death of 
        !           789:         *    panel_req_port will cause all pending panels in vol_panel_q to be
        !           790:         *    acked and removed. The death of vol_check_port isn't very 
        !           791:         *    interesting; we just NULL it out so we don't send any more
        !           792:         *    insertion events.
        !           793:         */
        !           794:         
        !           795:        struct vol_panel_resp *msgp;
        !           796:        kern_return_t krtn;
        !           797:        vpe_t vpe;
        !           798: 
        !           799:        msgp = (struct vol_panel_resp *)kalloc(MSG_SIZE_MAX);
        !           800:        
        !           801:        while(1) {
        !           802:                msgp->ps_header.msg_local_port = vol_receive_port;
        !           803:                msgp->ps_header.msg_size       = MSG_SIZE_MAX;
        !           804:                krtn = msg_receive(&msgp->ps_header, MSG_OPTION_NONE, 0);
        !           805:                if(krtn) {
        !           806:                        printf("vol_thread: msg_receive() returned %d\n", 
        !           807:                                krtn);
        !           808:                        continue;
        !           809:                }
        !           810:                vol_debug(("vol_thread: msg_id = 0x%x\n", 
        !           811:                        msgp->ps_header.msg_id));
        !           812:                switch(msgp->ps_header.msg_id) {
        !           813:                    case VOL_PANEL_RESP:
        !           814:                        /*
        !           815:                         * First we have to see if we know about a panel with 
        !           816:                         * this tag.
        !           817:                         */
        !           818:                        vpe = vol_panel_get_entry(msgp->ps_tag);
        !           819:                        if(vpe == NULL) {
        !           820:                                /*
        !           821:                                 * This is not an error; it could happen
        !           822:                                 * in a race condition in which this message
        !           823:                                 * came in just after a driver sent a 
        !           824:                                 * vol_panel_cancel message.
        !           825:                                 */
        !           826:                                vol_debug(("vol_thread: panel resp, tag not"
        !           827:                                        " found\n"));
        !           828:                                break;
        !           829:                        }
        !           830:                        /*
        !           831:                         * Perform callout if necessary, then dispose of
        !           832:                         * entry.
        !           833:                         */
        !           834:                        vol_debug(("vol_thread: doing VOL_PANEL_RESP "
        !           835:                                "callout\n"));
        !           836:                        if(vpe->fnc) {
        !           837:                                (*vpe->fnc)(vpe->param, 
        !           838:                                        vpe->tag, 
        !           839:                                        msgp->ps_value);
        !           840:                        }
        !           841:                        kfree(vpe, sizeof(*vpe));
        !           842:                        break;
        !           843:                        
        !           844:                    case NOTIFY_PORT_DELETED:
        !           845:                        vol_debug(("vol_thread: port death\n"));
        !           846:                        vol_port_death((notification_t *)msgp);
        !           847:                        break;
        !           848:                        
        !           849:                    default:
        !           850:                        printf("vol_thread: bogus message rec'd (msg_id = "
        !           851:                                "%d)\n", msgp->ps_header.msg_id);
        !           852:                        break;
        !           853:                }
        !           854:        }
        !           855: } /* vol_thread() */
        !           856: 
        !           857: static vpe_t vol_panel_get_entry(int tag) {
        !           858:        /*
        !           859:         * get vol_panel_entry associated with 'tag' from vol_panel_q. Removes
        !           860:         * entry from vol_panel_q. Returns NULL if entry not found.
        !           861:         */
        !           862:        vpe_t vpe;
        !           863: 
        !           864:        vpe = (vpe_t)queue_first(&vol_panel_q);
        !           865:        while(!queue_end(&vol_panel_q, (queue_entry_t)vpe)) {
        !           866:                if(vpe->tag == tag) {
        !           867:                        /*
        !           868:                         * Found it. 
        !           869:                         */
        !           870:                        queue_remove(&vol_panel_q,
        !           871:                                vpe,
        !           872:                                struct vol_panel_entry *,
        !           873:                                link);
        !           874:                        return(vpe);
        !           875:                }
        !           876:                vpe = (vpe_t)vpe->link.next;
        !           877:        }
        !           878:        /*
        !           879:         * Not found. 
        !           880:         */
        !           881:        return((vpe_t)NULL);
        !           882: }
        !           883: 
        !           884: static void vol_port_death(notification_t *nmsg)
        !           885: {
        !           886:        /*
        !           887:         * voltask has detected port death of one of our ports.
        !           888:         */
        !           889:        vol_debug(("vol_port_death: "));
        !           890:        if((kern_port_t)nmsg->notify_port == vol_check_port) {
        !           891:                vol_debug(("vol_check_port dead\n"));
        !           892:                vol_check_port = PORT_NULL;
        !           893:        }
        !           894:        else if ((kern_port_t)nmsg->notify_port == panel_req_port) {
        !           895:                vpe_t vpe, vpe_next;
        !           896:                
        !           897:                vol_debug(("panel_req_port dead\n"));
        !           898:                /*
        !           899:                 * Ack and dispose of every vol_panel_entry in vol_panel_q.
        !           900:                 */
        !           901:                vpe = (vpe_t)queue_first(&vol_panel_q);
        !           902:                while(!queue_end(&vol_panel_q, (queue_entry_t)vpe)) {
        !           903:                        vol_debug(("vol_port_death: doing VOL_PANEL_RESP "
        !           904:                                "callout\n"));
        !           905:                        vpe_next = (vpe_t)vpe->link.next;
        !           906:                        if(vpe->fnc) {
        !           907:                                (*vpe->fnc)(vpe->param, 
        !           908:                                        vpe->tag, 
        !           909:                                        0);     /* as in "disk not 
        !           910:                                                 * available" */
        !           911:                        }
        !           912:                        queue_remove(&vol_panel_q,
        !           913:                                vpe,
        !           914:                                struct vol_panel_entry *,
        !           915:                                link);
        !           916:                        kfree(vpe, sizeof(*vpe));
        !           917:                        vpe = vpe_next;
        !           918:                }
        !           919:                /*
        !           920:                 * Finally, inhibit further panel request messages.
        !           921:                 */
        !           922:                panel_req_port = PORT_NULL;
        !           923:        }
        !           924:        else 
        !           925:                vol_debug(("bogus notification\n"));
        !           926: }
        !           927: 
        !           928: void vol_start_thread()
        !           929: {
        !           930:        kern_return_t krtn;
        !           931: 
        !           932:        mach_port_t     name;
        !           933: 
        !           934:        krtn = ipc_port_alloc(kernel_task->itk_space, &name, &vol_local_port);
        !           935:        if(krtn) {
        !           936:                printf("vol_start_thread: port_alloc returned %d\n", 
        !           937:                        krtn);
        !           938:                return;
        !           939:        }
        !           940:        vol_receive_port = vol_local_port->ip_receiver_name;
        !           941:        ip_unlock(vol_local_port);
        !           942:        kernel_thread(kernel_task, vol_thread, (void *)0);
        !           943:        queue_init(&vol_panel_q);
        !           944:        vol_thread_alive = 1;
        !           945:        if(!vol_dev_init_flag) {
        !           946:                lock_init(&vol_notify_lock, TRUE);
        !           947:                vol_dev_init_flag = TRUE;
        !           948:        }
        !           949: }
        !           950: 
        !           951: #if    DRIVERKIT
        !           952: /* 
        !           953:  * Returns 1 if DKIOCCHECKINSERT has been executed since the last call,
        !           954:  * else returns 0.
        !           955:  */
        !           956: int vol_check_manual_poll()
        !           957: {
        !           958:        if(manual_poll) {
        !           959:                manual_poll = 0;
        !           960:                return(1);
        !           961:        }
        !           962:        else {
        !           963:                return(0);
        !           964:        }
        !           965: }
        !           966: 
        !           967: /*
        !           968:  * Internal version of ioctl(DKIOCCHECKINSERT).
        !           969:  */
        !           970: void vol_check_set_poll()
        !           971: {
        !           972:        manual_poll = 1;
        !           973: }
        !           974: 
        !           975: #endif DRIVERKIT
        !           976: 
        !           977: /* end of vol.c */
        !           978: 

unix.superglobalmegacorp.com

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