summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorn_hibma <n_hibma@FreeBSD.org>2000-04-02 16:59:16 +0000
committern_hibma <n_hibma@FreeBSD.org>2000-04-02 16:59:16 +0000
commit1d9f7bb597dbd671e7079f8c0c6174edae8ff204 (patch)
tree221b125cfb9d9876a3db62545d8a94a614c78c56 /sys
parentc512ee151f5e474e8679f0f4103163987f8ad41c (diff)
downloadFreeBSD-src-1d9f7bb597dbd671e7079f8c0c6174edae8ff204.zip
FreeBSD-src-1d9f7bb597dbd671e7079f8c0c6174edae8ff204.tar.gz
I got the CAM numbers (path id's, buses, unit numbers) and newbus
unit numbers all wrong. This did not show up because most of them where zero anyway. Use a separate buffer for command transforms instead of fiddling with the existing cdb_bytes. Take CAM_CDB_POINTER into account. Nobody is using it, but someone might in the future. Be more picky about what to accept in the UFI command set. First attempt at implementing the ATAPI command protocol transforms. This should at least make Imation Superdisk and other e-Shuttle based devices show as attached. Maybe they even work to some extent.
Diffstat (limited to 'sys')
-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