summaryrefslogtreecommitdiff
path: root/sys/dev/ic
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/dev/ic
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/dev/ic')
-rw-r--r--sys/dev/ic/aic6250.c43
-rw-r--r--sys/dev/ic/aic6250var.h6
2 files changed, 47 insertions, 2 deletions
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