esp.c revision 1.54 1 /* $NetBSD: esp.c,v 1.54 2007/03/05 15:05:24 tsutsui 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.54 2007/03/05 15:05:24 tsutsui 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 *, void **, 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 = (char *)*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, void **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 = bgn + 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;
877 esc->sc_main += slop_bgn_size;
878 esc->sc_main_size = (esc->sc_dmasize)-(slop_end_size+slop_bgn_size);
879
880 if (esc->sc_main_size) {
881 int error;
882
883 if (!esc->sc_datain || DMA_ENDALIGNED(esc->sc_main_size + slop_end_size)) {
884 KASSERT(DMA_SCSI_ALIGNMENT == DMA_ENDALIGNMENT);
885 KASSERT(DMA_BEGINALIGNMENT == DMA_ENDALIGNMENT);
886 esc->sc_main_size += slop_end_size;
887 slop_end_size = 0;
888 if (!esc->sc_datain) {
889 esc->sc_main_size = DMA_ENDALIGN(uint8_t *,esc->sc_main+esc->sc_main_size)-esc->sc_main;
890 }
891 }
892
893 error = bus_dmamap_load(esc->sc_dma->sc_dmat,
894 esc->sc_main_dmamap,
895 esc->sc_main, esc->sc_main_size,
896 NULL, BUS_DMA_NOWAIT);
897 if (error) {
898 #ifdef ESP_DEBUG
899 printf("%s: esc->sc_main_dmamap->_dm_size = %ld\n",
900 sc->sc_dev.dv_xname,esc->sc_main_dmamap->_dm_size);
901 printf("%s: esc->sc_main_dmamap->_dm_segcnt = %d\n",
902 sc->sc_dev.dv_xname,esc->sc_main_dmamap->_dm_segcnt);
903 printf("%s: esc->sc_main_dmamap->_dm_maxsegsz = %ld\n",
904 sc->sc_dev.dv_xname,esc->sc_main_dmamap->_dm_maxsegsz);
905 printf("%s: esc->sc_main_dmamap->_dm_boundary = %ld\n",
906 sc->sc_dev.dv_xname,esc->sc_main_dmamap->_dm_boundary);
907 esp_dma_print(sc);
908 #endif
909 panic("%s: can't load main DMA map. error = %d, addr=%p, size=0x%08x",
910 sc->sc_dev.dv_xname, error,esc->sc_main,esc->sc_main_size);
911 }
912 if (!esc->sc_datain) { /* patch the DMA map for write overrun */
913 esc->sc_main_dmamap->dm_mapsize += ESP_DMA_OVERRUN;
914 esc->sc_main_dmamap->dm_segs[esc->sc_main_dmamap->dm_nsegs - 1].ds_len +=
915 ESP_DMA_OVERRUN;
916 }
917 #if 0
918 bus_dmamap_sync(esc->sc_dma->sc_dmat, esc->sc_main_dmamap,
919 0, esc->sc_main_dmamap->dm_mapsize,
920 (esc->sc_datain ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE));
921 esc->sc_main_dmamap->dm_xfer_len = 0;
922 #endif
923 } else {
924 esc->sc_main = 0;
925 }
926 }
927
928 /* Load the tail DMA map */
929 if (slop_end_size) {
930 esc->sc_tail = DMA_ENDALIGN(uint8_t *,esc->sc_tailbuf+slop_end_size)-slop_end_size;
931 /* If the beginning of the tail is not correctly aligned,
932 * we have no choice but to align the start, which might then unalign the end.
933 */
934 esc->sc_tail = DMA_SCSI_ALIGN(uint8_t *,esc->sc_tail);
935 /* So therefore, we change the tail size to be end aligned again. */
936 esc->sc_tail_size = DMA_ENDALIGN(uint8_t *,esc->sc_tail+slop_end_size)-esc->sc_tail;
937
938 /* @@@ next DMA overrun lossage */
939 if (!esc->sc_datain) {
940 esc->sc_tail_size += ESP_DMA_OVERRUN;
941 }
942
943 {
944 int error;
945 error = bus_dmamap_load(esc->sc_dma->sc_dmat,
946 esc->sc_tail_dmamap,
947 esc->sc_tail, esc->sc_tail_size,
948 NULL, BUS_DMA_NOWAIT);
949 if (error) {
950 panic("%s: can't load tail DMA map. error = %d, addr=%p, size=0x%08x",
951 sc->sc_dev.dv_xname, error,esc->sc_tail,esc->sc_tail_size);
952 }
953 #if 0
954 bus_dmamap_sync(esc->sc_dma->sc_dmat, esc->sc_tail_dmamap,
955 0, esc->sc_tail_dmamap->dm_mapsize,
956 (esc->sc_datain ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE));
957 esc->sc_tail_dmamap->dm_xfer_len = 0;
958 #endif
959 }
960 }
961 #else
962
963 esc->sc_begin = *esc->sc_dmaaddr;
964 slop_bgn_size = DMA_SCSI_ALIGNMENT-((ulong)esc->sc_begin % DMA_SCSI_ALIGNMENT);
965 if (slop_bgn_size == DMA_SCSI_ALIGNMENT) slop_bgn_size = 0;
966 slop_end_size = esc->sc_dmasize - slop_bgn_size;
967
968 if (slop_bgn_size < esc->sc_dmasize) {
969 int error;
970
971 esc->sc_tail = 0;
972 esc->sc_tail_size = 0;
973
974 esc->sc_begin_size = slop_bgn_size;
975 esc->sc_main = *esc->sc_dmaaddr;
976 esc->sc_main += slop_bgn_size;
977 esc->sc_main_size = DMA_ENDALIGN(uint8_t *,esc->sc_main+esc->sc_dmasize-slop_bgn_size)-esc->sc_main;
978
979 if (!esc->sc_datain) {
980 esc->sc_main_size += ESP_DMA_OVERRUN;
981 }
982 error = bus_dmamap_load(esc->sc_dma->sc_dmat,
983 esc->sc_main_dmamap,
984 esc->sc_main, esc->sc_main_size,
985 NULL, BUS_DMA_NOWAIT);
986 if (error) {
987 panic("%s: can't load main DMA map. error = %d, addr=%p, size=0x%08x",
988 sc->sc_dev.dv_xname, error,esc->sc_main,esc->sc_main_size);
989 }
990 } else {
991 esc->sc_begin = 0;
992 esc->sc_begin_size = 0;
993 esc->sc_main = 0;
994 esc->sc_main_size = 0;
995
996 #if 0
997 esc->sc_tail = DMA_ENDALIGN(uint8_t *,esc->sc_tailbuf+slop_bgn_size)-slop_bgn_size;
998 /* If the beginning of the tail is not correctly aligned,
999 * we have no choice but to align the start, which might then unalign the end.
1000 */
1001 #endif
1002 esc->sc_tail = DMA_SCSI_ALIGN(void *,esc->sc_tailbuf);
1003 /* So therefore, we change the tail size to be end aligned again. */
1004 esc->sc_tail_size = DMA_ENDALIGN(uint8_t *,esc->sc_tail+esc->sc_dmasize)-esc->sc_tail;
1005
1006 /* @@@ next DMA overrun lossage */
1007 if (!esc->sc_datain) {
1008 esc->sc_tail_size += ESP_DMA_OVERRUN;
1009 }
1010
1011 {
1012 int error;
1013 error = bus_dmamap_load(esc->sc_dma->sc_dmat,
1014 esc->sc_tail_dmamap,
1015 esc->sc_tail, esc->sc_tail_size,
1016 NULL, BUS_DMA_NOWAIT);
1017 if (error) {
1018 panic("%s: can't load tail DMA map. error = %d, addr=%p, size=0x%08x",
1019 sc->sc_dev.dv_xname, error,esc->sc_tail,esc->sc_tail_size);
1020 }
1021 }
1022 }
1023 #endif
1024
1025 DPRINTF(("%s: setup: %8p %d %8p %d %8p %d %8p %d\n", sc->sc_dev.dv_xname,
1026 *esc->sc_dmaaddr, esc->sc_dmasize, esc->sc_begin,
1027 esc->sc_begin_size, esc->sc_main, esc->sc_main_size, esc->sc_tail,
1028 esc->sc_tail_size));
1029 }
1030
1031 return (0);
1032 }
1033
1034 #ifdef ESP_DEBUG
1035 /* For debugging */
1036 void
1037 esp_dma_store(struct ncr53c9x_softc *sc)
1038 {
1039 struct esp_softc *esc = (struct esp_softc *)sc;
1040 char *p = &esp_dma_dump[0];
1041
1042 p += sprintf(p,"%s: sc_datain=%d\n",sc->sc_dev.dv_xname,esc->sc_datain);
1043 p += sprintf(p,"%s: sc_loaded=0x%08x\n",sc->sc_dev.dv_xname,esc->sc_loaded);
1044
1045 if (esc->sc_dmaaddr) {
1046 p += sprintf(p,"%s: sc_dmaaddr=%p\n",sc->sc_dev.dv_xname,*esc->sc_dmaaddr);
1047 } else {
1048 p += sprintf(p,"%s: sc_dmaaddr=NULL\n",sc->sc_dev.dv_xname);
1049 }
1050 if (esc->sc_dmalen) {
1051 p += sprintf(p,"%s: sc_dmalen=0x%08x\n",sc->sc_dev.dv_xname,*esc->sc_dmalen);
1052 } else {
1053 p += sprintf(p,"%s: sc_dmalen=NULL\n",sc->sc_dev.dv_xname);
1054 }
1055 p += sprintf(p,"%s: sc_dmasize=0x%08x\n",sc->sc_dev.dv_xname,esc->sc_dmasize);
1056
1057 p += sprintf(p,"%s: sc_begin = %p, sc_begin_size = 0x%08x\n",
1058 sc->sc_dev.dv_xname, esc->sc_begin, esc->sc_begin_size);
1059 p += sprintf(p,"%s: sc_main = %p, sc_main_size = 0x%08x\n",
1060 sc->sc_dev.dv_xname, esc->sc_main, esc->sc_main_size);
1061 /* if (esc->sc_main) */ {
1062 int i;
1063 bus_dmamap_t map = esc->sc_main_dmamap;
1064 p += sprintf(p,"%s: sc_main_dmamap. mapsize = 0x%08lx, nsegs = %d\n",
1065 sc->sc_dev.dv_xname, map->dm_mapsize, map->dm_nsegs);
1066 for(i=0;i<map->dm_nsegs;i++) {
1067 p += sprintf(p,"%s: map->dm_segs[%d].ds_addr = 0x%08lx, len = 0x%08lx\n",
1068 sc->sc_dev.dv_xname, i, map->dm_segs[i].ds_addr, map->dm_segs[i].ds_len);
1069 }
1070 }
1071 p += sprintf(p,"%s: sc_tail = %p, sc_tail_size = 0x%08x\n",
1072 sc->sc_dev.dv_xname, esc->sc_tail, esc->sc_tail_size);
1073 /* if (esc->sc_tail) */ {
1074 int i;
1075 bus_dmamap_t map = esc->sc_tail_dmamap;
1076 p += sprintf(p,"%s: sc_tail_dmamap. mapsize = 0x%08lx, nsegs = %d\n",
1077 sc->sc_dev.dv_xname, map->dm_mapsize, map->dm_nsegs);
1078 for(i=0;i<map->dm_nsegs;i++) {
1079 p += sprintf(p,"%s: map->dm_segs[%d].ds_addr = 0x%08lx, len = 0x%08lx\n",
1080 sc->sc_dev.dv_xname, i, map->dm_segs[i].ds_addr, map->dm_segs[i].ds_len);
1081 }
1082 }
1083 }
1084
1085 void
1086 esp_dma_print(struct ncr53c9x_softc *sc)
1087 {
1088 esp_dma_store(sc);
1089 printf("%s",esp_dma_dump);
1090 }
1091 #endif
1092
1093 void
1094 esp_dma_go(struct ncr53c9x_softc *sc)
1095 {
1096 struct esp_softc *esc = (struct esp_softc *)sc;
1097 struct nextdma_softc *nsc = esc->sc_dma;
1098 struct nextdma_status *stat = &nsc->sc_stat;
1099 /* int s = spldma(); */
1100
1101 #ifdef ESP_DEBUG
1102 if (ndtracep != ndtrace) {
1103 if (ndtraceshow) {
1104 *ndtracep = '\0';
1105 printf ("esp ndtrace: %s\n", ndtrace);
1106 ndtraceshow = 0;
1107 } else {
1108 DPRINTF (("X"));
1109 }
1110 ndtracep = ndtrace;
1111 }
1112 #endif
1113
1114 DPRINTF(("%s: esp_dma_go(datain = %d)\n",
1115 sc->sc_dev.dv_xname, esc->sc_datain));
1116
1117 #ifdef ESP_DEBUG
1118 if (esp_debug) esp_dma_print(sc);
1119 else esp_dma_store(sc);
1120 #endif
1121
1122 #ifdef ESP_DEBUG
1123 {
1124 int n = NCR_READ_REG(sc, NCR_FFLAG);
1125 DPRINTF(("%s: fifo size = %d, seq = 0x%x\n",
1126 sc->sc_dev.dv_xname,
1127 n & NCRFIFO_FF, (n & NCRFIFO_SS)>>5));
1128 }
1129 #endif
1130
1131 /* zero length DMA transfers are boring */
1132 if (esc->sc_dmasize == 0) {
1133 /* splx(s); */
1134 return;
1135 }
1136
1137 #if defined(DIAGNOSTIC)
1138 if ((esc->sc_begin_size == 0) &&
1139 (esc->sc_main_dmamap->dm_mapsize == 0) &&
1140 (esc->sc_tail_dmamap->dm_mapsize == 0)) {
1141 #ifdef ESP_DEBUG
1142 esp_dma_print(sc);
1143 #endif
1144 panic("%s: No DMA requested!",sc->sc_dev.dv_xname);
1145 }
1146 #endif
1147
1148 /* Stuff the fifo with the begin buffer */
1149 if (esc->sc_datain) {
1150 int i;
1151 DPRINTF(("%s: FIFO read of %d bytes:",
1152 sc->sc_dev.dv_xname,esc->sc_begin_size));
1153 for(i=0;i<esc->sc_begin_size;i++) {
1154 esc->sc_begin[i]=NCR_READ_REG(sc, NCR_FIFO);
1155 DPRINTF((" %02x",esc->sc_begin[i]&0xff));
1156 }
1157 DPRINTF(("\n"));
1158 } else {
1159 int i;
1160 DPRINTF(("%s: FIFO write of %d bytes:",
1161 sc->sc_dev.dv_xname,esc->sc_begin_size));
1162 for(i=0;i<esc->sc_begin_size;i++) {
1163 NCR_WRITE_REG(sc, NCR_FIFO, esc->sc_begin[i]);
1164 DPRINTF((" %02x",esc->sc_begin[i]&0xff));
1165 }
1166 DPRINTF(("\n"));
1167 }
1168
1169 if (esc->sc_main_dmamap->dm_mapsize) {
1170 bus_dmamap_sync(esc->sc_dma->sc_dmat, esc->sc_main_dmamap,
1171 0, esc->sc_main_dmamap->dm_mapsize,
1172 (esc->sc_datain ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE));
1173 esc->sc_main_dmamap->dm_xfer_len = 0;
1174 }
1175
1176 if (esc->sc_tail_dmamap->dm_mapsize) {
1177 /* if we are a DMA write cycle, copy the end slop */
1178 if (!esc->sc_datain) {
1179 memcpy(esc->sc_tail, (char *)*esc->sc_dmaaddr+esc->sc_begin_size+esc->sc_main_size,
1180 esc->sc_dmasize-(esc->sc_begin_size+esc->sc_main_size));
1181 }
1182 bus_dmamap_sync(esc->sc_dma->sc_dmat, esc->sc_tail_dmamap,
1183 0, esc->sc_tail_dmamap->dm_mapsize,
1184 (esc->sc_datain ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE));
1185 esc->sc_tail_dmamap->dm_xfer_len = 0;
1186 }
1187
1188 stat->nd_exception = 0;
1189 nextdma_start(nsc, (esc->sc_datain ? DMACSR_SETREAD : DMACSR_SETWRITE));
1190
1191 if (esc->sc_datain) {
1192 NCR_WRITE_REG(sc, ESP_DCTL,
1193 ESPDCTL_16MHZ | ESPDCTL_INTENB | ESPDCTL_DMAMOD | ESPDCTL_DMARD);
1194 } else {
1195 NCR_WRITE_REG(sc, ESP_DCTL,
1196 ESPDCTL_16MHZ | ESPDCTL_INTENB | ESPDCTL_DMAMOD);
1197 }
1198 DPRINTF(("esp dctl is 0x%02x\n",NCR_READ_REG(sc,ESP_DCTL)));
1199
1200 NDTRACEIF (if (esc->sc_begin_size) { *ndtracep++ = '1'; *ndtracep++ = 'A' + esc->sc_begin_size; });
1201 NDTRACEIF (if (esc->sc_main_size) { *ndtracep++ = '2'; *ndtracep++ = '0' + esc->sc_main_dmamap->dm_nsegs; });
1202 NDTRACEIF (if (esc->sc_tail_size) { *ndtracep++ = '3'; *ndtracep++ = 'A' + esc->sc_tail_size; });
1203
1204 /* splx(s); */
1205 }
1206
1207 void
1208 esp_dma_stop(struct ncr53c9x_softc *sc)
1209 {
1210 struct esp_softc *esc = (struct esp_softc *)sc;
1211 nextdma_print(esc->sc_dma);
1212 #ifdef ESP_DEBUG
1213 esp_dma_print(sc);
1214 #endif
1215 #if 1
1216 panic("%s: stop not yet implemented",sc->sc_dev.dv_xname);
1217 #endif
1218 }
1219
1220 int
1221 esp_dma_isactive(struct ncr53c9x_softc *sc)
1222 {
1223 struct esp_softc *esc = (struct esp_softc *)sc;
1224 int r = (esc->sc_dmaaddr != NULL); /* !nextdma_finished(esc->sc_dma); */
1225 DPRINTF(("esp_dma_isactive = %d\n",r));
1226 return(r);
1227 }
1228
1229 /****************************************************************/
1230
1231 int esp_dma_int(void *);
1232 int esp_dma_int(void *arg)
1233 {
1234 void nextdma_rotate(struct nextdma_softc *);
1235 void nextdma_setup_curr_regs(struct nextdma_softc *);
1236 void nextdma_setup_cont_regs(struct nextdma_softc *);
1237
1238 struct ncr53c9x_softc *sc = (struct ncr53c9x_softc *)arg;
1239 struct esp_softc *esc = (struct esp_softc *)sc;
1240 struct nextdma_softc *nsc = esc->sc_dma;
1241 struct nextdma_status *stat = &nsc->sc_stat;
1242 unsigned int state;
1243
1244 NDTRACEIF (*ndtracep++ = 'E');
1245
1246 state = nd_bsr4 (DD_CSR);
1247
1248 #if 1
1249 NDTRACEIF (
1250 if (state & DMACSR_COMPLETE) *ndtracep++ = 'c';
1251 if (state & DMACSR_ENABLE) *ndtracep++ = 'e';
1252 if (state & DMACSR_BUSEXC) *ndtracep++ = 'b';
1253 if (state & DMACSR_READ) *ndtracep++ = 'r';
1254 if (state & DMACSR_SUPDATE) *ndtracep++ = 's';
1255 );
1256
1257 NDTRACEIF (*ndtracep++ = 'E');
1258
1259 #ifdef ESP_DEBUG
1260 if (0) if ((state & DMACSR_BUSEXC) && (state & DMACSR_ENABLE)) ndtraceshow++;
1261 if (0) if ((state & DMACSR_SUPDATE)) ndtraceshow++;
1262 #endif
1263 #endif
1264
1265 if ((stat->nd_exception == 0) && (state & DMACSR_COMPLETE) && (state & DMACSR_ENABLE)) {
1266 stat->nd_map->dm_xfer_len += stat->nd_map->dm_segs[stat->nd_idx].ds_len;
1267 }
1268
1269 if ((stat->nd_idx+1) == stat->nd_map->dm_nsegs) {
1270 if (nsc->sc_conf.nd_completed_cb)
1271 (*nsc->sc_conf.nd_completed_cb)(stat->nd_map, nsc->sc_conf.nd_cb_arg);
1272 }
1273 nextdma_rotate(nsc);
1274
1275 if ((state & DMACSR_COMPLETE) && (state & DMACSR_ENABLE)) {
1276 #if 0
1277 int l = nd_bsr4 (DD_LIMIT) & 0x7FFFFFFF;
1278 int s = nd_bsr4 (DD_STOP);
1279 #endif
1280 /* nextdma_setup_cont_regs(nsc); */
1281 if (stat->nd_map_cont) {
1282 nd_bsw4 (DD_START, stat->nd_map_cont->dm_segs[stat->nd_idx_cont].ds_addr);
1283 nd_bsw4 (DD_STOP, (stat->nd_map_cont->dm_segs[stat->nd_idx_cont].ds_addr +
1284 stat->nd_map_cont->dm_segs[stat->nd_idx_cont].ds_len));
1285 }
1286
1287 nd_bsw4 (DD_CSR, DMACSR_CLRCOMPLETE | (state & DMACSR_READ ? DMACSR_SETREAD : DMACSR_SETWRITE) |
1288 (stat->nd_map_cont ? DMACSR_SETSUPDATE : 0));
1289
1290 #if 0
1291 #ifdef ESP_DEBUG
1292 if (state & DMACSR_BUSEXC) {
1293 sprintf (ndtracep, "CE/BUSEXC: %08lX %08X %08X\n",
1294 (stat->nd_map->dm_segs[stat->nd_idx].ds_addr + stat->nd_map->dm_segs[stat->nd_idx].ds_len),
1295 l, s);
1296 ndtracep += strlen (ndtracep);
1297 }
1298 #endif
1299 #endif
1300 } else {
1301 #if 0
1302 if (state & DMACSR_BUSEXC) {
1303 while (nd_bsr4 (DD_NEXT) !=
1304 (nd_bsr4 (DD_LIMIT) & 0x7FFFFFFF))
1305 printf ("Y"); /* DELAY(50); */
1306 state = nd_bsr4 (DD_CSR);
1307 }
1308 #endif
1309
1310 if (!(state & DMACSR_SUPDATE)) {
1311 nextdma_rotate(nsc);
1312 } else {
1313 nd_bsw4 (DD_CSR, DMACSR_CLRCOMPLETE |
1314 DMACSR_INITBUF | DMACSR_RESET |
1315 (state & DMACSR_READ ? DMACSR_SETREAD : DMACSR_SETWRITE));
1316
1317 nd_bsw4 (DD_NEXT, stat->nd_map->dm_segs[stat->nd_idx].ds_addr);
1318 nd_bsw4 (DD_LIMIT,
1319 (stat->nd_map->dm_segs[stat->nd_idx].ds_addr +
1320 stat->nd_map->dm_segs[stat->nd_idx].ds_len) | 0/* x80000000 */);
1321 if (stat->nd_map_cont) {
1322 nd_bsw4 (DD_START,
1323 stat->nd_map_cont->dm_segs[stat->nd_idx_cont].ds_addr);
1324 nd_bsw4 (DD_STOP,
1325 (stat->nd_map_cont->dm_segs[stat->nd_idx_cont].ds_addr +
1326 stat->nd_map_cont->dm_segs[stat->nd_idx_cont].ds_len) | 0/* x80000000 */);
1327 }
1328 nd_bsw4 (DD_CSR, DMACSR_SETENABLE |
1329 DMACSR_CLRCOMPLETE | (state & DMACSR_READ ? DMACSR_SETREAD : DMACSR_SETWRITE) |
1330 (stat->nd_map_cont ? DMACSR_SETSUPDATE : 0));
1331 #if 1
1332 #ifdef ESP_DEBUG
1333 sprintf (ndtracep, "supdate ");
1334 ndtracep += strlen (ndtracep);
1335 sprintf (ndtracep, "%08X %08X %08X %08X ",
1336 nd_bsr4 (DD_NEXT),
1337 nd_bsr4 (DD_LIMIT) & 0x7FFFFFFF,
1338 nd_bsr4 (DD_START),
1339 nd_bsr4 (DD_STOP) & 0x7FFFFFFF);
1340 ndtracep += strlen (ndtracep);
1341 #endif
1342 #endif
1343 stat->nd_exception++;
1344 return(1);
1345 /* NCR_WRITE_REG(sc, ESP_DCTL, ctl); */
1346 goto restart;
1347 }
1348
1349 if (stat->nd_map) {
1350 #if 1
1351 #ifdef ESP_DEBUG
1352 sprintf (ndtracep, "%08X %08X %08X %08X ",
1353 nd_bsr4 (DD_NEXT),
1354 nd_bsr4 (DD_LIMIT) & 0x7FFFFFFF,
1355 nd_bsr4 (DD_START),
1356 nd_bsr4 (DD_STOP) & 0x7FFFFFFF);
1357 ndtracep += strlen (ndtracep);
1358 #endif
1359 #endif
1360
1361 #if 0
1362 nd_bsw4 (DD_CSR, DMACSR_CLRCOMPLETE | DMACSR_RESET);
1363
1364 nd_bsw4 (DD_CSR, 0);
1365 #endif
1366 #if 1
1367 /* 6/2 */
1368 nd_bsw4 (DD_CSR, DMACSR_CLRCOMPLETE |
1369 DMACSR_INITBUF | DMACSR_RESET |
1370 (state & DMACSR_READ ? DMACSR_SETREAD : DMACSR_SETWRITE));
1371
1372 /* nextdma_setup_curr_regs(nsc); */
1373 nd_bsw4 (DD_NEXT, stat->nd_map->dm_segs[stat->nd_idx].ds_addr);
1374 nd_bsw4 (DD_LIMIT,
1375 (stat->nd_map->dm_segs[stat->nd_idx].ds_addr +
1376 stat->nd_map->dm_segs[stat->nd_idx].ds_len) | 0/* x80000000 */);
1377 /* nextdma_setup_cont_regs(nsc); */
1378 if (stat->nd_map_cont) {
1379 nd_bsw4 (DD_START,
1380 stat->nd_map_cont->dm_segs[stat->nd_idx_cont].ds_addr);
1381 nd_bsw4 (DD_STOP,
1382 (stat->nd_map_cont->dm_segs[stat->nd_idx_cont].ds_addr +
1383 stat->nd_map_cont->dm_segs[stat->nd_idx_cont].ds_len) | 0/* x80000000 */);
1384 }
1385
1386 nd_bsw4 (DD_CSR,
1387 DMACSR_SETENABLE | (stat->nd_map_cont ? DMACSR_SETSUPDATE : 0) |
1388 (state & DMACSR_READ ? DMACSR_SETREAD : DMACSR_SETWRITE));
1389 #ifdef ESP_DEBUG
1390 /* ndtraceshow++; */
1391 #endif
1392 stat->nd_exception++;
1393 return(1);
1394 #endif
1395 /* NCR_WRITE_REG(sc, ESP_DCTL, ctl); */
1396 goto restart;
1397 restart:
1398 #if 1
1399 #ifdef ESP_DEBUG
1400 sprintf (ndtracep, "restart %08lX %08lX\n",
1401 stat->nd_map->dm_segs[stat->nd_idx].ds_addr,
1402 stat->nd_map->dm_segs[stat->nd_idx].ds_addr +
1403 stat->nd_map->dm_segs[stat->nd_idx].ds_len);
1404 if (stat->nd_map_cont) {
1405 sprintf (ndtracep + strlen(ndtracep) - 1, " %08lX %08lX\n",
1406 stat->nd_map_cont->dm_segs[stat->nd_idx_cont].ds_addr,
1407 stat->nd_map_cont->dm_segs[stat->nd_idx_cont].ds_addr +
1408 stat->nd_map_cont->dm_segs[stat->nd_idx_cont].ds_len);
1409 }
1410 ndtracep += strlen (ndtracep);
1411 #endif
1412 #endif
1413 nextdma_print(nsc);
1414 NCR_WRITE_REG(sc, ESP_DCTL, ESPDCTL_16MHZ | ESPDCTL_INTENB);
1415 printf ("ff:%02x tcm:%d tcl:%d esp_dstat:%02x state:%02x step: %02x intr:%02x state:%08X\n",
1416 NCR_READ_REG(sc, NCR_FFLAG),
1417 NCR_READ_REG((sc), NCR_TCM), NCR_READ_REG((sc), NCR_TCL),
1418 NCR_READ_REG(sc, ESP_DSTAT),
1419 NCR_READ_REG(sc, NCR_STAT), NCR_READ_REG(sc, NCR_STEP),
1420 NCR_READ_REG(sc, NCR_INTR), state);
1421 #ifdef ESP_DEBUG
1422 *ndtracep = '\0';
1423 printf ("ndtrace: %s\n", ndtrace);
1424 #endif
1425 panic("%s: busexc/supdate occurred. Please email this output to chris (at) pin.lu.",
1426 sc->sc_dev.dv_xname);
1427 #ifdef ESP_DEBUG
1428 ndtraceshow++;
1429 #endif
1430 } else {
1431 nd_bsw4 (DD_CSR, DMACSR_CLRCOMPLETE | DMACSR_RESET);
1432 if (nsc->sc_conf.nd_shutdown_cb)
1433 (*nsc->sc_conf.nd_shutdown_cb)(nsc->sc_conf.nd_cb_arg);
1434 }
1435 }
1436 return (1);
1437 }
1438
1439 /* Internal DMA callback routines */
1440 bus_dmamap_t
1441 esp_dmacb_continue(void *arg)
1442 {
1443 struct ncr53c9x_softc *sc = (struct ncr53c9x_softc *)arg;
1444 struct esp_softc *esc = (struct esp_softc *)sc;
1445
1446 NDTRACEIF (*ndtracep++ = 'x');
1447 DPRINTF(("%s: DMA continue\n",sc->sc_dev.dv_xname));
1448
1449 #ifdef DIAGNOSTIC
1450 if ((esc->sc_datain < 0) || (esc->sc_datain > 1)) {
1451 panic("%s: map not loaded in DMA continue callback, datain = %d",
1452 sc->sc_dev.dv_xname,esc->sc_datain);
1453 }
1454 #endif
1455
1456 if ((!(esc->sc_loaded & ESP_LOADED_MAIN)) &&
1457 (esc->sc_main_dmamap->dm_mapsize)) {
1458 DPRINTF(("%s: Loading main map\n",sc->sc_dev.dv_xname));
1459 #if 0
1460 bus_dmamap_sync(esc->sc_dma->sc_dmat, esc->sc_main_dmamap,
1461 0, esc->sc_main_dmamap->dm_mapsize,
1462 (esc->sc_datain ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE));
1463 esc->sc_main_dmamap->dm_xfer_len = 0;
1464 #endif
1465 esc->sc_loaded |= ESP_LOADED_MAIN;
1466 return(esc->sc_main_dmamap);
1467 }
1468
1469 if ((!(esc->sc_loaded & ESP_LOADED_TAIL)) &&
1470 (esc->sc_tail_dmamap->dm_mapsize)) {
1471 DPRINTF(("%s: Loading tail map\n",sc->sc_dev.dv_xname));
1472 #if 0
1473 bus_dmamap_sync(esc->sc_dma->sc_dmat, esc->sc_tail_dmamap,
1474 0, esc->sc_tail_dmamap->dm_mapsize,
1475 (esc->sc_datain ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE));
1476 esc->sc_tail_dmamap->dm_xfer_len = 0;
1477 #endif
1478 esc->sc_loaded |= ESP_LOADED_TAIL;
1479 return(esc->sc_tail_dmamap);
1480 }
1481
1482 DPRINTF(("%s: not loading map\n",sc->sc_dev.dv_xname));
1483 return(0);
1484 }
1485
1486
1487 void
1488 esp_dmacb_completed(bus_dmamap_t map, void *arg)
1489 {
1490 struct ncr53c9x_softc *sc = (struct ncr53c9x_softc *)arg;
1491 struct esp_softc *esc = (struct esp_softc *)sc;
1492
1493 NDTRACEIF (*ndtracep++ = 'X');
1494 DPRINTF(("%s: DMA completed\n",sc->sc_dev.dv_xname));
1495
1496 #ifdef DIAGNOSTIC
1497 if ((esc->sc_datain < 0) || (esc->sc_datain > 1)) {
1498 panic("%s: invalid DMA direction in completed callback, datain = %d",
1499 sc->sc_dev.dv_xname,esc->sc_datain);
1500 }
1501 #endif
1502
1503 #if defined(DIAGNOSTIC) && 0
1504 {
1505 int i;
1506 for(i=0;i<map->dm_nsegs;i++) {
1507 if (map->dm_xfer_len != map->dm_mapsize) {
1508 printf("%s: map->dm_mapsize = %d\n", sc->sc_dev.dv_xname,map->dm_mapsize);
1509 printf("%s: map->dm_nsegs = %d\n", sc->sc_dev.dv_xname,map->dm_nsegs);
1510 printf("%s: map->dm_xfer_len = %d\n", sc->sc_dev.dv_xname,map->dm_xfer_len);
1511 for(i=0;i<map->dm_nsegs;i++) {
1512 printf("%s: map->dm_segs[%d].ds_addr = 0x%08lx\n",
1513 sc->sc_dev.dv_xname,i,map->dm_segs[i].ds_addr);
1514 printf("%s: map->dm_segs[%d].ds_len = %d\n",
1515 sc->sc_dev.dv_xname,i,map->dm_segs[i].ds_len);
1516 }
1517 panic("%s: incomplete DMA transfer",sc->sc_dev.dv_xname);
1518 }
1519 }
1520 }
1521 #endif
1522
1523 if (map == esc->sc_main_dmamap) {
1524 #ifdef DIAGNOSTIC
1525 if ((esc->sc_loaded & ESP_UNLOADED_MAIN) ||
1526 !(esc->sc_loaded & ESP_LOADED_MAIN)) {
1527 panic("%s: unexpected completed call for main map",sc->sc_dev.dv_xname);
1528 }
1529 #endif
1530 esc->sc_loaded |= ESP_UNLOADED_MAIN;
1531 } else if (map == esc->sc_tail_dmamap) {
1532 #ifdef DIAGNOSTIC
1533 if ((esc->sc_loaded & ESP_UNLOADED_TAIL) ||
1534 !(esc->sc_loaded & ESP_LOADED_TAIL)) {
1535 panic("%s: unexpected completed call for tail map",sc->sc_dev.dv_xname);
1536 }
1537 #endif
1538 esc->sc_loaded |= ESP_UNLOADED_TAIL;
1539 }
1540 #ifdef DIAGNOSTIC
1541 else {
1542 panic("%s: unexpected completed map", sc->sc_dev.dv_xname);
1543 }
1544 #endif
1545
1546 #ifdef ESP_DEBUG
1547 if (esp_debug) {
1548 if (map == esc->sc_main_dmamap) {
1549 printf("%s: completed main map\n",sc->sc_dev.dv_xname);
1550 } else if (map == esc->sc_tail_dmamap) {
1551 printf("%s: completed tail map\n",sc->sc_dev.dv_xname);
1552 }
1553 }
1554 #endif
1555
1556 #if 0
1557 if ((map == esc->sc_tail_dmamap) ||
1558 ((esc->sc_tail_size == 0) && (map == esc->sc_main_dmamap))) {
1559
1560 /* Clear the DMAMOD bit in the DCTL register to give control
1561 * back to the scsi chip.
1562 */
1563 if (esc->sc_datain) {
1564 NCR_WRITE_REG(sc, ESP_DCTL,
1565 ESPDCTL_16MHZ | ESPDCTL_INTENB | ESPDCTL_DMARD);
1566 } else {
1567 NCR_WRITE_REG(sc, ESP_DCTL,
1568 ESPDCTL_16MHZ | ESPDCTL_INTENB);
1569 }
1570 DPRINTF(("esp dctl is 0x%02x\n",NCR_READ_REG(sc,ESP_DCTL)));
1571 }
1572 #endif
1573
1574
1575 #if 0
1576 bus_dmamap_sync(esc->sc_dma->sc_dmat, map,
1577 0, map->dm_mapsize,
1578 (esc->sc_datain ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE));
1579 #endif
1580
1581 }
1582
1583 void
1584 esp_dmacb_shutdown(void *arg)
1585 {
1586 struct ncr53c9x_softc *sc = (struct ncr53c9x_softc *)arg;
1587 struct esp_softc *esc = (struct esp_softc *)sc;
1588
1589 NDTRACEIF (*ndtracep++ = 'S');
1590 DPRINTF(("%s: DMA shutdown\n",sc->sc_dev.dv_xname));
1591
1592 if (esc->sc_loaded == 0)
1593 return;
1594
1595 #if 0
1596 {
1597 /* Clear the DMAMOD bit in the DCTL register to give control
1598 * back to the scsi chip.
1599 */
1600 if (esc->sc_datain) {
1601 NCR_WRITE_REG(sc, ESP_DCTL,
1602 ESPDCTL_16MHZ | ESPDCTL_INTENB | ESPDCTL_DMARD);
1603 } else {
1604 NCR_WRITE_REG(sc, ESP_DCTL,
1605 ESPDCTL_16MHZ | ESPDCTL_INTENB);
1606 }
1607 DPRINTF(("esp dctl is 0x%02x\n",NCR_READ_REG(sc,ESP_DCTL)));
1608 }
1609 #endif
1610
1611 DPRINTF(("%s: esp_dma_nest == %d\n",sc->sc_dev.dv_xname,esp_dma_nest));
1612
1613 /* Stuff the end slop into fifo */
1614
1615 #ifdef ESP_DEBUG
1616 if (esp_debug) {
1617
1618 int n = NCR_READ_REG(sc, NCR_FFLAG);
1619 DPRINTF(("%s: fifo size = %d, seq = 0x%x\n",
1620 sc->sc_dev.dv_xname,n & NCRFIFO_FF, (n & NCRFIFO_SS)>>5));
1621 }
1622 #endif
1623
1624 if (esc->sc_main_dmamap->dm_mapsize) {
1625 if (!esc->sc_datain) { /* unpatch the DMA map for write overrun */
1626 esc->sc_main_dmamap->dm_mapsize -= ESP_DMA_OVERRUN;
1627 esc->sc_main_dmamap->dm_segs[esc->sc_main_dmamap->dm_nsegs - 1].ds_len -=
1628 ESP_DMA_OVERRUN;
1629 }
1630 bus_dmamap_sync(esc->sc_dma->sc_dmat, esc->sc_main_dmamap,
1631 0, esc->sc_main_dmamap->dm_mapsize,
1632 (esc->sc_datain ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE));
1633 bus_dmamap_unload(esc->sc_dma->sc_dmat, esc->sc_main_dmamap);
1634 NDTRACEIF (
1635 sprintf (ndtracep, "m%ld", esc->sc_main_dmamap->dm_xfer_len);
1636 ndtracep += strlen (ndtracep);
1637 );
1638 }
1639
1640 if (esc->sc_tail_dmamap->dm_mapsize) {
1641 bus_dmamap_sync(esc->sc_dma->sc_dmat, esc->sc_tail_dmamap,
1642 0, esc->sc_tail_dmamap->dm_mapsize,
1643 (esc->sc_datain ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE));
1644 bus_dmamap_unload(esc->sc_dma->sc_dmat, esc->sc_tail_dmamap);
1645 /* copy the tail DMA buffer data for read transfers */
1646 if (esc->sc_datain) {
1647 memcpy((char *)*esc->sc_dmaaddr+esc->sc_begin_size+esc->sc_main_size,
1648 esc->sc_tail, esc->sc_dmasize-(esc->sc_begin_size+esc->sc_main_size));
1649 }
1650 NDTRACEIF (
1651 sprintf (ndtracep, "t%ld", esc->sc_tail_dmamap->dm_xfer_len);
1652 ndtracep += strlen (ndtracep);
1653 );
1654 }
1655
1656 #ifdef ESP_DEBUG
1657 if (esp_debug) {
1658 printf("%s: dma_shutdown: addr=%p,len=0x%08x,size=0x%08x\n",
1659 sc->sc_dev.dv_xname,
1660 *esc->sc_dmaaddr, *esc->sc_dmalen, esc->sc_dmasize);
1661 if (esp_debug > 10) {
1662 esp_hex_dump(*(esc->sc_dmaaddr),esc->sc_dmasize);
1663 printf("%s: tail=%p,tailbuf=%p,tail_size=0x%08x\n",
1664 sc->sc_dev.dv_xname,
1665 esc->sc_tail, &(esc->sc_tailbuf[0]), esc->sc_tail_size);
1666 esp_hex_dump(&(esc->sc_tailbuf[0]),sizeof(esc->sc_tailbuf));
1667 }
1668 }
1669 #endif
1670
1671 esc->sc_main = 0;
1672 esc->sc_main_size = 0;
1673 esc->sc_tail = 0;
1674 esc->sc_tail_size = 0;
1675
1676 esc->sc_datain = -1;
1677 /* esc->sc_dmaaddr = 0; */
1678 /* esc->sc_dmalen = 0; */
1679 /* esc->sc_dmasize = 0; */
1680
1681 esc->sc_loaded = 0;
1682
1683 esc->sc_begin = 0;
1684 esc->sc_begin_size = 0;
1685
1686 #ifdef ESP_DEBUG
1687 if (esp_debug) {
1688 char sbuf[256];
1689
1690 bitmask_snprintf((*(volatile u_long *)IIOV(NEXT_P_INTRSTAT)),
1691 NEXT_INTR_BITS, sbuf, sizeof(sbuf));
1692 printf(" *intrstat = 0x%s\n", sbuf);
1693
1694 bitmask_snprintf((*(volatile u_long *)IIOV(NEXT_P_INTRMASK)),
1695 NEXT_INTR_BITS, sbuf, sizeof(sbuf));
1696 printf(" *intrmask = 0x%s\n", sbuf);
1697 }
1698 #endif
1699 }
1700