nextdma.c revision 1.15 1 1.15 dbj /* $NetBSD: nextdma.c,v 1.15 1999/03/14 10:31:05 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.1 dbj #define _GENERIC_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 /* @@@ for debugging */
68 1.1 dbj struct nextdma_config *debugernd;
69 1.1 dbj struct nextdma_config *debugexnd;
70 1.1 dbj
71 1.1 dbj void next_dmamap_sync __P((bus_dma_tag_t, bus_dmamap_t, bus_addr_t,
72 1.1 dbj bus_size_t, int));
73 1.1 dbj int next_dma_continue __P((struct nextdma_config *));
74 1.1 dbj void next_dma_rotate __P((struct nextdma_config *));
75 1.1 dbj
76 1.1 dbj void next_dma_setup_cont_regs __P((struct nextdma_config *));
77 1.1 dbj void next_dma_setup_curr_regs __P((struct nextdma_config *));
78 1.1 dbj
79 1.1 dbj void
80 1.1 dbj nextdma_config(nd)
81 1.1 dbj struct nextdma_config *nd;
82 1.1 dbj {
83 1.1 dbj /* Initialize the dma_tag. As a hack, we currently
84 1.1 dbj * put the dma tag in the structure itself. It shouldn't be there.
85 1.1 dbj */
86 1.1 dbj
87 1.1 dbj {
88 1.1 dbj bus_dma_tag_t t;
89 1.1 dbj t = &nd->_nd_dmat;
90 1.1 dbj t->_cookie = nd;
91 1.1 dbj t->_get_tag = NULL; /* lose */
92 1.1 dbj t->_dmamap_create = _bus_dmamap_create;
93 1.1 dbj t->_dmamap_destroy = _bus_dmamap_destroy;
94 1.1 dbj t->_dmamap_load = _bus_dmamap_load_direct;
95 1.1 dbj t->_dmamap_load_mbuf = _bus_dmamap_load_mbuf_direct;
96 1.1 dbj t->_dmamap_load_uio = _bus_dmamap_load_uio_direct;
97 1.1 dbj t->_dmamap_load_raw = _bus_dmamap_load_raw_direct;
98 1.1 dbj t->_dmamap_unload = _bus_dmamap_unload;
99 1.1 dbj t->_dmamap_sync = next_dmamap_sync;
100 1.1 dbj
101 1.1 dbj t->_dmamem_alloc = _bus_dmamem_alloc;
102 1.1 dbj t->_dmamem_free = _bus_dmamem_free;
103 1.1 dbj t->_dmamem_map = _bus_dmamem_map;
104 1.1 dbj t->_dmamem_unmap = _bus_dmamem_unmap;
105 1.1 dbj t->_dmamem_mmap = _bus_dmamem_mmap;
106 1.1 dbj
107 1.1 dbj nd->nd_dmat = t;
108 1.1 dbj }
109 1.1 dbj
110 1.1 dbj /* @@@ for debugging */
111 1.1 dbj if (nd->nd_intr == NEXT_I_ENETR_DMA) {
112 1.1 dbj debugernd = nd;
113 1.1 dbj }
114 1.1 dbj if (nd->nd_intr == NEXT_I_ENETX_DMA) {
115 1.1 dbj debugexnd = nd;
116 1.1 dbj }
117 1.1 dbj
118 1.1 dbj nextdma_init(nd);
119 1.1 dbj
120 1.14 dbj isrlink_autovec(nextdma_intr, nd, NEXT_I_IPL(nd->nd_intr), 10);
121 1.14 dbj INTR_ENABLE(nd->nd_intr);
122 1.1 dbj }
123 1.1 dbj
124 1.1 dbj void
125 1.1 dbj nextdma_init(nd)
126 1.1 dbj struct nextdma_config *nd;
127 1.1 dbj {
128 1.1 dbj DPRINTF(("DMA init ipl (%ld) intr(0x%b)\n",
129 1.1 dbj NEXT_I_IPL(nd->nd_intr), NEXT_I_BIT(nd->nd_intr),NEXT_INTR_BITS));
130 1.1 dbj
131 1.1 dbj /* @@@ should probably check and free these maps */
132 1.1 dbj nd->_nd_map = NULL;
133 1.1 dbj nd->_nd_idx = 0;
134 1.1 dbj nd->_nd_map_cont = NULL;
135 1.1 dbj nd->_nd_idx_cont = 0;
136 1.1 dbj
137 1.1 dbj bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_CSR, 0);
138 1.1 dbj bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_CSR,
139 1.1 dbj DMACSR_INITBUF | DMACSR_CLRCOMPLETE | DMACSR_RESET);
140 1.1 dbj
141 1.1 dbj next_dma_setup_curr_regs(nd);
142 1.1 dbj next_dma_setup_cont_regs(nd);
143 1.1 dbj
144 1.1 dbj #if 0 && defined(DIAGNOSTIC)
145 1.1 dbj /* Today, my computer (mourning) appears to fail this test.
146 1.1 dbj * yesterday, another NeXT (milo) didn't have this problem
147 1.1 dbj * Darrin B. Jewell <jewell (at) mit.edu> Mon May 25 07:53:05 1998
148 1.1 dbj */
149 1.1 dbj {
150 1.1 dbj u_long state;
151 1.1 dbj state = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_CSR);
152 1.1 dbj state = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_CSR);
153 1.1 dbj state &= (DMACSR_BUSEXC | DMACSR_COMPLETE |
154 1.1 dbj DMACSR_SUPDATE | DMACSR_ENABLE);
155 1.1 dbj
156 1.1 dbj if (state) {
157 1.1 dbj next_dma_print(nd);
158 1.1 dbj panic("DMA did not reset\n");
159 1.1 dbj }
160 1.1 dbj }
161 1.1 dbj #endif
162 1.1 dbj }
163 1.1 dbj
164 1.4 dbj
165 1.1 dbj void
166 1.1 dbj nextdma_reset(nd)
167 1.1 dbj struct nextdma_config *nd;
168 1.1 dbj {
169 1.1 dbj int s;
170 1.1 dbj s = spldma(); /* @@@ should this be splimp()? */
171 1.8 dbj
172 1.8 dbj DPRINTF(("DMA reset\n"));
173 1.8 dbj
174 1.8 dbj #if (defined(ND_DEBUG))
175 1.8 dbj if (nextdma_debug) next_dma_print(nd);
176 1.8 dbj #endif
177 1.8 dbj
178 1.1 dbj nextdma_init(nd);
179 1.1 dbj splx(s);
180 1.1 dbj }
181 1.1 dbj
182 1.1 dbj /****************************************************************/
183 1.1 dbj
184 1.1 dbj /* If the next had multiple busses, this should probably
185 1.1 dbj * go elsewhere, but it is here anyway */
186 1.1 dbj void
187 1.1 dbj next_dmamap_sync(t, map, offset, len, ops)
188 1.1 dbj bus_dma_tag_t t;
189 1.1 dbj bus_dmamap_t map;
190 1.1 dbj bus_addr_t offset;
191 1.1 dbj bus_size_t len;
192 1.1 dbj int ops;
193 1.1 dbj {
194 1.1 dbj /* flush/purge the cache.
195 1.1 dbj * assumes pointers are aligned
196 1.3 dbj * @@@ should probably be fixed to use offset and len args.
197 1.3 dbj * should also optimize this to work on pages for larger regions?
198 1.1 dbj */
199 1.15 dbj
200 1.11 dbj if ((ops & BUS_DMASYNC_PREWRITE) ||
201 1.11 dbj (ops & BUS_DMASYNC_PREREAD)) {
202 1.1 dbj int i;
203 1.1 dbj for(i=0;i<map->dm_nsegs;i++) {
204 1.1 dbj bus_addr_t p = map->dm_segs[i].ds_addr;
205 1.1 dbj bus_addr_t e = p+map->dm_segs[i].ds_len;
206 1.15 dbj #ifdef DIAGNOSTIC
207 1.15 dbj if ((p % 16) || (e % 16)) {
208 1.15 dbj panic("unaligned address in next_dmamap_sync while flushing.\n"
209 1.15 dbj "address=0x%08x, length=0x%08x, ops=0x%x",
210 1.15 dbj p,e,ops);
211 1.15 dbj }
212 1.15 dbj #endif
213 1.1 dbj while(p<e) {
214 1.1 dbj DCFL(p); /* flush */
215 1.1 dbj p += 16; /* cache line length */
216 1.1 dbj }
217 1.1 dbj }
218 1.1 dbj }
219 1.1 dbj
220 1.11 dbj if ((ops & BUS_DMASYNC_POSTREAD) ||
221 1.11 dbj (ops & BUS_DMASYNC_POSTWRITE)) {
222 1.1 dbj int i;
223 1.1 dbj for(i=0;i<map->dm_nsegs;i++) {
224 1.1 dbj bus_addr_t p = map->dm_segs[i].ds_addr;
225 1.1 dbj bus_addr_t e = p+map->dm_segs[i].ds_len;
226 1.15 dbj #ifdef DIAGNOSTIC
227 1.15 dbj /* We don't check the end address for alignment since if the
228 1.15 dbj * dma operation stops short, the end address may be modified.
229 1.15 dbj */
230 1.15 dbj if (p % 16) {
231 1.15 dbj panic("unaligned address in next_dmamap_sync while purging.\n"
232 1.15 dbj "address=0x%08x, length=0x%08x, ops=0x%x",
233 1.15 dbj p,e,ops);
234 1.15 dbj }
235 1.15 dbj #endif
236 1.1 dbj while(p<e) {
237 1.1 dbj DCPL(p); /* purge */
238 1.1 dbj p += 16; /* cache line length */
239 1.1 dbj }
240 1.1 dbj }
241 1.1 dbj }
242 1.1 dbj }
243 1.1 dbj
244 1.1 dbj /****************************************************************/
245 1.1 dbj
246 1.1 dbj
247 1.1 dbj /* Call the completed and continue callbacks to try to fill
248 1.1 dbj * in the dma continue buffers.
249 1.1 dbj */
250 1.1 dbj void
251 1.1 dbj next_dma_rotate(nd)
252 1.1 dbj struct nextdma_config *nd;
253 1.1 dbj {
254 1.1 dbj
255 1.1 dbj DPRINTF(("DMA next_dma_rotate()\n"));
256 1.1 dbj
257 1.1 dbj /* If we've reached the end of the current map, then inform
258 1.1 dbj * that we've completed that map.
259 1.1 dbj */
260 1.1 dbj if (nd->_nd_map && ((nd->_nd_idx+1) == nd->_nd_map->dm_nsegs)) {
261 1.1 dbj if (nd->nd_completed_cb)
262 1.1 dbj (*nd->nd_completed_cb)(nd->_nd_map, nd->nd_cb_arg);
263 1.1 dbj }
264 1.1 dbj
265 1.1 dbj /* Rotate the continue map into the current map */
266 1.1 dbj nd->_nd_map = nd->_nd_map_cont;
267 1.1 dbj nd->_nd_idx = nd->_nd_idx_cont;
268 1.1 dbj
269 1.1 dbj if ((!nd->_nd_map_cont) ||
270 1.1 dbj ((nd->_nd_map_cont) &&
271 1.1 dbj (++nd->_nd_idx_cont >= nd->_nd_map_cont->dm_nsegs))) {
272 1.1 dbj if (nd->nd_continue_cb) {
273 1.1 dbj nd->_nd_map_cont = (*nd->nd_continue_cb)(nd->nd_cb_arg);
274 1.1 dbj } else {
275 1.1 dbj nd->_nd_map_cont = 0;
276 1.1 dbj }
277 1.1 dbj nd->_nd_idx_cont = 0;
278 1.1 dbj }
279 1.7 dbj
280 1.7 dbj #ifdef DIAGNOSTIC
281 1.7 dbj if (nd->_nd_map_cont) {
282 1.12 dbj if (!DMA_BEGINALIGNED(nd->_nd_map_cont->dm_segs[nd->_nd_idx_cont].ds_addr)) {
283 1.12 dbj next_dma_print(nd);
284 1.7 dbj panic("DMA request unaligned at start\n");
285 1.7 dbj }
286 1.12 dbj if (!DMA_ENDALIGNED(nd->_nd_map_cont->dm_segs[nd->_nd_idx_cont].ds_addr +
287 1.12 dbj nd->_nd_map_cont->dm_segs[nd->_nd_idx_cont].ds_len)) {
288 1.12 dbj next_dma_print(nd);
289 1.7 dbj panic("DMA request unaligned at end\n");
290 1.7 dbj }
291 1.7 dbj }
292 1.7 dbj #endif
293 1.7 dbj
294 1.1 dbj }
295 1.1 dbj
296 1.1 dbj void
297 1.1 dbj next_dma_setup_cont_regs(nd)
298 1.1 dbj struct nextdma_config *nd;
299 1.1 dbj {
300 1.1 dbj DPRINTF(("DMA next_dma_setup_regs()\n"));
301 1.1 dbj
302 1.1 dbj if (nd->_nd_map_cont) {
303 1.1 dbj
304 1.1 dbj if (nd->nd_intr == NEXT_I_ENETX_DMA) {
305 1.1 dbj /* Ethernet transmit needs secret magic */
306 1.1 dbj
307 1.1 dbj bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_START,
308 1.1 dbj nd->_nd_map_cont->dm_segs[nd->_nd_idx_cont].ds_addr);
309 1.1 dbj bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_STOP,
310 1.1 dbj ((nd->_nd_map_cont->dm_segs[nd->_nd_idx_cont].ds_addr +
311 1.1 dbj nd->_nd_map_cont->dm_segs[nd->_nd_idx_cont].ds_len)
312 1.1 dbj + 0x0) | 0x80000000);
313 1.15 dbj
314 1.15 dbj }
315 1.15 dbj #ifdef NEXTDMA_SCSI_HACK
316 1.15 dbj else if ((nd->nd_intr == NEXT_I_SCSI_DMA) && (nd->_nd_dmadir == DMACSR_WRITE)) {
317 1.15 dbj
318 1.15 dbj bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_START,
319 1.15 dbj nd->_nd_map_cont->dm_segs[nd->_nd_idx_cont].ds_addr);
320 1.15 dbj
321 1.15 dbj bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_STOP,
322 1.15 dbj ((nd->_nd_map_cont->dm_segs[nd->_nd_idx_cont].ds_addr +
323 1.15 dbj nd->_nd_map_cont->dm_segs[nd->_nd_idx_cont].ds_len)
324 1.15 dbj + 0x20));
325 1.15 dbj }
326 1.15 dbj #endif
327 1.15 dbj else {
328 1.1 dbj bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_START,
329 1.1 dbj nd->_nd_map_cont->dm_segs[nd->_nd_idx_cont].ds_addr);
330 1.1 dbj bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_STOP,
331 1.1 dbj nd->_nd_map_cont->dm_segs[nd->_nd_idx_cont].ds_addr +
332 1.1 dbj nd->_nd_map_cont->dm_segs[nd->_nd_idx_cont].ds_len);
333 1.1 dbj }
334 1.1 dbj
335 1.1 dbj } else {
336 1.1 dbj
337 1.6 dbj bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_START, 0xdeadbeef);
338 1.6 dbj bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_STOP, 0xdeadbeef);
339 1.1 dbj }
340 1.1 dbj
341 1.10 dbj #if 1 /* 0xfeedbeef in these registers leads to instability. it will
342 1.10 dbj * panic after a short while with 0xfeedbeef in the DD_START and DD_STOP
343 1.10 dbj * registers. I suspect that an unexpected hardware restart
344 1.10 dbj * is cycling the bogus values into the active registers. Until
345 1.10 dbj * that is understood, we seed these with the same as DD_START and DD_STOP
346 1.10 dbj */
347 1.1 dbj bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_START,
348 1.1 dbj bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_START));
349 1.1 dbj bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_STOP,
350 1.1 dbj bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_STOP));
351 1.7 dbj #else
352 1.7 dbj bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_START, 0xfeedbeef);
353 1.7 dbj bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_STOP, 0xfeedbeef);
354 1.7 dbj #endif
355 1.1 dbj
356 1.1 dbj }
357 1.1 dbj
358 1.1 dbj void
359 1.1 dbj next_dma_setup_curr_regs(nd)
360 1.1 dbj struct nextdma_config *nd;
361 1.1 dbj {
362 1.1 dbj DPRINTF(("DMA next_dma_setup_curr_regs()\n"));
363 1.1 dbj
364 1.15 dbj
365 1.15 dbj if (nd->_nd_map) {
366 1.15 dbj
367 1.15 dbj if (nd->nd_intr == NEXT_I_ENETX_DMA) {
368 1.1 dbj /* Ethernet transmit needs secret magic */
369 1.1 dbj
370 1.1 dbj bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_NEXT_INITBUF,
371 1.1 dbj nd->_nd_map->dm_segs[nd->_nd_idx].ds_addr);
372 1.1 dbj bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_LIMIT,
373 1.1 dbj ((nd->_nd_map->dm_segs[nd->_nd_idx].ds_addr +
374 1.1 dbj nd->_nd_map->dm_segs[nd->_nd_idx].ds_len)
375 1.1 dbj + 0x0) | 0x80000000);
376 1.1 dbj
377 1.1 dbj }
378 1.15 dbj #ifdef NEXTDMA_SCSI_HACK
379 1.15 dbj else if ((nd->nd_intr == NEXT_I_SCSI_DMA) && (nd->_nd_dmadir == DMACSR_WRITE)) {
380 1.15 dbj /* SCSI needs secret magic */
381 1.15 dbj
382 1.15 dbj bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_NEXT_INITBUF,
383 1.15 dbj nd->_nd_map->dm_segs[nd->_nd_idx].ds_addr);
384 1.15 dbj bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_LIMIT,
385 1.15 dbj ((nd->_nd_map->dm_segs[nd->_nd_idx].ds_addr +
386 1.15 dbj nd->_nd_map->dm_segs[nd->_nd_idx].ds_len)
387 1.15 dbj + 0x20));
388 1.7 dbj
389 1.15 dbj }
390 1.7 dbj #endif
391 1.15 dbj else {
392 1.9 dbj bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_NEXT_INITBUF,
393 1.1 dbj nd->_nd_map->dm_segs[nd->_nd_idx].ds_addr);
394 1.1 dbj bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_LIMIT,
395 1.1 dbj nd->_nd_map->dm_segs[nd->_nd_idx].ds_addr +
396 1.1 dbj nd->_nd_map->dm_segs[nd->_nd_idx].ds_len);
397 1.15 dbj }
398 1.1 dbj
399 1.15 dbj } else {
400 1.15 dbj bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_NEXT_INITBUF,0xdeadbeef);
401 1.15 dbj bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_LIMIT, 0xdeadbeef);
402 1.15 dbj }
403 1.1 dbj
404 1.10 dbj #if 1 /* See comment in next_dma_setup_cont_regs() above */
405 1.1 dbj bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_NEXT,
406 1.9 dbj bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_NEXT_INITBUF));
407 1.1 dbj bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_LIMIT,
408 1.1 dbj bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_LIMIT));
409 1.7 dbj #else
410 1.7 dbj bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_NEXT, 0xfeedbeef);
411 1.7 dbj bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_LIMIT, 0xfeedbeef);
412 1.7 dbj #endif
413 1.1 dbj
414 1.1 dbj }
415 1.1 dbj
416 1.1 dbj
417 1.1 dbj /* This routine is used for debugging */
418 1.1 dbj
419 1.1 dbj void
420 1.1 dbj next_dma_print(nd)
421 1.1 dbj struct nextdma_config *nd;
422 1.1 dbj {
423 1.1 dbj u_long dd_csr;
424 1.1 dbj u_long dd_next;
425 1.1 dbj u_long dd_next_initbuf;
426 1.1 dbj u_long dd_limit;
427 1.1 dbj u_long dd_start;
428 1.1 dbj u_long dd_stop;
429 1.1 dbj u_long dd_saved_next;
430 1.1 dbj u_long dd_saved_limit;
431 1.1 dbj u_long dd_saved_start;
432 1.1 dbj u_long dd_saved_stop;
433 1.1 dbj
434 1.1 dbj /* Read all of the registers before we print anything out,
435 1.1 dbj * in case something changes
436 1.1 dbj */
437 1.1 dbj dd_csr = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_CSR);
438 1.1 dbj dd_next = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_NEXT);
439 1.1 dbj dd_next_initbuf = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_NEXT_INITBUF);
440 1.1 dbj dd_limit = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_LIMIT);
441 1.1 dbj dd_start = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_START);
442 1.1 dbj dd_stop = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_STOP);
443 1.1 dbj dd_saved_next = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_NEXT);
444 1.1 dbj dd_saved_limit = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_LIMIT);
445 1.1 dbj dd_saved_start = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_START);
446 1.1 dbj dd_saved_stop = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_STOP);
447 1.1 dbj
448 1.12 dbj /* NDMAP is Next DMA Print (really!) */
449 1.12 dbj
450 1.12 dbj printf("NDMAP: nd->_nd_dmadir = 0x%08x\n",nd->_nd_dmadir);
451 1.12 dbj
452 1.1 dbj if (nd->_nd_map) {
453 1.11 dbj printf("NDMAP: nd->_nd_map->dm_mapsize = %d\n",
454 1.11 dbj nd->_nd_map->dm_mapsize);
455 1.11 dbj printf("NDMAP: nd->_nd_map->dm_nsegs = %d\n",
456 1.11 dbj nd->_nd_map->dm_nsegs);
457 1.1 dbj printf("NDMAP: nd->_nd_map->dm_segs[%d].ds_addr = 0x%08lx\n",
458 1.1 dbj nd->_nd_idx,nd->_nd_map->dm_segs[nd->_nd_idx].ds_addr);
459 1.1 dbj printf("NDMAP: nd->_nd_map->dm_segs[%d].ds_len = %d\n",
460 1.1 dbj nd->_nd_idx,nd->_nd_map->dm_segs[nd->_nd_idx].ds_len);
461 1.1 dbj } else {
462 1.1 dbj printf("NDMAP: nd->_nd_map = NULL\n");
463 1.1 dbj }
464 1.1 dbj if (nd->_nd_map_cont) {
465 1.11 dbj printf("NDMAP: nd->_nd_map_cont->dm_mapsize = %d\n",
466 1.11 dbj nd->_nd_map_cont->dm_mapsize);
467 1.11 dbj printf("NDMAP: nd->_nd_map_cont->dm_nsegs = %d\n",
468 1.11 dbj nd->_nd_map_cont->dm_nsegs);
469 1.1 dbj printf("NDMAP: nd->_nd_map_cont->dm_segs[%d].ds_addr = 0x%08lx\n",
470 1.1 dbj nd->_nd_idx_cont,nd->_nd_map_cont->dm_segs[nd->_nd_idx_cont].ds_addr);
471 1.2 dbj printf("NDMAP: nd->_nd_map_cont->dm_segs[%d].ds_len = %d\n",
472 1.1 dbj nd->_nd_idx_cont,nd->_nd_map_cont->dm_segs[nd->_nd_idx_cont].ds_len);
473 1.1 dbj } else {
474 1.1 dbj printf("NDMAP: nd->_nd_map_cont = NULL\n");
475 1.1 dbj }
476 1.1 dbj
477 1.1 dbj printf("NDMAP: dd->dd_csr = 0x%b\n", dd_csr, DMACSR_BITS);
478 1.1 dbj printf("NDMAP: dd->dd_saved_next = 0x%08x\n", dd_saved_next);
479 1.1 dbj printf("NDMAP: dd->dd_saved_limit = 0x%08x\n", dd_saved_limit);
480 1.1 dbj printf("NDMAP: dd->dd_saved_start = 0x%08x\n", dd_saved_start);
481 1.1 dbj printf("NDMAP: dd->dd_saved_stop = 0x%08x\n", dd_saved_stop);
482 1.1 dbj printf("NDMAP: dd->dd_next = 0x%08x\n", dd_next);
483 1.1 dbj printf("NDMAP: dd->dd_next_initbuf = 0x%08x\n", dd_next_initbuf);
484 1.1 dbj printf("NDMAP: dd->dd_limit = 0x%08x\n", dd_limit);
485 1.1 dbj printf("NDMAP: dd->dd_start = 0x%08x\n", dd_start);
486 1.1 dbj printf("NDMAP: dd->dd_stop = 0x%08x\n", dd_stop);
487 1.1 dbj
488 1.1 dbj printf("NDMAP: interrupt ipl (%ld) intr(0x%b)\n",
489 1.1 dbj NEXT_I_IPL(nd->nd_intr), NEXT_I_BIT(nd->nd_intr),NEXT_INTR_BITS);
490 1.1 dbj }
491 1.1 dbj
492 1.1 dbj /****************************************************************/
493 1.1 dbj
494 1.1 dbj int
495 1.1 dbj nextdma_intr(arg)
496 1.1 dbj void *arg;
497 1.1 dbj {
498 1.1 dbj struct nextdma_config *nd = arg;
499 1.1 dbj
500 1.1 dbj /* @@@ This is bogus, we can't be certain of arg's type
501 1.1 dbj * unless the interrupt is for us
502 1.1 dbj */
503 1.1 dbj
504 1.1 dbj if (!INTR_OCCURRED(nd->nd_intr)) return 0;
505 1.1 dbj /* Handle dma interrupts */
506 1.1 dbj
507 1.1 dbj #ifdef DIAGNOSTIC
508 1.1 dbj if (nd->nd_intr == NEXT_I_ENETR_DMA) {
509 1.1 dbj if (debugernd != nd) {
510 1.1 dbj panic("DMA incorrect handling of rx nd->nd_intr");
511 1.1 dbj }
512 1.1 dbj }
513 1.1 dbj if (nd->nd_intr == NEXT_I_ENETX_DMA) {
514 1.1 dbj if (debugexnd != nd) {
515 1.1 dbj panic("DMA incorrect handling of tx nd->nd_intr");
516 1.1 dbj }
517 1.1 dbj }
518 1.1 dbj #endif
519 1.1 dbj
520 1.1 dbj DPRINTF(("DMA interrupt ipl (%ld) intr(0x%b)\n",
521 1.1 dbj NEXT_I_IPL(nd->nd_intr), NEXT_I_BIT(nd->nd_intr),NEXT_INTR_BITS));
522 1.1 dbj
523 1.7 dbj #ifdef DIAGNOSTIC
524 1.7 dbj if (!nd->_nd_map) {
525 1.7 dbj next_dma_print(nd);
526 1.7 dbj panic("DMA missing current map in interrupt!\n");
527 1.7 dbj }
528 1.7 dbj #endif
529 1.7 dbj
530 1.1 dbj {
531 1.1 dbj int state = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_CSR);
532 1.1 dbj
533 1.7 dbj #ifdef DIAGNOSTIC
534 1.7 dbj if (!(state & DMACSR_COMPLETE)) {
535 1.1 dbj next_dma_print(nd);
536 1.7 dbj printf("DEBUG: state = 0x%b\n", state,DMACSR_BITS);
537 1.7 dbj panic("DMA ipl (%ld) intr(0x%b), DMACSR_COMPLETE not set in intr\n",
538 1.7 dbj NEXT_I_IPL(nd->nd_intr), NEXT_I_BIT(nd->nd_intr),NEXT_INTR_BITS);
539 1.7 dbj }
540 1.1 dbj #endif
541 1.1 dbj
542 1.7 dbj #if 0 /* This bit gets set sometimes & I don't know why. */
543 1.1 dbj #ifdef DIAGNOSTIC
544 1.7 dbj if (state & DMACSR_BUSEXC) {
545 1.1 dbj next_dma_print(nd);
546 1.1 dbj printf("DEBUG: state = 0x%b\n", state,DMACSR_BITS);
547 1.1 dbj panic("DMA ipl (%ld) intr(0x%b), DMACSR_COMPLETE not set in intr\n",
548 1.1 dbj NEXT_I_IPL(nd->nd_intr), NEXT_I_BIT(nd->nd_intr),NEXT_INTR_BITS);
549 1.7 dbj }
550 1.7 dbj #endif
551 1.7 dbj #endif
552 1.7 dbj
553 1.7 dbj /* Check to see if we are expecting dma to shut down */
554 1.7 dbj if (!nd->_nd_map_cont) {
555 1.7 dbj
556 1.7 dbj #ifdef DIAGNOSTIC
557 1.12 dbj #if 1 /* Sometimes the DMA registers have totally bogus values when read.
558 1.7 dbj * Until that's understood, we skip this check
559 1.7 dbj */
560 1.7 dbj
561 1.7 dbj /* Verify that the registers are laid out as expected */
562 1.7 dbj {
563 1.7 dbj bus_addr_t next;
564 1.7 dbj bus_addr_t limit;
565 1.7 dbj bus_addr_t expected_limit;
566 1.7 dbj expected_limit =
567 1.7 dbj nd->_nd_map->dm_segs[nd->_nd_idx].ds_addr +
568 1.7 dbj nd->_nd_map->dm_segs[nd->_nd_idx].ds_len;
569 1.7 dbj
570 1.7 dbj if (nd->nd_intr == NEXT_I_ENETX_DMA) {
571 1.7 dbj next = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_NEXT_INITBUF);
572 1.7 dbj limit = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_LIMIT) & ~0x80000000;
573 1.15 dbj }
574 1.15 dbj #ifdef NEXTDMA_SCSI_HACK
575 1.15 dbj else if ((nd->nd_intr == NEXT_I_SCSI_DMA) && (nd->_nd_dmadir == DMACSR_WRITE)) {
576 1.15 dbj next = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_NEXT) - 0x20;
577 1.15 dbj limit = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_LIMIT) - 0x20;
578 1.15 dbj }
579 1.15 dbj #endif
580 1.15 dbj else {
581 1.7 dbj next = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_NEXT);
582 1.7 dbj limit = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_LIMIT);
583 1.7 dbj }
584 1.7 dbj
585 1.7 dbj if ((next != limit) || (limit != expected_limit)) {
586 1.7 dbj next_dma_print(nd);
587 1.7 dbj printf("DEBUG: state = 0x%b\n", state,DMACSR_BITS);
588 1.7 dbj panic("unexpected DMA limit at shutdown 0x%08x, 0x%08x, 0x%08x",
589 1.7 dbj next,limit,expected_limit);
590 1.7 dbj }
591 1.12 dbj }
592 1.12 dbj #endif
593 1.12 dbj #endif
594 1.12 dbj
595 1.13 dbj #if 1
596 1.12 dbj #ifdef DIAGNOSTIC
597 1.12 dbj if (state & (DMACSR_SUPDATE|DMACSR_ENABLE)) {
598 1.12 dbj next_dma_print(nd);
599 1.12 dbj panic("DMA: unexpected bits set in DMA state at shutdown (0x%b)\n",
600 1.12 dbj state,DMACSR_BITS);
601 1.7 dbj }
602 1.7 dbj #endif
603 1.7 dbj #endif
604 1.7 dbj
605 1.7 dbj if ((nd->_nd_idx+1) == nd->_nd_map->dm_nsegs) {
606 1.7 dbj if (nd->nd_completed_cb)
607 1.7 dbj (*nd->nd_completed_cb)(nd->_nd_map, nd->nd_cb_arg);
608 1.7 dbj }
609 1.7 dbj nd->_nd_map = 0;
610 1.7 dbj nd->_nd_idx = 0;
611 1.7 dbj
612 1.7 dbj bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_CSR,
613 1.7 dbj DMACSR_CLRCOMPLETE | DMACSR_RESET);
614 1.7 dbj
615 1.7 dbj DPRINTF(("DMA: a normal and expected shutdown occurred\n"));
616 1.7 dbj if (nd->nd_shutdown_cb) (*nd->nd_shutdown_cb)(nd->nd_cb_arg);
617 1.7 dbj
618 1.2 dbj return(1);
619 1.7 dbj }
620 1.7 dbj
621 1.7 dbj #if 0
622 1.7 dbj #ifdef DIAGNOSTIC
623 1.7 dbj if (!(state & DMACSR_SUPDATE)) {
624 1.7 dbj next_dma_print(nd);
625 1.7 dbj printf("DEBUG: state = 0x%b\n", state,DMACSR_BITS);
626 1.7 dbj panic("SUPDATE not set with continuing DMA");
627 1.7 dbj }
628 1.2 dbj #endif
629 1.1 dbj #endif
630 1.1 dbj
631 1.7 dbj /* Check that the buffer we are interrupted for is the one we expect.
632 1.7 dbj * Shorten the buffer if the dma completed with a short buffer
633 1.1 dbj */
634 1.7 dbj {
635 1.1 dbj bus_addr_t next;
636 1.1 dbj bus_addr_t limit;
637 1.7 dbj bus_addr_t expected_next;
638 1.7 dbj bus_addr_t expected_limit;
639 1.7 dbj
640 1.7 dbj expected_next = nd->_nd_map->dm_segs[nd->_nd_idx].ds_addr;
641 1.7 dbj expected_limit = expected_next + nd->_nd_map->dm_segs[nd->_nd_idx].ds_len;
642 1.1 dbj
643 1.7 dbj #if 0 /* for some unknown reason, somtimes DD_SAVED_NEXT has value from
644 1.7 dbj * nd->_nd_map and sometimes it has value from nd->_nd_map_cont.
645 1.7 dbj * Somtimes, it has a completely different unknown value.
646 1.7 dbj * Until that's understood, we won't sanity check the expected_next value.
647 1.7 dbj */
648 1.7 dbj next = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_NEXT);
649 1.1 dbj #else
650 1.7 dbj next = expected_next;
651 1.1 dbj #endif
652 1.1 dbj limit = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_LIMIT);
653 1.1 dbj
654 1.1 dbj if (nd->nd_intr == NEXT_I_ENETX_DMA) {
655 1.1 dbj limit &= ~0x80000000;
656 1.1 dbj }
657 1.15 dbj #ifdef NEXTDMA_SCSI_HACK
658 1.15 dbj else if ((nd->nd_intr == NEXT_I_SCSI_DMA) && (nd->_nd_dmadir == DMACSR_WRITE)) {
659 1.15 dbj limit -= 0x20;
660 1.15 dbj }
661 1.15 dbj #endif
662 1.7 dbj
663 1.7 dbj if ((limit-next < 0) ||
664 1.7 dbj (limit-next >= expected_limit-expected_next)) {
665 1.7 dbj #ifdef DIAGNOSTIC
666 1.7 dbj #if 0 /* Sometimes, (under load I think) even DD_SAVED_LIMIT has
667 1.7 dbj * a bogus value. Until that's understood, we don't panic
668 1.7 dbj * here.
669 1.7 dbj */
670 1.7 dbj next_dma_print(nd);
671 1.7 dbj printf("DEBUG: state = 0x%b\n", state,DMACSR_BITS);
672 1.7 dbj panic("Unexpected saved registers values.");
673 1.7 dbj #endif
674 1.7 dbj #endif
675 1.7 dbj } else {
676 1.7 dbj /* Set the length of the segment to match actual length.
677 1.7 dbj * @@@ is it okay to resize dma segments here?
678 1.7 dbj * i should probably ask jason about this.
679 1.7 dbj */
680 1.7 dbj nd->_nd_map->dm_segs[nd->_nd_idx].ds_len = limit-next;
681 1.7 dbj expected_limit = expected_next + nd->_nd_map->dm_segs[nd->_nd_idx].ds_len;
682 1.7 dbj }
683 1.1 dbj
684 1.7 dbj #if 0 /* these checks are turned off until the above mentioned weirdness is fixed. */
685 1.1 dbj #ifdef DIAGNOSTIC
686 1.7 dbj if (next != expected_next) {
687 1.1 dbj next_dma_print(nd);
688 1.1 dbj printf("DEBUG: state = 0x%b\n", state,DMACSR_BITS);
689 1.7 dbj panic("unexpected DMA next buffer in interrupt (found 0x%08x, expected 0x%08x)",
690 1.7 dbj next,expected_next);
691 1.1 dbj }
692 1.7 dbj if (limit != expected_limit) {
693 1.1 dbj next_dma_print(nd);
694 1.1 dbj printf("DEBUG: state = 0x%b\n", state,DMACSR_BITS);
695 1.7 dbj panic("unexpected DMA limit buffer in interrupt (found 0x%08x, expected 0x%08x)",
696 1.7 dbj limit,expected_limit);
697 1.7 dbj }
698 1.7 dbj #endif
699 1.1 dbj #endif
700 1.1 dbj }
701 1.1 dbj
702 1.7 dbj next_dma_rotate(nd);
703 1.7 dbj next_dma_setup_cont_regs(nd);
704 1.1 dbj
705 1.7 dbj if (!(state & DMACSR_ENABLE)) {
706 1.10 dbj
707 1.10 dbj DPRINTF(("Unexpected DMA shutdown, restarting\n"));
708 1.1 dbj
709 1.1 dbj if (nd->_nd_map_cont) {
710 1.1 dbj bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_CSR,
711 1.9 dbj DMACSR_SETSUPDATE | DMACSR_SETENABLE | nd->_nd_dmadir);
712 1.1 dbj } else {
713 1.7 dbj bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_CSR,
714 1.9 dbj DMACSR_SETENABLE | nd->_nd_dmadir);
715 1.1 dbj }
716 1.1 dbj
717 1.1 dbj } else {
718 1.1 dbj
719 1.1 dbj if (nd->_nd_map_cont) {
720 1.1 dbj bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_CSR,
721 1.9 dbj DMACSR_SETSUPDATE | DMACSR_CLRCOMPLETE | nd->_nd_dmadir);
722 1.1 dbj } else {
723 1.1 dbj bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_CSR,
724 1.9 dbj DMACSR_CLRCOMPLETE | nd->_nd_dmadir);
725 1.1 dbj }
726 1.1 dbj }
727 1.1 dbj
728 1.1 dbj }
729 1.1 dbj
730 1.1 dbj DPRINTF(("DMA exiting interrupt ipl (%ld) intr(0x%b)\n",
731 1.1 dbj NEXT_I_IPL(nd->nd_intr), NEXT_I_BIT(nd->nd_intr),NEXT_INTR_BITS));
732 1.1 dbj
733 1.1 dbj return(1);
734 1.1 dbj }
735 1.1 dbj
736 1.1 dbj /*
737 1.1 dbj * Check to see if dma has finished for a channel */
738 1.1 dbj int
739 1.1 dbj nextdma_finished(nd)
740 1.1 dbj struct nextdma_config *nd;
741 1.1 dbj {
742 1.1 dbj int r;
743 1.1 dbj int s;
744 1.1 dbj s = spldma(); /* @@@ should this be splimp()? */
745 1.1 dbj r = (nd->_nd_map == NULL) && (nd->_nd_map_cont == NULL);
746 1.1 dbj splx(s);
747 1.1 dbj return(r);
748 1.1 dbj }
749 1.1 dbj
750 1.1 dbj void
751 1.1 dbj nextdma_start(nd, dmadir)
752 1.1 dbj struct nextdma_config *nd;
753 1.1 dbj u_long dmadir; /* DMACSR_READ or DMACSR_WRITE */
754 1.1 dbj {
755 1.1 dbj
756 1.1 dbj #ifdef DIAGNOSTIC
757 1.1 dbj if (!nextdma_finished(nd)) {
758 1.1 dbj panic("DMA trying to start before previous finished on intr(0x%b)\n",
759 1.1 dbj NEXT_I_BIT(nd->nd_intr),NEXT_INTR_BITS);
760 1.1 dbj }
761 1.1 dbj #endif
762 1.1 dbj
763 1.1 dbj DPRINTF(("DMA start (%ld) intr(0x%b)\n",
764 1.1 dbj NEXT_I_IPL(nd->nd_intr), NEXT_I_BIT(nd->nd_intr),NEXT_INTR_BITS));
765 1.1 dbj
766 1.1 dbj #ifdef DIAGNOSTIC
767 1.1 dbj if (nd->_nd_map) {
768 1.1 dbj next_dma_print(nd);
769 1.1 dbj panic("DMA: nextdma_start() with non null map\n");
770 1.1 dbj }
771 1.1 dbj if (nd->_nd_map_cont) {
772 1.1 dbj next_dma_print(nd);
773 1.1 dbj panic("DMA: nextdma_start() with non null continue map\n");
774 1.1 dbj }
775 1.1 dbj #endif
776 1.1 dbj
777 1.9 dbj #ifdef DIAGNOSTIC
778 1.9 dbj if ((dmadir != DMACSR_READ) && (dmadir != DMACSR_WRITE)) {
779 1.9 dbj panic("DMA: nextdma_start(), dmadir arg must be DMACSR_READ or DMACSR_WRITE\n");
780 1.9 dbj }
781 1.9 dbj #endif
782 1.9 dbj
783 1.9 dbj nd->_nd_dmadir = dmadir;
784 1.9 dbj
785 1.7 dbj /* preload both the current and the continue maps */
786 1.1 dbj next_dma_rotate(nd);
787 1.1 dbj
788 1.1 dbj #ifdef DIAGNOSTIC
789 1.1 dbj if (!nd->_nd_map_cont) {
790 1.1 dbj panic("No map available in nextdma_start()");
791 1.1 dbj }
792 1.1 dbj #endif
793 1.1 dbj
794 1.7 dbj next_dma_rotate(nd);
795 1.7 dbj
796 1.1 dbj DPRINTF(("DMA initiating DMA %s of %d segments on intr(0x%b)\n",
797 1.9 dbj (nd->_nd_dmadir == DMACSR_READ ? "read" : "write"), nd->_nd_map->dm_nsegs,
798 1.1 dbj NEXT_I_BIT(nd->nd_intr),NEXT_INTR_BITS));
799 1.1 dbj
800 1.1 dbj bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_CSR, 0);
801 1.1 dbj bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_CSR,
802 1.9 dbj DMACSR_INITBUF | DMACSR_RESET | nd->_nd_dmadir);
803 1.1 dbj
804 1.7 dbj next_dma_setup_curr_regs(nd);
805 1.1 dbj next_dma_setup_cont_regs(nd);
806 1.1 dbj
807 1.4 dbj #if (defined(ND_DEBUG))
808 1.8 dbj if (nextdma_debug) next_dma_print(nd);
809 1.4 dbj #endif
810 1.1 dbj
811 1.7 dbj if (nd->_nd_map_cont) {
812 1.1 dbj bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_CSR,
813 1.9 dbj DMACSR_SETSUPDATE | DMACSR_SETENABLE | nd->_nd_dmadir);
814 1.1 dbj } else {
815 1.1 dbj bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_CSR,
816 1.9 dbj DMACSR_SETENABLE | nd->_nd_dmadir);
817 1.1 dbj }
818 1.1 dbj
819 1.1 dbj }
820