Attached is a patch for 5.x that adds 2 new quirks.  NO_INQUIRY never
sends the device an inquiry and instead responds with some valid generic
data.  NO_INQUIRY_EVPD allows normal inquiries but returns "invalid
request" for inquiries with the evpd bit set.  This is due to the fact
that some devices cannot handle these commands (which is horribly broken).

This patch also fixes the umass device matching code so that wildcards for
product and vendor are also honored.  Before, only the revision wildcard
did anything.

Be careful with this actual patch since it will quirk ALL umass devices,
not any specific one (see the XXX part).  You can modify it to be more
specific to your device.  The version I plan to commit has a check for all
values set to wildcard and will skip such quirks.

If you were having problems attaching a USB mass storage device (usually
flash drives), please try this and report back to me.  Try it with each of
the quirks and see which is necessary (both are on by default).

-Nate
Index: umass.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/usb/umass.c,v
retrieving revision 1.78
diff -u -r1.78 umass.c
--- umass.c     11 Mar 2003 01:55:11 -0000      1.78
+++ umass.c     19 Mar 2003 01:50:00 -0000
@@ -319,9 +319,18 @@
 #      define NO_GETMAXLUN             0x0100
        /* The device uses a weird CSWSIGNATURE. */
 #      define WRONG_CSWSIG             0x0200
+       /* Device cannot handle INQUIRY so fake a generic response */
+#      define NO_INQUIRY               0x0400
+       /* Device cannot handle INQUIRY EVPD, return CHECK CONDITION */
+#      define NO_INQUIRY_EVPD          0x0800
 };
 
 Static struct umass_devdescr_t umass_devdescrs[] = {
+       /* XXX this is for testing only and matches ALL devices XXX */
+       { VID_WILDCARD, PID_WILDCARD, RID_WILDCARD,
+         UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+         NO_INQUIRY | NO_INQUIRY_EVPD
+       },
        { USB_VENDOR_ASAHIOPTICAL, USB_PRODUCT_ASAHIOPTICAL_OPTIO230,
          RID_WILDCARD,
          UMASS_PROTO_ATAPI | UMASS_PROTO_CBI_I,
@@ -542,7 +551,11 @@
 #endif
 
 Static struct cam_sim *umass_sim;      /* SCSI Interface Module */
-
+/* If device cannot return valid inquiry data, fake it */
+Static uint8_t fake_inq_data[SHORT_INQUIRY_LENGTH] = {
+       0, /*removable*/ 0x80, SCSI_REV_2, SCSI_REV_2,
+       /*additional_length*/ 31, 0, 0, 0
+};
 
 /* USB device probe/attach/detach functions */
 USB_DECLARE_DRIVER(umass);
@@ -708,16 +721,19 @@
         * 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].vid == UGETW(dd->idVendor) ||
+                    umass_devdescrs[i].vid == VID_WILDCARD)
+                && (umass_devdescrs[i].pid == UGETW(dd->idProduct) ||
+                    umass_devdescrs[i].pid == PID_WILDCARD)) {
                        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;
+                               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 */
                }
        }
@@ -2386,7 +2402,39 @@
                 */
 
                if (sc->transform(sc, cmd, cmdlen, &rcmd, &rcmdlen)) {
-                       if ((sc->quirks & FORCE_SHORT_INQUIRY) && (rcmd[0] == 
INQUIRY)) {
+                       /* 
+                        * Handle EVPD inquiry for broken devices first
+                        * NO_INQUIRY also implies NO_INQUIRY_EVPD
+                        */
+                       if ((sc->quirks & (NO_INQUIRY_EVPD | NO_INQUIRY)) &&
+                           rcmd[0] == INQUIRY && (rcmd[1] & SI_EVPD)) {
+                               struct scsi_sense_data *sense;
+
+                               sense = &ccb->csio.sense_data;
+                               bzero(sense, sizeof(*sense));
+                               sense->error_code = SSD_CURRENT_ERROR;
+                               sense->flags = SSD_KEY_ILLEGAL_REQUEST;
+                               sense->add_sense_code = 0x24;
+                               sense->extra_len = 10;
+                               ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
+                               ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR |
+                                   CAM_AUTOSNS_VALID;
+                               xpt_done(ccb);
+                               return;
+                       }
+                       /* Return fake inquiry data for broken devices */
+                       if ((sc->quirks & NO_INQUIRY) && rcmd[0] == INQUIRY) {
+                               struct ccb_scsiio *csio = &ccb->csio;
+
+                               memcpy(csio->data_ptr, &fake_inq_data,
+                                   sizeof(fake_inq_data));
+                               csio->scsi_status = SCSI_STATUS_OK;
+                               ccb->ccb_h.status = CAM_REQ_CMP;
+                               xpt_done(ccb);
+                               return;
+                       }
+                       if ((sc->quirks & FORCE_SHORT_INQUIRY) &&
+                           rcmd[0] == INQUIRY) {
                                csio->dxfer_len = SHORT_INQUIRY_LENGTH;
                        }
                        sc->transfer(sc, ccb->ccb_h.target_lun, rcmd, rcmdlen,

Reply via email to