aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/aic
diff options
context:
space:
mode:
authorLuoqi Chen <luoqi@FreeBSD.org>1999-12-16 16:11:49 +0000
committerLuoqi Chen <luoqi@FreeBSD.org>1999-12-16 16:11:49 +0000
commitda2c318f0b2a4533540460dab34ebba06f0dfca9 (patch)
tree6b813431e4c47444a880adcad16e2e6183609d2f /sys/dev/aic
parent410605d1227d519fb810ae266f662aee0393b203 (diff)
downloadsrc-da2c318f0b2a4533540460dab34ebba06f0dfca9.tar.gz
src-da2c318f0b2a4533540460dab34ebba06f0dfca9.zip
Adjust data pointers for untransmitted bytes in fifos when there's phase
change during data transfer.
Notes
Notes: svn path=/head/; revision=54687
Diffstat (limited to 'sys/dev/aic')
-rw-r--r--sys/dev/aic/aic.c18
1 files changed, 13 insertions, 5 deletions
diff --git a/sys/dev/aic/aic.c b/sys/dev/aic/aic.c
index 9cb2fa96483d..ad4dc96d0b1a 100644
--- a/sys/dev/aic/aic.c
+++ b/sys/dev/aic/aic.c
@@ -920,7 +920,7 @@ static void
aic_dataout(struct aic_softc *aic)
{
struct aic_scb *scb = aic->nexus;
- u_int8_t dmastat, dmacntrl0;
+ u_int8_t dmastat, dmacntrl0, sstat2;
int n;
CAM_DEBUG_PRINT(CAM_DEBUG_TRACE, ("aic_dataout\n"));
@@ -970,10 +970,19 @@ aic_dataout(struct aic_softc *aic)
for (;;) {
/* wait until all bytes in the fifos are transmitted */
dmastat = aic_inb(aic, DMASTAT);
- if (dmastat & INTSTAT)
+ sstat2 = aic_inb(aic, SSTAT2);
+ if ((dmastat & DFIFOEMP) && (sstat2 & SEMPTY))
break;
- if ((dmastat & DFIFOEMP) && (aic_inb(aic, SSTAT2) & SEMPTY))
+ if (dmastat & INTSTAT) {
+ /* adjust for untransmitted bytes */
+ n = aic_inb(aic, FIFOSTAT) + (sstat2 & 0xf);
+ scb->data_ptr -= n;
+ scb->data_len += n;
+ /* clear the fifo */
+ aic_outb(aic, SXFRCTL0, CHEN|CLRCH);
+ aic_outb(aic, DMACNTRL0, RSTFIFO);
break;
+ }
}
aic_outb(aic, SXFRCTL0, CHEN);
@@ -1008,8 +1017,7 @@ aic_cmd(struct aic_softc *aic)
aic_outb(aic, SIMODE1, ENSCSIRST|ENPHASEMIS|ENBUSFREE);
aic_outb(aic, DMACNTRL0, ENDMA|WRITE);
aic_outb(aic, SXFRCTL0, SCSIEN|DMAEN|CHEN);
- aic_outsw(aic, DMADATA, (u_int16_t *)scb->cmd_ptr,
- scb->cmd_len >> 1);
+ aic_outsw(aic, DMADATA, (u_int16_t *)scb->cmd_ptr, scb->cmd_len >> 1);
while ((aic_inb(aic, SSTAT2) & SEMPTY) == 0 &&
(aic_inb(aic, DMASTAT) & INTSTAT) == 0)
;