summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/dev/usb/storage/umass.c
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2013-11-06 16:20:21 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2013-11-11 10:08:08 +0100
commit66659ff1ad6831b0ea7425fa6ecd8a8687523658 (patch)
tree48e22b475fa8854128e0861a33fed6f78c8094b5 /freebsd/sys/dev/usb/storage/umass.c
parentDefine __GLOBL1() and __GLOBL() (diff)
downloadrtems-libbsd-66659ff1ad6831b0ea7425fa6ecd8a8687523658.tar.bz2
Update to FreeBSD 9.2
Diffstat (limited to 'freebsd/sys/dev/usb/storage/umass.c')
-rw-r--r--freebsd/sys/dev/usb/storage/umass.c292
1 files changed, 99 insertions, 193 deletions
diff --git a/freebsd/sys/dev/usb/storage/umass.c b/freebsd/sys/dev/usb/storage/umass.c
index d3d2040f..76a1fcb6 100644
--- a/freebsd/sys/dev/usb/storage/umass.c
+++ b/freebsd/sys/dev/usb/storage/umass.c
@@ -139,14 +139,6 @@ __FBSDID("$FreeBSD$");
#include <cam/cam_periph.h>
-#define UMASS_EXT_BUFFER
-#ifdef UMASS_EXT_BUFFER
-/* this enables loading of virtual buffers into DMA */
-#define UMASS_USB_FLAGS .ext_buffer=1,
-#else
-#define UMASS_USB_FLAGS
-#endif
-
#ifdef USB_DEBUG
#define DIF(m, x) \
do { \
@@ -173,19 +165,21 @@ __FBSDID("$FreeBSD$");
#define UDMASS_CBI 0x00400000 /* CBI transfers */
#define UDMASS_WIRE (UDMASS_BBB|UDMASS_CBI)
#define UDMASS_ALL 0xffff0000 /* all of the above */
-static int umass_debug = 0;
+static int umass_debug;
+static int umass_throttle;
-SYSCTL_NODE(_hw_usb, OID_AUTO, umass, CTLFLAG_RW, 0, "USB umass");
+static SYSCTL_NODE(_hw_usb, OID_AUTO, umass, CTLFLAG_RW, 0, "USB umass");
SYSCTL_INT(_hw_usb_umass, OID_AUTO, debug, CTLFLAG_RW | CTLFLAG_TUN,
&umass_debug, 0, "umass debug level");
TUNABLE_INT("hw.usb.umass.debug", &umass_debug);
+SYSCTL_INT(_hw_usb_umass, OID_AUTO, throttle, CTLFLAG_RW | CTLFLAG_TUN,
+ &umass_throttle, 0, "Forced delay between commands in milliseconds");
+TUNABLE_INT("hw.usb.umass.throttle", &umass_throttle);
#else
#define DIF(...) do { } while (0)
#define DPRINTF(...) do { } while (0)
#endif
-#define UMASS_GONE ((struct umass_softc *)1)
-
#define UMASS_BULK_SIZE (1 << 17)
#define UMASS_CBI_DIAGNOSTIC_CMDLEN 12 /* bytes */
#define UMASS_MAX_CMDLEN MAX(12, CAM_MAX_CDBLEN) /* bytes */
@@ -373,6 +367,8 @@ typedef uint8_t (umass_transform_t)(struct umass_softc *sc, uint8_t *cmd_ptr,
* result.
*/
#define NO_SYNCHRONIZE_CACHE 0x4000
+ /* Device does not support 'PREVENT/ALLOW MEDIUM REMOVAL'. */
+#define NO_PREVENT_ALLOW 0x8000
struct umass_softc {
@@ -545,7 +541,7 @@ static struct usb_config umass_bbb_config[UMASS_T_BBB_MAX] = {
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
.bufsize = UMASS_BULK_SIZE,
- .flags = {.proxy_buffer = 1,.short_xfer_ok = 1, UMASS_USB_FLAGS},
+ .flags = {.proxy_buffer = 1,.short_xfer_ok = 1,.ext_buffer=1,},
.callback = &umass_t_bbb_data_read_callback,
.timeout = 0, /* overwritten later */
},
@@ -564,7 +560,7 @@ static struct usb_config umass_bbb_config[UMASS_T_BBB_MAX] = {
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
.bufsize = UMASS_BULK_SIZE,
- .flags = {.proxy_buffer = 1,.short_xfer_ok = 1, UMASS_USB_FLAGS},
+ .flags = {.proxy_buffer = 1,.short_xfer_ok = 1,.ext_buffer=1,},
.callback = &umass_t_bbb_data_write_callback,
.timeout = 0, /* overwritten later */
},
@@ -637,7 +633,7 @@ static struct usb_config umass_cbi_config[UMASS_T_CBI_MAX] = {
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
.bufsize = UMASS_BULK_SIZE,
- .flags = {.proxy_buffer = 1,.short_xfer_ok = 1, UMASS_USB_FLAGS},
+ .flags = {.proxy_buffer = 1,.short_xfer_ok = 1,.ext_buffer=1,},
.callback = &umass_t_cbi_data_read_callback,
.timeout = 0, /* overwritten later */
},
@@ -656,7 +652,7 @@ static struct usb_config umass_cbi_config[UMASS_T_CBI_MAX] = {
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
.bufsize = UMASS_BULK_SIZE,
- .flags = {.proxy_buffer = 1,.short_xfer_ok = 1, UMASS_USB_FLAGS},
+ .flags = {.proxy_buffer = 1,.short_xfer_ok = 1,.ext_buffer=1,},
.callback = &umass_t_cbi_data_write_callback,
.timeout = 0, /* overwritten later */
},
@@ -845,6 +841,8 @@ umass_probe_proto(device_t dev, struct usb_attach_arg *uaa)
quirks |= NO_INQUIRY;
if (usb_test_quirk(uaa, UQ_MSC_NO_INQUIRY_EVPD))
quirks |= NO_INQUIRY_EVPD;
+ if (usb_test_quirk(uaa, UQ_MSC_NO_PREVENT_ALLOW))
+ quirks |= NO_PREVENT_ALLOW;
if (usb_test_quirk(uaa, UQ_MSC_NO_SYNC_CACHE))
quirks |= NO_SYNCHRONIZE_CACHE;
if (usb_test_quirk(uaa, UQ_MSC_SHUTTLE_INIT))
@@ -891,7 +889,7 @@ umass_attach(device_t dev)
struct usb_attach_arg *uaa = device_get_ivars(dev);
struct umass_probe_proto temp = umass_probe_proto(dev, uaa);
struct usb_interface_descriptor *id;
- int32_t err;
+ int err;
/*
* NOTE: the softc struct is cleared in device_set_driver.
@@ -1004,6 +1002,24 @@ umass_attach(device_t dev)
"transfers, %s\n", usbd_errstr(err));
goto detach;
}
+#ifdef USB_DEBUG
+ if (umass_throttle > 0) {
+ uint8_t x;
+ int iv;
+
+ iv = umass_throttle;
+
+ if (iv < 1)
+ iv = 1;
+ else if (iv > 8000)
+ iv = 8000;
+
+ for (x = 0; x != UMASS_T_MAX; x++) {
+ if (sc->sc_xfer[x] != NULL)
+ usbd_xfer_set_interval(sc->sc_xfer[x], iv);
+ }
+ }
+#endif
sc->sc_transform =
(sc->sc_proto & UMASS_PROTO_SCSI) ? &umass_scsi_transform :
(sc->sc_proto & UMASS_PROTO_UFI) ? &umass_ufi_transform :
@@ -1058,14 +1074,16 @@ umass_detach(device_t dev)
usbd_transfer_unsetup(sc->sc_xfer, UMASS_T_MAX);
-#if (__FreeBSD_version >= 700037)
mtx_lock(&sc->sc_mtx);
-#endif
+
+ /* cancel any leftover CCB's */
+
+ umass_cancel_ccb(sc);
+
umass_cam_detach_sim(sc);
-#if (__FreeBSD_version >= 700037)
mtx_unlock(&sc->sc_mtx);
-#endif
+
mtx_destroy(&sc->sc_mtx);
return (0); /* success */
@@ -1206,7 +1224,6 @@ umass_t_bbb_reset1_callback(struct usb_xfer *xfer, usb_error_t error)
default: /* Error */
umass_tr_error(xfer, error);
return;
-
}
}
@@ -1245,7 +1262,6 @@ tr_transferred:
default: /* Error */
umass_tr_error(xfer, error);
return;
-
}
}
@@ -1331,7 +1347,6 @@ umass_t_bbb_command_callback(struct usb_xfer *xfer, usb_error_t error)
default: /* Error */
umass_tr_error(xfer, error);
return;
-
}
}
@@ -1340,19 +1355,12 @@ umass_t_bbb_data_read_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct umass_softc *sc = usbd_xfer_softc(xfer);
uint32_t max_bulk = usbd_xfer_max_len(xfer);
-#ifndef UMASS_EXT_BUFFER
- struct usb_page_cache *pc;
-#endif
int actlen, sumlen;
usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL);
switch (USB_GET_STATE(xfer)) {
case USB_ST_TRANSFERRED:
-#ifndef UMASS_EXT_BUFFER
- pc = usbd_xfer_get_frame(xfer, 0);
- usbd_copy_out(pc, 0, sc->sc_transfer.data_ptr, actlen);
-#endif
sc->sc_transfer.data_rem -= actlen;
sc->sc_transfer.data_ptr += actlen;
sc->sc_transfer.actlen += actlen;
@@ -1374,12 +1382,9 @@ umass_t_bbb_data_read_callback(struct usb_xfer *xfer, usb_error_t error)
}
usbd_xfer_set_timeout(xfer, sc->sc_transfer.data_timeout);
-#ifdef UMASS_EXT_BUFFER
usbd_xfer_set_frame_data(xfer, 0, sc->sc_transfer.data_ptr,
max_bulk);
-#else
- usbd_xfer_set_frame_len(xfer, 0, max_bulk);
-#endif
+
usbd_transfer_submit(xfer);
return;
@@ -1390,7 +1395,6 @@ umass_t_bbb_data_read_callback(struct usb_xfer *xfer, usb_error_t error)
umass_transfer_start(sc, UMASS_T_BBB_DATA_RD_CS);
}
return;
-
}
}
@@ -1406,9 +1410,6 @@ umass_t_bbb_data_write_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct umass_softc *sc = usbd_xfer_softc(xfer);
uint32_t max_bulk = usbd_xfer_max_len(xfer);
-#ifndef UMASS_EXT_BUFFER
- struct usb_page_cache *pc;
-#endif
int actlen, sumlen;
usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL);
@@ -1436,14 +1437,8 @@ umass_t_bbb_data_write_callback(struct usb_xfer *xfer, usb_error_t error)
}
usbd_xfer_set_timeout(xfer, sc->sc_transfer.data_timeout);
-#ifdef UMASS_EXT_BUFFER
usbd_xfer_set_frame_data(xfer, 0, sc->sc_transfer.data_ptr,
max_bulk);
-#else
- pc = usbd_xfer_get_frame(xfer, 0);
- usbd_copy_in(pc, 0, sc->sc_transfer.data_ptr, max_bulk);
- usbd_xfer_set_frame_len(xfer, 0, max_bulk);
-#endif
usbd_transfer_submit(xfer);
return;
@@ -1455,7 +1450,6 @@ umass_t_bbb_data_write_callback(struct usb_xfer *xfer, usb_error_t error)
umass_transfer_start(sc, UMASS_T_BBB_DATA_WR_CS);
}
return;
-
}
}
@@ -1581,7 +1575,6 @@ tr_error:
umass_transfer_start(sc, UMASS_T_BBB_DATA_RD_CS);
}
return;
-
}
}
@@ -1612,8 +1605,7 @@ umass_command_start(struct umass_softc *sc, uint8_t dir,
if (sc->sc_xfer[sc->sc_last_xfer_index]) {
usbd_transfer_start(sc->sc_xfer[sc->sc_last_xfer_index]);
} else {
- ccb->ccb_h.status = CAM_TID_INVALID;
- xpt_done(ccb);
+ umass_cancel_ccb(sc);
}
}
@@ -1733,7 +1725,6 @@ umass_t_cbi_reset1_callback(struct usb_xfer *xfer, usb_error_t error)
else
umass_transfer_start(sc, UMASS_T_CBI_RESET2);
break;
-
}
}
@@ -1788,7 +1779,6 @@ tr_transferred:
default: /* Error */
umass_tr_error(xfer, error);
break;
-
}
}
@@ -1878,19 +1868,12 @@ umass_t_cbi_data_read_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct umass_softc *sc = usbd_xfer_softc(xfer);
uint32_t max_bulk = usbd_xfer_max_len(xfer);
-#ifndef UMASS_EXT_BUFFER
- struct usb_page_cache *pc;
-#endif
int actlen, sumlen;
usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL);
switch (USB_GET_STATE(xfer)) {
case USB_ST_TRANSFERRED:
-#ifndef UMASS_EXT_BUFFER
- pc = usbd_xfer_get_frame(xfer, 0);
- usbd_copy_out(pc, 0, sc->sc_transfer.data_ptr, actlen);
-#endif
sc->sc_transfer.data_rem -= actlen;
sc->sc_transfer.data_ptr += actlen;
sc->sc_transfer.actlen += actlen;
@@ -1912,12 +1895,9 @@ umass_t_cbi_data_read_callback(struct usb_xfer *xfer, usb_error_t error)
}
usbd_xfer_set_timeout(xfer, sc->sc_transfer.data_timeout);
-#ifdef UMASS_EXT_BUFFER
usbd_xfer_set_frame_data(xfer, 0, sc->sc_transfer.data_ptr,
max_bulk);
-#else
- usbd_xfer_set_frame_len(xfer, 0, max_bulk);
-#endif
+
usbd_transfer_submit(xfer);
break;
@@ -1929,7 +1909,6 @@ umass_t_cbi_data_read_callback(struct usb_xfer *xfer, usb_error_t error)
umass_transfer_start(sc, UMASS_T_CBI_DATA_RD_CS);
}
break;
-
}
}
@@ -1945,9 +1924,6 @@ umass_t_cbi_data_write_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct umass_softc *sc = usbd_xfer_softc(xfer);
uint32_t max_bulk = usbd_xfer_max_len(xfer);
-#ifndef UMASS_EXT_BUFFER
- struct usb_page_cache *pc;
-#endif
int actlen, sumlen;
usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL);
@@ -1975,14 +1951,8 @@ umass_t_cbi_data_write_callback(struct usb_xfer *xfer, usb_error_t error)
}
usbd_xfer_set_timeout(xfer, sc->sc_transfer.data_timeout);
-#ifdef UMASS_EXT_BUFFER
usbd_xfer_set_frame_data(xfer, 0, sc->sc_transfer.data_ptr,
max_bulk);
-#else
- pc = usbd_xfer_get_frame(xfer, 0);
- usbd_copy_in(pc, 0, sc->sc_transfer.data_ptr, max_bulk);
- usbd_xfer_set_frame_len(xfer, 0, max_bulk);
-#endif
usbd_transfer_submit(xfer);
break;
@@ -1995,7 +1965,6 @@ umass_t_cbi_data_write_callback(struct usb_xfer *xfer, usb_error_t error)
umass_transfer_start(sc, UMASS_T_CBI_DATA_WR_CS);
}
break;
-
}
}
@@ -2097,7 +2066,6 @@ tr_setup:
usbd_errstr(error));
umass_tr_error(xfer, error);
break;
-
}
}
@@ -2126,9 +2094,7 @@ umass_cam_attach_sim(struct umass_softc *sc)
DEVNAME_SIM,
sc /* priv */ ,
sc->sc_unit /* unit number */ ,
-#if (__FreeBSD_version >= 700037)
&sc->sc_mtx /* mutex */ ,
-#endif
1 /* maximum device openings */ ,
0 /* maximum tagged device openings */ ,
devq);
@@ -2138,27 +2104,15 @@ umass_cam_attach_sim(struct umass_softc *sc)
return (ENOMEM);
}
-#if (__FreeBSD_version >= 700037)
mtx_lock(&sc->sc_mtx);
-#endif
-#if (__FreeBSD_version >= 700048)
- if (xpt_bus_register(sc->sc_sim, sc->sc_dev, sc->sc_unit) != CAM_SUCCESS) {
+ if (xpt_bus_register(sc->sc_sim, sc->sc_dev,
+ sc->sc_unit) != CAM_SUCCESS) {
mtx_unlock(&sc->sc_mtx);
return (ENOMEM);
}
-#else
- if (xpt_bus_register(sc->sc_sim, sc->sc_unit) != CAM_SUCCESS) {
-#if (__FreeBSD_version >= 700037)
- mtx_unlock(&sc->sc_mtx);
-#endif
- return (ENOMEM);
- }
-#endif
-
-#if (__FreeBSD_version >= 700037)
mtx_unlock(&sc->sc_mtx);
-#endif
+
return (0);
}
@@ -2186,7 +2140,7 @@ umass_cam_detach_sim(struct umass_softc *sc)
if (sc->sc_sim != NULL) {
if (xpt_bus_deregister(cam_sim_path(sc->sc_sim))) {
/* accessing the softc is not possible after this */
- sc->sc_sim->softc = UMASS_GONE;
+ sc->sc_sim->softc = NULL;
cam_sim_free(sc->sc_sim, /* free_devq */ TRUE);
} else {
panic("%s: CAM layer is busy\n",
@@ -2205,68 +2159,11 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb)
{
struct umass_softc *sc = (struct umass_softc *)sim->softc;
- if (sc == UMASS_GONE ||
- (sc != NULL && !usbd_device_attached(sc->sc_udev))) {
+ if (sc == NULL) {
ccb->ccb_h.status = CAM_SEL_TIMEOUT;
xpt_done(ccb);
return;
}
- if (sc) {
-#if (__FreeBSD_version < 700037)
- mtx_lock(&sc->sc_mtx);
-#endif
- }
- /*
- * Verify, depending on the operation to perform, that we either got
- * a valid sc, because an existing target was referenced, or
- * otherwise the SIM is addressed.
- *
- * This avoids bombing out at a printf and does give the CAM layer some
- * sensible feedback on errors.
- */
- switch (ccb->ccb_h.func_code) {
- case XPT_SCSI_IO:
- case XPT_RESET_DEV:
- case XPT_GET_TRAN_SETTINGS:
- case XPT_SET_TRAN_SETTINGS:
- case XPT_CALC_GEOMETRY:
- /* the opcodes requiring a target. These should never occur. */
- if (sc == NULL) {
- DPRINTF(sc, UDMASS_GEN, "%s:%d:%d:%d:func_code 0x%04x: "
- "Invalid target (target needed)\n",
- DEVNAME_SIM, cam_sim_path(sc->sc_sim),
- ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
- ccb->ccb_h.func_code);
-
- ccb->ccb_h.status = CAM_TID_INVALID;
- xpt_done(ccb);
- goto done;
- }
- break;
- case XPT_PATH_INQ:
- case XPT_NOOP:
- /*
- * The opcodes sometimes aimed at a target (sc is valid),
- * sometimes aimed at the SIM (sc is invalid and target is
- * CAM_TARGET_WILDCARD)
- */
- if ((sc == NULL) &&
- (ccb->ccb_h.target_id != CAM_TARGET_WILDCARD)) {
- DPRINTF(sc, UDMASS_SCSI, "%s:%d:%d:%d:func_code 0x%04x: "
- "Invalid target (no wildcard)\n",
- DEVNAME_SIM, cam_sim_path(sc->sc_sim),
- ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
- ccb->ccb_h.func_code);
-
- ccb->ccb_h.status = CAM_TID_INVALID;
- xpt_done(ccb);
- goto done;
- }
- break;
- default:
- /* XXX Hm, we should check the input parameters */
- break;
- }
/* Perform the requested action */
switch (ccb->ccb_h.func_code) {
@@ -2353,17 +2250,20 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb)
*/
if ((sc->sc_quirks & (NO_INQUIRY_EVPD | NO_INQUIRY)) &&
(sc->sc_transfer.cmd_data[1] & SI_EVPD)) {
- struct scsi_sense_data *sense;
-
- sense = &ccb->csio.sense_data;
- bzero(sense, sizeof(*sense));
- sense->error_code = SSD_CURRENT_ERROR;
- sense->flags = SSD_KEY_ILLEGAL_REQUEST;
- sense->add_sense_code = 0x24;
- sense->extra_len = 10;
+
+ scsi_set_sense_data(&ccb->csio.sense_data,
+ /*sense_format*/ SSD_TYPE_NONE,
+ /*current_error*/ 1,
+ /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST,
+ /*asc*/ 0x24,
+ /*ascq*/ 0x00,
+ /*extra args*/ SSD_ELEM_NONE);
ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
- ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR |
- CAM_AUTOSNS_VALID;
+ ccb->ccb_h.status =
+ CAM_SCSI_STATUS_ERROR |
+ CAM_AUTOSNS_VALID |
+ CAM_DEV_QFRZN;
+ xpt_freeze_devq(ccb->ccb_h.path, 1);
xpt_done(ccb);
goto done;
}
@@ -2382,6 +2282,13 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb)
if (sc->sc_quirks & FORCE_SHORT_INQUIRY) {
ccb->csio.dxfer_len = SHORT_INQUIRY_LENGTH;
}
+ } else if (sc->sc_transfer.cmd_data[0] == PREVENT_ALLOW) {
+ if (sc->sc_quirks & NO_PREVENT_ALLOW) {
+ ccb->csio.scsi_status = SCSI_STATUS_OK;
+ ccb->ccb_h.status = CAM_REQ_CMP;
+ xpt_done(ccb);
+ goto done;
+ }
} else if (sc->sc_transfer.cmd_data[0] == SYNCHRONIZE_CACHE) {
if (sc->sc_quirks & NO_SYNCHRONIZE_CACHE) {
ccb->csio.scsi_status = SCSI_STATUS_OK;
@@ -2418,12 +2325,11 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb)
strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
cpi->unit_number = cam_sim_unit(sim);
cpi->bus_id = sc->sc_unit;
-#if (__FreeBSD_version >= 700025)
cpi->protocol = PROTO_SCSI;
cpi->protocol_version = SCSI_REV_2;
cpi->transport = XPORT_USB;
cpi->transport_version = 0;
-#endif
+
if (sc == NULL) {
cpi->base_transfer_speed = 0;
cpi->max_lun = 0;
@@ -2475,16 +2381,12 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb)
cam_sim_path(sc->sc_sim), ccb->ccb_h.target_id,
ccb->ccb_h.target_lun);
-#if (__FreeBSD_version >= 700025)
cts->protocol = PROTO_SCSI;
cts->protocol_version = SCSI_REV_2;
cts->transport = XPORT_USB;
cts->transport_version = 0;
cts->xport_specific.valid = 0;
-#else
- cts->valid = 0;
- cts->flags = 0; /* no disconnection, tagging */
-#endif
+
ccb->ccb_h.status = CAM_REQ_CMP;
xpt_done(ccb);
break;
@@ -2529,11 +2431,6 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb)
}
done:
-#if (__FreeBSD_version < 700037)
- if (sc) {
- mtx_unlock(&sc->sc_mtx);
- }
-#endif
return;
}
@@ -2542,7 +2439,7 @@ umass_cam_poll(struct cam_sim *sim)
{
struct umass_softc *sc = (struct umass_softc *)sim->softc;
- if (sc == UMASS_GONE)
+ if (sc == NULL)
return;
DPRINTF(sc, UDMASS_SCSI, "CAM poll\n");
@@ -2628,7 +2525,8 @@ umass_cam_cb(struct umass_softc *sc, union ccb *ccb, uint32_t residue,
* recovered. We return an error to CAM and let CAM
* retry the command if necessary.
*/
- ccb->ccb_h.status = CAM_REQ_CMP_ERR;
+ xpt_freeze_devq(ccb->ccb_h.path, 1);
+ ccb->ccb_h.status = CAM_REQ_CMP_ERR | CAM_DEV_QFRZN;
xpt_done(ccb);
break;
}
@@ -2642,12 +2540,17 @@ umass_cam_sense_cb(struct umass_softc *sc, union ccb *ccb, uint32_t residue,
uint8_t status)
{
uint8_t *cmd;
- uint8_t key;
switch (status) {
case STATUS_CMD_OK:
case STATUS_CMD_UNKNOWN:
- case STATUS_CMD_FAILED:
+ case STATUS_CMD_FAILED: {
+ int key, sense_len;
+
+ ccb->csio.sense_resid = residue;
+ sense_len = ccb->csio.sense_len - ccb->csio.sense_resid;
+ key = scsi_get_sense_key(&ccb->csio.sense_data, sense_len,
+ /*show_errors*/ 1);
if (ccb->csio.ccb_h.flags & CAM_CDB_POINTER) {
cmd = (uint8_t *)(ccb->csio.cdb_io.cdb_ptr);
@@ -2655,8 +2558,6 @@ umass_cam_sense_cb(struct umass_softc *sc, union ccb *ccb, uint32_t residue,
cmd = (uint8_t *)(ccb->csio.cdb_io.cdb_bytes);
}
- key = (ccb->csio.sense_data.flags & SSD_KEY);
-
/*
* Getting sense data always succeeds (apart from wire
* failures):
@@ -2688,8 +2589,9 @@ umass_cam_sense_cb(struct umass_softc *sc, union ccb *ccb, uint32_t residue,
* usual.
*/
+ xpt_freeze_devq(ccb->ccb_h.path, 1);
ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR
- | CAM_AUTOSNS_VALID;
+ | CAM_AUTOSNS_VALID | CAM_DEV_QFRZN;
ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
#if 0
@@ -2700,34 +2602,40 @@ umass_cam_sense_cb(struct umass_softc *sc, union ccb *ccb, uint32_t residue,
/* the rest of the command was filled in at attach */
- if (umass_std_transform(sc, ccb,
+ if ((sc->sc_transform)(sc,
&sc->cam_scsi_test_unit_ready.opcode,
- sizeof(sc->cam_scsi_test_unit_ready))) {
+ sizeof(sc->cam_scsi_test_unit_ready)) == 1) {
umass_command_start(sc, DIR_NONE, NULL, 0,
ccb->ccb_h.timeout,
&umass_cam_quirk_cb, ccb);
+ break;
}
- break;
} else {
- ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR
- | CAM_AUTOSNS_VALID;
- ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
+ xpt_freeze_devq(ccb->ccb_h.path, 1);
+ if (key >= 0) {
+ ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR
+ | CAM_AUTOSNS_VALID | CAM_DEV_QFRZN;
+ ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
+ } else
+ ccb->ccb_h.status = CAM_AUTOSENSE_FAIL
+ | CAM_DEV_QFRZN;
}
xpt_done(ccb);
break;
-
+ }
default:
DPRINTF(sc, UDMASS_SCSI, "Autosense failed, "
"status %d\n", status);
- ccb->ccb_h.status = CAM_AUTOSENSE_FAIL;
+ xpt_freeze_devq(ccb->ccb_h.path, 1);
+ ccb->ccb_h.status = CAM_AUTOSENSE_FAIL | CAM_DEV_QFRZN;
xpt_done(ccb);
}
}
/*
* This completion code just handles the fact that we sent a test-unit-ready
- * after having previously failed a READ CAPACITY with CHECK_COND. Even
- * though this command succeeded, we have to tell CAM to retry.
+ * after having previously failed a READ CAPACITY with CHECK_COND. The CCB
+ * status for CAM is already set earlier.
*/
static void
umass_cam_quirk_cb(struct umass_softc *sc, union ccb *ccb, uint32_t residue,
@@ -2736,9 +2644,6 @@ umass_cam_quirk_cb(struct umass_softc *sc, union ccb *ccb, uint32_t residue,
DPRINTF(sc, UDMASS_SCSI, "Test unit ready "
"returned status %d\n", status);
- ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR
- | CAM_AUTOSNS_VALID;
- ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
xpt_done(ccb);
}
@@ -3027,7 +2932,8 @@ umass_std_transform(struct umass_softc *sc, union ccb *ccb,
xpt_done(ccb);
return (0);
} else if (retval == 0) {
- ccb->ccb_h.status = CAM_REQ_INVALID;
+ xpt_freeze_devq(ccb->ccb_h.path, 1);
+ ccb->ccb_h.status = CAM_REQ_INVALID | CAM_DEV_QFRZN;
xpt_done(ccb);
return (0);
}