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) ...@@ -261,6 +261,14 @@ static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base, u8 req_mode)
break; break;
case XFER_MW_DMA_0: case XFER_MW_DMA_0:
mask = id[ATA_ID_MWDMA_MODES]; 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) if (port_ops && port_ops->mdma_filter)
mask &= port_ops->mdma_filter(drive); mask &= port_ops->mdma_filter(drive);
else else
......
...@@ -306,6 +306,7 @@ int ide_driveid_update(ide_drive_t *drive) ...@@ -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_UDMA_MODES] = id[ATA_ID_UDMA_MODES];
drive->id[ATA_ID_MWDMA_MODES] = id[ATA_ID_MWDMA_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_SWDMA_MODES] = id[ATA_ID_SWDMA_MODES];
drive->id[ATA_ID_CFA_MODES] = id[ATA_ID_CFA_MODES];
/* anything more ? */ /* anything more ? */
kfree(id); kfree(id);
...@@ -390,7 +391,10 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed) ...@@ -390,7 +391,10 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
id[ATA_ID_UDMA_MODES] &= ~0xFF00; id[ATA_ID_UDMA_MODES] &= ~0xFF00;
id[ATA_ID_MWDMA_MODES] &= ~0x0700; id[ATA_ID_MWDMA_MODES] &= ~0x0700;
id[ATA_ID_SWDMA_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: skip:
#ifdef CONFIG_BLK_DEV_IDEDMA #ifdef CONFIG_BLK_DEV_IDEDMA
...@@ -403,12 +407,18 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed) ...@@ -403,12 +407,18 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
if (speed >= XFER_UDMA_0) { if (speed >= XFER_UDMA_0) {
i = 1 << (speed - XFER_UDMA_0); i = 1 << (speed - XFER_UDMA_0);
id[ATA_ID_UDMA_MODES] |= (i << 8 | i); 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) { } else if (speed >= XFER_MW_DMA_0) {
i = 1 << (speed - XFER_MW_DMA_0); i = 1 << (speed - XFER_MW_DMA_0);
id[ATA_ID_MWDMA_MODES] |= (i << 8 | i); id[ATA_ID_MWDMA_MODES] |= (i << 8 | i);
} else if (speed >= XFER_SW_DMA_0) { } else if (speed >= XFER_SW_DMA_0) {
i = 1 << (speed - XFER_SW_DMA_0); i = 1 << (speed - XFER_SW_DMA_0);
id[ATA_ID_SWDMA_MODES] |= (i << 8 | i); 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) if (!drive->init_speed)
......
...@@ -43,6 +43,8 @@ static struct ide_timing ide_timing[] = { ...@@ -43,6 +43,8 @@ static struct ide_timing ide_timing[] = {
{ 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 },
{ 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_2, 25, 0, 0, 0, 70, 25, 120, 0 },
{ XFER_MW_DMA_1, 45, 0, 0, 0, 80, 50, 150, 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 }, { XFER_MW_DMA_0, 60, 0, 0, 0, 215, 215, 480, 0 },
...@@ -51,7 +53,8 @@ static struct ide_timing ide_timing[] = { ...@@ -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_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 },
...@@ -90,6 +93,10 @@ u16 ide_pio_cycle_time(ide_drive_t *drive, u8 pio) ...@@ -90,6 +93,10 @@ u16 ide_pio_cycle_time(ide_drive_t *drive, u8 pio)
/* conservative "downgrade" for all pre-ATA2 drives */ /* conservative "downgrade" for all pre-ATA2 drives */
if (pio < 3 && cycle < t->cycle) if (pio < 3 && cycle < t->cycle)
cycle = 0; /* use standard timing */ 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; return cycle ? cycle : t->cycle;
...@@ -161,7 +168,8 @@ int ide_timing_compute(ide_drive_t *drive, u8 speed, ...@@ -161,7 +168,8 @@ int ide_timing_compute(ide_drive_t *drive, u8 speed,
if (speed <= XFER_PIO_2) if (speed <= XFER_PIO_2)
p.cycle = p.cyc8b = id[ATA_ID_EIDE_PIO]; 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]; p.cycle = p.cyc8b = id[ATA_ID_EIDE_PIO_IORDY];
else if (speed >= XFER_MW_DMA_0 && speed <= XFER_MW_DMA_2) else if (speed >= XFER_MW_DMA_0 && speed <= XFER_MW_DMA_2)
p.cycle = id[ATA_ID_EIDE_DMA_MIN]; p.cycle = id[ATA_ID_EIDE_DMA_MIN];
......
...@@ -9,11 +9,11 @@ static const char *udma_str[] = ...@@ -9,11 +9,11 @@ static const char *udma_str[] =
{ "UDMA/16", "UDMA/25", "UDMA/33", "UDMA/44", { "UDMA/16", "UDMA/25", "UDMA/33", "UDMA/44",
"UDMA/66", "UDMA/100", "UDMA/133", "UDMA7" }; "UDMA/66", "UDMA/100", "UDMA/133", "UDMA7" };
static const char *mwdma_str[] = static const char *mwdma_str[] =
{ "MWDMA0", "MWDMA1", "MWDMA2" }; { "MWDMA0", "MWDMA1", "MWDMA2", "MWDMA3", "MWDMA4" };
static const char *swdma_str[] = static const char *swdma_str[] =
{ "SWDMA0", "SWDMA1", "SWDMA2" }; { "SWDMA0", "SWDMA1", "SWDMA2" };
static const char *pio_str[] = 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 * ide_xfer_verbose - return IDE mode names
...@@ -30,11 +30,11 @@ const char *ide_xfer_verbose(u8 mode) ...@@ -30,11 +30,11 @@ const char *ide_xfer_verbose(u8 mode)
if (mode >= XFER_UDMA_0 && mode <= XFER_UDMA_7) if (mode >= XFER_UDMA_0 && mode <= XFER_UDMA_7)
s = udma_str[i]; 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]; s = mwdma_str[i];
else if (mode >= XFER_SW_DMA_0 && mode <= XFER_SW_DMA_2) else if (mode >= XFER_SW_DMA_0 && mode <= XFER_SW_DMA_2)
s = swdma_str[i]; 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]; s = pio_str[i & 0x7];
else if (mode == XFER_PIO_SLOW) else if (mode == XFER_PIO_SLOW)
s = "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) ...@@ -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 (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) { if (id[ATA_ID_PIO_MODES] & 7) {
overridden = 0; overridden = 0;
if (id[ATA_ID_PIO_MODES] & 4) if (id[ATA_ID_PIO_MODES] & 4)
...@@ -239,7 +242,7 @@ int ide_set_xfer_rate(ide_drive_t *drive, u8 rate) ...@@ -239,7 +242,7 @@ int ide_set_xfer_rate(ide_drive_t *drive, u8 rate)
BUG_ON(rate < XFER_PIO_0); 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_pio_mode(drive, rate);
return ide_set_dma_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) ...@@ -61,7 +61,8 @@ static unsigned int get_pio_timings(ide_drive_t *drive, u8 pio)
if (cmd_off == 0) if (cmd_off == 0)
cmd_off = 1; 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; iordy = 0x40;
return (cmd_on - 1) << 8 | (cmd_off - 1) | iordy; 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