Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/macppc/dev Properly setup timings for ata-4 control...
details: https://anonhg.NetBSD.org/src/rev/1923691fa022
branches: trunk
changeset: 513505:1923691fa022
user: bouyer <bouyer%NetBSD.org@localhost>
date: Thu Aug 02 12:41:39 2001 +0000
description:
Properly setup timings for ata-4 controllers, including UDMA modes.
Tested on a brand new ("dual USB ?") ibook.
diffstat:
sys/arch/macppc/dev/wdc_obio.c | 129 +++++++++++++++++++++++++++++++++++-----
1 files changed, 113 insertions(+), 16 deletions(-)
diffs (193 lines):
diff -r ac8632cf671b -r 1923691fa022 sys/arch/macppc/dev/wdc_obio.c
--- a/sys/arch/macppc/dev/wdc_obio.c Thu Aug 02 12:24:05 2001 +0000
+++ b/sys/arch/macppc/dev/wdc_obio.c Thu Aug 02 12:41:39 2001 +0000
@@ -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 @@
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 @@
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 @@
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 @@
}
wdcattach(chp);
-
- /* modify DMA access timings */
- if (use_dma)
- adjust_timing(chp);
+ sc->sc_wdcdev.set_modes(chp);
}
@@ -236,7 +240,24 @@
{ 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 @@
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);
}
Home |
Main Index |
Thread Index |
Old Index