diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2013-11-06 16:20:21 +0100 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2013-11-11 10:08:08 +0100 |
commit | 66659ff1ad6831b0ea7425fa6ecd8a8687523658 (patch) | |
tree | 48e22b475fa8854128e0861a33fed6f78c8094b5 /freebsd/sys/dev/usb/storage/umass.c | |
parent | Define __GLOBL1() and __GLOBL() (diff) | |
download | rtems-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.c | 292 |
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); } |