esp.c revision 1.34.6.4 1 /* $NetBSD: esp.c,v 1.34.6.4 2005/01/17 19:29:49 skrll Exp $ */
2
3 /*
4 * Copyright (c) 1997 Jason R. Thorpe.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed for the NetBSD Project
18 * by Jason R. Thorpe.
19 * 4. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 /*
35 * Copyright (c) 1994 Peter Galbavy
36 * All rights reserved.
37 *
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
40 * are met:
41 * 1. Redistributions of source code must retain the above copyright
42 * notice, this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must reproduce the above copyright
44 * notice, this list of conditions and the following disclaimer in the
45 * documentation and/or other materials provided with the distribution.
46 * 3. All advertising materials mentioning features or use of this software
47 * must display the following acknowledgement:
48 * This product includes software developed by Peter Galbavy
49 * 4. The name of the author may not be used to endorse or promote products
50 * derived from this software without specific prior written permission.
51 *
52 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
53 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
54 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
55 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
56 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
57 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
58 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
60 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
61 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
62 * POSSIBILITY OF SUCH DAMAGE.
63 */
64
65 /*
66 * Based on aic6360 by Jarle Greipsland
67 *
68 * Acknowledgements: Many of the algorithms used in this driver are
69 * inspired by the work of Julian Elischer (julian (at) tfs.com) and
70 * Charles Hannum (mycroft (at) duality.gnu.ai.mit.edu). Thanks a million!
71 */
72
73 /*
74 * Initial m68k mac support from Allen Briggs <briggs (at) macbsd.com>
75 * (basically consisting of the match, a bit of the attach, and the
76 * "DMA" glue functions).
77 */
78
79 #include <sys/cdefs.h>
80 __KERNEL_RCSID(0, "$NetBSD: esp.c,v 1.34.6.4 2005/01/17 19:29:49 skrll Exp $");
81
82 #include <sys/types.h>
83 #include <sys/param.h>
84 #include <sys/systm.h>
85 #include <sys/kernel.h>
86 #include <sys/errno.h>
87 #include <sys/ioctl.h>
88 #include <sys/device.h>
89 #include <sys/buf.h>
90 #include <sys/proc.h>
91 #include <sys/user.h>
92 #include <sys/queue.h>
93
94 #include <dev/scsipi/scsi_all.h>
95 #include <dev/scsipi/scsipi_all.h>
96 #include <dev/scsipi/scsiconf.h>
97 #include <dev/scsipi/scsi_message.h>
98
99 #include <machine/cpu.h>
100 #include <machine/bus.h>
101 #include <machine/param.h>
102
103 #include <dev/ic/ncr53c9xreg.h>
104 #include <dev/ic/ncr53c9xvar.h>
105
106 #include <machine/viareg.h>
107
108 #include <mac68k/obio/espvar.h>
109 #include <mac68k/obio/obiovar.h>
110
111 void espattach(struct device *, struct device *, void *);
112 int espmatch(struct device *, struct cfdata *, void *);
113
114 /* Linkup to the rest of the kernel */
115 CFATTACH_DECL(esp, sizeof(struct esp_softc),
116 espmatch, espattach, NULL, NULL);
117
118 /*
119 * Functions and the switch for the MI code.
120 */
121 u_char esp_read_reg(struct ncr53c9x_softc *, int);
122 void esp_write_reg(struct ncr53c9x_softc *, int, u_char);
123 int esp_dma_isintr(struct ncr53c9x_softc *);
124 void esp_dma_reset(struct ncr53c9x_softc *);
125 int esp_dma_intr(struct ncr53c9x_softc *);
126 int esp_dma_setup(struct ncr53c9x_softc *, caddr_t *, size_t *, int,
127 size_t *);
128 void esp_dma_go(struct ncr53c9x_softc *);
129 void esp_dma_stop(struct ncr53c9x_softc *);
130 int esp_dma_isactive(struct ncr53c9x_softc *);
131 void esp_quick_write_reg(struct ncr53c9x_softc *, int, u_char);
132 int esp_quick_dma_intr(struct ncr53c9x_softc *);
133 int esp_quick_dma_setup(struct ncr53c9x_softc *, caddr_t *, size_t *, int,
134 size_t *);
135 void esp_quick_dma_go(struct ncr53c9x_softc *);
136
137 void esp_intr(void *);
138 void esp_dualbus_intr(void *);
139 static struct esp_softc *esp0, *esp1;
140
141 static __inline__ int esp_dafb_have_dreq(struct esp_softc *);
142 static __inline__ int esp_iosb_have_dreq(struct esp_softc *);
143 int (*esp_have_dreq)(struct esp_softc *);
144
145 struct ncr53c9x_glue esp_glue = {
146 esp_read_reg,
147 esp_write_reg,
148 esp_dma_isintr,
149 esp_dma_reset,
150 esp_dma_intr,
151 esp_dma_setup,
152 esp_dma_go,
153 esp_dma_stop,
154 esp_dma_isactive,
155 NULL, /* gl_clear_latched_intr */
156 };
157
158 int
159 espmatch(struct device *parent, struct cfdata *cf, void *aux)
160 {
161 int found = 0;
162
163 if ((cf->cf_unit == 0) && mac68k_machine.scsi96) {
164 found = 1;
165 }
166 if ((cf->cf_unit == 1) && mac68k_machine.scsi96_2) {
167 found = 1;
168 }
169
170 return found;
171 }
172
173 /*
174 * Attach this instance, and then all the sub-devices
175 */
176 void
177 espattach(struct device *parent, struct device *self, void *aux)
178 {
179 struct obio_attach_args *oa = (struct obio_attach_args *)aux;
180 extern vaddr_t SCSIBase;
181 struct esp_softc *esc = (void *)self;
182 struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x;
183 int quick = 0;
184 unsigned long reg_offset;
185
186 reg_offset = SCSIBase - IOBase;
187 esc->sc_tag = oa->oa_tag;
188
189 /*
190 * For Wombat, Primus and Optimus motherboards, DREQ is
191 * visible on bit 0 of the IOSB's emulated VIA2 vIFR (and
192 * the scsi registers are offset 0x1000 bytes from IOBase).
193 *
194 * For the Q700/900/950 it's at f9800024 for bus 0 and
195 * f9800028 for bus 1 (900/950). For these machines, that is also
196 * a (12-bit) configuration register for DAFB's control of the
197 * pseudo-DMA timing. The default value is 0x1d1.
198 */
199 esp_have_dreq = esp_dafb_have_dreq;
200 if (sc->sc_dev.dv_unit == 0) {
201 if (reg_offset == 0x10000) {
202 quick = 1;
203 esp_have_dreq = esp_iosb_have_dreq;
204 } else if (reg_offset == 0x18000) {
205 quick = 0;
206 } else {
207 if (bus_space_map(esc->sc_tag, 0xf9800024,
208 4, 0, &esc->sc_bsh)) {
209 printf("failed to map 4 at 0xf9800024.\n");
210 } else {
211 quick = 1;
212 bus_space_write_4(esc->sc_tag,
213 esc->sc_bsh, 0, 0x1d1);
214 }
215 }
216 } else {
217 if (bus_space_map(esc->sc_tag, 0xf9800028,
218 4, 0, &esc->sc_bsh)) {
219 printf("failed to map 4 at 0xf9800028.\n");
220 } else {
221 quick = 1;
222 bus_space_write_4(esc->sc_tag, esc->sc_bsh, 0, 0x1d1);
223 }
224 }
225 if (quick) {
226 esp_glue.gl_write_reg = esp_quick_write_reg;
227 esp_glue.gl_dma_intr = esp_quick_dma_intr;
228 esp_glue.gl_dma_setup = esp_quick_dma_setup;
229 esp_glue.gl_dma_go = esp_quick_dma_go;
230 }
231
232 /*
233 * Set up the glue for MI code early; we use some of it here.
234 */
235 sc->sc_glue = &esp_glue;
236
237 /*
238 * Save the regs
239 */
240 if (sc->sc_dev.dv_unit == 0) {
241 esp0 = esc;
242
243 esc->sc_reg = (volatile u_char *) SCSIBase;
244 via2_register_irq(VIA2_SCSIIRQ, esp_intr, esc);
245 esc->irq_mask = V2IF_SCSIIRQ;
246 if (reg_offset == 0x10000) {
247 /* From the Q650 developer's note */
248 sc->sc_freq = 16500000;
249 } else {
250 sc->sc_freq = 25000000;
251 }
252
253 if (esp_glue.gl_dma_go == esp_quick_dma_go) {
254 printf(" (quick)");
255 }
256 } else {
257 esp1 = esc;
258
259 esc->sc_reg = (volatile u_char *) SCSIBase + 0x402;
260 via2_register_irq(VIA2_SCSIIRQ, esp_dualbus_intr, NULL);
261 esc->irq_mask = 0;
262 sc->sc_freq = 25000000;
263
264 if (esp_glue.gl_dma_go == esp_quick_dma_go) {
265 printf(" (quick)");
266 }
267 }
268
269 printf(": address %p", esc->sc_reg);
270
271 sc->sc_id = 7;
272
273 /* gimme Mhz */
274 sc->sc_freq /= 1000000;
275
276 /*
277 * It is necessary to try to load the 2nd config register here,
278 * to find out what rev the esp chip is, else the esp_reset
279 * will not set up the defaults correctly.
280 */
281 sc->sc_cfg1 = sc->sc_id; /* | NCRCFG1_PARENB; */
282 sc->sc_cfg2 = NCRCFG2_SCSI2;
283 sc->sc_cfg3 = 0;
284 sc->sc_rev = NCR_VARIANT_NCR53C96;
285
286 /*
287 * This is the value used to start sync negotiations
288 * Note that the NCR register "SYNCTP" is programmed
289 * in "clocks per byte", and has a minimum value of 4.
290 * The SCSI period used in negotiation is one-fourth
291 * of the time (in nanoseconds) needed to transfer one byte.
292 * Since the chip's clock is given in MHz, we have the following
293 * formula: 4 * period = (1000 / freq) * 4
294 */
295 sc->sc_minsync = 1000 / sc->sc_freq;
296
297 /* We need this to fit into the TCR... */
298 sc->sc_maxxfer = 64 * 1024;
299
300 if (!quick) {
301 sc->sc_minsync = 0; /* No synchronous xfers w/o DMA */
302 sc->sc_maxxfer = 8 * 1024;
303 }
304
305 /*
306 * Configure interrupts.
307 */
308 if (esc->irq_mask) {
309 via2_reg(vPCR) = 0x22;
310 via2_reg(vIFR) = esc->irq_mask;
311 via2_reg(vIER) = 0x80 | esc->irq_mask;
312 }
313
314 /*
315 * Now try to attach all the sub-devices
316 */
317 sc->sc_adapter.adapt_minphys = minphys;
318 sc->sc_adapter.adapt_request = ncr53c9x_scsipi_request;
319 ncr53c9x_attach(sc);
320 }
321
322 /*
323 * Glue functions.
324 */
325
326 u_char
327 esp_read_reg(struct ncr53c9x_softc *sc, int reg)
328 {
329 struct esp_softc *esc = (struct esp_softc *)sc;
330
331 return esc->sc_reg[reg * 16];
332 }
333
334 void
335 esp_write_reg(struct ncr53c9x_softc *sc, int reg, u_char val)
336 {
337 struct esp_softc *esc = (struct esp_softc *)sc;
338 u_char v = val;
339
340 if (reg == NCR_CMD && v == (NCRCMD_TRANS|NCRCMD_DMA)) {
341 v = NCRCMD_TRANS;
342 }
343 esc->sc_reg[reg * 16] = v;
344 }
345
346 void
347 esp_dma_stop(struct ncr53c9x_softc *sc)
348 {
349 }
350
351 int
352 esp_dma_isactive(struct ncr53c9x_softc *sc)
353 {
354 struct esp_softc *esc = (struct esp_softc *)sc;
355
356 return esc->sc_active;
357 }
358
359 int
360 esp_dma_isintr(struct ncr53c9x_softc *sc)
361 {
362 struct esp_softc *esc = (struct esp_softc *)sc;
363
364 return esc->sc_reg[NCR_STAT * 16] & 0x80;
365 }
366
367 void
368 esp_dma_reset(struct ncr53c9x_softc *sc)
369 {
370 struct esp_softc *esc = (struct esp_softc *)sc;
371
372 esc->sc_active = 0;
373 esc->sc_tc = 0;
374 }
375
376 int
377 esp_dma_intr(struct ncr53c9x_softc *sc)
378 {
379 struct esp_softc *esc = (struct esp_softc *)sc;
380 volatile u_char *cmdreg, *intrreg, *statreg, *fiforeg;
381 u_char *p;
382 u_int espphase, espstat, espintr;
383 int cnt, s;
384
385 if (esc->sc_active == 0) {
386 printf("dma_intr--inactive DMA\n");
387 return -1;
388 }
389
390 if ((sc->sc_espintr & NCRINTR_BS) == 0) {
391 esc->sc_active = 0;
392 return 0;
393 }
394
395 cnt = *esc->sc_dmalen;
396 if (*esc->sc_dmalen == 0) {
397 printf("data interrupt, but no count left.");
398 }
399
400 p = *esc->sc_dmaaddr;
401 espphase = sc->sc_phase;
402 espstat = (u_int) sc->sc_espstat;
403 espintr = (u_int) sc->sc_espintr;
404 cmdreg = esc->sc_reg + NCR_CMD * 16;
405 fiforeg = esc->sc_reg + NCR_FIFO * 16;
406 statreg = esc->sc_reg + NCR_STAT * 16;
407 intrreg = esc->sc_reg + NCR_INTR * 16;
408 do {
409 if (esc->sc_datain) {
410 *p++ = *fiforeg;
411 cnt--;
412 if (espphase == DATA_IN_PHASE) {
413 *cmdreg = NCRCMD_TRANS;
414 } else {
415 esc->sc_active = 0;
416 }
417 } else {
418 if ( (espphase == DATA_OUT_PHASE)
419 || (espphase == MESSAGE_OUT_PHASE)) {
420 *fiforeg = *p++;
421 cnt--;
422 *cmdreg = NCRCMD_TRANS;
423 } else {
424 esc->sc_active = 0;
425 }
426 }
427
428 if (esc->sc_active) {
429 while (!(*statreg & 0x80));
430 s = splhigh();
431 espstat = *statreg;
432 espintr = *intrreg;
433 espphase = (espintr & NCRINTR_DIS)
434 ? /* Disconnected */ BUSFREE_PHASE
435 : espstat & PHASE_MASK;
436 splx(s);
437 }
438 } while (esc->sc_active && (espintr & NCRINTR_BS));
439 sc->sc_phase = espphase;
440 sc->sc_espstat = (u_char) espstat;
441 sc->sc_espintr = (u_char) espintr;
442 *esc->sc_dmaaddr = p;
443 *esc->sc_dmalen = cnt;
444
445 if (*esc->sc_dmalen == 0) {
446 esc->sc_tc = NCRSTAT_TC;
447 }
448 sc->sc_espstat |= esc->sc_tc;
449 return 0;
450 }
451
452 int
453 esp_dma_setup(struct ncr53c9x_softc *sc, caddr_t *addr, size_t *len, int datain,
454 size_t *dmasize)
455 {
456 struct esp_softc *esc = (struct esp_softc *)sc;
457
458 esc->sc_dmaaddr = addr;
459 esc->sc_dmalen = len;
460 esc->sc_datain = datain;
461 esc->sc_dmasize = *dmasize;
462 esc->sc_tc = 0;
463
464 return 0;
465 }
466
467 void
468 esp_dma_go(struct ncr53c9x_softc *sc)
469 {
470 struct esp_softc *esc = (struct esp_softc *)sc;
471
472 if (esc->sc_datain == 0) {
473 esc->sc_reg[NCR_FIFO * 16] = **esc->sc_dmaaddr;
474 (*esc->sc_dmalen)--;
475 (*esc->sc_dmaaddr)++;
476 }
477 esc->sc_active = 1;
478 }
479
480 void
481 esp_quick_write_reg(struct ncr53c9x_softc *sc, int reg, u_char val)
482 {
483 struct esp_softc *esc = (struct esp_softc *)sc;
484
485 esc->sc_reg[reg * 16] = val;
486 }
487
488 #if DEBUG
489 int mac68k_esp_debug=0;
490 #endif
491
492 int
493 esp_quick_dma_intr(struct ncr53c9x_softc *sc)
494 {
495 struct esp_softc *esc = (struct esp_softc *)sc;
496 int trans=0, resid=0;
497
498 if (esc->sc_active == 0)
499 panic("dma_intr--inactive DMA");
500
501 esc->sc_active = 0;
502
503 if (esc->sc_dmasize == 0) {
504 int res;
505
506 res = NCR_READ_REG(sc, NCR_TCL);
507 res += NCR_READ_REG(sc, NCR_TCM) << 8;
508 /* This can happen in the case of a TRPAD operation */
509 /* Pretend that it was complete */
510 sc->sc_espstat |= NCRSTAT_TC;
511 #if DEBUG
512 if (mac68k_esp_debug) {
513 printf("dmaintr: DMA xfer of zero xferred %d\n",
514 65536 - res);
515 }
516 #endif
517 return 0;
518 }
519
520 if ((sc->sc_espstat & NCRSTAT_TC) == 0) {
521 if (esc->sc_datain == 0) {
522 resid = NCR_READ_REG(sc, NCR_FFLAG) & 0x1f;
523 #if DEBUG
524 if (mac68k_esp_debug) {
525 printf("Write FIFO residual %d bytes\n", resid);
526 }
527 #endif
528 }
529 resid += NCR_READ_REG(sc, NCR_TCL);
530 resid += NCR_READ_REG(sc, NCR_TCM) << 8;
531 if (resid == 0)
532 resid = 65536;
533 }
534
535 trans = esc->sc_dmasize - resid;
536 if (trans < 0) {
537 printf("dmaintr: trans < 0????");
538 trans = *esc->sc_dmalen;
539 }
540
541 NCR_DMA(("dmaintr: trans %d, resid %d.\n", trans, resid));
542 #if DEBUG
543 if (mac68k_esp_debug) {
544 printf("eqd_intr: trans %d, resid %d.\n", trans, resid);
545 }
546 #endif
547 *esc->sc_dmaaddr += trans;
548 *esc->sc_dmalen -= trans;
549
550 return 0;
551 }
552
553 int
554 esp_quick_dma_setup(struct ncr53c9x_softc *sc, caddr_t *addr, size_t *len,
555 int datain, size_t *dmasize)
556 {
557 struct esp_softc *esc = (struct esp_softc *)sc;
558
559 esc->sc_dmaaddr = addr;
560 esc->sc_dmalen = len;
561
562 if (*len & 1) {
563 esc->sc_pad = 1;
564 } else {
565 esc->sc_pad = 0;
566 }
567
568 esc->sc_datain = datain;
569 esc->sc_dmasize = *dmasize;
570
571 #if DIAGNOSTIC
572 if (esc->sc_dmasize == 0) {
573 /* This can happen in the case of a TRPAD operation */
574 }
575 #endif
576 #if DEBUG
577 if (mac68k_esp_debug) {
578 printf("eqd_setup: addr %lx, len %lx, in? %d, dmasize %lx\n",
579 (long) *addr, (long) *len, datain, (long) esc->sc_dmasize);
580 }
581 #endif
582
583 return 0;
584 }
585
586 static __inline__ int
587 esp_dafb_have_dreq(struct esp_softc *esc)
588 {
589 return (*(volatile u_int32_t *)(esc->sc_bsh.base) & 0x200);
590 }
591
592 static __inline__ int
593 esp_iosb_have_dreq(struct esp_softc *esc)
594 {
595 return (via2_reg(vIFR) & V2IF_SCSIDRQ);
596 }
597
598 static volatile int espspl=-1;
599
600 /*
601 * Apple "DMA" is weird.
602 *
603 * Basically, the CPU acts like the DMA controller. The DREQ/ off the
604 * chip goes to a register that we've mapped at attach time (on the
605 * IOSB or DAFB, depending on the machine). Apple also provides some
606 * space for which the memory controller handshakes data to/from the
607 * NCR chip with the DACK/ line. This space appears to be mapped over
608 * and over, every 4 bytes, but only the lower 16 bits are valid (but
609 * reading the upper 16 bits will handshake DACK/ just fine, so if you
610 * read *u_int16_t++ = *u_int16_t++ in a loop, you'll get
611 * <databyte><databyte>0xff0xff<databyte><databyte>0xff0xff...
612 *
613 * When you're attempting to read or write memory to this DACK/ed space,
614 * and the NCR is not ready for some timeout period, the system will
615 * generate a bus error. This might be for one of several reasons:
616 *
617 * 1) (on write) The FIFO is full and is not draining.
618 * 2) (on read) The FIFO is empty and is not filling.
619 * 3) An interrupt condition has occurred.
620 * 4) Anything else?
621 *
622 * So if a bus error occurs, we first turn off the nofault bus error handler,
623 * then we check for an interrupt (which would render the first two
624 * possibilities moot). If there's no interrupt, check for a DREQ/. If we
625 * have that, then attempt to resume stuffing (or unstuffing) the FIFO. If
626 * neither condition holds, pause briefly and check again.
627 *
628 * NOTE!!! In order to make allowances for the hardware structure of
629 * the mac, spl values in here are hardcoded!!!!!!!!!
630 * This is done to allow serial interrupts to get in during
631 * scsi transfers. This is ugly.
632 */
633 void
634 esp_quick_dma_go(struct ncr53c9x_softc *sc)
635 {
636 struct esp_softc *esc = (struct esp_softc *)sc;
637 extern long mac68k_a2_fromfault;
638 extern int *nofault;
639 label_t faultbuf;
640 u_int16_t volatile *pdma;
641 u_int16_t *addr;
642 int len, res;
643 u_short cnt32, cnt2;
644 u_char volatile *statreg;
645
646 esc->sc_active = 1;
647
648 espspl = splhigh();
649
650 addr = (u_int16_t *) *esc->sc_dmaaddr;
651 len = esc->sc_dmasize;
652
653 restart_dmago:
654 #if DEBUG
655 if (mac68k_esp_debug) {
656 printf("eqdg: a %lx, l %lx, in? %d ... ",
657 (long) addr, (long) len, esc->sc_datain);
658 }
659 #endif
660 nofault = (int *) &faultbuf;
661 if (setjmp((label_t *) nofault)) {
662 int i=0;
663
664 nofault = (int *) 0;
665 #if DEBUG
666 if (mac68k_esp_debug) {
667 printf("be\n");
668 }
669 #endif
670 /*
671 * Bus error...
672 * So, we first check for an interrupt. If we have
673 * one, go handle it. Next we check for DREQ/. If
674 * we have it, then we restart the transfer. If
675 * neither, then loop until we get one or the other.
676 */
677 statreg = esc->sc_reg + NCR_STAT * 16;
678 for (;;) {
679 spl2(); /* Give serial a chance... */
680 splhigh(); /* That's enough... */
681
682 if (*statreg & 0x80) {
683 goto gotintr;
684 }
685
686 if (esp_have_dreq(esc)) {
687 /*
688 * Get the remaining length from the address
689 * differential.
690 */
691 addr = (u_int16_t *) mac68k_a2_fromfault;
692 len = esc->sc_dmasize -
693 ((long) addr - (long) *esc->sc_dmaaddr);
694
695 if (esc->sc_datain == 0) {
696 /*
697 * Let the FIFO drain before we read
698 * the transfer count.
699 * Do we need to do this?
700 * Can we do this?
701 */
702 while (NCR_READ_REG(sc, NCR_FFLAG)
703 & 0x1f);
704 /*
705 * Get the length from the transfer
706 * counters.
707 */
708 res = NCR_READ_REG(sc, NCR_TCL);
709 res += NCR_READ_REG(sc, NCR_TCM) << 8;
710 /*
711 * If they don't agree,
712 * adjust accordingly.
713 */
714 while (res > len) {
715 len+=2; addr--;
716 }
717 if (res != len) {
718 panic("esp_quick_dma_go: res %d != len %d",
719 res, len);
720 }
721 }
722 break;
723 }
724
725 DELAY(1);
726 if (i++ > 1000000)
727 panic("esp_dma_go: Bus error, but no condition! Argh!");
728 }
729 goto restart_dmago;
730 }
731
732 len &= ~1;
733
734 statreg = esc->sc_reg + NCR_STAT * 16;
735 pdma = (u_int16_t *) (esc->sc_reg + 0x100);
736
737 /*
738 * These loops are unrolled into assembly for two reasons:
739 * 1) We can make sure that they are as efficient as possible, and
740 * 2) (more importantly) we need the address that we are reading
741 * from or writing to to be in a2.
742 */
743 cnt32 = len / 32;
744 cnt2 = (len % 32) / 2;
745 if (esc->sc_datain == 0) {
746 /* while (cnt32--) { 16 instances of *pdma = *addr++; } */
747 /* while (cnt2--) { *pdma = *addr++; } */
748 __asm __volatile (
749 " movl %1, %%a2 \n"
750 " movl %2, %%a3 \n"
751 " movw %3, %%d2 \n"
752 " cmpw #0, %%d2 \n"
753 " beq 2f \n"
754 " subql #1, %%d2 \n"
755 "1: movw %%a2@+,%%a3@; movw %%a2@+,%%a3@ \n"
756 " movw %%a2@+,%%a3@; movw %%a2@+,%%a3@ \n"
757 " movw %%a2@+,%%a3@; movw %%a2@+,%%a3@ \n"
758 " movw %%a2@+,%%a3@; movw %%a2@+,%%a3@ \n"
759 " movw %%a2@+,%%a3@; movw %%a2@+,%%a3@ \n"
760 " movw %%a2@+,%%a3@; movw %%a2@+,%%a3@ \n"
761 " movw %%a2@+,%%a3@; movw %%a2@+,%%a3@ \n"
762 " movw %%a2@+,%%a3@; movw %%a2@+,%%a3@ \n"
763 " movw #8704,%%sr \n"
764 " movw #9728,%%sr \n"
765 " dbra %%d2, 1b \n"
766 "2: movw %4, %%d2 \n"
767 " cmpw #0, %%d2 \n"
768 " beq 4f \n"
769 " subql #1, %%d2 \n"
770 "3: movw %%a2@+,%%a3@ \n"
771 " dbra %%d2, 3b \n"
772 "4: movl %%a2, %0"
773 : "=g" (addr)
774 : "0" (addr), "g" (pdma), "g" (cnt32), "g" (cnt2)
775 : "a2", "a3", "d2");
776 if (esc->sc_pad) {
777 unsigned char *c;
778 c = (unsigned char *) addr;
779 /* Wait for DREQ */
780 while (!esp_have_dreq(esc)) {
781 if (*statreg & 0x80) {
782 nofault = (int *) 0;
783 goto gotintr;
784 }
785 }
786 *(unsigned char *)pdma = *c;
787 }
788 } else {
789 /* while (cnt32--) { 16 instances of *addr++ = *pdma; } */
790 /* while (cnt2--) { *addr++ = *pdma; } */
791 __asm __volatile (
792 " movl %1, %%a2 \n"
793 " movl %2, %%a3 \n"
794 " movw %3, %%d2 \n"
795 " cmpw #0, %%d2 \n"
796 " beq 6f \n"
797 " subql #1, %%d2 \n"
798 "5: movw %%a3@,%%a2@+; movw %%a3@,%%a2@+ \n"
799 " movw %%a3@,%%a2@+; movw %%a3@,%%a2@+ \n"
800 " movw %%a3@,%%a2@+; movw %%a3@,%%a2@+ \n"
801 " movw %%a3@,%%a2@+; movw %%a3@,%%a2@+ \n"
802 " movw %%a3@,%%a2@+; movw %%a3@,%%a2@+ \n"
803 " movw %%a3@,%%a2@+; movw %%a3@,%%a2@+ \n"
804 " movw %%a3@,%%a2@+; movw %%a3@,%%a2@+ \n"
805 " movw %%a3@,%%a2@+; movw %%a3@,%%a2@+ \n"
806 " movw #8704,%%sr \n"
807 " movw #9728,%%sr \n"
808 " dbra %%d2, 5b \n"
809 "6: movw %4, %%d2 \n"
810 " cmpw #0, %%d2 \n"
811 " beq 8f \n"
812 " subql #1, %%d2 \n"
813 "7: movw %%a3@,%%a2@+ \n"
814 " dbra %%d2, 7b \n"
815 "8: movl %%a2, %0"
816 : "=g" (addr)
817 : "0" (addr), "g" (pdma), "g" (cnt32), "g" (cnt2)
818 : "a2", "a3", "d2");
819 if (esc->sc_pad) {
820 unsigned char *c;
821 c = (unsigned char *) addr;
822 /* Wait for DREQ */
823 while (!esp_have_dreq(esc)) {
824 if (*statreg & 0x80) {
825 nofault = (int *) 0;
826 goto gotintr;
827 }
828 }
829 *c = *(unsigned char *)pdma;
830 }
831 }
832
833 nofault = (int *) 0;
834
835 /*
836 * If we have not received an interrupt yet, we should shortly,
837 * and we can't prevent it, so return and wait for it.
838 */
839 if ((*statreg & 0x80) == 0) {
840 #if DEBUG
841 if (mac68k_esp_debug) {
842 printf("g.\n");
843 }
844 #endif
845 if (espspl != -1) splx(espspl); espspl = -1;
846 return;
847 }
848
849 gotintr:
850 #if DEBUG
851 if (mac68k_esp_debug) {
852 printf("g!\n");
853 }
854 #endif
855 ncr53c9x_intr(sc);
856 if (espspl != -1) splx(espspl); espspl = -1;
857 }
858
859 void
860 esp_intr(void *sc)
861 {
862 struct esp_softc *esc = (struct esp_softc *)sc;
863
864 if (esc->sc_reg[NCR_STAT * 16] & 0x80) {
865 ncr53c9x_intr((struct ncr53c9x_softc *) esp0);
866 }
867 }
868
869 void
870 esp_dualbus_intr(void *sc)
871 {
872 if (esp0 && (esp0->sc_reg[NCR_STAT * 16] & 0x80)) {
873 ncr53c9x_intr((struct ncr53c9x_softc *) esp0);
874 }
875
876 if (esp1 && (esp1->sc_reg[NCR_STAT * 16] & 0x80)) {
877 ncr53c9x_intr((struct ncr53c9x_softc *) esp1);
878 }
879 }
880