- 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
This commit is contained in:
tsutsui 2001-11-18 14:50:11 +00:00
parent 689089f7a9
commit aca8e01877
2 changed files with 108 additions and 71 deletions

View File

@ -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

View File

@ -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 *);