summaryrefslogtreecommitdiff
path: root/sys/dev/ic
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/ic')
-rw-r--r--sys/dev/ic/siop.c161
-rw-r--r--sys/dev/ic/siop_common.c279
-rw-r--r--sys/dev/ic/siopreg.h69
-rw-r--r--sys/dev/ic/siopvar.h8
-rw-r--r--sys/dev/ic/siopvar_common.h65
5 files changed, 393 insertions, 189 deletions
diff --git a/sys/dev/ic/siop.c b/sys/dev/ic/siop.c
index c855a7c456f..d74355488dc 100644
--- a/sys/dev/ic/siop.c
+++ b/sys/dev/ic/siop.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: siop.c,v 1.5 2001/03/06 16:29:32 krw Exp $ */
+/* $OpenBSD: siop.c,v 1.6 2001/04/15 06:01:28 krw Exp $ */
/* $NetBSD: siop.c,v 1.39 2001/02/11 18:04:49 bouyer Exp $ */
/*
@@ -229,19 +229,24 @@ siop_attach(sc)
for (i = 0; i < 16; i++)
sc->targets[i] = NULL;
- /* find min/max sync period for this chip */
- sc->maxsync = 0;
- sc->minsync = 255;
- for (i = 0; i < sizeof(scf_period) / sizeof(scf_period[0]); i++) {
- if (sc->clock_period != scf_period[i].clock)
- continue;
- if (sc->maxsync < scf_period[i].period)
- sc->maxsync = scf_period[i].period;
- if (sc->minsync > scf_period[i].period)
- sc->minsync = scf_period[i].period;
- }
- if (sc->maxsync == 255 || sc->minsync == 0)
- panic("siop: can't find my sync parameters\n");
+ /* find min_dt_sync and min_st_sync for this chip */
+ sc->min_dt_sync = 0;
+ for (i = 0; i < sizeof(period_factor) / sizeof(period_factor[0]); i++)
+ if (period_factor[i].scf[sc->scf_index].dt_scf != 0) {
+ sc->min_dt_sync = period_factor[i].factor;
+ break;
+ }
+
+ sc->min_st_sync = 0;
+ for (i = 0; i < sizeof(period_factor) / sizeof(period_factor[0]); i++)
+ if (period_factor[i].scf[sc->scf_index].st_scf != 0) {
+ sc->min_st_sync = period_factor[i].factor;
+ break;
+ }
+
+ if (sc->min_st_sync == 0)
+ panic("%s: can't find minimum allowed sync period factor\n", sc->sc_dev.dv_xname);
+
/* Do a bus reset, so that devices fall back to narrow/async */
siop_resetbus(sc);
/*
@@ -742,7 +747,7 @@ scintr:
}
siop_target->status = TARST_SYNC_NEG;
siop_sdtr_msg(siop_cmd, 0,
- sc->minsync, sc->maxoff);
+ sc->min_st_sync, sc->maxoff);
siop_table_sync(siop_cmd,
BUS_DMASYNC_PREREAD |
BUS_DMASYNC_PREWRITE);
@@ -809,6 +814,7 @@ scintr:
CALL_SCRIPT(Ent_get_extmsgdata);
return 1;
case A_int_extmsgdata:
+ {
#ifdef SIOP_DEBUG_INTR
{
int i;
@@ -821,55 +827,56 @@ scintr:
printf("\n");
}
#endif
- if (siop_cmd->siop_tables.msg_in[2] == MSG_EXT_WDTR) {
- switch (siop_wdtr_neg(siop_cmd)) {
- case SIOP_NEG_MSGOUT:
- siop_update_scntl3(sc,
- siop_cmd->siop_target);
- siop_table_sync(siop_cmd,
- BUS_DMASYNC_PREREAD |
- BUS_DMASYNC_PREWRITE);
- CALL_SCRIPT(Ent_send_msgout);
- return(1);
- case SIOP_NEG_ACK:
- siop_update_scntl3(sc,
- siop_cmd->siop_target);
- CALL_SCRIPT(Ent_msgin_ack);
- return(1);
- default:
- panic("invalid retval from "
- "siop_wdtr_neg()");
- }
- return(1);
+ int neg_action = SIOP_NEG_NOP;
+ const char *neg_name = "";
+
+ switch (siop_cmd->siop_tables.msg_in[2]) {
+ case MSG_EXT_WDTR:
+ neg_action = siop_wdtr_neg(siop_cmd);
+ neg_name = "wdtr";
+ break;
+ case MSG_EXT_SDTR:
+ neg_action = siop_sdtr_neg(siop_cmd);
+ neg_name = "sdtr";
+ break;
+ case MSG_EXT_PPR:
+ neg_action = siop_ppr_neg(siop_cmd);
+ neg_name = "ppr";
+ break;
+ default:
+ neg_action = SIOP_NEG_MSGREJ;
+ break;
}
- if (siop_cmd->siop_tables.msg_in[2] == MSG_EXT_SDTR) {
- switch (siop_sdtr_neg(siop_cmd)) {
- case SIOP_NEG_MSGOUT:
- siop_update_scntl3(sc,
- siop_cmd->siop_target);
- siop_table_sync(siop_cmd,
- BUS_DMASYNC_PREREAD |
- BUS_DMASYNC_PREWRITE);
- CALL_SCRIPT(Ent_send_msgout);
- return(1);
- case SIOP_NEG_ACK:
- siop_update_scntl3(sc,
- siop_cmd->siop_target);
- CALL_SCRIPT(Ent_msgin_ack);
- return(1);
- default:
- panic("invalid retval from "
- "siop_wdtr_neg()");
- }
- return(1);
+
+ switch (neg_action) {
+ case SIOP_NEG_NOP:
+ break;
+ case SIOP_NEG_MSGOUT:
+ siop_update_scntl3(sc, siop_cmd->siop_target);
+ siop_table_sync(siop_cmd,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+ CALL_SCRIPT(Ent_send_msgout);
+ break;
+ case SIOP_NEG_ACK:
+ siop_update_scntl3(sc, siop_cmd->siop_target);
+ siop_table_sync(siop_cmd,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+ CALL_SCRIPT(Ent_msgin_ack);
+ break;
+ case SIOP_NEG_MSGREJ:
+ siop_cmd->siop_tables.msg_out[0] = MSG_MESSAGE_REJECT;
+ siop_cmd->siop_tables.t_msgout.count = htole32(1);
+ siop_table_sync(siop_cmd,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+ CALL_SCRIPT(Ent_send_msgout);
+ break;
+ default:
+ panic("invalid return value from siop_%s_neg(): 0x%x", neg_name, neg_action);
}
- /* send a message reject */
- siop_cmd->siop_tables.msg_out[0] = MSG_MESSAGE_REJECT;
- siop_cmd->siop_tables.t_msgout.count = htole32(1);
- siop_table_sync(siop_cmd,
- BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
- CALL_SCRIPT(Ent_send_msgout);
- return 1;
+
+ return (1);
+ }
+
case A_int_disc:
INCSTAT(siop_stat_intr_sdp);
offset = bus_space_read_1(sc->sc_rt, sc->sc_rh,
@@ -1180,7 +1187,7 @@ siop_handle_reset(sc)
}
}
sc->targets[target]->status = TARST_ASYNC;
- sc->targets[target]->flags &= ~TARF_ISWIDE;
+ sc->targets[target]->flags &= ~(TARF_ISWIDE | TARF_ISDT | TARF_ISQAS | TARF_ISIUS);
}
/* Next commands from the urgent list */
for (siop_cmd = TAILQ_FIRST(&sc->urgent_list); siop_cmd != NULL;
@@ -1363,11 +1370,19 @@ siop_scsicmd(xs)
sc->targets[target]->flags |= TARF_TAG;
xs->sc_link->openings += SIOP_NTAG - SIOP_OPENINGS;
}
+
if ((inqdata->flags & SID_WBus16) && (sc->features & SF_BUS_WIDE))
sc->targets[target]->flags |= TARF_WIDE;
if (inqdata->flags & SID_Sync)
sc->targets[target]->flags |= TARF_SYNC;
- if (sc->targets[target]->flags & (TARF_WIDE | TARF_SYNC)) {
+
+ if ((sc->features & SF_CHIP_C10)
+ && (sc->targets[target]->flags & TARF_WIDE)
+ && (inqdata->flags2 & (SID_CLOCKING | SID_QAS | SID_IUS)))
+ sc->targets[target]->flags |= TARF_PPR;
+
+ if (sc->targets[target]->flags
+ & (TARF_WIDE | TARF_SYNC | TARF_PPR)) {
sc->targets[target]->status = TARST_ASYNC;
siop_add_dev(sc, target, lun);
}
@@ -1728,13 +1743,13 @@ siop_morecbd(sc)
newcbd->cmds[i].siop_tables.t_msgout.count= htole32(1);
newcbd->cmds[i].siop_tables.t_msgout.addr = htole32(dsa);
newcbd->cmds[i].siop_tables.t_msgin.count= htole32(1);
- newcbd->cmds[i].siop_tables.t_msgin.addr = htole32(dsa + 8);
+ newcbd->cmds[i].siop_tables.t_msgin.addr = htole32(dsa + 16);
newcbd->cmds[i].siop_tables.t_extmsgin.count= htole32(2);
- newcbd->cmds[i].siop_tables.t_extmsgin.addr = htole32(dsa + 9);
+ newcbd->cmds[i].siop_tables.t_extmsgin.addr = htole32(dsa + 17);
newcbd->cmds[i].siop_tables.t_extmsgdata.addr =
- htole32(dsa + 11);
+ htole32(dsa + 19);
newcbd->cmds[i].siop_tables.t_status.count= htole32(1);
- newcbd->cmds[i].siop_tables.t_status.addr = htole32(dsa + 16);
+ newcbd->cmds[i].siop_tables.t_status.addr = htole32(dsa + 32);
/* The select/reselect script */
scr = &newcbd->cmds[i].siop_xfer->resel[0];
@@ -1894,6 +1909,16 @@ siop_update_scntl3(sc, siop_target)
siop_script_write(sc,
siop_target->lunsw->lunsw_off + (Ent_restore_scntl3 / 4) + 2,
0x78050000 | (siop_target->id & 0x0000ff00));
+ /* If DT, change null op ('MOVE 0xff TO SFBR') to 'MOVE n TO SCNTL4' */
+ if (siop_target->flags & TARF_ISDT)
+ siop_script_write(sc,
+ siop_target->lunsw->lunsw_off + (Ent_restore_scntl3 / 4) + 4,
+ 0x78bc0000 | ((siop_target->id << 8) & 0x0000ff00));
+ else
+ siop_script_write(sc,
+ siop_target->lunsw->lunsw_off + (Ent_restore_scntl3 / 4) + 4,
+ 0x7808ff00);
+
siop_script_sync(sc, BUS_DMASYNC_PREWRITE);
}
diff --git a/sys/dev/ic/siop_common.c b/sys/dev/ic/siop_common.c
index 47e1fd813c9..186f967e47b 100644
--- a/sys/dev/ic/siop_common.c
+++ b/sys/dev/ic/siop_common.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: siop_common.c,v 1.5 2001/03/10 05:04:06 krw Exp $ */
+/* $OpenBSD: siop_common.c,v 1.6 2001/04/15 06:01:29 krw Exp $ */
/* $NetBSD: siop_common.c,v 1.12 2001/02/11 18:04:50 bouyer Exp $ */
/*
@@ -71,6 +71,8 @@ siop_common_reset(sc)
SCNTL0_ARB_MASK | SCNTL0_EPC | SCNTL0_AAP);
bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL1, 0);
bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL3, sc->clock_div);
+ if (sc->features & SF_CHIP_C10)
+ bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL4, 0);
bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SXFER, 0);
bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_DIEN, 0xff);
bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SIEN0,
@@ -129,6 +131,7 @@ siop_setuptables(siop_cmd)
struct scsi_xfer *xs = siop_cmd->xs;
int target = xs->sc_link->target;
int lun = xs->sc_link->lun;
+ int targ_flags = sc->targets[target]->flags;
siop_cmd->siop_tables.id = htole32(sc->targets[target]->id);
memset(siop_cmd->siop_tables.msg_out, 0, 8);
@@ -138,18 +141,24 @@ siop_setuptables(siop_cmd)
siop_cmd->siop_tables.msg_out[0] = MSG_IDENTIFY(lun, 0);
siop_cmd->siop_tables.t_msgout.count= htole32(1);
if (sc->targets[target]->status == TARST_ASYNC) {
- if (sc->targets[target]->flags & TARF_WIDE) {
+ if (targ_flags & TARF_PPR) {
+ sc->targets[target]->status = TARST_PPR_NEG;
+ if (sc->min_dt_sync != 0)
+ siop_ppr_msg(siop_cmd, 1, sc->min_dt_sync, sc->maxoff);
+ else
+ siop_ppr_msg(siop_cmd, 1, sc->min_st_sync, sc->maxoff);
+ } else if (targ_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) {
+ } else if (targ_flags & TARF_SYNC) {
sc->targets[target]->status = TARST_SYNC_NEG;
- siop_sdtr_msg(siop_cmd, 1, sc->minsync, sc->maxoff);
+ siop_sdtr_msg(siop_cmd, 1, sc->min_st_sync, sc->maxoff);
} else {
sc->targets[target]->status = TARST_OK;
siop_print_info(sc, target);
}
} else if (sc->targets[target]->status == TARST_OK &&
- (sc->targets[target]->flags & TARF_TAG) &&
+ (targ_flags & TARF_TAG) &&
siop_cmd->status != CMDST_SENSE) {
siop_cmd->flags |= CMDFL_TAG;
}
@@ -173,6 +182,81 @@ siop_setuptables(siop_cmd)
}
int
+siop_ppr_neg(siop_cmd)
+ struct siop_cmd *siop_cmd;
+{
+ struct siop_softc *sc = siop_cmd->siop_sc;
+ struct siop_target *siop_target = siop_cmd->siop_target;
+ int target = siop_cmd->xs->sc_link->target;
+ struct siop_xfer_common *tables = &siop_cmd->siop_xfer->tables;
+ int offset, sync, protocol, scf;
+
+ sync = tables->msg_in[3];
+ offset = tables->msg_in[5];
+ protocol = tables->msg_in[7];
+
+#ifdef DEBUG
+ printf("%s: siop_ppr_neg: sync = %x, offset = %x, protocol = %x\n",
+ sc->sc_dev.dv_xname, sync, offset, protocol);
+#endif
+ /*
+ * Process protocol bits first, because finding the correct scf
+ * via siop_period_factor_to_scf() requires the TARF_ISDT flag
+ * to be correctly set.
+ */
+ if (protocol & MSG_EXT_PPR_PROT_IUS)
+ siop_target->flags |= TARF_ISIUS;
+
+ if (protocol & MSG_EXT_PPR_PROT_DT) {
+ siop_target->flags |= TARF_ISDT;
+ sc->targets[target]->id |= SCNTL4_ULTRA3;
+ }
+
+ if (protocol & MSG_EXT_PPR_PROT_QAS)
+ siop_target->flags |= TARF_ISQAS;
+
+ scf = siop_period_factor_to_scf(sc, sync, siop_target->flags);
+
+ if ((offset > sc->maxoff) ||
+ (scf == 0) ||
+ ((siop_target->flags & TARF_ISDT) && (offset == 1))) {
+ tables->t_msgout.count= htole32(1);
+ tables->msg_out[0] = MSG_MESSAGE_REJECT;
+ return (SIOP_NEG_MSGOUT);
+ }
+
+ siop_target->id |= scf << (24 + SCNTL3_SCF_SHIFT);
+
+ if (((sc->features & SF_CHIP_C10) == 0) && (sync < 25))
+ siop_target->id |= SCNTL3_ULTRA << 24;
+
+ siop_target->id |= (offset & 0xff) << 8;
+
+ if (tables->msg_in[6] == MSG_EXT_WDTR_BUS_16_BIT) {
+ siop_target->flags |= TARF_ISWIDE;
+ sc->targets[target]->id |= (SCNTL3_EWS << 24);
+ }
+
+#ifdef DEBUG
+ printf("%s: siop_ppr_neg: id now 0x%x, flags is now 0x%x\n",
+ sc->sc_dev.dv_xname, siop_target->id, siop_target->flags);
+#endif
+ tables->id = htole32(siop_target->id);
+ bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL3,
+ (siop_target->id >> 24) & 0xff);
+ bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SXFER,
+ (siop_target->id >> 8) & 0xff);
+ /* Only cards with SCNTL4 can cause PPR negotiations, so ... */
+ bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL4,
+ (siop_target->id & 0xff));
+
+ siop_target->status = TARST_OK;
+ siop_print_info(sc, target);
+
+ return (SIOP_NEG_ACK);
+}
+
+int
siop_wdtr_neg(siop_cmd)
struct siop_cmd *siop_cmd;
{
@@ -181,17 +265,17 @@ siop_wdtr_neg(siop_cmd)
int target = siop_cmd->xs->sc_link->target;
struct siop_xfer_common *tables = &siop_cmd->siop_xfer->tables;
- /* revert to async until told otherwise */
- sc->targets[target]->id &= ~(SCNTL3_SCF_MASK << 24);
- sc->targets[target]->id &= ~(SCNTL3_ULTRA << 24);
- sc->targets[target]->id &= ~(SXFER_MO_MASK << 8);
+ /* revert to narrow async until told otherwise */
+ sc->targets[target]->id &= 0x07ff0000; /* Keep SCNTL3.CCF and id */
+ sc->targets[target]->flags &= ~(TARF_ISWIDE | TARF_ISDT | TARF_ISQAS | TARF_ISIUS);
tables->id = htole32(sc->targets[target]->id);
bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL3,
(sc->targets[target]->id >> 24) & 0xff);
- bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SXFER,
- (sc->targets[target]->id >> 8) & 0xff);
+ bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SXFER, 0);
+ if (sc->features & SF_CHIP_C10)
+ bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL4, 0);
if (siop_target->status == TARST_WIDE_NEG) {
/* we initiated wide negotiation */
@@ -229,7 +313,7 @@ siop_wdtr_neg(siop_cmd)
/* we now need to do sync */
if (siop_target->flags & TARF_SYNC) {
siop_target->status = TARST_SYNC_NEG;
- siop_sdtr_msg(siop_cmd, 0, sc->minsync, sc->maxoff);
+ siop_sdtr_msg(siop_cmd, 0, sc->min_st_sync, sc->maxoff);
return SIOP_NEG_MSGOUT;
} else {
siop_target->status = TARST_OK;
@@ -269,7 +353,7 @@ siop_sdtr_neg(siop_cmd)
struct siop_softc *sc = siop_cmd->siop_sc;
struct siop_target *siop_target = siop_cmd->siop_target;
int target = siop_cmd->xs->sc_link->target;
- int sync, offset, i;
+ int sync, offset, scf;
int send_msgout = 0;
struct siop_xfer_common *tables = &siop_cmd->siop_xfer->tables;
@@ -277,35 +361,23 @@ siop_sdtr_neg(siop_cmd)
offset = tables->msg_in[4];
/* revert to async until told otherwise */
- sc->targets[target]->id &= ~(SCNTL3_SCF_MASK << 24);
- sc->targets[target]->id &= ~(SCNTL3_ULTRA << 24);
- sc->targets[target]->id &= ~(SXFER_MO_MASK << 8);
+ sc->targets[target]->id &= 0x0fff0000; /* Keep SCNTL3.EWS, SCNTL3.CCF and id */
+ sc->targets[target]->flags &= ~(TARF_ISDT | TARF_ISQAS | TARF_ISIUS);
if (siop_target->status == TARST_SYNC_NEG) {
/* we initiated sync negotiation */
#ifdef DEBUG
- printf("sdtr: sync %d offset %d\n", sync, offset);
+ printf("%s: sdtr for target %d: sync %d offset %d\n",
+ sc->sc_dev.dv_xname, target, sync, offset);
#endif
- if (offset > sc->maxoff || sync < sc->minsync ||
- sync > sc->maxsync)
+ scf = siop_period_factor_to_scf(sc, sync, sc->targets[target]->flags);
+ if (offset > sc->maxoff || scf == 0)
goto reject;
- for (i = 0; i < sizeof(scf_period) / sizeof(scf_period[0]);
- i++) {
- if (sc->clock_period != scf_period[i].clock)
- continue;
- if (scf_period[i].period == sync) {
- /* ok, found it. we now are sync. */
- sc->targets[target]->id |= scf_period[i].scf
- << (24 + SCNTL3_SCF_SHIFT);
- if ((sync < 25)
- && ((sc->features & SF_CHIP_C10) == 0))
- sc->targets[target]->id |=
- SCNTL3_ULTRA << 24;
- sc->targets[target]->id |=
- (offset & SXFER_MO_MASK) << 8;
- goto end;
- }
- }
+ sc->targets[target]->id |= scf << (24 + SCNTL3_SCF_SHIFT);
+ if (((sc->features & SF_CHIP_C10) == 0) && (sync < 25))
+ sc->targets[target]->id |= SCNTL3_ULTRA << 24;
+ sc->targets[target]->id |= (offset & 0xff) << 8;
+ goto end;
/*
* We didn't find it in our table, so stay async and send reject
* msg.
@@ -316,37 +388,30 @@ reject:
tables->msg_out[0] = MSG_MESSAGE_REJECT;
} else { /* target initiated sync neg */
#ifdef DEBUG
+ printf("%s: target initiated sdtr for target %d: sync %d offset %d\n",
+ sc->sc_dev.dv_xname, target, sync, offset);
printf("sdtr (target): sync %d offset %d\n", sync, offset);
#endif
+ if (sync < sc->min_st_sync)
+ sync = sc->min_st_sync;
+ scf = siop_period_factor_to_scf(sc, sync, sc->targets[target]->flags);
if ((sc->targets[target]->flags & TARF_SYNC) == 0
|| offset == 0
- || sync > sc->maxsync) {
+ || scf == 0) {
goto async;
}
+ if ((offset > 31) && ((sc->targets[target]->flags & TARF_ISDT) == 0))
+ offset = 31;
if (offset > sc->maxoff)
offset = sc->maxoff;
- if (sync < sc->minsync)
- sync = sc->minsync;
- /* look for sync period */
- for (i = 0; i < sizeof(scf_period) / sizeof(scf_period[0]);
- i++) {
- if (sc->clock_period != scf_period[i].clock)
- continue;
- if (scf_period[i].period == sync) {
- /* ok, found it. we now are sync. */
- sc->targets[target]->id |= scf_period[i].scf
- << (24 + SCNTL3_SCF_SHIFT);
- if ((sync < 25)
- && ((sc->features & SF_CHIP_C10) == 0))
- sc->targets[target]->id |=
- SCNTL3_ULTRA << 24;
- sc->targets[target]->id |=
- (offset & SXFER_MO_MASK) << 8;
- siop_sdtr_msg(siop_cmd, 0, sync, offset);
- send_msgout = 1;
- goto end;
- }
- }
+
+ sc->targets[target]->id |= scf << (24 + SCNTL3_SCF_SHIFT);
+ if (((sc->features & SF_CHIP_C10) == 0) && (sync < 25))
+ sc->targets[target]->id |= SCNTL3_ULTRA << 24;
+ sc->targets[target]->id |= (offset & 0xff) << 8;
+ siop_sdtr_msg(siop_cmd, 0, sync, offset);
+ send_msgout = 1;
+ goto end;
async:
siop_sdtr_msg(siop_cmd, 0, 0, 0);
send_msgout = 1;
@@ -374,6 +439,40 @@ end:
}
void
+siop_ppr_msg(siop_cmd, offset, ssync, soff)
+ struct siop_cmd *siop_cmd;
+ int offset, ssync, soff;
+{
+ struct siop_softc *sc = siop_cmd->siop_sc;
+ u_int8_t protocol;
+
+ siop_cmd->siop_tables.msg_out[offset + 0] = MSG_EXTENDED;
+ siop_cmd->siop_tables.msg_out[offset + 1] = MSG_EXT_PPR_LEN;
+ siop_cmd->siop_tables.msg_out[offset + 2] = MSG_EXT_PPR;
+ siop_cmd->siop_tables.msg_out[offset + 3] = ssync;
+ siop_cmd->siop_tables.msg_out[offset + 4] = 0; /* RESERVED */
+ siop_cmd->siop_tables.msg_out[offset + 5] = soff;
+ siop_cmd->siop_tables.msg_out[offset + 6] = MSG_EXT_WDTR_BUS_16_BIT;
+
+ protocol = 0;
+ if (sc->min_dt_sync != 0)
+ protocol |= MSG_EXT_PPR_PROT_DT;
+
+ /* XXX - need tests for chip's capability to do QAS & IUS
+ *
+ * if (test for QAS support)
+ * protocol |= MSG_EXT_PPR_PROT_QAS;
+ * if (test for IUS support)
+ * protocol |= MSG_EXT_PPR_PROT_IUS;
+ */
+
+ siop_cmd->siop_tables.msg_out[offset + 7] = protocol;
+
+ siop_cmd->siop_tables.t_msgout.count =
+ htole32(offset + MSG_EXT_PPR_LEN + 2);
+}
+
+void
siop_sdtr_msg(siop_cmd, offset, ssync, soff)
struct siop_cmd *siop_cmd;
int offset;
@@ -383,6 +482,10 @@ siop_sdtr_msg(siop_cmd, offset, ssync, soff)
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;
+
+ if ((soff > 31) && ((siop_cmd->siop_target->flags & TARF_ISDT) == 0))
+ soff = 31;
+
siop_cmd->siop_tables.msg_out[offset + 4] = soff;
siop_cmd->siop_tables.t_msgout.count =
htole32(offset + MSG_EXT_SDTR_LEN + 2);
@@ -585,30 +688,62 @@ siop_print_info(sc, target)
{
struct siop_target *siop_target = sc->targets[target];
u_int8_t scf, offset;
- int clock, i;
+ int scf_index, i;
+
+ const int factors = sizeof(period_factor) / sizeof(period_factor[0]);
+
+ offset = ((siop_target->id >> 8) & 0xff) >> SXFER_MO_SHIFT;
- offset = ((siop_target->id >> 8) & SXFER_MO_MASK) >> SXFER_MO_SHIFT;
scf = ((siop_target->id >> 24) & SCNTL3_SCF_MASK) >> SCNTL3_SCF_SHIFT;
- clock = sc->clock_period;
+ scf_index = sc->scf_index;
- printf("%s: target %d now using%s%d bit ",
+ printf("%s: target %d now using %s%s%s%s%d bit ",
sc->sc_dev.dv_xname, target,
- (siop_target->flags & TARF_TAG) ? " tagged " : " ",
+ (siop_target->flags & TARF_TAG) ? "tagged " : "",
+ (siop_target->flags & TARF_ISDT) ? "DT " : "",
+ (siop_target->flags & TARF_ISQAS) ? "QAS " : "",
+ (siop_target->flags & TARF_ISIUS) ? "IUS " : "",
(siop_target->flags & TARF_ISWIDE) ? 16 : 8);
if (offset == 0)
printf("async ");
- else {
- for (i = 0; i < sizeof(scf_period) / sizeof(scf_period[0]); i++)
- if ((scf_period[i].clock == clock)
- && (scf_period[i].scf == scf)) {
- printf("%s ", scf_period[i].rate);
- break;
+ else {
+ for (i = 0; i < factors; i++)
+ if (siop_target->flags & TARF_ISDT) {
+ if (period_factor[i].scf[scf_index].dt_scf == scf)
+ break;
}
- if (i == sizeof(scf_period) / sizeof(scf_period[0]))
- printf("? ");
+ else if (period_factor[i].scf[scf_index].st_scf == scf)
+ break;
+
+ if (i >= factors)
+ printf("?? ");
+ else
+ printf("%s ", period_factor[i].rate);
+
printf("MHz %d REQ/ACK offset ", offset);
}
printf("xfers\n");
}
+
+int
+siop_period_factor_to_scf(sc, pf, flags)
+ struct siop_softc *sc;
+ int pf, flags;
+{
+ const int scf_index = sc->scf_index;
+ int i;
+
+ const int factors = sizeof(period_factor) / sizeof(period_factor[0]);
+
+ for (i = 0; i < factors; i++)
+ if (period_factor[i].factor == pf) {
+ if (flags & TARF_ISDT)
+ return (period_factor[i].scf[scf_index].dt_scf);
+ else
+ return (period_factor[i].scf[scf_index].st_scf);
+ }
+
+ return (0);
+}
diff --git a/sys/dev/ic/siopreg.h b/sys/dev/ic/siopreg.h
index dc02816b7c4..c7bfde8e2a8 100644
--- a/sys/dev/ic/siopreg.h
+++ b/sys/dev/ic/siopreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: siopreg.h,v 1.2 2001/03/10 05:04:06 krw Exp $ */
+/* $OpenBSD: siopreg.h,v 1.3 2001/04/15 06:01:29 krw Exp $ */
/* $NetBSD: siopreg.h,v 1.7 2000/10/06 16:35:13 bouyer Exp $ */
/*
@@ -74,28 +74,49 @@
#define SCNTL3_CCF_SHIFT 0
#define SCNTL3_CCF_MASK 0x07
-/* periods for various SCF values, assume transfer period of 4 */
-struct scf_period {
- int clock; /* clock period (ns * 10) */
- int period; /* scsi period, as set in the SDTR message */
- int scf; /* scf value to use */
- char *rate; /* the resulting rate */
+#define SIOP_CLOCKS_SUPPORTED 3 /* 3 supported clocks: 25, 12.5, 6.25 ns */
+
+struct period_factor {
+ int factor; /* transfer period factor from sdtr/ppr */
+ char *rate; /* string describing transfer rate */
+ struct {
+ int st_scf;
+ int dt_scf;
+ } scf[SIOP_CLOCKS_SUPPORTED];
+ /* scf value to use in SCNTL3[6:4]
+ * 0 == SCLK/3
+ * 1 == SCLK/1
+ * 2 == SCLK/1.5
+ * 3 == SCLK/2
+ * 4 == SCLK/3
+ * 5 == SCLK/4
+ * 6 == SCLK/6
+ * 7 == SCLK/8
+ *
+ * One entry for each different clock
+ * supported, showing appropriate scf
+ * for the period_factor requested. A
+ * value of 0 indicates the rate is
+ * not supported.
+ *
+ * scf[0] == scf for a 25ns cycle
+ * scf[1] == scf for a 12.5 ns cycle
+ * scf[2] == scf for a 6.25 ns cycle
+ *
+ * min sync = first non zero in column
+ * max sync = last non zero in column
+ */
};
-static const struct scf_period scf_period[] __attribute__((__unused__)) = {
- {250, 25, 1, "10.0"},
- {250, 37, 2, "6.67"},
- {250, 50, 3, "5.0"},
- {250, 75, 4, "3.33"},
- {125, 12, 1, "20.0"},
- {125, 18, 2, "13.33"},
- {125, 25, 3, "10.0"},
- {125, 37, 4, "6.67"},
- {125, 50, 5, "5.0"},
- { 62, 10, 1, "40.0"},
- { 62, 12, 3, "20.0"},
- { 62, 18, 4, "13.3"},
- { 62, 25, 5, "10.0"},
+static const struct period_factor period_factor[] __attribute__((__unused__)) = {
+ {0x09, "80", {{0,0},{0,0},{0,1}}},
+ {0x0a, "40", {{0,0},{0,0},{1,3}}},
+ {0x0c, "20", {{0,0},{1,0},{3,5}}},
+ {0x12, "13.3", {{0,0},{2,0},{4,6}}},
+ {0x19, "10", {{1,0},{3,0},{5,7}}},
+ {0x25, "6.67", {{2,0},{4,0},{6,0}}},
+ {0x32, "5", {{3,0},{5,0},{7,0}}},
+ {0x4b, "3.33", {{4,0},{6,0},{0,0}}},
};
#define SIOP_SCID 0x04 /* SCSI chip ID R/W */
@@ -108,7 +129,7 @@ static const struct scf_period scf_period[] __attribute__((__unused__)) = {
#define SXFER_TP_SHIFT 5
#define SXFER_TP_MASK 0xe0
#define SXFER_MO_SHIFT 0
-#define SXFER_MO_MASK 0x1f
+#define SXFER_MO_MASK 0x1f
#define SIOP_SDID 0x06 /* SCSI destiation ID, R/W */
#define SDID_ENCID_SHIFT 0
@@ -376,4 +397,8 @@ static const struct scf_period scf_period[] __attribute__((__unused__)) = {
#define SIOP_SCRATCHJ 0x7c /* Scratch register J, R/W, 875-only */
+#define SIOP_SCNTL4 0xbc
+#define SCNTL4_ULTRA3 0x80
+#define SCNTL4_AIP 0x40
+
#define SIOP_DFBC 0xf0 /* DMA FIFO byte count, RO, C10-only */
diff --git a/sys/dev/ic/siopvar.h b/sys/dev/ic/siopvar.h
index b5ca1393cb1..e61fd9730b6 100644
--- a/sys/dev/ic/siopvar.h
+++ b/sys/dev/ic/siopvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: siopvar.h,v 1.3 2001/03/10 05:04:06 krw Exp $ */
+/* $OpenBSD: siopvar.h,v 1.4 2001/04/15 06:01:29 krw Exp $ */
/* $NetBSD: siopvar.h,v 1.13 2000/10/23 23:18:11 bouyer Exp $ */
/*
@@ -46,9 +46,9 @@ struct siop_softc {
int maxburst;
int maxoff;
int clock_div; /* async. clock divider (scntl3) */
- int clock_period; /* clock period (ns * 10) */
- int minsync; /* min and max sync period, */
- int maxsync; /* as sent in SDTR message */
+ int min_dt_sync; /* minimum acceptable double transition sync */
+ int min_st_sync; /* minimum acceptable single transition sync */
+ int scf_index; /* clock id == index into period_factor[].scf */
bus_space_tag_t sc_rt; /* bus_space registers tag */
bus_space_handle_t sc_rh; /* bus_space registers handle */
bus_addr_t sc_raddr; /* register adresses */
diff --git a/sys/dev/ic/siopvar_common.h b/sys/dev/ic/siopvar_common.h
index 565618cd043..f02c2d4127c 100644
--- a/sys/dev/ic/siopvar_common.h
+++ b/sys/dev/ic/siopvar_common.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: siopvar_common.h,v 1.3 2001/03/06 16:29:32 krw Exp $ */
+/* $OpenBSD: siopvar_common.h,v 1.4 2001/04/15 06:01:29 krw Exp $ */
/* $NetBSD: siopvar_common.h,v 1.10 2001/01/26 21:58:56 bouyer Exp $ */
/*
@@ -57,22 +57,22 @@ typedef struct scr_table {
* transfer.
*/
struct siop_xfer_common {
- u_int8_t msg_out[8]; /* 0 */
- u_int8_t msg_in[8]; /* 8 */
- u_int32_t status; /* 16 */
- u_int32_t pad1; /* 20 */
- u_int32_t id; /* 24 */
- u_int32_t pad2; /* 28 */
- scr_table_t t_msgin; /* 32 */
- scr_table_t t_extmsgin; /* 40 */
- scr_table_t t_extmsgdata; /* 48 */
- scr_table_t t_msgout; /* 56 */
- scr_table_t cmd; /* 64 */
- scr_table_t t_status; /* 72 */
- scr_table_t data[SIOP_NSG]; /* 80 */
+ u_int8_t msg_out[16]; /* 0 */
+ u_int8_t msg_in[16]; /* 16 */
+ u_int32_t status; /* 32 */
+ u_int32_t pad1; /* 36 */
+ u_int32_t id; /* 40 */
+ u_int32_t pad2; /* 44 */
+ scr_table_t t_msgin; /* 48 */
+ scr_table_t t_extmsgin; /* 56 */
+ scr_table_t t_extmsgdata; /* 64 */
+ scr_table_t t_msgout; /* 72 */
+ scr_table_t cmd; /* 80 */
+ scr_table_t t_status; /* 88 */
+ scr_table_t data[SIOP_NSG]; /* 96 */
} __attribute__((__packed__));
-/* status can hold the SCSI_* status values, and 2 additionnal values: */
+/* status can hold the SCSI_* status values, and 2 additional values: */
#define SCSI_SIOP_NOCHECK 0xfe /* don't check the scsi status */
#define SCSI_SIOP_NOSTATUS 0xff /* device didn't report status */
@@ -146,7 +146,12 @@ struct siop_lun {
struct siop_target {
int status; /* target status, see below */
int flags; /* target flags, see below */
- u_int32_t id; /* for SELECT FROM */
+ u_int32_t id; /* for SELECT FROM
+ * 31-24 == SCNTL3
+ * 23-16 == SCSI id
+ * 15- 8 == SXFER
+ * 7- 0 == SCNTL4
+ */
struct siop_lun *siop_lun[8]; /* per-lun state */
u_int reseloff; /* XXX */
struct siop_lunsw *lunsw; /* XXX */
@@ -157,13 +162,19 @@ struct siop_target {
#define TARST_ASYNC 1 /* target needs sync/wide negotiation */
#define TARST_WIDE_NEG 2 /* target is doing wide negotiation */
#define TARST_SYNC_NEG 3 /* target is doing sync negotiation */
-#define TARST_OK 4 /* sync/wide agreement is valid */
+#define TARST_PPR_NEG 4 /* target is doing PPR (Parallel Protocol Request) */
+#define TARST_OK 5 /* sync/wide agreement is valid */
/* target flags */
-#define TARF_SYNC 0x01 /* target can do sync */
-#define TARF_WIDE 0x02 /* target can do wide */
-#define TARF_TAG 0x04 /* target can do tags */
-#define TARF_ISWIDE 0x08 /* target is wide */
+#define TARF_SYNC 0x01 /* target can do sync xfers */
+#define TARF_WIDE 0x02 /* target can do wide xfers */
+#define TARF_TAG 0x04 /* target can do taggged queuing */
+#define TARF_PPR 0x08 /* target can do PPR negotiation */
+
+#define TARF_ISWIDE 0x10 /* target is using wide xfers */
+#define TARF_ISIUS 0x20 /* target is using IUS */
+#define TARF_ISDT 0x40 /* target is using DT */
+#define TARF_ISQAS 0x80 /* target is using QAS */
struct siop_lunsw {
TAILQ_ENTRY (siop_lunsw) next;
@@ -177,7 +188,7 @@ siop_table_sync(siop_cmd, ops)
struct siop_cmd *siop_cmd;
int ops;
{
- struct siop_softc *sc = siop_cmd->siop_sc;
+ struct siop_softc *sc = siop_cmd->siop_sc;
bus_dmamap_sync(sc->sc_dmat, siop_cmd->siop_cbdp->xferdma, ops);
}
@@ -187,18 +198,26 @@ int siop_modechange __P((struct siop_softc *));
int siop_wdtr_neg __P((struct siop_cmd *));
int siop_sdtr_neg __P((struct siop_cmd *));
+int siop_ppr_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() */
+void siop_ppr_msg __P((struct siop_cmd *, int, int, int));
+
+/* actions to take at return of siop_<xxx>_neg() */
#define SIOP_NEG_NOP 0x0
#define SIOP_NEG_MSGOUT 0x1
#define SIOP_NEG_ACK 0x2
+#define SIOP_NEG_MSGREJ 0x3
void siop_print_info __P((struct siop_softc *, int));
void siop_minphys __P((struct buf *));
void siop_sdp __P((struct siop_cmd *));
void siop_clearfifo __P((struct siop_softc *));
void siop_resetbus __P((struct siop_softc *));
+
+int siop_period_factor_to_scf __P((struct siop_softc *, int, int));
+int siop_scf_to_period_factor __P((struct siop_softc *, int, int));
+
/* XXXX should be callbacks */
void siop_add_dev __P((struct siop_softc *, int, int));
void siop_del_dev __P((struct siop_softc *, int, int));