提交 b352e57d 编写于 作者: A Alan Cox 提交者: Jeff Garzik

[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: NAlan Cox <alan@redhat.com>
Signed-off-by: NJeff Garzik <jeff@garzik.org>
上级 cea0d336
...@@ -386,9 +386,13 @@ static const char *ata_mode_string(unsigned int xfer_mask) ...@@ -386,9 +386,13 @@ static const char *ata_mode_string(unsigned int xfer_mask)
"PIO2", "PIO2",
"PIO3", "PIO3",
"PIO4", "PIO4",
"PIO5",
"PIO6",
"MWDMA0", "MWDMA0",
"MWDMA1", "MWDMA1",
"MWDMA2", "MWDMA2",
"MWDMA3",
"MWDMA4",
"UDMA/16", "UDMA/16",
"UDMA/25", "UDMA/25",
"UDMA/33", "UDMA/33",
...@@ -875,6 +879,23 @@ static unsigned int ata_id_xfermask(const u16 *id) ...@@ -875,6 +879,23 @@ static unsigned int ata_id_xfermask(const u16 *id)
mwdma_mask = id[ATA_ID_MWDMA_MODES] & 0x07; mwdma_mask = id[ATA_ID_MWDMA_MODES] & 0x07;
if (ata_id_is_cfa(id)) {
/*
* Process compact flash extended modes
*/
int pio = id[163] & 0x7;
int dma = (id[163] >> 3) & 7;
if (pio)
pio_mask |= (1 << 5);
if (pio > 1)
pio_mask |= (1 << 6);
if (dma)
mwdma_mask |= (1 << 3);
if (dma > 1)
mwdma_mask |= (1 << 4);
}
udma_mask = 0; udma_mask = 0;
if (id[ATA_ID_FIELD_VALID] & (1 << 2)) if (id[ATA_ID_FIELD_VALID] & (1 << 2))
udma_mask = id[ATA_ID_UDMA_MODES] & 0xff; udma_mask = id[ATA_ID_UDMA_MODES] & 0xff;
...@@ -1356,6 +1377,7 @@ int ata_dev_configure(struct ata_device *dev, int print_info) ...@@ -1356,6 +1377,7 @@ int ata_dev_configure(struct ata_device *dev, int print_info)
struct ata_port *ap = dev->ap; struct ata_port *ap = dev->ap;
const u16 *id = dev->id; const u16 *id = dev->id;
unsigned int xfer_mask; unsigned int xfer_mask;
char revbuf[7]; /* XYZ-99\0 */
int rc; int rc;
if (!ata_dev_enabled(dev) && ata_msg_info(ap)) { 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,6 +1421,15 @@ int ata_dev_configure(struct ata_device *dev, int print_info)
/* ATA-specific feature tests */ /* ATA-specific feature tests */
if (dev->class == ATA_DEV_ATA) { if (dev->class == ATA_DEV_ATA) {
if (ata_id_is_cfa(id)) {
if (id[162] & 1) /* CPRM may make this media unusable */
ata_dev_printk(dev, KERN_WARNING, "ata%u: device %u supports DRM functions and may not be fully accessable.\n",
ap->id, dev->devno);
snprintf(revbuf, 7, "CFA");
}
else
snprintf(revbuf, 7, "ATA-%d", ata_id_major_version(id));
dev->n_sectors = ata_id_n_sectors(id); dev->n_sectors = ata_id_n_sectors(id);
if (ata_id_has_lba(id)) { if (ata_id_has_lba(id)) {
...@@ -1417,9 +1448,9 @@ int ata_dev_configure(struct ata_device *dev, int print_info) ...@@ -1417,9 +1448,9 @@ int ata_dev_configure(struct ata_device *dev, int print_info)
/* print device info to dmesg */ /* print device info to dmesg */
if (ata_msg_drv(ap) && print_info) if (ata_msg_drv(ap) && print_info)
ata_dev_printk(dev, KERN_INFO, "ATA-%d, " ata_dev_printk(dev, KERN_INFO, "%s, "
"max %s, %Lu sectors: %s %s\n", "max %s, %Lu sectors: %s %s\n",
ata_id_major_version(id), revbuf,
ata_mode_string(xfer_mask), ata_mode_string(xfer_mask),
(unsigned long long)dev->n_sectors, (unsigned long long)dev->n_sectors,
lba_desc, ncq_desc); lba_desc, ncq_desc);
...@@ -1440,9 +1471,9 @@ int ata_dev_configure(struct ata_device *dev, int print_info) ...@@ -1440,9 +1471,9 @@ int ata_dev_configure(struct ata_device *dev, int print_info)
/* print device info to dmesg */ /* print device info to dmesg */
if (ata_msg_drv(ap) && print_info) if (ata_msg_drv(ap) && print_info)
ata_dev_printk(dev, KERN_INFO, "ATA-%d, " ata_dev_printk(dev, KERN_INFO, "%s, "
"max %s, %Lu sectors: CHS %u/%u/%u\n", "max %s, %Lu sectors: CHS %u/%u/%u\n",
ata_id_major_version(id), revbuf,
ata_mode_string(xfer_mask), ata_mode_string(xfer_mask),
(unsigned long long)dev->n_sectors, (unsigned long long)dev->n_sectors,
dev->cylinders, dev->heads, dev->cylinders, dev->heads,
...@@ -1900,10 +1931,11 @@ int sata_set_spd(struct ata_port *ap) ...@@ -1900,10 +1931,11 @@ int sata_set_spd(struct ata_port *ap)
* drivers/ide/ide-timing.h and was originally written by Vojtech Pavlik * drivers/ide/ide-timing.h and was originally written by Vojtech Pavlik
*/ */
/* /*
* PIO 0-5, MWDMA 0-2 and UDMA 0-6 timings (in nanoseconds). * PIO 0-4, MWDMA 0-2 and UDMA 0-6 timings (in nanoseconds).
* These were taken from ATA/ATAPI-6 standard, rev 0a, except * These were taken from ATA/ATAPI-6 standard, rev 0a, except
* for PIO 5, which is a nonstandard extension and UDMA6, which * for UDMA6, which is currently supported only by Maxtor drives.
* is currently supported only by Maxtor drives. *
* For PIO 5/6 MWDMA 3/4 see the CFA specification 3.0.
*/ */
static const struct ata_timing ata_timing[] = { static const struct ata_timing ata_timing[] = {
...@@ -1913,6 +1945,8 @@ static const struct ata_timing ata_timing[] = { ...@@ -1913,6 +1945,8 @@ static const struct ata_timing ata_timing[] = {
{ XFER_UDMA_4, 0, 0, 0, 0, 0, 0, 0, 30 }, { XFER_UDMA_4, 0, 0, 0, 0, 0, 0, 0, 30 },
{ XFER_UDMA_3, 0, 0, 0, 0, 0, 0, 0, 45 }, { XFER_UDMA_3, 0, 0, 0, 0, 0, 0, 0, 45 },
{ XFER_MW_DMA_4, 25, 0, 0, 0, 55, 20, 80, 0 },
{ XFER_MW_DMA_3, 25, 0, 0, 0, 65, 25, 100, 0 },
{ XFER_UDMA_2, 0, 0, 0, 0, 0, 0, 0, 60 }, { XFER_UDMA_2, 0, 0, 0, 0, 0, 0, 0, 60 },
{ XFER_UDMA_1, 0, 0, 0, 0, 0, 0, 0, 80 }, { XFER_UDMA_1, 0, 0, 0, 0, 0, 0, 0, 80 },
{ XFER_UDMA_0, 0, 0, 0, 0, 0, 0, 0, 120 }, { XFER_UDMA_0, 0, 0, 0, 0, 0, 0, 0, 120 },
...@@ -1927,7 +1961,8 @@ static const struct ata_timing ata_timing[] = { ...@@ -1927,7 +1961,8 @@ static const struct ata_timing ata_timing[] = {
{ XFER_SW_DMA_1, 90, 0, 0, 0, 240, 240, 480, 0 }, { XFER_SW_DMA_1, 90, 0, 0, 0, 240, 240, 480, 0 },
{ XFER_SW_DMA_0, 120, 0, 0, 0, 480, 480, 960, 0 }, { XFER_SW_DMA_0, 120, 0, 0, 0, 480, 480, 960, 0 },
/* { XFER_PIO_5, 20, 50, 30, 100, 50, 30, 100, 0 }, */ { XFER_PIO_6, 10, 55, 20, 80, 55, 20, 80, 0 },
{ XFER_PIO_5, 15, 65, 25, 100, 65, 25, 100, 0 },
{ XFER_PIO_4, 25, 70, 25, 120, 70, 25, 120, 0 }, { XFER_PIO_4, 25, 70, 25, 120, 70, 25, 120, 0 },
{ XFER_PIO_3, 30, 80, 70, 180, 80, 70, 180, 0 }, { XFER_PIO_3, 30, 80, 70, 180, 80, 70, 180, 0 },
...@@ -3062,6 +3097,17 @@ static void ata_dev_xfermask(struct ata_device *dev) ...@@ -3062,6 +3097,17 @@ static void ata_dev_xfermask(struct ata_device *dev)
dev->mwdma_mask, dev->udma_mask); dev->mwdma_mask, dev->udma_mask);
xfer_mask &= ata_id_xfermask(dev->id); xfer_mask &= ata_id_xfermask(dev->id);
/*
* CFA Advanced TrueIDE timings are not allowed on a shared
* cable
*/
if (ata_dev_pair(dev)) {
/* No PIO5 or PIO6 */
xfer_mask &= ~(0x03 << (ATA_SHIFT_PIO + 5));
/* No MWDMA3 or MWDMA 4 */
xfer_mask &= ~(0x03 << (ATA_SHIFT_MWDMA + 3));
}
if (ata_dma_blacklisted(dev)) { if (ata_dma_blacklisted(dev)) {
xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA); xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
ata_dev_printk(dev, KERN_WARNING, ata_dev_printk(dev, KERN_WARNING,
......
...@@ -170,12 +170,16 @@ enum { ...@@ -170,12 +170,16 @@ enum {
XFER_UDMA_2 = 0x42, XFER_UDMA_2 = 0x42,
XFER_UDMA_1 = 0x41, XFER_UDMA_1 = 0x41,
XFER_UDMA_0 = 0x40, XFER_UDMA_0 = 0x40,
XFER_MW_DMA_4 = 0x24, /* CFA only */
XFER_MW_DMA_3 = 0x23, /* CFA only */
XFER_MW_DMA_2 = 0x22, XFER_MW_DMA_2 = 0x22,
XFER_MW_DMA_1 = 0x21, XFER_MW_DMA_1 = 0x21,
XFER_MW_DMA_0 = 0x20, XFER_MW_DMA_0 = 0x20,
XFER_SW_DMA_2 = 0x12, XFER_SW_DMA_2 = 0x12,
XFER_SW_DMA_1 = 0x11, XFER_SW_DMA_1 = 0x11,
XFER_SW_DMA_0 = 0x10, XFER_SW_DMA_0 = 0x10,
XFER_PIO_6 = 0x0E, /* CFA only */
XFER_PIO_5 = 0x0D, /* CFA only */
XFER_PIO_4 = 0x0C, XFER_PIO_4 = 0x0C,
XFER_PIO_3 = 0x0B, XFER_PIO_3 = 0x0B,
XFER_PIO_2 = 0x0A, XFER_PIO_2 = 0x0A,
...@@ -274,7 +278,6 @@ struct ata_taskfile { ...@@ -274,7 +278,6 @@ struct ata_taskfile {
}; };
#define ata_id_is_ata(id) (((id)[0] & (1 << 15)) == 0) #define ata_id_is_ata(id) (((id)[0] & (1 << 15)) == 0)
#define ata_id_is_cfa(id) ((id)[0] == 0x848A)
#define ata_id_is_sata(id) ((id)[93] == 0) #define ata_id_is_sata(id) ((id)[93] == 0)
#define ata_id_rahead_enabled(id) ((id)[85] & (1 << 6)) #define ata_id_rahead_enabled(id) ((id)[85] & (1 << 6))
#define ata_id_wcache_enabled(id) ((id)[85] & (1 << 5)) #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,6 +309,9 @@ static inline unsigned int ata_id_major_version(const u16 *id)
{ {
unsigned int mver; unsigned int mver;
if (id[ATA_ID_MAJOR_VER] == 0xFFFF)
return 0;
for (mver = 14; mver >= 1; mver--) for (mver = 14; mver >= 1; mver--)
if (id[ATA_ID_MAJOR_VER] & (1 << mver)) if (id[ATA_ID_MAJOR_VER] & (1 << mver))
break; break;
...@@ -324,6 +330,18 @@ static inline int ata_id_current_chs_valid(const u16 *id) ...@@ -324,6 +330,18 @@ static inline int ata_id_current_chs_valid(const u16 *id)
id[56]; /* sectors in current translation */ id[56]; /* sectors in current translation */
} }
static inline int ata_id_is_cfa(const u16 *id)
{
u16 v = id[0];
if (v == 0x848A) /* Standard CF */
return 1;
/* Could be CF hiding as standard ATA */
if (ata_id_major_version(id) >= 3 && id[82] != 0xFFFF &&
(id[82] & ( 1 << 2)))
return 1;
return 0;
}
static inline int atapi_cdb_len(const u16 *dev_id) static inline int atapi_cdb_len(const u16 *dev_id)
{ {
u16 tmp = dev_id[0] & 0x3; u16 tmp = dev_id[0] & 0x3;
......
...@@ -225,8 +225,8 @@ enum { ...@@ -225,8 +225,8 @@ enum {
/* encoding various smaller bitmaps into a single /* encoding various smaller bitmaps into a single
* unsigned int bitmap * unsigned int bitmap
*/ */
ATA_BITS_PIO = 5, ATA_BITS_PIO = 7,
ATA_BITS_MWDMA = 3, ATA_BITS_MWDMA = 5,
ATA_BITS_UDMA = 8, ATA_BITS_UDMA = 8,
ATA_SHIFT_PIO = 0, ATA_SHIFT_PIO = 0,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册