patch-2.4.9 linux/drivers/scsi/aic7xxx/aic7xxx.seq
Next file: linux/drivers/scsi/aic7xxx/aic7xxx_93cx6.c
Previous file: linux/drivers/scsi/aic7xxx/aic7xxx.reg
Back to the patch index
Back to the overall index
- Lines: 367
- Date:
Sun Aug 12 10:51:42 2001
- Orig file:
v2.4.8/linux/drivers/scsi/aic7xxx/aic7xxx.seq
- Orig date:
Fri May 4 15:16:28 2001
diff -u --recursive --new-file v2.4.8/linux/drivers/scsi/aic7xxx/aic7xxx.seq linux/drivers/scsi/aic7xxx/aic7xxx.seq
@@ -28,11 +28,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $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 $
*/
+VERSION = "$Id: //depot/src/aic7xxx/aic7xxx.seq#33 $"
+
#include "aic7xxx.reg"
#include "scsi_message.h"
@@ -175,16 +175,7 @@
* We've just been selected. Assert BSY and
* setup the phase for receiving messages
* from the target.
- *
- * If bus reset interrupts have been disabled (from a
- * previous reset), re-enable them now. Resets are only
- * of interest when we have outstanding transactions, so
- * we can safely defer re-enabling the interrupt until,
- * as a target, we start receiving transactions again.
- */
- test SIMODE1, ENSCSIRST jnz . + 3;
- mvi CLRSINT1, CLRSCSIRSTI;
- or SIMODE1, ENSCSIRST;
+ */
mvi SCSISIGO, P_MESGOUT|BSYO;
/*
@@ -524,7 +515,7 @@
mvi MSG_DISCONNECT call target_outb;
target_busfree_wait:
- /* Wait for preceeding I/O session to complete. */
+ /* Wait for preceding I/O session to complete. */
test SCSISIGI, ACKI jnz .;
target_busfree:
and SIMODE1, ~ENBUSFREE;
@@ -749,13 +740,13 @@
if ((ahc->features & AHC_ULTRA2) != 0) {
/* Does the hardware have space for another SG entry? */
test DFSTATUS, PRELOAD_AVAIL jz return;
- bmov HADDR, CCSGRAM, 4;
- bmov SINDEX, CCSGRAM, 1;
- test SINDEX, 0x1 jz . + 2;
+ bmov HADDR, CCSGRAM, 7;
+ test HCNT[0], 0x1 jz . + 2;
xor DATA_COUNT_ODD, 0x1;
- bmov HCNT[0], SINDEX, 1;
- bmov HCNT[1], CCSGRAM, 2;
bmov SCB_RESIDUAL_DATACNT[3], CCSGRAM, 1;
+ if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {
+ mov SCB_RESIDUAL_DATACNT[3] call set_hhaddr;
+ }
call sg_advance;
mov SINDEX, SCB_RESIDUAL_SGPTR[0];
test DATA_COUNT_ODD, 0x1 jz . + 2;
@@ -803,29 +794,10 @@
adc HCNT[2], -1 ret;
}
-/*
- * If we re-enter the data phase after going through another phase, the
- * STCNT may have been cleared, so restore it from the residual field.
- */
-data_phase_reinit:
- if ((ahc->features & AHC_ULTRA2) != 0) {
- /*
- * The preload circuitry requires us to
- * reload the address too, so pull it from
- * the shaddow address.
- */
- bmov HADDR, SHADDR, 4;
- bmov HCNT, SCB_RESIDUAL_DATACNT, 3;
- } else if ((ahc->features & AHC_CMD_CHAN) != 0) {
- bmov STCNT, SCB_RESIDUAL_DATACNT, 3;
- } else {
- mvi DINDEX, STCNT;
- mvi SCB_RESIDUAL_DATACNT call bcopy_3;
- }
- and DATA_COUNT_ODD, 0x1, SCB_RESIDUAL_DATACNT[0];
- jmp data_phase_loop;
-
p_data:
+ test SEQ_FLAGS,IDENTIFY_SEEN jnz p_data_okay;
+ mvi NO_IDENT jmp set_seqint;
+p_data_okay:
if ((ahc->features & AHC_ULTRA2) != 0) {
mvi DMAPARAMS, PRELOADEN|SCSIEN|HDMAEN;
} else {
@@ -833,17 +805,23 @@
}
test LASTPHASE, IOI jnz . + 2;
or DMAPARAMS, DIRECTION;
- call assert; /*
- * Ensure entering a data
- * phase is okay - seen identify, etc.
- */
if ((ahc->features & AHC_CMD_CHAN) != 0) {
/* We don't have any valid S/G elements */
mvi CCSGADDR, SG_PREFETCH_CNT;
}
- test SEQ_FLAGS, DPHASE jnz data_phase_reinit;
+ test SEQ_FLAGS, DPHASE jz data_phase_initialize;
+
+ /*
+ * If we re-enter the data phase after going through another
+ * phase, our transfer location has almost certainly been
+ * corrupted by the interveining, non-data, transfers. Ask
+ * the host driver to fix us up based on the transfer residual.
+ */
+ mvi PDATA_REINIT call set_seqint;
+ jmp data_phase_loop;
- /* We have seen a data phase */
+data_phase_initialize:
+ /* We have seen a data phase for the first time */
or SEQ_FLAGS, DPHASE;
/*
@@ -853,6 +831,10 @@
* modify the saved values in the SCB until we see a save
* data pointers message.
*/
+ if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {
+ /* The lowest address byte must be loaded last. */
+ mov SCB_DATACNT[3] call set_hhaddr;
+ }
if ((ahc->features & AHC_CMD_CHAN) != 0) {
bmov HADDR, SCB_DATAPTR, 7;
bmov SCB_RESIDUAL_DATACNT[3], SCB_DATACNT[3], 5;
@@ -1057,6 +1039,29 @@
ultra2_dmahalt:
and DFCNTRL, ~(SCSIEN|HDMAEN);
test DFCNTRL, SCSIEN|HDMAEN jnz .;
+ if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {
+ /*
+ * Keep HHADDR cleared for future, 32bit addressed
+ * only, DMA operations.
+ *
+ * Due to bayonette style S/G handling, our residual
+ * data must be "fixed up" once the transfer is halted.
+ * Here we fixup the HSHADDR stored in the high byte
+ * of the residual data cnt. By postponing the fixup,
+ * we can batch the clearing of HADDR with the fixup.
+ * If we halted on the last segment, the residual is
+ * already correct. If we are not on the last
+ * segment, copy the high address directly from HSHADDR.
+ * We don't need to worry about maintaining the
+ * SG_LAST_SEG flag as it will always be false in the
+ * case where an update is required.
+ */
+ or DSCOMMAND1, HADDLDSEL0;
+ test SG_CACHE_SHADOW, LAST_SEG jnz . + 2;
+ mov SCB_RESIDUAL_DATACNT[3], SHADDR;
+ clr HADDR;
+ and DSCOMMAND1, ~HADDLDSEL0;
+ }
} else {
/* If we are the last SG block, tell the hardware. */
if ((ahc->bugs & AHC_PCI_MWI_BUG) != 0
@@ -1163,9 +1168,18 @@
call idle_loop;
test CCSGCTL, CCSGEN jnz . - 1;
bmov HADDR, CCSGRAM, 7;
- test CCSGRAM, SG_LAST_SEG jz . + 2;
- or SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG;
+ /*
+ * Workaround for flaky external SCB RAM
+ * on certain aic7895 setups. It seems
+ * unable to handle direct transfers from
+ * S/G ram to certain SCB locations.
+ */
+ mov SINDEX, CCSGRAM;
+ mov SCB_RESIDUAL_DATACNT[3], SINDEX;
} else {
+ if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {
+ mov ALLZEROS call set_hhaddr;
+ }
mvi DINDEX, HADDR;
mvi SCB_RESIDUAL_SGPTR call bcopy_4;
@@ -1180,6 +1194,17 @@
mov SCB_RESIDUAL_DATACNT[3], DFDAT;
}
+ if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {
+ mov SCB_RESIDUAL_DATACNT[3] call set_hhaddr;
+
+ /*
+ * The lowest address byte must be loaded
+ * last as it triggers the computation of
+ * some items in the PCI block. The ULTRA2
+ * chips do this on PRELOAD.
+ */
+ mov HADDR, HADDR;
+ }
if ((ahc->bugs & AHC_PCI_MWI_BUG) != 0
&& ahc->pci_cachesize != 0) {
call calc_mwi_residual;
@@ -1234,6 +1259,24 @@
call disable_ccsgen;
}
+ if ((ahc->features & AHC_ULTRA2) == 0) {
+ /*
+ * Clear the high address byte so that all other DMA
+ * operations, which use 32bit addressing, can assume
+ * HHADDR is 0.
+ */
+ if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {
+ mov ALLZEROS call set_hhaddr;
+ }
+ }
+
+ /*
+ * Update our residual information before the information is
+ * lost by some other type of SCSI I/O (e.g. PIO). If we have
+ * transferred all data, no update is needed.
+ *
+ */
+ test SCB_RESIDUAL_SGPTR, SG_LIST_NULL jnz residual_update_done;
if ((ahc->bugs & AHC_PCI_MWI_BUG) != 0
&& ahc->pci_cachesize != 0) {
if ((ahc->features & AHC_CMD_CHAN) != 0) {
@@ -1257,7 +1300,7 @@
mov SCB_RESIDUAL_DATACNT[1], STCNT[1];
mov SCB_RESIDUAL_DATACNT[2], STCNT[2];
}
-
+residual_update_done:
/*
* Since we've been through a data phase, the SCB_RESID* fields
* are now initialized. Clear the full residual flag.
@@ -1289,7 +1332,9 @@
* Command phase. Set up the DMA registers and let 'er rip.
*/
p_command:
- call assert;
+ test SEQ_FLAGS,IDENTIFY_SEEN jnz p_command_okay;
+ mvi NO_IDENT jmp set_seqint;
+p_command_okay:
if ((ahc->features & AHC_ULTRA2) != 0) {
bmov HCNT[0], SCB_CDB_LEN, 1;
@@ -1323,7 +1368,7 @@
jmp p_command_loop;
p_command_embedded:
/*
- * The data fifo seems to require 4 byte alligned
+ * The data fifo seems to require 4 byte aligned
* transfers from the sequencer. Force this to
* be the case by clearing HADDR[0] even though
* we aren't going to touch host memeory.
@@ -1383,8 +1428,9 @@
* and store it into the SCB.
*/
p_status:
- call assert;
-
+ test SEQ_FLAGS,IDENTIFY_SEEN jnz p_status_okay;
+ mvi NO_IDENT jmp set_seqint;
+p_status_okay:
mov SCB_SCSI_STATUS, SCSIDATL;
jmp ITloop;
@@ -1626,6 +1672,22 @@
} else {
test SEQ_FLAGS, DPHASE jz mesgin_done;
}
+
+ /*
+ * If we are asked to save our position at the end of the
+ * transfer, just mark us at the end rather than perform a
+ * full save.
+ */
+ test SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL jz mesgin_sdptrs_full;
+ or SCB_SGPTR, SG_LIST_NULL;
+ if ((ahc->features & AHC_ULTRA2) != 0) {
+ jmp ITloop;
+ } else {
+ jmp mesgin_done;
+ }
+
+mesgin_sdptrs_full:
+
/*
* The SCB_SGPTR becomes the next one we'll download,
* and the SCB_DATAPTR becomes the current SHADDR.
@@ -1907,16 +1969,6 @@
and SXFRCTL0, ~SPIOEN ret;
}
-
-/*
- * Assert that if we've been reselected, then we've seen an IDENTIFY
- * message.
- */
-assert:
- test SEQ_FLAGS,IDENTIFY_SEEN jnz return; /* seen IDENTIFY? */
-
- mvi NO_IDENT jmp set_seqint; /* no - tell the kernel */
-
/*
* Locate a disconnected SCB by SCBID. Upon return, SCBPTR and SINDEX will
* be set to the position of the SCB. If the SCB cannot be found locally,
@@ -2157,32 +2209,21 @@
* The PCI module no longer intends to perform
* a PCI transaction. Drain the fifo.
*/
-dma_scb_hang_empty_fifo:
- /*
- * Skip lines not yet transfered into the FIFO.
- */
- add SINDEX, 7, HCNT;
- shr SINDEX, 3;
-
- /*
- * Skip lines already copied out of the FIFO.
- */
- add A, A, SINDEX;
-
- call dma_scb_hang_dma_drain_fifo;
-
- /*
- * Set the lines transferred to all but
- * those yet to reach the FIFO.
- */
- not SINDEX;
- add A, 5, SINDEX;
- cmp A, 4 je dma_finish_nowait;
+dma_scb_hang_dma_drain_fifo:
+ not A, HCNT;
+ add A, SCB_DOWNLOAD_SIZE+SCB_BASE+1;
+ and A, ~0x7;
+ mov DINDIR,DFDAT;
+ cmp DINDEX, A jne . - 1;
+ cmp DINDEX, SCB_DOWNLOAD_SIZE+SCB_BASE
+ je dma_finish_nowait;
+ /* Restore A as the lines left to transfer. */
+ add A, -SCB_BASE, DINDEX;
+ shr A, 3;
jmp dma_scb_hang_fifo;
dma_scb_hang_dma_done:
and DFCNTRL, ~HDMAEN;
test DFCNTRL, HDMAEN jnz .;
-dma_scb_hang_dma_drain_fifo:
add SEQADDR0, A;
} else {
call dma_finish;
@@ -2249,6 +2290,13 @@
} else {
mvi SCB_TAG, SCB_LIST_NULL ret;
}
+
+if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {
+set_hhaddr:
+ or DSCOMMAND1, HADDLDSEL0;
+ and HADDR, SG_HIGH_ADDR_BITS, SINDEX;
+ and DSCOMMAND1, ~HADDLDSEL0 ret;
+}
if ((ahc->flags & AHC_PAGESCBS) != 0) {
get_free_or_disc_scb:
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)