summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKenneth R Westerback <krw@cvs.openbsd.org>2001-03-06 16:29:33 +0000
committerKenneth R Westerback <krw@cvs.openbsd.org>2001-03-06 16:29:33 +0000
commit3613c29005f1eb03d802347320a98efbafe5a5c4 (patch)
tree9a8d61168fad548109696bd818d81a7c4f0b86c8
parent769c25601defde21025d37cda98dd83dc785a8f8 (diff)
1) Enable tag queuing.
2) Negotiate and report wide/sync only after INQUIRY results known. 3) Clean up wide/sync negotiation code a bit, ensuring that an agressive target does not prematurely force negotiation before the INQUIRY is done. Seen by millert@. 4) Ensure that a wide negotiation always resets the sync settings to async. 5) Some error message improvements from thorpej@NetBSD. 6) Some KNF. 7) Print wide/sync negotiation results after each completed negotiation. 8) Print some relevant information just before a panic that should never happen. But does on PowerPC.
-rw-r--r--sys/dev/ic/siop.c136
-rw-r--r--sys/dev/ic/siop_common.c108
-rw-r--r--sys/dev/ic/siopvar_common.h8
3 files changed, 146 insertions, 106 deletions
diff --git a/sys/dev/ic/siop.c b/sys/dev/ic/siop.c
index 30e8bb6d5f0..c855a7c456f 100644
--- a/sys/dev/ic/siop.c
+++ b/sys/dev/ic/siop.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: siop.c,v 1.4 2001/03/01 17:14:27 krw Exp $ */
+/* $OpenBSD: siop.c,v 1.5 2001/03/06 16:29:32 krw Exp $ */
/* $NetBSD: siop.c,v 1.39 2001/02/11 18:04:49 bouyer Exp $ */
/*
@@ -86,7 +86,6 @@ int siop_morecbd __P((struct siop_softc *));
struct siop_lunsw *siop_get_lunsw __P((struct siop_softc *));
void siop_add_reselsw __P((struct siop_softc *, int));
void siop_update_scntl3 __P((struct siop_softc *, struct siop_target *));
-void siop_print_info __P((struct siop_softc *, int));
struct cfdriver siop_cd = {
NULL, "siop", DV_DULL
@@ -214,7 +213,7 @@ siop_attach(sc)
#endif
sc->sc_link.adapter_softc = sc;
- sc->sc_link.openings = 2;
+ sc->sc_link.openings = SIOP_OPENINGS;
sc->sc_link.adapter_buswidth =
(sc->features & SF_BUS_WIDE) ? 16 : 8;
sc->sc_link.adapter_target = bus_space_read_1(sc->sc_rt,
@@ -432,29 +431,29 @@ siop_intr(v)
return 1;
}
if (dstat & ~(DSTAT_SIR | DSTAT_DFE | DSTAT_SSI)) {
- printf("DMA IRQ:");
- if (dstat & DSTAT_IID)
- printf(" Illegal instruction");
- if (dstat & DSTAT_ABRT)
- printf(" abort");
- if (dstat & DSTAT_BF)
- printf(" bus fault");
- if (dstat & DSTAT_MDPE)
- printf(" parity");
- if (dstat & DSTAT_DFE)
- printf(" dma fifo empty");
- printf(", DSP=0x%x DSA=0x%x: ",
- (int)(bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP) -
- sc->sc_scriptaddr),
- bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSA));
- if (siop_cmd)
- printf("last msg_in=0x%x status=0x%x\n",
- siop_cmd->siop_tables.msg_in[0],
- letoh32(siop_cmd->siop_tables.status));
- else
- printf("%s: current DSA invalid\n",
- sc->sc_dev.dv_xname);
- need_reset = 1;
+ printf("DMA IRQ:");
+ if (dstat & DSTAT_IID)
+ printf("Illegal instruction");
+ if (dstat & DSTAT_ABRT)
+ printf(" abort");
+ if (dstat & DSTAT_BF)
+ printf(" bus fault");
+ if (dstat & DSTAT_MDPE)
+ printf(" parity");
+ if (dstat & DSTAT_DFE)
+ printf(" dma fifo empty");
+ printf(", DSP=0x%x DSA=0x%x: ",
+ (int)(bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP) -
+ sc->sc_scriptaddr),
+ bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSA));
+ if (siop_cmd)
+ printf("last msg_in=0x%x status=0x%x\n",
+ siop_cmd->siop_tables.msg_in[0],
+ letoh32(siop_cmd->siop_tables.status));
+ else
+ printf("%s: current DSA invalid\n",
+ sc->sc_dev.dv_xname);
+ need_reset = 1;
}
}
if (istat & ISTAT_SIP) {
@@ -736,6 +735,7 @@ scintr:
if ((siop_target->flags & TARF_SYNC)
== 0) {
siop_target->status = TARST_OK;
+ siop_print_info(sc, target);
/* no table to flush here */
CALL_SCRIPT(Ent_msgin_ack);
return 1;
@@ -751,6 +751,7 @@ scintr:
} else if (msg == MSG_EXTENDED &&
extmsg == MSG_EXT_SDTR) {
siop_target->status = TARST_OK;
+ siop_print_info(sc, target);
/* no table to flush here */
CALL_SCRIPT(Ent_msgin_ack);
return 1;
@@ -933,8 +934,12 @@ scintr:
}
return 1;
}
- /* We just should't get there */
- panic("siop_intr: I shouldn't be there !");
+ /* We just shouldn't get here */
+ printf("istat = 0x%x, dstat = 0x%x, sist = 0x%x, sstat1 = 0x%x\n", istat, dstat, sist, sstat1);
+ printf("need_reset = %d, irqcode = %d, siop_cmd = %p, siop_target = %p, xs = %p\n");
+ if (siop_cmd != NULL)
+ printf("siop_cmd->status = %d\n", siop_cmd->status);
+ panic("%s: siop_intr: I shouldn't be here!", sc->sc_dev.dv_xname);
return 1;
end:
/*
@@ -1046,7 +1051,8 @@ siop_scsicmd_end(siop_cmd)
&siop_cmd->rs_cmd, sizeof(struct scsi_sense),
NULL, BUS_DMA_NOWAIT);
if (error) {
- printf("%s: unable to load cmd DMA map: %d",
+ printf("%s: unable to load cmd DMA map "
+ "(for SENSE): %d\n",
sc->sc_dev.dv_xname, error);
xs->error = XS_DRIVER_STUFFUP;
goto out;
@@ -1055,7 +1061,8 @@ siop_scsicmd_end(siop_cmd)
&xs->sense, sizeof(struct scsi_sense_data),
NULL, BUS_DMA_NOWAIT);
if (error) {
- printf("%s: unable to load sense DMA map: %d",
+ printf("%s: unable to load data DMA map "
+ "(for SENSE): %d\n",
sc->sc_dev.dv_xname, error);
xs->error = XS_DRIVER_STUFFUP;
bus_dmamap_unload(sc->sc_dmat, siop_cmd->dmamap_cmd);
@@ -1217,41 +1224,11 @@ siop_handle_reset(sc)
}
}
-void
-siop_print_info(sc, target)
- struct siop_softc *sc;
- int target;
-{
- const u_int32_t id = sc->targets[target]->id;
- const u_int8_t scf = ((id >> 24) & SCNTL3_SCF_MASK) >> SCNTL3_SCF_SHIFT;
- const u_int8_t offset = ((id >> 8) & SXFER_MO_MASK) >> SXFER_MO_SHIFT;
- const int clock = sc->clock_period;
- int i;
-
- printf("%s: target %d using %d bit ", sc->sc_dev.dv_xname, target,
- (sc->targets[target]->flags & TARF_ISWIDE) ? 16 : 8);
-
- if (offset == 0)
- printf("async ");
- else {
- for (i = 0; i < sizeof(scf_period) / sizeof(scf_period[0]); i++)
- if ((scf_period[i].clock == clock)
- && (scf_period[i].scf == scf)) {
- printf("%s ", scf_period[i].rate);
- break;
- }
- if (i == sizeof(scf_period) / sizeof(scf_period[0]))
- printf("? ");
- printf("MHz %d REQ/ACK offset ", offset);
- }
-
- printf("xfers\n");
-}
-
int
siop_scsicmd(xs)
struct scsi_xfer *xs;
{
+ struct scsi_inquiry_data *inqdata;
struct siop_softc *sc = (struct siop_softc *)xs->sc_link->adapter_softc;
struct siop_cmd *siop_cmd;
int s, error, i;
@@ -1260,7 +1237,7 @@ siop_scsicmd(xs)
s = splbio();
#ifdef SIOP_DEBUG_SCHED
- printf("starting cmd for %d:%d\n", target, lun);
+ printf("starting cmd 0x%02x for %d:%d\n", xs->cmd->opcode, target, lun);
#endif
siop_cmd = TAILQ_FIRST(&sc->free_list);
if (siop_cmd) {
@@ -1303,12 +1280,7 @@ siop_scsicmd(xs)
return(TRY_AGAIN_LATER);
}
sc->targets[target]->status = TARST_PROBING;
-
- if (sc->features & SF_BUS_WIDE)
- sc->targets[target]->flags = TARF_SYNC | TARF_WIDE;
- else
- sc->targets[target]->flags = TARF_SYNC;
-
+ sc->targets[target]->flags = 0;
sc->targets[target]->id = sc->clock_div << 24; /* scntl3 */
sc->targets[target]->id |= target << 16; /* id */
/* sc->targets[target]->id |= 0x0 << 8; scxfer is 0 */
@@ -1325,8 +1297,7 @@ siop_scsicmd(xs)
for (i=0; i < 8; i++)
sc->targets[target]->siop_lun[i] = NULL;
siop_add_reselsw(sc, target);
- } else if (sc->targets[target]->status == TARST_PROBING)
- sc->targets[target]->status = TARST_ASYNC;
+ }
if (sc->targets[target]->siop_lun[lun] == NULL) {
sc->targets[target]->siop_lun[lun] =
@@ -1350,7 +1321,7 @@ siop_scsicmd(xs)
error = bus_dmamap_load(sc->sc_dmat, siop_cmd->dmamap_cmd,
xs->cmd, xs->cmdlen, NULL, BUS_DMA_NOWAIT);
if (error) {
- printf("%s: unable to load cmd DMA map: %d",
+ printf("%s: unable to load cmd DMA map: %d\n",
sc->sc_dev.dv_xname, error);
xs->error = XS_DRIVER_STUFFUP;
splx(s);
@@ -1360,7 +1331,7 @@ siop_scsicmd(xs)
error = bus_dmamap_load(sc->sc_dmat, siop_cmd->dmamap_data,
xs->data, xs->datalen, NULL, BUS_DMA_NOWAIT);
if (error) {
- printf("%s: unable to load cmd DMA map: %d",
+ printf("%s: unable to load cmd DMA map: %d\n",
sc->sc_dev.dv_xname, error);
xs->error = XS_DRIVER_STUFFUP;
bus_dmamap_unload(sc->sc_dmat, siop_cmd->dmamap_cmd);
@@ -1386,8 +1357,25 @@ siop_scsicmd(xs)
if (xs->flags & ITSDONE) {
if ((xs->cmd->opcode == INQUIRY)
&& (xs->sc_link->lun == 0)
- && (xs->error == XS_NOERROR))
- siop_print_info(sc, target);
+ && (xs->error == XS_NOERROR)) {
+ inqdata = (struct scsi_inquiry_data *)xs->data;
+ if (inqdata->flags & SID_CmdQue) {
+ sc->targets[target]->flags |= TARF_TAG;
+ xs->sc_link->openings += SIOP_NTAG - SIOP_OPENINGS;
+ }
+ if ((inqdata->flags & SID_WBus16) && (sc->features & SF_BUS_WIDE))
+ sc->targets[target]->flags |= TARF_WIDE;
+ if (inqdata->flags & SID_Sync)
+ sc->targets[target]->flags |= TARF_SYNC;
+ if (sc->targets[target]->flags & (TARF_WIDE | TARF_SYNC)) {
+ sc->targets[target]->status = TARST_ASYNC;
+ siop_add_dev(sc, target, lun);
+ }
+ else {
+ sc->targets[target]->status = TARST_OK;
+ siop_print_info(sc, target);
+ }
+ }
break;
}
delay(1000);
diff --git a/sys/dev/ic/siop_common.c b/sys/dev/ic/siop_common.c
index 7499240fef1..fc569695f60 100644
--- a/sys/dev/ic/siop_common.c
+++ b/sys/dev/ic/siop_common.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: siop_common.c,v 1.3 2001/03/01 17:14:28 krw Exp $ */
+/* $OpenBSD: siop_common.c,v 1.4 2001/03/06 16:29:32 krw Exp $ */
/* $NetBSD: siop_common.c,v 1.12 2001/02/11 18:04:50 bouyer Exp $ */
/*
@@ -146,6 +146,7 @@ siop_setuptables(siop_cmd)
siop_sdtr_msg(siop_cmd, 1, sc->minsync, sc->maxoff);
} else {
sc->targets[target]->status = TARST_OK;
+ siop_print_info(sc, target);
}
} else if (sc->targets[target]->status == TARST_OK &&
(sc->targets[target]->flags & TARF_TAG) &&
@@ -180,6 +181,18 @@ siop_wdtr_neg(siop_cmd)
int target = siop_cmd->xs->sc_link->target;
struct siop_xfer_common *tables = &siop_cmd->siop_xfer->tables;
+ /* revert to async until told otherwise */
+ sc->targets[target]->id &= ~(SCNTL3_SCF_MASK << 24);
+ sc->targets[target]->id &= ~(SCNTL3_ULTRA << 24);
+ sc->targets[target]->id &= ~(SXFER_MO_MASK << 8);
+
+ tables->id = htole32(sc->targets[target]->id);
+
+ bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL3,
+ (sc->targets[target]->id >> 24) & 0xff);
+ bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SXFER,
+ (sc->targets[target]->id >> 8) & 0xff);
+
if (siop_target->status == TARST_WIDE_NEG) {
/* we initiated wide negotiation */
switch (tables->msg_in[3]) {
@@ -204,6 +217,7 @@ siop_wdtr_neg(siop_cmd)
printf("%s: rejecting invalid wide negotiation from "
"target %d (%d)\n", sc->sc_dev.dv_xname, target,
tables->msg_in[3]);
+ siop_print_info(sc, target);
tables->t_msgout.count= htole32(1);
tables->msg_out[0] = MSG_MESSAGE_REJECT;
return SIOP_NEG_MSGOUT;
@@ -219,6 +233,7 @@ siop_wdtr_neg(siop_cmd)
return SIOP_NEG_MSGOUT;
} else {
siop_target->status = TARST_OK;
+ siop_print_info(sc, target);
return SIOP_NEG_ACK;
}
} else {
@@ -235,10 +250,12 @@ siop_wdtr_neg(siop_cmd)
bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL3,
(sc->targets[target]->id >> 24) & 0xff);
/*
- * we did reset wide parameters, so fall back to async,
- * but don't schedule a sync neg, target should initiate it
+ * Don't schedule a sync neg, target should initiate it.
*/
- siop_target->status = TARST_OK;
+ if (siop_target->status != TARST_PROBING) {
+ siop_target->status = TARST_OK;
+ siop_print_info(sc, target);
+ }
siop_wdtr_msg(siop_cmd, 0, (siop_target->flags & TARF_ISWIDE) ?
MSG_EXT_WDTR_BUS_16_BIT : MSG_EXT_WDTR_BUS_8_BIT);
return SIOP_NEG_MSGOUT;
@@ -259,9 +276,13 @@ siop_sdtr_neg(siop_cmd)
sync = tables->msg_in[3];
offset = tables->msg_in[4];
+ /* revert to async until told otherwise */
+ sc->targets[target]->id &= ~(SCNTL3_SCF_MASK << 24);
+ sc->targets[target]->id &= ~(SCNTL3_ULTRA << 24);
+ sc->targets[target]->id &= ~(SXFER_MO_MASK << 8);
+
if (siop_target->status == TARST_SYNC_NEG) {
/* we initiated sync negotiation */
- siop_target->status = TARST_OK;
#ifdef DEBUG
printf("sdtr: sync %d offset %d\n", sync, offset);
#endif
@@ -274,39 +295,31 @@ siop_sdtr_neg(siop_cmd)
continue;
if (scf_period[i].period == sync) {
/* ok, found it. we now are sync. */
- sc->targets[target]->id &=
- ~(SCNTL3_SCF_MASK << 24);
sc->targets[target]->id |= scf_period[i].scf
<< (24 + SCNTL3_SCF_SHIFT);
if (sync < 25) /* Ultra */
sc->targets[target]->id |=
SCNTL3_ULTRA << 24;
- else
- sc->targets[target]->id &=
- ~(SCNTL3_ULTRA << 24);
- sc->targets[target]->id &=
- ~(SXFER_MO_MASK << 8);
sc->targets[target]->id |=
(offset & SXFER_MO_MASK) << 8;
goto end;
}
}
/*
- * we didn't find it in our table, do async and send reject
- * msg
+ * We didn't find it in our table, so stay async and send reject
+ * msg.
*/
reject:
send_msgout = 1;
tables->t_msgout.count= htole32(1);
tables->msg_out[0] = MSG_MESSAGE_REJECT;
- sc->targets[target]->id &= ~(SCNTL3_SCF_MASK << 24);
- sc->targets[target]->id &= ~(SCNTL3_ULTRA << 24);
- sc->targets[target]->id &= ~(SXFER_MO_MASK << 8);
} else { /* target initiated sync neg */
#ifdef DEBUG
printf("sdtr (target): sync %d offset %d\n", sync, offset);
#endif
- if (offset == 0 || sync > sc->maxsync) { /* async */
+ if ((sc->targets[target]->flags & TARF_SYNC) == 0
+ || offset == 0
+ || sync > sc->maxsync) {
goto async;
}
if (offset > sc->maxoff)
@@ -320,18 +333,11 @@ reject:
continue;
if (scf_period[i].period == sync) {
/* ok, found it. we now are sync. */
- sc->targets[target]->id &=
- ~(SCNTL3_SCF_MASK << 24);
sc->targets[target]->id |= scf_period[i].scf
<< (24 + SCNTL3_SCF_SHIFT);
if (sync < 25) /* Ultra */
sc->targets[target]->id |=
SCNTL3_ULTRA << 24;
- else
- sc->targets[target]->id &=
- ~(SCNTL3_ULTRA << 24);
- sc->targets[target]->id &=
- ~(SXFER_MO_MASK << 8);
sc->targets[target]->id |=
(offset & SXFER_MO_MASK) << 8;
siop_sdtr_msg(siop_cmd, 0, sync, offset);
@@ -340,11 +346,6 @@ reject:
}
}
async:
- printf("%s: target %d asynchronous\n",
- sc->sc_dev.dv_xname, target);
- sc->targets[target]->id &= ~(SCNTL3_SCF_MASK << 24);
- sc->targets[target]->id &= ~(SCNTL3_ULTRA << 24);
- sc->targets[target]->id &= ~(SXFER_MO_MASK << 8);
siop_sdtr_msg(siop_cmd, 0, 0, 0);
send_msgout = 1;
}
@@ -357,6 +358,12 @@ end:
(sc->targets[target]->id >> 24) & 0xff);
bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SXFER,
(sc->targets[target]->id >> 8) & 0xff);
+
+ if (siop_target->status != TARST_PROBING) {
+ siop_target->status = TARST_OK;
+ siop_print_info(sc, target);
+ }
+
if (send_msgout) {
return SIOP_NEG_MSGOUT;
} else {
@@ -550,3 +557,44 @@ siop_resetbus(sc)
delay(100);
bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL1, scntl1);
}
+
+/*
+ * siop_print_info: print the current negotiated wide/sync xfer values for
+ * a particular target. This function is called whenever
+ * a wide/sync negotiation completes, i.e. whenever
+ * target->status is set to TARST_OK.
+ */
+void
+siop_print_info(sc, target)
+ struct siop_softc *sc;
+ int target;
+{
+ struct siop_target *siop_target = sc->targets[target];
+ u_int8_t scf, offset;
+ int clock, i;
+
+ offset = ((siop_target->id >> 8) & SXFER_MO_MASK) >> SXFER_MO_SHIFT;
+ scf = ((siop_target->id >> 24) & SCNTL3_SCF_MASK) >> SCNTL3_SCF_SHIFT;
+ clock = sc->clock_period;
+
+ printf("%s: target %d now using%s%d bit ",
+ sc->sc_dev.dv_xname, target,
+ (siop_target->flags & TARF_TAG) ? " tagged " : " ",
+ (siop_target->flags & TARF_ISWIDE) ? 16 : 8);
+
+ if (offset == 0)
+ printf("async ");
+ else {
+ for (i = 0; i < sizeof(scf_period) / sizeof(scf_period[0]); i++)
+ if ((scf_period[i].clock == clock)
+ && (scf_period[i].scf == scf)) {
+ printf("%s ", scf_period[i].rate);
+ break;
+ }
+ if (i == sizeof(scf_period) / sizeof(scf_period[0]))
+ printf("? ");
+ printf("MHz %d REQ/ACK offset ", offset);
+ }
+
+ printf("xfers\n");
+}
diff --git a/sys/dev/ic/siopvar_common.h b/sys/dev/ic/siopvar_common.h
index a8cb3e971e9..565618cd043 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.2 2001/03/01 17:14:28 krw Exp $ */
+/* $OpenBSD: siopvar_common.h,v 1.3 2001/03/06 16:29:32 krw Exp $ */
/* $NetBSD: siopvar_common.h,v 1.10 2001/01/26 21:58:56 bouyer Exp $ */
/*
@@ -46,9 +46,12 @@ typedef struct scr_table {
/* Number of scatter/gather entries */
#define SIOP_NSG (MAXPHYS/NBPG + 1) /* XXX NBPG */
-/* Number of tag */
+/* Number of tags, also number of openings if tags are used */
#define SIOP_NTAG 16
+/* Number of openings if tags are not used */
+#define SIOP_OPENINGS 2
+
/*
* This structure interfaces the SCRIPT with the driver; it describes a full
* transfer.
@@ -191,6 +194,7 @@ void siop_wdtr_msg __P((struct siop_cmd *, int, int));
#define SIOP_NEG_MSGOUT 0x1
#define SIOP_NEG_ACK 0x2
+void siop_print_info __P((struct siop_softc *, int));
void siop_minphys __P((struct buf *));
void siop_sdp __P((struct siop_cmd *));
void siop_clearfifo __P((struct siop_softc *));