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 | |
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.
-rw-r--r-- | sys/dev/ic/siop.c | 136 | ||||
-rw-r--r-- | sys/dev/ic/siop_common.c | 108 | ||||
-rw-r--r-- | sys/dev/ic/siopvar_common.h | 8 |
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 *)); |