Properly setup timings for ata-4 controllers, including UDMA modes.
Tested on a brand new ("dual USB ?") ibook.
This commit is contained in:
parent
ad2c12a28d
commit
f7c2f13a54
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: wdc_obio.c,v 1.15 2001/07/25 20:26:33 bouyer Exp $ */
|
||||
/* $NetBSD: wdc_obio.c,v 1.16 2001/08/02 12:41:39 bouyer Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
|
@ -81,6 +81,7 @@ int wdc_obio_dma_init __P((void *, int, int, void *, size_t, int));
|
|||
void wdc_obio_dma_start __P((void *, int, int));
|
||||
int wdc_obio_dma_finish __P((void *, int, int, int));
|
||||
static void adjust_timing __P((struct channel_softc *));
|
||||
static void ata4_adjust_timing __P((struct channel_softc *));
|
||||
|
||||
struct cfattach wdc_obio_ca = {
|
||||
sizeof(struct wdc_obio_softc), wdc_obio_probe, wdc_obio_attach,
|
||||
|
@ -169,6 +170,13 @@ wdc_obio_attach(parent, self, aux)
|
|||
ca->ca_reg[3]);
|
||||
sc->sc_wdcdev.cap |= WDC_CAPABILITY_DMA;
|
||||
sc->sc_wdcdev.DMA_cap = 2;
|
||||
if (strcmp(ca->ca_name, "ata-4") == 0) {
|
||||
sc->sc_wdcdev.cap |= WDC_CAPABILITY_UDMA;
|
||||
sc->sc_wdcdev.UDMA_cap = 4;
|
||||
sc->sc_wdcdev.set_modes = ata4_adjust_timing;
|
||||
} else {
|
||||
sc->sc_wdcdev.set_modes = adjust_timing;
|
||||
}
|
||||
#ifdef notyet
|
||||
/* Minimum cycle time is 150ns (DMA MODE 1) on ohare. */
|
||||
if (ohare) {
|
||||
|
@ -186,7 +194,6 @@ wdc_obio_attach(parent, self, aux)
|
|||
sc->sc_wdcdev.dma_init = wdc_obio_dma_init;
|
||||
sc->sc_wdcdev.dma_start = wdc_obio_dma_start;
|
||||
sc->sc_wdcdev.dma_finish = wdc_obio_dma_finish;
|
||||
sc->sc_wdcdev.set_modes = adjust_timing;
|
||||
chp->channel = 0;
|
||||
chp->wdc = &sc->sc_wdcdev;
|
||||
chp->ch_queue = malloc(sizeof(struct channel_queue),
|
||||
|
@ -211,10 +218,7 @@ wdc_obio_attach(parent, self, aux)
|
|||
}
|
||||
|
||||
wdcattach(chp);
|
||||
|
||||
/* modify DMA access timings */
|
||||
if (use_dma)
|
||||
adjust_timing(chp);
|
||||
sc->sc_wdcdev.set_modes(chp);
|
||||
|
||||
}
|
||||
|
||||
|
@ -236,7 +240,24 @@ static struct ide_timings dma_timing[3] = {
|
|||
{ 120, 70 }, /* Mode 2 */
|
||||
};
|
||||
|
||||
static struct ide_timings udma_timing[5] = {
|
||||
{114, 0}, /* Mode 0 */
|
||||
{ 75, 0}, /* Mode 1 */
|
||||
{ 55, 0}, /* Mode 2 */
|
||||
{ 45, 100}, /* Mode 3 */
|
||||
{ 25, 100} /* Mode 4 */
|
||||
};
|
||||
|
||||
#define TIME_TO_TICK(time) howmany((time), 30)
|
||||
#define PIO_REC_OFFSET 4
|
||||
#define PIO_REC_MIN 1
|
||||
#define PIO_ACT_MIN 1
|
||||
#define DMA_REC_OFFSET 1
|
||||
#define DMA_REC_MIN 1
|
||||
#define DMA_ACT_MIN 1
|
||||
|
||||
#define ATA4_TIME_TO_TICK(time) howmany((time) * 1000, 7500)
|
||||
|
||||
|
||||
#define CONFIG_REG (0x200 >> 4) /* IDE access timing register */
|
||||
|
||||
|
@ -278,30 +299,106 @@ adjust_timing(chp)
|
|||
|
||||
cycle_tick = TIME_TO_TICK(min_cycle);
|
||||
act_tick = TIME_TO_TICK(min_active);
|
||||
inact_tick = cycle_tick - act_tick - 1;
|
||||
if (inact_tick < 1)
|
||||
inact_tick = 1;
|
||||
if (act_tick < PIO_ACT_MIN)
|
||||
act_tick = PIO_ACT_MIN;
|
||||
inact_tick = cycle_tick - act_tick - PIO_REC_OFFSET;
|
||||
if (inact_tick < PIO_REC_MIN)
|
||||
inact_tick = PIO_REC_MIN;
|
||||
/* mask: 0x000007ff */
|
||||
conf = (inact_tick << 5) | act_tick;
|
||||
if (dmamode != -1) {
|
||||
/* there are active DMA mode */
|
||||
|
||||
min_cycle = dma_timing[dmamode].cycle;
|
||||
min_active = dma_timing[dmamode].active;
|
||||
|
||||
cycle_tick = TIME_TO_TICK(min_cycle);
|
||||
act_tick = TIME_TO_TICK(min_active);
|
||||
inact_tick = cycle_tick - act_tick - 1;
|
||||
if (inact_tick < 1)
|
||||
inact_tick = 1;
|
||||
inact_tick = cycle_tick - act_tick - DMA_REC_OFFSET;
|
||||
if (inact_tick < DMA_REC_MIN)
|
||||
inact_tick = DMA_REC_MIN;
|
||||
half_tick = 0; /* XXX */
|
||||
/* mask: 0xfffff800 */
|
||||
conf |=
|
||||
(half_tick << 21) | (inact_tick << 16) | (act_tick << 11);
|
||||
(half_tick << 21) |
|
||||
(inact_tick << 16) | (act_tick << 11);
|
||||
}
|
||||
bus_space_write_4(chp->cmd_iot, chp->cmd_ioh, CONFIG_REG, conf);
|
||||
#if 0
|
||||
printf("conf = 0x%x, cyc = %d (%d ns), act = %d (%d ns), inact = %d\n",
|
||||
conf, cycle_tick, min_cycle, act_tick, min_active, inact_tick);
|
||||
#endif
|
||||
wdc_print_modes(chp);
|
||||
}
|
||||
|
||||
void
|
||||
ata4_adjust_timing(chp)
|
||||
struct channel_softc *chp;
|
||||
{
|
||||
struct ata_drive_datas *drvp;
|
||||
u_int conf;
|
||||
int drive;
|
||||
int piomode = -1, dmamode = -1;
|
||||
int min_cycle, min_active;
|
||||
int cycle_tick, act_tick, inact_tick;
|
||||
int udmamode = -1;
|
||||
|
||||
|
||||
for (drive = 0; drive < 2; drive++) {
|
||||
drvp = &chp->ch_drive[drive];
|
||||
if ((drvp->drive_flags & DRIVE) == 0)
|
||||
continue;
|
||||
if (piomode == -1 || piomode > drvp->PIO_mode)
|
||||
piomode = drvp->PIO_mode;
|
||||
if (drvp->drive_flags & DRIVE_DMA) {
|
||||
if (dmamode == -1 || dmamode > drvp->DMA_mode)
|
||||
dmamode = drvp->DMA_mode;
|
||||
}
|
||||
if (drvp->drive_flags & DRIVE_UDMA) {
|
||||
if (udmamode == -1 || udmamode > drvp->UDMA_mode)
|
||||
udmamode = drvp->UDMA_mode;
|
||||
}
|
||||
}
|
||||
if (piomode == -1)
|
||||
return; /* No drive */
|
||||
for (drive = 0; drive < 2; drive++) {
|
||||
drvp = &chp->ch_drive[drive];
|
||||
if (drvp->drive_flags & DRIVE) {
|
||||
drvp->PIO_mode = piomode;
|
||||
if (drvp->drive_flags & DRIVE_DMA)
|
||||
drvp->DMA_mode = dmamode;
|
||||
if (drvp->drive_flags & DRIVE_UDMA)
|
||||
drvp->UDMA_mode = udmamode;
|
||||
}
|
||||
}
|
||||
min_cycle = pio_timing[piomode].cycle;
|
||||
min_active = pio_timing[piomode].active;
|
||||
|
||||
cycle_tick = ATA4_TIME_TO_TICK(min_cycle);
|
||||
act_tick = ATA4_TIME_TO_TICK(min_active);
|
||||
inact_tick = cycle_tick - act_tick;
|
||||
/* mask: 0x000003ff */
|
||||
conf = (inact_tick << 5) | act_tick;
|
||||
if (dmamode != -1) {
|
||||
/* there are active DMA mode */
|
||||
|
||||
min_cycle = dma_timing[dmamode].cycle;
|
||||
min_active = dma_timing[dmamode].active;
|
||||
cycle_tick = ATA4_TIME_TO_TICK(min_cycle);
|
||||
act_tick = ATA4_TIME_TO_TICK(min_active);
|
||||
inact_tick = cycle_tick - act_tick;
|
||||
/* mask: 0x001ffc00 */
|
||||
conf |= (act_tick << 10) | (inact_tick << 15);
|
||||
}
|
||||
if (udmamode != -1) {
|
||||
min_cycle = udma_timing[udmamode].cycle;
|
||||
min_active = udma_timing[udmamode].active;
|
||||
act_tick = ATA4_TIME_TO_TICK(min_active);
|
||||
cycle_tick = ATA4_TIME_TO_TICK(min_cycle);
|
||||
/* mask: 0x1ff00000 */
|
||||
conf |= (cycle_tick << 21) | (act_tick << 25) | 0x100000;
|
||||
}
|
||||
|
||||
bus_space_write_4(chp->cmd_iot, chp->cmd_ioh, CONFIG_REG, conf);
|
||||
printf("ata4 conf = 0x%x, cyc = %d (%d ns), act = %d (%d ns), inact = %d\n",
|
||||
conf, cycle_tick, min_cycle, act_tick, min_active, inact_tick);
|
||||
wdc_print_modes(chp);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue