summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/dev/usb/umass.c362
1 files changed, 231 insertions, 131 deletions
diff --git a/sys/dev/usb/umass.c b/sys/dev/usb/umass.c
index f598544..92b6103 100644
--- a/sys/dev/usb/umass.c
+++ b/sys/dev/usb/umass.c
@@ -45,7 +45,7 @@
* - UFI (floppy command set)
* - 8070i (ATA/ATAPI)
*
- * UFI and 8070i are transformed versions of the SCSI command set. The
+ * UFI and 8070i (ATAPI) are transformed versions of the SCSI command set. The
* sc->transform method is used to convert the commands into the appropriate
* format (if at all necessary). For example, UFI requires all commands to be
* 12 bytes in length amongst other things.
@@ -61,7 +61,7 @@
* - CAM (Common Access Method)
* - SCSI
* - UFI
- * - 8070i
+ * - 8070i (ATAPI)
*
* The protocols are implemented using a state machine, for the transfers as
* well as for the resets. The state machine is contained in umass_*_state.
@@ -85,10 +85,17 @@
*/
/* XXX Should we split the driver into a number of files? umass.c,
- * umass_scsi.c, umass_8070.c, umass_ufi.c, umass_bbb.c, umass_cbi.c or
+ * umass_scsi.c, umass_atapi.c, umass_ufi.c, umass_bbb.c, umass_cbi.c or
* something similar?
*/
+/*
+ * XXX Currently CBI with CCI is not supported because it bombs the system
+ * when the device is detached (low frequency interrupts are detached
+ * too late.
+ */
+#undef CBI_I
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
@@ -109,10 +116,8 @@
#include <cam/scsi/scsi_all.h>
#include <cam/scsi/scsi_da.h>
-#ifdef UMASS_DO_CAM_RESCAN
#include <sys/devicestat.h>
#include <cam/cam_periph.h>
-#endif
#ifdef UMASS_DEBUG
#define DIF(m, x) if (umassdebug & (m)) do { x ; } while (0)
@@ -120,7 +125,7 @@
#define UDMASS_GEN 0x00010000 /* general */
#define UDMASS_SCSI 0x00020000 /* scsi */
#define UDMASS_UFI 0x00040000 /* ufi command set */
-#define UDMASS_8070 0x00080000 /* 8070i command set */
+#define UDMASS_ATAPI 0x00080000 /* 8070i command set */
#define UDMASS_USB 0x00100000 /* USB general */
#define UDMASS_BBB 0x00200000 /* Bulk-Only transfers */
#define UDMASS_CBI 0x00400000 /* CBI transfers */
@@ -141,7 +146,7 @@ int umassdebug = UDMASS_ALL;
/* device name */
#define DEVNAME "umass"
-#define DEVNAME_SIM "umass-"
+#define DEVNAME_SIM "umass-sim"
#define UMASS_MAX_TRANSFER_SIZE 65536
#define UMASS_DEFAULT_TRANSFER_SPEED 150 /* in kb/s, conservative est. */
@@ -152,7 +157,7 @@ int umassdebug = UDMASS_ALL;
/* CAM specific definitions */
-/* The bus id, whatever that is */
+/* We only have one bus */
#define UMASS_SCSI_BUS 0
/* All USB drives are 'connected' to one SIM (SCSI controller). umass3
@@ -287,7 +292,7 @@ struct umass_softc {
# define PROTO_CBI_I 0x0004
# define PROTO_WIRE 0x00ff /* USB wire protocol mask */
# define PROTO_SCSI 0x0100 /* command protocol */
-# define PROTO_8070 0x0200
+# define PROTO_ATAPI 0x0200
# define PROTO_UFI 0x0400
# define PROTO_COMMAND 0xff00 /* command protocol mask */
@@ -389,6 +394,7 @@ struct umass_softc {
/* SCSI/CAM specific variables */
+ unsigned char cam_scsi_command[CAM_MAX_CDBLEN];
struct scsi_sense cam_scsi_sense;
int transfer_speed; /* in kb/s */
@@ -420,7 +426,6 @@ char *states[TSTATE_STATES+1] = {
#endif
struct cam_sim *umass_sim; /* SCSI Interface Module */
-struct cam_path *umass_path; /* and its path */
/* USB device probe/attach/detach functions */
@@ -474,9 +479,9 @@ static void umass_cam_cb __P((struct umass_softc *sc, void *priv,
static void umass_cam_sense_cb __P((struct umass_softc *sc, void *priv,
int residue, int status));
-#ifdef UMASS_DO_CAM_RESCAN
+static void umass_cam_rescan_callback
+ __P((struct cam_periph *periph,union ccb *ccb));
static void umass_cam_rescan __P((struct umass_softc *sc));
-#endif
static int umass_cam_attach_sim __P((void));
static int umass_cam_attach __P((struct umass_softc *sc));
@@ -490,12 +495,14 @@ static int umass_scsi_transform __P((struct umass_softc *sc,
unsigned char **rcmd, int *rcmdlen));
/* UFI specific functions */
+#define UFI_COMMAND_LENGTH 12 /* UFI commands are always 12b */
static int umass_ufi_transform __P((struct umass_softc *sc,
unsigned char *cmd, int cmdlen,
unsigned char **rcmd, int *rcmdlen));
-/* 8070 specific functions */
-static int umass_8070_transform __P((struct umass_softc *sc,
+/* ATAPI (8070i) specific functions */
+#define ATAPI_COMMAND_LENGTH 12 /* ATAPI commands are always 12b */
+static int umass_atapi_transform __P((struct umass_softc *sc,
unsigned char *cmd, int cmdlen,
unsigned char **rcmd, int *rcmdlen));
@@ -544,9 +551,9 @@ umass_match_proto(struct umass_softc *sc, usbd_interface_handle iface)
&& UGETW(dd->idProduct) == USB_PRODUCT_SHUTTLE_EUSB) {
sc->drive = SHUTTLE_EUSB;
#if CBI_I
- sc->proto = PROTO_8070 | PROTO_CBI_I;
+ sc->proto = PROTO_ATAPI | PROTO_CBI_I;
#else
- sc->proto = PROTO_8070 | PROTO_CBI;
+ sc->proto = PROTO_ATAPI | PROTO_CBI;
#endif
return UMATCH_VENDOR_PRODUCT;
}
@@ -593,7 +600,7 @@ umass_match_proto(struct umass_softc *sc, usbd_interface_handle iface)
sc->proto |= PROTO_UFI;
break;
case USUBCLASS_SFF8070I:
- sc->proto |= PROTO_8070;
+ sc->proto |= PROTO_ATAPI;
break;
default:
DPRINTF(UDMASS_GEN, ("%s: Unsupported command protocol %d\n",
@@ -671,8 +678,8 @@ USB_ATTACH(umass)
case PROTO_SCSI:
printf("SCSI");
break;
- case PROTO_8070:
- printf("8070i");
+ case PROTO_ATAPI:
+ printf("8070i (ATAPI)");
break;
case PROTO_UFI:
printf("UFI");
@@ -819,8 +826,8 @@ USB_ATTACH(umass)
sc->transform = umass_scsi_transform;
else if (sc->proto & PROTO_UFI)
sc->transform = umass_ufi_transform;
- else if (sc->proto & PROTO_8070)
- sc->transform = umass_8070_transform;
+ else if (sc->proto & PROTO_ATAPI)
+ sc->transform = umass_atapi_transform;
#ifdef UMASS_DEBUG
else
panic("No transformation defined for command proto 0x%02x\n",
@@ -830,7 +837,7 @@ USB_ATTACH(umass)
/* From here onwards the device can be used. */
if ((sc->proto & PROTO_SCSI) ||
- (sc->proto & PROTO_8070) ||
+ (sc->proto & PROTO_ATAPI) ||
(sc->proto & PROTO_UFI)) {
/* Prepare the SCSI command block */
sc->cam_scsi_sense.opcode = REQUEST_SENSE;
@@ -855,6 +862,7 @@ USB_ATTACH(umass)
__FILE__, __LINE__, sc->proto);
}
+
DPRINTF(UDMASS_GEN, ("%s: Attach finished\n", USBDEVNAME(sc->sc_dev)));
USB_ATTACH_SUCCESS_RETURN;
@@ -871,7 +879,7 @@ USB_DETACH(umass)
sc->flags |= UMASS_FLAGS_GONE;
if ((sc->proto & PROTO_SCSI) ||
- (sc->proto & PROTO_8070) ||
+ (sc->proto & PROTO_ATAPI) ||
(sc->proto & PROTO_UFI))
/* detach the device from the SCSI host controller (SIM) */
err = umass_cam_detach(sc);
@@ -1815,7 +1823,7 @@ umass_cbi_state(usbd_xfer_handle xfer, usbd_private_handle priv,
/*
- * CAM specific functions (used by SCSI, UFI, 8070)
+ * CAM specific functions (used by SCSI, UFI, 8070 (ATAPI))
*/
static int
@@ -1826,17 +1834,15 @@ umass_cam_attach_sim()
/* A HBA is attached to the CAM layer.
*
* The CAM layer will then after a while start probing for
- * devices on the bus. The number of devices is limitted to one.
+ * devices on the bus. The number of SIMs is limitted to one.
*/
- /* SCSI transparent command set */
-
devq = cam_simq_alloc(1 /*maximum openings*/);
if (devq == NULL)
return(ENOMEM);
- umass_sim = cam_sim_alloc(umass_cam_action, umass_cam_poll, DEVNAME,
- NULL /*priv*/, 0 /*unit number*/,
+ umass_sim = cam_sim_alloc(umass_cam_action, umass_cam_poll, DEVNAME_SIM,
+ NULL /*priv*/, UMASS_SCSIID_HOST/*unit number*/,
1 /*maximum device openings*/,
0 /*maximum tagged device openings*/,
devq);
@@ -1845,39 +1851,23 @@ umass_cam_attach_sim()
return(ENOMEM);
}
- if(xpt_bus_register(umass_sim, 0) != CAM_SUCCESS)
- return(ENOMEM);
-
- if (xpt_create_path(&umass_path, NULL, cam_sim_path(umass_sim),
- UMASS_SCSIID_HOST, 0)
- != CAM_REQ_CMP)
+ if(xpt_bus_register(umass_sim, UMASS_SCSI_BUS) != CAM_SUCCESS)
return(ENOMEM);
return(0);
}
-#ifdef UMASS_DO_CAM_RESCAN
-/* this function is only used from umass_cam_rescan, so mention
- * prototype down here.
- */
-static void umass_cam_rescan_callback(struct cam_periph *periph,union ccb *ccb);
-
static void
umass_cam_rescan_callback(struct cam_periph *periph, union ccb *ccb)
{
#ifdef UMASS_DEBUG
- struct umass_softc *sc = devclass_get_softc(umass_devclass,
- ccb->ccb_h.target_id);
-
if (ccb->ccb_h.status != CAM_REQ_CMP) {
- DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d: Rescan failed, 0x%04x\n",
- USBDEVNAME(sc->sc_dev), UMASS_SCSI_BUS,
- ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
+ DPRINTF(UDMASS_SCSI, ("scbus%d: Rescan failed, 0x%04x\n",
+ cam_sim_path(umass_sim),
ccb->ccb_h.status));
} else {
- DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d: Rescan succeeded, freeing resources.\n",
- USBDEVNAME(sc->sc_dev), UMASS_SCSI_BUS,
- ccb->ccb_h.target_id, ccb->ccb_h.target_lun));
+ DPRINTF(UDMASS_SCSI, ("scbus%d: Rescan succeeded\n",
+ cam_sim_path(umass_sim)));
}
#endif
@@ -1890,16 +1880,39 @@ umass_cam_rescan(struct umass_softc *sc)
{
struct cam_path *path;
union ccb *ccb = malloc(sizeof(union ccb), M_USBDEV, M_WAITOK);
+ struct cam_periph *periph;
memset(ccb, 0, sizeof(union ccb));
- DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d: scanning bus for new device %d\n",
- USBDEVNAME(sc->sc_dev), cam_sim_path(umass_sim),
- device_get_unit(sc->sc_dev), 0,
- device_get_unit(sc->sc_dev)));
+ DPRINTF(UDMASS_SCSI, ("scbus%d: scanning for %s:%d:%d:%d\n",
+ cam_sim_path(umass_sim),
+ USBDEVNAME(sc->sc_dev), cam_sim_path(umass_sim),
+ USBDEVUNIT(sc->sc_dev), CAM_LUN_WILDCARD));
+
+ /* Lookup the peripheral for the SIM */
+ if (xpt_create_path(&path, NULL, cam_sim_path(umass_sim),
+ UMASS_SCSIID_HOST, 0)
+ != CAM_REQ_CMP)
+ return;
+ periph = cam_periph_find(path, cam_sim_name(umass_sim));
+#ifdef UMASS_DO_CAM_RESCAN
+ if (periph == NULL) {
+ DPRINTF(UDMASS_SCSI, ("scbus%d: abusing xpt_periph\n",
+ cam_sim_path(umass_sim)));
+ periph = xpt_periph;
+ }
+#endif
+ if (periph == NULL) {
+ DPRINTF(UDMASS_SCSI, ("scbus%d: no periph, rescan failed\n",
+ cam_sim_path(umass_sim)));
+ xpt_free_path(path);
+ return;
+ }
+ xpt_free_path(path);
- if (xpt_create_path(&path, xpt_periph, cam_sim_path(umass_sim),
- device_get_unit(sc->sc_dev), 0)
+ /* Lookup the path again, but now include the periph in the path */
+ if (xpt_create_path(&path, periph, cam_sim_path(umass_sim),
+ UMASS_SCSIID_HOST, 0)
!= CAM_REQ_CMP)
return;
@@ -1911,7 +1924,6 @@ umass_cam_rescan(struct umass_softc *sc)
/* The scan is in progress now. */
}
-#endif
static int
umass_cam_attach(struct umass_softc *sc)
@@ -1923,14 +1935,21 @@ umass_cam_attach(struct umass_softc *sc)
/* The artificial limit UMASS_SCSIID_MAX is there because CAM expects
* a limit to the number of targets that are present on a SIM.
*/
- if (device_get_unit(sc->sc_dev) > UMASS_SCSIID_MAX) {
- printf("%s: Increase UMASS_SCSIID_MAX (currently %d) in %s "
- "and try again.\n", USBDEVNAME(sc->sc_dev),
- UMASS_SCSIID_MAX, __FILE__);
+ if (device_get_unit(sc->sc_dev) >= UMASS_SCSIID_MAX) {
+ printf("scbus%d: Increase UMASS_SCSIID_MAX (currently %d) in %s"
+ " and try again.\n",
+ cam_sim_path(umass_sim), UMASS_SCSIID_MAX, __FILE__);
return(1);
}
-
-#ifdef UMASS_DO_CAM_RESCAN
+
+#ifndef UMASS_DEBUG
+ if (bootverbose)
+#endif
+ printf("%s:%d:%d:%d: Attached to scbus%d as device %d\n",
+ USBDEVNAME(sc->sc_dev), cam_sim_path(umass_sim),
+ USBDEVUNIT(sc->sc_dev), CAM_LUN_WILDCARD,
+ cam_sim_path(umass_sim), USBDEVUNIT(sc->sc_dev));
+
if (!cold) {
/* Notify CAM of the new device. Any failure is benign, as the
* user can still do it by hand (camcontrol rescan <busno>).
@@ -1940,7 +1959,6 @@ umass_cam_attach(struct umass_softc *sc)
*/
umass_cam_rescan(sc);
}
-#endif
return(0); /* always succesfull */
}
@@ -1955,14 +1973,6 @@ umass_cam_detach_sim()
if (umass_sim)
return(EBUSY); /* XXX CAM can't handle disappearing SIMs yet */
- if (umass_path) {
- /* XXX do we need to send an asynchroneous event for the SIM?
- xpt_async(AC_LOST_DEVICE, umass_path, NULL);
- */
- xpt_free_path(umass_path);
- umass_path = NULL;
- }
-
if (umass_sim) {
if (xpt_bus_deregister(cam_sim_path(umass_sim)))
cam_sim_free(umass_sim, /*free_devq*/TRUE);
@@ -1981,11 +1991,12 @@ umass_cam_detach(struct umass_softc *sc)
struct cam_path *path;
/* detach of sim not done until module unload */
- DPRINTF(UDMASS_SCSI, ("%s: losing CAM device entry\n",
- USBDEVNAME(sc->sc_dev)));
+ DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d: losing CAM device entry\n",
+ USBDEVNAME(sc->sc_dev), cam_sim_path(umass_sim),
+ USBDEVUNIT(sc->sc_dev), CAM_LUN_WILDCARD));
if (xpt_create_path(&path, NULL, cam_sim_path(umass_sim),
- device_get_unit(sc->sc_dev), CAM_LUN_WILDCARD)
+ USBDEVUNIT(sc->sc_dev), CAM_LUN_WILDCARD)
!= CAM_REQ_CMP)
return(ENOMEM);
xpt_async(AC_LOST_DEVICE, path, NULL);
@@ -2012,7 +2023,7 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb)
if (sc && (sc->flags & UMASS_FLAGS_GONE)) {
DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:func_code 0x%04x: "
"Invalid target (gone)\n",
- USBDEVNAME(sc->sc_dev), UMASS_SCSI_BUS,
+ USBDEVNAME(sc->sc_dev), cam_sim_path(umass_sim),
ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
ccb->ccb_h.func_code));
ccb->ccb_h.status = CAM_TID_INVALID;
@@ -2037,7 +2048,7 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb)
if (sc == NULL) {
printf("%s:%d:%d:%d:func_code 0x%04x: "
"Invalid target\n",
- DEVNAME_SIM, UMASS_SCSI_BUS,
+ DEVNAME_SIM, cam_sim_path(umass_sim),
ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
ccb->ccb_h.func_code);
@@ -2055,7 +2066,7 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb)
if (sc == NULL && ccb->ccb_h.target_id != CAM_TARGET_WILDCARD) {
DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:func_code 0x%04x: "
"Invalid target\n",
- DEVNAME_SIM, UMASS_SCSI_BUS,
+ DEVNAME_SIM, cam_sim_path(umass_sim),
ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
ccb->ccb_h.func_code));
@@ -2076,11 +2087,13 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb)
int dir;
unsigned char *cmd;
int cmdlen;
+ unsigned char *rcmd;
+ int rcmdlen;
DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_SCSI_IO: "
"cmd: 0x%02x, flags: 0x%02x, "
"%db cmd/%db data/%db sense\n",
- USBDEVNAME(sc->sc_dev), UMASS_SCSI_BUS,
+ USBDEVNAME(sc->sc_dev), cam_sim_path(umass_sim),
ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
csio->cdb_io.cdb_bytes[0],
ccb->ccb_h.flags & CAM_DIR_MASK,
@@ -2098,7 +2111,7 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb)
if (sc->transfer_state != TSTATE_IDLE) {
DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_SCSI_IO: "
"I/O requested while busy (state %d, %s)\n",
- USBDEVNAME(sc->sc_dev), UMASS_SCSI_BUS,
+ USBDEVNAME(sc->sc_dev), cam_sim_path(umass_sim),
ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
sc->transfer_state,states[sc->transfer_state]));
ccb->ccb_h.status = CAM_SCSI_BUSY;
@@ -2118,9 +2131,27 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb)
}
ccb->ccb_h.status = CAM_REQ_INPROG | CAM_SIM_QUEUED;
- if (sc->transform(sc, csio->cdb_io.cdb_bytes, csio->cdb_len,
- &cmd, &cmdlen)) {
- sc->transfer(sc, ccb->ccb_h.target_lun, cmd, cmdlen,
+
+
+ if (csio->ccb_h.flags & CAM_CDB_POINTER) {
+ cmd = (unsigned char *) csio->cdb_io.cdb_ptr;
+ } else {
+ cmd = (unsigned char *) &csio->cdb_io.cdb_bytes;
+ }
+ cmdlen = csio->cdb_len;
+ rcmd = (unsigned char *) &sc->cam_scsi_command;
+ rcmdlen = sizeof(sc->cam_scsi_command);
+
+ /* sc->transform will convert the command to the command
+ * (format) needed by the specific command set and return
+ * the converted command in a buffer pointed to be rcmd.
+ * We pass in a buffer, but if the command does not
+ * have to be transformed it returns a ptr to the original
+ * buffer (see umass_scsi_transform).
+ */
+
+ if (sc->transform(sc, cmd, cmdlen, &rcmd, &rcmdlen)) {
+ sc->transfer(sc, ccb->ccb_h.target_lun, rcmd, rcmdlen,
csio->data_ptr,
csio->dxfer_len, dir,
umass_cam_cb, (void *) ccb);
@@ -2137,7 +2168,7 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb)
DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_PATH_INQ:.\n",
(sc == NULL? DEVNAME_SIM:USBDEVNAME(sc->sc_dev)),
- UMASS_SCSI_BUS,
+ cam_sim_path(umass_sim),
ccb->ccb_h.target_id, ccb->ccb_h.target_lun));
/* host specific information */
@@ -2164,7 +2195,7 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb)
case XPT_RESET_DEV:
{
DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_RESET_DEV:.\n",
- USBDEVNAME(sc->sc_dev), UMASS_SCSI_BUS,
+ USBDEVNAME(sc->sc_dev), cam_sim_path(umass_sim),
ccb->ccb_h.target_id, ccb->ccb_h.target_lun));
ccb->ccb_h.status = CAM_REQ_INPROG;
@@ -2176,7 +2207,7 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb)
struct ccb_trans_settings *cts = &ccb->cts;
DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_GET_TRAN_SETTINGS:.\n",
- USBDEVNAME(sc->sc_dev), UMASS_SCSI_BUS,
+ USBDEVNAME(sc->sc_dev), cam_sim_path(umass_sim),
ccb->ccb_h.target_id, ccb->ccb_h.target_lun));
cts->valid = 0;
@@ -2189,7 +2220,7 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb)
case XPT_SET_TRAN_SETTINGS:
{
DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_SET_TRAN_SETTINGS:.\n",
- USBDEVNAME(sc->sc_dev), UMASS_SCSI_BUS,
+ USBDEVNAME(sc->sc_dev), cam_sim_path(umass_sim),
ccb->ccb_h.target_id, ccb->ccb_h.target_lun));
ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
@@ -2202,7 +2233,7 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb)
DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_CALC_GEOMETRY: "
"Volume size = %d\n",
- USBDEVNAME(sc->sc_dev), UMASS_SCSI_BUS,
+ USBDEVNAME(sc->sc_dev), cam_sim_path(umass_sim),
ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
ccg->volume_size));
@@ -2235,7 +2266,7 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb)
{
DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_NOOP:.\n",
(sc == NULL? DEVNAME_SIM:USBDEVNAME(sc->sc_dev)),
- UMASS_SCSI_BUS,
+ cam_sim_path(umass_sim),
ccb->ccb_h.target_id, ccb->ccb_h.target_lun));
ccb->ccb_h.status = CAM_REQ_CMP;
@@ -2246,7 +2277,7 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb)
DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:func_code 0x%04x: "
"Not implemented\n",
(sc == NULL? DEVNAME_SIM:USBDEVNAME(sc->sc_dev)),
- UMASS_SCSI_BUS,
+ cam_sim_path(umass_sim),
ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
ccb->ccb_h.func_code));
@@ -2297,32 +2328,30 @@ umass_cam_cb(struct umass_softc *sc, void *priv, int residue, int status)
switch (ccb->ccb_h.func_code) {
case XPT_SCSI_IO:
{
- unsigned char *cmd;
- int cmdlen;
+ unsigned char *rcmd;
+ int rcmdlen;
/* fetch sense data */
DPRINTF(UDMASS_SCSI,("%s: Fetching %db sense data\n",
USBDEVNAME(sc->sc_dev),
sc->cam_scsi_sense.length));
+ /* the rest of the command was filled in at attach */
sc->cam_scsi_sense.length = csio->sense_len;
- if (sc->transform(sc, (char *) &sc->cam_scsi_sense,
- sizeof(sc->cam_scsi_sense),
- &cmd, &cmdlen)) {
+ rcmd = (unsigned char *) &sc->cam_scsi_command;
+
+ if (sc->transform(sc,
+ (unsigned char *) &sc->cam_scsi_sense,
+ sizeof(sc->cam_scsi_sense),
+ &rcmd, &rcmdlen)) {
sc->transfer(sc, ccb->ccb_h.target_lun,
- cmd, cmdlen,
+ rcmd, rcmdlen,
&csio->sense_data,
csio->sense_len, DIR_IN,
umass_cam_sense_cb, (void *) ccb);
} else {
-#ifdef UMASS_DEBUG
panic("transform(REQUEST_SENSE) failed\n");
-#else
- csio->resid = sc->transfer_datalen;
- ccb->ccb_h.status = CAM_REQ_CMP_ERR;
- xpt_done(ccb);
-#endif
}
break;
}
@@ -2428,7 +2457,7 @@ static int
umass_scsi_transform(struct umass_softc *sc, unsigned char *cmd, int cmdlen,
unsigned char **rcmd, int *rcmdlen)
{
- *rcmd = cmd; /* trivial copy */
+ *rcmd = cmd; /* We don't need to copy it */
*rcmdlen = cmdlen;
return 1; /* success */
@@ -2442,52 +2471,123 @@ static int
umass_ufi_transform(struct umass_softc *sc, unsigned char *cmd, int cmdlen,
unsigned char **rcmd, int *rcmdlen)
{
- *rcmd = cmd;
/* A UFI command is always 12 bytes in length */
- /* XXX cmd[(cmdlen+1)..12] contains garbage */
- *rcmdlen = 12;
+ KASSERT(*rcmdlen < UFI_COMMAND_LENGTH,
+ ("rcmdlen = %d < %d, buffer too small",
+ rcmdlen, UFI_COMMAND_LENGTH));
+
+ *rcmdlen = UFI_COMMAND_LENGTH;
+ memset(*rcmd, 0, UFI_COMMAND_LENGTH);
+
+ /* Handle any quirks */
+ if (cmd[0] == TEST_UNIT_READY
+ && sc->quirks & NO_TEST_UNIT_READY) {
+ /* Some devices do not support this command.
+ * Start Stop Unit should give the same results
+ */
+ DPRINTF(UDMASS_UFI, ("%s: Converted TEST_UNIT_READY "
+ "to START_UNIT\n", USBDEVNAME(sc->sc_dev)));
+ cmd[0] = START_STOP_UNIT;
+ cmd[4] = SSS_START;
+ return 1;
+ }
switch (cmd[0]) {
+ /* Commands of which the format has been verified. They should work. */
case TEST_UNIT_READY:
- if (sc->quirks & NO_TEST_UNIT_READY) {
- DPRINTF(UDMASS_UFI, ("%s: Converted TEST_UNIT_READY "
- "to START_UNIT\n", USBDEVNAME(sc->sc_dev)));
- cmd[0] = START_STOP_UNIT;
- cmd[4] = SSS_START;
- }
- return 1;
+ case REZERO_UNIT:
+ case REQUEST_SENSE:
case INQUIRY:
case START_STOP_UNIT:
- case MODE_SENSE:
+ case SEND_DIAGNOSTIC:
case PREVENT_ALLOW:
- case READ_10:
- case READ_12:
case READ_CAPACITY:
- case REQUEST_SENSE:
- case REZERO_UNIT:
- case POSITION_TO_ELEMENT: /* SEEK_10 */
- case SEND_DIAGNOSTIC:
+ case READ_10:
case WRITE_10:
- case WRITE_12:
- /* FORMAT_UNIT */
- /* MODE_SELECT */
- /* READ_FORMAT_CAPACITY */
- /* VERIFY */
- /* WRITE_AND_VERIFY */
+ case POSITION_TO_ELEMENT: /* SEEK_10 */
+ case MODE_SELECT_10:
+ case MODE_SENSE_10:
+ /* Copy the command into the (zeroed out) destination buffer */
+ memcpy(*rcmd, cmd, cmdlen);
return 1; /* success */
+
+ /* Other UFI commands: FORMAT_UNIT, MODE_SELECT, READ_FORMAT_CAPACITY,
+ * VERIFY, WRITE_AND_VERIFY.
+ * These should be checked whether they somehow can be made to fit.
+ */
+
+ /* These commands are known _not_ to work. They should be converted
+ * The 6 byte commands can be switched off with a CAM quirk. See
+ * the entry for the Y-E data drive.
+ */
+ case READ_6:
+ case WRITE_6:
+ case MODE_SENSE_6:
+ case MODE_SELECT_6:
+ case READ_12:
+ case WRITE_12:
default:
- return 0; /* success */
+ printf("%s: Unsupported UFI command 0x%02x",
+ USBDEVNAME(sc->sc_dev), cmd[0]);
+ if (cmdlen == 6)
+ printf(", 6 byte command should have been converted");
+ printf("\n");
+ return 0; /* failure */
}
}
/*
- * 8070 specific functions
+ * 8070 (ATAPI) specific functions
*/
static int
-umass_8070_transform(struct umass_softc *sc, unsigned char *cmd, int cmdlen,
- unsigned char **rcmd, int *rcmdlen)
+umass_atapi_transform(struct umass_softc *sc, unsigned char *cmd, int cmdlen,
+ unsigned char **rcmd, int *rcmdlen)
{
- return 0; /* failure */
+ /* A ATAPI command is always 12 bytes in length */
+ KASSERT(*rcmdlen < ATAPI_COMMAND_LENGTH,
+ ("rcmdlen = %d < %d, buffer too small",
+ rcmdlen, ATAPI_COMMAND_LENGTH));
+
+ *rcmdlen = ATAPI_COMMAND_LENGTH;
+ memset(*rcmd, 0, ATAPI_COMMAND_LENGTH);
+
+ switch (cmd[0]) {
+ /* Commands of which the format has been verified. They should work. */
+ case TEST_UNIT_READY:
+ case REZERO_UNIT:
+ case REQUEST_SENSE:
+ case INQUIRY:
+ case START_STOP_UNIT:
+ case SEND_DIAGNOSTIC:
+ case PREVENT_ALLOW:
+ case READ_CAPACITY:
+ case READ_10:
+ case WRITE_10:
+ case POSITION_TO_ELEMENT: /* SEEK_10 */
+ case MODE_SELECT_10:
+ case MODE_SENSE_10:
+ /* Copy the command into the (zeroed out) destination buffer */
+ memcpy(*rcmd, cmd, cmdlen);
+ return 1; /* success */
+
+ /* These commands are known _not_ to work. They should be converted
+ * The 6 byte commands can be switched off with a CAM quirk. See
+ * the entry for the Y-E data drive.
+ */
+ case READ_6:
+ case WRITE_6:
+ case MODE_SENSE_6:
+ case MODE_SELECT_6:
+ case READ_12:
+ case WRITE_12:
+ default:
+ printf("%s: Unsupported ATAPI command 0x%02x",
+ USBDEVNAME(sc->sc_dev), cmd[0]);
+ if (cmdlen == 6)
+ printf(", 6 byte command should have been converted");
+ printf("\n");
+ return 0; /* failure */
+ }
}
OpenPOWER on IntegriCloud