summaryrefslogtreecommitdiffstats
path: root/bin
diff options
context:
space:
mode:
authorken <ken@FreeBSD.org>2000-09-18 06:09:11 +0000
committerken <ken@FreeBSD.org>2000-09-18 06:09:11 +0000
commit91f91457a7cc308612accc12b3d87ddeb05c41bf (patch)
treeeb5e49d0b5963b35d0d810ba620fdccebc6d9e57 /bin
parent3dc41a81fd679aa0d272ceae39c4afe5b8501055 (diff)
downloadFreeBSD-src-91f91457a7cc308612accc12b3d87ddeb05c41bf.zip
FreeBSD-src-91f91457a7cc308612accc12b3d87ddeb05c41bf.tar.gz
Add two new features to chio(1):
- The ability to specify elements by volume tag instead of their actual physical location. e.g., instead of: chio move slot 3 slot 4 you would now use: chio move voltag FOO slot 4 - The ability to return an element to its previous location, as specified by the source element. e.g., instead of: chio move drive 0 slot 4 you would now use: chio return drive 0 or chio return voltag FOO These features will obviously only work with changers that support volume tags and/or source element IDs. chio(1) should fail gracefully if the user attempts to use these new features and the source element ID or volume tag are not found. PR: bin/21178 Submitted by: "C. Stephen Gunn" <csg@waterspout.com> Reviewed by: ken
Diffstat (limited to 'bin')
-rw-r--r--bin/chio/chio.136
-rw-r--r--bin/chio/chio.c283
2 files changed, 304 insertions, 15 deletions
diff --git a/bin/chio/chio.1 b/bin/chio/chio.1
index 34f913f..4697c9b 100644
--- a/bin/chio/chio.1
+++ b/bin/chio/chio.1
@@ -69,20 +69,27 @@ to the desired changer device.
.Pp
A medium changer apparatus is made up of
.Em elements .
-There are four element types:
+There are five element types:
.Em picker
(medium transport),
.Em slot
(storage),
.Em portal
-(import/export), and
+(import/export),
.Em drive
-(data transfer). In this command description, the shorthand
+(data transfer), and
+.Em voltag
+(select by volume identifier). The
+.Em voltag
+pseudo-element type allows the selection of tapes by their volume tag
+(typically a barcode on the tape).
+.Pp
+In this command description, the shorthand
.Em ET
will be used to represent an element type, and
.Em EU
-will be used to represent an element unit. For example, to represent
-the first robotic arm in the changer, the
+will be used to represent an element unit.
+For example, to represent the first robotic arm in the changer, the
.Em ET
would be
.Dq picker
@@ -137,6 +144,15 @@ Note that not all medium changers support the
.Ic exchange
operation; the changer must have multiple free pickers or emulate
multiple free pickers with transient storage.
+.It Xo Nm return
+.Ar <from ET> <from EU>
+.Xc
+Return the media unit to its source element.
+This command will query the status of the specified media unit, and
+will move it to the element specified in its source attribute.
+This is a convenient way to return media from a drive or portal
+to its previous element in the changer.
+.Pp
.It Xo Nm position
.Ar <to ET> <to EU>
.Op Ar inv
@@ -246,6 +262,11 @@ Element supports receiving media (importing) from an outside human operator.
.Bl -tag -width indent
.It Nm chio move slot 3 drive 0
Move the media in slot 3 (fourth slot) to drive 0 (first drive).
+.It Nm chio move voltag VOLUME01 drive 0
+Move the media with the barcode VOLUME01 to drive 0 (first drive).
+.It Nm chio return drive 0
+Remove the tape from drive 0 (first drive) and return it to its original
+location in the rack.
.It Nm chio setpicker 2
Configure the changer to use picker 2 (third picker) for operations.
.El
@@ -265,4 +286,7 @@ program and SCSI changer driver were written by
for And Communications, http://www.and.com/.
.br
Additional work by
-.An Hans Huebner Aq hans@artcom.de
+.An Hans Huebner
+.Aq hans@artcom.de
+and Steve Gunn
+.Aq csg@waterspout.com
diff --git a/bin/chio/chio.c b/bin/chio/chio.c
index e3f6551..31b69d4 100644
--- a/bin/chio/chio.c
+++ b/bin/chio/chio.c
@@ -32,6 +32,7 @@
*/
/*
* Additional Copyright (c) 1997, by Matthew Jacob, for NASA/Ames Research Ctr.
+ * Addidional Copyright (c) 2000, by C. Stephen Gunn, Waterspout Communications
*/
#ifndef lint
@@ -64,6 +65,9 @@ static int parse_special __P((char *));
static int is_special __P((char *));
static const char *bits_to_string __P((int, const char *));
+static void find_element __P((char *, u_int16_t *, u_int16_t *));
+static struct changer_element_status *get_element_status __P((u_int16_t, u_int16_t));
+
static int do_move __P((char *, int, char **));
static int do_exchange __P((char *, int, char **));
static int do_position __P((char *, int, char **));
@@ -72,14 +76,20 @@ static int do_getpicker __P((char *, int, char **));
static int do_setpicker __P((char *, int, char **));
static int do_status __P((char *, int, char **));
static int do_ielem __P((char *, int, char **));
+static int do_return __P((char *, int, char **));
static int do_voltag __P((char *, int, char **));
+#ifndef CHET_VT
+#define CHET_VT 10 /* Completely Arbitrary */
+#endif
+
/* Valid changer element types. */
const struct element_type elements[] = {
{ "drive", CHET_DT },
{ "picker", CHET_MT },
{ "portal", CHET_IE },
{ "slot", CHET_ST },
+ { "voltag", CHET_VT }, /* Select tapes by barcode */
{ NULL, 0 },
};
@@ -93,6 +103,7 @@ const struct changer_command commands[] = {
{ "position", do_position },
{ "setpicker", do_setpicker },
{ "status", do_status },
+ { "return", do_return },
{ "voltag", do_voltag },
{ NULL, 0 },
};
@@ -195,14 +206,24 @@ do_move(cname, argc, argv)
cmd.cm_fromtype = parse_element_type(*argv);
++argv; --argc;
- /* <from EU> */
- cmd.cm_fromunit = parse_element_unit(*argv);
+ /* Check for voltag virtual type */
+ if (CHET_VT == cmd.cm_fromtype) {
+ find_element(*argv, &cmd.cm_fromtype, &cmd.cm_fromunit);
+ } else {
+ /* <from EU> */
+ cmd.cm_fromunit = parse_element_unit(*argv);
+ }
++argv; --argc;
/* <to ET> */
cmd.cm_totype = parse_element_type(*argv);
++argv; --argc;
+ /* Check for voltag virtual type, and report error */
+ if (CHET_VT == cmd.cm_totype)
+ errx(1,"%s: voltag only makes sense as an element source",
+ cname);
+
/* <to EU> */
cmd.cm_tounit = parse_element_unit(*argv);
++argv; --argc;
@@ -266,16 +287,26 @@ do_exchange(cname, argc, argv)
cmd.ce_srctype = parse_element_type(*argv);
++argv; --argc;
- /* <src EU> */
- cmd.ce_srcunit = parse_element_unit(*argv);
+ /* Check for voltag virtual type */
+ if (CHET_VT == cmd.ce_srctype) {
+ find_element(*argv, &cmd.ce_srctype, &cmd.ce_srcunit);
+ } else {
+ /* <from EU> */
+ cmd.ce_srcunit = parse_element_unit(*argv);
+ }
++argv; --argc;
/* <dst1 ET> */
cmd.ce_fdsttype = parse_element_type(*argv);
++argv; --argc;
- /* <dst1 EU> */
- cmd.ce_fdstunit = parse_element_unit(*argv);
+ /* Check for voltag virtual type */
+ if (CHET_VT == cmd.ce_fdsttype) {
+ find_element(*argv, &cmd.ce_fdsttype, &cmd.ce_fdstunit);
+ } else {
+ /* <from EU> */
+ cmd.ce_fdstunit = parse_element_unit(*argv);
+ }
++argv; --argc;
/*
@@ -293,6 +324,10 @@ do_exchange(cname, argc, argv)
cmd.ce_sdsttype = parse_element_type(*argv);
++argv; --argc;
+ if (CHET_VT == cmd.ce_sdsttype)
+ errx(1,"%s %s: voltag only makes sense as an element source",
+ cname, *argv);
+
/* <dst2 EU> */
cmd.ce_sdstunit = parse_element_unit(*argv);
++argv; --argc;
@@ -652,9 +687,9 @@ do_status(cname, argc, argv)
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));
+ cesr.cesr_element_status =
+ (struct changer_element_status *)
+ calloc(count, sizeof(struct changer_element_status));
if (!cesr.cesr_element_status)
errx(1, "can't allocate status storage");
@@ -934,6 +969,236 @@ bits_to_string(v, cp)
return (buf);
}
+/*
+ * do_return()
+ *
+ * Given an element reference, ask the changer/picker to move that
+ * element back to its source slot.
+ */
+static int
+do_return(cname, argc, argv)
+ char *cname;
+ int argc;
+ char **argv;
+{
+ struct changer_element_status *ces;
+ struct changer_move cmd;
+ u_int16_t type, element;
+
+ ++argv; --argc;
+
+ if (argc < 2) {
+ warnx("%s: too few arguments", cname);
+ goto usage;
+ } else if (argc > 3) {
+ warnx("%s: too many arguments", cname);
+ goto usage;
+ }
+
+ type = parse_element_type(*argv);
+ ++argv; --argc;
+
+ /* Handle voltag virtual Changer Element Type */
+ if (CHET_VT == type) {
+ find_element(*argv, &type, &element);
+ } else {
+ element = parse_element_unit(*argv);
+ }
+ ++argv; --argc;
+
+ ces = get_element_status(type, element); /* Get the status */
+
+ if (NULL == ces)
+ errx(1, "%s: null element status pointer", cname);
+
+ if (!(ces->ces_flags & CES_SOURCE_VALID))
+ errx(1, "%s: no source information", cname);
+
+ (void) memset(&cmd, 0, sizeof(cmd));
+
+ cmd.cm_fromtype = type;
+ cmd.cm_fromunit = element;
+ cmd.cm_totype = ces->ces_source_type;
+ cmd.cm_tounit = ces->ces_source_addr;
+
+ if (ioctl(changer_fd, CHIOMOVE, &cmd) == -1)
+ err(1, "%s: CHIOMOVE", changer_name);
+ free(ces);
+
+ return(0);
+
+usage:
+ (void) fprintf(stderr, "usage: %s %s "
+ "<from ET> <from EU>\n", __progname, cname);
+ return(1);
+}
+
+/*
+ * get_element_status()
+ *
+ * return a *cesr for the specified changer element. This
+ * routing will malloc()/calloc() the memory. The caller
+ * should free() it when done.
+ */
+static struct changer_element_status *
+get_element_status(type, element)
+ u_int16_t type;
+ u_int16_t element;
+{
+ struct changer_element_status_request cesr;
+ struct changer_element_status *ces;
+
+ ces = (struct changer_element_status *)
+ calloc(1, sizeof(struct changer_element_status));
+
+ if (NULL == ces)
+ errx(1, "can't allocate status storage");
+
+ (void)memset(&cesr, 0, sizeof(cesr));
+
+ cesr.cesr_element_type = type;
+ cesr.cesr_element_base = element;
+ cesr.cesr_element_count = 1; /* Only this one element */
+ cesr.cesr_flags |= CESR_VOLTAGS; /* Grab voltags as well */
+ cesr.cesr_element_status = ces;
+
+ if (ioctl(changer_fd, CHIOGSTATUS, (char *)&cesr) == -1) {
+ free(ces);
+ err(1, "%s: CHIOGSTATUS", changer_name);
+ /* NOTREACHED */
+ }
+
+ return ces;
+}
+
+
+/*
+ * find_element()
+ *
+ * Given a <voltag> find the chager element and unit, or exit
+ * with an error if it isn't found. We grab the changer status
+ * and iterate until we find a match, or crap out.
+ */
+static void
+find_element(voltag, et, eu)
+ char *voltag;
+ u_int16_t *et;
+ u_int16_t *eu;
+{
+ struct changer_params cp;
+ struct changer_element_status_request cesr;
+ struct changer_element_status *ch_ces, *ces;
+ int elem, total_elem, found = 0;
+
+ /*
+ * Get the changer parameters, we're interested in the counts
+ * for all types of elements to perform our search.
+ */
+ if (ioctl(changer_fd, CHIOGPARAMS, (char *)&cp))
+ err(1, "%s: CHIOGPARAMS", changer_name);
+
+ /* Allocate some memory for the results */
+ total_elem = (cp.cp_nslots + cp.cp_ndrives
+ + cp.cp_npickers + cp.cp_nportals);
+
+ ch_ces = (struct changer_element_status *)
+ calloc(total_elem, sizeof(struct changer_element_status));
+
+ if (NULL == ch_ces)
+ errx(1, "can't allocate status storage");
+
+ ces = ch_ces;
+
+ /* Read in the changer slots */
+ if (cp.cp_nslots > 0) {
+ cesr.cesr_element_type = CHET_ST;
+ cesr.cesr_element_base = 0;
+ cesr.cesr_element_count = cp.cp_nslots;
+ cesr.cesr_flags |= CESR_VOLTAGS;
+ cesr.cesr_element_status = ces;
+
+ if (ioctl(changer_fd, CHIOGSTATUS, (char *)&cesr) == -1) {
+ free(ch_ces);
+ err(1, "%s: CHIOGSTATUS", changer_name);
+ }
+ ces += cp.cp_nslots;
+ }
+
+ /* Read in the drive information */
+ if (cp.cp_ndrives > 0 ) {
+
+ (void) memset(&cesr, 0, sizeof(cesr));
+ cesr.cesr_element_type = CHET_DT;
+ cesr.cesr_element_base = 0;
+ cesr.cesr_element_count = cp.cp_ndrives;
+ cesr.cesr_flags |= CESR_VOLTAGS;
+ cesr.cesr_element_status = ces;
+
+ if (ioctl(changer_fd, CHIOGSTATUS, (char *)&cesr) == -1) {
+ free(ch_ces);
+ err(1, "%s: CHIOGSTATUS", changer_name);
+ }
+ ces += cp.cp_ndrives;
+ }
+
+ /* Read in the portal information */
+ if (cp.cp_nportals > 0 ) {
+ (void) memset(&cesr, 0, sizeof(cesr));
+ cesr.cesr_element_type = CHET_IE;
+ cesr.cesr_element_base = 0;
+ cesr.cesr_element_count = cp.cp_nportals;
+ cesr.cesr_flags |= CESR_VOLTAGS;
+ cesr.cesr_element_status = ces;
+
+ if (ioctl(changer_fd, CHIOGSTATUS, (char *)&cesr) == -1) {
+ free(ch_ces);
+ err(1, "%s: CHIOGSTATUS", changer_name);
+ }
+ ces += cp.cp_nportals;
+ }
+
+ /* Read in the picker information */
+ if (cp.cp_npickers > 0) {
+ (void) memset(&cesr, 0, sizeof(cesr));
+ cesr.cesr_element_type = CHET_MT;
+ cesr.cesr_element_base = 0;
+ cesr.cesr_element_count = cp.cp_npickers;
+ cesr.cesr_flags |= CESR_VOLTAGS;
+ cesr.cesr_element_status = ces;
+
+ if (ioctl(changer_fd, CHIOGSTATUS, (char *)&cesr) == -1) {
+ free(ch_ces);
+ err(1, "%s: CHIOGSTATUS", changer_name);
+ }
+ }
+
+ /*
+ * Now search the list the specified <voltag>
+ */
+ for (elem = 0; elem <= total_elem; ++elem) {
+
+ ces = &ch_ces[elem];
+
+ /* Make sure we have a tape in this element */
+ if ((ces->ces_flags & (CES_STATUS_ACCESS|CES_STATUS_FULL))
+ != (CES_STATUS_ACCESS|CES_STATUS_FULL))
+ continue;
+
+ /* Check to see if it is our target */
+ if (strcasecmp(voltag, ces->ces_pvoltag.cv_volid) == 0) {
+ *et = ces->ces_type;
+ *eu = ces->ces_addr;
+ ++found;
+ break;
+ }
+ }
+ if (!found) {
+ errx(1, "%s: unable to locate voltag: %s", changer_name,
+ voltag);
+ }
+ free(ch_ces);
+ return;
+}
static void
cleanup()
OpenPOWER on IntegriCloud