📄 bs.c
字号:
} bs_hostque_head(bsc, ti); BS_SELECTION_TERMINATE BS_SETUP_PHASE(HOSTQUEUE)#ifdef BS_STATICS bs_statics[ti->ti_id].select_miss_by_reselect++; bs_statics[ti->ti_id].select_miss++;#endif /* BS_STATICS */ } /* who are you ? */ target = bshw_get_src_id(bsc); if ((ti = bsc->sc_ti[target]) == NULL) { bs_debug_print_all(bsc); printf("reselect: miss reselect. target(%d)\n", target); bs_reset_nexus(bsc); return NULL; } /* confirm nexus */ BS_HOST_START bshw_setup_ctrl_reg(bsc, ti->ti_cfgflags); if (ti->ti_ctab.tqh_first == NULL || ti->ti_phase != DISCONNECTED) { bs_printf(ti, "reselect", "phase mismatch"); BS_SETUP_PHASE(UNDEF) bs_force_abort(ti); bs_hostque_delete(bsc, ti); } else bsc->sc_dtgnum --; /* recover host */ bshw_set_dst_id(bsc, ti->ti_id, ti->ti_lun); bshw_set_sync_reg(bsc, ti->ti_sync); BS_RESTORE_SDP BS_SETUP_PHASE(RESELECTED)#ifdef BS_STATICS bs_statics[ti->ti_id].reselect++;#endif /* BS_STATICS */ return ti;}static BS_INLINE voidbs_sat_continue(bsc, ti, cb) struct bs_softc *bsc; struct targ_info *ti; struct ccb *cb;{ BS_SETUP_PHASE(SATRESEL); bshw_set_dst_id(bsc, ti->ti_id, ti->ti_lun); bshw_cmd_pass(bsc, 0x44); bshw_set_sync_reg(bsc, ti->ti_sync); bshw_issue_satcmd(bsc, cb, 0); if (bs_check_smit(ti) || bsc->sc_p.datalen <= 0) bshw_set_count(bsc, 0); else bs_dma_xfer(ti, BSHW_CMD_CHECK(cb, BSREAD)); bshw_set_lun(bsc, ti->ti_lun); /* XXX */ bshw_start_sat(bsc, 0);}/************************************************* * <DATA PHASE> *************************************************/#define DR (STR_BSY | STR_DBR)voidbs_poll_timeout(bsc, s) struct bs_softc *bsc; char *s;{ struct targ_info *ti; bs_printf(NULL, s, "timeout"); bsc->sc_flags |= BSRESET; if ((ti = bsc->sc_nexus) && ti->ti_ctab.tqh_first) ti->ti_error |= BSTIMEOUT;}static BS_INLINE u_int8_tbs_read_1byte(bsc) struct bs_softc *bsc;{ register u_int wc; bshw_start_sxfer(bsc); for (wc = bsc->sc_wc; (bshw_get_auxstat(bsc) & DR) != DR && --wc; ); if (wc) return bshw_read_data(bsc); else bs_poll_timeout(bsc, "read_1byte"); return 0;}static BS_INLINE voidbs_write_1byte(bsc, data) struct bs_softc *bsc; u_int8_t data;{ register u_int wc; bshw_start_sxfer(bsc); for (wc = bsc->sc_wc; (bshw_get_auxstat(bsc) & DR) != DR && --wc; ); if (wc) bshw_write_data(bsc, data); else bs_poll_timeout(bsc, "write_1byte");}static intbs_xfer(bsc, data, len) struct bs_softc *bsc; char *data; int len;{ u_int8_t aux; u_int count, wc; bshw_set_count(bsc, len); bshw_start_xfer(bsc); for (count = 0, wc = bsc->sc_wc; count < len && --wc; ) { if (((aux = bshw_get_auxstat(bsc)) & DR) == DR) { if (bsc->sc_busstat & BSHW_READ) *(data++) = bshw_read_data(bsc); else bshw_write_data(bsc, *(data++)); count++; wc = bsc->sc_wc; } if (aux & STR_INT) break; } if (wc == 0) bs_poll_timeout(bsc, "bs_xfer"); return count;}#undef DRstatic voidbs_io_xfer(ti) struct targ_info *ti;{ struct bs_softc *bsc = ti->ti_bsc; struct sc_p *sp = &bsc->sc_p; u_int count, dummy; /* switch dma trasnfr mode */ bshw_set_poll_trans(bsc, ti->ti_cfgflags); sp->seglen = 0; sp->bufp = NULL; if (sp->datalen <= 0) { ti->ti_error |= BSDMAABNORMAL; dummy = 0; count = bs_xfer(bsc, (u_int8_t *) &dummy, 1); } else count = bs_xfer(bsc, sp->data, sp->datalen); sp->data += count; sp->datalen -= count;}/************************************************ * <COMMAND PHASE> ************************************************/static BS_INLINE voidbs_commandout(bsc, ti, cb) struct bs_softc *bsc; struct targ_info *ti; struct ccb *cb;{ u_int8_t scsi_cmd[16]; int len; BS_SETUP_PHASE(CMDPHASE); if (bs_check_link(ti, cb)) { bcopy(cb->cmd, scsi_cmd, cb->cmdlen); scsi_cmd[cb->cmdlen - 1] |= 0x01; len = bs_xfer(bsc, scsi_cmd, cb->cmdlen); } else len = bs_xfer(bsc, cb->cmd, cb->cmdlen); if (len != cb->cmdlen) ti->ti_error |= BSCMDABNORMAL;}/************************************************ * <STATUS IN> ************************************************/static BS_INLINE voidbs_status_check(bsc, ti) struct bs_softc *bsc; struct targ_info *ti;{ if (ti->ti_status == ST_GOOD || ti->ti_status == ST_INTERGOOD) return; switch (ti->ti_status) { case ST_MET: case ST_INTERMET: case ST_CHKCOND: ti->ti_error |= BSREQSENSE; break; case ST_BUSY: ti->ti_error |= BSTARGETBUSY; break; default: ti->ti_error |= BSSTATUSERROR; break; }}/************************************************ * <MSG IN> ************************************************/#define MSGWAIT(cnt) { if (ti->ti_msginptr < (cnt)) return; }static voidbs_quick_abort(ti, msg) struct targ_info *ti; u_int msg;{ struct ccb *cb; if ((cb = ti->ti_ctab.tqh_first) == NULL) return; cb->msgoutlen = 1; cb->msgout[0] = msg; cb->rcnt++; ti->ti_error |= BSMSGERROR;}static voidbs_msgin_error(ti, count) struct targ_info *ti; u_int count;{ int n; MSGWAIT(count); bs_printf(ti, "msgin", "illegal msg"); for (n = 0; n < ti->ti_msginptr; n ++) printf("[0x%x] ", (u_int) ti->ti_msgin[n]); printf("\n"); bs_quick_abort(ti, MSG_REJECT); ti->ti_msginptr = 0;}static voidbs_msgin_ext(ti) struct targ_info *ti;{ struct bs_softc *bsc = ti->ti_bsc; struct ccb *cb = ti->ti_ctab.tqh_first; int count; u_int reqlen; u_int32_t *ptr; struct msgbase msg; MSGWAIT(2); reqlen = ti->ti_msgin[1]; if (reqlen == 0) reqlen = 256; if (ti->ti_msginptr >= MAXMSGLEN) ti->ti_msginptr = 3; /* XXX */ MSGWAIT(reqlen + 2); switch (MKMSG_EXTEND(ti->ti_msgin[1], ti->ti_msgin[2])) { case MKMSG_EXTEND(MSG_EXTEND_MDPLEN, MSG_EXTEND_MDPCODE): ptr = (u_int32_t *)(&ti->ti_msgin[3]); count = (int) htonl((long) (*ptr)); bsc->sc_p.seglen = ti->ti_scsp.seglen = 0; if (bsc->sc_p.datalen - count >= 0 && bsc->sc_p.datalen - count <= cb->datalen) { bsc->sc_p.datalen -= count; bsc->sc_p.data += count; } else bs_msgin_error(ti, 7); break; case MKMSG_EXTEND(MSG_EXTEND_SYNCHLEN, MSG_EXTEND_SYNCHCODE): ti->ti_syncnow.period = ti->ti_msgin[3]; ti->ti_syncnow.offset = ti->ti_msgin[4]; if (ti->ti_syncnow.offset == 0) ti->ti_syncnow.period = 0; if (ti->ti_syncnow.state != BS_SYNCMSG_ASSERT) { bs_start_syncmsg(ti, NULL, BS_SYNCMSG_REQUESTED); bscmdstart(ti, BSCMDSTART); } else BS_SETUP_SYNCSTATE(BS_SYNCMSG_ACCEPT) break; case MKMSG_EXTEND(MSG_EXTEND_WIDELEN, MSG_EXTEND_WIDECODE): msg.msglen = MSG_EXTEND_WIDELEN + 2; msg.msg[0] = MSG_EXTEND; msg.msg[1] = MSG_EXTEND_WIDELEN; msg.msg[2] = MSG_EXTEND_WIDECODE; msg.msg[3] = 0; msg.flag = 0; bs_make_msg_ccb(ti, cb->lun, cb, &msg, 0); break; default: bs_msgin_error(ti, 0); return; } ti->ti_msginptr = 0; return;}static voidbs_msg_reject(ti) struct targ_info *ti;{ struct bs_softc *bsc = ti->ti_bsc; struct ccb *cb = ti->ti_ctab.tqh_first; char *s = "unexpected msg reject"; switch (ti->ti_ophase) { case CMDPHASE: s = "cmd rejected"; cb->flags &= ~BSLINK; BS_SETUP_MSGPHASE(IOCOMPLETED); break; case MSGOUT: if (ti->ti_msgout & 0x80) { s = "identify msg rejected"; cb->flags &= ~BSDISC; BS_SETUP_MSGPHASE(IOCOMPLETED); } else if (ti->ti_msgout == MSG_EXTEND) { switch (ti->ti_emsgout) { case MSG_EXTEND_SYNCHCODE: BS_SETUP_SYNCSTATE(BS_SYNCMSG_REJECT); return; default: break; } } break; default: break; } bs_debug_print(bsc, ti); bs_printf(ti, "msgin", s); ti->ti_error |= BSMSGERROR;}static BS_INLINE voidbs_msgin(bsc, ti) struct bs_softc *bsc; struct targ_info *ti;{ BS_SETUP_PHASE(MSGIN); switch (ti->ti_msgin[0]) { case MSG_SAVESP: BS_SAVE_SDP break; case MSG_RESTORESP: BS_RESTORE_SDP bs_printf(ti, "msgin", "restore scsi pointer"); break; case MSG_REJECT: bs_msg_reject(ti); break; case 0xf: break; case MSG_I_ERROR:/* all I -> T : nothing to do*/ case MSG_ABORT: case MSG_PARITY: case MSG_RESET: case 0xe: bs_msgin_error(ti, 1); goto resume; case MSG_NOOP: break; case MSG_EXTEND: bs_msgin_ext(ti); goto resume; case 0xd: bs_msgin_error(ti, 2); goto resume; case MSG_DISCON: BS_SETUP_MSGPHASE(DISCONNECTASSERT); break; case MSG_COMP: BS_SETUP_MSGPHASE(IOCOMPLETED); break; case MSG_LCOMP: case MSG_LCOMP_F: bs_status_check(bsc, ti); if (bscmddone(ti) == NULL) { if (bscmdstart(ti, BSCMDSTART) == 0) { bs_printf(ti, "msgin", "cmd line miss"); bs_force_abort(ti); } } else bscmdstart(ti, BSCMDRESTART);#ifdef BS_STATICS bs_linkcmd_count[ti->ti_id]++;#endif /* BS_STATICS */ BS_LOAD_SDP ti->ti_status = ST_UNK; break; default: if (ti->ti_msgin[0] & 0x80) { if ((ti->ti_msgin[0] & 0x07) != ti->ti_lun) { ti->ti_lun = (ti->ti_msgin[0] & 0x07); bshw_set_dst_id(bsc, ti->ti_id, ti->ti_lun); bshw_set_sync_reg(bsc, ti->ti_sync); bs_printf(ti, "msgin", "lun error"); bs_quick_abort(ti, MSG_ABORT); } break; } else if (ti->ti_msgin[0] < 0x20) bs_msgin_error(ti, 1); else if (ti->ti_msgin[0] < 0x30) bs_msgin_error(ti, 2); else bs_msgin_error(ti, 1); goto resume; } ti->ti_msginptr = 0;resume: return;}/************************************************ * <MSG OUT> ************************************************/static BS_INLINE voidbs_msgout(bsc, ti, cb) struct bs_softc *bsc; struct targ_info *ti; struct ccb *cb;{ u_int8_t msg[MAXMSGLEN + 1]; if (ti->ti_phase == MSGOUT) { if (cb->rcnt ++ < bsc->sc_retry) cb->msgoutlen = ti->ti_omsgoutlen; } else BS_SETUP_PHASE(MSGOUT); if (ti->ti_ophase == SELECTED) {identify: if (cb->msgoutlen == 0) { ti->ti_msgout = bs_identify_msg(ti); ti->ti_omsgoutlen = 0; bs_write_1byte(bsc, ti->ti_msgout); } else { if (cb->msgout[0] != MSG_RESET && cb->msgout[0] != MSG_ABORT) { msg[0] = bs_identify_msg(ti); bcopy(cb->msgout, &msg[1], cb->msgoutlen); bs_xfer(bsc, msg, cb->msgoutlen + 1); } else bs_xfer(bsc, cb->msgout, cb->msgoutlen); ti->ti_msgout = cb->msgout[0]; ti->ti_emsgout = cb->msgout[2]; ti->ti_omsgoutlen = cb->msgoutlen; cb->msgoutlen = 0; } return; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -