Introduce the new umass quirk table.
Discussed with augustss.
This commit is contained in:
parent
576463d9d3
commit
7cd101a6ca
|
@ -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.
|
||||
# Included by ports that need it. Ports that use it must provide
|
||||
|
@ -83,6 +83,7 @@ device umass: scsi, atapi
|
|||
attach umass at uhub
|
||||
file dev/usb/umass.c umass
|
||||
file dev/usb/umassbus.c umass
|
||||
file dev/usb/umass_quirks.c umass
|
||||
|
||||
|
||||
# IrDA bridges
|
||||
|
|
|
@ -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>,
|
||||
* Nick Hibma <n_hibma@freebsd.org>
|
||||
|
@ -94,7 +94,7 @@
|
|||
*/
|
||||
|
||||
#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"
|
||||
|
||||
|
@ -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/umassvar.h>
|
||||
|
||||
#include <dev/usb/umass_quirks.h>
|
||||
|
||||
|
||||
|
||||
|
@ -156,10 +156,6 @@ char *states[TSTATE_STATES+1] = {
|
|||
/* USB device probe/attach/detach functions */
|
||||
USB_DECLARE_DRIVER(umass);
|
||||
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 */
|
||||
Static usbd_status umass_setup_transfer(struct umass_softc *sc,
|
||||
|
@ -219,271 +215,136 @@ Static void umass_dump_buffer(struct umass_softc *sc, u_int8_t *buffer,
|
|||
* 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_START(umass, uaa);
|
||||
#if defined(__FreeBSD__)
|
||||
struct umass_softc *sc = device_get_softc(self);
|
||||
#elif defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
struct umass_softc scs, *sc = &scs;
|
||||
memset(sc, 0, sizeof *sc);
|
||||
strcpy(sc->sc_dev.dv_xname, "umass");
|
||||
#endif
|
||||
const struct umass_quirk *quirk;
|
||||
usb_interface_descriptor_t *id;
|
||||
|
||||
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_START(umass, sc, uaa);
|
||||
const struct umass_quirk *quirk;
|
||||
usb_interface_descriptor_t *id;
|
||||
usb_endpoint_descriptor_t *ed;
|
||||
const char *sSubclass, *sProto;
|
||||
const char *sWire, *sCommand;
|
||||
char devinfo[1024];
|
||||
usbd_status err;
|
||||
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);
|
||||
USB_ATTACH_SETUP;
|
||||
|
||||
sc->sc_udev = uaa->device;
|
||||
sc->sc_iface = uaa->iface;
|
||||
sc->sc_ifaceno = uaa->ifaceno;
|
||||
|
||||
/* initialise the proto and drive values in the umass_softc (again) */
|
||||
if (umass_match_proto(sc, sc->sc_iface, uaa->device) == 0) {
|
||||
printf("%s: match failed\n", USBDEVNAME(sc->sc_dev));
|
||||
USB_ATTACH_ERROR_RETURN;
|
||||
quirk = umass_lookup(uaa->vendor, uaa->product);
|
||||
if (quirk != NULL) {
|
||||
sc->sc_wire = quirk->uq_wire;
|
||||
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) {
|
||||
err = usbd_set_interface(sc->sc_iface, 1);
|
||||
if (err) {
|
||||
DPRINTF(UDMASS_USB, ("%s: could not switch to "
|
||||
"Alt Interface %d\n",
|
||||
USBDEVNAME(sc->sc_dev), 1));
|
||||
umass_disco(sc);
|
||||
if (sc->transfer_speed == 0)
|
||||
sc->transfer_speed = UMASS_DEFAULT_TRANSFER_SPEED;
|
||||
|
||||
id = usbd_get_interface_descriptor(sc->sc_iface);
|
||||
if (id == NULL)
|
||||
USB_ATTACH_ERROR_RETURN;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The timeout is based on the maximum expected transfer size
|
||||
|
@ -497,49 +358,43 @@ USB_ATTACH(umass)
|
|||
printf("%s: timeout=%d ms\n", USBDEVNAME(sc->sc_dev), sc->timeout);
|
||||
#endif
|
||||
|
||||
id = usbd_get_interface_descriptor(sc->sc_iface);
|
||||
printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo);
|
||||
|
||||
switch (sc->subclass) {
|
||||
case UISUBCLASS_RBC:
|
||||
sSubclass = "RBC";
|
||||
switch (sc->sc_wire) {
|
||||
case UMASS_WPROTO_CBI:
|
||||
sWire = "CBI";
|
||||
break;
|
||||
case UISUBCLASS_SCSI:
|
||||
sSubclass = "SCSI";
|
||||
case UMASS_WPROTO_CBI_I:
|
||||
sWire = "CBI with CCI";
|
||||
break;
|
||||
case UISUBCLASS_UFI:
|
||||
sSubclass = "UFI";
|
||||
break;
|
||||
case UISUBCLASS_SFF8020I:
|
||||
sSubclass = "SFF8020i";
|
||||
break;
|
||||
case UISUBCLASS_SFF8070I:
|
||||
sSubclass = "SFF8070i";
|
||||
break;
|
||||
case UISUBCLASS_QIC157:
|
||||
sSubclass = "QIC157";
|
||||
case UMASS_WPROTO_BBB:
|
||||
sWire = "Bulk-Only";
|
||||
break;
|
||||
default:
|
||||
sSubclass = "unknown";
|
||||
sWire = "unknown";
|
||||
break;
|
||||
}
|
||||
switch (sc->protocol) {
|
||||
case UIPROTO_MASS_CBI:
|
||||
sProto = "CBI";
|
||||
|
||||
switch (sc->sc_cmd) {
|
||||
case UMASS_CPROTO_RBC:
|
||||
sCommand = "RBC";
|
||||
break;
|
||||
case UIPROTO_MASS_CBI_I:
|
||||
sProto = "CBI-I";
|
||||
case UMASS_CPROTO_SCSI:
|
||||
sCommand = "SCSI";
|
||||
break;
|
||||
case UIPROTO_MASS_BBB:
|
||||
case UIPROTO_MASS_BBB_OLD:
|
||||
sProto = "BBB";
|
||||
case UMASS_CPROTO_UFI:
|
||||
sCommand = "UFI";
|
||||
break;
|
||||
case UMASS_CPROTO_ATAPI:
|
||||
sCommand = "ATAPI";
|
||||
break;
|
||||
default:
|
||||
sProto = "unknown";
|
||||
sCommand = "unknown";
|
||||
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
|
||||
|
@ -554,7 +409,7 @@ USB_ATTACH(umass)
|
|||
*/
|
||||
for (i = 0 ; i < id->bNumEndpoints ; i++) {
|
||||
ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
|
||||
if (!ed) {
|
||||
if (ed == NULL) {
|
||||
printf("%s: could not read endpoint descriptor\n",
|
||||
USBDEVNAME(sc->sc_dev));
|
||||
USB_ATTACH_ERROR_RETURN;
|
||||
|
@ -565,7 +420,7 @@ USB_ATTACH(umass)
|
|||
} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT
|
||||
&& (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) {
|
||||
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
|
||||
&& (ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT) {
|
||||
sc->sc_epaddr[UMASS_INTRIN] = ed->bEndpointAddress;
|
||||
|
@ -581,19 +436,19 @@ USB_ATTACH(umass)
|
|||
|
||||
/* check whether we found all the endpoints we need */
|
||||
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",
|
||||
USBDEVNAME(sc->sc_dev), sc->sc_epaddr[UMASS_BULKIN],
|
||||
sc->sc_epaddr[UMASS_BULKOUT],
|
||||
sc->sc_epaddr[UMASS_INTRIN]));
|
||||
umass_disco(sc);
|
||||
USB_ATTACH_ERROR_RETURN;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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);
|
||||
if (err) {
|
||||
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
|
||||
* 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],
|
||||
USBD_EXCLUSIVE_USE, &sc->sc_pipe[UMASS_INTRIN]);
|
||||
if (err) {
|
||||
|
@ -660,14 +515,14 @@ USB_ATTACH(umass)
|
|||
}
|
||||
}
|
||||
/* Allocate buffer for data transfer (it's huge). */
|
||||
switch (sc->wire_proto) {
|
||||
case WPROTO_BBB:
|
||||
switch (sc->sc_wire) {
|
||||
case UMASS_WPROTO_BBB:
|
||||
bno = XFER_BBB_DATA;
|
||||
goto dalloc;
|
||||
case WPROTO_CBI:
|
||||
case UMASS_WPROTO_CBI:
|
||||
bno = XFER_CBI_DATA;
|
||||
goto dalloc;
|
||||
case WPROTO_CBI_I:
|
||||
case UMASS_WPROTO_CBI_I:
|
||||
bno = XFER_CBI_DATA;
|
||||
dalloc:
|
||||
sc->data_buffer = usbd_alloc_buffer(sc->transfer_xfer[bno],
|
||||
|
@ -682,20 +537,26 @@ USB_ATTACH(umass)
|
|||
}
|
||||
|
||||
/* 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;
|
||||
} else if (sc->wire_proto == WPROTO_CBI ||
|
||||
sc->wire_proto == WPROTO_CBI_I) {
|
||||
break;
|
||||
case UMASS_WPROTO_CBI:
|
||||
case UMASS_WPROTO_CBI_I:
|
||||
sc->sc_methods = &umass_cbi_methods;
|
||||
#ifdef UMASS_DEBUG
|
||||
} else {
|
||||
panic("%s:%d: Unknown wire proto 0x%02x\n",
|
||||
__FILE__, __LINE__, sc->wire_proto);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
umass_disco(sc);
|
||||
USB_ATTACH_ERROR_RETURN;
|
||||
}
|
||||
|
||||
if (sc->drive == SHUTTLE_EUSB)
|
||||
umass_init_shuttle(sc);
|
||||
if (quirk != NULL && quirk->uq_init != NULL) {
|
||||
err = (*quirk->uq_init)(sc);
|
||||
if (err) {
|
||||
umass_disco(sc);
|
||||
USB_ATTACH_ERROR_RETURN;
|
||||
}
|
||||
}
|
||||
|
||||
if (umass_attach_bus(sc)) {
|
||||
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
|
||||
*/
|
||||
|
@ -852,12 +698,12 @@ umass_clear_endpoint_stall(struct umass_softc *sc, int endpt,
|
|||
|
||||
usbd_clear_endpoint_toggle(sc->sc_pipe[endpt]);
|
||||
|
||||
sc->request.bmRequestType = UT_WRITE_ENDPOINT;
|
||||
sc->request.bRequest = UR_CLEAR_FEATURE;
|
||||
USETW(sc->request.wValue, UF_ENDPOINT_HALT);
|
||||
USETW(sc->request.wIndex, sc->sc_epaddr[endpt]);
|
||||
USETW(sc->request.wLength, 0);
|
||||
umass_setup_ctrl_transfer(sc, &sc->request, NULL, 0, 0, xfer);
|
||||
sc->sc_req.bmRequestType = UT_WRITE_ENDPOINT;
|
||||
sc->sc_req.bRequest = UR_CLEAR_FEATURE;
|
||||
USETW(sc->sc_req.wValue, UF_ENDPOINT_HALT);
|
||||
USETW(sc->sc_req.wIndex, sc->sc_epaddr[endpt]);
|
||||
USETW(sc->sc_req.wLength, 0);
|
||||
umass_setup_ctrl_transfer(sc, &sc->sc_req, NULL, 0, 0, xfer);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
@ -879,8 +725,9 @@ umass_reset(struct umass_softc *sc, transfer_cb_f cb, void *priv)
|
|||
Static void
|
||||
umass_bbb_reset(struct umass_softc *sc, int status)
|
||||
{
|
||||
KASSERT(sc->proto & PROTO_BBB,
|
||||
("sc->proto == 0x%02x wrong for umass_bbb_reset\n", sc->proto));
|
||||
KASSERT(sc->sc_wire & UMASS_WPROTO_BBB,
|
||||
("sc->sc_wire == 0x%02x wrong for umass_bbb_reset\n",
|
||||
sc->sc_wire));
|
||||
|
||||
if (sc->sc_dying)
|
||||
return;
|
||||
|
@ -908,12 +755,12 @@ umass_bbb_reset(struct umass_softc *sc, int status)
|
|||
sc->transfer_status = status;
|
||||
|
||||
/* reset is a class specific interface write */
|
||||
sc->request.bmRequestType = UT_WRITE_CLASS_INTERFACE;
|
||||
sc->request.bRequest = UR_BBB_RESET;
|
||||
USETW(sc->request.wValue, 0);
|
||||
USETW(sc->request.wIndex, sc->sc_ifaceno);
|
||||
USETW(sc->request.wLength, 0);
|
||||
umass_setup_ctrl_transfer(sc, &sc->request, NULL, 0, 0,
|
||||
sc->sc_req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
|
||||
sc->sc_req.bRequest = UR_BBB_RESET;
|
||||
USETW(sc->sc_req.wValue, 0);
|
||||
USETW(sc->sc_req.wIndex, sc->sc_ifaceno);
|
||||
USETW(sc->sc_req.wLength, 0);
|
||||
umass_setup_ctrl_transfer(sc, &sc->sc_req, NULL, 0, 0,
|
||||
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",
|
||||
USBDEVNAME(sc->sc_dev), *(u_char*)cmd));
|
||||
|
||||
KASSERT(sc->proto & PROTO_BBB,
|
||||
("sc->proto == 0x%02x wrong for umass_bbb_transfer\n",
|
||||
sc->proto));
|
||||
KASSERT(sc->sc_wire & UMASS_WPROTO_BBB,
|
||||
("sc->sc_wire == 0x%02x wrong for umass_bbb_transfer\n",
|
||||
sc->sc_wire));
|
||||
|
||||
/* Be a little generous. */
|
||||
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;
|
||||
usbd_xfer_handle next_xfer;
|
||||
|
||||
KASSERT(sc->proto & PROTO_BBB,
|
||||
("sc->proto == 0x%02x wrong for umass_bbb_state\n",sc->proto));
|
||||
KASSERT(sc->sc_wire & UMASS_WPROTO_BBB,
|
||||
("sc->sc_wire == 0x%02x wrong for umass_bbb_state\n",
|
||||
sc->sc_wire));
|
||||
|
||||
if (sc->sc_dying)
|
||||
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));
|
||||
|
||||
/* 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)
|
||||
USETDW(sc->csw.dCSWSignature, CSWSIGNATURE);
|
||||
|
||||
|
@ -1339,15 +1187,16 @@ Static int
|
|||
umass_cbi_adsc(struct umass_softc *sc, char *buffer, int buflen,
|
||||
usbd_xfer_handle xfer)
|
||||
{
|
||||
KASSERT(sc->proto & (PROTO_CBI|PROTO_CBI_I),
|
||||
("sc->proto == 0x%02x wrong for umass_cbi_adsc\n",sc->proto));
|
||||
KASSERT(sc->sc_wire & (UMASS_WPROTO_CBI|UMASS_WPROTO_CBI_I),
|
||||
("sc->sc_wire == 0x%02x wrong for umass_cbi_adsc\n",
|
||||
sc->sc_wire));
|
||||
|
||||
sc->request.bmRequestType = UT_WRITE_CLASS_INTERFACE;
|
||||
sc->request.bRequest = UR_CBI_ADSC;
|
||||
USETW(sc->request.wValue, 0);
|
||||
USETW(sc->request.wIndex, sc->sc_ifaceno);
|
||||
USETW(sc->request.wLength, buflen);
|
||||
return umass_setup_ctrl_transfer(sc, &sc->request, buffer,
|
||||
sc->sc_req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
|
||||
sc->sc_req.bRequest = UR_CBI_ADSC;
|
||||
USETW(sc->sc_req.wValue, 0);
|
||||
USETW(sc->sc_req.wIndex, sc->sc_ifaceno);
|
||||
USETW(sc->sc_req.wLength, buflen);
|
||||
return umass_setup_ctrl_transfer(sc, &sc->sc_req, buffer,
|
||||
buflen, 0, xfer);
|
||||
}
|
||||
|
||||
|
@ -1358,8 +1207,9 @@ umass_cbi_reset(struct umass_softc *sc, int status)
|
|||
int i;
|
||||
# define SEND_DIAGNOSTIC_CMDLEN 12
|
||||
|
||||
KASSERT(sc->proto & (PROTO_CBI|PROTO_CBI_I),
|
||||
("sc->proto == 0x%02x wrong for umass_cbi_reset\n",sc->proto));
|
||||
KASSERT(sc->sc_wire & (UMASS_WPROTO_CBI|UMASS_WPROTO_CBI_I),
|
||||
("sc->sc_wire == 0x%02x wrong for umass_cbi_reset\n",
|
||||
sc->sc_wire));
|
||||
|
||||
if (sc->sc_dying)
|
||||
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",
|
||||
USBDEVNAME(sc->sc_dev), *(u_char*)cmd, datalen));
|
||||
|
||||
KASSERT(sc->proto & (PROTO_CBI|PROTO_CBI_I),
|
||||
("sc->proto == 0x%02x wrong for umass_cbi_transfer\n",
|
||||
sc->proto));
|
||||
KASSERT(sc->sc_wire & (UMASS_WPROTO_CBI|UMASS_WPROTO_CBI_I),
|
||||
("sc->sc_wire == 0x%02x wrong for umass_cbi_transfer\n",
|
||||
sc->sc_wire));
|
||||
|
||||
if (sc->sc_dying)
|
||||
return;
|
||||
|
@ -1468,8 +1318,9 @@ umass_cbi_state(usbd_xfer_handle xfer, usbd_private_handle priv,
|
|||
{
|
||||
struct umass_softc *sc = (struct umass_softc *) priv;
|
||||
|
||||
KASSERT(sc->proto & (PROTO_CBI|PROTO_CBI_I),
|
||||
("sc->proto == 0x%02x wrong for umass_cbi_state\n", sc->proto));
|
||||
KASSERT(sc->sc_wire & (UMASS_WPROTO_CBI|UMASS_WPROTO_CBI_I),
|
||||
("sc->sc_wire == 0x%02x wrong for umass_cbi_state\n",
|
||||
sc->sc_wire));
|
||||
|
||||
if (sc->sc_dying)
|
||||
return;
|
||||
|
@ -1529,7 +1380,7 @@ 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->wire_proto == WPROTO_CBI_I) {
|
||||
} 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;
|
||||
|
@ -1582,7 +1433,7 @@ umass_cbi_state(usbd_xfer_handle xfer, usbd_private_handle priv,
|
|||
umass_dump_buffer(sc, sc->transfer_data,
|
||||
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;
|
||||
memset(&sc->sbl, 0, sizeof(sc->sbl));
|
||||
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 */
|
||||
|
||||
if (sc->cmd_proto == CPROTO_UFI) {
|
||||
if (sc->sc_cmd == UMASS_CPROTO_UFI) {
|
||||
int status;
|
||||
|
||||
/* Section 3.4.3.1.3 specifies that the UFI command
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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_ */
|
|
@ -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.
|
||||
|
@ -38,7 +38,7 @@
|
|||
*/
|
||||
|
||||
#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 "scsibus.h"
|
||||
|
@ -123,9 +123,9 @@ umass_attach_bus(struct umass_softc *sc)
|
|||
sc->bus.sc_channel.chan_max_periph = 1;
|
||||
|
||||
|
||||
switch (sc->cmd_proto) {
|
||||
case CPROTO_RBC:
|
||||
case CPROTO_SCSI:
|
||||
switch (sc->sc_cmd) {
|
||||
case UMASS_CPROTO_RBC:
|
||||
case UMASS_CPROTO_SCSI:
|
||||
#if NSCSIBUS > 0
|
||||
sc->bus.sc_channel.chan_bustype = &scsi_bustype;
|
||||
sc->bus.sc_channel.chan_ntargets = UMASS_SCSIID_DEVICE + 1;
|
||||
|
@ -140,14 +140,14 @@ umass_attach_bus(struct umass_softc *sc)
|
|||
#endif
|
||||
break;
|
||||
|
||||
case CPROTO_UFI:
|
||||
case CPROTO_ATAPI:
|
||||
case UMASS_CPROTO_UFI:
|
||||
case UMASS_CPROTO_ATAPI:
|
||||
#if NATAPIBUS > 0
|
||||
sc->bus.sc_channel.chan_bustype = &umass_atapi_bustype;
|
||||
sc->bus.sc_channel.chan_ntargets = 2;
|
||||
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;
|
||||
DPRINTF(UDMASS_USB, ("%s: umass_attach_bus: ATAPI\n",
|
||||
USBDEVNAME(sc->sc_dev)));
|
||||
|
@ -160,7 +160,7 @@ umass_attach_bus(struct umass_softc *sc)
|
|||
|
||||
default:
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -288,14 +288,14 @@ umass_scsipi_request(struct scsipi_channel *chan,
|
|||
/* XXX should use transform */
|
||||
|
||||
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));*/
|
||||
xs->error = XS_NOERROR;
|
||||
goto done;
|
||||
}
|
||||
|
||||
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
|
||||
* information.
|
||||
|
@ -413,7 +413,7 @@ umass_scsipi_getgeom(struct scsipi_periph *periph, struct disk_parms *dp,
|
|||
(void *)periph->periph_channel->chan_adapter->adapt_dev;
|
||||
|
||||
/* 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);
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
sc->sc_methods->wire_xfer(sc, periph->periph_lun,
|
||||
&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_UNKNOWN:
|
||||
/* getting sense data succeeded */
|
||||
if (xs->cmd->opcode == INQUIRY && (xs->resid < xs->datalen
|
||||
|| ((sc->quirks & RS_NO_CLEAR_UA) /* XXX */) )) {
|
||||
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.
|
||||
|
|
|
@ -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>,
|
||||
* Nick Hibma <n_hibma@freebsd.org>
|
||||
|
@ -162,53 +162,29 @@ struct umass_softc {
|
|||
|
||||
u_int8_t sc_epaddr[UMASS_NEP];
|
||||
usbd_pipe_handle sc_pipe[UMASS_NEP];
|
||||
usb_device_request_t sc_req;
|
||||
|
||||
const struct umass_wire_methods *sc_methods;
|
||||
|
||||
unsigned char drive;
|
||||
#define DRIVE_GENERIC 0 /* use defaults for this one */
|
||||
#define ZIP_100 1 /* to be used for quirks */
|
||||
#define ZIP_250 2
|
||||
#define SHUTTLE_EUSB 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
|
||||
u_int8_t sc_wire; /* wire protocol */
|
||||
#define UMASS_WPROTO_UNSPEC 0
|
||||
#define UMASS_WPROTO_BBB 1
|
||||
#define UMASS_WPROTO_CBI 2
|
||||
#define UMASS_WPROTO_CBI_I 3
|
||||
|
||||
/* The device uses a weird CSWSIGNATURE. */
|
||||
#define WRONG_CSWSIG 0x10
|
||||
u_int8_t sc_cmd; /* command protocol */
|
||||
#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 */
|
||||
#define WPROTO_BBB 1
|
||||
#define WPROTO_CBI 2
|
||||
#define WPROTO_CBI_I 3
|
||||
u_int8_t cmd_proto; /* command protocol */
|
||||
#define CPROTO_SCSI 1
|
||||
#define CPROTO_ATAPI 2
|
||||
#define CPROTO_UFI 3
|
||||
#define CPROTO_RBC 4
|
||||
|
||||
u_char subclass; /* interface subclass */
|
||||
u_char protocol; /* interface protocol */
|
||||
u_int32_t sc_quirks;
|
||||
#define UMASS_QUIRK_NO_TEST_UNIT_READY 0x00000001
|
||||
#define UMASS_QUIRK_RS_NO_CLEAR_UA 0x00000002
|
||||
#define UMASS_QUIRK_NO_START_STOP 0x00000004
|
||||
#define UMASS_QUIRK_FORCE_SHORT_INQUIRY 0x00000008
|
||||
#define UMASS_QUIRK_WRONG_CSWSIG 0x00000010
|
||||
|
||||
/* Bulk specific variables for transfers in progress */
|
||||
umass_bbb_cbw_t cbw; /* command block wrapper */
|
||||
|
@ -217,10 +193,6 @@ struct umass_softc {
|
|||
umass_cbi_cbl_t cbl; /* command block */
|
||||
umass_cbi_sbl_t sbl; /* status block */
|
||||
|
||||
/* generic variables for transfers in progress */
|
||||
/* ctrl transfer requests */
|
||||
usb_device_request_t request;
|
||||
|
||||
/* xfer handles
|
||||
* 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
|
||||
|
|
Loading…
Reference in New Issue