Introduce the new umass quirk table.

Discussed with augustss.
This commit is contained in:
gehenna 2001-12-17 12:16:14 +00:00
parent 576463d9d3
commit 7cd101a6ca
6 changed files with 549 additions and 412 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: files.usb,v 1.32 2001/12/12 15:27:24 augustss Exp $ # $NetBSD: files.usb,v 1.33 2001/12/17 12:16:14 gehenna Exp $
# #
# Config file and device description for machine-independent USB code. # Config file and device description for machine-independent USB code.
# Included by ports that need it. Ports that use it must provide # Included by ports that need it. Ports that use it must provide
@ -83,6 +83,7 @@ device umass: scsi, atapi
attach umass at uhub attach umass at uhub
file dev/usb/umass.c umass file dev/usb/umass.c umass
file dev/usb/umassbus.c umass file dev/usb/umassbus.c umass
file dev/usb/umass_quirks.c umass
# IrDA bridges # IrDA bridges

View File

@ -1,4 +1,4 @@
/* $NetBSD: umass.c,v 1.77 2001/12/15 00:26:14 augustss Exp $ */ /* $NetBSD: umass.c,v 1.78 2001/12/17 12:16:14 gehenna Exp $ */
/*- /*-
* Copyright (c) 1999 MAEKAWA Masahide <bishop@rr.iij4u.or.jp>, * Copyright (c) 1999 MAEKAWA Masahide <bishop@rr.iij4u.or.jp>,
* Nick Hibma <n_hibma@freebsd.org> * Nick Hibma <n_hibma@freebsd.org>
@ -94,7 +94,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: umass.c,v 1.77 2001/12/15 00:26:14 augustss Exp $"); __KERNEL_RCSID(0, "$NetBSD: umass.c,v 1.78 2001/12/17 12:16:14 gehenna Exp $");
#include "atapibus.h" #include "atapibus.h"
@ -122,7 +122,7 @@ __KERNEL_RCSID(0, "$NetBSD: umass.c,v 1.77 2001/12/15 00:26:14 augustss Exp $");
#include <dev/usb/umassbus.h> #include <dev/usb/umassbus.h>
#include <dev/usb/umassvar.h> #include <dev/usb/umassvar.h>
#include <dev/usb/umass_quirks.h>
@ -156,10 +156,6 @@ char *states[TSTATE_STATES+1] = {
/* USB device probe/attach/detach functions */ /* USB device probe/attach/detach functions */
USB_DECLARE_DRIVER(umass); USB_DECLARE_DRIVER(umass);
Static void umass_disco(struct umass_softc *sc); Static void umass_disco(struct umass_softc *sc);
Static int umass_match_proto(struct umass_softc *sc,
usbd_interface_handle iface,
usbd_device_handle dev);
Static void umass_init_shuttle(struct umass_softc *sc);
/* generic transfer functions */ /* generic transfer functions */
Static usbd_status umass_setup_transfer(struct umass_softc *sc, Static usbd_status umass_setup_transfer(struct umass_softc *sc,
@ -219,268 +215,133 @@ Static void umass_dump_buffer(struct umass_softc *sc, u_int8_t *buffer,
* USB device probe/attach/detach * USB device probe/attach/detach
*/ */
/*
* Match the device we are seeing with the devices supported. Fill in the
* proto and drive fields in the softc accordingly.
* This function is called from both probe and attach.
*/
Static int
umass_match_proto(struct umass_softc *sc, usbd_interface_handle iface,
usbd_device_handle dev)
{
usb_device_descriptor_t *dd;
usb_interface_descriptor_t *id;
u_int vendor, product;
/*
* Fill in sc->drive and sc->proto and return a match
* value if both are determined and 0 otherwise.
*/
sc->drive = DRIVE_GENERIC;
sc->transfer_speed = UMASS_DEFAULT_TRANSFER_SPEED;
sc->sc_udev = dev;
dd = usbd_get_device_descriptor(dev);
vendor = UGETW(dd->idVendor);
product = UGETW(dd->idProduct);
if (vendor == USB_VENDOR_SHUTTLE &&
(product == USB_PRODUCT_SHUTTLE_EUSB ||
product == USB_PRODUCT_SHUTTLE_ZIOMMC)
) {
if (product == USB_PRODUCT_SHUTTLE_EUSB)
sc->drive = SHUTTLE_EUSB;
#if CBI_I
sc->wire_proto = WPROTO_CBI_I;
sc->cmd_proto = CPROTO_ATAPI;
#else
sc->wire_proto = WPROTO_CBI;
sc->cmd_proto = CPROTO_ATAPI;
#endif
sc->subclass = UISUBCLASS_SFF8020I;
sc->protocol = UIPROTO_MASS_CBI;
sc->quirks |= NO_TEST_UNIT_READY | NO_START_STOP;
return (UMATCH_VENDOR_PRODUCT);
}
if (vendor == USB_VENDOR_MICROTECH &&
product == USB_PRODUCT_MICROTECH_DPCM) {
sc->wire_proto = WPROTO_CBI;
sc->cmd_proto = CPROTO_ATAPI;
sc->subclass = UISUBCLASS_SFF8070I;
sc->protocol = UIPROTO_MASS_CBI;
sc->transfer_speed = UMASS_ZIP100_TRANSFER_SPEED * 2;
return (UMATCH_VENDOR_PRODUCT);
}
if (vendor == USB_VENDOR_YANO &&
product == USB_PRODUCT_YANO_U640MO) {
#if CBI_I
sc->wire_proto = WPROTO_CBI_I;
sc->cmd_proto = CPROTO_ATAPI;
#else
sc->wire_proto = WPROTO_CBI;
sc->cmd_proto = CPROTO_ATAPI;
#endif
sc->quirks |= FORCE_SHORT_INQUIRY;
return (UMATCH_VENDOR_PRODUCT);
}
if (vendor == USB_VENDOR_SONY &&
product == USB_PRODUCT_SONY_MSC) {
sc->quirks |= FORCE_SHORT_INQUIRY;
}
if (vendor == USB_VENDOR_YEDATA &&
product == USB_PRODUCT_YEDATA_FLASHBUSTERU) {
/* Revisions < 1.28 do not handle the interrupt endpoint
* very well.
*/
if (UGETW(dd->bcdDevice) < 0x128) {
sc->wire_proto = WPROTO_CBI;
sc->cmd_proto = CPROTO_UFI;
} else
#if CBI_I
sc->wire_proto = WPROTO_CBI_I;
sc->cmd_proto = CPROTO_UFI;
#else
sc->wire_proto = WPROTO_CBI;
sc->cmd_proto = CPROTO_UFI;
#endif
/*
* 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->quirks |= NO_TEST_UNIT_READY;
sc->subclass = UISUBCLASS_UFI;
sc->protocol = UIPROTO_MASS_CBI;
sc->quirks |= RS_NO_CLEAR_UA;
sc->transfer_speed = UMASS_FLOPPY_TRANSFER_SPEED;
return (UMATCH_VENDOR_PRODUCT_REV);
}
if (vendor == USB_VENDOR_INSYSTEM &&
product == USB_PRODUCT_INSYSTEM_USBCABLE) {
sc->drive = INSYSTEM_USBCABLE;
sc->wire_proto = WPROTO_CBI;
sc->cmd_proto = CPROTO_ATAPI;
sc->quirks |= NO_TEST_UNIT_READY | NO_START_STOP;
return (UMATCH_VENDOR_PRODUCT);
}
if (vendor == USB_VENDOR_IOMEGA &&
(product == USB_PRODUCT_IOMEGA_ZIP100 ||
product == USB_PRODUCT_IOMEGA_ZIP250)) {
sc->drive = ZIP_100;
sc->transfer_speed = UMASS_ZIP100_TRANSFER_SPEED;
sc->quirks |= NO_TEST_UNIT_READY;
}
if (vendor == USB_VENDOR_OLYMPUS &&
product == USB_PRODUCT_OLYMPUS_C1) {
/*
* The Olympus C-1 camera uses a different command-status
* signature.
*/
sc->quirks |= WRONG_CSWSIG;
}
if (UGETW(dd->idVendor) == USB_VENDOR_SCANLOGIC &&
UGETW(dd->idProduct) == USB_PRODUCT_SCANLOGIC_SL11R) {
/*
* ScanLogic SL11R IDE adapter claims to support
* SCSI, but really needs UFI.
* Note also that these devices need firmware > 0.71
*/
sc->cmd_proto &= ~CPROTO_SCSI;
sc->cmd_proto |= CPROTO_UFI;
}
id = usbd_get_interface_descriptor(iface);
if (id == NULL || id->bInterfaceClass != UICLASS_MASS)
return (UMATCH_NONE);
if (vendor == USB_VENDOR_SONY && id->bInterfaceSubClass == 0xff) {
/*
* Sony DSC devices set the sub class to 0xff
* instead of 1 (RBC). Fix that here.
*/
id->bInterfaceSubClass = UISUBCLASS_RBC;
/* They also should be able to do higher speed. */
sc->transfer_speed = 500;
}
if (vendor == USB_VENDOR_FUJIPHOTO &&
product == USB_PRODUCT_FUJIPHOTO_MASS0100)
sc->quirks |= NO_TEST_UNIT_READY | NO_START_STOP;
sc->subclass = id->bInterfaceSubClass;
sc->protocol = id->bInterfaceProtocol;
switch (sc->subclass) {
case UISUBCLASS_SCSI:
sc->cmd_proto = CPROTO_SCSI;
break;
case UISUBCLASS_UFI:
sc->transfer_speed = UMASS_FLOPPY_TRANSFER_SPEED;
sc->cmd_proto = CPROTO_UFI;
break;
case UISUBCLASS_SFF8020I:
case UISUBCLASS_SFF8070I:
case UISUBCLASS_QIC157:
sc->cmd_proto = CPROTO_ATAPI;
break;
case UISUBCLASS_RBC:
sc->cmd_proto = CPROTO_RBC;
break;
default:
DPRINTF(UDMASS_GEN, ("%s: Unsupported command protocol %d\n",
USBDEVNAME(sc->sc_dev), id->bInterfaceSubClass));
return (UMATCH_NONE);
}
switch (sc->protocol) {
case UIPROTO_MASS_CBI:
sc->wire_proto = WPROTO_CBI;
break;
case UIPROTO_MASS_CBI_I:
#if CBI_I
sc->wire_proto = WPROTO_CBI_I;
#else
sc->wire_proto = WPROTO_CBI;
#endif
break;
case UIPROTO_MASS_BBB:
case UIPROTO_MASS_BBB_OLD:
sc->wire_proto = WPROTO_BBB;
break;
default:
DPRINTF(UDMASS_GEN, ("%s: Unsupported wire protocol %d\n",
USBDEVNAME(sc->sc_dev), id->bInterfaceProtocol));
return (UMATCH_NONE);
}
return (UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO);
}
USB_MATCH(umass) USB_MATCH(umass)
{ {
USB_MATCH_START(umass, uaa); USB_MATCH_START(umass, uaa);
#if defined(__FreeBSD__) const struct umass_quirk *quirk;
struct umass_softc *sc = device_get_softc(self); usb_interface_descriptor_t *id;
#elif defined(__NetBSD__) || defined(__OpenBSD__)
struct umass_softc scs, *sc = &scs;
memset(sc, 0, sizeof *sc);
strcpy(sc->sc_dev.dv_xname, "umass");
#endif
if (uaa->iface == NULL) if (uaa->iface == NULL)
return(UMATCH_NONE); return (UMATCH_NONE);
return (umass_match_proto(sc, uaa->iface, uaa->device)); quirk = umass_lookup(uaa->vendor, uaa->product);
if (quirk != NULL)
return (quirk->uq_match);
id = usbd_get_interface_descriptor(uaa->iface);
if (id == NULL || id->bInterfaceClass != UICLASS_MASS)
return (UMATCH_NONE);
switch (id->bInterfaceSubClass) {
case UISUBCLASS_RBC:
case UISUBCLASS_SFF8020I:
case UISUBCLASS_QIC157:
case UISUBCLASS_UFI:
case UISUBCLASS_SFF8070I:
case UISUBCLASS_SCSI:
break;
default:
return (UMATCH_IFACECLASS);
}
switch (id->bInterfaceProtocol) {
case UIPROTO_MASS_CBI_I:
case UIPROTO_MASS_CBI:
case UIPROTO_MASS_BBB_OLD:
case UIPROTO_MASS_BBB:
break;
default:
return (UMATCH_IFACECLASS_IFACESUBCLASS);
}
return (UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO);
} }
USB_ATTACH(umass) USB_ATTACH(umass)
{ {
USB_ATTACH_START(umass, sc, uaa); USB_ATTACH_START(umass, sc, uaa);
const struct umass_quirk *quirk;
usb_interface_descriptor_t *id; usb_interface_descriptor_t *id;
usb_endpoint_descriptor_t *ed; usb_endpoint_descriptor_t *ed;
const char *sSubclass, *sProto; const char *sWire, *sCommand;
char devinfo[1024]; char devinfo[1024];
usbd_status err;
int i, bno; int i, bno;
int err;
/*
* the softc struct is bzero-ed in device_set_driver. We can safely
* call umass_detach without specifically initialising the struct.
*/
usbd_devinfo(uaa->device, 0, devinfo); usbd_devinfo(uaa->device, 0, devinfo);
USB_ATTACH_SETUP; USB_ATTACH_SETUP;
sc->sc_udev = uaa->device;
sc->sc_iface = uaa->iface; sc->sc_iface = uaa->iface;
sc->sc_ifaceno = uaa->ifaceno; sc->sc_ifaceno = uaa->ifaceno;
/* initialise the proto and drive values in the umass_softc (again) */ quirk = umass_lookup(uaa->vendor, uaa->product);
if (umass_match_proto(sc, sc->sc_iface, uaa->device) == 0) { if (quirk != NULL) {
printf("%s: match failed\n", USBDEVNAME(sc->sc_dev)); sc->sc_wire = quirk->uq_wire;
USB_ATTACH_ERROR_RETURN; sc->sc_cmd = quirk->uq_cmd;
sc->sc_quirks = quirk->uq_flags;
if (quirk->uq_fixup != NULL)
(*quirk->uq_fixup)(sc);
} else {
sc->sc_wire = UMASS_WPROTO_UNSPEC;
sc->sc_cmd = UMASS_CPROTO_UNSPEC;
sc->sc_quirks = 0;
} }
if (sc->drive == INSYSTEM_USBCABLE) { if (sc->transfer_speed == 0)
err = usbd_set_interface(sc->sc_iface, 1); sc->transfer_speed = UMASS_DEFAULT_TRANSFER_SPEED;
if (err) {
DPRINTF(UDMASS_USB, ("%s: could not switch to " id = usbd_get_interface_descriptor(sc->sc_iface);
"Alt Interface %d\n", if (id == NULL)
USBDEVNAME(sc->sc_dev), 1)); USB_ATTACH_ERROR_RETURN;
umass_disco(sc);
if (sc->sc_wire == UMASS_WPROTO_UNSPEC) {
switch (id->bInterfaceProtocol) {
case UIPROTO_MASS_CBI:
sc->sc_wire = UMASS_WPROTO_CBI;
break;
case UIPROTO_MASS_CBI_I:
sc->sc_wire = UMASS_WPROTO_CBI_I;
break;
case UIPROTO_MASS_BBB:
case UIPROTO_MASS_BBB_OLD:
sc->sc_wire = UMASS_WPROTO_BBB;
break;
default:
DPRINTF(UDMASS_GEN,
("%s: Unsupported wire protocol %u\n",
USBDEVNAME(sc->sc_dev),
id->bInterfaceProtocol));
USB_ATTACH_ERROR_RETURN;
}
}
/* 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:
sc->sc_cmd = UMASS_CPROTO_SCSI;
break;
case UISUBCLASS_UFI:
sc->sc_cmd = UMASS_CPROTO_UFI;
break;
case UISUBCLASS_SFF8020I:
case UISUBCLASS_SFF8070I:
case UISUBCLASS_QIC157:
sc->sc_cmd = UMASS_CPROTO_ATAPI;
break;
case UISUBCLASS_RBC:
sc->sc_cmd = UMASS_CPROTO_RBC;
break;
default:
DPRINTF(UDMASS_GEN,
("%s: Unsupported command protocol %u\n",
USBDEVNAME(sc->sc_dev),
id->bInterfaceSubClass));
USB_ATTACH_ERROR_RETURN; USB_ATTACH_ERROR_RETURN;
} }
} }
@ -497,49 +358,43 @@ USB_ATTACH(umass)
printf("%s: timeout=%d ms\n", USBDEVNAME(sc->sc_dev), sc->timeout); printf("%s: timeout=%d ms\n", USBDEVNAME(sc->sc_dev), sc->timeout);
#endif #endif
id = usbd_get_interface_descriptor(sc->sc_iface);
printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo); printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo);
switch (sc->subclass) { switch (sc->sc_wire) {
case UISUBCLASS_RBC: case UMASS_WPROTO_CBI:
sSubclass = "RBC"; sWire = "CBI";
break; break;
case UISUBCLASS_SCSI: case UMASS_WPROTO_CBI_I:
sSubclass = "SCSI"; sWire = "CBI with CCI";
break; break;
case UISUBCLASS_UFI: case UMASS_WPROTO_BBB:
sSubclass = "UFI"; sWire = "Bulk-Only";
break;
case UISUBCLASS_SFF8020I:
sSubclass = "SFF8020i";
break;
case UISUBCLASS_SFF8070I:
sSubclass = "SFF8070i";
break;
case UISUBCLASS_QIC157:
sSubclass = "QIC157";
break; break;
default: default:
sSubclass = "unknown"; sWire = "unknown";
break; break;
} }
switch (sc->protocol) {
case UIPROTO_MASS_CBI: switch (sc->sc_cmd) {
sProto = "CBI"; case UMASS_CPROTO_RBC:
sCommand = "RBC";
break; break;
case UIPROTO_MASS_CBI_I: case UMASS_CPROTO_SCSI:
sProto = "CBI-I"; sCommand = "SCSI";
break; break;
case UIPROTO_MASS_BBB: case UMASS_CPROTO_UFI:
case UIPROTO_MASS_BBB_OLD: sCommand = "UFI";
sProto = "BBB"; break;
case UMASS_CPROTO_ATAPI:
sCommand = "ATAPI";
break; break;
default: default:
sProto = "unknown"; sCommand = "unknown";
break; break;
} }
printf("%s: using %s over %s\n", USBDEVNAME(sc->sc_dev), sSubclass,
sProto); printf("%s: using %s over %s\n", USBDEVNAME(sc->sc_dev), sCommand,
sWire);
/* /*
* In addition to the Control endpoint the following endpoints * In addition to the Control endpoint the following endpoints
@ -554,7 +409,7 @@ USB_ATTACH(umass)
*/ */
for (i = 0 ; i < id->bNumEndpoints ; i++) { for (i = 0 ; i < id->bNumEndpoints ; i++) {
ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i); ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
if (!ed) { if (ed == NULL) {
printf("%s: could not read endpoint descriptor\n", printf("%s: could not read endpoint descriptor\n",
USBDEVNAME(sc->sc_dev)); USBDEVNAME(sc->sc_dev));
USB_ATTACH_ERROR_RETURN; USB_ATTACH_ERROR_RETURN;
@ -565,7 +420,7 @@ USB_ATTACH(umass)
} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT
&& (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) { && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) {
sc->sc_epaddr[UMASS_BULKOUT] = ed->bEndpointAddress; sc->sc_epaddr[UMASS_BULKOUT] = ed->bEndpointAddress;
} else if (sc->wire_proto == WPROTO_CBI_I } else if (sc->sc_wire == UMASS_WPROTO_CBI_I
&& UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN
&& (ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT) { && (ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT) {
sc->sc_epaddr[UMASS_INTRIN] = ed->bEndpointAddress; sc->sc_epaddr[UMASS_INTRIN] = ed->bEndpointAddress;
@ -581,19 +436,19 @@ USB_ATTACH(umass)
/* check whether we found all the endpoints we need */ /* check whether we found all the endpoints we need */
if (!sc->sc_epaddr[UMASS_BULKIN] || !sc->sc_epaddr[UMASS_BULKOUT] || if (!sc->sc_epaddr[UMASS_BULKIN] || !sc->sc_epaddr[UMASS_BULKOUT] ||
(sc->wire_proto == WPROTO_CBI_I && !sc->sc_epaddr[UMASS_INTRIN]) ) { (sc->sc_wire == UMASS_WPROTO_CBI_I &&
!sc->sc_epaddr[UMASS_INTRIN])) {
DPRINTF(UDMASS_USB, ("%s: endpoint not found %u/%u/%u\n", DPRINTF(UDMASS_USB, ("%s: endpoint not found %u/%u/%u\n",
USBDEVNAME(sc->sc_dev), sc->sc_epaddr[UMASS_BULKIN], USBDEVNAME(sc->sc_dev), sc->sc_epaddr[UMASS_BULKIN],
sc->sc_epaddr[UMASS_BULKOUT], sc->sc_epaddr[UMASS_BULKOUT],
sc->sc_epaddr[UMASS_INTRIN])); sc->sc_epaddr[UMASS_INTRIN]));
umass_disco(sc);
USB_ATTACH_ERROR_RETURN; USB_ATTACH_ERROR_RETURN;
} }
/* /*
* Get the maximum LUN supported by the device. * Get the maximum LUN supported by the device.
*/ */
if (sc->wire_proto == WPROTO_BBB) { if (sc->sc_wire == UMASS_WPROTO_BBB) {
err = umass_bbb_get_max_lun(sc, &sc->maxlun); err = umass_bbb_get_max_lun(sc, &sc->maxlun);
if (err) { if (err) {
printf("%s: unable to get Max Lun: %s\n", printf("%s: unable to get Max Lun: %s\n",
@ -634,7 +489,7 @@ USB_ATTACH(umass)
* code for handling the data on that endpoint simpler. No data * code for handling the data on that endpoint simpler. No data
* arriving concurrently. * arriving concurrently.
*/ */
if (sc->wire_proto == WPROTO_CBI_I) { if (sc->sc_wire == UMASS_WPROTO_CBI_I) {
err = usbd_open_pipe(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]); USBD_EXCLUSIVE_USE, &sc->sc_pipe[UMASS_INTRIN]);
if (err) { if (err) {
@ -660,14 +515,14 @@ USB_ATTACH(umass)
} }
} }
/* Allocate buffer for data transfer (it's huge). */ /* Allocate buffer for data transfer (it's huge). */
switch (sc->wire_proto) { switch (sc->sc_wire) {
case WPROTO_BBB: case UMASS_WPROTO_BBB:
bno = XFER_BBB_DATA; bno = XFER_BBB_DATA;
goto dalloc; goto dalloc;
case WPROTO_CBI: case UMASS_WPROTO_CBI:
bno = XFER_CBI_DATA; bno = XFER_CBI_DATA;
goto dalloc; goto dalloc;
case WPROTO_CBI_I: case UMASS_WPROTO_CBI_I:
bno = XFER_CBI_DATA; bno = XFER_CBI_DATA;
dalloc: dalloc:
sc->data_buffer = usbd_alloc_buffer(sc->transfer_xfer[bno], sc->data_buffer = usbd_alloc_buffer(sc->transfer_xfer[bno],
@ -682,20 +537,26 @@ USB_ATTACH(umass)
} }
/* Initialise the wire protocol specific methods */ /* Initialise the wire protocol specific methods */
if (sc->wire_proto == WPROTO_BBB) { switch (sc->sc_wire) {
case UMASS_WPROTO_BBB:
sc->sc_methods = &umass_bbb_methods; sc->sc_methods = &umass_bbb_methods;
} else if (sc->wire_proto == WPROTO_CBI || break;
sc->wire_proto == WPROTO_CBI_I) { case UMASS_WPROTO_CBI:
case UMASS_WPROTO_CBI_I:
sc->sc_methods = &umass_cbi_methods; sc->sc_methods = &umass_cbi_methods;
#ifdef UMASS_DEBUG break;
} else { default:
panic("%s:%d: Unknown wire proto 0x%02x\n", umass_disco(sc);
__FILE__, __LINE__, sc->wire_proto); USB_ATTACH_ERROR_RETURN;
#endif
} }
if (sc->drive == SHUTTLE_EUSB) if (quirk != NULL && quirk->uq_init != NULL) {
umass_init_shuttle(sc); err = (*quirk->uq_init)(sc);
if (err) {
umass_disco(sc);
USB_ATTACH_ERROR_RETURN;
}
}
if (umass_attach_bus(sc)) { if (umass_attach_bus(sc)) {
DPRINTF(UDMASS_GEN, ("%s: bus attach failed\n", DPRINTF(UDMASS_GEN, ("%s: bus attach failed\n",
@ -766,21 +627,6 @@ umass_disco(struct umass_softc *sc)
} }
} }
Static void
umass_init_shuttle(struct umass_softc *sc)
{
usb_device_request_t req;
u_char status[2];
/* The Linux driver does this */
req.bmRequestType = UT_READ_VENDOR_DEVICE;
req.bRequest = 1;
USETW(req.wValue, 0);
USETW(req.wIndex, sc->sc_ifaceno);
USETW(req.wLength, sizeof status);
(void)usbd_do_request(sc->sc_udev, &req, &status);
}
/* /*
* Generic functions to handle transfers * Generic functions to handle transfers
*/ */
@ -852,12 +698,12 @@ umass_clear_endpoint_stall(struct umass_softc *sc, int endpt,
usbd_clear_endpoint_toggle(sc->sc_pipe[endpt]); usbd_clear_endpoint_toggle(sc->sc_pipe[endpt]);
sc->request.bmRequestType = UT_WRITE_ENDPOINT; sc->sc_req.bmRequestType = UT_WRITE_ENDPOINT;
sc->request.bRequest = UR_CLEAR_FEATURE; sc->sc_req.bRequest = UR_CLEAR_FEATURE;
USETW(sc->request.wValue, UF_ENDPOINT_HALT); USETW(sc->sc_req.wValue, UF_ENDPOINT_HALT);
USETW(sc->request.wIndex, sc->sc_epaddr[endpt]); USETW(sc->sc_req.wIndex, sc->sc_epaddr[endpt]);
USETW(sc->request.wLength, 0); USETW(sc->sc_req.wLength, 0);
umass_setup_ctrl_transfer(sc, &sc->request, NULL, 0, 0, xfer); umass_setup_ctrl_transfer(sc, &sc->sc_req, NULL, 0, 0, xfer);
} }
#if 0 #if 0
@ -879,8 +725,9 @@ umass_reset(struct umass_softc *sc, transfer_cb_f cb, void *priv)
Static void Static void
umass_bbb_reset(struct umass_softc *sc, int status) umass_bbb_reset(struct umass_softc *sc, int status)
{ {
KASSERT(sc->proto & PROTO_BBB, KASSERT(sc->sc_wire & UMASS_WPROTO_BBB,
("sc->proto == 0x%02x wrong for umass_bbb_reset\n", sc->proto)); ("sc->sc_wire == 0x%02x wrong for umass_bbb_reset\n",
sc->sc_wire));
if (sc->sc_dying) if (sc->sc_dying)
return; return;
@ -908,12 +755,12 @@ umass_bbb_reset(struct umass_softc *sc, int status)
sc->transfer_status = status; sc->transfer_status = status;
/* reset is a class specific interface write */ /* reset is a class specific interface write */
sc->request.bmRequestType = UT_WRITE_CLASS_INTERFACE; sc->sc_req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
sc->request.bRequest = UR_BBB_RESET; sc->sc_req.bRequest = UR_BBB_RESET;
USETW(sc->request.wValue, 0); USETW(sc->sc_req.wValue, 0);
USETW(sc->request.wIndex, sc->sc_ifaceno); USETW(sc->sc_req.wIndex, sc->sc_ifaceno);
USETW(sc->request.wLength, 0); USETW(sc->sc_req.wLength, 0);
umass_setup_ctrl_transfer(sc, &sc->request, NULL, 0, 0, umass_setup_ctrl_transfer(sc, &sc->sc_req, NULL, 0, 0,
sc->transfer_xfer[XFER_BBB_RESET1]); sc->transfer_xfer[XFER_BBB_RESET1]);
} }
@ -927,9 +774,9 @@ umass_bbb_transfer(struct umass_softc *sc, int lun, void *cmd, int cmdlen,
DPRINTF(UDMASS_BBB,("%s: umass_bbb_transfer cmd=0x%02x\n", DPRINTF(UDMASS_BBB,("%s: umass_bbb_transfer cmd=0x%02x\n",
USBDEVNAME(sc->sc_dev), *(u_char*)cmd)); USBDEVNAME(sc->sc_dev), *(u_char*)cmd));
KASSERT(sc->proto & PROTO_BBB, KASSERT(sc->sc_wire & UMASS_WPROTO_BBB,
("sc->proto == 0x%02x wrong for umass_bbb_transfer\n", ("sc->sc_wire == 0x%02x wrong for umass_bbb_transfer\n",
sc->proto)); sc->sc_wire));
/* Be a little generous. */ /* Be a little generous. */
sc->timeout = timeout + USBD_DEFAULT_TIMEOUT; sc->timeout = timeout + USBD_DEFAULT_TIMEOUT;
@ -1036,8 +883,9 @@ umass_bbb_state(usbd_xfer_handle xfer, usbd_private_handle priv,
struct umass_softc *sc = (struct umass_softc *) priv; struct umass_softc *sc = (struct umass_softc *) priv;
usbd_xfer_handle next_xfer; usbd_xfer_handle next_xfer;
KASSERT(sc->proto & PROTO_BBB, KASSERT(sc->sc_wire & UMASS_WPROTO_BBB,
("sc->proto == 0x%02x wrong for umass_bbb_state\n",sc->proto)); ("sc->sc_wire == 0x%02x wrong for umass_bbb_state\n",
sc->sc_wire));
if (sc->sc_dying) if (sc->sc_dying)
return; return;
@ -1206,7 +1054,7 @@ umass_bbb_state(usbd_xfer_handle xfer, usbd_private_handle priv,
DIF(UDMASS_BBB, umass_bbb_dump_csw(sc, &sc->csw)); DIF(UDMASS_BBB, umass_bbb_dump_csw(sc, &sc->csw));
/* Translate weird command-status signatures. */ /* Translate weird command-status signatures. */
if ((sc->quirks & WRONG_CSWSIG) && if ((sc->sc_quirks & UMASS_QUIRK_WRONG_CSWSIG) &&
UGETDW(sc->csw.dCSWSignature) == CSWSIGNATURE_OLYMPUS_C1) UGETDW(sc->csw.dCSWSignature) == CSWSIGNATURE_OLYMPUS_C1)
USETDW(sc->csw.dCSWSignature, CSWSIGNATURE); USETDW(sc->csw.dCSWSignature, CSWSIGNATURE);
@ -1339,15 +1187,16 @@ Static int
umass_cbi_adsc(struct umass_softc *sc, char *buffer, int buflen, umass_cbi_adsc(struct umass_softc *sc, char *buffer, int buflen,
usbd_xfer_handle xfer) usbd_xfer_handle xfer)
{ {
KASSERT(sc->proto & (PROTO_CBI|PROTO_CBI_I), KASSERT(sc->sc_wire & (UMASS_WPROTO_CBI|UMASS_WPROTO_CBI_I),
("sc->proto == 0x%02x wrong for umass_cbi_adsc\n",sc->proto)); ("sc->sc_wire == 0x%02x wrong for umass_cbi_adsc\n",
sc->sc_wire));
sc->request.bmRequestType = UT_WRITE_CLASS_INTERFACE; sc->sc_req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
sc->request.bRequest = UR_CBI_ADSC; sc->sc_req.bRequest = UR_CBI_ADSC;
USETW(sc->request.wValue, 0); USETW(sc->sc_req.wValue, 0);
USETW(sc->request.wIndex, sc->sc_ifaceno); USETW(sc->sc_req.wIndex, sc->sc_ifaceno);
USETW(sc->request.wLength, buflen); USETW(sc->sc_req.wLength, buflen);
return umass_setup_ctrl_transfer(sc, &sc->request, buffer, return umass_setup_ctrl_transfer(sc, &sc->sc_req, buffer,
buflen, 0, xfer); buflen, 0, xfer);
} }
@ -1358,8 +1207,9 @@ umass_cbi_reset(struct umass_softc *sc, int status)
int i; int i;
# define SEND_DIAGNOSTIC_CMDLEN 12 # define SEND_DIAGNOSTIC_CMDLEN 12
KASSERT(sc->proto & (PROTO_CBI|PROTO_CBI_I), KASSERT(sc->sc_wire & (UMASS_WPROTO_CBI|UMASS_WPROTO_CBI_I),
("sc->proto == 0x%02x wrong for umass_cbi_reset\n",sc->proto)); ("sc->sc_wire == 0x%02x wrong for umass_cbi_reset\n",
sc->sc_wire));
if (sc->sc_dying) if (sc->sc_dying)
return; return;
@ -1411,9 +1261,9 @@ umass_cbi_transfer(struct umass_softc *sc, int lun,
DPRINTF(UDMASS_CBI,("%s: umass_cbi_transfer cmd=0x%02x, len=%d\n", DPRINTF(UDMASS_CBI,("%s: umass_cbi_transfer cmd=0x%02x, len=%d\n",
USBDEVNAME(sc->sc_dev), *(u_char*)cmd, datalen)); USBDEVNAME(sc->sc_dev), *(u_char*)cmd, datalen));
KASSERT(sc->proto & (PROTO_CBI|PROTO_CBI_I), KASSERT(sc->sc_wire & (UMASS_WPROTO_CBI|UMASS_WPROTO_CBI_I),
("sc->proto == 0x%02x wrong for umass_cbi_transfer\n", ("sc->sc_wire == 0x%02x wrong for umass_cbi_transfer\n",
sc->proto)); sc->sc_wire));
if (sc->sc_dying) if (sc->sc_dying)
return; return;
@ -1468,8 +1318,9 @@ umass_cbi_state(usbd_xfer_handle xfer, usbd_private_handle priv,
{ {
struct umass_softc *sc = (struct umass_softc *) priv; struct umass_softc *sc = (struct umass_softc *) priv;
KASSERT(sc->proto & (PROTO_CBI|PROTO_CBI_I), KASSERT(sc->sc_wire & (UMASS_WPROTO_CBI|UMASS_WPROTO_CBI_I),
("sc->proto == 0x%02x wrong for umass_cbi_state\n", sc->proto)); ("sc->sc_wire == 0x%02x wrong for umass_cbi_state\n",
sc->sc_wire));
if (sc->sc_dying) if (sc->sc_dying)
return; return;
@ -1529,7 +1380,7 @@ umass_cbi_state(usbd_xfer_handle xfer, usbd_private_handle priv,
sc->transfer_xfer[XFER_CBI_DATA])) sc->transfer_xfer[XFER_CBI_DATA]))
umass_cbi_reset(sc, STATUS_WIRE_FAILED); umass_cbi_reset(sc, STATUS_WIRE_FAILED);
} else if (sc->wire_proto == WPROTO_CBI_I) { } else if (sc->sc_wire == UMASS_WPROTO_CBI_I) {
DPRINTF(UDMASS_CBI, ("%s: no data phase\n", DPRINTF(UDMASS_CBI, ("%s: no data phase\n",
USBDEVNAME(sc->sc_dev))); USBDEVNAME(sc->sc_dev)));
sc->transfer_state = TSTATE_CBI_STATUS; sc->transfer_state = TSTATE_CBI_STATUS;
@ -1582,7 +1433,7 @@ umass_cbi_state(usbd_xfer_handle xfer, usbd_private_handle priv,
umass_dump_buffer(sc, sc->transfer_data, umass_dump_buffer(sc, sc->transfer_data,
sc->transfer_actlen, 48)); sc->transfer_actlen, 48));
if (sc->wire_proto == WPROTO_CBI_I) { if (sc->sc_wire == UMASS_WPROTO_CBI_I) {
sc->transfer_state = TSTATE_CBI_STATUS; sc->transfer_state = TSTATE_CBI_STATUS;
memset(&sc->sbl, 0, sizeof(sc->sbl)); memset(&sc->sbl, 0, sizeof(sc->sbl));
if (umass_setup_transfer(sc, sc->sc_pipe[UMASS_INTRIN], if (umass_setup_transfer(sc, sc->sc_pipe[UMASS_INTRIN],
@ -1621,7 +1472,7 @@ umass_cbi_state(usbd_xfer_handle xfer, usbd_private_handle priv,
/* Dissect the information in the buffer */ /* Dissect the information in the buffer */
if (sc->cmd_proto == CPROTO_UFI) { if (sc->sc_cmd == UMASS_CPROTO_UFI) {
int status; int status;
/* Section 3.4.3.1.3 specifies that the UFI command /* Section 3.4.3.1.3 specifies that the UFI command

252
sys/dev/usb/umass_quirks.c Normal file
View File

@ -0,0 +1,252 @@
/* $NetBSD: umass_quirks.c,v 1.1 2001/12/17 12:16:15 gehenna Exp $ */
/*
* Copyright (c) 2001 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by MAEKAWA Masahide (gehenna@NetBSD.org).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/buf.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
#include <dev/usb/usbdevs.h>
#include <dev/usb/umassbus.h>
#include <dev/usb/umassvar.h>
#include <dev/usb/umass_quirks.h>
Static usbd_status umass_init_insystem(struct umass_softc *);
Static usbd_status umass_init_shuttle(struct umass_softc *);
Static void umass_fixup_iomega(struct umass_softc *);
Static void umass_fixup_microtech(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 },
UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC,
UMASS_QUIRK_NO_TEST_UNIT_READY | UMASS_QUIRK_NO_START_STOP,
UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO,
NULL, NULL
},
{ { USB_VENDOR_INSYSTEM, USB_PRODUCT_INSYSTEM_USBCABLE },
UMASS_WPROTO_CBI, UMASS_CPROTO_ATAPI,
UMASS_QUIRK_NO_TEST_UNIT_READY | UMASS_QUIRK_NO_START_STOP,
UMATCH_VENDOR_PRODUCT,
umass_init_insystem, NULL
},
{ { USB_VENDOR_IOMEGA, USB_PRODUCT_IOMEGA_ZIP100 },
UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC,
UMASS_QUIRK_NO_TEST_UNIT_READY,
UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO,
NULL, umass_fixup_iomega
},
{ { USB_VENDOR_IOMEGA, USB_PRODUCT_IOMEGA_ZIP250 },
UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC,
UMASS_QUIRK_NO_TEST_UNIT_READY,
UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO,
NULL, umass_fixup_iomega
},
{ { USB_VENDOR_MICROTECH, USB_PRODUCT_MICROTECH_DPCM },
UMASS_WPROTO_CBI, UMASS_CPROTO_ATAPI,
0,
UMATCH_VENDOR_PRODUCT,
NULL, umass_fixup_microtech
},
{ { USB_VENDOR_OLYMPUS, USB_PRODUCT_OLYMPUS_C1 },
UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC,
UMASS_QUIRK_WRONG_CSWSIG,
UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO,
NULL, NULL
},
{ { USB_VENDOR_SCANLOGIC, USB_PRODUCT_SCANLOGIC_SL11R },
UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UFI,
0,
UMATCH_VENDOR_PRODUCT,
NULL, NULL
},
{ { USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_EUSB },
UMASS_WPROTO_CBI_I, UMASS_CPROTO_ATAPI,
UMASS_QUIRK_NO_TEST_UNIT_READY | UMASS_QUIRK_NO_START_STOP,
UMATCH_VENDOR_PRODUCT,
umass_init_shuttle, NULL
},
{ { USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_ZIOMMC },
UMASS_WPROTO_CBI_I, UMASS_CPROTO_ATAPI,
UMASS_QUIRK_NO_TEST_UNIT_READY | UMASS_QUIRK_NO_START_STOP,
UMATCH_VENDOR_PRODUCT,
NULL, NULL
},
{ { USB_VENDOR_SONY, USB_PRODUCT_SONY_MSC },
UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC,
UMASS_QUIRK_FORCE_SHORT_INQUIRY,
UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO,
NULL, umass_fixup_sony
},
{ { USB_VENDOR_SONY, USB_PRODUCT_ANY },
UMASS_WPROTO_UNSPEC, UMASS_CPROTO_RBC,
0,
UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO,
NULL, umass_fixup_sony
},
{ { USB_VENDOR_YANO, USB_PRODUCT_YANO_U640MO },
UMASS_WPROTO_CBI_I, UMASS_CPROTO_ATAPI,
UMASS_QUIRK_FORCE_SHORT_INQUIRY,
UMATCH_VENDOR_PRODUCT,
NULL, NULL
},
{ { USB_VENDOR_YEDATA, USB_PRODUCT_YEDATA_FLASHBUSTERU },
UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UFI,
UMASS_QUIRK_RS_NO_CLEAR_UA,
UMATCH_VENDOR_PRODUCT_REV,
NULL, umass_fixup_yedata
},
};
const struct umass_quirk *
umass_lookup(u_int16_t vendor, u_int16_t product)
{
const struct usb_devno *udev;
int n, i;
n = sizeof(umass_quirks) / sizeof(umass_quirks[0]);
udev = usb_match_device((const struct usb_devno *)umass_quirks, n,
sizeof(struct umass_quirk), vendor, product);
if (udev != NULL)
return ((const struct umass_quirk *)udev);
for (i = 0 ; i < n ; i++) {
if (umass_quirks[i].uq_dev.ud_vendor == vendor &&
umass_quirks[i].uq_dev.ud_product == USB_PRODUCT_ANY)
return (&umass_quirks[i]);
}
return (NULL);
}
Static usbd_status
umass_init_insystem(struct umass_softc *sc)
{
usbd_status err;
err = usbd_set_interface(sc->sc_iface, 1);
if (err) {
DPRINTF(UDMASS_USB,
("%s: could not switch to Alt Interface 1\n",
USBDEVNAME(sc->sc_dev)));
return (err);
}
return (USBD_NORMAL_COMPLETION);
}
Static usbd_status
umass_init_shuttle(struct umass_softc *sc)
{
usb_device_request_t req;
u_int8_t status[2];
/* The Linux driver does this */
req.bmRequestType = UT_READ_VENDOR_DEVICE;
req.bRequest = 1;
USETW(req.wValue, 0);
USETW(req.wIndex, sc->sc_ifaceno);
USETW(req.wLength, sizeof(status));
return (usbd_do_request(sc->sc_udev, &req, &status));
}
Static void
umass_fixup_iomega(struct umass_softc *sc)
{
sc->transfer_speed = UMASS_ZIP100_TRANSFER_SPEED;
}
Static void
umass_fixup_microtech(struct umass_softc *sc)
{
sc->transfer_speed = UMASS_ZIP100_TRANSFER_SPEED * 2;
}
Static void
umass_fixup_sony(struct umass_softc *sc)
{
usb_interface_descriptor_t *id;
id = usbd_get_interface_descriptor(sc->sc_iface);
if (id->bInterfaceSubClass == 0xff) {
sc->sc_cmd = UMASS_CPROTO_RBC;
sc->transfer_speed = 500;
}
}
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_quirks |= UMASS_QUIRK_NO_TEST_UNIT_READY;
}

View File

@ -0,0 +1,61 @@
/* $NetBSD: umass_quirks.h,v 1.1 2001/12/17 12:16:15 gehenna Exp $ */
/*
* Copyright (c) 2001 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by MAEKAWA Masahide (gehenna@NetBSD.org).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _DEV_USB_UMASS_QUIRKS_H_
#define _DEV_USB_UMASS_QUIRKS_H_
typedef usbd_status (*umass_init_quirk)(struct umass_softc *);
typedef void (*umass_fixup_quirk)(struct umass_softc *);
struct umass_quirk {
struct usb_devno uq_dev;
#define USB_PRODUCT_ANY 0xffff /* XXX */
u_int8_t uq_wire;
u_int8_t uq_cmd;
u_int32_t uq_flags;
int uq_match;
umass_init_quirk uq_init;
umass_fixup_quirk uq_fixup;
};
const struct umass_quirk *umass_lookup(u_int16_t, u_int16_t);
#endif /* _DEV_USB_UMASS_QUIRKS_H_ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: umassbus.c,v 1.16 2001/12/14 08:46:20 gehenna Exp $ */ /* $NetBSD: umassbus.c,v 1.17 2001/12/17 12:16:15 gehenna Exp $ */
/* /*
* Copyright (c) 2001 The NetBSD Foundation, Inc. * Copyright (c) 2001 The NetBSD Foundation, Inc.
@ -38,7 +38,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: umassbus.c,v 1.16 2001/12/14 08:46:20 gehenna Exp $"); __KERNEL_RCSID(0, "$NetBSD: umassbus.c,v 1.17 2001/12/17 12:16:15 gehenna Exp $");
#include "atapibus.h" #include "atapibus.h"
#include "scsibus.h" #include "scsibus.h"
@ -123,9 +123,9 @@ umass_attach_bus(struct umass_softc *sc)
sc->bus.sc_channel.chan_max_periph = 1; sc->bus.sc_channel.chan_max_periph = 1;
switch (sc->cmd_proto) { switch (sc->sc_cmd) {
case CPROTO_RBC: case UMASS_CPROTO_RBC:
case CPROTO_SCSI: case UMASS_CPROTO_SCSI:
#if NSCSIBUS > 0 #if NSCSIBUS > 0
sc->bus.sc_channel.chan_bustype = &scsi_bustype; sc->bus.sc_channel.chan_bustype = &scsi_bustype;
sc->bus.sc_channel.chan_ntargets = UMASS_SCSIID_DEVICE + 1; sc->bus.sc_channel.chan_ntargets = UMASS_SCSIID_DEVICE + 1;
@ -140,14 +140,14 @@ umass_attach_bus(struct umass_softc *sc)
#endif #endif
break; break;
case CPROTO_UFI: case UMASS_CPROTO_UFI:
case CPROTO_ATAPI: case UMASS_CPROTO_ATAPI:
#if NATAPIBUS > 0 #if NATAPIBUS > 0
sc->bus.sc_channel.chan_bustype = &umass_atapi_bustype; sc->bus.sc_channel.chan_bustype = &umass_atapi_bustype;
sc->bus.sc_channel.chan_ntargets = 2; sc->bus.sc_channel.chan_ntargets = 2;
sc->bus.sc_channel.chan_nluns = 1; sc->bus.sc_channel.chan_nluns = 1;
if (sc->quirks & NO_TEST_UNIT_READY) if (sc->sc_quirks & UMASS_QUIRK_NO_TEST_UNIT_READY)
sc->bus.sc_channel.chan_defquirks |= PQUIRK_NOTUR; sc->bus.sc_channel.chan_defquirks |= PQUIRK_NOTUR;
DPRINTF(UDMASS_USB, ("%s: umass_attach_bus: ATAPI\n", DPRINTF(UDMASS_USB, ("%s: umass_attach_bus: ATAPI\n",
USBDEVNAME(sc->sc_dev))); USBDEVNAME(sc->sc_dev)));
@ -160,7 +160,7 @@ umass_attach_bus(struct umass_softc *sc)
default: default:
printf("%s: cmd proto=0x%x not supported yet\n", printf("%s: cmd proto=0x%x not supported yet\n",
USBDEVNAME(sc->sc_dev), sc->cmd_proto); USBDEVNAME(sc->sc_dev), sc->sc_cmd);
return (1); return (1);
} }
@ -288,14 +288,14 @@ umass_scsipi_request(struct scsipi_channel *chan,
/* XXX should use transform */ /* XXX should use transform */
if (cmd->opcode == START_STOP && if (cmd->opcode == START_STOP &&
(sc->quirks & NO_START_STOP)) { (sc->sc_quirks & UMASS_QUIRK_NO_START_STOP)) {
/*printf("%s: START_STOP\n", USBDEVNAME(sc->sc_dev));*/ /*printf("%s: START_STOP\n", USBDEVNAME(sc->sc_dev));*/
xs->error = XS_NOERROR; xs->error = XS_NOERROR;
goto done; goto done;
} }
if (cmd->opcode == INQUIRY && if (cmd->opcode == INQUIRY &&
(sc->quirks & FORCE_SHORT_INQUIRY)) { (sc->sc_quirks & UMASS_QUIRK_FORCE_SHORT_INQUIRY)) {
/* /*
* some drives wedge when asked for full inquiry * some drives wedge when asked for full inquiry
* information. * information.
@ -413,7 +413,7 @@ umass_scsipi_getgeom(struct scsipi_periph *periph, struct disk_parms *dp,
(void *)periph->periph_channel->chan_adapter->adapt_dev; (void *)periph->periph_channel->chan_adapter->adapt_dev;
/* If it's not a floppy, we don't know what to do. */ /* If it's not a floppy, we don't know what to do. */
if (sc->cmd_proto != CPROTO_UFI) if (sc->sc_cmd != UMASS_CPROTO_UFI)
return (0); return (0);
switch (sectors) { switch (sectors) {
@ -468,7 +468,7 @@ umass_scsipi_cb(struct umass_softc *sc, void *priv, int residue, int status)
sc->bus.sc_sense_cmd.length = sizeof(xs->sense); sc->bus.sc_sense_cmd.length = sizeof(xs->sense);
cmdlen = sizeof(sc->bus.sc_sense_cmd); cmdlen = sizeof(sc->bus.sc_sense_cmd);
if (sc->cmd_proto == CPROTO_UFI) /* XXX */ if (sc->sc_cmd == UMASS_CPROTO_UFI) /* XXX */
cmdlen = UFI_COMMAND_LENGTH; cmdlen = UFI_COMMAND_LENGTH;
sc->sc_methods->wire_xfer(sc, periph->periph_lun, sc->sc_methods->wire_xfer(sc, periph->periph_lun,
&sc->bus.sc_sense_cmd, cmdlen, &sc->bus.sc_sense_cmd, cmdlen,
@ -513,8 +513,8 @@ umass_scsipi_sense_cb(struct umass_softc *sc, void *priv, int residue,
case STATUS_CMD_OK: case STATUS_CMD_OK:
case STATUS_CMD_UNKNOWN: case STATUS_CMD_UNKNOWN:
/* getting sense data succeeded */ /* getting sense data succeeded */
if (xs->cmd->opcode == INQUIRY && (xs->resid < xs->datalen if (xs->cmd->opcode == INQUIRY && (xs->resid < xs->datalen ||
|| ((sc->quirks & RS_NO_CLEAR_UA) /* XXX */) )) { (sc->sc_quirks & UMASS_QUIRK_RS_NO_CLEAR_UA /* XXX */))) {
/* /*
* Some drivers return SENSE errors even after INQUIRY. * Some drivers return SENSE errors even after INQUIRY.
* The upper layer doesn't like that. * The upper layer doesn't like that.

View File

@ -1,4 +1,4 @@
/* $NetBSD: umassvar.h,v 1.8 2001/12/14 08:58:51 gehenna Exp $ */ /* $NetBSD: umassvar.h,v 1.9 2001/12/17 12:16:15 gehenna Exp $ */
/*- /*-
* Copyright (c) 1999 MAEKAWA Masahide <bishop@rr.iij4u.or.jp>, * Copyright (c) 1999 MAEKAWA Masahide <bishop@rr.iij4u.or.jp>,
* Nick Hibma <n_hibma@freebsd.org> * Nick Hibma <n_hibma@freebsd.org>
@ -162,53 +162,29 @@ struct umass_softc {
u_int8_t sc_epaddr[UMASS_NEP]; u_int8_t sc_epaddr[UMASS_NEP];
usbd_pipe_handle sc_pipe[UMASS_NEP]; usbd_pipe_handle sc_pipe[UMASS_NEP];
usb_device_request_t sc_req;
const struct umass_wire_methods *sc_methods; const struct umass_wire_methods *sc_methods;
unsigned char drive; u_int8_t sc_wire; /* wire protocol */
#define DRIVE_GENERIC 0 /* use defaults for this one */ #define UMASS_WPROTO_UNSPEC 0
#define ZIP_100 1 /* to be used for quirks */ #define UMASS_WPROTO_BBB 1
#define ZIP_250 2 #define UMASS_WPROTO_CBI 2
#define SHUTTLE_EUSB 3 #define UMASS_WPROTO_CBI_I 3
#define INSYSTEM_USBCABLE 4
unsigned char quirks;
/* The drive does not support Test Unit Ready. Convert to
* Start Unit.
* Y-E Data
* ZIP 100
*/
#define NO_TEST_UNIT_READY 0x01
/* The drive does not reset the Unit Attention state after
* REQUEST SENSE has been sent. The INQUIRY command does not reset
* the UA either, and so CAM runs in circles trying to retrieve the
* initial INQUIRY data.
* Y-E Data
*/
#define RS_NO_CLEAR_UA 0x02 /* no REQUEST SENSE on INQUIRY*/
/* The drive does not support START_STOP.
* Shuttle E-USB
*/
#define NO_START_STOP 0x04
/* Don't ask for full inquiry data (255 bytes).
* Yano ATAPI-USB
*/
#define FORCE_SHORT_INQUIRY 0x08
/* The device uses a weird CSWSIGNATURE. */ u_int8_t sc_cmd; /* command protocol */
#define WRONG_CSWSIG 0x10 #define UMASS_CPROTO_UNSPEC 0
#define UMASS_CPROTO_SCSI 1
#define UMASS_CPROTO_ATAPI 2
#define UMASS_CPROTO_UFI 3
#define UMASS_CPROTO_RBC 4
u_int8_t wire_proto; /* USB wire protocol */ u_int32_t sc_quirks;
#define WPROTO_BBB 1 #define UMASS_QUIRK_NO_TEST_UNIT_READY 0x00000001
#define WPROTO_CBI 2 #define UMASS_QUIRK_RS_NO_CLEAR_UA 0x00000002
#define WPROTO_CBI_I 3 #define UMASS_QUIRK_NO_START_STOP 0x00000004
u_int8_t cmd_proto; /* command protocol */ #define UMASS_QUIRK_FORCE_SHORT_INQUIRY 0x00000008
#define CPROTO_SCSI 1 #define UMASS_QUIRK_WRONG_CSWSIG 0x00000010
#define CPROTO_ATAPI 2
#define CPROTO_UFI 3
#define CPROTO_RBC 4
u_char subclass; /* interface subclass */
u_char protocol; /* interface protocol */
/* Bulk specific variables for transfers in progress */ /* Bulk specific variables for transfers in progress */
umass_bbb_cbw_t cbw; /* command block wrapper */ umass_bbb_cbw_t cbw; /* command block wrapper */
@ -217,10 +193,6 @@ struct umass_softc {
umass_cbi_cbl_t cbl; /* command block */ umass_cbi_cbl_t cbl; /* command block */
umass_cbi_sbl_t sbl; /* status block */ umass_cbi_sbl_t sbl; /* status block */
/* generic variables for transfers in progress */
/* ctrl transfer requests */
usb_device_request_t request;
/* xfer handles /* xfer handles
* Most of our operations are initiated from interrupt context, so * Most of our operations are initiated from interrupt context, so
* we need to avoid using the one that is in use. We want to avoid * we need to avoid using the one that is in use. We want to avoid