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 " | 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} |