1*c72b5b24Smillert /* $OpenBSD: chio.c,v 1.10 2002/02/16 21:27:06 millert 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 17d9248734Stodd * must display the following acknowledgments: 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 53*c72b5b24Smillert static void usage(void); 54*c72b5b24Smillert static void cleanup(void); 55*c72b5b24Smillert static int parse_element_type(char *); 56*c72b5b24Smillert static int parse_element_unit(char *); 57*c72b5b24Smillert static int parse_special(char *); 58*c72b5b24Smillert static int is_special(char *); 59*c72b5b24Smillert static char *bits_to_string(int, const char *); 60c16b380fSderaadt 61*c72b5b24Smillert static int do_move(char *, int, char **); 62*c72b5b24Smillert static int do_exchange(char *, int, char **); 63*c72b5b24Smillert static int do_position(char *, int, char **); 64*c72b5b24Smillert static int do_params(char *, int, char **); 65*c72b5b24Smillert static int do_getpicker(char *, int, char **); 66*c72b5b24Smillert static int do_setpicker(char *, int, char **); 67*c72b5b24Smillert static int do_status(char *, int, char **); 68c16b380fSderaadt 69c16b380fSderaadt /* Valid changer element types. */ 70c16b380fSderaadt const struct element_type elements[] = { 71c16b380fSderaadt { "drive", CHET_DT }, 72b13cd761Sderaadt { "picker", CHET_MT }, 73b13cd761Sderaadt { "portal", CHET_IE }, 74b13cd761Sderaadt { "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 }, 82b13cd761Sderaadt { "move", do_move }, 83b13cd761Sderaadt { "params", do_params }, 84b13cd761Sderaadt { "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 108c16b380fSderaadt while ((ch = getopt(argc, argv, "f:")) != -1) { 109c16b380fSderaadt switch (ch) { 110c16b380fSderaadt case 'f': 111c16b380fSderaadt changer_name = optarg; 112c16b380fSderaadt break; 113c16b380fSderaadt 114c16b380fSderaadt default: 115c16b380fSderaadt usage(); 116c16b380fSderaadt } 117c16b380fSderaadt } 118c16b380fSderaadt argc -= optind; 119c16b380fSderaadt argv += optind; 120c16b380fSderaadt 121c16b380fSderaadt if (argc == 0) 122c16b380fSderaadt usage(); 123c16b380fSderaadt 124c16b380fSderaadt /* Get the default changer if not already specified. */ 125c16b380fSderaadt if (changer_name == NULL) 126c16b380fSderaadt if ((changer_name = getenv(CHANGER_ENV_VAR)) == NULL) 127c16b380fSderaadt changer_name = _PATH_CH; 128c16b380fSderaadt 129c16b380fSderaadt /* Open the changer device. */ 130c16b380fSderaadt if ((changer_fd = open(changer_name, O_RDWR, 0600)) == -1) 131c16b380fSderaadt err(1, "%s: open", changer_name); 132c16b380fSderaadt 133c16b380fSderaadt /* Register cleanup function. */ 134c16b380fSderaadt if (atexit(cleanup)) 135c16b380fSderaadt err(1, "can't register cleanup function"); 136c16b380fSderaadt 137c16b380fSderaadt /* Find the specified command. */ 138c16b380fSderaadt for (i = 0; commands[i].cc_name != NULL; ++i) 139c16b380fSderaadt if (strcmp(*argv, commands[i].cc_name) == 0) 140c16b380fSderaadt break; 141b13cd761Sderaadt if (commands[i].cc_name == NULL) { 142b13cd761Sderaadt /* look for abbreviation */ 143b13cd761Sderaadt for (i = 0; commands[i].cc_name != NULL; ++i) 144b13cd761Sderaadt if (strncmp(*argv, commands[i].cc_name, 145b13cd761Sderaadt strlen(*argv)) == 0) 146b13cd761Sderaadt break; 147b13cd761Sderaadt } 148c16b380fSderaadt if (commands[i].cc_name == NULL) 149c16b380fSderaadt errx(1, "unknown command: %s", *argv); 150c16b380fSderaadt 151c16b380fSderaadt /* Skip over the command name and call handler. */ 152c16b380fSderaadt ++argv; --argc; 153c16b380fSderaadt exit ((*commands[i].cc_handler)(commands[i].cc_name, argc, argv)); 154c16b380fSderaadt } 155c16b380fSderaadt 156c16b380fSderaadt static int 157c16b380fSderaadt do_move(cname, argc, argv) 158c16b380fSderaadt char *cname; 159c16b380fSderaadt int argc; 160c16b380fSderaadt char **argv; 161c16b380fSderaadt { 162c16b380fSderaadt struct changer_move cmd; 163c16b380fSderaadt int val; 164c16b380fSderaadt 165c16b380fSderaadt /* 166c16b380fSderaadt * On a move command, we expect the following: 167c16b380fSderaadt * 168c16b380fSderaadt * <from ET> <from EU> <to ET> <to EU> [inv] 169c16b380fSderaadt * 170c16b380fSderaadt * where ET == element type and EU == element unit. 171c16b380fSderaadt */ 172c16b380fSderaadt if (argc < 4) { 173c16b380fSderaadt warnx("%s: too few arguments", cname); 174c16b380fSderaadt goto usage; 175c16b380fSderaadt } else if (argc > 5) { 176c16b380fSderaadt warnx("%s: too many arguments", cname); 177c16b380fSderaadt goto usage; 178c16b380fSderaadt } 179c16b380fSderaadt bzero(&cmd, sizeof(cmd)); 180c16b380fSderaadt 181c16b380fSderaadt /* <from ET> */ 182c16b380fSderaadt cmd.cm_fromtype = parse_element_type(*argv); 183c16b380fSderaadt ++argv; --argc; 184c16b380fSderaadt 185c16b380fSderaadt /* <from EU> */ 186c16b380fSderaadt cmd.cm_fromunit = parse_element_unit(*argv); 187c16b380fSderaadt ++argv; --argc; 188c16b380fSderaadt 189c16b380fSderaadt /* <to ET> */ 190c16b380fSderaadt cmd.cm_totype = parse_element_type(*argv); 191c16b380fSderaadt ++argv; --argc; 192c16b380fSderaadt 193c16b380fSderaadt /* <to EU> */ 194c16b380fSderaadt cmd.cm_tounit = parse_element_unit(*argv); 195c16b380fSderaadt ++argv; --argc; 196c16b380fSderaadt 197c16b380fSderaadt /* Deal with optional command modifier. */ 198c16b380fSderaadt if (argc) { 199c16b380fSderaadt val = parse_special(*argv); 200c16b380fSderaadt switch (val) { 201c16b380fSderaadt case SW_INVERT: 202c16b380fSderaadt cmd.cm_flags |= CM_INVERT; 203c16b380fSderaadt break; 204c16b380fSderaadt 205c16b380fSderaadt default: 206c16b380fSderaadt errx(1, "%s: inappropriate modifier `%s'", 207c16b380fSderaadt cname, *argv); 208c16b380fSderaadt /* NOTREACHED */ 209c16b380fSderaadt } 210c16b380fSderaadt } 211c16b380fSderaadt 212c16b380fSderaadt /* Send command to changer. */ 213c16b380fSderaadt if (ioctl(changer_fd, CHIOMOVE, (char *)&cmd)) 214c16b380fSderaadt err(1, "%s: CHIOMOVE", changer_name); 215c16b380fSderaadt 216c16b380fSderaadt return (0); 217c16b380fSderaadt 218c16b380fSderaadt usage: 219c16b380fSderaadt fprintf(stderr, "usage: %s %s " 220c16b380fSderaadt "<from ET> <from EU> <to ET> <to EU> [inv]\n", __progname, cname); 221c16b380fSderaadt return (1); 222c16b380fSderaadt } 223c16b380fSderaadt 224c16b380fSderaadt static int 225c16b380fSderaadt do_exchange(cname, argc, argv) 226c16b380fSderaadt char *cname; 227c16b380fSderaadt int argc; 228c16b380fSderaadt char **argv; 229c16b380fSderaadt { 230c16b380fSderaadt struct changer_exchange cmd; 231c16b380fSderaadt int val; 232c16b380fSderaadt 233c16b380fSderaadt /* 234c16b380fSderaadt * On an exchange command, we expect the following: 235c16b380fSderaadt * 236c16b380fSderaadt * <src ET> <src EU> <dst1 ET> <dst1 EU> [<dst2 ET> <dst2 EU>] [inv1] [inv2] 237c16b380fSderaadt * 238c16b380fSderaadt * where ET == element type and EU == element unit. 239c16b380fSderaadt */ 240c16b380fSderaadt if (argc < 4) { 241c16b380fSderaadt warnx("%s: too few arguments", cname); 242c16b380fSderaadt goto usage; 243c16b380fSderaadt } else if (argc > 8) { 244c16b380fSderaadt warnx("%s: too many arguments", cname); 245c16b380fSderaadt goto usage; 246c16b380fSderaadt } 247c16b380fSderaadt bzero(&cmd, sizeof(cmd)); 248c16b380fSderaadt 249c16b380fSderaadt /* <src ET> */ 250c16b380fSderaadt cmd.ce_srctype = parse_element_type(*argv); 251c16b380fSderaadt ++argv; --argc; 252c16b380fSderaadt 253c16b380fSderaadt /* <src EU> */ 254c16b380fSderaadt cmd.ce_srcunit = parse_element_unit(*argv); 255c16b380fSderaadt ++argv; --argc; 256c16b380fSderaadt 257c16b380fSderaadt /* <dst1 ET> */ 258c16b380fSderaadt cmd.ce_fdsttype = parse_element_type(*argv); 259c16b380fSderaadt ++argv; --argc; 260c16b380fSderaadt 261c16b380fSderaadt /* <dst1 EU> */ 262c16b380fSderaadt cmd.ce_fdstunit = parse_element_unit(*argv); 263c16b380fSderaadt ++argv; --argc; 264c16b380fSderaadt 265c16b380fSderaadt /* 266c16b380fSderaadt * If the next token is a special word or there are no more 267c16b380fSderaadt * arguments, then this is a case of simple exchange. 268c16b380fSderaadt * dst2 == src. 269c16b380fSderaadt */ 270c16b380fSderaadt if ((argc == 0) || is_special(*argv)) { 271c16b380fSderaadt cmd.ce_sdsttype = cmd.ce_srctype; 272c16b380fSderaadt cmd.ce_sdstunit = cmd.ce_srcunit; 273c16b380fSderaadt goto do_special; 274c16b380fSderaadt } 275c16b380fSderaadt 276c16b380fSderaadt /* <dst2 ET> */ 277c16b380fSderaadt cmd.ce_sdsttype = parse_element_type(*argv); 278c16b380fSderaadt ++argv; --argc; 279c16b380fSderaadt 280c16b380fSderaadt /* <dst2 EU> */ 281c16b380fSderaadt cmd.ce_sdstunit = parse_element_unit(*argv); 282c16b380fSderaadt ++argv; --argc; 283c16b380fSderaadt 284c16b380fSderaadt do_special: 285c16b380fSderaadt /* Deal with optional command modifiers. */ 286c16b380fSderaadt while (argc) { 287c16b380fSderaadt val = parse_special(*argv); 288c16b380fSderaadt ++argv; --argc; 289c16b380fSderaadt switch (val) { 290c16b380fSderaadt case SW_INVERT1: 291c16b380fSderaadt cmd.ce_flags |= CE_INVERT1; 292c16b380fSderaadt break; 293c16b380fSderaadt 294c16b380fSderaadt case SW_INVERT2: 295c16b380fSderaadt cmd.ce_flags |= CE_INVERT2; 296c16b380fSderaadt break; 297c16b380fSderaadt 298c16b380fSderaadt default: 299c16b380fSderaadt errx(1, "%s: inappropriate modifier `%s'", 300c16b380fSderaadt cname, *argv); 301c16b380fSderaadt /* NOTREACHED */ 302c16b380fSderaadt } 303c16b380fSderaadt } 304c16b380fSderaadt 305c16b380fSderaadt /* Send command to changer. */ 306c16b380fSderaadt if (ioctl(changer_fd, CHIOEXCHANGE, (char *)&cmd)) 307c16b380fSderaadt err(1, "%s: CHIOEXCHANGE", changer_name); 308c16b380fSderaadt 309c16b380fSderaadt return (0); 310c16b380fSderaadt 311c16b380fSderaadt usage: 312c16b380fSderaadt fprintf(stderr, "usage: %s %s <src ET> <src EU> <dst1 ET> <dst1 EU>\n" 313c16b380fSderaadt " [<dst2 ET> <dst2 EU>] [inv1] [inv2]\n", 314c16b380fSderaadt __progname, cname); 315c16b380fSderaadt return (1); 316c16b380fSderaadt } 317c16b380fSderaadt 318c16b380fSderaadt static int 319c16b380fSderaadt do_position(cname, argc, argv) 320c16b380fSderaadt char *cname; 321c16b380fSderaadt int argc; 322c16b380fSderaadt char **argv; 323c16b380fSderaadt { 324c16b380fSderaadt struct changer_position cmd; 325c16b380fSderaadt int val; 326c16b380fSderaadt 327c16b380fSderaadt /* 328c16b380fSderaadt * On a position command, we expect the following: 329c16b380fSderaadt * 330c16b380fSderaadt * <to ET> <to EU> [inv] 331c16b380fSderaadt * 332c16b380fSderaadt * where ET == element type and EU == element unit. 333c16b380fSderaadt */ 334c16b380fSderaadt if (argc < 2) { 335c16b380fSderaadt warnx("%s: too few arguments", cname); 336c16b380fSderaadt goto usage; 337c16b380fSderaadt } else if (argc > 3) { 338c16b380fSderaadt warnx("%s: too many arguments", cname); 339c16b380fSderaadt goto usage; 340c16b380fSderaadt } 341c16b380fSderaadt bzero(&cmd, sizeof(cmd)); 342c16b380fSderaadt 343c16b380fSderaadt /* <to ET> */ 344c16b380fSderaadt cmd.cp_type = parse_element_type(*argv); 345c16b380fSderaadt ++argv; --argc; 346c16b380fSderaadt 347c16b380fSderaadt /* <to EU> */ 348c16b380fSderaadt cmd.cp_unit = parse_element_unit(*argv); 349c16b380fSderaadt ++argv; --argc; 350c16b380fSderaadt 351c16b380fSderaadt /* Deal with optional command modifier. */ 352c16b380fSderaadt if (argc) { 353c16b380fSderaadt val = parse_special(*argv); 354c16b380fSderaadt switch (val) { 355c16b380fSderaadt case SW_INVERT: 356c16b380fSderaadt cmd.cp_flags |= CP_INVERT; 357c16b380fSderaadt break; 358c16b380fSderaadt 359c16b380fSderaadt default: 360c16b380fSderaadt errx(1, "%s: inappropriate modifier `%s'", 361c16b380fSderaadt cname, *argv); 362c16b380fSderaadt /* NOTREACHED */ 363c16b380fSderaadt } 364c16b380fSderaadt } 365c16b380fSderaadt 366c16b380fSderaadt /* Send command to changer. */ 367c16b380fSderaadt if (ioctl(changer_fd, CHIOPOSITION, (char *)&cmd)) 368c16b380fSderaadt err(1, "%s: CHIOPOSITION", changer_name); 369c16b380fSderaadt 370c16b380fSderaadt return (0); 371c16b380fSderaadt 372c16b380fSderaadt usage: 373c16b380fSderaadt fprintf(stderr, "usage: %s %s <to ET> <to EU> [inv]\n", 374c16b380fSderaadt __progname, cname); 375c16b380fSderaadt return (1); 376c16b380fSderaadt } 377c16b380fSderaadt 378c16b380fSderaadt static int 379c16b380fSderaadt do_params(cname, argc, argv) 380c16b380fSderaadt char *cname; 381c16b380fSderaadt int argc; 382c16b380fSderaadt char **argv; 383c16b380fSderaadt { 384c16b380fSderaadt struct changer_params data; 385c16b380fSderaadt 386c16b380fSderaadt /* No arguments to this command. */ 387c16b380fSderaadt if (argc) { 388d9248734Stodd warnx("%s: no arguments expected", cname); 389c16b380fSderaadt goto usage; 390c16b380fSderaadt } 391c16b380fSderaadt 392c16b380fSderaadt /* Get params from changer and display them. */ 393c16b380fSderaadt bzero(&data, sizeof(data)); 394c16b380fSderaadt if (ioctl(changer_fd, CHIOGPARAMS, (char *)&data)) 395c16b380fSderaadt err(1, "%s: CHIOGPARAMS", changer_name); 396c16b380fSderaadt 397c16b380fSderaadt printf("%s: %d slot%s, %d drive%s, %d picker%s", 398c16b380fSderaadt changer_name, 399c16b380fSderaadt data.cp_nslots, (data.cp_nslots > 1) ? "s" : "", 400c16b380fSderaadt data.cp_ndrives, (data.cp_ndrives > 1) ? "s" : "", 401c16b380fSderaadt data.cp_npickers, (data.cp_npickers > 1) ? "s" : ""); 402c16b380fSderaadt if (data.cp_nportals) 403c16b380fSderaadt printf(", %d portal%s", data.cp_nportals, 404c16b380fSderaadt (data.cp_nportals > 1) ? "s" : ""); 405c16b380fSderaadt printf("\n%s: current picker: %d\n", changer_name, data.cp_curpicker); 406c16b380fSderaadt 407c16b380fSderaadt return (0); 408c16b380fSderaadt 409c16b380fSderaadt usage: 410c16b380fSderaadt fprintf(stderr, "usage: %s %s\n", __progname, cname); 411c16b380fSderaadt return (1); 412c16b380fSderaadt } 413c16b380fSderaadt 414c16b380fSderaadt static int 415c16b380fSderaadt do_getpicker(cname, argc, argv) 416c16b380fSderaadt char *cname; 417c16b380fSderaadt int argc; 418c16b380fSderaadt char **argv; 419c16b380fSderaadt { 420c16b380fSderaadt int picker; 421c16b380fSderaadt 422c16b380fSderaadt /* No arguments to this command. */ 423c16b380fSderaadt if (argc) { 424c16b380fSderaadt warnx("%s: no arguments expected", cname); 425c16b380fSderaadt goto usage; 426c16b380fSderaadt } 427c16b380fSderaadt 428c16b380fSderaadt /* Get current picker from changer and display it. */ 429c16b380fSderaadt if (ioctl(changer_fd, CHIOGPICKER, (char *)&picker)) 430c16b380fSderaadt err(1, "%s: CHIOGPICKER", changer_name); 431c16b380fSderaadt 432c16b380fSderaadt printf("%s: current picker: %d\n", changer_name, picker); 433c16b380fSderaadt 434c16b380fSderaadt return (0); 435c16b380fSderaadt 436c16b380fSderaadt usage: 437c16b380fSderaadt fprintf(stderr, "usage: %s %s\n", __progname, cname); 438c16b380fSderaadt return (1); 439c16b380fSderaadt } 440c16b380fSderaadt 441c16b380fSderaadt static int 442c16b380fSderaadt do_setpicker(cname, argc, argv) 443c16b380fSderaadt char *cname; 444c16b380fSderaadt int argc; 445c16b380fSderaadt char **argv; 446c16b380fSderaadt { 447c16b380fSderaadt int picker; 448c16b380fSderaadt 449c16b380fSderaadt if (argc < 1) { 450c16b380fSderaadt warnx("%s: too few arguments", cname); 451c16b380fSderaadt goto usage; 452c16b380fSderaadt } else if (argc > 1) { 453c16b380fSderaadt warnx("%s: too many arguments", cname); 454c16b380fSderaadt goto usage; 455c16b380fSderaadt } 456c16b380fSderaadt 457c16b380fSderaadt picker = parse_element_unit(*argv); 458c16b380fSderaadt 459c16b380fSderaadt /* Set the changer picker. */ 460c16b380fSderaadt if (ioctl(changer_fd, CHIOSPICKER, (char *)&picker)) 461c16b380fSderaadt err(1, "%s: CHIOSPICKER", changer_name); 462c16b380fSderaadt 463c16b380fSderaadt return (0); 464c16b380fSderaadt 465c16b380fSderaadt usage: 466c16b380fSderaadt fprintf(stderr, "usage: %s %s <picker>\n", __progname, cname); 467c16b380fSderaadt return (1); 468c16b380fSderaadt } 469c16b380fSderaadt 470c16b380fSderaadt static int 471c16b380fSderaadt do_status(cname, argc, argv) 472c16b380fSderaadt char *cname; 473c16b380fSderaadt int argc; 474c16b380fSderaadt char **argv; 475c16b380fSderaadt { 476c16b380fSderaadt struct changer_element_status cmd; 477c16b380fSderaadt struct changer_params data; 478c16b380fSderaadt u_int8_t *statusp; 479c16b380fSderaadt int i, count, chet, schet, echet; 480764064c4Smickey char *description; 481764064c4Smickey 482764064c4Smickey #ifdef lint 483764064c4Smickey count = 0; 484764064c4Smickey description = NULL; 485764064c4Smickey #endif 486c16b380fSderaadt 487c16b380fSderaadt /* 488c16b380fSderaadt * On a status command, we expect the following: 489c16b380fSderaadt * 490c16b380fSderaadt * [<ET>] 491c16b380fSderaadt * 492c16b380fSderaadt * where ET == element type. 493c16b380fSderaadt * 494c16b380fSderaadt * If we get no arguments, we get the status of all 495c16b380fSderaadt * known element types. 496c16b380fSderaadt */ 497c16b380fSderaadt if (argc > 1) { 498c16b380fSderaadt warnx("%s: too many arguments", cname); 499c16b380fSderaadt goto usage; 500c16b380fSderaadt } 501c16b380fSderaadt 502c16b380fSderaadt /* 503c16b380fSderaadt * Get params from changer. Specifically, we need the element 504c16b380fSderaadt * counts. 505c16b380fSderaadt */ 506c16b380fSderaadt bzero(&data, sizeof(data)); 507c16b380fSderaadt if (ioctl(changer_fd, CHIOGPARAMS, (char *)&data)) 508c16b380fSderaadt err(1, "%s: CHIOGPARAMS", changer_name); 509c16b380fSderaadt 510c16b380fSderaadt if (argc) 511c16b380fSderaadt schet = echet = parse_element_type(*argv); 512c16b380fSderaadt else { 513c16b380fSderaadt schet = CHET_MT; 514c16b380fSderaadt echet = CHET_DT; 515c16b380fSderaadt } 516c16b380fSderaadt 517c16b380fSderaadt for (chet = schet; chet <= echet; ++chet) { 518c16b380fSderaadt switch (chet) { 519c16b380fSderaadt case CHET_MT: 520c16b380fSderaadt count = data.cp_npickers; 521c16b380fSderaadt description = "picker"; 522c16b380fSderaadt break; 523c16b380fSderaadt 524c16b380fSderaadt case CHET_ST: 525c16b380fSderaadt count = data.cp_nslots; 526c16b380fSderaadt description = "slot"; 527c16b380fSderaadt break; 528c16b380fSderaadt 529c16b380fSderaadt case CHET_IE: 530c16b380fSderaadt count = data.cp_nportals; 531c16b380fSderaadt description = "portal"; 532c16b380fSderaadt break; 533c16b380fSderaadt 534c16b380fSderaadt case CHET_DT: 535c16b380fSderaadt count = data.cp_ndrives; 536c16b380fSderaadt description = "drive"; 537c16b380fSderaadt break; 538c16b380fSderaadt } 539c16b380fSderaadt 540c16b380fSderaadt if (count == 0) { 541c16b380fSderaadt if (argc == 0) 542c16b380fSderaadt continue; 543c16b380fSderaadt else { 544c16b380fSderaadt printf("%s: no %s elements\n", 545c16b380fSderaadt changer_name, description); 546c16b380fSderaadt return (0); 547c16b380fSderaadt } 548c16b380fSderaadt } 549c16b380fSderaadt 550c16b380fSderaadt /* Allocate storage for the status bytes. */ 551c16b380fSderaadt if ((statusp = (u_int8_t *)malloc(count)) == NULL) 552c16b380fSderaadt errx(1, "can't allocate status storage"); 553c16b380fSderaadt 554c16b380fSderaadt bzero(statusp, count); 555c16b380fSderaadt bzero(&cmd, sizeof(cmd)); 556c16b380fSderaadt 557c16b380fSderaadt cmd.ces_type = chet; 558c16b380fSderaadt cmd.ces_data = statusp; 559c16b380fSderaadt 560c16b380fSderaadt if (ioctl(changer_fd, CHIOGSTATUS, (char *)&cmd)) { 561c16b380fSderaadt free(statusp); 562c16b380fSderaadt err(1, "%s: CHIOGSTATUS", changer_name); 563c16b380fSderaadt } 564c16b380fSderaadt 565c16b380fSderaadt /* Dump the status for each element of this type. */ 566c16b380fSderaadt for (i = 0; i < count; ++i) { 567c16b380fSderaadt printf("%s %d: %s\n", description, i, 568c16b380fSderaadt bits_to_string(statusp[i], CESTATUS_BITS)); 569c16b380fSderaadt } 570c16b380fSderaadt 571c16b380fSderaadt free(statusp); 572c16b380fSderaadt } 573c16b380fSderaadt 574c16b380fSderaadt return (0); 575c16b380fSderaadt 576c16b380fSderaadt usage: 577c16b380fSderaadt fprintf(stderr, "usage: %s %s [<element type>]\n", __progname, 578c16b380fSderaadt cname); 579c16b380fSderaadt return (1); 580c16b380fSderaadt } 581c16b380fSderaadt 582c16b380fSderaadt static int 583c16b380fSderaadt parse_element_type(cp) 584c16b380fSderaadt char *cp; 585c16b380fSderaadt { 586c16b380fSderaadt int i; 587c16b380fSderaadt 588c16b380fSderaadt for (i = 0; elements[i].et_name != NULL; ++i) 589c16b380fSderaadt if (strcmp(elements[i].et_name, cp) == 0) 590c16b380fSderaadt return (elements[i].et_type); 591c16b380fSderaadt 592c16b380fSderaadt errx(1, "invalid element type `%s'", cp); 593c16b380fSderaadt } 594c16b380fSderaadt 595c16b380fSderaadt static int 596c16b380fSderaadt parse_element_unit(cp) 597c16b380fSderaadt char *cp; 598c16b380fSderaadt { 599c16b380fSderaadt int i; 600c16b380fSderaadt char *p; 601c16b380fSderaadt 602c16b380fSderaadt i = (int)strtol(cp, &p, 10); 603c16b380fSderaadt if ((i < 0) || (*p != '\0')) 604c16b380fSderaadt errx(1, "invalid unit number `%s'", cp); 605c16b380fSderaadt 606c16b380fSderaadt return (i); 607c16b380fSderaadt } 608c16b380fSderaadt 609c16b380fSderaadt static int 610c16b380fSderaadt parse_special(cp) 611c16b380fSderaadt char *cp; 612c16b380fSderaadt { 613c16b380fSderaadt int val; 614c16b380fSderaadt 615c16b380fSderaadt val = is_special(cp); 616c16b380fSderaadt if (val) 617c16b380fSderaadt return (val); 618c16b380fSderaadt 619c16b380fSderaadt errx(1, "invalid modifier `%s'", cp); 620c16b380fSderaadt } 621c16b380fSderaadt 622c16b380fSderaadt static int 623c16b380fSderaadt is_special(cp) 624c16b380fSderaadt char *cp; 625c16b380fSderaadt { 626c16b380fSderaadt int i; 627c16b380fSderaadt 628c16b380fSderaadt for (i = 0; specials[i].sw_name != NULL; ++i) 629c16b380fSderaadt if (strcmp(specials[i].sw_name, cp) == 0) 630c16b380fSderaadt return (specials[i].sw_value); 631c16b380fSderaadt 632c16b380fSderaadt return (0); 633c16b380fSderaadt } 634c16b380fSderaadt 635c16b380fSderaadt static char * 636c16b380fSderaadt bits_to_string(v, cp) 637c16b380fSderaadt int v; 638c16b380fSderaadt const char *cp; 639c16b380fSderaadt { 640c16b380fSderaadt const char *np; 641c16b380fSderaadt char f, sep, *bp; 642c16b380fSderaadt static char buf[128]; 643c16b380fSderaadt 644c16b380fSderaadt bp = buf; 645c16b380fSderaadt bzero(buf, sizeof(buf)); 646c16b380fSderaadt 647c16b380fSderaadt for (sep = '<'; (f = *cp++) != 0; cp = np) { 648c16b380fSderaadt for (np = cp; *np >= ' ';) 649c16b380fSderaadt np++; 650c16b380fSderaadt if ((v & (1 << (f - 1))) == 0) 651c16b380fSderaadt continue; 6522f61c7c6Smillert (void)snprintf(bp, sizeof(buf) - (bp - &buf[0]), 653707c1213Sart "%c%.*s", sep, (int)(np - cp), cp); 6542f61c7c6Smillert bp += strlen(bp); 655c16b380fSderaadt sep = ','; 656c16b380fSderaadt } 657c16b380fSderaadt if (sep != '<') 658c16b380fSderaadt *bp = '>'; 659c16b380fSderaadt 660c16b380fSderaadt return (buf); 661c16b380fSderaadt } 662c16b380fSderaadt 663c16b380fSderaadt static void 664c16b380fSderaadt cleanup() 665c16b380fSderaadt { 666c16b380fSderaadt 667c16b380fSderaadt /* Simple enough... */ 668c16b380fSderaadt (void)close(changer_fd); 669c16b380fSderaadt } 670c16b380fSderaadt 671c16b380fSderaadt static void 672c16b380fSderaadt usage() 673c16b380fSderaadt { 674b13cd761Sderaadt int i; 675c16b380fSderaadt 676b13cd761Sderaadt fprintf(stderr, "usage: %s [-f device] command [args ...]\n", 677b13cd761Sderaadt __progname); 678b13cd761Sderaadt fprintf(stderr, "commands:"); 679b13cd761Sderaadt for (i = 0; commands[i].cc_name; i++) 680b13cd761Sderaadt fprintf(stderr, " %s", commands[i].cc_name); 681b13cd761Sderaadt fprintf(stderr, "\n"); 682c16b380fSderaadt exit(1); 683c16b380fSderaadt } 684