esp.c revision 1.18
1/*	$NetBSD: esp.c,v 1.18 1998/10/10 00:28:30 thorpej 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/types.h>
80#include <sys/param.h>
81#include <sys/systm.h>
82#include <sys/kernel.h>
83#include <sys/errno.h>
84#include <sys/ioctl.h>
85#include <sys/device.h>
86#include <sys/buf.h>
87#include <sys/proc.h>
88#include <sys/user.h>
89#include <sys/queue.h>
90
91#include <dev/scsipi/scsi_all.h>
92#include <dev/scsipi/scsipi_all.h>
93#include <dev/scsipi/scsiconf.h>
94#include <dev/scsipi/scsi_message.h>
95
96#include <machine/cpu.h>
97#include <machine/bus.h>
98#include <machine/param.h>
99
100#include <dev/ic/ncr53c9xreg.h>
101#include <dev/ic/ncr53c9xvar.h>
102
103#include <machine/viareg.h>
104
105#include <mac68k/obio/espvar.h>
106#include <mac68k/obio/obiovar.h>
107
108void	espattach	__P((struct device *, struct device *, void *));
109int	espmatch	__P((struct device *, struct cfdata *, void *));
110
111/* Linkup to the rest of the kernel */
112struct cfattach esp_ca = {
113	sizeof(struct esp_softc), espmatch, espattach
114};
115
116struct scsipi_adapter esp_switch = {
117	ncr53c9x_scsi_cmd,
118	minphys,		/* no max at this level; handled by DMA code */
119	NULL,			/* scsipi_ioctl */
120};
121
122struct scsipi_device esp_dev = {
123	NULL,			/* Use default error handler */
124	NULL,			/* have a queue, served by this */
125	NULL,			/* have no async handler */
126	NULL,			/* Use default 'done' routine */
127};
128
129/*
130 * Functions and the switch for the MI code.
131 */
132u_char	esp_read_reg __P((struct ncr53c9x_softc *, int));
133void	esp_write_reg __P((struct ncr53c9x_softc *, int, u_char));
134int	esp_dma_isintr __P((struct ncr53c9x_softc *));
135void	esp_dma_reset __P((struct ncr53c9x_softc *));
136int	esp_dma_intr __P((struct ncr53c9x_softc *));
137int	esp_dma_setup __P((struct ncr53c9x_softc *, caddr_t *,
138	    size_t *, int, size_t *));
139void	esp_dma_go __P((struct ncr53c9x_softc *));
140void	esp_dma_stop __P((struct ncr53c9x_softc *));
141int	esp_dma_isactive __P((struct ncr53c9x_softc *));
142void	esp_quick_write_reg __P((struct ncr53c9x_softc *, int, u_char));
143int	esp_quick_dma_intr __P((struct ncr53c9x_softc *));
144int	esp_quick_dma_setup __P((struct ncr53c9x_softc *, caddr_t *,
145	    size_t *, int, size_t *));
146void	esp_quick_dma_go __P((struct ncr53c9x_softc *));
147
148int	esp_dualbus_intr __P((register struct ncr53c9x_softc *sc));
149static struct esp_softc		*esp0 = NULL, *esp1 = NULL;
150
151static __inline__ int esp_dafb_have_dreq __P((struct esp_softc *esc));
152static __inline__ int esp_iosb_have_dreq __P((struct esp_softc *esc));
153int (*esp_have_dreq) __P((struct esp_softc *esc));
154
155struct ncr53c9x_glue esp_glue = {
156	esp_read_reg,
157	esp_write_reg,
158	esp_dma_isintr,
159	esp_dma_reset,
160	esp_dma_intr,
161	esp_dma_setup,
162	esp_dma_go,
163	esp_dma_stop,
164	esp_dma_isactive,
165	NULL,			/* gl_clear_latched_intr */
166};
167
168int
169espmatch(parent, cf, aux)
170	struct device *parent;
171	struct cfdata *cf;
172	void *aux;
173{
174	int	found = 0;
175
176	if ((cf->cf_unit == 0) && mac68k_machine.scsi96) {
177		found = 1;
178	}
179	if ((cf->cf_unit == 1) && mac68k_machine.scsi96_2) {
180		found = 1;
181	}
182
183	return found;
184}
185
186/*
187 * Attach this instance, and then all the sub-devices
188 */
189void
190espattach(parent, self, aux)
191	struct device *parent, *self;
192	void *aux;
193{
194	struct obio_attach_args *oa = (struct obio_attach_args *)aux;
195	extern vm_offset_t	SCSIBase;
196	struct esp_softc	*esc = (void *)self;
197	struct ncr53c9x_softc	*sc = &esc->sc_ncr53c9x;
198	int			quick = 0;
199	unsigned long		reg_offset;
200
201	reg_offset = SCSIBase - IOBase;
202	esc->sc_tag = oa->oa_tag;
203	/*
204	 * For Wombat, Primus and Optimus motherboards, DREQ is
205	 * visible on bit 0 of the IOSB's emulated VIA2 vIFR (and
206	 * the scsi registers are offset 0x1000 bytes from IOBase).
207	 *
208	 * For the Q700/900/950 it's at f9800024 for bus 0 and
209	 * f9800028 for bus 1 (900/950).  For these machines, that is also
210	 * a (12-bit) configuration register for DAFB's control of the
211	 * pseudo-DMA timing.  The default value is 0x1d1.
212	 */
213	esp_have_dreq = esp_dafb_have_dreq;
214	if (sc->sc_dev.dv_unit == 0) {
215		if (reg_offset == 0x10000) {
216			quick = 1;
217			esp_have_dreq = esp_iosb_have_dreq;
218		} else if (reg_offset == 0x18000) {
219			quick = 0;
220		} else {
221			if (bus_space_map(esc->sc_tag, 0xf9800024,
222					  4, 0, &esc->sc_bsh)) {
223				printf("failed to map 4 at 0xf9800024.\n");
224			} else {
225				quick = 1;
226				bus_space_write_4(esc->sc_tag,
227						  esc->sc_bsh, 0, 0x1d1);
228			}
229		}
230	} else {
231		if (bus_space_map(esc->sc_tag, 0xf9800028,
232				  4, 0, &esc->sc_bsh)) {
233			printf("failed to map 4 at 0xf9800028.\n");
234		} else {
235			quick = 1;
236			bus_space_write_4(esc->sc_tag, esc->sc_bsh, 0, 0x1d1);
237		}
238	}
239	if (quick) {
240		esp_glue.gl_write_reg = esp_quick_write_reg;
241		esp_glue.gl_dma_intr = esp_quick_dma_intr;
242		esp_glue.gl_dma_setup = esp_quick_dma_setup;
243		esp_glue.gl_dma_go = esp_quick_dma_go;
244	}
245
246	/*
247	 * Set up the glue for MI code early; we use some of it here.
248	 */
249	sc->sc_glue = &esp_glue;
250
251	/*
252	 * Save the regs
253	 */
254	if (sc->sc_dev.dv_unit == 0) {
255		esp0 = esc;
256
257		esc->sc_reg = (volatile u_char *) SCSIBase;
258		via2_register_irq(VIA2_SCSIIRQ,
259		    (void (*)(void *))ncr53c9x_intr, esc);
260		esc->irq_mask = V2IF_SCSIIRQ;
261		if (reg_offset == 0x10000) {
262			sc->sc_freq = 16500000;
263		} else {
264			sc->sc_freq = 25000000;
265		}
266
267		if (esp_glue.gl_dma_go == esp_quick_dma_go) {
268			printf(" (quick)");
269		}
270	} else {
271		esp1 = esc;
272
273		esc->sc_reg = (volatile u_char *) SCSIBase + 0x402;
274		via2_register_irq(VIA2_SCSIIRQ,
275		    (void (*)(void *))esp_dualbus_intr, NULL);
276		esc->irq_mask = 0;
277		sc->sc_freq = 25000000;
278
279		if (esp_glue.gl_dma_go == esp_quick_dma_go) {
280			printf(" (quick)");
281		}
282	}
283
284	printf(": address %p", esc->sc_reg);
285
286	sc->sc_id = 7;
287
288	/* gimme Mhz */
289	sc->sc_freq /= 1000000;
290
291	/*
292	 * It is necessary to try to load the 2nd config register here,
293	 * to find out what rev the esp chip is, else the esp_reset
294	 * will not set up the defaults correctly.
295	 */
296	sc->sc_cfg1 = sc->sc_id; /* | NCRCFG1_PARENB; */
297	sc->sc_cfg2 = NCRCFG2_SCSI2;
298	sc->sc_cfg3 = 0;
299	sc->sc_rev = NCR_VARIANT_NCR53C96;
300
301	/*
302	 * This is the value used to start sync negotiations
303	 * Note that the NCR register "SYNCTP" is programmed
304	 * in "clocks per byte", and has a minimum value of 4.
305	 * The SCSI period used in negotiation is one-fourth
306	 * of the time (in nanoseconds) needed to transfer one byte.
307	 * Since the chip's clock is given in MHz, we have the following
308	 * formula: 4 * period = (1000 / freq) * 4
309	 */
310	sc->sc_minsync = 1000 / sc->sc_freq;
311
312	sc->sc_minsync = 0;	/* No synchronous xfers w/o DMA */
313	/* Really no limit, but since we want to fit into the TCR... */
314	sc->sc_maxxfer = 8 * 1024; /*64 * 1024; XXX */
315
316	/*
317	 * Now try to attach all the sub-devices
318	 */
319	ncr53c9x_attach(sc, &esp_switch, &esp_dev);
320
321	/*
322	 * Configure interrupts.
323	 */
324	if (esc->irq_mask) {
325		via2_reg(vPCR) = 0x22;
326		via2_reg(vIFR) = esc->irq_mask;
327		via2_reg(vIER) = 0x80 | esc->irq_mask;
328	}
329}
330
331/*
332 * Glue functions.
333 */
334
335u_char
336esp_read_reg(sc, reg)
337	struct ncr53c9x_softc *sc;
338	int reg;
339{
340	struct esp_softc *esc = (struct esp_softc *)sc;
341
342	return esc->sc_reg[reg * 16];
343}
344
345void
346esp_write_reg(sc, reg, val)
347	struct ncr53c9x_softc *sc;
348	int reg;
349	u_char val;
350{
351	struct esp_softc *esc = (struct esp_softc *)sc;
352	u_char v = val;
353
354	if (reg == NCR_CMD && v == (NCRCMD_TRANS|NCRCMD_DMA)) {
355		v = NCRCMD_TRANS;
356	}
357	esc->sc_reg[reg * 16] = v;
358}
359
360void
361esp_dma_stop(sc)
362	struct ncr53c9x_softc *sc;
363{
364}
365
366int
367esp_dma_isactive(sc)
368	struct ncr53c9x_softc *sc;
369{
370	struct esp_softc *esc = (struct esp_softc *)sc;
371
372	return esc->sc_active;
373}
374
375int
376esp_dma_isintr(sc)
377	struct ncr53c9x_softc *sc;
378{
379	struct esp_softc *esc = (struct esp_softc *)sc;
380
381	return esc->sc_reg[NCR_STAT * 16] & 0x80;
382}
383
384void
385esp_dma_reset(sc)
386	struct ncr53c9x_softc *sc;
387{
388	struct esp_softc *esc = (struct esp_softc *)sc;
389
390	esc->sc_active = 0;
391	esc->sc_tc = 0;
392}
393
394int
395esp_dma_intr(sc)
396	struct ncr53c9x_softc *sc;
397{
398	register struct esp_softc *esc = (struct esp_softc *)sc;
399	register u_char	*p;
400	volatile u_char *cmdreg, *intrreg, *statreg, *fiforeg;
401	register u_int	espphase, espstat, espintr;
402	register int	cnt;
403
404	if (esc->sc_active == 0) {
405		printf("dma_intr--inactive DMA\n");
406		return -1;
407	}
408
409	if ((sc->sc_espintr & NCRINTR_BS) == 0) {
410		esc->sc_active = 0;
411		return 0;
412	}
413
414	cnt = *esc->sc_dmalen;
415	if (*esc->sc_dmalen == 0) {
416		printf("data interrupt, but no count left.");
417	}
418
419	p = *esc->sc_dmaaddr;
420	espphase = sc->sc_phase;
421	espstat = (u_int) sc->sc_espstat;
422	espintr = (u_int) sc->sc_espintr;
423	cmdreg = esc->sc_reg + NCR_CMD * 16;
424	fiforeg = esc->sc_reg + NCR_FIFO * 16;
425	statreg = esc->sc_reg + NCR_STAT * 16;
426	intrreg = esc->sc_reg + NCR_INTR * 16;
427	do {
428		if (esc->sc_datain) {
429			*p++ = *fiforeg;
430			cnt--;
431			if (espphase == DATA_IN_PHASE) {
432				*cmdreg = NCRCMD_TRANS;
433			} else {
434				esc->sc_active = 0;
435			}
436	 	} else {
437			if (   (espphase == DATA_OUT_PHASE)
438			    || (espphase == MESSAGE_OUT_PHASE)) {
439				*fiforeg = *p++;
440				cnt--;
441				*cmdreg = NCRCMD_TRANS;
442			} else {
443				esc->sc_active = 0;
444			}
445		}
446
447		if (esc->sc_active) {
448			while (!(*statreg & 0x80));
449			espstat = *statreg;
450			espintr = *intrreg;
451			espphase = (espintr & NCRINTR_DIS)
452				    ? /* Disconnected */ BUSFREE_PHASE
453				    : espstat & PHASE_MASK;
454		}
455	} while (esc->sc_active && (espintr & NCRINTR_BS));
456	sc->sc_phase = espphase;
457	sc->sc_espstat = (u_char) espstat;
458	sc->sc_espintr = (u_char) espintr;
459	*esc->sc_dmaaddr = p;
460	*esc->sc_dmalen = cnt;
461
462	if (*esc->sc_dmalen == 0) {
463		esc->sc_tc = NCRSTAT_TC;
464	}
465	sc->sc_espstat |= esc->sc_tc;
466	return 0;
467}
468
469int
470esp_dma_setup(sc, addr, len, datain, dmasize)
471	struct ncr53c9x_softc *sc;
472	caddr_t *addr;
473	size_t *len;
474	int datain;
475	size_t *dmasize;
476{
477	struct esp_softc *esc = (struct esp_softc *)sc;
478
479	esc->sc_dmaaddr = addr;
480	esc->sc_dmalen = len;
481	esc->sc_datain = datain;
482	esc->sc_dmasize = *dmasize;
483	esc->sc_tc = 0;
484
485	return 0;
486}
487
488void
489esp_dma_go(sc)
490	struct ncr53c9x_softc *sc;
491{
492	struct esp_softc *esc = (struct esp_softc *)sc;
493
494	if (esc->sc_datain == 0) {
495		esc->sc_reg[NCR_FIFO * 16] = **esc->sc_dmaaddr;
496		(*esc->sc_dmalen)--;
497		(*esc->sc_dmaaddr)++;
498	}
499	esc->sc_active = 1;
500}
501
502void
503esp_quick_write_reg(sc, reg, val)
504	struct ncr53c9x_softc *sc;
505	int reg;
506	u_char val;
507{
508	struct esp_softc *esc = (struct esp_softc *)sc;
509	u_char v = val;
510
511	esc->sc_reg[reg * 16] = v;
512}
513
514int
515esp_quick_dma_intr(sc)
516	struct ncr53c9x_softc *sc;
517{
518	struct esp_softc *esc = (struct esp_softc *)sc;
519	int trans=0, resid=0;
520
521	if (esc->sc_active == 0)
522		panic("dma_intr--inactive DMA\n");
523
524	esc->sc_active = 0;
525
526	if (esc->sc_dmasize == 0) {
527		int	res;
528
529		res = 65536;
530		res -= NCR_READ_REG(sc, NCR_TCL);
531		res -= NCR_READ_REG(sc, NCR_TCM) << 8;
532		printf("dmaintr: discarded %d b (last transfer was %d b).\n",
533			res, esc->sc_prevdmasize);
534		return 0;
535	}
536
537	if (esc->sc_datain &&
538	    (resid = (NCR_READ_REG(sc, NCR_FFLAG) & NCRFIFO_FF)) != 0) {
539		printf("dmaintr: empty FIFO of %d\n", resid);
540		DELAY(1);
541	}
542
543	if ((sc->sc_espstat & NCRSTAT_TC) == 0) {
544		resid += NCR_READ_REG(sc, NCR_TCL);
545		resid += NCR_READ_REG(sc, NCR_TCM) << 8;
546
547		if (resid == 0)
548			resid = 65536;
549	}
550
551	trans = esc->sc_dmasize - resid;
552	if (trans < 0) {
553		printf("dmaintr: trans < 0????");
554		trans = esc->sc_dmasize;
555	}
556
557	NCR_DMA(("dmaintr: trans %d, resid %d.\n", trans, resid));
558	*esc->sc_dmaaddr += trans;
559	*esc->sc_dmalen -= trans;
560
561	return 0;
562}
563
564int
565esp_quick_dma_setup(sc, addr, len, datain, dmasize)
566	struct ncr53c9x_softc *sc;
567	caddr_t *addr;
568	size_t *len;
569	int datain;
570	size_t *dmasize;
571{
572	struct esp_softc *esc = (struct esp_softc *)sc;
573
574	esc->sc_dmaaddr = addr;
575	esc->sc_dmalen = len;
576
577	esc->sc_pdmaddr = (u_int16_t *) *addr;
578	esc->sc_pdmalen = *len;
579	if (esc->sc_pdmalen & 1) {
580		esc->sc_pdmalen--;
581		esc->sc_pad = 1;
582	} else {
583		esc->sc_pad = 0;
584	}
585
586	esc->sc_datain = datain;
587	esc->sc_prevdmasize = esc->sc_dmasize;
588	esc->sc_dmasize = *dmasize;
589
590	return 0;
591}
592
593static __inline__ int
594esp_dafb_have_dreq(esc)
595	struct esp_softc *esc;
596{
597	u_int32_t r;
598
599	r = bus_space_read_4(esc->sc_tag, esc->sc_bsh, 0);
600	return (r & 0x200);
601}
602
603static __inline__ int
604esp_iosb_have_dreq(esc)
605	struct esp_softc *esc;
606{
607	return (via2_reg(vIFR) & V2IF_SCSIDRQ);
608}
609
610static int espspl=-1;
611#define __splx(s) __asm __volatile ("movew %0,sr" : : "di" (s));
612#define __spl2()  __splx(PSL_S|PSL_IPL2)
613#define __spl4()  __splx(PSL_S|PSL_IPL4)
614
615void
616esp_quick_dma_go(sc)
617	struct ncr53c9x_softc *sc;
618{
619	struct esp_softc *esc = (struct esp_softc *)sc;
620	extern int *nofault;
621	label_t faultbuf;
622	u_int16_t volatile *pdma;
623	u_char volatile *statreg;
624
625	esc->sc_active = 1;
626
627	espspl = spl2();
628
629restart_dmago:
630	nofault = (int *) &faultbuf;
631	if (setjmp((label_t *) nofault)) {
632		int	i=0;
633
634		nofault = (int *) 0;
635		statreg = esc->sc_reg + NCR_STAT * 16;
636		for (;;) {
637			if (*statreg & 0x80) {
638				goto gotintr;
639			}
640
641			if (esp_have_dreq(esc)) {
642				break;
643			}
644
645			DELAY(1);
646			if (i++ > 10000)
647				panic("esp_dma_go: Argh!");
648		}
649		goto restart_dmago;
650	}
651
652	statreg = esc->sc_reg + NCR_STAT * 16;
653	pdma = (u_int16_t *) (esc->sc_reg + 0x100);
654
655#define WAIT while (!esp_have_dreq(esc)) if (*statreg & 0x80) goto gotintr
656
657	if (esc->sc_datain == 0) {
658		while (esc->sc_pdmalen) {
659			WAIT;
660			__spl4(); *pdma = *(esc->sc_pdmaddr)++; __spl2()
661			esc->sc_pdmalen -= 2;
662		}
663		if (esc->sc_pad) {
664			unsigned short	us;
665			unsigned char	*c;
666			c = (unsigned char *) esc->sc_pdmaddr;
667			us = *c;
668			WAIT;
669			__spl4(); *pdma = us; __spl2()
670		}
671	} else {
672		while (esc->sc_pdmalen) {
673			WAIT;
674			__spl4(); *(esc->sc_pdmaddr)++ = *pdma; __spl2()
675			esc->sc_pdmalen -= 2;
676		}
677		if (esc->sc_pad) {
678			unsigned short	us;
679			unsigned char	*c;
680			WAIT;
681			__spl4(); us = *pdma; __spl2()
682			c = (unsigned char *) esc->sc_pdmaddr;
683			*c = us & 0xff;
684		}
685	}
686#undef WAIT
687
688	nofault = (int *) 0;
689
690	if ((*statreg & 0x80) == 0) {
691		if (espspl != -1) splx(espspl); espspl = -1;
692		return;
693	}
694
695gotintr:
696	ncr53c9x_intr(sc);
697	if (espspl != -1) splx(espspl); espspl = -1;
698}
699
700int
701esp_dualbus_intr(sc)
702	register struct ncr53c9x_softc *sc;
703{
704	if (esp0 && (esp0->sc_reg[NCR_STAT * 16] & 0x80))
705		ncr53c9x_intr((struct ncr53c9x_softc *) esp0);
706
707	if (esp1 && (esp1->sc_reg[NCR_STAT * 16] & 0x80))
708		ncr53c9x_intr((struct ncr53c9x_softc *) esp1);
709
710	return 0;
711}
712