summaryrefslogtreecommitdiffstats
path: root/sbin
diff options
context:
space:
mode:
authorken <ken@FreeBSD.org>1999-10-31 02:39:44 +0000
committerken <ken@FreeBSD.org>1999-10-31 02:39:44 +0000
commitb57c214bcc798094ac9d02b7cd0fb77213049fe7 (patch)
tree70ab9efa10a5a8527db4754db00ebc8fc70ead3d /sbin
parentf66b8ba3d1ba606c5dc7ad0355144655f64859ac (diff)
downloadFreeBSD-src-b57c214bcc798094ac9d02b7cd0fb77213049fe7.zip
FreeBSD-src-b57c214bcc798094ac9d02b7cd0fb77213049fe7.tar.gz
Fix Bus Device Resets from userland, and specifically from camcontrol.
camcontrol was setup to use the old scheme of going through the xpt(4) device, which never worked properly (and has been disabled for a while). camcontrol now sends BDRs through the pass(4) device, and XPT_RESET_DEV CCBs are put on the device queue in the transport layer, as they should be. Submitted by: luoqi Reviewed by: ken
Diffstat (limited to 'sbin')
-rw-r--r--sbin/camcontrol/camcontrol.c52
1 files changed, 41 insertions, 11 deletions
diff --git a/sbin/camcontrol/camcontrol.c b/sbin/camcontrol/camcontrol.c
index f2ac816..c5b2c93 100644
--- a/sbin/camcontrol/camcontrol.c
+++ b/sbin/camcontrol/camcontrol.c
@@ -1029,6 +1029,7 @@ static int
scanlun_or_reset_dev(int bus, int target, int lun, int scan)
{
union ccb ccb;
+ struct cam_device *device;
int fd;
if (bus < 0) {
@@ -1046,31 +1047,60 @@ scanlun_or_reset_dev(int bus, int target, int lun, int scan)
return(1);
}
- if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
- warnx("error opening tranport layer device %s\n",
- XPT_DEVICE);
- warn("%s", XPT_DEVICE);
- return(1);
+ fd = -1;
+
+ bzero(&ccb, sizeof(union ccb));
+
+ if (scan) {
+ if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
+ warnx("error opening tranport layer device %s\n",
+ XPT_DEVICE);
+ warn("%s", XPT_DEVICE);
+ return(1);
+ }
+ } else {
+ device = cam_open_btl(bus, target, lun, O_RDWR, NULL);
+ if (device == NULL) {
+ warnx("%s", cam_errbuf);
+ return(1);
+ }
}
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;
+ ccb.ccb_h.timeout = 5000;
ccb.crcn.flags = CAM_FLAG_NONE;
/* run this at a low priority */
ccb.ccb_h.pinfo.priority = 5;
- if (ioctl(fd, CAMIOCOMMAND, &ccb) < 0) {
- warn("CAMIOCOMMAND ioctl failed");
- close(fd);
- return(1);
+ if (scan) {
+ if (ioctl(fd, CAMIOCOMMAND, &ccb) < 0) {
+ warn("CAMIOCOMMAND ioctl failed");
+ close(fd);
+ return(1);
+ }
+ } else {
+ if (cam_send_ccb(device, &ccb) < 0) {
+ warn("error sending XPT_RESET_DEV CCB");
+ cam_close_device(device);
+ return(1);
+ }
}
- close(fd);
+ if (scan)
+ close(fd);
+ else
+ cam_close_device(device);
- if ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
+ /*
+ * An error code of CAM_BDR_SENT is normal for a BDR request.
+ */
+ if (((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
+ || ((!scan)
+ && ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_BDR_SENT))) {
fprintf(stdout, "%s of %d:%d:%d was successful\n",
scan? "Re-scan" : "Reset", bus, target, lun);
return(0);
OpenPOWER on IntegriCloud