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>
This commit is contained in:
Martin K. Petersen 2009-05-15 00:40:34 -04:00 committed by Jeff Garzik
parent d358724385
commit 61d79a8eb3

View File

@ -2376,7 +2376,23 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf)
*/
static unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf)
{
u64 last_lba = args->dev->n_sectors - 1; /* LBA of the last block */
struct ata_device *dev = args->dev;
u64 last_lba = dev->n_sectors - 1; /* LBA of the last block */
u8 log_per_phys = 0;
u16 lowest_aligned = 0;
u16 word_106 = dev->id[106];
u16 word_209 = dev->id[209];
if ((word_106 & 0xc000) == 0x4000) {
/* Number and offset of logical sectors per physical sector */
if (word_106 & (1 << 13))
log_per_phys = word_106 & 0xf;
if ((word_209 & 0xc000) == 0x4000) {
u16 first = dev->id[209] & 0x3fff;
if (first > 0)
lowest_aligned = (1 << log_per_phys) - first;
}
}
VPRINTK("ENTER\n");
@ -2407,6 +2423,11 @@ static unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf)
/* sector size */
rbuf[10] = ATA_SECT_SIZE >> 8;
rbuf[11] = ATA_SECT_SIZE & 0xff;
rbuf[12] = 0;
rbuf[13] = log_per_phys;
rbuf[14] = (lowest_aligned >> 8) & 0x3f;
rbuf[15] = lowest_aligned;
}
return 0;