summaryrefslogtreecommitdiffstats
path: root/sys/dev/usb
diff options
context:
space:
mode:
authorn_hibma <n_hibma@FreeBSD.org>2010-11-10 18:41:38 +0000
committern_hibma <n_hibma@FreeBSD.org>2010-11-10 18:41:38 +0000
commitc905973491138e09498591249e79537ca474f694 (patch)
tree27917b5824dcee576de20f2d4480605f711f735e /sys/dev/usb
parent540593911ba28e330a197daaea7ed02aae240c33 (diff)
downloadFreeBSD-src-c905973491138e09498591249e79537ca474f694.zip
FreeBSD-src-c905973491138e09498591249e79537ca474f694.tar.gz
Allow specification of eject method through quirks, so people can test
drive eject methods before supplying patches.
Diffstat (limited to 'sys/dev/usb')
-rw-r--r--sys/dev/usb/quirk/usb_quirk.c10
-rw-r--r--sys/dev/usb/quirk/usb_quirk.h58
-rw-r--r--sys/dev/usb/serial/u3g.c38
3 files changed, 77 insertions, 29 deletions
diff --git a/sys/dev/usb/quirk/usb_quirk.c b/sys/dev/usb/quirk/usb_quirk.c
index c619a24..6691538 100644
--- a/sys/dev/usb/quirk/usb_quirk.c
+++ b/sys/dev/usb/quirk/usb_quirk.c
@@ -512,6 +512,16 @@ static const char *usb_quirk_str[USB_QUIRK_MAX] = {
[UQ_MSC_FORCE_PROTO_ATAPI] = "UQ_MSC_FORCE_PROTO_ATAPI",
[UQ_MSC_FORCE_PROTO_UFI] = "UQ_MSC_FORCE_PROTO_UFI",
[UQ_MSC_FORCE_PROTO_RBC] = "UQ_MSC_FORCE_PROTO_RBC",
+ [UQ_MSC_EJECT_HUAWEI] = "UQ_MSC_EJECT_HUAWEI",
+ [UQ_MSC_EJECT_SIERRA] = "UQ_MSC_EJECT_SIERRA",
+ [UQ_MSC_EJECT_SCSIEJECT] = "UQ_MSC_EJECT_SCSIEJECT",
+ [UQ_MSC_EJECT_REZERO] = "UQ_MSC_EJECT_REZERO",
+ [UQ_MSC_EJECT_ZTESTOR] = "UQ_MSC_EJECT_ZTESTOR",
+ [UQ_MSC_EJECT_CMOTECH] = "UQ_MSC_EJECT_CMOTECH",
+ [UQ_MSC_EJECT_WAIT] = "UQ_MSC_EJECT_WAIT",
+ [UQ_MSC_EJECT_SAEL_M460] = "UQ_MSC_EJECT_SAEL_M460",
+ [UQ_MSC_EJECT_HUAWEISCSI] = "UQ_MSC_EJECT_HUAWEISCSI",
+ [UQ_MSC_EJECT_TCT] = "UQ_MSC_EJECT_TCT",
};
/*------------------------------------------------------------------------*
diff --git a/sys/dev/usb/quirk/usb_quirk.h b/sys/dev/usb/quirk/usb_quirk.h
index d681402..856ab89 100644
--- a/sys/dev/usb/quirk/usb_quirk.h
+++ b/sys/dev/usb/quirk/usb_quirk.h
@@ -59,31 +59,43 @@ enum { /* keep in sync with usb_quirk_str table */
UQ_CFG_INDEX_3, /* select configuration index 3 by default */
UQ_CFG_INDEX_4, /* select configuration index 4 by default */
UQ_CFG_INDEX_0, /* select configuration index 0 by default */
- UQ_ASSUME_CM_OVER_DATA, /* modem device breaks on cm over data */
+ UQ_ASSUME_CM_OVER_DATA, /* assume cm over data feature */
/* USB Mass Storage Quirks. See "storage/umass.c" for a detailed description. */
- UQ_MSC_NO_TEST_UNIT_READY,
- UQ_MSC_NO_RS_CLEAR_UA,
- UQ_MSC_NO_START_STOP,
- UQ_MSC_NO_GETMAXLUN,
- UQ_MSC_NO_INQUIRY,
- UQ_MSC_NO_INQUIRY_EVPD,
- UQ_MSC_NO_SYNC_CACHE,
- UQ_MSC_SHUTTLE_INIT,
- UQ_MSC_ALT_IFACE_1,
- UQ_MSC_FLOPPY_SPEED,
- UQ_MSC_IGNORE_RESIDUE,
- UQ_MSC_WRONG_CSWSIG,
- UQ_MSC_RBC_PAD_TO_12,
- UQ_MSC_READ_CAP_OFFBY1,
- UQ_MSC_FORCE_SHORT_INQ,
- UQ_MSC_FORCE_WIRE_BBB,
- UQ_MSC_FORCE_WIRE_CBI,
- UQ_MSC_FORCE_WIRE_CBI_I,
- UQ_MSC_FORCE_PROTO_SCSI,
- UQ_MSC_FORCE_PROTO_ATAPI,
- UQ_MSC_FORCE_PROTO_UFI,
- UQ_MSC_FORCE_PROTO_RBC,
+ UQ_MSC_NO_TEST_UNIT_READY, /* send start/stop instead of TUR */
+ UQ_MSC_NO_RS_CLEAR_UA, /* does not reset Unit Att. */
+ UQ_MSC_NO_START_STOP, /* does not support start/stop */
+ UQ_MSC_NO_GETMAXLUN, /* does not support get max LUN */
+ UQ_MSC_NO_INQUIRY, /* fake generic inq response */
+ UQ_MSC_NO_INQUIRY_EVPD, /* does not support inq EVPD */
+ UQ_MSC_NO_SYNC_CACHE, /* does not support sync cache */
+ UQ_MSC_SHUTTLE_INIT, /* requires Shuttle init sequence */
+ UQ_MSC_ALT_IFACE_1, /* switch to alternate interface 1 */
+ UQ_MSC_FLOPPY_SPEED, /* does floppy speeds (20kb/s) */
+ UQ_MSC_IGNORE_RESIDUE, /* gets residue wrong */
+ UQ_MSC_WRONG_CSWSIG, /* uses wrong CSW signature */
+ UQ_MSC_RBC_PAD_TO_12, /* pad RBC requests to 12 bytes */
+ UQ_MSC_READ_CAP_OFFBY1, /* reports sector count, not max sec. */
+ UQ_MSC_FORCE_SHORT_INQ, /* does not support full inq. */
+ UQ_MSC_FORCE_WIRE_BBB, /* force BBB wire protocol */
+ UQ_MSC_FORCE_WIRE_CBI, /* force CBI wire protocol */
+ UQ_MSC_FORCE_WIRE_CBI_I, /* force CBI with int. wire protocol */
+ UQ_MSC_FORCE_PROTO_SCSI, /* force SCSI command protocol */
+ UQ_MSC_FORCE_PROTO_ATAPI, /* force ATAPI command protocol */
+ UQ_MSC_FORCE_PROTO_UFI, /* force UFI command protocol */
+ UQ_MSC_FORCE_PROTO_RBC, /* force RBC command protocol */
+
+ /* Ejection of mass storage (driver disk) */
+ UQ_MSC_EJECT_HUAWEI, /* ejects after Huawei USB command */
+ UQ_MSC_EJECT_SIERRA, /* ejects after Sierra USB command */
+ UQ_MSC_EJECT_SCSIEJECT, /* ejects after SCSI eject command */
+ UQ_MSC_EJECT_REZERO, /* ejects after SCSI rezero command */
+ UQ_MSC_EJECT_ZTESTOR, /* ejects after ZTE SCSI command */
+ UQ_MSC_EJECT_CMOTECH, /* ejects after C-motech SCSI cmd */
+ UQ_MSC_EJECT_WAIT, /* wait for the device to eject */
+ UQ_MSC_EJECT_SAEL_M460, /* ejects after Sael USB commands */
+ UQ_MSC_EJECT_HUAWEISCSI, /* ejects after Huawei SCSI command */
+ UQ_MSC_EJECT_TCT, /* ejects after TCT SCSI command */
USB_QUIRK_MAX
};
diff --git a/sys/dev/usb/serial/u3g.c b/sys/dev/usb/serial/u3g.c
index 9376e9e..12bd3f4 100644
--- a/sys/dev/usb/serial/u3g.c
+++ b/sys/dev/usb/serial/u3g.c
@@ -62,6 +62,7 @@
#include <dev/usb/usb_msctest.h>
#include <dev/usb/serial/usb_serial.h>
+#include <dev/usb/quirk/usb_quirk.h>
#ifdef USB_DEBUG
static int u3g_debug = 0;
@@ -84,6 +85,7 @@ SYSCTL_INT(_hw_usb_u3g, OID_AUTO, debug, CTLFLAG_RW,
#define U3GSP_HSPA 6
#define U3GSP_MAX 7
+/* Eject methods; See also usb_quirks.h:UQ_MSC_EJECT_* */
#define U3GINIT_HUAWEI 1 /* Requires Huawei init command */
#define U3GINIT_SIERRA 2 /* Requires Sierra init command */
#define U3GINIT_SCSIEJECT 3 /* Requires SCSI eject command */
@@ -641,6 +643,7 @@ u3g_test_autoinst(void *arg, struct usb_device *udev,
struct usb_interface *iface;
struct usb_interface_descriptor *id;
int error;
+ unsigned long method;
if (uaa->dev_state != UAA_DEV_READY)
return;
@@ -651,16 +654,37 @@ u3g_test_autoinst(void *arg, struct usb_device *udev,
id = iface->idesc;
if (id == NULL || id->bInterfaceClass != UICLASS_MASS)
return;
- if (usbd_lookup_id_by_uaa(u3g_devs, sizeof(u3g_devs), uaa))
+
+ if (usb_test_quirk(uaa, UQ_MSC_EJECT_HUAWEI))
+ method = U3GINIT_HUAWEI;
+ else if (usb_test_quirk(uaa, UQ_MSC_EJECT_SIERRA))
+ method = U3GINIT_SIERRA;
+ else if (usb_test_quirk(uaa, UQ_MSC_EJECT_SCSIEJECT))
+ method = U3GINIT_SCSIEJECT;
+ else if (usb_test_quirk(uaa, UQ_MSC_EJECT_REZERO))
+ method = U3GINIT_REZERO;
+ else if (usb_test_quirk(uaa, UQ_MSC_EJECT_ZTESTOR))
+ method = U3GINIT_ZTESTOR;
+ else if (usb_test_quirk(uaa, UQ_MSC_EJECT_CMOTECH))
+ method = U3GINIT_CMOTECH;
+ else if (usb_test_quirk(uaa, UQ_MSC_EJECT_WAIT))
+ method = U3GINIT_WAIT;
+ else if (usb_test_quirk(uaa, UQ_MSC_EJECT_HUAWEISCSI))
+ method = U3GINIT_HUAWEISCSI;
+ else if (usb_test_quirk(uaa, UQ_MSC_EJECT_TCT))
+ method = U3GINIT_TCT;
+ else if (usbd_lookup_id_by_uaa(u3g_devs, sizeof(u3g_devs), uaa) == 0)
+ method = USB_GET_DRIVER_INFO(uaa);
+ else
return; /* no device match */
if (bootverbose) {
- printf("Ejecting 0x%04x:0x%04x using method %ld\n",
- uaa->info.idVendor, uaa->info.idProduct,
- USB_GET_DRIVER_INFO(uaa));
+ printf("Ejecting %s %s using method %ld\n",
+ usb_get_manufacturer(udev),
+ usb_get_product(udev), method);
}
- switch (USB_GET_DRIVER_INFO(uaa)) {
+ switch (method) {
case U3GINIT_HUAWEI:
error = u3g_huawei_init(udev);
break;
@@ -752,8 +776,10 @@ u3g_attach(device_t dev)
DPRINTF("sc=%p\n", sc);
type = USB_GET_DRIVER_INFO(uaa);
- if (type == U3GINIT_SAEL_M460)
+ if (type == U3GINIT_SAEL_M460
+ || usb_test_quirk(uaa, UQ_MSC_EJECT_SAEL_M460)) {
u3g_sael_m460_init(uaa->device);
+ }
/* copy in USB config */
for (n = 0; n != U3G_N_TRANSFER; n++)
OpenPOWER on IntegriCloud