diff options
author | ken <ken@FreeBSD.org> | 1999-10-31 02:39:44 +0000 |
---|---|---|
committer | ken <ken@FreeBSD.org> | 1999-10-31 02:39:44 +0000 |
commit | b57c214bcc798094ac9d02b7cd0fb77213049fe7 (patch) | |
tree | 70ab9efa10a5a8527db4754db00ebc8fc70ead3d /sbin | |
parent | f66b8ba3d1ba606c5dc7ad0355144655f64859ac (diff) | |
download | FreeBSD-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.c | 52 |
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); |