Import Jason Thorpe's contribution for an updated SCSI media changer

device (now, finally!).
This commit is contained in:
joerg 1997-03-06 15:30:06 +00:00
parent c7d5f60d3a
commit 22817fb6a1
8 changed files with 2151 additions and 1140 deletions

9
bin/chio/Makefile Normal file
View File

@ -0,0 +1,9 @@
# $Id: $
# @(#)Makefile 8.1 (Berkeley) 6/6/93
PROG= chio
SRCS= chio.c
BINOWN= root
BINMODE=4555
.include <bsd.prog.mk>

202
bin/chio/chio.1 Normal file
View File

@ -0,0 +1,202 @@
.\" $NetBSD: $
.\"
.\" Copyright (c) 1996 Jason R. Thorpe <thorpej@and.com>
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgements:
.\" This product includes software developed by Jason R. Thorpe
.\" for And Communications, http://www.and.com/
.\" 4. The name of the author may not be used to endorse or promote products
.\" derived from this software without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
.\" BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
.\" LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
.\" AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
.\" OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd April 2, 1996
.Dt CHIO 1
.Os
.Sh NAME
.Nm chio
.Nd medium changer control utility
.Sh SYNOPSIS
.Nm chio
.Op Fl f Ar changer
.Ar command
.Ar arg1
.Ar arg2
.Oo
.Ar arg3 Oo ...
.Oc
.Oc
.Sh DESCRIPTION
.Nm Chio
is used to control the operation of medium changers, such as those found
in tape and optical disk jukeboxes.
.Pp
The options are as follows:
.Bl -tag -width indent
.It Fl f Ar changer
Use the device
.Pa changer
rather than the default device
.Pa /dev/ch0 .
.El
.Pp
The default changer may be overridden by setting the environment variable
.Nm CHANGER
to the desired changer device.
.Pp
A medium changer apparatus is made up of
.Pa elements .
There are four element types:
.Pa picker
(medium transport),
.Pa slot
(storage),
.Pa portal
(import/export), and
.Pa drive
(data transfer). In this command description, the shorthand
.Nm ET
will be used to represent an element type, and
.Nm EU
will be used to represent an element unit. For example, to represent
the first robotic arm in the changer, the ET would be
.Dq picker
and the EU would be
.Dq 0 .
.Pp
.Sh SUPPORTED COMMANDS
.Nm chio move
.Ar <from ET> <from EU> <to ET> <to EU>
.Op Ar inv
.Pp
Moves the media unit from
.Pa <from ET/EU>
to
.Pa <to ET/EU> .
If the optional modifier
.Pa inv
is specified, the media unit will be inverted before insertion.
.Pp
.Nm chio exchange
.Ar <src ET> <src EU> <dst1 ET> <dst1 EU>
.Op Ar <dst2 ET> <dst2 ET>
.Op Ar inv1
.Op Ar inv2
.Pp
Performs a media unit exchange operation. The media unit in
.Pa <src ET/EU>
is moved to
.Pa <dst1 ET/EU>
and the media unit previously in
.Pa <dst1 ET/EU>
is moved to
.Pa <dst2 ET/EU> .
In the case of a simple exchange,
.Pa <dst2 ET/EU>
is omitted and the values
.Pa <src ET/EU>
are used in their place.
The optional modifiers
.Pa inv1
and
.Pa inv2
specify whether the media units are to be inverted before insertion into
.Pa <dst1 ET/EU>
and
.Pa <dst2 ET/EU>
respecitively.
.Pp
Note that not all medium changers support the
.Nm exchange
operation; The changer must have multiple free pickers or emulate
multiple free pickers with transient storage.
.Pp
.Nm chio position
.Ar <to ET> <to EU>
.Op Ar inv
.Pp
Position the picker in front of the element described by
.Pa <to ET/EU> .
If the optional modifier
.Pa inv
is specified, the media unit will be inverted before insertion.
.Pp
Note that not all changers behave as expected when issued this command.
.Pp
.Nm chio params
.Pp
Report the number of slots, drives, pickers, and portals in the changer,
and which picker unit the changer is currently configured to use.
.Pp
.Nm chio getpicker
.Pp
Report which picker unit the changer is currently configured to use.
.Pp
.Nm chio setpicker
.Ar <unit>
.Pp
Configure the changer to use picker
.Pa <unit> .
.Pp
.Nm chio status
.Op Ar <type>
.Pp
Report the status of all elements in the changer. If
.Pa <type>
is specified, report the status of all elements of type
.Pa <type> .
.Pp
The status bits are defined as follows:
.Bl -tag -width indent
.It Nm FULL
Element contains a media unit.
.It Nm IMPEXP
Media was deposited into element by an outside human operator.
.It Nm EXCEPT
Element is in an abnormal state.
.It Nm ACCESS
Media in this element is accessible by a picker.
.It Nm EXENAB
Element supports passing media (exporting) to an outsite human operator.
.It Nm INENAB
Element supports receiving media (importing) from an outside human operator.
.El
.Pp
.Sh EXAMPLES
.Nm chio move slot 3 drive 0
.Pp
Moves the media in slot 3 (fourth slot) to drive 0 (first drive).
.Pp
.Nm chio setpicker 2
Configures the changer to use picker 2 (third picker) for operations.
.Pp
.Sh FILES
/dev/ch0 - default changer device
.Sh SEE ALSO
.Xr mt 1 ,
.Xr mount 8 .
.Sh AUTHOR
The
.Nm chio
program and SCSI changer driver were written by Jason R. Thorpe
<thorpej@and.com> for And Communications, http://www.and.com/

663
bin/chio/chio.c Normal file
View File

@ -0,0 +1,663 @@
/* $Id: $ */
/*
* Copyright (c) 1996 Jason R. Thorpe <thorpej@and.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgements:
* This product includes software developed by Jason R. Thorpe
* for And Communications, http://www.and.com/
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/chio.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "defs.h"
#include "pathnames.h"
extern char *__progname; /* from crt0.o */
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 **));
/* Valid changer element types. */
const struct element_type elements[] = {
{ "picker", CHET_MT },
{ "slot", CHET_ST },
{ "portal", CHET_IE },
{ "drive", CHET_DT },
{ NULL, 0 },
};
/* Valid commands. */
const struct changer_command commands[] = {
{ "move", do_move },
{ "exchange", do_exchange },
{ "position", do_position },
{ "params", do_params },
{ "getpicker", do_getpicker },
{ "setpicker", do_setpicker },
{ "status", do_status },
{ NULL, 0 },
};
/* Valid special words. */
const struct special_word specials[] = {
{ "inv", SW_INVERT },
{ "inv1", SW_INVERT1 },
{ "inv2", SW_INVERT2 },
{ NULL, 0 },
};
static int changer_fd;
static char *changer_name;
int
main(argc, argv)
int argc;
char **argv;
{
int ch, i;
char *cp;
while ((ch = getopt(argc, argv, "f:")) != -1) {
switch (ch) {
case 'f':
changer_name = optarg;
break;
default:
usage();
}
}
argc -= optind;
argv += optind;
if (argc == 0)
usage();
/* Get the default changer if not already specified. */
if (changer_name == NULL)
if ((changer_name = getenv(CHANGER_ENV_VAR)) == NULL)
changer_name = _PATH_CH;
/* Open the changer device. */
if ((changer_fd = open(changer_name, O_RDWR, 0600)) == -1)
err(1, "%s: open", changer_name);
/* Register cleanup function. */
if (atexit(cleanup))
err(1, "can't register cleanup function");
/* Find the specified command. */
for (i = 0; commands[i].cc_name != NULL; ++i)
if (strcmp(*argv, commands[i].cc_name) == 0)
break;
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));
}
static int
do_move(cname, argc, argv)
char *cname;
int argc;
char **argv;
{
struct changer_move cmd;
int val;
/*
* On a move command, we expect the following:
*
* <from ET> <from EU> <to ET> <to EU> [inv]
*
* where ET == element type and EU == element unit.
*/
if (argc < 4) {
warnx("%s: too few arguments", cname);
goto usage;
} else if (argc > 5) {
warnx("%s: too many arguments", cname);
goto usage;
}
bzero(&cmd, sizeof(cmd));
/* <from ET> */
cmd.cm_fromtype = parse_element_type(*argv);
++argv; --argc;
/* <from EU> */
cmd.cm_fromunit = parse_element_unit(*argv);
++argv; --argc;
/* <to ET> */
cmd.cm_totype = parse_element_type(*argv);
++argv; --argc;
/* <to EU> */
cmd.cm_tounit = parse_element_unit(*argv);
++argv; --argc;
/* Deal with optional command modifier. */
if (argc) {
val = parse_special(*argv);
switch (val) {
case SW_INVERT:
cmd.cm_flags |= CM_INVERT;
break;
default:
errx(1, "%s: inappropriate modifier `%s'",
cname, *argv);
/* NOTREACHED */
}
}
/* Send command to changer. */
if (ioctl(changer_fd, CHIOMOVE, (char *)&cmd))
err(1, "%s: CHIOMOVE", changer_name);
return (0);
usage:
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;
{
struct changer_exchange cmd;
int val;
/*
* On an exchange command, we expect the following:
*
* <src ET> <src EU> <dst1 ET> <dst1 EU> [<dst2 ET> <dst2 EU>] [inv1] [inv2]
*
* where ET == element type and EU == element unit.
*/
if (argc < 4) {
warnx("%s: too few arguments", cname);
goto usage;
} else if (argc > 8) {
warnx("%s: too many arguments", cname);
goto usage;
}
bzero(&cmd, sizeof(cmd));
/* <src ET> */
cmd.ce_srctype = parse_element_type(*argv);
++argv; --argc;
/* <src 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);
++argv; --argc;
/*
* If the next token is a special word or there are no more
* arguments, then this is a case of simple exchange.
* dst2 == src.
*/
if ((argc == 0) || is_special(*argv)) {
cmd.ce_sdsttype = cmd.ce_srctype;
cmd.ce_sdstunit = cmd.ce_srcunit;
goto do_special;
}
/* <dst2 ET> */
cmd.ce_sdsttype = parse_element_type(*argv);
++argv; --argc;
/* <dst2 EU> */
cmd.ce_sdstunit = parse_element_unit(*argv);
++argv; --argc;
do_special:
/* Deal with optional command modifiers. */
while (argc) {
val = parse_special(*argv);
++argv; --argc;
switch (val) {
case SW_INVERT1:
cmd.ce_flags |= CE_INVERT1;
break;
case SW_INVERT2:
cmd.ce_flags |= CE_INVERT2;
break;
default:
errx(1, "%s: inappropriate modifier `%s'",
cname, *argv);
/* NOTREACHED */
}
}
/* Send command to changer. */
if (ioctl(changer_fd, CHIOEXCHANGE, (char *)&cmd))
err(1, "%s: CHIOEXCHANGE", changer_name);
return (0);
usage:
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;
{
struct changer_position cmd;
int val;
/*
* On a position command, we expect the following:
*
* <to ET> <to EU> [inv]
*
* where ET == element type and EU == element unit.
*/
if (argc < 2) {
warnx("%s: too few arguments", cname);
goto usage;
} else if (argc > 3) {
warnx("%s: too many arguments", cname);
goto usage;
}
bzero(&cmd, sizeof(cmd));
/* <to ET> */
cmd.cp_type = parse_element_type(*argv);
++argv; --argc;
/* <to EU> */
cmd.cp_unit = parse_element_unit(*argv);
++argv; --argc;
/* Deal with optional command modifier. */
if (argc) {
val = parse_special(*argv);
switch (val) {
case SW_INVERT:
cmd.cp_flags |= CP_INVERT;
break;
default:
errx(1, "%s: inappropriate modifier `%s'",
cname, *argv);
/* NOTREACHED */
}
}
/* Send command to changer. */
if (ioctl(changer_fd, CHIOPOSITION, (char *)&cmd))
err(1, "%s: CHIOPOSITION", changer_name);
return (0);
usage:
fprintf(stderr, "usage: %s %s <to ET> <to EU> [inv]\n",
__progname, cname);
return (1);
}
static int
do_params(cname, argc, argv)
char *cname;
int argc;
char **argv;
{
struct changer_params data;
/* No arguments to this command. */
if (argc) {
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))
err(1, "%s: CHIOGPARAMS", changer_name);
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,
(data.cp_nportals > 1) ? "s" : "");
printf("\n%s: current picker: %d\n", changer_name, data.cp_curpicker);
return (0);
usage:
fprintf(stderr, "usage: %s %s\n", __progname, cname);
return (1);
}
static int
do_getpicker(cname, argc, argv)
char *cname;
int argc;
char **argv;
{
int picker;
/* No arguments to this command. */
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))
err(1, "%s: CHIOGPICKER", changer_name);
printf("%s: current picker: %d\n", changer_name, picker);
return (0);
usage:
fprintf(stderr, "usage: %s %s\n", __progname, cname);
return (1);
}
static int
do_setpicker(cname, argc, argv)
char *cname;
int argc;
char **argv;
{
int picker;
if (argc < 1) {
warnx("%s: too few arguments", cname);
goto usage;
} else if (argc > 1) {
warnx("%s: too many arguments", cname);
goto usage;
}
picker = parse_element_unit(*argv);
/* Set the changer picker. */
if (ioctl(changer_fd, CHIOSPICKER, (char *)&picker))
err(1, "%s: CHIOSPICKER", changer_name);
return (0);
usage:
fprintf(stderr, "usage: %s %s <picker>\n", __progname, cname);
return (1);
}
static int
do_status(cname, argc, argv)
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;
char *cmdname, *description;
/*
* On a status command, we expect the following:
*
* [<ET>]
*
* where ET == element type.
*
* If we get no arguments, we get the status of all
* known element types.
*/
if (argc > 1) {
warnx("%s: too many arguments", cname);
goto usage;
}
/*
* Get params from changer. Specifically, we need the element
* counts.
*/
bzero(&data, sizeof(data));
if (ioctl(changer_fd, CHIOGPARAMS, (char *)&data))
err(1, "%s: CHIOGPARAMS", changer_name);
if (argc)
schet = echet = parse_element_type(*argv);
else {
schet = CHET_MT;
echet = CHET_DT;
}
for (chet = schet; chet <= echet; ++chet) {
switch (chet) {
case CHET_MT:
count = data.cp_npickers;
description = "picker";
break;
case CHET_ST:
count = data.cp_nslots;
description = "slot";
break;
case CHET_IE:
count = data.cp_nportals;
description = "portal";
break;
case CHET_DT:
count = data.cp_ndrives;
description = "drive";
break;
}
if (count == 0) {
if (argc == 0)
continue;
else {
printf("%s: no %s elements\n",
changer_name, description);
return (0);
}
}
/* Allocate storage for the status bytes. */
if ((statusp = (u_int8_t *)malloc(count)) == NULL)
errx(1, "can't allocate status storage");
bzero(statusp, count);
bzero(&cmd, sizeof(cmd));
cmd.ces_type = chet;
cmd.ces_data = statusp;
if (ioctl(changer_fd, CHIOGSTATUS, (char *)&cmd)) {
free(statusp);
err(1, "%s: CHIOGSTATUS", changer_name);
}
/* Dump the status for each element of this type. */
for (i = 0; i < count; ++i) {
printf("%s %d: %s\n", description, i,
bits_to_string(statusp[i], CESTATUS_BITS));
}
free(statusp);
}
return (0);
usage:
fprintf(stderr, "usage: %s %s [<element type>]\n", __progname,
cname);
return (1);
}
static int
parse_element_type(cp)
char *cp;
{
int i;
for (i = 0; elements[i].et_name != NULL; ++i)
if (strcmp(elements[i].et_name, cp) == 0)
return (elements[i].et_type);
errx(1, "invalid element type `%s'", cp);
}
static int
parse_element_unit(cp)
char *cp;
{
int i;
char *p;
i = (int)strtol(cp, &p, 10);
if ((i < 0) || (*p != '\0'))
errx(1, "invalid unit number `%s'", cp);
return (i);
}
static int
parse_special(cp)
char *cp;
{
int val;
val = is_special(cp);
if (val)
return (val);
errx(1, "invalid modifier `%s'", cp);
}
static int
is_special(cp)
char *cp;
{
int i;
for (i = 0; specials[i].sw_name != NULL; ++i)
if (strcmp(specials[i].sw_name, cp) == 0)
return (specials[i].sw_value);
return (0);
}
static char *
bits_to_string(v, cp)
int v;
const char *cp;
{
const char *np;
char f, sep, *bp;
static char buf[128];
bp = buf;
bzero(buf, sizeof(buf));
for (sep = '<'; (f = *cp++) != 0; cp = np) {
for (np = cp; *np >= ' ';)
np++;
if ((v & (1 << (f - 1))) == 0)
continue;
bp += sprintf(bp, "%c%.*s", sep, np - cp, cp);
sep = ',';
}
if (sep != '<')
*bp = '>';
return (buf);
}
static void
cleanup()
{
/* Simple enough... */
(void)close(changer_fd);
}
static void
usage()
{
fprintf(stderr, "usage: %s command arg1 arg2 ...\n", __progname);
exit(1);
}

57
bin/chio/defs.h Normal file
View File

@ -0,0 +1,57 @@
/* $Id: $ */
/*
* Copyright (c) 1996 Jason R. Thorpe <thorpej@and.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgements:
* This product includes software developed by Jason R. Thorpe
* for And Communications, http://www.and.com/
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
struct element_type {
char *et_name; /* name; i.e. "picker, "slot", etc. */
int et_type; /* type number */
};
struct changer_command {
char *cc_name; /* command name */
/* command handler */
int (*cc_handler) __P((char *, int, char **));
};
struct special_word {
char *sw_name; /* special word */
int sw_value; /* token value */
};
/* sw_value */
#define SW_INVERT 1 /* set "invert media" flag */
#define SW_INVERT1 2 /* set "invert media 1" flag */
#define SW_INVERT2 3 /* set "invert media 2" flag */
/* Environment variable to check for default changer. */
#define CHANGER_ENV_VAR "CHANGER"

35
bin/chio/pathnames.h Normal file
View File

@ -0,0 +1,35 @@
/* $Id: $ */
/*
* Copyright (c) 1996 Jason R. Thorpe <thorpej@and.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgements:
* This product includes software developed by Jason R. Thorpe
* for And Communications, http://www.and.com/
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#define _PATH_CH "/dev/ch0"

File diff suppressed because it is too large Load Diff

View File

@ -1,13 +1,39 @@
/* $Id: $ */
/*
* HISTORY
* Copyright (c) 1996 Jason R. Thorpe <thorpej@and.com>
* All rights reserved.
*
* PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
* -------------------- ----- ----------------------
* CURRENT PATCH LEVEL: 1 00098
* -------------------- ----- ----------------------
* Partially based on an autochanger driver written by Stefan Grefen
* and on an autochanger driver written by the Systems Programming Group
* at the University of Utah Computer Science Department.
*
* 16 Feb 93 Julian Elischer ADDED for SCSI system
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgements:
* This product includes software developed by Jason R. Thorpe
* for And Communications, http://www.and.com/
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
@ -15,7 +41,8 @@
*/
/*
* Written by Stefan Grefen (grefen@goofy.zdv.uni-mainz.de soon grefen@convex.com)
* Partially derived from software written by Stefan Grefen
* (grefen@goofy.zdv.uni-mainz.de soon grefen@convex.com)
* based on the SCSI System by written Julian Elischer (julian@tfs.com)
* for TRW Financial Systems.
*
@ -29,90 +56,345 @@
* on the understanding that TFS is not responsible for the correct
* functioning of this software in any circumstances.
*
*/
/*
* Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
*/
#ifndef _SCSI_SCSI_CHANGER_H
#define _SCSI_SCSI_CHANGER_H 1
/*
* SCSI command format
*/
struct scsi_read_element_status
{
u_char op_code;
u_char element_type_code:4;
u_char voltag:1;
u_char lun:3;
u_char starting_element_addr[2];
u_char number_of_elements[2];
u_char resv1;
u_char allocation_length[3];
u_char resv2;
u_char link:1;
u_char flag:1;
u_char :6;
};
#define RE_ALL_ELEMENTS 0
#define RE_MEDIUM_TRANSPORT_ELEMENT 1
#define RE_STORAGE_ELEMENT 2
#define RE_IMPORT_EXPORT 3
#define RE_DATA_TRANSFER_ELEMENT 4
struct scsi_move_medium
{
u_char op_code;
u_char :5;
u_char lun:3;
u_char transport_element_address[2];
u_char source_address[2];
u_char destination_address[2];
u_char rsvd[2];
u_char invert:1;
u_char :7;
u_char link:1;
u_char flag:1;
u_char :6;
};
struct scsi_position_to_element
{
u_char op_code;
u_char :5;
u_char lun:3;
u_char transport_element_address[2];
u_char source_address[2];
u_char rsvd[2];
u_char invert:1;
u_char :7;
u_char link:1;
u_char flag:1;
u_char :6;
};
/*
* Opcodes
* Exchange the medium in the source element with the medium
* located at the destination element.
*/
#define POSITION_TO_ELEMENT 0x2b
#define MOVE_MEDIUM 0xa5
#define READ_ELEMENT_STATUS 0xb8
struct scsi_element_status_data
{
u_char first_element_reported[2];
u_char number_of_elements_reported[2];
u_char rsvd;
u_char byte_count_of_report[3];
struct scsi_exchange_medium {
u_int8_t opcode;
#define EXCHANGE_MEDIUM 0xa6
u_int8_t byte2;
u_int8_t tea[2]; /* transport element address */
u_int8_t src[2]; /* source address */
u_int8_t fdst[2]; /* first destination address */
u_int8_t sdst[2]; /* second destination address */
u_int8_t flags;
#define EXCHANGE_MEDIUM_INV1 0x01
#define EXCHANGE_MEDIUM_INV2 0x02
u_int8_t control;
};
struct element_status_page
{
u_char element_type_code;
u_char :5;
u_char avoltag:1;
u_char pvoltag:1;
u_char element_descriptor_length[2];
u_char rsvd;
u_char byte_count_of_descriptor_data[3];
/*
* Cause the medium changer to check all elements for medium and any
* other status relevant to the element.
*/
struct scsi_initialize_elememt_status {
u_int8_t opcode;
#define INITIALIZE_ELEMENT_STATUS 0x07
u_int8_t byte2;
u_int8_t reserved[3];
u_int8_t control;
};
/*
* Request the changer to move a unit of media from the source element
* to the destination element.
*/
struct scsi_move_medium {
u_int8_t opcode;
#define MOVE_MEDIUM 0xa5
u_int8_t byte2;
u_int8_t tea[2]; /* transport element address */
u_int8_t src[2]; /* source element address */
u_int8_t dst[2]; /* destination element address */
u_int8_t reserved[2];
u_int8_t flags;
#define MOVE_MEDIUM_INVERT 0x01
u_int8_t control;
};
/*
* Position the specified transport element (picker) in front of
* the destination element specified.
*/
struct scsi_position_to_element {
u_int8_t opcode;
#define POSITION_TO_ELEMENT 0x2b
u_int8_t byte2;
u_int8_t tea[2]; /* transport element address */
u_int8_t dst[2]; /* destination element address */
u_int8_t reserved[2];
u_int8_t flags;
#define POSITION_TO_ELEMENT_INVERT 0x01
u_int8_t control;
};
/*
* Request that the changer report the status of its internal elements.
*/
struct scsi_read_element_status {
u_int8_t opcode;
#define READ_ELEMENT_STATUS 0xb8
u_int8_t byte2;
#define READ_ELEMENT_STATUS_VOLTAG 0x10 /* report volume tag info */
/* ...next 4 bits are an element type code... */
u_int8_t sea[2]; /* starting element address */
u_int8_t count[2]; /* number of elements */
u_int8_t reserved0;
u_int8_t len[3]; /* length of data buffer */
u_int8_t reserved1;
u_int8_t control;
};
struct scsi_request_volume_element_address {
u_int8_t opcode;
#define REQUEST_VOLUME_ELEMENT_ADDRESS 0xb5
u_int8_t byte2;
#define REQUEST_VOLUME_ELEMENT_ADDRESS_VOLTAG 0x10
/* ...next 4 bits are an element type code... */
u_int8_t eaddr[2]; /* element address */
u_int8_t count[2]; /* number of elements */
u_int8_t reserved0;
u_int8_t len[3]; /* length of data buffer */
u_int8_t reserved1;
u_int8_t control;
};
/* XXX scsi_release */
/*
* Data returned by READ ELEMENT STATUS consists of an 8-byte header
* followed by one or more read_element_status_pages.
*/
struct read_element_status_header {
u_int8_t fear[2]; /* first element address reported */
u_int8_t count[2]; /* number of elements available */
u_int8_t reserved;
u_int8_t nbytes[3]; /* byte count of all pages */
};
struct read_element_status_page_header {
u_int8_t type; /* element type code; see type codes below */
u_int8_t flags;
#define READ_ELEMENT_STATUS_AVOLTAG 0x40
#define READ_ELEMENT_STATUS_PVOLTAG 0x80
u_int8_t edl[2]; /* element descriptor length */
u_int8_t reserved;
u_int8_t nbytes[3]; /* byte count of all descriptors */
};
struct read_element_status_descriptor {
u_int8_t eaddr[2]; /* element address */
u_int8_t flags1;
#define READ_ELEMENT_STATUS_FULL 0x01
#define READ_ELEMENT_STATUS_IMPEXP 0x02
#define READ_ELEMENT_STATUS_EXCEPT 0x04
#define READ_ELEMENT_STATUS_ACCESS 0x08
#define READ_ELEMENT_STATUS_EXENAB 0x10
#define READ_ELEMENT_STATUS_INENAB 0x20
#define READ_ELEMENT_STATUS_MT_MASK1 0x05
#define READ_ELEMENT_STATUS_ST_MASK1 0x0c
#define READ_ELEMENT_STATUS_IE_MASK1 0x3f
#define READ_ELEMENT_STATUS_DT_MASK1 0x0c
u_int8_t reserved0;
u_int8_t sense_code;
u_int8_t sense_qual;
/*
* dt_scsi_flags and dt_scsi_addr are valid only on data transport
* elements. These bytes are undefined for all other element types.
*/
u_int8_t dt_scsi_flags;
#define READ_ELEMENT_STATUS_DT_LUNMASK 0x07
#define READ_ELEMENT_STATUS_DT_LUVALID 0x10
#define READ_ELEMENT_STATUS_DT_IDVALID 0x20
#define READ_ELEMENT_STATUS_DT_NOTBUS 0x80
u_int8_t dt_scsi_addr;
u_int8_t reserved1;
u_int8_t flags2;
#define READ_ELEMENT_STATUS_INVERT 0x40
#define READ_ELEMENT_STATUS_SVALID 0x80
u_int8_t ssea[2]; /* source storage element address */
/*
* bytes 12-47: Primary volume tag information.
* (field omitted if PVOLTAG = 0)
*
* bytes 48-83: Alternate volume tag information.
* (field omitted if AVOLTAG = 0)
*
* bytes 84-87: Reserved (moved up if either of the above fields
* are omitted)
*
* bytes 88-end: Vendor-specific: (moved up if either of the
* above fields are missing)
*/
};
/* XXX add data returned by REQUEST VOLUME ELEMENT ADDRESS */
/* Element type codes */
#define ELEMENT_TYPE_MASK 0x0f /* Note: these aren't bits */
#define ELEMENT_TYPE_ALL 0x00
#define ELEMENT_TYPE_MT 0x01
#define ELEMENT_TYPE_ST 0x02
#define ELEMENT_TYPE_IE 0x03
#define ELEMENT_TYPE_DT 0x04
/*
* XXX The following definitions should be common to all SCSI device types.
*/
#define PGCODE_MASK 0x3f /* valid page number bits in pg_code */
#define PGCODE_PS 0x80 /* indicates page is savable */
/*
* Device capabilities page.
*
* This page defines characteristics of the elemenet types in the
* medium changer device.
*
* Note in the definitions below, the following abbreviations are
* used:
* MT Medium transport element (picker)
* ST Storage transport element (slot)
* IE Import/export element (portal)
* DT Data tranfer element (tape/disk drive)
*/
struct page_device_capabilities {
u_int8_t pg_code; /* page code (0x1f) */
u_int8_t pg_length; /* page length (0x12) */
/*
* The STOR_xx bits indicate that an element of a given
* type may provide independent storage for a unit of
* media. The top four bits of this value are reserved.
*/
u_int8_t stor;
#define STOR_MT 0x01
#define STOR_ST 0x02
#define STOR_IE 0x04
#define STOR_DT 0x08
u_int8_t reserved0;
/*
* The MOVE_TO_yy bits indicate the changer supports
* moving a unit of medium from an element of a given type to an
* element of type yy. This is used to determine if a given
* MOVE MEDIUM command is legal. The top four bits of each
* of these values are reserved.
*/
u_int8_t move_from_mt;
u_int8_t move_from_st;
u_int8_t move_from_ie;
u_int8_t move_from_dt;
#define MOVE_TO_MT 0x01
#define MOVE_TO_ST 0x02
#define MOVE_TO_IE 0x04
#define MOVE_TO_DT 0x08
u_int8_t reserved1[2];
/*
* Similar to above, but for EXCHANGE MEDIUM.
*/
u_int8_t exchange_with_mt;
u_int8_t exchange_with_st;
u_int8_t exchange_with_ie;
u_int8_t exchange_with_dt;
#define EXCHANGE_WITH_MT 0x01
#define EXCHANGE_WITH_ST 0x02
#define EXCHANGE_WITH_IE 0x04
#define EXCHANGE_WITH_DT 0x08
};
/*
* Medium changer elemement address assignment page.
*
* Some of these fields can be a little confusing, so an explanation
* is in order.
*
* Each component within a a medium changer apparatus is called an
* "element".
*
* The "medium transport element address" is the address of the first
* picker (robotic arm). "Number of medium transport elements" tells
* us how many pickers exist in the changer.
*
* The "first storage element address" is the address of the first
* slot in the tape or disk magazine. "Number of storage elements" tells
* us how many slots exist in the changer.
*
* The "first import/export element address" is the address of the first
* medium portal accessible both by the medium changer and an outside
* human operator. This is where the changer might deposit tapes destined
* for some vault. The "number of import/export elements" tells us
* not many of these portals exist in the changer. NOTE: this number may
* be 0.
*
* The "first data transfer element address" is the address of the first
* tape or disk drive in the changer. "Number of data transfer elements"
* tells us how many drives exist in the changer.
*/
struct page_element_address_assignment {
u_int8_t pg_code; /* page code (0x1d) */
u_int8_t pg_length; /* page length (0x12) */
/* Medium transport element address */
u_int8_t mtea[2];
/* Number of medium transport elements */
u_int8_t nmte[2];
/* First storage element address */
u_int8_t fsea[2];
/* Number of storage elements */
u_int8_t nse[2];
/* First import/export element address */
u_int8_t fieea[2];
/* Number of import/export elements */
u_int8_t niee[2];
/* First data transfer element address */
u_int8_t fdtea[2];
/* Number of data trafer elements */
u_int8_t ndte[2];
u_int8_t reserved[2];
};
/*
* Transport geometry parameters page.
*
* Defines whether each medium transport element is a member of a set of
* elements that share a common robotics subsystem and whether the element
* is capable of media rotation. One transport geometry descriptor is
* transferred for each medium transport element, beginning with the first
* medium transport element (other than the default transport element address
* of 0).
*/
struct page_transport_geometry_parameters {
u_int8_t pg_code; /* page code (0x1e) */
u_int8_t pg_length; /* page length; variable */
/* Transport geometry descriptor(s) are here. */
u_int8_t misc;
#define CAN_ROTATE 0x01
/* Member number in transport element set. */
u_int8_t member;
};
#endif /* _SCSI_SCSI_CHANGER_H */

View File

@ -1,5 +1,7 @@
/* $Id: $ */
/*
* Copyright (c) 1982, 1986 The Regents of the University of California.
* Copyright (c) 1996 Jason R. Thorpe <thorpej@and.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -11,117 +13,139 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* must display the following acknowledgements:
* This product includes software developed by Jason R. Thorpe
* for And Communications, http://www.and.com/
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)chio.h 7.6 (Berkeley) 2/5/91
*
* PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
* -------------------- ----- ----------------------
* CURRENT PATCH LEVEL: 1 00098
* -------------------- ----- ----------------------
*
* 16 Feb 93 Julian Elischer ADDED for SCSI system
*/
/* This is a "convertet" mtio.h from 386BSD
Stefan Grefen grefen@goofy.zdv.uni-mainz.de
*/
#ifndef _SYS_CHIO_H_
#define _SYS_CHIO_H_
/*
* Structures and definitions for changer io control commands
* Element types. Used as "to" and "from" type indicators in move
* and exchange operations.
*
* Note that code in sys/scsi/ch.c relies on these values (uses them
* as offsets in an array, and other evil), so don't muck with them
* unless you know what you're doing.
*/
#ifndef _CHIO_H_
#define _CHIO_H_
#define CHET_MT 0 /* medium transport (picker) */
#define CHET_ST 1 /* storage transport (slot) */
#define CHET_IE 2 /* import/export (portal) */
#define CHET_DT 3 /* data transfer (drive) */
#define CH_INVERT 0x10000
#define CH_ADDR_MASK 0xffff
struct chop {
short ch_op; /* operations defined below */
short result; /* The result */
union {
struct {
int chm; /* Transport element */
int from;
int to;
} move;
struct {
int chm; /* Transport element */
int to;
} position;
struct {
short chmo; /* Offset of first CHM */
short chms; /* No. of CHM */
short slots; /* No. of Storage Elements */
short sloto; /* Offset of first SE */
short imexs; /* No. of Import/Export Slots */
short imexo; /* Offset of first IM/EX */
short drives; /* No. of CTS */
short driveo; /* Offset of first CTS */
short rot; /* CHM can rotate */
} getparam;
struct {
int type;
#define CH_CHM 1
#define CH_STOR 2
#define CH_IMEX 3
#define CH_CTS 4
int from;
struct {
u_char elema_1;
u_char elema_0;
u_char full:1;
u_char rsvd:1;
u_char except:1;
u_char :5;
u_char rsvd2;
union {
struct {
u_char add_sense_code;
u_char add_sense_code_qualifier;
} specs;
short add_sense;
/* WARINING LSB only */
#define CH_CHOLDER 0x0290 /* Cartridge holder is missing */
#define CH_STATUSQ 0x0390 /* Status is questionable */
#define CH_CTS_CLOSED 0x0490 /* CTS door is closed */
} ch_add_sense;
u_char rsvd3[3];
u_char :6;
u_char invert:1;
u_char svalid:1;
u_char source_1;
u_char source_0;
u_char rsvd4[4];
} elem_data;
} get_elem_stat;
} u;
/*
* Structure used to execute a MOVE MEDIUM command.
*/
struct changer_move {
int cm_fromtype; /* element type to move from */
int cm_fromunit; /* logical unit of from element */
int cm_totype; /* element type to move to */
int cm_tounit; /* logical unit of to element */
int cm_flags; /* misc. flags */
};
/* operations */
#define CHMOVE 1
#define CHPOSITION 2
#define CHGETPARAM 3
#define CHGETELEM 4
/* cm_flags */
#define CM_INVERT 0x01 /* invert media */
/*
* Structure used to execute an EXCHANGE MEDIUM command. In an
* exchange operation, the following steps occur:
*
* - media from source is moved to first destination.
*
* - media previously occupying first destination is moved
* to the second destination.
*
* The second destination may or may not be the same as the source.
* In the case of a simple exchange, the source and second destination
* are the same.
*/
struct changer_exchange {
int ce_srctype; /* element type of source */
int ce_srcunit; /* logical unit of source */
int ce_fdsttype; /* element type of first destination */
int ce_fdstunit; /* logical unit of first destination */
int ce_sdsttype; /* element type of second destination */
int ce_sdstunit; /* logical unit of second destination */
int ce_flags; /* misc. flags */
};
/* Changer IO control command */
#define CHIOOP _IOWR('c', 1, struct chop) /* do a mag tape op */
#endif
/* ce_flags */
#define CE_INVERT1 0x01 /* invert media 1 */
#define CE_INVERT2 0x02 /* invert media 2 */
/*
* Structure used to execute a POSITION TO ELEMENT command. This
* moves the current picker in front of the specified element.
*/
struct changer_position {
int cp_type; /* element type */
int cp_unit; /* logical unit of element */
int cp_flags; /* misc. flags */
};
/* cp_flags */
#define CP_INVERT 0x01 /* invert picker */
/*
* Data returned by CHIOGPARAMS.
*/
struct changer_params {
int cp_curpicker; /* current picker */
int cp_npickers; /* number of pickers */
int cp_nslots; /* number of slots */
int cp_nportals; /* number of import/export portals */
int cp_ndrives; /* number of drives */
};
/*
* Command used to get element status.
*/
struct changer_element_status {
int ces_type; /* element type */
u_int8_t *ces_data; /* pre-allocated data storage */
};
/*
* Data returned by CHIOGSTATUS is an array of flags bytes.
* Not all flags have meaning for all element types.
*/
#define CESTATUS_FULL 0x01 /* element is full */
#define CESTATUS_IMPEXP 0x02 /* media deposited by operator */
#define CESTATUS_EXCEPT 0x04 /* element in abnormal state */
#define CESTATUS_ACCESS 0x08 /* media accessible by picker */
#define CESTATUS_EXENAB 0x10 /* element supports exporting */
#define CESTATUS_INENAB 0x20 /* element supports importing */
#define CESTATUS_PICKER_MASK 0x05 /* flags valid for pickers */
#define CESTATUS_SLOT_MASK 0x0c /* flags valid for slots */
#define CESTATUS_PORTAL_MASK 0x3f /* flags valid for portals */
#define CESTATUS_DRIVE_MASK 0x0c /* flags valid for drives */
#define CESTATUS_BITS \
"\20\6INEAB\5EXENAB\4ACCESS\3EXCEPT\2IMPEXP\1FULL"
#define CHIOMOVE _IOW('c', 0x01, struct changer_move)
#define CHIOEXCHANGE _IOW('c', 0x02, struct changer_exchange)
#define CHIOPOSITION _IOW('c', 0x03, struct changer_position)
#define CHIOGPICKER _IOR('c', 0x04, int)
#define CHIOSPICKER _IOW('c', 0x05, int)
#define CHIOGPARAMS _IOR('c', 0x06, struct changer_params)
#define CHIOGSTATUS _IOW('c', 0x08, struct changer_element_status)
#endif /* _SYS_CHIO_H_ */