diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2013-10-23 10:07:15 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2013-10-23 10:07:15 +0000 |
commit | 0a855a73716d4fe9756848fbe8c78eb51571bb38 (patch) | |
tree | 9fe19150b497cc5481d8b4e0ba94151f52e20522 /sys/dev/ic | |
parent | 14e6eb75fff5b96950832ec33edd2fa22c98ddcd (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.c | 43 | ||||
-rw-r--r-- | sys/dev/ic/aic6250var.h | 6 |
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 |