Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev - do sync/wide negotiation
details: https://anonhg.NetBSD.org/src/rev/154c3951af0e
branches: trunk
changeset: 485668:154c3951af0e
user: bouyer <bouyer%NetBSD.org@localhost>
date: Tue May 02 19:03:02 2000 +0000
description:
- do sync/wide negotiation
- use a circular queue for the start slots, so that order has better chances
to be preserved.
diffstat:
sys/dev/ic/siop.c | 677 ++++++++++++++++++++++++++++++++++++++----------
sys/dev/ic/siopreg.h | 39 ++-
sys/dev/ic/siopvar.h | 17 +-
sys/dev/pci/siop_pci.c | 40 +-
4 files changed, 604 insertions(+), 169 deletions(-)
diffs (truncated from 1240 to 300 lines):
diff -r 0971e73780d2 -r 154c3951af0e sys/dev/ic/siop.c
--- a/sys/dev/ic/siop.c Tue May 02 19:02:28 2000 +0000
+++ b/sys/dev/ic/siop.c Tue May 02 19:03:02 2000 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: siop.c,v 1.6 2000/04/27 16:49:07 bouyer Exp $ */
+/* $NetBSD: siop.c,v 1.7 2000/05/02 19:03:02 bouyer Exp $ */
/*
* Copyright (c) 2000 Manuel Bouyer.
@@ -108,7 +108,7 @@
*/
struct siop_cmd {
TAILQ_ENTRY (siop_cmd) next;
- struct siop_softc *siop_sc; /* pointer to adapter */
+ struct siop_target *siop_target; /* pointer to our target def */
struct scsipi_xfer *xs; /* xfer from the upper level */
struct siop_xfer *siop_table; /* tables dealing with this xfer */
bus_addr_t dsa; /* DSA value to load */
@@ -133,9 +133,31 @@
/* initial number of cmd descriptors */
#define SIOP_NCMD 10
+/* per-target struct */
+struct siop_target {
+ int status; /* target status see below */
+ int flags; /* target flags, see below */
+ u_int32_t id; /* for SELECT FROM */
+ struct cmd_list active_list[8]; /* per-lun active cmds */
+ struct siop_softc *siop_sc; /* points back to our adapter */
+};
+
+/* target status */
+#define TARST_PROBING 0 /* target is being probed */
+#define TARST_ASYNC 1 /* target needs sync/wide negotiation */
+#define TARST_WIDE_NEG 2 /* target is doing wide negotiation */
+#define TARST_SYNC_NEG 3 /* target is doing sync negotiation */
+#define TARST_OK 4 /* sync/wide agreement is valid */
+
+/* target flags */
+#define TARF_SYNC 0x00 /* target is sync */
+#define TARF_WIDE 0x01 /* target is wide */
+
void siop_reset __P((struct siop_softc *));
void siop_handle_reset __P((struct siop_softc *));
void siop_scsicmd_end __P((struct siop_cmd *));
+void siop_wdtr_neg __P((struct siop_cmd *siop_cmd));
+void siop_sdtr_neg __P((struct siop_cmd *siop_cmd));
void siop_start __P((struct siop_softc *));
void siop_timeout __P((void *));
void siop_minphys __P((struct buf *));
@@ -180,7 +202,7 @@
struct siop_cmd *siop_cmd;
int ops;
{
- struct siop_softc *sc = siop_cmd->siop_sc;
+ struct siop_softc *sc = siop_cmd->siop_target->siop_sc;
bus_addr_t offset;
offset = sc->sc_scriptdma->dm_segs[0].ds_addr - siop_cmd->dsa;
@@ -238,8 +260,6 @@
return;
}
TAILQ_INIT(&sc->free_list);
- for (i = 0; i < 16; i++)
- TAILQ_INIT(&sc->active_list[i]);
/* allocate cmd list */
sc->cmds =
malloc(sizeof(struct siop_cmd) * SIOP_NCMD, M_DEVBUF, M_NOWAIT);
@@ -267,7 +287,6 @@
sc->sc_dev.dv_xname, error);
return;
}
- sc->cmds[i].siop_sc = sc;
sc->cmds[i].siop_table =
&((struct siop_xfer *)(&sc->sc_script[CMD_OFF/4]))[i];
sc->cmds[i].dsa = sc->sc_scriptdma->dm_segs[0].ds_addr +
@@ -300,6 +319,7 @@
+ 8 /* extra NOP at end of main script */
- sizeof(endslot_script) /* memory needed at end of sheduler */
) / (sizeof(slot_script) - 8);
+ sc->sc_currshedslot = 0;
#ifdef DEBUG
printf("%s: script size = %d, PHY addr=0x%x, VIRT=%p nslots %d\n",
sc->sc_dev.dv_xname, (int)sizeof(siop_script),
@@ -324,6 +344,22 @@
sc->sc_link.device = &siop_dev;
sc->sc_link.flags = 0;
+ for (i = 0; i < 16; i++)
+ sc->targets[i] = NULL;
+
+ /* find min/max sync period for this chip */
+ sc->maxsync = 0;
+ sc->minsync = 255;
+ for (i = 0; i < sizeof(scf_period) / sizeof(scf_period[0]); i++) {
+ if (sc->clock_period != scf_period[i].clock)
+ continue;
+ if (sc->maxsync < scf_period[i].period)
+ sc->maxsync = scf_period[i].period;
+ if (sc->minsync > scf_period[i].period)
+ sc->minsync = scf_period[i].period;
+ }
+ if (sc->maxsync == 255 || sc->minsync == 0)
+ panic("siop: can't find my sync parameters\n");
siop_reset(sc);
#ifdef DUMP_SCRIPT
siop_dump_script(sc);
@@ -338,6 +374,7 @@
{
int i, j;
u_int32_t *scr;
+ u_int32_t stest3;
bus_addr_t physaddr;
/* reset the chip */
@@ -387,7 +424,7 @@
bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL0,
SCNTL0_ARB_MASK | SCNTL0_EPC | SCNTL0_AAP);
bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL1, 0);
- bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL3, 0x3);
+ bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL3, sc->clock_div);
bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_DIEN, 0xff);
bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SIEN0,
0xff & ~(SIEN0_CMP | SIEN0_SEL | SIEN0_RSL));
@@ -401,7 +438,31 @@
sc->sc_link.scsipi_scsi.adapter_target | SCID_RRE);
bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_RESPID0,
1 << sc->sc_link.scsipi_scsi.adapter_target);
- bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_DCNTL, 0);
+ bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_DCNTL, DCNTL_COM);
+
+ /* enable clock doubler or quadruler if appropriate */
+ if (sc->features & (SF_CHIP_DBLR | SF_CHIP_QUAD)) {
+ stest3 = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_STEST3);
+ bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_STEST1,
+ STEST1_DBLEN);
+ if (sc->features & SF_CHIP_QUAD) {
+ /* wait for PPL to lock */
+ while ((bus_space_read_1(sc->sc_rt, sc->sc_rh,
+ SIOP_STEST4) & STEST4_LOCK) == 0)
+ delay(10);
+ } else {
+ /* data sheet says 20us - more won't hurt */
+ delay(100);
+ }
+ /* halt scsi clock, select doubler/quad, restart clock */
+ bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_STEST3,
+ stest3 | STEST3_HSC);
+ bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_STEST1,
+ STEST1_DBLEN | STEST1_DBLSEL);
+ bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_STEST3, stest3);
+ } else {
+ bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_STEST1, 0);
+ }
/* start script */
siop_script_sync(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
@@ -427,12 +488,13 @@
void *v;
{
struct siop_softc *sc = v;
+ struct siop_target *siop_target;
struct siop_cmd *siop_cmd;
struct scsipi_xfer *xs;
u_int8_t istat, sist0, sist1, sstat1, dstat, scntl1;
u_int32_t irqcode;
int need_reset = 0;
- int offset, target;
+ int offset, target, lun;
bus_addr_t dsa;
istat = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_ISTAT);
@@ -462,7 +524,8 @@
dstat = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_DSTAT);
if (dstat & DSTAT_SSI) {
printf("single step dsp 0x%08x dsa 0x08%x\n",
- bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP),
+ (int)(bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP) -
+ sc->sc_scriptdma->dm_segs[0].ds_addr),
bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSA));
if ((dstat & ~(DSTAT_DFE | DSTAT_SSI)) == 0 &&
(istat & ISTAT_SIP) == 0) {
@@ -485,7 +548,8 @@
if (dstat & DSTAT_DFE)
printf(" dma fifo empty");
printf(", DSP=0x%x DSA=0x%x: ",
- bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP),
+ (int)(bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP) -
+ sc->sc_scriptdma->dm_segs[0].ds_addr),
bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSA));
p = sc->sc_script +
(bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP) -
@@ -519,10 +583,13 @@
"DSA=0x%x DSP=0x%x\n", sist0, sist1,
bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_SSTAT1),
bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSA),
- bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP));
+ bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP) -
+ sc->sc_scriptdma->dm_segs[0].ds_addr);
#endif
- if (siop_cmd)
+ if (siop_cmd) {
xs = siop_cmd->xs;
+ siop_target = siop_cmd->siop_target;
+ }
if (sist0 & SIST0_RST) {
siop_handle_reset(sc);
siop_start(sc);
@@ -606,7 +673,7 @@
* a fatal condition this way. Attempt to get sense.
*/
if (siop_cmd)
- goto check_sense;
+ goto check_sense;
printf("%s: unexpected disconnect without "
"command\n", sc->sc_dev.dv_xname);
goto reset;
@@ -617,7 +684,8 @@
sist0, sist1,
bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_SSTAT1),
bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSA),
- bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP));
+ (int)(bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP) -
+ sc->sc_scriptdma->dm_segs[0].ds_addr));
if (siop_cmd) {
siop_cmd->status = CMDST_DONE;
xs->error = XS_SELTIMEOUT;
@@ -657,12 +725,15 @@
"status %d) !\n", sc->sc_dev.dv_xname,
irqcode, siop_cmd->status);
xs = NULL;
- } else
+ } else {
xs = siop_cmd->xs;
+ siop_target = siop_cmd->siop_target;
+ }
switch(irqcode) {
case A_int_err:
printf("error, DSP=0x%x\n",
- bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP));
+ (int)(bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP) -
+ sc->sc_scriptdma->dm_segs[0].ds_addr));
if (xs) {
xs->error = XS_SELTIMEOUT;
goto end;
@@ -684,12 +755,29 @@
/* MSG_REJECT for a MSG_REJECT !*/
goto reset;
}
+ if (siop_cmd->siop_table->msg_out[0] ==
+ MSG_EXTENDED &&
+ siop_cmd->siop_table->msg_out[2] ==
+ MSG_EXT_WDTR) {
+ /* wide rejected, do sync */
+ siop_cmd->siop_target->status =
+ TARST_WIDE_NEG;
+ } else if (siop_cmd->siop_table->msg_out[0] ==
+ MSG_EXTENDED &&
+ siop_cmd->siop_table->msg_out[2] ==
+ MSG_EXT_SDTR) {
+ /* sync rejected */
+ siop_cmd->siop_target->status =
+ TARST_OK;
+ }
/* no table to flush here */
CALL_SCRIPT(Ent_msgin_ack);
return 1;
}
- printf("unhandled message 0x%x\n",
- siop_cmd->siop_table->msg_in[0]);
+ printf("unhandled message 0x%x, DSP=0x%x\n",
+ siop_cmd->siop_table->msg_in[0],
+ (int)(bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP) -
+ sc->sc_scriptdma->dm_segs[0].ds_addr));
siop_cmd->siop_table->t_msgout.count= htole32(1);
siop_cmd->siop_table->t_msgout.addr =
htole32(siop_cmd->dsa);
@@ -727,27 +815,21 @@
printf("\n");
}
#endif
+ if (siop_cmd->siop_table->msg_in[2] == MSG_EXT_WDTR) {
+ siop_wdtr_neg(siop_cmd);
+ return(1);
+ }
if (siop_cmd->siop_table->msg_in[2] == MSG_EXT_SDTR) {
- /* anserw with async for now */
- siop_cmd->siop_table->msg_out[0] = MSG_EXTENDED;
- siop_cmd->siop_table->msg_out[1] =
- MSG_EXT_SDTR_LEN;
- siop_cmd->siop_table->msg_out[2] = MSG_EXT_SDTR;
- siop_cmd->siop_table->msg_out[3] = 0;
- siop_cmd->siop_table->msg_out[4] = 0;
- siop_cmd->siop_table->t_msgout.count =
- htole32(MSG_EXT_SDTR_LEN + 2);
- siop_cmd->siop_table->t_msgout.addr =
- htole32(siop_cmd->dsa);
- } else {
- /* send a message reject */
- siop_cmd->siop_table->t_msgout.count =
Home |
Main Index |
Thread Index |
Old Index