patch-2.4.5 linux/drivers/scsi/aic7xxx/aic7xxx.seq
Next file: linux/drivers/scsi/aic7xxx/aic7xxx_inline.h
Previous file: linux/drivers/scsi/aic7xxx/aic7xxx.reg
Back to the patch index
Back to the overall index
- Lines: 432
- Date:
Fri May 4 15:16:28 2001
- Orig file:
v2.4.4/linux/drivers/scsi/aic7xxx/aic7xxx.seq
- Orig date:
Sun Mar 4 14:30:18 2001
diff -u --recursive --new-file v2.4.4/linux/drivers/scsi/aic7xxx/aic7xxx.seq linux/drivers/scsi/aic7xxx/aic7xxx.seq
@@ -28,7 +28,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: //depot/src/aic7xxx/aic7xxx.seq#22 $
+ * $Id: //depot/src/aic7xxx/aic7xxx.seq#27 $
*
* $FreeBSD: src/sys/dev/aic7xxx/aic7xxx.seq,v 1.106 2000/11/12 05:19:46 gibbs Exp $
*/
@@ -153,7 +153,9 @@
* the kernel driver if it happens.
*/
mvi CLRSINT1,CLRBUSFREE;
- or SIMODE1, ENBUSFREE;
+ if ((ahc->features & AHC_DT) == 0) {
+ or SIMODE1, ENBUSFREE;
+ }
/*
* Guard against a bus free after (re)selection
@@ -479,6 +481,9 @@
*/
mov SEQ_FLAGS, SCB_TARGET_INFO[SCB_TARGET_PHASES];
+ test SCB_CONTROL, MK_MESSAGE jz target_ITloop;
+ mvi P_MESGIN|BSYO call change_phase;
+ jmp host_target_message_loop;
target_ITloop:
/*
* Start honoring ATN signals now that
@@ -494,12 +499,12 @@
* on the state of NO_DISCONNECT.
*/
test SEQ_FLAGS, NO_DISCONNECT jz target_disconnect;
- if ((ahc->flags & AHC_PAGESCBS) != 0) {
- mov ALLZEROS call get_free_or_disc_scb;
- }
mov RETURN_1, ALLZEROS;
call complete_target_cmd;
cmp RETURN_1, CONT_MSG_LOOP jne .;
+ if ((ahc->flags & AHC_PAGESCBS) != 0) {
+ mov ALLZEROS call get_free_or_disc_scb;
+ }
mvi DMAPARAMS, HDMAEN|DIRECTION|FIFORESET;
mov SCB_TAG call dma_scb;
jmp target_synccmd;
@@ -703,6 +708,11 @@
test CCSGCTL, CCSGEN jnz .;
ret;
idle_loop:
+ /*
+ * Do we need any more segments for this transfer?
+ */
+ test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jnz return;
+
/* Did we just finish fetching segs? */
cmp CCSGCTL, CCSGEN|CCSGDONE je idle_sgfetch_complete;
@@ -710,11 +720,6 @@
test CCSGCTL, CCSGEN jnz return;
/*
- * Do we need any more segments?
- */
- test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jnz return;
-
- /*
* Do we have any prefetch left???
*/
cmp CCSGADDR, SG_PREFETCH_CNT jne idle_sg_avail;
@@ -758,8 +763,8 @@
test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz . + 2;
or SINDEX, LAST_SEG;
mov SG_CACHE_PRE, SINDEX;
- /* Load the segment by writing DFCNTRL again */
- mov DFCNTRL, DMAPARAMS;
+ /* Load the segment */
+ or DFCNTRL, PRELOADEN;
}
ret;
}
@@ -882,7 +887,11 @@
and DMAPARAMS, DIRECTION;
mov DFCNTRL, DMAPARAMS;
or SXFRCTL1,BITBUCKET;
- test SSTAT1,PHASEMIS jz .;
+ if ((ahc->features & AHC_DT) == 0) {
+ test SSTAT1,PHASEMIS jz .;
+ } else {
+ test SCSIPHASE, DATA_PHASE_MASK jnz .;
+ }
and SXFRCTL1, ~BITBUCKET;
mvi DATA_OVERRUN call set_seqint;
jmp ITloop;
@@ -903,54 +912,48 @@
* completes or the target changes phase.
*/
test SG_CACHE_SHADOW, LAST_SEG_DONE jnz ultra2_dmafinish;
- if ((ahc->flags & AHC_TARGETROLE) != 0) {
- /*
- * As a target, we control the phases,
- * so ignore PHASEMIS.
- */
- test SSTAT0, TARGET jnz ultra2_dma_loop;
- }
- if ((ahc->flags & AHC_INITIATORROLE) != 0) {
- test SSTAT1,PHASEMIS jz ultra2_dma_loop;
+ if ((ahc->features & AHC_DT) == 0) {
+ if ((ahc->flags & AHC_TARGETROLE) != 0) {
+ /*
+ * As a target, we control the phases,
+ * so ignore PHASEMIS.
+ */
+ test SSTAT0, TARGET jnz ultra2_dma_loop;
+ }
+ if ((ahc->flags & AHC_INITIATORROLE) != 0) {
+ test SSTAT1,PHASEMIS jz ultra2_dma_loop;
+ }
+ } else {
+ test DFCNTRL, SCSIEN jnz ultra2_dma_loop;
}
ultra2_dmafinish:
- test DFCNTRL, DIRECTION jnz ultra2_dmafifoempty;
- if ((ahc->features & AHC_DT) == 0) {
- and DFCNTRL, ~SCSIEN;
- test DFCNTRL, SCSIEN jnz .;
- }
-ultra2_dmafifoflush:
+ /*
+ * The transfer has terminated either due to a phase
+ * change, and/or the completion of the last segment.
+ * We have two goals here. Do as much other work
+ * as possible while the data fifo drains on a read
+ * and respond as quickly as possible to the standard
+ * messages (save data pointers/disconnect and command
+ * complete) that usually follow a data phase.
+ */
if ((ahc->bugs & AHC_AUTOFLUSH_BUG) != 0) {
/*
- * On Rev A of the aic7890, the autoflush
- * features doesn't function correctly.
- * Perform an explicit manual flush. During
- * a manual flush, the FIFOEMP bit becomes
- * true every time the PCI FIFO empties
- * regardless of the state of the SCSI FIFO.
- * It can take up to 4 clock cycles for the
- * SCSI FIFO to get data into the PCI FIFO
- * and for FIFOEMP to de-assert. Here we
- * guard against this condition by making
- * sure the FIFOEMP bit stays on for 5 full
- * clock cycles.
+ * On chips with broken auto-flush, start
+ * the flushing process now. We'll poke
+ * the chip from time to time to keep the
+ * flush process going as we complete the
+ * data phase.
*/
or DFCNTRL, FIFOFLUSH;
- test DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
- test DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
- test DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
- test DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
}
- test DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
-ultra2_dmafifoempty:
- /* Don't clobber an inprogress host data transfer */
- test DFSTATUS, MREQPEND jnz ultra2_dmafifoempty;
-ultra2_dmahalt:
- and DFCNTRL, ~(SCSIEN|HDMAEN);
- test DFCNTRL, HDMAEN jnz .;
-
/*
+ * We assume that, even though data may still be
+ * transferring to the host, that the SCSI side of
+ * the DMA engine is now in a static state. This
+ * allows us to update our notion of where we are
+ * in this transfer.
+ *
* If, by chance, we stopped before being able
* to fetch additional segments for this transfer,
* yet the last S/G was completely exhausted,
@@ -961,14 +964,14 @@
* If we happened to stop on the last segment, then
* our residual information is still correct from
* the idle loop and there is no need to perform
- * any fixups. Just jump to data_phase_finish.
+ * any fixups.
*/
ultra2_ensure_sg:
test SG_CACHE_SHADOW, LAST_SEG jz ultra2_shvalid;
/* Record if we've consumed all S/G entries */
- test SG_CACHE_SHADOW, LAST_SEG_DONE jz data_phase_finish;
+ test SSTAT2, SHVALID jnz residuals_correct;
or SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL;
- jmp data_phase_finish;
+ jmp residuals_correct;
ultra2_shvalid:
test SSTAT2, SHVALID jnz sgptr_fixup;
@@ -998,6 +1001,62 @@
test SG_CACHE_SHADOW, ODD_SEG jz . + 2;
or DATA_COUNT_ODD, 0x1;
clr SCB_RESIDUAL_DATACNT[3]; /* We are not the last seg */
+residuals_correct:
+ /*
+ * Go ahead and shut down the DMA engine now.
+ * In the future, we'll want to handle end of
+ * transfer messages prior to doing this, but this
+ * requires similar restructuring for pre-ULTRA2
+ * controllers.
+ */
+ test DMAPARAMS, DIRECTION jnz ultra2_fifoempty;
+ultra2_fifoflush:
+ if ((ahc->features & AHC_DT) == 0) {
+ if ((ahc->bugs & AHC_AUTOFLUSH_BUG) != 0) {
+ /*
+ * On Rev A of the aic7890, the autoflush
+ * feature doesn't function correctly.
+ * Perform an explicit manual flush. During
+ * a manual flush, the FIFOEMP bit becomes
+ * true every time the PCI FIFO empties
+ * regardless of the state of the SCSI FIFO.
+ * It can take up to 4 clock cycles for the
+ * SCSI FIFO to get data into the PCI FIFO
+ * and for FIFOEMP to de-assert. Here we
+ * guard against this condition by making
+ * sure the FIFOEMP bit stays on for 5 full
+ * clock cycles.
+ */
+ or DFCNTRL, FIFOFLUSH;
+ test DFSTATUS, FIFOEMP jz ultra2_fifoflush;
+ test DFSTATUS, FIFOEMP jz ultra2_fifoflush;
+ test DFSTATUS, FIFOEMP jz ultra2_fifoflush;
+ test DFSTATUS, FIFOEMP jz ultra2_fifoflush;
+ }
+ test DFSTATUS, FIFOEMP jz ultra2_fifoflush;
+ } else {
+ /*
+ * We enable the auto-ack feature on DT capable
+ * controllers. This means that the controller may
+ * have already transferred some overrun bytes into
+ * the data FIFO and acked them on the bus. The only
+ * way to detect this situation is to wait for
+ * LAST_SEG_DONE to come true on a completed transfer
+ * and then test to see if the data FIFO is non-empty.
+ */
+ test SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL jz . + 4;
+ test SG_CACHE_SHADOW, LAST_SEG_DONE jz .;
+ test DFSTATUS, FIFOEMP jnz ultra2_fifoempty;
+ /* Overrun */
+ jmp data_phase_loop;
+ test DFSTATUS, FIFOEMP jz .;
+ }
+ultra2_fifoempty:
+ /* Don't clobber an inprogress host data transfer */
+ test DFSTATUS, MREQPEND jnz ultra2_fifoempty;
+ultra2_dmahalt:
+ and DFCNTRL, ~(SCSIEN|HDMAEN);
+ test DFCNTRL, SCSIEN|HDMAEN jnz .;
} else {
/* If we are the last SG block, tell the hardware. */
if ((ahc->bugs & AHC_PCI_MWI_BUG) != 0
@@ -1156,7 +1215,11 @@
}
if ((ahc->flags & AHC_INITIATORROLE) != 0) {
test SSTAT1, REQINIT jz .;
- test SSTAT1,PHASEMIS jz data_phase_loop;
+ if ((ahc->features & AHC_DT) == 0) {
+ test SSTAT1,PHASEMIS jz data_phase_loop;
+ } else {
+ test SCSIPHASE, DATA_PHASE_MASK jnz data_phase_loop;
+ }
}
data_phase_done:
@@ -1296,13 +1359,17 @@
or DFCNTRL, FIFOFLUSH;
}
p_command_loop:
- test SSTAT0, SDONE jnz . + 2;
- test SSTAT1, PHASEMIS jz p_command_loop;
- /*
- * Wait for our ACK to go-away on it's own
- * instead of being killed by SCSIEN getting cleared.
- */
- test SCSISIGI, ACKI jnz .;
+ if ((ahc->features & AHC_DT) == 0) {
+ test SSTAT0, SDONE jnz . + 2;
+ test SSTAT1, PHASEMIS jz p_command_loop;
+ /*
+ * Wait for our ACK to go-away on it's own
+ * instead of being killed by SCSIEN getting cleared.
+ */
+ test SCSISIGI, ACKI jnz .;
+ } else {
+ test DFCNTRL, SCSIEN jnz p_command_loop;
+ }
and DFCNTRL, ~(SCSIEN|SDMAEN|HDMAEN);
test DFCNTRL, (SCSIEN|SDMAEN|HDMAEN) jnz .;
if ((ahc->features & AHC_ULTRA2) != 0) {
@@ -1346,23 +1413,16 @@
* reason.
*/
p_mesgout_retry:
- or SCSISIGO,ATNO,LASTPHASE;/* turn on ATN for the retry */
+ /* Turn on ATN for the retry */
+ if ((ahc->features & AHC_DT) == 0) {
+ or SCSISIGO, ATNO, LASTPHASE;
+ } else {
+ mvi SCSISIGO, ATNO;
+ }
p_mesgout:
mov SINDEX, MSG_OUT;
cmp SINDEX, MSG_IDENTIFYFLAG jne p_mesgout_from_host;
test SCB_CONTROL,MK_MESSAGE jnz host_message_loop;
- mov FUNCTION1, SCB_SCSIID;
- mov A, FUNCTION1;
- mov SINDEX, TARGET_MSG_REQUEST[0];
- if ((ahc->features & AHC_TWIN) != 0) {
- /* Second Channel uses high byte bits */
- test SCB_SCSIID, TWIN_CHNLB jz . + 2;
- mov SINDEX, TARGET_MSG_REQUEST[1];
- } else if ((ahc->features & AHC_WIDE) != 0) {
- test SCB_SCSIID, 0x80 jz . + 2; /* target > 7 */
- mov SINDEX, TARGET_MSG_REQUEST[1];
- }
- test SINDEX, A jnz host_message_loop;
p_mesgout_identify:
or SINDEX, MSG_IDENTIFYFLAG|DISCENB, SCB_LUN;
test SCB_CONTROL, DISCENB jnz . + 2;
@@ -1555,10 +1615,17 @@
* only if we've actually been into a data phase to change them. This
* protects against bogus data in scratch ram and the residual counts
* since they are only initialized when we go into data_in or data_out.
+ * Ack the message as soon as possible. For chips without S/G pipelining,
+ * we can only ack the message after SHADDR has been saved. On these
+ * chips, SHADDR increments with every bus transaction, even PIO.
*/
mesgin_sdptrs:
- test SEQ_FLAGS, DPHASE jz mesgin_done;
-
+ if ((ahc->features & AHC_ULTRA2) != 0) {
+ mov NONE,SCSIDATL; /*dummy read from latch to ACK*/
+ test SEQ_FLAGS, DPHASE jz ITloop;
+ } else {
+ test SEQ_FLAGS, DPHASE jz mesgin_done;
+ }
/*
* The SCB_SGPTR becomes the next one we'll download,
* and the SCB_DATAPTR becomes the current SHADDR.
@@ -1567,13 +1634,17 @@
*/
if ((ahc->features & AHC_CMD_CHAN) != 0) {
bmov SCB_DATAPTR, SHADDR, 4;
+ if ((ahc->features & AHC_ULTRA2) == 0) {
+ mov NONE,SCSIDATL; /*dummy read from latch to ACK*/
+ }
bmov SCB_DATACNT, SCB_RESIDUAL_DATACNT, 8;
} else {
mvi DINDEX, SCB_DATAPTR;
mvi SHADDR call bcopy_4;
+ mov NONE,SCSIDATL; /*dummy read from latch to ACK*/
mvi SCB_RESIDUAL_DATACNT call bcopy_8;
}
- jmp mesgin_done;
+ jmp ITloop;
/*
* Restore pointers message? Data pointers are recopied from the
@@ -1751,7 +1822,11 @@
jmp mesgin_done;
mk_mesg:
- or SCSISIGO,ATNO,LASTPHASE;/* turn on ATNO */
+ if ((ahc->features & AHC_DT) == 0) {
+ or SCSISIGO, ATNO, LASTPHASE;
+ } else {
+ mvi SCSISIGO, ATNO;
+ }
mov MSG_OUT,SINDEX ret;
/*
@@ -1924,7 +1999,9 @@
test SSTAT1, REQINIT jz phase_lock;
test SSTAT1, SCSIPERR jnz phase_lock_perr;
phase_lock_latch_phase:
- and SCSISIGO, PHASE_MASK, SCSISIGI;
+ if ((ahc->features & AHC_DT) == 0) {
+ and SCSISIGO, PHASE_MASK, SCSISIGI;
+ }
and LASTPHASE, PHASE_MASK, SCSISIGI ret;
if ((ahc->features & AHC_CMD_CHAN) == 0) {
@@ -2068,9 +2145,9 @@
* latch is full.
*/
clr A;
- /* Wait for some data to arrive. */
+ /* Wait for at least 8 bytes of data to arrive. */
dma_scb_hang_fifo:
- test DFSTATUS, FIFOEMP jnz dma_scb_hang_fifo;
+ test DFSTATUS, FIFOQWDEMP jnz dma_scb_hang_fifo;
dma_scb_hang_wait:
test DFSTATUS, MREQPEND jnz dma_scb_hang_wait;
test DFSTATUS, HDONE jnz dma_scb_hang_dma_done;
@@ -2078,8 +2155,7 @@
test DFSTATUS, HDONE jnz dma_scb_hang_dma_done;
/*
* The PCI module no longer intends to perform
- * a PCI transaction and HDONE has not come true.
- * We are hung. Drain the fifo.
+ * a PCI transaction. Drain the fifo.
*/
dma_scb_hang_empty_fifo:
/*
@@ -2101,6 +2177,7 @@
*/
not SINDEX;
add A, 5, SINDEX;
+ cmp A, 4 je dma_finish_nowait;
jmp dma_scb_hang_fifo;
dma_scb_hang_dma_done:
and DFCNTRL, ~HDMAEN;
@@ -2146,6 +2223,7 @@
*/
dma_finish:
test DFSTATUS,HDONE jz dma_finish;
+dma_finish_nowait:
/* Turn off DMA */
and DFCNTRL, ~HDMAEN;
test DFCNTRL, HDMAEN jnz .;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)