summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgibbs <gibbs@FreeBSD.org>1998-12-15 08:22:42 +0000
committergibbs <gibbs@FreeBSD.org>1998-12-15 08:22:42 +0000
commit4bb599f96ca8518733c65bfc1ae889e53f69d282 (patch)
tree5727a212c14d64ba0911fe96bfd4eb9dfde75eb7
parent41e7e01c3b4d0b2cfd3e5887f58ed3dc5ad4166a (diff)
downloadFreeBSD-src-4bb599f96ca8518733c65bfc1ae889e53f69d282.zip
FreeBSD-src-4bb599f96ca8518733c65bfc1ae889e53f69d282.tar.gz
Perform a save data pointers operation if a data transfer was performed
in target mode, but we are not completing the command. Use a template of allowed bus arbitration phases to selectively and dynamically enable/disable initiator or target (re)selection. Properly handle timeouts for target role transactions - just go to the bus free state and report the error to the peripheral driver. Checkpoint support for the XPT_ABORT_CCB function code. This currently handles the accept tio and immediate notify ccb types, but does not handle the continue target I/O or SCSI I/O ccb types. This is enough to handle dynamic target enable/disable events. Clean up the SCSI reset code so that we perform at most 1 SCSI bus reset at initialization, the reset requested by the XPT layer.
-rw-r--r--sys/dev/aic7xxx/aic7xxx.c283
-rw-r--r--sys/dev/aic7xxx/aic7xxx.h14
-rw-r--r--sys/dev/aic7xxx/aic7xxx.reg17
-rw-r--r--sys/dev/aic7xxx/aic7xxx.seq25
4 files changed, 277 insertions, 62 deletions
diff --git a/sys/dev/aic7xxx/aic7xxx.c b/sys/dev/aic7xxx/aic7xxx.c
index c5ffbf2..f4cc6cc 100644
--- a/sys/dev/aic7xxx/aic7xxx.c
+++ b/sys/dev/aic7xxx/aic7xxx.c
@@ -36,7 +36,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: aic7xxx.c,v 1.11 1998/12/04 22:54:44 archie Exp $
+ * $Id: aic7xxx.c,v 1.12 1998/12/10 04:14:49 gibbs Exp $
*/
/*
* A few notes on features of the driver.
@@ -255,6 +255,8 @@ static void ahc_print_scb(struct scb *scb);
static int ahc_search_qinfifo(struct ahc_softc *ahc, int target,
char channel, int lun, u_int tag,
u_int32_t status, ahc_search_action action);
+static void ahc_abort_ccb(struct ahc_softc *ahc, struct cam_sim *sim,
+ union ccb *ccb);
static int ahc_reset_channel(struct ahc_softc *ahc, char channel,
int initiate_reset);
static int ahc_abort_scbs(struct ahc_softc *ahc, int target,
@@ -2807,6 +2809,7 @@ ahc_init(struct ahc_softc *ahc)
int i;
int term;
u_int scsi_conf;
+ u_int scsiseq_template;
#ifdef AHC_PRINT_SRAM
printf("Scratch Ram:");
@@ -2939,13 +2942,9 @@ ahc_init(struct ahc_softc *ahc)
ahc_outb(ahc, SIMODE1, ENSELTIMO|ENSCSIRST|ENSCSIPERR);
ahc_outb(ahc, SXFRCTL0, DFON|SPIOEN);
- if (scsi_conf & RESET_SCSI) {
- /* Reset the bus */
- if (bootverbose)
- printf("%s: Resetting Channel B\n",
- ahc_name(ahc));
- ahc_reset_current_bus(ahc);
- }
+ if ((scsi_conf & RESET_SCSI) != 0
+ && (ahc->flags & AHC_INITIATORMODE) != 0)
+ ahc->flags |= AHC_RESET_BUS_B;
/* Select Channel A */
ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) & ~SELBUSB);
@@ -2973,14 +2972,9 @@ ahc_init(struct ahc_softc *ahc)
ahc_name(ahc));
}
- if (scsi_conf & RESET_SCSI) {
- /* Reset the bus */
- if (bootverbose)
- printf("%s: Resetting Channel %c\n", ahc_name(ahc),
- ahc->channel);
-
- ahc_reset_current_bus(ahc);
- }
+ if ((scsi_conf & RESET_SCSI) != 0
+ && (ahc->flags & AHC_INITIATORMODE) != 0)
+ ahc->flags |= AHC_RESET_BUS_A;
/*
* Look at the information that board initialization or
@@ -3216,6 +3210,16 @@ ahc_init(struct ahc_softc *ahc)
ahc_outb(ahc, MSG_OUT, MSG_NOOP);
/*
+ * Setup the allowed SCSI Sequences based on operational mode.
+ * If we are a target, we'll enalbe select in operations once
+ * we've had a lun enabled.
+ */
+ scsiseq_template = ENSELO|ENAUTOATNO|ENAUTOATNP;
+ if ((ahc->flags & AHC_INITIATORMODE) != 0)
+ scsiseq_template |= ENRSELI;
+ ahc_outb(ahc, SCSISEQ_TEMPLATE, scsiseq_template);
+
+ /*
* Load the Sequencer program and Enable the adapter
* in "fast" mode.
*/
@@ -3460,6 +3464,8 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
target = ccb->ccb_h.target_id;
lun = ccb->ccb_h.target_lun;
if (cel->enable != 0) {
+ u_int scsiseq;
+
/* Are we already enabled?? */
if (lstate != NULL) {
ccb->ccb_h.status = CAM_LUN_ALRDY_ENA;
@@ -3503,41 +3509,122 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
SLIST_INIT(&lstate->accept_tios);
SLIST_INIT(&lstate->immed_notifies);
tstate->enabled_luns[lun] = lstate;
+ pause_sequencer(ahc);
if ((ahc->features & AHC_MULTI_TID) != 0) {
u_int16_t targid_mask;
- pause_sequencer(ahc);
targid_mask = ahc_inb(ahc, TARGID)
| (ahc_inb(ahc, TARGID + 1) << 8);
targid_mask |= (0x01 << target);
ahc_outb(ahc, TARGID, targid_mask);
ahc_outb(ahc, TARGID+1, (targid_mask >> 8));
- unpause_sequencer(ahc, /*always?*/FALSE);
}
+ /* Allow select-in operations */
+ scsiseq = ahc_inb(ahc, SCSISEQ_TEMPLATE);
+ scsiseq |= ENSELI;
+ ahc_outb(ahc, SCSISEQ_TEMPLATE, scsiseq);
+ scsiseq = ahc_inb(ahc, SCSISEQ);
+ scsiseq |= ENSELI;
+ ahc_outb(ahc, SCSISEQ, scsiseq);
+ unpause_sequencer(ahc, /*always?*/FALSE);
ccb->ccb_h.status = CAM_REQ_CMP;
xpt_print_path(ccb->ccb_h.path);
printf("Lun now enabled for target mode\n");
xpt_done(ccb);
break;
} else {
+ struct ccb_hdr *elm;
+
/* XXX Fully Implement Disable */
if (lstate == NULL) {
ccb->ccb_h.status = CAM_LUN_INVALID;
xpt_done(ccb);
break;
}
+
ccb->ccb_h.status = CAM_REQ_CMP;
+ LIST_FOREACH(elm, &ahc->pending_ccbs, sim_links.le) {
+ if (elm->func_code == XPT_CONT_TARGET_IO
+ && !xpt_path_comp(elm->path, ccb->ccb_h.path)){
+ ccb->ccb_h.status = CAM_REQ_INVALID;
+ break;
+ }
+ }
+
+ if (SLIST_FIRST(&lstate->accept_tios) != NULL)
+ ccb->ccb_h.status = CAM_REQ_INVALID;
+
+ if (SLIST_FIRST(&lstate->immed_notifies) != NULL)
+ ccb->ccb_h.status = CAM_REQ_INVALID;
+
+ if (ccb->ccb_h.status == CAM_REQ_CMP) {
+ int i, empty;
+
+ free(lstate, M_DEVBUF);
+ tstate->enabled_luns[lun] = NULL;
+
+ /* Can we clean up the target too? */
+ for (empty = 1, i = 0; i < 8; i++)
+ if (tstate->enabled_luns[i] != NULL) {
+ empty = 0;
+ break;
+ }
+ if (empty) {
+ printf("Target Empty\n");
+ free(tstate, M_DEVBUF);
+ ahc->enabled_targets[target] = NULL;
+ pause_sequencer(ahc);
+ if (ahc->features & AHC_MULTI_TID) {
+ u_int16_t targid_mask;
+
+ targid_mask =
+ ahc_inb(ahc, TARGID)
+ | (ahc_inb(ahc, TARGID + 1)
+ << 8);
+
+ targid_mask &= (0x01 << target);
+ ahc_outb(ahc, TARGID,
+ targid_mask);
+ ahc_outb(ahc, TARGID+1,
+ (targid_mask >> 8));
+ }
+
+ for (empty = 1, i = 0; i < 16; i++)
+ if (ahc->enabled_targets[i]
+ != NULL) {
+ empty = 0;
+ break;
+ }
+ if (empty) {
+ /* Disallow select-in */
+ u_int scsiseq;
+
+ printf("No targets\n");
+ scsiseq =
+ ahc_inb(ahc,
+ SCSISEQ_TEMPLATE);
+ scsiseq &= ~ENSELI;
+ ahc_outb(ahc, SCSISEQ_TEMPLATE,
+ scsiseq);
+ scsiseq = ahc_inb(ahc, SCSISEQ);
+ scsiseq &= ~ENSELI;
+ ahc_outb(ahc, SCSISEQ, scsiseq);
+ }
+ unpause_sequencer(ahc,
+ /*always?*/FALSE);
+ }
+ }
xpt_done(ccb);
break;
}
break;
}
case XPT_ABORT: /* Abort the specified CCB */
- /* XXX Implement */
- ccb->ccb_h.status = CAM_REQ_INVALID;
- xpt_done(ccb);
+ {
+ ahc_abort_ccb(ahc, sim, ccb);
break;
+ }
case XPT_SET_TRAN_SETTINGS:
{
struct ahc_devinfo devinfo;
@@ -3745,14 +3832,19 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
cpi->target_sprt = 0;
}
cpi->hba_misc = (ahc->flags & AHC_INITIATORMODE)
- ? 0 : PIM_NOINITIATOR|PIM_NOBUSRESET;
+ ? 0 : PIM_NOINITIATOR;
cpi->hba_eng_cnt = 0;
cpi->max_target = (ahc->features & AHC_WIDE) ? 15 : 7;
cpi->max_lun = 7;
- if (SIM_IS_SCSIBUS_B(ahc, sim))
+ if (SIM_IS_SCSIBUS_B(ahc, sim)) {
cpi->initiator_id = ahc->our_id_b;
- else
+ if ((ahc->flags & AHC_RESET_BUS_B) == 0)
+ cpi->hba_misc |= PIM_NOBUSRESET;
+ } else {
cpi->initiator_id = ahc->our_id;
+ if ((ahc->flags & AHC_RESET_BUS_A) == 0)
+ cpi->hba_misc |= PIM_NOBUSRESET;
+ }
cpi->bus_id = cam_sim_bus(sim);
strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
strncpy(cpi->hba_vid, "Adaptec", HBA_IDLEN);
@@ -4448,15 +4540,14 @@ ahc_timeout(void *arg)
break;
}
- printf(", SCSISIGI == 0x%x\n", ahc_inb(ahc, SCSISIGI));
-
- printf("SEQADDR == 0x%x\n", ahc_inb(ahc, SEQADDR0)
- | (ahc_inb(ahc, SEQADDR1) << 8));
+ printf(", SEQADDR == 0x%x\n",
+ ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8));
+#if 0
+ printf(", SCSISIGI == 0x%x\n", ahc_inb(ahc, SCSISIGI));
printf("SIMODE1 = 0x%x\n", ahc_inb(ahc, SIMODE1));
printf("INTSTAT = 0x%x\n", ahc_inb(ahc, INTSTAT));
printf("SSTAT1 == 0x%x\n", ahc_inb(ahc, SSTAT1));
-#if 0
printf("SCSIRATE == 0x%x\n", ahc_inb(ahc, SCSIRATE));
printf("CCSCBCTL == 0x%x\n", ahc_inb(ahc, CCSCBCTL));
printf("CCSCBCNT == 0x%x\n", ahc_inb(ahc, CCSCBCNT));
@@ -4464,7 +4555,6 @@ ahc_timeout(void *arg)
printf("DFSTATUS == 0x%x\n", ahc_inb(ahc, DFSTATUS));
printf("CCHCNT == 0x%x\n", ahc_inb(ahc, CCHCNT));
#endif
- /* Decide our course of action */
if (scb->flags & SCB_DEVICE_RESET) {
/*
* Been down this road before.
@@ -4477,18 +4567,26 @@ bus_reset:
"%d SCBs aborted\n", ahc_name(ahc), channel, found);
} else {
/*
- * Send a Bus Device Reset message:
- * The target that is holding up the bus may not
+ * If we are a target, transition to bus free and report
+ * the timeout.
+ *
+ * The target/initiator that is holding up the bus may not
* be the same as the one that triggered this timeout
* (different commands have different timeout lengths).
- * Our strategy here is to queue a BDR message
- * to the timed out target if the bus is idle.
- * Otherwise, if we have an active target we stuff the
- * message buffer with a BDR message and assert ATN
- * in the hopes that the target will let go of the bus
- * and go to the mesgout phase. If this fails, we'll
- * get another timeout 2 seconds later which will attempt
- * a bus reset.
+ * If the bus is idle and we are actiing as the initiator
+ * for this request, queue a BDR message to the timed out
+ * target. Otherwise, if the timed out transaction is
+ * active:
+ * Initiator transaction:
+ * Stuff the message buffer with a BDR message and assert
+ * ATN in the hopes that the target will let go of the bus
+ * and go to the mesgout phase. If this fails, we'll
+ * get another timeout 2 seconds later which will attempt
+ * a bus reset.
+ *
+ * Target transaction:
+ * Transition to BUS FREE and report the error.
+ * It's good to be the target!
*/
u_int active_scb_index;
@@ -4519,7 +4617,25 @@ bus_reset:
(newtimeout * hz) / 1000);
splx(s);
return;
+ }
+
+ /* It's us */
+ if ((scb->hscb->control & TARGET_SCB) != 0) {
+
+ /*
+ * Send back any queued up transactions
+ * and properly record the error condition.
+ */
+ ahc_freeze_devq(ahc, scb->ccb->ccb_h.path);
+ ahc_set_ccb_status(scb->ccb, CAM_CMD_TIMEOUT);
+ ahc_freeze_ccb(scb->ccb);
+ ahc_done(ahc, scb);
+
+ /* Will clear us from the bus */
+ restart_sequencer(ahc);
+ return;
}
+
ahc_set_recoveryscb(ahc, active_scb);
ahc_outb(ahc, MSG_OUT, MSG_BUS_DEV_RESET);
ahc_outb(ahc, SCSISIGO, bus_state|ATNO);
@@ -4532,6 +4648,15 @@ bus_reset:
} else {
int disconnected;
+ if (bus_state != P_BUSFREE
+ && (ahc_inb(ahc, SSTAT0) & TARGET) != 0) {
+ /* Hung target selection. Goto busfree */
+ printf("%s: Hung target selection\n",
+ ahc_name(ahc));
+ restart_sequencer(ahc);
+ return;
+ }
+
if (ahc_search_qinfifo(ahc, target, channel, lun,
scb->hscb->tag, /*status*/0,
SEARCH_COUNT) > 0) {
@@ -4658,6 +4783,84 @@ ahc_search_qinfifo(struct ahc_softc *ahc, int target, char channel,
}
+static void
+ahc_abort_ccb(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb)
+{
+ union ccb *abort_ccb;
+
+ abort_ccb = ccb->cab.abort_ccb;
+ switch (abort_ccb->ccb_h.func_code) {
+ case XPT_ACCEPT_TARGET_IO:
+ case XPT_IMMED_NOTIFY:
+ case XPT_CONT_TARGET_IO:
+ {
+ struct tmode_tstate *tstate;
+ struct tmode_lstate *lstate;
+ struct ccb_hdr_slist *list;
+ cam_status status;
+
+ status = ahc_find_tmode_devs(ahc, sim, abort_ccb, &tstate,
+ &lstate, TRUE);
+
+ if (status != CAM_REQ_CMP) {
+ ccb->ccb_h.status = status;
+ break;
+ }
+
+ if (abort_ccb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO)
+ list = &lstate->accept_tios;
+ else if (abort_ccb->ccb_h.func_code == XPT_IMMED_NOTIFY)
+ list = &lstate->immed_notifies;
+ else
+ list = NULL;
+
+ if (list != NULL) {
+ struct ccb_hdr *curelm;
+ int found;
+
+ curelm = SLIST_FIRST(list);
+ found = 0;
+ if (curelm == &abort_ccb->ccb_h) {
+ found = 1;
+ SLIST_REMOVE_HEAD(list, sim_links.sle);
+ } else {
+ while(curelm != NULL) {
+ struct ccb_hdr *nextelm;
+
+ nextelm =
+ SLIST_NEXT(curelm, sim_links.sle);
+
+ if (nextelm == &abort_ccb->ccb_h) {
+ found = 1;
+ SLIST_NEXT(curelm,
+ sim_links.sle) =
+ SLIST_NEXT(nextelm,
+ sim_links.sle);
+ break;
+ }
+ curelm = nextelm;
+ }
+ }
+
+ if (found)
+ abort_ccb->ccb_h.status = CAM_REQ_ABORTED;
+ else
+ ccb->ccb_h.status = CAM_PATH_INVALID;
+ break;
+ }
+ /* FALLTHROUGH */
+ }
+ case XPT_SCSI_IO:
+ /* XXX Fully implement the hard ones */
+ ccb->ccb_h.status = CAM_UA_ABORT;
+ break;
+ default:
+ ccb->ccb_h.status = CAM_REQ_INVALID;
+ break;
+ }
+ xpt_done(ccb);
+}
+
/*
* Abort all SCBs that match the given description (target/channel/lun/tag),
* setting their status to the passed in status if the status has not already
diff --git a/sys/dev/aic7xxx/aic7xxx.h b/sys/dev/aic7xxx/aic7xxx.h
index b2c240f..bfe74a0 100644
--- a/sys/dev/aic7xxx/aic7xxx.h
+++ b/sys/dev/aic7xxx/aic7xxx.h
@@ -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.2 1998/11/23 01:33:47 gibbs Exp $
+ * $Id: aic7xxx.h,v 1.3 1998/12/10 04:14:50 gibbs Exp $
*/
#ifndef _AIC7XXX_H_
@@ -117,9 +117,11 @@ typedef enum {
AHC_AIC7860_FE = AHC_ULTRA|AHC_SPIOCAP,
AHC_AIC7870_FE = AHC_FENONE,
AHC_AIC7880_FE = AHC_ULTRA,
- AHC_AIC7890_FE = AHC_MORE_SRAM|AHC_CMD_CHAN|AHC_ULTRA2|AHC_QUEUE_REGS|AHC_SG_PRELOAD|AHC_MULTI_TID,
+ AHC_AIC7890_FE = AHC_MORE_SRAM|AHC_CMD_CHAN|AHC_ULTRA2|AHC_QUEUE_REGS
+ |AHC_SG_PRELOAD|AHC_MULTI_TID,
AHC_AIC7895_FE = AHC_MORE_SRAM|AHC_CMD_CHAN|AHC_ULTRA,
- AHC_AIC7896_FE = AHC_MORE_SRAM|AHC_CMD_CHAN|AHC_ULTRA2|AHC_QUEUE_REGS|AHC_SG_PRELOAD|AHC_MULTI_TID,
+ AHC_AIC7896_FE = AHC_MORE_SRAM|AHC_CMD_CHAN|AHC_ULTRA2|AHC_QUEUE_REGS
+ |AHC_SG_PRELOAD|AHC_MULTI_TID,
} ahc_feature;
typedef enum {
@@ -139,6 +141,8 @@ typedef enum {
AHC_INDIRECT_PAGING = 0x008,
AHC_SHARED_SRAM = 0x010,
AHC_LARGE_SEEPROM = 0x020,/* Uses C56_66 not C46 */
+ AHC_RESET_BUS_A = 0x040,
+ AHC_RESET_BUS_B = 0x080,
AHC_EXTENDED_TRANS_A = 0x100,
AHC_EXTENDED_TRANS_B = 0x200,
AHC_TERM_ENB_A = 0x400,
@@ -269,8 +273,8 @@ struct target_cmd {
* and immediate notify CCB pools.
*/
struct tmode_lstate {
- SLIST_HEAD(, ccb_hdr) accept_tios;
- SLIST_HEAD(, ccb_hdr) immed_notifies;
+ struct ccb_hdr_slist accept_tios;
+ struct ccb_hdr_slist immed_notifies;
};
/*
diff --git a/sys/dev/aic7xxx/aic7xxx.reg b/sys/dev/aic7xxx/aic7xxx.reg
index bcb96c2..f6138f6 100644
--- a/sys/dev/aic7xxx/aic7xxx.reg
+++ b/sys/dev/aic7xxx/aic7xxx.reg
@@ -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.8 1998/11/23 01:33:47 gibbs Exp $
+ * $Id: aic7xxx.reg,v 1.9 1998/12/10 04:14:50 gibbs Exp $
*/
/*
@@ -1316,6 +1316,21 @@ scratch_ram {
}
/*
+ * Sequences the kernel driver has okayed for us. This allows
+ * the driver to do things like prevent initiator or target
+ * operations.
+ */
+ SCSISEQ_TEMPLATE {
+ size 1
+ bit ENSELO 0x40
+ bit ENSELI 0x20
+ bit ENRSELI 0x10
+ bit ENAUTOATNO 0x08
+ bit ENAUTOATNI 0x04
+ bit ENAUTOATNP 0x02
+ }
+
+ /*
* These are reserved registers in the card's scratch ram. Some of
* the values are specified in the AHA2742 technical reference manual
* and are initialized by the BIOS at boot time.
diff --git a/sys/dev/aic7xxx/aic7xxx.seq b/sys/dev/aic7xxx/aic7xxx.seq
index 007a3af..c0651f6 100644
--- a/sys/dev/aic7xxx/aic7xxx.seq
+++ b/sys/dev/aic7xxx/aic7xxx.seq
@@ -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.80 1998/11/23 01:33:47 gibbs Exp $
+ * $Id: aic7xxx.seq,v 1.81 1998/12/10 04:14:50 gibbs Exp $
*/
#include <dev/aic7xxx/aic7xxx.reg>
@@ -60,11 +60,7 @@ reset:
clr SCSISIGO; /* De-assert BSY */
and SXFRCTL1, ~BITBUCKET;
/* Always allow reselection */
- if ((ahc->flags & AHC_TARGETMODE) != 0) {
- mvi SCSISEQ, ENSELI|ENRSELI|ENAUTOATNP;
- } else {
- mvi SCSISEQ, ENRSELI|ENAUTOATNP;
- }
+ and SCSISEQ, ENSELI|ENRSELI|ENAUTOATNP, SCSISEQ_TEMPLATE;
if ((ahc->features & AHC_CMD_CHAN) != 0) {
/* Ensure that no DMA operations are in progress */
@@ -182,13 +178,12 @@ initialize_scsiid:
and SCSIID, OID; /* Clear old target */
or SCSIID, A;
}
+ mov SINDEX, SCSISEQ_TEMPLATE;
if ((ahc->flags & AHC_TARGETMODE) != 0) {
- and SINDEX, TARGET_SCB, SCB_CONTROL;
- or SCSISEQ, ENSELO|ENAUTOATNO|ENSELI
- |ENRSELI|ENAUTOATNP, SINDEX ret ;
- } else if ((ahc->flags & AHC_INITIATORMODE) != 0) {
- mvi SCSISEQ, ENSELO|ENAUTOATNO|ENRSELI|ENAUTOATNP ret;
+ test SCB_CONTROL, TARGET_SCB jz . + 2;
+ or SINDEX, TEMODE;
}
+ mov SCSISEQ, SINDEX ret;
/*
* Initialize transfer settings and clear the SCSI channel.
@@ -435,11 +430,7 @@ initiator_reselect:
*/
select_out:
/* Turn off the selection hardware */
- if ((ahc->flags & AHC_TARGETMODE) != 0) {
- mvi SCSISEQ, ENSELI|ENRSELI|ENAUTOATNP;
- } else if ((ahc->flags & AHC_INITIATORMODE) != 0) {
- mvi SCSISEQ, ENRSELI|ENAUTOATNP;
- }
+ and SCSISEQ, ENSELI|ENRSELI|ENAUTOATNP, SCSISEQ_TEMPLATE;
mvi CLRSINT0, CLRSELDO;
mov SCBPTR, WAITING_SCBH;
mov WAITING_SCBH,SCB_NEXT;
@@ -509,6 +500,8 @@ target_mesgout_pending_msg:
target_disconnect:
mvi P_MESGIN|BSYO call change_phase;
+ test SEQ_FLAGS, DPHASE jz . + 2;
+ mvi MSG_SAVEDATAPOINTER call target_outb;
mvi MSG_DISCONNECT call target_outb;
target_busfree:
OpenPOWER on IntegriCloud