diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-02-24 00:12:35 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-02-24 00:12:35 +0000 |
commit | 482368b1a8e45430672c58c9a42e7d2004367126 (patch) | |
tree | ce2a1a567d4d62dee7c2e71a46a99cf72cf1d606 /drivers/scsi/aic7xxx/aic7xxx.seq | |
parent | e4d0251c6f56ab2e191afb70f80f382793e23f74 (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.seq | 48 |
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: |