summaryrefslogtreecommitdiffstats
path: root/sbin/scsi
diff options
context:
space:
mode:
authordufault <dufault@FreeBSD.org>1995-01-24 12:07:27 +0000
committerdufault <dufault@FreeBSD.org>1995-01-24 12:07:27 +0000
commit2b302b8741c690e273b2aad119196671c59af52a (patch)
treea1b395c3c860c22de35f015c7c1acc6ea8ade4fb /sbin/scsi
downloadFreeBSD-src-2b302b8741c690e273b2aad119196671c59af52a.zip
FreeBSD-src-2b302b8741c690e273b2aad119196671c59af52a.tar.gz
Submitted by: Julian Elischer and Peter Dufault
Obtained from: 1.1.5 "scsi (8)" from 1.1.5, with added support for any command from the command line.
Diffstat (limited to 'sbin/scsi')
-rw-r--r--sbin/scsi/Makefile7
-rw-r--r--sbin/scsi/scsi.8192
-rw-r--r--sbin/scsi/scsi.c441
3 files changed, 640 insertions, 0 deletions
diff --git a/sbin/scsi/Makefile b/sbin/scsi/Makefile
new file mode 100644
index 0000000..07b6321
--- /dev/null
+++ b/sbin/scsi/Makefile
@@ -0,0 +1,7 @@
+# @(#)Makefile 8.1 (Berkeley) 6/5/93
+
+PROG= scsi
+MAN8= scsi.8
+LDADD= -lscsi
+
+.include <bsd.prog.mk>
diff --git a/sbin/scsi/scsi.8 b/sbin/scsi/scsi.8
new file mode 100644
index 0000000..65ea194
--- /dev/null
+++ b/sbin/scsi/scsi.8
@@ -0,0 +1,192 @@
+.\"
+.\" Written By Julian ELischer
+.\" Copyright julian Elischer 1993.
+.\" Permission is granted to use or redistribute this file in any way as long
+.\" as this notice remains. Julian Elischer does not guarantee that this file
+.\" is totally correct for any given task and users of this file must
+.\" accept responsibility for any damage that occurs from the application of this
+.\" file.
+.\"
+.\" (julian@tfs.com julian@dialix.oz.au)
+.\" User SCSI hooks added by Peter Dufault:
+.\"
+.\" Copyright (c) 1994 HD Associates
+.\" (contact: dufault@hda.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. The name of HD Associates
+.\" may not be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY HD ASSOCIATES ``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 HD ASSOCIATES 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.
+.\"
+.\"
+.\" $Id: scsi.1,v 1.1 1993/11/18 05:05:27 rgrimes Exp $
+.\"
+.Dd October 11, 1993
+.Dt SCSI 1
+.Os BSD 4
+.Sh NAME
+.Nm scsi
+.Nd program to assist with scsi devices.
+.Sh SYNOPSIS
+.Bd -literal -offset
+Usage:
+scsi -f device -d debug_level # To set debug level
+scsi -f device -p [-b bus] [-l lun] # To probe all devices
+scsi -f device -r [-b bus] [-t targ] [-l lun] # To reprobe a device
+scsi -f device [-v] -c cmd_fmt [arg0 ... argn] \\ # To send a command...
+ -o count out_fmt [arg0 ... argn] # EITHER (for data out)
+ -i count in_fmt # OR (for data in)
+.Pp
+"out_fmt" can be "-" to read output data from stdin;
+"in_fmt" can be "-" to write input data to stdout;
+.Pp
+If debugging is not compiled in the kernel, "-d" will have no effect
+.Ed
+.Sh DESCRIPTION
+The
+.Nm scsi
+program is used to send commands to a scsi device. It is also
+a sample usage of the user level SCSI commands.
+.Pp
+The
+.Fr -d
+option sets the SCSI kernel debug level. The kernel must have been compiled
+with the
+.Em SCSIDEBUG
+option. See
+.Fr /sys/scsi/scsi_debug.h
+to figure out what to set the kernel debug level to.
+.Pp
+The
+.Fr -p
+option can be used against the "super scsi" device
+.Fr /dev/scsi/super
+to probe all devices with a given SCSI lun on a given SCSI bus.
+The bus can be selected with the -b option and the default is 0.
+The lun can be selected with the -l option and the default is 0.
+See
+.Xr scsi 4
+for a description of the "super scsi" device.
+.Pp
+The
+.Fr -r
+option can be used in FreeBSD 1.1 to reprobe a specific SCSI device at a given
+Bus, Target and Lun.
+This is not needed in FreeBSD 2.1, since opening a fixed SCSI device
+has the side effect of reprobing it, and probing with the bus with the
+-p option should bring on line any newly found devices.
+See
+.Xr scsi 4
+for a description of fixed scsi devices.
+.Pp
+The
+.Fr -c
+option permits you to send user level SCSI commands specified on
+the command line to a
+device. The command is sent using the SCIOCCOMMAND ioctl, so the
+device you are accessing must permit this ioctl. See
+.Xr scsi 4
+for full details of which minor devices permit the ioctl, and
+.Xr scsi 3
+for the full details on how to build up the commands and data phases
+using the format arguments.
+.Pp
+.Fr -v
+turns on more verbose information.
+.Pp
+.Fr "-c cmd_fmt"
+specifies the command as described in
+.Xr scsi 3 "."
+The additional arguments provide values for any variables
+specified in the command format.
+.Pp
+.Fr "-o count out_fmt arg0 ... argn"
+indicates that this is a data out command (i.e., data will be sent from
+the system to the device) with
+.Fr count
+bytes of data. The data out is built up using the facilities described in
+.Xr scsi 3
+using the provided arguments to fill in any integer variables.
+.Fr out_fmt
+can be specified as a hyphen ("-") to indicate that the
+.Fr count
+bytes of data should be read from the standard input.
+.Pp
+.Fr "-o count out_fmt arg0 ... argn"
+.Fr "-i count in_fmt"
+indicates that this is a data in command (i.e., data will be read from
+the device into the system) with
+.Fr count
+bytes of data read in. The information is extracted according to
+.Fr in_fmt
+using the facilities described in
+.Xr scsi 3
+and displayed on the standard output.
+.Fr in_fmt
+can be specified as a hyphen ("-") to indicate that the
+.Fr count
+bytes of data input should be written to the standard output.
+.Sh EXAMPLES
+To verify that the device type for the disk /dev/rsd0d is 0
+(direct access device):
+.Bd -literal -offset
+root# scsi -f /dev/rsd0d -c "12 0 0 0 64 0" -i 64 "*b3 b5"
+0
+.Ed
+.Pp
+To do an inquiry to /dev/rsd2d:
+.Bd -literal -offset
+root# scsi -f /dev/rsd2d -c "12 0 0 0 64 0" -i 64 "s8 z8 z16 z4"
+FUJITSU M2654S-512 010P
+.Ed
+.Pp
+.Sh SEE ALSO
+.Xr scsi 4 ,
+.Xr scsi 3
+.Sh BUGS
+.Pp
+.Fr out_fmt
+support for
+.Fr "-o count out_fmt arg0 ... argn"
+isn't written yet. You have to specify out_fmt as "-" and read the
+data in from standard input. If you want that capability
+ask dufault@hda.com.
+.Pp
+This command wasn't ready for inclusion in 2.0R and so is missing in
+that release.
+.Pp
+Some devices respond to an inquiry for all LUNS. This will cause them
+to come on line to 8 times during reprobe to different logical units.
+.Pp
+The "-i" option to do an inquiry went away in 2.1. The new facilities
+provided by "-c" supercede that.
+.Pp
+Check your permissions carefully.
+"scsi -f /dev/rsd0d -c "4 0 0 0 0 0" permits anyone who can open
+/dev/rsd0d to format the disk drive. This must be changed to
+at least require write access to the drive.
+.Sh HISTORY
+The
+.Nm scsi
+command appeared in 386BSD 0.1.2.4/FreeBSD to support the new reprobe
+and user SCSI commands.
diff --git a/sbin/scsi/scsi.c b/sbin/scsi/scsi.c
new file mode 100644
index 0000000..603fd8e
--- /dev/null
+++ b/sbin/scsi/scsi.c
@@ -0,0 +1,441 @@
+/*
+ * Written By Julian ELischer
+ * Copyright julian Elischer 1993.
+ * Permission is granted to use or redistribute this file in any way as long
+ * as this notice remains. Julian Elischer does not guarantee that this file
+ * is totally correct for any given task and users of this file must
+ * accept responsibility for any damage that occurs from the application of this
+ * file.
+ *
+ * (julian@tfs.com julian@dialix.oz.au)
+ *
+ * User SCSI hooks added by Peter Dufault:
+ *
+ * Copyright (c) 1994 HD Associates
+ * (contact: dufault@hda.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. The name of HD Associates
+ * may not be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY HD ASSOCIATES ``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 HD ASSOCIATES 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.
+ *
+ * $Id: scsi.c,v 1.1 1993/11/18 05:05:28 rgrimes Exp $
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/scsiio.h>
+#include <sys/file.h>
+#include <scsi.h>
+
+int fd;
+int debuglevel;
+int dflag,cmd;
+int reprobe;
+int probe_all;
+int verbose = 0;
+int bus = -1; /* all busses */
+int targ = -1; /* all targs */
+int lun = 0; /* just lun 0 */
+
+usage()
+{
+ printf(
+
+"Usage:\n"
+"\n"
+" scsi -f device -d debug_level # To set debug level\n"
+" scsi -f device -p [-b bus] [-l lun] # To probe all devices\n"
+" scsi -f device -r [-b bus] [-t targ] [-l lun] # To reprobe a device\n"
+" scsi -f device [-v] -c cmd_fmt [arg0 ... argn] \\ # To send a command...\n"
+" -o count out_fmt [arg0 ... argn] # EITHER (for data out)\n"
+" -i count in_fmt # OR (for data in)\n"
+"\n"
+"\"out_fmt\" can be \"-\" to read output data from stdin;\n"
+"\"in_fmt\" can be \"-\" to write input data to stdout;\n"
+"\n"
+"If debugging is not compiled in the kernel, \"-d\" will have no effect\n"
+
+);
+
+ exit (1);
+}
+
+void procargs(int *argc_p, char ***argv_p)
+{
+ int argc = *argc_p;
+ char **argv = *argv_p;
+ extern char *optarg;
+ extern int optind;
+ int fflag,
+ ch;
+
+ fflag = 0;
+ cmd = 0;
+ dflag = 0;
+ while ((ch = getopt(argc, argv, "vpcrf:d:b:t:l:")) != EOF) {
+ switch (ch) {
+ case 'p':
+ probe_all = 1;
+ break;
+ case 'r':
+ reprobe = 1;
+ break;
+ case 'c':
+ cmd = 1;
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ case 'f':
+ if ((fd = scsi_open(optarg, O_RDWR)) < 0) {
+ (void) fprintf(stderr,
+ "%s: unable to open device %s: %s\n",
+ argv[0], optarg, strerror(errno));
+ exit(errno);
+ }
+ fflag = 1;
+ break;
+ case 'd':
+ debuglevel = atoi(optarg);
+ dflag = 1;
+ break;
+ case 'b':
+ bus = atoi(optarg);
+ break;
+ case 't':
+ targ = atoi(optarg);
+ break;
+ case 'l':
+ lun = atoi(optarg);
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ }
+ *argc_p = argc - optind;
+ *argv_p = argv + optind;
+
+ if (!fflag) usage();
+}
+
+/* get_hook: Structure for evaluating args in a callback.
+ */
+struct get_hook
+{
+ int argc;
+ char **argv;
+ int got;
+};
+
+/* iget: Integer argument callback
+ */
+int iget(void *hook, char *name)
+{
+ struct get_hook *h = (struct get_hook *)hook;
+ int arg;
+
+ if (h->got >= h->argc)
+ {
+ fprintf(stderr, "Expecting an integer argument.\n");
+ usage();
+ }
+ arg = atol(h->argv[h->got]);
+ h->got++;
+
+ return arg;
+}
+
+/* cget: char * argument callback
+ */
+char *cget(void *hook, char *name)
+{
+ struct get_hook *h = (struct get_hook *)hook;
+ char *arg;
+
+ if (h->got >= h->argc)
+ {
+ fprintf(stderr, "Expecting a character pointer argument.\n");
+ usage();
+ }
+ arg = h->argv[h->got];
+ h->got++;
+
+ return arg;
+}
+
+/* arg_put: "put argument" callback
+ */
+void arg_put(void *hook, int letter, void *arg, int count, char *name)
+{
+ if (verbose)
+ printf("%s: ", name);
+
+ switch(letter)
+ {
+ case 'i':
+ case 'b':
+ printf("%d ", (int)arg);
+ break;
+
+ case 'c':
+ case 'z':
+ {
+ char *p = malloc(count + 1);
+ p[count] = 0;
+ strncpy(p, (char *)arg, count);
+ if (letter == 'z')
+ {
+ int i;
+ for (i = count - 1; i >= 0; i--)
+ if (p[i] == ' ')
+ p[i] = 0;
+ else
+ break;
+ }
+ printf("%s ", p);
+ }
+
+ break;
+
+ default:
+ printf("Unknown format letter: '%c'\n", letter);
+ }
+ if (verbose)
+ putchar('\n');
+}
+
+/* data_phase: SCSI bus data phase: DATA IN, DATA OUT, or no data transfer.
+ */
+enum data_phase {none = 0, in, out};
+
+/* do_cmd: Send a command to a SCSI device
+ */
+void do_cmd(int fd, char *fmt, int argc, char **argv)
+{
+ struct get_hook h;
+ scsireq_t *scsireq = scsireq_new();
+ enum data_phase data_phase;
+ int output = 0;
+
+ h.argc = argc;
+ h.argv = argv;
+ h.got = 0;
+
+ scsireq_reset(scsireq);
+
+ scsireq_build_visit(scsireq, 0, 0, 0, fmt, iget, (void *)&h);
+
+ /* Three choices here:
+ * 1. We've used up all the args and have no data phase.
+ * 2. We have input data ("-i")
+ * 3. We have output data ("-o")
+ */
+
+ if (h.got >= h.argc)
+ data_phase = none;
+ else
+ {
+ char *flag = cget(&h, 0);
+
+ if (strcmp(flag, "-o") == 0)
+ data_phase = out;
+ else if (strcmp(flag, "-i") == 0)
+ data_phase = in;
+ else
+ {
+ fprintf(stderr,
+ "Need either \"-i\" or \"-o\" for data phase; not \"%s\".\n", flag);
+ usage();
+ }
+ }
+
+ if (data_phase == none)
+ scsireq->datalen = 0;
+ else
+ {
+ int count;
+
+ if (data_phase == out)
+ scsireq->flags = SCCMD_WRITE;
+ else
+ scsireq->flags = SCCMD_READ;
+
+ count = iget(&h, 0);
+ scsireq->datalen = count;
+
+ if (count)
+ {
+ char *data_fmt;
+ data_fmt = cget(&h, 0);
+
+ scsireq->databuf = malloc(count);
+
+ if (data_phase == out)
+ {
+ if (strcmp(data_fmt, "-") == 0) /* stdin */
+ {
+ if (read(0, scsireq->databuf, count) != count)
+ {
+ perror("read");
+ exit(errno);
+ }
+ }
+ else /* XXX: Not written yet */
+ {
+ fprintf(stderr, "Can't set up output data using %s.\n",
+ data_fmt);
+ exit(-1);
+ }
+ }
+
+ if (scsireq_enter(fd, scsireq) == -1)
+ {
+ scsi_debug(stderr, -1, scsireq);
+ exit(errno);
+ }
+
+ if (data_phase == in)
+ {
+ if (strcmp(data_fmt, "-") == 0) /* stdout */
+ {
+ if (write(1, scsireq->databuf, count) != count)
+ {
+ perror("write");
+ exit(errno);
+ }
+ }
+ else
+ {
+ scsireq_decode_visit(scsireq, data_fmt, arg_put, 0);
+ putchar('\n');
+ }
+ }
+ }
+ }
+}
+
+/* do_probe_all: Loop over all SCSI IDs and see if something is
+ * there. This only does BUS 0 LUN 0.
+ */
+do_probe_all()
+{
+ scsireq_t *scsireq;
+
+ char vendor_id[8 + 1], product_id[16 + 1], revision[4 + 1];
+ int id;
+ u_char *inq_buf = malloc(96);
+ struct scsi_addr addr;
+
+ scsireq = scsireq_build(scsireq_new(),
+ 96, inq_buf, SCCMD_READ,
+ "12 0 0 0 v 0", 96);
+
+ addr.scbus = (bus == -1) ? 0 : bus;
+ addr.lun = lun;
+
+ if (addr.scbus || addr.lun)
+ {
+ printf("For bus %d lun %d:\n", addr.scbus, addr.lun);
+ }
+
+ for (id = 0; id < 8; id++)
+ {
+ addr.target = id;
+
+ printf("%d: ", id);
+ if (ioctl(fd, SCIOCADDR, &addr) == -1) {
+ if (errno == ENXIO)
+ {
+ errno = 0;
+ printf("nothing.\n");
+ }
+ else
+ printf("SCIOCADDR: %s\n", strerror(errno));
+
+ continue;
+ }
+
+ if (scsireq_enter(fd, scsireq) == -1) {
+ printf("scsireq_enter: %s\n", strerror(errno));
+ continue;
+ }
+
+ vendor_id[sizeof(vendor_id) - 1] = 0;
+ product_id[sizeof(product_id) - 1] = 0;
+ revision[sizeof(revision) - 1] = 0;
+
+ scsireq_decode(scsireq, "s8 c8 c16 c4",
+ vendor_id, product_id, revision);
+
+ printf("%s %s %s\n", vendor_id, product_id, revision);
+ }
+}
+
+main(int argc, char **argv)
+{
+ struct scsi_addr scaddr;
+
+ procargs(&argc,&argv);
+
+ if (probe_all) {
+ do_probe_all();
+ }
+
+ if(reprobe) {
+ scaddr.scbus = bus;
+ scaddr.target = targ;
+ scaddr.lun = lun;
+
+ if (ioctl(fd,SCIOCREPROBE,&scaddr) == -1)
+ perror("ioctl");
+ }
+
+ if(dflag) {
+ if (ioctl(fd,SCIOCDEBUG,&debuglevel) == -1)
+ {
+ perror("ioctl [SCIODEBUG]");
+ exit(1);
+ }
+ }
+
+ if (cmd) {
+ char *fmt;
+
+ if (argc <= 1)
+ {
+ fprintf(stderr, "Need the command format string.\n");
+ usage();
+ }
+
+ fmt = argv[0];
+
+ argc -= 1;
+ argv += 1;
+
+ do_cmd(fd, fmt, argc, argv);
+ }
+}
OpenPOWER on IntegriCloud