patch-2.3.44 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 --recursive --new-file v2.3.43/linux/drivers/scsi/aic7xxx/aic7xxx.seq linux/drivers/scsi/aic7xxx/aic7xxx.seq
@@ -517,10 +517,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 +532,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 +617,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 +716,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 +833,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 +1061,36 @@
 	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)
+ */
+ 	if ((p->features & AHC_ULTRA2) != 0) {
+		test	SSTAT2, WIDE_RES jnz mesgin_done;
+	} else {
+		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 +1127,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)