diff options
author | Kenneth R Westerback <krw@cvs.openbsd.org> | 2001-03-06 16:29:33 +0000 |
---|---|---|
committer | Kenneth R Westerback <krw@cvs.openbsd.org> | 2001-03-06 16:29:33 +0000 |
commit | 3613c29005f1eb03d802347320a98efbafe5a5c4 (patch) | |
tree | 9a8d61168fad548109696bd818d81a7c4f0b86c8 /sys/dev/ic/siop_common.c | |
parent | 769c25601defde21025d37cda98dd83dc785a8f8 (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.
Diffstat (limited to 'sys/dev/ic/siop_common.c')
-rw-r--r-- | sys/dev/ic/siop_common.c | 108 |
1 files changed, 78 insertions, 30 deletions
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"); +} |