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:
parent
644a4857fb
commit
b8fd3dab7d
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue