[BACK]Return to chio.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / bin / chio

Annotation of src/bin/chio/chio.c, Revision 1.31

1.31    ! joerg       1: /* $NetBSD: chio.c,v 1.30 2008/07/20 00:52:39 lukem Exp $ */
1.1       thorpej     2:
1.13      thorpej     3: /*-
                      4:  * Copyright (c) 1996, 1998, 1999 The NetBSD Foundation, Inc.
1.1       thorpej     5:  * All rights reserved.
                      6:  *
1.13      thorpej     7:  * This code is derived from software contributed to The NetBSD Foundation
                      8:  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
                      9:  * NASA Ames Research Center.
                     10:  *
1.1       thorpej    11:  * Redistribution and use in source and binary forms, with or without
                     12:  * modification, are permitted provided that the following conditions
                     13:  * are met:
                     14:  * 1. Redistributions of source code must retain the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer.
                     16:  * 2. Redistributions in binary form must reproduce the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer in the
                     18:  *    documentation and/or other materials provided with the distribution.
                     19:  *
1.13      thorpej    20:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     21:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     22:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     23:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     24:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     25:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     26:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     27:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     28:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     29:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     30:  * POSSIBILITY OF SUCH DAMAGE.
1.1       thorpej    31:  */
1.13      thorpej    32:
1.5       mjacob     33: /*
                     34:  * Additional Copyright (c) 1997, by Matthew Jacob, for NASA/Ames Research Ctr.
                     35:  */
1.1       thorpej    36:
1.2       thorpej    37: #include <sys/cdefs.h>
                     38: #ifndef lint
1.7       hpeyerl    39: __COPYRIGHT(
1.13      thorpej    40: "@(#) Copyright (c) 1996, 1998, 1999\
1.30      lukem      41:  The NetBSD Foundation, Inc.  All rights reserved.");
1.31    ! joerg      42: __RCSID("$NetBSD: chio.c,v 1.30 2008/07/20 00:52:39 lukem Exp $");
1.2       thorpej    43: #endif
                     44:
1.1       thorpej    45: #include <sys/param.h>
                     46: #include <sys/ioctl.h>
1.18      enami      47: #include <sys/chio.h>
1.7       hpeyerl    48: #include <sys/cdio.h>  /* for ATAPI CD changer; too bad it uses a lame API */
1.16      wiz        49:
1.13      thorpej    50: #include <ctype.h>
1.1       thorpej    51: #include <err.h>
                     52: #include <errno.h>
                     53: #include <fcntl.h>
                     54: #include <limits.h>
                     55: #include <stdio.h>
                     56: #include <stdlib.h>
                     57: #include <string.h>
                     58: #include <unistd.h>
                     59:
                     60: #include "defs.h"
                     61: #include "pathnames.h"
                     62:
1.16      wiz        63: int main(int, char *[]);
1.31    ! joerg      64: __dead static void usage(void);
1.16      wiz        65: static void cleanup(void);
                     66: static int parse_element_type(const char *);
                     67: static int parse_element_unit(const char *);
                     68: static int parse_special(const char *);
                     69: static int is_special(const char *);
                     70: static const char *bits_to_string(int, const char *);
                     71:
                     72: static int do_move(const char *, int, char **);
                     73: static int do_exchange(const char *, int, char **);
                     74: static int do_position(const char *, int, char **);
                     75: static int do_params(const char *, int, char **);
                     76: static int do_getpicker(const char *, int, char **);
                     77: static int do_setpicker(const char *, int, char **);
                     78: static int do_status(const char *, int, char **);
                     79: static int do_ielem(const char *, int, char **);
                     80: static int do_cdlu(const char *, int, char **);
1.1       thorpej    81:
                     82: /* Valid changer element types. */
                     83: const struct element_type elements[] = {
                     84:        { "picker",             CHET_MT },
                     85:        { "slot",               CHET_ST },
                     86:        { "portal",             CHET_IE },
                     87:        { "drive",              CHET_DT },
                     88:        { NULL,                 0 },
                     89: };
                     90:
                     91: /* Valid commands. */
                     92: const struct changer_command commands[] = {
1.12      thorpej    93:        { "move",       " <from ET> <from EU> <to ET> <to EU> [inv]",
                     94:          do_move },
                     95:
1.11      hubertf    96:        { "exchange",   " <src ET> <src EU> <dst1 ET> <dst1 EU>\n"
1.18      enami      97:                        "\t\t [<dst2 ET> <dst2 EU>] [inv1] [inv2]",
1.12      thorpej    98:          do_exchange },
                     99:
                    100:        { "position",   " <to ET> <to EU> [inv]", do_position },
                    101:
                    102:        { "params",     "",
                    103:          do_params },
                    104:
                    105:        { "getpicker",  "",
                    106:          do_getpicker },
                    107:
                    108:        { "setpicker",  " <picker>",
                    109:          do_setpicker },
                    110:
1.13      thorpej   111:        { "status",     " [<ET> [unit [count]]] [voltags]",
1.12      thorpej   112:          do_status },
                    113:
                    114:        { "ielem",      "",
                    115:          do_ielem },
                    116:
1.11      hubertf   117:        { "cdlu",       " load|unload <slot>\n"
1.18      enami     118:                        "\t     abort",
1.12      thorpej   119:          do_cdlu },
                    120:
                    121:        { NULL,         NULL,
                    122:          NULL },
1.1       thorpej   123: };
                    124:
                    125: /* Valid special words. */
                    126: const struct special_word specials[] = {
                    127:        { "inv",                SW_INVERT },
                    128:        { "inv1",               SW_INVERT1 },
                    129:        { "inv2",               SW_INVERT2 },
1.13      thorpej   130:        { "voltags",            SW_VOLTAGS },
1.1       thorpej   131:        { NULL,                 0 },
                    132: };
                    133:
1.16      wiz       134: static const char *changer_name;
                    135: static int changer_fd;
1.1       thorpej   136:
                    137: int
1.16      wiz       138: main(int argc, char *argv[])
1.1       thorpej   139: {
                    140:        int ch, i;
                    141:
1.17      wiz       142:        setprogname(argv[0]);
1.1       thorpej   143:        while ((ch = getopt(argc, argv, "f:")) != -1) {
                    144:                switch (ch) {
                    145:                case 'f':
                    146:                        changer_name = optarg;
                    147:                        break;
                    148:                default:
                    149:                        usage();
1.20      jschauma  150:                        /* NOTREACHED */
1.1       thorpej   151:                }
                    152:        }
                    153:        argc -= optind;
                    154:        argv += optind;
                    155:
                    156:        if (argc == 0)
                    157:                usage();
1.20      jschauma  158:                /* NOTREACHED */
                    159:
1.1       thorpej   160:        /* Get the default changer if not already specified. */
                    161:        if (changer_name == NULL)
                    162:                if ((changer_name = getenv(CHANGER_ENV_VAR)) == NULL)
                    163:                        changer_name = _PATH_CH;
                    164:
                    165:        /* Open the changer device. */
                    166:        if ((changer_fd = open(changer_name, O_RDWR, 0600)) == -1)
1.22      jschauma  167:                err(EXIT_FAILURE, "%s: open", changer_name);
1.20      jschauma  168:                /* NOTREACHED */
1.1       thorpej   169:
                    170:        /* Register cleanup function. */
                    171:        if (atexit(cleanup))
1.20      jschauma  172:                err(EXIT_FAILURE, "can't register cleanup function");
                    173:                /* NOTREACHED */
1.1       thorpej   174:
                    175:        /* Find the specified command. */
                    176:        for (i = 0; commands[i].cc_name != NULL; ++i)
                    177:                if (strcmp(*argv, commands[i].cc_name) == 0)
                    178:                        break;
                    179:        if (commands[i].cc_name == NULL)
1.20      jschauma  180:                errx(EXIT_FAILURE, "unknown command: %s", *argv);
                    181:                /* NOTREACHED */
1.1       thorpej   182:
                    183:        /* Skip over the command name and call handler. */
                    184:        ++argv; --argc;
1.18      enami     185:        exit((*commands[i].cc_handler)(commands[i].cc_name, argc, argv));
1.6       thorpej   186:        /* NOTREACHED */
1.1       thorpej   187: }
                    188:
                    189: static int
1.16      wiz       190: do_move(const char *cname, int argc, char **argv)
1.1       thorpej   191: {
1.13      thorpej   192:        struct changer_move_request cmd;
1.1       thorpej   193:        int val;
                    194:
                    195:        /*
                    196:         * On a move command, we expect the following:
                    197:         *
                    198:         * <from ET> <from EU> <to ET> <to EU> [inv]
                    199:         *
                    200:         * where ET == element type and EU == element unit.
                    201:         */
                    202:        if (argc < 4) {
                    203:                warnx("%s: too few arguments", cname);
1.11      hubertf   204:                usage();
1.20      jschauma  205:                /*NOTREACHED*/
1.1       thorpej   206:        } else if (argc > 5) {
                    207:                warnx("%s: too many arguments", cname);
1.11      hubertf   208:                usage();
1.20      jschauma  209:                /*NOTREACHED*/
1.1       thorpej   210:        }
1.16      wiz       211:        (void)memset(&cmd, 0, sizeof(cmd));
1.1       thorpej   212:
                    213:        /* <from ET>  */
                    214:        cmd.cm_fromtype = parse_element_type(*argv);
                    215:        ++argv; --argc;
                    216:
                    217:        /* <from EU> */
                    218:        cmd.cm_fromunit = parse_element_unit(*argv);
                    219:        ++argv; --argc;
                    220:
                    221:        /* <to ET> */
                    222:        cmd.cm_totype = parse_element_type(*argv);
                    223:        ++argv; --argc;
                    224:
                    225:        /* <to EU> */
                    226:        cmd.cm_tounit = parse_element_unit(*argv);
                    227:        ++argv; --argc;
                    228:
                    229:        /* Deal with optional command modifier. */
                    230:        if (argc) {
                    231:                val = parse_special(*argv);
                    232:                switch (val) {
                    233:                case SW_INVERT:
                    234:                        cmd.cm_flags |= CM_INVERT;
                    235:                        break;
                    236:                default:
1.20      jschauma  237:                        errx(EXIT_FAILURE, "%s: inappropriate modifier `%s'",
1.1       thorpej   238:                            cname, *argv);
                    239:                        /* NOTREACHED */
                    240:                }
                    241:        }
                    242:
                    243:        /* Send command to changer. */
1.6       thorpej   244:        if (ioctl(changer_fd, CHIOMOVE, &cmd))
1.22      jschauma  245:                err(EXIT_FAILURE, "%s: CHIOMOVE", changer_name);
1.20      jschauma  246:                /* NOTREACHED */
1.1       thorpej   247:
                    248:        return (0);
                    249: }
                    250:
                    251: static int
1.16      wiz       252: do_exchange(const char *cname, int argc, char **argv)
1.1       thorpej   253: {
1.13      thorpej   254:        struct changer_exchange_request cmd;
1.1       thorpej   255:        int val;
                    256:
                    257:        /*
                    258:         * On an exchange command, we expect the following:
                    259:         *
                    260:   * <src ET> <src EU> <dst1 ET> <dst1 EU> [<dst2 ET> <dst2 EU>] [inv1] [inv2]
                    261:         *
                    262:         * where ET == element type and EU == element unit.
                    263:         */
                    264:        if (argc < 4) {
                    265:                warnx("%s: too few arguments", cname);
1.11      hubertf   266:                usage();
1.20      jschauma  267:                /*NOTREACHED*/
1.1       thorpej   268:        } else if (argc > 8) {
                    269:                warnx("%s: too many arguments", cname);
1.11      hubertf   270:                usage();
1.20      jschauma  271:                /*NOTREACHED*/
1.1       thorpej   272:        }
1.16      wiz       273:        (void)memset(&cmd, 0, sizeof(cmd));
1.1       thorpej   274:
                    275:        /* <src ET>  */
                    276:        cmd.ce_srctype = parse_element_type(*argv);
                    277:        ++argv; --argc;
                    278:
                    279:        /* <src EU> */
                    280:        cmd.ce_srcunit = parse_element_unit(*argv);
                    281:        ++argv; --argc;
                    282:
                    283:        /* <dst1 ET> */
                    284:        cmd.ce_fdsttype = parse_element_type(*argv);
                    285:        ++argv; --argc;
                    286:
                    287:        /* <dst1 EU> */
                    288:        cmd.ce_fdstunit = parse_element_unit(*argv);
                    289:        ++argv; --argc;
                    290:
                    291:        /*
                    292:         * If the next token is a special word or there are no more
                    293:         * arguments, then this is a case of simple exchange.
                    294:         * dst2 == src.
                    295:         */
                    296:        if ((argc == 0) || is_special(*argv)) {
                    297:                cmd.ce_sdsttype = cmd.ce_srctype;
                    298:                cmd.ce_sdstunit = cmd.ce_srcunit;
                    299:                goto do_special;
                    300:        }
                    301:
                    302:        /* <dst2 ET> */
                    303:        cmd.ce_sdsttype = parse_element_type(*argv);
                    304:        ++argv; --argc;
                    305:
                    306:        /* <dst2 EU> */
                    307:        cmd.ce_sdstunit = parse_element_unit(*argv);
                    308:        ++argv; --argc;
                    309:
                    310:  do_special:
                    311:        /* Deal with optional command modifiers. */
                    312:        while (argc) {
                    313:                val = parse_special(*argv);
                    314:                ++argv; --argc;
                    315:                switch (val) {
                    316:                case SW_INVERT1:
                    317:                        cmd.ce_flags |= CE_INVERT1;
                    318:                        break;
                    319:                case SW_INVERT2:
                    320:                        cmd.ce_flags |= CE_INVERT2;
                    321:                        break;
                    322:                default:
1.20      jschauma  323:                        errx(EXIT_FAILURE, "%s: inappropriate modifier `%s'",
1.1       thorpej   324:                            cname, *argv);
                    325:                        /* NOTREACHED */
                    326:                }
                    327:        }
                    328:
                    329:        /* Send command to changer. */
1.6       thorpej   330:        if (ioctl(changer_fd, CHIOEXCHANGE, &cmd))
1.22      jschauma  331:                err(EXIT_FAILURE, "%s: CHIOEXCHANGE", changer_name);
1.20      jschauma  332:                /* NOTREACHED */
1.1       thorpej   333:
                    334:        return (0);
                    335: }
                    336:
                    337: static int
1.16      wiz       338: do_position(const char *cname, int argc, char **argv)
1.1       thorpej   339: {
1.13      thorpej   340:        struct changer_position_request cmd;
1.1       thorpej   341:        int val;
                    342:
                    343:        /*
                    344:         * On a position command, we expect the following:
                    345:         *
                    346:         * <to ET> <to EU> [inv]
                    347:         *
                    348:         * where ET == element type and EU == element unit.
                    349:         */
                    350:        if (argc < 2) {
                    351:                warnx("%s: too few arguments", cname);
1.11      hubertf   352:                usage();
1.20      jschauma  353:                /*NOTREACHED*/
1.1       thorpej   354:        } else if (argc > 3) {
                    355:                warnx("%s: too many arguments", cname);
1.11      hubertf   356:                usage();
1.20      jschauma  357:                /*NOTREACHED*/
1.1       thorpej   358:        }
1.16      wiz       359:        (void)memset(&cmd, 0, sizeof(cmd));
1.1       thorpej   360:
                    361:        /* <to ET>  */
                    362:        cmd.cp_type = parse_element_type(*argv);
                    363:        ++argv; --argc;
                    364:
                    365:        /* <to EU> */
                    366:        cmd.cp_unit = parse_element_unit(*argv);
                    367:        ++argv; --argc;
                    368:
                    369:        /* Deal with optional command modifier. */
                    370:        if (argc) {
                    371:                val = parse_special(*argv);
                    372:                switch (val) {
                    373:                case SW_INVERT:
                    374:                        cmd.cp_flags |= CP_INVERT;
                    375:                        break;
                    376:                default:
1.20      jschauma  377:                        errx(EXIT_FAILURE, "%s: inappropriate modifier `%s'",
1.1       thorpej   378:                            cname, *argv);
                    379:                        /* NOTREACHED */
                    380:                }
                    381:        }
                    382:
                    383:        /* Send command to changer. */
1.6       thorpej   384:        if (ioctl(changer_fd, CHIOPOSITION, &cmd))
1.22      jschauma  385:                err(EXIT_FAILURE, "%s: CHIOPOSITION", changer_name);
1.20      jschauma  386:                /* NOTREACHED */
1.1       thorpej   387:
                    388:        return (0);
                    389: }
                    390:
1.6       thorpej   391: /* ARGSUSED */
1.1       thorpej   392: static int
1.16      wiz       393: do_params(const char *cname, int argc, char **argv)
1.1       thorpej   394: {
                    395:        struct changer_params data;
                    396:
                    397:        /* No arguments to this command. */
                    398:        if (argc) {
1.28      msaitoh   399:                warnx("%s: no arguments expected", cname);
1.11      hubertf   400:                usage();
1.20      jschauma  401:                /* NOTREACHED */
1.1       thorpej   402:        }
1.20      jschauma  403:
1.1       thorpej   404:        /* Get params from changer and display them. */
1.16      wiz       405:        (void)memset(&data, 0, sizeof(data));
1.6       thorpej   406:        if (ioctl(changer_fd, CHIOGPARAMS, &data))
1.22      jschauma  407:                err(EXIT_FAILURE, "%s: CHIOGPARAMS", changer_name);
1.20      jschauma  408:                /* NOTREACHED */
1.1       thorpej   409:
1.13      thorpej   410: #define        PLURAL(n)       (n) > 1 ? "s" : ""
                    411:
1.16      wiz       412:        (void)printf("%s: %d slot%s, %d drive%s, %d picker%s",
1.22      jschauma  413:            changer_name,
1.13      thorpej   414:            data.cp_nslots, PLURAL(data.cp_nslots),
                    415:            data.cp_ndrives, PLURAL(data.cp_ndrives),
                    416:            data.cp_npickers, PLURAL(data.cp_npickers));
1.1       thorpej   417:        if (data.cp_nportals)
1.16      wiz       418:                (void)printf(", %d portal%s", data.cp_nportals,
1.13      thorpej   419:                    PLURAL(data.cp_nportals));
                    420:
                    421: #undef PLURAL
                    422:
1.22      jschauma  423:        (void)printf("\n%s: current picker: %d\n", changer_name, data.cp_curpicker);
1.1       thorpej   424:
                    425:        return (0);
                    426: }
                    427:
1.6       thorpej   428: /* ARGSUSED */
1.1       thorpej   429: static int
1.16      wiz       430: do_getpicker(const char *cname, int argc, char **argv)
1.1       thorpej   431: {
                    432:        int picker;
                    433:
                    434:        /* No arguments to this command. */
                    435:        if (argc) {
                    436:                warnx("%s: no arguments expected", cname);
1.11      hubertf   437:                usage();
1.20      jschauma  438:                /*NOTREACHED*/
1.1       thorpej   439:        }
                    440:
                    441:        /* Get current picker from changer and display it. */
1.6       thorpej   442:        if (ioctl(changer_fd, CHIOGPICKER, &picker))
1.22      jschauma  443:                err(EXIT_FAILURE, "%s: CHIOGPICKER", changer_name);
1.20      jschauma  444:                /* NOTREACHED */
1.1       thorpej   445:
1.22      jschauma  446:        (void)printf("%s: current picker: %d\n", changer_name, picker);
1.1       thorpej   447:
                    448:        return (0);
                    449: }
                    450:
                    451: static int
1.16      wiz       452: do_setpicker(const char *cname, int argc, char **argv)
1.1       thorpej   453: {
                    454:        int picker;
                    455:
                    456:        if (argc < 1) {
                    457:                warnx("%s: too few arguments", cname);
1.11      hubertf   458:                usage();
1.20      jschauma  459:                /*NOTREACHED*/
1.1       thorpej   460:        } else if (argc > 1) {
                    461:                warnx("%s: too many arguments", cname);
1.11      hubertf   462:                usage();
1.20      jschauma  463:                /*NOTREACHED*/
1.1       thorpej   464:        }
                    465:
                    466:        picker = parse_element_unit(*argv);
                    467:
                    468:        /* Set the changer picker. */
1.6       thorpej   469:        if (ioctl(changer_fd, CHIOSPICKER, &picker))
1.22      jschauma  470:                err(EXIT_FAILURE, "%s: CHIOSPICKER", changer_name);
1.1       thorpej   471:
                    472:        return (0);
                    473: }
                    474:
                    475: static int
1.16      wiz       476: do_status(const char *cname, int argc, char **argv)
1.1       thorpej   477: {
1.13      thorpej   478:        struct changer_element_status_request cmd;
1.1       thorpej   479:        struct changer_params data;
1.13      thorpej   480:        struct changer_element_status *ces;
1.16      wiz       481:        int i, chet, count, echet, flags, have_ucount, have_unit;
                    482:        int schet, ucount, unit;
1.13      thorpej   483:        size_t size;
1.18      enami     484:
1.16      wiz       485:        flags = 0;
1.27      lukem     486:        ucount = 0;
                    487:        unit = 0;
1.16      wiz       488:        have_ucount = 0;
                    489:        have_unit = 0;
1.1       thorpej   490:
                    491:        /*
                    492:         * On a status command, we expect the following:
                    493:         *
1.13      thorpej   494:         * [<ET> [unit [count]]] [voltags]
1.1       thorpej   495:         *
                    496:         * where ET == element type.
                    497:         *
1.13      thorpej   498:         * If we get no element-related arguments, we get the status of all
1.1       thorpej   499:         * known element types.
                    500:         */
1.13      thorpej   501:        if (argc > 4) {
1.1       thorpej   502:                warnx("%s: too many arguments", cname);
1.11      hubertf   503:                usage();
1.20      jschauma  504:                /*NOTREACHED*/
1.1       thorpej   505:        }
                    506:
                    507:        /*
                    508:         * Get params from changer.  Specifically, we need the element
                    509:         * counts.
                    510:         */
1.16      wiz       511:        (void)memset(&data, 0, sizeof(data));
1.6       thorpej   512:        if (ioctl(changer_fd, CHIOGPARAMS, &data))
1.22      jschauma  513:                err(EXIT_FAILURE, "%s: CHIOGPARAMS", changer_name);
1.20      jschauma  514:                /* NOTREACHED */
1.1       thorpej   515:
1.13      thorpej   516:        schet = CHET_MT;
                    517:        echet = CHET_DT;
                    518:
                    519:        for (; argc != 0; argc--, argv++) {
                    520:                /*
                    521:                 * If we have the voltags modifier, it must be the
                    522:                 * last argument.
                    523:                 */
                    524:                if (is_special(argv[0])) {
                    525:                        if (argc != 1) {
                    526:                                warnx("%s: malformed command line", cname);
                    527:                                usage();
1.20      jschauma  528:                                /*NOTREACHED*/
1.13      thorpej   529:                        }
                    530:                        if (parse_special(argv[0]) != SW_VOLTAGS)
1.20      jschauma  531:                                errx(EXIT_FAILURE,
                    532:                                    "%s: inappropriate special word: %s",
1.13      thorpej   533:                                    cname, argv[0]);
1.20      jschauma  534:                                /* NOTREACHED */
1.13      thorpej   535:                        flags |= CESR_VOLTAGS;
                    536:                        continue;
                    537:                }
                    538:
                    539:                /*
                    540:                 * If we get an element type, we can't have specified
                    541:                 * anything else.
                    542:                 */
1.26      dsl       543:                if (isdigit((unsigned char)*argv[0]) == 0) {
1.13      thorpej   544:                        if (schet == echet || flags != 0 || have_unit ||
                    545:                            have_ucount) {
                    546:                                warnx("%s: malformed command line", cname);
                    547:                                usage();
1.20      jschauma  548:                                /*NOTREACHED*/
1.13      thorpej   549:                        }
                    550:                        schet = echet = parse_element_type(argv[0]);
                    551:                        continue;
                    552:                }
                    553:
                    554:                /*
                    555:                 * We know we have a digit here.  If we do, we must
                    556:                 * have specified an element type.
                    557:                 */
                    558:                if (schet != echet) {
                    559:                        warnx("%s: malformed command line", cname);
                    560:                        usage();
1.20      jschauma  561:                        /*NOTREACHED*/
1.13      thorpej   562:                }
                    563:
                    564:                i = parse_element_unit(argv[0]);
                    565:
                    566:                if (have_unit == 0) {
                    567:                        unit = i;
                    568:                        have_unit = 1;
                    569:                } else if (have_ucount == 0) {
                    570:                        ucount = i;
                    571:                        have_ucount = 1;
                    572:                } else {
                    573:                        warnx("%s: malformed command line", cname);
                    574:                        usage();
1.20      jschauma  575:                        /*NOTREACHED*/
1.13      thorpej   576:                }
1.1       thorpej   577:        }
                    578:
                    579:        for (chet = schet; chet <= echet; ++chet) {
                    580:                switch (chet) {
                    581:                case CHET_MT:
                    582:                        count = data.cp_npickers;
                    583:                        break;
                    584:                case CHET_ST:
                    585:                        count = data.cp_nslots;
                    586:                        break;
                    587:                case CHET_IE:
                    588:                        count = data.cp_nportals;
                    589:                        break;
                    590:                case CHET_DT:
                    591:                        count = data.cp_ndrives;
                    592:                        break;
1.2       thorpej   593:                default:
                    594:                        /* To appease gcc -Wuninitialized. */
                    595:                        count = 0;
1.1       thorpej   596:                }
                    597:
                    598:                if (count == 0) {
1.13      thorpej   599:                        if (schet != echet)
1.1       thorpej   600:                                continue;
                    601:                        else {
1.16      wiz       602:                                (void)printf("%s: no %s elements\n",
1.22      jschauma  603:                                    changer_name,
1.13      thorpej   604:                                    elements[chet].et_name);
1.1       thorpej   605:                                return (0);
                    606:                        }
                    607:                }
                    608:
1.13      thorpej   609:                /*
                    610:                 * If we have a unit, we may or may not have a count.
                    611:                 * If we don't have a unit, we don't have a count, either.
                    612:                 *
                    613:                 * Make sure both are initialized.
                    614:                 */
                    615:                if (have_unit) {
                    616:                        if (have_ucount == 0)
                    617:                                ucount = 1;
                    618:                } else {
                    619:                        unit = 0;
                    620:                        ucount = count;
                    621:                }
                    622:
                    623:                if ((unit + ucount) > count)
1.20      jschauma  624:                        errx(EXIT_FAILURE, "%s: unvalid unit/count %d/%d",
1.13      thorpej   625:                            cname, unit, ucount);
1.20      jschauma  626:                        /* NOTREACHED */
1.13      thorpej   627:
                    628:                size = ucount * sizeof(struct changer_element_status);
                    629:
1.1       thorpej   630:                /* Allocate storage for the status bytes. */
1.13      thorpej   631:                if ((ces = malloc(size)) == NULL)
1.20      jschauma  632:                        errx(EXIT_FAILURE, "can't allocate status storage");
                    633:                        /* NOTREACHED */
1.1       thorpej   634:
1.16      wiz       635:                (void)memset(ces, 0, size);
                    636:                (void)memset(&cmd, 0, sizeof(cmd));
1.1       thorpej   637:
1.13      thorpej   638:                cmd.cesr_type = chet;
                    639:                cmd.cesr_unit = unit;
                    640:                cmd.cesr_count = ucount;
                    641:                cmd.cesr_flags = flags;
                    642:                cmd.cesr_data = ces;
                    643:
                    644:                /*
                    645:                 * Should we deal with this eventually?
                    646:                 */
                    647:                cmd.cesr_vendor_data = NULL;
1.1       thorpej   648:
1.6       thorpej   649:                if (ioctl(changer_fd, CHIOGSTATUS, &cmd)) {
1.13      thorpej   650:                        free(ces);
1.22      jschauma  651:                        err(EXIT_FAILURE, "%s: CHIOGSTATUS", changer_name);
1.20      jschauma  652:                        /* NOTREACHED */
1.1       thorpej   653:                }
                    654:
                    655:                /* Dump the status for each element of this type. */
1.13      thorpej   656:                for (i = 0; i < ucount; i++) {
1.16      wiz       657:                        (void)printf("%s %d: ", elements[chet].et_name,
1.13      thorpej   658:                            unit + i);
                    659:                        if ((ces[i].ces_flags & CESTATUS_STATUS_VALID) == 0) {
1.16      wiz       660:                                (void)printf("status not available\n");
1.13      thorpej   661:                                continue;
                    662:                        }
1.16      wiz       663:                        (void)printf("%s", bits_to_string(ces[i].ces_flags,
1.13      thorpej   664:                            CESTATUS_BITS));
                    665:                        if (ces[i].ces_flags & CESTATUS_XNAME_VALID)
1.16      wiz       666:                                (void)printf(" (%s)", ces[i].ces_xname);
                    667:                        (void)printf("\n");
1.13      thorpej   668:                        if (ces[i].ces_flags & CESTATUS_PVOL_VALID)
1.16      wiz       669:                                (void)printf("\tPrimary volume tag: %s "
1.13      thorpej   670:                                    "ver. %d\n",
                    671:                                    ces[i].ces_pvoltag.cv_tag,
                    672:                                    ces[i].ces_pvoltag.cv_serial);
                    673:                        if (ces[i].ces_flags & CESTATUS_AVOL_VALID)
1.16      wiz       674:                                (void)printf("\tAlternate volume tag: %s "
1.13      thorpej   675:                                    "ver. %d\n",
                    676:                                    ces[i].ces_avoltag.cv_tag,
                    677:                                    ces[i].ces_avoltag.cv_serial);
                    678:                        if (ces[i].ces_flags & CESTATUS_FROM_VALID)
1.16      wiz       679:                                (void)printf("\tFrom: %s %d\n",
1.13      thorpej   680:                                    elements[ces[i].ces_from_type].et_name,
                    681:                                    ces[i].ces_from_unit);
1.14      thorpej   682:                        if (ces[i].ces_vendor_len)
1.16      wiz       683:                                (void)printf("\tVendor-specific data size: "
1.14      thorpej   684:                                    "%lu\n", (u_long)ces[i].ces_vendor_len);
1.1       thorpej   685:                }
1.13      thorpej   686:                free(ces);
1.1       thorpej   687:        }
                    688:
                    689:        return (0);
                    690: }
                    691:
1.6       thorpej   692: /* ARGSUSED */
1.1       thorpej   693: static int
1.16      wiz       694: do_ielem(const char *cname, int argc, char **argv)
1.5       mjacob    695: {
1.18      enami     696:
1.6       thorpej   697:        if (ioctl(changer_fd, CHIOIELEM, NULL))
1.22      jschauma  698:                err(EXIT_FAILURE, "%s: CHIOIELEM", changer_name);
1.20      jschauma  699:                /* NOTREACHED */
1.5       mjacob    700:
                    701:        return (0);
                    702: }
                    703:
1.13      thorpej   704: /* ARGSUSED */
1.7       hpeyerl   705: static int
1.16      wiz       706: do_cdlu(const char *cname, int argc, char **argv)
1.7       hpeyerl   707: {
                    708:        static const struct special_word cdlu_subcmds[] = {
                    709:                { "load",       CD_LU_LOAD },
                    710:                { "unload",     CD_LU_UNLOAD },
                    711:                { "abort",      CD_LU_ABORT },
                    712:                { NULL,         0 },
                    713:        };
1.16      wiz       714:        struct ioc_load_unload cmd;
                    715:        int i;
1.7       hpeyerl   716:
                    717:        /*
                    718:         * This command is a little different, since we are mostly dealing
                    719:         * with ATAPI CD changers, which have a lame API (since ATAPI doesn't
                    720:         * have LUNs).
                    721:         *
                    722:         * We have 3 sub-commands: "load", "unload", and "abort".  The
                    723:         * first two take a slot number.  The latter does not.
                    724:         */
                    725:
                    726:        if (argc < 1 || argc > 2)
1.11      hubertf   727:                usage();
1.20      jschauma  728:                /*NOTREACHED*/
1.7       hpeyerl   729:
                    730:        for (i = 0; cdlu_subcmds[i].sw_name != NULL; i++) {
                    731:                if (strcmp(argv[0], cdlu_subcmds[i].sw_name) == 0) {
                    732:                        cmd.options = cdlu_subcmds[i].sw_value;
                    733:                        break;
                    734:                }
                    735:        }
                    736:        if (cdlu_subcmds[i].sw_name == NULL)
1.11      hubertf   737:                usage();
1.20      jschauma  738:                /*NOTREACHED*/
1.7       hpeyerl   739:
                    740:        if (strcmp(argv[0], "abort") == 0)
                    741:                cmd.slot = 0;
                    742:        else
                    743:                cmd.slot = parse_element_unit(argv[1]);
                    744:
                    745:        /*
                    746:         * XXX Should maybe do something different with the device
                    747:         * XXX handling for cdlu; think about this some more.
                    748:         */
                    749:        if (ioctl(changer_fd, CDIOCLOADUNLOAD, &cmd))
1.22      jschauma  750:                err(EXIT_FAILURE, "%s: CDIOCLOADUNLOAD", changer_name);
1.20      jschauma  751:                /* NOTREACHED */
1.7       hpeyerl   752:
                    753:        return (0);
                    754: }
1.5       mjacob    755:
                    756: static int
1.16      wiz       757: parse_element_type(const char *cp)
1.1       thorpej   758: {
                    759:        int i;
                    760:
                    761:        for (i = 0; elements[i].et_name != NULL; ++i)
                    762:                if (strcmp(elements[i].et_name, cp) == 0)
                    763:                        return (elements[i].et_type);
                    764:
1.20      jschauma  765:        errx(EXIT_FAILURE, "invalid element type `%s'", cp);
1.6       thorpej   766:        /* NOTREACHED */
1.1       thorpej   767: }
                    768:
                    769: static int
1.16      wiz       770: parse_element_unit(const char *cp)
1.1       thorpej   771: {
1.16      wiz       772:        char *p;
1.1       thorpej   773:        int i;
                    774:
                    775:        i = (int)strtol(cp, &p, 10);
                    776:        if ((i < 0) || (*p != '\0'))
1.20      jschauma  777:                errx(EXIT_FAILURE, "invalid unit number `%s'", cp);
1.1       thorpej   778:
                    779:        return (i);
                    780: }
                    781:
                    782: static int
1.16      wiz       783: parse_special(const char *cp)
1.1       thorpej   784: {
                    785:        int val;
                    786:
                    787:        val = is_special(cp);
                    788:        if (val)
                    789:                return (val);
                    790:
1.20      jschauma  791:        errx(EXIT_FAILURE, "invalid modifier `%s'", cp);
1.6       thorpej   792:        /* NOTREACHED */
1.1       thorpej   793: }
                    794:
                    795: static int
1.16      wiz       796: is_special(const char *cp)
1.1       thorpej   797: {
                    798:        int i;
                    799:
                    800:        for (i = 0; specials[i].sw_name != NULL; ++i)
                    801:                if (strcmp(specials[i].sw_name, cp) == 0)
                    802:                        return (specials[i].sw_value);
                    803:
                    804:        return (0);
                    805: }
                    806:
1.8       mycroft   807: static const char *
1.16      wiz       808: bits_to_string(int v, const char *cp)
1.1       thorpej   809: {
1.16      wiz       810:        static char buf[128];
1.1       thorpej   811:        const char *np;
1.16      wiz       812:        char *bp, f;
1.8       mycroft   813:        int first;
1.1       thorpej   814:
                    815:        bp = buf;
1.8       mycroft   816:        *bp++ = '<';
                    817:        for (first = 1; (f = *cp++) != 0; cp = np) {
1.1       thorpej   818:                for (np = cp; *np >= ' ';)
                    819:                        np++;
                    820:                if ((v & (1 << (f - 1))) == 0)
                    821:                        continue;
1.8       mycroft   822:                if (first)
                    823:                        first = 0;
                    824:                else
                    825:                        *bp++ = ',';
1.16      wiz       826:                (void)memcpy(bp, cp, np - cp);
1.8       mycroft   827:                bp += np - cp;
1.1       thorpej   828:        }
1.8       mycroft   829:        *bp++ = '>';
                    830:        *bp = '\0';
1.1       thorpej   831:
                    832:        return (buf);
                    833: }
                    834:
                    835: static void
1.16      wiz       836: cleanup(void)
1.1       thorpej   837: {
1.18      enami     838:
1.1       thorpej   839:        /* Simple enough... */
                    840:        (void)close(changer_fd);
                    841: }
                    842:
                    843: static void
1.16      wiz       844: usage(void)
1.1       thorpej   845: {
1.11      hubertf   846:        int i;
1.1       thorpej   847:
1.25      wiz       848:        (void)fprintf(stderr,
                    849:            "usage: %s [-f changer] command arg1 arg2 [arg3 [...]]\n",
1.15      cgd       850:            getprogname());
1.18      enami     851:
1.16      wiz       852:        (void)fprintf(stderr, "Where command (and args) are:\n");
1.13      thorpej   853:        for (i = 0; commands[i].cc_name != NULL; i++)
1.16      wiz       854:                (void)fprintf(stderr, "\t%s%s\n", commands[i].cc_name,
1.13      thorpej   855:                    commands[i].cc_args);
1.1       thorpej   856:        exit(1);
1.10      mycroft   857:        /* NOTREACHED */
1.1       thorpej   858: }

CVSweb <webmaster@jp.NetBSD.org>