198ae496fSKris Kennaway /* $NetBSD: chio.c,v 1.6 1998/01/04 23:53:58 thorpej Exp $ */
29ddb49cbSWarner Losh /*-
3224c8a5bSJoerg Wunsch * Copyright (c) 1996 Jason R. Thorpe <thorpej@and.com>
4224c8a5bSJoerg Wunsch * All rights reserved.
5224c8a5bSJoerg Wunsch *
6224c8a5bSJoerg Wunsch * Redistribution and use in source and binary forms, with or without
7224c8a5bSJoerg Wunsch * modification, are permitted provided that the following conditions
8224c8a5bSJoerg Wunsch * are met:
9224c8a5bSJoerg Wunsch * 1. Redistributions of source code must retain the above copyright
10224c8a5bSJoerg Wunsch * notice, this list of conditions and the following disclaimer.
11224c8a5bSJoerg Wunsch * 2. Redistributions in binary form must reproduce the above copyright
12224c8a5bSJoerg Wunsch * notice, this list of conditions and the following disclaimer in the
13224c8a5bSJoerg Wunsch * documentation and/or other materials provided with the distribution.
14224c8a5bSJoerg Wunsch * 3. All advertising materials mentioning features or use of this software
15224c8a5bSJoerg Wunsch * must display the following acknowledgements:
16224c8a5bSJoerg Wunsch * This product includes software developed by Jason R. Thorpe
17224c8a5bSJoerg Wunsch * for And Communications, http://www.and.com/
18224c8a5bSJoerg Wunsch * 4. The name of the author may not be used to endorse or promote products
19224c8a5bSJoerg Wunsch * derived from this software without specific prior written permission.
20224c8a5bSJoerg Wunsch *
21224c8a5bSJoerg Wunsch * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22224c8a5bSJoerg Wunsch * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23224c8a5bSJoerg Wunsch * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24224c8a5bSJoerg Wunsch * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25224c8a5bSJoerg Wunsch * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26224c8a5bSJoerg Wunsch * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27224c8a5bSJoerg Wunsch * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28224c8a5bSJoerg Wunsch * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29224c8a5bSJoerg Wunsch * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30224c8a5bSJoerg Wunsch * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31224c8a5bSJoerg Wunsch * SUCH DAMAGE.
32224c8a5bSJoerg Wunsch */
3320bf9a14SJustin T. Gibbs /*
3420bf9a14SJustin T. Gibbs * Additional Copyright (c) 1997, by Matthew Jacob, for NASA/Ames Research Ctr.
35*8b6876e1SWilbert Allen Koeswoyo Suwito * Additional Copyright (c) 2000, by C. Stephen Gunn, Waterspout Communications
3620bf9a14SJustin T. Gibbs */
37224c8a5bSJoerg Wunsch
38930ab418SPhilippe Charnier #include <sys/param.h>
39224c8a5bSJoerg Wunsch #include <sys/chio.h>
40224c8a5bSJoerg Wunsch #include <err.h>
41224c8a5bSJoerg Wunsch #include <fcntl.h>
42224c8a5bSJoerg Wunsch #include <stdio.h>
43250a0cefSWarner Losh #include <stdint.h>
44224c8a5bSJoerg Wunsch #include <stdlib.h>
45224c8a5bSJoerg Wunsch #include <string.h>
46224c8a5bSJoerg Wunsch #include <unistd.h>
4721b6ee96SKenneth D. Merry #include <langinfo.h>
4821b6ee96SKenneth D. Merry #include <locale.h>
49224c8a5bSJoerg Wunsch
50224c8a5bSJoerg Wunsch #include "defs.h"
51224c8a5bSJoerg Wunsch #include "pathnames.h"
52224c8a5bSJoerg Wunsch
53e9746806SAlfonso Gregory static void usage(void) __dead2;
545dce647cSWarner Losh static void cleanup(void);
55ece57645SMark Murray static u_int16_t parse_element_type(char *);
56ece57645SMark Murray static u_int16_t parse_element_unit(char *);
575dce647cSWarner Losh static const char * element_type_name(int et);
585dce647cSWarner Losh static int parse_special(char *);
595dce647cSWarner Losh static int is_special(char *);
605dce647cSWarner Losh static const char *bits_to_string(ces_status_flags, const char *);
6120bf9a14SJustin T. Gibbs
62250a0cefSWarner Losh static void find_element(char *, uint16_t *, uint16_t *);
6361620393SMike Heffner static struct changer_element_status *get_element_status
647f33c7ddSJoerg Wunsch (unsigned int, unsigned int, int);
65f944dc77SKenneth D. Merry
665dce647cSWarner Losh static int do_move(const char *, int, char **);
675dce647cSWarner Losh static int do_exchange(const char *, int, char **);
685dce647cSWarner Losh static int do_position(const char *, int, char **);
695dce647cSWarner Losh static int do_params(const char *, int, char **);
705dce647cSWarner Losh static int do_getpicker(const char *, int, char **);
715dce647cSWarner Losh static int do_setpicker(const char *, int, char **);
725dce647cSWarner Losh static int do_status(const char *, int, char **);
735dce647cSWarner Losh static int do_ielem(const char *, int, char **);
745dce647cSWarner Losh static int do_return(const char *, int, char **);
755dce647cSWarner Losh static int do_voltag(const char *, int, char **);
7621b6ee96SKenneth D. Merry static void print_designator(const char *, u_int8_t, u_int8_t);
77224c8a5bSJoerg Wunsch
78f944dc77SKenneth D. Merry #ifndef CHET_VT
79f944dc77SKenneth D. Merry #define CHET_VT 10 /* Completely Arbitrary */
80f944dc77SKenneth D. Merry #endif
81f944dc77SKenneth D. Merry
82224c8a5bSJoerg Wunsch /* Valid changer element types. */
8346974387SEd Schouten static const struct element_type elements[] = {
84224c8a5bSJoerg Wunsch { "drive", CHET_DT },
85305a253aSKris Kennaway { "picker", CHET_MT },
86305a253aSKris Kennaway { "portal", CHET_IE },
87305a253aSKris Kennaway { "slot", CHET_ST },
88f944dc77SKenneth D. Merry { "voltag", CHET_VT }, /* Select tapes by barcode */
89224c8a5bSJoerg Wunsch { NULL, 0 },
90224c8a5bSJoerg Wunsch };
91224c8a5bSJoerg Wunsch
92224c8a5bSJoerg Wunsch /* Valid commands. */
9346974387SEd Schouten static const struct changer_command commands[] = {
94224c8a5bSJoerg Wunsch { "exchange", do_exchange },
95224c8a5bSJoerg Wunsch { "getpicker", do_getpicker },
96305a253aSKris Kennaway { "ielem", do_ielem },
97305a253aSKris Kennaway { "move", do_move },
98305a253aSKris Kennaway { "params", do_params },
99305a253aSKris Kennaway { "position", do_position },
100224c8a5bSJoerg Wunsch { "setpicker", do_setpicker },
101224c8a5bSJoerg Wunsch { "status", do_status },
102f944dc77SKenneth D. Merry { "return", do_return },
10320bf9a14SJustin T. Gibbs { "voltag", do_voltag },
104224c8a5bSJoerg Wunsch { NULL, 0 },
105224c8a5bSJoerg Wunsch };
106224c8a5bSJoerg Wunsch
107224c8a5bSJoerg Wunsch /* Valid special words. */
10846974387SEd Schouten static const struct special_word specials[] = {
109224c8a5bSJoerg Wunsch { "inv", SW_INVERT },
110224c8a5bSJoerg Wunsch { "inv1", SW_INVERT1 },
111224c8a5bSJoerg Wunsch { "inv2", SW_INVERT2 },
112224c8a5bSJoerg Wunsch { NULL, 0 },
113224c8a5bSJoerg Wunsch };
114224c8a5bSJoerg Wunsch
115224c8a5bSJoerg Wunsch static int changer_fd;
116794bf053SKris Kennaway static const char *changer_name;
117224c8a5bSJoerg Wunsch
118224c8a5bSJoerg Wunsch int
main(int argc,char ** argv)1195dce647cSWarner Losh main(int argc, char **argv)
120224c8a5bSJoerg Wunsch {
121224c8a5bSJoerg Wunsch int ch, i;
122224c8a5bSJoerg Wunsch
123224c8a5bSJoerg Wunsch while ((ch = getopt(argc, argv, "f:")) != -1) {
124224c8a5bSJoerg Wunsch switch (ch) {
125224c8a5bSJoerg Wunsch case 'f':
126224c8a5bSJoerg Wunsch changer_name = optarg;
127224c8a5bSJoerg Wunsch break;
128224c8a5bSJoerg Wunsch
129224c8a5bSJoerg Wunsch default:
130224c8a5bSJoerg Wunsch usage();
131224c8a5bSJoerg Wunsch }
132224c8a5bSJoerg Wunsch }
133224c8a5bSJoerg Wunsch argc -= optind;
134224c8a5bSJoerg Wunsch argv += optind;
135224c8a5bSJoerg Wunsch
136224c8a5bSJoerg Wunsch if (argc == 0)
137224c8a5bSJoerg Wunsch usage();
138224c8a5bSJoerg Wunsch
139224c8a5bSJoerg Wunsch /* Get the default changer if not already specified. */
140224c8a5bSJoerg Wunsch if (changer_name == NULL)
141224c8a5bSJoerg Wunsch if ((changer_name = getenv(CHANGER_ENV_VAR)) == NULL)
142224c8a5bSJoerg Wunsch changer_name = _PATH_CH;
143224c8a5bSJoerg Wunsch
144224c8a5bSJoerg Wunsch /* Open the changer device. */
145224c8a5bSJoerg Wunsch if ((changer_fd = open(changer_name, O_RDWR, 0600)) == -1)
146224c8a5bSJoerg Wunsch err(1, "%s: open", changer_name);
147224c8a5bSJoerg Wunsch
148224c8a5bSJoerg Wunsch /* Register cleanup function. */
149224c8a5bSJoerg Wunsch if (atexit(cleanup))
150224c8a5bSJoerg Wunsch err(1, "can't register cleanup function");
151224c8a5bSJoerg Wunsch
152224c8a5bSJoerg Wunsch /* Find the specified command. */
153224c8a5bSJoerg Wunsch for (i = 0; commands[i].cc_name != NULL; ++i)
154224c8a5bSJoerg Wunsch if (strcmp(*argv, commands[i].cc_name) == 0)
155224c8a5bSJoerg Wunsch break;
156305a253aSKris Kennaway if (commands[i].cc_name == NULL) {
157305a253aSKris Kennaway /* look for abbreviation */
158305a253aSKris Kennaway for (i = 0; commands[i].cc_name != NULL; ++i)
159305a253aSKris Kennaway if (strncmp(*argv, commands[i].cc_name,
160305a253aSKris Kennaway strlen(*argv)) == 0)
161305a253aSKris Kennaway break;
162305a253aSKris Kennaway }
163305a253aSKris Kennaway
164224c8a5bSJoerg Wunsch if (commands[i].cc_name == NULL)
165224c8a5bSJoerg Wunsch errx(1, "unknown command: %s", *argv);
166224c8a5bSJoerg Wunsch
167224c8a5bSJoerg Wunsch exit ((*commands[i].cc_handler)(commands[i].cc_name, argc, argv));
16820bf9a14SJustin T. Gibbs /* NOTREACHED */
169224c8a5bSJoerg Wunsch }
170224c8a5bSJoerg Wunsch
171224c8a5bSJoerg Wunsch static int
do_move(const char * cname,int argc,char ** argv)1725dce647cSWarner Losh do_move(const char *cname, int argc, char **argv)
173224c8a5bSJoerg Wunsch {
174224c8a5bSJoerg Wunsch struct changer_move cmd;
175224c8a5bSJoerg Wunsch int val;
176224c8a5bSJoerg Wunsch
177224c8a5bSJoerg Wunsch /*
178224c8a5bSJoerg Wunsch * On a move command, we expect the following:
179224c8a5bSJoerg Wunsch *
180224c8a5bSJoerg Wunsch * <from ET> <from EU> <to ET> <to EU> [inv]
181224c8a5bSJoerg Wunsch *
182224c8a5bSJoerg Wunsch * where ET == element type and EU == element unit.
183224c8a5bSJoerg Wunsch */
18420bf9a14SJustin T. Gibbs
18520bf9a14SJustin T. Gibbs ++argv; --argc;
18620bf9a14SJustin T. Gibbs
187224c8a5bSJoerg Wunsch if (argc < 4) {
188224c8a5bSJoerg Wunsch warnx("%s: too few arguments", cname);
189224c8a5bSJoerg Wunsch goto usage;
190224c8a5bSJoerg Wunsch } else if (argc > 5) {
191224c8a5bSJoerg Wunsch warnx("%s: too many arguments", cname);
192224c8a5bSJoerg Wunsch goto usage;
193224c8a5bSJoerg Wunsch }
19420bf9a14SJustin T. Gibbs (void) memset(&cmd, 0, sizeof(cmd));
195224c8a5bSJoerg Wunsch
196224c8a5bSJoerg Wunsch /* <from ET> */
197224c8a5bSJoerg Wunsch cmd.cm_fromtype = parse_element_type(*argv);
198224c8a5bSJoerg Wunsch ++argv; --argc;
199224c8a5bSJoerg Wunsch
200f944dc77SKenneth D. Merry /* Check for voltag virtual type */
201f944dc77SKenneth D. Merry if (CHET_VT == cmd.cm_fromtype) {
202f944dc77SKenneth D. Merry find_element(*argv, &cmd.cm_fromtype, &cmd.cm_fromunit);
203f944dc77SKenneth D. Merry } else {
204224c8a5bSJoerg Wunsch /* <from EU> */
205224c8a5bSJoerg Wunsch cmd.cm_fromunit = parse_element_unit(*argv);
206f944dc77SKenneth D. Merry }
207224c8a5bSJoerg Wunsch ++argv; --argc;
208224c8a5bSJoerg Wunsch
209224c8a5bSJoerg Wunsch /* <to ET> */
210224c8a5bSJoerg Wunsch cmd.cm_totype = parse_element_type(*argv);
211224c8a5bSJoerg Wunsch ++argv; --argc;
212224c8a5bSJoerg Wunsch
213f944dc77SKenneth D. Merry /* Check for voltag virtual type, and report error */
214f944dc77SKenneth D. Merry if (CHET_VT == cmd.cm_totype)
215f944dc77SKenneth D. Merry errx(1,"%s: voltag only makes sense as an element source",
216f944dc77SKenneth D. Merry cname);
217f944dc77SKenneth D. Merry
218224c8a5bSJoerg Wunsch /* <to EU> */
219224c8a5bSJoerg Wunsch cmd.cm_tounit = parse_element_unit(*argv);
220224c8a5bSJoerg Wunsch ++argv; --argc;
221224c8a5bSJoerg Wunsch
222224c8a5bSJoerg Wunsch /* Deal with optional command modifier. */
223224c8a5bSJoerg Wunsch if (argc) {
224224c8a5bSJoerg Wunsch val = parse_special(*argv);
225224c8a5bSJoerg Wunsch switch (val) {
226224c8a5bSJoerg Wunsch case SW_INVERT:
227224c8a5bSJoerg Wunsch cmd.cm_flags |= CM_INVERT;
228224c8a5bSJoerg Wunsch break;
229224c8a5bSJoerg Wunsch
230224c8a5bSJoerg Wunsch default:
231224c8a5bSJoerg Wunsch errx(1, "%s: inappropriate modifier `%s'",
232224c8a5bSJoerg Wunsch cname, *argv);
233224c8a5bSJoerg Wunsch /* NOTREACHED */
234224c8a5bSJoerg Wunsch }
235224c8a5bSJoerg Wunsch }
236224c8a5bSJoerg Wunsch
237224c8a5bSJoerg Wunsch /* Send command to changer. */
23820bf9a14SJustin T. Gibbs if (ioctl(changer_fd, CHIOMOVE, &cmd))
239224c8a5bSJoerg Wunsch err(1, "%s: CHIOMOVE", changer_name);
240224c8a5bSJoerg Wunsch
241224c8a5bSJoerg Wunsch return (0);
242224c8a5bSJoerg Wunsch
243224c8a5bSJoerg Wunsch usage:
24420bf9a14SJustin T. Gibbs (void) fprintf(stderr, "usage: %s %s "
24555fad6bbSMark Murray "<from ET> <from EU> <to ET> <to EU> [inv]\n", getprogname(), cname);
246224c8a5bSJoerg Wunsch return (1);
247224c8a5bSJoerg Wunsch }
248224c8a5bSJoerg Wunsch
249224c8a5bSJoerg Wunsch static int
do_exchange(const char * cname,int argc,char ** argv)2505dce647cSWarner Losh do_exchange(const char *cname, int argc, char **argv)
251224c8a5bSJoerg Wunsch {
252224c8a5bSJoerg Wunsch struct changer_exchange cmd;
253224c8a5bSJoerg Wunsch int val;
254224c8a5bSJoerg Wunsch
255224c8a5bSJoerg Wunsch /*
256224c8a5bSJoerg Wunsch * On an exchange command, we expect the following:
257224c8a5bSJoerg Wunsch *
258224c8a5bSJoerg Wunsch * <src ET> <src EU> <dst1 ET> <dst1 EU> [<dst2 ET> <dst2 EU>] [inv1] [inv2]
259224c8a5bSJoerg Wunsch *
260224c8a5bSJoerg Wunsch * where ET == element type and EU == element unit.
261224c8a5bSJoerg Wunsch */
26220bf9a14SJustin T. Gibbs
26320bf9a14SJustin T. Gibbs ++argv; --argc;
26420bf9a14SJustin T. Gibbs
265224c8a5bSJoerg Wunsch if (argc < 4) {
266224c8a5bSJoerg Wunsch warnx("%s: too few arguments", cname);
267224c8a5bSJoerg Wunsch goto usage;
268224c8a5bSJoerg Wunsch } else if (argc > 8) {
269224c8a5bSJoerg Wunsch warnx("%s: too many arguments", cname);
270224c8a5bSJoerg Wunsch goto usage;
271224c8a5bSJoerg Wunsch }
27220bf9a14SJustin T. Gibbs (void) memset(&cmd, 0, sizeof(cmd));
273224c8a5bSJoerg Wunsch
274224c8a5bSJoerg Wunsch /* <src ET> */
275224c8a5bSJoerg Wunsch cmd.ce_srctype = parse_element_type(*argv);
276224c8a5bSJoerg Wunsch ++argv; --argc;
277224c8a5bSJoerg Wunsch
278f944dc77SKenneth D. Merry /* Check for voltag virtual type */
279f944dc77SKenneth D. Merry if (CHET_VT == cmd.ce_srctype) {
280f944dc77SKenneth D. Merry find_element(*argv, &cmd.ce_srctype, &cmd.ce_srcunit);
281f944dc77SKenneth D. Merry } else {
282f944dc77SKenneth D. Merry /* <from EU> */
283224c8a5bSJoerg Wunsch cmd.ce_srcunit = parse_element_unit(*argv);
284f944dc77SKenneth D. Merry }
285224c8a5bSJoerg Wunsch ++argv; --argc;
286224c8a5bSJoerg Wunsch
287224c8a5bSJoerg Wunsch /* <dst1 ET> */
288224c8a5bSJoerg Wunsch cmd.ce_fdsttype = parse_element_type(*argv);
289224c8a5bSJoerg Wunsch ++argv; --argc;
290224c8a5bSJoerg Wunsch
291f944dc77SKenneth D. Merry /* Check for voltag virtual type */
292f944dc77SKenneth D. Merry if (CHET_VT == cmd.ce_fdsttype) {
293f944dc77SKenneth D. Merry find_element(*argv, &cmd.ce_fdsttype, &cmd.ce_fdstunit);
294f944dc77SKenneth D. Merry } else {
295f944dc77SKenneth D. Merry /* <from EU> */
296224c8a5bSJoerg Wunsch cmd.ce_fdstunit = parse_element_unit(*argv);
297f944dc77SKenneth D. Merry }
298224c8a5bSJoerg Wunsch ++argv; --argc;
299224c8a5bSJoerg Wunsch
300224c8a5bSJoerg Wunsch /*
301224c8a5bSJoerg Wunsch * If the next token is a special word or there are no more
302224c8a5bSJoerg Wunsch * arguments, then this is a case of simple exchange.
303224c8a5bSJoerg Wunsch * dst2 == src.
304224c8a5bSJoerg Wunsch */
305224c8a5bSJoerg Wunsch if ((argc == 0) || is_special(*argv)) {
306224c8a5bSJoerg Wunsch cmd.ce_sdsttype = cmd.ce_srctype;
307224c8a5bSJoerg Wunsch cmd.ce_sdstunit = cmd.ce_srcunit;
308224c8a5bSJoerg Wunsch goto do_special;
309224c8a5bSJoerg Wunsch }
310224c8a5bSJoerg Wunsch
311224c8a5bSJoerg Wunsch /* <dst2 ET> */
312224c8a5bSJoerg Wunsch cmd.ce_sdsttype = parse_element_type(*argv);
313224c8a5bSJoerg Wunsch ++argv; --argc;
314224c8a5bSJoerg Wunsch
315f944dc77SKenneth D. Merry if (CHET_VT == cmd.ce_sdsttype)
316f944dc77SKenneth D. Merry errx(1,"%s %s: voltag only makes sense as an element source",
317f944dc77SKenneth D. Merry cname, *argv);
318f944dc77SKenneth D. Merry
319224c8a5bSJoerg Wunsch /* <dst2 EU> */
320224c8a5bSJoerg Wunsch cmd.ce_sdstunit = parse_element_unit(*argv);
321224c8a5bSJoerg Wunsch ++argv; --argc;
322224c8a5bSJoerg Wunsch
323224c8a5bSJoerg Wunsch do_special:
324224c8a5bSJoerg Wunsch /* Deal with optional command modifiers. */
325224c8a5bSJoerg Wunsch while (argc) {
326224c8a5bSJoerg Wunsch val = parse_special(*argv);
327224c8a5bSJoerg Wunsch ++argv; --argc;
328224c8a5bSJoerg Wunsch switch (val) {
329224c8a5bSJoerg Wunsch case SW_INVERT1:
330224c8a5bSJoerg Wunsch cmd.ce_flags |= CE_INVERT1;
331224c8a5bSJoerg Wunsch break;
332224c8a5bSJoerg Wunsch
333224c8a5bSJoerg Wunsch case SW_INVERT2:
334224c8a5bSJoerg Wunsch cmd.ce_flags |= CE_INVERT2;
335224c8a5bSJoerg Wunsch break;
336224c8a5bSJoerg Wunsch
337224c8a5bSJoerg Wunsch default:
338224c8a5bSJoerg Wunsch errx(1, "%s: inappropriate modifier `%s'",
339224c8a5bSJoerg Wunsch cname, *argv);
340224c8a5bSJoerg Wunsch /* NOTREACHED */
341224c8a5bSJoerg Wunsch }
342224c8a5bSJoerg Wunsch }
343224c8a5bSJoerg Wunsch
344224c8a5bSJoerg Wunsch /* Send command to changer. */
34520bf9a14SJustin T. Gibbs if (ioctl(changer_fd, CHIOEXCHANGE, &cmd))
346224c8a5bSJoerg Wunsch err(1, "%s: CHIOEXCHANGE", changer_name);
347224c8a5bSJoerg Wunsch
348224c8a5bSJoerg Wunsch return (0);
349224c8a5bSJoerg Wunsch
350224c8a5bSJoerg Wunsch usage:
35120bf9a14SJustin T. Gibbs (void) fprintf(stderr,
35220bf9a14SJustin T. Gibbs "usage: %s %s <src ET> <src EU> <dst1 ET> <dst1 EU>\n"
35320bf9a14SJustin T. Gibbs " [<dst2 ET> <dst2 EU>] [inv1] [inv2]\n",
35455fad6bbSMark Murray getprogname(), cname);
355224c8a5bSJoerg Wunsch return (1);
356224c8a5bSJoerg Wunsch }
357224c8a5bSJoerg Wunsch
358224c8a5bSJoerg Wunsch static int
do_position(const char * cname,int argc,char ** argv)3595dce647cSWarner Losh do_position(const char *cname, int argc, char **argv)
360224c8a5bSJoerg Wunsch {
361224c8a5bSJoerg Wunsch struct changer_position cmd;
362224c8a5bSJoerg Wunsch int val;
363224c8a5bSJoerg Wunsch
364224c8a5bSJoerg Wunsch /*
365224c8a5bSJoerg Wunsch * On a position command, we expect the following:
366224c8a5bSJoerg Wunsch *
367224c8a5bSJoerg Wunsch * <to ET> <to EU> [inv]
368224c8a5bSJoerg Wunsch *
369224c8a5bSJoerg Wunsch * where ET == element type and EU == element unit.
370224c8a5bSJoerg Wunsch */
37120bf9a14SJustin T. Gibbs
37220bf9a14SJustin T. Gibbs ++argv; --argc;
37320bf9a14SJustin T. Gibbs
374224c8a5bSJoerg Wunsch if (argc < 2) {
375224c8a5bSJoerg Wunsch warnx("%s: too few arguments", cname);
376224c8a5bSJoerg Wunsch goto usage;
377224c8a5bSJoerg Wunsch } else if (argc > 3) {
378224c8a5bSJoerg Wunsch warnx("%s: too many arguments", cname);
379224c8a5bSJoerg Wunsch goto usage;
380224c8a5bSJoerg Wunsch }
38120bf9a14SJustin T. Gibbs (void) memset(&cmd, 0, sizeof(cmd));
382224c8a5bSJoerg Wunsch
383224c8a5bSJoerg Wunsch /* <to ET> */
384224c8a5bSJoerg Wunsch cmd.cp_type = parse_element_type(*argv);
385224c8a5bSJoerg Wunsch ++argv; --argc;
386224c8a5bSJoerg Wunsch
387224c8a5bSJoerg Wunsch /* <to EU> */
388224c8a5bSJoerg Wunsch cmd.cp_unit = parse_element_unit(*argv);
389224c8a5bSJoerg Wunsch ++argv; --argc;
390224c8a5bSJoerg Wunsch
391224c8a5bSJoerg Wunsch /* Deal with optional command modifier. */
392224c8a5bSJoerg Wunsch if (argc) {
393224c8a5bSJoerg Wunsch val = parse_special(*argv);
394224c8a5bSJoerg Wunsch switch (val) {
395224c8a5bSJoerg Wunsch case SW_INVERT:
396224c8a5bSJoerg Wunsch cmd.cp_flags |= CP_INVERT;
397224c8a5bSJoerg Wunsch break;
398224c8a5bSJoerg Wunsch
399224c8a5bSJoerg Wunsch default:
400224c8a5bSJoerg Wunsch errx(1, "%s: inappropriate modifier `%s'",
401224c8a5bSJoerg Wunsch cname, *argv);
402224c8a5bSJoerg Wunsch /* NOTREACHED */
403224c8a5bSJoerg Wunsch }
404224c8a5bSJoerg Wunsch }
405224c8a5bSJoerg Wunsch
406224c8a5bSJoerg Wunsch /* Send command to changer. */
40720bf9a14SJustin T. Gibbs if (ioctl(changer_fd, CHIOPOSITION, &cmd))
408224c8a5bSJoerg Wunsch err(1, "%s: CHIOPOSITION", changer_name);
409224c8a5bSJoerg Wunsch
410224c8a5bSJoerg Wunsch return (0);
411224c8a5bSJoerg Wunsch
412224c8a5bSJoerg Wunsch usage:
41320bf9a14SJustin T. Gibbs (void) fprintf(stderr, "usage: %s %s <to ET> <to EU> [inv]\n",
41455fad6bbSMark Murray getprogname(), cname);
415224c8a5bSJoerg Wunsch return (1);
416224c8a5bSJoerg Wunsch }
417224c8a5bSJoerg Wunsch
41820bf9a14SJustin T. Gibbs /* ARGSUSED */
419224c8a5bSJoerg Wunsch static int
do_params(const char * cname,int argc,char ** argv __unused)4203b899d5aSWarner Losh do_params(const char *cname, int argc, char **argv __unused)
421224c8a5bSJoerg Wunsch {
422224c8a5bSJoerg Wunsch struct changer_params data;
423c8c7ba2bSKenneth D. Merry int picker;
424224c8a5bSJoerg Wunsch
425224c8a5bSJoerg Wunsch /* No arguments to this command. */
42620bf9a14SJustin T. Gibbs
42720bf9a14SJustin T. Gibbs ++argv; --argc;
42820bf9a14SJustin T. Gibbs
429224c8a5bSJoerg Wunsch if (argc) {
4309776f3dbSBruce Evans warnx("%s: no arguments expected", cname);
431224c8a5bSJoerg Wunsch goto usage;
432224c8a5bSJoerg Wunsch }
433224c8a5bSJoerg Wunsch
434224c8a5bSJoerg Wunsch /* Get params from changer and display them. */
43520bf9a14SJustin T. Gibbs (void) memset(&data, 0, sizeof(data));
43620bf9a14SJustin T. Gibbs if (ioctl(changer_fd, CHIOGPARAMS, &data))
437224c8a5bSJoerg Wunsch err(1, "%s: CHIOGPARAMS", changer_name);
438224c8a5bSJoerg Wunsch
43920bf9a14SJustin T. Gibbs (void) printf("%s: %d slot%s, %d drive%s, %d picker%s",
440224c8a5bSJoerg Wunsch changer_name,
441224c8a5bSJoerg Wunsch data.cp_nslots, (data.cp_nslots > 1) ? "s" : "",
442224c8a5bSJoerg Wunsch data.cp_ndrives, (data.cp_ndrives > 1) ? "s" : "",
443224c8a5bSJoerg Wunsch data.cp_npickers, (data.cp_npickers > 1) ? "s" : "");
444224c8a5bSJoerg Wunsch if (data.cp_nportals)
44520bf9a14SJustin T. Gibbs (void) printf(", %d portal%s", data.cp_nportals,
446224c8a5bSJoerg Wunsch (data.cp_nportals > 1) ? "s" : "");
447224c8a5bSJoerg Wunsch
448c8c7ba2bSKenneth D. Merry /* Get current picker from changer and display it. */
449c8c7ba2bSKenneth D. Merry if (ioctl(changer_fd, CHIOGPICKER, &picker))
450c8c7ba2bSKenneth D. Merry err(1, "%s: CHIOGPICKER", changer_name);
451c8c7ba2bSKenneth D. Merry
452c8c7ba2bSKenneth D. Merry (void) printf("\n%s: current picker: %d\n", changer_name, picker);
453c8c7ba2bSKenneth D. Merry
454224c8a5bSJoerg Wunsch return (0);
455224c8a5bSJoerg Wunsch
456224c8a5bSJoerg Wunsch usage:
45755fad6bbSMark Murray (void) fprintf(stderr, "usage: %s %s\n", getprogname(), cname);
458224c8a5bSJoerg Wunsch return (1);
459224c8a5bSJoerg Wunsch }
460224c8a5bSJoerg Wunsch
46120bf9a14SJustin T. Gibbs /* ARGSUSED */
462224c8a5bSJoerg Wunsch static int
do_getpicker(const char * cname,int argc,char ** argv __unused)4633b899d5aSWarner Losh do_getpicker(const char *cname, int argc, char **argv __unused)
464224c8a5bSJoerg Wunsch {
465224c8a5bSJoerg Wunsch int picker;
466224c8a5bSJoerg Wunsch
467224c8a5bSJoerg Wunsch /* No arguments to this command. */
46820bf9a14SJustin T. Gibbs
46920bf9a14SJustin T. Gibbs ++argv; --argc;
47020bf9a14SJustin T. Gibbs
471224c8a5bSJoerg Wunsch if (argc) {
472224c8a5bSJoerg Wunsch warnx("%s: no arguments expected", cname);
473224c8a5bSJoerg Wunsch goto usage;
474224c8a5bSJoerg Wunsch }
475224c8a5bSJoerg Wunsch
476224c8a5bSJoerg Wunsch /* Get current picker from changer and display it. */
47720bf9a14SJustin T. Gibbs if (ioctl(changer_fd, CHIOGPICKER, &picker))
478224c8a5bSJoerg Wunsch err(1, "%s: CHIOGPICKER", changer_name);
479224c8a5bSJoerg Wunsch
48020bf9a14SJustin T. Gibbs (void) printf("%s: current picker: %d\n", changer_name, picker);
481224c8a5bSJoerg Wunsch
482224c8a5bSJoerg Wunsch return (0);
483224c8a5bSJoerg Wunsch
484224c8a5bSJoerg Wunsch usage:
48555fad6bbSMark Murray (void) fprintf(stderr, "usage: %s %s\n", getprogname(), cname);
486224c8a5bSJoerg Wunsch return (1);
487224c8a5bSJoerg Wunsch }
488224c8a5bSJoerg Wunsch
489224c8a5bSJoerg Wunsch static int
do_setpicker(const char * cname,int argc,char ** argv)4905dce647cSWarner Losh do_setpicker(const char *cname, int argc, char **argv)
491224c8a5bSJoerg Wunsch {
492224c8a5bSJoerg Wunsch int picker;
493224c8a5bSJoerg Wunsch
49420bf9a14SJustin T. Gibbs ++argv; --argc;
49520bf9a14SJustin T. Gibbs
496224c8a5bSJoerg Wunsch if (argc < 1) {
497224c8a5bSJoerg Wunsch warnx("%s: too few arguments", cname);
498224c8a5bSJoerg Wunsch goto usage;
499224c8a5bSJoerg Wunsch } else if (argc > 1) {
500224c8a5bSJoerg Wunsch warnx("%s: too many arguments", cname);
501224c8a5bSJoerg Wunsch goto usage;
502224c8a5bSJoerg Wunsch }
503224c8a5bSJoerg Wunsch
504224c8a5bSJoerg Wunsch picker = parse_element_unit(*argv);
505224c8a5bSJoerg Wunsch
506224c8a5bSJoerg Wunsch /* Set the changer picker. */
50720bf9a14SJustin T. Gibbs if (ioctl(changer_fd, CHIOSPICKER, &picker))
508224c8a5bSJoerg Wunsch err(1, "%s: CHIOSPICKER", changer_name);
509224c8a5bSJoerg Wunsch
510224c8a5bSJoerg Wunsch return (0);
511224c8a5bSJoerg Wunsch
512224c8a5bSJoerg Wunsch usage:
51355fad6bbSMark Murray (void) fprintf(stderr, "usage: %s %s <picker>\n", getprogname(), cname);
514224c8a5bSJoerg Wunsch return (1);
515224c8a5bSJoerg Wunsch }
516224c8a5bSJoerg Wunsch
517224c8a5bSJoerg Wunsch static int
do_status(const char * cname,int argc,char ** argv)5185dce647cSWarner Losh do_status(const char *cname, int argc, char **argv)
519224c8a5bSJoerg Wunsch {
52020bf9a14SJustin T. Gibbs struct changer_params cp;
52120bf9a14SJustin T. Gibbs struct changer_element_status_request cesr;
522ece57645SMark Murray int i;
523ece57645SMark Murray u_int16_t base, count, chet, schet, echet;
5246c120f46SMike Heffner const char *description;
52520bf9a14SJustin T. Gibbs int pvoltag = 0;
52620bf9a14SJustin T. Gibbs int avoltag = 0;
52720bf9a14SJustin T. Gibbs int sense = 0;
52820bf9a14SJustin T. Gibbs int scsi = 0;
52920bf9a14SJustin T. Gibbs int source = 0;
53020bf9a14SJustin T. Gibbs int intaddr = 0;
53120bf9a14SJustin T. Gibbs int c;
53273087c02SPhilippe Charnier
53373087c02SPhilippe Charnier count = 0;
53420bf9a14SJustin T. Gibbs base = 0;
53573087c02SPhilippe Charnier description = NULL;
536224c8a5bSJoerg Wunsch
53720bf9a14SJustin T. Gibbs optind = optreset = 1;
538b790f1b6SWarner Losh while ((c = getopt(argc, argv, "vVsSbaI")) != -1) {
53920bf9a14SJustin T. Gibbs switch (c) {
54020bf9a14SJustin T. Gibbs case 'v':
54120bf9a14SJustin T. Gibbs pvoltag = 1;
54220bf9a14SJustin T. Gibbs break;
54320bf9a14SJustin T. Gibbs case 'V':
54420bf9a14SJustin T. Gibbs avoltag = 1;
54520bf9a14SJustin T. Gibbs break;
54620bf9a14SJustin T. Gibbs case 's':
54720bf9a14SJustin T. Gibbs sense = 1;
54820bf9a14SJustin T. Gibbs break;
54920bf9a14SJustin T. Gibbs case 'S':
55020bf9a14SJustin T. Gibbs source = 1;
55120bf9a14SJustin T. Gibbs break;
55220bf9a14SJustin T. Gibbs case 'b':
55320bf9a14SJustin T. Gibbs scsi = 1;
55420bf9a14SJustin T. Gibbs break;
55520bf9a14SJustin T. Gibbs case 'I':
55620bf9a14SJustin T. Gibbs intaddr = 1;
55720bf9a14SJustin T. Gibbs break;
55820bf9a14SJustin T. Gibbs case 'a':
55920bf9a14SJustin T. Gibbs pvoltag = avoltag = source = sense = scsi = intaddr = 1;
56020bf9a14SJustin T. Gibbs break;
56120bf9a14SJustin T. Gibbs default:
5629776f3dbSBruce Evans warnx("%s: bad option", cname);
56320bf9a14SJustin T. Gibbs goto usage;
56420bf9a14SJustin T. Gibbs }
56520bf9a14SJustin T. Gibbs }
56620bf9a14SJustin T. Gibbs
56720bf9a14SJustin T. Gibbs argc -= optind;
56820bf9a14SJustin T. Gibbs argv += optind;
56920bf9a14SJustin T. Gibbs
570224c8a5bSJoerg Wunsch /*
571224c8a5bSJoerg Wunsch * On a status command, we expect the following:
572224c8a5bSJoerg Wunsch *
57320bf9a14SJustin T. Gibbs * [<ET> [<start> [<end>] ] ]
574224c8a5bSJoerg Wunsch *
57520bf9a14SJustin T. Gibbs * where ET == element type, start == first element to report,
57620bf9a14SJustin T. Gibbs * end == number of elements to report
577224c8a5bSJoerg Wunsch *
578224c8a5bSJoerg Wunsch * If we get no arguments, we get the status of all
579224c8a5bSJoerg Wunsch * known element types.
580224c8a5bSJoerg Wunsch */
58120bf9a14SJustin T. Gibbs if (argc > 3) {
582224c8a5bSJoerg Wunsch warnx("%s: too many arguments", cname);
583224c8a5bSJoerg Wunsch goto usage;
584224c8a5bSJoerg Wunsch }
585224c8a5bSJoerg Wunsch
586224c8a5bSJoerg Wunsch /*
587224c8a5bSJoerg Wunsch * Get params from changer. Specifically, we need the element
588224c8a5bSJoerg Wunsch * counts.
589224c8a5bSJoerg Wunsch */
59020bf9a14SJustin T. Gibbs if (ioctl(changer_fd, CHIOGPARAMS, (char *)&cp))
591224c8a5bSJoerg Wunsch err(1, "%s: CHIOGPARAMS", changer_name);
592224c8a5bSJoerg Wunsch
59320bf9a14SJustin T. Gibbs if (argc > 0)
59420bf9a14SJustin T. Gibbs schet = echet = parse_element_type(argv[0]);
595224c8a5bSJoerg Wunsch else {
596224c8a5bSJoerg Wunsch schet = CHET_MT;
597224c8a5bSJoerg Wunsch echet = CHET_DT;
598224c8a5bSJoerg Wunsch }
59920bf9a14SJustin T. Gibbs if (argc > 1) {
600ece57645SMark Murray base = (u_int16_t)atol(argv[1]);
60120bf9a14SJustin T. Gibbs count = 1;
60220bf9a14SJustin T. Gibbs }
60320bf9a14SJustin T. Gibbs if (argc > 2)
604ece57645SMark Murray count = (u_int16_t)atol(argv[2]) - base + 1;
605224c8a5bSJoerg Wunsch
606224c8a5bSJoerg Wunsch for (chet = schet; chet <= echet; ++chet) {
607224c8a5bSJoerg Wunsch switch (chet) {
608224c8a5bSJoerg Wunsch case CHET_MT:
60920bf9a14SJustin T. Gibbs if (count == 0)
61020bf9a14SJustin T. Gibbs count = cp.cp_npickers;
61120bf9a14SJustin T. Gibbs else if (count > cp.cp_npickers)
61220bf9a14SJustin T. Gibbs errx(1, "not that many pickers in device");
613224c8a5bSJoerg Wunsch description = "picker";
614224c8a5bSJoerg Wunsch break;
615224c8a5bSJoerg Wunsch
616224c8a5bSJoerg Wunsch case CHET_ST:
61720bf9a14SJustin T. Gibbs if (count == 0)
61820bf9a14SJustin T. Gibbs count = cp.cp_nslots;
61920bf9a14SJustin T. Gibbs else if (count > cp.cp_nslots)
62020bf9a14SJustin T. Gibbs errx(1, "not that many slots in device");
621224c8a5bSJoerg Wunsch description = "slot";
622224c8a5bSJoerg Wunsch break;
623224c8a5bSJoerg Wunsch
624224c8a5bSJoerg Wunsch case CHET_IE:
62520bf9a14SJustin T. Gibbs if (count == 0)
62620bf9a14SJustin T. Gibbs count = cp.cp_nportals;
62720bf9a14SJustin T. Gibbs else if (count > cp.cp_nportals)
62820bf9a14SJustin T. Gibbs errx(1, "not that many portals in device");
629224c8a5bSJoerg Wunsch description = "portal";
630224c8a5bSJoerg Wunsch break;
631224c8a5bSJoerg Wunsch
632224c8a5bSJoerg Wunsch case CHET_DT:
63320bf9a14SJustin T. Gibbs if (count == 0)
63420bf9a14SJustin T. Gibbs count = cp.cp_ndrives;
63520bf9a14SJustin T. Gibbs else if (count > cp.cp_ndrives)
63620bf9a14SJustin T. Gibbs errx(1, "not that many drives in device");
637224c8a5bSJoerg Wunsch description = "drive";
638224c8a5bSJoerg Wunsch break;
63920bf9a14SJustin T. Gibbs
64020bf9a14SJustin T. Gibbs default:
64120bf9a14SJustin T. Gibbs /* To appease gcc -Wuninitialized. */
64220bf9a14SJustin T. Gibbs count = 0;
64320bf9a14SJustin T. Gibbs description = NULL;
644224c8a5bSJoerg Wunsch }
645224c8a5bSJoerg Wunsch
646224c8a5bSJoerg Wunsch if (count == 0) {
647224c8a5bSJoerg Wunsch if (argc == 0)
648224c8a5bSJoerg Wunsch continue;
649224c8a5bSJoerg Wunsch else {
650224c8a5bSJoerg Wunsch printf("%s: no %s elements\n",
651224c8a5bSJoerg Wunsch changer_name, description);
652224c8a5bSJoerg Wunsch return (0);
653224c8a5bSJoerg Wunsch }
654224c8a5bSJoerg Wunsch }
655224c8a5bSJoerg Wunsch
65620bf9a14SJustin T. Gibbs bzero(&cesr, sizeof(cesr));
65720bf9a14SJustin T. Gibbs cesr.cesr_element_type = chet;
65820bf9a14SJustin T. Gibbs cesr.cesr_element_base = base;
65920bf9a14SJustin T. Gibbs cesr.cesr_element_count = count;
66020bf9a14SJustin T. Gibbs /* Allocate storage for the status structures. */
661f944dc77SKenneth D. Merry cesr.cesr_element_status =
662f944dc77SKenneth D. Merry (struct changer_element_status *)
66361620393SMike Heffner calloc((size_t)count, sizeof(struct changer_element_status));
66420bf9a14SJustin T. Gibbs
66520bf9a14SJustin T. Gibbs if (!cesr.cesr_element_status)
666224c8a5bSJoerg Wunsch errx(1, "can't allocate status storage");
667224c8a5bSJoerg Wunsch
66820bf9a14SJustin T. Gibbs if (avoltag || pvoltag)
66920bf9a14SJustin T. Gibbs cesr.cesr_flags |= CESR_VOLTAGS;
670224c8a5bSJoerg Wunsch
67120bf9a14SJustin T. Gibbs if (ioctl(changer_fd, CHIOGSTATUS, (char *)&cesr)) {
67220bf9a14SJustin T. Gibbs free(cesr.cesr_element_status);
673224c8a5bSJoerg Wunsch err(1, "%s: CHIOGSTATUS", changer_name);
674224c8a5bSJoerg Wunsch }
675224c8a5bSJoerg Wunsch
67620bf9a14SJustin T. Gibbs /* Dump the status for each reported element. */
677224c8a5bSJoerg Wunsch for (i = 0; i < count; ++i) {
67820bf9a14SJustin T. Gibbs struct changer_element_status *ces =
67920bf9a14SJustin T. Gibbs &(cesr.cesr_element_status[i]);
68020bf9a14SJustin T. Gibbs printf("%s %d: %s", description, ces->ces_addr,
68120bf9a14SJustin T. Gibbs bits_to_string(ces->ces_flags,
68220bf9a14SJustin T. Gibbs CESTATUS_BITS));
68320bf9a14SJustin T. Gibbs if (sense)
68420bf9a14SJustin T. Gibbs printf(" sense: <0x%02x/0x%02x>",
68520bf9a14SJustin T. Gibbs ces->ces_sensecode,
68620bf9a14SJustin T. Gibbs ces->ces_sensequal);
68720bf9a14SJustin T. Gibbs if (pvoltag)
68820bf9a14SJustin T. Gibbs printf(" voltag: <%s:%d>",
68920bf9a14SJustin T. Gibbs ces->ces_pvoltag.cv_volid,
69020bf9a14SJustin T. Gibbs ces->ces_pvoltag.cv_serial);
69120bf9a14SJustin T. Gibbs if (avoltag)
69220bf9a14SJustin T. Gibbs printf(" avoltag: <%s:%d>",
69320bf9a14SJustin T. Gibbs ces->ces_avoltag.cv_volid,
69420bf9a14SJustin T. Gibbs ces->ces_avoltag.cv_serial);
695426e9c1dSWarner Losh if (source) {
69620bf9a14SJustin T. Gibbs if (ces->ces_flags & CES_SOURCE_VALID)
69720bf9a14SJustin T. Gibbs printf(" source: <%s %d>",
69820bf9a14SJustin T. Gibbs element_type_name(
69920bf9a14SJustin T. Gibbs ces->ces_source_type),
70020bf9a14SJustin T. Gibbs ces->ces_source_addr);
70120bf9a14SJustin T. Gibbs else
70220bf9a14SJustin T. Gibbs printf(" source: <>");
703426e9c1dSWarner Losh }
70420bf9a14SJustin T. Gibbs if (intaddr)
70520bf9a14SJustin T. Gibbs printf(" intaddr: <%d>", ces->ces_int_addr);
70620bf9a14SJustin T. Gibbs if (scsi) {
70720bf9a14SJustin T. Gibbs printf(" scsi: <");
70820bf9a14SJustin T. Gibbs if (ces->ces_flags & CES_SCSIID_VALID)
70920bf9a14SJustin T. Gibbs printf("%d", ces->ces_scsi_id);
71020bf9a14SJustin T. Gibbs else
71120bf9a14SJustin T. Gibbs putchar('?');
71220bf9a14SJustin T. Gibbs putchar(':');
71320bf9a14SJustin T. Gibbs if (ces->ces_flags & CES_LUN_VALID)
71420bf9a14SJustin T. Gibbs printf("%d", ces->ces_scsi_lun);
71520bf9a14SJustin T. Gibbs else
71620bf9a14SJustin T. Gibbs putchar('?');
71720bf9a14SJustin T. Gibbs putchar('>');
71820bf9a14SJustin T. Gibbs }
71921b6ee96SKenneth D. Merry if (ces->ces_designator_length > 0)
72021b6ee96SKenneth D. Merry print_designator(ces->ces_designator,
72121b6ee96SKenneth D. Merry ces->ces_code_set,
72221b6ee96SKenneth D. Merry ces->ces_designator_length);
72320bf9a14SJustin T. Gibbs putchar('\n');
724224c8a5bSJoerg Wunsch }
725224c8a5bSJoerg Wunsch
72620bf9a14SJustin T. Gibbs free(cesr.cesr_element_status);
72720bf9a14SJustin T. Gibbs count = 0;
728224c8a5bSJoerg Wunsch }
729224c8a5bSJoerg Wunsch
730224c8a5bSJoerg Wunsch return (0);
731224c8a5bSJoerg Wunsch
732224c8a5bSJoerg Wunsch usage:
73320bf9a14SJustin T. Gibbs (void) fprintf(stderr, "usage: %s %s [-vVsSbaA] [<element type> [<start-addr> [<end-addr>] ] ]\n",
73455fad6bbSMark Murray getprogname(), cname);
735224c8a5bSJoerg Wunsch return (1);
736224c8a5bSJoerg Wunsch }
737224c8a5bSJoerg Wunsch
738224c8a5bSJoerg Wunsch static int
do_ielem(const char * cname,int argc,char ** argv)7395dce647cSWarner Losh do_ielem(const char *cname, int argc, char **argv)
74020bf9a14SJustin T. Gibbs {
74120bf9a14SJustin T. Gibbs int timeout = 0;
74220bf9a14SJustin T. Gibbs
74320bf9a14SJustin T. Gibbs if (argc == 2) {
74420bf9a14SJustin T. Gibbs timeout = atol(argv[1]);
74520bf9a14SJustin T. Gibbs } else if (argc > 1) {
74620bf9a14SJustin T. Gibbs warnx("%s: too many arguments", cname);
74720bf9a14SJustin T. Gibbs goto usage;
74820bf9a14SJustin T. Gibbs }
74920bf9a14SJustin T. Gibbs
75020bf9a14SJustin T. Gibbs if (ioctl(changer_fd, CHIOIELEM, &timeout))
75120bf9a14SJustin T. Gibbs err(1, "%s: CHIOIELEM", changer_name);
75220bf9a14SJustin T. Gibbs
75320bf9a14SJustin T. Gibbs return (0);
75420bf9a14SJustin T. Gibbs
75520bf9a14SJustin T. Gibbs usage:
75620bf9a14SJustin T. Gibbs (void) fprintf(stderr, "usage: %s %s [<timeout>]\n",
75755fad6bbSMark Murray getprogname(), cname);
75820bf9a14SJustin T. Gibbs return (1);
75920bf9a14SJustin T. Gibbs }
76020bf9a14SJustin T. Gibbs
76120bf9a14SJustin T. Gibbs static int
do_voltag(const char * cname,int argc,char ** argv)7625dce647cSWarner Losh do_voltag(const char *cname, int argc, char **argv)
76320bf9a14SJustin T. Gibbs {
76420bf9a14SJustin T. Gibbs int force = 0;
76520bf9a14SJustin T. Gibbs int clear = 0;
76620bf9a14SJustin T. Gibbs int alternate = 0;
76720bf9a14SJustin T. Gibbs int c;
76820bf9a14SJustin T. Gibbs struct changer_set_voltag_request csvr;
76920bf9a14SJustin T. Gibbs
77020bf9a14SJustin T. Gibbs bzero(&csvr, sizeof(csvr));
77120bf9a14SJustin T. Gibbs
77220bf9a14SJustin T. Gibbs optind = optreset = 1;
773b790f1b6SWarner Losh while ((c = getopt(argc, argv, "fca")) != -1) {
77420bf9a14SJustin T. Gibbs switch (c) {
77520bf9a14SJustin T. Gibbs case 'f':
77620bf9a14SJustin T. Gibbs force = 1;
77720bf9a14SJustin T. Gibbs break;
77820bf9a14SJustin T. Gibbs case 'c':
77920bf9a14SJustin T. Gibbs clear = 1;
78020bf9a14SJustin T. Gibbs break;
78120bf9a14SJustin T. Gibbs case 'a':
78220bf9a14SJustin T. Gibbs alternate = 1;
78320bf9a14SJustin T. Gibbs break;
78420bf9a14SJustin T. Gibbs default:
7859776f3dbSBruce Evans warnx("%s: bad option", cname);
78620bf9a14SJustin T. Gibbs goto usage;
78720bf9a14SJustin T. Gibbs }
78820bf9a14SJustin T. Gibbs }
78920bf9a14SJustin T. Gibbs
79020bf9a14SJustin T. Gibbs argc -= optind;
79120bf9a14SJustin T. Gibbs argv += optind;
79220bf9a14SJustin T. Gibbs
79320bf9a14SJustin T. Gibbs if (argc < 2) {
7949776f3dbSBruce Evans warnx("%s: missing element specification", cname);
79520bf9a14SJustin T. Gibbs goto usage;
79620bf9a14SJustin T. Gibbs }
79720bf9a14SJustin T. Gibbs
79820bf9a14SJustin T. Gibbs csvr.csvr_type = parse_element_type(argv[0]);
799ece57645SMark Murray csvr.csvr_addr = (u_int16_t)atol(argv[1]);
80020bf9a14SJustin T. Gibbs
80120bf9a14SJustin T. Gibbs if (!clear) {
80220bf9a14SJustin T. Gibbs if (argc < 3 || argc > 4) {
8039776f3dbSBruce Evans warnx("%s: missing argument", cname);
80420bf9a14SJustin T. Gibbs goto usage;
80520bf9a14SJustin T. Gibbs }
80620bf9a14SJustin T. Gibbs
80720bf9a14SJustin T. Gibbs if (force)
80820bf9a14SJustin T. Gibbs csvr.csvr_flags = CSVR_MODE_REPLACE;
80920bf9a14SJustin T. Gibbs else
81020bf9a14SJustin T. Gibbs csvr.csvr_flags = CSVR_MODE_SET;
81120bf9a14SJustin T. Gibbs
81220bf9a14SJustin T. Gibbs if (strlen(argv[2]) > sizeof(csvr.csvr_voltag.cv_volid)) {
8139776f3dbSBruce Evans warnx("%s: volume label too long", cname);
81420bf9a14SJustin T. Gibbs goto usage;
81520bf9a14SJustin T. Gibbs }
81620bf9a14SJustin T. Gibbs
81761620393SMike Heffner strlcpy((char *)csvr.csvr_voltag.cv_volid, argv[2],
81820bf9a14SJustin T. Gibbs sizeof(csvr.csvr_voltag.cv_volid));
81920bf9a14SJustin T. Gibbs
82020bf9a14SJustin T. Gibbs if (argc == 4) {
821ece57645SMark Murray csvr.csvr_voltag.cv_serial = (u_int16_t)atol(argv[3]);
82220bf9a14SJustin T. Gibbs }
82320bf9a14SJustin T. Gibbs } else {
82420bf9a14SJustin T. Gibbs if (argc != 2) {
8259776f3dbSBruce Evans warnx("%s: unexpected argument", cname);
82620bf9a14SJustin T. Gibbs goto usage;
82720bf9a14SJustin T. Gibbs }
82820bf9a14SJustin T. Gibbs csvr.csvr_flags = CSVR_MODE_CLEAR;
82920bf9a14SJustin T. Gibbs }
83020bf9a14SJustin T. Gibbs
83120bf9a14SJustin T. Gibbs if (alternate) {
83220bf9a14SJustin T. Gibbs csvr.csvr_flags |= CSVR_ALTERNATE;
83320bf9a14SJustin T. Gibbs }
83420bf9a14SJustin T. Gibbs
83520bf9a14SJustin T. Gibbs if (ioctl(changer_fd, CHIOSETVOLTAG, &csvr))
83620bf9a14SJustin T. Gibbs err(1, "%s: CHIOSETVOLTAG", changer_name);
83720bf9a14SJustin T. Gibbs
83820bf9a14SJustin T. Gibbs return 0;
83920bf9a14SJustin T. Gibbs usage:
84020bf9a14SJustin T. Gibbs (void) fprintf(stderr,
84120bf9a14SJustin T. Gibbs "usage: %s %s [-fca] <element> [<voltag> [<vsn>] ]\n",
84255fad6bbSMark Murray getprogname(), cname);
84320bf9a14SJustin T. Gibbs return 1;
84420bf9a14SJustin T. Gibbs }
84520bf9a14SJustin T. Gibbs
846ece57645SMark Murray static u_int16_t
parse_element_type(char * cp)8475dce647cSWarner Losh parse_element_type(char *cp)
848224c8a5bSJoerg Wunsch {
849224c8a5bSJoerg Wunsch int i;
850224c8a5bSJoerg Wunsch
851224c8a5bSJoerg Wunsch for (i = 0; elements[i].et_name != NULL; ++i)
852224c8a5bSJoerg Wunsch if (strcmp(elements[i].et_name, cp) == 0)
853ece57645SMark Murray return ((u_int16_t)elements[i].et_type);
854224c8a5bSJoerg Wunsch
855224c8a5bSJoerg Wunsch errx(1, "invalid element type `%s'", cp);
85620bf9a14SJustin T. Gibbs /* NOTREACHED */
85720bf9a14SJustin T. Gibbs }
85820bf9a14SJustin T. Gibbs
85920bf9a14SJustin T. Gibbs static const char *
element_type_name(int et)8605dce647cSWarner Losh element_type_name(int et)
86120bf9a14SJustin T. Gibbs {
86220bf9a14SJustin T. Gibbs int i;
86320bf9a14SJustin T. Gibbs
86420bf9a14SJustin T. Gibbs for (i = 0; elements[i].et_name != NULL; i++)
86520bf9a14SJustin T. Gibbs if (elements[i].et_type == et)
86620bf9a14SJustin T. Gibbs return elements[i].et_name;
86720bf9a14SJustin T. Gibbs
86820bf9a14SJustin T. Gibbs return "unknown";
869224c8a5bSJoerg Wunsch }
870224c8a5bSJoerg Wunsch
871ece57645SMark Murray static u_int16_t
parse_element_unit(char * cp)8725dce647cSWarner Losh parse_element_unit(char *cp)
873224c8a5bSJoerg Wunsch {
874224c8a5bSJoerg Wunsch int i;
875224c8a5bSJoerg Wunsch char *p;
876224c8a5bSJoerg Wunsch
877224c8a5bSJoerg Wunsch i = (int)strtol(cp, &p, 10);
878224c8a5bSJoerg Wunsch if ((i < 0) || (*p != '\0'))
879224c8a5bSJoerg Wunsch errx(1, "invalid unit number `%s'", cp);
880224c8a5bSJoerg Wunsch
881ece57645SMark Murray return ((u_int16_t)i);
882224c8a5bSJoerg Wunsch }
883224c8a5bSJoerg Wunsch
884224c8a5bSJoerg Wunsch static int
parse_special(char * cp)8855dce647cSWarner Losh parse_special(char *cp)
886224c8a5bSJoerg Wunsch {
887224c8a5bSJoerg Wunsch int val;
888224c8a5bSJoerg Wunsch
889224c8a5bSJoerg Wunsch val = is_special(cp);
890224c8a5bSJoerg Wunsch if (val)
891224c8a5bSJoerg Wunsch return (val);
892224c8a5bSJoerg Wunsch
893224c8a5bSJoerg Wunsch errx(1, "invalid modifier `%s'", cp);
89420bf9a14SJustin T. Gibbs /* NOTREACHED */
895224c8a5bSJoerg Wunsch }
896224c8a5bSJoerg Wunsch
897224c8a5bSJoerg Wunsch static int
is_special(char * cp)8985dce647cSWarner Losh is_special(char *cp)
899224c8a5bSJoerg Wunsch {
900224c8a5bSJoerg Wunsch int i;
901224c8a5bSJoerg Wunsch
902224c8a5bSJoerg Wunsch for (i = 0; specials[i].sw_name != NULL; ++i)
903224c8a5bSJoerg Wunsch if (strcmp(specials[i].sw_name, cp) == 0)
904224c8a5bSJoerg Wunsch return (specials[i].sw_value);
905224c8a5bSJoerg Wunsch
906224c8a5bSJoerg Wunsch return (0);
907224c8a5bSJoerg Wunsch }
908224c8a5bSJoerg Wunsch
909794bf053SKris Kennaway static const char *
bits_to_string(ces_status_flags v,const char * cp)9105dce647cSWarner Losh bits_to_string(ces_status_flags v, const char *cp)
911224c8a5bSJoerg Wunsch {
912224c8a5bSJoerg Wunsch const char *np;
913224c8a5bSJoerg Wunsch char f, sep, *bp;
914224c8a5bSJoerg Wunsch static char buf[128];
915224c8a5bSJoerg Wunsch
916224c8a5bSJoerg Wunsch bp = buf;
91720bf9a14SJustin T. Gibbs (void) memset(buf, 0, sizeof(buf));
918224c8a5bSJoerg Wunsch
919224c8a5bSJoerg Wunsch for (sep = '<'; (f = *cp++) != 0; cp = np) {
920224c8a5bSJoerg Wunsch for (np = cp; *np >= ' ';)
921224c8a5bSJoerg Wunsch np++;
922ece57645SMark Murray if (((int)v & (1 << (f - 1))) == 0)
923224c8a5bSJoerg Wunsch continue;
924ece57645SMark Murray (void) snprintf(bp, sizeof(buf) - (size_t)(bp - &buf[0]),
925305a253aSKris Kennaway "%c%.*s", sep, (int)(long)(np - cp), cp);
926305a253aSKris Kennaway bp += strlen(bp);
927224c8a5bSJoerg Wunsch sep = ',';
928224c8a5bSJoerg Wunsch }
929224c8a5bSJoerg Wunsch if (sep != '<')
930224c8a5bSJoerg Wunsch *bp = '>';
931224c8a5bSJoerg Wunsch
932224c8a5bSJoerg Wunsch return (buf);
933224c8a5bSJoerg Wunsch }
934f944dc77SKenneth D. Merry /*
935f944dc77SKenneth D. Merry * do_return()
936f944dc77SKenneth D. Merry *
937f944dc77SKenneth D. Merry * Given an element reference, ask the changer/picker to move that
938f944dc77SKenneth D. Merry * element back to its source slot.
939f944dc77SKenneth D. Merry */
940f944dc77SKenneth D. Merry static int
do_return(const char * cname,int argc,char ** argv)9415dce647cSWarner Losh do_return(const char *cname, int argc, char **argv)
942f944dc77SKenneth D. Merry {
943f944dc77SKenneth D. Merry struct changer_element_status *ces;
944f944dc77SKenneth D. Merry struct changer_move cmd;
945250a0cefSWarner Losh uint16_t type, element;
946f944dc77SKenneth D. Merry
947f944dc77SKenneth D. Merry ++argv; --argc;
948f944dc77SKenneth D. Merry
949f944dc77SKenneth D. Merry if (argc < 2) {
950f944dc77SKenneth D. Merry warnx("%s: too few arguments", cname);
951f944dc77SKenneth D. Merry goto usage;
952f944dc77SKenneth D. Merry } else if (argc > 3) {
953f944dc77SKenneth D. Merry warnx("%s: too many arguments", cname);
954f944dc77SKenneth D. Merry goto usage;
955f944dc77SKenneth D. Merry }
956f944dc77SKenneth D. Merry
957f944dc77SKenneth D. Merry type = parse_element_type(*argv);
958f944dc77SKenneth D. Merry ++argv; --argc;
959f944dc77SKenneth D. Merry
960f944dc77SKenneth D. Merry /* Handle voltag virtual Changer Element Type */
961f944dc77SKenneth D. Merry if (CHET_VT == type) {
962f944dc77SKenneth D. Merry find_element(*argv, &type, &element);
963f944dc77SKenneth D. Merry } else {
964f944dc77SKenneth D. Merry element = parse_element_unit(*argv);
965f944dc77SKenneth D. Merry }
966f944dc77SKenneth D. Merry ++argv; --argc;
967f944dc77SKenneth D. Merry
96861620393SMike Heffner /* Get the status */
9697f33c7ddSJoerg Wunsch ces = get_element_status((unsigned int)type, (unsigned int)element,
9707f33c7ddSJoerg Wunsch CHET_VT == type);
971f944dc77SKenneth D. Merry
972f944dc77SKenneth D. Merry if (NULL == ces)
973f944dc77SKenneth D. Merry errx(1, "%s: null element status pointer", cname);
974f944dc77SKenneth D. Merry
975f944dc77SKenneth D. Merry if (!(ces->ces_flags & CES_SOURCE_VALID))
976f944dc77SKenneth D. Merry errx(1, "%s: no source information", cname);
977f944dc77SKenneth D. Merry
978f944dc77SKenneth D. Merry (void) memset(&cmd, 0, sizeof(cmd));
979f944dc77SKenneth D. Merry
980f944dc77SKenneth D. Merry cmd.cm_fromtype = type;
981f944dc77SKenneth D. Merry cmd.cm_fromunit = element;
982f944dc77SKenneth D. Merry cmd.cm_totype = ces->ces_source_type;
983f944dc77SKenneth D. Merry cmd.cm_tounit = ces->ces_source_addr;
984f944dc77SKenneth D. Merry
985f944dc77SKenneth D. Merry if (ioctl(changer_fd, CHIOMOVE, &cmd) == -1)
986f944dc77SKenneth D. Merry err(1, "%s: CHIOMOVE", changer_name);
987f944dc77SKenneth D. Merry free(ces);
988f944dc77SKenneth D. Merry
989f944dc77SKenneth D. Merry return(0);
990f944dc77SKenneth D. Merry
991f944dc77SKenneth D. Merry usage:
992f944dc77SKenneth D. Merry (void) fprintf(stderr, "usage: %s %s "
99355fad6bbSMark Murray "<from ET> <from EU>\n", getprogname(), cname);
994f944dc77SKenneth D. Merry return(1);
995f944dc77SKenneth D. Merry }
996f944dc77SKenneth D. Merry
997f944dc77SKenneth D. Merry /*
998f944dc77SKenneth D. Merry * get_element_status()
999f944dc77SKenneth D. Merry *
1000f944dc77SKenneth D. Merry * return a *cesr for the specified changer element. This
1001f944dc77SKenneth D. Merry * routing will malloc()/calloc() the memory. The caller
1002f944dc77SKenneth D. Merry * should free() it when done.
1003f944dc77SKenneth D. Merry */
1004f944dc77SKenneth D. Merry static struct changer_element_status *
get_element_status(unsigned int type,unsigned int element,int use_voltags)10057f33c7ddSJoerg Wunsch get_element_status(unsigned int type, unsigned int element, int use_voltags)
1006f944dc77SKenneth D. Merry {
1007f944dc77SKenneth D. Merry struct changer_element_status_request cesr;
1008f944dc77SKenneth D. Merry struct changer_element_status *ces;
1009f944dc77SKenneth D. Merry
1010f944dc77SKenneth D. Merry ces = (struct changer_element_status *)
101161620393SMike Heffner calloc((size_t)1, sizeof(struct changer_element_status));
1012f944dc77SKenneth D. Merry
1013f944dc77SKenneth D. Merry if (NULL == ces)
1014f944dc77SKenneth D. Merry errx(1, "can't allocate status storage");
1015f944dc77SKenneth D. Merry
1016f944dc77SKenneth D. Merry (void)memset(&cesr, 0, sizeof(cesr));
1017f944dc77SKenneth D. Merry
1018250a0cefSWarner Losh cesr.cesr_element_type = (uint16_t)type;
1019250a0cefSWarner Losh cesr.cesr_element_base = (uint16_t)element;
1020f944dc77SKenneth D. Merry cesr.cesr_element_count = 1; /* Only this one element */
10217f33c7ddSJoerg Wunsch if (use_voltags)
1022f944dc77SKenneth D. Merry cesr.cesr_flags |= CESR_VOLTAGS; /* Grab voltags as well */
1023f944dc77SKenneth D. Merry cesr.cesr_element_status = ces;
1024f944dc77SKenneth D. Merry
1025f944dc77SKenneth D. Merry if (ioctl(changer_fd, CHIOGSTATUS, (char *)&cesr) == -1) {
1026f944dc77SKenneth D. Merry free(ces);
1027f944dc77SKenneth D. Merry err(1, "%s: CHIOGSTATUS", changer_name);
1028f944dc77SKenneth D. Merry /* NOTREACHED */
1029f944dc77SKenneth D. Merry }
1030f944dc77SKenneth D. Merry
1031f944dc77SKenneth D. Merry return ces;
1032f944dc77SKenneth D. Merry }
1033f944dc77SKenneth D. Merry
1034f944dc77SKenneth D. Merry
1035f944dc77SKenneth D. Merry /*
1036f944dc77SKenneth D. Merry * find_element()
1037f944dc77SKenneth D. Merry *
1038f944dc77SKenneth D. Merry * Given a <voltag> find the chager element and unit, or exit
1039f944dc77SKenneth D. Merry * with an error if it isn't found. We grab the changer status
1040f944dc77SKenneth D. Merry * and iterate until we find a match, or crap out.
1041f944dc77SKenneth D. Merry */
1042f944dc77SKenneth D. Merry static void
find_element(char * voltag,uint16_t * et,uint16_t * eu)1043250a0cefSWarner Losh find_element(char *voltag, uint16_t *et, uint16_t *eu)
1044f944dc77SKenneth D. Merry {
1045f944dc77SKenneth D. Merry struct changer_params cp;
1046f944dc77SKenneth D. Merry struct changer_element_status_request cesr;
1047f944dc77SKenneth D. Merry struct changer_element_status *ch_ces, *ces;
104861620393SMike Heffner int found = 0;
104961620393SMike Heffner size_t elem, total_elem;
1050f944dc77SKenneth D. Merry
1051f944dc77SKenneth D. Merry /*
1052f944dc77SKenneth D. Merry * Get the changer parameters, we're interested in the counts
1053f944dc77SKenneth D. Merry * for all types of elements to perform our search.
1054f944dc77SKenneth D. Merry */
1055f944dc77SKenneth D. Merry if (ioctl(changer_fd, CHIOGPARAMS, (char *)&cp))
1056f944dc77SKenneth D. Merry err(1, "%s: CHIOGPARAMS", changer_name);
1057f944dc77SKenneth D. Merry
1058f944dc77SKenneth D. Merry /* Allocate some memory for the results */
1059f944dc77SKenneth D. Merry total_elem = (cp.cp_nslots + cp.cp_ndrives
1060f944dc77SKenneth D. Merry + cp.cp_npickers + cp.cp_nportals);
1061f944dc77SKenneth D. Merry
1062f944dc77SKenneth D. Merry ch_ces = (struct changer_element_status *)
1063f944dc77SKenneth D. Merry calloc(total_elem, sizeof(struct changer_element_status));
1064f944dc77SKenneth D. Merry
1065f944dc77SKenneth D. Merry if (NULL == ch_ces)
1066f944dc77SKenneth D. Merry errx(1, "can't allocate status storage");
1067f944dc77SKenneth D. Merry
1068f944dc77SKenneth D. Merry ces = ch_ces;
1069f944dc77SKenneth D. Merry
1070f944dc77SKenneth D. Merry /* Read in the changer slots */
1071f944dc77SKenneth D. Merry if (cp.cp_nslots > 0) {
1072c5d27505SUlrich Spörlein (void) memset(&cesr, 0, sizeof(cesr));
1073f944dc77SKenneth D. Merry cesr.cesr_element_type = CHET_ST;
1074f944dc77SKenneth D. Merry cesr.cesr_element_base = 0;
1075f944dc77SKenneth D. Merry cesr.cesr_element_count = cp.cp_nslots;
1076f944dc77SKenneth D. Merry cesr.cesr_flags |= CESR_VOLTAGS;
1077f944dc77SKenneth D. Merry cesr.cesr_element_status = ces;
1078f944dc77SKenneth D. Merry
1079f944dc77SKenneth D. Merry if (ioctl(changer_fd, CHIOGSTATUS, (char *)&cesr) == -1) {
1080f944dc77SKenneth D. Merry free(ch_ces);
1081f944dc77SKenneth D. Merry err(1, "%s: CHIOGSTATUS", changer_name);
1082f944dc77SKenneth D. Merry }
1083f944dc77SKenneth D. Merry ces += cp.cp_nslots;
1084f944dc77SKenneth D. Merry }
1085f944dc77SKenneth D. Merry
1086f944dc77SKenneth D. Merry /* Read in the drive information */
1087f944dc77SKenneth D. Merry if (cp.cp_ndrives > 0 ) {
1088f944dc77SKenneth D. Merry
1089f944dc77SKenneth D. Merry (void) memset(&cesr, 0, sizeof(cesr));
1090f944dc77SKenneth D. Merry cesr.cesr_element_type = CHET_DT;
1091f944dc77SKenneth D. Merry cesr.cesr_element_base = 0;
1092f944dc77SKenneth D. Merry cesr.cesr_element_count = cp.cp_ndrives;
1093f944dc77SKenneth D. Merry cesr.cesr_flags |= CESR_VOLTAGS;
1094f944dc77SKenneth D. Merry cesr.cesr_element_status = ces;
1095f944dc77SKenneth D. Merry
1096f944dc77SKenneth D. Merry if (ioctl(changer_fd, CHIOGSTATUS, (char *)&cesr) == -1) {
1097f944dc77SKenneth D. Merry free(ch_ces);
1098f944dc77SKenneth D. Merry err(1, "%s: CHIOGSTATUS", changer_name);
1099f944dc77SKenneth D. Merry }
1100f944dc77SKenneth D. Merry ces += cp.cp_ndrives;
1101f944dc77SKenneth D. Merry }
1102f944dc77SKenneth D. Merry
1103f944dc77SKenneth D. Merry /* Read in the portal information */
1104f944dc77SKenneth D. Merry if (cp.cp_nportals > 0 ) {
1105f944dc77SKenneth D. Merry (void) memset(&cesr, 0, sizeof(cesr));
1106f944dc77SKenneth D. Merry cesr.cesr_element_type = CHET_IE;
1107f944dc77SKenneth D. Merry cesr.cesr_element_base = 0;
1108f944dc77SKenneth D. Merry cesr.cesr_element_count = cp.cp_nportals;
1109f944dc77SKenneth D. Merry cesr.cesr_flags |= CESR_VOLTAGS;
1110f944dc77SKenneth D. Merry cesr.cesr_element_status = ces;
1111f944dc77SKenneth D. Merry
1112f944dc77SKenneth D. Merry if (ioctl(changer_fd, CHIOGSTATUS, (char *)&cesr) == -1) {
1113f944dc77SKenneth D. Merry free(ch_ces);
1114f944dc77SKenneth D. Merry err(1, "%s: CHIOGSTATUS", changer_name);
1115f944dc77SKenneth D. Merry }
1116f944dc77SKenneth D. Merry ces += cp.cp_nportals;
1117f944dc77SKenneth D. Merry }
1118f944dc77SKenneth D. Merry
1119f944dc77SKenneth D. Merry /* Read in the picker information */
1120f944dc77SKenneth D. Merry if (cp.cp_npickers > 0) {
1121f944dc77SKenneth D. Merry (void) memset(&cesr, 0, sizeof(cesr));
1122f944dc77SKenneth D. Merry cesr.cesr_element_type = CHET_MT;
1123f944dc77SKenneth D. Merry cesr.cesr_element_base = 0;
1124f944dc77SKenneth D. Merry cesr.cesr_element_count = cp.cp_npickers;
1125f944dc77SKenneth D. Merry cesr.cesr_flags |= CESR_VOLTAGS;
1126f944dc77SKenneth D. Merry cesr.cesr_element_status = ces;
1127f944dc77SKenneth D. Merry
1128f944dc77SKenneth D. Merry if (ioctl(changer_fd, CHIOGSTATUS, (char *)&cesr) == -1) {
1129f944dc77SKenneth D. Merry free(ch_ces);
1130f944dc77SKenneth D. Merry err(1, "%s: CHIOGSTATUS", changer_name);
1131f944dc77SKenneth D. Merry }
1132f944dc77SKenneth D. Merry }
1133f944dc77SKenneth D. Merry
1134f944dc77SKenneth D. Merry /*
1135f944dc77SKenneth D. Merry * Now search the list the specified <voltag>
1136f944dc77SKenneth D. Merry */
11378550ddb2SEd Maste for (elem = 0; elem < total_elem; ++elem) {
1138f944dc77SKenneth D. Merry
1139f944dc77SKenneth D. Merry ces = &ch_ces[elem];
1140f944dc77SKenneth D. Merry
1141f944dc77SKenneth D. Merry /* Make sure we have a tape in this element */
1142f944dc77SKenneth D. Merry if ((ces->ces_flags & (CES_STATUS_ACCESS|CES_STATUS_FULL))
1143f944dc77SKenneth D. Merry != (CES_STATUS_ACCESS|CES_STATUS_FULL))
1144f944dc77SKenneth D. Merry continue;
1145f944dc77SKenneth D. Merry
1146f944dc77SKenneth D. Merry /* Check to see if it is our target */
114761620393SMike Heffner if (strcasecmp(voltag,
114861620393SMike Heffner (const char *)ces->ces_pvoltag.cv_volid) == 0) {
1149f944dc77SKenneth D. Merry *et = ces->ces_type;
1150f944dc77SKenneth D. Merry *eu = ces->ces_addr;
1151f944dc77SKenneth D. Merry ++found;
1152f944dc77SKenneth D. Merry break;
1153f944dc77SKenneth D. Merry }
1154f944dc77SKenneth D. Merry }
1155f944dc77SKenneth D. Merry if (!found) {
1156f944dc77SKenneth D. Merry errx(1, "%s: unable to locate voltag: %s", changer_name,
1157f944dc77SKenneth D. Merry voltag);
1158f944dc77SKenneth D. Merry }
1159f944dc77SKenneth D. Merry free(ch_ces);
1160f944dc77SKenneth D. Merry return;
1161f944dc77SKenneth D. Merry }
1162224c8a5bSJoerg Wunsch
1163224c8a5bSJoerg Wunsch static void
cleanup(void)11645dce647cSWarner Losh cleanup(void)
1165224c8a5bSJoerg Wunsch {
1166224c8a5bSJoerg Wunsch /* Simple enough... */
1167224c8a5bSJoerg Wunsch (void)close(changer_fd);
1168224c8a5bSJoerg Wunsch }
1169224c8a5bSJoerg Wunsch
1170224c8a5bSJoerg Wunsch static void
usage(void)11715dce647cSWarner Losh usage(void)
1172224c8a5bSJoerg Wunsch {
1173794bf053SKris Kennaway (void)fprintf(stderr, "usage: %s [-f changer] command [-<flags>] "
117455fad6bbSMark Murray "arg1 arg2 [arg3 [...]]\n", getprogname());
1175224c8a5bSJoerg Wunsch exit(1);
1176224c8a5bSJoerg Wunsch }
117721b6ee96SKenneth D. Merry
117821b6ee96SKenneth D. Merry #define UTF8CODESET "UTF-8"
117921b6ee96SKenneth D. Merry
118021b6ee96SKenneth D. Merry static void
print_designator(const char * designator,u_int8_t code_set,u_int8_t designator_length)118121b6ee96SKenneth D. Merry print_designator(const char *designator, u_int8_t code_set,
118221b6ee96SKenneth D. Merry u_int8_t designator_length)
118321b6ee96SKenneth D. Merry {
118421b6ee96SKenneth D. Merry printf(" serial number: <");
118521b6ee96SKenneth D. Merry switch (code_set) {
118621b6ee96SKenneth D. Merry case CES_CODE_SET_ASCII: {
118721b6ee96SKenneth D. Merry /*
118821b6ee96SKenneth D. Merry * The driver insures that the string is always NUL terminated.
118921b6ee96SKenneth D. Merry */
119021b6ee96SKenneth D. Merry printf("%s", designator);
119121b6ee96SKenneth D. Merry break;
119221b6ee96SKenneth D. Merry }
119321b6ee96SKenneth D. Merry case CES_CODE_SET_UTF_8: {
119421b6ee96SKenneth D. Merry char *cs_native;
119521b6ee96SKenneth D. Merry
119621b6ee96SKenneth D. Merry setlocale(LC_ALL, "");
119721b6ee96SKenneth D. Merry cs_native = nl_langinfo(CODESET);
119821b6ee96SKenneth D. Merry
119921b6ee96SKenneth D. Merry /* See if we can natively print UTF-8 */
120021b6ee96SKenneth D. Merry if (strcmp(cs_native, UTF8CODESET) == 0)
120121b6ee96SKenneth D. Merry cs_native = NULL;
120221b6ee96SKenneth D. Merry
120321b6ee96SKenneth D. Merry if (cs_native == NULL) {
120421b6ee96SKenneth D. Merry /* We can natively print UTF-8, so use printf. */
120521b6ee96SKenneth D. Merry printf("%s", designator);
120621b6ee96SKenneth D. Merry } else {
120721b6ee96SKenneth D. Merry int i;
120821b6ee96SKenneth D. Merry
120921b6ee96SKenneth D. Merry /*
121021b6ee96SKenneth D. Merry * We can't natively print UTF-8. We should
121121b6ee96SKenneth D. Merry * convert it to the terminal's codeset, but that
121221b6ee96SKenneth D. Merry * requires iconv(3) and FreeBSD doesn't have
121321b6ee96SKenneth D. Merry * iconv(3) in the base system yet. So we use %XX
121421b6ee96SKenneth D. Merry * notation for non US-ASCII characters instead.
121521b6ee96SKenneth D. Merry */
121621b6ee96SKenneth D. Merry for (i = 0; i < designator_length &&
121721b6ee96SKenneth D. Merry designator[i] != '\0'; i++) {
121821b6ee96SKenneth D. Merry if ((unsigned char)designator[i] < 0x80)
121921b6ee96SKenneth D. Merry printf("%c", designator[i]);
122021b6ee96SKenneth D. Merry else
122121b6ee96SKenneth D. Merry printf("%%%02x",
122221b6ee96SKenneth D. Merry (unsigned char)designator[i]);
122321b6ee96SKenneth D. Merry }
122421b6ee96SKenneth D. Merry }
122521b6ee96SKenneth D. Merry break;
122621b6ee96SKenneth D. Merry }
122721b6ee96SKenneth D. Merry case CES_CODE_SET_BINARY: {
122821b6ee96SKenneth D. Merry int i;
122921b6ee96SKenneth D. Merry
123021b6ee96SKenneth D. Merry for (i = 0; i < designator_length; i++)
123121b6ee96SKenneth D. Merry printf("%02X%s", designator[i],
123221b6ee96SKenneth D. Merry (i == designator_length - 1) ? "" : " ");
123321b6ee96SKenneth D. Merry break;
123421b6ee96SKenneth D. Merry }
123521b6ee96SKenneth D. Merry default:
123621b6ee96SKenneth D. Merry break;
123721b6ee96SKenneth D. Merry }
123821b6ee96SKenneth D. Merry printf(">");
123921b6ee96SKenneth D. Merry }
1240