1 /* $NetBSD: esp.c,v 1.51 2008/06/02 12:01:11 hauke Exp $ */
4 * Copyright (c) 1997 Jason R. Thorpe.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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.
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.
35 * Copyright (c) 1994 Peter Galbavy
36 * All rights reserved.
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
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.
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.
66 * Based on aic6360 by Jarle Greipsland
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!
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).
79 #include <sys/cdefs.h>
80 __KERNEL_RCSID(0, "$NetBSD: esp.c,v 1.51 2008/06/02 12:01:11 hauke Exp $");
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>
91 #include <sys/queue.h>
93 #include <dev/scsipi/scsi_all.h>
94 #include <dev/scsipi/scsipi_all.h>
95 #include <dev/scsipi/scsiconf.h>
96 #include <dev/scsipi/scsi_message.h>
98 #include <machine/cpu.h>
99 #include <machine/bus.h>
100 #include <machine/param.h>
102 #include <dev/ic/ncr53c9xreg.h>
103 #include <dev/ic/ncr53c9xvar.h>
105 #include <machine/viareg.h>
107 #include <mac68k/obio/espvar.h>
108 #include <mac68k/obio/obiovar.h>
110 int espmatch(device_t
, cfdata_t
, void *);
111 void espattach(device_t
, device_t
, void *);
113 /* Linkup to the rest of the kernel */
114 CFATTACH_DECL_NEW(esp
, sizeof(struct esp_softc
),
115 espmatch
, espattach
, NULL
, NULL
);
118 * Functions and the switch for the MI code.
120 uint8_t esp_read_reg(struct ncr53c9x_softc
*, int);
121 void esp_write_reg(struct ncr53c9x_softc
*, int, uint8_t);
122 int esp_dma_isintr(struct ncr53c9x_softc
*);
123 void esp_dma_reset(struct ncr53c9x_softc
*);
124 int esp_dma_intr(struct ncr53c9x_softc
*);
125 int esp_dma_setup(struct ncr53c9x_softc
*, uint8_t **, size_t *, int,
127 void esp_dma_go(struct ncr53c9x_softc
*);
128 void esp_dma_stop(struct ncr53c9x_softc
*);
129 int esp_dma_isactive(struct ncr53c9x_softc
*);
130 void esp_quick_write_reg(struct ncr53c9x_softc
*, int, u_char
);
131 int esp_quick_dma_intr(struct ncr53c9x_softc
*);
132 int esp_quick_dma_setup(struct ncr53c9x_softc
*, uint8_t **, size_t *, int,
134 void esp_quick_dma_go(struct ncr53c9x_softc
*);
136 void esp_intr(void *);
137 void esp_dualbus_intr(void *);
138 static struct esp_softc
*esp0
, *esp1
;
140 static inline int esp_dafb_have_dreq(struct esp_softc
*);
141 static inline int esp_iosb_have_dreq(struct esp_softc
*);
142 int (*esp_have_dreq
)(struct esp_softc
*);
144 struct ncr53c9x_glue esp_glue
= {
154 NULL
, /* gl_clear_latched_intr */
158 espmatch(device_t parent
, cfdata_t cf
, void *aux
)
160 struct obio_attach_args
*oa
= aux
;
162 if (oa
->oa_addr
== 0 && mac68k_machine
.scsi96
) {
165 if (oa
->oa_addr
== 1 && mac68k_machine
.scsi96_2
) {
172 * Attach this instance, and then all the sub-devices
175 espattach(device_t parent
, device_t self
, void *aux
)
177 struct esp_softc
*esc
= device_private(self
);
178 struct ncr53c9x_softc
*sc
= &esc
->sc_ncr53c9x
;
179 struct obio_attach_args
*oa
= aux
;
181 unsigned long reg_offset
;
182 extern vaddr_t SCSIBase
;
186 reg_offset
= SCSIBase
- IOBase
;
187 esc
->sc_tag
= oa
->oa_tag
;
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).
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.
199 esp_have_dreq
= esp_dafb_have_dreq
;
200 if (oa
->oa_addr
== 0) {
201 if (reg_offset
== 0x10000) {
203 esp_have_dreq
= esp_iosb_have_dreq
;
204 } else if (reg_offset
== 0x18000) {
207 if (bus_space_map(esc
->sc_tag
, 0xf9800024,
208 4, 0, &esc
->sc_bsh
)) {
209 aprint_error(": failed to map 4"
210 " at 0xf9800024.\n");
213 bus_space_write_4(esc
->sc_tag
,
214 esc
->sc_bsh
, 0, 0x1d1);
218 if (bus_space_map(esc
->sc_tag
, 0xf9800028,
219 4, 0, &esc
->sc_bsh
)) {
220 aprint_error(": failed to map 4 at 0xf9800028.\n");
223 bus_space_write_4(esc
->sc_tag
, esc
->sc_bsh
, 0, 0x1d1);
227 esp_glue
.gl_write_reg
= esp_quick_write_reg
;
228 esp_glue
.gl_dma_intr
= esp_quick_dma_intr
;
229 esp_glue
.gl_dma_setup
= esp_quick_dma_setup
;
230 esp_glue
.gl_dma_go
= esp_quick_dma_go
;
234 * Set up the glue for MI code early; we use some of it here.
236 sc
->sc_glue
= &esp_glue
;
241 if (oa
->oa_addr
== 0) {
244 esc
->sc_reg
= (volatile uint8_t *)SCSIBase
;
245 via2_register_irq(VIA2_SCSIIRQ
, esp_intr
, esc
);
246 esc
->irq_mask
= V2IF_SCSIIRQ
;
247 if (reg_offset
== 0x10000) {
248 /* From the Q650 developer's note */
249 sc
->sc_freq
= 16500000;
251 sc
->sc_freq
= 25000000;
254 if (esp_glue
.gl_dma_go
== esp_quick_dma_go
) {
255 aprint_normal(" (quick)");
260 esc
->sc_reg
= (volatile uint8_t *)SCSIBase
+ 0x402;
261 via2_register_irq(VIA2_SCSIIRQ
, esp_dualbus_intr
, NULL
);
263 sc
->sc_freq
= 25000000;
265 if (esp_glue
.gl_dma_go
== esp_quick_dma_go
) {
270 aprint_normal(": address %p", esc
->sc_reg
);
275 sc
->sc_freq
/= 1000000;
278 * It is necessary to try to load the 2nd config register here,
279 * to find out what rev the esp chip is, else the esp_reset
280 * will not set up the defaults correctly.
282 sc
->sc_cfg1
= sc
->sc_id
; /* | NCRCFG1_PARENB; */
283 sc
->sc_cfg2
= NCRCFG2_SCSI2
;
285 sc
->sc_rev
= NCR_VARIANT_NCR53C96
;
288 * This is the value used to start sync negotiations
289 * Note that the NCR register "SYNCTP" is programmed
290 * in "clocks per byte", and has a minimum value of 4.
291 * The SCSI period used in negotiation is one-fourth
292 * of the time (in nanoseconds) needed to transfer one byte.
293 * Since the chip's clock is given in MHz, we have the following
294 * formula: 4 * period = (1000 / freq) * 4
296 sc
->sc_minsync
= 1000 / sc
->sc_freq
;
298 /* We need this to fit into the TCR... */
299 sc
->sc_maxxfer
= 64 * 1024;
301 switch (current_mac_model
->machineid
) {
303 /* XXX on LC630 64k xfer causes timeout error */
304 sc
->sc_maxxfer
= 63 * 1024;
309 sc
->sc_minsync
= 0; /* No synchronous xfers w/o DMA */
310 sc
->sc_maxxfer
= 8 * 1024;
314 * Configure interrupts.
317 via2_reg(vPCR
) = 0x22;
318 via2_reg(vIFR
) = esc
->irq_mask
;
319 via2_reg(vIER
) = 0x80 | esc
->irq_mask
;
323 * Now try to attach all the sub-devices
325 sc
->sc_adapter
.adapt_minphys
= minphys
;
326 sc
->sc_adapter
.adapt_request
= ncr53c9x_scsipi_request
;
335 esp_read_reg(struct ncr53c9x_softc
*sc
, int reg
)
337 struct esp_softc
*esc
= (struct esp_softc
*)sc
;
339 return esc
->sc_reg
[reg
* 16];
343 esp_write_reg(struct ncr53c9x_softc
*sc
, int reg
, uint8_t val
)
345 struct esp_softc
*esc
= (struct esp_softc
*)sc
;
348 if (reg
== NCR_CMD
&& v
== (NCRCMD_TRANS
|NCRCMD_DMA
)) {
351 esc
->sc_reg
[reg
* 16] = v
;
355 esp_dma_stop(struct ncr53c9x_softc
*sc
)
360 esp_dma_isactive(struct ncr53c9x_softc
*sc
)
362 struct esp_softc
*esc
= (struct esp_softc
*)sc
;
364 return esc
->sc_active
;
368 esp_dma_isintr(struct ncr53c9x_softc
*sc
)
370 struct esp_softc
*esc
= (struct esp_softc
*)sc
;
372 return esc
->sc_reg
[NCR_STAT
* 16] & 0x80;
376 esp_dma_reset(struct ncr53c9x_softc
*sc
)
378 struct esp_softc
*esc
= (struct esp_softc
*)sc
;
385 esp_dma_intr(struct ncr53c9x_softc
*sc
)
387 struct esp_softc
*esc
= (struct esp_softc
*)sc
;
388 volatile u_char
*cmdreg
, *intrreg
, *statreg
, *fiforeg
;
390 u_int espphase
, espstat
, espintr
;
393 if (esc
->sc_active
== 0) {
394 printf("dma_intr--inactive DMA\n");
398 if ((sc
->sc_espintr
& NCRINTR_BS
) == 0) {
403 cnt
= *esc
->sc_dmalen
;
404 if (*esc
->sc_dmalen
== 0) {
405 printf("data interrupt, but no count left.");
408 p
= *esc
->sc_dmaaddr
;
409 espphase
= sc
->sc_phase
;
410 espstat
= (u_int
)sc
->sc_espstat
;
411 espintr
= (u_int
)sc
->sc_espintr
;
412 cmdreg
= esc
->sc_reg
+ NCR_CMD
* 16;
413 fiforeg
= esc
->sc_reg
+ NCR_FIFO
* 16;
414 statreg
= esc
->sc_reg
+ NCR_STAT
* 16;
415 intrreg
= esc
->sc_reg
+ NCR_INTR
* 16;
417 if (esc
->sc_datain
) {
420 if (espphase
== DATA_IN_PHASE
) {
421 *cmdreg
= NCRCMD_TRANS
;
426 if ( (espphase
== DATA_OUT_PHASE
)
427 || (espphase
== MESSAGE_OUT_PHASE
)) {
430 *cmdreg
= NCRCMD_TRANS
;
436 if (esc
->sc_active
) {
437 while (!(*statreg
& 0x80));
441 espphase
= (espintr
& NCRINTR_DIS
)
442 ? /* Disconnected */ BUSFREE_PHASE
443 : espstat
& PHASE_MASK
;
446 } while (esc
->sc_active
&& (espintr
& NCRINTR_BS
));
447 sc
->sc_phase
= espphase
;
448 sc
->sc_espstat
= (u_char
)espstat
;
449 sc
->sc_espintr
= (u_char
)espintr
;
450 *esc
->sc_dmaaddr
= p
;
451 *esc
->sc_dmalen
= cnt
;
453 if (*esc
->sc_dmalen
== 0) {
454 esc
->sc_tc
= NCRSTAT_TC
;
456 sc
->sc_espstat
|= esc
->sc_tc
;
461 esp_dma_setup(struct ncr53c9x_softc
*sc
, uint8_t **addr
, size_t *len
,
462 int datain
, size_t *dmasize
)
464 struct esp_softc
*esc
= (struct esp_softc
*)sc
;
466 esc
->sc_dmaaddr
= addr
;
467 esc
->sc_dmalen
= len
;
468 esc
->sc_datain
= datain
;
469 esc
->sc_dmasize
= *dmasize
;
476 esp_dma_go(struct ncr53c9x_softc
*sc
)
478 struct esp_softc
*esc
= (struct esp_softc
*)sc
;
480 if (esc
->sc_datain
== 0) {
481 esc
->sc_reg
[NCR_FIFO
* 16] = **esc
->sc_dmaaddr
;
483 (*esc
->sc_dmaaddr
)++;
489 esp_quick_write_reg(struct ncr53c9x_softc
*sc
, int reg
, u_char val
)
491 struct esp_softc
*esc
= (struct esp_softc
*)sc
;
493 esc
->sc_reg
[reg
* 16] = val
;
497 int mac68k_esp_debug
=0;
501 esp_quick_dma_intr(struct ncr53c9x_softc
*sc
)
503 struct esp_softc
*esc
= (struct esp_softc
*)sc
;
504 int trans
=0, resid
=0;
506 if (esc
->sc_active
== 0)
507 panic("dma_intr--inactive DMA");
511 if (esc
->sc_dmasize
== 0) {
514 res
= NCR_READ_REG(sc
, NCR_TCL
);
515 res
+= NCR_READ_REG(sc
, NCR_TCM
) << 8;
516 /* This can happen in the case of a TRPAD operation */
517 /* Pretend that it was complete */
518 sc
->sc_espstat
|= NCRSTAT_TC
;
520 if (mac68k_esp_debug
) {
521 printf("dmaintr: DMA xfer of zero xferred %d\n",
528 if ((sc
->sc_espstat
& NCRSTAT_TC
) == 0) {
529 if (esc
->sc_datain
== 0) {
530 resid
= NCR_READ_REG(sc
, NCR_FFLAG
) & 0x1f;
532 if (mac68k_esp_debug
) {
533 printf("Write FIFO residual %d bytes\n", resid
);
537 resid
+= NCR_READ_REG(sc
, NCR_TCL
);
538 resid
+= NCR_READ_REG(sc
, NCR_TCM
) << 8;
543 trans
= esc
->sc_dmasize
- resid
;
545 printf("dmaintr: trans < 0????");
546 trans
= *esc
->sc_dmalen
;
549 NCR_DMA(("dmaintr: trans %d, resid %d.\n", trans
, resid
));
551 if (mac68k_esp_debug
) {
552 printf("eqd_intr: trans %d, resid %d.\n", trans
, resid
);
555 *esc
->sc_dmaaddr
+= trans
;
556 *esc
->sc_dmalen
-= trans
;
562 esp_quick_dma_setup(struct ncr53c9x_softc
*sc
, uint8_t **addr
, size_t *len
,
563 int datain
, size_t *dmasize
)
565 struct esp_softc
*esc
= (struct esp_softc
*)sc
;
567 esc
->sc_dmaaddr
= addr
;
568 esc
->sc_dmalen
= len
;
576 esc
->sc_datain
= datain
;
577 esc
->sc_dmasize
= *dmasize
;
580 if (esc
->sc_dmasize
== 0) {
581 /* This can happen in the case of a TRPAD operation */
585 if (mac68k_esp_debug
) {
586 printf("eqd_setup: addr %lx, len %lx, in? %d, dmasize %lx\n",
587 (long) *addr
, (long) *len
, datain
, (long) esc
->sc_dmasize
);
595 esp_dafb_have_dreq(struct esp_softc
*esc
)
598 return *(volatile uint32_t *)(esc
->sc_bsh
.base
) & 0x200;
602 esp_iosb_have_dreq(struct esp_softc
*esc
)
605 return via2_reg(vIFR
) & V2IF_SCSIDRQ
;
608 static volatile int espspl
= -1;
611 * Apple "DMA" is weird.
613 * Basically, the CPU acts like the DMA controller. The DREQ/ off the
614 * chip goes to a register that we've mapped at attach time (on the
615 * IOSB or DAFB, depending on the machine). Apple also provides some
616 * space for which the memory controller handshakes data to/from the
617 * NCR chip with the DACK/ line. This space appears to be mapped over
618 * and over, every 4 bytes, but only the lower 16 bits are valid (but
619 * reading the upper 16 bits will handshake DACK/ just fine, so if you
620 * read *u_int16_t++ = *u_int16_t++ in a loop, you'll get
621 * <databyte><databyte>0xff0xff<databyte><databyte>0xff0xff...
623 * When you're attempting to read or write memory to this DACK/ed space,
624 * and the NCR is not ready for some timeout period, the system will
625 * generate a bus error. This might be for one of several reasons:
627 * 1) (on write) The FIFO is full and is not draining.
628 * 2) (on read) The FIFO is empty and is not filling.
629 * 3) An interrupt condition has occurred.
632 * So if a bus error occurs, we first turn off the nofault bus error handler,
633 * then we check for an interrupt (which would render the first two
634 * possibilities moot). If there's no interrupt, check for a DREQ/. If we
635 * have that, then attempt to resume stuffing (or unstuffing) the FIFO. If
636 * neither condition holds, pause briefly and check again.
638 * NOTE!!! In order to make allowances for the hardware structure of
639 * the mac, spl values in here are hardcoded!!!!!!!!!
640 * This is done to allow serial interrupts to get in during
641 * scsi transfers. This is ugly.
644 esp_quick_dma_go(struct ncr53c9x_softc
*sc
)
646 struct esp_softc
*esc
= (struct esp_softc
*)sc
;
647 extern long mac68k_a2_fromfault
;
650 uint16_t volatile *pdma
;
653 uint16_t cnt32
, cnt2
;
654 volatile uint8_t *statreg
;
660 addr
= (uint16_t *)*esc
->sc_dmaaddr
;
661 len
= esc
->sc_dmasize
;
665 if (mac68k_esp_debug
) {
666 printf("eqdg: a %lx, l %lx, in? %d ... ",
667 (long) addr
, (long) len
, esc
->sc_datain
);
670 nofault
= (int *)&faultbuf
;
671 if (setjmp((label_t
*)nofault
)) {
676 if (mac68k_esp_debug
) {
682 * So, we first check for an interrupt. If we have
683 * one, go handle it. Next we check for DREQ/. If
684 * we have it, then we restart the transfer. If
685 * neither, then loop until we get one or the other.
687 statreg
= esc
->sc_reg
+ NCR_STAT
* 16;
689 spl2(); /* Give serial a chance... */
690 splhigh(); /* That's enough... */
692 if (*statreg
& 0x80) {
696 if (esp_have_dreq(esc
)) {
698 * Get the remaining length from the address
701 addr
= (uint16_t *)mac68k_a2_fromfault
;
702 len
= esc
->sc_dmasize
-
703 ((long)addr
- (long)*esc
->sc_dmaaddr
);
705 if (esc
->sc_datain
== 0) {
707 * Let the FIFO drain before we read
708 * the transfer count.
709 * Do we need to do this?
712 while (NCR_READ_REG(sc
, NCR_FFLAG
)
715 * Get the length from the transfer
718 res
= NCR_READ_REG(sc
, NCR_TCL
);
719 res
+= NCR_READ_REG(sc
, NCR_TCM
) << 8;
721 * If they don't agree,
722 * adjust accordingly.
728 panic("%s: res %d != len %d",
737 panic("%s: Bus error, but no condition! Argh!",
745 statreg
= esc
->sc_reg
+ NCR_STAT
* 16;
746 pdma
= (volatile uint16_t *)(esc
->sc_reg
+ 0x100);
749 * These loops are unrolled into assembly for two reasons:
750 * 1) We can make sure that they are as efficient as possible, and
751 * 2) (more importantly) we need the address that we are reading
752 * from or writing to to be in a2.
755 cnt2
= (len
% 32) / 2;
756 if (esc
->sc_datain
== 0) {
757 /* while (cnt32--) { 16 instances of *pdma = *addr++; } */
758 /* while (cnt2--) { *pdma = *addr++; } */
766 "1: movw %%a2@+,%%a3@; movw %%a2@+,%%a3@ \n"
767 " 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 #8704,%%sr \n"
775 " movw #9728,%%sr \n"
777 "2: movw %4, %%d2 \n"
781 "3: movw %%a2@+,%%a3@ \n"
785 : "0" (addr
), "g" (pdma
), "g" (cnt32
), "g" (cnt2
)
789 c
= (volatile uint8_t *) addr
;
791 while (!esp_have_dreq(esc
)) {
792 if (*statreg
& 0x80) {
797 *(volatile int8_t *)pdma
= *c
;
800 /* while (cnt32--) { 16 instances of *addr++ = *pdma; } */
801 /* while (cnt2--) { *addr++ = *pdma; } */
809 "5: movw %%a3@,%%a2@+; movw %%a3@,%%a2@+ \n"
810 " 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 #8704,%%sr \n"
818 " movw #9728,%%sr \n"
820 "6: movw %4, %%d2 \n"
824 "7: movw %%a3@,%%a2@+ \n"
828 : "0" (addr
), "g" (pdma
), "g" (cnt32
), "g" (cnt2
)
832 c
= (volatile int8_t *)addr
;
834 while (!esp_have_dreq(esc
)) {
835 if (*statreg
& 0x80) {
840 *c
= *(volatile uint8_t *)pdma
;
847 * If we have not received an interrupt yet, we should shortly,
848 * and we can't prevent it, so return and wait for it.
850 if ((*statreg
& 0x80) == 0) {
852 if (mac68k_esp_debug
) {
864 if (mac68k_esp_debug
) {
869 * We have been called from the MI ncr53c9x_intr() handler,
870 * which protects itself against multiple invocation with a
871 * simple_lock. Follow the example of ncr53c9x_poll().
873 simple_unlock(&sc
->sc_lock
);
875 simple_lock(&sc
->sc_lock
);
884 struct esp_softc
*esc
= (struct esp_softc
*)sc
;
886 if (esc
->sc_reg
[NCR_STAT
* 16] & 0x80) {
887 ncr53c9x_intr((struct ncr53c9x_softc
*)esp0
);
892 esp_dualbus_intr(void *sc
)
894 if (esp0
&& (esp0
->sc_reg
[NCR_STAT
* 16] & 0x80)) {
895 ncr53c9x_intr((struct ncr53c9x_softc
*)esp0
);
898 if (esp1
&& (esp1
->sc_reg
[NCR_STAT
* 16] & 0x80)) {
899 ncr53c9x_intr((struct ncr53c9x_softc
*)esp1
);