Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/netbsd-1-5]: src/sys/arch/mac68k/obio Pull up revisions 1.26-1.28 (reque...



details:   https://anonhg.NetBSD.org/src/rev/1ba38e2d56a8
branches:  netbsd-1-5
changeset: 490504:1ba38e2d56a8
user:      jhawk <jhawk%NetBSD.org@localhost>
date:      Thu Jan 25 17:39:22 2001 +0000

description:
Pull up revisions 1.26-1.28 (requested by briggs):
 Improve performance of the pseudo-DMA mode of the esp driver, and handle
 residual FIFO data on write.

diffstat:

 sys/arch/mac68k/obio/esp.c |  354 +++++++++++++++++++++++++++++++++-----------
 1 files changed, 267 insertions(+), 87 deletions(-)

diffs (truncated from 518 to 300 lines):

diff -r 6ac68b818bb5 -r 1ba38e2d56a8 sys/arch/mac68k/obio/esp.c
--- a/sys/arch/mac68k/obio/esp.c        Thu Jan 25 17:39:18 2001 +0000
+++ b/sys/arch/mac68k/obio/esp.c        Thu Jan 25 17:39:22 2001 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: esp.c,v 1.25 2000/06/05 07:59:52 nisimura Exp $        */
+/*     $NetBSD: esp.c,v 1.25.2.1 2001/01/25 17:39:22 jhawk Exp $       */
 
 /*
  * Copyright (c) 1997 Jason R. Thorpe.
@@ -246,6 +246,7 @@
                via2_register_irq(VIA2_SCSIIRQ, esp_intr, esc);
                esc->irq_mask = V2IF_SCSIIRQ;
                if (reg_offset == 0x10000) {
+                       /* From the Q650 developer's note */
                        sc->sc_freq = 16500000;
                } else {
                        sc->sc_freq = 25000000;
@@ -295,9 +296,13 @@
         */
        sc->sc_minsync = 1000 / sc->sc_freq;
 
-       sc->sc_minsync = 0;     /* No synchronous xfers w/o DMA */
-       /* Really no limit, but since we want to fit into the TCR... */
-       sc->sc_maxxfer = 8 * 1024; /*64 * 1024; XXX */
+       /* We need this to fit into the TCR... */
+       sc->sc_maxxfer = 64 * 1024;
+
+       if (!quick) {
+               sc->sc_minsync = 0;     /* No synchronous xfers w/o DMA */
+               sc->sc_maxxfer = 8 * 1024;
+       }
 
        /*
         * Configure interrupts.
@@ -397,8 +402,8 @@
                return 0;
        }
 
-       cnt = *esc->sc_dmalen;
-       if (*esc->sc_dmalen == 0) {
+       cnt = esc->sc_dmasize;
+       if (esc->sc_dmasize == 0) {
                printf("data interrupt, but no count left.");
        }
 
@@ -445,9 +450,9 @@
        sc->sc_espstat = (u_char) espstat;
        sc->sc_espintr = (u_char) espintr;
        *esc->sc_dmaaddr = p;
-       *esc->sc_dmalen = cnt;
+       esc->sc_dmasize = cnt;
 
-       if (*esc->sc_dmalen == 0) {
+       if (esc->sc_dmasize == 0) {
                esc->sc_tc = NCRSTAT_TC;
        }
        sc->sc_espstat |= esc->sc_tc;
@@ -498,6 +503,10 @@
        esc->sc_reg[reg * 16] = val;
 }
 
+#if DEBUG
+int mac68k_esp_debug=0;
+#endif
+
 int
 esp_quick_dma_intr(sc)
        struct ncr53c9x_softc *sc;
@@ -513,24 +522,31 @@
        if (esc->sc_dmasize == 0) {
                int     res;
 
-               res = 65536;
-               res -= NCR_READ_REG(sc, NCR_TCL);
-               res -= NCR_READ_REG(sc, NCR_TCM) << 8;
-               printf("dmaintr: discarded %d b (last transfer was %d b).\n",
-                       res, esc->sc_prevdmasize);
+               res = NCR_READ_REG(sc, NCR_TCL);
+               res += NCR_READ_REG(sc, NCR_TCM) << 8;
+               /* This can happen in the case of a TRPAD operation */
+               /* Pretend that it was complete */
+               sc->sc_espstat |= NCRSTAT_TC;
+#if DEBUG
+               if (mac68k_esp_debug) {
+                       printf("dmaintr: DMA xfer of zero xferred %d\n",
+                           65536 - res);
+               }
+#endif
                return 0;
        }
 
-       if (esc->sc_datain &&
-           (resid = (NCR_READ_REG(sc, NCR_FFLAG) & NCRFIFO_FF)) != 0) {
-               printf("dmaintr: empty FIFO of %d\n", resid);
-               DELAY(1);
-       }
-
        if ((sc->sc_espstat & NCRSTAT_TC) == 0) {
+               if (esc->sc_datain == 0) {
+                       resid = NCR_READ_REG(sc, NCR_FFLAG) & 0x1f;
+#if DEBUG
+                       if (mac68k_esp_debug) {
+                               printf("Write FIFO residual %d bytes\n", resid);
+                       }
+#endif
+               }
                resid += NCR_READ_REG(sc, NCR_TCL);
                resid += NCR_READ_REG(sc, NCR_TCM) << 8;
-
                if (resid == 0)
                        resid = 65536;
        }
@@ -538,10 +554,15 @@
        trans = esc->sc_dmasize - resid;
        if (trans < 0) {
                printf("dmaintr: trans < 0????");
-               trans = esc->sc_dmasize;
+               trans = *esc->sc_dmalen;
        }
 
        NCR_DMA(("dmaintr: trans %d, resid %d.\n", trans, resid));
+#if DEBUG
+       if (mac68k_esp_debug) {
+               printf("eqd_intr: trans %d, resid %d.\n", trans, resid);
+       }
+#endif
        *esc->sc_dmaaddr += trans;
        *esc->sc_dmalen -= trans;
 
@@ -561,19 +582,27 @@
        esc->sc_dmaaddr = addr;
        esc->sc_dmalen = len;
 
-       esc->sc_pdmaddr = (u_int16_t *) *addr;
-       esc->sc_pdmalen = *len;
-       if (esc->sc_pdmalen & 1) {
-               esc->sc_pdmalen--;
+       if (*len & 1) {
                esc->sc_pad = 1;
        } else {
                esc->sc_pad = 0;
        }
 
        esc->sc_datain = datain;
-       esc->sc_prevdmasize = esc->sc_dmasize;
        esc->sc_dmasize = *dmasize;
 
+#if DIAGNOSTIC
+       if (esc->sc_dmasize == 0) {
+               /* This can happen in the case of a TRPAD operation */
+       }
+#endif
+#if DEBUG
+       if (mac68k_esp_debug) {
+       printf("eqd_setup: addr %lx, len %lx, in? %d, dmasize %lx\n",
+           (long) *addr, (long) *len, datain, (long) esc->sc_dmasize);
+       }
+#endif
+
        return 0;
 }
 
@@ -581,10 +610,7 @@
 esp_dafb_have_dreq(esc)
        struct esp_softc *esc;
 {
-       u_int32_t r;
-
-       r = bus_space_read_4(esc->sc_tag, esc->sc_bsh, 0);
-       return (r & 0x200);
+       return (*(volatile u_int32_t *)(esc->sc_bsh.base) & 0x200);
 }
 
 static __inline__ int
@@ -594,92 +620,264 @@
        return (via2_reg(vIFR) & V2IF_SCSIDRQ);
 }
 
-static int espspl=-1;
-#define __splx(s) __asm __volatile ("movew %0,sr" : : "di" (s));
-#define __spl2()  __splx(PSL_S|PSL_IPL2)
-#define __spl6()  __splx(PSL_S|PSL_IPL6)
+static volatile int espspl=-1;
 
+/*
+ * Apple "DMA" is weird.
+ *
+ * Basically, the CPU acts like the DMA controller.  The DREQ/ off the
+ * chip goes to a register that we've mapped at attach time (on the
+ * IOSB or DAFB, depending on the machine).  Apple also provides some
+ * space for which the memory controller handshakes data to/from the
+ * NCR chip with the DACK/ line.  This space appears to be mapped over
+ * and over, every 4 bytes, but only the lower 16 bits are valid (but
+ * reading the upper 16 bits will handshake DACK/ just fine, so if you
+ * read *u_int16_t++ = *u_int16_t++ in a loop, you'll get
+ * <databyte><databyte>0xff0xff<databyte><databyte>0xff0xff...
+ *
+ * When you're attempting to read or write memory to this DACK/ed space,
+ * and the NCR is not ready for some timeout period, the system will
+ * generate a bus error.  This might be for one of several reasons:
+ *
+ *     1) (on write) The FIFO is full and is not draining.
+ *     2) (on read) The FIFO is empty and is not filling.
+ *     3) An interrupt condition has occurred.
+ *     4) Anything else?
+ *
+ * So if a bus error occurs, we first turn off the nofault bus error handler,
+ * then we check for an interrupt (which would render the first two
+ * possibilities moot).  If there's no interrupt, check for a DREQ/.  If we
+ * have that, then attempt to resume stuffing (or unstuffing) the FIFO.  If
+ * neither condition holds, pause briefly and check again.
+ *
+ * NOTE!!!  In order to make allowances for the hardware structure of
+ *          the mac, spl values in here are hardcoded!!!!!!!!!
+ *          This is done to allow serial interrupts to get in during
+ *          scsi transfers.  This is ugly.
+ */
 void
 esp_quick_dma_go(sc)
        struct ncr53c9x_softc *sc;
 {
        struct esp_softc *esc = (struct esp_softc *)sc;
+       extern long mac68k_a2_fromfault;
        extern int *nofault;
        label_t faultbuf;
        u_int16_t volatile *pdma;
+       u_int16_t *addr;
+       int             len, res;
+       u_short         cnt32, cnt2;
        u_char volatile *statreg;
 
        esc->sc_active = 1;
 
-       espspl = spl2();
+       espspl = splhigh();
+
+       addr = (u_int16_t *) *esc->sc_dmaaddr;
+       len  = esc->sc_dmasize;
 
 restart_dmago:
+#if DEBUG
+       if (mac68k_esp_debug) {
+               printf("eqdg: a %lx, l %lx, in? %d ... ",
+                   (long) addr, (long) len, esc->sc_datain);
+       }
+#endif
        nofault = (int *) &faultbuf;
        if (setjmp((label_t *) nofault)) {
                int     i=0;
 
                nofault = (int *) 0;
+#if DEBUG
+               if (mac68k_esp_debug) {
+                       printf("be\n");
+               }
+#endif
+               /*
+                * Bus error...
+                * So, we first check for an interrupt.  If we have
+                * one, go handle it.  Next we check for DREQ/.  If
+                * we have it, then we restart the transfer.  If
+                * neither, then loop until we get one or the other.
+                */
                statreg = esc->sc_reg + NCR_STAT * 16;
                for (;;) {
+                       spl2();         /* Give serial a chance... */
+                       splhigh();      /* That's enough... */
+
                        if (*statreg & 0x80) {
                                goto gotintr;
                        }
 
                        if (esp_have_dreq(esc)) {
+                               /*
+                                * Get the remaining length from the address
+                                * differential.
+                                */
+                               addr = (u_int16_t *) mac68k_a2_fromfault;
+                               len = esc->sc_dmasize -
+                                   ((long) addr - (long) *esc->sc_dmaaddr);
+
+                               if (esc->sc_datain == 0) {
+                                       /*
+                                        * Let the FIFO drain before we read
+                                        * the transfer count.
+                                        * Do we need to do this?
+                                        * Can we do this?
+                                        */
+                                       while (NCR_READ_REG(sc, NCR_FFLAG)
+                                           & 0x1f);
+                                       /*
+                                        * Get the length from the transfer
+                                        * counters.
+                                        */
+                                       res = NCR_READ_REG(sc, NCR_TCL);
+                                       res += NCR_READ_REG(sc, NCR_TCM) << 8;
+                                       /*
+                                        * If they don't agree,
+                                        * adjust accordingly.
+                                        */



Home | Main Index | Thread Index | Old Index