diff options
author | Joshua M. Clulow <josh@sysmgr.org> | 2021-06-29 11:29:52 -0700 |
---|---|---|
committer | Joshua M. Clulow <josh@sysmgr.org> | 2021-06-29 11:29:52 -0700 |
commit | 47b9747f90c9eb7e841fb67c110f8cc5fca20cd1 (patch) | |
tree | 8c81147b386ecc6f129e4a3b9c6e25452bf95804 | |
parent | a547d3069fbb76f7603ab6fe082827b54e008a3e (diff) | |
download | illumos-joyent-47b9747f90c9eb7e841fb67c110f8cc5fca20cd1.tar.gz |
13817 scsa2usb quirks list does not correctly use revision field
Reviewed by: Toomas Soome <tsoome@me.com>
Approved by: Richard Lowe <richlowe@richlowe.net>
-rw-r--r-- | usr/src/uts/common/io/usb/scsa2usb/scsa2usb.c | 199 | ||||
-rw-r--r-- | usr/src/uts/common/sys/usb/scsa2usb/scsa2usb.h | 18 |
2 files changed, 105 insertions, 112 deletions
diff --git a/usr/src/uts/common/io/usb/scsa2usb/scsa2usb.c b/usr/src/uts/common/io/usb/scsa2usb/scsa2usb.c index c35e1bdb6a..2e440ef448 100644 --- a/usr/src/uts/common/io/usb/scsa2usb/scsa2usb.c +++ b/usr/src/uts/common/io/usb/scsa2usb/scsa2usb.c @@ -78,7 +78,7 @@ static int scsa2usb_info(dev_info_t *, ddi_info_cmd_t, void *, void **); static int scsa2usb_detach(dev_info_t *, ddi_detach_cmd_t); static int scsa2usb_cleanup(dev_info_t *, scsa2usb_state_t *); -static void scsa2usb_validate_attrs(scsa2usb_state_t *); +static void scsa2usb_detect_quirks(scsa2usb_state_t *); static void scsa2usb_create_luns(scsa2usb_state_t *); static int scsa2usb_is_usb(dev_info_t *); static void scsa2usb_fake_inquiry(scsa2usb_state_t *, @@ -124,9 +124,9 @@ static int scsa2usb_scsi_bus_unconfig(dev_info_t *, uint_t, /* functions for command and transport support */ static void scsa2usb_prepare_pkt(scsa2usb_state_t *, struct scsi_pkt *); static int scsa2usb_cmd_transport(scsa2usb_state_t *, scsa2usb_cmd_t *); -static int scsa2usb_check_bulkonly_blacklist_attrs(scsa2usb_state_t *, - scsa2usb_cmd_t *, uchar_t); -static int scsa2usb_check_ufi_blacklist_attrs(scsa2usb_state_t *, uchar_t, +static int scsa2usb_check_bulkonly_quirks(scsa2usb_state_t *, + scsa2usb_cmd_t *); +static int scsa2usb_check_ufi_quirks(scsa2usb_state_t *, scsa2usb_cmd_t *); static int scsa2usb_handle_scsi_cmd_sub_class(scsa2usb_state_t *, scsa2usb_cmd_t *, struct scsi_pkt *); @@ -262,71 +262,75 @@ static char *scsa2usb_cmds[] = { /* - * Mass-Storage devices masquerade as "sd" disks. - * - * These devices may not support all SCSI CDBs in their - * entirety due to their hardware implementation limitations. + * Mass-Storage devices masquerade as "sd" disks. These devices may not + * support all SCSI CDBs in their entirety due to implementation + * limitations. * - * As such, following is a list of some of the black-listed - * devices w/ the attributes that they do not support. - * (See scsa2usb.h for description on each attribute) + * The following table contains a list of quirks for devices that are known to + * misbehave. See the comments in scsa2usb.h for a description of each + * quirk attribute. + */ + +/* + * Either the product ID (q_pid) or the revision number (q_rev) can be a + * wildcard match using this constant: */ -#define X ((uint16_t)(-1)) - -static struct blacklist { - uint16_t idVendor; /* vendor ID */ - uint16_t idProduct; /* product ID */ - uint16_t bcdDevice; /* device release number in bcd */ - uint16_t attributes; /* attributes to blacklist */ -} scsa2usb_blacklist[] = { +#define X UINT16_MAX + +static struct quirk { + uint16_t q_vid; /* Vendor ID */ + uint16_t q_pid; /* Product ID */ + uint16_t q_rev; /* Device revision number in BCD */ + uint16_t q_attr; /* Quirk attributes for this device */ +} scsa2usb_quirks[] = { /* Iomega Zip100 drive (prototype) with flaky bridge */ - {MS_IOMEGA_VID, MS_IOMEGA_PID1_ZIP100, 0, + {MS_IOMEGA_VID, MS_IOMEGA_PID1_ZIP100, X, SCSA2USB_ATTRS_GET_LUN | SCSA2USB_ATTRS_PM}, /* Iomega Zip100 drive (newer model) with flaky bridge */ - {MS_IOMEGA_VID, MS_IOMEGA_PID2_ZIP100, 0, + {MS_IOMEGA_VID, MS_IOMEGA_PID2_ZIP100, X, SCSA2USB_ATTRS_GET_LUN | SCSA2USB_ATTRS_PM}, /* Iomega Zip100 drive (newer model) with flaky bridge */ - {MS_IOMEGA_VID, MS_IOMEGA_PID3_ZIP100, 0, + {MS_IOMEGA_VID, MS_IOMEGA_PID3_ZIP100, X, SCSA2USB_ATTRS_GET_LUN | SCSA2USB_ATTRS_PM}, /* Iomega Zip250 drive */ - {MS_IOMEGA_VID, MS_IOMEGA_PID_ZIP250, 0, SCSA2USB_ATTRS_GET_LUN}, + {MS_IOMEGA_VID, MS_IOMEGA_PID_ZIP250, X, SCSA2USB_ATTRS_GET_LUN}, /* Iomega Clik! drive */ - {MS_IOMEGA_VID, MS_IOMEGA_PID_CLIK, 0, + {MS_IOMEGA_VID, MS_IOMEGA_PID_CLIK, X, SCSA2USB_ATTRS_GET_LUN | SCSA2USB_ATTRS_START_STOP}, /* Kingston DataTraveler Stick / PNY Attache Stick */ - {MS_TOSHIBA_VID, MS_TOSHIBA_PID0, 0, + {MS_TOSHIBA_VID, MS_TOSHIBA_PID0, X, SCSA2USB_ATTRS_GET_LUN}, /* PNY Floppy drive */ - {MS_PNY_VID, MS_PNY_PID0, 0, + {MS_PNY_VID, MS_PNY_PID0, X, SCSA2USB_ATTRS_GET_LUN}, /* SMSC floppy Device - and its clones */ - {MS_SMSC_VID, X, 0, SCSA2USB_ATTRS_START_STOP}, + {MS_SMSC_VID, X, X, SCSA2USB_ATTRS_START_STOP}, /* Hagiwara SmartMedia Device */ - {MS_HAGIWARA_SYS_COM_VID, MS_HAGIWARA_SYSCOM_PID1, 0, + {MS_HAGIWARA_SYS_COM_VID, MS_HAGIWARA_SYSCOM_PID1, X, SCSA2USB_ATTRS_GET_LUN | SCSA2USB_ATTRS_START_STOP}, /* Hagiwara CompactFlash Device */ - {MS_HAGIWARA_SYS_COM_VID, MS_HAGIWARA_SYSCOM_PID2, 0, + {MS_HAGIWARA_SYS_COM_VID, MS_HAGIWARA_SYSCOM_PID2, X, SCSA2USB_ATTRS_GET_LUN | SCSA2USB_ATTRS_START_STOP}, /* Hagiwara SmartMedia/CompactFlash Combo Device */ - {MS_HAGIWARA_SYS_COM_VID, MS_HAGIWARA_SYSCOM_PID3, 0, + {MS_HAGIWARA_SYS_COM_VID, MS_HAGIWARA_SYSCOM_PID3, X, SCSA2USB_ATTRS_START_STOP}, /* Hagiwara new SM Device */ - {MS_HAGIWARA_SYS_COM_VID, MS_HAGIWARA_SYSCOM_PID4, 0, + {MS_HAGIWARA_SYS_COM_VID, MS_HAGIWARA_SYSCOM_PID4, X, SCSA2USB_ATTRS_GET_LUN | SCSA2USB_ATTRS_START_STOP}, /* Hagiwara new CF Device */ - {MS_HAGIWARA_SYS_COM_VID, MS_HAGIWARA_SYSCOM_PID5, 0, + {MS_HAGIWARA_SYS_COM_VID, MS_HAGIWARA_SYSCOM_PID5, X, SCSA2USB_ATTRS_GET_LUN | SCSA2USB_ATTRS_START_STOP}, /* Mitsumi CD-RW Device(s) */ @@ -334,63 +338,60 @@ static struct blacklist { SCSA2USB_ATTRS_GET_CONF | SCSA2USB_ATTRS_GET_PERF}, /* Neodio Technologies Corporation SM/CF/MS/SD Combo Device */ - {MS_NEODIO_VID, MS_NEODIO_DEVICE_3050, 0, + {MS_NEODIO_VID, MS_NEODIO_DEVICE_3050, X, SCSA2USB_ATTRS_MODE_SENSE }, /* dumb flash devices */ - {MS_SONY_FLASH_VID, MS_SONY_FLASH_PID, 0, + {MS_SONY_FLASH_VID, MS_SONY_FLASH_PID, X, SCSA2USB_ATTRS_REDUCED_CMD}, - {MS_TREK_FLASH_VID, MS_TREK_FLASH_PID, 0, + {MS_TREK_FLASH_VID, MS_TREK_FLASH_PID, X, SCSA2USB_ATTRS_REDUCED_CMD}, - {MS_PENN_FLASH_VID, MS_PENN_FLASH_PID, 0, + {MS_PENN_FLASH_VID, MS_PENN_FLASH_PID, X, SCSA2USB_ATTRS_REDUCED_CMD}, /* SimpleTech UCF-100 CF Device */ - {MS_SIMPLETECH_VID, MS_SIMPLETECH_PID1, 0, + {MS_SIMPLETECH_VID, MS_SIMPLETECH_PID1, X, SCSA2USB_ATTRS_REDUCED_CMD}, {MS_ADDONICS_CARD_READER_VID, MS_ADDONICS_CARD_READER_PID, - 0, SCSA2USB_ATTRS_REDUCED_CMD}, + X, SCSA2USB_ATTRS_REDUCED_CMD}, /* Acomdata 80GB USB/1394 Hard Disk */ - {MS_ACOMDATA_VID, MS_ACOMDATA_PID1, 0, + {MS_ACOMDATA_VID, MS_ACOMDATA_PID1, X, SCSA2USB_ATTRS_USE_CSW_RESIDUE}, /* OTi6828 Flash Disk */ - {MS_OTI_VID, MS_OTI_DEVICE_6828, 0, + {MS_OTI_VID, MS_OTI_DEVICE_6828, X, SCSA2USB_ATTRS_USE_CSW_RESIDUE}, /* AMI Virtual Floppy */ - {MS_AMI_VID, MS_AMI_VIRTUAL_FLOPPY, 0, + {MS_AMI_VID, MS_AMI_VIRTUAL_FLOPPY, X, SCSA2USB_ATTRS_NO_MEDIA_CHECK}, /* ScanLogic USB Storage Device */ - {MS_SCANLOGIC_VID, MS_SCANLOGIC_PID1, 0, + {MS_SCANLOGIC_VID, MS_SCANLOGIC_PID1, X, SCSA2USB_ATTRS_NO_CAP_ADJUST}, /* Super Top USB 2.0 IDE Device */ - {MS_SUPERTOP_VID, MS_SUPERTOP_DEVICE_6600, 0, + {MS_SUPERTOP_VID, MS_SUPERTOP_DEVICE_6600, X, SCSA2USB_ATTRS_USE_CSW_RESIDUE}, /* Aigo Miniking Device NEHFSP14 */ - {MS_AIGO_VID, MS_AIGO_DEVICE_6981, 0, + {MS_AIGO_VID, MS_AIGO_DEVICE_6981, X, SCSA2USB_ATTRS_USE_CSW_RESIDUE}, /* Alcor Micro Corp 6387 flash disk */ - {MS_ALCOR_VID, MS_ALCOR_PID0, 0, + {MS_ALCOR_VID, MS_ALCOR_PID0, X, SCSA2USB_ATTRS_GET_LUN | SCSA2USB_ATTRS_USE_CSW_RESIDUE}, /* Western Digital External HDD */ - {MS_WD_VID, MS_WD_PID, 0, - SCSA2USB_ATTRS_INQUIRY_EVPD} + {MS_WD_VID, MS_WD_PID, X, + SCSA2USB_ATTRS_INQUIRY_EVPD}, }; -#define N_SCSA2USB_BLACKLIST (sizeof (scsa2usb_blacklist))/ \ - sizeof (struct blacklist) - /* * Attribute values can be overridden by values * contained in the scsa2usb.conf file. @@ -705,10 +706,14 @@ scsa2usb_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) mutex_enter(&scsa2usbp->scsa2usb_mutex); scsa2usbp->scsa2usb_dip = dip; scsa2usbp->scsa2usb_instance = instance; + /* + * Devices begin with all attributes enabled. Attributes may be + * disabled later through detected quirks or through the configuration + * file. + */ scsa2usbp->scsa2usb_attrs = SCSA2USB_ALL_ATTRS; scsa2usbp->scsa2usb_dev_data = dev_data; - /* save the default pipe handle */ scsa2usbp->scsa2usb_default_pipe = dev_data->dev_default_ph; @@ -874,10 +879,7 @@ scsa2usb_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) goto fail; } - /* - * Validate the black-listed attributes - */ - scsa2usb_validate_attrs(scsa2usbp); + scsa2usb_detect_quirks(scsa2usbp); /* Print the serial number from the registration data */ if (scsa2usbp->scsa2usb_dev_data->dev_serial) { @@ -1733,30 +1735,34 @@ scsa2usb_strtok_r(char *p, char *sep, char **lasts) /* - * scsa2usb_validate_attrs: - * many devices have BO/CB/CBI protocol support issues. - * use vendor/product info to reset the - * individual erroneous attributes - * - * NOTE: we look at only device at a time (at attach time) + * Some devices are not complete or compatible implementations of the USB mass + * storage protocols, and need special handling. This routine checks various + * aspects of the device against internal lists of quirky hardware. */ static void -scsa2usb_validate_attrs(scsa2usb_state_t *scsa2usbp) +scsa2usb_detect_quirks(scsa2usb_state_t *scsa2usbp) { - int i, mask; + int mask; usb_dev_descr_t *desc = scsa2usbp->scsa2usb_dev_data->dev_descr; if (!SCSA2USB_IS_BULK_ONLY(scsa2usbp)) { scsa2usbp->scsa2usb_attrs &= ~SCSA2USB_ATTRS_GET_LUN; } - /* determine if this device is on the blacklist */ - for (i = 0; i < N_SCSA2USB_BLACKLIST; i++) { - if ((scsa2usb_blacklist[i].idVendor == desc->idVendor) && - ((scsa2usb_blacklist[i].idProduct == desc->idProduct) || - (scsa2usb_blacklist[i].idProduct == X))) { - scsa2usbp->scsa2usb_attrs &= - ~(scsa2usb_blacklist[i].attributes); + /* + * Determine if this device is on the quirks list: + */ + for (uint_t i = 0; i < ARRAY_SIZE(scsa2usb_quirks); i++) { + struct quirk *q = &scsa2usb_quirks[i]; + + if (q->q_vid == desc->idVendor && + (q->q_pid == desc->idProduct || q->q_pid == X) && + (q->q_rev == desc->bcdDevice || q->q_rev == X)) { + /* + * Remove any attribute bits specified in the quirks + * table: + */ + scsa2usbp->scsa2usb_attrs &= ~(q->q_attr); break; } } @@ -3047,9 +3053,6 @@ scsa2usb_force_invalid_request(scsa2usb_state_t *scsa2usbp, } -/* - * scsa2usb_cmd_transport: - */ static int scsa2usb_cmd_transport(scsa2usb_state_t *scsa2usbp, scsa2usb_cmd_t *cmd) { @@ -3065,13 +3068,15 @@ scsa2usb_cmd_transport(scsa2usb_state_t *scsa2usbp, scsa2usb_cmd_t *cmd) pkt = scsa2usbp->scsa2usb_cur_pkt = cmd->cmd_pkt; - /* check black-listed attrs first */ + /* + * Check per-device quirks first: + */ if (SCSA2USB_IS_BULK_ONLY(scsa2usbp)) { - transport = scsa2usb_check_bulkonly_blacklist_attrs(scsa2usbp, - cmd, pkt->pkt_cdbp[0]); + transport = scsa2usb_check_bulkonly_quirks(scsa2usbp, cmd); } else if (SCSA2USB_IS_CB(scsa2usbp) || SCSA2USB_IS_CBI(scsa2usbp)) { - transport = scsa2usb_check_ufi_blacklist_attrs(scsa2usbp, - pkt->pkt_cdbp[0], cmd); + transport = scsa2usb_check_ufi_quirks(scsa2usbp, cmd); + } else { + return (TRAN_FATAL_ERROR); } /* just accept the command or return error */ @@ -3119,30 +3124,22 @@ scsa2usb_cmd_transport(scsa2usb_state_t *scsa2usbp, scsa2usb_cmd_t *cmd) /* - * scsa2usb_check_bulkonly_blacklist_attrs: - * validate "scsa2usb_blacklist_attrs" (see scsa2usb.h) - * if blacklisted attrs match accept the request - * attributes checked are:- - * SCSA2USB_ATTRS_START_STOP + * Check this Bulk Only command against the quirks for this particular device. + * Returns a transport disposition. */ int -scsa2usb_check_bulkonly_blacklist_attrs(scsa2usb_state_t *scsa2usbp, - scsa2usb_cmd_t *cmd, uchar_t opcode) +scsa2usb_check_bulkonly_quirks(scsa2usb_state_t *scsa2usbp, scsa2usb_cmd_t *cmd) { struct scsi_inquiry *inq = &scsa2usbp->scsa2usb_lun_inquiry[cmd->cmd_pkt->pkt_address.a_lun]; - USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, - "scsa2usb_check_bulkonly_blacklist_attrs: opcode = %s", - scsi_cname(opcode, scsa2usb_cmds)); - ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); /* * decode and convert the packet * for most cmds, we can bcopy the cdb */ - switch (opcode) { + switch (cmd->cmd_pkt->pkt_cdbp[0]) { case SCMD_DOORLOCK: if (!(scsa2usbp->scsa2usb_attrs & SCSA2USB_ATTRS_DOORLOCK)) { @@ -3574,23 +3571,17 @@ scsa2usb_do_tur(scsa2usb_state_t *scsa2usbp, struct scsi_address *ap) /* - * scsa2usb_check_ufi_blacklist_attrs: - * validate "scsa2usb_blacklist_attrs" (see scsa2usb.h) - * if blacklisted attrs match accept the request - * attributes checked are:- - * SCSA2USB_ATTRS_GET_CONF - * SCSA2USB_ATTRS_GET_PERF - * SCSA2USB_ATTRS_GET_START_STOP + * Check this UFI command against the quirks for this particular device. + * Returns a transport disposition. */ static int -scsa2usb_check_ufi_blacklist_attrs(scsa2usb_state_t *scsa2usbp, uchar_t opcode, - scsa2usb_cmd_t *cmd) +scsa2usb_check_ufi_quirks(scsa2usb_state_t *scsa2usbp, scsa2usb_cmd_t *cmd) { - int rval = SCSA2USB_TRANSPORT; + int rval = SCSA2USB_TRANSPORT; ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); - switch (opcode) { + switch (cmd->cmd_pkt->pkt_cdbp[0]) { case SCMD_PRIN: case SCMD_PROUT: rval = SCSA2USB_JUST_ACCEPT; @@ -3667,7 +3658,7 @@ int scsa2usb_handle_ufi_subclass_cmd(scsa2usb_state_t *scsa2usbp, scsa2usb_cmd_t *cmd, struct scsi_pkt *pkt) { - uchar_t opcode = pkt->pkt_cdbp[0]; + uchar_t opcode = pkt->pkt_cdbp[0]; USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, "scsa2usb_handle_ufi_subclass_cmd: cmd = 0x%p pkt = 0x%p", @@ -5600,13 +5591,11 @@ scsa2usb_create_pm_components(dev_info_t *dip, scsa2usb_state_t *scsa2usbp) (void *)dip, (void *)scsa2usbp); /* - * determine if this device is on the blacklist - * or if a conf file entry has disabled PM + * Check if power management is disabled by a per-device quirk: */ if ((scsa2usbp->scsa2usb_attrs & SCSA2USB_ATTRS_PM) == 0) { USB_DPRINTF_L2(DPRINT_MASK_PM, scsa2usbp->scsa2usb_log_handle, "device cannot be power managed"); - return; } diff --git a/usr/src/uts/common/sys/usb/scsa2usb/scsa2usb.h b/usr/src/uts/common/sys/usb/scsa2usb/scsa2usb.h index c619a32e64..8177f9542d 100644 --- a/usr/src/uts/common/sys/usb/scsa2usb/scsa2usb.h +++ b/usr/src/uts/common/sys/usb/scsa2usb/scsa2usb.h @@ -56,7 +56,9 @@ extern "C" { */ #define SCSA2USB_MAX_BULK_XFER_SIZE (64 * 1024) -/* Blacklist some vendors whose devices could cause problems */ +/* + * Identify devices with quirks of implementation that we need to work around: + */ #define MS_HAGIWARA_SYS_COM_VID 0x693 /* VendorId of Hagiwara Sys-Com */ #define MS_HAGIWARA_SYSCOM_PID1 0x1 /* PID for SmartMedia(SM) device */ #define MS_HAGIWARA_SYSCOM_PID2 0x3 /* PID for CompactFlash(CF) device */ @@ -143,7 +145,7 @@ extern "C" { * Reducing timeout value to 1 second can help a little bit, but the delay * is still noticeable, because the target driver would make many retries * for this command. It is not desirable to mess with the target driver - * for a broken USB device. So adding the device to the scsa2usb blacklist + * for a broken USB device. So adding the device to the scsa2usb quirks list * is the best choice we have. * * It is found that the READ CAPACITY failure only happens when there is @@ -187,7 +189,7 @@ extern "C" { * instead of highest logical block address on READ_CAPACITY cmd. * * NOTE: If a device simply STALLs the GET_MAX_LUN BO class-specific command - * and recovers then it will not be added to the scsa2usb_blacklist[] table + * and recovers then it will not be added to the scsa2usb_quirks[] table * in scsa2usb.c. The other attributes will not be taken of the table unless * their inclusion causes a recovery and retries (thus seriously affecting * the driver performance). @@ -508,10 +510,12 @@ _NOTE(SCHEME_PROTECTS_DATA("unshared data", usb_bulk_req_t)) FORMG0COUNT(((union scsi_cdb *)(pktp)->pkt_cdbp), (cnt)) -/* transport related */ -#define SCSA2USB_JUST_ACCEPT 0 -#define SCSA2USB_TRANSPORT 1 -#define SCSA2USB_REJECT -1 +/* + * Transport dispositions for commands: + */ +#define SCSA2USB_JUST_ACCEPT 0 /* Simulate command without device */ +#define SCSA2USB_TRANSPORT 1 /* Send the command to the device */ +#define SCSA2USB_REJECT -1 /* Reject with immediate fatal error */ /* * The scsa2usb_cpr_info data structure is used for cpr related |