Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/next68k/dev minor rework of dma driver



details:   https://anonhg.NetBSD.org/src/rev/1af8576e058a
branches:  trunk
changeset: 475882:1af8576e058a
user:      dbj <dbj%NetBSD.org@localhost>
date:      Sun Aug 29 05:56:26 1999 +0000

description:
minor rework of dma driver
now uses the DMACSR_READ bit and no longer keeps _nd_dmadir in softc
unified transfer cleanup code, now in routine next_dma_finish_xfer()
fixed bounds checking on registers after transfer.
removed checking for bus errors since the bit is always set on some nexts
(specifically, on mourning, a 25mhz 68040 mono slab)
fixed a couple of dma bugs involving chaining dma buffers.

diffstat:

 sys/arch/next68k/dev/nextdma.c    |  419 ++++++++++++++-----------------------
 sys/arch/next68k/dev/nextdmavar.h |    4 +-
 2 files changed, 166 insertions(+), 257 deletions(-)

diffs (truncated from 597 to 300 lines):

diff -r 549137e440b1 -r 1af8576e058a sys/arch/next68k/dev/nextdma.c
--- a/sys/arch/next68k/dev/nextdma.c    Sun Aug 29 05:51:45 1999 +0000
+++ b/sys/arch/next68k/dev/nextdma.c    Sun Aug 29 05:56:26 1999 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: nextdma.c,v 1.19 1999/08/28 09:19:05 dbj Exp $ */
+/*     $NetBSD: nextdma.c,v 1.20 1999/08/29 05:56:26 dbj Exp $ */
 /*
  * Copyright (c) 1998 Darrin B. Jewell
  * All rights reserved.
@@ -71,6 +71,7 @@
 
 void next_dma_setup_cont_regs __P((struct nextdma_config *));
 void next_dma_setup_curr_regs __P((struct nextdma_config *));
+void next_dma_finish_xfer __P((struct nextdma_config *));
 
 void
 nextdma_config(nd)
@@ -115,7 +116,6 @@
   DPRINTF(("DMA init ipl (%ld) intr(0x%b)\n",
                        NEXT_I_IPL(nd->nd_intr), NEXT_I_BIT(nd->nd_intr),NEXT_INTR_BITS));
 
-       /* @@@ should probably check and free these maps */
        nd->_nd_map = NULL;
        nd->_nd_idx = 0;
        nd->_nd_map_cont = NULL;
@@ -123,26 +123,29 @@
 
        bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_CSR, 0);
        bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_CSR,
-                       DMACSR_INITBUF | DMACSR_CLRCOMPLETE | DMACSR_RESET);
+                       DMACSR_RESET | DMACSR_INITBUF);
 
        next_dma_setup_curr_regs(nd);
        next_dma_setup_cont_regs(nd);
 
-#if 0 && defined(DIAGNOSTIC)
-       /* Today, my computer (mourning) appears to fail this test.
-        * yesterday, another NeXT (milo) didn't have this problem
-        * Darrin B. Jewell <jewell%mit.edu@localhost>  Mon May 25 07:53:05 1998
-        */
+#if defined(DIAGNOSTIC)
        {
                u_long state;
                state = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_CSR);
-               state = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_CSR);
+
+#if 1
+       /* mourning (a 25Mhz 68040 mono slab) appears to set BUSEXC
+        * milo (a 25Mhz 68040 mono cube) didn't have this problem
+        * Darrin B. Jewell <jewell%mit.edu@localhost>  Mon May 25 07:53:05 1998
+        */
+    state &= (DMACSR_COMPLETE | DMACSR_SUPDATE | DMACSR_ENABLE);
+#else
     state &= (DMACSR_BUSEXC | DMACSR_COMPLETE | 
               DMACSR_SUPDATE | DMACSR_ENABLE);
-
+#endif
                if (state) {
                        next_dma_print(nd);
-                       panic("DMA did not reset\n");
+                       panic("DMA did not reset");
                }
        }
 #endif
@@ -162,6 +165,8 @@
        if (nextdma_debug) next_dma_print(nd);
 #endif
 
+       /* @@@ clean up dma maps */
+
        nextdma_init(nd);
        splx(s);
 }
@@ -179,22 +184,6 @@
 
        DPRINTF(("DMA next_dma_rotate()\n"));
 
-#ifdef DIAGNOSTIC
-       if (nd->_nd_map && 
-                       nd->_nd_map->dm_segs[nd->_nd_idx].ds_xfer_len == 0x1234beef) {
-               next_dma_print(nd);
-               panic("DMA didn't set xfer length of segment");
-       }
-#endif
-
-       /* If we've reached the end of the current map, then inform
-        * that we've completed that map.
-        */
-       if (nd->_nd_map && ((nd->_nd_idx+1) == nd->_nd_map->dm_nsegs)) {
-               if (nd->nd_completed_cb) 
-                       (*nd->nd_completed_cb)(nd->_nd_map, nd->nd_cb_arg);
-       }
-
        /* Rotate the continue map into the current map */
        nd->_nd_map = nd->_nd_map_cont;
        nd->_nd_idx = nd->_nd_idx_cont;
@@ -236,95 +225,91 @@
 next_dma_setup_cont_regs(nd)
        struct nextdma_config *nd;
 {
+       bus_addr_t dd_start;
+       bus_addr_t dd_stop;
+       bus_addr_t dd_saved_start;
+       bus_addr_t dd_saved_stop;
+
        DPRINTF(("DMA next_dma_setup_regs()\n"));
 
        if (nd->_nd_map_cont) {
+               dd_start = nd->_nd_map_cont->dm_segs[nd->_nd_idx_cont].ds_addr;
+               dd_stop  = (nd->_nd_map_cont->dm_segs[nd->_nd_idx_cont].ds_addr +
+                               nd->_nd_map_cont->dm_segs[nd->_nd_idx_cont].ds_len);
 
                if (nd->nd_intr == NEXT_I_ENETX_DMA) {
-                       /* Ethernet transmit needs secret magic */
-
-                       bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_START,
-                                       nd->_nd_map_cont->dm_segs[nd->_nd_idx_cont].ds_addr);
-                       bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_STOP,
-                                       ((nd->_nd_map_cont->dm_segs[nd->_nd_idx_cont].ds_addr +
-                                                       nd->_nd_map_cont->dm_segs[nd->_nd_idx_cont].ds_len)
-                                                       + 0x0) | 0x80000000);
-
+                       dd_stop |= 0x80000000;          /* Ethernet transmit needs secret magic */
                }
-               else {
-                       bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_START,
-                                       nd->_nd_map_cont->dm_segs[nd->_nd_idx_cont].ds_addr);
-                       bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_STOP,
-                                       nd->_nd_map_cont->dm_segs[nd->_nd_idx_cont].ds_addr +
-                                       nd->_nd_map_cont->dm_segs[nd->_nd_idx_cont].ds_len);
-               }
-
        } else {
-
-               bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_START, 0xdeadbeef);
-               bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_STOP, 0xdeadbeef);
+               dd_start = 0xdeadbeef;
+               dd_stop = 0xdeadbeef;
        }
 
-#if 1 /* 0xfeedbeef in these registers leads to instability.  it will
-                        * panic after a short while with 0xfeedbeef in the DD_START and DD_STOP
-                        * registers.  I suspect that an unexpected hardware restart
-                        * is cycling the bogus values into the active registers.  Until
-                        * that is understood, we seed these with the same as DD_START and DD_STOP
-                        */
-       bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_START, 
-                       bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_START));
-       bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_STOP,
-                       bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_STOP));
-#else
-       bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_START, 0xfeedbeef);
-       bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_STOP, 0xfeedbeef);
+       dd_saved_start = dd_start;
+       dd_saved_stop  = dd_stop;
+
+       bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_START, dd_start);
+       bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_STOP, dd_stop);
+       bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_START, dd_saved_start);
+       bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_STOP, dd_saved_stop);
+
+#ifdef DIAGNOSTIC
+       if ((bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_START) != dd_start) ||
+                       (bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_STOP) != dd_stop) ||
+                       (bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_START) != dd_saved_start) ||
+                       (bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_STOP) != dd_saved_stop)) {
+               next_dma_print(nd);
+               panic("DMA failure writing to continue regs");
+       }
 #endif
-
 }
 
 void
 next_dma_setup_curr_regs(nd)
        struct nextdma_config *nd;
 {
+       bus_addr_t dd_next;
+       bus_addr_t dd_limit;
+       bus_addr_t dd_saved_next;
+       bus_addr_t dd_saved_limit;
+
        DPRINTF(("DMA next_dma_setup_curr_regs()\n"));
 
 
        if (nd->_nd_map) {
-
+               dd_next = nd->_nd_map->dm_segs[nd->_nd_idx].ds_addr;
+               dd_limit = (nd->_nd_map->dm_segs[nd->_nd_idx].ds_addr +
+                               nd->_nd_map->dm_segs[nd->_nd_idx].ds_len);
                if (nd->nd_intr == NEXT_I_ENETX_DMA) {
-                       /* Ethernet transmit needs secret magic */
-
-                       bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_NEXT_INITBUF,
-                                       nd->_nd_map->dm_segs[nd->_nd_idx].ds_addr);
-                       bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_LIMIT,
-                                       ((nd->_nd_map->dm_segs[nd->_nd_idx].ds_addr +
-                                                       nd->_nd_map->dm_segs[nd->_nd_idx].ds_len)
-                                                       + 0x0) | 0x80000000);
-
+                       dd_limit |= 0x80000000; /* Ethernet transmit needs secret magic */
                }
-               else {
-                       bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_NEXT_INITBUF,
-                                       nd->_nd_map->dm_segs[nd->_nd_idx].ds_addr);
-                       bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_LIMIT,
-                                       nd->_nd_map->dm_segs[nd->_nd_idx].ds_addr +
-                                       nd->_nd_map->dm_segs[nd->_nd_idx].ds_len);
-               }
-
        } else {
-               bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_NEXT_INITBUF,0xdeadbeef);
-               bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_LIMIT, 0xdeadbeef);
+               dd_next = 0xdeadbeef;
+               dd_limit = 0xdeadbeef;
        }
 
-#if 1  /* See comment in next_dma_setup_cont_regs() above */
-               bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_NEXT, 
-                               bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_NEXT_INITBUF));
-               bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_LIMIT,
-                               bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_LIMIT));
-#else
-               bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_NEXT, 0xfeedbeef);
-               bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_LIMIT, 0xfeedbeef);
+       dd_saved_next = dd_next;
+       dd_saved_limit = dd_limit;
+
+       if (nd->nd_intr == NEXT_I_ENETX_DMA) {
+               bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_NEXT_INITBUF, dd_next);
+       } else {
+               bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_NEXT, dd_next);
+       }
+       bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_LIMIT, dd_limit);
+       bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_NEXT, dd_saved_next);
+       bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_LIMIT, dd_saved_limit);
+
+#ifdef DIAGNOSTIC
+       if ((bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_NEXT_INITBUF) != dd_next) ||
+                       (bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_NEXT) != dd_next) ||
+                       (bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_LIMIT) != dd_limit) ||
+                       (bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_NEXT) != dd_saved_next) ||
+                       (bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_LIMIT) != dd_saved_limit)) {
+               next_dma_print(nd);
+               panic("DMA failure writing to current regs");
+       }
 #endif
-
 }
 
 
@@ -359,9 +344,12 @@
        dd_saved_start  = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_START);
        dd_saved_stop   = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_STOP);
 
-       /* NDMAP is Next DMA Print (really!) */
+       printf("NDMAP: *intrstat = 0x%b\n",
+                       (*(volatile u_long *)IIOV(NEXT_P_INTRSTAT)),NEXT_INTR_BITS);
+       printf("NDMAP: *intrmask = 0x%b\n",
+                       (*(volatile u_long *)IIOV(NEXT_P_INTRMASK)),NEXT_INTR_BITS);
 
-       printf("NDMAP: nd->_nd_dmadir = 0x%08x\n",nd->_nd_dmadir);
+       /* NDMAP is Next DMA Print (really!) */
 
        if (nd->_nd_map) {
                printf("NDMAP: nd->_nd_map->dm_mapsize = %d\n",
@@ -408,6 +396,47 @@
 }
 
 /****************************************************************/
+void
+next_dma_finish_xfer(nd)
+       struct nextdma_config *nd;
+{
+       bus_addr_t onext;
+       bus_addr_t olimit;
+       bus_addr_t slimit;
+                       
+       onext = nd->_nd_map->dm_segs[nd->_nd_idx].ds_addr;
+       olimit = onext + nd->_nd_map->dm_segs[nd->_nd_idx].ds_len;
+
+       if ((nd->_nd_map_cont == NULL) && (nd->_nd_idx+1 == nd->_nd_map->dm_nsegs)) {
+               slimit = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_LIMIT);
+       } else {
+               slimit = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_LIMIT);
+       }
+
+       if (nd->nd_intr == NEXT_I_ENETX_DMA) {
+               slimit &= ~0x80000000;
+       }
+
+#ifdef DIAGNOSTIC
+       if ((slimit < onext) || (slimit > olimit)) {
+               next_dma_print(nd);
+               panic("DMA: Unexpected registers in finish_xfer\n");
+       }
+#endif
+
+       nd->_nd_map->dm_segs[nd->_nd_idx].ds_xfer_len = slimit-onext;
+



Home | Main Index | Thread Index | Old Index