summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/aic/aic.c109
1 files changed, 61 insertions, 48 deletions
diff --git a/sys/dev/aic/aic.c b/sys/dev/aic/aic.c
index db8c2b7..e103a6f 100644
--- a/sys/dev/aic/aic.c
+++ b/sys/dev/aic/aic.c
@@ -59,7 +59,6 @@ static void aic_reselected __P((struct aic_softc *aic));
static void aic_cmd __P((struct aic_softc *aic));
static void aic_msgin __P((struct aic_softc *aic));
static void aic_handle_msgin __P((struct aic_softc *aic));
-static void aic_sched_msgout __P((struct aic_softc *aic, u_int8_t msg));
static void aic_msgout __P((struct aic_softc *aic));
static void aic_datain __P((struct aic_softc *aic));
static void aic_dataout __P((struct aic_softc *aic));
@@ -464,6 +463,20 @@ aic_reselected(struct aic_softc *aic)
}
/*
+ * Raise ATNO to signal the target that we have a message for it.
+ */
+static __inline void
+aic_sched_msgout(struct aic_softc *aic, u_int8_t msg)
+{
+ if (msg) {
+ aic->msg_buf[0] = msg;
+ aic->msg_len = 1;
+ }
+ aic->msg_outq |= AIC_MSG_MSGBUF;
+ aic_outb(aic, SCSISIGO, aic_inb(aic, SCSISIGI) | ATNO);
+}
+
+/*
* Wait for SPIORDY (SCSI PIO ready) flag, or a phase change.
*/
static __inline int
@@ -595,7 +608,10 @@ aic_handle_msgin(struct aic_softc *aic)
/* ABORT if nothing is found */
if (!ccb_h) {
- aic_sched_msgout(aic, MSG_ABORT); /* MSG_ABORT_TAG?*/
+ if (tag == -1)
+ aic_sched_msgout(aic, MSG_ABORT);
+ else
+ aic_sched_msgout(aic, MSG_ABORT_TAG);
return;
}
@@ -733,20 +749,6 @@ aic_handle_msgin(struct aic_softc *aic)
}
/*
- * Raise ATNO to signal the target that we have a message for it.
- */
-static void
-aic_sched_msgout(struct aic_softc *aic, u_int8_t msg)
-{
- if (msg) {
- aic->msg_buf[0] = msg;
- aic->msg_len = 1;
- }
- aic->msg_outq |= AIC_MSG_MSGBUF;
- aic_outb(aic, SCSISIGO, aic_inb(aic, SCSISIGI) | ATNO);
-}
-
-/*
* Send messages.
*/
static void
@@ -841,7 +843,7 @@ static void
aic_datain(struct aic_softc *aic)
{
struct aic_scb *scb = aic->nexus;
- u_int8_t dmastat;
+ u_int8_t dmastat, dmacntrl0;
int n;
CAM_DEBUG_PRINT(CAM_DEBUG_TRACE, ("aic_datain\n"));
@@ -849,9 +851,14 @@ aic_datain(struct aic_softc *aic)
aic_outb(aic, SIMODE1, ENSCSIRST|ENPHASEMIS|ENBUSFREE);
aic_outb(aic, SXFRCTL0, SCSIEN|DMAEN|CHEN);
+ dmacntrl0 = ENDMA;
+ if (aic->flags & AIC_DWIO_ENABLE)
+ dmacntrl0 |= DWORDPIO;
+ aic_outb(aic, DMACNTRL0, dmacntrl0);
+
while (scb->data_len > 0) {
for (;;) {
- /* wait for the fifo the fill up or a phase change */
+ /* wait for the fifo to fill up or a phase change */
dmastat = aic_inb(aic, DMASTAT);
if (dmastat & (INTSTAT|DFIFOFULL))
break;
@@ -868,25 +875,27 @@ aic_datain(struct aic_softc *aic)
n = aic_inb(aic, FIFOSTAT);
}
n = imin(scb->data_len, n);
- if (n >= 12 && (aic->flags & AIC_DWIO_ENABLE)) {
- aic_outb(aic, DMACNTRL0, ENDMA|DWORDPIO);
- aic_insl(aic, DMADATALONG, scb->data_ptr, n >> 2);
- scb->data_ptr += n & ~3;
- scb->data_len -= n & ~3;
- n &= 3;
- }
- if (n >= 8) {
- aic_outb(aic, DMACNTRL0, ENDMA);
- aic_insw(aic, DMADATA, scb->data_ptr, n >> 1);
- scb->data_ptr += n & ~1;
- scb->data_len -= n & ~1;
- n &= 1;
+ if (aic->flags & AIC_DWIO_ENABLE) {
+ if (n >= 12) {
+ aic_insl(aic, DMADATALONG, scb->data_ptr, n>>2);
+ scb->data_ptr += n & ~3;
+ scb->data_len -= n & ~3;
+ n &= 3;
+ }
+ } else {
+ if (n >= 8) {
+ aic_insw(aic, DMADATA, scb->data_ptr, n >> 1);
+ scb->data_ptr += n & ~1;
+ scb->data_len -= n & ~1;
+ n &= 1;
+ }
}
if (n) {
aic_outb(aic, DMACNTRL0, ENDMA|B8MODE);
aic_insb(aic, DMADATA, scb->data_ptr, n);
scb->data_ptr += n;
scb->data_len -= n;
+ aic_outb(aic, DMACNTRL0, dmacntrl0);
}
if (dmastat & INTSTAT)
@@ -904,7 +913,7 @@ static void
aic_dataout(struct aic_softc *aic)
{
struct aic_scb *scb = aic->nexus;
- u_int8_t dmastat;
+ u_int8_t dmastat, dmacntrl0;
int n;
CAM_DEBUG_PRINT(CAM_DEBUG_TRACE, ("aic_dataout\n"));
@@ -912,6 +921,11 @@ aic_dataout(struct aic_softc *aic)
aic_outb(aic, SIMODE1, ENSCSIRST|ENPHASEMIS|ENBUSFREE);
aic_outb(aic, SXFRCTL0, SCSIEN|DMAEN|CHEN);
+ dmacntrl0 = ENDMA|WRITE;
+ if (aic->flags & AIC_DWIO_ENABLE)
+ dmacntrl0 |= DWORDPIO;
+ aic_outb(aic, DMACNTRL0, dmacntrl0);
+
while (scb->data_len > 0) {
for (;;) {
/* wait for the fifo to clear up or a phase change */
@@ -922,25 +936,27 @@ aic_dataout(struct aic_softc *aic)
if (dmastat & INTSTAT)
break;
n = imin(scb->data_len, FIFOSIZE);
- if (n >= 12 && (aic->flags & AIC_DWIO_ENABLE)) {
- aic_outb(aic, DMACNTRL0, ENDMA|WRITE|DWORDPIO);
- aic_outsl(aic, DMADATALONG, scb->data_ptr, n >> 2);
- scb->data_ptr += n & ~3;
- scb->data_len -= n & ~3;
- n &= 3;
- }
- if (n >= 8) {
- aic_outb(aic, DMACNTRL0, ENDMA|WRITE);
- aic_outsl(aic, DMADATA, scb->data_ptr, n >> 2);
- scb->data_ptr += n & ~1;
- scb->data_len -= n & ~1;
- n &= 1;
+ if (aic->flags & AIC_DWIO_ENABLE) {
+ if (n >= 12) {
+ aic_outsl(aic, DMADATALONG, scb->data_ptr,n>>2);
+ scb->data_ptr += n & ~3;
+ scb->data_len -= n & ~3;
+ n &= 3;
+ }
+ } else {
+ if (n >= 8) {
+ aic_outsw(aic, DMADATA, scb->data_ptr, n >> 1);
+ scb->data_ptr += n & ~1;
+ scb->data_len -= n & ~1;
+ n &= 1;
+ }
}
if (n) {
aic_outb(aic, DMACNTRL0, ENDMA|WRITE|B8MODE);
aic_outsb(aic, DMADATA, scb->data_ptr, n);
scb->data_ptr += n;
scb->data_len -= n;
+ aic_outb(aic, DMACNTRL0, dmacntrl0);
}
}
@@ -1231,9 +1247,6 @@ aic_intr(void *arg)
aic_outb(aic, SCSISEQ, 0);
aic_outb(aic, CLRSINT0, sstat0);
aic_outb(aic, CLRSINT1, sstat1);
- aic_outb(aic, SIMODE0, ENSELDI);
- aic_outb(aic, SIMODE1, ENSCSIRST);
- aic_outb(aic, SCSISEQ, ENRESELI);
if ((scb = aic->nexus)) {
if ((aic->flags & AIC_BUSFREE_OK) == 0) {
ccb = scb->ccb;
OpenPOWER on IntegriCloud