📄 bs.c
字号:
if (ti->ti_ophase == SATSEL) { /* XXX: * Maybe identify msg rejected due to * a parity error in target side. */ bs_printf(ti, "msgout", "msg identify retry (SAT)"); goto identify; } if (cb->msgoutlen == 0) { ti->ti_msgout = MSG_REJECT; ti->ti_omsgoutlen = 0; bs_write_1byte(bsc, ti->ti_msgout); } else { ti->ti_msgout = cb->msgout[0]; ti->ti_emsgout = cb->msgout[2]; ti->ti_omsgoutlen = cb->msgoutlen; bs_xfer(bsc, cb->msgout, cb->msgoutlen); cb->msgoutlen = 0; }}/************************************************ * <DISCONNECT> ************************************************/static BS_INLINE voidbs_disconnect_phase(bsc, ti, cb) struct bs_softc *bsc; struct targ_info *ti; struct ccb *cb;{ switch (bsc->sc_msgphase) { default: panic("%s unknown msg phase\n", bsc->sc_dvname); break; case DISCONNECTASSERT: case FREE:#ifdef BS_STATICS bs_statics[ti->ti_id].disconnected++;#endif /* BS_STATICS */ if (ti->ti_cfgflags & BS_SCSI_SAVESP) BS_SAVE_SDP; BS_HOST_TERMINATE; BS_SETUP_PHASE(DISCONNECTED); bsc->sc_dtgnum ++; bshoststart(bsc, NULL); break; case IOCOMPLETED: bs_status_check(bsc, ti); cb = bscmddone(ti);#ifdef BS_DIAG ti->ti_flags &= ~BSNEXUS;#endif /* BS_DIAG */ BS_SETUP_PHASE(FREE); if (cb || bsc->sc_sttab.tqh_first == NULL) { BS_HOST_TERMINATE; bscmdstart(ti, BSCMDSTART); } else { /* give a chance to other target */ bscmdstart(ti, BSCMDSTART); BS_HOST_TERMINATE; bshoststart(bsc, NULL); } break; } BS_SETUP_MSGPHASE(FREE);}/************************************************** * <PHASE ERROR> **************************************************/#define scsi_status (bsc->sc_busstat)struct bs_err { u_char *pe_msg; u_int pe_err; u_int pe_ph;};struct bs_err bs_cmderr[] = {/*0*/ { "illegal cmd", BSABNORMAL, UNDEF },/*1*/ { "unexpected bus free", BSABNORMAL, FREE },/*2*/ { NULL, BSSELTIMEOUT, FREE},/*3*/ { "scsi bus parity error", BSPARITY, UNDEF },/*4*/ { "scsi bus parity error", BSPARITY, UNDEF },/*5*/ { "unknown" , BSFATALIO, UNDEF },/*6*/ { "miss reselection (target mode)", BSFATALIO, UNDEF },/*7*/ { "wrong status byte", BSPARITY, STATUSIN },};static voidbs_phase_error(ti, cb) struct targ_info *ti; struct ccb *cb;{ struct bs_softc *bsc = ti->ti_bsc; struct bs_err *pep; if ((scsi_status & BSR_CM) == BSR_CMDERR && (scsi_status & BSR_PHVALID) == 0) { pep = &bs_cmderr[scsi_status & BSR_PM]; ti->ti_error |= pep->pe_err; if (pep->pe_msg) { bs_debug_print(bsc, ti); bs_printf(ti, "bsintr", pep->pe_msg); } BS_SETUP_PHASE(pep->pe_ph); } else { ti->ti_error |= BSABNORMAL; bs_debug_print(bsc, ti); bs_printf(ti, "bsintr", "phase error"); BS_SETUP_PHASE(UNDEF); } BS_SETUP_MSGPHASE(FREE); switch (ti->ti_phase) { case FREE: BS_SETUP_PHASE(UNDEF); cb = bscmddone(ti);#ifdef BS_DIAG ti->ti_flags &= ~BSNEXUS;#endif /* BS_DIAG */ BS_HOST_TERMINATE; BS_SETUP_PHASE(FREE); bscmdstart(ti, ((cb == NULL) ? BSCMDSTART : BSCMDRESTART)); break; case STATUSIN: ti->ti_error |= BSSTATUSERROR; ti->ti_status = bshw_get_status_insat(bsc); /* XXX SAT */ bs_debug_print(bsc, ti); break; case UNDEF: default: ti->ti_error |= BSABNORMAL; bs_reset_nexus(bsc); break; }}/************************************************** * ### SCSI PHASE SEQUENCER ### **************************************************/static inline void bs_ack_wait __P((struct bs_softc *, struct targ_info *, struct ccb *));static inline voidbs_ack_wait(bsc, ti, cb) struct bs_softc *bsc; struct targ_info *ti; struct ccb *cb;{ int wc = bsc->sc_wc; for (wc = bsc->sc_wc; bshw_get_busstat(bsc) != BSR_ACKREQ && wc > 0; ) wc --; if (wc <= 0) { bs_printf(ti, "bs_ack_wait", "timeout I"); return; } bshw_get_auxstat(bsc); scsi_status = bshw_get_busstat(bsc); if (cb->msgoutlen > 0) { bshw_assert_atn(bsc); delay(800); BS_SETUP_PHASE(ATTENTIONASSERT); } bshw_negate_ack(bsc);#ifdef WAITNEXTP for (wc = bsc->sc_wc; bshw_get_busstat(bsc) == BSR_ACKREQ && wc > 0; ) wc --; if (wc <= 0) bs_printf(ti, "bs_ack_wait", "timeout II");#endif /* WAITNEXTP */}intbs_sequencer(bsc) struct bs_softc *bsc;{ register struct targ_info *ti; struct ccb *cb; /************************************************** * Check reset **************************************************/ if (bsc->sc_flags & (BSRESET | BSINACTIVE)) { if (bsc->sc_flags & BSRESET) bs_reset_nexus(bsc); return 1; } /************************************************** * Get status & bus phase **************************************************/ if ((bshw_get_auxstat(bsc) & STR_INT) == 0) return 0; scsi_status = bshw_get_busstat(bsc); if (scsi_status == ((u_int8_t) -1)) { bs_debug_print_all(bsc); return 1; } /************************************************** * Check reselection, or nexus **************************************************/ if (scsi_status == BSR_RESEL) { bs_reselect(bsc); return 1; } ti = bsc->sc_nexus; if (ti == NULL || (cb = ti->ti_ctab.tqh_first) == NULL) { bs_debug_print_all(bsc); bs_printf(ti, "bsintr", "no nexus"); bs_reset_nexus(bsc); return 1; } /************************************************** * Debug section **************************************************/#ifdef BS_DEBUG if (bs_debug_flag) { bs_debug_print(bsc, ti); if (bs_debug_flag > 1) Debugger(); }#endif /* BS_DEBUG */ /************************************************** * internal scsi phase **************************************************/ switch (ti->ti_phase) { case SELECTASSERT: bs_selected(bsc, ti, cb); return 1; case SATSEL: BS_SELECTION_TERMINATE; case SATRESEL: if (bsc->sc_flags & (BSDMASTART | BSSMITSTART)) { if (bsc->sc_flags & BSSMITSTART) { bs_debug_print_all(bsc); bs_reset_nexus(bsc); bs_printf(ti, "bsintr", "smit transfer"); return 1; } BS_SETUP_PHASE(DATAPHASE); /* XXX */ bs_dma_xfer_end(ti); ti->ti_phase = ti->ti_ophase; /* XXX */ } break; default: /* XXX: * check check check for safty !! */ if (bsc->sc_selwait) { /* Ghaaa! phase error! retry! */ bs_phase_error(ti, cb); return 1; } if (bsc->sc_flags & (BSDMASTART | BSSMITSTART)) { if (bsc->sc_flags & BSDMASTART) bs_dma_xfer_end(ti); else bs_smit_xfer_end(ti); } break; } /************************************************** * hw scsi phase **************************************************/ if (scsi_status & BSR_PHVALID) { /************************************************** * Normal SCSI phase. **************************************************/ if ((scsi_status & BSR_CM) == BSR_CMDABT) { bs_phase_error(ti, cb); return 1; } switch (scsi_status & BSR_PM) { case BSR_DATAOUT: case BSR_DATAIN: BS_SETUP_PHASE(DATAPHASE); if (bsc->sc_p.datalen <= 0 || (ti->ti_flags & BSFORCEIOPOLL)) { bs_io_xfer(ti); return 1; } if (bs_check_smit(ti) && (bsc->sc_p.datalen % sizeof(u_int32_t)) == 0) { bs_lc_smit_xfer(ti, scsi_status & BSR_IOR); return 1; } bs_dma_xfer(ti, scsi_status & BSR_IOR); bshw_start_xfer(bsc); return 1; case BSR_CMDOUT: bs_commandout(bsc, ti, cb); return 1; case BSR_STATIN: if (bs_check_sat(ti)) { BS_SETUP_PHASE(SATCOMPSEQ); bshw_set_count(bsc, 0); bshw_cmd_pass(bsc, 0x41); bshw_start_sat(bsc, 0); } else { BS_SETUP_PHASE(STATUSIN); ti->ti_status = bs_read_1byte(bsc); } return 1; case BSR_UNSPINFO0: case BSR_UNSPINFO1: bs_debug_print(bsc, ti); bs_printf(ti, "bsintr", "illegal bus phase"); return 1; case BSR_MSGOUT: bs_msgout(bsc, ti, cb); return 1; case BSR_MSGIN:/* msg in */ if (bs_check_sat(ti)) { if (ti->ti_phase == RESELECTED) { bs_sat_continue(bsc, ti, cb); return 1; } /* XXX */ if (ti->ti_status == ST_UNK) ti->ti_status = bshw_get_status_insat(bsc); } ti->ti_msgin[ti->ti_msginptr ++] = bs_read_1byte(bsc); bs_msgin(bsc, ti); if (bsc->sc_cfgflags & BSC_FASTACK) bs_ack_wait(bsc, ti, cb); return 1; } } else { /************************************************** * Special SCSI phase **************************************************/ switch (scsi_status) { case BSR_SATSDP:/* SAT with save data pointer */ BS_SAVE_SDP bshw_cmd_pass(bsc, 0x41); bshw_start_sat(bsc, 0); BS_SETUP_PHASE(SATSDP) return 1; case BSR_SATFIN:/* SAT COMPLETE */ ti->ti_status = bshw_get_status_insat(bsc); BS_SETUP_MSGPHASE(IOCOMPLETED); bs_disconnect_phase(bsc, ti, cb); return 1; case BSR_ACKREQ:/* negate ACK */ if (cb->msgoutlen > 0) { bshw_assert_atn(bsc); delay(800); BS_SETUP_PHASE(ATTENTIONASSERT); } bshw_negate_ack(bsc); return 1; case BSR_DISC:/* disconnect */ bs_disconnect_phase(bsc, ti, cb); return 1; default: break; } } bs_phase_error(ti, cb); return 1;}/***************************************************************** * INTERNAL POLLING FUNCTIONS *****************************************************************/static intbs_scsi_cmd_poll_internal(cti) struct targ_info *cti;{ struct bs_softc *bsc = cti->ti_bsc; struct targ_info *ti; struct ccb *cb; int i, waits, delay_count; bsc->sc_poll++; /* setup timeout count */ if ((ti = bsc->sc_nexus) == NULL || (cb = ti->ti_ctab.tqh_first) == NULL) waits = BS_DEFAULT_TIMEOUT_SECOND * 1000000; else waits = cb->tcmax * 1000000; /* force all current jobs into the polling state. */ for (i = 0; i < NTARGETS; i++) { if ((ti = bsc->sc_ti[i]) != NULL) { ti->ti_flags |= BSFORCEIOPOLL; if ((cb = ti->ti_ctab.tqh_first) != NULL) cb->flags |= BSFORCEIOPOLL; } } /* do io */ bsc->sc_flags &= ~BSJOBDONE; do { delay_count = ((bsc->sc_flags & BSDMASTART) ? 1000000 : 100); delay(delay_count); waits -= delay_count; bs_sequencer(bsc); } while (waits >= 0 && (bsc->sc_flags & (BSUNDERRESET | BSJOBDONE)) == 0); /* done */ bsc->sc_poll--; if (waits < 0 || (bsc->sc_flags & BSUNDERRESET)) { bs_printf(NULL, "cmd_poll", "timeout or fatal"); return HASERROR; } return COMPLETE;}intbs_scsi_cmd_poll(cti, targetcb) struct targ_info *cti; struct ccb *targetcb;{ struct bs_softc *bsc = cti->ti_bsc; struct targ_info *ti; int s, error = COMPLETE; s = splbio(); bs_terminate_timeout(bsc); if (bsc->sc_hstate == BSC_TARG_CHECK) { if ((error = bs_scsi_cmd_poll_internal(cti)) != COMPLETE) bs_reset_nexus(bsc); } else { if (bsc->sc_outccb) bs_panic(bsc, "bs_cmd_poll: internal error"); bsc->sc_flags &= ~BSPOLLDONE; bsc->sc_outccb = targetcb; while ((bsc->sc_flags & BSPOLLDONE) == 0) { if (bs_scsi_cmd_poll_internal(cti) != COMPLETE) { if ((ti = bsc->sc_nexus) && ti->ti_ctab.tqh_first) ti->ti_error |= (BSTIMEOUT | BSABNORMAL); bs_reset_nexus(bsc); } } bsc->sc_outccb = NULL; } bs_start_timeout(bsc); softintr(bsc->sc_irq); splx(s); return error;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -