xref: /netbsd-src/sys/arch/mac68k/obio/esp.c (revision 6a493d6bc668897c91594964a732d38505b70cbb)
1 /*	$NetBSD: esp.c,v 1.55 2012/02/18 23:51:27 rmind 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@tfs.com) and
70  * Charles Hannum (mycroft@duality.gnu.ai.mit.edu).  Thanks a million!
71  */
72 
73 /*
74  * Initial m68k mac support from Allen Briggs <briggs@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.55 2012/02/18 23:51:27 rmind 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/queue.h>
92 #include <sys/mutex.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 int	espmatch(device_t, cfdata_t, void *);
112 void	espattach(device_t, device_t, void *);
113 
114 /* Linkup to the rest of the kernel */
115 CFATTACH_DECL_NEW(esp, sizeof(struct esp_softc),
116     espmatch, espattach, NULL, NULL);
117 
118 /*
119  * Functions and the switch for the MI code.
120  */
121 uint8_t	esp_read_reg(struct ncr53c9x_softc *, int);
122 void	esp_write_reg(struct ncr53c9x_softc *, int, uint8_t);
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 *, uint8_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 *, uint8_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(device_t parent, cfdata_t cf, void *aux)
160 {
161 	struct obio_attach_args *oa = aux;
162 
163 	if (oa->oa_addr == 0 && mac68k_machine.scsi96) {
164 		return 1;
165 	}
166 	if (oa->oa_addr == 1 && mac68k_machine.scsi96_2) {
167 		return 1;
168 	}
169 	return 0;
170 }
171 
172 /*
173  * Attach this instance, and then all the sub-devices
174  */
175 void
176 espattach(device_t parent, device_t self, void *aux)
177 {
178 	struct esp_softc	*esc = device_private(self);
179 	struct ncr53c9x_softc	*sc = &esc->sc_ncr53c9x;
180 	struct obio_attach_args *oa = aux;
181 	int			quick = 0;
182 	unsigned long		reg_offset;
183 	extern vaddr_t		SCSIBase;
184 
185 	sc->sc_dev = self;
186 
187 	reg_offset = SCSIBase - IOBase;
188 	esc->sc_tag = oa->oa_tag;
189 
190 	/*
191 	 * For Wombat, Primus and Optimus motherboards, DREQ is
192 	 * visible on bit 0 of the IOSB's emulated VIA2 vIFR (and
193 	 * the scsi registers are offset 0x1000 bytes from IOBase).
194 	 *
195 	 * For the Q700/900/950 it's at f9800024 for bus 0 and
196 	 * f9800028 for bus 1 (900/950).  For these machines, that is also
197 	 * a (12-bit) configuration register for DAFB's control of the
198 	 * pseudo-DMA timing.  The default value is 0x1d1.
199 	 */
200 	esp_have_dreq = esp_dafb_have_dreq;
201 	if (oa->oa_addr == 0) {
202 		if (reg_offset == 0x10000) {
203 			quick = 1;
204 			esp_have_dreq = esp_iosb_have_dreq;
205 		} else if (reg_offset == 0x18000) {
206 			quick = 0;
207 		} else {
208 			if (bus_space_map(esc->sc_tag, 0xf9800024,
209 					  4, 0, &esc->sc_bsh)) {
210 				aprint_error(": failed to map 4"
211 				    " at 0xf9800024.\n");
212 			} else {
213 				quick = 1;
214 				bus_space_write_4(esc->sc_tag,
215 						  esc->sc_bsh, 0, 0x1d1);
216 			}
217 		}
218 	} else {
219 		if (bus_space_map(esc->sc_tag, 0xf9800028,
220 				  4, 0, &esc->sc_bsh)) {
221 			aprint_error(": failed to map 4 at 0xf9800028.\n");
222 		} else {
223 			quick = 1;
224 			bus_space_write_4(esc->sc_tag, esc->sc_bsh, 0, 0x1d1);
225 		}
226 	}
227 	if (quick) {
228 		esp_glue.gl_write_reg = esp_quick_write_reg;
229 		esp_glue.gl_dma_intr = esp_quick_dma_intr;
230 		esp_glue.gl_dma_setup = esp_quick_dma_setup;
231 		esp_glue.gl_dma_go = esp_quick_dma_go;
232 	}
233 
234 	/*
235 	 * Set up the glue for MI code early; we use some of it here.
236 	 */
237 	sc->sc_glue = &esp_glue;
238 
239 	/*
240 	 * Save the regs
241 	 */
242 	if (oa->oa_addr == 0) {
243 		esp0 = esc;
244 
245 		esc->sc_reg = (volatile uint8_t *)SCSIBase;
246 		via2_register_irq(VIA2_SCSIIRQ, esp_intr, esc);
247 		esc->irq_mask = V2IF_SCSIIRQ;
248 		if (reg_offset == 0x10000) {
249 			/* From the Q650 developer's note */
250 			sc->sc_freq = 16500000;
251 		} else {
252 			sc->sc_freq = 25000000;
253 		}
254 
255 		if (esp_glue.gl_dma_go == esp_quick_dma_go) {
256 			aprint_normal(" (quick)");
257 		}
258 	} else {
259 		esp1 = esc;
260 
261 		esc->sc_reg = (volatile uint8_t *)SCSIBase + 0x402;
262 		via2_register_irq(VIA2_SCSIIRQ, esp_dualbus_intr, NULL);
263 		esc->irq_mask = 0;
264 		sc->sc_freq = 25000000;
265 
266 		if (esp_glue.gl_dma_go == esp_quick_dma_go) {
267 			printf(" (quick)");
268 		}
269 	}
270 
271 	aprint_normal(": address %p", esc->sc_reg);
272 
273 	sc->sc_id = 7;
274 
275 	/* gimme MHz */
276 	sc->sc_freq /= 1000000;
277 
278 	/*
279 	 * It is necessary to try to load the 2nd config register here,
280 	 * to find out what rev the esp chip is, else the esp_reset
281 	 * will not set up the defaults correctly.
282 	 */
283 	sc->sc_cfg1 = sc->sc_id; /* | NCRCFG1_PARENB; */
284 	sc->sc_cfg2 = NCRCFG2_SCSI2;
285 	sc->sc_cfg3 = 0;
286 	sc->sc_rev = NCR_VARIANT_NCR53C96;
287 
288 	/*
289 	 * This is the value used to start sync negotiations
290 	 * Note that the NCR register "SYNCTP" is programmed
291 	 * in "clocks per byte", and has a minimum value of 4.
292 	 * The SCSI period used in negotiation is one-fourth
293 	 * of the time (in nanoseconds) needed to transfer one byte.
294 	 * Since the chip's clock is given in MHz, we have the following
295 	 * formula: 4 * period = (1000 / freq) * 4
296 	 */
297 	sc->sc_minsync = 1000 / sc->sc_freq;
298 
299 	/* We need this to fit into the TCR... */
300 	sc->sc_maxxfer = 64 * 1024;
301 
302         switch (current_mac_model->machineid) {
303         case MACH_MACQ630:
304 		/* XXX on LC630 64k xfer causes timeout error */
305 		sc->sc_maxxfer = 63 * 1024;
306 		break;
307 	}
308 
309 	if (!quick) {
310 		sc->sc_minsync = 0;	/* No synchronous xfers w/o DMA */
311 		sc->sc_maxxfer = 8 * 1024;
312 	}
313 
314 	/*
315 	 * Configure interrupts.
316 	 */
317 	if (esc->irq_mask) {
318 		via2_reg(vPCR) = 0x22;
319 		via2_reg(vIFR) = esc->irq_mask;
320 		via2_reg(vIER) = 0x80 | esc->irq_mask;
321 	}
322 
323 	/*
324 	 * Now try to attach all the sub-devices
325 	 */
326 	sc->sc_adapter.adapt_minphys = minphys;
327 	sc->sc_adapter.adapt_request = ncr53c9x_scsipi_request;
328 	ncr53c9x_attach(sc);
329 }
330 
331 /*
332  * Glue functions.
333  */
334 
335 uint8_t
336 esp_read_reg(struct ncr53c9x_softc *sc, int reg)
337 {
338 	struct esp_softc *esc = (struct esp_softc *)sc;
339 
340 	return esc->sc_reg[reg * 16];
341 }
342 
343 void
344 esp_write_reg(struct ncr53c9x_softc *sc, int reg, uint8_t val)
345 {
346 	struct esp_softc *esc = (struct esp_softc *)sc;
347 	uint8_t	v = val;
348 
349 	if (reg == NCR_CMD && v == (NCRCMD_TRANS|NCRCMD_DMA)) {
350 		v = NCRCMD_TRANS;
351 	}
352 	esc->sc_reg[reg * 16] = v;
353 }
354 
355 void
356 esp_dma_stop(struct ncr53c9x_softc *sc)
357 {
358 }
359 
360 int
361 esp_dma_isactive(struct ncr53c9x_softc *sc)
362 {
363 	struct esp_softc *esc = (struct esp_softc *)sc;
364 
365 	return esc->sc_active;
366 }
367 
368 int
369 esp_dma_isintr(struct ncr53c9x_softc *sc)
370 {
371 	struct esp_softc *esc = (struct esp_softc *)sc;
372 
373 	return esc->sc_reg[NCR_STAT * 16] & 0x80;
374 }
375 
376 void
377 esp_dma_reset(struct ncr53c9x_softc *sc)
378 {
379 	struct esp_softc *esc = (struct esp_softc *)sc;
380 
381 	esc->sc_active = 0;
382 	esc->sc_tc = 0;
383 }
384 
385 int
386 esp_dma_intr(struct ncr53c9x_softc *sc)
387 {
388 	struct esp_softc *esc = (struct esp_softc *)sc;
389 	volatile u_char *cmdreg, *intrreg, *statreg, *fiforeg;
390 	uint8_t	*p;
391 	u_int	espphase, espstat, espintr;
392 	int	cnt, s;
393 
394 	if (esc->sc_active == 0) {
395 		printf("dma_intr--inactive DMA\n");
396 		return -1;
397 	}
398 
399 	if ((sc->sc_espintr & NCRINTR_BS) == 0) {
400 		esc->sc_active = 0;
401 		return 0;
402 	}
403 
404 	cnt = *esc->sc_dmalen;
405 	if (*esc->sc_dmalen == 0) {
406 		printf("data interrupt, but no count left.");
407 	}
408 
409 	p = *esc->sc_dmaaddr;
410 	espphase = sc->sc_phase;
411 	espstat = (u_int)sc->sc_espstat;
412 	espintr = (u_int)sc->sc_espintr;
413 	cmdreg = esc->sc_reg + NCR_CMD * 16;
414 	fiforeg = esc->sc_reg + NCR_FIFO * 16;
415 	statreg = esc->sc_reg + NCR_STAT * 16;
416 	intrreg = esc->sc_reg + NCR_INTR * 16;
417 	do {
418 		if (esc->sc_datain) {
419 			*p++ = *fiforeg;
420 			cnt--;
421 			if (espphase == DATA_IN_PHASE) {
422 				*cmdreg = NCRCMD_TRANS;
423 			} else {
424 				esc->sc_active = 0;
425 			}
426 	 	} else {
427 			if (   (espphase == DATA_OUT_PHASE)
428 			    || (espphase == MESSAGE_OUT_PHASE)) {
429 				*fiforeg = *p++;
430 				cnt--;
431 				*cmdreg = NCRCMD_TRANS;
432 			} else {
433 				esc->sc_active = 0;
434 			}
435 		}
436 
437 		if (esc->sc_active) {
438 			while (!(*statreg & 0x80));
439 			s = splhigh();
440 			espstat = *statreg;
441 			espintr = *intrreg;
442 			espphase = (espintr & NCRINTR_DIS)
443 				    ? /* Disconnected */ BUSFREE_PHASE
444 				    : espstat & PHASE_MASK;
445 			splx(s);
446 		}
447 	} while (esc->sc_active && (espintr & NCRINTR_BS));
448 	sc->sc_phase = espphase;
449 	sc->sc_espstat = (u_char)espstat;
450 	sc->sc_espintr = (u_char)espintr;
451 	*esc->sc_dmaaddr = p;
452 	*esc->sc_dmalen = cnt;
453 
454 	if (*esc->sc_dmalen == 0) {
455 		esc->sc_tc = NCRSTAT_TC;
456 	}
457 	sc->sc_espstat |= esc->sc_tc;
458 	return 0;
459 }
460 
461 int
462 esp_dma_setup(struct ncr53c9x_softc *sc, uint8_t **addr, size_t *len,
463     int datain, size_t *dmasize)
464 {
465 	struct esp_softc *esc = (struct esp_softc *)sc;
466 
467 	esc->sc_dmaaddr = addr;
468 	esc->sc_dmalen = len;
469 	esc->sc_datain = datain;
470 	esc->sc_dmasize = *dmasize;
471 	esc->sc_tc = 0;
472 
473 	return 0;
474 }
475 
476 void
477 esp_dma_go(struct ncr53c9x_softc *sc)
478 {
479 	struct esp_softc *esc = (struct esp_softc *)sc;
480 
481 	if (esc->sc_datain == 0) {
482 		esc->sc_reg[NCR_FIFO * 16] = **esc->sc_dmaaddr;
483 		(*esc->sc_dmalen)--;
484 		(*esc->sc_dmaaddr)++;
485 	}
486 	esc->sc_active = 1;
487 }
488 
489 void
490 esp_quick_write_reg(struct ncr53c9x_softc *sc, int reg, u_char val)
491 {
492 	struct esp_softc *esc = (struct esp_softc *)sc;
493 
494 	esc->sc_reg[reg * 16] = val;
495 }
496 
497 #if DEBUG
498 int mac68k_esp_debug=0;
499 #endif
500 
501 int
502 esp_quick_dma_intr(struct ncr53c9x_softc *sc)
503 {
504 	struct esp_softc *esc = (struct esp_softc *)sc;
505 	int trans=0, resid=0;
506 
507 	if (esc->sc_active == 0)
508 		panic("dma_intr--inactive DMA");
509 
510 	esc->sc_active = 0;
511 
512 	if (esc->sc_dmasize == 0) {
513 		int	res;
514 
515 		res = NCR_READ_REG(sc, NCR_TCL);
516 		res += NCR_READ_REG(sc, NCR_TCM) << 8;
517 		/* This can happen in the case of a TRPAD operation */
518 		/* Pretend that it was complete */
519 		sc->sc_espstat |= NCRSTAT_TC;
520 #if DEBUG
521 		if (mac68k_esp_debug) {
522 			printf("dmaintr: DMA xfer of zero xferred %d\n",
523 			    65536 - res);
524 		}
525 #endif
526 		return 0;
527 	}
528 
529 	if ((sc->sc_espstat & NCRSTAT_TC) == 0) {
530 		if (esc->sc_datain == 0) {
531 			resid = NCR_READ_REG(sc, NCR_FFLAG) & 0x1f;
532 #if DEBUG
533 			if (mac68k_esp_debug) {
534 				printf("Write FIFO residual %d bytes\n", resid);
535 			}
536 #endif
537 		}
538 		resid += NCR_READ_REG(sc, NCR_TCL);
539 		resid += NCR_READ_REG(sc, NCR_TCM) << 8;
540 		if (resid == 0)
541 			resid = 65536;
542 	}
543 
544 	trans = esc->sc_dmasize - resid;
545 	if (trans < 0) {
546 		printf("dmaintr: trans < 0????");
547 		trans = *esc->sc_dmalen;
548 	}
549 
550 	NCR_DMA(("dmaintr: trans %d, resid %d.\n", trans, resid));
551 #if DEBUG
552 	if (mac68k_esp_debug) {
553 		printf("eqd_intr: trans %d, resid %d.\n", trans, resid);
554 	}
555 #endif
556 	*esc->sc_dmaaddr += trans;
557 	*esc->sc_dmalen -= trans;
558 
559 	return 0;
560 }
561 
562 int
563 esp_quick_dma_setup(struct ncr53c9x_softc *sc, uint8_t **addr, size_t *len,
564     int datain, size_t *dmasize)
565 {
566 	struct esp_softc *esc = (struct esp_softc *)sc;
567 
568 	esc->sc_dmaaddr = addr;
569 	esc->sc_dmalen = len;
570 
571 	if (*len & 1) {
572 		esc->sc_pad = 1;
573 	} else {
574 		esc->sc_pad = 0;
575 	}
576 
577 	esc->sc_datain = datain;
578 	esc->sc_dmasize = *dmasize;
579 
580 #if DIAGNOSTIC
581 	if (esc->sc_dmasize == 0) {
582 		/* This can happen in the case of a TRPAD operation */
583 	}
584 #endif
585 #if DEBUG
586 	if (mac68k_esp_debug) {
587 	printf("eqd_setup: addr %lx, len %lx, in? %d, dmasize %lx\n",
588 	    (long) *addr, (long) *len, datain, (long) esc->sc_dmasize);
589 	}
590 #endif
591 
592 	return 0;
593 }
594 
595 static inline int
596 esp_dafb_have_dreq(struct esp_softc *esc)
597 {
598 
599 	return *(volatile uint32_t *)(esc->sc_bsh.base) & 0x200;
600 }
601 
602 static inline int
603 esp_iosb_have_dreq(struct esp_softc *esc)
604 {
605 
606 	return via2_reg(vIFR) & V2IF_SCSIDRQ;
607 }
608 
609 static volatile int espspl = -1;
610 
611 /*
612  * Apple "DMA" is weird.
613  *
614  * Basically, the CPU acts like the DMA controller.  The DREQ/ off the
615  * chip goes to a register that we've mapped at attach time (on the
616  * IOSB or DAFB, depending on the machine).  Apple also provides some
617  * space for which the memory controller handshakes data to/from the
618  * NCR chip with the DACK/ line.  This space appears to be mapped over
619  * and over, every 4 bytes, but only the lower 16 bits are valid (but
620  * reading the upper 16 bits will handshake DACK/ just fine, so if you
621  * read *u_int16_t++ = *u_int16_t++ in a loop, you'll get
622  * <databyte><databyte>0xff0xff<databyte><databyte>0xff0xff...
623  *
624  * When you're attempting to read or write memory to this DACK/ed space,
625  * and the NCR is not ready for some timeout period, the system will
626  * generate a bus error.  This might be for one of several reasons:
627  *
628  *	1) (on write) The FIFO is full and is not draining.
629  *	2) (on read) The FIFO is empty and is not filling.
630  *	3) An interrupt condition has occurred.
631  *	4) Anything else?
632  *
633  * So if a bus error occurs, we first turn off the nofault bus error handler,
634  * then we check for an interrupt (which would render the first two
635  * possibilities moot).  If there's no interrupt, check for a DREQ/.  If we
636  * have that, then attempt to resume stuffing (or unstuffing) the FIFO.  If
637  * neither condition holds, pause briefly and check again.
638  *
639  * NOTE!!!  In order to make allowances for the hardware structure of
640  *          the mac, spl values in here are hardcoded!!!!!!!!!
641  *          This is done to allow serial interrupts to get in during
642  *          scsi transfers.  This is ugly.
643  */
644 void
645 esp_quick_dma_go(struct ncr53c9x_softc *sc)
646 {
647 	struct esp_softc *esc = (struct esp_softc *)sc;
648 	extern long mac68k_a2_fromfault;
649 	extern int *nofault;
650 	label_t faultbuf;
651 	uint16_t volatile *pdma;
652 	uint16_t *addr;
653 	int		len, res;
654 	uint16_t	cnt32, cnt2;
655 	volatile uint8_t *statreg;
656 
657 	esc->sc_active = 1;
658 
659 	espspl = splhigh();
660 
661 	addr = (uint16_t *)*esc->sc_dmaaddr;
662 	len  = esc->sc_dmasize;
663 
664 restart_dmago:
665 #if DEBUG
666 	if (mac68k_esp_debug) {
667 		printf("eqdg: a %lx, l %lx, in? %d ... ",
668 		    (long) addr, (long) len, esc->sc_datain);
669 	}
670 #endif
671 	nofault = (int *)&faultbuf;
672 	if (setjmp((label_t *)nofault)) {
673 		int	i = 0;
674 
675 		nofault = NULL;
676 #if DEBUG
677 		if (mac68k_esp_debug) {
678 			printf("be\n");
679 		}
680 #endif
681 		/*
682 		 * Bus error...
683 		 * So, we first check for an interrupt.  If we have
684 		 * one, go handle it.  Next we check for DREQ/.  If
685 		 * we have it, then we restart the transfer.  If
686 		 * neither, then loop until we get one or the other.
687 		 */
688 		statreg = esc->sc_reg + NCR_STAT * 16;
689 		for (;;) {
690 			spl2();		/* Give serial a chance... */
691 			splhigh();	/* That's enough... */
692 
693 			if (*statreg & 0x80) {
694 				goto gotintr;
695 			}
696 
697 			if (esp_have_dreq(esc)) {
698 				/*
699 				 * Get the remaining length from the address
700 				 * differential.
701 				 */
702 				addr = (uint16_t *)mac68k_a2_fromfault;
703 				len = esc->sc_dmasize -
704 				    ((long)addr - (long)*esc->sc_dmaaddr);
705 
706 				if (esc->sc_datain == 0) {
707 					/*
708 					 * Let the FIFO drain before we read
709 					 * the transfer count.
710 					 * Do we need to do this?
711 					 * Can we do this?
712 					 */
713 					while (NCR_READ_REG(sc, NCR_FFLAG)
714 					    & 0x1f);
715 					/*
716 					 * Get the length from the transfer
717 					 * counters.
718 					 */
719 					res = NCR_READ_REG(sc, NCR_TCL);
720 					res += NCR_READ_REG(sc, NCR_TCM) << 8;
721 					/*
722 					 * If they don't agree,
723 					 * adjust accordingly.
724 					 */
725 					while (res > len) {
726 						len+=2; addr--;
727 					}
728 					if (res != len) {
729 						panic("%s: res %d != len %d",
730 						    __func__, res, len);
731 					}
732 				}
733 				break;
734 			}
735 
736 			DELAY(1);
737 			if (i++ > 1000000)
738 				panic("%s: Bus error, but no condition!  Argh!",
739 				    __func__);
740 		}
741 		goto restart_dmago;
742 	}
743 
744 	len &= ~1;
745 
746 	statreg = esc->sc_reg + NCR_STAT * 16;
747 	pdma = (volatile uint16_t *)(esc->sc_reg + 0x100);
748 
749 	/*
750 	 * These loops are unrolled into assembly for two reasons:
751 	 * 1) We can make sure that they are as efficient as possible, and
752 	 * 2) (more importantly) we need the address that we are reading
753 	 *    from or writing to to be in a2.
754 	 */
755 	cnt32 = len / 32;
756 	cnt2 = (len % 32) / 2;
757 	if (esc->sc_datain == 0) {
758 		/* while (cnt32--) { 16 instances of *pdma = *addr++; } */
759 		/* while (cnt2--) { *pdma = *addr++; } */
760 		__asm volatile (
761 			"	movl %1, %%a2	\n"
762 			"	movl %2, %%a3	\n"
763 			"	movw %3, %%d2	\n"
764 			"	cmpw #0, %%d2	\n"
765 			"	beq  2f		\n"
766 			"	subql #1, %%d2	\n"
767 			"1:	movw %%a2@+,%%a3@; movw %%a2@+,%%a3@	\n"
768 			"	movw %%a2@+,%%a3@; movw %%a2@+,%%a3@	\n"
769 			"	movw %%a2@+,%%a3@; movw %%a2@+,%%a3@	\n"
770 			"	movw %%a2@+,%%a3@; movw %%a2@+,%%a3@	\n"
771 			"	movw %%a2@+,%%a3@; movw %%a2@+,%%a3@	\n"
772 			"	movw %%a2@+,%%a3@; movw %%a2@+,%%a3@	\n"
773 			"	movw %%a2@+,%%a3@; movw %%a2@+,%%a3@	\n"
774 			"	movw %%a2@+,%%a3@; movw %%a2@+,%%a3@	\n"
775 			"	movw #8704,%%sr	\n"
776 			"	movw #9728,%%sr	\n"
777 			"	dbra %%d2, 1b	\n"
778 			"2:	movw %4, %%d2	\n"
779 			"	cmpw #0, %%d2	\n"
780 			"	beq  4f		\n"
781 			"	subql #1, %%d2	\n"
782 			"3:	movw %%a2@+,%%a3@ \n"
783 			"	dbra %%d2, 3b	\n"
784 			"4:	movl %%a2, %0"
785 			: "=g" (addr)
786 			: "0" (addr), "g" (pdma), "g" (cnt32), "g" (cnt2)
787 			: "a2", "a3", "d2");
788 		if (esc->sc_pad) {
789 			volatile uint8_t *c;
790 			c = (volatile uint8_t *) addr;
791 			/* Wait for DREQ */
792 			while (!esp_have_dreq(esc)) {
793 				if (*statreg & 0x80) {
794 					nofault = NULL;
795 					goto gotintr;
796 				}
797 			}
798 			*(volatile int8_t *)pdma = *c;
799 		}
800 	} else {
801 		/* while (cnt32--) { 16 instances of *addr++ = *pdma; } */
802 		/* while (cnt2--) { *addr++ = *pdma; } */
803 		__asm volatile (
804 			"	movl %1, %%a2	\n"
805 			"	movl %2, %%a3	\n"
806 			"	movw %3, %%d2	\n"
807 			"	cmpw #0, %%d2	\n"
808 			"	beq  6f		\n"
809 			"	subql #1, %%d2	\n"
810 			"5:	movw %%a3@,%%a2@+; movw %%a3@,%%a2@+	\n"
811 			"	movw %%a3@,%%a2@+; movw %%a3@,%%a2@+	\n"
812 			"	movw %%a3@,%%a2@+; movw %%a3@,%%a2@+	\n"
813 			"	movw %%a3@,%%a2@+; movw %%a3@,%%a2@+	\n"
814 			"	movw %%a3@,%%a2@+; movw %%a3@,%%a2@+	\n"
815 			"	movw %%a3@,%%a2@+; movw %%a3@,%%a2@+	\n"
816 			"	movw %%a3@,%%a2@+; movw %%a3@,%%a2@+	\n"
817 			"	movw %%a3@,%%a2@+; movw %%a3@,%%a2@+	\n"
818 			"	movw #8704,%%sr	\n"
819 			"	movw #9728,%%sr	\n"
820 			"	dbra %%d2, 5b	\n"
821 			"6:	movw %4, %%d2	\n"
822 			"	cmpw #0, %%d2	\n"
823 			"	beq  8f		\n"
824 			"	subql #1, %%d2	\n"
825 			"7:	movw %%a3@,%%a2@+ \n"
826 			"	dbra %%d2, 7b	\n"
827 			"8:	movl %%a2, %0"
828 			: "=g" (addr)
829 			: "0" (addr), "g" (pdma), "g" (cnt32), "g" (cnt2)
830 			: "a2", "a3", "d2");
831 		if (esc->sc_pad) {
832 			volatile uint8_t *c;
833 			c = (volatile int8_t *)addr;
834 			/* Wait for DREQ */
835 			while (!esp_have_dreq(esc)) {
836 				if (*statreg & 0x80) {
837 					nofault = NULL;
838 					goto gotintr;
839 				}
840 			}
841 			*c = *(volatile uint8_t *)pdma;
842 		}
843 	}
844 
845 	nofault = NULL;
846 
847 	/*
848 	 * If we have not received an interrupt yet, we should shortly,
849 	 * and we can't prevent it, so return and wait for it.
850 	 */
851 	if ((*statreg & 0x80) == 0) {
852 #if DEBUG
853 		if (mac68k_esp_debug) {
854 			printf("g.\n");
855 		}
856 #endif
857 		if (espspl != -1)
858 			splx(espspl);
859 		espspl = -1;
860 		return;
861 	}
862 
863 gotintr:
864 #if DEBUG
865 	if (mac68k_esp_debug) {
866 		printf("g!\n");
867 	}
868 #endif
869 	/*
870 	 * We have been called from the MI ncr53c9x_intr() handler,
871 	 * which protects itself against multiple invocation with a
872 	 * lock.  Follow the example of ncr53c9x_poll().
873 	 */
874 	mutex_exit(&sc->sc_lock);
875 	ncr53c9x_intr(sc);
876 	mutex_enter(&sc->sc_lock);
877 	if (espspl != -1)
878 		splx(espspl);
879 	espspl = -1;
880 }
881 
882 void
883 esp_intr(void *sc)
884 {
885 	struct esp_softc *esc = (struct esp_softc *)sc;
886 
887 	if (esc->sc_reg[NCR_STAT * 16] & 0x80) {
888 		ncr53c9x_intr((struct ncr53c9x_softc *)esp0);
889 	}
890 }
891 
892 void
893 esp_dualbus_intr(void *sc)
894 {
895 	if (esp0 && (esp0->sc_reg[NCR_STAT * 16] & 0x80)) {
896 		ncr53c9x_intr((struct ncr53c9x_softc *)esp0);
897 	}
898 
899 	if (esp1 && (esp1->sc_reg[NCR_STAT * 16] & 0x80)) {
900 		ncr53c9x_intr((struct ncr53c9x_softc *)esp1);
901 	}
902 }
903