diff --git a/sbin/camcontrol/camcontrol.8 b/sbin/camcontrol/camcontrol.8 index cb77793e6b05..1ab0f8ffc3bc 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.7 1998/10/06 00:32:58 ken Exp $ +.\" $Id: camcontrol.8,v 1.8 1998/12/02 22:42:36 billf Exp $ .\" .Dd September 14, 1998 .Dt CAMCONTROL 8 @@ -67,6 +67,9 @@ eject rescan .Aq bus Ns Op :target:lun .Nm camcontrol +reset +.Aq bus Ns Op :target:lun +.Nm camcontrol defects .Op generic args .Aq Fl f Ar format @@ -184,6 +187,12 @@ Tell the kernel to scan the given bus (XPT_SCAN_BUS), or bus:target:lun (XPT_SCAN_LUN) for new devices or devices that have gone away. The user may only specify a bus to scan, or a lun. Scanning all luns on a target isn't supported. +.It reset +Tell the kernel to reset the given bus (XPT_RESET_BUS) by issuing a SCSI bus +reset for that bus, or to reset the given bus:target:lun +(XPT_RESET_DEV), typically by issuing a BUS DEVICE RESET message after +connecting to that device. Note that this can have a destructive impact +on the system. .It defects Send the SCSI READ DEFECT DATA (10) command (0x37) to the given device, and print out any combination of: the total number of defects, the primary diff --git a/sbin/camcontrol/camcontrol.c b/sbin/camcontrol/camcontrol.c index 054027fe7de3..61caea11239c 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.5 1998/10/13 22:02:38 ken Exp $ + * $Id: camcontrol.c,v 1.6 1998/11/12 17:47:24 ken Exp $ */ #include @@ -64,6 +64,7 @@ typedef enum { CAM_ARG_DEVTREE = 0x00000009, CAM_ARG_USAGE = 0x0000000a, CAM_ARG_DEBUG = 0x0000000b, + CAM_ARG_RESET = 0x0000000c, CAM_ARG_OPT_MASK = 0x0000000f, CAM_ARG_VERBOSE = 0x00000010, CAM_ARG_DEVICE = 0x00000020, @@ -115,6 +116,7 @@ struct camcontrol_opts option_table[] = { {"stop", CAM_ARG_STARTSTOP, NULL}, {"eject", CAM_ARG_STARTSTOP | CAM_ARG_EJECT, NULL}, {"rescan", CAM_ARG_RESCAN, NULL}, + {"reset", CAM_ARG_RESET, NULL}, {"cmd", CAM_ARG_SCSI_CMD, scsicmd_opts}, {"command", CAM_ARG_SCSI_CMD, scsicmd_opts}, {"defects", CAM_ARG_READ_DEFECTS, readdefect_opts}, @@ -150,9 +152,9 @@ 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 dorescan(int argc, char **argv); -static int rescanbus(int bus); -static int scanlun(int bus, int target, int lun); +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); static int readdefects(struct cam_device *device, int argc, char **argv, char *combinedopt, int retry_count, int timeout); static void modepage(struct cam_device *device, int argc, char **argv, @@ -797,14 +799,16 @@ scsixferrate(struct cam_device *device) } static int -dorescan(int argc, char **argv) +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 bus = -1, target = -1, lun = -1; char *tstr, *tmpstr = NULL; if (argc < 3) { - warnx("you must specify a bus, or a bus:target:lun to rescan"); + warnx(must, rescan? "rescan" : "reset"); return(1); } /* @@ -833,13 +837,12 @@ dorescan(int argc, char **argv) arglist |= CAM_ARG_LUN; } else { error = 1; - warnx("you must specify either a bus or"); - warnx("a bus, target and lun for rescanning"); + warnx(must, rescan? "rescan" : "reset"); } } } else { error = 1; - warnx("you must at least specify a bus to rescan"); + warnx(must, rescan? "rescan" : "reset"); } @@ -847,20 +850,19 @@ dorescan(int argc, char **argv) if ((arglist & CAM_ARG_BUS) && (arglist & CAM_ARG_TARGET) && (arglist & CAM_ARG_LUN)) - error = scanlun(bus, target, lun); + error = scanlun_or_reset_dev(bus, target, lun, rescan); else if (arglist & CAM_ARG_BUS) - error = rescanbus(bus); + error = rescan_or_reset_bus(bus, rescan); else { error = 1; - warnx("you must specify either a bus or"); - warnx("a bus, target and lun for rescanning"); + warnx(must, rescan? "rescan" : "reset"); } } return(error); } static int -rescanbus(int bus) +rescan_or_reset_bus(int bus, int rescan) { union ccb ccb; int fd; @@ -876,7 +878,7 @@ rescanbus(int bus) return(1); } - ccb.ccb_h.func_code = XPT_SCAN_BUS; + ccb.ccb_h.func_code = rescan? XPT_SCAN_BUS : XPT_RESET_BUS; ccb.ccb_h.path_id = bus; ccb.ccb_h.target_id = CAM_TARGET_WILDCARD; ccb.ccb_h.target_lun = CAM_LUN_WILDCARD; @@ -894,17 +896,19 @@ rescanbus(int bus) close(fd); if ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { - fprintf(stdout, "Re-scan of bus %d was successful\n", bus); + fprintf(stdout, "%s of bus %d was successful\n", bus, + rescan? "Re-scan" : "Reset"); return(0); } else { - fprintf(stdout, "Re-scan of bus %d returned error %#x\n", - bus, ccb.ccb_h.status & CAM_STATUS_MASK); + fprintf(stdout, "%s of bus %d returned error %#x\n", + rescan? "Re-scan" : "Reset", bus, + ccb.ccb_h.status & CAM_STATUS_MASK); return(1); } } static int -scanlun(int bus, int target, int lun) +scanlun_or_reset_dev(int bus, int target, int lun, int scan) { union ccb ccb; int fd; @@ -931,7 +935,7 @@ scanlun(int bus, int target, int lun) return(1); } - ccb.ccb_h.func_code = XPT_SCAN_LUN; + ccb.ccb_h.func_code = (scan)? XPT_SCAN_LUN : XPT_RESET_DEV; ccb.ccb_h.path_id = bus; ccb.ccb_h.target_id = target; ccb.ccb_h.target_lun = lun; @@ -949,12 +953,13 @@ scanlun(int bus, int target, int lun) close(fd); if ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { - fprintf(stdout, "Re-scan of %d:%d:%d was successful\n", - bus, target, lun); + fprintf(stdout, "%s of %d:%d:%d was successful\n", + scan? "Re-scan" : "Reset", bus, target, lun); return(0); } else { - fprintf(stdout, "Re-scan of %d:%d:%d returned error %#x\n", - bus, target, lun, ccb.ccb_h.status & CAM_STATUS_MASK); + fprintf(stdout, "%s of %d:%d:%d returned error %#x\n", + scan? "Re-scan" : "Reset", bus, target, lun, + ccb.ccb_h.status & CAM_STATUS_MASK); return(1); } } @@ -1789,6 +1794,7 @@ usage(void) " camcontrol stop [generic args]\n" " camcontrol eject [generic args]\n" " camcontrol rescan \n" +" camcontrol reset \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" @@ -1803,6 +1809,7 @@ usage(void) "stop send a Stop Unit command to the device\n" "eject send a Stop Unit command to the device with the eject bit set\n" "rescan rescan the given bus, or bus:target:lun\n" +"reset reset the given bus, or bus:target:lun\n" "defects read the defect list of the specified device\n" "modepage display or edit (-e) the given mode page\n" "cmd send the given scsi command, may need -i or -o as well\n" @@ -1989,7 +1996,8 @@ 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) + 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)) { @@ -2026,7 +2034,10 @@ main(int argc, char **argv) timeout); break; case CAM_ARG_RESCAN: - error = dorescan(argc, argv); + error = dorescan_or_reset(argc, argv, 1); + break; + case CAM_ARG_RESET: + error = dorescan_or_reset(argc, argv, 0); break; case CAM_ARG_READ_DEFECTS: error = readdefects(cam_dev, argc, argv, combinedopt,