summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authortsutsui <tsutsui@NetBSD.org>2001-11-18 14:50:11 +0000
committertsutsui <tsutsui@NetBSD.org>2001-11-18 14:50:11 +0000
commitaca8e01877e03e794a28045c7f2c3bad96bf700f (patch)
tree816d1db822781ef55c1b40b4b5a9e220e87d209a /sys/dev
parent689089f7a9e61bd346d7d1f49c44fef2d8956b87 (diff)
- 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
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ic/osiop.c147
-rw-r--r--sys/dev/ic/osiopvar.h32
2 files changed, 108 insertions, 71 deletions
diff --git a/sys/dev/ic/osiop.c b/sys/dev/ic/osiop.c
index 81cd3dad0ba..a76ab3de4a4 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 <sys/cdefs.h>
-__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 bbabd04ac70..9ff0c57f8d8 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 *);