esp.c revision 1.46 1 /* $NetBSD: esp.c,v 1.46 2003/09/27 20:16:59 cl Exp $ */
2
3 /*-
4 * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace
9 * Simulation Facility, NASA Ames Research Center.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the NetBSD
22 * Foundation, Inc. and its contributors.
23 * 4. Neither the name of The NetBSD Foundation nor the names of its
24 * contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
38 */
39
40 /*
41 * Copyright (c) 1994 Peter Galbavy
42 * All rights reserved.
43 *
44 * Redistribution and use in source and binary forms, with or without
45 * modification, are permitted provided that the following conditions
46 * are met:
47 * 1. Redistributions of source code must retain the above copyright
48 * notice, this list of conditions and the following disclaimer.
49 * 2. Redistributions in binary form must reproduce the above copyright
50 * notice, this list of conditions and the following disclaimer in the
51 * documentation and/or other materials provided with the distribution.
52 * 3. All advertising materials mentioning features or use of this software
53 * must display the following acknowledgement:
54 * This product includes software developed by Peter Galbavy
55 * 4. The name of the author may not be used to endorse or promote products
56 * derived from this software without specific prior written permission.
57 *
58 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
59 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
60 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
61 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
62 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
63 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
64 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
65 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
66 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
67 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
68 * POSSIBILITY OF SUCH DAMAGE.
69 */
70
71 /*
72 * Based on aic6360 by Jarle Greipsland
73 *
74 * Acknowledgements: Many of the algorithms used in this driver are
75 * inspired by the work of Julian Elischer (julian (at) tfs.com) and
76 * Charles Hannum (mycroft (at) duality.gnu.ai.mit.edu). Thanks a million!
77 */
78
79 /*
80 * Grabbed from the sparc port at revision 1.73 for the NeXT.
81 * Darrin B. Jewell <dbj (at) netbsd.org> Sat Jul 4 15:41:32 1998
82 */
83
84 #include <sys/cdefs.h>
85 __KERNEL_RCSID(0, "$NetBSD: esp.c,v 1.46 2003/09/27 20:16:59 cl Exp $");
86
87 #include <sys/types.h>
88 #include <sys/param.h>
89 #include <sys/systm.h>
90 #include <sys/kernel.h>
91 #include <sys/errno.h>
92 #include <sys/ioctl.h>
93 #include <sys/device.h>
94 #include <sys/buf.h>
95 #include <sys/proc.h>
96 #include <sys/user.h>
97 #include <sys/queue.h>
98
99 #include <uvm/uvm_extern.h>
100
101 #include <dev/scsipi/scsi_all.h>
102 #include <dev/scsipi/scsipi_all.h>
103 #include <dev/scsipi/scsiconf.h>
104 #include <dev/scsipi/scsi_message.h>
105
106 #include <machine/bus.h>
107 #include <machine/autoconf.h>
108 #include <machine/cpu.h>
109
110 #include <dev/ic/ncr53c9xreg.h>
111 #include <dev/ic/ncr53c9xvar.h>
112
113 #include <next68k/next68k/isr.h>
114
115 #include <next68k/dev/intiovar.h>
116 #include <next68k/dev/nextdmareg.h>
117 #include <next68k/dev/nextdmavar.h>
118
119 #include <next68k/dev/espreg.h>
120 #include <next68k/dev/espvar.h>
121
122 #ifdef DEBUG
123 #undef ESP_DEBUG
124 #endif
125
126 #ifdef ESP_DEBUG
127 int esp_debug = 0;
128 #define DPRINTF(x) if (esp_debug) printf x;
129 extern char *ndtracep;
130 extern char ndtrace[];
131 extern int ndtraceshow;
132 #define NDTRACEIF(x) if (10 && ndtracep < (ndtrace + 8192)) do {x;} while (0)
133 #else
134 #define DPRINTF(x)
135 #define NDTRACEIF(x)
136 #endif
137 #define PRINTF(x) printf x;
138
139
140 void espattach_intio __P((struct device *, struct device *, void *));
141 int espmatch_intio __P((struct device *, struct cfdata *, void *));
142
143 /* DMA callbacks */
144 bus_dmamap_t esp_dmacb_continue __P((void *arg));
145 void esp_dmacb_completed __P((bus_dmamap_t map, void *arg));
146 void esp_dmacb_shutdown __P((void *arg));
147
148 static void findchannel_defer __P((struct device *));
149
150 #ifdef ESP_DEBUG
151 char esp_dma_dump[5*1024] = "";
152 struct ncr53c9x_softc *esp_debug_sc = 0;
153 void esp_dma_store __P((struct ncr53c9x_softc *sc));
154 void esp_dma_print __P((struct ncr53c9x_softc *sc));
155 int esp_dma_nest = 0;
156 #endif
157
158
159 /* Linkup to the rest of the kernel */
160 CFATTACH_DECL(esp, sizeof(struct esp_softc),
161 espmatch_intio, espattach_intio, NULL, NULL);
162
163 static int attached = 0;
164
165 /*
166 * Functions and the switch for the MI code.
167 */
168 u_char esp_read_reg __P((struct ncr53c9x_softc *, int));
169 void esp_write_reg __P((struct ncr53c9x_softc *, int, u_char));
170 int esp_dma_isintr __P((struct ncr53c9x_softc *));
171 void esp_dma_reset __P((struct ncr53c9x_softc *));
172 int esp_dma_intr __P((struct ncr53c9x_softc *));
173 int esp_dma_setup __P((struct ncr53c9x_softc *, caddr_t *,
174 size_t *, int, size_t *));
175 void esp_dma_go __P((struct ncr53c9x_softc *));
176 void esp_dma_stop __P((struct ncr53c9x_softc *));
177 int esp_dma_isactive __P((struct ncr53c9x_softc *));
178
179 struct ncr53c9x_glue esp_glue = {
180 esp_read_reg,
181 esp_write_reg,
182 esp_dma_isintr,
183 esp_dma_reset,
184 esp_dma_intr,
185 esp_dma_setup,
186 esp_dma_go,
187 esp_dma_stop,
188 esp_dma_isactive,
189 NULL, /* gl_clear_latched_intr */
190 };
191
192 #ifdef ESP_DEBUG
193 #define XCHR(x) "0123456789abcdef"[(x) & 0xf]
194 static void
195 esp_hex_dump(unsigned char *pkt, size_t len)
196 {
197 size_t i, j;
198
199 printf("00000000 ");
200 for(i=0; i<len; i++) {
201 printf("%c%c ", XCHR(pkt[i]>>4), XCHR(pkt[i]));
202 if ((i+1) % 16 == 8) {
203 printf(" ");
204 }
205 if ((i+1) % 16 == 0) {
206 printf(" %c", '|');
207 for(j=0; j<16; j++) {
208 printf("%c", pkt[i-15+j]>=32 && pkt[i-15+j]<127?pkt[i-15+j]:'.');
209 }
210 printf("%c\n%c%c%c%c%c%c%c%c ", '|',
211 XCHR((i+1)>>28),XCHR((i+1)>>24),XCHR((i+1)>>20),XCHR((i+1)>>16),
212 XCHR((i+1)>>12), XCHR((i+1)>>8), XCHR((i+1)>>4), XCHR(i+1));
213 }
214 }
215 printf("\n");
216 }
217 #endif
218
219 int
220 espmatch_intio(parent, cf, aux)
221 struct device *parent;
222 struct cfdata *cf;
223 void *aux;
224 {
225 struct intio_attach_args *ia = (struct intio_attach_args *)aux;
226
227 if (attached)
228 return (0);
229
230 ia->ia_addr = (void *)NEXT_P_SCSI;
231
232 return(1);
233 }
234
235 static void
236 findchannel_defer(self)
237 struct device *self;
238 {
239 struct esp_softc *esc = (void *)self;
240 struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x;
241 int error;
242
243 if (!esc->sc_dma) {
244 printf ("%s", sc->sc_dev.dv_xname);
245 esc->sc_dma = nextdma_findchannel ("scsi");
246 if (!esc->sc_dma)
247 panic ("%s: can't find DMA channel",
248 sc->sc_dev.dv_xname);
249 }
250
251 nextdma_setconf (esc->sc_dma, shutdown_cb, &esp_dmacb_shutdown);
252 nextdma_setconf (esc->sc_dma, continue_cb, &esp_dmacb_continue);
253 nextdma_setconf (esc->sc_dma, completed_cb, &esp_dmacb_completed);
254 nextdma_setconf (esc->sc_dma, cb_arg, sc);
255
256 error = bus_dmamap_create(esc->sc_dma->sc_dmat,
257 sc->sc_maxxfer,
258 sc->sc_maxxfer/PAGE_SIZE+1, sc->sc_maxxfer,
259 0, BUS_DMA_ALLOCNOW, &esc->sc_main_dmamap);
260 if (error) {
261 panic("%s: can't create main i/o DMA map, error = %d",
262 sc->sc_dev.dv_xname, error);
263 }
264
265 error = bus_dmamap_create(esc->sc_dma->sc_dmat,
266 ESP_DMA_TAILBUFSIZE, 1, ESP_DMA_TAILBUFSIZE,
267 0, BUS_DMA_ALLOCNOW, &esc->sc_tail_dmamap);
268 if (error) {
269 panic("%s: can't create tail i/o DMA map, error = %d",
270 sc->sc_dev.dv_xname, error);
271 }
272
273 #if 0
274 /* Turn on target selection using the `DMA' method */
275 sc->sc_features |= NCR_F_DMASELECT;
276 #endif
277
278 /* Do the common parts of attachment. */
279 sc->sc_adapter.adapt_minphys = minphys;
280 sc->sc_adapter.adapt_request = ncr53c9x_scsipi_request;
281 ncr53c9x_attach(sc);
282
283 /* Establish interrupt channel */
284 isrlink_autovec(ncr53c9x_intr, sc, NEXT_I_IPL(NEXT_I_SCSI), 0, NULL);
285 INTR_ENABLE(NEXT_I_SCSI);
286
287 /* register interrupt stats */
288 evcnt_attach_dynamic(&sc->sc_intrcnt, EVCNT_TYPE_INTR, NULL,
289 sc->sc_dev.dv_xname, "intr");
290
291 printf ("%s: using DMA channel %s\n", sc->sc_dev.dv_xname,
292 esc->sc_dma->sc_dev.dv_xname);
293 }
294
295 void
296 espattach_intio(parent, self, aux)
297 struct device *parent, *self;
298 void *aux;
299 {
300 struct esp_softc *esc = (void *)self;
301 struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x;
302 struct intio_attach_args *ia = (struct intio_attach_args *)aux;
303
304 #ifdef ESP_DEBUG
305 esp_debug_sc = sc;
306 #endif
307
308 esc->sc_bst = ia->ia_bst;
309 if (bus_space_map(esc->sc_bst, NEXT_P_SCSI,
310 ESP_DEVICE_SIZE, 0, &esc->sc_bsh)) {
311 panic("\n%s: can't map ncr53c90 registers",
312 sc->sc_dev.dv_xname);
313 }
314
315 sc->sc_id = 7;
316 sc->sc_freq = 20; /* Mhz */
317
318 /*
319 * Set up glue for MI code early; we use some of it here.
320 */
321 sc->sc_glue = &esp_glue;
322
323 /*
324 * XXX More of this should be in ncr53c9x_attach(), but
325 * XXX should we really poke around the chip that much in
326 * XXX the MI code? Think about this more...
327 */
328
329 /*
330 * It is necessary to try to load the 2nd config register here,
331 * to find out what rev the esp chip is, else the ncr53c9x_reset
332 * will not set up the defaults correctly.
333 */
334 sc->sc_cfg1 = sc->sc_id | NCRCFG1_PARENB;
335 sc->sc_cfg2 = NCRCFG2_SCSI2 | NCRCFG2_RPE;
336 sc->sc_cfg3 = NCRCFG3_CDB;
337 NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
338
339 if ((NCR_READ_REG(sc, NCR_CFG2) & ~NCRCFG2_RSVD) !=
340 (NCRCFG2_SCSI2 | NCRCFG2_RPE)) {
341 sc->sc_rev = NCR_VARIANT_ESP100;
342 } else {
343 sc->sc_cfg2 = NCRCFG2_SCSI2;
344 NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
345 sc->sc_cfg3 = 0;
346 NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
347 sc->sc_cfg3 = (NCRCFG3_CDB | NCRCFG3_FCLK);
348 NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
349 if (NCR_READ_REG(sc, NCR_CFG3) !=
350 (NCRCFG3_CDB | NCRCFG3_FCLK)) {
351 sc->sc_rev = NCR_VARIANT_ESP100A;
352 } else {
353 /* NCRCFG2_FE enables > 64K transfers */
354 sc->sc_cfg2 |= NCRCFG2_FE;
355 sc->sc_cfg3 = 0;
356 NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
357 sc->sc_rev = NCR_VARIANT_ESP200;
358 }
359 }
360
361 /*
362 * XXX minsync and maxxfer _should_ be set up in MI code,
363 * XXX but it appears to have some dependency on what sort
364 * XXX of DMA we're hooked up to, etc.
365 */
366
367 /*
368 * This is the value used to start sync negotiations
369 * Note that the NCR register "SYNCTP" is programmed
370 * in "clocks per byte", and has a minimum value of 4.
371 * The SCSI period used in negotiation is one-fourth
372 * of the time (in nanoseconds) needed to transfer one byte.
373 * Since the chip's clock is given in MHz, we have the following
374 * formula: 4 * period = (1000 / freq) * 4
375 */
376 sc->sc_minsync = /* 1000 / sc->sc_freq */ 0;
377
378 /*
379 * Alas, we must now modify the value a bit, because it's
380 * only valid when can switch on FASTCLK and FASTSCSI bits
381 * in config register 3...
382 */
383 switch (sc->sc_rev) {
384 case NCR_VARIANT_ESP100:
385 sc->sc_maxxfer = 64 * 1024;
386 sc->sc_minsync = 0; /* No synch on old chip? */
387 break;
388
389 case NCR_VARIANT_ESP100A:
390 sc->sc_maxxfer = 64 * 1024;
391 /* Min clocks/byte is 5 */
392 sc->sc_minsync = /* ncr53c9x_cpb2stp(sc, 5) */ 0;
393 break;
394
395 case NCR_VARIANT_ESP200:
396 sc->sc_maxxfer = 16 * 1024 * 1024;
397 /* XXX - do actually set FAST* bits */
398 break;
399 }
400
401 /* @@@ Some ESP_DCTL bits probably need setting */
402 NCR_WRITE_REG(sc, ESP_DCTL,
403 ESPDCTL_16MHZ | ESPDCTL_INTENB | ESPDCTL_RESET);
404 DELAY(10);
405 DPRINTF(("esp dctl is 0x%02x\n",NCR_READ_REG(sc,ESP_DCTL)));
406 NCR_WRITE_REG(sc, ESP_DCTL, ESPDCTL_16MHZ | ESPDCTL_INTENB);
407 DELAY(10);
408 DPRINTF(("esp dctl is 0x%02x\n",NCR_READ_REG(sc,ESP_DCTL)));
409
410 esc->sc_dma = nextdma_findchannel ("scsi");
411 if (esc->sc_dma) {
412 findchannel_defer (self);
413 } else {
414 printf ("\n");
415 config_defer (self, findchannel_defer);
416 }
417
418 attached = 1;
419 }
420
421 /*
422 * Glue functions.
423 */
424
425 u_char
426 esp_read_reg(sc, reg)
427 struct ncr53c9x_softc *sc;
428 int reg;
429 {
430 struct esp_softc *esc = (struct esp_softc *)sc;
431
432 return(bus_space_read_1(esc->sc_bst, esc->sc_bsh, reg));
433 }
434
435 void
436 esp_write_reg(sc, reg, val)
437 struct ncr53c9x_softc *sc;
438 int reg;
439 u_char val;
440 {
441 struct esp_softc *esc = (struct esp_softc *)sc;
442
443 bus_space_write_1(esc->sc_bst, esc->sc_bsh, reg, val);
444 }
445
446 volatile u_int32_t save1;
447
448 #define xADDR 0x0211a000
449 int doze __P((volatile int));
450 int
451 doze(c)
452 volatile int c;
453 {
454 /* static int tmp1; */
455 u_int32_t tmp1;
456 volatile u_int8_t tmp2;
457 volatile u_int8_t *reg = (volatile u_int8_t *)IIOV(xADDR);
458 if (c > 244) return (0);
459 if (c == 0) return (0);
460 /* ((*(volatile u_long *)IIOV(NEXT_P_INTRMASK))&=(~NEXT_I_BIT(x))) */
461 (*reg) = 0;
462 (*reg) = 0;
463 do {
464 save1 = (*reg);
465 tmp2 = *(reg + 3);
466 tmp1 = tmp2;
467 } while (tmp1 <= c);
468 return (0);
469 }
470
471 int
472 esp_dma_isintr(sc)
473 struct ncr53c9x_softc *sc;
474 {
475 struct esp_softc *esc = (struct esp_softc *)sc;
476 if (INTR_OCCURRED(NEXT_I_SCSI)) {
477 NDTRACEIF (*ndtracep++ = 'i');
478 NCR_WRITE_REG(sc, ESP_DCTL, ESPDCTL_16MHZ | ESPDCTL_INTENB | (esc->sc_datain ? ESPDCTL_DMARD : 0));
479 return (1);
480 } else {
481 return (0);
482 }
483 }
484
485 #define nd_bsr4(reg) bus_space_read_4(nsc->sc_bst, nsc->sc_bsh, (reg))
486 #define nd_bsw4(reg,val) bus_space_write_4(nsc->sc_bst, nsc->sc_bsh, (reg), (val))
487 int
488 esp_dma_intr(sc)
489 struct ncr53c9x_softc *sc;
490 {
491 struct esp_softc *esc = (struct esp_softc *)sc;
492 struct nextdma_softc *nsc = esc->sc_dma;
493 struct nextdma_status *stat = &nsc->sc_stat;
494
495 int r = (INTR_OCCURRED(NEXT_I_SCSI));
496 int flushcount;
497 r = 1;
498
499 NDTRACEIF (*ndtracep++ = 'I');
500 if (r) {
501 /* printf ("esp_dma_isintr start\n"); */
502 {
503 int s = spldma();
504 void *ndmap = stat->nd_map;
505 int ndidx = stat->nd_idx;
506 splx(s);
507
508 flushcount = 0;
509
510 #ifdef ESP_DEBUG
511 /* esp_dma_nest++; */
512
513 if (esp_debug) {
514 char sbuf[256];
515
516 bitmask_snprintf((*(volatile u_long *)IIOV(NEXT_P_INTRSTAT)),
517 NEXT_INTR_BITS, sbuf, sizeof(sbuf));
518 printf("esp_dma_isintr = 0x%s\n", sbuf);
519 }
520 #endif
521
522 while (!nextdma_finished(nsc)) { /* esp_dma_isactive(sc)) { */
523 NDTRACEIF (*ndtracep++ = 'w');
524 NDTRACEIF (
525 sprintf (ndtracep, "f%dm%dl%dw", NCR_READ_REG(sc, NCR_FFLAG) & NCRFIFO_FF,
526 NCR_READ_REG((sc), NCR_TCM), NCR_READ_REG((sc), NCR_TCL));
527 ndtracep += strlen (ndtracep);
528 );
529 if (NCR_READ_REG(sc, NCR_FFLAG) & NCRFIFO_FF)
530 flushcount=5;
531 NCR_WRITE_REG(sc, ESP_DCTL, ESPDCTL_16MHZ | ESPDCTL_INTENB | ESPDCTL_DMAMOD |
532 (esc->sc_datain ? ESPDCTL_DMARD : 0));
533
534 s = spldma();
535 while (ndmap == stat->nd_map && ndidx == stat->nd_idx &&
536 !(nd_bsr4 (DD_CSR) & 0x08000000) &&
537 ++flushcount < 5) {
538 splx(s);
539 NDTRACEIF (*ndtracep++ = 'F');
540 NCR_WRITE_REG(sc, ESP_DCTL, ESPDCTL_FLUSH |
541 ESPDCTL_16MHZ | ESPDCTL_INTENB | ESPDCTL_DMAMOD |
542 (esc->sc_datain ? ESPDCTL_DMARD : 0));
543 doze(0x32);
544 NCR_WRITE_REG(sc, ESP_DCTL,
545 ESPDCTL_16MHZ | ESPDCTL_INTENB | ESPDCTL_DMAMOD |
546 (esc->sc_datain ? ESPDCTL_DMARD : 0));
547 doze(0x32);
548 s = spldma();
549 }
550 NDTRACEIF (*ndtracep++ = '0' + flushcount);
551 if (flushcount > 4) {
552 int next;
553 int onext = 0;
554 splx(s);
555 DPRINTF (("DMA reset\n"));
556 while (((next = nd_bsr4 (DD_NEXT)) !=
557 (nd_bsr4 (DD_LIMIT) & 0x7FFFFFFF)) &&
558 onext != next) {
559 onext = next;
560 DELAY(50);
561 }
562 NDTRACEIF (*ndtracep++ = 'R');
563 NCR_WRITE_REG(sc, ESP_DCTL, ESPDCTL_16MHZ | ESPDCTL_INTENB);
564 NDTRACEIF (
565 sprintf (ndtracep, "ff:%d tcm:%d tcl:%d ",
566 NCR_READ_REG(sc, NCR_FFLAG) & NCRFIFO_FF,
567 NCR_READ_REG((sc), NCR_TCM), NCR_READ_REG((sc), NCR_TCL));
568 ndtracep += strlen (ndtracep);
569 );
570 s = spldma();
571 nextdma_reset (nsc);
572 splx(s);
573 goto out;
574 }
575 splx(s);
576
577 #ifdef DIAGNOSTIC
578 if (flushcount > 4) {
579 NDTRACEIF (*ndtracep++ = '+');
580 printf("%s: unexpected flushcount %d on %s\n",sc->sc_dev.dv_xname,
581 flushcount, esc->sc_datain ? "read" : "write");
582 }
583 #endif
584
585 if (!nextdma_finished(nsc)) { /* esp_dma_isactive(sc)) { */
586 NDTRACEIF (*ndtracep++ = '1');
587 }
588 flushcount = 0;
589 s = spldma();
590 ndmap = stat->nd_map;
591 ndidx = stat->nd_idx;
592 splx(s);
593
594 }
595 out: ;
596
597 #ifdef ESP_DEBUG
598 /* esp_dma_nest--; */
599 #endif
600
601 }
602
603 doze (0x32);
604 NCR_WRITE_REG(sc, ESP_DCTL, ESPDCTL_16MHZ | ESPDCTL_INTENB | (esc->sc_datain ? ESPDCTL_DMARD : 0));
605 NDTRACEIF (*ndtracep++ = 'b');
606
607 while (esc->sc_datain != -1) DELAY(50);
608
609 if (esc->sc_dmaaddr) {
610 bus_size_t xfer_len = 0;
611 int resid;
612
613 NCR_WRITE_REG(sc, ESP_DCTL, ESPDCTL_16MHZ | ESPDCTL_INTENB);
614 if (stat->nd_exception == 0) {
615 resid = NCR_READ_REG((sc), NCR_TCL) + (NCR_READ_REG((sc), NCR_TCM) << 8);
616 if (resid) {
617 resid += (NCR_READ_REG(sc, NCR_FFLAG) & NCRFIFO_FF);
618 #ifdef ESP_DEBUG
619 if (NCR_READ_REG(sc, NCR_FFLAG) & NCRFIFO_FF)
620 if ((NCR_READ_REG(sc, NCR_FFLAG) & NCRFIFO_FF) != 16 || NCR_READ_REG((sc), NCR_TCL) != 240)
621 ndtraceshow++;
622 #endif
623 }
624 xfer_len = esc->sc_dmasize - resid;
625 } else {
626 /*static*/ void ncr53c9x_abort(struct ncr53c9x_softc *, struct ncr53c9x_ecb *);
627 #define ncr53c9x_sched_msgout(m) \
628 do { \
629 NCR_MISC(("ncr53c9x_sched_msgout %x %d", m, __LINE__)); \
630 NCRCMD(sc, NCRCMD_SETATN); \
631 sc->sc_flags |= NCR_ATN; \
632 sc->sc_msgpriq |= (m); \
633 } while (0)
634 int i;
635 xfer_len = 0;
636 if (esc->sc_begin)
637 xfer_len += esc->sc_begin_size;
638 if (esc->sc_main_dmamap)
639 xfer_len += esc->sc_main_dmamap->dm_xfer_len;
640 if (esc->sc_tail_dmamap)
641 xfer_len += esc->sc_tail_dmamap->dm_xfer_len;
642 resid = 0;
643 printf ("X\n");
644 for (i = 0; i < 16; i++) {
645 NCR_WRITE_REG(sc, ESP_DCTL, ESPDCTL_FLUSH |
646 ESPDCTL_16MHZ | ESPDCTL_INTENB |
647 (esc->sc_datain ? ESPDCTL_DMARD : 0));
648 NCR_WRITE_REG(sc, ESP_DCTL,
649 ESPDCTL_16MHZ | ESPDCTL_INTENB |
650 (esc->sc_datain ? ESPDCTL_DMARD : 0));
651 }
652 #if 0
653 printf ("ff:%02x tcm:%d tcl:%d esp_dstat:%02x stat:%02x step: %02x intr:%02x new stat:%02X\n",
654 NCR_READ_REG(sc, NCR_FFLAG),
655 NCR_READ_REG((sc), NCR_TCM), NCR_READ_REG((sc), NCR_TCL),
656 NCR_READ_REG(sc, ESP_DSTAT),
657 sc->sc_espstat, sc->sc_espstep,
658 sc->sc_espintr, NCR_READ_REG(sc, NCR_STAT));
659 printf ("sc->sc_state: %x sc->sc_phase: %x sc->sc_espstep:%x sc->sc_prevphase:%x sc->sc_flags:%x\n",
660 sc->sc_state, sc->sc_phase, sc->sc_espstep, sc->sc_prevphase, sc->sc_flags);
661 #endif
662 /* sc->sc_flags &= ~NCR_ICCS; */
663 sc->sc_nexus->flags |= ECB_ABORT;
664 if (sc->sc_phase == MESSAGE_IN_PHASE) {
665 /* ncr53c9x_sched_msgout(SEND_ABORT); */
666 ncr53c9x_abort(sc, sc->sc_nexus);
667 } else if (sc->sc_phase != STATUS_PHASE) {
668 printf ("ATTENTION!!! not message/status phase: %d\n", sc->sc_phase);
669 }
670 }
671
672 NDTRACEIF (
673 sprintf (ndtracep, "f%dm%dl%ds%dx%dr%dS", NCR_READ_REG(sc, NCR_FFLAG) & NCRFIFO_FF, NCR_READ_REG((sc), NCR_TCM),
674 NCR_READ_REG((sc), NCR_TCL), esc->sc_dmasize, (int)xfer_len, resid);
675 ndtracep += strlen (ndtracep);
676 );
677
678 *(esc->sc_dmaaddr) += xfer_len;
679 *(esc->sc_dmalen) -= xfer_len;
680 esc->sc_dmaaddr = 0;
681 esc->sc_dmalen = 0;
682 esc->sc_dmasize = 0;
683 }
684
685 NDTRACEIF (*ndtracep++ = 'B');
686 sc->sc_espstat = NCR_READ_REG(sc, NCR_STAT) | (sc->sc_espstat & NCRSTAT_INT);
687
688 DPRINTF(("esp dctl is 0x%02x\n",NCR_READ_REG(sc,ESP_DCTL)));
689 /* printf ("esp_dma_isintr DONE\n"); */
690
691 }
692
693 return (r);
694 }
695
696 void
697 esp_dma_reset(sc)
698 struct ncr53c9x_softc *sc;
699 {
700 struct esp_softc *esc = (struct esp_softc *)sc;
701
702 DPRINTF(("esp DMA reset\n"));
703
704 #ifdef ESP_DEBUG
705 if (esp_debug) {
706 char sbuf[256];
707
708 bitmask_snprintf((*(volatile u_long *)IIOV(NEXT_P_INTRSTAT)),
709 NEXT_INTR_BITS, sbuf, sizeof(sbuf));
710 printf(" *intrstat = 0x%s\n", sbuf);
711
712 bitmask_snprintf((*(volatile u_long *)IIOV(NEXT_P_INTRMASK)),
713 NEXT_INTR_BITS, sbuf, sizeof(sbuf));
714 printf(" *intrmask = 0x%s\n", sbuf);
715 }
716 #endif
717
718 #if 0
719 /* Clear the DMAMOD bit in the DCTL register: */
720 NCR_WRITE_REG(sc, ESP_DCTL,
721 ESPDCTL_16MHZ | ESPDCTL_INTENB);
722 DPRINTF(("esp dctl is 0x%02x\n",NCR_READ_REG(sc,ESP_DCTL)));
723 #endif
724
725 nextdma_reset(esc->sc_dma);
726 nextdma_init(esc->sc_dma);
727
728 esc->sc_datain = -1;
729 esc->sc_dmaaddr = 0;
730 esc->sc_dmalen = 0;
731 esc->sc_dmasize = 0;
732
733 esc->sc_loaded = 0;
734
735 esc->sc_begin = 0;
736 esc->sc_begin_size = 0;
737
738 if (esc->sc_main_dmamap->dm_mapsize) {
739 bus_dmamap_unload(esc->sc_dma->sc_dmat, esc->sc_main_dmamap);
740 }
741 esc->sc_main = 0;
742 esc->sc_main_size = 0;
743
744 if (esc->sc_tail_dmamap->dm_mapsize) {
745 bus_dmamap_unload(esc->sc_dma->sc_dmat, esc->sc_tail_dmamap);
746 }
747 esc->sc_tail = 0;
748 esc->sc_tail_size = 0;
749 }
750
751 /* it appears that:
752 * addr and len arguments to this need to be kept up to date
753 * with the status of the transfter.
754 * the dmasize of this is the actual length of the transfer
755 * request, which is guaranteed to be less than maxxfer.
756 * (len may be > maxxfer)
757 */
758
759 int
760 esp_dma_setup(sc, addr, len, datain, dmasize)
761 struct ncr53c9x_softc *sc;
762 caddr_t *addr;
763 size_t *len;
764 int datain;
765 size_t *dmasize;
766 {
767 struct esp_softc *esc = (struct esp_softc *)sc;
768
769 NDTRACEIF (*ndtracep++ = 'h');
770 #ifdef DIAGNOSTIC
771 #ifdef ESP_DEBUG
772 /* if this is a read DMA, pre-fill the buffer with 0xdeadbeef
773 * to identify bogus reads
774 */
775 if (datain) {
776 int *v = (int *)(*addr);
777 int i;
778 for(i=0;i<((*len)/4);i++) v[i] = 0xdeadbeef;
779 v = (int *)(&(esc->sc_tailbuf[0]));
780 for(i=0;i<((sizeof(esc->sc_tailbuf)/4));i++) v[i] = 0xdeafbeef;
781 } else {
782 int *v;
783 int i;
784 v = (int *)(&(esc->sc_tailbuf[0]));
785 for(i=0;i<((sizeof(esc->sc_tailbuf)/4));i++) v[i] = 0xfeeb1eed;
786 }
787 #endif
788 #endif
789
790 DPRINTF(("esp_dma_setup(%p,0x%08x,0x%08x)\n",*addr,*len,*dmasize));
791
792 #if 0
793 #ifdef DIAGNOSTIC /* @@@ this is ok sometimes. verify that we handle it ok
794 * and then remove this check
795 */
796 if (*len != *dmasize) {
797 panic("esp dmalen 0x%lx != size 0x%lx",*len,*dmasize);
798 }
799 #endif
800 #endif
801
802 #ifdef DIAGNOSTIC
803 if ((esc->sc_datain != -1) ||
804 (esc->sc_main_dmamap->dm_mapsize != 0) ||
805 (esc->sc_tail_dmamap->dm_mapsize != 0) ||
806 (esc->sc_dmasize != 0)) {
807 panic("%s: map already loaded in esp_dma_setup"
808 "\tdatain = %d\n\tmain_mapsize=%ld\n\tail_mapsize=%ld\n\tdmasize = %d",
809 sc->sc_dev.dv_xname, esc->sc_datain,
810 esc->sc_main_dmamap->dm_mapsize,
811 esc->sc_tail_dmamap->dm_mapsize,
812 esc->sc_dmasize);
813 }
814 #endif
815
816 /* we are sometimes asked to DMA zero bytes, that's easy */
817 if (*dmasize <= 0) {
818 return(0);
819 }
820
821 if (*dmasize > ESP_MAX_DMASIZE)
822 *dmasize = ESP_MAX_DMASIZE;
823
824 /* Save these in case we have to abort DMA */
825 esc->sc_datain = datain;
826 esc->sc_dmaaddr = addr;
827 esc->sc_dmalen = len;
828 esc->sc_dmasize = *dmasize;
829
830 esc->sc_loaded = 0;
831
832 #define DMA_SCSI_ALIGNMENT 16
833 #define DMA_SCSI_ALIGN(type, addr) \
834 ((type)(((unsigned)(addr)+DMA_SCSI_ALIGNMENT-1) \
835 &~(DMA_SCSI_ALIGNMENT-1)))
836 #define DMA_SCSI_ALIGNED(addr) \
837 (((unsigned)(addr)&(DMA_SCSI_ALIGNMENT-1))==0)
838
839 {
840 size_t slop_bgn_size; /* # bytes to be fifo'd at beginning */
841 size_t slop_end_size; /* # bytes to be transferred in tail buffer */
842
843 {
844 u_long bgn = (u_long)(*esc->sc_dmaaddr);
845 u_long end = (u_long)(*esc->sc_dmaaddr+esc->sc_dmasize);
846
847 slop_bgn_size = DMA_SCSI_ALIGNMENT-(bgn % DMA_SCSI_ALIGNMENT);
848 if (slop_bgn_size == DMA_SCSI_ALIGNMENT) slop_bgn_size = 0;
849 slop_end_size = (end % DMA_ENDALIGNMENT);
850 }
851
852 /* Force a minimum slop end size. This ensures that write
853 * requests will overrun, as required to get completion interrupts.
854 * In addition, since the tail buffer is guaranteed to be mapped
855 * in a single DMA segment, the overrun won't accidentally
856 * end up in its own segment.
857 */
858 if (!esc->sc_datain) {
859 #if 0
860 slop_end_size += ESP_DMA_MAXTAIL;
861 #else
862 slop_end_size += 0x10;
863 #endif
864 }
865
866 /* Check to make sure we haven't counted extra slop
867 * as would happen for a very short DMA buffer, also
868 * for short buffers, just stuff the entire thing in the tail
869 */
870 if ((slop_bgn_size+slop_end_size >= esc->sc_dmasize)
871 #if 0
872 || (esc->sc_dmasize <= ESP_DMA_MAXTAIL)
873 #endif
874 )
875 {
876 slop_bgn_size = 0;
877 slop_end_size = esc->sc_dmasize;
878 }
879
880 /* initialize the fifo buffer */
881 if (slop_bgn_size) {
882 esc->sc_begin = *esc->sc_dmaaddr;
883 esc->sc_begin_size = slop_bgn_size;
884 } else {
885 esc->sc_begin = 0;
886 esc->sc_begin_size = 0;
887 }
888
889 #if 01
890 /* Load the normal DMA map */
891 {
892 esc->sc_main = *esc->sc_dmaaddr+slop_bgn_size;
893 esc->sc_main_size = (esc->sc_dmasize)-(slop_end_size+slop_bgn_size);
894
895 if (esc->sc_main_size) {
896 int error;
897
898 if (!esc->sc_datain || DMA_ENDALIGNED(esc->sc_main_size + slop_end_size)) {
899 KASSERT(DMA_SCSI_ALIGNMENT == DMA_ENDALIGNMENT);
900 KASSERT(DMA_BEGINALIGNMENT == DMA_ENDALIGNMENT);
901 esc->sc_main_size += slop_end_size;
902 slop_end_size = 0;
903 if (!esc->sc_datain) {
904 esc->sc_main_size = DMA_ENDALIGN(caddr_t,esc->sc_main+esc->sc_main_size)-esc->sc_main;
905 }
906 }
907
908 error = bus_dmamap_load(esc->sc_dma->sc_dmat,
909 esc->sc_main_dmamap,
910 esc->sc_main, esc->sc_main_size,
911 NULL, BUS_DMA_NOWAIT);
912 if (error) {
913 #ifdef ESP_DEBUG
914 printf("%s: esc->sc_main_dmamap->_dm_size = %ld\n",
915 sc->sc_dev.dv_xname,esc->sc_main_dmamap->_dm_size);
916 printf("%s: esc->sc_main_dmamap->_dm_segcnt = %d\n",
917 sc->sc_dev.dv_xname,esc->sc_main_dmamap->_dm_segcnt);
918 printf("%s: esc->sc_main_dmamap->_dm_maxsegsz = %ld\n",
919 sc->sc_dev.dv_xname,esc->sc_main_dmamap->_dm_maxsegsz);
920 printf("%s: esc->sc_main_dmamap->_dm_boundary = %ld\n",
921 sc->sc_dev.dv_xname,esc->sc_main_dmamap->_dm_boundary);
922 esp_dma_print(sc);
923 #endif
924 panic("%s: can't load main DMA map. error = %d, addr=%p, size=0x%08x",
925 sc->sc_dev.dv_xname, error,esc->sc_main,esc->sc_main_size);
926 }
927 if (!esc->sc_datain) { /* patch the DMA map for write overrun */
928 esc->sc_main_dmamap->dm_mapsize += ESP_DMA_OVERRUN;
929 esc->sc_main_dmamap->dm_segs[esc->sc_main_dmamap->dm_nsegs - 1].ds_len +=
930 ESP_DMA_OVERRUN;
931 }
932 #if 0
933 bus_dmamap_sync(esc->sc_dma->sc_dmat, esc->sc_main_dmamap,
934 0, esc->sc_main_dmamap->dm_mapsize,
935 (esc->sc_datain ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE));
936 esc->sc_main_dmamap->dm_xfer_len = 0;
937 #endif
938 } else {
939 esc->sc_main = 0;
940 }
941 }
942
943 /* Load the tail DMA map */
944 if (slop_end_size) {
945 esc->sc_tail = DMA_ENDALIGN(caddr_t,esc->sc_tailbuf+slop_end_size)-slop_end_size;
946 /* If the beginning of the tail is not correctly aligned,
947 * we have no choice but to align the start, which might then unalign the end.
948 */
949 esc->sc_tail = DMA_SCSI_ALIGN(caddr_t,esc->sc_tail);
950 /* So therefore, we change the tail size to be end aligned again. */
951 esc->sc_tail_size = DMA_ENDALIGN(caddr_t,esc->sc_tail+slop_end_size)-esc->sc_tail;
952
953 /* @@@ next DMA overrun lossage */
954 if (!esc->sc_datain) {
955 esc->sc_tail_size += ESP_DMA_OVERRUN;
956 }
957
958 {
959 int error;
960 error = bus_dmamap_load(esc->sc_dma->sc_dmat,
961 esc->sc_tail_dmamap,
962 esc->sc_tail, esc->sc_tail_size,
963 NULL, BUS_DMA_NOWAIT);
964 if (error) {
965 panic("%s: can't load tail DMA map. error = %d, addr=%p, size=0x%08x",
966 sc->sc_dev.dv_xname, error,esc->sc_tail,esc->sc_tail_size);
967 }
968 #if 0
969 bus_dmamap_sync(esc->sc_dma->sc_dmat, esc->sc_tail_dmamap,
970 0, esc->sc_tail_dmamap->dm_mapsize,
971 (esc->sc_datain ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE));
972 esc->sc_tail_dmamap->dm_xfer_len = 0;
973 #endif
974 }
975 }
976 #else
977
978 esc->sc_begin = *esc->sc_dmaaddr;
979 slop_bgn_size = DMA_SCSI_ALIGNMENT-((ulong)esc->sc_begin % DMA_SCSI_ALIGNMENT);
980 if (slop_bgn_size == DMA_SCSI_ALIGNMENT) slop_bgn_size = 0;
981 slop_end_size = esc->sc_dmasize - slop_bgn_size;
982
983 if (slop_bgn_size < esc->sc_dmasize) {
984 int error;
985
986 esc->sc_tail = 0;
987 esc->sc_tail_size = 0;
988
989 esc->sc_begin_size = slop_bgn_size;
990 esc->sc_main = *esc->sc_dmaaddr+slop_bgn_size;
991 esc->sc_main_size = DMA_ENDALIGN(caddr_t,esc->sc_main+esc->sc_dmasize-slop_bgn_size)-esc->sc_main;
992
993 if (!esc->sc_datain) {
994 esc->sc_main_size += ESP_DMA_OVERRUN;
995 }
996 error = bus_dmamap_load(esc->sc_dma->sc_dmat,
997 esc->sc_main_dmamap,
998 esc->sc_main, esc->sc_main_size,
999 NULL, BUS_DMA_NOWAIT);
1000 if (error) {
1001 panic("%s: can't load main DMA map. error = %d, addr=%p, size=0x%08x",
1002 sc->sc_dev.dv_xname, error,esc->sc_main,esc->sc_main_size);
1003 }
1004 } else {
1005 esc->sc_begin = 0;
1006 esc->sc_begin_size = 0;
1007 esc->sc_main = 0;
1008 esc->sc_main_size = 0;
1009
1010 #if 0
1011 esc->sc_tail = DMA_ENDALIGN(caddr_t,esc->sc_tailbuf+slop_bgn_size)-slop_bgn_size;
1012 /* If the beginning of the tail is not correctly aligned,
1013 * we have no choice but to align the start, which might then unalign the end.
1014 */
1015 #endif
1016 esc->sc_tail = DMA_SCSI_ALIGN(caddr_t,esc->sc_tailbuf);
1017 /* So therefore, we change the tail size to be end aligned again. */
1018 esc->sc_tail_size = DMA_ENDALIGN(caddr_t,esc->sc_tail+esc->sc_dmasize)-esc->sc_tail;
1019
1020 /* @@@ next DMA overrun lossage */
1021 if (!esc->sc_datain) {
1022 esc->sc_tail_size += ESP_DMA_OVERRUN;
1023 }
1024
1025 {
1026 int error;
1027 error = bus_dmamap_load(esc->sc_dma->sc_dmat,
1028 esc->sc_tail_dmamap,
1029 esc->sc_tail, esc->sc_tail_size,
1030 NULL, BUS_DMA_NOWAIT);
1031 if (error) {
1032 panic("%s: can't load tail DMA map. error = %d, addr=%p, size=0x%08x",
1033 sc->sc_dev.dv_xname, error,esc->sc_tail,esc->sc_tail_size);
1034 }
1035 }
1036 }
1037 #endif
1038
1039 DPRINTF(("%s: setup: %8p %d %8p %d %8p %d %8p %d\n", sc->sc_dev.dv_xname,
1040 *esc->sc_dmaaddr, esc->sc_dmasize, esc->sc_begin,
1041 esc->sc_begin_size, esc->sc_main, esc->sc_main_size, esc->sc_tail,
1042 esc->sc_tail_size));
1043 }
1044
1045 return (0);
1046 }
1047
1048 #ifdef ESP_DEBUG
1049 /* For debugging */
1050 void
1051 esp_dma_store(sc)
1052 struct ncr53c9x_softc *sc;
1053 {
1054 struct esp_softc *esc = (struct esp_softc *)sc;
1055 char *p = &esp_dma_dump[0];
1056
1057 p += sprintf(p,"%s: sc_datain=%d\n",sc->sc_dev.dv_xname,esc->sc_datain);
1058 p += sprintf(p,"%s: sc_loaded=0x%08x\n",sc->sc_dev.dv_xname,esc->sc_loaded);
1059
1060 if (esc->sc_dmaaddr) {
1061 p += sprintf(p,"%s: sc_dmaaddr=%p\n",sc->sc_dev.dv_xname,*esc->sc_dmaaddr);
1062 } else {
1063 p += sprintf(p,"%s: sc_dmaaddr=NULL\n",sc->sc_dev.dv_xname);
1064 }
1065 if (esc->sc_dmalen) {
1066 p += sprintf(p,"%s: sc_dmalen=0x%08x\n",sc->sc_dev.dv_xname,*esc->sc_dmalen);
1067 } else {
1068 p += sprintf(p,"%s: sc_dmalen=NULL\n",sc->sc_dev.dv_xname);
1069 }
1070 p += sprintf(p,"%s: sc_dmasize=0x%08x\n",sc->sc_dev.dv_xname,esc->sc_dmasize);
1071
1072 p += sprintf(p,"%s: sc_begin = %p, sc_begin_size = 0x%08x\n",
1073 sc->sc_dev.dv_xname, esc->sc_begin, esc->sc_begin_size);
1074 p += sprintf(p,"%s: sc_main = %p, sc_main_size = 0x%08x\n",
1075 sc->sc_dev.dv_xname, esc->sc_main, esc->sc_main_size);
1076 /* if (esc->sc_main) */ {
1077 int i;
1078 bus_dmamap_t map = esc->sc_main_dmamap;
1079 p += sprintf(p,"%s: sc_main_dmamap. mapsize = 0x%08lx, nsegs = %d\n",
1080 sc->sc_dev.dv_xname, map->dm_mapsize, map->dm_nsegs);
1081 for(i=0;i<map->dm_nsegs;i++) {
1082 p += sprintf(p,"%s: map->dm_segs[%d].ds_addr = 0x%08lx, len = 0x%08lx\n",
1083 sc->sc_dev.dv_xname, i, map->dm_segs[i].ds_addr, map->dm_segs[i].ds_len);
1084 }
1085 }
1086 p += sprintf(p,"%s: sc_tail = %p, sc_tail_size = 0x%08x\n",
1087 sc->sc_dev.dv_xname, esc->sc_tail, esc->sc_tail_size);
1088 /* if (esc->sc_tail) */ {
1089 int i;
1090 bus_dmamap_t map = esc->sc_tail_dmamap;
1091 p += sprintf(p,"%s: sc_tail_dmamap. mapsize = 0x%08lx, nsegs = %d\n",
1092 sc->sc_dev.dv_xname, map->dm_mapsize, map->dm_nsegs);
1093 for(i=0;i<map->dm_nsegs;i++) {
1094 p += sprintf(p,"%s: map->dm_segs[%d].ds_addr = 0x%08lx, len = 0x%08lx\n",
1095 sc->sc_dev.dv_xname, i, map->dm_segs[i].ds_addr, map->dm_segs[i].ds_len);
1096 }
1097 }
1098 }
1099
1100 void
1101 esp_dma_print(sc)
1102 struct ncr53c9x_softc *sc;
1103 {
1104 esp_dma_store(sc);
1105 printf("%s",esp_dma_dump);
1106 }
1107 #endif
1108
1109 void
1110 esp_dma_go(sc)
1111 struct ncr53c9x_softc *sc;
1112 {
1113 struct esp_softc *esc = (struct esp_softc *)sc;
1114 struct nextdma_softc *nsc = esc->sc_dma;
1115 struct nextdma_status *stat = &nsc->sc_stat;
1116 /* int s = spldma(); */
1117
1118 #ifdef ESP_DEBUG
1119 if (ndtracep != ndtrace) {
1120 if (ndtraceshow) {
1121 *ndtracep = '\0';
1122 printf ("esp ndtrace: %s\n", ndtrace);
1123 ndtraceshow = 0;
1124 } else {
1125 DPRINTF (("X"));
1126 }
1127 ndtracep = ndtrace;
1128 }
1129 #endif
1130
1131 DPRINTF(("%s: esp_dma_go(datain = %d)\n",
1132 sc->sc_dev.dv_xname, esc->sc_datain));
1133
1134 #ifdef ESP_DEBUG
1135 if (esp_debug) esp_dma_print(sc);
1136 else esp_dma_store(sc);
1137 #endif
1138
1139 #ifdef ESP_DEBUG
1140 {
1141 int n = NCR_READ_REG(sc, NCR_FFLAG);
1142 DPRINTF(("%s: fifo size = %d, seq = 0x%x\n",
1143 sc->sc_dev.dv_xname,
1144 n & NCRFIFO_FF, (n & NCRFIFO_SS)>>5));
1145 }
1146 #endif
1147
1148 /* zero length DMA transfers are boring */
1149 if (esc->sc_dmasize == 0) {
1150 /* splx(s); */
1151 return;
1152 }
1153
1154 #if defined(DIAGNOSTIC)
1155 if ((esc->sc_begin_size == 0) &&
1156 (esc->sc_main_dmamap->dm_mapsize == 0) &&
1157 (esc->sc_tail_dmamap->dm_mapsize == 0)) {
1158 #ifdef ESP_DEBUG
1159 esp_dma_print(sc);
1160 #endif
1161 panic("%s: No DMA requested!",sc->sc_dev.dv_xname);
1162 }
1163 #endif
1164
1165 /* Stuff the fifo with the begin buffer */
1166 if (esc->sc_datain) {
1167 int i;
1168 DPRINTF(("%s: FIFO read of %d bytes:",
1169 sc->sc_dev.dv_xname,esc->sc_begin_size));
1170 for(i=0;i<esc->sc_begin_size;i++) {
1171 esc->sc_begin[i]=NCR_READ_REG(sc, NCR_FIFO);
1172 DPRINTF((" %02x",esc->sc_begin[i]&0xff));
1173 }
1174 DPRINTF(("\n"));
1175 } else {
1176 int i;
1177 DPRINTF(("%s: FIFO write of %d bytes:",
1178 sc->sc_dev.dv_xname,esc->sc_begin_size));
1179 for(i=0;i<esc->sc_begin_size;i++) {
1180 NCR_WRITE_REG(sc, NCR_FIFO, esc->sc_begin[i]);
1181 DPRINTF((" %02x",esc->sc_begin[i]&0xff));
1182 }
1183 DPRINTF(("\n"));
1184 }
1185
1186 if (esc->sc_main_dmamap->dm_mapsize) {
1187 bus_dmamap_sync(esc->sc_dma->sc_dmat, esc->sc_main_dmamap,
1188 0, esc->sc_main_dmamap->dm_mapsize,
1189 (esc->sc_datain ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE));
1190 esc->sc_main_dmamap->dm_xfer_len = 0;
1191 }
1192
1193 if (esc->sc_tail_dmamap->dm_mapsize) {
1194 /* if we are a DMA write cycle, copy the end slop */
1195 if (!esc->sc_datain) {
1196 memcpy(esc->sc_tail, *esc->sc_dmaaddr+esc->sc_begin_size+esc->sc_main_size,
1197 esc->sc_dmasize-(esc->sc_begin_size+esc->sc_main_size));
1198 }
1199 bus_dmamap_sync(esc->sc_dma->sc_dmat, esc->sc_tail_dmamap,
1200 0, esc->sc_tail_dmamap->dm_mapsize,
1201 (esc->sc_datain ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE));
1202 esc->sc_tail_dmamap->dm_xfer_len = 0;
1203 }
1204
1205 stat->nd_exception = 0;
1206 nextdma_start(nsc, (esc->sc_datain ? DMACSR_SETREAD : DMACSR_SETWRITE));
1207
1208 if (esc->sc_datain) {
1209 NCR_WRITE_REG(sc, ESP_DCTL,
1210 ESPDCTL_16MHZ | ESPDCTL_INTENB | ESPDCTL_DMAMOD | ESPDCTL_DMARD);
1211 } else {
1212 NCR_WRITE_REG(sc, ESP_DCTL,
1213 ESPDCTL_16MHZ | ESPDCTL_INTENB | ESPDCTL_DMAMOD);
1214 }
1215 DPRINTF(("esp dctl is 0x%02x\n",NCR_READ_REG(sc,ESP_DCTL)));
1216
1217 NDTRACEIF (if (esc->sc_begin_size) { *ndtracep++ = '1'; *ndtracep++ = 'A' + esc->sc_begin_size; });
1218 NDTRACEIF (if (esc->sc_main_size) { *ndtracep++ = '2'; *ndtracep++ = '0' + esc->sc_main_dmamap->dm_nsegs; });
1219 NDTRACEIF (if (esc->sc_tail_size) { *ndtracep++ = '3'; *ndtracep++ = 'A' + esc->sc_tail_size; });
1220
1221 /* splx(s); */
1222 }
1223
1224 void
1225 esp_dma_stop(sc)
1226 struct ncr53c9x_softc *sc;
1227 {
1228 struct esp_softc *esc = (struct esp_softc *)sc;
1229 nextdma_print(esc->sc_dma);
1230 #ifdef ESP_DEBUG
1231 esp_dma_print(sc);
1232 #endif
1233 #if 1
1234 panic("%s: stop not yet implemented",sc->sc_dev.dv_xname);
1235 #endif
1236 }
1237
1238 int
1239 esp_dma_isactive(sc)
1240 struct ncr53c9x_softc *sc;
1241 {
1242 struct esp_softc *esc = (struct esp_softc *)sc;
1243 int r = (esc->sc_dmaaddr != NULL); /* !nextdma_finished(esc->sc_dma); */
1244 DPRINTF(("esp_dma_isactive = %d\n",r));
1245 return(r);
1246 }
1247
1248 /****************************************************************/
1249
1250 int esp_dma_int __P((void *));
1251 int esp_dma_int(arg)
1252 void *arg;
1253 {
1254 void nextdma_rotate __P((struct nextdma_softc *));
1255 void nextdma_setup_curr_regs __P((struct nextdma_softc *));
1256 void nextdma_setup_cont_regs __P((struct nextdma_softc *));
1257
1258 struct ncr53c9x_softc *sc = (struct ncr53c9x_softc *)arg;
1259 struct esp_softc *esc = (struct esp_softc *)sc;
1260 struct nextdma_softc *nsc = esc->sc_dma;
1261 struct nextdma_status *stat = &nsc->sc_stat;
1262 unsigned int state;
1263
1264 NDTRACEIF (*ndtracep++ = 'E');
1265
1266 state = nd_bsr4 (DD_CSR);
1267
1268 #if 1
1269 NDTRACEIF (
1270 if (state & DMACSR_COMPLETE) *ndtracep++ = 'c';
1271 if (state & DMACSR_ENABLE) *ndtracep++ = 'e';
1272 if (state & DMACSR_BUSEXC) *ndtracep++ = 'b';
1273 if (state & DMACSR_READ) *ndtracep++ = 'r';
1274 if (state & DMACSR_SUPDATE) *ndtracep++ = 's';
1275 );
1276
1277 NDTRACEIF (*ndtracep++ = 'E');
1278
1279 #ifdef ESP_DEBUG
1280 if (0) if ((state & DMACSR_BUSEXC) && (state & DMACSR_ENABLE)) ndtraceshow++;
1281 if (0) if ((state & DMACSR_SUPDATE)) ndtraceshow++;
1282 #endif
1283 #endif
1284
1285 if ((stat->nd_exception == 0) && (state & DMACSR_COMPLETE) && (state & DMACSR_ENABLE)) {
1286 stat->nd_map->dm_xfer_len += stat->nd_map->dm_segs[stat->nd_idx].ds_len;
1287 }
1288
1289 if ((stat->nd_idx+1) == stat->nd_map->dm_nsegs) {
1290 if (nsc->sc_conf.nd_completed_cb)
1291 (*nsc->sc_conf.nd_completed_cb)(stat->nd_map, nsc->sc_conf.nd_cb_arg);
1292 }
1293 nextdma_rotate(nsc);
1294
1295 if ((state & DMACSR_COMPLETE) && (state & DMACSR_ENABLE)) {
1296 #if 0
1297 int l = nd_bsr4 (DD_LIMIT) & 0x7FFFFFFF;
1298 int s = nd_bsr4 (DD_STOP);
1299 #endif
1300 /* nextdma_setup_cont_regs(nsc); */
1301 if (stat->nd_map_cont) {
1302 nd_bsw4 (DD_START, stat->nd_map_cont->dm_segs[stat->nd_idx_cont].ds_addr);
1303 nd_bsw4 (DD_STOP, (stat->nd_map_cont->dm_segs[stat->nd_idx_cont].ds_addr +
1304 stat->nd_map_cont->dm_segs[stat->nd_idx_cont].ds_len));
1305 }
1306
1307 nd_bsw4 (DD_CSR, DMACSR_CLRCOMPLETE | (state & DMACSR_READ ? DMACSR_SETREAD : DMACSR_SETWRITE) |
1308 (stat->nd_map_cont ? DMACSR_SETSUPDATE : 0));
1309
1310 #if 0
1311 #ifdef ESP_DEBUG
1312 if (state & DMACSR_BUSEXC) {
1313 sprintf (ndtracep, "CE/BUSEXC: %08lX %08X %08X\n",
1314 (stat->nd_map->dm_segs[stat->nd_idx].ds_addr + stat->nd_map->dm_segs[stat->nd_idx].ds_len),
1315 l, s);
1316 ndtracep += strlen (ndtracep);
1317 }
1318 #endif
1319 #endif
1320 } else {
1321 #if 0
1322 if (state & DMACSR_BUSEXC) {
1323 while (nd_bsr4 (DD_NEXT) !=
1324 (nd_bsr4 (DD_LIMIT) & 0x7FFFFFFF))
1325 printf ("Y"); /* DELAY(50); */
1326 state = nd_bsr4 (DD_CSR);
1327 }
1328 #endif
1329
1330 if (!(state & DMACSR_SUPDATE)) {
1331 nextdma_rotate(nsc);
1332 } else {
1333 nd_bsw4 (DD_CSR, DMACSR_CLRCOMPLETE |
1334 DMACSR_INITBUF | DMACSR_RESET |
1335 (state & DMACSR_READ ? DMACSR_SETREAD : DMACSR_SETWRITE));
1336
1337 nd_bsw4 (DD_NEXT, stat->nd_map->dm_segs[stat->nd_idx].ds_addr);
1338 nd_bsw4 (DD_LIMIT,
1339 (stat->nd_map->dm_segs[stat->nd_idx].ds_addr +
1340 stat->nd_map->dm_segs[stat->nd_idx].ds_len) | 0/* x80000000 */);
1341 if (stat->nd_map_cont) {
1342 nd_bsw4 (DD_START,
1343 stat->nd_map_cont->dm_segs[stat->nd_idx_cont].ds_addr);
1344 nd_bsw4 (DD_STOP,
1345 (stat->nd_map_cont->dm_segs[stat->nd_idx_cont].ds_addr +
1346 stat->nd_map_cont->dm_segs[stat->nd_idx_cont].ds_len) | 0/* x80000000 */);
1347 }
1348 nd_bsw4 (DD_CSR, DMACSR_SETENABLE |
1349 DMACSR_CLRCOMPLETE | (state & DMACSR_READ ? DMACSR_SETREAD : DMACSR_SETWRITE) |
1350 (stat->nd_map_cont ? DMACSR_SETSUPDATE : 0));
1351 #if 1
1352 #ifdef ESP_DEBUG
1353 sprintf (ndtracep, "supdate ");
1354 ndtracep += strlen (ndtracep);
1355 sprintf (ndtracep, "%08X %08X %08X %08X ",
1356 nd_bsr4 (DD_NEXT),
1357 nd_bsr4 (DD_LIMIT) & 0x7FFFFFFF,
1358 nd_bsr4 (DD_START),
1359 nd_bsr4 (DD_STOP) & 0x7FFFFFFF);
1360 ndtracep += strlen (ndtracep);
1361 #endif
1362 #endif
1363 stat->nd_exception++;
1364 return(1);
1365 /* NCR_WRITE_REG(sc, ESP_DCTL, ctl); */
1366 goto restart;
1367 }
1368
1369 if (stat->nd_map) {
1370 #if 1
1371 #ifdef ESP_DEBUG
1372 sprintf (ndtracep, "%08X %08X %08X %08X ",
1373 nd_bsr4 (DD_NEXT),
1374 nd_bsr4 (DD_LIMIT) & 0x7FFFFFFF,
1375 nd_bsr4 (DD_START),
1376 nd_bsr4 (DD_STOP) & 0x7FFFFFFF);
1377 ndtracep += strlen (ndtracep);
1378 #endif
1379 #endif
1380
1381 #if 0
1382 nd_bsw4 (DD_CSR, DMACSR_CLRCOMPLETE | DMACSR_RESET);
1383
1384 nd_bsw4 (DD_CSR, 0);
1385 #endif
1386 #if 1
1387 /* 6/2 */
1388 nd_bsw4 (DD_CSR, DMACSR_CLRCOMPLETE |
1389 DMACSR_INITBUF | DMACSR_RESET |
1390 (state & DMACSR_READ ? DMACSR_SETREAD : DMACSR_SETWRITE));
1391
1392 /* nextdma_setup_curr_regs(nsc); */
1393 nd_bsw4 (DD_NEXT, stat->nd_map->dm_segs[stat->nd_idx].ds_addr);
1394 nd_bsw4 (DD_LIMIT,
1395 (stat->nd_map->dm_segs[stat->nd_idx].ds_addr +
1396 stat->nd_map->dm_segs[stat->nd_idx].ds_len) | 0/* x80000000 */);
1397 /* nextdma_setup_cont_regs(nsc); */
1398 if (stat->nd_map_cont) {
1399 nd_bsw4 (DD_START,
1400 stat->nd_map_cont->dm_segs[stat->nd_idx_cont].ds_addr);
1401 nd_bsw4 (DD_STOP,
1402 (stat->nd_map_cont->dm_segs[stat->nd_idx_cont].ds_addr +
1403 stat->nd_map_cont->dm_segs[stat->nd_idx_cont].ds_len) | 0/* x80000000 */);
1404 }
1405
1406 nd_bsw4 (DD_CSR,
1407 DMACSR_SETENABLE | (stat->nd_map_cont ? DMACSR_SETSUPDATE : 0) |
1408 (state & DMACSR_READ ? DMACSR_SETREAD : DMACSR_SETWRITE));
1409 #ifdef ESP_DEBUG
1410 /* ndtraceshow++; */
1411 #endif
1412 stat->nd_exception++;
1413 return(1);
1414 #endif
1415 /* NCR_WRITE_REG(sc, ESP_DCTL, ctl); */
1416 goto restart;
1417 restart:
1418 #if 1
1419 #ifdef ESP_DEBUG
1420 sprintf (ndtracep, "restart %08lX %08lX\n",
1421 stat->nd_map->dm_segs[stat->nd_idx].ds_addr,
1422 stat->nd_map->dm_segs[stat->nd_idx].ds_addr +
1423 stat->nd_map->dm_segs[stat->nd_idx].ds_len);
1424 if (stat->nd_map_cont) {
1425 sprintf (ndtracep + strlen(ndtracep) - 1, " %08lX %08lX\n",
1426 stat->nd_map_cont->dm_segs[stat->nd_idx_cont].ds_addr,
1427 stat->nd_map_cont->dm_segs[stat->nd_idx_cont].ds_addr +
1428 stat->nd_map_cont->dm_segs[stat->nd_idx_cont].ds_len);
1429 }
1430 ndtracep += strlen (ndtracep);
1431 #endif
1432 #endif
1433 nextdma_print(nsc);
1434 NCR_WRITE_REG(sc, ESP_DCTL, ESPDCTL_16MHZ | ESPDCTL_INTENB);
1435 printf ("ff:%02x tcm:%d tcl:%d esp_dstat:%02x state:%02x step: %02x intr:%02x state:%08X\n",
1436 NCR_READ_REG(sc, NCR_FFLAG),
1437 NCR_READ_REG((sc), NCR_TCM), NCR_READ_REG((sc), NCR_TCL),
1438 NCR_READ_REG(sc, ESP_DSTAT),
1439 NCR_READ_REG(sc, NCR_STAT), NCR_READ_REG(sc, NCR_STEP),
1440 NCR_READ_REG(sc, NCR_INTR), state);
1441 #ifdef ESP_DEBUG
1442 *ndtracep = '\0';
1443 printf ("ndtrace: %s\n", ndtrace);
1444 #endif
1445 panic("%s: busexc/supdate occured. Please email this output to chris (at) pin.lu.",
1446 sc->sc_dev.dv_xname);
1447 #ifdef ESP_DEBUG
1448 ndtraceshow++;
1449 #endif
1450 } else {
1451 nd_bsw4 (DD_CSR, DMACSR_CLRCOMPLETE | DMACSR_RESET);
1452 if (nsc->sc_conf.nd_shutdown_cb)
1453 (*nsc->sc_conf.nd_shutdown_cb)(nsc->sc_conf.nd_cb_arg);
1454 }
1455 }
1456 return (1);
1457 }
1458
1459 /* Internal DMA callback routines */
1460 bus_dmamap_t
1461 esp_dmacb_continue(arg)
1462 void *arg;
1463 {
1464 struct ncr53c9x_softc *sc = (struct ncr53c9x_softc *)arg;
1465 struct esp_softc *esc = (struct esp_softc *)sc;
1466
1467 NDTRACEIF (*ndtracep++ = 'x');
1468 DPRINTF(("%s: DMA continue\n",sc->sc_dev.dv_xname));
1469
1470 #ifdef DIAGNOSTIC
1471 if ((esc->sc_datain < 0) || (esc->sc_datain > 1)) {
1472 panic("%s: map not loaded in DMA continue callback, datain = %d",
1473 sc->sc_dev.dv_xname,esc->sc_datain);
1474 }
1475 #endif
1476
1477 if ((!(esc->sc_loaded & ESP_LOADED_MAIN)) &&
1478 (esc->sc_main_dmamap->dm_mapsize)) {
1479 DPRINTF(("%s: Loading main map\n",sc->sc_dev.dv_xname));
1480 #if 0
1481 bus_dmamap_sync(esc->sc_dma->sc_dmat, esc->sc_main_dmamap,
1482 0, esc->sc_main_dmamap->dm_mapsize,
1483 (esc->sc_datain ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE));
1484 esc->sc_main_dmamap->dm_xfer_len = 0;
1485 #endif
1486 esc->sc_loaded |= ESP_LOADED_MAIN;
1487 return(esc->sc_main_dmamap);
1488 }
1489
1490 if ((!(esc->sc_loaded & ESP_LOADED_TAIL)) &&
1491 (esc->sc_tail_dmamap->dm_mapsize)) {
1492 DPRINTF(("%s: Loading tail map\n",sc->sc_dev.dv_xname));
1493 #if 0
1494 bus_dmamap_sync(esc->sc_dma->sc_dmat, esc->sc_tail_dmamap,
1495 0, esc->sc_tail_dmamap->dm_mapsize,
1496 (esc->sc_datain ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE));
1497 esc->sc_tail_dmamap->dm_xfer_len = 0;
1498 #endif
1499 esc->sc_loaded |= ESP_LOADED_TAIL;
1500 return(esc->sc_tail_dmamap);
1501 }
1502
1503 DPRINTF(("%s: not loading map\n",sc->sc_dev.dv_xname));
1504 return(0);
1505 }
1506
1507
1508 void
1509 esp_dmacb_completed(map, arg)
1510 bus_dmamap_t map;
1511 void *arg;
1512 {
1513 struct ncr53c9x_softc *sc = (struct ncr53c9x_softc *)arg;
1514 struct esp_softc *esc = (struct esp_softc *)sc;
1515
1516 NDTRACEIF (*ndtracep++ = 'X');
1517 DPRINTF(("%s: DMA completed\n",sc->sc_dev.dv_xname));
1518
1519 #ifdef DIAGNOSTIC
1520 if ((esc->sc_datain < 0) || (esc->sc_datain > 1)) {
1521 panic("%s: invalid DMA direction in completed callback, datain = %d",
1522 sc->sc_dev.dv_xname,esc->sc_datain);
1523 }
1524 #endif
1525
1526 #if defined(DIAGNOSTIC) && 0
1527 {
1528 int i;
1529 for(i=0;i<map->dm_nsegs;i++) {
1530 if (map->dm_xfer_len != map->dm_mapsize) {
1531 printf("%s: map->dm_mapsize = %d\n", sc->sc_dev.dv_xname,map->dm_mapsize);
1532 printf("%s: map->dm_nsegs = %d\n", sc->sc_dev.dv_xname,map->dm_nsegs);
1533 printf("%s: map->dm_xfer_len = %d\n", sc->sc_dev.dv_xname,map->dm_xfer_len);
1534 for(i=0;i<map->dm_nsegs;i++) {
1535 printf("%s: map->dm_segs[%d].ds_addr = 0x%08lx\n",
1536 sc->sc_dev.dv_xname,i,map->dm_segs[i].ds_addr);
1537 printf("%s: map->dm_segs[%d].ds_len = %d\n",
1538 sc->sc_dev.dv_xname,i,map->dm_segs[i].ds_len);
1539 }
1540 panic("%s: incomplete DMA transfer",sc->sc_dev.dv_xname);
1541 }
1542 }
1543 }
1544 #endif
1545
1546 if (map == esc->sc_main_dmamap) {
1547 #ifdef DIAGNOSTIC
1548 if ((esc->sc_loaded & ESP_UNLOADED_MAIN) ||
1549 !(esc->sc_loaded & ESP_LOADED_MAIN)) {
1550 panic("%s: unexpected completed call for main map",sc->sc_dev.dv_xname);
1551 }
1552 #endif
1553 esc->sc_loaded |= ESP_UNLOADED_MAIN;
1554 } else if (map == esc->sc_tail_dmamap) {
1555 #ifdef DIAGNOSTIC
1556 if ((esc->sc_loaded & ESP_UNLOADED_TAIL) ||
1557 !(esc->sc_loaded & ESP_LOADED_TAIL)) {
1558 panic("%s: unexpected completed call for tail map",sc->sc_dev.dv_xname);
1559 }
1560 #endif
1561 esc->sc_loaded |= ESP_UNLOADED_TAIL;
1562 }
1563 #ifdef DIAGNOSTIC
1564 else {
1565 panic("%s: unexpected completed map", sc->sc_dev.dv_xname);
1566 }
1567 #endif
1568
1569 #ifdef ESP_DEBUG
1570 if (esp_debug) {
1571 if (map == esc->sc_main_dmamap) {
1572 printf("%s: completed main map\n",sc->sc_dev.dv_xname);
1573 } else if (map == esc->sc_tail_dmamap) {
1574 printf("%s: completed tail map\n",sc->sc_dev.dv_xname);
1575 }
1576 }
1577 #endif
1578
1579 #if 0
1580 if ((map == esc->sc_tail_dmamap) ||
1581 ((esc->sc_tail_size == 0) && (map == esc->sc_main_dmamap))) {
1582
1583 /* Clear the DMAMOD bit in the DCTL register to give control
1584 * back to the scsi chip.
1585 */
1586 if (esc->sc_datain) {
1587 NCR_WRITE_REG(sc, ESP_DCTL,
1588 ESPDCTL_16MHZ | ESPDCTL_INTENB | ESPDCTL_DMARD);
1589 } else {
1590 NCR_WRITE_REG(sc, ESP_DCTL,
1591 ESPDCTL_16MHZ | ESPDCTL_INTENB);
1592 }
1593 DPRINTF(("esp dctl is 0x%02x\n",NCR_READ_REG(sc,ESP_DCTL)));
1594 }
1595 #endif
1596
1597
1598 #if 0
1599 bus_dmamap_sync(esc->sc_dma->sc_dmat, map,
1600 0, map->dm_mapsize,
1601 (esc->sc_datain ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE));
1602 #endif
1603
1604 }
1605
1606 void
1607 esp_dmacb_shutdown(arg)
1608 void *arg;
1609 {
1610 struct ncr53c9x_softc *sc = (struct ncr53c9x_softc *)arg;
1611 struct esp_softc *esc = (struct esp_softc *)sc;
1612
1613 NDTRACEIF (*ndtracep++ = 'S');
1614 DPRINTF(("%s: DMA shutdown\n",sc->sc_dev.dv_xname));
1615
1616 if (esc->sc_loaded == 0)
1617 return;
1618
1619 #if 0
1620 {
1621 /* Clear the DMAMOD bit in the DCTL register to give control
1622 * back to the scsi chip.
1623 */
1624 if (esc->sc_datain) {
1625 NCR_WRITE_REG(sc, ESP_DCTL,
1626 ESPDCTL_16MHZ | ESPDCTL_INTENB | ESPDCTL_DMARD);
1627 } else {
1628 NCR_WRITE_REG(sc, ESP_DCTL,
1629 ESPDCTL_16MHZ | ESPDCTL_INTENB);
1630 }
1631 DPRINTF(("esp dctl is 0x%02x\n",NCR_READ_REG(sc,ESP_DCTL)));
1632 }
1633 #endif
1634
1635 DPRINTF(("%s: esp_dma_nest == %d\n",sc->sc_dev.dv_xname,esp_dma_nest));
1636
1637 /* Stuff the end slop into fifo */
1638
1639 #ifdef ESP_DEBUG
1640 if (esp_debug) {
1641
1642 int n = NCR_READ_REG(sc, NCR_FFLAG);
1643 DPRINTF(("%s: fifo size = %d, seq = 0x%x\n",
1644 sc->sc_dev.dv_xname,n & NCRFIFO_FF, (n & NCRFIFO_SS)>>5));
1645 }
1646 #endif
1647
1648 if (esc->sc_main_dmamap->dm_mapsize) {
1649 if (!esc->sc_datain) { /* unpatch the DMA map for write overrun */
1650 esc->sc_main_dmamap->dm_mapsize -= ESP_DMA_OVERRUN;
1651 esc->sc_main_dmamap->dm_segs[esc->sc_main_dmamap->dm_nsegs - 1].ds_len -=
1652 ESP_DMA_OVERRUN;
1653 }
1654 bus_dmamap_sync(esc->sc_dma->sc_dmat, esc->sc_main_dmamap,
1655 0, esc->sc_main_dmamap->dm_mapsize,
1656 (esc->sc_datain ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE));
1657 bus_dmamap_unload(esc->sc_dma->sc_dmat, esc->sc_main_dmamap);
1658 NDTRACEIF (
1659 sprintf (ndtracep, "m%ld", esc->sc_main_dmamap->dm_xfer_len);
1660 ndtracep += strlen (ndtracep);
1661 );
1662 }
1663
1664 if (esc->sc_tail_dmamap->dm_mapsize) {
1665 bus_dmamap_sync(esc->sc_dma->sc_dmat, esc->sc_tail_dmamap,
1666 0, esc->sc_tail_dmamap->dm_mapsize,
1667 (esc->sc_datain ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE));
1668 bus_dmamap_unload(esc->sc_dma->sc_dmat, esc->sc_tail_dmamap);
1669 /* copy the tail DMA buffer data for read transfers */
1670 if (esc->sc_datain) {
1671 memcpy(*esc->sc_dmaaddr+esc->sc_begin_size+esc->sc_main_size,
1672 esc->sc_tail, esc->sc_dmasize-(esc->sc_begin_size+esc->sc_main_size));
1673 }
1674 NDTRACEIF (
1675 sprintf (ndtracep, "t%ld", esc->sc_tail_dmamap->dm_xfer_len);
1676 ndtracep += strlen (ndtracep);
1677 );
1678 }
1679
1680 #ifdef ESP_DEBUG
1681 if (esp_debug) {
1682 printf("%s: dma_shutdown: addr=%p,len=0x%08x,size=0x%08x\n",
1683 sc->sc_dev.dv_xname,
1684 *esc->sc_dmaaddr, *esc->sc_dmalen, esc->sc_dmasize);
1685 if (esp_debug > 10) {
1686 esp_hex_dump(*(esc->sc_dmaaddr),esc->sc_dmasize);
1687 printf("%s: tail=%p,tailbuf=%p,tail_size=0x%08x\n",
1688 sc->sc_dev.dv_xname,
1689 esc->sc_tail, &(esc->sc_tailbuf[0]), esc->sc_tail_size);
1690 esp_hex_dump(&(esc->sc_tailbuf[0]),sizeof(esc->sc_tailbuf));
1691 }
1692 }
1693 #endif
1694
1695 esc->sc_main = 0;
1696 esc->sc_main_size = 0;
1697 esc->sc_tail = 0;
1698 esc->sc_tail_size = 0;
1699
1700 esc->sc_datain = -1;
1701 /* esc->sc_dmaaddr = 0; */
1702 /* esc->sc_dmalen = 0; */
1703 /* esc->sc_dmasize = 0; */
1704
1705 esc->sc_loaded = 0;
1706
1707 esc->sc_begin = 0;
1708 esc->sc_begin_size = 0;
1709
1710 #ifdef ESP_DEBUG
1711 if (esp_debug) {
1712 char sbuf[256];
1713
1714 bitmask_snprintf((*(volatile u_long *)IIOV(NEXT_P_INTRSTAT)),
1715 NEXT_INTR_BITS, sbuf, sizeof(sbuf));
1716 printf(" *intrstat = 0x%s\n", sbuf);
1717
1718 bitmask_snprintf((*(volatile u_long *)IIOV(NEXT_P_INTRMASK)),
1719 NEXT_INTR_BITS, sbuf, sizeof(sbuf));
1720 printf(" *intrmask = 0x%s\n", sbuf);
1721 }
1722 #endif
1723 }
1724