summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authorguido <guido@FreeBSD.org>2002-01-24 15:10:53 +0000
committerguido <guido@FreeBSD.org>2002-01-24 15:10:53 +0000
commit9145fb545645d9c40f4b5b3b5977138afd82e066 (patch)
treeb6d4f4c41db12dca2038c283bbdd32b77f102c8c /sys/dev
parent205d3c89825fa40880d67d4c9c2b89d21bcb8e7f (diff)
downloadFreeBSD-src-9145fb545645d9c40f4b5b3b5977138afd82e066.zip
FreeBSD-src-9145fb545645d9c40f4b5b3b5977138afd82e066.tar.gz
1) Fix a debug statement by filling in its data before the printf in
stead of after 2) Honour NO_TEST_UNIT_READY quirk for atapi devices as well 3) Actually support FujiFilm FinePix 6800 camera's. Will very likely also work for other FinePix models. Based on a debug session about half a year ago with Nik Hibma. MFC after: 2 weeks
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/usb/umass.c75
1 files changed, 72 insertions, 3 deletions
diff --git a/sys/dev/usb/umass.c b/sys/dev/usb/umass.c
index e2918e1..a549a2a 100644
--- a/sys/dev/usb/umass.c
+++ b/sys/dev/usb/umass.c
@@ -413,7 +413,9 @@ struct umass_softc {
/* SCSI/CAM specific variables */
unsigned char cam_scsi_command[CAM_MAX_CDBLEN];
+ unsigned char cam_scsi_command2[CAM_MAX_CDBLEN];
struct scsi_sense cam_scsi_sense;
+ struct scsi_sense cam_scsi_test_unit_ready;
int transfer_speed; /* in kb/s */
int maxlun; /* maximum LUN number */
@@ -504,6 +506,8 @@ Static void umass_cam_cb (struct umass_softc *sc, void *priv,
int residue, int status);
Static void umass_cam_sense_cb (struct umass_softc *sc, void *priv,
int residue, int status);
+Static void umass_cam_quirk_cb (struct umass_softc *sc, void *priv,
+ int residue, int status);
Static void umass_cam_rescan_callback
(struct cam_periph *periph,union ccb *ccb);
@@ -624,6 +628,11 @@ umass_match_proto(struct umass_softc *sc, usbd_interface_handle iface,
return(UMATCH_VENDOR_PRODUCT);
}
+ if (UGETW(dd->idVendor) == USB_VENDOR_FUJIPHOTO
+ && UGETW(dd->idProduct) == USB_PRODUCT_FUJIPHOTO_MASS0100) {
+ sc->quirks |= RS_NO_CLEAR_UA;
+ }
+
if (UGETW(dd->idVendor) == USB_VENDOR_YEDATA
&& UGETW(dd->idProduct) == USB_PRODUCT_YEDATA_FLASHBUSTERU) {
@@ -981,6 +990,7 @@ USB_ATTACH(umass)
(sc->proto & PROTO_RBC)) {
/* Prepare the SCSI command block */
sc->cam_scsi_sense.opcode = REQUEST_SENSE;
+ sc->cam_scsi_test_unit_ready.opcode = TEST_UNIT_READY;
/* If this is the first device register the SIM */
if (umass_sim == NULL) {
@@ -2519,13 +2529,13 @@ umass_cam_cb(struct umass_softc *sc, void *priv, int residue, int status)
int rcmdlen;
/* fetch sense data */
+ /* the rest of the command was filled in at attach */
+ sc->cam_scsi_sense.length = csio->sense_len;
+
DPRINTF(UDMASS_SCSI,("%s: Fetching %db sense data\n",
USBDEVNAME(sc->sc_dev),
csio->sense_len));
- /* the rest of the command was filled in at attach */
- sc->cam_scsi_sense.length = csio->sense_len;
-
rcmd = (unsigned char *) &sc->cam_scsi_command;
rcmdlen = sizeof(sc->cam_scsi_command);
@@ -2574,6 +2584,8 @@ umass_cam_sense_cb(struct umass_softc *sc, void *priv, int residue, int status)
{
union ccb *ccb = (union ccb *) priv;
struct ccb_scsiio *csio = &ccb->csio; /* deref union */
+ unsigned char *rcmd;
+ int rcmdlen;
switch (status) {
case STATUS_CMD_OK:
@@ -2598,6 +2610,41 @@ umass_cam_sense_cb(struct umass_softc *sc, void *priv, int residue, int status)
* CCI)
*/
ccb->ccb_h.status = CAM_REQ_CMP;
+ } else if ((sc->quirks & RS_NO_CLEAR_UA) && /* XXX */
+ (csio->cdb_io.cdb_bytes[0] == READ_CAPACITY) &&
+ ((csio->sense_data.flags & SSD_KEY)
+ == SSD_KEY_UNIT_ATTENTION)) {
+ /* Ignore unit attention errors in the case where
+ * the Unit Attention state is not cleared on
+ * REQUEST SENSE. They will appear again at the next
+ * command.
+ */
+ ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR
+ | CAM_AUTOSNS_VALID;
+ csio->scsi_status = SCSI_STATUS_CHECK_COND;
+
+ DPRINTF(UDMASS_SCSI,("%s: Doing a sneaky
+ TEST_UNIT_READY\n",
+ USBDEVNAME(sc->sc_dev)));
+
+ /* the rest of the command was filled in at attach */
+
+ rcmd = (unsigned char *) &sc->cam_scsi_command2;
+ rcmdlen = sizeof(sc->cam_scsi_command2);
+
+ if (sc->transform(sc,
+ (unsigned char *)
+ &sc->cam_scsi_test_unit_ready,
+ sizeof(sc->cam_scsi_test_unit_ready),
+ &rcmd, &rcmdlen)) {
+ sc->transfer(sc, ccb->ccb_h.target_lun,
+ rcmd, rcmdlen,
+ NULL, 0, DIR_NONE,
+ umass_cam_quirk_cb, (void *) ccb);
+ } else {
+ panic("transform(TEST_UNIT_READY) failed\n");
+ }
+ break;
} else {
ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR
| CAM_AUTOSNS_VALID;
@@ -2614,6 +2661,16 @@ umass_cam_sense_cb(struct umass_softc *sc, void *priv, int residue, int status)
}
}
+Static void
+umass_cam_quirk_cb(struct umass_softc *sc, void *priv, int residue, int status)
+{
+ union ccb *ccb = (union ccb *) priv;
+
+ DPRINTF(UDMASS_SCSI, ("%s: Test unit ready returned status %d\n",
+ USBDEVNAME(sc->sc_dev), status));
+ ccb->ccb_h.status = CAM_REQ_CMP;
+ xpt_done(ccb);
+}
Static int
umass_driver_load(module_t mod, int what, void *arg)
@@ -2869,6 +2926,18 @@ umass_atapi_transform(struct umass_softc *sc, unsigned char *cmd, int cmdlen,
return 1;
case TEST_UNIT_READY:
+ if (sc->quirks & NO_TEST_UNIT_READY) {
+ KASSERT(*rcmdlen >= sizeof(struct scsi_start_stop_unit),
+ ("rcmdlen = %d < %d, buffer too small",
+ *rcmdlen, sizeof(struct scsi_start_stop_unit)));
+ DPRINTF(UDMASS_SCSI, ("%s: Converted TEST_UNIT_READY "
+ "to START_UNIT\n", USBDEVNAME(sc->sc_dev)));
+ memset(*rcmd, 0, *rcmdlen);
+ (*rcmd)[0] = START_STOP_UNIT;
+ (*rcmd)[4] = SSS_START;
+ return 1;
+ }
+ /* fallthrough */
case REZERO_UNIT:
case REQUEST_SENSE:
case START_STOP_UNIT:
OpenPOWER on IntegriCloud