summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgibbs <gibbs@FreeBSD.org>1998-12-17 00:06:52 +0000
committergibbs <gibbs@FreeBSD.org>1998-12-17 00:06:52 +0000
commitdc4a57e23b4d77723f188305a262ca30d0aedda5 (patch)
treec2751d5e9b545b57798e8fd079d2a8d7697d93ca
parent11a6f2ec08fc9292d556ca429d1f87f553125a89 (diff)
downloadFreeBSD-src-dc4a57e23b4d77723f188305a262ca30d0aedda5.zip
FreeBSD-src-dc4a57e23b4d77723f188305a262ca30d0aedda5.tar.gz
Fix a few problems with handling rejected transfer negotiation messages.
Use the host message loop for any unknown message types instead of performing a reject message in the sequencer. Pass reject messages to the host message loop too which frees up a sequencer interrupt type slot. Default to issuing a bus reset if initiator mode is enabled. It seems that the reset scsi bus bit is not defined in the same location for all aic78xx BIOSes, so attempting to honor this setting will have to wait until I get more information on how to detect it. Nuke some unused variables.
-rw-r--r--sys/dev/aic7xxx/aic7xxx.c112
-rw-r--r--sys/dev/aic7xxx/aic7xxx.reg3
-rw-r--r--sys/dev/aic7xxx/aic7xxx.seq48
3 files changed, 72 insertions, 91 deletions
diff --git a/sys/dev/aic7xxx/aic7xxx.c b/sys/dev/aic7xxx/aic7xxx.c
index f4cc6cc..7b22345 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.12 1998/12/10 04:14:49 gibbs Exp $
+ * $Id: aic7xxx.c,v 1.13 1998/12/15 08:22:40 gibbs Exp $
*/
/*
* A few notes on features of the driver.
@@ -188,9 +188,10 @@ static int ahc_debug = AHC_DEBUG;
void ahc_pci_intr(struct ahc_softc *ahc);
#endif
+#if UNUSED
static void ahc_dump_targcmd(struct target_cmd *cmd);
+#endif
static void ahc_shutdown(int howto, void *arg);
-static void ahcminphys(struct buf *bp);
static cam_status
ahc_find_tmode_devs(struct ahc_softc *ahc,
struct cam_sim *sim, union ccb *ccb,
@@ -229,7 +230,7 @@ static void ahc_setup_initiator_msgout(struct ahc_softc *ahc,
struct scb *scb);
static void ahc_setup_target_msgin(struct ahc_softc *ahc,
struct ahc_devinfo *devinfo);
-static void ahc_handle_msg_reject(struct ahc_softc *ahc,
+static int ahc_handle_msg_reject(struct ahc_softc *ahc,
struct ahc_devinfo *devinfo);
static void ahc_clear_msg_state(struct ahc_softc *ahc);
static void ahc_handle_message_phase(struct ahc_softc *ahc,
@@ -755,7 +756,6 @@ ahc_create_path(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
struct cam_path **path)
{
path_id_t path_id;
- int error;
if (devinfo->channel == 'B')
path_id = cam_sim_path(ahc->sim_b);
@@ -1251,6 +1251,7 @@ ahc_handle_target_cmd(struct ahc_softc *ahc, struct target_cmd *cmd)
printf("No ATIOs for incoming command\n");
return;
}
+ SLIST_REMOVE_HEAD(&lstate->accept_tios, sim_links.sle);
/*
* Package it up and send it off to
@@ -1291,7 +1292,6 @@ ahc_handle_target_cmd(struct ahc_softc *ahc, struct target_cmd *cmd)
}
bcopy(byte, atio->cdb_io.cdb_bytes, atio->cdb_len);
- SLIST_REMOVE_HEAD(&lstate->accept_tios, sim_links.sle);
atio->ccb_h.status |= CAM_CDB_RECVD;
if ((cmd->identify & MSG_IDENTIFY_DISCFLAG) == 0) {
@@ -1378,11 +1378,6 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
devinfo.target);
}
break;
- case REJECT_MSG:
- {
- ahc_handle_msg_reject(ahc, &devinfo);
- break;
- }
case BAD_STATUS:
{
u_int scb_index;
@@ -1797,7 +1792,6 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
lastphase, ahc_inb(ahc, SEQADDR0)
| (ahc_inb(ahc, SEQADDR1) << 8));
}
- ahc_outb(ahc, MSG_OUT, MSG_NOOP);
ahc_clear_msg_state(ahc);
ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) & ~ENBUSFREE);
ahc_outb(ahc, CLRSINT1, CLRBUSFREE);
@@ -1822,11 +1816,6 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
"valid during SELTO scb(%d, %d)\n",
ahc_name(ahc), scbptr, scb_index);
} else {
- /*
- * Clear any pending messages for the timed out
- * target.
- */
- ahc_outb(ahc, MSG_OUT, MSG_NOOP);
ahc_handle_devreset(ahc, SCB_TARGET(scb),
SCB_CHANNEL(scb), CAM_SEL_TIMEOUT,
/*ac_code*/0, "Selection Timeout",
@@ -1947,11 +1936,16 @@ ahc_build_transfer_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
if (dowide)
ahc_construct_wdtr(ahc, tinfo->goal.width);
else if (dosync) {
+ struct ahc_syncrate *rate;
u_int period;
+ u_int offset;
period = tinfo->goal.period;
- ahc_devlimited_syncrate(ahc, &period);
- ahc_construct_sdtr(ahc, period, tinfo->goal.offset);
+ rate = ahc_devlimited_syncrate(ahc, &period);
+ offset = tinfo->goal.offset;
+ ahc_validate_offset(ahc, rate, &offset,
+ tinfo->current.width);
+ ahc_construct_sdtr(ahc, period, offset);
} else {
panic("ahc_intr: AWAITING_MSG for negotiation, "
"but no negotiation needed\n");
@@ -2040,7 +2034,7 @@ ahc_setup_target_msgin(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
ahc->msg_type = MSG_TYPE_TARGET_MSGIN;
}
-static void
+static int
ahc_handle_msg_reject(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
{
/*
@@ -2052,6 +2046,7 @@ ahc_handle_msg_reject(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
struct scb *scb;
u_int scb_index;
u_int last_msg;
+ int response = 0;
scb_index = ahc_inb(ahc, SCB_TAG);
scb = ahc->scb_data->scbarray[scb_index];
@@ -2082,7 +2077,8 @@ ahc_handle_msg_reject(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
ahc->msgout_index = 0;
ahc->msgout_len = 0;
ahc_construct_sdtr(ahc, period, tinfo->goal.offset);
- ahc_outb(ahc, SCSISIGO, ahc_inb(ahc, SCSISIGO) | ATNO);
+ ahc->msgout_index = 0;
+ response = 1;
}
} else if (ahc_sent_msg(ahc, MSG_EXT_SDTR, /*full*/FALSE)) {
/* note asynch xfers and clear flag */
@@ -2134,6 +2130,7 @@ ahc_handle_msg_reject(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
ahc_name(ahc), devinfo->channel, devinfo->target,
last_msg);
}
+ return (response);
}
static void
@@ -2142,6 +2139,7 @@ ahc_clear_msg_state(struct ahc_softc *ahc)
ahc->msgout_len = 0;
ahc->msgin_index = 0;
ahc->msg_type = MSG_TYPE_NONE;
+ ahc_outb(ahc, MSG_OUT, MSG_NOOP);
}
static void
@@ -2171,14 +2169,13 @@ reswitch:
phasemis = bus_phase != P_MESGOUT;
if (phasemis) {
if (bus_phase == P_MESGIN) {
- u_int scsisigo;
-
/*
* Change gears and see if
* this messages is of interest to
* us or should be passed back to
* the sequencer.
*/
+ ahc_outb(ahc, CLRSINT1, CLRATNO);
ahc->send_msg_perror = FALSE;
ahc->msg_type = MSG_TYPE_INITIATOR_MSGIN;
ahc->msgin_index = 0;
@@ -2233,8 +2230,6 @@ reswitch:
&& (ahc->send_msg_perror == TRUE
|| (ahc->msgout_len != 0
&& ahc->msgout_index == 0))) {
- u_int scsisigo;
-
ahc->msg_type = MSG_TYPE_INITIATOR_MSGOUT;
goto reswitch;
}
@@ -2455,7 +2450,7 @@ ahc_parse_msg(struct ahc_softc *ahc, struct cam_path *path,
* extended message type.
*/
if (ahc->msgin_buf[0] == MSG_MESSAGE_REJECT) {
- ahc_handle_msg_reject(ahc, devinfo);
+ response = ahc_handle_msg_reject(ahc, devinfo);
done = TRUE;
} else if (ahc->msgin_buf[0] == MSG_NOOP) {
done = TRUE;
@@ -2469,7 +2464,6 @@ ahc_parse_msg(struct ahc_softc *ahc, struct cam_path *path,
u_int period;
u_int offset;
u_int saved_offset;
- u_int maxsync;
if (ahc->msgin_buf[1] != MSG_EXT_SDTR_LEN) {
reject = TRUE;
@@ -2542,6 +2536,11 @@ ahc_parse_msg(struct ahc_softc *ahc, struct cam_path *path,
if (ahc->msgin_index < (MSG_EXT_WDTR_LEN + 1))
break;
+ if (devinfo->role == ROLE_TARGET) {
+ reject = TRUE;
+ break;
+ }
+
bus_width = ahc->msgin_buf[3];
if (ahc_sent_msg(ahc, MSG_EXT_WDTR, /*full*/TRUE)) {
/*
@@ -2605,15 +2604,20 @@ ahc_parse_msg(struct ahc_softc *ahc, struct cam_path *path,
tinfo = &ahc->transinfo[devinfo->target_offset];
if (tinfo->goal.period) {
- u_int period;
+ struct ahc_syncrate *rate;
+ u_int period;
+ u_int offset;
/* Start the sync negotiation */
period = tinfo->goal.period;
- ahc_devlimited_syncrate(ahc, &period);
+ rate = ahc_devlimited_syncrate(ahc,
+ &period);
+ offset = tinfo->goal.offset;
+ ahc_validate_offset(ahc, rate, &offset,
+ tinfo->current.width);
ahc->msgout_index = 0;
ahc->msgout_len = 0;
- ahc_construct_sdtr(ahc, period,
- tinfo->goal.offset);
+ ahc_construct_sdtr(ahc, period, offset);
ahc->msgout_index = 0;
response = TRUE;
}
@@ -2942,9 +2946,14 @@ ahc_init(struct ahc_softc *ahc)
ahc_outb(ahc, SIMODE1, ENSELTIMO|ENSCSIRST|ENSCSIPERR);
ahc_outb(ahc, SXFRCTL0, DFON|SPIOEN);
+#if 0
if ((scsi_conf & RESET_SCSI) != 0
&& (ahc->flags & AHC_INITIATORMODE) != 0)
ahc->flags |= AHC_RESET_BUS_B;
+#else
+ if ((ahc->flags & AHC_INITIATORMODE) != 0)
+ ahc->flags |= AHC_RESET_BUS_B;
+#endif
/* Select Channel A */
ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) & ~SELBUSB);
@@ -2972,9 +2981,14 @@ ahc_init(struct ahc_softc *ahc)
ahc_name(ahc));
}
+#if 0
if ((scsi_conf & RESET_SCSI) != 0
&& (ahc->flags & AHC_INITIATORMODE) != 0)
ahc->flags |= AHC_RESET_BUS_A;
+#else
+ if ((ahc->flags & AHC_INITIATORMODE) != 0)
+ ahc->flags |= AHC_RESET_BUS_A;
+#endif
/*
* Look at the information that board initialization or
@@ -3235,21 +3249,6 @@ ahc_init(struct ahc_softc *ahc)
return (0);
}
-static void
-ahcminphys(struct buf *bp)
-{
-/*
- * Even though the card can transfer up to 16megs per command
- * we are limited by the number of segments in the dma segment
- * list that we can hold. The worst case is that all pages are
- * discontinuous physically, hense the "page per segment" limit
- * enforced here.
- */
- if (bp->b_bcount > ((AHC_NSEG - 1) * PAGE_SIZE)) {
- bp->b_bcount = ((AHC_NSEG - 1) * PAGE_SIZE);
- }
-}
-
static cam_status
ahc_find_tmode_devs(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb,
struct tmode_tstate **tstate, struct tmode_lstate **lstate,
@@ -3547,16 +3546,21 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
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)){
+ printf("CTIO pending\n");
ccb->ccb_h.status = CAM_REQ_INVALID;
break;
}
}
- if (SLIST_FIRST(&lstate->accept_tios) != NULL)
+ if (SLIST_FIRST(&lstate->accept_tios) != NULL) {
+ printf("ATIOs pending\n");
ccb->ccb_h.status = CAM_REQ_INVALID;
+ }
- if (SLIST_FIRST(&lstate->immed_notifies) != NULL)
+ if (SLIST_FIRST(&lstate->immed_notifies) != NULL) {
+ printf("INOTs pending\n");
ccb->ccb_h.status = CAM_REQ_INVALID;
+ }
if (ccb->ccb_h.status == CAM_REQ_CMP) {
int i, empty;
@@ -3688,17 +3692,13 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
else
maxsync = AHC_SYNCRATE_FAST;
- if ((cts->valid & CCB_TRANS_SYNC_OFFSET_VALID) != 0) {
- if (cts->sync_offset != 0)
- cts->sync_offset = ~0;
- } else {
+ if ((cts->valid & CCB_TRANS_SYNC_OFFSET_VALID) == 0)
cts->sync_offset = 0;
- }
syncrate = ahc_find_syncrate(ahc, &cts->sync_period,
maxsync);
ahc_validate_offset(ahc, syncrate, &cts->sync_offset,
- tinfo->goal.width);
+ MSG_EXT_WDTR_BUS_8_BIT);
/* We use a period of 0 to represent async */
if (cts->sync_offset == 0)
@@ -4844,8 +4844,10 @@ ahc_abort_ccb(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb)
if (found)
abort_ccb->ccb_h.status = CAM_REQ_ABORTED;
- else
+ else {
+ printf("Not found\n");
ccb->ccb_h.status = CAM_PATH_INVALID;
+ }
break;
}
/* FALLTHROUGH */
@@ -5366,6 +5368,7 @@ ahc_update_pending_syncrates(struct ahc_softc *ahc)
ahc_outb(ahc, SCBPTR, saved_scbptr);
}
+#if UNUSED
static void
ahc_dump_targcmd(struct target_cmd *cmd)
{
@@ -5391,6 +5394,7 @@ ahc_dump_targcmd(struct target_cmd *cmd)
}
}
}
+#endif
static void
ahc_shutdown(int howto, void *arg)
diff --git a/sys/dev/aic7xxx/aic7xxx.reg b/sys/dev/aic7xxx/aic7xxx.reg
index f6138f6..058bc8f 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.9 1998/12/10 04:14:50 gibbs Exp $
+ * $Id: aic7xxx.reg,v 1.10 1998/12/15 08:22:42 gibbs Exp $
*/
/*
@@ -676,7 +676,6 @@ register INTSTAT {
mask NO_IDENT 0x20|SEQINT /* no IDENTIFY after reconnect*/
mask NO_MATCH 0x30|SEQINT /* no cmd match for reconnect */
mask ABORT_REQUESTED 0x50|SEQINT /* Reconect of aborted SCB */
- mask REJECT_MSG 0x60|SEQINT /* Reject message received */
mask BAD_STATUS 0x70|SEQINT /* Bad status from target */
mask RESIDUAL 0x80|SEQINT /* Residual byte count != 0 */
mask HOST_MSG_LOOP 0xa0|SEQINT /*
diff --git a/sys/dev/aic7xxx/aic7xxx.seq b/sys/dev/aic7xxx/aic7xxx.seq
index c0651f6..504a876 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.81 1998/12/10 04:14:50 gibbs Exp $
+ * $Id: aic7xxx.seq,v 1.82 1998/12/15 08:22:42 gibbs Exp $
*/
#include <dev/aic7xxx/aic7xxx.reg>
@@ -1066,21 +1066,6 @@ p_mesgout_done:
jmp ITloop;
/*
- * Pushed message loop to allow the kernel to
- * RUN IT's own message state engine. To avoid an
- * extra nop instruction after signaling the kernel,
- * we perform the phase_lock before checking to see
- * if we should exit the loop and skip the phase_lock
- * in the ITloop. Performing back to back phase_locks
- * shouldn't hurt, but why do it twice...
- */
-host_message_loop:
- mvi INTSTAT, HOST_MSG_LOOP;
- call phase_lock;
- cmp RETURN_1, EXIT_MSG_LOOP je ITloop + 1;
- jmp host_message_loop;
-
-/*
* Message in phase. Bytes are read using Automatic PIO mode.
*/
p_mesgin:
@@ -1091,19 +1076,22 @@ p_mesgin:
cmp A,MSG_SAVEDATAPOINTER je mesgin_sdptrs;
cmp ALLZEROS,A je mesgin_complete;
cmp A,MSG_RESTOREPOINTERS je mesgin_rdptrs;
- cmp A,MSG_EXTENDED je host_message_loop;
- cmp A,MSG_MESSAGE_REJECT je mesgin_reject;
cmp A,MSG_NOOP je mesgin_done;
-rej_mesgin:
/*
- * We have no idea what this message in is, so we issue a message reject
- * and hope for the best. In any case, rejection should be a rare
- * occurrence - signal the driver when it happens.
+ * Pushed message loop to allow the kernel to
+ * RUN IT's own message state engine. To avoid an
+ * extra nop instruction after signaling the kernel,
+ * we perform the phase_lock before checking to see
+ * if we should exit the loop and skip the phase_lock
+ * in the ITloop. Performing back to back phase_locks
+ * shouldn't hurt, but why do it twice...
*/
- mvi INTSTAT,SEND_REJECT; /* let driver know */
-
- mvi MSG_MESSAGE_REJECT call mk_mesg;
+host_message_loop:
+ mvi INTSTAT, HOST_MSG_LOOP;
+ call phase_lock;
+ cmp RETURN_1, EXIT_MSG_LOOP je ITloop + 1;
+ jmp host_message_loop;
mesgin_done:
mov NONE,SCSIDATL; /*dummy read from latch to ACK*/
@@ -1314,16 +1302,6 @@ not_found:
jmp mesgin_done;
/*
- * Message reject? Let the kernel driver handle this. If we have an
- * outstanding WDTR or SDTR negotiation, assume that it's a response from
- * the target selecting 8bit or asynchronous transfer, otherwise just ignore
- * it since we have no clue what it pertains to.
- */
-mesgin_reject:
- mvi INTSTAT, REJECT_MSG;
- jmp mesgin_done;
-
-/*
* [ ADD MORE MESSAGE HANDLING HERE ]
*/
OpenPOWER on IntegriCloud