summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authormartin <martin@openbsd.org>2005-11-03 11:00:36 +0000
committermartin <martin@openbsd.org>2005-11-03 11:00:36 +0000
commit4ddf9cadb463dbf8706f75761482ddc1ab5a6937 (patch)
tree272e198f42cf438634c80078ffea05bfe6fab8d2 /sys
parentuse splvm() here instead of splimp(). in currently unused MULTIPROCESSOR code. (diff)
downloadwireguard-openbsd-4ddf9cadb463dbf8706f75761482ddc1ab5a6937.tar.xz
wireguard-openbsd-4ddf9cadb463dbf8706f75761482ddc1ab5a6937.zip
revert to 20051009 for now, need to investigate strange behaviour with
some controllers discussed with otto@ and henning@, first noted by miod@
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/ic/siop.c93
-rw-r--r--sys/dev/ic/siop_common.c177
-rw-r--r--sys/dev/ic/siopvar_common.h9
3 files changed, 54 insertions, 225 deletions
diff --git a/sys/dev/ic/siop.c b/sys/dev/ic/siop.c
index 15b14e60696..9bad2466ee6 100644
--- a/sys/dev/ic/siop.c
+++ b/sys/dev/ic/siop.c
@@ -1,5 +1,5 @@
-/* $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 $ */
+/* $OpenBSD: siop.c,v 1.41 2005/11/03 11:00:36 martin Exp $ */
+/* $NetBSD: siop.c,v 1.65 2002/11/08 22:04:41 bouyer 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 = 0;
+ int istat, sist, sstat1, dstat;
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). Compute resid and
- * just go to status, the command should
- * terminate.
+ * transfer than requested). Just go to status
+ * and the command should terminate.
*/
INCSTAT(siop_stat_intr_shortxfer);
- if (scratcha0 & A_flag_data)
- siop_ma(&siop_cmd->cmd_c);
- else if ((dstat & DSTAT_DFE) == 0)
+ 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
- * Compute resid which would be used later
- * if a save data pointer is needed.
- */
+ /*
+ * target may be ready to disconnect
+ * Save data pointers just in case.
+ */
INCSTAT(siop_stat_intr_xferdisc);
if (scratcha0 & A_flag_data)
- siop_ma(&siop_cmd->cmd_c);
+ siop_sdp(&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,15 +816,6 @@ 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
@@ -868,29 +859,6 @@ 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:
@@ -968,9 +936,25 @@ scintr:
#ifdef SIOP_DEBUG_DR
printf("disconnect offset %d\n", offset);
#endif
- siop_sdp(&siop_cmd->cmd_c, offset);
- siop_table_sync(siop_cmd,
- BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+ 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);
CALL_SCRIPT(Ent_script_sched);
return 1;
case A_int_resfail:
@@ -997,10 +981,6 @@ 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
@@ -1165,10 +1145,7 @@ out:
xs->flags |= ITSDONE;
siop_cmd->cmd_c.status = CMDST_FREE;
TAILQ_INSERT_TAIL(&sc->free_list, siop_cmd, next);
-#if 0
- if (xs->resid != 0)
- printf("resid %d datalen %d\n", xs->resid, xs->datalen);
-#endif
+ xs->resid = 0;
scsi_done(xs);
}
diff --git a/sys/dev/ic/siop_common.c b/sys/dev/ic/siop_common.c
index 4d51b36f05b..73a6dccb34f 100644
--- a/sys/dev/ic/siop_common.c
+++ b/sys/dev/ic/siop_common.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: siop_common.c,v 1.25 2005/10/31 19:02:06 miod Exp $ */
-/* $NetBSD: siop_common.c,v 1.37 2005/02/27 00:27:02 perry Exp $ */
+/* $OpenBSD: siop_common.c,v 1.26 2005/11/03 11:00:36 martin Exp $ */
+/* $NetBSD: siop_common.c,v 1.31 2002/09/27 15:37:18 provos Exp $ */
/*
* Copyright (c) 2000, 2002 Manuel Bouyer.
@@ -21,7 +21,7 @@
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
@@ -68,7 +68,7 @@ siop_common_attach(sc)
* Allocate DMA-safe memory for the script and map it.
*/
if ((sc->features & SF_CHIP_RAM) == 0) {
- error = bus_dmamem_alloc(sc->sc_dmat, PAGE_SIZE,
+ error = bus_dmamem_alloc(sc->sc_dmat, PAGE_SIZE,
PAGE_SIZE, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT);
if (error) {
printf("%s: unable to allocate script DMA memory, "
@@ -441,7 +441,7 @@ siop_ppr_neg(siop_cmd)
siop_target->period = 0;
goto reject;
}
-
+
if (offset > sc->maxoff || sync < sc->dt_minsync ||
sync > sc->dt_maxsync) {
printf("%s: ppr negotiation for target %d: "
@@ -714,21 +714,17 @@ siop_minphys(bp)
}
void
-siop_ma(siop_cmd)
+siop_sdp(siop_cmd)
struct siop_common_cmd *siop_cmd;
{
+ /* save data pointer. Handle async only for now */
int offset, dbc, sstat;
struct siop_common_softc *sc = siop_cmd->siop_sc;
- scr_table_t *table; /* table with partial xfer */
+ scr_table_t *table; /* table to patch */
- /*
- * compute how much of the current table didn't get handled when
- * a phase mismatch occurs
- */
if ((siop_cmd->xs->flags & (SCSI_DATA_OUT | SCSI_DATA_IN))
== 0)
- return; /* no valid data transfer */
-
+ return; /* no data pointers to save */
offset = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_SCRATCHA + 1);
if (offset >= SIOP_NSG) {
printf("%s: bad offset in siop_sdp (%d)\n",
@@ -737,8 +733,8 @@ siop_ma(siop_cmd)
}
table = &siop_cmd->siop_tables->data[offset];
#ifdef DEBUG_DR
- printf("siop_ma: offset %d count=%d addr=0x%x ", offset,
- table->count, table->addr);
+ printf("sdp: offset %d count=%d addr=0x%x ", offset,
+ letoh32(table->count), letoh32(table->addr));
#endif
dbc = bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DBC) & 0x00ffffff;
if (siop_cmd->xs->flags & SCSI_DATA_OUT) {
@@ -776,152 +772,13 @@ siop_ma(siop_cmd)
bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_CTEST3) |
CTEST3_CLF);
}
- siop_cmd->flags |= CMDFL_RESID;
- siop_cmd->resid = dbc;
-}
-
-void
-siop_sdp(siop_cmd, offset)
- struct siop_common_cmd *siop_cmd;
- int offset;
-{
- scr_table_t *table;
-
- if ((siop_cmd->xs->flags & (SCSI_DATA_OUT | SCSI_DATA_IN))
- == 0)
- return; /* no data pointers to save */
-
- /*
- * offset == SIOP_NSG may be a valid condition if we get a Save data
- * pointer when the xfer is done. Just ignore the Save data pointer
- * in this case
- */
- if (offset == SIOP_NSG)
- return;
-#ifdef DIAGNOSTIC
- if (offset > SIOP_NSG) {
- sc_print_addr(siop_cmd->xs->sc_link);
- printf(": offset %d > %d\n", offset, SIOP_NSG);
- panic("siop_sdp: offset");
- }
+ table->addr =
+ htole32(letoh32(table->addr) + letoh32(table->count) - dbc);
+ table->count = htole32(dbc);
+#ifdef DEBUG_DR
+ printf("now count=%d addr=0x%x\n",
+ letoh32(table->count), letoh32(table->addr));
#endif
- /*
- * Save data pointer. We do this by adjusting the tables to point
- * at the begginning of the data not yet transfered.
- * offset points to the first table with untransfered data.
- */
-
- /*
- * before doing that we decrease resid from the amount of data which
- * has been transfered.
- */
- siop_update_resid(siop_cmd, offset);
-
- /*
- * First let see if we have a resid from a phase mismatch. If so,
- * we have to adjst the table at offset to remove transfered data.
- */
- if (siop_cmd->flags & CMDFL_RESID) {
- siop_cmd->flags &= ~CMDFL_RESID;
- table = &siop_cmd->siop_tables->data[offset];
- /* "cut" already transfered data from this table */
- table->addr =
- htole32(letoh32(table->addr) +
- letoh32(table->count) - siop_cmd->resid);
- table->count = htole32(siop_cmd->resid);
- }
-
- /*
- * now we can remove entries which have been transfered.
- * We just move the entries with data left at the beggining of the
- * tables
- */
- bcopy(&siop_cmd->siop_tables->data[offset],
- &siop_cmd->siop_tables->data[0],
- (SIOP_NSG - offset) * sizeof(scr_table_t));
-}
-
-void
-siop_update_resid(siop_cmd, offset)
- struct siop_common_cmd *siop_cmd;
- int offset;
-{
- scr_table_t *table;
- int i;
-
- if ((siop_cmd->xs->flags & (SCSI_DATA_OUT | SCSI_DATA_IN))
- == 0)
- return; /* no data to transfer */
-
- /*
- * update resid. First account for the table entries which have
- * been fully completed.
- */
- for (i = 0; i < offset; i++)
- siop_cmd->xs->resid -=
- letoh32(siop_cmd->siop_tables->data[i].count);
- /*
- * if CMDFL_RESID is set, the last table (pointed by offset) is a
- * partial transfers. If not, offset points to the entry folloing
- * the last full transfer.
- */
- if (siop_cmd->flags & CMDFL_RESID) {
- table = &siop_cmd->siop_tables->data[offset];
- siop_cmd->xs->resid -= letoh32(table->count) - siop_cmd->resid;
- }
-}
-
-int
-siop_iwr(siop_cmd)
- struct siop_common_cmd *siop_cmd;
-{
- int offset;
- scr_table_t *table; /* table with IWR */
- struct siop_common_softc *sc = siop_cmd->siop_sc;
- /* handle ignore wide residue messages */
-
- /* if target isn't wide, reject */
- if ((siop_cmd->siop_target->flags & TARF_ISWIDE) == 0) {
- siop_cmd->siop_tables->t_msgout.count= htole32(1);
- siop_cmd->siop_tables->msg_out[0] = MSG_MESSAGE_REJECT;
- return SIOP_NEG_MSGOUT;
- }
- /* get index of current command in table */
- offset = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_SCRATCHA + 1);
- /*
- * if the current table did complete, we're now pointing at the
- * next one. Go back one if we didn't see a phase mismatch.
- */
- if ((siop_cmd->flags & CMDFL_RESID) == 0)
- offset--;
- table = &siop_cmd->siop_tables->data[offset];
-
- if ((siop_cmd->flags & CMDFL_RESID) == 0) {
- if (letoh32(table->count) & 1) {
- /* we really got the number of bytes we expected */
- return SIOP_NEG_ACK;
- } else {
- /*
- * now we really had a short xfer, by one byte.
- * handle it just as if we had a phase mistmatch
- * (there is a resid of one for this table).
- * Update scratcha1 to reflect the fact that
- * this xfer isn't complete.
- */
- siop_cmd->flags |= CMDFL_RESID;
- siop_cmd->resid = 1;
- bus_space_write_1(sc->sc_rt, sc->sc_rh,
- SIOP_SCRATCHA + 1, offset);
- return SIOP_NEG_ACK;
- }
- } else {
- /*
- * we already have a short xfer for this table; it's
- * just one byte less than we though it was
- */
- siop_cmd->resid--;
- return SIOP_NEG_ACK;
- }
}
void
diff --git a/sys/dev/ic/siopvar_common.h b/sys/dev/ic/siopvar_common.h
index c9db45647d3..efe32a8e41b 100644
--- a/sys/dev/ic/siopvar_common.h
+++ b/sys/dev/ic/siopvar_common.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: siopvar_common.h,v 1.21 2005/10/10 16:27:23 krw Exp $ */
+/* $OpenBSD: siopvar_common.h,v 1.22 2005/11/03 11:00:37 martin Exp $ */
/* $NetBSD: siopvar_common.h,v 1.32 2005/02/27 00:27:02 perry Exp $ */
/*
@@ -86,7 +86,6 @@ struct siop_common_cmd {
int status;
int flags;
int tag; /* tag used for tagged command queuing */
- int resid; /* valid when CMDFL_RESID is set */
};
/* status defs */
@@ -100,7 +99,6 @@ struct siop_common_cmd {
/* flags defs */
#define CMDFL_TIMEOUT 0x0001 /* cmd timed out */
#define CMDFL_TAG 0x0002 /* tagged cmd */
-#define CMDFL_RESID 0x0004 /* current offset in table is partial */
/* per-target struct */
struct siop_common_target {
@@ -194,15 +192,12 @@ void siop_sdtr_msg(struct siop_common_cmd *, int, int, int);
void siop_wdtr_msg(struct siop_common_cmd *, int, int);
void siop_ppr_msg(struct siop_common_cmd *, int, int, int);
void siop_update_xfer_mode(struct siop_common_softc *, int);
-int siop_iwr(struct siop_common_cmd *);
/* actions to take at return of siop_wdtr_neg() and siop_sdtr_neg() */
#define SIOP_NEG_NOP 0x0
#define SIOP_NEG_MSGOUT 0x1
#define SIOP_NEG_ACK 0x2
void siop_minphys(struct buf *);
-void siop_ma(struct siop_common_cmd *);
-void siop_sdp(struct siop_common_cmd *, int);
-void siop_update_resid(struct siop_common_cmd *, int);
+void siop_sdp(struct siop_common_cmd *);
void siop_clearfifo(struct siop_common_softc *);
void siop_resetbus(struct siop_common_softc *);