Home | History | Annotate | Line # | Download | only in dev
nextdma.c revision 1.19
      1 /*	$NetBSD: nextdma.c,v 1.19 1999/08/28 09:19:05 dbj Exp $	*/
      2 /*
      3  * Copyright (c) 1998 Darrin B. Jewell
      4  * All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  * 3. All advertising materials mentioning features or use of this software
     15  *    must display the following acknowledgement:
     16  *      This product includes software developed by Darrin B. Jewell
     17  * 4. The name of the author may not be used to endorse or promote products
     18  *    derived from this software without specific prior written permission
     19  *
     20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #include <sys/param.h>
     33 #include <sys/systm.h>
     34 #include <sys/mbuf.h>
     35 #include <sys/syslog.h>
     36 #include <sys/socket.h>
     37 #include <sys/device.h>
     38 #include <sys/malloc.h>
     39 #include <sys/ioctl.h>
     40 #include <sys/errno.h>
     41 
     42 #include <machine/autoconf.h>
     43 #include <machine/cpu.h>
     44 #include <machine/intr.h>
     45 
     46 #include <m68k/cacheops.h>
     47 
     48 #include <next68k/next68k/isr.h>
     49 
     50 #define _NEXT68K_BUS_DMA_PRIVATE
     51 #include <machine/bus.h>
     52 
     53 #include "nextdmareg.h"
     54 #include "nextdmavar.h"
     55 
     56 #if 1
     57 #define ND_DEBUG
     58 #endif
     59 
     60 #if defined(ND_DEBUG)
     61 int nextdma_debug = 0;
     62 #define DPRINTF(x) if (nextdma_debug) printf x;
     63 #else
     64 #define DPRINTF(x)
     65 #endif
     66 
     67 void next_dmamap_sync __P((bus_dma_tag_t, bus_dmamap_t, bus_addr_t,
     68                        bus_size_t, int));
     69 int next_dma_continue __P((struct nextdma_config *));
     70 void next_dma_rotate __P((struct nextdma_config *));
     71 
     72 void next_dma_setup_cont_regs __P((struct nextdma_config *));
     73 void next_dma_setup_curr_regs __P((struct nextdma_config *));
     74 
     75 void
     76 nextdma_config(nd)
     77 	struct nextdma_config *nd;
     78 {
     79 	/* Initialize the dma_tag. As a hack, we currently
     80 	 * put the dma tag in the structure itself.  It shouldn't be there.
     81 	 */
     82 
     83 	{
     84 		bus_dma_tag_t t;
     85 		t = &nd->_nd_dmat;
     86 		t->_cookie = nd;
     87 		t->_dmamap_create = _bus_dmamap_create;
     88 		t->_dmamap_destroy = _bus_dmamap_destroy;
     89 		t->_dmamap_load = _bus_dmamap_load_direct;
     90 		t->_dmamap_load_mbuf = _bus_dmamap_load_mbuf_direct;
     91 		t->_dmamap_load_uio = _bus_dmamap_load_uio_direct;
     92 		t->_dmamap_load_raw = _bus_dmamap_load_raw_direct;
     93 		t->_dmamap_unload = _bus_dmamap_unload;
     94 		t->_dmamap_sync = _bus_dmamap_sync;
     95 
     96 		t->_dmamem_alloc = _bus_dmamem_alloc;
     97 		t->_dmamem_free = _bus_dmamem_free;
     98 		t->_dmamem_map = _bus_dmamem_map;
     99 		t->_dmamem_unmap = _bus_dmamem_unmap;
    100 		t->_dmamem_mmap = _bus_dmamem_mmap;
    101 
    102 		nd->nd_dmat = t;
    103 	}
    104 
    105 	nextdma_init(nd);
    106 
    107 	isrlink_autovec(nextdma_intr, nd, NEXT_I_IPL(nd->nd_intr), 10);
    108 	INTR_ENABLE(nd->nd_intr);
    109 }
    110 
    111 void
    112 nextdma_init(nd)
    113 	struct nextdma_config *nd;
    114 {
    115   DPRINTF(("DMA init ipl (%ld) intr(0x%b)\n",
    116 			NEXT_I_IPL(nd->nd_intr), NEXT_I_BIT(nd->nd_intr),NEXT_INTR_BITS));
    117 
    118 	/* @@@ should probably check and free these maps */
    119 	nd->_nd_map = NULL;
    120 	nd->_nd_idx = 0;
    121 	nd->_nd_map_cont = NULL;
    122 	nd->_nd_idx_cont = 0;
    123 
    124 	bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_CSR, 0);
    125 	bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_CSR,
    126 			DMACSR_INITBUF | DMACSR_CLRCOMPLETE | DMACSR_RESET);
    127 
    128 	next_dma_setup_curr_regs(nd);
    129 	next_dma_setup_cont_regs(nd);
    130 
    131 #if 0 && defined(DIAGNOSTIC)
    132 	/* Today, my computer (mourning) appears to fail this test.
    133 	 * yesterday, another NeXT (milo) didn't have this problem
    134 	 * Darrin B. Jewell <jewell (at) mit.edu>  Mon May 25 07:53:05 1998
    135 	 */
    136 	{
    137 		u_long state;
    138 		state = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_CSR);
    139 		state = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_CSR);
    140     state &= (DMACSR_BUSEXC | DMACSR_COMPLETE |
    141               DMACSR_SUPDATE | DMACSR_ENABLE);
    142 
    143 		if (state) {
    144 			next_dma_print(nd);
    145 			panic("DMA did not reset\n");
    146 		}
    147 	}
    148 #endif
    149 }
    150 
    151 
    152 void
    153 nextdma_reset(nd)
    154 	struct nextdma_config *nd;
    155 {
    156 	int s;
    157 	s = spldma();
    158 
    159 	DPRINTF(("DMA reset\n"));
    160 
    161 #if (defined(ND_DEBUG))
    162 	if (nextdma_debug) next_dma_print(nd);
    163 #endif
    164 
    165 	nextdma_init(nd);
    166 	splx(s);
    167 }
    168 
    169 /****************************************************************/
    170 
    171 
    172 /* Call the completed and continue callbacks to try to fill
    173  * in the dma continue buffers.
    174  */
    175 void
    176 next_dma_rotate(nd)
    177 	struct nextdma_config *nd;
    178 {
    179 
    180 	DPRINTF(("DMA next_dma_rotate()\n"));
    181 
    182 #ifdef DIAGNOSTIC
    183 	if (nd->_nd_map &&
    184 			nd->_nd_map->dm_segs[nd->_nd_idx].ds_xfer_len == 0x1234beef) {
    185 		next_dma_print(nd);
    186 		panic("DMA didn't set xfer length of segment");
    187 	}
    188 #endif
    189 
    190 	/* If we've reached the end of the current map, then inform
    191 	 * that we've completed that map.
    192 	 */
    193 	if (nd->_nd_map && ((nd->_nd_idx+1) == nd->_nd_map->dm_nsegs)) {
    194 		if (nd->nd_completed_cb)
    195 			(*nd->nd_completed_cb)(nd->_nd_map, nd->nd_cb_arg);
    196 	}
    197 
    198 	/* Rotate the continue map into the current map */
    199 	nd->_nd_map = nd->_nd_map_cont;
    200 	nd->_nd_idx = nd->_nd_idx_cont;
    201 
    202 	if ((!nd->_nd_map_cont) ||
    203 			((nd->_nd_map_cont) &&
    204 					(++nd->_nd_idx_cont >= nd->_nd_map_cont->dm_nsegs))) {
    205 		if (nd->nd_continue_cb) {
    206 			nd->_nd_map_cont = (*nd->nd_continue_cb)(nd->nd_cb_arg);
    207 		} else {
    208 			nd->_nd_map_cont = 0;
    209 		}
    210 		nd->_nd_idx_cont = 0;
    211 	}
    212 
    213 #ifdef DIAGNOSTIC
    214 	if (nd->_nd_map) {
    215 		nd->_nd_map->dm_segs[nd->_nd_idx].ds_xfer_len = 0x1234beef;
    216 	}
    217 #endif
    218 
    219 #ifdef DIAGNOSTIC
    220 	if (nd->_nd_map_cont) {
    221 		if (!DMA_BEGINALIGNED(nd->_nd_map_cont->dm_segs[nd->_nd_idx_cont].ds_addr)) {
    222 			next_dma_print(nd);
    223 			panic("DMA request unaligned at start\n");
    224 		}
    225 		if (!DMA_ENDALIGNED(nd->_nd_map_cont->dm_segs[nd->_nd_idx_cont].ds_addr +
    226 				nd->_nd_map_cont->dm_segs[nd->_nd_idx_cont].ds_len)) {
    227 			next_dma_print(nd);
    228 			panic("DMA request unaligned at end\n");
    229 		}
    230 	}
    231 #endif
    232 
    233 }
    234 
    235 void
    236 next_dma_setup_cont_regs(nd)
    237 	struct nextdma_config *nd;
    238 {
    239 	DPRINTF(("DMA next_dma_setup_regs()\n"));
    240 
    241 	if (nd->_nd_map_cont) {
    242 
    243 		if (nd->nd_intr == NEXT_I_ENETX_DMA) {
    244 			/* Ethernet transmit needs secret magic */
    245 
    246 			bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_START,
    247 					nd->_nd_map_cont->dm_segs[nd->_nd_idx_cont].ds_addr);
    248 			bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_STOP,
    249 					((nd->_nd_map_cont->dm_segs[nd->_nd_idx_cont].ds_addr +
    250 							nd->_nd_map_cont->dm_segs[nd->_nd_idx_cont].ds_len)
    251 							+ 0x0) | 0x80000000);
    252 
    253 		}
    254 		else {
    255 			bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_START,
    256 					nd->_nd_map_cont->dm_segs[nd->_nd_idx_cont].ds_addr);
    257 			bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_STOP,
    258 					nd->_nd_map_cont->dm_segs[nd->_nd_idx_cont].ds_addr +
    259 					nd->_nd_map_cont->dm_segs[nd->_nd_idx_cont].ds_len);
    260 		}
    261 
    262 	} else {
    263 
    264 		bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_START, 0xdeadbeef);
    265 		bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_STOP, 0xdeadbeef);
    266 	}
    267 
    268 #if 1 /* 0xfeedbeef in these registers leads to instability.  it will
    269 			 * panic after a short while with 0xfeedbeef in the DD_START and DD_STOP
    270 			 * registers.  I suspect that an unexpected hardware restart
    271 			 * is cycling the bogus values into the active registers.  Until
    272 			 * that is understood, we seed these with the same as DD_START and DD_STOP
    273 			 */
    274 	bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_START,
    275 			bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_START));
    276 	bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_STOP,
    277 			bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_STOP));
    278 #else
    279 	bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_START, 0xfeedbeef);
    280 	bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_STOP, 0xfeedbeef);
    281 #endif
    282 
    283 }
    284 
    285 void
    286 next_dma_setup_curr_regs(nd)
    287 	struct nextdma_config *nd;
    288 {
    289 	DPRINTF(("DMA next_dma_setup_curr_regs()\n"));
    290 
    291 
    292 	if (nd->_nd_map) {
    293 
    294 		if (nd->nd_intr == NEXT_I_ENETX_DMA) {
    295 			/* Ethernet transmit needs secret magic */
    296 
    297 			bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_NEXT_INITBUF,
    298 					nd->_nd_map->dm_segs[nd->_nd_idx].ds_addr);
    299 			bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_LIMIT,
    300 					((nd->_nd_map->dm_segs[nd->_nd_idx].ds_addr +
    301 							nd->_nd_map->dm_segs[nd->_nd_idx].ds_len)
    302 							+ 0x0) | 0x80000000);
    303 
    304 		}
    305 		else {
    306 			bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_NEXT_INITBUF,
    307 					nd->_nd_map->dm_segs[nd->_nd_idx].ds_addr);
    308 			bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_LIMIT,
    309 					nd->_nd_map->dm_segs[nd->_nd_idx].ds_addr +
    310 					nd->_nd_map->dm_segs[nd->_nd_idx].ds_len);
    311 		}
    312 
    313 	} else {
    314 		bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_NEXT_INITBUF,0xdeadbeef);
    315 		bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_LIMIT, 0xdeadbeef);
    316 	}
    317 
    318 #if 1  /* See comment in next_dma_setup_cont_regs() above */
    319 		bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_NEXT,
    320 				bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_NEXT_INITBUF));
    321 		bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_LIMIT,
    322 				bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_LIMIT));
    323 #else
    324 		bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_NEXT, 0xfeedbeef);
    325 		bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_LIMIT, 0xfeedbeef);
    326 #endif
    327 
    328 }
    329 
    330 
    331 /* This routine is used for debugging */
    332 
    333 void
    334 next_dma_print(nd)
    335 	struct nextdma_config *nd;
    336 {
    337 	u_long dd_csr;
    338 	u_long dd_next;
    339 	u_long dd_next_initbuf;
    340 	u_long dd_limit;
    341 	u_long dd_start;
    342 	u_long dd_stop;
    343 	u_long dd_saved_next;
    344 	u_long dd_saved_limit;
    345 	u_long dd_saved_start;
    346 	u_long dd_saved_stop;
    347 
    348   /* Read all of the registers before we print anything out,
    349 	 * in case something changes
    350 	 */
    351 	dd_csr          = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_CSR);
    352 	dd_next         = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_NEXT);
    353 	dd_next_initbuf = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_NEXT_INITBUF);
    354 	dd_limit        = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_LIMIT);
    355 	dd_start        = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_START);
    356 	dd_stop         = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_STOP);
    357 	dd_saved_next   = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_NEXT);
    358 	dd_saved_limit  = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_LIMIT);
    359 	dd_saved_start  = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_START);
    360 	dd_saved_stop   = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_STOP);
    361 
    362 	/* NDMAP is Next DMA Print (really!) */
    363 
    364 	printf("NDMAP: nd->_nd_dmadir = 0x%08x\n",nd->_nd_dmadir);
    365 
    366 	if (nd->_nd_map) {
    367 		printf("NDMAP: nd->_nd_map->dm_mapsize = %d\n",
    368 				nd->_nd_map->dm_mapsize);
    369 		printf("NDMAP: nd->_nd_map->dm_nsegs = %d\n",
    370 				nd->_nd_map->dm_nsegs);
    371 		printf("NDMAP: nd->_nd_map->dm_segs[%d].ds_addr = 0x%08lx\n",
    372 				nd->_nd_idx,nd->_nd_map->dm_segs[nd->_nd_idx].ds_addr);
    373 		printf("NDMAP: nd->_nd_map->dm_segs[%d].ds_len = %d\n",
    374 				nd->_nd_idx,nd->_nd_map->dm_segs[nd->_nd_idx].ds_len);
    375 		printf("NDMAP: nd->_nd_map->dm_segs[%d].ds_xfer_len = %d\n",
    376 				nd->_nd_idx,nd->_nd_map->dm_segs[nd->_nd_idx].ds_xfer_len);
    377 	} else {
    378 		printf("NDMAP: nd->_nd_map = NULL\n");
    379 	}
    380 	if (nd->_nd_map_cont) {
    381 		printf("NDMAP: nd->_nd_map_cont->dm_mapsize = %d\n",
    382 				nd->_nd_map_cont->dm_mapsize);
    383 		printf("NDMAP: nd->_nd_map_cont->dm_nsegs = %d\n",
    384 				nd->_nd_map_cont->dm_nsegs);
    385 		printf("NDMAP: nd->_nd_map_cont->dm_segs[%d].ds_addr = 0x%08lx\n",
    386 				nd->_nd_idx_cont,nd->_nd_map_cont->dm_segs[nd->_nd_idx_cont].ds_addr);
    387 		printf("NDMAP: nd->_nd_map_cont->dm_segs[%d].ds_len = %d\n",
    388 				nd->_nd_idx_cont,nd->_nd_map_cont->dm_segs[nd->_nd_idx_cont].ds_len);
    389 		printf("NDMAP: nd->_nd_map_cont->dm_segs[%d].ds_xfer_len = %d\n",
    390 				nd->_nd_idx_cont,nd->_nd_map_cont->dm_segs[nd->_nd_idx_cont].ds_xfer_len);
    391 	} else {
    392 		printf("NDMAP: nd->_nd_map_cont = NULL\n");
    393 	}
    394 
    395 	printf("NDMAP: dd->dd_csr          = 0x%b\n",   dd_csr,   DMACSR_BITS);
    396 	printf("NDMAP: dd->dd_saved_next   = 0x%08x\n", dd_saved_next);
    397 	printf("NDMAP: dd->dd_saved_limit  = 0x%08x\n", dd_saved_limit);
    398 	printf("NDMAP: dd->dd_saved_start  = 0x%08x\n", dd_saved_start);
    399 	printf("NDMAP: dd->dd_saved_stop   = 0x%08x\n", dd_saved_stop);
    400 	printf("NDMAP: dd->dd_next         = 0x%08x\n", dd_next);
    401 	printf("NDMAP: dd->dd_next_initbuf = 0x%08x\n", dd_next_initbuf);
    402 	printf("NDMAP: dd->dd_limit        = 0x%08x\n", dd_limit);
    403 	printf("NDMAP: dd->dd_start        = 0x%08x\n", dd_start);
    404 	printf("NDMAP: dd->dd_stop         = 0x%08x\n", dd_stop);
    405 
    406 	printf("NDMAP: interrupt ipl (%ld) intr(0x%b)\n",
    407 			NEXT_I_IPL(nd->nd_intr), NEXT_I_BIT(nd->nd_intr),NEXT_INTR_BITS);
    408 }
    409 
    410 /****************************************************************/
    411 
    412 int
    413 nextdma_intr(arg)
    414      void *arg;
    415 {
    416   /* @@@ This is bogus, we can't be certain of arg's type
    417 	 * unless the interrupt is for us.  For now we successfully
    418 	 * cheat because DMA interrupts are the only things invoked
    419 	 * at this interrupt level.
    420 	 */
    421   struct nextdma_config *nd = arg;
    422 
    423   if (!INTR_OCCURRED(nd->nd_intr)) return 0;
    424   /* Handle dma interrupts */
    425 
    426   DPRINTF(("DMA interrupt ipl (%ld) intr(0x%b)\n",
    427           NEXT_I_IPL(nd->nd_intr), NEXT_I_BIT(nd->nd_intr),NEXT_INTR_BITS));
    428 
    429 #ifdef DIAGNOSTIC
    430 	if (!nd->_nd_map) {
    431 		next_dma_print(nd);
    432 		panic("DMA missing current map in interrupt!\n");
    433 	}
    434 #endif
    435 
    436   {
    437     int state = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_CSR);
    438 
    439 #ifdef DIAGNOSTIC
    440 		if (!(state & DMACSR_COMPLETE)) {
    441 			next_dma_print(nd);
    442 			printf("DEBUG: state = 0x%b\n", state,DMACSR_BITS);
    443 			panic("DMA  ipl (%ld) intr(0x%b), DMACSR_COMPLETE not set in intr\n",
    444 					NEXT_I_IPL(nd->nd_intr), NEXT_I_BIT(nd->nd_intr),NEXT_INTR_BITS);
    445 		}
    446 #endif
    447 
    448 #if 0 /* This bit gets set sometimes & I don't know why. */
    449 #ifdef DIAGNOSTIC
    450 		if (state & DMACSR_BUSEXC) {
    451 			next_dma_print(nd);
    452 			printf("DEBUG: state = 0x%b\n", state,DMACSR_BITS);
    453 			panic("DMA  ipl (%ld) intr(0x%b), DMACSR_COMPLETE not set in intr\n",
    454 					NEXT_I_IPL(nd->nd_intr), NEXT_I_BIT(nd->nd_intr),NEXT_INTR_BITS);
    455 		}
    456 #endif
    457 #endif
    458 
    459 		/* Check to see if we are expecting dma to shut down */
    460 		if (!nd->_nd_map_cont) {
    461 
    462 #ifdef DIAGNOSTIC
    463 #if 1 /* Sometimes the DMA registers have totally bogus values when read.
    464 			 * Until that's understood, we skip this check
    465 			 */
    466 
    467 			/* Verify that the registers are laid out as expected */
    468 			{
    469 				bus_addr_t next;
    470 				bus_addr_t limit;
    471 				bus_addr_t expected_limit;
    472 				expected_limit =
    473 						nd->_nd_map->dm_segs[nd->_nd_idx].ds_addr +
    474 						nd->_nd_map->dm_segs[nd->_nd_idx].ds_len;
    475 
    476 				if (nd->nd_intr == NEXT_I_ENETX_DMA) {
    477 					next  = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_NEXT_INITBUF);
    478 					limit = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_LIMIT) & ~0x80000000;
    479 				}
    480 				else {
    481 					next  = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_NEXT);
    482 					limit = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_LIMIT);
    483 				}
    484 
    485 				if ((next != limit) || (limit != expected_limit)) {
    486 					next_dma_print(nd);
    487 					printf("DEBUG: state = 0x%b\n", state,DMACSR_BITS);
    488 					panic("unexpected DMA limit at shutdown 0x%08x, 0x%08x, 0x%08x",
    489 							next,limit,expected_limit);
    490 				}
    491 			}
    492 #endif
    493 #endif
    494 
    495 #if 1
    496 #ifdef DIAGNOSTIC
    497 			if (state & (DMACSR_SUPDATE|DMACSR_ENABLE)) {
    498 				next_dma_print(nd);
    499 				panic("DMA: unexpected bits set in DMA state at shutdown (0x%b)\n",
    500 						state,DMACSR_BITS);
    501 			}
    502 #endif
    503 #endif
    504 
    505 			if ((nd->_nd_idx+1) == nd->_nd_map->dm_nsegs) {
    506 				if (nd->nd_completed_cb)
    507 					(*nd->nd_completed_cb)(nd->_nd_map, nd->nd_cb_arg);
    508 			}
    509 			nd->_nd_map = 0;
    510 			nd->_nd_idx = 0;
    511 
    512 			bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_CSR,
    513 					DMACSR_CLRCOMPLETE | DMACSR_RESET);
    514 
    515 			DPRINTF(("DMA: a normal and expected shutdown occurred\n"));
    516 			if (nd->nd_shutdown_cb) (*nd->nd_shutdown_cb)(nd->nd_cb_arg);
    517 
    518 			return(1);
    519 		}
    520 
    521 #if 0
    522 #ifdef DIAGNOSTIC
    523 		if (!(state & DMACSR_SUPDATE)) {
    524 			next_dma_print(nd);
    525 			printf("DEBUG: state = 0x%b\n", state,DMACSR_BITS);
    526 			panic("SUPDATE not set with continuing DMA");
    527 		}
    528 #endif
    529 #endif
    530 
    531 		/* Check that the buffer we are interrupted for is the one we expect.
    532 		 * Shorten the buffer if the dma completed with a short buffer
    533 		 */
    534 		{
    535 			bus_addr_t next;
    536 			bus_addr_t limit;
    537 			bus_addr_t expected_next;
    538 			bus_addr_t expected_limit;
    539 
    540 			expected_next = nd->_nd_map->dm_segs[nd->_nd_idx].ds_addr;
    541 			expected_limit = expected_next + nd->_nd_map->dm_segs[nd->_nd_idx].ds_len;
    542 
    543 #if 0 /* for some unknown reason, somtimes DD_SAVED_NEXT has value from
    544 			 * nd->_nd_map and sometimes it has value from nd->_nd_map_cont.
    545 			 * Somtimes, it has a completely different unknown value.
    546 			 * Until that's understood, we won't sanity check the expected_next value.
    547 			 */
    548 			next  = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_NEXT);
    549 #else
    550 			next  = expected_next;
    551 #endif
    552 			limit = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_LIMIT);
    553 
    554 			if (nd->nd_intr == NEXT_I_ENETX_DMA) {
    555 				limit &= ~0x80000000;
    556 			}
    557 
    558 			if ((limit-next < 0) ||
    559 					(limit-next >= expected_limit-expected_next)) {
    560 #ifdef DIAGNOSTIC
    561 #if 0 /* Sometimes, (under load I think) even DD_SAVED_LIMIT has
    562 			 * a bogus value.  Until that's understood, we don't panic
    563 			 * here.
    564 			 */
    565 				next_dma_print(nd);
    566 				printf("DEBUG: state = 0x%b\n", state,DMACSR_BITS);
    567 				panic("Unexpected saved registers values.");
    568 #endif
    569 #endif
    570 
    571 				/* @@@ we pretend the entire buffer transferred ok.
    572 				 * we might consider throwing away this transfer instead
    573 				 */
    574 				nd->_nd_map->dm_segs[nd->_nd_idx].ds_xfer_len = expected_limit-expected_next;
    575 			} else {
    576 				nd->_nd_map->dm_segs[nd->_nd_idx].ds_xfer_len = limit-next;
    577 				expected_limit = expected_next + (limit-next);
    578 			}
    579 
    580 #if 0 /* these checks are turned off until the above mentioned weirdness is fixed. */
    581 #ifdef DIAGNOSTIC
    582 			if (next != expected_next) {
    583 				next_dma_print(nd);
    584 				printf("DEBUG: state = 0x%b\n", state,DMACSR_BITS);
    585 				panic("unexpected DMA next buffer in interrupt (found 0x%08x, expected 0x%08x)",
    586 						next,expected_next);
    587 			}
    588 			if (limit != expected_limit) {
    589 				next_dma_print(nd);
    590 				printf("DEBUG: state = 0x%b\n", state,DMACSR_BITS);
    591 				panic("unexpected DMA limit buffer in interrupt (found 0x%08x, expected 0x%08x)",
    592 						limit,expected_limit);
    593 			}
    594 #endif
    595 #endif
    596 		}
    597 
    598 		next_dma_rotate(nd);
    599 		next_dma_setup_cont_regs(nd);
    600 
    601 		if (!(state & DMACSR_ENABLE)) {
    602 
    603 			DPRINTF(("Unexpected DMA shutdown, restarting\n"));
    604 
    605 			if (nd->_nd_map_cont) {
    606 				bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_CSR,
    607 						DMACSR_SETSUPDATE | DMACSR_SETENABLE | nd->_nd_dmadir);
    608 			} else {
    609 				bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_CSR,
    610 						DMACSR_SETENABLE | nd->_nd_dmadir);
    611 			}
    612 
    613 		} else {
    614 
    615 			if (nd->_nd_map_cont) {
    616 				bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_CSR,
    617 						DMACSR_SETSUPDATE | DMACSR_CLRCOMPLETE | nd->_nd_dmadir);
    618 			} else {
    619 				bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_CSR,
    620 						DMACSR_CLRCOMPLETE | nd->_nd_dmadir);
    621 			}
    622 		}
    623 
    624 	}
    625 
    626   DPRINTF(("DMA exiting interrupt ipl (%ld) intr(0x%b)\n",
    627           NEXT_I_IPL(nd->nd_intr), NEXT_I_BIT(nd->nd_intr),NEXT_INTR_BITS));
    628 
    629   return(1);
    630 }
    631 
    632 /*
    633  * Check to see if dma has finished for a channel */
    634 int
    635 nextdma_finished(nd)
    636 	struct nextdma_config *nd;
    637 {
    638 	int r;
    639 	int s;
    640 	s = spldma();									/* @@@ should this be splimp()? */
    641 	r = (nd->_nd_map == NULL) && (nd->_nd_map_cont == NULL);
    642 	splx(s);
    643 	return(r);
    644 }
    645 
    646 void
    647 nextdma_start(nd, dmadir)
    648 	struct nextdma_config *nd;
    649 	u_long dmadir;								/* 	DMACSR_SETREAD or DMACSR_SETWRITE */
    650 {
    651 
    652 #ifdef DIAGNOSTIC
    653 	if (!nextdma_finished(nd)) {
    654 		panic("DMA trying to start before previous finished on intr(0x%b)\n",
    655 				NEXT_I_BIT(nd->nd_intr),NEXT_INTR_BITS);
    656 	}
    657 #endif
    658 
    659   DPRINTF(("DMA start (%ld) intr(0x%b)\n",
    660           NEXT_I_IPL(nd->nd_intr), NEXT_I_BIT(nd->nd_intr),NEXT_INTR_BITS));
    661 
    662 #ifdef DIAGNOSTIC
    663 	if (nd->_nd_map) {
    664 		next_dma_print(nd);
    665 		panic("DMA: nextdma_start() with non null map\n");
    666 	}
    667 	if (nd->_nd_map_cont) {
    668 		next_dma_print(nd);
    669 		panic("DMA: nextdma_start() with non null continue map\n");
    670 	}
    671 #endif
    672 
    673 #ifdef DIAGNOSTIC
    674 	if ((dmadir != DMACSR_SETREAD) && (dmadir != DMACSR_SETWRITE)) {
    675 		panic("DMA: nextdma_start(), dmadir arg must be DMACSR_SETREAD or DMACSR_SETWRITE\n");
    676 	}
    677 #endif
    678 
    679 	nd->_nd_dmadir = dmadir;
    680 
    681 	/* preload both the current and the continue maps */
    682 	next_dma_rotate(nd);
    683 
    684 #ifdef DIAGNOSTIC
    685 	if (!nd->_nd_map_cont) {
    686 		panic("No map available in nextdma_start()");
    687 	}
    688 #endif
    689 
    690 	next_dma_rotate(nd);
    691 
    692 	DPRINTF(("DMA initiating DMA %s of %d segments on intr(0x%b)\n",
    693 			(nd->_nd_dmadir == DMACSR_SETREAD ? "read" : "write"), nd->_nd_map->dm_nsegs,
    694 			NEXT_I_BIT(nd->nd_intr),NEXT_INTR_BITS));
    695 
    696 	bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_CSR, 0);
    697 	bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_CSR,
    698 			DMACSR_INITBUF | DMACSR_RESET | nd->_nd_dmadir);
    699 
    700 	next_dma_setup_curr_regs(nd);
    701 	next_dma_setup_cont_regs(nd);
    702 
    703 #if (defined(ND_DEBUG))
    704 	if (nextdma_debug) next_dma_print(nd);
    705 #endif
    706 
    707 	if (nd->_nd_map_cont) {
    708 		bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_CSR,
    709 				DMACSR_SETSUPDATE | DMACSR_SETENABLE | nd->_nd_dmadir);
    710 	} else {
    711 		bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_CSR,
    712 				DMACSR_SETENABLE | nd->_nd_dmadir);
    713 	}
    714 
    715 }
    716