summaryrefslogtreecommitdiffstats
path: root/bin/chio/chio.c
diff options
context:
space:
mode:
Diffstat (limited to 'bin/chio/chio.c')
-rw-r--r--bin/chio/chio.c487
1 files changed, 361 insertions, 126 deletions
diff --git a/bin/chio/chio.c b/bin/chio/chio.c
index 7488e7a..c2da513 100644
--- a/bin/chio/chio.c
+++ b/bin/chio/chio.c
@@ -1,3 +1,4 @@
+/* $NetBSD: chio.c,v 1.6 1998/01/04 23:53:58 thorpej Exp $ */
/*
* Copyright (c) 1996 Jason R. Thorpe <thorpej@and.com>
* All rights reserved.
@@ -29,11 +30,15 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
+/*
+ * Additional Copyright (c) 1997, by Matthew Jacob, for NASA/Ames Research Ctr.
+ */
+#include <sys/cdefs.h>
#ifndef lint
-static const char rcsid[] =
- "$Id: chio.c,v 1.5 1998/05/06 06:49:56 charnier Exp $";
-#endif /* not lint */
+__COPYRIGHT("@(#) Copyright (c) 1996 Jason R. Thorpe. All rights reserved.");
+__RCSID("$NetBSD: chio.c,v 1.6 1998/01/04 23:53:58 thorpej Exp $");
+#endif
#include <sys/param.h>
#include <sys/chio.h>
@@ -47,21 +52,28 @@ static const char rcsid[] =
#include "defs.h"
#include "pathnames.h"
-static void usage __P((void));
-static void cleanup __P((void));
-static int parse_element_type __P((char *));
-static int parse_element_unit __P((char *));
-static int parse_special __P((char *));
-static int is_special __P((char *));
-static char *bits_to_string __P((int, const char *));
-
-static int do_move __P((char *, int, char **));
-static int do_exchange __P((char *, int, char **));
-static int do_position __P((char *, int, char **));
-static int do_params __P((char *, int, char **));
-static int do_getpicker __P((char *, int, char **));
-static int do_setpicker __P((char *, int, char **));
-static int do_status __P((char *, int, char **));
+extern char *__progname; /* from crt0.o */
+extern int optreset; /* from getopt.o */
+
+int main(int, char *[]);
+static void usage(void);
+static void cleanup(void);
+static int parse_element_type(char *);
+static int parse_element_unit(char *);
+static const char * element_type_name(int et);
+static int parse_special(char *);
+static int is_special(char *);
+static char *bits_to_string(int, const char *);
+
+static int do_move(char *, int, char **);
+static int do_exchange(char *, int, char **);
+static int do_position(char *, int, char **);
+static int do_params(char *, int, char **);
+static int do_getpicker(char *, int, char **);
+static int do_setpicker(char *, int, char **);
+static int do_status(char *, int, char **);
+static int do_ielem(char *, int, char **);
+static int do_voltag(char *, int, char **);
/* Valid changer element types. */
const struct element_type elements[] = {
@@ -81,6 +93,8 @@ const struct changer_command commands[] = {
{ "getpicker", do_getpicker },
{ "setpicker", do_setpicker },
{ "status", do_status },
+ { "ielem", do_ielem },
+ { "voltag", do_voltag },
{ NULL, 0 },
};
@@ -96,9 +110,7 @@ static int changer_fd;
static char *changer_name;
int
-main(argc, argv)
- int argc;
- char **argv;
+main(int argc, char *argv[])
{
int ch, i;
@@ -138,16 +150,12 @@ main(argc, argv)
if (commands[i].cc_name == NULL)
errx(1, "unknown command: %s", *argv);
- /* Skip over the command name and call handler. */
- ++argv; --argc;
- exit ((*commands[i].cc_handler)(commands[i].cc_name, argc, argv));
+ exit((*commands[i].cc_handler)(commands[i].cc_name, argc, argv));
+ /* NOTREACHED */
}
static int
-do_move(cname, argc, argv)
- char *cname;
- int argc;
- char **argv;
+do_move(char *cname, int argc, char **argv)
{
struct changer_move cmd;
int val;
@@ -159,6 +167,9 @@ do_move(cname, argc, argv)
*
* where ET == element type and EU == element unit.
*/
+
+ ++argv; --argc;
+
if (argc < 4) {
warnx("%s: too few arguments", cname);
goto usage;
@@ -166,7 +177,7 @@ do_move(cname, argc, argv)
warnx("%s: too many arguments", cname);
goto usage;
}
- bzero(&cmd, sizeof(cmd));
+ (void) memset(&cmd, 0, sizeof(cmd));
/* <from ET> */
cmd.cm_fromtype = parse_element_type(*argv);
@@ -200,22 +211,19 @@ do_move(cname, argc, argv)
}
/* Send command to changer. */
- if (ioctl(changer_fd, CHIOMOVE, (char *)&cmd))
+ if (ioctl(changer_fd, CHIOMOVE, &cmd))
err(1, "%s: CHIOMOVE", changer_name);
return (0);
usage:
- fprintf(stderr, "usage: chio %s "
- "<from ET> <from EU> <to ET> <to EU> [inv]\n", cname);
+ (void) fprintf(stderr, "usage: %s %s "
+ "<from ET> <from EU> <to ET> <to EU> [inv]\n", __progname, cname);
return (1);
}
static int
-do_exchange(cname, argc, argv)
- char *cname;
- int argc;
- char **argv;
+do_exchange(char *cname, int argc, char **argv)
{
struct changer_exchange cmd;
int val;
@@ -227,6 +235,9 @@ do_exchange(cname, argc, argv)
*
* where ET == element type and EU == element unit.
*/
+
+ ++argv; --argc;
+
if (argc < 4) {
warnx("%s: too few arguments", cname);
goto usage;
@@ -234,7 +245,7 @@ do_exchange(cname, argc, argv)
warnx("%s: too many arguments", cname);
goto usage;
}
- bzero(&cmd, sizeof(cmd));
+ (void) memset(&cmd, 0, sizeof(cmd));
/* <src ET> */
cmd.ce_srctype = parse_element_type(*argv);
@@ -293,23 +304,21 @@ do_exchange(cname, argc, argv)
}
/* Send command to changer. */
- if (ioctl(changer_fd, CHIOEXCHANGE, (char *)&cmd))
+ if (ioctl(changer_fd, CHIOEXCHANGE, &cmd))
err(1, "%s: CHIOEXCHANGE", changer_name);
return (0);
usage:
- fprintf(stderr,
- "usage: chio %s <src ET> <src EU> <dst1 ET> <dst1 EU>\n"
- " [<dst2 ET> <dst2 EU>] [inv1] [inv2]\n", cname);
+ (void) fprintf(stderr,
+ "usage: %s %s <src ET> <src EU> <dst1 ET> <dst1 EU>\n"
+ " [<dst2 ET> <dst2 EU>] [inv1] [inv2]\n",
+ __progname, cname);
return (1);
}
static int
-do_position(cname, argc, argv)
- char *cname;
- int argc;
- char **argv;
+do_position(char *cname, int argc, char **argv)
{
struct changer_position cmd;
int val;
@@ -321,6 +330,9 @@ do_position(cname, argc, argv)
*
* where ET == element type and EU == element unit.
*/
+
+ ++argv; --argc;
+
if (argc < 2) {
warnx("%s: too few arguments", cname);
goto usage;
@@ -328,7 +340,7 @@ do_position(cname, argc, argv)
warnx("%s: too many arguments", cname);
goto usage;
}
- bzero(&cmd, sizeof(cmd));
+ (void) memset(&cmd, 0, sizeof(cmd));
/* <to ET> */
cmd.cp_type = parse_element_type(*argv);
@@ -354,87 +366,88 @@ do_position(cname, argc, argv)
}
/* Send command to changer. */
- if (ioctl(changer_fd, CHIOPOSITION, (char *)&cmd))
+ if (ioctl(changer_fd, CHIOPOSITION, &cmd))
err(1, "%s: CHIOPOSITION", changer_name);
return (0);
usage:
- fprintf(stderr, "usage: chio %s <to ET> <to EU> [inv]\n", cname);
+ (void) fprintf(stderr, "usage: %s %s <to ET> <to EU> [inv]\n",
+ __progname, cname);
return (1);
}
+/* ARGSUSED */
static int
-do_params(cname, argc, argv)
- char *cname;
- int argc;
- char **argv;
+do_params(char *cname, int argc, char **argv)
{
struct changer_params data;
/* No arguments to this command. */
+
+ ++argv; --argc;
+
if (argc) {
- warnx("%s: no arguments expected", cname);
+ warnx("%s: no arguements expected", cname);
goto usage;
}
/* Get params from changer and display them. */
- bzero(&data, sizeof(data));
- if (ioctl(changer_fd, CHIOGPARAMS, (char *)&data))
+ (void) memset(&data, 0, sizeof(data));
+ if (ioctl(changer_fd, CHIOGPARAMS, &data))
err(1, "%s: CHIOGPARAMS", changer_name);
- printf("%s: %d slot%s, %d drive%s, %d picker%s",
+ (void) printf("%s: %d slot%s, %d drive%s, %d picker%s",
changer_name,
data.cp_nslots, (data.cp_nslots > 1) ? "s" : "",
data.cp_ndrives, (data.cp_ndrives > 1) ? "s" : "",
data.cp_npickers, (data.cp_npickers > 1) ? "s" : "");
if (data.cp_nportals)
- printf(", %d portal%s", data.cp_nportals,
+ (void) printf(", %d portal%s", data.cp_nportals,
(data.cp_nportals > 1) ? "s" : "");
- printf("\n%s: current picker: %d\n", changer_name, data.cp_curpicker);
return (0);
usage:
- fprintf(stderr, "usage: chio %s\n", cname);
+ (void) fprintf(stderr, "usage: %s %s\n", __progname, cname);
return (1);
}
+/* ARGSUSED */
static int
-do_getpicker(cname, argc, argv)
- char *cname;
- int argc;
- char **argv;
+do_getpicker(char *cname, int argc, char **argv)
{
int picker;
/* No arguments to this command. */
+
+ ++argv; --argc;
+
if (argc) {
warnx("%s: no arguments expected", cname);
goto usage;
}
/* Get current picker from changer and display it. */
- if (ioctl(changer_fd, CHIOGPICKER, (char *)&picker))
+ if (ioctl(changer_fd, CHIOGPICKER, &picker))
err(1, "%s: CHIOGPICKER", changer_name);
- printf("%s: current picker: %d\n", changer_name, picker);
+ (void) printf("%s: current picker: %d\n", changer_name, picker);
return (0);
usage:
- fprintf(stderr, "usage: chio %s\n", cname);
+ (void) fprintf(stderr, "usage: %s %s\n", __progname, cname);
return (1);
}
static int
-do_setpicker(cname, argc, argv)
- char *cname;
- int argc;
- char **argv;
+do_setpicker(char *cname, int argc, char **argv)
{
int picker;
+ ++argv; --argc;
+
if (argc < 1) {
warnx("%s: too few arguments", cname);
goto usage;
@@ -446,42 +459,80 @@ do_setpicker(cname, argc, argv)
picker = parse_element_unit(*argv);
/* Set the changer picker. */
- if (ioctl(changer_fd, CHIOSPICKER, (char *)&picker))
+ if (ioctl(changer_fd, CHIOSPICKER, &picker))
err(1, "%s: CHIOSPICKER", changer_name);
return (0);
usage:
- fprintf(stderr, "usage: chio %s <picker>\n", cname);
+ (void) fprintf(stderr, "usage: %s %s <picker>\n", __progname, cname);
return (1);
}
static int
-do_status(cname, argc, argv)
- char *cname;
- int argc;
- char **argv;
+do_status(char *cname, int argc, char **argv)
{
- struct changer_element_status cmd;
- struct changer_params data;
- u_int8_t *statusp;
- int i, count, chet, schet, echet;
+ struct changer_params cp;
+ struct changer_element_status_request cesr;
+ int i, count, base, chet, schet, echet;
char *description;
+ int pvoltag = 0;
+ int avoltag = 0;
+ int sense = 0;
+ int scsi = 0;
+ int source = 0;
+ int intaddr = 0;
+ int c;
count = 0;
+ base = 0;
description = NULL;
+ optind = optreset = 1;
+ while ((c = getopt(argc, argv, "vVsSbaI")) != EOF) {
+ switch (c) {
+ case 'v':
+ pvoltag = 1;
+ break;
+ case 'V':
+ avoltag = 1;
+ break;
+ case 's':
+ sense = 1;
+ break;
+ case 'S':
+ source = 1;
+ break;
+ case 'b':
+ scsi = 1;
+ break;
+ case 'I':
+ intaddr = 1;
+ break;
+ case 'a':
+ pvoltag = avoltag = source = sense = scsi = intaddr = 1;
+ break;
+ default:
+ warnx("bad option", cname);
+ goto usage;
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
/*
* On a status command, we expect the following:
*
- * [<ET>]
+ * [<ET> [<start> [<end>] ] ]
*
- * where ET == element type.
+ * where ET == element type, start == first element to report,
+ * end == number of elements to report
*
* If we get no arguments, we get the status of all
* known element types.
*/
- if (argc > 1) {
+ if (argc > 3) {
warnx("%s: too many arguments", cname);
goto usage;
}
@@ -490,38 +541,63 @@ do_status(cname, argc, argv)
* Get params from changer. Specifically, we need the element
* counts.
*/
- bzero(&data, sizeof(data));
- if (ioctl(changer_fd, CHIOGPARAMS, (char *)&data))
+ if (ioctl(changer_fd, CHIOGPARAMS, (char *)&cp))
err(1, "%s: CHIOGPARAMS", changer_name);
- if (argc)
- schet = echet = parse_element_type(*argv);
+ if (argc > 0)
+ schet = echet = parse_element_type(argv[0]);
else {
schet = CHET_MT;
echet = CHET_DT;
}
+ if (argc > 1) {
+ base = atol(argv[1]);
+ count = 1;
+ }
+ if (argc > 2)
+ count = atol(argv[2]) - base + 1;
+
+ if (base < 0 || count < 0)
+ errx(1, "bad arguments");
for (chet = schet; chet <= echet; ++chet) {
switch (chet) {
case CHET_MT:
- count = data.cp_npickers;
+ if (count == 0)
+ count = cp.cp_npickers;
+ else if (count > cp.cp_npickers)
+ errx(1, "not that many pickers in device");
description = "picker";
break;
case CHET_ST:
- count = data.cp_nslots;
+ if (count == 0)
+ count = cp.cp_nslots;
+ else if (count > cp.cp_nslots)
+ errx(1, "not that many slots in device");
description = "slot";
break;
case CHET_IE:
- count = data.cp_nportals;
+ if (count == 0)
+ count = cp.cp_nportals;
+ else if (count > cp.cp_nportals)
+ errx(1, "not that many portals in device");
description = "portal";
break;
case CHET_DT:
- count = data.cp_ndrives;
+ if (count == 0)
+ count = cp.cp_ndrives;
+ else if (count > cp.cp_ndrives)
+ errx(1, "not that many drives in device");
description = "drive";
break;
+
+ default:
+ /* To appease gcc -Wuninitialized. */
+ count = 0;
+ description = NULL;
}
if (count == 0) {
@@ -534,40 +610,193 @@ do_status(cname, argc, argv)
}
}
- /* Allocate storage for the status bytes. */
- if ((statusp = (u_int8_t *)malloc(count)) == NULL)
+ bzero(&cesr, sizeof(cesr));
+ cesr.cesr_element_type = chet;
+ cesr.cesr_element_base = base;
+ cesr.cesr_element_count = count;
+ /* Allocate storage for the status structures. */
+ cesr.cesr_element_status
+ = (struct changer_element_status *)
+ malloc(count * sizeof(struct changer_element_status));
+
+ if (!cesr.cesr_element_status)
errx(1, "can't allocate status storage");
- bzero(statusp, count);
- bzero(&cmd, sizeof(cmd));
-
- cmd.ces_type = chet;
- cmd.ces_data = statusp;
+ if (avoltag || pvoltag)
+ cesr.cesr_flags |= CESR_VOLTAGS;
- if (ioctl(changer_fd, CHIOGSTATUS, (char *)&cmd)) {
- free(statusp);
+ if (ioctl(changer_fd, CHIOGSTATUS, (char *)&cesr)) {
+ free(cesr.cesr_element_status);
err(1, "%s: CHIOGSTATUS", changer_name);
}
- /* Dump the status for each element of this type. */
+ /* Dump the status for each reported element. */
for (i = 0; i < count; ++i) {
- printf("%s %d: %s\n", description, i,
- bits_to_string(statusp[i], CESTATUS_BITS));
+ struct changer_element_status *ces =
+ &(cesr.cesr_element_status[i]);
+ printf("%s %d: %s", description, ces->ces_addr,
+ bits_to_string(ces->ces_flags,
+ CESTATUS_BITS));
+ if (sense)
+ printf(" sense: <0x%02x/0x%02x>",
+ ces->ces_sensecode,
+ ces->ces_sensequal);
+ if (pvoltag)
+ printf(" voltag: <%s:%d>",
+ ces->ces_pvoltag.cv_volid,
+ ces->ces_pvoltag.cv_serial);
+ if (avoltag)
+ printf(" avoltag: <%s:%d>",
+ ces->ces_avoltag.cv_volid,
+ ces->ces_avoltag.cv_serial);
+ if (source)
+ if (ces->ces_flags & CES_SOURCE_VALID)
+ printf(" source: <%s %d>",
+ element_type_name(
+ ces->ces_source_type),
+ ces->ces_source_addr);
+ else
+ printf(" source: <>");
+ if (intaddr)
+ printf(" intaddr: <%d>", ces->ces_int_addr);
+ if (scsi) {
+ printf(" scsi: <");
+ if (ces->ces_flags & CES_SCSIID_VALID)
+ printf("%d", ces->ces_scsi_id);
+ else
+ putchar('?');
+ putchar(':');
+ if (ces->ces_flags & CES_LUN_VALID)
+ printf("%d", ces->ces_scsi_lun);
+ else
+ putchar('?');
+ putchar('>');
+ }
+ putchar('\n');
}
- free(statusp);
+ free(cesr.cesr_element_status);
+ count = 0;
}
return (0);
usage:
- fprintf(stderr, "usage: chio %s [<element type>]\n", cname);
+ (void) fprintf(stderr, "usage: %s %s [-vVsSbaA] [<element type> [<start-addr> [<end-addr>] ] ]\n",
+ __progname, cname);
return (1);
}
static int
-parse_element_type(cp)
- char *cp;
+do_ielem(char *cname, int argc, char **argv)
+{
+ int timeout = 0;
+
+ if (argc == 2) {
+ timeout = atol(argv[1]);
+ } else if (argc > 1) {
+ warnx("%s: too many arguments", cname);
+ goto usage;
+ }
+
+ if (ioctl(changer_fd, CHIOIELEM, &timeout))
+ err(1, "%s: CHIOIELEM", changer_name);
+
+ return (0);
+
+ usage:
+ (void) fprintf(stderr, "usage: %s %s [<timeout>]\n",
+ __progname, cname);
+ return (1);
+}
+
+static int
+do_voltag(char *cname, int argc, char **argv)
+{
+ int force = 0;
+ int clear = 0;
+ int alternate = 0;
+ int c;
+ struct changer_set_voltag_request csvr;
+
+ bzero(&csvr, sizeof(csvr));
+
+ optind = optreset = 1;
+ while ((c = getopt(argc, argv, "fca")) != EOF) {
+ switch (c) {
+ case 'f':
+ force = 1;
+ break;
+ case 'c':
+ clear = 1;
+ break;
+ case 'a':
+ alternate = 1;
+ break;
+ default:
+ warnx("bad option", cname);
+ goto usage;
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc < 2) {
+ warnx("missing element specification", cname);
+ goto usage;
+ }
+
+ csvr.csvr_type = parse_element_type(argv[0]);
+ csvr.csvr_addr = atol(argv[1]);
+
+ if (!clear) {
+ if (argc < 3 || argc > 4) {
+ warnx("missing argument", cname);
+ goto usage;
+ }
+
+ if (force)
+ csvr.csvr_flags = CSVR_MODE_REPLACE;
+ else
+ csvr.csvr_flags = CSVR_MODE_SET;
+
+ if (strlen(argv[2]) > sizeof(csvr.csvr_voltag.cv_volid)) {
+ warnx("volume label too long", cname);
+ goto usage;
+ }
+
+ strncpy(csvr.csvr_voltag.cv_volid, argv[2],
+ sizeof(csvr.csvr_voltag.cv_volid));
+
+ if (argc == 4) {
+ csvr.csvr_voltag.cv_serial = atol(argv[3]);
+ }
+ } else {
+ if (argc != 2) {
+ warnx("unexpected argument", cname);
+ goto usage;
+ }
+ csvr.csvr_flags = CSVR_MODE_CLEAR;
+ }
+
+ if (alternate) {
+ csvr.csvr_flags |= CSVR_ALTERNATE;
+ }
+
+ if (ioctl(changer_fd, CHIOSETVOLTAG, &csvr))
+ err(1, "%s: CHIOSETVOLTAG", changer_name);
+
+ return 0;
+ usage:
+ (void) fprintf(stderr,
+ "usage: %s %s [-fca] <element> [<voltag> [<vsn>] ]\n",
+ __progname, cname);
+ return 1;
+}
+
+static int
+parse_element_type(char *cp)
{
int i;
@@ -576,11 +805,23 @@ parse_element_type(cp)
return (elements[i].et_type);
errx(1, "invalid element type `%s'", cp);
+ /* NOTREACHED */
+}
+
+static const char *
+element_type_name(int et)
+{
+ int i;
+
+ for (i = 0; elements[i].et_name != NULL; i++)
+ if (elements[i].et_type == et)
+ return elements[i].et_name;
+
+ return "unknown";
}
static int
-parse_element_unit(cp)
- char *cp;
+parse_element_unit(char *cp)
{
int i;
char *p;
@@ -593,8 +834,7 @@ parse_element_unit(cp)
}
static int
-parse_special(cp)
- char *cp;
+parse_special(char *cp)
{
int val;
@@ -603,11 +843,11 @@ parse_special(cp)
return (val);
errx(1, "invalid modifier `%s'", cp);
+ /* NOTREACHED */
}
static int
-is_special(cp)
- char *cp;
+is_special(char *cp)
{
int i;
@@ -619,24 +859,21 @@ is_special(cp)
}
static char *
-bits_to_string(v, cp)
- int v;
- const char *cp;
+bits_to_string(int v, const char *cp)
{
const char *np;
char f, sep, *bp;
static char buf[128];
bp = buf;
- bzero(buf, sizeof(buf));
+ (void) memset(buf, 0, sizeof(buf));
for (sep = '<'; (f = *cp++) != 0; cp = np) {
for (np = cp; *np >= ' ';)
np++;
if ((v & (1 << (f - 1))) == 0)
continue;
- bp += snprintf(bp, sizeof(buf) - (bp - &buf[0]),
- "%c%.*s", sep, np - cp, cp);
+ bp += sprintf(bp, "%c%.*s", sep, (int)(long)(np - cp), cp);
sep = ',';
}
if (sep != '<')
@@ -648,7 +885,6 @@ bits_to_string(v, cp)
static void
cleanup()
{
-
/* Simple enough... */
(void)close(changer_fd);
}
@@ -656,12 +892,11 @@ cleanup()
static void
usage()
{
- int i;
- fprintf(stderr, "usage: chio [-f changer] command [args ...]\n");
- fprintf(stderr, "commands:");
- for (i = 0; commands[i].cc_name; i++)
- fprintf(stderr, " %s", commands[i].cc_name);
- fprintf(stderr, "\n");
+ (void) fprintf(stderr, "usage: %s command arg1 arg2 ...\n", __progname);
+ (void) fprintf(stderr, "Examples:\n");
+ (void) fprintf(stderr, "\tchio -f /dev/ch0 move slot 1 drive 0\n");
+ (void) fprintf(stderr, "\tchio ielem\n");
+ (void) fprintf(stderr, "\tchio -f /dev/ch1 status\n");
exit(1);
}
OpenPOWER on IntegriCloud