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

📄 scsi_1185.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
}#define GET_MIN_COUNT	127/* *	SCSI message accept routine */sc_min(cs)	register struct sc_chan_stat *cs;{	register struct scsi *sc;	register struct scsi_stat *ss;	register VOLATILE int dummy;	sc = cs->sc;	ss = &scsi_stat;	sc_intok2 = Rb_FNC|Rb_DCNT|Rb_SRST|Rb_PHC|Rb_SPE|Rb_RMSG;	DMAC_WAIT0;	if (min_flag == 1)		flush_fifo();	dummy = sc_cmonr;	DMAC_WAIT0;	if ((dummy & R4_MREQ) == 0) {		printf("sc_min: !REQ cmonr=%x\n", dummy);		print_scsi_stat();		scsi_hardreset();		return;	}    retry_cmd_issue:	int_stat2 &= ~R3_FNC;	SET_CMD(SCMD_TR_INFO);	do {		do {			dummy = sc_statr;			DMAC_WAIT0;		} while (dummy & R0_CIP);		GET_INTR(&int_stat1, &int_stat2);	/* clear interrupt */	} while ((int_stat2 & R3_FNC) == 0);	int_stat2 &= ~R3_FNC;	dummy = sc_ffstr;	if (dummy & R5_FIE) {		DMAC_WAIT;		dummy = sc_ffstr;		DMAC_WAIT0;		if (dummy & R5_FIE) {			dummy = sc_statr;			DMAC_WAIT0;			if ((dummy & R0_INIT) == 0) {				/*				 * CXD1185 detect BSY false				 */				scsi_hardreset();				return;			}		}	}	dummy = sc_datr;				/* get message byte */	DMAC_WAIT0;	if (min_cnt[cs->chan_num] == 0) {		sc->sc_message = sc->sc_identify;		if (dummy == MSG_EXTND) {			/* Extended Message */			min_cnt[cs->chan_num] = GET_MIN_COUNT;			min_point[cs->chan_num] = sc->sc_param;			bzero((caddr_t)sc->sc_param, 8);			*min_point[cs->chan_num]++ = dummy;		} else {			switch ((dummy & MSG_IDENT)? MSG_IDENT : dummy) {			case MSG_CCOMP:				sc->sc_istatus |= INST_EP;				break;			case MSG_MREJ:#ifndef NOT_SUPPORT_SYNCTR				if (mout_flag[cs->chan_num] == MOUT_SYNC_TR)					sync_tr[cs->chan_num] = 0;#endif				break;			case MSG_IDENT:			case MSG_RDP:	ss->dma_stat = OFF;	pad_start = 0;				cs->comflg = OFF;				/*				 * restore the saved value to Active pointers				 */				act_cmd_pointer = sc->sc_cdb.un_reserved;				cs->act_trcnt = sc->sc_ctrnscnt;				cs->act_point = sc->sc_cpoint;				cs->act_tag = sc->sc_ctag;				cs->act_offset = sc->sc_coffset;				break;			case MSG_SDP:				/*				 * save Active pointers				 */				sc->sc_ctrnscnt = cs->act_trcnt;				sc->sc_ctag = cs->act_tag;				sc->sc_coffset = cs->act_offset;				sc->sc_cpoint = cs->act_point;				break;			case MSG_DCNT:				sc->sc_istatus |= INST_WR;				ss->wrc++;				break;			default:				sc->sc_message = MSG_MREJ;				SET_CMD(SCMD_AST_ATN);				printf("SCSI%d:sc_min() Unknown mes=0x%x, \n",					cs->chan_num, dummy);			}		}	} else {		*min_point[cs->chan_num]++ = dummy;		if (min_cnt[cs->chan_num] == GET_MIN_COUNT)			min_cnt[cs->chan_num] = dummy;		else			min_cnt[cs->chan_num]--;		if (min_cnt[cs->chan_num] <= 0) {#ifdef ABORT_SYNCTR_MES_FROM_TARGET			if ((sc->sc_param[2] == 0x01)			    && (mout_flag[cs->chan_num] == MOUT_SYNC_TR)) {#else			if (sc->sc_param[2] == 0x01) { /*}*/#endif				register int i;				/*				 * receive Synchronous transfer message reply				 *	calculate transfer period val				 *	tpm * 4/1000 us = 4/16 * (tpv + 1)				 */#define	TPM2TPV(tpm)	(((tpm)*16 + 999) / 1000 - 1)#ifndef NOT_SUPPORT_SYNCTR				i = sc->sc_param[3];	/* get tpm */				i = TPM2TPV(i) << 4;				if (sc->sc_param[4] == 0)					sync_tr[cs->chan_num] = 0;				else					sync_tr[cs->chan_num] = i | sc->sc_param[4];#endif /* !NOT_SUPPORT_SYNCTR */			} else {				sc->sc_message = MSG_MREJ;				SET_CMD(SCMD_AST_ATN);	/* assert ATN */			}		}	}	SET_CMD(SCMD_NGT_ACK);}/* *	SCSI message send routine */intsc_mout(cs)	register struct sc_chan_stat *cs;{	register struct scsi *sc = cs->sc;	register u_char *mp;	register int cnt;	register int iloop;	register VOLATILE int dummy;	VOLATILE int tmp;	VOLATILE int tmp0;	flush_fifo();	if (mout_flag[cs->chan_num] == 0) {		mout_flag[cs->chan_num] = MOUT_IDENTIFY;		if (sc->sc_message != 0) {			sc_intok2 = Rb_FNC|Rb_DCNT|Rb_SRST|Rb_PHC|Rb_SPE|Rb_RMSG;			DMAC_WAIT0;			if ((sc->sc_message == MSG_EXTND)					&& (sc->sc_param[2] == 0x01)) {				cnt = 5;				mp = sc->sc_param;				sc->sc_param[3] = MIN_TP;				if (sc->sc_param[4] > MAX_OFFSET_BYTES)					sc->sc_param[4] = MAX_OFFSET_BYTES;				mout_flag[cs->chan_num] = MOUT_SYNC_TR;			} else {				cnt = 1;				mp = &sc->sc_message;			}			SET_CNT(cnt);			SET_CMD(SCMD_TR_INFO|R0_TRBE);			sc_datr = sc->sc_identify;			DMAC_WAIT0;			for (iloop = 1; iloop < cnt; iloop++) {				sc_datr = *mp++;				DMAC_WAIT;			}			do {				dummy = sc_cmonr;				DMAC_WAIT0;				if ((dummy & R4_MBSY) == 0)					return;				dummy = sc_statr;				DMAC_WAIT0;			} while (dummy & R0_CIP);			tmp = 0;			GET_INTR(&tmp0, &tmp);		/* clear interrupt */			if ((tmp & R3_FNC) == 0) {				(void) WAIT_STATR_BITSET(R0_MIRQ);				GET_INTR(&tmp0, &tmp);	/* clear interrupt */			}			do {				dummy = sc_cmonr;				DMAC_WAIT0;				if ((dummy & R4_MBSY) == 0)					return;			} while ((dummy & R4_MREQ) == 0);			SET_CMD(SCMD_NGT_ATN);			(void) WAIT_STATR_BITCLR(R0_CIP);			GET_INTR(&tmp0, &tmp);		/* clear interrupt */			dummy = sc_cmonr;			DMAC_WAIT0;			if ((dummy & R4_MREQ) == 0) {				printf("sc_mout: !REQ cmonr=%x\n", dummy);				print_scsi_stat();				scsi_hardreset();				return;			}			SET_CMD(SCMD_TR_INFO);			sc_datr = *mp++;			DMAC_WAIT0;		} else {			dummy = sc_cmonr;			DMAC_WAIT0;			if (dummy & R4_MATN) {				SET_CMD(SCMD_NGT_ATN);				(void) WAIT_STATR_BITCLR(R0_CIP);				GET_INTR(&tmp0, &tmp);	/* clear interrupt */			}			iloop = 0;			do {				dummy = sc_cmonr;				DMAC_WAIT0;				if (iloop++ > CHECK_LOOP_CNT)					break;			} while ((dummy & R4_MREQ) == 0);			SET_CMD(SCMD_TR_INFO);			sc_datr = sc->sc_identify;			DMAC_WAIT0;		}	} else {		dummy = sc_cmonr;		DMAC_WAIT0;		if (dummy & R4_MATN) {			SET_CMD(SCMD_NGT_ATN);			(void) WAIT_STATR_BITCLR(R0_CIP);			GET_INTR(&tmp0, &tmp);		/* clear interrupt */		}		dummy = sc_cmonr;		DMAC_WAIT0;		if ((dummy & R4_MREQ) == 0) {			printf("sc_mout: !REQ cmonr=%x\n", dummy);			print_scsi_stat();			scsi_hardreset();			return;		}		SET_CMD(SCMD_TR_INFO);		sc_datr = sc->sc_message;		DMAC_WAIT0;	}}/* *	SCSI status accept routine */sc_sin(cs)	register VOLATILE struct sc_chan_stat *cs;{	register VOLATILE int dummy;	register int iloop;	flush_fifo();	dummy = sc_cmonr;	DMAC_WAIT0;	if ((dummy & R4_MREQ) == 0) {		printf("sc_sin: !REQ cmonr=%x\n", dummy);		print_scsi_stat();		scsi_hardreset();		return;	}	sc_intok2 = Rb_FNC|Rb_DCNT|Rb_SRST|Rb_PHC|Rb_SPE|Rb_RMSG;	DMAC_WAIT0;	SET_CMD(SCMD_TR_INFO);	(void) WAIT_STATR_BITCLR(R0_CIP);	int_stat2 &= ~R3_FNC;	iloop = 0;	do {		if (iloop++ > CHECK_LOOP_CNT)			break;		GET_INTR(&int_stat1, &int_stat2);	/* clear interrupt */	} while ((int_stat2 & R3_FNC) == 0);	int_stat2 &= ~R3_FNC;	cs->sc->sc_tstatus = sc_datr;		/* get status byte */	DMAC_WAIT0;}/* *	SCSI data in/out routine */sc_dio(cs)	register VOLATILE struct sc_chan_stat *cs;{	register VOLATILE struct scsi *sc;	register struct scsi_stat *ss;	register int i;	register int pages;	register u_int tag;	register u_int pfn;	VOLATILE int phase;	sc = cs->sc;	ss = &scsi_stat;	sc_intok2 = Rb_FNC|Rb_DCNT|Rb_SRST|Rb_PHC|Rb_SPE;	DMAC_WAIT0;	if (cs->act_trcnt <= 0) {		sc_dio_pad(cs);		return;	}	switch (sc->sc_opcode) {	case SCOP_READ:	case SCOP_WRITE:	case SCOP_EREAD:	case SCOP_EWRITE:		i = (cs->act_trcnt + sc->sc_bytesec -1) / sc->sc_bytesec;		i *= sc->sc_bytesec;		break;	default:		i = cs->act_trcnt;		break;	}	SET_CNT(i);	pad_cnt[cs->chan_num] = i - cs->act_trcnt;	phase = sc_cmonr & SC_PMASK;	DMAC_WAIT0;	if (phase == DAT_IN) {		if (sc_syncr == OFF) {			DMAC_WAIT0;			flush_fifo();		}	}#if defined(mips) && defined(CPU_SINGLE)	SET_CMD(SCMD_TR_INFO|R0_DMA|R0_TRBE);#endif#if defined(mips) && defined(CPU_SINGLE)	dmac_gsel = CH_SCSI;	dmac_ctrcl = (u_char)(cs->act_trcnt & 0xff);	dmac_ctrcm = (u_char)((cs->act_trcnt >> 8) & 0xff);	dmac_ctrch = (u_char)((cs->act_trcnt >> 16) & 0x0f);	dmac_cofsh = (u_char)((cs->act_offset >> 8) & 0xf);	dmac_cofsl = (u_char)(cs->act_offset & 0xff);#endif	tag = 0;	if (sc->sc_map && (sc->sc_map->mp_pages > 0)) {		/*		 * Set DMAC map entry from map table		 */		pages = sc->sc_map->mp_pages;		for (i = cs->act_tag; i < pages; i++) {			if ((pfn = sc->sc_map->mp_addr[i]) == 0)				panic("SCSI:sc_dma() zero entry");#if defined(mips) && defined(CPU_SINGLE)			dmac_gsel = CH_SCSI;			dmac_ctag = (u_char)tag++;			dmac_cmap = (u_short)pfn;#endif		}#ifdef MAP_OVER_ACCESS# if defined(mips) && defined(CPU_SINGLE)		dmac_gsel = CH_SCSI;		dmac_ctag = (u_char)tag++;		dmac_cmap = (u_short)pfn;# endif#endif	} else {		/*		 * Set DMAC map entry from logical address		 */		pfn = (u_int)vtophys(cs->act_point) >> PGSHIFT;		pages = (cs->act_trcnt >> PGSHIFT) + 2;		for (i = 0; i < pages; i++) {#if defined(mips) && defined(CPU_SINGLE)			dmac_gsel = CH_SCSI;			dmac_ctag = (u_char)tag++;			dmac_cmap = (u_short)pfn + i;#endif		}	}#if defined(mips) && defined(CPU_SINGLE)	dmac_gsel = CH_SCSI;	dmac_ctag = 0;#endif	if (phase == DAT_IN) {		ss->dma_stat = SC_DMAC_RD;#if defined(mips) && defined(CPU_SINGLE)		/*		 * auto pad flag is always on		 */		dmac_gsel = CH_SCSI;		dmac_cctl = DM_MODE|DM_APAD;		DMAC_WAIT;		dmac_cctl = DM_MODE|DM_APAD|DM_ENABLE;		DMAC_WAIT0;#endif	}	else if (phase == DAT_OUT) {		ss->dma_stat = SC_DMAC_WR;#if defined(mips) && defined(CPU_SINGLE)		dmac_gsel = CH_SCSI;		dmac_cctl = DM_APAD;		DMAC_WAIT;		dmac_cctl = DM_APAD|DM_ENABLE;		DMAC_WAIT0;#endif						/* DMAC start on mem->I/O */	}}#define MAX_TR_CNT24	((1 << 24) -1)sc_dio_pad(cs)	register VOLATILE struct sc_chan_stat *cs;{	register VOLATILE int phase;	register int dummy;	if (cs->act_trcnt >= 0)		return;	pad_start = 1;	SET_CNT(MAX_TR_CNT24);	SET_CMD(SCMD_TR_PAD|R0_TRBE);	dummy = sc_cmonr & SC_PMASK;	DMAC_WAIT0;	if (dummy == DAT_IN)		dummy = sc_datr;		/* get data */	else		sc_datr = 0;			/* send data */}print_scsi_stat(){	register struct scsi_stat *ss;	register VOLATILE int i;	int dummy;	ss = &scsi_stat;	printf("ipc=%d wrc=%d wbc=%d\n", ss->ipc, ss->wrc, ss->wbc);}/* *	return 0 if it was done.  Or retun TRUE if it is busy. */sc_busy(chan)	register int chan;{	return ((int)chan_stat[chan].sc);}/* *	append channel into Waiting Bus_free queue */append_wb(cs)	register VOLATILE struct sc_chan_stat *cs;{	register int s;	s = splclock();			/* inhibit process switch */	if (wbq_actf == NULL)		wbq_actf = cs;	else		wbq_actl->wb_next = cs;	wbq_actl = cs;	cs->sc->sc_istatus = INST_WAIT;	scsi_stat.wbc++;	splx(s);}/* *	get channel from Waiting Bus_free queue */get_wb_chan(){	register int s;	register int chan;	s = splclock();			/* inhibit process switch */	if (wbq_actf == NULL) {		chan = -1;	} else {		chan = wbq_actf->chan_num;		if ((chan < 0) || (chan >= NTARGET) || (chan == SC_OWNID))			chan = -1;	}	splx(s);	return (chan);}/* *	release channel from Waiting Bus_free queue */release_wb(){	register VOLATILE struct sc_chan_stat *cs;	register int s;	int error;	s = splclock();			/* inhibit process switch */	error = 0;	if (wbq_actf == NULL) {		error = -1;	} else {		cs = wbq_actf;		wbq_actf = cs->wb_next;		cs->wb_next = NULL;		if (wbq_actl == cs)			wbq_actl = NULL;		cs->sc->sc_istatus &= ~INST_WAIT;		scsi_stat.wbc--;	}	splx(s);	return (error);}adjust_transfer(cs)	register struct sc_chan_stat *cs;{	register struct scsi *sc;	register struct scsi_stat *ss;	register VOLATILE u_int remain_cnt;	register u_int offset;	u_int sent_byte;	sc = cs->sc;	ss = &scsi_stat;	if (pad_start) {		pad_start = 0;		remain_cnt = 0;	} else {# if defined(mips) && defined(CPU_SINGLE)		remain_cnt = GET_CNT();		remain_cnt -= pad_cnt[cs->chan_num];		if (ss->dma_stat == SC_DMAC_WR) {			/*			 * adjust counter in the FIFO			 */			remain_cnt += sc_ffstr & R5_FIFOREM;		}# endif	}	sent_byte = sc->sc_ctrnscnt - remain_cnt;	cs->act_trcnt = remain_cnt;	offset = sc->sc_coffset + sent_byte;	cs->act_tag += (offset >> PGSHIFT);	cs->act_offset = offset & PGOFSET;	if ((sc->sc_map == NULL) || (sc->sc_map->mp_pages <= 0))		cs->act_point += sent_byte;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -