summaryrefslogtreecommitdiff
path: root/sys/dev/ic/siop.c
diff options
context:
space:
mode:
authorKenneth R Westerback <krw@cvs.openbsd.org>2005-10-10 16:27:25 +0000
committerKenneth R Westerback <krw@cvs.openbsd.org>2005-10-10 16:27:25 +0000
commit4d7328af0d8545d1c5e98867adc169655e14f971 (patch)
treef59e1da363bf6e99c31ec1ea3170ba585eecbc09 /sys/dev/ic/siop.c
parent77c0482e5a60827b70e8e722468bd328f0b82193 (diff)
Add handling for IGNORE WIDE RESIDUE messages. Actually calculate
resid instead of assuming it is always 0. From bouyer via NetBSD. Note we are now sync'd with the latest (1.78 siop.c, 1.37 siop_common.c) NetBSD code. Tested by various people over the last year+. Didn't solve any of their problems but didn't cause any regression either.
Diffstat (limited to 'sys/dev/ic/siop.c')
-rw-r--r--sys/dev/ic/siop.c93
1 files changed, 58 insertions, 35 deletions
diff --git a/sys/dev/ic/siop.c b/sys/dev/ic/siop.c
index aa8f81b00ea..15b14e60696 100644
--- a/sys/dev/ic/siop.c
+++ b/sys/dev/ic/siop.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: siop.c,v 1.39 2005/10/08 19:48:42 krw Exp $ */
-/* $NetBSD: siop.c,v 1.65 2002/11/08 22:04:41 bouyer Exp $ */
+/* $OpenBSD: siop.c,v 1.40 2005/10/10 16:27:23 krw Exp $ */
+/* $NetBSD: siop.c,v 1.78 2005/02/27 00:27:02 perry Exp $ */
/*
* Copyright (c) 2000 Manuel Bouyer.
@@ -343,7 +343,7 @@ siop_intr(v)
struct siop_cmd *siop_cmd;
struct siop_lun *siop_lun;
struct scsi_xfer *xs;
- int istat, sist, sstat1, dstat;
+ int istat, sist, sstat1, dstat = 0;
u_int32_t irqcode;
int need_reset = 0;
int offset, target, lun, tag;
@@ -518,31 +518,31 @@ siop_intr(v)
/*
* previous phase may be aborted for any reason
* ( for example, the target has less data to
- * transfer than requested). Just go to status
- * and the command should terminate.
+ * transfer than requested). Compute resid and
+ * just go to status, the command should
+ * terminate.
*/
INCSTAT(siop_stat_intr_shortxfer);
- if ((dstat & DSTAT_DFE) == 0)
+ if (scratcha0 & A_flag_data)
+ siop_ma(&siop_cmd->cmd_c);
+ else if ((dstat & DSTAT_DFE) == 0)
siop_clearfifo(&sc->sc_c);
- /* no table to flush here */
CALL_SCRIPT(Ent_status);
return 1;
case SSTAT1_PHASE_MSGIN:
- /*
- * target may be ready to disconnect
- * Save data pointers just in case.
- */
+ /*
+ * target may be ready to disconnect
+ * Compute resid which would be used later
+ * if a save data pointer is needed.
+ */
INCSTAT(siop_stat_intr_xferdisc);
if (scratcha0 & A_flag_data)
- siop_sdp(&siop_cmd->cmd_c);
+ siop_ma(&siop_cmd->cmd_c);
else if ((dstat & DSTAT_DFE) == 0)
siop_clearfifo(&sc->sc_c);
bus_space_write_1(sc->sc_c.sc_rt,
sc->sc_c.sc_rh, SIOP_SCRATCHA,
scratcha0 & ~A_flag_data);
- siop_table_sync(siop_cmd,
- BUS_DMASYNC_PREREAD |
- BUS_DMASYNC_PREWRITE);
CALL_SCRIPT(Ent_msgin);
return 1;
}
@@ -816,6 +816,15 @@ scintr:
CALL_SCRIPT(Ent_msgin_ack);
return 1;
}
+ if (msgin == MSG_IGN_WIDE_RESIDUE) {
+ /* use the extmsgdata table to get the second byte */
+ siop_cmd->cmd_tables->t_extmsgdata.count =
+ htole32(1);
+ siop_table_sync(siop_cmd,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+ CALL_SCRIPT(Ent_get_extmsgdata);
+ return 1;
+ }
if (xs)
sc_print_addr(xs->sc_link);
else
@@ -859,6 +868,29 @@ scintr:
printf("\n");
}
#endif
+ if (siop_cmd->cmd_tables->msg_in[0] ==
+ MSG_IGN_WIDE_RESIDUE) {
+ /* we got the second byte of MSG_IGN_WIDE_RESIDUE */
+ if (siop_cmd->cmd_tables->msg_in[3] != 1)
+ printf("MSG_IGN_WIDE_RESIDUE: "
+ "bad len %d\n",
+ siop_cmd->cmd_tables->msg_in[3]);
+ switch (siop_iwr(&siop_cmd->cmd_c)) {
+ case SIOP_NEG_MSGOUT:
+ siop_table_sync(siop_cmd,
+ BUS_DMASYNC_PREREAD |
+ BUS_DMASYNC_PREWRITE);
+ CALL_SCRIPT(Ent_send_msgout);
+ return(1);
+ case SIOP_NEG_ACK:
+ CALL_SCRIPT(Ent_msgin_ack);
+ return(1);
+ default:
+ panic("invalid retval from "
+ "siop_iwr()");
+ }
+ return(1);
+ }
if (siop_cmd->cmd_tables->msg_in[2] == MSG_EXT_WDTR) {
switch (siop_wdtr_neg(&siop_cmd->cmd_c)) {
case SIOP_NEG_MSGOUT:
@@ -936,25 +968,9 @@ scintr:
#ifdef SIOP_DEBUG_DR
printf("disconnect offset %d\n", offset);
#endif
- if (offset > SIOP_NSG) {
- printf("%s: bad offset for disconnect (%d)\n",
- sc->sc_c.sc_dev.dv_xname, offset);
- goto reset;
- }
- /*
- * offset == SIOP_NSG may be a valid condition if
- * we get a sdp when the xfer is done.
- * Don't call bcopy in this case.
- */
- if (offset < SIOP_NSG) {
- bcopy(&siop_cmd->cmd_tables->data[offset],
- &siop_cmd->cmd_tables->data[0],
- (SIOP_NSG - offset) * sizeof(scr_table_t));
- siop_table_sync(siop_cmd,
- BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
- }
- /* check if we can put some command in scheduler */
- siop_start(sc);
+ siop_sdp(&siop_cmd->cmd_c, offset);
+ siop_table_sync(siop_cmd,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
CALL_SCRIPT(Ent_script_sched);
return 1;
case A_int_resfail:
@@ -981,6 +997,10 @@ scintr:
letoh32(siop_cmd->cmd_tables->status));
#endif
INCSTAT(siop_stat_intr_done);
+ /* update resid. */
+ offset = bus_space_read_1(sc->sc_c.sc_rt,
+ sc->sc_c.sc_rh, SIOP_SCRATCHA + 1);
+ siop_update_resid(&siop_cmd->cmd_c, offset);
if (siop_cmd->cmd_c.status == CMDST_SENSE_ACTIVE)
siop_cmd->cmd_c.status = CMDST_SENSE_DONE;
else
@@ -1145,7 +1165,10 @@ out:
xs->flags |= ITSDONE;
siop_cmd->cmd_c.status = CMDST_FREE;
TAILQ_INSERT_TAIL(&sc->free_list, siop_cmd, next);
- xs->resid = 0;
+#if 0
+ if (xs->resid != 0)
+ printf("resid %d datalen %d\n", xs->resid, xs->datalen);
+#endif
scsi_done(xs);
}