Rearrange for script changes (scheduler core in main script, command part

of the scheduler in command table).
Add tagged command queuing support.
This commit is contained in:
bouyer 2000-10-23 14:56:16 +00:00
parent 5113af09e3
commit 7777f61cbe
4 changed files with 588 additions and 454 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
/* $NetBSD: siop_common.c,v 1.9 2000/10/18 17:06:52 bouyer Exp $ */
/* $NetBSD: siop_common.c,v 1.10 2000/10/23 14:56:17 bouyer Exp $ */
/*
* Copyright (c) 2000 Manuel Bouyer.
@ -120,6 +120,54 @@ siop_common_reset(sc)
sc->sc_reset(sc);
}
/* prepare tables before sending a cmd */
void
siop_setuptables(siop_cmd)
struct siop_cmd *siop_cmd;
{
int i;
struct siop_softc *sc = siop_cmd->siop_sc;
struct scsipi_xfer *xs = siop_cmd->xs;
int target = xs->sc_link->scsipi_scsi.target;
int lun = xs->sc_link->scsipi_scsi.lun;
siop_cmd->siop_tables.id = htole32(sc->targets[target]->id);
memset(siop_cmd->siop_tables.msg_out, 0, 8);
siop_cmd->siop_tables.msg_out[0] = MSG_IDENTIFY(lun, 1);
siop_cmd->siop_tables.t_msgout.count= htole32(1);
if (sc->targets[target]->status == TARST_ASYNC) {
if (sc->targets[target]->flags & TARF_WIDE) {
sc->targets[target]->status = TARST_WIDE_NEG;
siop_wdtr_msg(siop_cmd, 1, MSG_EXT_WDTR_BUS_16_BIT);
} else if (sc->targets[target]->flags & TARF_SYNC) {
sc->targets[target]->status = TARST_SYNC_NEG;
siop_sdtr_msg(siop_cmd, 1, sc->minsync, sc->maxoff);
} else {
sc->targets[target]->status = TARST_OK;
}
} else if (sc->targets[target]->status == TARST_OK &&
(sc->targets[target]->flags & TARF_TAG) &&
(siop_cmd->status == CMDST_SENSE) == 0) {
siop_cmd->flags |= CMDFL_TAG;
}
siop_cmd->siop_tables.status = htole32(0xff); /* set invalid status */
siop_cmd->siop_tables.cmd.count =
htole32(siop_cmd->dmamap_cmd->dm_segs[0].ds_len);
siop_cmd->siop_tables.cmd.addr =
htole32(siop_cmd->dmamap_cmd->dm_segs[0].ds_addr);
if ((xs->xs_control & (XS_CTL_DATA_IN | XS_CTL_DATA_OUT)) ||
siop_cmd->status == CMDST_SENSE) {
for (i = 0; i < siop_cmd->dmamap_data->dm_nsegs; i++) {
siop_cmd->siop_tables.data[i].count =
htole32(siop_cmd->dmamap_data->dm_segs[i].ds_len);
siop_cmd->siop_tables.data[i].addr =
htole32(siop_cmd->dmamap_data->dm_segs[i].ds_addr);
}
}
siop_table_sync(siop_cmd, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
}
int
siop_wdtr_neg(siop_cmd)
struct siop_cmd *siop_cmd;
@ -158,7 +206,6 @@ siop_wdtr_neg(siop_cmd)
"target %d (%d)\n", sc->sc_dev.dv_xname, target,
tables->msg_in[3]);
tables->t_msgout.count= htole32(1);
tables->t_msgout.addr = htole32(siop_cmd->dsa);
tables->msg_out[0] = MSG_MESSAGE_REJECT;
return SIOP_NEG_MSGOUT;
}
@ -169,13 +216,7 @@ siop_wdtr_neg(siop_cmd)
/* we now need to do sync */
if (siop_target->flags & TARF_SYNC) {
siop_target->status = TARST_SYNC_NEG;
tables->msg_out[0] = MSG_EXTENDED;
tables->msg_out[1] = MSG_EXT_SDTR_LEN;
tables->msg_out[2] = MSG_EXT_SDTR;
tables->msg_out[3] = sc->minsync;
tables->msg_out[4] = sc->maxoff;
tables->t_msgout.count = htole32(MSG_EXT_SDTR_LEN + 2);
tables->t_msgout.addr = htole32(siop_cmd->dsa);
siop_sdtr_msg(siop_cmd, 0, sc->minsync, sc->maxoff);
return SIOP_NEG_MSGOUT;
} else {
siop_target->status = TARST_OK;
@ -189,13 +230,11 @@ siop_wdtr_neg(siop_cmd)
sc->sc_dev.dv_xname, target);
siop_target->flags |= TARF_ISWIDE;
sc->targets[target]->id |= SCNTL3_EWS << 24;
tables->msg_out[3] = MSG_EXT_WDTR_BUS_16_BIT;
} else {
printf("%s: target %d using 8bit transfers\n",
sc->sc_dev.dv_xname, target);
siop_target->flags &= ~TARF_ISWIDE;
sc->targets[target]->id &= ~(SCNTL3_EWS << 24);
tables->msg_out[3] = MSG_EXT_WDTR_BUS_8_BIT;
}
tables->id = htole32(sc->targets[target]->id);
bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL3,
@ -205,12 +244,8 @@ siop_wdtr_neg(siop_cmd)
* but don't schedule a sync neg, target should initiate it
*/
siop_target->status = TARST_OK;
tables->msg_out[0] = MSG_EXTENDED;
tables->msg_out[1] = MSG_EXT_WDTR_LEN;
tables->msg_out[2] = MSG_EXT_WDTR;
tables->t_msgout.count=
htole32(MSG_EXT_WDTR_LEN + 2);
tables->t_msgout.addr = htole32(siop_cmd->dsa);
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;
}
}
@ -312,13 +347,7 @@ reject:
~(SXFER_MO_MASK << 8);
sc->targets[target]->id |=
(offset & SXFER_MO_MASK) << 8;
tables->msg_out[0] = MSG_EXTENDED;
tables->msg_out[1] = MSG_EXT_SDTR_LEN;
tables->msg_out[2] = MSG_EXT_SDTR;
tables->msg_out[3] = sync;
tables->msg_out[4] = offset;
tables->t_msgout.count=
htole32(MSG_EXT_SDTR_LEN + 2);
siop_sdtr_msg(siop_cmd, 0, sync, offset);
send_msgout = 1;
goto end;
}
@ -329,13 +358,7 @@ async:
sc->targets[target]->id &= ~(SCNTL3_SCF_MASK << 24);
sc->targets[target]->id &= ~(SCNTL3_ULTRA << 24);
sc->targets[target]->id &= ~(SXFER_MO_MASK << 8);
tables->msg_out[0] = MSG_EXTENDED;
tables->msg_out[1] = MSG_EXT_SDTR_LEN;
tables->msg_out[2] = MSG_EXT_SDTR;
tables->msg_out[3] = 0;
tables->msg_out[4] = 0;
tables->t_msgout.count=
htole32(MSG_EXT_SDTR_LEN + 2);
siop_sdtr_msg(siop_cmd, 0, 0, 0);
send_msgout = 1;
}
end:
@ -348,13 +371,40 @@ end:
bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SXFER,
(sc->targets[target]->id >> 8) & 0xff);
if (send_msgout) {
tables->t_msgout.addr = htole32(siop_cmd->dsa);
return SIOP_NEG_MSGOUT;
} else {
return SIOP_NEG_ACK;
}
}
void
siop_sdtr_msg(siop_cmd, offset, ssync, soff)
struct siop_cmd *siop_cmd;
int offset;
int ssync, soff;
{
siop_cmd->siop_tables.msg_out[offset + 0] = MSG_EXTENDED;
siop_cmd->siop_tables.msg_out[offset + 1] = MSG_EXT_SDTR_LEN;
siop_cmd->siop_tables.msg_out[offset + 2] = MSG_EXT_SDTR;
siop_cmd->siop_tables.msg_out[offset + 3] = ssync;
siop_cmd->siop_tables.msg_out[offset + 4] = soff;
siop_cmd->siop_tables.t_msgout.count =
htole32(offset + MSG_EXT_SDTR_LEN + 2);
}
void
siop_wdtr_msg(siop_cmd, offset, wide)
struct siop_cmd *siop_cmd;
int offset;
{
siop_cmd->siop_tables.msg_out[offset + 0] = MSG_EXTENDED;
siop_cmd->siop_tables.msg_out[offset + 1] = MSG_EXT_WDTR_LEN;
siop_cmd->siop_tables.msg_out[offset + 2] = MSG_EXT_WDTR;
siop_cmd->siop_tables.msg_out[offset + 3] = wide;
siop_cmd->siop_tables.t_msgout.count =
htole32(offset + MSG_EXT_WDTR_LEN + 2);
}
void
siop_minphys(bp)
struct buf *bp;
@ -380,23 +430,30 @@ siop_ioctl(link, cmd, arg, flag, p)
struct scbusaccel_args *sp = (struct scbusaccel_args *)arg;
s = splbio();
if (sp->sa_lun == 0) {
#if 0
if (sp->sa_flags & SC_ACCEL_TAGS) {
sc->targets[sp->sa_target]->flags |= TARF_TAG;
printf("%s: target %d using tagged queuing\n",
sc->sc_dev.dv_xname, sp->sa_target);
sc->sc_dev.dv_xname, sp->sa_target);
}
#endif
if ((sp->sa_flags & SC_ACCEL_WIDE) &&
(sc->features & SF_BUS_WIDE))
sc->targets[sp->sa_target]->flags |= TARF_WIDE;
if (sp->sa_flags & SC_ACCEL_SYNC)
sc->targets[sp->sa_target]->flags |= TARF_SYNC;
if (sp->sa_flags & (SC_ACCEL_SYNC | SC_ACCEL_WIDE) &&
sc->targets[sp->sa_target]->status > TARST_ASYNC)
if ((sp->sa_flags & (SC_ACCEL_SYNC | SC_ACCEL_WIDE)) ||
sc->targets[sp->sa_target]->status == TARST_PROBING)
sc->targets[sp->sa_target]->status =
TARST_ASYNC;
}
/* allocate a lun sw entry for this device */
siop_add_dev(sc, sp->sa_target, sp->sa_lun);
/*
* if we can to tagged queueing, inform upper layer
* we can have NIOP_NTAG concurent commands
*/
if (sc->targets[sp->sa_target]->flags & TARF_TAG)
link->openings = SIOP_NTAG;
splx(s);
return 0;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: siopvar.h,v 1.11 2000/10/18 17:06:52 bouyer Exp $ */
/* $NetBSD: siopvar.h,v 1.12 2000/10/23 14:56:17 bouyer Exp $ */
/*
* Copyright (c) 2000 Manuel Bouyer.
@ -41,6 +41,7 @@ struct siop_softc {
struct device sc_dev;
struct scsipi_link sc_link; /* link to upper level */
int features; /* chip's features */
int ram_size;
int maxburst;
int maxoff;
int clock_div; /* async. clock divider (scntl3) */
@ -52,21 +53,20 @@ struct siop_softc {
bus_addr_t sc_raddr; /* register adresses */
bus_space_tag_t sc_ramt; /* bus_space ram tag */
bus_space_handle_t sc_ramh; /* bus_space ram handle */
bus_addr_t sc_scriptaddr; /* on-board ram or physical adress */
bus_dma_tag_t sc_dmat; /* bus DMA tag */
void (*sc_reset) __P((struct siop_softc*)); /* reset callback */
bus_dmamap_t sc_scriptdma; /* DMA map for script */
bus_dmamap_t sc_scheddma; /* DMA map for sched script */
bus_addr_t sc_scriptaddr; /* on-board ram or physical adress */
u_int32_t *sc_script; /* script location in memory */
u_int32_t *sc_sched; /* script scheduler location in mem */
int sc_nschedslots; /* number of scheduler slots */
int sc_currschedslot; /* current scheduler slot */
struct cbd_list cmds; /* list of command block descriptors */
struct cmd_list free_list; /* cmd descr free list */
struct cmd_list ready_list; /* cmd descr ready list */
struct lunsw_list lunsw_list; /* lunsw free list */
u_int32_t ram_free; /* free ram offset from sc_scriptaddr */
u_int32_t script_free_lo; /* free ram offset from sc_scriptaddr */
u_int32_t script_free_hi; /* free ram offset from sc_scriptaddr */
struct siop_target *targets[16]; /* per-target states */
int sc_ntargets; /* number of known targets */
u_int32_t sc_flags;
};
/* defs for sc_flags */

View File

@ -1,4 +1,4 @@
/* $NetBSD: siopvar_common.h,v 1.6 2000/10/18 17:06:52 bouyer Exp $ */
/* $NetBSD: siopvar_common.h,v 1.7 2000/10/23 14:56:17 bouyer Exp $ */
/*
* Copyright (c) 2000 Manuel Bouyer.
@ -45,6 +45,9 @@ typedef struct scr_table {
/* Number of scatter/gather entries */
#define SIOP_NSG (MAXPHYS/NBPG + 1)
/* Number of tag */
#define SIOP_NTAG 16
/*
* This structure interfaces the SCRIPT with the driver; it describes a full
* transfer.
@ -59,18 +62,17 @@ struct siop_xfer_common {
scr_table_t t_msgin; /* 32 */
scr_table_t t_extmsgin; /* 40 */
scr_table_t t_extmsgdata; /* 48 */
scr_table_t t_msgtag; /* 56 */
scr_table_t t_msgout; /* 64 */
scr_table_t cmd; /* 72 */
scr_table_t t_status; /* 80 */
scr_table_t data[SIOP_NSG]; /* 88 */
scr_table_t t_msgout; /* 56 */
scr_table_t cmd; /* 64 */
scr_table_t t_status; /* 72 */
scr_table_t data[SIOP_NSG]; /* 80 */
} __attribute__((__packed__));
/* xfer description of the script: tables and reselect script */
struct siop_xfer {
struct siop_xfer_common tables;
/* u_int32_t resel[sizeof(load_dsa) / sizeof(load_dsa[0])]; */
u_int32_t resel[14];
u_int32_t resel[24];
} __attribute__((__packed__));
/*
@ -90,9 +92,10 @@ struct siop_cmd {
bus_dmamap_t dmamap_cmd;
bus_dmamap_t dmamap_data;
struct scsipi_sense rs_cmd; /* request sense command buffer */
int status;
int flags;
int reselslot; /* the reselect slot used */
int status;
int flags;
int reselslot; /* the reselect slot used */
int tag; /* tag used for tagged command queuing */
};
/* command block descriptors: an array of siop_cmd + an array of siop_xfer */
@ -116,20 +119,29 @@ struct siop_cbd {
#define CMDFL_TIMEOUT 0x0001 /* cmd timed out */
#define CMDFL_TAG 0x0002 /* tagged cmd */
/* per-tag struct */
struct siop_tag {
struct siop_cmd *active; /* active command */
u_int reseloff; /* XXX */
};
/* per lun struct */
struct siop_lun {
struct siop_cmd *active; /* active command */
int reseloff; /* XXX tmp */
struct siop_tag siop_tag[SIOP_NTAG]; /* tag array */
int lun_flags; /* per-lun flags, see below */
u_int reseloff; /* XXX */
};
#define SIOP_LUNF_FULL 0x01 /* queue full message */
/* per-target struct */
struct siop_target {
int status; /* target status, see below */
int flags; /* target flags, see below */
u_int32_t id; /* for SELECT FROM */
struct siop_lun siop_lun[8]; /* per-lun state, XXX should be dynamic */
int reseloff; /* XXX tmp */
struct siop_lunsw *lunsw; /* XXX tmp */
struct siop_lun *siop_lun[8]; /* per-lun state */
u_int reseloff; /* XXX */
struct siop_lunsw *lunsw; /* XXX */
};
/* target status */
@ -148,13 +160,32 @@ struct siop_target {
struct siop_lunsw {
TAILQ_ENTRY (siop_lunsw) next;
u_int32_t lunsw_off; /* offset of this lun sw, from sc_scriptaddr*/
u_int32_t lunsw_size; /* size of this lun sw */
};
static __inline__ void siop_table_sync __P((struct siop_cmd *, int));
static __inline__ void
siop_table_sync(siop_cmd, ops)
struct siop_cmd *siop_cmd;
int ops;
{
struct siop_softc *sc = siop_cmd->siop_sc;
bus_addr_t offset;
offset = siop_cmd->dsa -
siop_cmd->siop_cbdp->xferdma->dm_segs[0].ds_addr;
bus_dmamap_sync(sc->sc_dmat, siop_cmd->siop_cbdp->xferdma, offset,
sizeof(struct siop_xfer), ops);
}
void siop_common_reset __P((struct siop_softc *));
void siop_setuptables __P((struct siop_cmd *));
int siop_modechange __P((struct siop_softc *));
int siop_wdtr_neg __P((struct siop_cmd *siop_cmd));
int siop_sdtr_neg __P((struct siop_cmd *siop_cmd));
int siop_wdtr_neg __P((struct siop_cmd *));
int siop_sdtr_neg __P((struct siop_cmd *));
void siop_sdtr_msg __P((struct siop_cmd *, int, int, int));
void siop_wdtr_msg __P((struct siop_cmd *, int, int));
/* actions to take at return of siop_wdtr_neg() and siop_sdtr_neg() */
#define SIOP_NEG_NOP 0x0
#define SIOP_NEG_MSGOUT 0x1
@ -166,3 +197,6 @@ int siop_ioctl __P((struct scsipi_link *, u_long,
void siop_sdp __P((struct siop_cmd *));
void siop_clearfifo __P((struct siop_softc *));
void siop_resetbus __P((struct siop_softc *));
/* XXXX should be callbacks */
void siop_add_dev __P((struct siop_softc *, int, int));
void siop_del_dev __P((struct siop_softc *, int, int));