summaryrefslogtreecommitdiffstats
path: root/sys/dev/aic7xxx/aic7xxx.seq
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/aic7xxx/aic7xxx.seq')
-rw-r--r--sys/dev/aic7xxx/aic7xxx.seq166
1 files changed, 97 insertions, 69 deletions
diff --git a/sys/dev/aic7xxx/aic7xxx.seq b/sys/dev/aic7xxx/aic7xxx.seq
index fa42362..543c2d6 100644
--- a/sys/dev/aic7xxx/aic7xxx.seq
+++ b/sys/dev/aic7xxx/aic7xxx.seq
@@ -1,7 +1,8 @@
/*
* Adaptec 274x/284x/294x device driver firmware for Linux and FreeBSD.
*
- * Copyright (c) 1994-2001 Justin Gibbs.
+ * Copyright (c) 1994-2001 Justin T. Gibbs.
+ * Copyright (c) 2000-2001 Adaptec Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -10,28 +11,37 @@
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
- * 2. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
- * GNU Public License ("GPL").
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
*
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
*
* $FreeBSD$
*/
-VERSION = "$Id: //depot/src/aic7xxx/aic7xxx.seq#32 $"
+VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#40 $"
+PATCH_ARG_LIST = "struct ahc_softc *ahc"
#include "aic7xxx.reg"
#include "scsi_message.h"
@@ -80,7 +90,7 @@ poll_for_work_loop:
test SSTAT0, SELDO|SELDI jnz selection;
test_queue:
/* Has the driver posted any work for us? */
-BEGIN_CRITICAL
+BEGIN_CRITICAL;
if ((ahc->features & AHC_QUEUE_REGS) != 0) {
test QOFF_CTLSTA, SCB_AVAIL jz poll_for_work_loop;
} else {
@@ -101,7 +111,7 @@ BEGIN_CRITICAL
mov SCBPTR, ARG_1;
}
or SEQ_FLAGS2, SCB_DMA;
-END_CRITICAL
+END_CRITICAL;
dma_queued_scb:
/*
* DMA the SCB from host ram into the current SCB location.
@@ -115,7 +125,7 @@ dma_queued_scb:
* value.
*/
mov A, ARG_1;
-BEGIN_CRITICAL
+BEGIN_CRITICAL;
cmp NEXT_QUEUED_SCB, A jne abort_qinscb;
if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {
cmp SCB_TAG, A je . + 2;
@@ -130,7 +140,7 @@ BEGIN_CRITICAL
inc QINPOS;
}
and SEQ_FLAGS2, ~SCB_DMA;
-END_CRITICAL
+END_CRITICAL;
start_waiting:
/*
* Start the first entry on the waiting SCB list.
@@ -242,6 +252,7 @@ select_in:
} else {
mov DFDAT, DINDEX;
}
+ and SAVED_LUN, MSG_IDENTIFY_LUNMASK, DINDEX;
/* Remember for disconnection decision */
test DINDEX, MSG_IDENTIFY_DISCFLAG jnz . + 2;
@@ -257,9 +268,10 @@ select_in:
* < MSG_IGN_WIDE_RESIDUE.
*/
add A, -MSG_SIMPLE_Q_TAG, DINDEX;
- jnc ident_messages_done;
+ jnc ident_messages_done_msg_pending;
add A, -MSG_IGN_WIDE_RESIDUE, DINDEX;
- jc ident_messages_done;
+ jc ident_messages_done_msg_pending;
+
/* Store for host */
if ((ahc->features & AHC_CMD_CHAN) != 0) {
mov CCSCBRAM, DINDEX;
@@ -285,9 +297,23 @@ select_in:
}
mov INITIATOR_TAG, DINDEX;
or SEQ_FLAGS, TARGET_CMD_IS_TAGGED;
- test SCSISIGI, ATNI jz . + 2;
- /* Initiator still wants to give us messages */
- call target_inb;
+
+ident_messages_done:
+ /* Terminate the ident list */
+ if ((ahc->features & AHC_CMD_CHAN) != 0) {
+ mvi CCSCBRAM, SCB_LIST_NULL;
+ } else {
+ mvi DFDAT, SCB_LIST_NULL;
+ }
+ or SEQ_FLAGS, TARG_CMD_PENDING|IDENTIFY_SEEN;
+ test SEQ_FLAGS2, TARGET_MSG_PENDING
+ jnz target_mesgout_pending;
+ test SCSISIGI, ATNI jnz target_mesgout_continue;
+ jmp target_ITloop;
+
+
+ident_messages_done_msg_pending:
+ or SEQ_FLAGS2, TARGET_MSG_PENDING;
jmp ident_messages_done;
/*
@@ -299,31 +325,6 @@ host_target_message_loop:
cmp RETURN_1, EXIT_MSG_LOOP je target_ITloop;
test SSTAT0, SPIORDY jz .;
jmp host_target_message_loop;
-
-ident_messages_done:
- /* If ring buffer is full, return busy or queue full */
- if ((ahc->features & AHC_HS_MAILBOX) != 0) {
- and A, HOST_TQINPOS, HS_MAILBOX;
- } else {
- mov A, KERNEL_TQINPOS;
- }
- cmp TQINPOS, A jne tqinfifo_has_space;
- mvi P_STATUS|BSYO call change_phase;
- test SEQ_FLAGS, TARGET_CMD_IS_TAGGED jz . + 3;
- mvi STATUS_QUEUE_FULL call target_outb;
- jmp target_busfree_wait;
- mvi STATUS_BUSY call target_outb;
- jmp target_busfree_wait;
-tqinfifo_has_space:
- /* Terminate the ident list */
- if ((ahc->features & AHC_CMD_CHAN) != 0) {
- mvi CCSCBRAM, SCB_LIST_NULL;
- } else {
- mvi DFDAT, SCB_LIST_NULL;
- }
- or SEQ_FLAGS, TARG_CMD_PENDING|IDENTIFY_SEEN;
- test SCSISIGI, ATNI jnz target_mesgout_pending;
- jmp target_ITloop;
}
if ((ahc->flags & AHC_INITIATORROLE) != 0) {
@@ -464,13 +465,13 @@ select_out:
*/
test SCB_CONTROL, TAG_ENB jz . + 3;
mvi MSG_SIMPLE_Q_TAG call target_outb;
- mov SCB_TARGET_INFO[SCB_INITIATOR_TAG] call target_outb;
+ mov SCB_TARGET_ITAG call target_outb;
target_synccmd:
/*
* Now determine what phases the host wants us
* to go through.
*/
- mov SEQ_FLAGS, SCB_TARGET_INFO[SCB_TARGET_PHASES];
+ mov SEQ_FLAGS, SCB_TARGET_PHASES;
test SCB_CONTROL, MK_MESSAGE jz target_ITloop;
mvi P_MESGIN|BSYO call change_phase;
@@ -498,6 +499,7 @@ target_ITloop:
}
mvi DMAPARAMS, HDMAEN|DIRECTION|FIFORESET;
mov SCB_TAG call dma_scb;
+ call set_transfer_settings;
jmp target_synccmd;
target_mesgout:
@@ -528,6 +530,24 @@ target_busfree:
jmp poll_for_work;
target_cmdphase:
+ /*
+ * The target has dropped ATN (doesn't want to abort or BDR)
+ * and we believe this selection to be valid. If the ring
+ * buffer for new commands is full, return busy or queue full.
+ */
+ if ((ahc->features & AHC_HS_MAILBOX) != 0) {
+ and A, HOST_TQINPOS, HS_MAILBOX;
+ } else {
+ mov A, KERNEL_TQINPOS;
+ }
+ cmp TQINPOS, A jne tqinfifo_has_space;
+ mvi P_STATUS|BSYO call change_phase;
+ test SEQ_FLAGS, TARGET_CMD_IS_TAGGED jz . + 3;
+ mvi STATUS_QUEUE_FULL call target_outb;
+ jmp target_busfree_wait;
+ mvi STATUS_BUSY call target_outb;
+ jmp target_busfree_wait;
+tqinfifo_has_space:
mvi P_COMMAND|BSYO call change_phase;
call target_inb;
mov A, DINDEX;
@@ -576,15 +596,14 @@ target_dphase:
* data direction of the DMA. Toggle it for
* target transfers.
*/
- xor LASTPHASE, IOI, SCB_TARGET_INFO[SCB_TARGET_DATA_DIR];
- or SCB_TARGET_INFO[SCB_TARGET_DATA_DIR], BSYO
- call change_phase;
+ xor LASTPHASE, IOI, SCB_TARGET_DATA_DIR;
+ or SCB_TARGET_DATA_DIR, BSYO call change_phase;
jmp p_data;
target_sphase:
mvi P_STATUS|BSYO call change_phase;
mvi LASTPHASE, P_STATUS;
- mov SCB_TARGET_INFO[SCB_TARGET_STATUS] call target_outb;
+ mov SCB_SCSI_STATUS call target_outb;
/* XXX Watch for ATN or parity errors??? */
mvi SCSISIGO, P_MESGIN|BSYO;
/* MSG_CMDCMPLT is 0, but we can't do an immediate of 0 */
@@ -951,12 +970,12 @@ ultra2_dmafinish:
ultra2_ensure_sg:
test SG_CACHE_SHADOW, LAST_SEG jz ultra2_shvalid;
/* Record if we've consumed all S/G entries */
- test SSTAT2, SHVALID jnz residuals_correct;
+ test SSTAT2, SHVALID jnz residuals_correct;
or SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL;
jmp residuals_correct;
ultra2_shvalid:
- test SSTAT2, SHVALID jnz sgptr_fixup;
+ test SSTAT2, SHVALID jnz sgptr_fixup;
call idle_loop;
jmp ultra2_ensure_sg;
@@ -1318,10 +1337,19 @@ residual_update_done:
and SEQ_FLAGS, ~DPHASE_PENDING;
/*
* For data-in phases, wait for any pending acks from the
- * initiator before changing phase.
+ * initiator before changing phase. We only need to
+ * send Ignore Wide Residue messages for data-in phases.
*/
test DFCNTRL, DIRECTION jz target_ITloop;
test SSTAT1, REQINIT jnz .;
+ test DATA_COUNT_ODD, 0x1 jz target_ITloop;
+ test SCSIRATE, WIDEXFER jz target_ITloop;
+ /*
+ * Issue an Ignore Wide Residue Message.
+ */
+ mvi P_MESGIN|BSYO call change_phase;
+ mvi MSG_IGN_WIDE_RESIDUE call target_outb;
+ mvi 1 call target_outb;
jmp target_ITloop;
} else {
jmp ITloop;
@@ -1371,7 +1399,7 @@ p_command_embedded:
* 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.
+ * we aren't going to touch host memory.
*/
clr HADDR[0];
if ((ahc->features & AHC_ULTRA2) != 0) {
@@ -1977,7 +2005,7 @@ target_outb:
* removal of the found SCB from the disconnected list.
*/
if ((ahc->flags & AHC_PAGESCBS) != 0) {
-BEGIN_CRITICAL
+BEGIN_CRITICAL;
findSCB:
mov A, SINDEX; /* Tag passed in SINDEX */
cmp DISCONNECTED_SCBH, SCB_LIST_NULL je findSCB_notFound;
@@ -1999,7 +2027,7 @@ rem_scb_from_disc_list:
mov SCBPTR, SINDEX ret;
rHead:
mov DISCONNECTED_SCBH,SCB_NEXT ret;
-END_CRITICAL
+END_CRITICAL;
findSCB_notFound:
/*
* We didn't find it. Page in the SCB.
@@ -2124,7 +2152,7 @@ set_1byte_addr:
adc DINDIR, A, SINDIR ret;
/*
- * Either post or fetch and SCB from host memory based on the
+ * Either post or fetch an SCB from host memory based on the
* DIRECTION bit in DMAPARAMS. The host SCB index is in SINDEX.
*/
dma_scb:
@@ -2282,11 +2310,11 @@ cleanup_scb:
}
add_scb_to_free_list:
if ((ahc->flags & AHC_PAGESCBS) != 0) {
-BEGIN_CRITICAL
+BEGIN_CRITICAL;
mov SCB_NEXT, FREE_SCBH;
mvi SCB_TAG, SCB_LIST_NULL;
mov FREE_SCBH, SCBPTR ret;
-END_CRITICAL
+END_CRITICAL;
} else {
mvi SCB_TAG, SCB_LIST_NULL ret;
}
@@ -2300,7 +2328,7 @@ set_hhaddr:
if ((ahc->flags & AHC_PAGESCBS) != 0) {
get_free_or_disc_scb:
-BEGIN_CRITICAL
+BEGIN_CRITICAL;
cmp FREE_SCBH, SCB_LIST_NULL jne dequeue_free_scb;
cmp DISCONNECTED_SCBH, SCB_LIST_NULL jne dequeue_disc_scb;
return_error:
@@ -2309,14 +2337,14 @@ return_error:
dequeue_disc_scb:
mov SCBPTR, DISCONNECTED_SCBH;
mov DISCONNECTED_SCBH, SCB_NEXT;
-END_CRITICAL
+END_CRITICAL;
mvi DMAPARAMS, FIFORESET;
mov SCB_TAG jmp dma_scb;
-BEGIN_CRITICAL
+BEGIN_CRITICAL;
dequeue_free_scb:
mov SCBPTR, FREE_SCBH;
mov FREE_SCBH, SCB_NEXT ret;
-END_CRITICAL
+END_CRITICAL;
add_scb_to_disc_list:
/*
@@ -2324,10 +2352,10 @@ add_scb_to_disc_list:
* candidates for paging out an SCB if one is needed for a new command.
* Modifying the disconnected list is a critical(pause dissabled) section.
*/
-BEGIN_CRITICAL
+BEGIN_CRITICAL;
mov SCB_NEXT, DISCONNECTED_SCBH;
mov DISCONNECTED_SCBH, SCBPTR ret;
-END_CRITICAL
+END_CRITICAL;
}
set_seqint:
mov INTSTAT, SINDEX;
OpenPOWER on IntegriCloud