summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2013-10-23 10:07:15 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2013-10-23 10:07:15 +0000
commit0a855a73716d4fe9756848fbe8c78eb51571bb38 (patch)
tree9fe19150b497cc5481d8b4e0ba94151f52e20522 /sys
parent14e6eb75fff5b96950832ec33edd2fa22c98ddcd (diff)
Checkpoint of work-in-progress DMA support for oaic(4). Not working yet,
probably due to incorrect programming of the system board ``Diagnostic Control Register'', for which I do not have documentation yet; commited so as not to lose this work, since the machine I was testing on has apparently commited suicide and will no longer POST.
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/aviion/aviion/av400_machdep.c6
-rw-r--r--sys/arch/aviion/aviion/av530_machdep.c4
-rw-r--r--sys/arch/aviion/dev/dma.c217
-rw-r--r--sys/arch/aviion/dev/dmareg.h40
-rw-r--r--sys/arch/aviion/dev/dmavar.h23
-rw-r--r--sys/arch/aviion/dev/oaic_syscon.c89
-rw-r--r--sys/arch/aviion/include/board.h5
-rw-r--r--sys/dev/ic/aic6250.c43
-rw-r--r--sys/dev/ic/aic6250var.h6
9 files changed, 424 insertions, 9 deletions
diff --git a/sys/arch/aviion/aviion/av400_machdep.c b/sys/arch/aviion/aviion/av400_machdep.c
index ad06858f2d5..65c495d170b 100644
--- a/sys/arch/aviion/aviion/av400_machdep.c
+++ b/sys/arch/aviion/aviion/av400_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: av400_machdep.c,v 1.25 2013/10/10 21:24:58 miod Exp $ */
+/* $OpenBSD: av400_machdep.c,v 1.26 2013/10/23 10:07:14 miod Exp $ */
/*
* Copyright (c) 2006, 2007, Miodrag Vallat.
*
@@ -522,7 +522,7 @@ av400_intsrc(int i)
AV400_IRQ_ECI,
0,
AV400_IRQ_SCI,
- 0,
+ AV400_IRQ_DTC,
AV400_IRQ_VME1,
AV400_IRQ_VME2,
AV400_IRQ_VME3,
@@ -558,7 +558,7 @@ static const u_int av400_obio_vec[32] = {
INTSRC_VME(3), /* VME3 */
0, /* DWP */
INTSRC_VME(4), /* VME4 */
- 0, /* DTC */
+ INTSRC_DMA, /* DTC */
INTSRC_VME(5), /* VME5 */
INTSRC_ETHERNET1, /* ECI */
INTSRC_DUART2, /* DI2 */
diff --git a/sys/arch/aviion/aviion/av530_machdep.c b/sys/arch/aviion/aviion/av530_machdep.c
index c0603e9b740..503d4ab9ecf 100644
--- a/sys/arch/aviion/aviion/av530_machdep.c
+++ b/sys/arch/aviion/aviion/av530_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: av530_machdep.c,v 1.11 2013/10/10 21:24:58 miod Exp $ */
+/* $OpenBSD: av530_machdep.c,v 1.12 2013/10/23 10:07:14 miod Exp $ */
/*
* Copyright (c) 2006, 2007, 2010 Miodrag Vallat.
*
@@ -428,6 +428,7 @@ av530_intsrc(int i)
0,
0,
0,
+ 0,
AV530_IRQ_VME1,
AV530_IRQ_VME2,
AV530_IRQ_VME3,
@@ -461,6 +462,7 @@ av530_exintsrc(int i)
0,
0,
0,
+ 0,
0
};
diff --git a/sys/arch/aviion/dev/dma.c b/sys/arch/aviion/dev/dma.c
new file mode 100644
index 00000000000..eedb46875f1
--- /dev/null
+++ b/sys/arch/aviion/dev/dma.c
@@ -0,0 +1,217 @@
+/* $OpenBSD: dma.c,v 1.1 2013/10/23 10:07:14 miod Exp $ */
+
+/*
+ * Copyright (c) 2013 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+#include <sys/queue.h>
+
+#include <uvm/uvm.h>
+
+#include <machine/autoconf.h>
+#include <machine/board.h>
+
+#include <aviion/dev/sysconvar.h>
+
+#include <aviion/dev/dmareg.h>
+#include <aviion/dev/dmavar.h>
+
+/*
+ * DMA request information structure.
+ */
+struct dmareq {
+ TAILQ_ENTRY(dmareq) chain;
+
+ vaddr_t mem;
+ size_t len;
+ uint dir;
+
+ size_t lastcnt;
+
+ void *cbarg;
+ void (*cbstart)(void *);
+ void (*cbdone)(void *);
+};
+
+struct dma_softc {
+ struct device sc_dev;
+
+ struct intrhand sc_ih;
+
+ TAILQ_HEAD(, dmareq) sc_req;
+};
+
+int dma_match(struct device *, void *, void *);
+void dma_attach(struct device *, struct device *, void *);
+
+const struct cfattach dma_ca = {
+ sizeof(struct dma_softc), dma_match, dma_attach
+};
+
+struct cfdriver dma_cd = {
+ NULL, "dma", DV_DULL
+};
+
+int dma_intr(void *);
+void dma_start(struct dma_softc *);
+
+int
+dma_match(struct device *parent, void *match, void *aux)
+{
+ struct confargs *ca = aux;
+
+ switch (cpuid) {
+#ifdef AV400
+ case AVIION_300_310:
+ case AVIION_400_4000:
+ case AVIION_410_4100:
+ case AVIION_300C_310C:
+ case AVIION_300CD_310CD:
+ case AVIION_300D_310D:
+ case AVIION_4300_25:
+ case AVIION_4300_20:
+ case AVIION_4300_16:
+ if (ca->ca_paddr == DMA_MAP)
+ return 1;
+ /* FALLTHROUGH */
+#endif
+ default:
+ return 0;
+ }
+}
+
+void
+dma_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct dma_softc *sc = (struct dma_softc *)self;
+
+ printf("\n");
+
+ *(volatile uint32_t *)DMA_COUNT = 0; /* clear possibly pending int */
+
+ TAILQ_INIT(&sc->sc_req);
+
+ sc->sc_ih.ih_fn = dma_intr;
+ sc->sc_ih.ih_arg = sc;
+ sc->sc_ih.ih_flags = 0;
+ sc->sc_ih.ih_ipl = IPL_BIO;
+ sysconintr_establish(INTSRC_DMA, &sc->sc_ih, self->dv_xname);
+}
+
+int
+dma_intr(void *v)
+{
+ struct dma_softc *sc = v;
+ struct dmareq *req;
+ size_t tc;
+
+ req = TAILQ_FIRST(&sc->sc_req);
+ if (req == NULL) {
+ printf("%s: interrupt but no active request?\n", __func__);
+ *(volatile uint32_t *)DMA_STOP = DMASTOP_INHIBIT;
+ return -1;
+ }
+
+ tc = *(volatile uint32_t *)DMA_COUNT;
+ if (tc != 0)
+ printf("%s: unexpected intr, TC = %x\n", __func__, tc);
+ req->len -= req->lastcnt;
+ if (req->len == 0) {
+ /* this transfer is over */
+ TAILQ_REMOVE(&sc->sc_req, req, chain);
+
+ if (req->cbdone != NULL)
+ (*req->cbdone)(req->cbarg);
+
+ free(req, M_DEVBUF);
+ } else {
+ req->mem += req->lastcnt;
+ }
+ dma_start(sc);
+
+ return 1;
+}
+
+int
+dma_req(void *vaddr, size_t sz, int dir, void (*cbstart)(void *),
+ void (*cbdone)(void *), void *cbarg)
+{
+ struct dma_softc *sc;
+ struct dmareq *req;
+ int run;
+ int s;
+
+ if (dma_cd.cd_devs == NULL ||
+ (sc = (struct dma_softc *)dma_cd.cd_devs[0]) == NULL)
+ return ENXIO;
+ req = malloc(sizeof *req, M_DEVBUF, M_NOWAIT | M_CANFAIL);
+ if (req == NULL)
+ return ENOMEM;
+
+ req->mem = (vaddr_t)vaddr;
+ req->len = sz;
+ req->dir = dir;
+ req->cbstart = cbstart;
+ req->cbdone = cbdone;
+ req->cbarg = cbarg;
+ req->lastcnt = 0;
+
+ s = splbio();
+ run = TAILQ_EMPTY(&sc->sc_req);
+ TAILQ_INSERT_TAIL(&sc->sc_req, req, chain);
+ if (run)
+ dma_start(sc);
+ splx(s);
+
+ return 0;
+}
+
+void
+dma_start(struct dma_softc *sc)
+{
+ struct dmareq *req;
+ paddr_t pa, paoff;
+
+ req = TAILQ_FIRST(&sc->sc_req);
+ if (req == NULL) {
+ *(volatile uint32_t *)DMA_STOP = DMASTOP_INHIBIT;
+ return;
+ }
+
+ if (pmap_extract(pmap_kernel(), req->mem, &pa) == FALSE)
+ panic("%s: pmap_extract(%p) failed",
+ __func__, (void *)req->mem);
+
+ paoff = pa & ~DMAMAP_MASK;
+
+ req->lastcnt = DMA_BOUNDARY - paoff;
+ if (req->lastcnt > req->len)
+ req->lastcnt = req->len;
+
+ *(volatile uint32_t *)DMA_DIR = req->dir;
+ *(volatile uint32_t *)DMA_COUNT = req->lastcnt;
+ *(volatile uint32_t *)DMA_OFF = paoff;
+ *(volatile uint32_t *)DMA_MAP = (pa & DMAMAP_MASK) |
+ DMAMAP_G | DMAMAP_V;
+ *(volatile uint32_t *)DMA_CLR_INVALID = DMACLR;
+ *(volatile uint32_t *)DMA_STOP = DMASTOP_RESTART;
+
+ if (req->cbstart != NULL)
+ (*req->cbstart)(req->cbarg);
+}
diff --git a/sys/arch/aviion/dev/dmareg.h b/sys/arch/aviion/dev/dmareg.h
new file mode 100644
index 00000000000..d60301c15c3
--- /dev/null
+++ b/sys/arch/aviion/dev/dmareg.h
@@ -0,0 +1,40 @@
+/* $OpenBSD: dmareg.h,v 1.1 2013/10/23 10:07:14 miod Exp $ */
+
+/*
+ * Copyright (c) 2013 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * AV400 family DMA controller definitions
+ */
+
+#define DMA_BOUNDARY 0x1000
+
+#define DMA_MAP 0xfff8b000
+#define DMAMAP_MASK 0xfffff000
+#define DMAMAP_G 0x00000080
+#define DMAMAP_RO 0x00000004
+#define DMAMAP_V 0x00000001
+#define DMA_OFF 0xfff8b004
+#define DMAOFF_MASK 0x00000ffe
+#define DMA_COUNT 0xfff8b008
+#define DMACOUNTC_MASK 0x00001ffe
+#define DMA_DIR 0xfff8b00c
+#define DMA_CLR_INVALID 0xfff8b010
+#define DMA_CLR_WP 0xfff8b014
+#define DMACLR 0x00000000
+#define DMA_STOP 0xfff8b018
+#define DMASTOP_RESTART 0x00000000 /* restart DMA */
+#define DMASTOP_INHIBIT 0x00000001 /* do not restart DMA */
diff --git a/sys/arch/aviion/dev/dmavar.h b/sys/arch/aviion/dev/dmavar.h
new file mode 100644
index 00000000000..23527e9821d
--- /dev/null
+++ b/sys/arch/aviion/dev/dmavar.h
@@ -0,0 +1,23 @@
+/* $OpenBSD: dmavar.h,v 1.1 2013/10/23 10:07:14 miod Exp $ */
+
+/*
+ * Copyright (c) 2013 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#define DMADIR_TO_DEVICE 0x00000001 /* DMA from memory to device */
+#define DMADIR_FROM_DEVICE 0x00000000 /* DMA from device to memory */
+
+int dma_req(void *, size_t, int,
+ void (*)(void *), void (*)(void *), void *);
diff --git a/sys/arch/aviion/dev/oaic_syscon.c b/sys/arch/aviion/dev/oaic_syscon.c
index 83294ae47ce..3d3402ec051 100644
--- a/sys/arch/aviion/dev/oaic_syscon.c
+++ b/sys/arch/aviion/dev/oaic_syscon.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: oaic_syscon.c,v 1.1 2013/10/15 01:41:44 miod Exp $ */
+/* $OpenBSD: oaic_syscon.c,v 1.2 2013/10/23 10:07:14 miod Exp $ */
/*
* Copyright (c) 2013 Miodrag Vallat.
@@ -33,6 +33,9 @@
#include <dev/ic/aic6250reg.h>
#include <dev/ic/aic6250var.h>
+#if 0
+#include <aviion/dev/dmavar.h>
+#endif
int oaic_syscon_match(struct device *, void *, void *);
void oaic_syscon_attach(struct device *, struct device *, void *);
@@ -42,6 +45,9 @@ struct oaic_syscon_softc {
bus_space_tag_t sc_iot;
bus_space_handle_t sc_ioh;
struct intrhand sc_ih;
+#if 0
+ uint8_t sc_dmac;
+#endif
};
const struct cfattach oaic_syscon_ca = {
@@ -52,6 +58,13 @@ const struct cfattach oaic_syscon_ca = {
uint8_t oaic_read(struct aic6250_softc *, uint);
void oaic_write(struct aic6250_softc *, uint, uint8_t);
+#if 0
+int oaic_dmastart(struct aic6250_softc *, void *, size_t, int);
+int oaic_dmadone(struct aic6250_softc *);
+void oaic_dmago(void *);
+void oaic_dmastop(void *);
+#endif
+
int
oaic_syscon_match(struct device *parent, void *match, void *aux)
{
@@ -122,6 +135,11 @@ oaic_syscon_attach(struct device *parent, struct device *self, void *aux)
sc->sc_read = oaic_read;
sc->sc_write = oaic_write;
+#if 0
+ sc->sc_dma_start = oaic_dmastart;
+ sc->sc_dma_done = oaic_dmadone;
+#endif
+
aic6250_attach(sc);
ssc->sc_ih.ih_fn = (int(*)(void *))aic6250_intr;
@@ -149,3 +167,72 @@ oaic_write(struct aic6250_softc *sc, uint reg, uint8_t val)
bus_space_write_4(ssc->sc_iot, ssc->sc_ioh, reg << 2, val);
}
+
+#if 0
+int
+oaic_dmastart(struct aic6250_softc *sc, void *addr, size_t size, int datain)
+{
+ struct oaic_syscon_softc *osc = (struct oaic_syscon_softc *)sc;
+ char *vaddr = (char *)addr;
+
+ /*
+ * The DMA engine can only operate on 16-bit words.
+ */
+ if (size & 1)
+ return EINVAL;
+
+ osc->sc_dmac = AIC_DC_DMA_XFER_EN | (datain ? 0 : AIC_DC_TRANSFER_DIR);
+ if ((vaddr_t)vaddr & 1) {
+ if (datain) {
+ /*
+ * The AIC_DC_ODD_XFER_START bit ought to have been
+ * set before changing phase to DATA IN.
+ */
+ return EINVAL;
+ }
+ vaddr--;
+ osc->sc_dmac |= AIC_DC_ODD_XFER_START;
+ }
+
+ return dma_req(vaddr, size,
+ datain ? DMADIR_FROM_DEVICE : DMADIR_TO_DEVICE,
+ oaic_dmago, oaic_dmastop, sc);
+}
+
+void
+oaic_dmago(void *v)
+{
+ struct aic6250_softc *sc = (struct aic6250_softc *)v;
+ struct oaic_syscon_softc *osc = (struct oaic_syscon_softc *)sc;
+
+ sc->sc_flags |= AIC_DOINGDMA;
+
+ oaic_write(sc, AIC_DMA_BYTE_COUNT_H, sc->sc_dleft >> 16);
+ oaic_write(sc, AIC_DMA_BYTE_COUNT_M, sc->sc_dleft >> 8);
+ oaic_write(sc, AIC_DMA_BYTE_COUNT_L, sc->sc_dleft);
+ oaic_write(sc, AIC_DMA_CNTRL, osc->sc_dmac);
+}
+
+void
+oaic_dmastop(void *v)
+{
+ struct aic6250_softc *sc = (struct aic6250_softc *)v;
+
+ sc->sc_flags &= ~AIC_DOINGDMA;
+}
+
+int
+oaic_dmadone(struct aic6250_softc *sc)
+{
+ int resid;
+
+ resid = oaic_read(sc, AIC_DMA_BYTE_COUNT_H) << 16 |
+ oaic_read(sc, AIC_DMA_BYTE_COUNT_M) << 8 |
+ oaic_read(sc, AIC_DMA_BYTE_COUNT_L);
+
+ sc->sc_dp += sc->sc_dleft - resid;
+ sc->sc_dleft = resid;
+
+ return 0;
+}
+#endif
diff --git a/sys/arch/aviion/include/board.h b/sys/arch/aviion/include/board.h
index 6946b1ad329..9102a931416 100644
--- a/sys/arch/aviion/include/board.h
+++ b/sys/arch/aviion/include/board.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: board.h,v 1.13 2013/10/10 21:24:59 miod Exp $ */
+/* $OpenBSD: board.h,v 1.14 2013/10/23 10:07:14 miod Exp $ */
/*
* Copyright (c) 2006, 2007, Miodrag Vallat
*
@@ -139,7 +139,8 @@ extern const struct board *platform;/* just to have people confuse both names */
#define INTSRC_ETHERNET2 8 /* second on-board Ethernet */
#define INTSRC_SCSI1 9 /* first on-board SCSI controller */
#define INTSRC_SCSI2 10 /* second on-board SCSI controller */
-#define NINTSRC_SYSCON 11 /* total number of non-VME sources */
+#define INTSRC_DMA 11 /* DMA completion interrupt */
+#define NINTSRC_SYSCON 12 /* total number of non-VME sources */
#define INTSRC_VME(lvl) (NINTSRC_SYSCON + (lvl) - 1) /* seven VME levels */
#define IS_VME_INTSRC(intsrc) ((intsrc) >= NINTSRC_SYSCON)
diff --git a/sys/dev/ic/aic6250.c b/sys/dev/ic/aic6250.c
index c0c4f5c88a2..67a2bd02e48 100644
--- a/sys/dev/ic/aic6250.c
+++ b/sys/dev/ic/aic6250.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: aic6250.c,v 1.1 2013/10/15 01:41:45 miod Exp $ */
+/* $OpenBSD: aic6250.c,v 1.2 2013/10/23 10:07:14 miod Exp $ */
/*
* Copyright (c) 2010, 2013 Miodrag Vallat.
@@ -100,6 +100,9 @@
#define AIC_ABORT_TIMEOUT 2000 /* time to wait for abort */
+/* threshold length for DMA transfer */
+#define AIC_MIN_DMA_LEN 32
+
/* End of customizable parameters */
#include <sys/types.h>
@@ -1376,11 +1379,20 @@ aic6250_intr(void *arg)
loop:
sr0 = (*sc->sc_read)(sc, AIC_STATUS_REG0);
+
/*
* First check for abnormal conditions, such as reset.
*/
AIC_MISC(("sr0:0x%02x ", sr0));
+ /*
+ * Check for the end of a DMA operation before doing anything else...
+ */
+ if ((sc->sc_flags & AIC_DOINGDMA) != 0 &&
+ (sr0 & AIC_SR1_CMD_DONE) != 0) {
+ (*sc->sc_dma_done)(sc);
+ }
+
if ((sr0 & AIC_SR0_SCSI_RST_OCCURED) != 0) {
printf("%s: SCSI bus reset\n", sc->sc_dev.dv_xname);
while (((*sc->sc_read)(sc, AIC_STATUS_REG1) &
@@ -1618,6 +1630,13 @@ loop:
}
}
+ /*
+ * Do not change phase (yet) if we have a pending DMA operation.
+ */
+ if ((sc->sc_flags & AIC_DOINGDMA) != 0) {
+ goto out;
+ }
+
dophase:
if ((sr0 & AIC_SR0_SCSI_REQ_ON) == 0) {
/* Wait for AIC_SR0_SCSI_REQ_ON. */
@@ -1665,6 +1684,17 @@ dophase:
if (sc->sc_state != AIC_CONNECTED)
break;
AIC_MISC(("dataout dleft=%lu ", (u_long)sc->sc_dleft));
+ if (sc->sc_dma_start != NULL &&
+ sc->sc_dleft > AIC_MIN_DMA_LEN) {
+ AIC_ASSERT(sc->sc_nexus != NULL);
+ acb = sc->sc_nexus;
+ if ((acb->xs->flags & SCSI_POLL) == 0 &&
+ (*sc->sc_dma_start)
+ (sc, sc->sc_dp, sc->sc_dleft, 0) == 0) {
+ sc->sc_prevphase = PH_DATAOUT;
+ goto out;
+ }
+ }
n = aic6250_dataout_pio(sc, sc->sc_dp, sc->sc_dleft, PH_DATAOUT);
sc->sc_dp += n;
sc->sc_dleft -= n;
@@ -1675,6 +1705,17 @@ dophase:
if (sc->sc_state != AIC_CONNECTED)
break;
AIC_MISC(("datain %lu ", (u_long)sc->sc_dleft));
+ if (sc->sc_dma_start != NULL &&
+ sc->sc_dleft > AIC_MIN_DMA_LEN) {
+ AIC_ASSERT(sc->sc_nexus != NULL);
+ acb = sc->sc_nexus;
+ if ((acb->xs->flags & SCSI_POLL) == 0 &&
+ (*sc->sc_dma_start)
+ (sc, sc->sc_dp, sc->sc_dleft, 1) == 0) {
+ sc->sc_prevphase = PH_DATAIN;
+ goto out;
+ }
+ }
n = aic6250_datain_pio(sc, sc->sc_dp, sc->sc_dleft, PH_DATAIN);
sc->sc_dp += n;
sc->sc_dleft -= n;
diff --git a/sys/dev/ic/aic6250var.h b/sys/dev/ic/aic6250var.h
index 713e165ce0f..f5e49a24015 100644
--- a/sys/dev/ic/aic6250var.h
+++ b/sys/dev/ic/aic6250var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: aic6250var.h,v 1.1 2013/10/15 01:41:46 miod Exp $ */
+/* $OpenBSD: aic6250var.h,v 1.2 2013/10/23 10:07:14 miod Exp $ */
/*
* Copyright (c) 2010, 2013 Miodrag Vallat.
@@ -190,6 +190,10 @@ struct aic6250_softc {
int sc_freq; /* Clock frequency in MHz */
int sc_minsync; /* Minimum sync period / 4 */
int sc_maxsync; /* Maximum sync period / 4 */
+
+ /* DMA function set from MD code */
+ int (*sc_dma_start)(struct aic6250_softc *, void *, size_t, int);
+ int (*sc_dma_done)(struct aic6250_softc *);
};
#if AIC_DEBUG