esp.c revision 1.9 1 /* $NetBSD: esp.c,v 1.9 1998/11/19 21:47:39 thorpej 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/types.h>
85 #include <sys/param.h>
86 #include <sys/systm.h>
87 #include <sys/kernel.h>
88 #include <sys/errno.h>
89 #include <sys/ioctl.h>
90 #include <sys/device.h>
91 #include <sys/buf.h>
92 #include <sys/proc.h>
93 #include <sys/user.h>
94 #include <sys/queue.h>
95
96 #include <dev/scsipi/scsi_all.h>
97 #include <dev/scsipi/scsipi_all.h>
98 #include <dev/scsipi/scsiconf.h>
99 #include <dev/scsipi/scsi_message.h>
100
101 #include <machine/bus.h>
102 #include <machine/autoconf.h>
103 #include <machine/cpu.h>
104
105 #include <dev/ic/ncr53c9xreg.h>
106 #include <dev/ic/ncr53c9xvar.h>
107
108 #include <next68k/next68k/isr.h>
109
110 #include <next68k/dev/nextdmareg.h>
111 #include <next68k/dev/nextdmavar.h>
112
113 #include "espreg.h"
114 #include "espvar.h"
115
116 #if 1
117 #define ESP_DEBUG
118 #endif
119
120 #ifdef ESP_DEBUG
121 #define DPRINTF(x) printf x;
122 #else
123 #define DPRINTF(x)
124 #endif
125
126
127 void espattach_intio __P((struct device *, struct device *, void *));
128 int espmatch_intio __P((struct device *, struct cfdata *, void *));
129
130 /* DMA callbacks */
131 bus_dmamap_t esp_dmacb_continue __P((void *arg));
132 void esp_dmacb_completed __P((bus_dmamap_t map, void *arg));
133 void esp_dmacb_shutdown __P((void *arg));
134
135 /* Linkup to the rest of the kernel */
136 struct cfattach esp_ca = {
137 sizeof(struct esp_softc), espmatch_intio, espattach_intio
138 };
139
140 struct scsipi_device esp_dev = {
141 NULL, /* Use default error handler */
142 NULL, /* have a queue, served by this */
143 NULL, /* have no async handler */
144 NULL, /* Use default 'done' routine */
145 };
146
147 /*
148 * Functions and the switch for the MI code.
149 */
150 u_char esp_read_reg __P((struct ncr53c9x_softc *, int));
151 void esp_write_reg __P((struct ncr53c9x_softc *, int, u_char));
152 int esp_dma_isintr __P((struct ncr53c9x_softc *));
153 void esp_dma_reset __P((struct ncr53c9x_softc *));
154 int esp_dma_intr __P((struct ncr53c9x_softc *));
155 int esp_dma_setup __P((struct ncr53c9x_softc *, caddr_t *,
156 size_t *, int, size_t *));
157 void esp_dma_go __P((struct ncr53c9x_softc *));
158 void esp_dma_stop __P((struct ncr53c9x_softc *));
159 int esp_dma_isactive __P((struct ncr53c9x_softc *));
160
161 struct ncr53c9x_glue esp_glue = {
162 esp_read_reg,
163 esp_write_reg,
164 esp_dma_isintr,
165 esp_dma_reset,
166 esp_dma_intr,
167 esp_dma_setup,
168 esp_dma_go,
169 esp_dma_stop,
170 esp_dma_isactive,
171 NULL, /* gl_clear_latched_intr */
172 };
173
174 int
175 espmatch_intio(parent, cf, aux)
176 struct device *parent;
177 struct cfdata *cf;
178 void *aux;
179 {
180 /* should probably probe here */
181 /* Should also probably set up data from config */
182
183 #if 1
184 /* this code isn't working yet, don't match on it */
185 return(0);
186 #else
187 return(1);
188 #endif
189 }
190
191 void
192 espattach_intio(parent, self, aux)
193 struct device *parent, *self;
194 void *aux;
195 {
196 struct esp_softc *esc = (void *)self;
197 struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x;
198
199 esc->sc_bst = NEXT68K_INTIO_BUS_SPACE;
200 if (bus_space_map(esc->sc_bst, NEXT_P_SCSI,
201 ESP_DEVICE_SIZE, 0, &esc->sc_bsh)) {
202 panic("\n%s: can't map ncr53c90 registers",
203 sc->sc_dev.dv_xname);
204 }
205
206 sc->sc_id = 7;
207 sc->sc_freq = 20; /* Mhz */
208
209 /*
210 * Set up glue for MI code early; we use some of it here.
211 */
212 sc->sc_glue = &esp_glue;
213
214 /*
215 * XXX More of this should be in ncr53c9x_attach(), but
216 * XXX should we really poke around the chip that much in
217 * XXX the MI code? Think about this more...
218 */
219
220 /*
221 * It is necessary to try to load the 2nd config register here,
222 * to find out what rev the esp chip is, else the ncr53c9x_reset
223 * will not set up the defaults correctly.
224 */
225 sc->sc_cfg1 = sc->sc_id | NCRCFG1_PARENB;
226 sc->sc_cfg2 = NCRCFG2_SCSI2 | NCRCFG2_RPE;
227 sc->sc_cfg3 = NCRCFG3_CDB;
228 NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
229
230 if ((NCR_READ_REG(sc, NCR_CFG2) & ~NCRCFG2_RSVD) !=
231 (NCRCFG2_SCSI2 | NCRCFG2_RPE)) {
232 sc->sc_rev = NCR_VARIANT_ESP100;
233 } else {
234 sc->sc_cfg2 = NCRCFG2_SCSI2;
235 NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
236 sc->sc_cfg3 = 0;
237 NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
238 sc->sc_cfg3 = (NCRCFG3_CDB | NCRCFG3_FCLK);
239 NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
240 if (NCR_READ_REG(sc, NCR_CFG3) !=
241 (NCRCFG3_CDB | NCRCFG3_FCLK)) {
242 sc->sc_rev = NCR_VARIANT_ESP100A;
243 } else {
244 /* NCRCFG2_FE enables > 64K transfers */
245 sc->sc_cfg2 |= NCRCFG2_FE;
246 sc->sc_cfg3 = 0;
247 NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
248 sc->sc_rev = NCR_VARIANT_ESP200;
249 }
250 }
251
252 /*
253 * XXX minsync and maxxfer _should_ be set up in MI code,
254 * XXX but it appears to have some dependency on what sort
255 * XXX of DMA we're hooked up to, etc.
256 */
257
258 /*
259 * This is the value used to start sync negotiations
260 * Note that the NCR register "SYNCTP" is programmed
261 * in "clocks per byte", and has a minimum value of 4.
262 * The SCSI period used in negotiation is one-fourth
263 * of the time (in nanoseconds) needed to transfer one byte.
264 * Since the chip's clock is given in MHz, we have the following
265 * formula: 4 * period = (1000 / freq) * 4
266 */
267 sc->sc_minsync = 1000 / sc->sc_freq;
268
269 /*
270 * Alas, we must now modify the value a bit, because it's
271 * only valid when can switch on FASTCLK and FASTSCSI bits
272 * in config register 3...
273 */
274 switch (sc->sc_rev) {
275 case NCR_VARIANT_ESP100:
276 sc->sc_maxxfer = 64 * 1024;
277 sc->sc_minsync = 0; /* No synch on old chip? */
278 break;
279
280 case NCR_VARIANT_ESP100A:
281 sc->sc_maxxfer = 64 * 1024;
282 /* Min clocks/byte is 5 */
283 sc->sc_minsync = ncr53c9x_cpb2stp(sc, 5);
284 break;
285
286 case NCR_VARIANT_ESP200:
287 sc->sc_maxxfer = 16 * 1024 * 1024;
288 /* XXX - do actually set FAST* bits */
289 break;
290 }
291
292 /* @@@ Some ESP_DCTL bits probably need setting */
293 NCR_WRITE_REG(sc, ESP_DCTL,
294 ESPDCTL_20MHZ | ESPDCTL_INTENB | ESPDCTL_RESET);
295 DELAY(10);
296 NCR_WRITE_REG(sc, ESP_DCTL, ESPDCTL_20MHZ | ESPDCTL_INTENB);
297 DELAY(10);
298
299 /* Set up SCSI DMA */
300 {
301 esc->sc_scsi_dma.nd_bst = NEXT68K_INTIO_BUS_SPACE;
302
303 if (bus_space_map(esc->sc_scsi_dma.nd_bst, NEXT_P_SCSI_CSR,
304 sizeof(struct dma_dev),0, &esc->sc_scsi_dma.nd_bsh)) {
305 panic("\n%s: can't map scsi DMA registers",
306 sc->sc_dev.dv_xname);
307 }
308
309 esc->sc_scsi_dma.nd_intr = NEXT_I_SCSI_DMA;
310 esc->sc_scsi_dma.nd_chaining_flag = 0;
311 esc->sc_scsi_dma.nd_shutdown_cb = &esp_dmacb_shutdown;
312 esc->sc_scsi_dma.nd_continue_cb = &esp_dmacb_continue;
313 esc->sc_scsi_dma.nd_completed_cb = &esp_dmacb_completed;
314 esc->sc_scsi_dma.nd_cb_arg = sc;
315 nextdma_config(&esc->sc_scsi_dma);
316 nextdma_init(&esc->sc_scsi_dma);
317
318 {
319 int error;
320 if ((error = bus_dmamap_create(esc->sc_scsi_dma.nd_dmat,
321 sc->sc_maxxfer, 1, sc->sc_maxxfer,
322 0, BUS_DMA_ALLOCNOW, &esc->sc_dmamap)) != 0) {
323 panic("%s: can't create i/o DMA map, error = %d",
324 sc->sc_dev.dv_xname,error);
325 }
326 }
327 }
328
329 #if 0
330 /* Turn on target selection using the `dma' method */
331 ncr53c9x_dmaselect = 1;
332 #else
333 ncr53c9x_dmaselect = 0;
334 #endif
335
336 esc->sc_slop_bgn_addr = 0;
337 esc->sc_slop_bgn_size = 0;
338 esc->sc_slop_end_addr = 0;
339 esc->sc_slop_end_size = 0;
340 esc->sc_datain = -1;
341
342 /* Establish interrupt channel */
343 isrlink_autovec((int(*)__P((void*)))ncr53c9x_intr, sc,
344 NEXT_I_IPL(NEXT_I_SCSI), 0);
345 INTR_ENABLE(NEXT_I_SCSI);
346
347 /* register interrupt stats */
348 evcnt_attach(&sc->sc_dev, "intr", &sc->sc_intrcnt);
349
350 /* Do the common parts of attachment. */
351 sc->sc_adapter.scsipi_cmd = ncr53c9x_scsi_cmd;
352 sc->sc_adapter.scsipi_minphys = minphys;
353 ncr53c9x_attach(sc, &esp_dev);
354 }
355
356 /*
357 * Glue functions.
358 */
359
360 u_char
361 esp_read_reg(sc, reg)
362 struct ncr53c9x_softc *sc;
363 int reg;
364 {
365 struct esp_softc *esc = (struct esp_softc *)sc;
366
367 return(bus_space_read_1(esc->sc_bst, esc->sc_bsh, reg));
368 }
369
370 void
371 esp_write_reg(sc, reg, val)
372 struct ncr53c9x_softc *sc;
373 int reg;
374 u_char val;
375 {
376 struct esp_softc *esc = (struct esp_softc *)sc;
377
378 bus_space_write_1(esc->sc_bst, esc->sc_bsh, reg, val);
379 }
380
381 int
382 esp_dma_isintr(sc)
383 struct ncr53c9x_softc *sc;
384 {
385 struct esp_softc *esc = (struct esp_softc *)sc;
386
387 int r = (INTR_OCCURRED(NEXT_I_SCSI));
388
389 if (r) {
390 DPRINTF(("esp_dma_isintr = %d\n",r));
391
392 if (esc->sc_datain) {
393 NCR_WRITE_REG(sc, ESP_DCTL,
394 ESPDCTL_20MHZ | ESPDCTL_INTENB | ESPDCTL_DMARD);
395 } else {
396 NCR_WRITE_REG(sc, ESP_DCTL,
397 ESPDCTL_20MHZ | ESPDCTL_INTENB);
398 }
399 }
400
401 return (r);
402 }
403
404 void
405 esp_dma_reset(sc)
406 struct ncr53c9x_softc *sc;
407 {
408 struct esp_softc *esc = (struct esp_softc *)sc;
409
410 nextdma_reset(&esc->sc_scsi_dma);
411
412 if (esc->sc_dmamap->dm_mapsize != 0) {
413 bus_dmamap_unload(esc->sc_scsi_dma.nd_dmat, esc->sc_dmamap);
414 }
415
416 esc->sc_slop_bgn_addr = 0;
417 esc->sc_slop_bgn_size = 0;
418 esc->sc_slop_end_addr = 0;
419 esc->sc_slop_end_size = 0;
420 esc->sc_datain = -1;
421 }
422
423 int
424 esp_dma_intr(sc)
425 struct ncr53c9x_softc *sc;
426 {
427 int trans;
428 int resid;
429 int datain;
430 struct esp_softc *esc = (struct esp_softc *)sc;
431
432 datain = esc->sc_datain;
433
434 DPRINTF(("esp_dma_intr resetting dma\n"));
435
436 /* If the dma hasn't finished when we are in a scsi
437 * interrupt. Then, "Houston, we have a problem."
438 * Stop DMA and figure out how many bytes were transferred
439 */
440 esp_dma_reset(sc);
441
442 resid = 0;
443
444 /*
445 * If a transfer onto the SCSI bus gets interrupted by the device
446 * (e.g. for a SAVEPOINTER message), the data in the FIFO counts
447 * as residual since the ESP counter registers get decremented as
448 * bytes are clocked into the FIFO.
449 */
450
451 if (! datain) {
452 resid = (NCR_READ_REG(sc, NCR_FFLAG) & NCRFIFO_FF);
453 if (resid) {
454 NCR_DMA(("dmaintr: empty esp FIFO of %d ", resid));
455 NCRCMD(sc, NCRCMD_FLUSH);
456 DELAY(1);
457 }
458 }
459
460 if ((sc->sc_espstat & NCRSTAT_TC) == 0) {
461 /*
462 * `Terminal count' is off, so read the residue
463 * out of the ESP counter registers.
464 */
465 resid += (NCR_READ_REG(sc, NCR_TCL) |
466 (NCR_READ_REG(sc, NCR_TCM) << 8) |
467 ((sc->sc_cfg2 & NCRCFG2_FE)
468 ? (NCR_READ_REG(sc, NCR_TCH) << 16)
469 : 0));
470
471 if (resid == 0 && esc->sc_dmasize == 65536 &&
472 (sc->sc_cfg2 & NCRCFG2_FE) == 0)
473 /* A transfer of 64K is encoded as `TCL=TCM=0' */
474 resid = 65536;
475 }
476
477 trans = esc->sc_dmasize - resid;
478 if (trans < 0) { /* transferred < 0 ? */
479 #if 0
480 /*
481 * This situation can happen in perfectly normal operation
482 * if the ESP is reselected while using DMA to select
483 * another target. As such, don't print the warning.
484 */
485 printf("%s: xfer (%d) > req (%d)\n",
486 esc->sc_dev.dv_xname, trans, esc->sc_dmasize);
487 #endif
488 trans = esc->sc_dmasize;
489 }
490
491 NCR_DMA(("dmaintr: tcl=%d, tcm=%d, tch=%d; trans=%d, resid=%d\n",
492 NCR_READ_REG(sc, NCR_TCL),
493 NCR_READ_REG(sc, NCR_TCM),
494 (sc->sc_cfg2 & NCRCFG2_FE)
495 ? NCR_READ_REG(sc, NCR_TCH) : 0,
496 trans, resid));
497
498 *esc->sc_dmalen -= trans;
499 *esc->sc_dmaaddr += trans;
500
501 return 0;
502 }
503
504 int
505 esp_dma_setup(sc, addr, len, datain, dmasize)
506 struct ncr53c9x_softc *sc;
507 caddr_t *addr;
508 size_t *len;
509 int datain;
510 size_t *dmasize;
511 {
512 struct esp_softc *esc = (struct esp_softc *)sc;
513
514 /* Save these in case we have to abort DMA */
515 esc->sc_dmaaddr = addr;
516 esc->sc_dmalen = len;
517 esc->sc_dmasize = *dmasize;
518
519 DPRINTF(("esp_dma_setup(0x%08lx,0x%08lx)\n",*addr,*dmasize));
520
521 #ifdef DIAGNOSTIC
522 if ((esc->sc_datain != -1) ||
523 (esc->sc_dmamap->dm_mapsize != 0)) {
524 panic("%s: map already loaded in esp_dma_setup\n"
525 "\tdatain = %d\n\tmapsize=%d",
526 sc->sc_dev.dv_xname,esc->sc_datain,esc->sc_dmamap->dm_mapsize);
527 }
528 #endif
529
530 /* Deal with DMA alignment issues, by stuffing the FIFO.
531 * This assumes that if bus_dmamap_load is given an aligned
532 * buffer, then it will generate aligned hardware addresses
533 * to give to the device. Perhaps that is not a good assumption,
534 * but it is probably true. [dbj (at) netbsd.org:19980719.0135EDT]
535 */
536 {
537 int slop_bgn_size; /* # bytes to be fifo'd at beginning */
538 int slop_end_size; /* # bytes to be fifo'd at end */
539
540 {
541 u_long bgn = (u_long)(*addr);
542 u_long end = (u_long)(*addr+*dmasize);
543
544 slop_bgn_size = DMA_BEGINALIGNMENT-(bgn % DMA_BEGINALIGNMENT);
545 if (slop_bgn_size == DMA_BEGINALIGNMENT) slop_bgn_size = 0;
546 slop_end_size = end % DMA_ENDALIGNMENT;
547 }
548
549 /* Check to make sure we haven't counted the slop twice
550 * as would happen for a very short dma buffer */
551 if (slop_bgn_size+slop_end_size > *dmasize) {
552 #if defined(DIAGNOSTIC)
553 if ((slop_bgn_size != *dmasize) ||
554 (slop_end_size != *dmasize)) {
555 panic("%s: confused alignment calculation\n"
556 "\tslop_bgn_size %d\n\tslop_end_size %d\n\tdmasize %d",
557 sc->sc_dev.dv_xname,slop_bgn_size,slop_end_size,*dmasize);
558 }
559 #endif
560 slop_end_size = 0;
561 }
562
563 if (slop_bgn_size+slop_end_size < *dmasize) {
564 int error;
565 error = bus_dmamap_load(esc->sc_scsi_dma.nd_dmat,
566 esc->sc_dmamap,
567 *addr+slop_bgn_size,
568 *dmasize-(slop_bgn_size+slop_end_size),
569 NULL, BUS_DMA_NOWAIT);
570 if (error) {
571 panic("%s: can't load dma map. error = %d",
572 sc->sc_dev.dv_xname, error);
573 }
574
575 } else {
576 /* If there's no DMA, then coalesce the fifo buffers */
577 slop_bgn_size += slop_end_size;
578 slop_end_size = 0;
579 }
580
581 esc->sc_slop_bgn_addr = *addr;
582 esc->sc_slop_bgn_size = slop_bgn_size;
583 esc->sc_slop_end_addr = (*addr+*dmasize)-slop_end_size;
584 esc->sc_slop_end_size = slop_end_size;
585 }
586
587 esc->sc_datain = datain;
588
589 return (0);
590 }
591
592 void
593 esp_dma_go(sc)
594 struct ncr53c9x_softc *sc;
595 {
596 struct esp_softc *esc = (struct esp_softc *)sc;
597
598 DPRINTF(("esp_dma_go(datain = %d)\n",esc->sc_datain));
599
600 DPRINTF(("\tbgn slop = %d\n\tend slop = %d\n\tmapsize = %d\n",
601 esc->sc_slop_bgn_size,esc->sc_slop_end_size,
602 esc->sc_dmamap->dm_mapsize));
603
604 DPRINTF(("esp fifo size = %d\n",
605 (NCR_READ_REG(sc, NCR_FFLAG) & NCRFIFO_FF)));
606
607 if (esc->sc_datain) {
608 NCR_WRITE_REG(sc, ESP_DCTL,
609 ESPDCTL_20MHZ | ESPDCTL_INTENB | ESPDCTL_DMARD);
610 } else {
611 NCR_WRITE_REG(sc, ESP_DCTL,
612 ESPDCTL_20MHZ | ESPDCTL_INTENB);
613 }
614
615 if (esc->sc_datain) {
616 int i;
617 #ifdef DIAGNOSTIC
618 #if 0 /* This is a fine thing to happen */
619 int n = (NCR_READ_REG(sc, NCR_FFLAG) & NCRFIFO_FF);
620 if (n != esc->sc_slop_bgn_size) {
621 panic("%s: Unexpected data in fifo n = %d, expecting %d ",
622 sc->sc_dev.dv_xname, n, esc->sc_slop_bgn_size);
623 }
624 #endif
625 #endif
626 for(i=0;i<esc->sc_slop_bgn_size;i++) {
627 esc->sc_slop_bgn_addr[i]=NCR_READ_REG(sc, NCR_FIFO);
628 }
629
630 } else {
631 int i;
632 for(i=0;i<esc->sc_slop_bgn_size;i++) {
633 NCR_WRITE_REG(sc, NCR_FIFO, esc->sc_slop_bgn_addr[i]);
634 }
635
636 DPRINTF(("esp fifo size = %d\n",
637 (NCR_READ_REG(sc, NCR_FFLAG) & NCRFIFO_FF)));
638 }
639
640 if (esc->sc_dmamap->dm_mapsize != 0) {
641 if (esc->sc_datain) {
642 NCR_WRITE_REG(sc, ESP_DCTL,
643 ESPDCTL_20MHZ | ESPDCTL_INTENB | ESPDCTL_DMAMOD | ESPDCTL_DMARD);
644 } else {
645 NCR_WRITE_REG(sc, ESP_DCTL,
646 ESPDCTL_20MHZ | ESPDCTL_INTENB | ESPDCTL_DMAMOD);
647 }
648
649
650 nextdma_start(&esc->sc_scsi_dma,
651 (esc->sc_datain ? DMACSR_READ : DMACSR_WRITE));
652 } else {
653 #if defined(DIAGNOSTIC)
654 /* verify that end slop is 0, since the shutdown
655 * callback will not be called.
656 */
657 if (esc->sc_slop_end_size != 0) {
658 panic("%s: Unexpected end slop with no DMA, slop = %d",
659 sc->sc_dev.dv_xname, esc->sc_slop_end_size);
660 }
661 #endif
662 #if 0
663 if (esc->sc_datain) {
664 NCR_WRITE_REG(sc, ESP_DCTL,
665 ESPDCTL_20MHZ | ESPDCTL_INTENB | ESPDCTL_DMARD | ESPDCTL_FLUSH);
666 } else {
667 NCR_WRITE_REG(sc, ESP_DCTL, ESPDCTL_20MHZ | ESPDCTL_INTENB);
668 NCR_WRITE_REG(sc, ESP_DCTL, ESPDCTL_20MHZ | ESPDCTL_INTENB | ESPDCTL_FLUSH);
669 NCR_WRITE_REG(sc, ESP_DCTL, ESPDCTL_20MHZ | ESPDCTL_INTENB);
670 }
671 #endif
672
673 esc->sc_datain = -1;
674 esc->sc_slop_bgn_addr = 0;
675 esc->sc_slop_bgn_size = 0;
676 esc->sc_slop_end_addr = 0;
677 esc->sc_slop_end_size = 0;
678
679 DPRINTF(("esp fifo size = %d\n",
680 (NCR_READ_REG(sc, NCR_FFLAG) & NCRFIFO_FF)));
681 }
682 }
683
684 void
685 esp_dma_stop(sc)
686 struct ncr53c9x_softc *sc;
687 {
688 panic("Not yet implemented");
689 }
690
691 int
692 esp_dma_isactive(sc)
693 struct ncr53c9x_softc *sc;
694 {
695 struct esp_softc *esc = (struct esp_softc *)sc;
696 return( !nextdma_finished(&esc->sc_scsi_dma));
697 }
698
699 /****************************************************************/
700
701 /* Internal dma callback routines */
702 bus_dmamap_t
703 esp_dmacb_continue(arg)
704 void *arg;
705 {
706 struct ncr53c9x_softc *sc = (struct ncr53c9x_softc *)arg;
707 struct esp_softc *esc = (struct esp_softc *)sc;
708
709 DPRINTF(("esp dma continue\n"));
710
711 bus_dmamap_sync(esc->sc_scsi_dma.nd_dmat, esc->sc_dmamap,
712 0, esc->sc_dmamap->dm_mapsize,
713 (esc->sc_datain ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE));
714
715 #ifdef DIAGNOSTIC
716 if ((esc->sc_datain < 0) || (esc->sc_datain > 1)) {
717 panic("%s: map not loaded in dma continue callback, datain = %d",
718 sc->sc_dev.dv_xname,esc->sc_datain);
719 }
720 #endif
721
722 return(esc->sc_dmamap);
723 }
724
725 void
726 esp_dmacb_completed(map, arg)
727 bus_dmamap_t map;
728 void *arg;
729 {
730 struct ncr53c9x_softc *sc = (struct ncr53c9x_softc *)arg;
731 struct esp_softc *esc = (struct esp_softc *)sc;
732
733 DPRINTF(("esp dma completed\n"));
734
735 #ifdef DIAGNOSTIC
736 if ((esc->sc_datain < 0) || (esc->sc_datain > 1)) {
737 panic("%s: map not loaded in dma completed callback, datain = %d",
738 sc->sc_dev.dv_xname,esc->sc_datain);
739 }
740 if (map != esc->sc_dmamap) {
741 panic("%s: unexpected tx completed map", sc->sc_dev.dv_xname);
742 }
743 #endif
744
745 /* @@@ Flush the fifo? */
746
747 bus_dmamap_sync(esc->sc_scsi_dma.nd_dmat, esc->sc_dmamap,
748 0, esc->sc_dmamap->dm_mapsize,
749 (esc->sc_datain ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE));
750 }
751
752 void
753 esp_dmacb_shutdown(arg)
754 void *arg;
755 {
756 struct ncr53c9x_softc *sc = (struct ncr53c9x_softc *)arg;
757 struct esp_softc *esc = (struct esp_softc *)sc;
758
759 DPRINTF(("esp dma shutdown\n"));
760
761 #ifdef DIAGNOSTIC
762 if ((esc->sc_datain < 0) || (esc->sc_datain > 1)) {
763 panic("%s: map not loaded in dma shutdown callback, datain = %d",
764 sc->sc_dev.dv_xname,esc->sc_datain);
765 }
766 #endif
767
768 bus_dmamap_unload(esc->sc_scsi_dma.nd_dmat, esc->sc_dmamap);
769
770 /* Stuff the end slop into fifo */
771
772 {
773 if (esc->sc_datain) {
774 NCR_WRITE_REG(sc, ESP_DCTL,
775 ESPDCTL_20MHZ | ESPDCTL_INTENB | ESPDCTL_DMARD);
776 } else {
777 NCR_WRITE_REG(sc, ESP_DCTL,
778 ESPDCTL_20MHZ | ESPDCTL_INTENB);
779 }
780
781 if (esc->sc_datain) {
782 int i;
783 #ifdef DIAGNOSTIC
784 int n = (NCR_READ_REG(sc, NCR_FFLAG) & NCRFIFO_FF);
785 if (n != esc->sc_slop_end_size) {
786 panic("%s: Unexpected data in fifo n = %d, expecting %d at end",
787 sc->sc_dev.dv_xname, n, esc->sc_slop_end_size);
788 }
789 #endif
790 for(i=0;i<esc->sc_slop_end_size;i++) {
791 esc->sc_slop_end_addr[i]=NCR_READ_REG(sc, NCR_FIFO);
792 }
793
794 } else {
795 int i;
796 for(i=0;i<esc->sc_slop_end_size;i++) {
797 NCR_WRITE_REG(sc, NCR_FIFO, esc->sc_slop_end_addr[i]);
798 }
799 }
800 }
801
802
803 esc->sc_datain = -1;
804 esc->sc_slop_bgn_addr = 0;
805 esc->sc_slop_bgn_size = 0;
806 esc->sc_slop_end_addr = 0;
807 esc->sc_slop_end_size = 0;
808 }
809