summaryrefslogtreecommitdiff
path: root/sys/dev/ic/siop.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/ic/siop.c')
-rw-r--r--sys/dev/ic/siop.c161
1 files changed, 93 insertions, 68 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);
}