summaryrefslogtreecommitdiff
path: root/sys/arch/macppc/dev
diff options
context:
space:
mode:
authorbouyer <bouyer@NetBSD.org>2001-06-15 10:35:26 +0000
committerbouyer <bouyer@NetBSD.org>2001-06-15 10:35:26 +0000
commit17eff1c958d1de016aa09f73edae4e0ad62379cb (patch)
treef3c5ac96cdc6476d3735b93013a561442e2fb3dc /sys/arch/macppc/dev
parent361f8ca97546046d82a1b5d6e5eb68253f85a43d (diff)
Pass WDC_CAPABILITY_MODE to the wdc core, so that it will set timings
on the drive side too. Deal properly with the case where master and slave don't have the same timings, and set PIO timings too.
Diffstat (limited to 'sys/arch/macppc/dev')
-rw-r--r--sys/arch/macppc/dev/wdc_obio.c102
1 files changed, 67 insertions, 35 deletions
diff --git a/sys/arch/macppc/dev/wdc_obio.c b/sys/arch/macppc/dev/wdc_obio.c
index a51eab868c7..bfe078e15af 100644
--- a/sys/arch/macppc/dev/wdc_obio.c
+++ b/sys/arch/macppc/dev/wdc_obio.c
@@ -1,4 +1,4 @@
-/* $NetBSD: wdc_obio.c,v 1.12 2001/06/08 00:32:02 matt Exp $ */
+/* $NetBSD: wdc_obio.c,v 1.13 2001/06/15 10:35:26 bouyer Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -168,9 +168,17 @@ wdc_obio_attach(parent, self, aux)
sc->sc_dmareg = mapiodev(ca->ca_baseaddr + ca->ca_reg[2],
ca->ca_reg[3]);
sc->sc_wdcdev.cap |= WDC_CAPABILITY_DMA;
+ sc->sc_wdcdev.DMA_cap = 2;
+#ifdef notyet
+ /* Minimum cycle time is 150ns (DMA MODE 1) on ohare. */
+ if (ohare) {
+ sc->sc_wdcdev.PIO_cap = 3;
+ sc->sc_wdcdev.DMA_cap = 1;
+ }
+#endif
}
- sc->sc_wdcdev.cap |= WDC_CAPABILITY_DATA16;
- sc->sc_wdcdev.PIO_cap = 0;
+ sc->sc_wdcdev.PIO_cap = 4;
+ sc->sc_wdcdev.cap |= WDC_CAPABILITY_DATA16 | WDC_CAPABILITY_MODE;
sc->wdc_chanptr = chp;
sc->sc_wdcdev.channels = &sc->wdc_chanptr;
sc->sc_wdcdev.nchannels = 1;
@@ -178,6 +186,7 @@ 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),
@@ -207,14 +216,21 @@ wdc_obio_attach(parent, self, aux)
if (use_dma)
adjust_timing(chp);
- wdc_print_modes(chp);
}
/* Multiword DMA transfer timings */
-static struct {
+struct ide_timings {
int cycle; /* minimum cycle time [ns] */
int active; /* minimum command active time [ns] */
-} dma_timing[3] = {
+};
+static struct ide_timings pio_timing[5] = {
+ { 600, 165 }, /* Mode 0 */
+ { 383, 125 }, /* 1 */
+ { 240, 100 }, /* 2 */
+ { 180, 80 }, /* 3 */
+ { 120, 70 } /* 4 */
+};
+static struct ide_timings dma_timing[3] = {
{ 480, 215 }, /* Mode 0 */
{ 150, 80 }, /* Mode 1 */
{ 120, 70 }, /* Mode 2 */
@@ -228,47 +244,63 @@ void
adjust_timing(chp)
struct channel_softc *chp;
{
- struct ataparams params;
- struct ata_drive_datas *drvp = &chp->ch_drive[0]; /* XXX */
+ struct ata_drive_datas *drvp;
u_int conf;
- int mode;
- int cycle, active, min_cycle, min_active;
+ int drive;
+ int piomode = -1, dmamode = -1;
+ int 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 */
+ 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;
+ }
+ }
+ 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;
+ }
+ }
+ min_cycle = pio_timing[piomode].cycle;
+ min_active = pio_timing[piomode].active;
- cycle_tick = TIME_TO_TICK(cycle);
- act_tick = TIME_TO_TICK(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;
- half_tick = 0; /* XXX */
- conf = (half_tick << 21) | (inact_tick << 16) | (act_tick << 11);
+ 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;
+ 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);
+ conf, cycle_tick, min_cycle, act_tick, min_active, inact_tick);
#endif
+ wdc_print_modes(chp);
}
int