Keep track of negotiated transfer parameters for each initiator<->target
connection. Clean up support for devices featuring the multiple target SCSI ID feature. On aic7890/91/96/97 chips, we can now assume the target role on multiple target ids simultaneously. Although these chips also have sufficient instruction space to hold to support the initiator and target role at the same time, the initiator role is currently disabled as it will conflict (chip design restriction) with the multi-tid feature. I'll probably add a nob to enable the initiator (there-by disabling multi-tid) some time in the future. Return queue full or busy, depending on the tagged nature of the incoming request, if our command input queue fills up in host memeory. Deal with accept target I/O resource shortages. If we get an underrun on a transaction that wasn't supposed to transmit any data, don't attempt to print out the S/G list. The code would run until hitting a non-present page. (oops)
This commit is contained in:
parent
f15aa8d8d9
commit
c562189829
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=44507
File diff suppressed because it is too large
Load Diff
@ -34,7 +34,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: aic7xxx.h,v 1.4 1998/12/15 08:22:41 gibbs Exp $
|
||||
* $Id: aic7xxx.h,v 1.5 1999/01/14 06:14:15 gibbs Exp $
|
||||
*/
|
||||
|
||||
#ifndef _AIC7XXX_H_
|
||||
@ -156,7 +156,8 @@ typedef enum {
|
||||
* controller.
|
||||
*/
|
||||
AHC_NEWEEPROM_FMT = 0x4000,
|
||||
AHC_RESOURCE_SHORTAGE = 0x8000
|
||||
AHC_RESOURCE_SHORTAGE = 0x8000,
|
||||
AHC_TQINFIFO_BLOCKED = 0x10000,/* Blocked waiting for ATIOs */
|
||||
} ahc_flag;
|
||||
|
||||
typedef enum {
|
||||
@ -277,12 +278,40 @@ struct tmode_lstate {
|
||||
struct ccb_hdr_slist immed_notifies;
|
||||
};
|
||||
|
||||
#define AHC_TRANS_CUR 0x01 /* Modify current neogtiation status */
|
||||
#define AHC_TRANS_ACTIVE 0x03 /* Assume this is the active target */
|
||||
#define AHC_TRANS_GOAL 0x04 /* Modify negotiation goal */
|
||||
#define AHC_TRANS_USER 0x08 /* Modify user negotiation settings */
|
||||
|
||||
struct ahc_transinfo {
|
||||
u_int8_t width;
|
||||
u_int8_t period;
|
||||
u_int8_t offset;
|
||||
};
|
||||
|
||||
struct ahc_initiator_tinfo {
|
||||
u_int8_t scsirate;
|
||||
struct ahc_transinfo current;
|
||||
struct ahc_transinfo goal;
|
||||
struct ahc_transinfo user;
|
||||
};
|
||||
|
||||
/*
|
||||
* Per target mode enabled target state. Esentially just an array of
|
||||
* pointers to lun target state.
|
||||
* pointers to lun target state as well as sync/wide negotiation information
|
||||
* for each initiator<->target mapping (including the mapping for when we
|
||||
* are the initiator).
|
||||
*/
|
||||
struct tmode_tstate {
|
||||
struct tmode_lstate* enabled_luns[8];
|
||||
struct tmode_lstate* enabled_luns[8];
|
||||
struct ahc_initiator_tinfo transinfo[16];
|
||||
|
||||
/*
|
||||
* Per initiator state bitmasks.
|
||||
*/
|
||||
u_int16_t ultraenb; /* Using ultra sync rate */
|
||||
u_int16_t discenable; /* Disconnection allowed */
|
||||
u_int16_t tagenable; /* Tagged Queuing allowed */
|
||||
};
|
||||
|
||||
/*
|
||||
@ -356,24 +385,6 @@ struct seeprom_config {
|
||||
u_int16_t checksum; /* word 31 */
|
||||
};
|
||||
|
||||
#define AHC_TRANS_CUR 0x01 /* Modify current neogtiation status */
|
||||
#define AHC_TRANS_ACTIVE 0x03 /* Assume this is the active target */
|
||||
#define AHC_TRANS_GOAL 0x04 /* Modify negotiation goal */
|
||||
#define AHC_TRANS_USER 0x08 /* Modify user negotiation settings */
|
||||
|
||||
struct ahc_transinfo {
|
||||
u_int8_t width;
|
||||
u_int8_t period;
|
||||
u_int8_t offset;
|
||||
};
|
||||
|
||||
struct ahc_target_tinfo {
|
||||
u_int8_t scsirate;
|
||||
struct ahc_transinfo current;
|
||||
struct ahc_transinfo goal;
|
||||
struct ahc_transinfo user;
|
||||
};
|
||||
|
||||
struct ahc_syncrate {
|
||||
int sxfr_ultra2;
|
||||
int sxfr;
|
||||
@ -405,6 +416,8 @@ struct ahc_softc {
|
||||
/*
|
||||
* Target mode related state kept on a per enabled lun basis.
|
||||
* Targets that are not enabled will have null entries.
|
||||
* As an initiator, we keep one target entry for our initiator
|
||||
* ID to store our sync/wide transfer settings.
|
||||
*/
|
||||
struct tmode_tstate* enabled_targets[16];
|
||||
|
||||
@ -443,19 +456,6 @@ struct ahc_softc {
|
||||
*/
|
||||
u_int8_t untagged_scbs[256];
|
||||
|
||||
/*
|
||||
* User/Current/Active Negotiation settings
|
||||
*/
|
||||
struct ahc_target_tinfo transinfo[16];
|
||||
|
||||
/*
|
||||
* Per target state bitmasks.
|
||||
*/
|
||||
u_int16_t ultraenb; /* Using ultra sync rate */
|
||||
u_int16_t discenable; /* Disconnection allowed */
|
||||
u_int16_t tagenable; /* Tagged Queuing allowed */
|
||||
u_int16_t targ_msg_req; /* Need negotiation messages */
|
||||
|
||||
/*
|
||||
* Hooks into the XPT.
|
||||
*/
|
||||
@ -474,6 +474,9 @@ struct ahc_softc {
|
||||
u_int8_t our_id;
|
||||
u_int8_t our_id_b;
|
||||
|
||||
/* Targets that need negotiation messages */
|
||||
u_int16_t targ_msg_req;
|
||||
|
||||
/*
|
||||
* PCI error detection and data for running the
|
||||
* PCI error interrupt handler.
|
||||
@ -498,6 +501,7 @@ struct ahc_softc {
|
||||
u_int msgout_index; /* Current index in msgout */
|
||||
u_int msgin_index; /* Current index in msgin */
|
||||
|
||||
/* Number of enabled target mode device on this card */
|
||||
u_int enabled_luns;
|
||||
|
||||
/*
|
||||
|
@ -32,7 +32,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: aic7xxx.reg,v 1.11 1998/12/17 00:06:52 gibbs Exp $
|
||||
* $Id: aic7xxx.reg,v 1.12 1999/01/14 06:14:15 gibbs Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -882,7 +882,6 @@ scb {
|
||||
}
|
||||
SCB_CMDPTR {
|
||||
alias SCB_TARGET_PHASES
|
||||
alias SCB_TARGET_ID /* Byte 2 */
|
||||
bit TARGET_DATA_IN 0x1 /* In the second byte */
|
||||
size 4
|
||||
}
|
||||
@ -1267,7 +1266,7 @@ scratch_ram {
|
||||
/*
|
||||
* Kernel and sequencer offsets into the queue of
|
||||
* incoming target mode command descriptors. The
|
||||
* queue is full when the ((KERNEL_TQINPOS - TQINPOS) == 1)
|
||||
* queue is full when the KERNEL_TQINPOS == TQINPOS.
|
||||
*/
|
||||
KERNEL_TQINPOS {
|
||||
size 1
|
||||
@ -1408,6 +1407,12 @@ const CMD_GROUP3_BYTE_DELTA -15
|
||||
const CMD_GROUP4_BYTE_DELTA 4
|
||||
const CMD_GROUP5_BYTE_DELTA 11
|
||||
|
||||
const TCL_TARGET_SHIFT 4
|
||||
/* The update interval must be a power of 2 */
|
||||
const TQINFIFO_UPDATE_CNT 32
|
||||
|
||||
const STATUS_BUSY 0x08
|
||||
const STATUS_QUEUE_FULL 0x28
|
||||
|
||||
/*
|
||||
* Downloaded (kernel inserted) constants
|
||||
|
@ -32,7 +32,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: aic7xxx.seq,v 1.84 1999/01/14 06:14:15 gibbs Exp $
|
||||
* $Id: aic7xxx.seq,v 1.85 1999/02/11 07:10:20 gibbs Exp $
|
||||
*/
|
||||
|
||||
#include <dev/aic7xxx/aic7xxx.reg>
|
||||
@ -68,8 +68,8 @@ reset:
|
||||
clr CCSCBCTL;
|
||||
}
|
||||
|
||||
call clear_target_state;
|
||||
poll_for_work:
|
||||
call clear_target_state;
|
||||
and SXFRCTL0, ~SPIOEN;
|
||||
if ((ahc->features & AHC_QUEUE_REGS) == 0) {
|
||||
mov A, QINPOS;
|
||||
@ -169,6 +169,17 @@ start_selection:
|
||||
mov SBLKCTL,SINDEX; /* select channel */
|
||||
}
|
||||
initialize_scsiid:
|
||||
mov SINDEX, SCSISEQ_TEMPLATE;
|
||||
if ((ahc->flags & AHC_TARGETMODE) != 0) {
|
||||
test SCB_CONTROL, TARGET_SCB jz . + 4;
|
||||
if ((ahc->features & AHC_ULTRA2) != 0) {
|
||||
mov SCSIID_ULTRA2, SCB_CMDPTR[2];
|
||||
} else {
|
||||
mov SCSIID, SCB_CMDPTR[2];
|
||||
}
|
||||
or SINDEX, TEMODE;
|
||||
jmp initialize_scsiid_fini;
|
||||
}
|
||||
if ((ahc->features & AHC_ULTRA2) != 0) {
|
||||
and A, TID, SCB_TCL; /* Get target ID */
|
||||
and SCSIID_ULTRA2, OID; /* Clear old target */
|
||||
@ -178,11 +189,7 @@ initialize_scsiid:
|
||||
and SCSIID, OID; /* Clear old target */
|
||||
or SCSIID, A;
|
||||
}
|
||||
mov SINDEX, SCSISEQ_TEMPLATE;
|
||||
if ((ahc->flags & AHC_TARGETMODE) != 0) {
|
||||
test SCB_CONTROL, TARGET_SCB jz . + 2;
|
||||
or SINDEX, TEMODE;
|
||||
}
|
||||
initialize_scsiid_fini:
|
||||
mov SCSISEQ, SINDEX ret;
|
||||
|
||||
/*
|
||||
@ -230,7 +237,6 @@ select_in:
|
||||
*/
|
||||
or SEQ_FLAGS, CMDPHASE_PENDING;
|
||||
|
||||
/* XXX If ring buffer is full, return busy or queue full */
|
||||
mov A, TQINPOS;
|
||||
if ((ahc->features & AHC_CMD_CHAN) != 0) {
|
||||
mvi DINDEX, CCHADDR;
|
||||
@ -251,15 +257,19 @@ select_in:
|
||||
}
|
||||
|
||||
/* The Target ID we were selected at */
|
||||
if ((ahc->features & AHC_MULTI_TID) != 0) {
|
||||
if ((ahc->features & AHC_CMD_CHAN) != 0) {
|
||||
and CCSCBRAM, 0x0f, TARGIDIN;
|
||||
if ((ahc->features & AHC_CMD_CHAN) != 0) {
|
||||
if ((ahc->features & AHC_MULTI_TID) != 0) {
|
||||
and CCSCBRAM, OID, TARGIDIN;
|
||||
} else if ((ahc->features & AHC_ULTRA2) != 0) {
|
||||
and CCSCBRAM, OID, SCSIID_ULTRA2;
|
||||
} else {
|
||||
and DFDAT, 0x0f, TARGIDIN;
|
||||
and CCSCBRAM, OID, SCSIID;
|
||||
}
|
||||
} else {
|
||||
if ((ahc->features & AHC_CMD_CHAN) != 0) {
|
||||
and CCSCBRAM, OID, SCSIID;
|
||||
if ((ahc->features & AHC_MULTI_TID) != 0) {
|
||||
and DFDAT, OID, TARGIDIN;
|
||||
} else if ((ahc->features & AHC_ULTRA2) != 0) {
|
||||
and DFDAT, OID, SCSIID_ULTRA2;
|
||||
} else {
|
||||
and DFDAT, OID, SCSIID;
|
||||
}
|
||||
@ -349,6 +359,16 @@ host_target_message_loop:
|
||||
jmp host_target_message_loop;
|
||||
|
||||
ident_messages_done:
|
||||
/* If ring buffer is full, return busy or queue full */
|
||||
mov A, KERNEL_TQINPOS;
|
||||
cmp TQINPOS, A jne tqinfifo_has_space;
|
||||
mvi P_STATUS|BSYO call change_phase;
|
||||
cmp INITIATOR_TAG, SCB_LIST_NULL je . + 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;
|
||||
@ -450,7 +470,7 @@ target_synccmd:
|
||||
target_ITloop:
|
||||
/*
|
||||
* Start honoring ATN signals now that
|
||||
* we properly identified ourself.
|
||||
* we properly identified ourselves.
|
||||
*/
|
||||
test SCSISIGI, ATNI jnz target_mesgout;
|
||||
test SEQ_FLAGS, CMDPHASE_PENDING jnz target_cmdphase;
|
||||
@ -491,7 +511,6 @@ target_busfree_wait:
|
||||
target_busfree:
|
||||
clr SCSISIGO;
|
||||
call complete_target_cmd;
|
||||
call clear_target_state;
|
||||
jmp poll_for_work;
|
||||
|
||||
target_cmdphase:
|
||||
@ -625,7 +644,6 @@ ITloop:
|
||||
|
||||
await_busfree:
|
||||
and SIMODE1, ~ENBUSFREE;
|
||||
call clear_target_state;
|
||||
mov NONE, SCSIDATL; /* Ack the last byte */
|
||||
and SXFRCTL0, ~SPIOEN;
|
||||
test SSTAT1,REQINIT|BUSFREE jz .;
|
||||
@ -1146,14 +1164,12 @@ complete:
|
||||
|
||||
complete_queue:
|
||||
mov SCB_TAG call complete_post;
|
||||
|
||||
add_to_free_list:
|
||||
call add_scb_to_free_list;
|
||||
jmp await_busfree;
|
||||
}
|
||||
|
||||
complete_post:
|
||||
/* Post the SCBID in SINDEX and issue an interrupt */
|
||||
call add_scb_to_free_list;
|
||||
mov ARG_1, SINDEX;
|
||||
if ((ahc->features & AHC_QUEUE_REGS) != 0) {
|
||||
mov A, SDSCB_QOFF;
|
||||
|
Loading…
Reference in New Issue
Block a user