summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKenneth R Westerback <krw@cvs.openbsd.org>2005-05-14 23:36:27 +0000
committerKenneth R Westerback <krw@cvs.openbsd.org>2005-05-14 23:36:27 +0000
commit66ced9bada92fa1376dfd55073b763f781d4764f (patch)
tree9dfc9add08e6e90114c3d5bc822fbec4f015581d
parent5e017dfcaee3abb57aab4fdf622aa4c9ccf67bda (diff)
Try to ensure that UFI/ATAPI USB umass devices always get the zero
padded 12 byte commands mandated by the standard. Adapt the Linux data length twiddling on certain commands. We used to have some of this in a different form, curtesy of csapuntz@, but it got lost in subsequent merges. Fixes the USB card reader of Quentin Barnes who provided much testing and feedback for over a year! Tested by drahn@, ok marco@, 'this is good stuff' deraadt@.
-rw-r--r--sys/dev/usb/umass.c56
-rw-r--r--sys/dev/usb/umass_scsi.c4
2 files changed, 46 insertions, 14 deletions
diff --git a/sys/dev/usb/umass.c b/sys/dev/usb/umass.c
index ab2a7ea7c67..736aa574850 100644
--- a/sys/dev/usb/umass.c
+++ b/sys/dev/usb/umass.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: umass.c,v 1.39 2005/04/01 06:41:13 pascoe Exp $ */
+/* $OpenBSD: umass.c,v 1.40 2005/05/14 23:36:26 krw Exp $ */
/* $NetBSD: umass.c,v 1.116 2004/06/30 05:53:46 mycroft Exp $ */
/*
@@ -131,15 +131,6 @@
* umass_cam_cb again to complete the CAM command.
*/
-#if defined(__NetBSD__)
-#include "atapibus.h"
-#include "scsibus.h"
-#elif defined(__OpenBSD__)
-#include "atapiscsi.h"
-#endif
-
-#include "wd.h"
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
@@ -157,6 +148,8 @@
#endif
#include <machine/bus.h>
+#include <scsi/scsi_all.h>
+
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
#include <dev/usb/usbdi_util.h>
@@ -212,6 +205,7 @@ Static usbd_status umass_setup_ctrl_transfer(struct umass_softc *sc,
usbd_xfer_handle xfer);
Static void umass_clear_endpoint_stall(struct umass_softc *sc, int endpt,
usbd_xfer_handle xfer);
+Static void umass_adjust_transfer(struct umass_softc *);
#if 0
Static void umass_reset(struct umass_softc *sc, transfer_cb_f cb, void *priv);
#endif
@@ -879,6 +873,41 @@ umass_setup_ctrl_transfer(struct umass_softc *sc, usb_device_request_t *req,
}
Static void
+umass_adjust_transfer(struct umass_softc *sc)
+{
+ switch (sc->sc_cmd) {
+ case UMASS_CPROTO_UFI:
+ sc->cbw.bCDBLength = UFI_COMMAND_LENGTH;
+ /* Adjust the length field in certain scsi commands. */
+ switch (sc->cbw.CBWCDB[0]) {
+ case INQUIRY:
+ if (sc->transfer_datalen > 36) {
+ sc->transfer_datalen = 36;
+ sc->cbw.CBWCDB[4] = 36;
+ }
+ break;
+ case MODE_SENSE_BIG:
+ if (sc->transfer_datalen > 8) {
+ sc->transfer_datalen = 8;
+ sc->cbw.CBWCDB[7] = 0;
+ sc->cbw.CBWCDB[8] = 8;
+ }
+ break;
+ case REQUEST_SENSE:
+ if (sc->transfer_datalen > 18) {
+ sc->transfer_datalen = 18;
+ sc->cbw.CBWCDB[4] = 18;
+ }
+ break;
+ }
+ break;
+ case UMASS_CPROTO_ATAPI:
+ sc->cbw.bCDBLength = UFI_COMMAND_LENGTH;
+ break;
+ }
+}
+
+Static void
umass_clear_endpoint_stall(struct umass_softc *sc, int endpt,
usbd_xfer_handle xfer)
{
@@ -1049,6 +1078,7 @@ umass_bbb_transfer(struct umass_softc *sc, int lun, void *cmd, int cmdlen,
sc->cbw.bCBWFlags = (dir == DIR_IN? CBWFLAGS_IN:CBWFLAGS_OUT);
sc->cbw.bCBWLUN = lun;
sc->cbw.bCDBLength = cmdlen;
+ bzero(sc->cbw.CBWCDB, sizeof(sc->cbw.CBWCDB));
memcpy(sc->cbw.CBWCDB, cmd, cmdlen);
DIF(UDMASS_BBB, umass_bbb_dump_cbw(sc, &sc->cbw));
@@ -1066,6 +1096,7 @@ umass_bbb_transfer(struct umass_softc *sc, int lun, void *cmd, int cmdlen,
sc->transfer_state = TSTATE_BBB_COMMAND;
/* Send the CBW from host to device via bulk-out endpoint. */
+ umass_adjust_transfer(sc);
if ((err = umass_setup_transfer(sc, sc->sc_pipe[UMASS_BULKOUT],
&sc->cbw, UMASS_BBB_CBW_SIZE, 0,
sc->transfer_xfer[XFER_BBB_CBW])))
@@ -1516,7 +1547,10 @@ umass_cbi_transfer(struct umass_softc *sc, int lun,
sc->transfer_state = TSTATE_CBI_COMMAND;
/* Send the Command Block from host to device via control endpoint. */
- if ((err = umass_cbi_adsc(sc, cmd, cmdlen,
+ bzero(sc->cbw.CBWCDB, sizeof(sc->cbw.CBWCDB));
+ memcpy(sc->cbw.CBWCDB, cmd, cmdlen);
+ umass_adjust_transfer(sc);
+ if ((err = umass_cbi_adsc(sc, (void *)sc->cbw.CBWCDB, sc->cbw.bCDBLength,
sc->transfer_xfer[XFER_CBI_CB])))
umass_cbi_reset(sc, STATUS_WIRE_FAILED);
diff --git a/sys/dev/usb/umass_scsi.c b/sys/dev/usb/umass_scsi.c
index 435ae278d59..537c17f5ed8 100644
--- a/sys/dev/usb/umass_scsi.c
+++ b/sys/dev/usb/umass_scsi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: umass_scsi.c,v 1.11 2005/04/27 23:54:44 krw Exp $ */
+/* $OpenBSD: umass_scsi.c,v 1.12 2005/05/14 23:36:26 krw Exp $ */
/* $NetBSD: umass_scsipi.c,v 1.9 2003/02/16 23:14:08 augustss Exp $ */
/*
* Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -364,8 +364,6 @@ umass_scsi_cb(struct umass_softc *sc, void *priv, int residue, int status)
scbus->sc_sense_cmd.length = sizeof(xs->sense);
cmdlen = sizeof(scbus->sc_sense_cmd);
- if (sc->sc_cmd == UMASS_CPROTO_UFI) /* XXX */
- cmdlen = UFI_COMMAND_LENGTH;
sc->sc_methods->wire_xfer(sc, link->lun,
&scbus->sc_sense_cmd, cmdlen,
&xs->sense, sizeof(xs->sense),