Commit 74638c84 authored by Sergei Shtylyov's avatar Sergei Shtylyov Committed by Bartlomiej Zolnierkiewicz

ide: add support for CFA specified transfer modes (take 3)

Add support for the CompactFlash specific PIO modes 5/6 and MWDMA modes 3/4.

Since there were no PIO5 capable hard drives produced and one would also need
66 MHz IDE clock to actually get the difference WRT the address setup timings
programmed, I decided to simply replace the old non-standard PIO mode 5 timings
with the CFA specified ones.
Signed-off-by: default avatarSergei Shtylyov <sshtylyov@ru.mvista.com>
Cc: stf_xl@wp.pl
Signed-off-by: default avatarBartlomiej Zolnierkiewicz <bzolnier@gmail.com>
parent c4199930
......@@ -261,6 +261,14 @@ static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base, u8 req_mode)
break;
case XFER_MW_DMA_0:
mask = id[ATA_ID_MWDMA_MODES];
/* Also look for the CF specific MWDMA modes... */
if (ata_id_is_cfa(id) && (id[ATA_ID_CFA_MODES] & 0x38)) {
u8 mode = ((id[ATA_ID_CFA_MODES] & 0x38) >> 3) - 1;
mask |= ((2 << mode) - 1) << 3;
}
if (port_ops && port_ops->mdma_filter)
mask &= port_ops->mdma_filter(drive);
else
......
......@@ -306,6 +306,7 @@ int ide_driveid_update(ide_drive_t *drive)
drive->id[ATA_ID_UDMA_MODES] = id[ATA_ID_UDMA_MODES];
drive->id[ATA_ID_MWDMA_MODES] = id[ATA_ID_MWDMA_MODES];
drive->id[ATA_ID_SWDMA_MODES] = id[ATA_ID_SWDMA_MODES];
drive->id[ATA_ID_CFA_MODES] = id[ATA_ID_CFA_MODES];
/* anything more ? */
kfree(id);
......@@ -390,7 +391,10 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
id[ATA_ID_UDMA_MODES] &= ~0xFF00;
id[ATA_ID_MWDMA_MODES] &= ~0x0700;
id[ATA_ID_SWDMA_MODES] &= ~0x0700;
}
if (ata_id_is_cfa(id))
id[ATA_ID_CFA_MODES] &= ~0x0E00;
} else if (ata_id_is_cfa(id))
id[ATA_ID_CFA_MODES] &= ~0x01C0;
skip:
#ifdef CONFIG_BLK_DEV_IDEDMA
......@@ -403,12 +407,18 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
if (speed >= XFER_UDMA_0) {
i = 1 << (speed - XFER_UDMA_0);
id[ATA_ID_UDMA_MODES] |= (i << 8 | i);
} else if (ata_id_is_cfa(id) && speed >= XFER_MW_DMA_3) {
i = speed - XFER_MW_DMA_2;
id[ATA_ID_CFA_MODES] |= i << 9;
} else if (speed >= XFER_MW_DMA_0) {
i = 1 << (speed - XFER_MW_DMA_0);
id[ATA_ID_MWDMA_MODES] |= (i << 8 | i);
} else if (speed >= XFER_SW_DMA_0) {
i = 1 << (speed - XFER_SW_DMA_0);
id[ATA_ID_SWDMA_MODES] |= (i << 8 | i);
} else if (ata_id_is_cfa(id) && speed >= XFER_PIO_5) {
i = speed - XFER_PIO_4;
id[ATA_ID_CFA_MODES] |= i << 6;
}
if (!drive->init_speed)
......
......@@ -43,6 +43,8 @@ static struct ide_timing ide_timing[] = {
{ XFER_UDMA_1, 0, 0, 0, 0, 0, 0, 0, 80 },
{ XFER_UDMA_0, 0, 0, 0, 0, 0, 0, 0, 120 },
{ 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_MW_DMA_2, 25, 0, 0, 0, 70, 25, 120, 0 },
{ XFER_MW_DMA_1, 45, 0, 0, 0, 80, 50, 150, 0 },
{ XFER_MW_DMA_0, 60, 0, 0, 0, 215, 215, 480, 0 },
......@@ -51,7 +53,8 @@ static struct ide_timing ide_timing[] = {
{ 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_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_3, 30, 80, 70, 180, 80, 70, 180, 0 },
......@@ -90,6 +93,10 @@ u16 ide_pio_cycle_time(ide_drive_t *drive, u8 pio)
/* conservative "downgrade" for all pre-ATA2 drives */
if (pio < 3 && cycle < t->cycle)
cycle = 0; /* use standard timing */
/* Use the standard timing for the CF specific modes too */
if (pio > 4 && ata_id_is_cfa(id))
cycle = 0;
}
return cycle ? cycle : t->cycle;
......@@ -161,7 +168,8 @@ int ide_timing_compute(ide_drive_t *drive, u8 speed,
if (speed <= XFER_PIO_2)
p.cycle = p.cyc8b = id[ATA_ID_EIDE_PIO];
else if (speed <= XFER_PIO_5)
else if ((speed <= XFER_PIO_4) ||
(speed == XFER_PIO_5 && !ata_id_is_cfa(id)))
p.cycle = p.cyc8b = id[ATA_ID_EIDE_PIO_IORDY];
else if (speed >= XFER_MW_DMA_0 && speed <= XFER_MW_DMA_2)
p.cycle = id[ATA_ID_EIDE_DMA_MIN];
......
......@@ -9,11 +9,11 @@ static const char *udma_str[] =
{ "UDMA/16", "UDMA/25", "UDMA/33", "UDMA/44",
"UDMA/66", "UDMA/100", "UDMA/133", "UDMA7" };
static const char *mwdma_str[] =
{ "MWDMA0", "MWDMA1", "MWDMA2" };
{ "MWDMA0", "MWDMA1", "MWDMA2", "MWDMA3", "MWDMA4" };
static const char *swdma_str[] =
{ "SWDMA0", "SWDMA1", "SWDMA2" };
static const char *pio_str[] =
{ "PIO0", "PIO1", "PIO2", "PIO3", "PIO4", "PIO5" };
{ "PIO0", "PIO1", "PIO2", "PIO3", "PIO4", "PIO5", "PIO6" };
/**
* ide_xfer_verbose - return IDE mode names
......@@ -30,11 +30,11 @@ const char *ide_xfer_verbose(u8 mode)
if (mode >= XFER_UDMA_0 && mode <= XFER_UDMA_7)
s = udma_str[i];
else if (mode >= XFER_MW_DMA_0 && mode <= XFER_MW_DMA_2)
else if (mode >= XFER_MW_DMA_0 && mode <= XFER_MW_DMA_4)
s = mwdma_str[i];
else if (mode >= XFER_SW_DMA_0 && mode <= XFER_SW_DMA_2)
s = swdma_str[i];
else if (mode >= XFER_PIO_0 && mode <= XFER_PIO_5)
else if (mode >= XFER_PIO_0 && mode <= XFER_PIO_6)
s = pio_str[i & 0x7];
else if (mode == XFER_PIO_SLOW)
s = "PIO SLOW";
......@@ -79,7 +79,10 @@ u8 ide_get_best_pio_mode(ide_drive_t *drive, u8 mode_wanted, u8 max_mode)
}
if (id[ATA_ID_FIELD_VALID] & 2) { /* ATA2? */
if (ata_id_has_iordy(id)) {
if (ata_id_is_cfa(id) && (id[ATA_ID_CFA_MODES] & 7))
pio_mode = 4 + min_t(int, 2,
id[ATA_ID_CFA_MODES] & 7);
else if (ata_id_has_iordy(id)) {
if (id[ATA_ID_PIO_MODES] & 7) {
overridden = 0;
if (id[ATA_ID_PIO_MODES] & 4)
......@@ -239,7 +242,7 @@ int ide_set_xfer_rate(ide_drive_t *drive, u8 rate)
BUG_ON(rate < XFER_PIO_0);
if (rate >= XFER_PIO_0 && rate <= XFER_PIO_5)
if (rate >= XFER_PIO_0 && rate <= XFER_PIO_6)
return ide_set_pio_mode(drive, rate);
return ide_set_dma_mode(drive, rate);
......
......@@ -61,7 +61,8 @@ static unsigned int get_pio_timings(ide_drive_t *drive, u8 pio)
if (cmd_off == 0)
cmd_off = 1;
if (pio > 2 || ata_id_has_iordy(drive->id))
if ((pio > 2 || ata_id_has_iordy(drive->id)) &&
!(pio > 4 && ata_id_is_cfa(drive->id)))
iordy = 0x40;
return (cmd_on - 1) << 8 | (cmd_off - 1) | iordy;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment