Skip to content

Commit

Permalink
[SCSI] aic79xx: sequencer fixes
Browse files Browse the repository at this point in the history
This patch updates the aic79xx sequencer with latest fixes from adaptec.
The sequencer code now corresponds with adaptec version 2.0.15.

Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
  • Loading branch information
Hannes Reinecke authored and James Bottomley committed Jan 31, 2006
1 parent 2628ed2 commit 53467e6
Show file tree
Hide file tree
Showing 9 changed files with 834 additions and 553 deletions.
29 changes: 25 additions & 4 deletions drivers/scsi/aic7xxx/aic79xx.reg
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* Aic79xx register and scratch ram definitions.
*
* Copyright (c) 1994-2001 Justin T. Gibbs.
* Copyright (c) 1994-2001, 2004 Justin T. Gibbs.
* Copyright (c) 2000-2002 Adaptec Inc.
* All rights reserved.
*
Expand Down Expand Up @@ -39,7 +39,7 @@
*
* $FreeBSD$
*/
VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#76 $"
VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#77 $"

/*
* This file is processed by the aic7xxx_asm utility for use in assembling
Expand Down Expand Up @@ -3715,8 +3715,9 @@ scratch_ram {
SEQ_FLAGS2 {
size 1
field TARGET_MSG_PENDING 0x02
field SELECTOUT_QFROZEN 0x04
field PENDING_MK_MESSAGE 0x01
field TARGET_MSG_PENDING 0x02
field SELECTOUT_QFROZEN 0x04
}
ALLOCFIFO_SCBPTR {
Expand Down Expand Up @@ -3777,6 +3778,26 @@ scratch_ram {
CMDSIZE_TABLE {
size 8
}
/*
* When an SCB with the MK_MESSAGE flag is
* queued to the controller, it cannot enter
* the waiting for selection list until the
* selections for any previously queued
* commands to that target complete. During
* the wait, the MK_MESSAGE SCB is queued
* here.
*/
MK_MESSAGE_SCB {
size 2
}
/*
* Saved SCSIID of MK_MESSAGE_SCB to avoid
* an extra SCBPTR operation when deciding
* if the MK_MESSAGE_SCB can be run.
*/
MK_MESSAGE_SCSIID {
size 1
}
}
/************************* Hardware SCB Definition ****************************/
Expand Down
143 changes: 120 additions & 23 deletions drivers/scsi/aic7xxx/aic79xx.seq
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* Adaptec U320 device driver firmware for Linux and FreeBSD.
*
* Copyright (c) 1994-2001 Justin T. Gibbs.
* Copyright (c) 1994-2001, 2004 Justin T. Gibbs.
* Copyright (c) 2000-2002 Adaptec Inc.
* All rights reserved.
*
Expand Down Expand Up @@ -40,7 +40,7 @@
* $FreeBSD$
*/

VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#119 $"
VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#120 $"
PATCH_ARG_LIST = "struct ahd_softc *ahd"
PREFIX = "ahd_"

Expand Down Expand Up @@ -110,10 +110,8 @@ check_waiting_list:
* one last time.
*/
test SSTAT0, SELDO jnz select_out;
END_CRITICAL;
call start_selection;
idle_loop_checkbus:
BEGIN_CRITICAL;
test SSTAT0, SELDO jnz select_out;
END_CRITICAL;
test SSTAT0, SELDI jnz select_in;
Expand Down Expand Up @@ -294,7 +292,6 @@ fetch_new_scb_inprog:
test CCSCBCTL, ARRDONE jz return;
fetch_new_scb_done:
and CCSCBCTL, ~(CCARREN|CCSCBEN);
bmov REG0, SCBPTR, 2;
clr A;
add CMDS_PENDING, 1;
adc CMDS_PENDING[1], A;
Expand All @@ -316,43 +313,117 @@ fetch_new_scb_done:
clr SCB_FIFO_USE_COUNT;
/* Update the next SCB address to download. */
bmov NEXT_QUEUED_SCB_ADDR, SCB_NEXT_SCB_BUSADDR, 4;
/*
* NULL out the SCB links since these fields
* occupy the same location as SCB_NEXT_SCB_BUSADDR.
*/
mvi SCB_NEXT[1], SCB_LIST_NULL;
mvi SCB_NEXT2[1], SCB_LIST_NULL;
/* Increment our position in the QINFIFO. */
mov NONE, SNSCB_QOFF;

/*
* SCBs that want to send messages are always
* queued independently. This ensures that they
* are at the head of the SCB list to select out
* to a target and we will see the MK_MESSAGE flag.
* Save SCBID of this SCB in REG0 since
* SCBPTR will be clobbered during target
* list updates. We also record the SCB's
* flags so that we can refer to them even
* after SCBPTR has been changed.
*/
bmov REG0, SCBPTR, 2;
mov A, SCB_CONTROL;

/*
* Find the tail SCB of the execution queue
* for this target.
*/
test SCB_CONTROL, MK_MESSAGE jnz first_new_target_scb;
shr SINDEX, 3, SCB_SCSIID;
and SINDEX, ~0x1;
mvi SINDEX[1], (WAITING_SCB_TAILS >> 8);
bmov DINDEX, SINDEX, 2;
bmov SCBPTR, SINDIR, 2;

/*
* Update the tail to point to the new SCB.
*/
bmov DINDIR, REG0, 2;

/*
* If the queue was empty, queue this SCB as
* the first for this target.
*/
cmp SCBPTR[1], SCB_LIST_NULL je first_new_target_scb;

/*
* SCBs that want to send messages must always be
* at the head of their per-target queue so that
* ATN can be asserted even if the current
* negotiation agreement is packetized. If the
* target queue is empty, the SCB can be queued
* immediately. If the queue is not empty, we must
* wait for it to empty before entering this SCB
* into the waiting for selection queue. Otherwise
* our batching and round-robin selection scheme
* could allow commands to be queued out of order.
* To simplify the implementation, we stop pulling
* new commands from the host until the MK_MESSAGE
* SCB can be queued to the waiting for selection
* list.
*/
test A, MK_MESSAGE jz batch_scb;

/*
* If the last SCB is also a MK_MESSAGE SCB, then
* order is preserved even if we batch.
*/
test SCB_CONTROL, MK_MESSAGE jz batch_scb;

/*
* Defer this SCB and stop fetching new SCBs until
* it can be queued. Since the SCB_SCSIID of the
* tail SCB must be the same as that of the newly
* queued SCB, there is no need to restore the SCBID
* here.
*/
or SEQ_FLAGS2, PENDING_MK_MESSAGE;
bmov MK_MESSAGE_SCB, REG0, 2;
mov MK_MESSAGE_SCSIID, SCB_SCSIID ret;

batch_scb:
/*
* Otherwise just update the previous tail SCB to
* point to the new tail.
*/
bmov SCB_NEXT, REG0, 2 ret;

first_new_target_scb:
/*
* Append SCB to the tail of the waiting for
* selection list.
*/
cmp WAITING_TID_HEAD[1], SCB_LIST_NULL je first_new_scb;
bmov SCBPTR, WAITING_TID_TAIL, 2;
bmov SCB_NEXT2, REG0, 2;
bmov WAITING_TID_TAIL, REG0, 2 ret;
first_new_scb:
/*
* Whole list is empty, so the head of
* the list must be initialized too.
*/
bmov WAITING_TID_HEAD, REG0, 2;
bmov WAITING_TID_TAIL, REG0, 2 ret;
END_CRITICAL;

scbdma_idle:
/*
* Give precedence to downloading new SCBs to execute
* unless select-outs are currently frozen.
* Don't bother downloading new SCBs to execute
* if select-outs are currently frozen or we have
* a MK_MESSAGE SCB waiting to enter the queue.
*/
test SEQ_FLAGS2, SELECTOUT_QFROZEN jnz . + 2;
test SEQ_FLAGS2, SELECTOUT_QFROZEN|PENDING_MK_MESSAGE
jnz scbdma_no_new_scbs;
BEGIN_CRITICAL;
test QOFF_CTLSTA, NEW_SCB_AVAIL jnz fetch_new_scb;
scbdma_no_new_scbs:
cmp COMPLETE_DMA_SCB_HEAD[1], SCB_LIST_NULL jne dma_complete_scb;
cmp COMPLETE_SCB_HEAD[1], SCB_LIST_NULL je return;
/* FALLTHROUGH */
Expand Down Expand Up @@ -671,27 +742,41 @@ curscb_ww_done:
}

/*
* Requeue any SCBs not sent, to the tail of the waiting Q.
* The whole list made it. Clear our tail pointer to indicate
* that the per-target selection queue is now empty.
*/
cmp SCB_NEXT[1], SCB_LIST_NULL je select_out_list_done;
cmp SCB_NEXT[1], SCB_LIST_NULL je select_out_clear_tail;

/*
* Requeue any SCBs not sent, to the tail of the waiting Q.
* We know that neither the per-TID list nor the list of
* TIDs is empty. Use this knowledge to our advantage.
* TIDs is empty. Use this knowledge to our advantage and
* queue the remainder to the tail of the global execution
* queue.
*/
bmov REG0, SCB_NEXT, 2;
select_out_queue_remainder:
bmov SCBPTR, WAITING_TID_TAIL, 2;
bmov SCB_NEXT2, REG0, 2;
bmov WAITING_TID_TAIL, REG0, 2;
jmp select_out_inc_tid_q;

select_out_list_done:
select_out_clear_tail:
/*
* Queue any pending MK_MESSAGE SCB for this target now
* that the queue is empty.
*/
test SEQ_FLAGS2, PENDING_MK_MESSAGE jz select_out_no_mk_message_scb;
mov A, MK_MESSAGE_SCSIID;
cmp SCB_SCSIID, A jne select_out_no_mk_message_scb;
and SEQ_FLAGS2, ~PENDING_MK_MESSAGE;
bmov REG0, MK_MESSAGE_SCB, 2;
jmp select_out_queue_remainder;

select_out_no_mk_message_scb:
/*
* The whole list made it. Just clear our TID's tail pointer
* unless we were queued independently due to our need to
* send a message.
* Clear this target's execution tail and increment the queue.
*/
test SCB_CONTROL, MK_MESSAGE jnz select_out_inc_tid_q;
shr DINDEX, 3, SCB_SCSIID;
or DINDEX, 1; /* Want only the second byte */
mvi DINDEX[1], ((WAITING_SCB_TAILS) >> 8);
Expand All @@ -703,8 +788,8 @@ select_out_inc_tid_q:
mvi WAITING_TID_TAIL[1], SCB_LIST_NULL;
bmov SCBPTR, CURRSCB, 2;
mvi CLRSINT0, CLRSELDO;
test LQOSTAT2, LQOPHACHGOUTPKT jnz unexpected_nonpkt_phase;
test LQOSTAT1, LQOPHACHGINPKT jnz unexpected_nonpkt_phase;
test LQOSTAT2, LQOPHACHGOUTPKT jnz unexpected_nonpkt_mode_cleared;
test LQOSTAT1, LQOPHACHGINPKT jnz unexpected_nonpkt_mode_cleared;

/*
* If this is a packetized connection, return to our
Expand Down Expand Up @@ -2127,6 +2212,18 @@ SET_DST_MODE M_DFF0;
mvi DFFSXFRCTL, CLRCHN;
unexpected_nonpkt_mode_cleared:
mvi CLRSINT2, CLRNONPACKREQ;
if ((ahd->bugs & AHD_BUSFREEREV_BUG) != 0) {
/*
* Test to ensure that the bus has not
* already gone free prior to clearing
* any stale busfree status. This avoids
* a window whereby a busfree just after
* a selection could be missed.
*/
test SCSISIGI, BSYI jz . + 2;
mvi CLRSINT1,CLRBUSFREE;
or SIMODE1, ENBUSFREE;
}
test SCSIPHASE, ~(MSG_IN_PHASE|MSG_OUT_PHASE) jnz illegal_phase;
SET_SEQINTCODE(ENTERING_NONPACK)
jmp ITloop;
Expand Down
Loading

0 comments on commit 53467e6

Please sign in to comment.