From aca8e01877e03e794a28045c7f2c3bad96bf700f Mon Sep 17 00:00:00 2001 From: tsutsui Date: Sun, 18 Nov 2001 14:50:11 +0000 Subject: [PATCH] - Use MI ADAPTER_REQ_SET_XFER_MODE callback - Move values in sc_sync[] member to sc_tinfo[] - Change some u_int8_t values to int - Remove unused wide negotiation states - Misc cleanup --- sys/dev/ic/osiop.c | 147 +++++++++++++++++++++++++++--------------- sys/dev/ic/osiopvar.h | 32 ++++----- 2 files changed, 108 insertions(+), 71 deletions(-) diff --git a/sys/dev/ic/osiop.c b/sys/dev/ic/osiop.c index 81cd3dad0ba6..a76ab3de4a45 100644 --- a/sys/dev/ic/osiop.c +++ b/sys/dev/ic/osiop.c @@ -1,4 +1,4 @@ -/* $NetBSD: osiop.c,v 1.6 2001/11/13 13:14:42 lukem Exp $ */ +/* $NetBSD: osiop.c,v 1.7 2001/11/18 14:50:11 tsutsui Exp $ */ /* * Copyright (c) 2001 Izumi Tsutsui. All rights reserved. @@ -76,7 +76,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: osiop.c,v 1.6 2001/11/13 13:14:42 lukem Exp $"); +__KERNEL_RCSID(0, "$NetBSD: osiop.c,v 1.7 2001/11/18 14:50:11 tsutsui Exp $"); /* #define OSIOP_DEBUG */ @@ -119,6 +119,7 @@ void osiop_resetbus(struct osiop_softc *); void osiop_start(struct osiop_softc *); int osiop_checkintr(struct osiop_softc *, u_int8_t, u_int8_t, u_int8_t, int *); void osiop_select(struct osiop_softc *); +void osiop_update_xfer_mode(struct osiop_softc *, int); void scsi_period_to_osiop(struct osiop_softc *, int); void osiop_timeout(void *); @@ -481,7 +482,25 @@ osiop_scsipi_request(chan, req, arg) return; case ADAPTER_REQ_SET_XFER_MODE: - return; + { + struct osiop_tinfo *ti; + struct scsipi_xfer_mode *xm = arg; + + ti = &sc->sc_tinfo[xm->xm_target]; + + if ((xm->xm_mode & PERIPH_CAP_SYNC) != 0 && + (ti->flags & TI_NOSYNC) == 0) + ti->state = NEG_INIT; + + /* + * If we're not going to negotiate, send the + * notification now, since it won't happen later. + */ + if (ti->state == NEG_DONE) + osiop_update_xfer_mode(sc, xm->xm_target); + + return; + } } } @@ -811,7 +830,7 @@ osiop_reset(sc) struct osiop_softc *sc; { struct osiop_acb *acb; - int s; + int i, s; u_int8_t stat; #ifdef OSIOP_DEBUG @@ -857,7 +876,11 @@ osiop_reset(sc) osiop_read_1(sc, OSIOP_CTEST7) | sc->sc_ctest7); /* will need to re-negotiate sync xfers */ - memset(&sc->sc_sync, 0, sizeof(sc->sc_sync)); + for (i = 0; i < OSIOP_NTGT; i++) { + sc->sc_tinfo[i].state = NEG_INIT; + sc->sc_tinfo[i].period = 0; + sc->sc_tinfo[i].offset = 0; + } stat = osiop_read_1(sc, OSIOP_ISTAT); if (stat & OSIOP_ISTAT_SIP) @@ -920,10 +943,10 @@ osiop_start(sc) struct osiop_ds *ds = acb->ds; struct scsipi_xfer *xs = acb->xs; bus_dmamap_t dsdma = sc->sc_dsdma, datadma = acb->datadma; + struct osiop_tinfo *ti; int target = xs->xs_periph->periph_target; int lun = xs->xs_periph->periph_lun; - int disconnect; - int i; + int disconnect, i; #ifdef OSIOP_DEBUG if (osiop_debug & DEBUG_DISC && @@ -954,10 +977,11 @@ osiop_start(sc) ds->cmd.count = acb->cmdlen; ds->cmd.addr = acb->cmddma->dm_segs[0].ds_addr; - ds->scsi_addr = (1 << (16 + target)) | (sc->sc_sync[target].sxfer << 8); + ti = &sc->sc_tinfo[target]; + ds->scsi_addr = ((1 << 16) << target) | (ti->sxfer << 8); disconnect = (xs->xs_control & XS_CTL_REQSENSE) == 0 && - (sc->sc_tinfo[target].flags & TI_NODISC) == 0; + (ti->flags & TI_NODISC) == 0; ds->msgout[0] = MSG_IDENTIFY(lun, disconnect); ds->id.count = 1; @@ -970,11 +994,14 @@ osiop_start(sc) * doesn't do wide transfers, just begin the synchronous transfer * negotation here. */ - if (sc->sc_sync[target].state == NEG_INIT) { - if ((sc->sc_tinfo[target].flags & TI_NOSYNC) != 0) { - sc->sc_sync[target].state = NEG_DONE; - sc->sc_sync[target].sbcl = 0; - sc->sc_sync[target].sxfer = 0; + if (ti->state == NEG_INIT) { + if ((ti->flags & TI_NOSYNC) != 0) { + ti->state = NEG_DONE; + ti->sbcl = 0; + ti->sxfer = 0; + ti->period = 0; + ti->offset = 0; + osiop_update_xfer_mode(sc, target); #ifdef OSIOP_DEBUG if (osiopsync_debug) printf("Forcing target %d asynchronous\n", @@ -987,8 +1014,8 @@ osiop_start(sc) ds->msgout[3] = MSG_EXT_SDTR; ds->msgout[4] = sc->sc_minsync; ds->msgout[5] = OSIOP_MAX_OFFSET; - ds->id.count = 6; - sc->sc_sync[target].state = NEG_WAITS; + ds->id.count = MSG_EXT_SDTR_LEN + 3; + ti->state = NEG_WAITS; #ifdef OSIOP_DEBUG if (osiopsync_debug) printf("Sending sync request to target %d\n", @@ -1046,7 +1073,7 @@ osiop_start(sc) printf("%s: osiop_select while connected?\n", sc->sc_dev.dv_xname); osiop_write_4(sc, OSIOP_TEMP, 0); - osiop_write_1(sc, OSIOP_SBCL, sc->sc_sync[target].sbcl); + osiop_write_1(sc, OSIOP_SBCL, ti->sbcl); osiop_write_4(sc, OSIOP_DSA, dsdma->dm_segs[0].ds_addr + acb->dsoffset); osiop_write_4(sc, OSIOP_DSP, @@ -1129,6 +1156,7 @@ osiop_checkintr(sc, istat, dstat, sstat0, status) if (dstat & OSIOP_DSTAT_SIR && intcode == A_ok) { /* Normal completion status, or check condition */ + struct osiop_tinfo *ti; #ifdef OSIOP_DEBUG if (osiop_read_4(sc, OSIOP_DSA) != dsdma->dm_segs[0].ds_addr + acb->dsoffset) { @@ -1139,19 +1167,18 @@ osiop_checkintr(sc, istat, dstat, sstat0, status) } #endif target = acb->xs->xs_periph->periph_target; - if (sc->sc_sync[target].state == NEG_WAITS) { + ti = &sc->sc_tinfo[target]; + if (ti->state == NEG_WAITS) { if (ds->msgbuf[1] == MSG_INVALID) printf("%s: target %d ignored sync request\n", sc->sc_dev.dv_xname, target); else if (ds->msgbuf[1] == MSG_MESSAGE_REJECT) printf("%s: target %d rejected sync request\n", sc->sc_dev.dv_xname, target); - else -/* XXX - need to set sync transfer parameters */ - printf("%s: target %d (sync) %02x %02x %02x\n", - sc->sc_dev.dv_xname, target, ds->msgbuf[1], - ds->msgbuf[2], ds->msgbuf[3]); - sc->sc_sync[target].state = NEG_DONE; + ti->period = 0; + ti->offset = 0; + osiop_update_xfer_mode(sc, target); + ti->state = NEG_DONE; } #ifdef OSIOP_DEBUG if (osiop_read_1(sc, OSIOP_SBCL) & OSIOP_BSY) { @@ -1179,6 +1206,7 @@ osiop_checkintr(sc, istat, dstat, sstat0, status) if (ds->msgbuf[1] == MSG_EXTENDED && ds->msgbuf[2] == MSG_EXT_SDTR_LEN && ds->msgbuf[3] == MSG_EXT_SDTR) { + struct osiop_tinfo *ti = &sc->sc_tinfo[target]; #ifdef OSIOP_DEBUG if (osiopsync_debug) printf("sync msg in: " @@ -1187,33 +1215,28 @@ osiop_checkintr(sc, istat, dstat, sstat0, status) ds->msgbuf[2], ds->msgbuf[3], ds->msgbuf[4], ds->msgbuf[5]); #endif - sc->sc_sync[target].sxfer = 0; - sc->sc_sync[target].sbcl = 0; - if (ds->msgbuf[2] == MSG_EXT_SDTR_LEN && - ds->msgbuf[3] == MSG_EXT_SDTR && - ds->msgbuf[5] != 0) { - printf("%s: target %d now synchronous, " - "period=%d ns, offset=%d\n", - sc->sc_dev.dv_xname, target, - ds->msgbuf[4] * 4, ds->msgbuf[5]); - scsi_period_to_osiop(sc, target); - } + ti->period = ds->msgbuf[4]; + ti->offset = ds->msgbuf[5]; + ti->sxfer = 0; + ti->sbcl = 0; + if (ds->msgbuf[5] != 0) + scsi_period_to_osiop(sc, target); + osiop_update_xfer_mode(sc, target); + bus_dmamap_sync(sc->sc_dmat, dsdma, acb->dsoffset, sizeof(struct osiop_ds), BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); - osiop_write_1(sc, OSIOP_SXFER, - sc->sc_sync[target].sxfer); - osiop_write_1(sc, OSIOP_SBCL, - sc->sc_sync[target].sbcl); - if (sc->sc_sync[target].state == NEG_WAITS) { - sc->sc_sync[target].state = NEG_DONE; + osiop_write_1(sc, OSIOP_SXFER, ti->sxfer); + osiop_write_1(sc, OSIOP_SBCL, ti->sbcl); + if (ti->state == NEG_WAITS) { + ti->state = NEG_DONE; osiop_write_4(sc, OSIOP_DSP, scraddr + Ent_clear_ack); return (0); } osiop_write_1(sc, OSIOP_DCNTL, osiop_read_1(sc, OSIOP_DCNTL) | OSIOP_DCNTL_STD); - sc->sc_sync[target].state = NEG_DONE; + ti->state = NEG_DONE; return (0); } /* XXX - not SDTR message */ @@ -1547,9 +1570,9 @@ osiop_checkintr(sc, istat, dstat, sstat0, status) osiop_write_4(sc, OSIOP_DSA, dsdma->dm_segs[0].ds_addr + acb->dsoffset); osiop_write_1(sc, OSIOP_SXFER, - sc->sc_sync[reselid].sxfer); + sc->sc_tinfo[reselid].sxfer); osiop_write_1(sc, OSIOP_SBCL, - sc->sc_sync[reselid].sbcl); + sc->sc_tinfo[reselid].sbcl); break; } if (acb == NULL) { @@ -1598,8 +1621,8 @@ osiop_checkintr(sc, istat, dstat, sstat0, status) osiop_write_4(sc, OSIOP_TEMP, 0); osiop_write_4(sc, OSIOP_DSA, dsdma->dm_segs[0].ds_addr + sc->sc_nexus->dsoffset); - osiop_write_1(sc, OSIOP_SXFER, sc->sc_sync[target].sxfer); - osiop_write_1(sc, OSIOP_SBCL, sc->sc_sync[target].sbcl); + osiop_write_1(sc, OSIOP_SXFER, sc->sc_tinfo[target].sxfer); + osiop_write_1(sc, OSIOP_SBCL, sc->sc_tinfo[target].sbcl); osiop_write_4(sc, OSIOP_DSP, scraddr + Ent_scripts); return (0); } @@ -1800,6 +1823,28 @@ osiop_intr(sc) splx(s); } +void +osiop_update_xfer_mode(sc, target) + struct osiop_softc *sc; + int target; +{ + struct osiop_tinfo *tinfo = &sc->sc_tinfo[target]; + struct scsipi_xfer_mode xm; + + xm.xm_target = target; + xm.xm_mode = 0; + xm.xm_period = 0; + xm.xm_offset = 0; + + if (tinfo->period) { + xm.xm_mode |= PERIPH_CAP_SYNC; + xm.xm_period = tinfo->period; + xm.xm_offset = tinfo->offset; + } + + scsipi_async_event(&sc->sc_channel, ASYNC_EVENT_XFER_MODE, &xm); +} + /* * This is based on the Progressive Peripherals 33Mhz Zeus driver and will * not be correct for other 53c710 boards. @@ -1810,13 +1855,13 @@ scsi_period_to_osiop(sc, target) struct osiop_softc *sc; int target; { - int period, offset, sxfer, sbcl = 0; + int period, offset, sxfer, sbcl; #ifdef DEBUG_SYNC int i; #endif - period = sc->sc_nexus->ds->msgbuf[4]; - offset = sc->sc_nexus->ds->msgbuf[5]; + period = sc->sc_tinfo[target].period; + offset = sc->sc_tinfo[target].offset; #ifdef DEBUG_SYNC sxfer = 0; if (offset <= OSIOP_MAX_OFFSET) @@ -1853,8 +1898,8 @@ scsi_period_to_osiop(sc, target) sc->sc_tcp[sbcl] * ((sxfer >> 4) + 4)); #endif } - sc->sc_sync[target].sxfer = sxfer; - sc->sc_sync[target].sbcl = sbcl; + sc->sc_tinfo[target].sxfer = sxfer; + sc->sc_tinfo[target].sbcl = sbcl; #ifdef DEBUG_SYNC printf("osiop sync: osiop_sxfr %02x, osiop_sbcl %02x\n", sxfer, sbcl); #endif diff --git a/sys/dev/ic/osiopvar.h b/sys/dev/ic/osiopvar.h index bbabd04ac703..9ff0c57f8d89 100644 --- a/sys/dev/ic/osiopvar.h +++ b/sys/dev/ic/osiopvar.h @@ -1,4 +1,4 @@ -/* $NetBSD: osiopvar.h,v 1.1 2001/04/30 04:47:51 tsutsui Exp $ */ +/* $NetBSD: osiopvar.h,v 1.2 2001/11/18 14:50:11 tsutsui Exp $ */ /* * Copyright (c) 2001 Izumi Tsutsui. All rights reserved. @@ -180,13 +180,15 @@ struct osiop_tinfo { int dconns; /* number of disconnects */ int touts; /* number of timeouts */ int perrs; /* number of parity errors */ - u_int8_t lubusy; /* What local units/subr. are busy? */ - u_int8_t period; /* Period suggestion */ - u_int8_t offset; /* Offset suggestion */ - u_int8_t flags; /* misc flags per each target */ + int lubusy; /* What local units/subr. are busy? */ + int period; /* Period suggestion */ + int offset; /* Offset suggestion */ + int flags; /* misc flags per each target */ #define TI_NOSYNC 0x01 /* disable sync xfer on this target */ #define TI_NODISC 0x02 /* disable disconnect on this target */ - + int state; /* negotiation state */ + u_int8_t sxfer; /* value for SXFER reg */ + u_int8_t sbcl; /* value for SBCL reg */ } tinfo_t; struct osiop_softc { @@ -228,15 +230,7 @@ struct osiop_softc { int sc_cfflags; /* copy of config flags */ - /* one for each target */ - struct syncpar { - u_int8_t state; - u_int8_t sxfer; - u_int8_t sbcl; - u_int8_t pad; - } sc_sync[OSIOP_NTGT]; - - u_int8_t sc_minsync; + int sc_minsync; u_int8_t sc_dstat; u_int8_t sc_sstat0; @@ -250,11 +244,9 @@ struct osiop_softc { /* negotiation states */ #define NEG_INIT 0 /* Initial negotiate state */ -#define NEG_WIDE 0 /* Negotiate wide transfers */ -#define NEG_WAITW 1 /* Waiting for wide negotation response */ -#define NEG_SYNC 2 /* Negotiate synch transfers */ -#define NEG_WAITS 3 /* Waiting for synch negoation response */ -#define NEG_DONE 4 /* Wide and/or sync negotation done */ +#define NEG_SYNC NEG_INIT /* Negotiate synch transfers */ +#define NEG_WAITS 1 /* Waiting for synch negoation response */ +#define NEG_DONE 2 /* Wide and/or sync negotation done */ void osiop_attach(struct osiop_softc *); void osiop_intr(struct osiop_softc *);