diff options
author | Alan Cox <alan@lxorguk.ukuu.org.uk> | 2006-08-10 13:52:12 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-08-14 14:04:37 -0400 |
commit | b352e57dc3bb5033996adaa67c2f69b795eddd39 (patch) | |
tree | 2bfec75e331452c84a591b6fad1e1407b22a1922 | |
parent | cea0d336e7e139becc9432499e0ba8234ffbed5f (diff) |
[PATCH] libata: Add CompactFlash support
The CFA world has some additional rules and drive modes we need to support for
newer expansion cards and on embedded boxes
Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
-rw-r--r-- | drivers/ata/libata-core.c | 62 | ||||
-rw-r--r-- | include/linux/ata.h | 20 | ||||
-rw-r--r-- | include/linux/libata.h | 4 |
3 files changed, 75 insertions, 11 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 0ac0b519cf2d..9092416a6301 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c | |||
@@ -386,9 +386,13 @@ static const char *ata_mode_string(unsigned int xfer_mask) | |||
386 | "PIO2", | 386 | "PIO2", |
387 | "PIO3", | 387 | "PIO3", |
388 | "PIO4", | 388 | "PIO4", |
389 | "PIO5", | ||
390 | "PIO6", | ||
389 | "MWDMA0", | 391 | "MWDMA0", |
390 | "MWDMA1", | 392 | "MWDMA1", |
391 | "MWDMA2", | 393 | "MWDMA2", |
394 | "MWDMA3", | ||
395 | "MWDMA4", | ||
392 | "UDMA/16", | 396 | "UDMA/16", |
393 | "UDMA/25", | 397 | "UDMA/25", |
394 | "UDMA/33", | 398 | "UDMA/33", |
@@ -875,6 +879,23 @@ static unsigned int ata_id_xfermask(const u16 *id) | |||
875 | 879 | ||
876 | mwdma_mask = id[ATA_ID_MWDMA_MODES] & 0x07; | 880 | mwdma_mask = id[ATA_ID_MWDMA_MODES] & 0x07; |
877 | 881 | ||
882 | if (ata_id_is_cfa(id)) { | ||
883 | /* | ||
884 | * Process compact flash extended modes | ||
885 | */ | ||
886 | int pio = id[163] & 0x7; | ||
887 | int dma = (id[163] >> 3) & 7; | ||
888 | |||
889 | if (pio) | ||
890 | pio_mask |= (1 << 5); | ||
891 | if (pio > 1) | ||
892 | pio_mask |= (1 << 6); | ||
893 | if (dma) | ||
894 | mwdma_mask |= (1 << 3); | ||
895 | if (dma > 1) | ||
896 | mwdma_mask |= (1 << 4); | ||
897 | } | ||
898 | |||
878 | udma_mask = 0; | 899 | udma_mask = 0; |
879 | if (id[ATA_ID_FIELD_VALID] & (1 << 2)) | 900 | if (id[ATA_ID_FIELD_VALID] & (1 << 2)) |
880 | udma_mask = id[ATA_ID_UDMA_MODES] & 0xff; | 901 | udma_mask = id[ATA_ID_UDMA_MODES] & 0xff; |
@@ -1356,6 +1377,7 @@ int ata_dev_configure(struct ata_device *dev, int print_info) | |||
1356 | struct ata_port *ap = dev->ap; | 1377 | struct ata_port *ap = dev->ap; |
1357 | const u16 *id = dev->id; | 1378 | const u16 *id = dev->id; |
1358 | unsigned int xfer_mask; | 1379 | unsigned int xfer_mask; |
1380 | char revbuf[7]; /* XYZ-99\0 */ | ||
1359 | int rc; | 1381 | int rc; |
1360 | 1382 | ||
1361 | if (!ata_dev_enabled(dev) && ata_msg_info(ap)) { | 1383 | if (!ata_dev_enabled(dev) && ata_msg_info(ap)) { |
@@ -1399,6 +1421,15 @@ int ata_dev_configure(struct ata_device *dev, int print_info) | |||
1399 | 1421 | ||
1400 | /* ATA-specific feature tests */ | 1422 | /* ATA-specific feature tests */ |
1401 | if (dev->class == ATA_DEV_ATA) { | 1423 | if (dev->class == ATA_DEV_ATA) { |
1424 | if (ata_id_is_cfa(id)) { | ||
1425 | if (id[162] & 1) /* CPRM may make this media unusable */ | ||
1426 | ata_dev_printk(dev, KERN_WARNING, "ata%u: device %u supports DRM functions and may not be fully accessable.\n", | ||
1427 | ap->id, dev->devno); | ||
1428 | snprintf(revbuf, 7, "CFA"); | ||
1429 | } | ||
1430 | else | ||
1431 | snprintf(revbuf, 7, "ATA-%d", ata_id_major_version(id)); | ||
1432 | |||
1402 | dev->n_sectors = ata_id_n_sectors(id); | 1433 | dev->n_sectors = ata_id_n_sectors(id); |
1403 | 1434 | ||
1404 | if (ata_id_has_lba(id)) { | 1435 | if (ata_id_has_lba(id)) { |
@@ -1417,9 +1448,9 @@ int ata_dev_configure(struct ata_device *dev, int print_info) | |||
1417 | 1448 | ||
1418 | /* print device info to dmesg */ | 1449 | /* print device info to dmesg */ |
1419 | if (ata_msg_drv(ap) && print_info) | 1450 | if (ata_msg_drv(ap) && print_info) |
1420 | ata_dev_printk(dev, KERN_INFO, "ATA-%d, " | 1451 | ata_dev_printk(dev, KERN_INFO, "%s, " |
1421 | "max %s, %Lu sectors: %s %s\n", | 1452 | "max %s, %Lu sectors: %s %s\n", |
1422 | ata_id_major_version(id), | 1453 | revbuf, |
1423 | ata_mode_string(xfer_mask), | 1454 | ata_mode_string(xfer_mask), |
1424 | (unsigned long long)dev->n_sectors, | 1455 | (unsigned long long)dev->n_sectors, |
1425 | lba_desc, ncq_desc); | 1456 | lba_desc, ncq_desc); |
@@ -1440,9 +1471,9 @@ int ata_dev_configure(struct ata_device *dev, int print_info) | |||
1440 | 1471 | ||
1441 | /* print device info to dmesg */ | 1472 | /* print device info to dmesg */ |
1442 | if (ata_msg_drv(ap) && print_info) | 1473 | if (ata_msg_drv(ap) && print_info) |
1443 | ata_dev_printk(dev, KERN_INFO, "ATA-%d, " | 1474 | ata_dev_printk(dev, KERN_INFO, "%s, " |
1444 | "max %s, %Lu sectors: CHS %u/%u/%u\n", | 1475 | "max %s, %Lu sectors: CHS %u/%u/%u\n", |
1445 | ata_id_major_version(id), | 1476 | revbuf, |
1446 | ata_mode_string(xfer_mask), | 1477 | ata_mode_string(xfer_mask), |
1447 | (unsigned long long)dev->n_sectors, | 1478 | (unsigned long long)dev->n_sectors, |
1448 | dev->cylinders, dev->heads, | 1479 | dev->cylinders, dev->heads, |
@@ -1900,10 +1931,11 @@ int sata_set_spd(struct ata_port *ap) | |||
1900 | * drivers/ide/ide-timing.h and was originally written by Vojtech Pavlik | 1931 | * drivers/ide/ide-timing.h and was originally written by Vojtech Pavlik |
1901 | */ | 1932 | */ |
1902 | /* | 1933 | /* |
1903 | * PIO 0-5, MWDMA 0-2 and UDMA 0-6 timings (in nanoseconds). | 1934 | * PIO 0-4, MWDMA 0-2 and UDMA 0-6 timings (in nanoseconds). |
1904 | * These were taken from ATA/ATAPI-6 standard, rev 0a, except | 1935 | * These were taken from ATA/ATAPI-6 standard, rev 0a, except |
1905 | * for PIO 5, which is a nonstandard extension and UDMA6, which | 1936 | * for UDMA6, which is currently supported only by Maxtor drives. |
1906 | * is currently supported only by Maxtor drives. | 1937 | * |
1938 | * For PIO 5/6 MWDMA 3/4 see the CFA specification 3.0. | ||
1907 | */ | 1939 | */ |
1908 | 1940 | ||
1909 | static const struct ata_timing ata_timing[] = { | 1941 | static const struct ata_timing ata_timing[] = { |
@@ -1913,6 +1945,8 @@ static const struct ata_timing ata_timing[] = { | |||
1913 | { XFER_UDMA_4, 0, 0, 0, 0, 0, 0, 0, 30 }, | 1945 | { XFER_UDMA_4, 0, 0, 0, 0, 0, 0, 0, 30 }, |
1914 | { XFER_UDMA_3, 0, 0, 0, 0, 0, 0, 0, 45 }, | 1946 | { XFER_UDMA_3, 0, 0, 0, 0, 0, 0, 0, 45 }, |
1915 | 1947 | ||
1948 | { XFER_MW_DMA_4, 25, 0, 0, 0, 55, 20, 80, 0 }, | ||
1949 | { XFER_MW_DMA_3, 25, 0, 0, 0, 65, 25, 100, 0 }, | ||
1916 | { XFER_UDMA_2, 0, 0, 0, 0, 0, 0, 0, 60 }, | 1950 | { XFER_UDMA_2, 0, 0, 0, 0, 0, 0, 0, 60 }, |
1917 | { XFER_UDMA_1, 0, 0, 0, 0, 0, 0, 0, 80 }, | 1951 | { XFER_UDMA_1, 0, 0, 0, 0, 0, 0, 0, 80 }, |
1918 | { XFER_UDMA_0, 0, 0, 0, 0, 0, 0, 0, 120 }, | 1952 | { XFER_UDMA_0, 0, 0, 0, 0, 0, 0, 0, 120 }, |
@@ -1927,7 +1961,8 @@ static const struct ata_timing ata_timing[] = { | |||
1927 | { XFER_SW_DMA_1, 90, 0, 0, 0, 240, 240, 480, 0 }, | 1961 | { XFER_SW_DMA_1, 90, 0, 0, 0, 240, 240, 480, 0 }, |
1928 | { XFER_SW_DMA_0, 120, 0, 0, 0, 480, 480, 960, 0 }, | 1962 | { XFER_SW_DMA_0, 120, 0, 0, 0, 480, 480, 960, 0 }, |
1929 | 1963 | ||
1930 | /* { XFER_PIO_5, 20, 50, 30, 100, 50, 30, 100, 0 }, */ | 1964 | { XFER_PIO_6, 10, 55, 20, 80, 55, 20, 80, 0 }, |
1965 | { XFER_PIO_5, 15, 65, 25, 100, 65, 25, 100, 0 }, | ||
1931 | { XFER_PIO_4, 25, 70, 25, 120, 70, 25, 120, 0 }, | 1966 | { XFER_PIO_4, 25, 70, 25, 120, 70, 25, 120, 0 }, |
1932 | { XFER_PIO_3, 30, 80, 70, 180, 80, 70, 180, 0 }, | 1967 | { XFER_PIO_3, 30, 80, 70, 180, 80, 70, 180, 0 }, |
1933 | 1968 | ||
@@ -3062,6 +3097,17 @@ static void ata_dev_xfermask(struct ata_device *dev) | |||
3062 | dev->mwdma_mask, dev->udma_mask); | 3097 | dev->mwdma_mask, dev->udma_mask); |
3063 | xfer_mask &= ata_id_xfermask(dev->id); | 3098 | xfer_mask &= ata_id_xfermask(dev->id); |
3064 | 3099 | ||
3100 | /* | ||
3101 | * CFA Advanced TrueIDE timings are not allowed on a shared | ||
3102 | * cable | ||
3103 | */ | ||
3104 | if (ata_dev_pair(dev)) { | ||
3105 | /* No PIO5 or PIO6 */ | ||
3106 | xfer_mask &= ~(0x03 << (ATA_SHIFT_PIO + 5)); | ||
3107 | /* No MWDMA3 or MWDMA 4 */ | ||
3108 | xfer_mask &= ~(0x03 << (ATA_SHIFT_MWDMA + 3)); | ||
3109 | } | ||
3110 | |||
3065 | if (ata_dma_blacklisted(dev)) { | 3111 | if (ata_dma_blacklisted(dev)) { |
3066 | xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA); | 3112 | xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA); |
3067 | ata_dev_printk(dev, KERN_WARNING, | 3113 | ata_dev_printk(dev, KERN_WARNING, |
diff --git a/include/linux/ata.h b/include/linux/ata.h index 8d708a3d505b..991b858acc30 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h | |||
@@ -170,12 +170,16 @@ enum { | |||
170 | XFER_UDMA_2 = 0x42, | 170 | XFER_UDMA_2 = 0x42, |
171 | XFER_UDMA_1 = 0x41, | 171 | XFER_UDMA_1 = 0x41, |
172 | XFER_UDMA_0 = 0x40, | 172 | XFER_UDMA_0 = 0x40, |
173 | XFER_MW_DMA_4 = 0x24, /* CFA only */ | ||
174 | XFER_MW_DMA_3 = 0x23, /* CFA only */ | ||
173 | XFER_MW_DMA_2 = 0x22, | 175 | XFER_MW_DMA_2 = 0x22, |
174 | XFER_MW_DMA_1 = 0x21, | 176 | XFER_MW_DMA_1 = 0x21, |
175 | XFER_MW_DMA_0 = 0x20, | 177 | XFER_MW_DMA_0 = 0x20, |
176 | XFER_SW_DMA_2 = 0x12, | 178 | XFER_SW_DMA_2 = 0x12, |
177 | XFER_SW_DMA_1 = 0x11, | 179 | XFER_SW_DMA_1 = 0x11, |
178 | XFER_SW_DMA_0 = 0x10, | 180 | XFER_SW_DMA_0 = 0x10, |
181 | XFER_PIO_6 = 0x0E, /* CFA only */ | ||
182 | XFER_PIO_5 = 0x0D, /* CFA only */ | ||
179 | XFER_PIO_4 = 0x0C, | 183 | XFER_PIO_4 = 0x0C, |
180 | XFER_PIO_3 = 0x0B, | 184 | XFER_PIO_3 = 0x0B, |
181 | XFER_PIO_2 = 0x0A, | 185 | XFER_PIO_2 = 0x0A, |
@@ -274,7 +278,6 @@ struct ata_taskfile { | |||
274 | }; | 278 | }; |
275 | 279 | ||
276 | #define ata_id_is_ata(id) (((id)[0] & (1 << 15)) == 0) | 280 | #define ata_id_is_ata(id) (((id)[0] & (1 << 15)) == 0) |
277 | #define ata_id_is_cfa(id) ((id)[0] == 0x848A) | ||
278 | #define ata_id_is_sata(id) ((id)[93] == 0) | 281 | #define ata_id_is_sata(id) ((id)[93] == 0) |
279 | #define ata_id_rahead_enabled(id) ((id)[85] & (1 << 6)) | 282 | #define ata_id_rahead_enabled(id) ((id)[85] & (1 << 6)) |
280 | #define ata_id_wcache_enabled(id) ((id)[85] & (1 << 5)) | 283 | #define ata_id_wcache_enabled(id) ((id)[85] & (1 << 5)) |
@@ -306,6 +309,9 @@ static inline unsigned int ata_id_major_version(const u16 *id) | |||
306 | { | 309 | { |
307 | unsigned int mver; | 310 | unsigned int mver; |
308 | 311 | ||
312 | if (id[ATA_ID_MAJOR_VER] == 0xFFFF) | ||
313 | return 0; | ||
314 | |||
309 | for (mver = 14; mver >= 1; mver--) | 315 | for (mver = 14; mver >= 1; mver--) |
310 | if (id[ATA_ID_MAJOR_VER] & (1 << mver)) | 316 | if (id[ATA_ID_MAJOR_VER] & (1 << mver)) |
311 | break; | 317 | break; |
@@ -324,6 +330,18 @@ static inline int ata_id_current_chs_valid(const u16 *id) | |||
324 | id[56]; /* sectors in current translation */ | 330 | id[56]; /* sectors in current translation */ |
325 | } | 331 | } |
326 | 332 | ||
333 | static inline int ata_id_is_cfa(const u16 *id) | ||
334 | { | ||
335 | u16 v = id[0]; | ||
336 | if (v == 0x848A) /* Standard CF */ | ||
337 | return 1; | ||
338 | /* Could be CF hiding as standard ATA */ | ||
339 | if (ata_id_major_version(id) >= 3 && id[82] != 0xFFFF && | ||
340 | (id[82] & ( 1 << 2))) | ||
341 | return 1; | ||
342 | return 0; | ||
343 | } | ||
344 | |||
327 | static inline int atapi_cdb_len(const u16 *dev_id) | 345 | static inline int atapi_cdb_len(const u16 *dev_id) |
328 | { | 346 | { |
329 | u16 tmp = dev_id[0] & 0x3; | 347 | u16 tmp = dev_id[0] & 0x3; |
diff --git a/include/linux/libata.h b/include/linux/libata.h index 060da736b3a8..806682603ac5 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h | |||
@@ -225,8 +225,8 @@ enum { | |||
225 | /* encoding various smaller bitmaps into a single | 225 | /* encoding various smaller bitmaps into a single |
226 | * unsigned int bitmap | 226 | * unsigned int bitmap |
227 | */ | 227 | */ |
228 | ATA_BITS_PIO = 5, | 228 | ATA_BITS_PIO = 7, |
229 | ATA_BITS_MWDMA = 3, | 229 | ATA_BITS_MWDMA = 5, |
230 | ATA_BITS_UDMA = 8, | 230 | ATA_BITS_UDMA = 8, |
231 | 231 | ||
232 | ATA_SHIFT_PIO = 0, | 232 | ATA_SHIFT_PIO = 0, |