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