cc -pipe -ffreestanding -O2 -Werror -Wall -Wno-main -Wno-format-zero-length -Fix several problems with CCI handling, and enable it:

* We were never calling the callback function when we got a UFI CCI(!).
* We were passing a bogus residual count on non-UFI CCIs.
* After a REQUEST SENSE, the UFI CCI may include the ASC/ASCQ from the sense
  information -- don't consider this a failure.
In addition, remove a horrible hack that was causing us to drop sense
information on the floor and return empty INQUIRY responses, often in the case
where there is a UNIT ATTENTION pending during the INQUIRY.  (Some drives send
the data and then fail, some don't.)

This eliminates the need for quirks for the Y-E DATA FlashBuster.

These changes work on:

umass0: SAMSUNG SFD-321U [FW 0C], rev 1.10/2.10, addr 2
umass0: using UFI over CBI with CCI
sd0 at atapibus1 drive 0: <SMSC, USB FDC, 2.10> disk removable

umass0: TEAC TEAC FD-05PUB, rev 1.10/0.00, addr 2
umass0: using UFI over CBI with CCI
sd0 at atapibus0 drive 0: <TEAC, FD-05PUB, 1026> disk removable

umass0: Y-E DATA FlashBuster-U, rev 1.00/3.04, addr 2
umass0: using UFI over CBI with CCI
sd0 at atapibus0 drive 0: <Y-E DATA, USB-FDU, 3.04> disk removable
This commit is contained in:
mycroft 2003-09-10 02:49:18 +00:00
parent 644a4857fb
commit b8fd3dab7d
4 changed files with 55 additions and 108 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: umass.c,v 1.99 2003/09/08 19:57:32 mycroft Exp $ */
/* $NetBSD: umass.c,v 1.100 2003/09/10 02:49:18 mycroft Exp $ */
/*-
* Copyright (c) 1999 MAEKAWA Masahide <bishop@rr.iij4u.or.jp>,
* Nick Hibma <n_hibma@freebsd.org>
@ -94,7 +94,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: umass.c,v 1.99 2003/09/08 19:57:32 mycroft Exp $");
__KERNEL_RCSID(0, "$NetBSD: umass.c,v 1.100 2003/09/10 02:49:18 mycroft Exp $");
#include "atapibus.h"
#include "scsibus.h"
@ -320,10 +320,6 @@ USB_ATTACH(umass)
}
}
/* XXX - Now unsupported CBI with CCI */
if (sc->sc_wire == UMASS_WPROTO_CBI_I)
sc->sc_wire = UMASS_WPROTO_CBI;
if (sc->sc_cmd == UMASS_CPROTO_UNSPEC) {
switch (id->bInterfaceSubClass) {
case UISUBCLASS_SCSI:
@ -456,6 +452,9 @@ USB_ATTACH(umass)
}
/* Open the bulk-in and -out pipe */
DPRINTF(UDMASS_USB, ("%s: opening iface %p epaddr %d for BULKOUT\n",
USBDEVNAME(sc->sc_dev), sc->sc_iface,
sc->sc_epaddr[UMASS_BULKOUT]));
err = usbd_open_pipe(sc->sc_iface, sc->sc_epaddr[UMASS_BULKOUT],
USBD_EXCLUSIVE_USE,
&sc->sc_pipe[UMASS_BULKOUT]);
@ -465,6 +464,9 @@ USB_ATTACH(umass)
umass_disco(sc);
USB_ATTACH_ERROR_RETURN;
}
DPRINTF(UDMASS_USB, ("%s: opening iface %p epaddr %d for BULKIN\n",
USBDEVNAME(sc->sc_dev), sc->sc_iface,
sc->sc_epaddr[UMASS_BULKIN]));
err = usbd_open_pipe(sc->sc_iface, sc->sc_epaddr[UMASS_BULKIN],
USBD_EXCLUSIVE_USE, &sc->sc_pipe[UMASS_BULKIN]);
if (err) {
@ -486,6 +488,9 @@ USB_ATTACH(umass)
* arriving concurrently.
*/
if (sc->sc_wire == UMASS_WPROTO_CBI_I) {
DPRINTF(UDMASS_USB, ("%s: opening iface %p epaddr %d for INTRIN\n",
USBDEVNAME(sc->sc_dev), sc->sc_iface,
sc->sc_epaddr[UMASS_INTRIN]));
err = usbd_open_pipe(sc->sc_iface, sc->sc_epaddr[UMASS_INTRIN],
USBD_EXCLUSIVE_USE, &sc->sc_pipe[UMASS_INTRIN]);
if (err) {
@ -1453,27 +1458,11 @@ umass_cbi_state(usbd_xfer_handle xfer, usbd_private_handle priv,
sc->transfer_xfer[XFER_CBI_DATA]))
umass_cbi_reset(sc, STATUS_WIRE_FAILED);
} else if (sc->sc_wire == UMASS_WPROTO_CBI_I) {
DPRINTF(UDMASS_CBI, ("%s: no data phase\n",
USBDEVNAME(sc->sc_dev)));
sc->transfer_state = TSTATE_CBI_STATUS;
if (umass_setup_transfer(sc, sc->sc_pipe[UMASS_INTRIN],
&sc->sbl, sizeof(sc->sbl),
0, /* fixed length transfer */
sc->transfer_xfer[XFER_CBI_STATUS])){
umass_cbi_reset(sc, STATUS_WIRE_FAILED);
}
} else {
DPRINTF(UDMASS_CBI, ("%s: no data phase\n",
USBDEVNAME(sc->sc_dev)));
/* No command completion interrupt. Request
* sense data.
*/
sc->transfer_state = TSTATE_IDLE;
sc->transfer_cb(sc, sc->transfer_priv,
0, STATUS_CMD_UNKNOWN);
goto dostatus;
}
return;
case TSTATE_CBI_DATA:
@ -1506,15 +1495,15 @@ umass_cbi_state(usbd_xfer_handle xfer, usbd_private_handle priv,
umass_dump_buffer(sc, sc->transfer_data,
sc->transfer_actlen, 48));
dostatus:
if (sc->sc_wire == UMASS_WPROTO_CBI_I) {
sc->transfer_state = TSTATE_CBI_STATUS;
memset(&sc->sbl, 0, sizeof(sc->sbl));
if (umass_setup_transfer(sc, sc->sc_pipe[UMASS_INTRIN],
&sc->sbl, sizeof(sc->sbl),
0, /* fixed length transfer */
sc->transfer_xfer[XFER_CBI_STATUS])){
sc->transfer_xfer[XFER_CBI_STATUS]))
umass_cbi_reset(sc, STATUS_WIRE_FAILED);
}
} else {
/* No command completion interrupt. Request
* sense to get status of command.
@ -1545,6 +1534,15 @@ umass_cbi_state(usbd_xfer_handle xfer, usbd_private_handle priv,
/* Dissect the information in the buffer */
{
u_int32_t actlen;
usbd_get_xfer_status(xfer,NULL,NULL,&actlen,NULL);
DPRINTF(UDMASS_CBI, ("%s: CBI_STATUS actlen=%d\n",
USBDEVNAME(sc->sc_dev), actlen));
if (actlen != 2)
break;
}
if (sc->sc_cmd == UMASS_CPROTO_UFI) {
int status;
@ -1558,37 +1556,42 @@ umass_cbi_state(usbd_xfer_handle xfer, usbd_private_handle priv,
USBDEVNAME(sc->sc_dev),
sc->sbl.ufi.asc, sc->sbl.ufi.ascq));
if (sc->sbl.ufi.asc == 0 && sc->sbl.ufi.ascq == 0)
if ((sc->sbl.ufi.asc == 0 && sc->sbl.ufi.ascq == 0) ||
sc->sc_sense)
status = STATUS_CMD_OK;
else
status = STATUS_CMD_FAILED;
/* No sense, command successful */
/* No autosense, command successful */
sc->transfer_state = TSTATE_IDLE;
sc->transfer_cb(sc, sc->transfer_priv,
sc->transfer_datalen - sc->transfer_actlen, status);
} else {
int status;
/* Command Interrupt Data Block */
DPRINTF(UDMASS_CBI, ("%s: type=0x%02x, value=0x%02x\n",
USBDEVNAME(sc->sc_dev),
sc->sbl.common.type, sc->sbl.common.value));
if (sc->sbl.common.type == IDB_TYPE_CCI) {
int err;
if ((sc->sbl.common.value&IDB_VALUE_STATUS_MASK)
== IDB_VALUE_PASS) {
err = STATUS_CMD_OK;
} else if ((sc->sbl.common.value & IDB_VALUE_STATUS_MASK)
== IDB_VALUE_FAIL ||
(sc->sbl.common.value & IDB_VALUE_STATUS_MASK)
== IDB_VALUE_PERSISTENT) {
err = STATUS_CMD_FAILED;
} else {
err = STATUS_WIRE_FAILED;
switch (sc->sbl.common.value & IDB_VALUE_STATUS_MASK) {
case IDB_VALUE_PASS:
status = STATUS_CMD_OK;
break;
case IDB_VALUE_FAIL:
case IDB_VALUE_PERSISTENT:
status = STATUS_CMD_FAILED;
break;
case IDB_VALUE_PHASE:
status = STATUS_WIRE_FAILED;
break;
}
sc->transfer_state = TSTATE_IDLE;
sc->transfer_cb(sc, sc->transfer_priv,
sc->transfer_datalen,
err);
sc->transfer_datalen - sc->transfer_actlen, status);
}
}
return;

View File

@ -1,4 +1,4 @@
/* $NetBSD: umass_quirks.c,v 1.51 2003/09/09 01:35:47 mycroft Exp $ */
/* $NetBSD: umass_quirks.c,v 1.52 2003/09/10 02:49:19 mycroft Exp $ */
/*
* Copyright (c) 2001 The NetBSD Foundation, Inc.
@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: umass_quirks.c,v 1.51 2003/09/09 01:35:47 mycroft Exp $");
__KERNEL_RCSID(0, "$NetBSD: umass_quirks.c,v 1.52 2003/09/10 02:49:19 mycroft Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -58,7 +58,6 @@ Static usbd_status umass_init_insystem(struct umass_softc *);
Static usbd_status umass_init_shuttle(struct umass_softc *);
Static void umass_fixup_sony(struct umass_softc *);
Static void umass_fixup_yedata(struct umass_softc *);
Static const struct umass_quirk umass_quirks[] = {
{ { USB_VENDOR_FUJIPHOTO, USB_PRODUCT_FUJIPHOTO_MASS0100 },
@ -142,22 +141,6 @@ Static const struct umass_quirk umass_quirks[] = {
NULL, umass_fixup_sony
},
{ { USB_VENDOR_SONY, USB_PRODUCT_SONY_MSC_U03 },
UMASS_WPROTO_CBI, UMASS_CPROTO_UFI,
0,
0,
UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO,
NULL, umass_fixup_sony
},
{ { USB_VENDOR_SONY, USB_PRODUCT_SONY_MSC },
UMASS_WPROTO_CBI, UMASS_CPROTO_UFI,
UMASS_QUIRK_FORCE_SHORT_INQUIRY | UMASS_QUIRK_RS_NO_CLEAR_UA,
0,
UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO,
NULL, NULL
},
{ { USB_VENDOR_YANO, USB_PRODUCT_YANO_U640MO },
UMASS_WPROTO_CBI_I, UMASS_CPROTO_ATAPI,
UMASS_QUIRK_FORCE_SHORT_INQUIRY,
@ -166,14 +149,6 @@ Static const struct umass_quirk umass_quirks[] = {
NULL, NULL
},
{ { USB_VENDOR_YEDATA, USB_PRODUCT_YEDATA_FLASHBUSTERU },
UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UFI,
UMASS_QUIRK_RS_NO_CLEAR_UA,
0,
UMATCH_VENDOR_PRODUCT_REV,
NULL, umass_fixup_yedata
},
{ { USB_VENDOR_GENESYS,USB_PRODUCT_GENESYS_GL641USB },
UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC,
UMASS_QUIRK_FORCE_SHORT_INQUIRY,
@ -232,26 +207,3 @@ umass_fixup_sony(struct umass_softc *sc)
sc->sc_cmd = UMASS_CPROTO_RBC;
}
}
Static void
umass_fixup_yedata(struct umass_softc *sc)
{
usb_device_descriptor_t *dd;
dd = usbd_get_device_descriptor(sc->sc_udev);
/*
* Revisions < 1.28 do not handle the interrupt endpoint very well.
*/
if (UGETW(dd->bcdDevice) < 0x128)
sc->sc_wire = UMASS_WPROTO_CBI;
else
sc->sc_wire = UMASS_WPROTO_CBI_I;
/*
* Revisions < 1.28 do not have the TEST UNIT READY command
* Revisions == 1.28 have a broken TEST UNIT READY
*/
if (UGETW(dd->bcdDevice) <= 0x128)
sc->sc_busquirks |= PQUIRK_NOTUR;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: umass_scsipi.c,v 1.10 2003/09/08 19:31:00 mycroft Exp $ */
/* $NetBSD: umass_scsipi.c,v 1.11 2003/09/10 02:49:19 mycroft Exp $ */
/*
* Copyright (c) 2001 The NetBSD Foundation, Inc.
@ -38,7 +38,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: umass_scsipi.c,v 1.10 2003/09/08 19:31:00 mycroft Exp $");
__KERNEL_RCSID(0, "$NetBSD: umass_scsipi.c,v 1.11 2003/09/10 02:49:19 mycroft Exp $");
#include "atapibus.h"
#include "scsibus.h"
@ -486,6 +486,7 @@ umass_scsipi_cb(struct umass_softc *sc, void *priv, int residue, int status)
/* FALLTHROUGH */
case STATUS_CMD_FAILED:
/* fetch sense data */
sc->sc_sense = 1;
memset(&scbus->sc_sense_cmd, 0, sizeof(scbus->sc_sense_cmd));
scbus->sc_sense_cmd.opcode = REQUEST_SENSE;
scbus->sc_sense_cmd.byte2 = periph->periph_lun <<
@ -534,20 +535,11 @@ umass_scsipi_sense_cb(struct umass_softc *sc, void *priv, int residue,
DPRINTF(UDMASS_CMD,("umass_scsipi_sense_cb: xs=%p residue=%d "
"status=%d\n", xs, residue, status));
sc->sc_sense = 0;
switch (status) {
case STATUS_CMD_OK:
case STATUS_CMD_UNKNOWN:
/* getting sense data succeeded */
if (xs->cmd->opcode == INQUIRY && (xs->resid < xs->datalen ||
(sc->sc_quirks & UMASS_QUIRK_RS_NO_CLEAR_UA /* XXX */))) {
/*
* Some drivers return SENSE errors even after INQUIRY.
* The upper layer doesn't like that.
*/
xs->error = XS_NOERROR;
break;
}
/* XXX look at residue */
if (residue == 0 || residue == 14)/* XXX */
xs->error = XS_SENSE;
else

View File

@ -1,4 +1,4 @@
/* $NetBSD: umassvar.h,v 1.20 2003/09/08 19:31:01 mycroft Exp $ */
/* $NetBSD: umassvar.h,v 1.21 2003/09/10 02:49:19 mycroft Exp $ */
/*-
* Copyright (c) 1999 MAEKAWA Masahide <bishop@rr.iij4u.or.jp>,
* Nick Hibma <n_hibma@freebsd.org>
@ -176,10 +176,9 @@ struct umass_softc {
#define UMASS_CPROTO_ISD_ATA 5
u_int32_t sc_quirks;
#define UMASS_QUIRK_RS_NO_CLEAR_UA 0x00000001
#define UMASS_QUIRK_FORCE_SHORT_INQUIRY 0x00000002
#define UMASS_QUIRK_WRONG_CSWSIG 0x00000004
#define UMASS_QUIRK_WRONG_CSWTAG 0x00000008
#define UMASS_QUIRK_FORCE_SHORT_INQUIRY 0x00000001
#define UMASS_QUIRK_WRONG_CSWSIG 0x00000002
#define UMASS_QUIRK_WRONG_CSWTAG 0x00000004
u_int32_t sc_busquirks;
@ -262,6 +261,7 @@ struct umass_softc {
int sc_xfer_flags;
char sc_dying;
int sc_refcnt;
int sc_sense;
struct umassbus_softc *bus; /* bus dependent data */
};