xref: /netbsd/sys/arch/next68k/dev/nextdma.c (revision 6550d01e)
1 /*	$NetBSD: nextdma.c,v 1.47 2010/06/06 02:51:46 mrg 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  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 #include <sys/cdefs.h>
28 __KERNEL_RCSID(0, "$NetBSD: nextdma.c,v 1.47 2010/06/06 02:51:46 mrg Exp $");
29 
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/mbuf.h>
33 #include <sys/syslog.h>
34 #include <sys/socket.h>
35 #include <sys/device.h>
36 #include <sys/malloc.h>
37 #include <sys/ioctl.h>
38 #include <sys/errno.h>
39 
40 #define _M68K_BUS_DMA_PRIVATE
41 #include <machine/autoconf.h>
42 #include <machine/cpu.h>
43 #include <machine/intr.h>
44 
45 #include <m68k/cacheops.h>
46 
47 #include <next68k/next68k/isr.h>
48 #include <next68k/next68k/nextrom.h>
49 
50 #include <next68k/dev/intiovar.h>
51 
52 #include "nextdmareg.h"
53 #include "nextdmavar.h"
54 
55 #include "esp.h"
56 #include "xe.h"
57 
58 #if DEBUG
59 #define ND_DEBUG
60 #endif
61 
62 extern int turbo;
63 
64 #define panic		__asm volatile("trap  #15"); printf
65 
66 #define NEXTDMA_DEBUG nextdma_debug
67 /* (nsc->sc_chan->nd_intr == NEXT_I_SCSI_DMA) && nextdma_debug */
68 #if defined(ND_DEBUG)
69 int nextdma_debug = 0;
70 #define DPRINTF(x) if (NEXTDMA_DEBUG) printf x;
71 int ndtraceshow = 0;
72 char ndtrace[8192+100];
73 char *ndtracep = ndtrace;
74 #define NDTRACEIF(x) if (10 && /* (nsc->sc_chan->nd_intr == NEXT_I_SCSI_DMA) && */ ndtracep < (ndtrace + 8192)) do {x;} while (0)
75 #else
76 #define DPRINTF(x)
77 #define NDTRACEIF(x)
78 #endif
79 #define PRINTF(x) printf x
80 
81 #if defined(ND_DEBUG)
82 int nextdma_debug_enetr_idx = 0;
83 unsigned int nextdma_debug_enetr_state[100] = { 0 };
84 int nextdma_debug_scsi_idx = 0;
85 unsigned int nextdma_debug_scsi_state[100] = { 0 };
86 
87 void nextdma_debug_initstate(struct nextdma_softc *);
88 void nextdma_debug_savestate(struct nextdma_softc *, unsigned int);
89 void nextdma_debug_scsi_dumpstate(void);
90 void nextdma_debug_enetr_dumpstate(void);
91 #endif
92 
93 
94 int	nextdma_match(struct device *, struct cfdata *, void *);
95 void	nextdma_attach(struct device *, struct device *, void *);
96 
97 void nextdmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t, bus_size_t, int);
98 int nextdma_continue(struct nextdma_softc *);
99 void nextdma_rotate(struct nextdma_softc *);
100 
101 void nextdma_setup_cont_regs(struct nextdma_softc *);
102 void nextdma_setup_curr_regs(struct nextdma_softc *);
103 
104 #if NESP > 0
105 static int nextdma_esp_intr(void *);
106 #endif
107 #if NXE > 0
108 static int nextdma_enet_intr(void *);
109 #endif
110 
111 #define nd_bsr4(reg) \
112 	bus_space_read_4(nsc->sc_bst, nsc->sc_bsh, (reg))
113 #define nd_bsw4(reg,val) \
114 	bus_space_write_4(nsc->sc_bst, nsc->sc_bsh, (reg), (val))
115 
116 CFATTACH_DECL(nextdma, sizeof(struct nextdma_softc),
117     nextdma_match, nextdma_attach, NULL, NULL);
118 
119 static struct nextdma_channel nextdma_channel[] = {
120 #if NESP > 0
121 	{ "scsi", NEXT_P_SCSI_CSR, DD_SIZE, NEXT_I_SCSI_DMA, &nextdma_esp_intr },
122 #endif
123 #if NXE > 0
124 	{ "enetx", NEXT_P_ENETX_CSR, DD_SIZE, NEXT_I_ENETX_DMA, &nextdma_enet_intr },
125 	{ "enetr", NEXT_P_ENETR_CSR, DD_SIZE, NEXT_I_ENETR_DMA, &nextdma_enet_intr },
126 #endif
127 };
128 static int nnextdma_channels = (sizeof(nextdma_channel)/sizeof(nextdma_channel[0]));
129 
130 static int attached = 0;
131 
132 struct nextdma_softc *
133 nextdma_findchannel(const char *name)
134 {
135 	device_t dev;
136 	deviter_t di;
137 
138 	for (dev = deviter_first(&di, DEVITER_F_ROOT_FIRST);
139 	     dev != NULL;
140 	     dev = deviter_next(&di)) {
141 		if (strncmp(dev->dv_xname, "nextdma", 7) == 0) {
142 			struct nextdma_softc *nsc = device_private(dev);
143 			if (strcmp(nsc->sc_chan->nd_name, name) == 0)
144 				break;
145 		}
146 	}
147 	deviter_release(&di);
148 	if (dev == NULL)
149 		return NULL;
150 	return device_private(dev);
151 }
152 
153 int
154 nextdma_match(struct device *parent, struct cfdata *match, void *aux)
155 {
156 	struct intio_attach_args *ia = (struct intio_attach_args *)aux;
157 
158 	if (attached >= nnextdma_channels)
159 		return (0);
160 
161 	ia->ia_addr = (void *)nextdma_channel[attached].nd_base;
162 
163 	return (1);
164 }
165 
166 void
167 nextdma_attach(struct device *parent, struct device *self, void *aux)
168 {
169 	struct nextdma_softc *nsc = (struct nextdma_softc *)self;
170 	struct intio_attach_args *ia = (struct intio_attach_args *)aux;
171 
172 	if (attached >= nnextdma_channels)
173 		return;
174 
175 	nsc->sc_chan = &nextdma_channel[attached];
176 
177 	nsc->sc_dmat = ia->ia_dmat;
178 	nsc->sc_bst = ia->ia_bst;
179 
180 	if (bus_space_map(nsc->sc_bst, nsc->sc_chan->nd_base,
181 			  nsc->sc_chan->nd_size, 0, &nsc->sc_bsh)) {
182 		panic("%s: can't map DMA registers for channel %s",
183 		      nsc->sc_dev.dv_xname, nsc->sc_chan->nd_name);
184 	}
185 
186 	nextdma_init (nsc);
187 
188 	isrlink_autovec(nsc->sc_chan->nd_intrfunc, nsc,
189 			NEXT_I_IPL(nsc->sc_chan->nd_intr), 10, NULL);
190 	INTR_ENABLE(nsc->sc_chan->nd_intr);
191 
192 	printf (": channel %d (%s)\n", attached,
193 		nsc->sc_chan->nd_name);
194 	attached++;
195 
196 	return;
197 }
198 
199 void
200 nextdma_init(struct nextdma_softc *nsc)
201 {
202 #ifdef ND_DEBUG
203 	if (NEXTDMA_DEBUG) {
204 		char sbuf[256];
205 
206 		snprintb(sbuf, sizeof(sbuf), NEXT_INTR_BITS,
207 		    NEXT_I_BIT(nsc->sc_chan->nd_intr));
208 		printf("DMA init ipl (%ld) intr(0x%s)\n",
209 			NEXT_I_IPL(nsc->sc_chan->nd_intr), sbuf);
210 	}
211 #endif
212 
213 	nsc->sc_stat.nd_map = NULL;
214 	nsc->sc_stat.nd_idx = 0;
215 	nsc->sc_stat.nd_map_cont = NULL;
216 	nsc->sc_stat.nd_idx_cont = 0;
217 	nsc->sc_stat.nd_exception = 0;
218 
219 	nd_bsw4 (DD_CSR, DMACSR_RESET | DMACSR_CLRCOMPLETE);
220 	nd_bsw4 (DD_CSR, 0);
221 
222 #if 01
223 	nextdma_setup_curr_regs(nsc);
224 	nextdma_setup_cont_regs(nsc);
225 #endif
226 
227 #if defined(DIAGNOSTIC)
228 	{
229 		u_long state;
230 		state = nd_bsr4 (DD_CSR);
231 
232 #if 1
233 		/* mourning (a 25 MHz 68040 mono slab) appears to set BUSEXC
234 		 * milo (a 25 MHz 68040 mono cube) didn't have this problem
235 		 * Darrin B. Jewell <jewell@mit.edu>  Mon May 25 07:53:05 1998
236 		 */
237 		state &= (DMACSR_COMPLETE | DMACSR_SUPDATE | DMACSR_ENABLE);
238 #else
239 		state &= (DMACSR_BUSEXC | DMACSR_COMPLETE |
240 			  DMACSR_SUPDATE | DMACSR_ENABLE);
241 #endif
242 		if (state) {
243 			nextdma_print(nsc);
244 			panic("DMA did not reset");
245 		}
246 	}
247 #endif
248 }
249 
250 void
251 nextdma_reset(struct nextdma_softc *nsc)
252 {
253 	int s;
254 	struct nextdma_status *stat = &nsc->sc_stat;
255 
256 	s = spldma();
257 
258 	DPRINTF(("DMA reset\n"));
259 
260 #if (defined(ND_DEBUG))
261 	if (NEXTDMA_DEBUG > 1) nextdma_print(nsc);
262 #endif
263 
264 	nd_bsw4 (DD_CSR, DMACSR_CLRCOMPLETE | DMACSR_RESET);
265 	if ((stat->nd_map) || (stat->nd_map_cont)) {
266 		if (stat->nd_map_cont) {
267 			DPRINTF(("DMA: resetting with non null continue map\n"));
268 			if (nsc->sc_conf.nd_completed_cb)
269 				(*nsc->sc_conf.nd_completed_cb)
270 					(stat->nd_map_cont, nsc->sc_conf.nd_cb_arg);
271 
272 			stat->nd_map_cont = 0;
273 			stat->nd_idx_cont = 0;
274 		}
275 		if (nsc->sc_conf.nd_shutdown_cb)
276 			(*nsc->sc_conf.nd_shutdown_cb)(nsc->sc_conf.nd_cb_arg);
277 		stat->nd_map = 0;
278 		stat->nd_idx = 0;
279 	}
280 
281 	splx(s);
282 }
283 
284 /****************************************************************/
285 
286 
287 /* Call the completed and continue callbacks to try to fill
288  * in the dma continue buffers.
289  */
290 void
291 nextdma_rotate(struct nextdma_softc *nsc)
292 {
293 	struct nextdma_status *stat = &nsc->sc_stat;
294 
295 	NDTRACEIF (*ndtracep++ = 'r');
296 	DPRINTF(("DMA nextdma_rotate()\n"));
297 
298 	/* Rotate the continue map into the current map */
299 	stat->nd_map = stat->nd_map_cont;
300 	stat->nd_idx = stat->nd_idx_cont;
301 
302 	if ((!stat->nd_map_cont) ||
303 	    ((++stat->nd_idx_cont >= stat->nd_map_cont->dm_nsegs))) {
304 		if (nsc->sc_conf.nd_continue_cb) {
305 			stat->nd_map_cont = (*nsc->sc_conf.nd_continue_cb)
306 				(nsc->sc_conf.nd_cb_arg);
307 			if (stat->nd_map_cont) {
308 				stat->nd_map_cont->dm_xfer_len = 0;
309 			}
310 		} else {
311 			stat->nd_map_cont = 0;
312 		}
313 		stat->nd_idx_cont = 0;
314 	}
315 
316 #if defined(DIAGNOSTIC) && 0
317 	if (stat->nd_map_cont) {
318 		if (!DMA_BEGINALIGNED(stat->nd_map_cont->dm_segs[stat->nd_idx_cont].ds_addr)) {
319 			nextdma_print(nsc);
320 			panic("DMA request unaligned at start");
321 		}
322 		if (!DMA_ENDALIGNED(stat->nd_map_cont->dm_segs[stat->nd_idx_cont].ds_addr +
323 				stat->nd_map_cont->dm_segs[stat->nd_idx_cont].ds_len)) {
324 			nextdma_print(nsc);
325 			panic("DMA request unaligned at end");
326 		}
327 	}
328 #endif
329 
330 }
331 
332 void
333 nextdma_setup_curr_regs(struct nextdma_softc *nsc)
334 {
335 	bus_addr_t dd_next;
336 	bus_addr_t dd_limit;
337 	bus_addr_t dd_saved_next;
338 	bus_addr_t dd_saved_limit;
339 	struct nextdma_status *stat = &nsc->sc_stat;
340 
341 	NDTRACEIF (*ndtracep++ = 'C');
342 	DPRINTF(("DMA nextdma_setup_curr_regs()\n"));
343 
344 	if (stat->nd_map) {
345 		dd_next = stat->nd_map->dm_segs[stat->nd_idx].ds_addr;
346 		dd_limit = (stat->nd_map->dm_segs[stat->nd_idx].ds_addr +
347 			    stat->nd_map->dm_segs[stat->nd_idx].ds_len);
348 
349 		if (!turbo && nsc->sc_chan->nd_intr == NEXT_I_ENETX_DMA) {
350 			dd_limit |= 0x80000000; /* Ethernet transmit needs secret magic */
351 			dd_limit += 15;
352 		}
353 	} else {
354 		dd_next = turbo ? 0 : 0xdeadbeef;
355 		dd_limit = turbo ? 0 : 0xdeadbeef;
356 	}
357 
358 	dd_saved_next = dd_next;
359 	dd_saved_limit = dd_limit;
360 
361 	NDTRACEIF (if (stat->nd_map) {
362 		sprintf (ndtracep, "%ld", stat->nd_map->dm_segs[stat->nd_idx].ds_len);
363 		ndtracep += strlen (ndtracep);
364 	});
365 
366 	if (!turbo && (nsc->sc_chan->nd_intr == NEXT_I_ENETX_DMA)) {
367 		nd_bsw4 (DD_NEXT_INITBUF, dd_next);
368 	} else {
369 		nd_bsw4 (DD_NEXT, dd_next);
370 	}
371 	nd_bsw4 (DD_LIMIT, dd_limit);
372 	if (!turbo) nd_bsw4 (DD_SAVED_NEXT, dd_saved_next);
373 	if (!turbo) nd_bsw4 (DD_SAVED_LIMIT, dd_saved_limit);
374 
375 #ifdef DIAGNOSTIC
376 	if ((nd_bsr4 (DD_NEXT_INITBUF) != dd_next)
377 	    || (nd_bsr4 (DD_NEXT) != dd_next)
378 	    || (nd_bsr4 (DD_LIMIT) != dd_limit)
379 	    || (!turbo && (nd_bsr4 (DD_SAVED_NEXT) != dd_saved_next))
380 	    || (!turbo && (nd_bsr4 (DD_SAVED_LIMIT) != dd_saved_limit))
381 		) {
382 		nextdma_print(nsc);
383 		panic("DMA failure writing to current regs");
384 	}
385 #endif
386 }
387 
388 void
389 nextdma_setup_cont_regs(struct nextdma_softc *nsc)
390 {
391 	bus_addr_t dd_start;
392 	bus_addr_t dd_stop;
393 	bus_addr_t dd_saved_start;
394 	bus_addr_t dd_saved_stop;
395 	struct nextdma_status *stat = &nsc->sc_stat;
396 
397 	NDTRACEIF (*ndtracep++ = 'c');
398 	DPRINTF(("DMA nextdma_setup_regs()\n"));
399 
400 	if (stat->nd_map_cont) {
401 		dd_start = stat->nd_map_cont->dm_segs[stat->nd_idx_cont].ds_addr;
402 		dd_stop  = (stat->nd_map_cont->dm_segs[stat->nd_idx_cont].ds_addr +
403 			    stat->nd_map_cont->dm_segs[stat->nd_idx_cont].ds_len);
404 
405 		if (!turbo && nsc->sc_chan->nd_intr == NEXT_I_ENETX_DMA) {
406 			dd_stop |= 0x80000000; /* Ethernet transmit needs secret magic */
407 			dd_stop += 15;
408 		}
409 	} else {
410 		dd_start = turbo ? nd_bsr4 (DD_NEXT) : 0xdeadbee0;
411 		dd_stop = turbo ? 0 : 0xdeadbee0;
412 	}
413 
414 	dd_saved_start = dd_start;
415 	dd_saved_stop  = dd_stop;
416 
417 	NDTRACEIF (if (stat->nd_map_cont) {
418 		sprintf (ndtracep, "%ld", stat->nd_map_cont->dm_segs[stat->nd_idx_cont].ds_len);
419 		ndtracep += strlen (ndtracep);
420 	});
421 
422 	nd_bsw4 (DD_START, dd_start);
423 	nd_bsw4 (DD_STOP, dd_stop);
424 	if (!turbo) nd_bsw4 (DD_SAVED_START, dd_saved_start);
425 	if (!turbo) nd_bsw4 (DD_SAVED_STOP, dd_saved_stop);
426 	if (turbo && nsc->sc_chan->nd_intr == NEXT_I_ENETR_DMA)
427 		nd_bsw4 (DD_STOP - 0x40, dd_start);
428 
429 #ifdef DIAGNOSTIC
430 	if ((nd_bsr4 (DD_START) != dd_start)
431 	    || (dd_stop && (nd_bsr4 (DD_STOP) != dd_stop))
432 	    || (!turbo && (nd_bsr4 (DD_SAVED_START) != dd_saved_start))
433 	    || (!turbo && (nd_bsr4 (DD_SAVED_STOP) != dd_saved_stop))
434 		) {
435 		nextdma_print(nsc);
436 		panic("DMA failure writing to continue regs");
437 	}
438 #endif
439 }
440 
441 /****************************************************************/
442 
443 #if NESP > 0
444 static int
445 nextdma_esp_intr(void *arg)
446 {
447 	/* @@@ This is bogus, we can't be certain of arg's type
448 	 * unless the interrupt is for us.  For now we successfully
449 	 * cheat because DMA interrupts are the only things invoked
450 	 * at this interrupt level.
451 	 */
452 	struct nextdma_softc *nsc = arg;
453 	int esp_dma_int(void *); /* XXX */
454 
455 	if (!INTR_OCCURRED(nsc->sc_chan->nd_intr))
456 		return 0;
457 	/* Handle dma interrupts */
458 
459 	return esp_dma_int (nsc->sc_conf.nd_cb_arg);
460 
461 }
462 #endif
463 
464 #if NXE > 0
465 static int
466 nextdma_enet_intr(void *arg)
467 {
468 	/* @@@ This is bogus, we can't be certain of arg's type
469 	 * unless the interrupt is for us.  For now we successfully
470 	 * cheat because DMA interrupts are the only things invoked
471 	 * at this interrupt level.
472 	 */
473 	struct nextdma_softc *nsc = arg;
474 	unsigned int state;
475 	bus_addr_t onext;
476 	bus_addr_t olimit;
477 	bus_addr_t slimit;
478 	int result;
479 	struct nextdma_status *stat = &nsc->sc_stat;
480 
481 	if (!INTR_OCCURRED(nsc->sc_chan->nd_intr))
482 		return 0;
483 	/* Handle dma interrupts */
484 
485 	NDTRACEIF (*ndtracep++ = 'D');
486 #ifdef ND_DEBUG
487 	if (NEXTDMA_DEBUG) {
488 		char sbuf[256];
489 
490 		snprintb(sbuf, sizeof(sbuf), NEXT_INTR_BITS,
491 		    NEXT_I_BIT(nsc->sc_chan->nd_intr));
492 		printf("DMA interrupt ipl (%ld) intr(0x%s)\n",
493 		       NEXT_I_IPL(nsc->sc_chan->nd_intr), sbuf);
494 	}
495 #endif
496 
497 #ifdef DIAGNOSTIC
498 	if (!stat->nd_map) {
499 		nextdma_print(nsc);
500 		panic("DMA missing current map in interrupt!");
501 	}
502 #endif
503 
504 	state = nd_bsr4 (DD_CSR);
505 
506 #if defined(ND_DEBUG)
507 	nextdma_debug_savestate(nsc, state);
508 #endif
509 
510 #ifdef DIAGNOSTIC
511 	if (/* (state & DMACSR_READ) || */ !(state & DMACSR_COMPLETE)) {
512 		char sbuf[256];
513 		nextdma_print(nsc);
514 		snprintb(sbuf, sizeof(sbuf), DMACSR_BITS, state);
515 		printf("DMA: state 0x%s\n",sbuf);
516 		panic("DMA complete not set in interrupt");
517 	}
518 #endif
519 
520 	DPRINTF(("DMA: finishing xfer\n"));
521 
522 	onext = stat->nd_map->dm_segs[stat->nd_idx].ds_addr;
523 	olimit = onext + stat->nd_map->dm_segs[stat->nd_idx].ds_len;
524 
525 	result = 0;
526 	if (state & DMACSR_ENABLE) {
527 		/* enable bit was set */
528 		result |= 0x01;
529 	}
530 	if (state & DMACSR_SUPDATE) {
531 		/* supdate bit was set */
532 		result |= 0x02;
533 	}
534 	if (stat->nd_map_cont == NULL) {
535 		KASSERT(stat->nd_idx+1 == stat->nd_map->dm_nsegs);
536 		/* Expecting a shutdown, didn't SETSUPDATE last turn */
537 		result |= 0x04;
538 	}
539 	if (state & DMACSR_BUSEXC) {
540 		/* bus exception bit was set */
541 		result |= 0x08;
542 	}
543 	switch (result) {
544 	case 0x00: /* !BUSEXC && !expecting && !SUPDATE && !ENABLE */
545 	case 0x08: /* BUSEXC && !expecting && !SUPDATE && !ENABLE */
546 		if (turbo) {
547 			volatile u_int *limit = (volatile u_int *)IIOV(0x2000050+0x4000);
548 			slimit = *limit;
549 		} else {
550 			slimit = nd_bsr4 (DD_SAVED_LIMIT);
551 		}
552 		break;
553 	case 0x01: /* !BUSEXC && !expecting && !SUPDATE && ENABLE */
554 	case 0x09: /* BUSEXC && !expecting && !SUPDATE && ENABLE */
555 		if (turbo) {
556 			volatile u_int *limit = (volatile u_int *)IIOV(0x2000050+0x4000);
557 			slimit = *limit;
558 		} else {
559 			slimit = nd_bsr4 (DD_SAVED_LIMIT);
560 		}
561 		break;
562 	case 0x02: /* !BUSEXC && !expecting && SUPDATE && !ENABLE */
563 	case 0x0a: /* BUSEXC && !expecting && SUPDATE && !ENABLE */
564 		slimit = nd_bsr4 (DD_NEXT);
565 		break;
566 	case 0x04:  /* !BUSEXC && expecting && !SUPDATE && !ENABLE */
567 	case 0x0c: /* BUSEXC && expecting && !SUPDATE && !ENABLE */
568 		slimit = nd_bsr4 (DD_LIMIT);
569 		break;
570 	default:
571 #ifdef DIAGNOSTIC
572 	{
573 		char sbuf[256];
574 		printf("DMA: please send this output to port-next68k-maintainer@NetBSD.org:\n");
575 		snprintb(sbuf, sizeof(sbuf), DMACSR_BITS, state);
576 		printf("DMA: state 0x%s\n",sbuf);
577 		nextdma_print(nsc);
578 		panic("DMA: condition 0x%02x not yet documented to occur",result);
579 	}
580 #endif
581 	slimit = olimit;
582 	break;
583 	}
584 
585 	if (!turbo && nsc->sc_chan->nd_intr == NEXT_I_ENETX_DMA) {
586 		slimit &= ~0x80000000;
587 		slimit -= 15;
588 	}
589 
590 #ifdef DIAGNOSTIC
591 	if ((state & DMACSR_READ))
592 		DPRINTF (("limits: 0x%08lx <= 0x%08lx <= 0x%08lx %s\n", onext, slimit, olimit,
593 			  (state & DMACSR_READ) ? "read" : "write"));
594 	if ((slimit < onext) || (slimit > olimit)) {
595 		char sbuf[256];
596 		snprintb(sbuf, sizeof(sbuf), DMACSR_BITS, state);
597 		printf("DMA: state 0x%s\n",sbuf);
598 		nextdma_print(nsc);
599 		panic("DMA: Unexpected limit register (0x%08lx) in finish_xfer",slimit);
600 	}
601 #endif
602 
603 #ifdef DIAGNOSTIC
604 	if ((state & DMACSR_ENABLE) && ((stat->nd_idx+1) != stat->nd_map->dm_nsegs)) {
605 		if (slimit != olimit) {
606 			char sbuf[256];
607 			snprintb(sbuf, sizeof(sbuf), DMACSR_BITS, state);
608 			printf("DMA: state 0x%s\n",sbuf);
609 			nextdma_print(nsc);
610 			panic("DMA: short limit register (0x%08lx) w/o finishing map.",slimit);
611 		}
612 	}
613 #endif
614 
615 #if (defined(ND_DEBUG))
616 	if (NEXTDMA_DEBUG > 2) nextdma_print(nsc);
617 #endif
618 
619 	stat->nd_map->dm_xfer_len += slimit-onext;
620 
621 	/* If we've reached the end of the current map, then inform
622 	 * that we've completed that map.
623 	 */
624 	if ((stat->nd_idx+1) == stat->nd_map->dm_nsegs) {
625 		if (nsc->sc_conf.nd_completed_cb)
626 			(*nsc->sc_conf.nd_completed_cb)
627 				(stat->nd_map, nsc->sc_conf.nd_cb_arg);
628 	} else {
629 		KASSERT(stat->nd_map == stat->nd_map_cont);
630 		KASSERT(stat->nd_idx+1 == stat->nd_idx_cont);
631 	}
632 	stat->nd_map = 0;
633 	stat->nd_idx = 0;
634 
635 #if (defined(ND_DEBUG))
636 	if (NEXTDMA_DEBUG) {
637 		char sbuf[256];
638 		snprintb(sbuf, sizeof(sbuf), DMACSR_BITS, state);
639 		printf("CLNDMAP: dd->dd_csr          = 0x%s\n",   sbuf);
640 	}
641 #endif
642 	if (state & DMACSR_ENABLE) {
643 		u_long dmadir;		/* DMACSR_SETREAD or DMACSR_SETWRITE */
644 
645 		nextdma_rotate(nsc);
646 		nextdma_setup_cont_regs(nsc);
647 
648 		if (state & DMACSR_READ) {
649 			dmadir = DMACSR_SETREAD;
650 		} else {
651 			dmadir = DMACSR_SETWRITE;
652 		}
653 
654 		if (stat->nd_map_cont == NULL) {
655 			KASSERT(stat->nd_idx+1 == stat->nd_map->dm_nsegs);
656 			nd_bsw4 (DD_CSR, DMACSR_CLRCOMPLETE | dmadir);
657 			NDTRACEIF (*ndtracep++ = 'g');
658 		} else {
659 			nd_bsw4 (DD_CSR, DMACSR_CLRCOMPLETE | dmadir | DMACSR_SETSUPDATE);
660 			NDTRACEIF (*ndtracep++ = 'G');
661 		}
662 	} else {
663 		DPRINTF(("DMA: a shutdown occurred\n"));
664 		nd_bsw4 (DD_CSR, DMACSR_CLRCOMPLETE | DMACSR_RESET);
665 
666 		/* Cleanup more incomplete transfers */
667 		/* cleanup continue map */
668 		if (stat->nd_map_cont) {
669 			DPRINTF(("DMA: shutting down with non null continue map\n"));
670 			if (nsc->sc_conf.nd_completed_cb)
671 				(*nsc->sc_conf.nd_completed_cb)
672 					(stat->nd_map_cont, nsc->sc_conf.nd_cb_arg);
673 
674 			stat->nd_map_cont = 0;
675 			stat->nd_idx_cont = 0;
676 		}
677 		if (nsc->sc_conf.nd_shutdown_cb)
678 			(*nsc->sc_conf.nd_shutdown_cb)(nsc->sc_conf.nd_cb_arg);
679 	}
680 
681 #ifdef ND_DEBUG
682 	if (NEXTDMA_DEBUG) {
683 		char sbuf[256];
684 
685 		snprintb(sbuf, sizeof(sbuf),
686 		    NEXT_INTR_BITS, NEXT_I_BIT(nsc->sc_chan->nd_intr));
687 		printf("DMA exiting interrupt ipl (%ld) intr(0x%s)\n",
688 		       NEXT_I_IPL(nsc->sc_chan->nd_intr), sbuf);
689 	}
690 #endif
691 
692 	return(1);
693 }
694 #endif
695 
696 /*
697  * Check to see if dma has finished for a channel */
698 int
699 nextdma_finished(struct nextdma_softc *nsc)
700 {
701 	int r;
702 	int s;
703 	struct nextdma_status *stat = &nsc->sc_stat;
704 
705 	s = spldma();
706 	r = (stat->nd_map == NULL) && (stat->nd_map_cont == NULL);
707 	splx(s);
708 
709 	return(r);
710 }
711 
712 void
713 nextdma_start(struct nextdma_softc *nsc, u_long dmadir)
714 {
715 	struct nextdma_status *stat = &nsc->sc_stat;
716 
717 	NDTRACEIF (*ndtracep++ = 'n');
718 #ifdef DIAGNOSTIC
719 	if (!nextdma_finished(nsc)) {
720 		char sbuf[256];
721 
722 		snprintb(sbuf, sizeof(sbuf),
723 		    NEXT_INTR_BITS, NEXT_I_BIT(nsc->sc_chan->nd_intr));
724 		panic("DMA trying to start before previous finished on intr(0x%s)", sbuf);
725 	}
726 #endif
727 
728 #ifdef ND_DEBUG
729 	if (NEXTDMA_DEBUG) {
730 		char sbuf[256];
731 
732 		snprintb(sbuf, sizeof(sbuf),
733 		    NEXT_INTR_BITS, NEXT_I_BIT(nsc->sc_chan->nd_intr));
734 		printf("DMA start (%ld) intr(0x%s)\n",
735 		       NEXT_I_IPL(nsc->sc_chan->nd_intr), sbuf);
736 	}
737 #endif
738 
739 #ifdef DIAGNOSTIC
740 	if (stat->nd_map) {
741 		nextdma_print(nsc);
742 		panic("DMA: nextdma_start() with non null map");
743 	}
744 	if (stat->nd_map_cont) {
745 		nextdma_print(nsc);
746 		panic("DMA: nextdma_start() with non null continue map");
747 	}
748 #endif
749 
750 #ifdef DIAGNOSTIC
751 	if ((dmadir != DMACSR_SETREAD) && (dmadir != DMACSR_SETWRITE)) {
752 		panic("DMA: nextdma_start(), dmadir arg must be DMACSR_SETREAD or DMACSR_SETWRITE");
753 	}
754 #endif
755 
756 #if defined(ND_DEBUG)
757 	nextdma_debug_initstate(nsc);
758 #endif
759 
760 	/* preload both the current and the continue maps */
761 	nextdma_rotate(nsc);
762 
763 #ifdef DIAGNOSTIC
764 	if (!stat->nd_map_cont) {
765 		panic("No map available in nextdma_start()");
766 	}
767 #endif
768 
769 	nextdma_rotate(nsc);
770 
771 #ifdef ND_DEBUG
772 	if (NEXTDMA_DEBUG) {
773 		char sbuf[256];
774 
775 		snprintb(sbuf, sizeof(sbuf),
776 		    NEXT_INTR_BITS, NEXT_I_BIT(nsc->sc_chan->nd_intr));
777 		printf("DMA initiating DMA %s of %d segments on intr(0x%s)\n",
778 		       (dmadir == DMACSR_SETREAD ? "read" : "write"), stat->nd_map->dm_nsegs, sbuf);
779 	}
780 #endif
781 
782 	nd_bsw4 (DD_CSR, (turbo ? DMACSR_INITBUFTURBO : DMACSR_INITBUF) |
783 		 DMACSR_RESET | dmadir);
784 	nd_bsw4 (DD_CSR, 0);
785 
786 	nextdma_setup_curr_regs(nsc);
787 	nextdma_setup_cont_regs(nsc);
788 
789 #if (defined(ND_DEBUG))
790 	if (NEXTDMA_DEBUG > 2) nextdma_print(nsc);
791 #endif
792 
793 	if (stat->nd_map_cont == NULL) {
794 		nd_bsw4 (DD_CSR, DMACSR_SETENABLE | dmadir);
795 	} else {
796 		nd_bsw4 (DD_CSR, DMACSR_SETSUPDATE | DMACSR_SETENABLE | dmadir);
797 	}
798 }
799 
800 /* This routine is used for debugging */
801 void
802 nextdma_print(struct nextdma_softc *nsc)
803 {
804 	u_long dd_csr;
805 	u_long dd_next;
806 	u_long dd_next_initbuf;
807 	u_long dd_limit;
808 	u_long dd_start;
809 	u_long dd_stop;
810 	u_long dd_saved_next;
811 	u_long dd_saved_limit;
812 	u_long dd_saved_start;
813 	u_long dd_saved_stop;
814 	char sbuf[256];
815 	struct nextdma_status *stat = &nsc->sc_stat;
816 
817 	/* Read all of the registers before we print anything out,
818 	 * in case something changes
819 	 */
820 	dd_csr          = nd_bsr4 (DD_CSR);
821 	dd_next         = nd_bsr4 (DD_NEXT);
822 	dd_next_initbuf = nd_bsr4 (DD_NEXT_INITBUF);
823 	dd_limit        = nd_bsr4 (DD_LIMIT);
824 	dd_start        = nd_bsr4 (DD_START);
825 	dd_stop         = nd_bsr4 (DD_STOP);
826 	dd_saved_next   = nd_bsr4 (DD_SAVED_NEXT);
827 	dd_saved_limit  = nd_bsr4 (DD_SAVED_LIMIT);
828 	dd_saved_start  = nd_bsr4 (DD_SAVED_START);
829 	dd_saved_stop   = nd_bsr4 (DD_SAVED_STOP);
830 
831 	snprintb(sbuf, sizeof(sbuf), NEXT_INTR_BITS,
832 	    *(volatile u_long *)IIOV(NEXT_P_INTRSTAT));
833 	printf("NDMAP: *intrstat = 0x%s\n", sbuf);
834 
835 	snprintb(sbuf, sizeof(sbuf), NEXT_INTR_BITS,
836 	    *(volatile u_long *)IIOV(NEXT_P_INTRMASK));
837 	printf("NDMAP: *intrmask = 0x%s\n", sbuf);
838 
839 	/* NDMAP is Next DMA Print (really!) */
840 
841 	if (stat->nd_map) {
842 		int i;
843 
844 		printf("NDMAP: nd_map->dm_mapsize = %ld\n",
845 		       stat->nd_map->dm_mapsize);
846 		printf("NDMAP: nd_map->dm_nsegs = %d\n",
847 		       stat->nd_map->dm_nsegs);
848 		printf("NDMAP: nd_map->dm_xfer_len = %ld\n",
849 		       stat->nd_map->dm_xfer_len);
850 		printf("NDMAP: nd_map->dm_segs[%d].ds_addr = 0x%08lx\n",
851 		       stat->nd_idx, stat->nd_map->dm_segs[stat->nd_idx].ds_addr);
852 		printf("NDMAP: nd_map->dm_segs[%d].ds_len = %ld\n",
853 		       stat->nd_idx, stat->nd_map->dm_segs[stat->nd_idx].ds_len);
854 
855 		printf("NDMAP: Entire map;\n");
856 		for(i=0;i<stat->nd_map->dm_nsegs;i++) {
857 			printf("NDMAP:   nd_map->dm_segs[%d].ds_addr = 0x%08lx\n",
858 			       i,stat->nd_map->dm_segs[i].ds_addr);
859 			printf("NDMAP:   nd_map->dm_segs[%d].ds_len = %ld\n",
860 			       i,stat->nd_map->dm_segs[i].ds_len);
861 		}
862 	} else {
863 		printf("NDMAP: nd_map = NULL\n");
864 	}
865 	if (stat->nd_map_cont) {
866 		printf("NDMAP: nd_map_cont->dm_mapsize = %ld\n",
867 		       stat->nd_map_cont->dm_mapsize);
868 		printf("NDMAP: nd_map_cont->dm_nsegs = %d\n",
869 		       stat->nd_map_cont->dm_nsegs);
870 		printf("NDMAP: nd_map_cont->dm_xfer_len = %ld\n",
871 		       stat->nd_map_cont->dm_xfer_len);
872 		printf("NDMAP: nd_map_cont->dm_segs[%d].ds_addr = 0x%08lx\n",
873 		       stat->nd_idx_cont,stat->nd_map_cont->dm_segs[stat->nd_idx_cont].ds_addr);
874 		printf("NDMAP: nd_map_cont->dm_segs[%d].ds_len = %ld\n",
875 		       stat->nd_idx_cont,stat->nd_map_cont->dm_segs[stat->nd_idx_cont].ds_len);
876 		if (stat->nd_map_cont != stat->nd_map) {
877 			int i;
878 			printf("NDMAP: Entire map;\n");
879 			for(i=0;i<stat->nd_map_cont->dm_nsegs;i++) {
880 				printf("NDMAP:   nd_map_cont->dm_segs[%d].ds_addr = 0x%08lx\n",
881 				       i,stat->nd_map_cont->dm_segs[i].ds_addr);
882 				printf("NDMAP:   nd_map_cont->dm_segs[%d].ds_len = %ld\n",
883 				       i,stat->nd_map_cont->dm_segs[i].ds_len);
884 			}
885 		}
886 	} else {
887 		printf("NDMAP: nd_map_cont = NULL\n");
888 	}
889 
890 	snprintb(sbuf, sizeof(sbuf), DMACSR_BITS, dd_csr);
891 	printf("NDMAP: dd->dd_csr          = 0x%s\n",   sbuf);
892 
893 	printf("NDMAP: dd->dd_saved_next   = 0x%08lx\n", dd_saved_next);
894 	printf("NDMAP: dd->dd_saved_limit  = 0x%08lx\n", dd_saved_limit);
895 	printf("NDMAP: dd->dd_saved_start  = 0x%08lx\n", dd_saved_start);
896 	printf("NDMAP: dd->dd_saved_stop   = 0x%08lx\n", dd_saved_stop);
897 	printf("NDMAP: dd->dd_next         = 0x%08lx\n", dd_next);
898 	printf("NDMAP: dd->dd_next_initbuf = 0x%08lx\n", dd_next_initbuf);
899 	printf("NDMAP: dd->dd_limit        = 0x%08lx\n", dd_limit);
900 	printf("NDMAP: dd->dd_start        = 0x%08lx\n", dd_start);
901 	printf("NDMAP: dd->dd_stop         = 0x%08lx\n", dd_stop);
902 
903 	snprintb(sbuf, sizeof(sbuf), NEXT_INTR_BITS,
904 	    NEXT_I_BIT(nsc->sc_chan->nd_intr));
905 	printf("NDMAP: interrupt ipl (%ld) intr(0x%s)\n",
906 			NEXT_I_IPL(nsc->sc_chan->nd_intr), sbuf);
907 }
908 
909 #if defined(ND_DEBUG)
910 void
911 nextdma_debug_initstate(struct nextdma_softc *nsc)
912 {
913 	switch(nsc->sc_chan->nd_intr) {
914 	case NEXT_I_ENETR_DMA:
915 		memset(nextdma_debug_enetr_state,0,sizeof(nextdma_debug_enetr_state));
916 		break;
917 	case NEXT_I_SCSI_DMA:
918 		memset(nextdma_debug_scsi_state,0,sizeof(nextdma_debug_scsi_state));
919 		break;
920 	}
921 }
922 
923 void
924 nextdma_debug_savestate(struct nextdma_softc *nsc, unsigned int state)
925 {
926 	switch(nsc->sc_chan->nd_intr) {
927 	case NEXT_I_ENETR_DMA:
928 		nextdma_debug_enetr_state[nextdma_debug_enetr_idx++] = state;
929 		nextdma_debug_enetr_idx %= (sizeof(nextdma_debug_enetr_state)/sizeof(unsigned int));
930 		break;
931 	case NEXT_I_SCSI_DMA:
932 		nextdma_debug_scsi_state[nextdma_debug_scsi_idx++] = state;
933 		nextdma_debug_scsi_idx %= (sizeof(nextdma_debug_scsi_state)/sizeof(unsigned int));
934 		break;
935 	}
936 }
937 
938 void
939 nextdma_debug_enetr_dumpstate(void)
940 {
941 	int i;
942 	int s;
943 	s = spldma();
944 	i = nextdma_debug_enetr_idx;
945 	do {
946 		char sbuf[256];
947 		if (nextdma_debug_enetr_state[i]) {
948 			snprintb(sbuf, sizeof(sbuf), DMACSR_BITS, nextdma_debug_enetr_state[i]);
949 			printf("DMA: 0x%02x state 0x%s\n",i,sbuf);
950 		}
951 		i++;
952 		i %= (sizeof(nextdma_debug_enetr_state)/sizeof(unsigned int));
953 	} while (i != nextdma_debug_enetr_idx);
954 	splx(s);
955 }
956 
957 void
958 nextdma_debug_scsi_dumpstate(void)
959 {
960 	int i;
961 	int s;
962 	s = spldma();
963 	i = nextdma_debug_scsi_idx;
964 	do {
965 		char sbuf[256];
966 		if (nextdma_debug_scsi_state[i]) {
967 			snprintb(sbuf, sizeof(sbuf), DMACSR_BITS, nextdma_debug_scsi_state[i]);
968 			printf("DMA: 0x%02x state 0x%s\n",i,sbuf);
969 		}
970 		i++;
971 		i %= (sizeof(nextdma_debug_scsi_state)/sizeof(unsigned int));
972 	} while (i != nextdma_debug_scsi_idx);
973 	splx(s);
974 }
975 #endif
976 
977