diff --git a/sys/dev/aic7xxx/aic7xxx.seq b/sys/dev/aic7xxx/aic7xxx.seq index 4613d9fc6458..36ff790fa1c1 100644 --- a/sys/dev/aic7xxx/aic7xxx.seq +++ b/sys/dev/aic7xxx/aic7xxx.seq @@ -39,7 +39,7 @@ * *-M************************************************************************/ -VERSION AIC7XXX_SEQ_VER "$Id: aic7xxx.seq,v 1.40 1996/05/31 06:30:15 gibbs Exp $" +VERSION AIC7XXX_SEQ_VER "$Id: aic7xxx.seq,v 1.41 1996/06/08 06:54:06 gibbs Exp $" #if defined(__NetBSD__) #include "../../../../dev/ic/aic7xxxreg.h" @@ -340,12 +340,29 @@ data_phase_init: or FLAGS, DPHASE /* We have seen a data phase */ data_phase_loop: +/* Guard against overruns */ + test SG_COUNT, 0xff jnz data_phase_inbounds +/* + * Turn on 'Bit Bucket' mode, set the transfer count to + * 16meg and let the target run until it changes phase. + * When the transfer completes, notify the host that we + * had an overrun. + */ + or SXFRCTL1,BITBUCKET + mvi STCNT0,0xff + mvi STCNT1,0xff + mvi STCNT2,0xff + +data_phase_inbounds: /* If we are the last SG block, don't set wideodd. */ cmp SG_COUNT,0x01 jne data_phase_wideodd and DMAPARAMS, 0xbf /* Turn off WIDEODD */ data_phase_wideodd: mov DMAPARAMS call dma +/* Go tell the host about any overruns */ + test SXFRCTL1,BITBUCKET jnz data_phase_overrun + /* Exit if we had an underrun */ test SSTAT0,SDONE jz data_phase_finish /* underrun STCNT != 0 */ @@ -447,6 +464,14 @@ data_phase_finish: mov SCB_RESID_SGCNT, SG_COUNT jmp ITloop +data_phase_overrun: +/* + * Turn off BITBUCKET mode and notify the host + */ + and SXFRCTL1,0x7f /* ~BITBUCKET */ + mvi INTSTAT,DATA_OVERRUN + jmp ITloop + /* * Command phase. Set up the DMA registers and let 'er rip. */ diff --git a/sys/dev/aic7xxx/aic7xxx_reg.h b/sys/dev/aic7xxx/aic7xxx_reg.h index 5226dbb62f72..b9cd5d20091a 100644 --- a/sys/dev/aic7xxx/aic7xxx_reg.h +++ b/sys/dev/aic7xxx/aic7xxx_reg.h @@ -28,7 +28,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: aic7xxx_reg.h,v 1.10 1996/05/10 16:28:00 gibbs Exp $ + * $Id: aic7xxx_reg.h,v 1.11 1996/05/21 18:32:23 gibbs Exp $ */ /* @@ -434,6 +434,11 @@ * when we were expecting * another msgin byte. */ +#define DATA_OVERRUN 0xe1 /* + * Target attempted to write + * beyond the bounds of its + * command. + */ #define BRKADRINT 0x08 #define SCSIINT 0x04 #define CMDCMPLT 0x02 diff --git a/sys/i386/scsi/aic7xxx.c b/sys/i386/scsi/aic7xxx.c index a416a6604c1d..ead323b3f736 100644 --- a/sys/i386/scsi/aic7xxx.c +++ b/sys/i386/scsi/aic7xxx.c @@ -31,7 +31,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: aic7xxx.c,v 1.72 1996/05/31 06:32:09 gibbs Exp $ + * $Id: aic7xxx.c,v 1.73 1996/06/08 06:55:01 gibbs Exp $ */ /* * TODO: @@ -1649,6 +1649,31 @@ ahc_intr(arg) "unknown operation."); break; } + case DATA_OVERRUN: + { + /* + * When the sequencer detects an overrun, it + * sets STCNT to 0x00ffffff and allows the + * target to complete its transfer in + * BITBUCKET mode. + */ + u_char scbindex = AHC_INB(ahc, SCB_TAG); + u_int32_t overrun; + scb = ahc->scbarray[scbindex]; + overrun = AHC_INB(ahc, STCNT0) + | (AHC_INB(ahc, STCNT1) << 8) + | (AHC_INB(ahc, STCNT2) << 16); + overrun = 0x00ffffff - overrun; + sc_print_addr(scb->xs->sc_link); + printf("data overrun of %d bytes detected." + " Forcing a retry.\n", overrun); + /* + * Set this and it will take affect when the + * target does a command complete. + */ + scb->xs->error = XS_DRIVER_STUFFUP; + break; + } #if NOT_YET /* XXX Fill these in later */ case MESG_BUFFER_BUSY: