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