aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/libata-scsi.c
diff options
context:
space:
mode:
authorMartin K. Petersen <martin.petersen@oracle.com>2009-05-15 00:40:34 -0400
committerJeff Garzik <jgarzik@redhat.com>2009-05-15 14:14:22 -0400
commit61d79a8eb362f826a002d3d14c4f9a070a818542 (patch)
treef67dce998de1d28da9a0aea898208d512728ef1e /drivers/ata/libata-scsi.c
parentd358724385d9bb3e360f5b95c17ec4f77c913460 (diff)
libata: Report disk alignment and physical block size
For disks with 4KB sectors, report the correct block size and alignment when filling out the READ CAPACITY(16) response. This patch is based upon code from Matthew Wilcox' 4KB ATA tree. I fixed the bug I reported a while back caused by ATA and SCSI using different approaches to describing the alignment. Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/ata/libata-scsi.c')
-rw-r--r--drivers/ata/libata-scsi.c23
1 files changed, 22 insertions, 1 deletions
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 68d9132d8f6f..d1718a1f278a 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -2376,7 +2376,23 @@ saving_not_supp:
2376 */ 2376 */
2377static unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf) 2377static unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf)
2378{ 2378{
2379 u64 last_lba = args->dev->n_sectors - 1; /* LBA of the last block */ 2379 struct ata_device *dev = args->dev;
2380 u64 last_lba = dev->n_sectors - 1; /* LBA of the last block */
2381 u8 log_per_phys = 0;
2382 u16 lowest_aligned = 0;
2383 u16 word_106 = dev->id[106];
2384 u16 word_209 = dev->id[209];
2385
2386 if ((word_106 & 0xc000) == 0x4000) {
2387 /* Number and offset of logical sectors per physical sector */
2388 if (word_106 & (1 << 13))
2389 log_per_phys = word_106 & 0xf;
2390 if ((word_209 & 0xc000) == 0x4000) {
2391 u16 first = dev->id[209] & 0x3fff;
2392 if (first > 0)
2393 lowest_aligned = (1 << log_per_phys) - first;
2394 }
2395 }
2380 2396
2381 VPRINTK("ENTER\n"); 2397 VPRINTK("ENTER\n");
2382 2398
@@ -2407,6 +2423,11 @@ static unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf)
2407 /* sector size */ 2423 /* sector size */
2408 rbuf[10] = ATA_SECT_SIZE >> 8; 2424 rbuf[10] = ATA_SECT_SIZE >> 8;
2409 rbuf[11] = ATA_SECT_SIZE & 0xff; 2425 rbuf[11] = ATA_SECT_SIZE & 0xff;
2426
2427 rbuf[12] = 0;
2428 rbuf[13] = log_per_phys;
2429 rbuf[14] = (lowest_aligned >> 8) & 0x3f;
2430 rbuf[15] = lowest_aligned;
2410 } 2431 }
2411 2432
2412 return 0; 2433 return 0;