summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorken <ken@FreeBSD.org>1999-05-10 23:30:04 +0000
committerken <ken@FreeBSD.org>1999-05-10 23:30:04 +0000
commit5553fc066610f4bcda2854fa7607e25a18ec7578 (patch)
tree1c5de8a5424cc55605a438a67428e5d7d77b14e3
parentd2071f7fb823fca6d3f4948da0847b45ed5a11b2 (diff)
downloadFreeBSD-src-5553fc066610f4bcda2854fa7607e25a18ec7578.zip
FreeBSD-src-5553fc066610f4bcda2854fa7607e25a18ec7578.tar.gz
Add a new device specification syntax to camcontrol. It is now possible to
do things like: camcontrol tur da5 or camcontrol tur 1:2:0 or camcontrol tur 1:2 These changes are fully backwards compatible with the original device specification syntax (-n dev -u unit), so it is possible to use either method to specify a device now. The device specification changes do not affect the rescan, reset or debug commands, since by design, those commands work on a bus or bus:target:lun basis only. Also, shorten the default usage statement so that it fits in a 24 column terminal. The full usage statement is still available by using the "help" "-h" or "-?" arguments to camcontrol. Submitted by: Joerg Wunsch <joerg_wunsch@interface-business.de>
-rw-r--r--sbin/camcontrol/camcontrol.862
-rw-r--r--sbin/camcontrol/camcontrol.c217
-rw-r--r--sbin/camcontrol/camcontrol.h4
-rw-r--r--sbin/camcontrol/modeedit.c6
-rw-r--r--sbin/camcontrol/util.c6
5 files changed, 204 insertions, 91 deletions
diff --git a/sbin/camcontrol/camcontrol.8 b/sbin/camcontrol/camcontrol.8
index f5dea97..81fbfb6 100644
--- a/sbin/camcontrol/camcontrol.8
+++ b/sbin/camcontrol/camcontrol.8
@@ -25,7 +25,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $Id: camcontrol.8,v 1.10 1999/02/27 07:55:58 ken Exp $
+.\" $Id: camcontrol.8,v 1.11 1999/05/06 20:15:37 ken Exp $
.\"
.Dd September 14, 1998
.Dt CAMCONTROL 8
@@ -36,6 +36,7 @@
.Sh SYNOPSIS
.Nm camcontrol
.Aq command
+.Op device id
.Op generic args
.Op command args
.Nm camcontrol
@@ -43,25 +44,31 @@ devlist
.Op Fl v
.Nm camcontrol
periphlist
+.Op device id
.Op Fl n Ar dev_name
.Op Fl u Ar unit_number
.Nm camcontrol
tur
+.Op device id
.Op generic args
.Nm camcontrol
inquiry
+.Op device id
.Op generic args
.Op Fl D
.Op Fl S
.Op Fl R
.Nm camcontrol
start
+.Op device id
.Op generic args
.Nm camcontrol
stop
+.Op device id
.Op generic args
.Nm camcontrol
eject
+.Op device id
.Op generic args
.Nm camcontrol
rescan
@@ -71,12 +78,14 @@ reset
.Aq bus Ns Op :target:lun
.Nm camcontrol
defects
+.Op device id
.Op generic args
.Aq Fl f Ar format
.Op Fl P
.Op Fl G
.Nm camcontrol
modepage
+.Op device id
.Op generic args
.Aq Fl m Ar page
.Op Fl P Ar pgctl
@@ -84,6 +93,7 @@ modepage
.Op Fl d
.Nm camcontrol
cmd
+.Op device id
.Op generic args
.Aq Fl c Ar cmd Op args
.Op Fl i Ar len Ar fmt
@@ -99,12 +109,14 @@ debug
.Aq all|off|bus Ns Op :target Ns Op :lun
.Nm camcontrol
tags
+.Op device id
.Op generic args
.Op Fl N Ar tags
.Op Fl q
.Op Fl v
.Nm camcontrol
negotiate
+.Op device id
.Op generic args
.Op Fl c
.Op Fl D Ar enable|disable
@@ -115,6 +127,8 @@ negotiate
.Op Fl U
.Op Fl W Ar bus_width
.Op Fl v
+.Nm camcontrol
+help
.Sh DESCRIPTION
.Nm camcontrol
is a utility designed to provide a way for users to access and control the
@@ -127,8 +141,42 @@ expert users are encouraged to exercise caution when using this command.
Novice users should stay away from this utility.
.Pp
.Nm camcontrol
-has a number of primary functions, most of which take some generic
-arguments:
+has a number of primary functions, many of which support an optional
+device identifier. A device identifier can take one of three forms:
+.Bl -tag -width 01234567890123
+.It deviceUNIT
+Specify a device name and unit number combination, like "da5" or "cd3".
+Note that character device node names (e.g. /dev/rsd0.ctl) are
+.Em not
+allowed here.
+.It bus:target
+Specify a bus number and target id. The bus number can be determined from
+the output of
+.Dq camcontrol devlist .
+The lun defaults to 0.
+.It bus:target:lun
+Specify the bus, target and lun for a device. (e.g. 1:2:0)
+.El
+.Pp
+The device identifier, if it is specified,
+.Em must
+come immediately after the function name, and before any generic or
+function-specific arguments. Note that the
+.Fl n
+and
+.Fl u
+arguments described below will override any device name or unit number
+specified beforehand. The
+.Fl n
+and
+.Fl u
+arguments will
+.Em not
+override a specified bus:target or bus:target:lun, howevever.
+.Pp
+Most of the
+.Nm camcontrol
+primary functions support these generic arguments:
.Bl -tag -width 01234567890123
.It Fl C Ar count
SCSI command retry count. In order for this to work, error recovery
@@ -461,6 +509,8 @@ device until a command has been sent to the device. The
.Fl a
switch above will automatically send a Test Unit Ready to the device so
negotiation parameters will take effect.
+.It help
+Print out a verbose usage information.
.El
.Sh ENVIRONMENT
The
@@ -497,7 +547,7 @@ information if the command fails since the
switch was not specified.
.Pp
.Bd -literal -offset foobar
-camcontrol tur -n da -u 1 -E -C 4 -t 50 -v
+camcontrol tur da1 -E -C 4 -t 50 -v
.Ed
.Pp
Send a test unit ready command to da1. Enable kernel error recovery.
@@ -528,7 +578,7 @@ the command fails. Be very careful with this command, improper use may
cause data corruption.
.Pp
.Bd -literal -offset foobar
-camcontrol modepage -n da -u 3 -m 1 -e -P 3
+camcontrol modepage da3 -m 1 -e -P 3
.Ed
.Pp
Edit mode page 1 (the Read-Write Error Recover page) for da3, and save the
@@ -544,7 +594,7 @@ Rescan SCSI bus 0 for devices that have been added, removed or changed.
Rescan SCSI bus 0, target 1, lun 0 to see if it has been added, removed, or
changed.
.Pp
-.Dl camcontrol tags -n da -u 5 -N 24
+.Dl camcontrol tags da5 -N 24
.Pp
Set the number of concurrent transactions for da5 to 24.
.Pp
diff --git a/sbin/camcontrol/camcontrol.c b/sbin/camcontrol/camcontrol.c
index 385e677..a129e18 100644
--- a/sbin/camcontrol/camcontrol.c
+++ b/sbin/camcontrol/camcontrol.c
@@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: camcontrol.c,v 1.9 1999/01/14 05:56:30 gibbs Exp $
+ * $Id: camcontrol.c,v 1.10 1999/05/06 20:15:38 ken Exp $
*/
#include <sys/ioctl.h>
@@ -145,6 +145,7 @@ typedef enum {
} camcontrol_optret;
cam_argmask arglist;
+int bus, target, lun;
camcontrol_optret getoption(char *arg, cam_argmask *argnum, char **subopt);
@@ -159,6 +160,8 @@ static int scsidoinquiry(struct cam_device *device, int argc, char **argv,
static int scsiinquiry(struct cam_device *device, int retry_count, int timeout);
static int scsiserial(struct cam_device *device, int retry_count, int timeout);
static int scsixferrate(struct cam_device *device);
+static int parse_btl(char *tstr, int *bus, int *target, int *lun,
+ cam_argmask *arglist);
static int dorescan_or_reset(int argc, char **argv, int rescan);
static int rescan_or_reset_bus(int bus, int rescan);
static int scanlun_or_reset_dev(int bus, int target, int lun, int scan);
@@ -908,12 +911,52 @@ xferrate_bailout:
return(retval);
}
+/*
+ * Parse out a bus, or a bus, target and lun in the following
+ * format:
+ * bus
+ * bus:target
+ * bus:target:lun
+ *
+ * Returns the number of parsed components, or 0.
+ */
+static int
+parse_btl(char *tstr, int *bus, int *target, int *lun, cam_argmask *arglist)
+{
+ char *tmpstr;
+ int convs = 0;
+
+ while (isspace(*tstr) && (*tstr != '\0'))
+ tstr++;
+
+ tmpstr = (char *)strtok(tstr, ":");
+ if ((tmpstr != NULL) && (*tmpstr != '\0')) {
+ *bus = strtol(tmpstr, NULL, 0);
+ *arglist |= CAM_ARG_BUS;
+ convs++;
+ tmpstr = (char *)strtok(NULL, ":");
+ if ((tmpstr != NULL) && (*tmpstr != '\0')) {
+ *target = strtol(tmpstr, NULL, 0);
+ *arglist |= CAM_ARG_TARGET;
+ convs++;
+ tmpstr = (char *)strtok(NULL, ":");
+ if ((tmpstr != NULL) && (*tmpstr != '\0')) {
+ *lun = strtol(tmpstr, NULL, 0);
+ *arglist |= CAM_ARG_LUN;
+ convs++;
+ }
+ }
+ }
+
+ return convs;
+}
+
static int
dorescan_or_reset(int argc, char **argv, int rescan)
{
static const char *must =
"you must specify a bus, or a bus:target:lun to %s";
- int error = 0;
+ int rv, error = 0;
int bus = -1, target = -1, lun = -1;
char *tstr, *tmpstr = NULL;
@@ -921,53 +964,19 @@ dorescan_or_reset(int argc, char **argv, int rescan)
warnx(must, rescan? "rescan" : "reset");
return(1);
}
- /*
- * Parse out a bus, or a bus, target and lun in the following
- * format:
- * bus
- * bus:target:lun
- * It is an error to specify a bus and target, but not a lun.
- */
- tstr = argv[optind];
-
- while (isspace(*tstr) && (*tstr != '\0'))
- tstr++;
-
- tmpstr = (char *)strtok(tstr, ":");
- if ((tmpstr != NULL) && (*tmpstr != '\0')){
- bus = strtol(tmpstr, NULL, 0);
- arglist |= CAM_ARG_BUS;
- tmpstr = (char *)strtok(NULL, ":");
- if ((tmpstr != NULL) && (*tmpstr != '\0')){
- target = strtol(tmpstr, NULL, 0);
- arglist |= CAM_ARG_TARGET;
- tmpstr = (char *)strtok(NULL, ":");
- if ((tmpstr != NULL) && (*tmpstr != '\0')){
- lun = strtol(tmpstr, NULL, 0);
- arglist |= CAM_ARG_LUN;
- } else {
- error = 1;
- warnx(must, rescan? "rescan" : "reset");
- }
- }
- } else {
- error = 1;
+ rv = parse_btl(argv[optind], &bus, &target, &lun, &arglist);
+ if (rv != 1 && rv != 3) {
warnx(must, rescan? "rescan" : "reset");
+ return(1);
}
+ if ((arglist & CAM_ARG_BUS)
+ && (arglist & CAM_ARG_TARGET)
+ && (arglist & CAM_ARG_LUN))
+ error = scanlun_or_reset_dev(bus, target, lun, rescan);
+ else
+ error = rescan_or_reset_bus(bus, rescan);
- if (error == 0) {
- if ((arglist & CAM_ARG_BUS)
- && (arglist & CAM_ARG_TARGET)
- && (arglist & CAM_ARG_LUN))
- error = scanlun_or_reset_dev(bus, target, lun, rescan);
- else if (arglist & CAM_ARG_BUS)
- error = rescan_or_reset_bus(bus, rescan);
- else {
- error = 1;
- warnx(must, rescan? "rescan" : "reset");
- }
- }
return(error);
}
@@ -2575,28 +2584,34 @@ ratecontrol_bailout:
}
void
-usage(void)
+usage(int verbose)
{
fprintf(stderr,
-"usage: camcontrol <command> [ generic args ] [ command args ]\n"
+"usage: camcontrol <command> [device id][generic args][command args]\n"
" camcontrol devlist [-v]\n"
-" camcontrol periphlist [-n dev_name] [-u unit]\n"
-" camcontrol tur [generic args]\n"
-" camcontrol inquiry [generic args] [-D] [-S] [-R]\n"
-" camcontrol start [generic args]\n"
-" camcontrol stop [generic args]\n"
-" camcontrol eject [generic args]\n"
+" camcontrol periphlist [dev_id][-n dev_name] [-u unit]\n"
+" camcontrol tur [dev_id][generic args]\n"
+" camcontrol inquiry [dev_id][generic args] [-D] [-S] [-R]\n"
+" camcontrol start [dev_id][generic args]\n"
+" camcontrol stop [dev_id][generic args]\n"
+" camcontrol eject [dev_id][generic args]\n"
" camcontrol rescan <bus[:target:lun]>\n"
" camcontrol reset <bus[:target:lun]>\n"
-" camcontrol defects [generic args] <-f format> [-P][-G]\n"
-" camcontrol modepage [generic args] <-m page> [-P pagectl][-e][-d]\n"
-" camcontrol cmd [generic args] <-c cmd [args]> \n"
+" camcontrol defects [dev_id][generic args] <-f format> [-P][-G]\n"
+" camcontrol modepage [dev_id][generic args] <-m page> [-P pagectl]\n"
+" [-e][-d]\n"
+" camcontrol cmd [dev_id][generic args] <-c cmd [args]>\n"
" [-i len fmt|-o len fmt [args]]\n"
" camcontrol debug [-I][-T][-S][-c] <all|bus[:target[:lun]]|off>\n"
-" camcontrol tags [generic args] [-N tags] [-q] [-v]\n"
-" camcontrol negotiate [generic args] [-a][-c][-D <enable|disable>]\n"
-" [-O offset][-q][-R syncrate][-v]\n"
-" [-T <enable|disable>][-U][-W bus_width]\n"
+" camcontrol tags [dev_id][generic args] [-N tags] [-q] [-v]\n"
+" camcontrol negotiate [dev_id][generic args] [-a][-c]\n"
+" [-D <enable|disable>][-O offset][-q]\n"
+" [-R syncrate][-v][-T <enable|disable>]\n"
+" [-U][-W bus_width]\n"
+" camcontrol help\n");
+ if (!verbose)
+ return;
+ fprintf(stderr,
"Specify one of the following options:\n"
"devlist list all CAM devices\n"
"periphlist list all CAM peripheral drivers attached to a device\n"
@@ -2613,6 +2628,11 @@ usage(void)
"debug turn debugging on/off for a bus, target, or lun, or all devices\n"
"tags report or set the number of transaction slots for a device\n"
"negotiate report or set device negotiation parameters\n"
+"help this message\n"
+"Device Identifiers:\n"
+"bus:target specify the bus and target, lun defaults to 0\n"
+"bus:target:lun specify the bus, target and lun\n"
+"deviceUNIT specify the device name, like \"da4\" or \"cd2\"\n"
"Generic arguments:\n"
"-v be verbose, print out sense information\n"
"-t timeout command timeout in seconds, overrides default timeout\n"
@@ -2673,12 +2693,13 @@ main(int argc, char **argv)
char *mainopt = "C:En:t:u:v";
char *subopt = NULL;
char combinedopt[256];
- int error = 0;
+ int error = 0, optstart = 2;
+ int devopen = 1;
arglist = CAM_ARG_NONE;
if (argc < 2) {
- usage();
+ usage(0);
exit(1);
}
@@ -2689,11 +2710,11 @@ main(int argc, char **argv)
if (optreturn == CC_OR_AMBIGUOUS) {
warnx("ambiguous option %s", argv[1]);
- usage();
+ usage(0);
exit(1);
} else if (optreturn == CC_OR_NOT_FOUND) {
warnx("option %s not found", argv[1]);
- usage();
+ usage(0);
exit(1);
}
@@ -2750,10 +2771,52 @@ main(int argc, char **argv)
sprintf(combinedopt, "%s", mainopt);
/*
- * Start getopt processing at argv[2], since we've already accepted
- * argv[1] as the command name.
+ * For these options we do not parse optional device arguments and
+ * we do not open a passthrough device.
*/
- optind = 2;
+ if (((arglist & CAM_ARG_OPT_MASK) == CAM_ARG_RESCAN)
+ || ((arglist & CAM_ARG_OPT_MASK) == CAM_ARG_RESET)
+ || ((arglist & CAM_ARG_OPT_MASK) == CAM_ARG_DEVTREE)
+ || ((arglist & CAM_ARG_OPT_MASK) == CAM_ARG_USAGE)
+ || ((arglist & CAM_ARG_OPT_MASK) == CAM_ARG_DEBUG))
+ devopen = 0;
+
+ if ((devopen == 1)
+ && (argc > 2 && argv[2][0] != '-')) {
+ char name[30];
+ int rv;
+
+ /*
+ * First catch people who try to do things like:
+ * camcontrol tur /dev/rsd0.ctl
+ * camcontrol doesn't take device nodes as arguments.
+ */
+ if (argv[2][0] == '/') {
+ warnx("%s is not a valid device identifier", argv[2]);
+ errx(1, "please read the camcontrol(8) man page");
+ } else if (isdigit(argv[2][0])) {
+ /* device specified as bus:target[:lun] */
+ rv = parse_btl(argv[2], &bus, &target, &lun, &arglist);
+ if (rv < 2)
+ errx(1, "numeric device specification must "
+ "be either bus:target, or "
+ "bus:target:lun");
+ optstart++;
+ } else {
+ if (cam_get_device(argv[2], name, sizeof name, &unit)
+ == -1)
+ errx(1, "%s", cam_errbuf);
+ device = strdup(name);
+ arglist |= CAM_ARG_DEVICE | CAM_ARG_UNIT;
+ optstart++;
+ }
+ }
+ /*
+ * Start getopt processing at argv[2/3], since we've already
+ * accepted argv[1..2] as the command name, and as a possible
+ * device name.
+ */
+ optind = optstart;
/*
* Now we run through the argument list looking for generic
@@ -2811,14 +2874,11 @@ main(int argc, char **argv)
* commands, we don't use a passthrough device at all, just the
* transport layer device.
*/
- if (((arglist & CAM_ARG_OPT_MASK) != CAM_ARG_RESCAN)
- && ((arglist & CAM_ARG_OPT_MASK) != CAM_ARG_RESET)
- && ((arglist & CAM_ARG_OPT_MASK) != CAM_ARG_DEVTREE)
- && ((arglist & CAM_ARG_OPT_MASK) != CAM_ARG_USAGE)
- && ((arglist & CAM_ARG_OPT_MASK) != CAM_ARG_DEBUG)) {
-
- if ((cam_dev = cam_open_spec_device(device,unit,O_RDWR,
- NULL))== NULL)
+ if (devopen == 1) {
+ if ((cam_dev = ((arglist & (CAM_ARG_BUS | CAM_ARG_TARGET))?
+ cam_open_btl(bus, target, lun, O_RDWR, NULL) :
+ cam_open_spec_device(device,unit,O_RDWR,NULL)))
+ == NULL)
errx(1,"%s", cam_errbuf);
}
@@ -2826,7 +2886,7 @@ main(int argc, char **argv)
* Reset optind to 2, and reset getopt, so these routines can parse
* the arguments again.
*/
- optind = 2;
+ optind = optstart;
optreset = 1;
switch(arglist & CAM_ARG_OPT_MASK) {
@@ -2876,8 +2936,11 @@ main(int argc, char **argv)
error = ratecontrol(cam_dev, retry_count, timeout,
argc, argv, combinedopt);
break;
+ case CAM_ARG_USAGE:
+ usage(1);
+ break;
default:
- usage();
+ usage(0);
error = 1;
break;
}
diff --git a/sbin/camcontrol/camcontrol.h b/sbin/camcontrol/camcontrol.h
index 8fb64a7..e821834 100644
--- a/sbin/camcontrol/camcontrol.h
+++ b/sbin/camcontrol/camcontrol.h
@@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id$
+ * $Id: camcontrol.h,v 1.1 1998/09/15 06:43:02 gibbs Exp $
*/
#ifndef _CAMCONTROL_H
@@ -50,5 +50,5 @@ void mode_edit(struct cam_device *device, int page, int page_control, int dbd,
char *cget(void *hook, char *name);
int iget(void *hook, char *name);
void arg_put(void *hook, int letter, void *arg, int count, char *name);
-void usage(void);
+void usage(int verbose);
#endif /* _CAMCONTROL_H */
diff --git a/sbin/camcontrol/modeedit.c b/sbin/camcontrol/modeedit.c
index 131624f..6df2392 100644
--- a/sbin/camcontrol/modeedit.c
+++ b/sbin/camcontrol/modeedit.c
@@ -45,7 +45,7 @@
*/
#ifndef lint
static const char rcsid[] =
- "$Id$";
+ "$Id: modeedit.c,v 1.1 1998/09/15 06:43:02 gibbs Exp $";
#endif /* not lint */
#include <ctype.h>
@@ -76,7 +76,7 @@ iget(void *hook, char *name)
if (h->got >= h->argc)
{
fprintf(stderr, "Expecting an integer argument.\n");
- usage();
+ usage(0);
exit(1);
}
arg = strtol(h->argv[h->got], 0, 0);
@@ -99,7 +99,7 @@ cget(void *hook, char *name)
if (h->got >= h->argc)
{
fprintf(stderr, "Expecting a character pointer argument.\n");
- usage();
+ usage(0);
exit(1);
}
arg = h->argv[h->got];
diff --git a/sbin/camcontrol/util.c b/sbin/camcontrol/util.c
index 131624f..6df2392 100644
--- a/sbin/camcontrol/util.c
+++ b/sbin/camcontrol/util.c
@@ -45,7 +45,7 @@
*/
#ifndef lint
static const char rcsid[] =
- "$Id$";
+ "$Id: modeedit.c,v 1.1 1998/09/15 06:43:02 gibbs Exp $";
#endif /* not lint */
#include <ctype.h>
@@ -76,7 +76,7 @@ iget(void *hook, char *name)
if (h->got >= h->argc)
{
fprintf(stderr, "Expecting an integer argument.\n");
- usage();
+ usage(0);
exit(1);
}
arg = strtol(h->argv[h->got], 0, 0);
@@ -99,7 +99,7 @@ cget(void *hook, char *name)
if (h->got >= h->argc)
{
fprintf(stderr, "Expecting a character pointer argument.\n");
- usage();
+ usage(0);
exit(1);
}
arg = h->argv[h->got];
OpenPOWER on IntegriCloud