patch-2.2.15 linux/drivers/scsi/aic7xxx/aic7xxx.seq

Next file: linux/drivers/scsi/aic7xxx.c
Previous file: linux/drivers/scsi/aic7xxx/aic7xxx.reg
Back to the patch index
Back to the overall index

diff -u --new-file --recursive --exclude-from ../../exclude v2.2.14/drivers/scsi/aic7xxx/aic7xxx.seq linux/drivers/scsi/aic7xxx/aic7xxx.seq
@@ -182,6 +182,15 @@
 		and	SCSIID, OID;		/* Clear old target */
 		or	SCSIID, A;
 	}
+	mov	SCSIDATL, ALLZEROS;		/* clear out the latched */
+						/* data register, this */
+						/* fixes a bug on some */
+						/* controllers where the */
+						/* last byte written to */
+						/* this register can leak */
+						/* onto the data bus at */
+						/* bad times, such as during */
+						/* selection timeouts */
 	mvi	SCSISEQ, ENSELO|ENAUTOATNO|ENRSELI|ENAUTOATNP ret;
 
 /*
@@ -448,8 +457,9 @@
 		if ((p->features & AHC_ULTRA2) != 0) {
 			bmov	HADDR, SHADDR, 4;
 			bmov    HCNT, SCB_RESID_DCNT, 3;
+		} else {
+			bmov    STCNT, SCB_RESID_DCNT, 3;
 		}
-		bmov    STCNT, SCB_RESID_DCNT, 3;
 	} else {
 		mvi	DINDEX, STCNT;
 		mvi	SCB_RESID_DCNT	call bcopy_3;
@@ -517,10 +527,12 @@
 	}
 data_phase_inbounds:
 /* If we are the last SG block, tell the hardware. */
-if ((p->features & AHC_ULTRA2) == 0) {
 	cmp	SG_COUNT,0x01 jne data_phase_wideodd;
-	and	DMAPARAMS, ~WIDEODD;
-}
+	if ((p->features & AHC_ULTRA2) == 0) {
+		and	DMAPARAMS, ~WIDEODD;
+	} else {
+		mvi	SG_CACHEPTR, LAST_SEG;
+	}
 data_phase_wideodd:
 	if ((p->features & AHC_ULTRA2) != 0) {
 		mov	SINDEX, ALLONES;
@@ -530,7 +542,7 @@
 		test	SSTAT0, SDONE jnz data_phase_dma_done;
 		test	SSTAT1,PHASEMIS	jz data_phase_dma_loop;	/* ie. underrun */
 data_phase_dma_phasemis:
-		test	SSTAT0,SDONE	jnz . + 2;
+		test	SSTAT0,SDONE	jnz data_phase_dma_done;
 		clr	SINDEX;			/* Remember the phasemiss */
 	} else {
 		mov	DMAPARAMS  call dma;
@@ -615,9 +627,10 @@
 	test    SSTAT1, REQINIT jz .;
 	test	SSTAT1,PHASEMIS	jz data_phase_loop;
 
+/* This drops the last SG segment down to the shadow layer for us */
 	if ((p->features & AHC_ULTRA2) != 0) {
 		mov	DFCNTRL, DMAPARAMS;
-		test	SSTAT0, SDONE jnz .;
+		test	SSTAT0, SDONE	jnz .;
 	}
 
 data_phase_finish:
@@ -713,7 +726,7 @@
 		mvi	DFCNTRL, (PRELOADEN|SCSIEN|HDMAEN|DIRECTION);
 		test	SSTAT0, SDONE jnz .;
 p_command_dma_loop:
-		test	SSTAT0, DMADONE jnz p_command_ultra2_dma_done;
+		test	SSTAT0, SDONE jnz p_command_ultra2_dma_done;
 		test	SSTAT1,PHASEMIS	jz p_command_dma_loop;	/* ie. underrun */
 p_command_ultra2_dma_done:
 		and     DFCNTRL, ~HDMAEN;
@@ -830,6 +843,7 @@
 	cmp	A,MSG_EXTENDED		je mesgin_extended;
 	cmp	A,MSG_MESSAGE_REJECT	je mesgin_reject;
 	cmp	A,MSG_NOOP		je mesgin_done;
+	cmp	A,MSG_IGN_WIDE_RESIDUE	je mesgin_wide_residue;
 
 rej_mesgin:
 /*
@@ -1057,6 +1071,33 @@
 	jmp	mesgin_done;
 
 /*
+ * Wide Residue.  We handle the simple cases, but pass of the one hard case
+ * to the kernel (when the residue byte happened to cause us to advance our
+ * sg element array, so we know have to back that advance out).
+ */
+mesgin_wide_residue:
+	mvi	ARG_1	call inb_next; /* ACK the wide_residue and get */
+				       /* the size byte */
+/*
+ * See if we'll ignore this wide residue (because it's an overrun byte)
+ */
+	test	SCB_RESID_SGCNT,0xff jnz wide_residue_int;
+	test	SCB_RESID_DCNT[0],0xff jnz wide_residue_int;
+	test	SCB_RESID_DCNT[1],0xff jnz wide_residue_int;
+	test	SCB_RESID_DCNT[2],0xff jnz wide_residue_int;
+	jmp	mesgin_done;
+
+wide_residue_int:
+/*
+ * In order for this to be reliable, we have to do all sorts of horrible
+ * magic in terms of resetting the datafifo and reloading the shadow layer
+ * with the correct new values (so that a subsequent save data pointers
+ * message will do the right thing).  We let the kernel do that work.
+ */
+ 	mvi	INTSTAT,WIDE_RESIDUE;
+	jmp	mesgin_done;
+	
+/*
  * [ ADD MORE MESSAGE HANDLING HERE ]
  */
 
@@ -1093,7 +1134,7 @@
 	 * before continuing.
 	 */
 	test	SSTAT1, REQINIT	jz inb_next_wait;
-	test	SSTAT1, SCSIPERR jnz inb_next_wait;
+	test	SSTAT1, SCSIPERR jnz .;
 	and	LASTPHASE, PHASE_MASK, SCSISIGI;
 	cmp	LASTPHASE, P_MESGIN jne mesgin_phasemis;
 inb_first:

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)