IDEMA, the International Disk Drive Equipment and Materials Association, publishes a specification that defines how to translate from LBA count to "marketing" gigabytes used to label drives. This patch updates the size calculations in sd.c so that the base 10 size is adjusted according to the IDEMA spec. Signed-off-by: Martin K. Petersen <martin.petersen@xxxxxxxxxx> --- diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1416,6 +1416,34 @@ static int read_capacity_10(struct scsi_ return sector_size; } +u64 sd_idema_capacity(u64 lba_count, unsigned int sector_size) +{ + /* This looks like black magic but these numbers are mandated in + * the IDEMA LBA specification that drive manufacturers use to + * indicate drive capacity. As of revision 1.3 these sizes are + * also mandatory for SCSI-class drives. + */ + u64 capacity; + unsigned int idema_sub = 97696368; + unsigned int idema_div = 1953504; + unsigned int scale = sector_size; + + do_div(scale, 512); + do_div(idema_sub, scale); + do_div(idema_div, scale); + + /* The adjustments only work for drives > 50GB */ + if (lba_count <= idema_sub) + return lba_count << ilog2(sector_size); + + capacity = lba_count - idema_sub; + do_div(capacity, idema_div); + capacity += 50; + capacity *= 1000*1000*1000; + + return capacity; +} + /* * read disk capacity */ @@ -1505,10 +1533,12 @@ got_data: { char cap_str_2[10], cap_str_10[10]; u64 sz = (u64)sdkp->capacity << ilog2(sector_size); + u64 idema_sz = sd_idema_capacity((u64)sdkp->capacity, + sector_size); string_get_size(sz, STRING_UNITS_2, cap_str_2, sizeof(cap_str_2)); - string_get_size(sz, STRING_UNITS_10, cap_str_10, + string_get_size(idema_sz, STRING_UNITS_10, cap_str_10, sizeof(cap_str_10)); sd_printk(KERN_NOTICE, sdkp, -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html