summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/aic7xxx/aic7xxx.seq
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-02-24 00:12:35 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-02-24 00:12:35 +0000
commit482368b1a8e45430672c58c9a42e7d2004367126 (patch)
treece2a1a567d4d62dee7c2e71a46a99cf72cf1d606 /drivers/scsi/aic7xxx/aic7xxx.seq
parente4d0251c6f56ab2e191afb70f80f382793e23f74 (diff)
Merge with 2.3.47. Guys, this is buggy as shit. You've been warned.
Diffstat (limited to 'drivers/scsi/aic7xxx/aic7xxx.seq')
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx.seq48
1 files changed, 41 insertions, 7 deletions
diff --git a/drivers/scsi/aic7xxx/aic7xxx.seq b/drivers/scsi/aic7xxx/aic7xxx.seq
index 8e8dc98ee..de3afbf92 100644
--- a/drivers/scsi/aic7xxx/aic7xxx.seq
+++ b/drivers/scsi/aic7xxx/aic7xxx.seq
@@ -517,10 +517,12 @@ data_phase_loop:
}
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 @@ data_phase_dma_loop:
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 @@ prefetched_segs_avail:
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 @@ p_command:
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 @@ p_mesgin:
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 @@ mesgin_reject:
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 @@ inb_next_wait:
* 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: