⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bs.c

📁 freebsd v4.4内核源码
💻 C
📖 第 1 页 / 共 3 页
字号:
	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 + -