diff options
Diffstat (limited to 'include/linux/ata.h')
| -rw-r--r-- | include/linux/ata.h | 46 | 
1 files changed, 40 insertions, 6 deletions
| diff --git a/include/linux/ata.h b/include/linux/ata.h index fe6e681a9d74..0c4929fa34d3 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h | |||
| @@ -89,6 +89,7 @@ enum { | |||
| 89 | ATA_ID_SPG = 98, | 89 | ATA_ID_SPG = 98, | 
| 90 | ATA_ID_LBA_CAPACITY_2 = 100, | 90 | ATA_ID_LBA_CAPACITY_2 = 100, | 
| 91 | ATA_ID_SECTOR_SIZE = 106, | 91 | ATA_ID_SECTOR_SIZE = 106, | 
| 92 | ATA_ID_LOGICAL_SECTOR_SIZE = 117, /* and 118 */ | ||
| 92 | ATA_ID_LAST_LUN = 126, | 93 | ATA_ID_LAST_LUN = 126, | 
| 93 | ATA_ID_DLF = 128, | 94 | ATA_ID_DLF = 128, | 
| 94 | ATA_ID_CSFO = 129, | 95 | ATA_ID_CSFO = 129, | 
| @@ -640,16 +641,49 @@ static inline int ata_id_flush_ext_enabled(const u16 *id) | |||
| 640 | return (id[ATA_ID_CFS_ENABLE_2] & 0x2400) == 0x2400; | 641 | return (id[ATA_ID_CFS_ENABLE_2] & 0x2400) == 0x2400; | 
| 641 | } | 642 | } | 
| 642 | 643 | ||
| 643 | static inline int ata_id_has_large_logical_sectors(const u16 *id) | 644 | static inline u32 ata_id_logical_sector_size(const u16 *id) | 
| 644 | { | 645 | { | 
| 645 | if ((id[ATA_ID_SECTOR_SIZE] & 0xc000) != 0x4000) | 646 | /* T13/1699-D Revision 6a, Sep 6, 2008. Page 128. | 
| 646 | return 0; | 647 | * IDENTIFY DEVICE data, word 117-118. | 
| 647 | return id[ATA_ID_SECTOR_SIZE] & (1 << 13); | 648 | * 0xd000 ignores bit 13 (logical:physical > 1) | 
| 649 | */ | ||
| 650 | if ((id[ATA_ID_SECTOR_SIZE] & 0xd000) == 0x5000) | ||
| 651 | return (((id[ATA_ID_LOGICAL_SECTOR_SIZE+1] << 16) | ||
| 652 | + id[ATA_ID_LOGICAL_SECTOR_SIZE]) * sizeof(u16)) ; | ||
| 653 | return ATA_SECT_SIZE; | ||
| 654 | } | ||
| 655 | |||
| 656 | static inline u8 ata_id_log2_per_physical_sector(const u16 *id) | ||
| 657 | { | ||
| 658 | /* T13/1699-D Revision 6a, Sep 6, 2008. Page 128. | ||
| 659 | * IDENTIFY DEVICE data, word 106. | ||
| 660 | * 0xe000 ignores bit 12 (logical sector > 512 bytes) | ||
| 661 | */ | ||
| 662 | if ((id[ATA_ID_SECTOR_SIZE] & 0xe000) == 0x6000) | ||
| 663 | return (id[ATA_ID_SECTOR_SIZE] & 0xf); | ||
| 664 | return 0; | ||
| 648 | } | 665 | } | 
| 649 | 666 | ||
| 650 | static inline u16 ata_id_logical_per_physical_sectors(const u16 *id) | 667 | /* Offset of logical sectors relative to physical sectors. | 
| 668 | * | ||
| 669 | * If device has more than one logical sector per physical sector | ||
| 670 | * (aka 512 byte emulation), vendors might offset the "sector 0" address | ||
| 671 | * so sector 63 is "naturally aligned" - e.g. FAT partition table. | ||
| 672 | * This avoids Read/Mod/Write penalties when using FAT partition table | ||
| 673 | * and updating "well aligned" (FS perspective) physical sectors on every | ||
| 674 | * transaction. | ||
| 675 | */ | ||
| 676 | static inline u16 ata_id_logical_sector_offset(const u16 *id, | ||
| 677 | u8 log2_per_phys) | ||
| 651 | { | 678 | { | 
| 652 | return 1 << (id[ATA_ID_SECTOR_SIZE] & 0xf); | 679 | u16 word_209 = id[209]; | 
| 680 | |||
| 681 | if ((log2_per_phys > 1) && (word_209 & 0xc000) == 0x4000) { | ||
| 682 | u16 first = word_209 & 0x3fff; | ||
| 683 | if (first > 0) | ||
| 684 | return (1 << log2_per_phys) - first; | ||
| 685 | } | ||
| 686 | return 0; | ||
| 653 | } | 687 | } | 
| 654 | 688 | ||
| 655 | static inline int ata_id_has_lba48(const u16 *id) | 689 | static inline int ata_id_has_lba48(const u16 *id) | 
