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