]> Pileus Git - ~andy/linux/blobdiff - include/linux/ata.h
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ecryptfs...
[~andy/linux] / include / linux / ata.h
index fe6e681a9d742788be67c16003662b9a7a218e89..0c4929fa34d31da64a79bd22dbfdccd8aaba33dc 100644 (file)
@@ -89,6 +89,7 @@ enum {
        ATA_ID_SPG              = 98,
        ATA_ID_LBA_CAPACITY_2   = 100,
        ATA_ID_SECTOR_SIZE      = 106,
+       ATA_ID_LOGICAL_SECTOR_SIZE      = 117,  /* and 118 */
        ATA_ID_LAST_LUN         = 126,
        ATA_ID_DLF              = 128,
        ATA_ID_CSFO             = 129,
@@ -640,16 +641,49 @@ static inline int ata_id_flush_ext_enabled(const u16 *id)
        return (id[ATA_ID_CFS_ENABLE_2] & 0x2400) == 0x2400;
 }
 
-static inline int ata_id_has_large_logical_sectors(const u16 *id)
+static inline u32 ata_id_logical_sector_size(const u16 *id)
 {
-       if ((id[ATA_ID_SECTOR_SIZE] & 0xc000) != 0x4000)
-               return 0;
-       return id[ATA_ID_SECTOR_SIZE] & (1 << 13);
+       /* T13/1699-D Revision 6a, Sep 6, 2008. Page 128.
+        * IDENTIFY DEVICE data, word 117-118.
+        * 0xd000 ignores bit 13 (logical:physical > 1)
+        */
+       if ((id[ATA_ID_SECTOR_SIZE] & 0xd000) == 0x5000)
+               return (((id[ATA_ID_LOGICAL_SECTOR_SIZE+1] << 16)
+                        + id[ATA_ID_LOGICAL_SECTOR_SIZE]) * sizeof(u16)) ;
+       return ATA_SECT_SIZE;
+}
+
+static inline u8 ata_id_log2_per_physical_sector(const u16 *id)
+{
+       /* T13/1699-D Revision 6a, Sep 6, 2008. Page 128.
+        * IDENTIFY DEVICE data, word 106.
+        * 0xe000 ignores bit 12 (logical sector > 512 bytes)
+        */
+       if ((id[ATA_ID_SECTOR_SIZE] & 0xe000) == 0x6000)
+               return (id[ATA_ID_SECTOR_SIZE] & 0xf);
+       return 0;
 }
 
-static inline u16 ata_id_logical_per_physical_sectors(const u16 *id)
+/* Offset of logical sectors relative to physical sectors.
+ *
+ * If device has more than one logical sector per physical sector
+ * (aka 512 byte emulation), vendors might offset the "sector 0" address
+ * so sector 63 is "naturally aligned" - e.g. FAT partition table.
+ * This avoids Read/Mod/Write penalties when using FAT partition table
+ * and updating "well aligned" (FS perspective) physical sectors on every
+ * transaction.
+ */
+static inline u16 ata_id_logical_sector_offset(const u16 *id,
+        u8 log2_per_phys)
 {
-       return 1 << (id[ATA_ID_SECTOR_SIZE] & 0xf);
+       u16 word_209 = id[209];
+
+       if ((log2_per_phys > 1) && (word_209 & 0xc000) == 0x4000) {
+               u16 first = word_209 & 0x3fff;
+               if (first > 0)
+                       return (1 << log2_per_phys) - first;
+       }
+       return 0;
 }
 
 static inline int ata_id_has_lba48(const u16 *id)