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,