diff options
author | ken <ken@FreeBSD.org> | 1999-05-10 23:30:04 +0000 |
---|---|---|
committer | ken <ken@FreeBSD.org> | 1999-05-10 23:30:04 +0000 |
commit | 5553fc066610f4bcda2854fa7607e25a18ec7578 (patch) | |
tree | 1c5de8a5424cc55605a438a67428e5d7d77b14e3 | |
parent | d2071f7fb823fca6d3f4948da0847b45ed5a11b2 (diff) | |
download | FreeBSD-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.8 | 62 | ||||
-rw-r--r-- | sbin/camcontrol/camcontrol.c | 217 | ||||
-rw-r--r-- | sbin/camcontrol/camcontrol.h | 4 | ||||
-rw-r--r-- | sbin/camcontrol/modeedit.c | 6 | ||||
-rw-r--r-- | sbin/camcontrol/util.c | 6 |
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]; |