chio.c revision 23449
123449Sjoerg/* $Id: $ */ 223449Sjoerg 323449Sjoerg/* 423449Sjoerg * Copyright (c) 1996 Jason R. Thorpe <thorpej@and.com> 523449Sjoerg * All rights reserved. 623449Sjoerg * 723449Sjoerg * Redistribution and use in source and binary forms, with or without 823449Sjoerg * modification, are permitted provided that the following conditions 923449Sjoerg * are met: 1023449Sjoerg * 1. Redistributions of source code must retain the above copyright 1123449Sjoerg * notice, this list of conditions and the following disclaimer. 1223449Sjoerg * 2. Redistributions in binary form must reproduce the above copyright 1323449Sjoerg * notice, this list of conditions and the following disclaimer in the 1423449Sjoerg * documentation and/or other materials provided with the distribution. 1523449Sjoerg * 3. All advertising materials mentioning features or use of this software 1623449Sjoerg * must display the following acknowledgements: 1723449Sjoerg * This product includes software developed by Jason R. Thorpe 1823449Sjoerg * for And Communications, http://www.and.com/ 1923449Sjoerg * 4. The name of the author may not be used to endorse or promote products 2023449Sjoerg * derived from this software without specific prior written permission. 2123449Sjoerg * 2223449Sjoerg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2323449Sjoerg * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2423449Sjoerg * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2523449Sjoerg * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2623449Sjoerg * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 2723449Sjoerg * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 2823449Sjoerg * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 2923449Sjoerg * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 3023449Sjoerg * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3123449Sjoerg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3223449Sjoerg * SUCH DAMAGE. 3323449Sjoerg */ 3423449Sjoerg 3523449Sjoerg#include <sys/param.h> 3623449Sjoerg#include <sys/ioctl.h> 3723449Sjoerg#include <sys/chio.h> 3823449Sjoerg#include <err.h> 3923449Sjoerg#include <errno.h> 4023449Sjoerg#include <fcntl.h> 4123449Sjoerg#include <limits.h> 4223449Sjoerg#include <stdio.h> 4323449Sjoerg#include <stdlib.h> 4423449Sjoerg#include <string.h> 4523449Sjoerg#include <unistd.h> 4623449Sjoerg 4723449Sjoerg#include "defs.h" 4823449Sjoerg#include "pathnames.h" 4923449Sjoerg 5023449Sjoergextern char *__progname; /* from crt0.o */ 5123449Sjoerg 5223449Sjoergstatic void usage __P((void)); 5323449Sjoergstatic void cleanup __P((void)); 5423449Sjoergstatic int parse_element_type __P((char *)); 5523449Sjoergstatic int parse_element_unit __P((char *)); 5623449Sjoergstatic int parse_special __P((char *)); 5723449Sjoergstatic int is_special __P((char *)); 5823449Sjoergstatic char *bits_to_string __P((int, const char *)); 5923449Sjoerg 6023449Sjoergstatic int do_move __P((char *, int, char **)); 6123449Sjoergstatic int do_exchange __P((char *, int, char **)); 6223449Sjoergstatic int do_position __P((char *, int, char **)); 6323449Sjoergstatic int do_params __P((char *, int, char **)); 6423449Sjoergstatic int do_getpicker __P((char *, int, char **)); 6523449Sjoergstatic int do_setpicker __P((char *, int, char **)); 6623449Sjoergstatic int do_status __P((char *, int, char **)); 6723449Sjoerg 6823449Sjoerg/* Valid changer element types. */ 6923449Sjoergconst struct element_type elements[] = { 7023449Sjoerg { "picker", CHET_MT }, 7123449Sjoerg { "slot", CHET_ST }, 7223449Sjoerg { "portal", CHET_IE }, 7323449Sjoerg { "drive", CHET_DT }, 7423449Sjoerg { NULL, 0 }, 7523449Sjoerg}; 7623449Sjoerg 7723449Sjoerg/* Valid commands. */ 7823449Sjoergconst struct changer_command commands[] = { 7923449Sjoerg { "move", do_move }, 8023449Sjoerg { "exchange", do_exchange }, 8123449Sjoerg { "position", do_position }, 8223449Sjoerg { "params", do_params }, 8323449Sjoerg { "getpicker", do_getpicker }, 8423449Sjoerg { "setpicker", do_setpicker }, 8523449Sjoerg { "status", do_status }, 8623449Sjoerg { NULL, 0 }, 8723449Sjoerg}; 8823449Sjoerg 8923449Sjoerg/* Valid special words. */ 9023449Sjoergconst struct special_word specials[] = { 9123449Sjoerg { "inv", SW_INVERT }, 9223449Sjoerg { "inv1", SW_INVERT1 }, 9323449Sjoerg { "inv2", SW_INVERT2 }, 9423449Sjoerg { NULL, 0 }, 9523449Sjoerg}; 9623449Sjoerg 9723449Sjoergstatic int changer_fd; 9823449Sjoergstatic char *changer_name; 9923449Sjoerg 10023449Sjoergint 10123449Sjoergmain(argc, argv) 10223449Sjoerg int argc; 10323449Sjoerg char **argv; 10423449Sjoerg{ 10523449Sjoerg int ch, i; 10623449Sjoerg char *cp; 10723449Sjoerg 10823449Sjoerg while ((ch = getopt(argc, argv, "f:")) != -1) { 10923449Sjoerg switch (ch) { 11023449Sjoerg case 'f': 11123449Sjoerg changer_name = optarg; 11223449Sjoerg break; 11323449Sjoerg 11423449Sjoerg default: 11523449Sjoerg usage(); 11623449Sjoerg } 11723449Sjoerg } 11823449Sjoerg argc -= optind; 11923449Sjoerg argv += optind; 12023449Sjoerg 12123449Sjoerg if (argc == 0) 12223449Sjoerg usage(); 12323449Sjoerg 12423449Sjoerg /* Get the default changer if not already specified. */ 12523449Sjoerg if (changer_name == NULL) 12623449Sjoerg if ((changer_name = getenv(CHANGER_ENV_VAR)) == NULL) 12723449Sjoerg changer_name = _PATH_CH; 12823449Sjoerg 12923449Sjoerg /* Open the changer device. */ 13023449Sjoerg if ((changer_fd = open(changer_name, O_RDWR, 0600)) == -1) 13123449Sjoerg err(1, "%s: open", changer_name); 13223449Sjoerg 13323449Sjoerg /* Register cleanup function. */ 13423449Sjoerg if (atexit(cleanup)) 13523449Sjoerg err(1, "can't register cleanup function"); 13623449Sjoerg 13723449Sjoerg /* Find the specified command. */ 13823449Sjoerg for (i = 0; commands[i].cc_name != NULL; ++i) 13923449Sjoerg if (strcmp(*argv, commands[i].cc_name) == 0) 14023449Sjoerg break; 14123449Sjoerg if (commands[i].cc_name == NULL) 14223449Sjoerg errx(1, "unknown command: %s", *argv); 14323449Sjoerg 14423449Sjoerg /* Skip over the command name and call handler. */ 14523449Sjoerg ++argv; --argc; 14623449Sjoerg exit ((*commands[i].cc_handler)(commands[i].cc_name, argc, argv)); 14723449Sjoerg} 14823449Sjoerg 14923449Sjoergstatic int 15023449Sjoergdo_move(cname, argc, argv) 15123449Sjoerg char *cname; 15223449Sjoerg int argc; 15323449Sjoerg char **argv; 15423449Sjoerg{ 15523449Sjoerg struct changer_move cmd; 15623449Sjoerg int val; 15723449Sjoerg 15823449Sjoerg /* 15923449Sjoerg * On a move command, we expect the following: 16023449Sjoerg * 16123449Sjoerg * <from ET> <from EU> <to ET> <to EU> [inv] 16223449Sjoerg * 16323449Sjoerg * where ET == element type and EU == element unit. 16423449Sjoerg */ 16523449Sjoerg if (argc < 4) { 16623449Sjoerg warnx("%s: too few arguments", cname); 16723449Sjoerg goto usage; 16823449Sjoerg } else if (argc > 5) { 16923449Sjoerg warnx("%s: too many arguments", cname); 17023449Sjoerg goto usage; 17123449Sjoerg } 17223449Sjoerg bzero(&cmd, sizeof(cmd)); 17323449Sjoerg 17423449Sjoerg /* <from ET> */ 17523449Sjoerg cmd.cm_fromtype = parse_element_type(*argv); 17623449Sjoerg ++argv; --argc; 17723449Sjoerg 17823449Sjoerg /* <from EU> */ 17923449Sjoerg cmd.cm_fromunit = parse_element_unit(*argv); 18023449Sjoerg ++argv; --argc; 18123449Sjoerg 18223449Sjoerg /* <to ET> */ 18323449Sjoerg cmd.cm_totype = parse_element_type(*argv); 18423449Sjoerg ++argv; --argc; 18523449Sjoerg 18623449Sjoerg /* <to EU> */ 18723449Sjoerg cmd.cm_tounit = parse_element_unit(*argv); 18823449Sjoerg ++argv; --argc; 18923449Sjoerg 19023449Sjoerg /* Deal with optional command modifier. */ 19123449Sjoerg if (argc) { 19223449Sjoerg val = parse_special(*argv); 19323449Sjoerg switch (val) { 19423449Sjoerg case SW_INVERT: 19523449Sjoerg cmd.cm_flags |= CM_INVERT; 19623449Sjoerg break; 19723449Sjoerg 19823449Sjoerg default: 19923449Sjoerg errx(1, "%s: inappropriate modifier `%s'", 20023449Sjoerg cname, *argv); 20123449Sjoerg /* NOTREACHED */ 20223449Sjoerg } 20323449Sjoerg } 20423449Sjoerg 20523449Sjoerg /* Send command to changer. */ 20623449Sjoerg if (ioctl(changer_fd, CHIOMOVE, (char *)&cmd)) 20723449Sjoerg err(1, "%s: CHIOMOVE", changer_name); 20823449Sjoerg 20923449Sjoerg return (0); 21023449Sjoerg 21123449Sjoerg usage: 21223449Sjoerg fprintf(stderr, "usage: %s %s " 21323449Sjoerg "<from ET> <from EU> <to ET> <to EU> [inv]\n", __progname, cname); 21423449Sjoerg return (1); 21523449Sjoerg} 21623449Sjoerg 21723449Sjoergstatic int 21823449Sjoergdo_exchange(cname, argc, argv) 21923449Sjoerg char *cname; 22023449Sjoerg int argc; 22123449Sjoerg char **argv; 22223449Sjoerg{ 22323449Sjoerg struct changer_exchange cmd; 22423449Sjoerg int val; 22523449Sjoerg 22623449Sjoerg /* 22723449Sjoerg * On an exchange command, we expect the following: 22823449Sjoerg * 22923449Sjoerg * <src ET> <src EU> <dst1 ET> <dst1 EU> [<dst2 ET> <dst2 EU>] [inv1] [inv2] 23023449Sjoerg * 23123449Sjoerg * where ET == element type and EU == element unit. 23223449Sjoerg */ 23323449Sjoerg if (argc < 4) { 23423449Sjoerg warnx("%s: too few arguments", cname); 23523449Sjoerg goto usage; 23623449Sjoerg } else if (argc > 8) { 23723449Sjoerg warnx("%s: too many arguments", cname); 23823449Sjoerg goto usage; 23923449Sjoerg } 24023449Sjoerg bzero(&cmd, sizeof(cmd)); 24123449Sjoerg 24223449Sjoerg /* <src ET> */ 24323449Sjoerg cmd.ce_srctype = parse_element_type(*argv); 24423449Sjoerg ++argv; --argc; 24523449Sjoerg 24623449Sjoerg /* <src EU> */ 24723449Sjoerg cmd.ce_srcunit = parse_element_unit(*argv); 24823449Sjoerg ++argv; --argc; 24923449Sjoerg 25023449Sjoerg /* <dst1 ET> */ 25123449Sjoerg cmd.ce_fdsttype = parse_element_type(*argv); 25223449Sjoerg ++argv; --argc; 25323449Sjoerg 25423449Sjoerg /* <dst1 EU> */ 25523449Sjoerg cmd.ce_fdstunit = parse_element_unit(*argv); 25623449Sjoerg ++argv; --argc; 25723449Sjoerg 25823449Sjoerg /* 25923449Sjoerg * If the next token is a special word or there are no more 26023449Sjoerg * arguments, then this is a case of simple exchange. 26123449Sjoerg * dst2 == src. 26223449Sjoerg */ 26323449Sjoerg if ((argc == 0) || is_special(*argv)) { 26423449Sjoerg cmd.ce_sdsttype = cmd.ce_srctype; 26523449Sjoerg cmd.ce_sdstunit = cmd.ce_srcunit; 26623449Sjoerg goto do_special; 26723449Sjoerg } 26823449Sjoerg 26923449Sjoerg /* <dst2 ET> */ 27023449Sjoerg cmd.ce_sdsttype = parse_element_type(*argv); 27123449Sjoerg ++argv; --argc; 27223449Sjoerg 27323449Sjoerg /* <dst2 EU> */ 27423449Sjoerg cmd.ce_sdstunit = parse_element_unit(*argv); 27523449Sjoerg ++argv; --argc; 27623449Sjoerg 27723449Sjoerg do_special: 27823449Sjoerg /* Deal with optional command modifiers. */ 27923449Sjoerg while (argc) { 28023449Sjoerg val = parse_special(*argv); 28123449Sjoerg ++argv; --argc; 28223449Sjoerg switch (val) { 28323449Sjoerg case SW_INVERT1: 28423449Sjoerg cmd.ce_flags |= CE_INVERT1; 28523449Sjoerg break; 28623449Sjoerg 28723449Sjoerg case SW_INVERT2: 28823449Sjoerg cmd.ce_flags |= CE_INVERT2; 28923449Sjoerg break; 29023449Sjoerg 29123449Sjoerg default: 29223449Sjoerg errx(1, "%s: inappropriate modifier `%s'", 29323449Sjoerg cname, *argv); 29423449Sjoerg /* NOTREACHED */ 29523449Sjoerg } 29623449Sjoerg } 29723449Sjoerg 29823449Sjoerg /* Send command to changer. */ 29923449Sjoerg if (ioctl(changer_fd, CHIOEXCHANGE, (char *)&cmd)) 30023449Sjoerg err(1, "%s: CHIOEXCHANGE", changer_name); 30123449Sjoerg 30223449Sjoerg return (0); 30323449Sjoerg 30423449Sjoerg usage: 30523449Sjoerg fprintf(stderr, "usage: %s %s <src ET> <src EU> <dst1 ET> <dst1 EU>\n" 30623449Sjoerg " [<dst2 ET> <dst2 EU>] [inv1] [inv2]\n", 30723449Sjoerg __progname, cname); 30823449Sjoerg return (1); 30923449Sjoerg} 31023449Sjoerg 31123449Sjoergstatic int 31223449Sjoergdo_position(cname, argc, argv) 31323449Sjoerg char *cname; 31423449Sjoerg int argc; 31523449Sjoerg char **argv; 31623449Sjoerg{ 31723449Sjoerg struct changer_position cmd; 31823449Sjoerg int val; 31923449Sjoerg 32023449Sjoerg /* 32123449Sjoerg * On a position command, we expect the following: 32223449Sjoerg * 32323449Sjoerg * <to ET> <to EU> [inv] 32423449Sjoerg * 32523449Sjoerg * where ET == element type and EU == element unit. 32623449Sjoerg */ 32723449Sjoerg if (argc < 2) { 32823449Sjoerg warnx("%s: too few arguments", cname); 32923449Sjoerg goto usage; 33023449Sjoerg } else if (argc > 3) { 33123449Sjoerg warnx("%s: too many arguments", cname); 33223449Sjoerg goto usage; 33323449Sjoerg } 33423449Sjoerg bzero(&cmd, sizeof(cmd)); 33523449Sjoerg 33623449Sjoerg /* <to ET> */ 33723449Sjoerg cmd.cp_type = parse_element_type(*argv); 33823449Sjoerg ++argv; --argc; 33923449Sjoerg 34023449Sjoerg /* <to EU> */ 34123449Sjoerg cmd.cp_unit = parse_element_unit(*argv); 34223449Sjoerg ++argv; --argc; 34323449Sjoerg 34423449Sjoerg /* Deal with optional command modifier. */ 34523449Sjoerg if (argc) { 34623449Sjoerg val = parse_special(*argv); 34723449Sjoerg switch (val) { 34823449Sjoerg case SW_INVERT: 34923449Sjoerg cmd.cp_flags |= CP_INVERT; 35023449Sjoerg break; 35123449Sjoerg 35223449Sjoerg default: 35323449Sjoerg errx(1, "%s: inappropriate modifier `%s'", 35423449Sjoerg cname, *argv); 35523449Sjoerg /* NOTREACHED */ 35623449Sjoerg } 35723449Sjoerg } 35823449Sjoerg 35923449Sjoerg /* Send command to changer. */ 36023449Sjoerg if (ioctl(changer_fd, CHIOPOSITION, (char *)&cmd)) 36123449Sjoerg err(1, "%s: CHIOPOSITION", changer_name); 36223449Sjoerg 36323449Sjoerg return (0); 36423449Sjoerg 36523449Sjoerg usage: 36623449Sjoerg fprintf(stderr, "usage: %s %s <to ET> <to EU> [inv]\n", 36723449Sjoerg __progname, cname); 36823449Sjoerg return (1); 36923449Sjoerg} 37023449Sjoerg 37123449Sjoergstatic int 37223449Sjoergdo_params(cname, argc, argv) 37323449Sjoerg char *cname; 37423449Sjoerg int argc; 37523449Sjoerg char **argv; 37623449Sjoerg{ 37723449Sjoerg struct changer_params data; 37823449Sjoerg 37923449Sjoerg /* No arguments to this command. */ 38023449Sjoerg if (argc) { 38123449Sjoerg warnx("%s: no arguements expected", cname); 38223449Sjoerg goto usage; 38323449Sjoerg } 38423449Sjoerg 38523449Sjoerg /* Get params from changer and display them. */ 38623449Sjoerg bzero(&data, sizeof(data)); 38723449Sjoerg if (ioctl(changer_fd, CHIOGPARAMS, (char *)&data)) 38823449Sjoerg err(1, "%s: CHIOGPARAMS", changer_name); 38923449Sjoerg 39023449Sjoerg printf("%s: %d slot%s, %d drive%s, %d picker%s", 39123449Sjoerg changer_name, 39223449Sjoerg data.cp_nslots, (data.cp_nslots > 1) ? "s" : "", 39323449Sjoerg data.cp_ndrives, (data.cp_ndrives > 1) ? "s" : "", 39423449Sjoerg data.cp_npickers, (data.cp_npickers > 1) ? "s" : ""); 39523449Sjoerg if (data.cp_nportals) 39623449Sjoerg printf(", %d portal%s", data.cp_nportals, 39723449Sjoerg (data.cp_nportals > 1) ? "s" : ""); 39823449Sjoerg printf("\n%s: current picker: %d\n", changer_name, data.cp_curpicker); 39923449Sjoerg 40023449Sjoerg return (0); 40123449Sjoerg 40223449Sjoerg usage: 40323449Sjoerg fprintf(stderr, "usage: %s %s\n", __progname, cname); 40423449Sjoerg return (1); 40523449Sjoerg} 40623449Sjoerg 40723449Sjoergstatic int 40823449Sjoergdo_getpicker(cname, argc, argv) 40923449Sjoerg char *cname; 41023449Sjoerg int argc; 41123449Sjoerg char **argv; 41223449Sjoerg{ 41323449Sjoerg int picker; 41423449Sjoerg 41523449Sjoerg /* No arguments to this command. */ 41623449Sjoerg if (argc) { 41723449Sjoerg warnx("%s: no arguments expected", cname); 41823449Sjoerg goto usage; 41923449Sjoerg } 42023449Sjoerg 42123449Sjoerg /* Get current picker from changer and display it. */ 42223449Sjoerg if (ioctl(changer_fd, CHIOGPICKER, (char *)&picker)) 42323449Sjoerg err(1, "%s: CHIOGPICKER", changer_name); 42423449Sjoerg 42523449Sjoerg printf("%s: current picker: %d\n", changer_name, picker); 42623449Sjoerg 42723449Sjoerg return (0); 42823449Sjoerg 42923449Sjoerg usage: 43023449Sjoerg fprintf(stderr, "usage: %s %s\n", __progname, cname); 43123449Sjoerg return (1); 43223449Sjoerg} 43323449Sjoerg 43423449Sjoergstatic int 43523449Sjoergdo_setpicker(cname, argc, argv) 43623449Sjoerg char *cname; 43723449Sjoerg int argc; 43823449Sjoerg char **argv; 43923449Sjoerg{ 44023449Sjoerg int picker; 44123449Sjoerg 44223449Sjoerg if (argc < 1) { 44323449Sjoerg warnx("%s: too few arguments", cname); 44423449Sjoerg goto usage; 44523449Sjoerg } else if (argc > 1) { 44623449Sjoerg warnx("%s: too many arguments", cname); 44723449Sjoerg goto usage; 44823449Sjoerg } 44923449Sjoerg 45023449Sjoerg picker = parse_element_unit(*argv); 45123449Sjoerg 45223449Sjoerg /* Set the changer picker. */ 45323449Sjoerg if (ioctl(changer_fd, CHIOSPICKER, (char *)&picker)) 45423449Sjoerg err(1, "%s: CHIOSPICKER", changer_name); 45523449Sjoerg 45623449Sjoerg return (0); 45723449Sjoerg 45823449Sjoerg usage: 45923449Sjoerg fprintf(stderr, "usage: %s %s <picker>\n", __progname, cname); 46023449Sjoerg return (1); 46123449Sjoerg} 46223449Sjoerg 46323449Sjoergstatic int 46423449Sjoergdo_status(cname, argc, argv) 46523449Sjoerg char *cname; 46623449Sjoerg int argc; 46723449Sjoerg char **argv; 46823449Sjoerg{ 46923449Sjoerg struct changer_element_status cmd; 47023449Sjoerg struct changer_params data; 47123449Sjoerg u_int8_t *statusp; 47223449Sjoerg int i, count, chet, schet, echet; 47323449Sjoerg char *cmdname, *description; 47423449Sjoerg 47523449Sjoerg /* 47623449Sjoerg * On a status command, we expect the following: 47723449Sjoerg * 47823449Sjoerg * [<ET>] 47923449Sjoerg * 48023449Sjoerg * where ET == element type. 48123449Sjoerg * 48223449Sjoerg * If we get no arguments, we get the status of all 48323449Sjoerg * known element types. 48423449Sjoerg */ 48523449Sjoerg if (argc > 1) { 48623449Sjoerg warnx("%s: too many arguments", cname); 48723449Sjoerg goto usage; 48823449Sjoerg } 48923449Sjoerg 49023449Sjoerg /* 49123449Sjoerg * Get params from changer. Specifically, we need the element 49223449Sjoerg * counts. 49323449Sjoerg */ 49423449Sjoerg bzero(&data, sizeof(data)); 49523449Sjoerg if (ioctl(changer_fd, CHIOGPARAMS, (char *)&data)) 49623449Sjoerg err(1, "%s: CHIOGPARAMS", changer_name); 49723449Sjoerg 49823449Sjoerg if (argc) 49923449Sjoerg schet = echet = parse_element_type(*argv); 50023449Sjoerg else { 50123449Sjoerg schet = CHET_MT; 50223449Sjoerg echet = CHET_DT; 50323449Sjoerg } 50423449Sjoerg 50523449Sjoerg for (chet = schet; chet <= echet; ++chet) { 50623449Sjoerg switch (chet) { 50723449Sjoerg case CHET_MT: 50823449Sjoerg count = data.cp_npickers; 50923449Sjoerg description = "picker"; 51023449Sjoerg break; 51123449Sjoerg 51223449Sjoerg case CHET_ST: 51323449Sjoerg count = data.cp_nslots; 51423449Sjoerg description = "slot"; 51523449Sjoerg break; 51623449Sjoerg 51723449Sjoerg case CHET_IE: 51823449Sjoerg count = data.cp_nportals; 51923449Sjoerg description = "portal"; 52023449Sjoerg break; 52123449Sjoerg 52223449Sjoerg case CHET_DT: 52323449Sjoerg count = data.cp_ndrives; 52423449Sjoerg description = "drive"; 52523449Sjoerg break; 52623449Sjoerg } 52723449Sjoerg 52823449Sjoerg if (count == 0) { 52923449Sjoerg if (argc == 0) 53023449Sjoerg continue; 53123449Sjoerg else { 53223449Sjoerg printf("%s: no %s elements\n", 53323449Sjoerg changer_name, description); 53423449Sjoerg return (0); 53523449Sjoerg } 53623449Sjoerg } 53723449Sjoerg 53823449Sjoerg /* Allocate storage for the status bytes. */ 53923449Sjoerg if ((statusp = (u_int8_t *)malloc(count)) == NULL) 54023449Sjoerg errx(1, "can't allocate status storage"); 54123449Sjoerg 54223449Sjoerg bzero(statusp, count); 54323449Sjoerg bzero(&cmd, sizeof(cmd)); 54423449Sjoerg 54523449Sjoerg cmd.ces_type = chet; 54623449Sjoerg cmd.ces_data = statusp; 54723449Sjoerg 54823449Sjoerg if (ioctl(changer_fd, CHIOGSTATUS, (char *)&cmd)) { 54923449Sjoerg free(statusp); 55023449Sjoerg err(1, "%s: CHIOGSTATUS", changer_name); 55123449Sjoerg } 55223449Sjoerg 55323449Sjoerg /* Dump the status for each element of this type. */ 55423449Sjoerg for (i = 0; i < count; ++i) { 55523449Sjoerg printf("%s %d: %s\n", description, i, 55623449Sjoerg bits_to_string(statusp[i], CESTATUS_BITS)); 55723449Sjoerg } 55823449Sjoerg 55923449Sjoerg free(statusp); 56023449Sjoerg } 56123449Sjoerg 56223449Sjoerg return (0); 56323449Sjoerg 56423449Sjoerg usage: 56523449Sjoerg fprintf(stderr, "usage: %s %s [<element type>]\n", __progname, 56623449Sjoerg cname); 56723449Sjoerg return (1); 56823449Sjoerg} 56923449Sjoerg 57023449Sjoergstatic int 57123449Sjoergparse_element_type(cp) 57223449Sjoerg char *cp; 57323449Sjoerg{ 57423449Sjoerg int i; 57523449Sjoerg 57623449Sjoerg for (i = 0; elements[i].et_name != NULL; ++i) 57723449Sjoerg if (strcmp(elements[i].et_name, cp) == 0) 57823449Sjoerg return (elements[i].et_type); 57923449Sjoerg 58023449Sjoerg errx(1, "invalid element type `%s'", cp); 58123449Sjoerg} 58223449Sjoerg 58323449Sjoergstatic int 58423449Sjoergparse_element_unit(cp) 58523449Sjoerg char *cp; 58623449Sjoerg{ 58723449Sjoerg int i; 58823449Sjoerg char *p; 58923449Sjoerg 59023449Sjoerg i = (int)strtol(cp, &p, 10); 59123449Sjoerg if ((i < 0) || (*p != '\0')) 59223449Sjoerg errx(1, "invalid unit number `%s'", cp); 59323449Sjoerg 59423449Sjoerg return (i); 59523449Sjoerg} 59623449Sjoerg 59723449Sjoergstatic int 59823449Sjoergparse_special(cp) 59923449Sjoerg char *cp; 60023449Sjoerg{ 60123449Sjoerg int val; 60223449Sjoerg 60323449Sjoerg val = is_special(cp); 60423449Sjoerg if (val) 60523449Sjoerg return (val); 60623449Sjoerg 60723449Sjoerg errx(1, "invalid modifier `%s'", cp); 60823449Sjoerg} 60923449Sjoerg 61023449Sjoergstatic int 61123449Sjoergis_special(cp) 61223449Sjoerg char *cp; 61323449Sjoerg{ 61423449Sjoerg int i; 61523449Sjoerg 61623449Sjoerg for (i = 0; specials[i].sw_name != NULL; ++i) 61723449Sjoerg if (strcmp(specials[i].sw_name, cp) == 0) 61823449Sjoerg return (specials[i].sw_value); 61923449Sjoerg 62023449Sjoerg return (0); 62123449Sjoerg} 62223449Sjoerg 62323449Sjoergstatic char * 62423449Sjoergbits_to_string(v, cp) 62523449Sjoerg int v; 62623449Sjoerg const char *cp; 62723449Sjoerg{ 62823449Sjoerg const char *np; 62923449Sjoerg char f, sep, *bp; 63023449Sjoerg static char buf[128]; 63123449Sjoerg 63223449Sjoerg bp = buf; 63323449Sjoerg bzero(buf, sizeof(buf)); 63423449Sjoerg 63523449Sjoerg for (sep = '<'; (f = *cp++) != 0; cp = np) { 63623449Sjoerg for (np = cp; *np >= ' ';) 63723449Sjoerg np++; 63823449Sjoerg if ((v & (1 << (f - 1))) == 0) 63923449Sjoerg continue; 64023449Sjoerg bp += sprintf(bp, "%c%.*s", sep, np - cp, cp); 64123449Sjoerg sep = ','; 64223449Sjoerg } 64323449Sjoerg if (sep != '<') 64423449Sjoerg *bp = '>'; 64523449Sjoerg 64623449Sjoerg return (buf); 64723449Sjoerg} 64823449Sjoerg 64923449Sjoergstatic void 65023449Sjoergcleanup() 65123449Sjoerg{ 65223449Sjoerg 65323449Sjoerg /* Simple enough... */ 65423449Sjoerg (void)close(changer_fd); 65523449Sjoerg} 65623449Sjoerg 65723449Sjoergstatic void 65823449Sjoergusage() 65923449Sjoerg{ 66023449Sjoerg 66123449Sjoerg fprintf(stderr, "usage: %s command arg1 arg2 ...\n", __progname); 66223449Sjoerg exit(1); 66323449Sjoerg} 664