Some USB mass storage devices return the number of sectors in response
to a READ_CAPACITY request rather than the maximum sector (off by one problem). This causes a huge cascade of errors as the geom tasting code tries to read the last sector (which isn't really there in the face of this error). automated tools that manipulate disk labels and such also have issues. Create a new quirk READ_CAPACITY_OFFBY1 and add a quirk for the SanDISK ImageMate that I have that suffers from this problem (the SDDR-31). It intercepts the READ_CAPACITY response and adjusts it from number of sectors to max sector for devices with this quirk. Reading the Linux source suggests that there are a host of other devices with this issue, including iPods and some popular cameras. I've not added quirks for them, since I don't have the devices in front of me to test.
This commit is contained in:
parent
0bd2af4cfe
commit
b8fed42140
@ -317,6 +317,10 @@ struct umass_devdescr_t {
|
||||
# define NO_INQUIRY_EVPD 0x0800
|
||||
/* Pad all RBC requests to 12 bytes. */
|
||||
# define RBC_PAD_TO_12 0x1000
|
||||
/* Device reports number of sectors from READ_CAPACITY, not max
|
||||
* sector number.
|
||||
*/
|
||||
# define READ_CAPACITY_OFFBY1 0x2000
|
||||
};
|
||||
|
||||
static struct umass_devdescr_t umass_devdescrs[] = {
|
||||
@ -446,6 +450,10 @@ static struct umass_devdescr_t umass_devdescrs[] = {
|
||||
UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
|
||||
IGNORE_RESIDUE | NO_START_STOP
|
||||
},
|
||||
{ USB_VENDOR_SANDISK, USB_PRODUCT_SANDISK_SDDR31, RID_WILDCARD,
|
||||
UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
|
||||
READ_CAPACITY_OFFBY1
|
||||
},
|
||||
{ USB_VENDOR_SANDISK, USB_PRODUCT_SANDISK_SDCZ2_256, RID_WILDCARD,
|
||||
UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
|
||||
IGNORE_RESIDUE
|
||||
@ -2698,6 +2706,16 @@ umass_cam_cb(struct umass_softc *sc, void *priv, int residue, int status)
|
||||
switch (status) {
|
||||
case STATUS_CMD_OK:
|
||||
ccb->ccb_h.status = CAM_REQ_CMP;
|
||||
if ((sc->quirks & READ_CAPACITY_OFFBY1) &&
|
||||
(ccb->ccb_h.func_code == XPT_SCSI_IO) &&
|
||||
(csio->cdb_io.cdb_bytes[0] == READ_CAPACITY)) {
|
||||
struct scsi_read_capacity_data *rcap;
|
||||
uint32_t maxsector;
|
||||
|
||||
rcap = (struct scsi_read_capacity_data *)csio->data_ptr;
|
||||
maxsector = scsi_4btoul(rcap->addr) - 1;
|
||||
scsi_ulto4b(maxsector, rcap->addr);
|
||||
}
|
||||
xpt_done(ccb);
|
||||
break;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user