summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorn_hibma <n_hibma@FreeBSD.org>2002-06-16 20:53:35 +0000
committern_hibma <n_hibma@FreeBSD.org>2002-06-16 20:53:35 +0000
commitbc70083f07c892b75a47690a1ab68930321a910d (patch)
tree9eb8f59f9a1b60a43e3ee306e81da05515e13129 /sys
parent078dff0f246379483b322973aa3b645331acc4dc (diff)
downloadFreeBSD-src-bc70083f07c892b75a47690a1ab68930321a910d.zip
FreeBSD-src-bc70083f07c892b75a47690a1ab68930321a910d.tar.gz
Rewrite the probe routine. This makes adding drives and quirks more easy.
While there change a few names to less confusing ones.
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/usb/umass.c518
1 files changed, 251 insertions, 267 deletions
diff --git a/sys/dev/usb/umass.c b/sys/dev/usb/umass.c
index fbb985d..7d2f612 100644
--- a/sys/dev/usb/umass.c
+++ b/sys/dev/usb/umass.c
@@ -152,9 +152,8 @@ int umassdebug = UDMASS_ALL;
#define DEVNAME_SIM "umass-sim"
#define UMASS_MAX_TRANSFER_SIZE 65536
-#define UMASS_DEFAULT_TRANSFER_SPEED 150 /* in kb/s, conservative est. */
+#define UMASS_DEFAULT_TRANSFER_SPEED 1000
#define UMASS_FLOPPY_TRANSFER_SPEED 20
-#define UMASS_ZIP100_TRANSFER_SPEED 650
#define UMASS_TIMEOUT 5000 /* msecs */
@@ -167,8 +166,7 @@ int umassdebug = UDMASS_ALL;
* ends up being target 3 on that SIM. When a request for target 3
* comes in we fetch the softc with devclass_get_softc(target_id).
*
- * The SIM is the highest target number. This makes sure that umass0 corresponds
- * to target 0 on the USB SCSI bus.
+ * The SIM is the highest target number, so umass0 corresponds to SCSI target 0.
*/
#ifndef UMASS_DEBUG
#define UMASS_SCSIID_MAX 32 /* maximum number of drives expected */
@@ -267,56 +265,121 @@ typedef int (*command_transform_f) (struct umass_softc *sc,
unsigned char **rcmd, int *rcmdlen);
+struct umass_devdescr_t {
+ u_int32_t vid;
+# define VID_WILDCARD 0xffffffff
+# define VID_EOT 0xfffffffe
+ u_int32_t pid;
+# define PID_WILDCARD 0xffffffff
+# define PID_EOT 0xfffffffe
+ u_int32_t rid;
+# define RID_WILDCARD 0xffffffff
+# define RID_EOT 0xfffffffe
+
+ /* wire and command protocol */
+ u_int16_t proto;
+# define UMASS_PROTO_BBB 0x0001 /* USB wire protocol */
+# define UMASS_PROTO_CBI 0x0002
+# define UMASS_PROTO_CBI_I 0x0004
+# define UMASS_PROTO_WIRE 0x00ff /* USB wire protocol mask */
+# define UMASS_PROTO_SCSI 0x0100 /* command protocol */
+# define UMASS_PROTO_ATAPI 0x0200
+# define UMASS_PROTO_UFI 0x0400
+# define UMASS_PROTO_RBC 0x0800
+# define UMASS_PROTO_COMMAND 0xff00 /* command protocol mask */
+
+ /* Device specific quirks */
+ u_int16_t quirks;
+# define NO_QUIRKS 0x0000
+ /* The drive does not support Test Unit Ready. Convert to Start Unit
+ */
+# define NO_TEST_UNIT_READY 0x0001
+ /* 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.
+ */
+# define RS_NO_CLEAR_UA 0x0002
+ /* The drive does not support START STOP. */
+# define NO_START_STOP 0x0004
+ /* Don't ask for full inquiry data (255b). */
+# define FORCE_SHORT_INQUIRY 0x0008
+ /* Needs to be initialised the Shuttle way */
+# define SHUTTLE_INIT 0x0010
+ /* Drive needs to be switched to alternate iface 1 */
+# define ALT_IFACE_1 0x0020
+ /* Drive does not do 1Mb/s, but just floppy speeds (20kb/s) */
+# define FLOPPY_SPEED 0x0040
+ /* The device can't count and gets the residue of transfers wrong */
+# define IGNORE_RESIDUE 0x0080
+ /* No GetMaxLun call */
+# define NO_GETMAXLUN 0x0100
+ /* The device uses a weird CSWSIGNATURE. */
+# define WRONG_CSWSIG 0x0200
+};
+
+Static struct umass_devdescr_t umass_devdescrs[] = {
+ { USB_VENDOR_FUJIPHOTO, USB_PRODUCT_FUJIPHOTO_MASS0100, RID_WILDCARD,
+ UMASS_PROTO_ATAPI | UMASS_PROTO_CBI_I,
+ RS_NO_CLEAR_UA
+ },
+ { USB_VENDOR_HP, USB_PRODUCT_HP_CDW8200, RID_WILDCARD,
+ UMASS_PROTO_ATAPI | UMASS_PROTO_CBI_I,
+ NO_TEST_UNIT_READY | NO_START_STOP
+ },
+ { USB_VENDOR_INSYSTEM, USB_PRODUCT_INSYSTEM_USBCABLE, RID_WILDCARD,
+ UMASS_PROTO_ATAPI | UMASS_PROTO_CBI,
+ NO_TEST_UNIT_READY | NO_START_STOP | ALT_IFACE_1
+ },
+ { USB_VENDOR_IOMEGA, USB_PRODUCT_IOMEGA_ZIP100, RID_WILDCARD,
+ /* XXX This is not correct as there are Zip drives that use ATAPI.
+ */
+ UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+ NO_TEST_UNIT_READY
+ },
+ { USB_VENDOR_MICROTECH, USB_PRODUCT_MICROTECH_DPCM, RID_WILDCARD,
+ UMASS_PROTO_SCSI | UMASS_PROTO_CBI,
+ NO_TEST_UNIT_READY | NO_START_STOP
+ },
+ { USB_VENDOR_OLYMPUS, USB_PRODUCT_OLYMPUS_C1, RID_WILDCARD,
+ UMASS_PROTO_ATAPI | UMASS_PROTO_CBI_I,
+ WRONG_CSWSIG
+ },
+ { USB_VENDOR_SCANLOGIC, USB_PRODUCT_SCANLOGIC_SL11R, RID_WILDCARD,
+ UMASS_PROTO_ATAPI | UMASS_PROTO_CBI_I,
+ NO_QUIRKS
+ },
+ { USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_EUSB, RID_WILDCARD,
+ UMASS_PROTO_ATAPI | UMASS_PROTO_CBI_I,
+ NO_TEST_UNIT_READY | NO_START_STOP | SHUTTLE_INIT
+ },
+ { USB_VENDOR_SONY, USB_PRODUCT_SONY_DSC, RID_WILDCARD,
+ UMASS_PROTO_RBC | UMASS_PROTO_CBI,
+ NO_QUIRKS
+ },
+ { USB_VENDOR_SONY, USB_PRODUCT_SONY_MSC, RID_WILDCARD,
+ UMASS_PROTO_RBC | UMASS_PROTO_CBI,
+ NO_QUIRKS
+ },
+ { USB_VENDOR_YANO, USB_PRODUCT_YANO_U640MO, RID_WILDCARD,
+ UMASS_PROTO_ATAPI | UMASS_PROTO_CBI_I,
+ FORCE_SHORT_INQUIRY
+ },
+
+ { VID_EOT, PID_EOT, RID_EOT, 0, 0 }
+};
+
+
/* the per device structure */
struct umass_softc {
USBBASEDEVICE sc_dev; /* base device */
usbd_device_handle sc_udev; /* USB device */
unsigned char flags; /* various device flags */
-# define UMASS_FLAGS_GONE 0x01 /* devices is no more */
-
- 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
- /* 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. */
-# define WRONG_CSWSIG 0x10
-
- unsigned int proto;
-# define PROTO_UNKNOWN 0x0000 /* unknown protocol */
-# define PROTO_BBB 0x0001 /* USB wire protocol */
-# define PROTO_CBI 0x0002
-# define PROTO_CBI_I 0x0004
-# define PROTO_WIRE 0x00ff /* USB wire protocol mask */
-# define PROTO_SCSI 0x0100 /* command protocol */
-# define PROTO_ATAPI 0x0200
-# define PROTO_UFI 0x0400
-# define PROTO_RBC 0x0800
-# define PROTO_COMMAND 0xff00 /* command protocol mask */
+# define UMASS_FLAGS_GONE 0x01 /* devices is no more */
+
+ u_int16_t proto; /* wire and cmd protocol */
+ u_int16_t quirks; /* they got it almost right */
usbd_interface_handle iface; /* Mass Storage interface */
int ifaceno; /* MS iface number */
@@ -422,7 +485,6 @@ struct umass_softc {
struct scsi_sense cam_scsi_sense;
struct scsi_sense cam_scsi_test_unit_ready;
- int transfer_speed; /* in kb/s */
int maxlun; /* maximum LUN number */
};
@@ -535,13 +597,13 @@ Static int umass_scsi_6_to_10 (unsigned char *cmd, int cmdlen,
unsigned char **rcmd, int *rcmdlen);
/* UFI specific functions */
-#define UFI_COMMAND_LENGTH 12 /* UFI commands are always 12b */
+#define UFI_COMMAND_LENGTH 12 /* UFI commands are always 12 bytes */
Static int umass_ufi_transform (struct umass_softc *sc,
unsigned char *cmd, int cmdlen,
unsigned char **rcmd, int *rcmdlen);
/* ATAPI (8070i) specific functions */
-#define ATAPI_COMMAND_LENGTH 12 /* ATAPI commands are always 12b */
+#define ATAPI_COMMAND_LENGTH 12 /* ATAPI commands are always 12 bytes */
Static int umass_atapi_transform (struct umass_softc *sc,
unsigned char *cmd, int cmdlen,
unsigned char **rcmd, int *rcmdlen);
@@ -570,8 +632,8 @@ MODULE_DEPEND(umass, cam, 1,1,1);
/*
* 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.
+ * description in the softc accordingly. This function is called from both
+ * probe and attach.
*/
Static int
@@ -580,64 +642,18 @@ umass_match_proto(struct umass_softc *sc, usbd_interface_handle iface,
{
usb_device_descriptor_t *dd;
usb_interface_descriptor_t *id;
+ int i;
+ int found = 0;
sc->sc_udev = udev;
-
- /*
- * Fill in sc->drive and sc->proto and return a match
- * value if both are determined and 0 otherwise.
- */
-
- sc->drive = DRIVE_GENERIC;
- sc->proto = PROTO_UNKNOWN;
- sc->transfer_speed = UMASS_DEFAULT_TRANSFER_SPEED;
+ sc->proto = 0;
+ sc->quirks = 0;
dd = usbd_get_device_descriptor(udev);
- if (UGETW(dd->idVendor) == USB_VENDOR_SHUTTLE
- && UGETW(dd->idProduct) == USB_PRODUCT_SHUTTLE_EUSB) {
- sc->drive = SHUTTLE_EUSB;
-#if CBI_I
- sc->proto = PROTO_ATAPI | PROTO_CBI_I;
-#else
- sc->proto = PROTO_ATAPI | PROTO_CBI;
-#endif
- sc->quirks |= NO_TEST_UNIT_READY | NO_START_STOP;
- return(UMATCH_VENDOR_PRODUCT);
- }
-
- if (UGETW(dd->idVendor) == USB_VENDOR_INSYSTEM
- && UGETW(dd->idProduct) == USB_PRODUCT_INSYSTEM_USBCABLE) {
- sc->drive = INSYSTEM_USBCABLE;
- sc->proto = PROTO_ATAPI | PROTO_CBI;
- sc->quirks |= NO_TEST_UNIT_READY | NO_START_STOP;
- return(UMATCH_VENDOR_PRODUCT);
- }
-
- if (UGETW(dd->idVendor) == USB_VENDOR_YANO
- && UGETW(dd->idProduct) == USB_PRODUCT_YANO_U640MO) {
- sc->proto = PROTO_ATAPI | PROTO_CBI_I;
- sc->quirks |= FORCE_SHORT_INQUIRY;
- return(UMATCH_VENDOR_PRODUCT);
- }
-
- if (UGETW(dd->idVendor) == USB_VENDOR_HP
- && UGETW(dd->idProduct) == USB_PRODUCT_HP_CDW8200) {
- sc->drive = SHUTTLE_EUSB;
-#if CBI_I
- sc->proto = PROTO_ATAPI | PROTO_CBI_I;
-#else
- sc->proto = PROTO_ATAPI | PROTO_CBI;
-#endif
- sc->quirks |= NO_TEST_UNIT_READY | NO_START_STOP;
- return(UMATCH_VENDOR_PRODUCT);
- }
-
- if (UGETW(dd->idVendor) == USB_VENDOR_FUJIPHOTO
- && UGETW(dd->idProduct) == USB_PRODUCT_FUJIPHOTO_MASS0100) {
- sc->quirks |= RS_NO_CLEAR_UA;
- }
-
+ /* An entry specifically for Y-E Data devices as they don't fit in the
+ * device description table.
+ */
if (UGETW(dd->idVendor) == USB_VENDOR_YEDATA
&& UGETW(dd->idProduct) == USB_PRODUCT_YEDATA_FLASHBUSTERU) {
@@ -645,13 +661,9 @@ umass_match_proto(struct umass_softc *sc, usbd_interface_handle iface,
* very well.
*/
if (UGETW(dd->bcdDevice) < 0x128) {
- sc->proto = PROTO_UFI | PROTO_CBI;
+ sc->proto = UMASS_PROTO_UFI | UMASS_PROTO_CBI;
} else {
-#if CBI_I
- sc->proto = PROTO_UFI | PROTO_CBI_I;
-#else
- sc->proto = PROTO_UFI | PROTO_CBI;
-#endif
+ sc->proto = UMASS_PROTO_UFI | UMASS_PROTO_CBI_I;
}
/*
@@ -661,60 +673,46 @@ umass_match_proto(struct umass_softc *sc, usbd_interface_handle iface,
if (UGETW(dd->bcdDevice) <= 0x128)
sc->quirks |= NO_TEST_UNIT_READY;
- sc->quirks |= RS_NO_CLEAR_UA;
- sc->transfer_speed = UMASS_FLOPPY_TRANSFER_SPEED;
+ sc->quirks |= RS_NO_CLEAR_UA | FLOPPY_SPEED;
return(UMATCH_VENDOR_PRODUCT);
}
- if (UGETW(dd->idVendor) == USB_VENDOR_MICROTECH
- && UGETW(dd->idProduct) == USB_PRODUCT_MICROTECH_DPCM) {
- /* the cameramate does not provide valid
- class/subclass information. fake it. */
- sc->proto = PROTO_SCSI | PROTO_CBI;
- sc->quirks |= NO_TEST_UNIT_READY | NO_START_STOP;
- return(UMATCH_VENDOR_PRODUCT);
+ /* Check the list of supported devices for a match. While looking,
+ * check for wildcarded and fully matched. First match wins.
+ */
+ for (i = 0; umass_devdescrs[i].vid != VID_EOT && !found; i++) {
+ if (umass_devdescrs[i].vid == UGETW(dd->idVendor)
+ && umass_devdescrs[i].pid == UGETW(dd->idProduct)) {
+ if (umass_devdescrs[i].rid == RID_WILDCARD) {
+ sc->proto = umass_devdescrs[i].proto;
+ sc->quirks = umass_devdescrs[i].quirks;
+ return UMATCH_VENDOR_PRODUCT;
+ } else if (umass_devdescrs[i].rid == UGETW(dd->bcdDevice)) {
+ sc->proto = umass_devdescrs[i].proto;
+ sc->quirks = umass_devdescrs[i].quirks;
+ return UMATCH_VENDOR_PRODUCT_REV;
+ } /* else RID does not match */
+ }
}
+ /* Check for a standards compliant device */
id = usbd_get_interface_descriptor(iface);
if (id == NULL || id->bInterfaceClass != UICLASS_MASS)
return(UMATCH_NONE);
- if (UGETW(dd->idVendor) == USB_VENDOR_SONY
- && id->bInterfaceSubClass==0xff) {
-
- /* Sony DSC devices set the sub class to 0xff
- * instead of 1 (RBC). Fix that here.
- */
- id->bInterfaceSubClass = 1;
-
- /* They also should be able to do higher speed.
- */
- sc->transfer_speed = 500;
- }
-
- if (UGETW(dd->idVendor) == USB_VENDOR_OLYMPUS &&
- UGETW(dd->idProduct) == USB_PRODUCT_OLYMPUS_C1) {
- /*
- * The Olympus C-1 camera uses a different command-status
- * signature.
- */
- sc->quirks |= WRONG_CSWSIG;
- }
-
switch (id->bInterfaceSubClass) {
case UISUBCLASS_SCSI:
- sc->proto |= PROTO_SCSI;
+ sc->proto |= UMASS_PROTO_SCSI;
break;
case UISUBCLASS_UFI:
- sc->transfer_speed = UMASS_FLOPPY_TRANSFER_SPEED;
- sc->proto |= PROTO_UFI;
+ sc->proto |= UMASS_PROTO_UFI;
break;
case UISUBCLASS_RBC:
- sc->proto |= PROTO_RBC;
+ sc->proto |= UMASS_PROTO_RBC;
break;
case UISUBCLASS_SFF8020I:
case UISUBCLASS_SFF8070I:
- sc->proto |= PROTO_ATAPI;
+ sc->proto |= UMASS_PROTO_ATAPI;
break;
default:
DPRINTF(UDMASS_GEN, ("%s: Unsupported command protocol %d\n",
@@ -724,23 +722,14 @@ umass_match_proto(struct umass_softc *sc, usbd_interface_handle iface,
switch (id->bInterfaceProtocol) {
case UIPROTO_MASS_CBI:
- sc->proto |= PROTO_CBI;
+ sc->proto |= UMASS_PROTO_CBI;
break;
case UIPROTO_MASS_CBI_I:
-#if CBI_I
- sc->proto |= PROTO_CBI_I;
-#else
- sc->proto |= PROTO_CBI;
-#endif
+ sc->proto |= UMASS_PROTO_CBI_I;
break;
case UIPROTO_MASS_BBB_OLD:
- sc->proto |= PROTO_BBB;
- break;
case UIPROTO_MASS_BBB:
- sc->drive = ZIP_100;
- sc->proto |= PROTO_BBB;
- sc->transfer_speed = UMASS_ZIP100_TRANSFER_SPEED;
- sc->quirks |= NO_TEST_UNIT_READY;
+ sc->proto |= UMASS_PROTO_BBB;
break;
default:
DPRINTF(UDMASS_GEN, ("%s: Unsupported wire protocol %d\n",
@@ -748,16 +737,6 @@ umass_match_proto(struct umass_softc *sc, usbd_interface_handle iface,
return(UMATCH_NONE);
}
- if (UGETW(dd->idVendor) == USB_VENDOR_SCANLOGIC
- && UGETW(dd->idProduct) == 0x0002) {
- /* ScanLogic SL11R IDE adapter claims to support
- * SCSI, but really needs ATAPI.
- * Note also that these devices need firmware > 0.71
- */
- sc->proto &= ~PROTO_SCSI;
- sc->proto |= PROTO_ATAPI;
- }
-
return(UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO);
}
@@ -798,44 +777,54 @@ USB_ATTACH(umass)
(void) umass_match_proto(sc, sc->iface, uaa->device);
id = usbd_get_interface_descriptor(sc->iface);
- printf("%s: %s", USBDEVNAME(sc->sc_dev), devinfo);
+ printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo);
#ifdef UMASS_DEBUG
- printf(", ");
- switch (sc->proto&PROTO_COMMAND) {
- case PROTO_SCSI:
+ printf("%s: ", USBDEVNAME(sc->sc_dev));
+ switch (sc->proto&UMASS_PROTO_COMMAND) {
+ case UMASS_PROTO_SCSI:
printf("SCSI");
break;
- case PROTO_ATAPI:
+ case UMASS_PROTO_ATAPI:
printf("8070i (ATAPI)");
break;
- case PROTO_UFI:
+ case UMASS_PROTO_UFI:
printf("UFI");
break;
- case PROTO_RBC:
+ case UMASS_PROTO_RBC:
printf("RBC");
break;
default:
- printf("(unknown 0x%02x)", sc->proto&PROTO_COMMAND);
+ printf("(unknown 0x%02x)", sc->proto&UMASS_PROTO_COMMAND);
break;
}
printf(" over ");
- switch (sc->proto&PROTO_WIRE) {
- case PROTO_BBB:
+ switch (sc->proto&UMASS_PROTO_WIRE) {
+ case UMASS_PROTO_BBB:
printf("Bulk-Only");
break;
- case PROTO_CBI: /* uses Comand/Bulk pipes */
+ case UMASS_PROTO_CBI: /* uses Comand/Bulk pipes */
printf("CBI");
break;
- case PROTO_CBI_I: /* uses Comand/Bulk/Interrupt pipes */
+ case UMASS_PROTO_CBI_I: /* uses Comand/Bulk/Interrupt pipes */
printf("CBI with CCI");
+#ifndef CBI_I
+ printf(" (using CBI)");
+#endif
break;
default:
- printf("(unknown 0x%02x)", sc->proto&PROTO_WIRE);
+ printf("(unknown 0x%02x)", sc->proto&UMASS_PROTO_WIRE);
}
+ printf("; quirks = 0x%04x\n", sc->quirks);
#endif
- printf("\n");
- if (sc->drive == INSYSTEM_USBCABLE) {
+#ifndef CBI_I
+ if (sc->proto & UMASS_PROTO_CBI_I) {
+ /* See beginning of file for comment on the use of CBI with CCI */
+ sc->proto = (sc->proto & ~UMASS_PROTO_CBI_I) | UMASS_PROTO_CBI;
+ }
+#endif
+
+ if (sc->quirks & ALT_IFACE_1) {
err = usbd_set_interface(0, 1);
if (err) {
DPRINTF(UDMASS_USB, ("%s: could not switch to "
@@ -870,7 +859,7 @@ USB_ATTACH(umass)
} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT
&& (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) {
sc->bulkout = ed->bEndpointAddress;
- } else if (sc->proto & PROTO_CBI_I
+ } else if (sc->proto & UMASS_PROTO_CBI_I
&& UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN
&& (ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT) {
sc->intrin = ed->bEndpointAddress;
@@ -886,7 +875,7 @@ USB_ATTACH(umass)
/* check whether we found all the endpoints we need */
if (!sc->bulkin || !sc->bulkout
- || (sc->proto & PROTO_CBI_I && !sc->intrin) ) {
+ || (sc->proto & UMASS_PROTO_CBI_I && !sc->intrin) ) {
DPRINTF(UDMASS_USB, ("%s: endpoint not found %d/%d/%d\n",
USBDEVNAME(sc->sc_dev),
sc->bulkin, sc->bulkout, sc->intrin));
@@ -922,7 +911,7 @@ USB_ATTACH(umass)
* code for handling the data on that endpoint simpler. No data
* arriving concurently.
*/
- if (sc->proto & PROTO_CBI_I) {
+ if (sc->proto & UMASS_PROTO_CBI_I) {
err = usbd_open_pipe(sc->iface, sc->intrin,
USBD_EXCLUSIVE_USE, &sc->intrin_pipe);
if (err) {
@@ -948,11 +937,11 @@ USB_ATTACH(umass)
}
/* Initialise the wire protocol specific methods */
- if (sc->proto & PROTO_BBB) {
+ if (sc->proto & UMASS_PROTO_BBB) {
sc->reset = umass_bbb_reset;
sc->transfer = umass_bbb_transfer;
sc->state = umass_bbb_state;
- } else if ((sc->proto & PROTO_CBI) || (sc->proto & PROTO_CBI_I)) {
+ } else if (sc->proto & (UMASS_PROTO_CBI|UMASS_PROTO_CBI_I)) {
sc->reset = umass_cbi_reset;
sc->transfer = umass_cbi_transfer;
sc->state = umass_cbi_state;
@@ -963,36 +952,36 @@ USB_ATTACH(umass)
#endif
}
- if (sc->proto & PROTO_SCSI)
+ if (sc->proto & UMASS_PROTO_SCSI)
sc->transform = umass_scsi_transform;
- else if (sc->proto & PROTO_UFI)
+ else if (sc->proto & UMASS_PROTO_UFI)
sc->transform = umass_ufi_transform;
- else if (sc->proto & PROTO_ATAPI)
+ else if (sc->proto & UMASS_PROTO_ATAPI)
sc->transform = umass_atapi_transform;
- else if (sc->proto & PROTO_RBC)
+ else if (sc->proto & UMASS_PROTO_RBC)
sc->transform = umass_rbc_transform;
#ifdef UMASS_DEBUG
else
panic("No transformation defined for command proto 0x%02x\n",
- sc->proto & PROTO_COMMAND);
+ sc->proto & UMASS_PROTO_COMMAND);
#endif
/* From here onwards the device can be used. */
- if (sc->drive == SHUTTLE_EUSB)
+ if (sc->quirks & SHUTTLE_INIT)
umass_init_shuttle(sc);
/* Get the maximum LUN supported by the device.
*/
- if ((sc->proto & PROTO_WIRE) == PROTO_BBB)
+ if ((sc->proto & UMASS_PROTO_WIRE) == UMASS_PROTO_BBB)
sc->maxlun = umass_bbb_get_max_lun(sc);
else
sc->maxlun = 0;
- if ((sc->proto & PROTO_SCSI) ||
- (sc->proto & PROTO_ATAPI) ||
- (sc->proto & PROTO_UFI) ||
- (sc->proto & PROTO_RBC)) {
+ if ((sc->proto & UMASS_PROTO_SCSI) ||
+ (sc->proto & UMASS_PROTO_ATAPI) ||
+ (sc->proto & UMASS_PROTO_UFI) ||
+ (sc->proto & UMASS_PROTO_RBC)) {
/* Prepare the SCSI command block */
sc->cam_scsi_sense.opcode = REQUEST_SENSE;
sc->cam_scsi_test_unit_ready.opcode = TEST_UNIT_READY;
@@ -1033,10 +1022,10 @@ USB_DETACH(umass)
sc->flags |= UMASS_FLAGS_GONE;
- if ((sc->proto & PROTO_SCSI) ||
- (sc->proto & PROTO_ATAPI) ||
- (sc->proto & PROTO_UFI) ||
- (sc->proto & PROTO_RBC))
+ if ((sc->proto & UMASS_PROTO_SCSI) ||
+ (sc->proto & UMASS_PROTO_ATAPI) ||
+ (sc->proto & UMASS_PROTO_UFI) ||
+ (sc->proto & UMASS_PROTO_RBC))
/* detach the device from the SCSI host controller (SIM) */
err = umass_cam_detach(sc);
@@ -1065,11 +1054,14 @@ umass_init_shuttle(struct umass_softc *sc)
* command does.
*/
req.bmRequestType = UT_READ_VENDOR_DEVICE;
- req.bRequest = 1;
+ req.bRequest = 1; /* XXX unknown command */
USETW(req.wValue, 0);
USETW(req.wIndex, sc->ifaceno);
USETW(req.wLength, sizeof status);
(void) usbd_do_request(sc->sc_udev, &req, &status);
+
+ DPRINTF(UDMASS_GEN, ("%s: Shuttle init returned 0x%02x%02x\n",
+ USBDEVNAME(sc->sc_dev), status[0], status[1]));
}
/*
@@ -1167,7 +1159,7 @@ umass_bbb_reset(struct umass_softc *sc, int status)
{
usbd_device_handle udev;
- KASSERT(sc->proto & PROTO_BBB,
+ KASSERT(sc->proto & UMASS_PROTO_BBB,
("sc->proto == 0x%02x wrong for umass_bbb_reset\n", sc->proto));
/*
@@ -1209,7 +1201,7 @@ umass_bbb_transfer(struct umass_softc *sc, int lun, void *cmd, int cmdlen,
void *data, int datalen, int dir,
transfer_cb_f cb, void *priv)
{
- KASSERT(sc->proto & PROTO_BBB,
+ KASSERT(sc->proto & UMASS_PROTO_BBB,
("sc->proto == 0x%02x wrong for umass_bbb_transfer\n",
sc->proto));
@@ -1278,7 +1270,7 @@ umass_bbb_transfer(struct umass_softc *sc, int lun, void *cmd, int cmdlen,
* We fill in all the fields, so there is no need to bzero it first.
*/
USETDW(sc->cbw.dCBWSignature, CBWSIGNATURE);
- /* We don't care what the initial value was, as long as the values are unique */
+ /* We don't care about the initial value, as long as the values are unique */
USETDW(sc->cbw.dCBWTag, UGETDW(sc->cbw.dCBWTag) + 1);
USETDW(sc->cbw.dCBWDataTransferLength, datalen);
/* DIR_NONE is treated as DIR_OUT (0x00) */
@@ -1317,7 +1309,7 @@ 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,
+ KASSERT(sc->proto & UMASS_PROTO_BBB,
("sc->proto == 0x%02x wrong for umass_bbb_state\n",sc->proto));
/*
@@ -1533,12 +1525,13 @@ umass_bbb_state(usbd_xfer_handle xfer, usbd_private_handle priv,
USBDEVNAME(sc->sc_dev),
sc->transfer_actlen, sc->transfer_datalen);
} else if (sc->transfer_datalen - sc->transfer_actlen
- != UGETDW(sc->csw.dCSWDataResidue)) {
- DPRINTF(UDMASS_BBB, ("%s: residue=%d != calc.res.=%d\n",
+ != UGETDW(sc->csw.dCSWDataResidue)
+ && !(sc->quirks & IGNORE_RESIDUE)) {
+ printf("%s: Residue incorrect, was %d, "
+ "should've been %d\n",
USBDEVNAME(sc->sc_dev),
UGETDW(sc->csw.dCSWDataResidue),
- sc->transfer_datalen - sc->transfer_actlen));
-
+ sc->transfer_datalen-sc->transfer_actlen);
umass_bbb_reset(sc, STATUS_WIRE_FAILED);
return;
@@ -1658,7 +1651,7 @@ umass_cbi_adsc(struct umass_softc *sc, char *buffer, int buflen,
{
usbd_device_handle udev;
- KASSERT(sc->proto & (PROTO_CBI|PROTO_CBI_I),
+ KASSERT(sc->proto & (UMASS_PROTO_CBI|UMASS_PROTO_CBI_I),
("sc->proto == 0x%02x wrong for umass_cbi_adsc\n",sc->proto));
usbd_interface2device_handle(sc->iface, &udev);
@@ -1679,7 +1672,7 @@ umass_cbi_reset(struct umass_softc *sc, int status)
int i;
# define SEND_DIAGNOSTIC_CMDLEN 12
- KASSERT(sc->proto & (PROTO_CBI|PROTO_CBI_I),
+ KASSERT(sc->proto & (UMASS_PROTO_CBI|UMASS_PROTO_CBI_I),
("sc->proto == 0x%02x wrong for umass_cbi_reset\n",sc->proto));
/*
@@ -1726,7 +1719,7 @@ umass_cbi_transfer(struct umass_softc *sc, int lun,
void *cmd, int cmdlen, void *data, int datalen, int dir,
transfer_cb_f cb, void *priv)
{
- KASSERT(sc->proto & (PROTO_CBI|PROTO_CBI_I),
+ KASSERT(sc->proto & (UMASS_PROTO_CBI|UMASS_PROTO_CBI_I),
("sc->proto == 0x%02x wrong for umass_cbi_transfer\n",
sc->proto));
@@ -1779,7 +1772,7 @@ 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),
+ KASSERT(sc->proto & (UMASS_PROTO_CBI|UMASS_PROTO_CBI_I),
("sc->proto == 0x%02x wrong for umass_cbi_state\n", sc->proto));
/*
@@ -1835,7 +1828,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->proto & PROTO_CBI_I) {
+ } else if (sc->proto & UMASS_PROTO_CBI_I) {
DPRINTF(UDMASS_CBI, ("%s: no data phase\n",
USBDEVNAME(sc->sc_dev)));
sc->transfer_state = TSTATE_CBI_STATUS;
@@ -1883,7 +1876,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->proto & PROTO_CBI_I) {
+ if (sc->proto & UMASS_PROTO_CBI_I) {
sc->transfer_state = TSTATE_CBI_STATUS;
if (umass_setup_transfer(sc, sc->intrin_pipe,
&sc->sbl, sizeof(sc->sbl),
@@ -1922,7 +1915,7 @@ umass_cbi_state(usbd_xfer_handle xfer, usbd_private_handle priv,
/* Dissect the information in the buffer */
- if (sc->proto & PROTO_UFI) {
+ if (sc->proto & UMASS_PROTO_UFI) {
int status;
/* Section 3.4.3.1.3 specifies that the UFI command
@@ -2156,11 +2149,11 @@ umass_cam_attach(struct umass_softc *sc)
cam_sim_path(umass_sim), USBDEVUNIT(sc->sc_dev));
if (!cold) {
- /* Notify CAM of the new device. Any failure is benign, as the
- * user can still do it by hand (camcontrol rescan <busno>).
- * Only do this if we are not booting, because CAM does a scan
- * after booting has completed, when interrupts have been
- * enabled.
+ /* Notify CAM of the new device after 1 second delay. Any
+ * failure is benign, as the user can still do it by hand
+ * (camcontrol rescan <busno>). Only do this if we are not
+ * booting, because CAM does a scan after booting has
+ * completed, when interrupts have been enabled.
*/
/* XXX This will bomb if the driver is unloaded between attach
@@ -2179,9 +2172,6 @@ umass_cam_attach(struct umass_softc *sc)
Static int
umass_cam_detach_sim()
{
- if (umass_sim)
- return(EBUSY); /* XXX CAM can't handle disappearing SIMs yet */
-
if (umass_sim) {
if (xpt_bus_deregister(cam_sim_path(umass_sim)))
cam_sim_free(umass_sim, /*free_devq*/TRUE);
@@ -2323,7 +2313,7 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb)
if (sc->transfer_state != TSTATE_IDLE) {
DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_SCSI_IO: "
- "I/O requested while busy (state %d, %s)\n",
+ "I/O in progress, deferring (state %d, %s)\n",
USBDEVNAME(sc->sc_dev), cam_sim_path(umass_sim),
ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
sc->transfer_state,states[sc->transfer_state]));
@@ -2391,18 +2381,24 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb)
cpi->hba_misc = 0;
cpi->hba_eng_cnt = 0;
cpi->max_target = UMASS_SCSIID_MAX; /* one target */
- if (sc == NULL)
- cpi->max_lun = 0;
- else
- cpi->max_lun = sc->maxlun;
cpi->initiator_id = UMASS_SCSIID_HOST;
strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
strncpy(cpi->hba_vid, "USB SCSI", HBA_IDLEN);
strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
cpi->unit_number = cam_sim_unit(sim);
cpi->bus_id = UMASS_SCSI_BUS;
- if (sc)
- cpi->base_transfer_speed = sc->transfer_speed;
+
+ if (sc == NULL) {
+ cpi->base_transfer_speed = 0;
+ cpi->max_lun = 0;
+ } else {
+ if (sc->quirks & FLOPPY_SPEED) {
+ cpi->base_transfer_speed = UMASS_FLOPPY_TRANSFER_SPEED;
+ } else {
+ cpi->base_transfer_speed = UMASS_DEFAULT_TRANSFER_SPEED;
+ }
+ cpi->max_lun = sc->maxlun;
+ }
cpi->ccb_h.status = CAM_REQ_CMP;
xpt_done(ccb);
@@ -2445,35 +2441,16 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb)
}
case XPT_CALC_GEOMETRY:
{
+#ifdef UMASS_DEBUG
struct ccb_calc_geometry *ccg = &ccb->ccg;
-
+#endif
DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_CALC_GEOMETRY: "
- "Volume size = %d\n",
+ "Volume size = %d (unimplemented)\n",
USBDEVNAME(sc->sc_dev), cam_sim_path(umass_sim),
ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
ccg->volume_size));
- /* XXX We should probably ask the drive for the details
- * instead of cluching them up ourselves
- */
- if (sc->drive == ZIP_100) {
- ccg->heads = 64;
- ccg->secs_per_track = 32;
- ccg->cylinders = ccg->volume_size / ccg->heads
- / ccg->secs_per_track;
- ccb->ccb_h.status = CAM_REQ_CMP;
- break;
- } else if (sc->proto & PROTO_UFI) {
- ccg->heads = 2;
- if (ccg->volume_size == 2880)
- ccg->secs_per_track = 18;
- else
- ccg->secs_per_track = 9;
- ccg->cylinders = 80;
- break;
- } else {
- ccb->ccb_h.status = CAM_REQ_CMP_ERR;
- }
+ ccb->ccb_h.status = CAM_REQ_CMP_ERR;
xpt_done(ccb);
break;
@@ -2608,9 +2585,9 @@ umass_cam_sense_cb(struct umass_softc *sc, void *priv, int residue, int status)
switch (status) {
case STATUS_CMD_OK:
case STATUS_CMD_UNKNOWN:
- /* Getting sense data succeeded. The length of the sense data
- * is not returned in any way. The sense data itself contains
- * the length of the sense data that is valid.
+ case STATUS_CMD_FAILED:
+ /* Getting sense data always succeeds (apart from wire
+ * failures).
*/
if (sc->quirks & RS_NO_CLEAR_UA
&& csio->cdb_io.cdb_bytes[0] == INQUIRY
@@ -2632,11 +2609,13 @@ umass_cam_sense_cb(struct umass_softc *sc, void *priv, int residue, int status)
(csio->cdb_io.cdb_bytes[0] == READ_CAPACITY) &&
((csio->sense_data.flags & SSD_KEY)
== SSD_KEY_UNIT_ATTENTION)) {
- /* Ignore unit attention errors in the case where
- * the Unit Attention state is not cleared on
- * REQUEST SENSE. They will appear again at the next
- * command.
- */
+
+ /* Some devices do not clear the unit attention error
+ * on request sense. We insert a test unit ready
+ * command to make sure we clear the unit attention
+ * condition.
+ */
+
ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR
| CAM_AUTOSNS_VALID;
csio->scsi_status = SCSI_STATUS_CHECK_COND;
@@ -2867,8 +2846,13 @@ umass_ufi_transform(struct umass_softc *sc, unsigned char *cmd, int cmdlen,
*rcmdlen = UFI_COMMAND_LENGTH;
memset(*rcmd, 0, UFI_COMMAND_LENGTH);
+ /* Convert 6 byte commands that have a 10 byte version as well to the
+ * longer one. Many devices do not understand the 6 byte ones and
+ * wedge, mainly the drives that use the ATAPI & UFI command sets.
+ */
if (umass_scsi_6_to_10(cmd, cmdlen, rcmd, rcmdlen))
return (1);
+
switch (cmd[0]) {
/* Commands of which the format has been verified. They should work.
* Copy the command into the (zeroed out) destination buffer.
OpenPOWER on IntegriCloud