diff options
Diffstat (limited to 'sys/dev/ic')
-rw-r--r-- | sys/dev/ic/siop.c | 161 | ||||
-rw-r--r-- | sys/dev/ic/siop_common.c | 279 | ||||
-rw-r--r-- | sys/dev/ic/siopreg.h | 69 | ||||
-rw-r--r-- | sys/dev/ic/siopvar.h | 8 | ||||
-rw-r--r-- | sys/dev/ic/siopvar_common.h | 65 |
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)); |