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