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/9d84dd2e2fd9
branches: trunk
changeset: 842746:9d84dd2e2fd9
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 deeadf89e35c -r 9d84dd2e2fd9 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 deeadf89e35c -r 9d84dd2e2fd9 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 deeadf89e35c -r 9d84dd2e2fd9 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