Source-Changes-HG archive

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

[src/trunk]: src/sys/arch/mac68k PR port-mac68k/24883



details:   https://anonhg.NetBSD.org/src/rev/27bab5f8ad0f
branches:  trunk
changeset: 457868:27bab5f8ad0f
user:      rin <rin%NetBSD.org@localhost>
date:      Tue Jul 23 15:19:07 2019 +0000

description:
PR port-mac68k/24883

Support DMA xfer for SCSI adapter of AV Mac (660/840AV), written by
Michael Zucca.

This improves disk I/O performance by nearly one order of magnitude.
In addition, interrupt storm due to heavy disk PIO is resolved.

I'm deeply grateful to Michael Zucca for his analysis of DMA engine
and submission of PR. I also thank Izumi Tsutsui (useful comments on
port-mac68k@) and Martin Husemann (test on 660AV).

diffstat:

 sys/arch/mac68k/include/psc.h |   20 +-
 sys/arch/mac68k/mac68k/psc.c  |  168 ++++++++++++++-
 sys/arch/mac68k/obio/esp.c    |  471 +++++++++++++++++++++++++++++++++++++++++-
 sys/arch/mac68k/obio/espvar.h |    8 +-
 4 files changed, 655 insertions(+), 12 deletions(-)

diffs (truncated from 818 to 300 lines):

diff -r 421a215da55c -r 27bab5f8ad0f sys/arch/mac68k/include/psc.h
--- a/sys/arch/mac68k/include/psc.h     Tue Jul 23 14:34:11 2019 +0000
+++ b/sys/arch/mac68k/include/psc.h     Tue Jul 23 15:19:07 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: psc.h,v 1.7 2005/12/11 12:18:03 christos Exp $ */
+/*     $NetBSD: psc.h,v 1.8 2019/07/23 15:19:07 rin Exp $      */
 
 /*-
  * Copyright (c) 1997 David Huang <khym%azeotrope.org@localhost>
@@ -25,6 +25,8 @@
  *
  */
 
+#include <sys/bus.h>   /* XXX for bus_addr_t */
+
 /*
  * Some register definitions for the PSC, present only on the
  * Centris/Quadra 660av and the Quadra 840av.
@@ -48,6 +50,11 @@
 int    remove_psc_lev5_intr(int);
 int    remove_psc_lev6_intr(int);
 
+int    start_psc_dma(int, int *, bus_addr_t, uint32_t, int);
+int    pause_psc_dma(int);
+int    wait_psc_dma(int, int, uint32_t *);
+int    stop_psc_dma(int, int, uint32_t *, int);
+
 /*
  * Reading an interrupt status register returns a mask of the
  * currently interrupting devices (one bit per device). Reading an
@@ -123,3 +130,14 @@
  */
 #define        PSC_SET0        0x00
 #define        PSC_SET1        0x10
+
+/*
+ * Pseudo channels for the dma control functions
+ */
+#define        PSC_DMA_CHANNEL_SCSI    0
+#define        PSC_DMA_CHANNEL_ENETRD  1
+#define        PSC_DMA_CHANNEL_ENETWR  2
+#define        PSC_DMA_CHANNEL_FDC     3
+#define        PSC_DMA_CHANNEL_SCCA    4
+#define        PSC_DMA_CHANNEL_SCCB    5
+#define        PSC_DMA_CHANNEL_SCCATX  6
diff -r 421a215da55c -r 27bab5f8ad0f sys/arch/mac68k/mac68k/psc.c
--- a/sys/arch/mac68k/mac68k/psc.c      Tue Jul 23 14:34:11 2019 +0000
+++ b/sys/arch/mac68k/mac68k/psc.c      Tue Jul 23 15:19:07 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: psc.c,v 1.10 2005/12/11 12:18:03 christos Exp $        */
+/*     $NetBSD: psc.c,v 1.11 2019/07/23 15:19:07 rin Exp $     */
 
 /*-
  * Copyright (c) 1997 David Huang <khym%azeotrope.org@localhost>
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: psc.c,v 1.10 2005/12/11 12:18:03 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: psc.c,v 1.11 2019/07/23 15:19:07 rin Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -51,6 +51,9 @@
 int            psc_lev6_intr(void *);
 static void    psc_lev6_noint(void *);
 
+static int     stop_read_psc_dma(int, int, uint32_t *);
+static int     stop_write_psc_dma(int, int, uint32_t *);
+
 void   (*psc3_ihandler)(void *) = psc_lev3_noint;
 void   *psc3_iarg;
 
@@ -324,3 +327,164 @@
 {
        printf("psc_lev6_noint: device %d\n", (int)arg);
 }
+
+/*
+ * DMA Control routines for esp(4).
+ * XXX Need to be merged with DMA engine of mc(4).
+ */
+
+int
+start_psc_dma(int channel, int *rset, bus_addr_t addr, uint32_t len, int datain)
+{
+       int chan_ctrl, rset_addr, rset_len, rset_cmd, s;
+
+       s = splhigh(); 
+
+       chan_ctrl = PSC_CTLBASE + (channel << 4);
+
+       pause_psc_dma(channel);
+
+       *rset = (psc_reg2(chan_ctrl) & 1) << 4;
+
+       rset_addr = PSC_ADDRBASE + (0x20 * channel) + *rset;
+       rset_len = rset_addr + 4;
+       rset_cmd = rset_addr + 8;
+
+       (void)psc_reg2(rset_cmd);
+       psc_reg4(rset_len) = len;
+       psc_reg4(rset_addr) = addr;
+
+       if (datain)
+               psc_reg2(rset_cmd) = 0x8200;
+       else
+               psc_reg2(rset_cmd) = 0x200;
+
+       psc_reg2(rset_cmd) = 0x100;
+       psc_reg2(rset_cmd) = 0x8800;
+       psc_reg2(chan_ctrl) = 0x400;
+
+       splx(s);
+
+       return 0;
+}
+
+int
+pause_psc_dma(int channel)
+{
+       int chan_ctrl, s;
+
+       s = splhigh();
+
+       chan_ctrl = PSC_CTLBASE + (channel << 4);
+
+       psc_reg2(chan_ctrl) = 0x8400;
+
+       while (!(psc_reg2(chan_ctrl) & 0x4000))
+               continue;
+
+       splx(s);
+
+       return 0;
+}
+
+int
+wait_psc_dma(int channel, int rset, uint32_t *residual)
+{
+       int rset_addr, rset_len, rset_cmd, s;
+
+       s = splhigh();
+
+       rset_addr = PSC_ADDRBASE + (0x20 * channel) + rset;
+       rset_len = rset_addr + 4;
+       rset_cmd = rset_addr + 8;
+
+       while (!(psc_reg2(rset_cmd) & 0x100))
+               continue;
+
+       while (psc_reg2(rset_cmd) & 0x800)
+               continue;
+
+       *residual = psc_reg4(rset_len);
+
+       splx(s);
+
+       if (*residual)
+               return -1;
+       else
+               return 0;
+}
+
+int
+stop_psc_dma(int channel, int rset, uint32_t *residual, int datain)
+{
+       int rval, s;
+
+       s = splhigh();
+
+       if (datain)
+               rval = stop_read_psc_dma(channel, rset, residual);
+       else
+               rval = stop_write_psc_dma(channel, rset, residual);
+
+       splx(s);
+
+       return rval;
+}
+
+static int
+stop_read_psc_dma(int channel, int rset, uint32_t *residual)
+{
+       int chan_ctrl, rset_addr, rset_len, rset_cmd;
+
+       chan_ctrl = PSC_CTLBASE + (channel << 4);
+       rset_addr = PSC_ADDRBASE + (0x20 * channel) + rset;
+       rset_len = rset_addr + 4;
+       rset_cmd = rset_addr + 8;
+
+       if (psc_reg2(rset_cmd) & 0x400) {
+               *residual = 0;
+               return 0;
+       }
+
+       psc_reg2(chan_ctrl) = 0x8200;
+
+       while (psc_reg2(chan_ctrl) & 0x200)
+               continue;
+
+       pause_psc_dma(channel);
+
+       *residual = psc_reg4(rset_len);
+       if (*residual == 0)
+               return 0;
+
+       do {
+               psc_reg4(rset_len) = 0;
+       } while (psc_reg4(rset_len));
+
+       return 0;
+}
+
+static int
+stop_write_psc_dma(int channel, int rset, uint32_t *residual)
+{
+       int chan_ctrl, rset_addr, rset_len, rset_cmd;
+
+       rset_addr = PSC_ADDRBASE + (0x20 * channel) + rset;
+       rset_cmd = rset_addr + 8;
+
+       if (psc_reg2(rset_cmd) & 0x400) {
+               *residual = 0;
+               return 0;
+       }
+
+       chan_ctrl = PSC_CTLBASE + (channel << 4); 
+       rset_len = rset_addr + 4;
+
+       pause_psc_dma(channel);
+
+       *residual = psc_reg4(rset_len);
+
+       psc_reg2(chan_ctrl) = 0x8800;
+
+       return 0;
+}
diff -r 421a215da55c -r 27bab5f8ad0f sys/arch/mac68k/obio/esp.c
--- a/sys/arch/mac68k/obio/esp.c        Tue Jul 23 14:34:11 2019 +0000
+++ b/sys/arch/mac68k/obio/esp.c        Tue Jul 23 15:19:07 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: esp.c,v 1.57 2019/07/23 07:52:53 rin Exp $     */
+/*     $NetBSD: esp.c,v 1.58 2019/07/23 15:19:07 rin Exp $     */
 
 /*
  * Copyright (c) 1997 Jason R. Thorpe.
@@ -76,8 +76,12 @@
  *  "DMA" glue functions).
  */
 
+/*
+ * AV DMA support from Michael Zucca (mrz5149%acm.org@localhost)
+ */
+
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: esp.c,v 1.57 2019/07/23 07:52:53 rin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: esp.c,v 1.58 2019/07/23 15:19:07 rin Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -85,12 +89,15 @@
 #include <sys/bus.h>
 #include <sys/device.h>
 
+#include <uvm/uvm_extern.h>
+
 #include <dev/scsipi/scsiconf.h>
 
 #include <dev/ic/ncr53c9xreg.h>
 #include <dev/ic/ncr53c9xvar.h>
 
 #include <machine/cpu.h>
+#include <machine/psc.h>
 #include <machine/viareg.h>
 
 #include <mac68k/obio/espvar.h>
@@ -122,6 +129,15 @@
                        size_t *, int, size_t *);
 static void    esp_quick_dma_go(struct ncr53c9x_softc *);
 
+static void    esp_av_write_reg(struct ncr53c9x_softc *, int, uint8_t);
+static void    esp_av_dma_reset(struct ncr53c9x_softc *);
+static int     esp_av_dma_intr(struct ncr53c9x_softc *);
+static int     esp_av_pio_intr(struct ncr53c9x_softc *);
+static int     esp_av_dma_setup(struct ncr53c9x_softc *, uint8_t **, size_t *,
+                       int, size_t *);
+static void    esp_av_dma_go(struct ncr53c9x_softc *);
+static void    esp_av_dma_stop(struct ncr53c9x_softc *);
+
 static void    esp_intr(void *);
 static void    esp_dualbus_intr(void *);
 
@@ -167,7 +183,7 @@
        struct obio_attach_args *oa = aux;
        bus_addr_t              addr;
        unsigned long           reg_offset;
-       int                     quick = 0;
+       int                     quick = 0, avdma = 0;
        uint8_t                 irq_mask;       /* mask for clearing IRQ */



Home | Main Index | Thread Index | Old Index