Deleted Added
full compact
chio.c (36001) chio.c (39227)
1/* $NetBSD: chio.c,v 1.6 1998/01/04 23:53:58 thorpej Exp $ */
1/*
2 * Copyright (c) 1996 Jason R. Thorpe <thorpej@and.com>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 15 unchanged lines hidden (view full) ---

24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
2/*
3 * Copyright (c) 1996 Jason R. Thorpe <thorpej@and.com>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright

--- 15 unchanged lines hidden (view full) ---

25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33/*
34 * Additional Copyright (c) 1997, by Matthew Jacob, for NASA/Ames Research Ctr.
35 */
32
36
37#include <sys/cdefs.h>
33#ifndef lint
38#ifndef lint
34static const char rcsid[] =
35 "$Id: chio.c,v 1.5 1998/05/06 06:49:56 charnier Exp $";
36#endif /* not lint */
39__COPYRIGHT("@(#) Copyright (c) 1996 Jason R. Thorpe. All rights reserved.");
40__RCSID("$NetBSD: chio.c,v 1.6 1998/01/04 23:53:58 thorpej Exp $");
41#endif
37
38#include <sys/param.h>
39#include <sys/chio.h>
40#include <err.h>
41#include <fcntl.h>
42#include <stdio.h>
43#include <stdlib.h>
44#include <string.h>
45#include <unistd.h>
46
47#include "defs.h"
48#include "pathnames.h"
49
42
43#include <sys/param.h>
44#include <sys/chio.h>
45#include <err.h>
46#include <fcntl.h>
47#include <stdio.h>
48#include <stdlib.h>
49#include <string.h>
50#include <unistd.h>
51
52#include "defs.h"
53#include "pathnames.h"
54
50static void usage __P((void));
51static void cleanup __P((void));
52static int parse_element_type __P((char *));
53static int parse_element_unit __P((char *));
54static int parse_special __P((char *));
55static int is_special __P((char *));
56static char *bits_to_string __P((int, const char *));
55extern char *__progname; /* from crt0.o */
56extern int optreset; /* from getopt.o */
57
57
58static int do_move __P((char *, int, char **));
59static int do_exchange __P((char *, int, char **));
60static int do_position __P((char *, int, char **));
61static int do_params __P((char *, int, char **));
62static int do_getpicker __P((char *, int, char **));
63static int do_setpicker __P((char *, int, char **));
64static int do_status __P((char *, int, char **));
58int main(int, char *[]);
59static void usage(void);
60static void cleanup(void);
61static int parse_element_type(char *);
62static int parse_element_unit(char *);
63static const char * element_type_name(int et);
64static int parse_special(char *);
65static int is_special(char *);
66static char *bits_to_string(int, const char *);
65
67
68static int do_move(char *, int, char **);
69static int do_exchange(char *, int, char **);
70static int do_position(char *, int, char **);
71static int do_params(char *, int, char **);
72static int do_getpicker(char *, int, char **);
73static int do_setpicker(char *, int, char **);
74static int do_status(char *, int, char **);
75static int do_ielem(char *, int, char **);
76static int do_voltag(char *, int, char **);
77
66/* Valid changer element types. */
67const struct element_type elements[] = {
68 { "picker", CHET_MT },
69 { "slot", CHET_ST },
70 { "portal", CHET_IE },
71 { "drive", CHET_DT },
72 { NULL, 0 },
73};
74
75/* Valid commands. */
76const struct changer_command commands[] = {
77 { "move", do_move },
78 { "exchange", do_exchange },
79 { "position", do_position },
80 { "params", do_params },
81 { "getpicker", do_getpicker },
82 { "setpicker", do_setpicker },
83 { "status", do_status },
78/* Valid changer element types. */
79const struct element_type elements[] = {
80 { "picker", CHET_MT },
81 { "slot", CHET_ST },
82 { "portal", CHET_IE },
83 { "drive", CHET_DT },
84 { NULL, 0 },
85};
86
87/* Valid commands. */
88const struct changer_command commands[] = {
89 { "move", do_move },
90 { "exchange", do_exchange },
91 { "position", do_position },
92 { "params", do_params },
93 { "getpicker", do_getpicker },
94 { "setpicker", do_setpicker },
95 { "status", do_status },
96 { "ielem", do_ielem },
97 { "voltag", do_voltag },
84 { NULL, 0 },
85};
86
87/* Valid special words. */
88const struct special_word specials[] = {
89 { "inv", SW_INVERT },
90 { "inv1", SW_INVERT1 },
91 { "inv2", SW_INVERT2 },
92 { NULL, 0 },
93};
94
95static int changer_fd;
96static char *changer_name;
97
98int
98 { NULL, 0 },
99};
100
101/* Valid special words. */
102const struct special_word specials[] = {
103 { "inv", SW_INVERT },
104 { "inv1", SW_INVERT1 },
105 { "inv2", SW_INVERT2 },
106 { NULL, 0 },
107};
108
109static int changer_fd;
110static char *changer_name;
111
112int
99main(argc, argv)
100 int argc;
101 char **argv;
113main(int argc, char *argv[])
102{
103 int ch, i;
104
105 while ((ch = getopt(argc, argv, "f:")) != -1) {
106 switch (ch) {
107 case 'f':
108 changer_name = optarg;
109 break;

--- 23 unchanged lines hidden (view full) ---

133
134 /* Find the specified command. */
135 for (i = 0; commands[i].cc_name != NULL; ++i)
136 if (strcmp(*argv, commands[i].cc_name) == 0)
137 break;
138 if (commands[i].cc_name == NULL)
139 errx(1, "unknown command: %s", *argv);
140
114{
115 int ch, i;
116
117 while ((ch = getopt(argc, argv, "f:")) != -1) {
118 switch (ch) {
119 case 'f':
120 changer_name = optarg;
121 break;

--- 23 unchanged lines hidden (view full) ---

145
146 /* Find the specified command. */
147 for (i = 0; commands[i].cc_name != NULL; ++i)
148 if (strcmp(*argv, commands[i].cc_name) == 0)
149 break;
150 if (commands[i].cc_name == NULL)
151 errx(1, "unknown command: %s", *argv);
152
141 /* Skip over the command name and call handler. */
142 ++argv; --argc;
143 exit ((*commands[i].cc_handler)(commands[i].cc_name, argc, argv));
153 exit((*commands[i].cc_handler)(commands[i].cc_name, argc, argv));
154 /* NOTREACHED */
144}
145
146static int
155}
156
157static int
147do_move(cname, argc, argv)
148 char *cname;
149 int argc;
150 char **argv;
158do_move(char *cname, int argc, char **argv)
151{
152 struct changer_move cmd;
153 int val;
154
155 /*
156 * On a move command, we expect the following:
157 *
158 * <from ET> <from EU> <to ET> <to EU> [inv]
159 *
160 * where ET == element type and EU == element unit.
161 */
159{
160 struct changer_move cmd;
161 int val;
162
163 /*
164 * On a move command, we expect the following:
165 *
166 * <from ET> <from EU> <to ET> <to EU> [inv]
167 *
168 * where ET == element type and EU == element unit.
169 */
170
171 ++argv; --argc;
172
162 if (argc < 4) {
163 warnx("%s: too few arguments", cname);
164 goto usage;
165 } else if (argc > 5) {
166 warnx("%s: too many arguments", cname);
167 goto usage;
168 }
173 if (argc < 4) {
174 warnx("%s: too few arguments", cname);
175 goto usage;
176 } else if (argc > 5) {
177 warnx("%s: too many arguments", cname);
178 goto usage;
179 }
169 bzero(&cmd, sizeof(cmd));
180 (void) memset(&cmd, 0, sizeof(cmd));
170
171 /* <from ET> */
172 cmd.cm_fromtype = parse_element_type(*argv);
173 ++argv; --argc;
174
175 /* <from EU> */
176 cmd.cm_fromunit = parse_element_unit(*argv);
177 ++argv; --argc;

--- 17 unchanged lines hidden (view full) ---

195 default:
196 errx(1, "%s: inappropriate modifier `%s'",
197 cname, *argv);
198 /* NOTREACHED */
199 }
200 }
201
202 /* Send command to changer. */
181
182 /* <from ET> */
183 cmd.cm_fromtype = parse_element_type(*argv);
184 ++argv; --argc;
185
186 /* <from EU> */
187 cmd.cm_fromunit = parse_element_unit(*argv);
188 ++argv; --argc;

--- 17 unchanged lines hidden (view full) ---

206 default:
207 errx(1, "%s: inappropriate modifier `%s'",
208 cname, *argv);
209 /* NOTREACHED */
210 }
211 }
212
213 /* Send command to changer. */
203 if (ioctl(changer_fd, CHIOMOVE, (char *)&cmd))
214 if (ioctl(changer_fd, CHIOMOVE, &cmd))
204 err(1, "%s: CHIOMOVE", changer_name);
205
206 return (0);
207
208 usage:
215 err(1, "%s: CHIOMOVE", changer_name);
216
217 return (0);
218
219 usage:
209 fprintf(stderr, "usage: chio %s "
210 " [inv]\n", cname);
220 (void) fprintf(stderr, "usage: %s %s "
221 "<from ET> <from EU> <to ET> <to EU> [inv]\n", __progname, cname);
211 return (1);
212}
213
214static int
222 return (1);
223}
224
225static int
215do_exchange(cname, argc, argv)
216 char *cname;
217 int argc;
218 char **argv;
226do_exchange(char *cname, int argc, char **argv)
219{
220 struct changer_exchange cmd;
221 int val;
222
223 /*
224 * On an exchange command, we expect the following:
225 *
226 * <src ET> <src EU> <dst1 ET> <dst1 EU> [<dst2 ET> <dst2 EU>] [inv1] [inv2]
227 *
228 * where ET == element type and EU == element unit.
229 */
227{
228 struct changer_exchange cmd;
229 int val;
230
231 /*
232 * On an exchange command, we expect the following:
233 *
234 * <src ET> <src EU> <dst1 ET> <dst1 EU> [<dst2 ET> <dst2 EU>] [inv1] [inv2]
235 *
236 * where ET == element type and EU == element unit.
237 */
238
239 ++argv; --argc;
240
230 if (argc < 4) {
231 warnx("%s: too few arguments", cname);
232 goto usage;
233 } else if (argc > 8) {
234 warnx("%s: too many arguments", cname);
235 goto usage;
236 }
241 if (argc < 4) {
242 warnx("%s: too few arguments", cname);
243 goto usage;
244 } else if (argc > 8) {
245 warnx("%s: too many arguments", cname);
246 goto usage;
247 }
237 bzero(&cmd, sizeof(cmd));
248 (void) memset(&cmd, 0, sizeof(cmd));
238
239 /* <src ET> */
240 cmd.ce_srctype = parse_element_type(*argv);
241 ++argv; --argc;
242
243 /* <src EU> */
244 cmd.ce_srcunit = parse_element_unit(*argv);
245 ++argv; --argc;

--- 42 unchanged lines hidden (view full) ---

288 default:
289 errx(1, "%s: inappropriate modifier `%s'",
290 cname, *argv);
291 /* NOTREACHED */
292 }
293 }
294
295 /* Send command to changer. */
249
250 /* <src ET> */
251 cmd.ce_srctype = parse_element_type(*argv);
252 ++argv; --argc;
253
254 /* <src EU> */
255 cmd.ce_srcunit = parse_element_unit(*argv);
256 ++argv; --argc;

--- 42 unchanged lines hidden (view full) ---

299 default:
300 errx(1, "%s: inappropriate modifier `%s'",
301 cname, *argv);
302 /* NOTREACHED */
303 }
304 }
305
306 /* Send command to changer. */
296 if (ioctl(changer_fd, CHIOEXCHANGE, (char *)&cmd))
307 if (ioctl(changer_fd, CHIOEXCHANGE, &cmd))
297 err(1, "%s: CHIOEXCHANGE", changer_name);
298
299 return (0);
300
301 usage:
308 err(1, "%s: CHIOEXCHANGE", changer_name);
309
310 return (0);
311
312 usage:
302 fprintf(stderr,
303 "usage: chio %s <src ET> <src EU> <dst1 ET> <dst1 EU>\n"
304 " [<dst2 ET> <dst2 EU>] [inv1] [inv2]\n", cname);
313 (void) fprintf(stderr,
314 "usage: %s %s <src ET> <src EU> <dst1 ET> <dst1 EU>\n"
315 " [<dst2 ET> <dst2 EU>] [inv1] [inv2]\n",
316 __progname, cname);
305 return (1);
306}
307
308static int
317 return (1);
318}
319
320static int
309do_position(cname, argc, argv)
310 char *cname;
311 int argc;
312 char **argv;
321do_position(char *cname, int argc, char **argv)
313{
314 struct changer_position cmd;
315 int val;
316
317 /*
318 * On a position command, we expect the following:
319 *
320 * <to ET> <to EU> [inv]
321 *
322 * where ET == element type and EU == element unit.
323 */
322{
323 struct changer_position cmd;
324 int val;
325
326 /*
327 * On a position command, we expect the following:
328 *
329 * <to ET> <to EU> [inv]
330 *
331 * where ET == element type and EU == element unit.
332 */
333
334 ++argv; --argc;
335
324 if (argc < 2) {
325 warnx("%s: too few arguments", cname);
326 goto usage;
327 } else if (argc > 3) {
328 warnx("%s: too many arguments", cname);
329 goto usage;
330 }
336 if (argc < 2) {
337 warnx("%s: too few arguments", cname);
338 goto usage;
339 } else if (argc > 3) {
340 warnx("%s: too many arguments", cname);
341 goto usage;
342 }
331 bzero(&cmd, sizeof(cmd));
343 (void) memset(&cmd, 0, sizeof(cmd));
332
333 /* <to ET> */
334 cmd.cp_type = parse_element_type(*argv);
335 ++argv; --argc;
336
337 /* <to EU> */
338 cmd.cp_unit = parse_element_unit(*argv);
339 ++argv; --argc;

--- 9 unchanged lines hidden (view full) ---

349 default:
350 errx(1, "%s: inappropriate modifier `%s'",
351 cname, *argv);
352 /* NOTREACHED */
353 }
354 }
355
356 /* Send command to changer. */
344
345 /* <to ET> */
346 cmd.cp_type = parse_element_type(*argv);
347 ++argv; --argc;
348
349 /* <to EU> */
350 cmd.cp_unit = parse_element_unit(*argv);
351 ++argv; --argc;

--- 9 unchanged lines hidden (view full) ---

361 default:
362 errx(1, "%s: inappropriate modifier `%s'",
363 cname, *argv);
364 /* NOTREACHED */
365 }
366 }
367
368 /* Send command to changer. */
357 if (ioctl(changer_fd, CHIOPOSITION, (char *)&cmd))
369 if (ioctl(changer_fd, CHIOPOSITION, &cmd))
358 err(1, "%s: CHIOPOSITION", changer_name);
359
360 return (0);
361
362 usage:
370 err(1, "%s: CHIOPOSITION", changer_name);
371
372 return (0);
373
374 usage:
363 fprintf(stderr, "usage: chio %s <to ET> <to EU> [inv]\n", cname);
375 (void) fprintf(stderr, "usage: %s %s <to ET> <to EU> [inv]\n",
376 __progname, cname);
364 return (1);
365}
366
377 return (1);
378}
379
380/* ARGSUSED */
367static int
381static int
368do_params(cname, argc, argv)
369 char *cname;
370 int argc;
371 char **argv;
382do_params(char *cname, int argc, char **argv)
372{
373 struct changer_params data;
374
375 /* No arguments to this command. */
383{
384 struct changer_params data;
385
386 /* No arguments to this command. */
387
388 ++argv; --argc;
389
376 if (argc) {
390 if (argc) {
377 warnx("%s: no arguments expected", cname);
391 warnx("%s: no arguements expected", cname);
378 goto usage;
379 }
380
381 /* Get params from changer and display them. */
392 goto usage;
393 }
394
395 /* Get params from changer and display them. */
382 bzero(&data, sizeof(data));
383 if (ioctl(changer_fd, CHIOGPARAMS, (char *)&data))
396 (void) memset(&data, 0, sizeof(data));
397 if (ioctl(changer_fd, CHIOGPARAMS, &data))
384 err(1, "%s: CHIOGPARAMS", changer_name);
385
398 err(1, "%s: CHIOGPARAMS", changer_name);
399
386 printf("%s: %d slot%s, %d drive%s, %d picker%s",
400 (void) printf("%s: %d slot%s, %d drive%s, %d picker%s",
387 changer_name,
388 data.cp_nslots, (data.cp_nslots > 1) ? "s" : "",
389 data.cp_ndrives, (data.cp_ndrives > 1) ? "s" : "",
390 data.cp_npickers, (data.cp_npickers > 1) ? "s" : "");
391 if (data.cp_nportals)
401 changer_name,
402 data.cp_nslots, (data.cp_nslots > 1) ? "s" : "",
403 data.cp_ndrives, (data.cp_ndrives > 1) ? "s" : "",
404 data.cp_npickers, (data.cp_npickers > 1) ? "s" : "");
405 if (data.cp_nportals)
392 printf(", %d portal%s", data.cp_nportals,
406 (void) printf(", %d portal%s", data.cp_nportals,
393 (data.cp_nportals > 1) ? "s" : "");
407 (data.cp_nportals > 1) ? "s" : "");
394 printf("\n%s: current picker: %d\n", changer_name, data.cp_curpicker);
395
396 return (0);
397
398 usage:
408
409 return (0);
410
411 usage:
399 fprintf(stderr, "usage: chio %s\n", cname);
412 (void) fprintf(stderr, "usage: %s %s\n", __progname, cname);
400 return (1);
401}
402
413 return (1);
414}
415
416/* ARGSUSED */
403static int
417static int
404do_getpicker(cname, argc, argv)
405 char *cname;
406 int argc;
407 char **argv;
418do_getpicker(char *cname, int argc, char **argv)
408{
409 int picker;
410
411 /* No arguments to this command. */
419{
420 int picker;
421
422 /* No arguments to this command. */
423
424 ++argv; --argc;
425
412 if (argc) {
413 warnx("%s: no arguments expected", cname);
414 goto usage;
415 }
416
417 /* Get current picker from changer and display it. */
426 if (argc) {
427 warnx("%s: no arguments expected", cname);
428 goto usage;
429 }
430
431 /* Get current picker from changer and display it. */
418 if (ioctl(changer_fd, CHIOGPICKER, (char *)&picker))
432 if (ioctl(changer_fd, CHIOGPICKER, &picker))
419 err(1, "%s: CHIOGPICKER", changer_name);
420
433 err(1, "%s: CHIOGPICKER", changer_name);
434
421 printf("%s: current picker: %d\n", changer_name, picker);
435 (void) printf("%s: current picker: %d\n", changer_name, picker);
422
423 return (0);
424
425 usage:
436
437 return (0);
438
439 usage:
426 fprintf(stderr, "usage: chio %s\n", cname);
440 (void) fprintf(stderr, "usage: %s %s\n", __progname, cname);
427 return (1);
428}
429
430static int
441 return (1);
442}
443
444static int
431do_setpicker(cname, argc, argv)
432 char *cname;
433 int argc;
434 char **argv;
445do_setpicker(char *cname, int argc, char **argv)
435{
436 int picker;
437
446{
447 int picker;
448
449 ++argv; --argc;
450
438 if (argc < 1) {
439 warnx("%s: too few arguments", cname);
440 goto usage;
441 } else if (argc > 1) {
442 warnx("%s: too many arguments", cname);
443 goto usage;
444 }
445
446 picker = parse_element_unit(*argv);
447
448 /* Set the changer picker. */
451 if (argc < 1) {
452 warnx("%s: too few arguments", cname);
453 goto usage;
454 } else if (argc > 1) {
455 warnx("%s: too many arguments", cname);
456 goto usage;
457 }
458
459 picker = parse_element_unit(*argv);
460
461 /* Set the changer picker. */
449 if (ioctl(changer_fd, CHIOSPICKER, (char *)&picker))
462 if (ioctl(changer_fd, CHIOSPICKER, &picker))
450 err(1, "%s: CHIOSPICKER", changer_name);
451
452 return (0);
453
454 usage:
463 err(1, "%s: CHIOSPICKER", changer_name);
464
465 return (0);
466
467 usage:
455 fprintf(stderr, "usage: chio %s <picker>\n", cname);
468 (void) fprintf(stderr, "usage: %s %s <picker>\n", __progname, cname);
456 return (1);
457}
458
459static int
469 return (1);
470}
471
472static int
460do_status(cname, argc, argv)
461 char *cname;
462 int argc;
463 char **argv;
473do_status(char *cname, int argc, char **argv)
464{
474{
465 struct changer_element_status cmd;
466 struct changer_params data;
467 u_int8_t *statusp;
468 int i, count, chet, schet, echet;
475 struct changer_params cp;
476 struct changer_element_status_request cesr;
477 int i, count, base, chet, schet, echet;
469 char *description;
478 char *description;
479 int pvoltag = 0;
480 int avoltag = 0;
481 int sense = 0;
482 int scsi = 0;
483 int source = 0;
484 int intaddr = 0;
485 int c;
470
471 count = 0;
486
487 count = 0;
488 base = 0;
472 description = NULL;
473
489 description = NULL;
490
491 optind = optreset = 1;
492 while ((c = getopt(argc, argv, "vVsSbaI")) != EOF) {
493 switch (c) {
494 case 'v':
495 pvoltag = 1;
496 break;
497 case 'V':
498 avoltag = 1;
499 break;
500 case 's':
501 sense = 1;
502 break;
503 case 'S':
504 source = 1;
505 break;
506 case 'b':
507 scsi = 1;
508 break;
509 case 'I':
510 intaddr = 1;
511 break;
512 case 'a':
513 pvoltag = avoltag = source = sense = scsi = intaddr = 1;
514 break;
515 default:
516 warnx("bad option", cname);
517 goto usage;
518 }
519 }
520
521 argc -= optind;
522 argv += optind;
523
474 /*
475 * On a status command, we expect the following:
476 *
524 /*
525 * On a status command, we expect the following:
526 *
477 * []
527 * [<ET> [<start> [<end>] ] ]
478 *
528 *
479 * where ET == element type.
529 * where ET == element type, start == first element to report,
530 * end == number of elements to report
480 *
481 * If we get no arguments, we get the status of all
482 * known element types.
483 */
531 *
532 * If we get no arguments, we get the status of all
533 * known element types.
534 */
484 if (argc > 1) {
535 if (argc > 3) {
485 warnx("%s: too many arguments", cname);
486 goto usage;
487 }
488
489 /*
490 * Get params from changer. Specifically, we need the element
491 * counts.
492 */
536 warnx("%s: too many arguments", cname);
537 goto usage;
538 }
539
540 /*
541 * Get params from changer. Specifically, we need the element
542 * counts.
543 */
493 bzero(&data, sizeof(data));
494 if (ioctl(changer_fd, CHIOGPARAMS, (char *)&data))
544 if (ioctl(changer_fd, CHIOGPARAMS, (char *)&cp))
495 err(1, "%s: CHIOGPARAMS", changer_name);
496
545 err(1, "%s: CHIOGPARAMS", changer_name);
546
497 if (argc)
498 schet = echet = parse_element_type(*argv);
547 if (argc > 0)
548 schet = echet = parse_element_type(argv[0]);
499 else {
500 schet = CHET_MT;
501 echet = CHET_DT;
502 }
549 else {
550 schet = CHET_MT;
551 echet = CHET_DT;
552 }
553 if (argc > 1) {
554 base = atol(argv[1]);
555 count = 1;
556 }
557 if (argc > 2)
558 count = atol(argv[2]) - base + 1;
503
559
560 if (base < 0 || count < 0)
561 errx(1, "bad arguments");
562
504 for (chet = schet; chet <= echet; ++chet) {
505 switch (chet) {
506 case CHET_MT:
563 for (chet = schet; chet <= echet; ++chet) {
564 switch (chet) {
565 case CHET_MT:
507 count = data.cp_npickers;
566 if (count == 0)
567 count = cp.cp_npickers;
568 else if (count > cp.cp_npickers)
569 errx(1, "not that many pickers in device");
508 description = "picker";
509 break;
510
511 case CHET_ST:
570 description = "picker";
571 break;
572
573 case CHET_ST:
512 count = data.cp_nslots;
574 if (count == 0)
575 count = cp.cp_nslots;
576 else if (count > cp.cp_nslots)
577 errx(1, "not that many slots in device");
513 description = "slot";
514 break;
515
516 case CHET_IE:
578 description = "slot";
579 break;
580
581 case CHET_IE:
517 count = data.cp_nportals;
582 if (count == 0)
583 count = cp.cp_nportals;
584 else if (count > cp.cp_nportals)
585 errx(1, "not that many portals in device");
518 description = "portal";
519 break;
520
521 case CHET_DT:
586 description = "portal";
587 break;
588
589 case CHET_DT:
522 count = data.cp_ndrives;
590 if (count == 0)
591 count = cp.cp_ndrives;
592 else if (count > cp.cp_ndrives)
593 errx(1, "not that many drives in device");
523 description = "drive";
524 break;
594 description = "drive";
595 break;
596
597 default:
598 /* To appease gcc -Wuninitialized. */
599 count = 0;
600 description = NULL;
525 }
526
527 if (count == 0) {
528 if (argc == 0)
529 continue;
530 else {
531 printf("%s: no %s elements\n",
532 changer_name, description);
533 return (0);
534 }
535 }
536
601 }
602
603 if (count == 0) {
604 if (argc == 0)
605 continue;
606 else {
607 printf("%s: no %s elements\n",
608 changer_name, description);
609 return (0);
610 }
611 }
612
537 /* Allocate storage for the status bytes. */
538 if ((statusp = (u_int8_t *)malloc(count)) == NULL)
613 bzero(&cesr, sizeof(cesr));
614 cesr.cesr_element_type = chet;
615 cesr.cesr_element_base = base;
616 cesr.cesr_element_count = count;
617 /* Allocate storage for the status structures. */
618 cesr.cesr_element_status
619 = (struct changer_element_status *)
620 malloc(count * sizeof(struct changer_element_status));
621
622 if (!cesr.cesr_element_status)
539 errx(1, "can't allocate status storage");
540
623 errx(1, "can't allocate status storage");
624
541 bzero(statusp, count);
542 bzero(&cmd, sizeof(cmd));
625 if (avoltag || pvoltag)
626 cesr.cesr_flags |= CESR_VOLTAGS;
543
627
544 cmd.ces_type = chet;
545 cmd.ces_data = statusp;
546
547 if (ioctl(changer_fd, CHIOGSTATUS, (char *)&cmd)) {
548 free(statusp);
628 if (ioctl(changer_fd, CHIOGSTATUS, (char *)&cesr)) {
629 free(cesr.cesr_element_status);
549 err(1, "%s: CHIOGSTATUS", changer_name);
550 }
551
630 err(1, "%s: CHIOGSTATUS", changer_name);
631 }
632
552 /* Dump the status for each element of this type. */
633 /* Dump the status for each reported element. */
553 for (i = 0; i < count; ++i) {
634 for (i = 0; i < count; ++i) {
554 printf("%s %d: %s\n", description, i,
555 bits_to_string(statusp[i], CESTATUS_BITS));
635 struct changer_element_status *ces =
636 &(cesr.cesr_element_status[i]);
637 printf("%s %d: %s", description, ces->ces_addr,
638 bits_to_string(ces->ces_flags,
639 CESTATUS_BITS));
640 if (sense)
641 printf(" sense: <0x%02x/0x%02x>",
642 ces->ces_sensecode,
643 ces->ces_sensequal);
644 if (pvoltag)
645 printf(" voltag: <%s:%d>",
646 ces->ces_pvoltag.cv_volid,
647 ces->ces_pvoltag.cv_serial);
648 if (avoltag)
649 printf(" avoltag: <%s:%d>",
650 ces->ces_avoltag.cv_volid,
651 ces->ces_avoltag.cv_serial);
652 if (source)
653 if (ces->ces_flags & CES_SOURCE_VALID)
654 printf(" source: <%s %d>",
655 element_type_name(
656 ces->ces_source_type),
657 ces->ces_source_addr);
658 else
659 printf(" source: <>");
660 if (intaddr)
661 printf(" intaddr: <%d>", ces->ces_int_addr);
662 if (scsi) {
663 printf(" scsi: <");
664 if (ces->ces_flags & CES_SCSIID_VALID)
665 printf("%d", ces->ces_scsi_id);
666 else
667 putchar('?');
668 putchar(':');
669 if (ces->ces_flags & CES_LUN_VALID)
670 printf("%d", ces->ces_scsi_lun);
671 else
672 putchar('?');
673 putchar('>');
674 }
675 putchar('\n');
556 }
557
676 }
677
558 free(statusp);
678 free(cesr.cesr_element_status);
679 count = 0;
559 }
560
561 return (0);
562
563 usage:
680 }
681
682 return (0);
683
684 usage:
564 fprintf(stderr, "usage: chio %s [<element type>]\n", cname);
685 (void) fprintf(stderr, "usage: %s %s [-vVsSbaA] [<element type> [<start-addr> [<end-addr>] ] ]\n",
686 __progname, cname);
565 return (1);
566}
567
568static int
687 return (1);
688}
689
690static int
569parse_element_type(cp)
570 char *cp;
691do_ielem(char *cname, int argc, char **argv)
571{
692{
693 int timeout = 0;
694
695 if (argc == 2) {
696 timeout = atol(argv[1]);
697 } else if (argc > 1) {
698 warnx("%s: too many arguments", cname);
699 goto usage;
700 }
701
702 if (ioctl(changer_fd, CHIOIELEM, &timeout))
703 err(1, "%s: CHIOIELEM", changer_name);
704
705 return (0);
706
707 usage:
708 (void) fprintf(stderr, "usage: %s %s [<timeout>]\n",
709 __progname, cname);
710 return (1);
711}
712
713static int
714do_voltag(char *cname, int argc, char **argv)
715{
716 int force = 0;
717 int clear = 0;
718 int alternate = 0;
719 int c;
720 struct changer_set_voltag_request csvr;
721
722 bzero(&csvr, sizeof(csvr));
723
724 optind = optreset = 1;
725 while ((c = getopt(argc, argv, "fca")) != EOF) {
726 switch (c) {
727 case 'f':
728 force = 1;
729 break;
730 case 'c':
731 clear = 1;
732 break;
733 case 'a':
734 alternate = 1;
735 break;
736 default:
737 warnx("bad option", cname);
738 goto usage;
739 }
740 }
741
742 argc -= optind;
743 argv += optind;
744
745 if (argc < 2) {
746 warnx("missing element specification", cname);
747 goto usage;
748 }
749
750 csvr.csvr_type = parse_element_type(argv[0]);
751 csvr.csvr_addr = atol(argv[1]);
752
753 if (!clear) {
754 if (argc < 3 || argc > 4) {
755 warnx("missing argument", cname);
756 goto usage;
757 }
758
759 if (force)
760 csvr.csvr_flags = CSVR_MODE_REPLACE;
761 else
762 csvr.csvr_flags = CSVR_MODE_SET;
763
764 if (strlen(argv[2]) > sizeof(csvr.csvr_voltag.cv_volid)) {
765 warnx("volume label too long", cname);
766 goto usage;
767 }
768
769 strncpy(csvr.csvr_voltag.cv_volid, argv[2],
770 sizeof(csvr.csvr_voltag.cv_volid));
771
772 if (argc == 4) {
773 csvr.csvr_voltag.cv_serial = atol(argv[3]);
774 }
775 } else {
776 if (argc != 2) {
777 warnx("unexpected argument", cname);
778 goto usage;
779 }
780 csvr.csvr_flags = CSVR_MODE_CLEAR;
781 }
782
783 if (alternate) {
784 csvr.csvr_flags |= CSVR_ALTERNATE;
785 }
786
787 if (ioctl(changer_fd, CHIOSETVOLTAG, &csvr))
788 err(1, "%s: CHIOSETVOLTAG", changer_name);
789
790 return 0;
791 usage:
792 (void) fprintf(stderr,
793 "usage: %s %s [-fca] <element> [<voltag> [<vsn>] ]\n",
794 __progname, cname);
795 return 1;
796}
797
798static int
799parse_element_type(char *cp)
800{
572 int i;
573
574 for (i = 0; elements[i].et_name != NULL; ++i)
575 if (strcmp(elements[i].et_name, cp) == 0)
576 return (elements[i].et_type);
577
578 errx(1, "invalid element type `%s'", cp);
801 int i;
802
803 for (i = 0; elements[i].et_name != NULL; ++i)
804 if (strcmp(elements[i].et_name, cp) == 0)
805 return (elements[i].et_type);
806
807 errx(1, "invalid element type `%s'", cp);
808 /* NOTREACHED */
579}
580
809}
810
811static const char *
812element_type_name(int et)
813{
814 int i;
815
816 for (i = 0; elements[i].et_name != NULL; i++)
817 if (elements[i].et_type == et)
818 return elements[i].et_name;
819
820 return "unknown";
821}
822
581static int
823static int
582parse_element_unit(cp)
583 char *cp;
824parse_element_unit(char *cp)
584{
585 int i;
586 char *p;
587
588 i = (int)strtol(cp, &p, 10);
589 if ((i < 0) || (*p != '\0'))
590 errx(1, "invalid unit number `%s'", cp);
591
592 return (i);
593}
594
595static int
825{
826 int i;
827 char *p;
828
829 i = (int)strtol(cp, &p, 10);
830 if ((i < 0) || (*p != '\0'))
831 errx(1, "invalid unit number `%s'", cp);
832
833 return (i);
834}
835
836static int
596parse_special(cp)
597 char *cp;
837parse_special(char *cp)
598{
599 int val;
600
601 val = is_special(cp);
602 if (val)
603 return (val);
604
605 errx(1, "invalid modifier `%s'", cp);
838{
839 int val;
840
841 val = is_special(cp);
842 if (val)
843 return (val);
844
845 errx(1, "invalid modifier `%s'", cp);
846 /* NOTREACHED */
606}
607
608static int
847}
848
849static int
609is_special(cp)
610 char *cp;
850is_special(char *cp)
611{
612 int i;
613
614 for (i = 0; specials[i].sw_name != NULL; ++i)
615 if (strcmp(specials[i].sw_name, cp) == 0)
616 return (specials[i].sw_value);
617
618 return (0);
619}
620
621static char *
851{
852 int i;
853
854 for (i = 0; specials[i].sw_name != NULL; ++i)
855 if (strcmp(specials[i].sw_name, cp) == 0)
856 return (specials[i].sw_value);
857
858 return (0);
859}
860
861static char *
622bits_to_string(v, cp)
623 int v;
624 const char *cp;
862bits_to_string(int v, const char *cp)
625{
626 const char *np;
627 char f, sep, *bp;
628 static char buf[128];
629
630 bp = buf;
863{
864 const char *np;
865 char f, sep, *bp;
866 static char buf[128];
867
868 bp = buf;
631 bzero(buf, sizeof(buf));
869 (void) memset(buf, 0, sizeof(buf));
632
633 for (sep = '<'; (f = *cp++) != 0; cp = np) {
634 for (np = cp; *np >= ' ';)
635 np++;
636 if ((v & (1 << (f - 1))) == 0)
637 continue;
870
871 for (sep = '<'; (f = *cp++) != 0; cp = np) {
872 for (np = cp; *np >= ' ';)
873 np++;
874 if ((v & (1 << (f - 1))) == 0)
875 continue;
638 bp += snprintf(bp, sizeof(buf) - (bp - &buf[0]),
639 "%c%.*s", sep, np - cp, cp);
876 bp += sprintf(bp, "%c%.*s", sep, (int)(long)(np - cp), cp);
640 sep = ',';
641 }
642 if (sep != '<')
643 *bp = '>';
644
645 return (buf);
646}
647
648static void
649cleanup()
650{
877 sep = ',';
878 }
879 if (sep != '<')
880 *bp = '>';
881
882 return (buf);
883}
884
885static void
886cleanup()
887{
651
652 /* Simple enough... */
653 (void)close(changer_fd);
654}
655
656static void
657usage()
658{
888 /* Simple enough... */
889 (void)close(changer_fd);
890}
891
892static void
893usage()
894{
659 int i;
660
895
661 fprintf(stderr, "usage: chio [-f changer] command [args ...]\n");
662 fprintf(stderr, "commands:");
663 for (i = 0; commands[i].cc_name; i++)
664 fprintf(stderr, " %s", commands[i].cc_name);
665 fprintf(stderr, "\n");
896 (void) fprintf(stderr, "usage: %s command arg1 arg2 ...\n", __progname);
897 (void) fprintf(stderr, "Examples:\n");
898 (void) fprintf(stderr, "\tchio -f /dev/ch0 move slot 1 drive 0\n");
899 (void) fprintf(stderr, "\tchio ielem\n");
900 (void) fprintf(stderr, "\tchio -f /dev/ch1 status\n");
666 exit(1);
667}
901 exit(1);
902}