From 0d92877ac3b7bf4b9127049da7d2b82f83638ed4 Mon Sep 17 00:00:00 2001 From: Sascha Wildner Date: Mon, 13 Aug 2012 02:33:30 +0200 Subject: [PATCH] ahci(4)/sili(4): Fix for drives >2TB. CAM will issue the 16 byte version of the READ CAPACITY command when maxsector is 0xffffffff: ----- scsi_da.c ----- if (maxsector == 0xffffffff) { softc->state = DA_STATE_PROBE2; kfree(rdcap, M_SCSIDA); xpt_release_ccb(done_ccb); xpt_schedule(periph, /*priority*/5); return; } --------------------- However, we are subtracting 1 from it (presumably because it's a "last sector on the device" value starting at 0) so in CAM, it ended up being 0xfffffffe, resulting in disks attached via ahci(4) and sili(4) to be limited to 2TB. To fix, set the local var to 0 in this case, so that after subtracting 1 from the value (cast to 32 bit) CAM gets 0xffffffff. Fix-by: dillon --- sys/dev/disk/ahci/ahci_cam.c | 10 ++++++++-- sys/dev/disk/sili/sili_cam.c | 10 ++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/sys/dev/disk/ahci/ahci_cam.c b/sys/dev/disk/ahci/ahci_cam.c index d225919c65..3b5d857bd1 100644 --- a/sys/dev/disk/ahci/ahci_cam.c +++ b/sys/dev/disk/ahci/ahci_cam.c @@ -1121,8 +1121,14 @@ ahci_xpt_scsi_disk_io(struct ahci_port *ap, struct ata_port *atx, bzero(rdata, rdata_len); if (cdb->generic.opcode == READ_CAPACITY) { rdata_len = sizeof(rdata->read_capacity_data); - if (capacity > 0xFFFFFFFFU) - capacity = 0xFFFFFFFFU; + if (capacity > 0xFFFFFFFFU) { + /* + * Set capacity to 0 so maxsector winds up + * being 0xffffffff in CAM in order to trigger + * DA_STATE_PROBE2. + */ + capacity = 0; + } bzero(&rdata->read_capacity_data, rdata_len); scsi_ulto4b((u_int32_t)capacity - 1, rdata->read_capacity_data.addr); diff --git a/sys/dev/disk/sili/sili_cam.c b/sys/dev/disk/sili/sili_cam.c index 11fc6953da..ec4350bdf5 100644 --- a/sys/dev/disk/sili/sili_cam.c +++ b/sys/dev/disk/sili/sili_cam.c @@ -1093,8 +1093,14 @@ sili_xpt_scsi_disk_io(struct sili_port *ap, struct ata_port *atx, bzero(rdata, rdata_len); if (cdb->generic.opcode == READ_CAPACITY) { rdata_len = sizeof(rdata->read_capacity_data); - if (capacity > 0xFFFFFFFFU) - capacity = 0xFFFFFFFFU; + if (capacity > 0xFFFFFFFFU) { + /* + * Set capacity to 0 so maxsector winds up + * being 0xffffffff in CAM in order to trigger + * DA_STATE_PROBE2. + */ + capacity = 0; + } bzero(&rdata->read_capacity_data, rdata_len); scsi_ulto4b((u_int32_t)capacity - 1, rdata->read_capacity_data.addr); -- 2.41.0