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:
parent
5113af09e3
commit
7777f61cbe
File diff suppressed because it is too large
Load Diff
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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));
|
||||
|
|
Loading…
Reference in New Issue