1*c16b380fSderaadt /* $NetBSD: chio.c,v 1.1.1.1 1996/04/03 00:34:38 thorpej Exp $ */ 2*c16b380fSderaadt 3*c16b380fSderaadt /* 4*c16b380fSderaadt * Copyright (c) 1996 Jason R. Thorpe <thorpej@and.com> 5*c16b380fSderaadt * All rights reserved. 6*c16b380fSderaadt * 7*c16b380fSderaadt * Redistribution and use in source and binary forms, with or without 8*c16b380fSderaadt * modification, are permitted provided that the following conditions 9*c16b380fSderaadt * are met: 10*c16b380fSderaadt * 1. Redistributions of source code must retain the above copyright 11*c16b380fSderaadt * notice, this list of conditions and the following disclaimer. 12*c16b380fSderaadt * 2. Redistributions in binary form must reproduce the above copyright 13*c16b380fSderaadt * notice, this list of conditions and the following disclaimer in the 14*c16b380fSderaadt * documentation and/or other materials provided with the distribution. 15*c16b380fSderaadt * 3. All advertising materials mentioning features or use of this software 16*c16b380fSderaadt * must display the following acknowledgements: 17*c16b380fSderaadt * This product includes software developed by Jason R. Thorpe 18*c16b380fSderaadt * for And Communications, http://www.and.com/ 19*c16b380fSderaadt * 4. The name of the author may not be used to endorse or promote products 20*c16b380fSderaadt * derived from this software without specific prior written permission. 21*c16b380fSderaadt * 22*c16b380fSderaadt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23*c16b380fSderaadt * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24*c16b380fSderaadt * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25*c16b380fSderaadt * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26*c16b380fSderaadt * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 27*c16b380fSderaadt * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28*c16b380fSderaadt * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29*c16b380fSderaadt * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30*c16b380fSderaadt * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31*c16b380fSderaadt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32*c16b380fSderaadt * SUCH DAMAGE. 33*c16b380fSderaadt */ 34*c16b380fSderaadt 35*c16b380fSderaadt #include <sys/param.h> 36*c16b380fSderaadt #include <sys/ioctl.h> 37*c16b380fSderaadt #include <sys/chio.h> 38*c16b380fSderaadt #include <err.h> 39*c16b380fSderaadt #include <errno.h> 40*c16b380fSderaadt #include <fcntl.h> 41*c16b380fSderaadt #include <limits.h> 42*c16b380fSderaadt #include <stdio.h> 43*c16b380fSderaadt #include <stdlib.h> 44*c16b380fSderaadt #include <string.h> 45*c16b380fSderaadt #include <unistd.h> 46*c16b380fSderaadt 47*c16b380fSderaadt #include "defs.h" 48*c16b380fSderaadt #include "pathnames.h" 49*c16b380fSderaadt 50*c16b380fSderaadt extern char *__progname; /* from crt0.o */ 51*c16b380fSderaadt 52*c16b380fSderaadt static void usage __P((void)); 53*c16b380fSderaadt static void cleanup __P((void)); 54*c16b380fSderaadt static int parse_element_type __P((char *)); 55*c16b380fSderaadt static int parse_element_unit __P((char *)); 56*c16b380fSderaadt static int parse_special __P((char *)); 57*c16b380fSderaadt static int is_special __P((char *)); 58*c16b380fSderaadt static char *bits_to_string __P((int, const char *)); 59*c16b380fSderaadt 60*c16b380fSderaadt static int do_move __P((char *, int, char **)); 61*c16b380fSderaadt static int do_exchange __P((char *, int, char **)); 62*c16b380fSderaadt static int do_position __P((char *, int, char **)); 63*c16b380fSderaadt static int do_params __P((char *, int, char **)); 64*c16b380fSderaadt static int do_getpicker __P((char *, int, char **)); 65*c16b380fSderaadt static int do_setpicker __P((char *, int, char **)); 66*c16b380fSderaadt static int do_status __P((char *, int, char **)); 67*c16b380fSderaadt 68*c16b380fSderaadt /* Valid changer element types. */ 69*c16b380fSderaadt const struct element_type elements[] = { 70*c16b380fSderaadt { "picker", CHET_MT }, 71*c16b380fSderaadt { "slot", CHET_ST }, 72*c16b380fSderaadt { "portal", CHET_IE }, 73*c16b380fSderaadt { "drive", CHET_DT }, 74*c16b380fSderaadt { NULL, 0 }, 75*c16b380fSderaadt }; 76*c16b380fSderaadt 77*c16b380fSderaadt /* Valid commands. */ 78*c16b380fSderaadt const struct changer_command commands[] = { 79*c16b380fSderaadt { "move", do_move }, 80*c16b380fSderaadt { "exchange", do_exchange }, 81*c16b380fSderaadt { "position", do_position }, 82*c16b380fSderaadt { "params", do_params }, 83*c16b380fSderaadt { "getpicker", do_getpicker }, 84*c16b380fSderaadt { "setpicker", do_setpicker }, 85*c16b380fSderaadt { "status", do_status }, 86*c16b380fSderaadt { NULL, 0 }, 87*c16b380fSderaadt }; 88*c16b380fSderaadt 89*c16b380fSderaadt /* Valid special words. */ 90*c16b380fSderaadt const struct special_word specials[] = { 91*c16b380fSderaadt { "inv", SW_INVERT }, 92*c16b380fSderaadt { "inv1", SW_INVERT1 }, 93*c16b380fSderaadt { "inv2", SW_INVERT2 }, 94*c16b380fSderaadt { NULL, 0 }, 95*c16b380fSderaadt }; 96*c16b380fSderaadt 97*c16b380fSderaadt static int changer_fd; 98*c16b380fSderaadt static char *changer_name; 99*c16b380fSderaadt 100*c16b380fSderaadt int 101*c16b380fSderaadt main(argc, argv) 102*c16b380fSderaadt int argc; 103*c16b380fSderaadt char **argv; 104*c16b380fSderaadt { 105*c16b380fSderaadt int ch, i; 106*c16b380fSderaadt char *cp; 107*c16b380fSderaadt 108*c16b380fSderaadt while ((ch = getopt(argc, argv, "f:")) != -1) { 109*c16b380fSderaadt switch (ch) { 110*c16b380fSderaadt case 'f': 111*c16b380fSderaadt changer_name = optarg; 112*c16b380fSderaadt break; 113*c16b380fSderaadt 114*c16b380fSderaadt default: 115*c16b380fSderaadt usage(); 116*c16b380fSderaadt } 117*c16b380fSderaadt } 118*c16b380fSderaadt argc -= optind; 119*c16b380fSderaadt argv += optind; 120*c16b380fSderaadt 121*c16b380fSderaadt if (argc == 0) 122*c16b380fSderaadt usage(); 123*c16b380fSderaadt 124*c16b380fSderaadt /* Get the default changer if not already specified. */ 125*c16b380fSderaadt if (changer_name == NULL) 126*c16b380fSderaadt if ((changer_name = getenv(CHANGER_ENV_VAR)) == NULL) 127*c16b380fSderaadt changer_name = _PATH_CH; 128*c16b380fSderaadt 129*c16b380fSderaadt /* Open the changer device. */ 130*c16b380fSderaadt if ((changer_fd = open(changer_name, O_RDWR, 0600)) == -1) 131*c16b380fSderaadt err(1, "%s: open", changer_name); 132*c16b380fSderaadt 133*c16b380fSderaadt /* Register cleanup function. */ 134*c16b380fSderaadt if (atexit(cleanup)) 135*c16b380fSderaadt err(1, "can't register cleanup function"); 136*c16b380fSderaadt 137*c16b380fSderaadt /* Find the specified command. */ 138*c16b380fSderaadt for (i = 0; commands[i].cc_name != NULL; ++i) 139*c16b380fSderaadt if (strcmp(*argv, commands[i].cc_name) == 0) 140*c16b380fSderaadt break; 141*c16b380fSderaadt if (commands[i].cc_name == NULL) 142*c16b380fSderaadt errx(1, "unknown command: %s", *argv); 143*c16b380fSderaadt 144*c16b380fSderaadt /* Skip over the command name and call handler. */ 145*c16b380fSderaadt ++argv; --argc; 146*c16b380fSderaadt exit ((*commands[i].cc_handler)(commands[i].cc_name, argc, argv)); 147*c16b380fSderaadt } 148*c16b380fSderaadt 149*c16b380fSderaadt static int 150*c16b380fSderaadt do_move(cname, argc, argv) 151*c16b380fSderaadt char *cname; 152*c16b380fSderaadt int argc; 153*c16b380fSderaadt char **argv; 154*c16b380fSderaadt { 155*c16b380fSderaadt struct changer_move cmd; 156*c16b380fSderaadt int val; 157*c16b380fSderaadt 158*c16b380fSderaadt /* 159*c16b380fSderaadt * On a move command, we expect the following: 160*c16b380fSderaadt * 161*c16b380fSderaadt * <from ET> <from EU> <to ET> <to EU> [inv] 162*c16b380fSderaadt * 163*c16b380fSderaadt * where ET == element type and EU == element unit. 164*c16b380fSderaadt */ 165*c16b380fSderaadt if (argc < 4) { 166*c16b380fSderaadt warnx("%s: too few arguments", cname); 167*c16b380fSderaadt goto usage; 168*c16b380fSderaadt } else if (argc > 5) { 169*c16b380fSderaadt warnx("%s: too many arguments", cname); 170*c16b380fSderaadt goto usage; 171*c16b380fSderaadt } 172*c16b380fSderaadt bzero(&cmd, sizeof(cmd)); 173*c16b380fSderaadt 174*c16b380fSderaadt /* <from ET> */ 175*c16b380fSderaadt cmd.cm_fromtype = parse_element_type(*argv); 176*c16b380fSderaadt ++argv; --argc; 177*c16b380fSderaadt 178*c16b380fSderaadt /* <from EU> */ 179*c16b380fSderaadt cmd.cm_fromunit = parse_element_unit(*argv); 180*c16b380fSderaadt ++argv; --argc; 181*c16b380fSderaadt 182*c16b380fSderaadt /* <to ET> */ 183*c16b380fSderaadt cmd.cm_totype = parse_element_type(*argv); 184*c16b380fSderaadt ++argv; --argc; 185*c16b380fSderaadt 186*c16b380fSderaadt /* <to EU> */ 187*c16b380fSderaadt cmd.cm_tounit = parse_element_unit(*argv); 188*c16b380fSderaadt ++argv; --argc; 189*c16b380fSderaadt 190*c16b380fSderaadt /* Deal with optional command modifier. */ 191*c16b380fSderaadt if (argc) { 192*c16b380fSderaadt val = parse_special(*argv); 193*c16b380fSderaadt switch (val) { 194*c16b380fSderaadt case SW_INVERT: 195*c16b380fSderaadt cmd.cm_flags |= CM_INVERT; 196*c16b380fSderaadt break; 197*c16b380fSderaadt 198*c16b380fSderaadt default: 199*c16b380fSderaadt errx(1, "%s: inappropriate modifier `%s'", 200*c16b380fSderaadt cname, *argv); 201*c16b380fSderaadt /* NOTREACHED */ 202*c16b380fSderaadt } 203*c16b380fSderaadt } 204*c16b380fSderaadt 205*c16b380fSderaadt /* Send command to changer. */ 206*c16b380fSderaadt if (ioctl(changer_fd, CHIOMOVE, (char *)&cmd)) 207*c16b380fSderaadt err(1, "%s: CHIOMOVE", changer_name); 208*c16b380fSderaadt 209*c16b380fSderaadt return (0); 210*c16b380fSderaadt 211*c16b380fSderaadt usage: 212*c16b380fSderaadt fprintf(stderr, "usage: %s %s " 213*c16b380fSderaadt "<from ET> <from EU> <to ET> <to EU> [inv]\n", __progname, cname); 214*c16b380fSderaadt return (1); 215*c16b380fSderaadt } 216*c16b380fSderaadt 217*c16b380fSderaadt static int 218*c16b380fSderaadt do_exchange(cname, argc, argv) 219*c16b380fSderaadt char *cname; 220*c16b380fSderaadt int argc; 221*c16b380fSderaadt char **argv; 222*c16b380fSderaadt { 223*c16b380fSderaadt struct changer_exchange cmd; 224*c16b380fSderaadt int val; 225*c16b380fSderaadt 226*c16b380fSderaadt /* 227*c16b380fSderaadt * On an exchange command, we expect the following: 228*c16b380fSderaadt * 229*c16b380fSderaadt * <src ET> <src EU> <dst1 ET> <dst1 EU> [<dst2 ET> <dst2 EU>] [inv1] [inv2] 230*c16b380fSderaadt * 231*c16b380fSderaadt * where ET == element type and EU == element unit. 232*c16b380fSderaadt */ 233*c16b380fSderaadt if (argc < 4) { 234*c16b380fSderaadt warnx("%s: too few arguments", cname); 235*c16b380fSderaadt goto usage; 236*c16b380fSderaadt } else if (argc > 8) { 237*c16b380fSderaadt warnx("%s: too many arguments", cname); 238*c16b380fSderaadt goto usage; 239*c16b380fSderaadt } 240*c16b380fSderaadt bzero(&cmd, sizeof(cmd)); 241*c16b380fSderaadt 242*c16b380fSderaadt /* <src ET> */ 243*c16b380fSderaadt cmd.ce_srctype = parse_element_type(*argv); 244*c16b380fSderaadt ++argv; --argc; 245*c16b380fSderaadt 246*c16b380fSderaadt /* <src EU> */ 247*c16b380fSderaadt cmd.ce_srcunit = parse_element_unit(*argv); 248*c16b380fSderaadt ++argv; --argc; 249*c16b380fSderaadt 250*c16b380fSderaadt /* <dst1 ET> */ 251*c16b380fSderaadt cmd.ce_fdsttype = parse_element_type(*argv); 252*c16b380fSderaadt ++argv; --argc; 253*c16b380fSderaadt 254*c16b380fSderaadt /* <dst1 EU> */ 255*c16b380fSderaadt cmd.ce_fdstunit = parse_element_unit(*argv); 256*c16b380fSderaadt ++argv; --argc; 257*c16b380fSderaadt 258*c16b380fSderaadt /* 259*c16b380fSderaadt * If the next token is a special word or there are no more 260*c16b380fSderaadt * arguments, then this is a case of simple exchange. 261*c16b380fSderaadt * dst2 == src. 262*c16b380fSderaadt */ 263*c16b380fSderaadt if ((argc == 0) || is_special(*argv)) { 264*c16b380fSderaadt cmd.ce_sdsttype = cmd.ce_srctype; 265*c16b380fSderaadt cmd.ce_sdstunit = cmd.ce_srcunit; 266*c16b380fSderaadt goto do_special; 267*c16b380fSderaadt } 268*c16b380fSderaadt 269*c16b380fSderaadt /* <dst2 ET> */ 270*c16b380fSderaadt cmd.ce_sdsttype = parse_element_type(*argv); 271*c16b380fSderaadt ++argv; --argc; 272*c16b380fSderaadt 273*c16b380fSderaadt /* <dst2 EU> */ 274*c16b380fSderaadt cmd.ce_sdstunit = parse_element_unit(*argv); 275*c16b380fSderaadt ++argv; --argc; 276*c16b380fSderaadt 277*c16b380fSderaadt do_special: 278*c16b380fSderaadt /* Deal with optional command modifiers. */ 279*c16b380fSderaadt while (argc) { 280*c16b380fSderaadt val = parse_special(*argv); 281*c16b380fSderaadt ++argv; --argc; 282*c16b380fSderaadt switch (val) { 283*c16b380fSderaadt case SW_INVERT1: 284*c16b380fSderaadt cmd.ce_flags |= CE_INVERT1; 285*c16b380fSderaadt break; 286*c16b380fSderaadt 287*c16b380fSderaadt case SW_INVERT2: 288*c16b380fSderaadt cmd.ce_flags |= CE_INVERT2; 289*c16b380fSderaadt break; 290*c16b380fSderaadt 291*c16b380fSderaadt default: 292*c16b380fSderaadt errx(1, "%s: inappropriate modifier `%s'", 293*c16b380fSderaadt cname, *argv); 294*c16b380fSderaadt /* NOTREACHED */ 295*c16b380fSderaadt } 296*c16b380fSderaadt } 297*c16b380fSderaadt 298*c16b380fSderaadt /* Send command to changer. */ 299*c16b380fSderaadt if (ioctl(changer_fd, CHIOEXCHANGE, (char *)&cmd)) 300*c16b380fSderaadt err(1, "%s: CHIOEXCHANGE", changer_name); 301*c16b380fSderaadt 302*c16b380fSderaadt return (0); 303*c16b380fSderaadt 304*c16b380fSderaadt usage: 305*c16b380fSderaadt fprintf(stderr, "usage: %s %s <src ET> <src EU> <dst1 ET> <dst1 EU>\n" 306*c16b380fSderaadt " [<dst2 ET> <dst2 EU>] [inv1] [inv2]\n", 307*c16b380fSderaadt __progname, cname); 308*c16b380fSderaadt return (1); 309*c16b380fSderaadt } 310*c16b380fSderaadt 311*c16b380fSderaadt static int 312*c16b380fSderaadt do_position(cname, argc, argv) 313*c16b380fSderaadt char *cname; 314*c16b380fSderaadt int argc; 315*c16b380fSderaadt char **argv; 316*c16b380fSderaadt { 317*c16b380fSderaadt struct changer_position cmd; 318*c16b380fSderaadt int val; 319*c16b380fSderaadt 320*c16b380fSderaadt /* 321*c16b380fSderaadt * On a position command, we expect the following: 322*c16b380fSderaadt * 323*c16b380fSderaadt * <to ET> <to EU> [inv] 324*c16b380fSderaadt * 325*c16b380fSderaadt * where ET == element type and EU == element unit. 326*c16b380fSderaadt */ 327*c16b380fSderaadt if (argc < 2) { 328*c16b380fSderaadt warnx("%s: too few arguments", cname); 329*c16b380fSderaadt goto usage; 330*c16b380fSderaadt } else if (argc > 3) { 331*c16b380fSderaadt warnx("%s: too many arguments", cname); 332*c16b380fSderaadt goto usage; 333*c16b380fSderaadt } 334*c16b380fSderaadt bzero(&cmd, sizeof(cmd)); 335*c16b380fSderaadt 336*c16b380fSderaadt /* <to ET> */ 337*c16b380fSderaadt cmd.cp_type = parse_element_type(*argv); 338*c16b380fSderaadt ++argv; --argc; 339*c16b380fSderaadt 340*c16b380fSderaadt /* <to EU> */ 341*c16b380fSderaadt cmd.cp_unit = parse_element_unit(*argv); 342*c16b380fSderaadt ++argv; --argc; 343*c16b380fSderaadt 344*c16b380fSderaadt /* Deal with optional command modifier. */ 345*c16b380fSderaadt if (argc) { 346*c16b380fSderaadt val = parse_special(*argv); 347*c16b380fSderaadt switch (val) { 348*c16b380fSderaadt case SW_INVERT: 349*c16b380fSderaadt cmd.cp_flags |= CP_INVERT; 350*c16b380fSderaadt break; 351*c16b380fSderaadt 352*c16b380fSderaadt default: 353*c16b380fSderaadt errx(1, "%s: inappropriate modifier `%s'", 354*c16b380fSderaadt cname, *argv); 355*c16b380fSderaadt /* NOTREACHED */ 356*c16b380fSderaadt } 357*c16b380fSderaadt } 358*c16b380fSderaadt 359*c16b380fSderaadt /* Send command to changer. */ 360*c16b380fSderaadt if (ioctl(changer_fd, CHIOPOSITION, (char *)&cmd)) 361*c16b380fSderaadt err(1, "%s: CHIOPOSITION", changer_name); 362*c16b380fSderaadt 363*c16b380fSderaadt return (0); 364*c16b380fSderaadt 365*c16b380fSderaadt usage: 366*c16b380fSderaadt fprintf(stderr, "usage: %s %s <to ET> <to EU> [inv]\n", 367*c16b380fSderaadt __progname, cname); 368*c16b380fSderaadt return (1); 369*c16b380fSderaadt } 370*c16b380fSderaadt 371*c16b380fSderaadt static int 372*c16b380fSderaadt do_params(cname, argc, argv) 373*c16b380fSderaadt char *cname; 374*c16b380fSderaadt int argc; 375*c16b380fSderaadt char **argv; 376*c16b380fSderaadt { 377*c16b380fSderaadt struct changer_params data; 378*c16b380fSderaadt 379*c16b380fSderaadt /* No arguments to this command. */ 380*c16b380fSderaadt if (argc) { 381*c16b380fSderaadt warnx("%s: no arguements expected", cname); 382*c16b380fSderaadt goto usage; 383*c16b380fSderaadt } 384*c16b380fSderaadt 385*c16b380fSderaadt /* Get params from changer and display them. */ 386*c16b380fSderaadt bzero(&data, sizeof(data)); 387*c16b380fSderaadt if (ioctl(changer_fd, CHIOGPARAMS, (char *)&data)) 388*c16b380fSderaadt err(1, "%s: CHIOGPARAMS", changer_name); 389*c16b380fSderaadt 390*c16b380fSderaadt printf("%s: %d slot%s, %d drive%s, %d picker%s", 391*c16b380fSderaadt changer_name, 392*c16b380fSderaadt data.cp_nslots, (data.cp_nslots > 1) ? "s" : "", 393*c16b380fSderaadt data.cp_ndrives, (data.cp_ndrives > 1) ? "s" : "", 394*c16b380fSderaadt data.cp_npickers, (data.cp_npickers > 1) ? "s" : ""); 395*c16b380fSderaadt if (data.cp_nportals) 396*c16b380fSderaadt printf(", %d portal%s", data.cp_nportals, 397*c16b380fSderaadt (data.cp_nportals > 1) ? "s" : ""); 398*c16b380fSderaadt printf("\n%s: current picker: %d\n", changer_name, data.cp_curpicker); 399*c16b380fSderaadt 400*c16b380fSderaadt return (0); 401*c16b380fSderaadt 402*c16b380fSderaadt usage: 403*c16b380fSderaadt fprintf(stderr, "usage: %s %s\n", __progname, cname); 404*c16b380fSderaadt return (1); 405*c16b380fSderaadt } 406*c16b380fSderaadt 407*c16b380fSderaadt static int 408*c16b380fSderaadt do_getpicker(cname, argc, argv) 409*c16b380fSderaadt char *cname; 410*c16b380fSderaadt int argc; 411*c16b380fSderaadt char **argv; 412*c16b380fSderaadt { 413*c16b380fSderaadt int picker; 414*c16b380fSderaadt 415*c16b380fSderaadt /* No arguments to this command. */ 416*c16b380fSderaadt if (argc) { 417*c16b380fSderaadt warnx("%s: no arguments expected", cname); 418*c16b380fSderaadt goto usage; 419*c16b380fSderaadt } 420*c16b380fSderaadt 421*c16b380fSderaadt /* Get current picker from changer and display it. */ 422*c16b380fSderaadt if (ioctl(changer_fd, CHIOGPICKER, (char *)&picker)) 423*c16b380fSderaadt err(1, "%s: CHIOGPICKER", changer_name); 424*c16b380fSderaadt 425*c16b380fSderaadt printf("%s: current picker: %d\n", changer_name, picker); 426*c16b380fSderaadt 427*c16b380fSderaadt return (0); 428*c16b380fSderaadt 429*c16b380fSderaadt usage: 430*c16b380fSderaadt fprintf(stderr, "usage: %s %s\n", __progname, cname); 431*c16b380fSderaadt return (1); 432*c16b380fSderaadt } 433*c16b380fSderaadt 434*c16b380fSderaadt static int 435*c16b380fSderaadt do_setpicker(cname, argc, argv) 436*c16b380fSderaadt char *cname; 437*c16b380fSderaadt int argc; 438*c16b380fSderaadt char **argv; 439*c16b380fSderaadt { 440*c16b380fSderaadt int picker; 441*c16b380fSderaadt 442*c16b380fSderaadt if (argc < 1) { 443*c16b380fSderaadt warnx("%s: too few arguments", cname); 444*c16b380fSderaadt goto usage; 445*c16b380fSderaadt } else if (argc > 1) { 446*c16b380fSderaadt warnx("%s: too many arguments", cname); 447*c16b380fSderaadt goto usage; 448*c16b380fSderaadt } 449*c16b380fSderaadt 450*c16b380fSderaadt picker = parse_element_unit(*argv); 451*c16b380fSderaadt 452*c16b380fSderaadt /* Set the changer picker. */ 453*c16b380fSderaadt if (ioctl(changer_fd, CHIOSPICKER, (char *)&picker)) 454*c16b380fSderaadt err(1, "%s: CHIOSPICKER", changer_name); 455*c16b380fSderaadt 456*c16b380fSderaadt return (0); 457*c16b380fSderaadt 458*c16b380fSderaadt usage: 459*c16b380fSderaadt fprintf(stderr, "usage: %s %s <picker>\n", __progname, cname); 460*c16b380fSderaadt return (1); 461*c16b380fSderaadt } 462*c16b380fSderaadt 463*c16b380fSderaadt static int 464*c16b380fSderaadt do_status(cname, argc, argv) 465*c16b380fSderaadt char *cname; 466*c16b380fSderaadt int argc; 467*c16b380fSderaadt char **argv; 468*c16b380fSderaadt { 469*c16b380fSderaadt struct changer_element_status cmd; 470*c16b380fSderaadt struct changer_params data; 471*c16b380fSderaadt u_int8_t *statusp; 472*c16b380fSderaadt int i, count, chet, schet, echet; 473*c16b380fSderaadt char *cmdname, *description; 474*c16b380fSderaadt 475*c16b380fSderaadt /* 476*c16b380fSderaadt * On a status command, we expect the following: 477*c16b380fSderaadt * 478*c16b380fSderaadt * [<ET>] 479*c16b380fSderaadt * 480*c16b380fSderaadt * where ET == element type. 481*c16b380fSderaadt * 482*c16b380fSderaadt * If we get no arguments, we get the status of all 483*c16b380fSderaadt * known element types. 484*c16b380fSderaadt */ 485*c16b380fSderaadt if (argc > 1) { 486*c16b380fSderaadt warnx("%s: too many arguments", cname); 487*c16b380fSderaadt goto usage; 488*c16b380fSderaadt } 489*c16b380fSderaadt 490*c16b380fSderaadt /* 491*c16b380fSderaadt * Get params from changer. Specifically, we need the element 492*c16b380fSderaadt * counts. 493*c16b380fSderaadt */ 494*c16b380fSderaadt bzero(&data, sizeof(data)); 495*c16b380fSderaadt if (ioctl(changer_fd, CHIOGPARAMS, (char *)&data)) 496*c16b380fSderaadt err(1, "%s: CHIOGPARAMS", changer_name); 497*c16b380fSderaadt 498*c16b380fSderaadt if (argc) 499*c16b380fSderaadt schet = echet = parse_element_type(*argv); 500*c16b380fSderaadt else { 501*c16b380fSderaadt schet = CHET_MT; 502*c16b380fSderaadt echet = CHET_DT; 503*c16b380fSderaadt } 504*c16b380fSderaadt 505*c16b380fSderaadt for (chet = schet; chet <= echet; ++chet) { 506*c16b380fSderaadt switch (chet) { 507*c16b380fSderaadt case CHET_MT: 508*c16b380fSderaadt count = data.cp_npickers; 509*c16b380fSderaadt description = "picker"; 510*c16b380fSderaadt break; 511*c16b380fSderaadt 512*c16b380fSderaadt case CHET_ST: 513*c16b380fSderaadt count = data.cp_nslots; 514*c16b380fSderaadt description = "slot"; 515*c16b380fSderaadt break; 516*c16b380fSderaadt 517*c16b380fSderaadt case CHET_IE: 518*c16b380fSderaadt count = data.cp_nportals; 519*c16b380fSderaadt description = "portal"; 520*c16b380fSderaadt break; 521*c16b380fSderaadt 522*c16b380fSderaadt case CHET_DT: 523*c16b380fSderaadt count = data.cp_ndrives; 524*c16b380fSderaadt description = "drive"; 525*c16b380fSderaadt break; 526*c16b380fSderaadt } 527*c16b380fSderaadt 528*c16b380fSderaadt if (count == 0) { 529*c16b380fSderaadt if (argc == 0) 530*c16b380fSderaadt continue; 531*c16b380fSderaadt else { 532*c16b380fSderaadt printf("%s: no %s elements\n", 533*c16b380fSderaadt changer_name, description); 534*c16b380fSderaadt return (0); 535*c16b380fSderaadt } 536*c16b380fSderaadt } 537*c16b380fSderaadt 538*c16b380fSderaadt /* Allocate storage for the status bytes. */ 539*c16b380fSderaadt if ((statusp = (u_int8_t *)malloc(count)) == NULL) 540*c16b380fSderaadt errx(1, "can't allocate status storage"); 541*c16b380fSderaadt 542*c16b380fSderaadt bzero(statusp, count); 543*c16b380fSderaadt bzero(&cmd, sizeof(cmd)); 544*c16b380fSderaadt 545*c16b380fSderaadt cmd.ces_type = chet; 546*c16b380fSderaadt cmd.ces_data = statusp; 547*c16b380fSderaadt 548*c16b380fSderaadt if (ioctl(changer_fd, CHIOGSTATUS, (char *)&cmd)) { 549*c16b380fSderaadt free(statusp); 550*c16b380fSderaadt err(1, "%s: CHIOGSTATUS", changer_name); 551*c16b380fSderaadt } 552*c16b380fSderaadt 553*c16b380fSderaadt /* Dump the status for each element of this type. */ 554*c16b380fSderaadt for (i = 0; i < count; ++i) { 555*c16b380fSderaadt printf("%s %d: %s\n", description, i, 556*c16b380fSderaadt bits_to_string(statusp[i], CESTATUS_BITS)); 557*c16b380fSderaadt } 558*c16b380fSderaadt 559*c16b380fSderaadt free(statusp); 560*c16b380fSderaadt } 561*c16b380fSderaadt 562*c16b380fSderaadt return (0); 563*c16b380fSderaadt 564*c16b380fSderaadt usage: 565*c16b380fSderaadt fprintf(stderr, "usage: %s %s [<element type>]\n", __progname, 566*c16b380fSderaadt cname); 567*c16b380fSderaadt return (1); 568*c16b380fSderaadt } 569*c16b380fSderaadt 570*c16b380fSderaadt static int 571*c16b380fSderaadt parse_element_type(cp) 572*c16b380fSderaadt char *cp; 573*c16b380fSderaadt { 574*c16b380fSderaadt int i; 575*c16b380fSderaadt 576*c16b380fSderaadt for (i = 0; elements[i].et_name != NULL; ++i) 577*c16b380fSderaadt if (strcmp(elements[i].et_name, cp) == 0) 578*c16b380fSderaadt return (elements[i].et_type); 579*c16b380fSderaadt 580*c16b380fSderaadt errx(1, "invalid element type `%s'", cp); 581*c16b380fSderaadt } 582*c16b380fSderaadt 583*c16b380fSderaadt static int 584*c16b380fSderaadt parse_element_unit(cp) 585*c16b380fSderaadt char *cp; 586*c16b380fSderaadt { 587*c16b380fSderaadt int i; 588*c16b380fSderaadt char *p; 589*c16b380fSderaadt 590*c16b380fSderaadt i = (int)strtol(cp, &p, 10); 591*c16b380fSderaadt if ((i < 0) || (*p != '\0')) 592*c16b380fSderaadt errx(1, "invalid unit number `%s'", cp); 593*c16b380fSderaadt 594*c16b380fSderaadt return (i); 595*c16b380fSderaadt } 596*c16b380fSderaadt 597*c16b380fSderaadt static int 598*c16b380fSderaadt parse_special(cp) 599*c16b380fSderaadt char *cp; 600*c16b380fSderaadt { 601*c16b380fSderaadt int val; 602*c16b380fSderaadt 603*c16b380fSderaadt val = is_special(cp); 604*c16b380fSderaadt if (val) 605*c16b380fSderaadt return (val); 606*c16b380fSderaadt 607*c16b380fSderaadt errx(1, "invalid modifier `%s'", cp); 608*c16b380fSderaadt } 609*c16b380fSderaadt 610*c16b380fSderaadt static int 611*c16b380fSderaadt is_special(cp) 612*c16b380fSderaadt char *cp; 613*c16b380fSderaadt { 614*c16b380fSderaadt int i; 615*c16b380fSderaadt 616*c16b380fSderaadt for (i = 0; specials[i].sw_name != NULL; ++i) 617*c16b380fSderaadt if (strcmp(specials[i].sw_name, cp) == 0) 618*c16b380fSderaadt return (specials[i].sw_value); 619*c16b380fSderaadt 620*c16b380fSderaadt return (0); 621*c16b380fSderaadt } 622*c16b380fSderaadt 623*c16b380fSderaadt static char * 624*c16b380fSderaadt bits_to_string(v, cp) 625*c16b380fSderaadt int v; 626*c16b380fSderaadt const char *cp; 627*c16b380fSderaadt { 628*c16b380fSderaadt const char *np; 629*c16b380fSderaadt char f, sep, *bp; 630*c16b380fSderaadt static char buf[128]; 631*c16b380fSderaadt 632*c16b380fSderaadt bp = buf; 633*c16b380fSderaadt bzero(buf, sizeof(buf)); 634*c16b380fSderaadt 635*c16b380fSderaadt for (sep = '<'; (f = *cp++) != 0; cp = np) { 636*c16b380fSderaadt for (np = cp; *np >= ' ';) 637*c16b380fSderaadt np++; 638*c16b380fSderaadt if ((v & (1 << (f - 1))) == 0) 639*c16b380fSderaadt continue; 640*c16b380fSderaadt bp += sprintf(bp, "%c%.*s", sep, np - cp, cp); 641*c16b380fSderaadt sep = ','; 642*c16b380fSderaadt } 643*c16b380fSderaadt if (sep != '<') 644*c16b380fSderaadt *bp = '>'; 645*c16b380fSderaadt 646*c16b380fSderaadt return (buf); 647*c16b380fSderaadt } 648*c16b380fSderaadt 649*c16b380fSderaadt static void 650*c16b380fSderaadt cleanup() 651*c16b380fSderaadt { 652*c16b380fSderaadt 653*c16b380fSderaadt /* Simple enough... */ 654*c16b380fSderaadt (void)close(changer_fd); 655*c16b380fSderaadt } 656*c16b380fSderaadt 657*c16b380fSderaadt static void 658*c16b380fSderaadt usage() 659*c16b380fSderaadt { 660*c16b380fSderaadt 661*c16b380fSderaadt fprintf(stderr, "usage: %s command arg1 arg2 ...\n", __progname); 662*c16b380fSderaadt exit(1); 663*c16b380fSderaadt } 664