Modify DMA access timings.

This commit is contained in:
tsubai 2000-05-23 13:20:58 +00:00
parent 7b961f3147
commit f12221a5f5
1 changed files with 77 additions and 10 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: wdc_obio.c,v 1.8 2000/04/14 10:22:06 tsubai Exp $ */ /* $NetBSD: wdc_obio.c,v 1.9 2000/05/23 13:20:58 tsubai Exp $ */
/*- /*-
* Copyright (c) 1998 The NetBSD Foundation, Inc. * Copyright (c) 1998 The NetBSD Foundation, Inc.
@ -46,6 +46,7 @@
#include <machine/bus.h> #include <machine/bus.h>
#include <machine/autoconf.h> #include <machine/autoconf.h>
#include <dev/ata/atareg.h>
#include <dev/ata/atavar.h> #include <dev/ata/atavar.h>
#include <dev/ic/wdcvar.h> #include <dev/ic/wdcvar.h>
@ -71,18 +72,19 @@ struct wdc_obio_softc {
void *sc_ih; void *sc_ih;
}; };
int wdc_obio_probe __P((struct device *, struct cfdata *, void *)); int wdc_obio_probe __P((struct device *, struct cfdata *, void *));
void wdc_obio_attach __P((struct device *, struct device *, void *)); void wdc_obio_attach __P((struct device *, struct device *, void *));
int wdc_obio_detach __P((struct device *, int)); int wdc_obio_detach __P((struct device *, int));
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 *));
struct cfattach wdc_obio_ca = { struct cfattach wdc_obio_ca = {
sizeof(struct wdc_obio_softc), wdc_obio_probe, wdc_obio_attach, sizeof(struct wdc_obio_softc), wdc_obio_probe, wdc_obio_attach,
wdc_obio_detach, wdcactivate wdc_obio_detach, wdcactivate
}; };
static int wdc_obio_dma_init __P((void *, int, int, void *, size_t, int));
static void wdc_obio_dma_start __P((void *, int, int));
static int wdc_obio_dma_finish __P((void *, int, int, int));
int int
wdc_obio_probe(parent, match, aux) wdc_obio_probe(parent, match, aux)
@ -198,6 +200,71 @@ wdc_obio_attach(parent, self, aux)
} }
wdcattach(chp); wdcattach(chp);
/* modify DMA access timings */
if (use_dma)
adjust_timing(chp);
}
/* Multiword DMA transfer timings */
static struct {
int cycle; /* minimum cycle time [ns] */
int active; /* minimum command active time [ns] */
} dma_timing[3] = {
480, 215, /* Mode 0 */
150, 80, /* Mode 1 */
120, 70, /* Mode 2 */
};
#define TIME_TO_TICK(time) howmany((time), 30)
#define CONFIG_REG (0x200 >> 4) /* IDE access timing register */
void
adjust_timing(chp)
struct channel_softc *chp;
{
struct ataparams params;
struct ata_drive_datas *drvp = &chp->ch_drive[0]; /* XXX */
u_int conf;
int mode;
int cycle, active, min_cycle, min_active;
int cycle_tick, act_tick, inact_tick, half_tick;
if (ata_get_params(drvp, AT_POLL, &params) != CMD_OK)
return;
for (mode = 2; mode >= 0; mode--)
if (params.atap_dmamode_act & (1 << mode))
goto found;
/* No active DMA mode is found... Do nothing. */
return;
found:
min_cycle = dma_timing[mode].cycle;
min_active = dma_timing[mode].active;
#ifdef notyet
/* Minimum cycle time is 150ns on ohare. */
if (ohare && params.atap_dmatiming_recom < 150)
params.atap_dmatiming_recom = 150;
#endif
cycle = max(min_cycle, params.atap_dmatiming_recom);
active = min_active + (cycle - min_cycle); /* XXX */
cycle_tick = TIME_TO_TICK(cycle);
act_tick = TIME_TO_TICK(active);
inact_tick = cycle_tick - act_tick - 1;
if (inact_tick < 1)
inact_tick = 1;
half_tick = 0; /* XXX */
conf = (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, cycle, act_tick, active, inact_tick);
#endif
} }
int int
@ -226,7 +293,7 @@ wdc_obio_detach(self, flags)
return 0; return 0;
} }
static int int
wdc_obio_dma_init(v, channel, drive, databuf, datalen, read) wdc_obio_dma_init(v, channel, drive, databuf, datalen, read)
void *v; void *v;
void *databuf; void *databuf;
@ -278,7 +345,7 @@ wdc_obio_dma_init(v, channel, drive, databuf, datalen, read)
return 0; return 0;
} }
static void void
wdc_obio_dma_start(v, channel, drive) wdc_obio_dma_start(v, channel, drive)
void *v; void *v;
int channel, drive; int channel, drive;
@ -288,7 +355,7 @@ wdc_obio_dma_start(v, channel, drive)
dbdma_start(sc->sc_dmareg, sc->sc_dmacmd); dbdma_start(sc->sc_dmareg, sc->sc_dmacmd);
} }
static int int
wdc_obio_dma_finish(v, channel, drive, read) wdc_obio_dma_finish(v, channel, drive, read)
void *v; void *v;
int channel, drive; int channel, drive;