From b8fd3dab7dd5b51926efb56a870fcb6437adaf9f Mon Sep 17 00:00:00 2001 From: mycroft Date: Wed, 10 Sep 2003 02:49:18 +0000 Subject: [PATCH] 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: 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: 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: disk removable --- sys/dev/usb/umass.c | 85 ++++++++++++++++++++------------------ sys/dev/usb/umass_quirks.c | 52 +---------------------- sys/dev/usb/umass_scsipi.c | 16 ++----- sys/dev/usb/umassvar.h | 10 ++--- 4 files changed, 55 insertions(+), 108 deletions(-) diff --git a/sys/dev/usb/umass.c b/sys/dev/usb/umass.c index 6973a02bcd70..6a7138363ff9 100644 --- a/sys/dev/usb/umass.c +++ b/sys/dev/usb/umass.c @@ -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 , * Nick Hibma @@ -94,7 +94,7 @@ */ #include -__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; diff --git a/sys/dev/usb/umass_quirks.c b/sys/dev/usb/umass_quirks.c index 8e4a0b8f3f59..f00beb0a700c 100644 --- a/sys/dev/usb/umass_quirks.c +++ b/sys/dev/usb/umass_quirks.c @@ -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 -__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 #include @@ -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; -} diff --git a/sys/dev/usb/umass_scsipi.c b/sys/dev/usb/umass_scsipi.c index 0c833ec5019d..2f703b71ce5c 100644 --- a/sys/dev/usb/umass_scsipi.c +++ b/sys/dev/usb/umass_scsipi.c @@ -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 -__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 diff --git a/sys/dev/usb/umassvar.h b/sys/dev/usb/umassvar.h index 1aa17430fa64..a30d23dcbae8 100644 --- a/sys/dev/usb/umassvar.h +++ b/sys/dev/usb/umassvar.h @@ -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 , * Nick Hibma @@ -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 */ };