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

📄 scsi_1185.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
		sel_stat[ss->ipc] = SEL_RSLD;		ss->ipc = -1;		int_stat1 |= R2_RSL;	}	if (int_stat1 & R2_RSL) {		/*		 * Reselection		 */		sc_resel();		int_stat1 &= ~R2_RSL;		if (sel_stat[ss->ipc] == SEL_RSL_WAIT)			goto scintr_exit;	}	if ((ss->ipc >= 0) && (ss->ipc != SC_OWNID) &&	    (sel_stat[ss->ipc] == SEL_SUCCESS)) {		if (int_stat2 & R3_PHC) {			/*			 * Phase change			 */			int_stat2 &= ~(R3_PHC|R3_RMSG);			sc_pmatch();		} else if (int_stat2 & R3_RMSG) {			/*			 * message Phase			 */			if (min_flag > 0) {				int_stat2 &= ~(R3_PHC|R3_RMSG);				sc_pmatch();			}		}		else if (ss->dma_stat != OFF) {			dummy = sc_cmonr;			DMAC_WAIT0;			if ((dummy & (R4_MMSG|R4_MCD|R4_MREQ)) == R4_MREQ) {				/*				 * still DATA transfer phase				 */				sc_dio_pad(ss->ip);			}		}		else if (ss->ip->comflg == CF_SEND) {			dummy = sc_cmonr;			DMAC_WAIT0;			if ((dummy & SC_PMASK) == COM_OUT) {				/*				 * command out phase				 */				sc_cout(ss->ip);			}		}	} else {		if (int_stat2 & (R3_PHC|R3_RMSG))			goto scintr_exit;	}	if ((int_stat1 & (R2_STO|R2_RSL|R2_ARBF))	    || (int_stat2 & (R3_DCNT|R3_SRST|R3_PHC|R3_SPE))) {		/*		 * still remain intrq		 */		goto scintr_loop;	}scintr_exit:	return (1);}/* *	SCSI bus reset routine *		scsi_hardreset() is occered a reset interrupt. *		And call scsi_softreset(). */scsi_hardreset(){	register int s;#ifdef DMAC_MAP_INIT	register int i;#endif	s = splscsi();	scsi_chipreset();	DMAC_WAIT0;	int_stat1 = 0;	int_stat2 = 0;	SET_CMD(SCMD_AST_RST);			/* assert RST signal */#ifdef DMAC_MAP_INIT	if (dmac_map_init == 0) {		dmac_map_init++;		for (i = 0; i < NDMACMAP; i++) {# if defined(mips) && defined(CPU_SINGLE)			dmac_gsel = CH_SCSI;			dmac_ctag = (u_char)i;			dmac_cmap = (u_short)0;# endif		}	}#endif	splx(s);}/* * I/O port (sc_ioptr) bit assign *	 *	Rf_PRT3		-	<reserved> *	Rf_PRT2		-	<reserved> *	Rf_PRT1		out	Floppy Disk Density control *	Rf_PRT0		out	Floppy Disk Eject control */scsi_chipreset(){	register int s;	register int iloop;	register VOLATILE int save_ioptr;	register VOLATILE int dummy;	int s_int1, s_int2;	s = splscsi();#if defined(mips) && defined(CPU_SINGLE)	dmac_gsel = CH_SCSI;	dmac_cwid = 4;				/* initialize DMAC SCSI chan */	*(unsigned VOLATILE char *)PINTEN |= DMA_INTEN;	dma_reset(CH_SCSI);#endif	sc_envir = 0;				/* 1/4 clock */	DMAC_WAIT0;	save_ioptr = sc_ioptr;	DMAC_WAIT0;	last_cmd = SCMD_CHIP_RST;	sc_comr = SCMD_CHIP_RST;		/* reset chip */	DMAC_WAIT;	(void) WAIT_STATR_BITCLR(R0_CIP);	/*	 * SCMD_CHIP_RST command reset all register	 *				except sc_statr<7:6> & sc_cmonr.	 * So, bit R0_MIRQ & R3_FNC will be not set.	 */	sc_idenr = SC_OWNID;	DMAC_WAIT0;	sc_intok1 = Ra_STO|Ra_RSL|Ra_ARBF;	DMAC_WAIT0;	sc_intok2 = Rb_FNC|Rb_SRST|Rb_PHC|Rb_SPE|Rb_RMSG;	DMAC_WAIT0;	sc_ioptr = save_ioptr;	DMAC_WAIT;	sc_moder = Rc_TMSL;			/* RST drive time = 25.5 us */	DMAC_WAIT0;	sc_timer = 0x2;	DMAC_WAIT0;	sc_moder = Rc_SPHI;			/* selection timeout = 252 ms */	DMAC_WAIT0;	sc_timer = SEL_TIMEOUT_VALUE;	DMAC_WAIT0;#ifdef SCSI_1185AQ	if (scsi_1185AQ)		SET_CMD(SCMD_ENB_SEL);		/* enable reselection */#endif	int_stat1 &= ~R2_RSL;			/* ignore RSL inter request */	splx(s);}scsi_softreset(){	register VOLATILE struct sc_chan_stat *cs;	register struct scsi_stat *ss;	register int (*handler)();	register int i;#ifdef mips	extern struct sc_data sc_data[];	register struct sc_data *scdp;#endif	wbq_actf = NULL;	wbq_actl = NULL;	ss = &scsi_stat;	ss->wbc = 0;	ss->wrc = 0;	ss->ip = NULL;	ss->ipc = -1;	ss->dma_stat = OFF;	pad_start = 0;	for (i = 0; i < NTARGET; ++i) {		if (i == SC_OWNID)			continue;		cs = &chan_stat[i];		cs->wb_next = NULL;#ifndef NOT_SUPPORT_SYNCTR		sync_tr[i] = 0;			/* asynchronous mode */#endif		sel_stat[i] = SEL_WAIT;		if (cs->sc != NULL) {			if ((cs->sc->sc_istatus & INST_EP) == 0)				cs->sc->sc_istatus = (INST_EP|INST_HE);			cs->sc = NULL;#ifdef mips			scdp = &sc_data[cs->chan_num];			MachFlushDCache(scdp->scd_scaddr, sizeof(struct scsi));			if (MACH_IS_USPACE(scdp->scd_vaddr)) {				panic("scsi_softreset: user address is not supported");			} else if (MACH_IS_CACHED(scdp->scd_vaddr)) {			    MachFlushDCache(scdp->scd_vaddr, scdp->scd_count);			} else if (MACH_IS_MAPPED(scdp->scd_vaddr)) {#ifdef notyet /* KU:XXX */				clean_k2dcache(scdp->scd_vaddr, scdp->scd_count);#else				MachFlushCache();#endif			}#endif /* mips */			if ((cs->intr_flg == SCSI_INTEN)				    && (handler = scintsw[i].sci_inthandler)) {#ifdef noyet /* KU:XXX */				intrcnt[INTR_SCSI00 + i]++;#endif				(*handler)(scintsw[i].sci_ctlr);			}		}	}}/* *	RESELECTION interrupt service routine *		( RESELECTION phase ) */sc_resel(){	register struct sc_chan_stat *cs;	register struct scsi_stat *ss;	register VOLATILE int chan;	register VOLATILE int statr;	register int iloop;	min_flag = 0;	chan = (sc_idenr & R6_SID_MASK) >> SC_TG_SHIFT;	if (chan == SC_OWNID)		return;	statr = sc_statr;	DMAC_WAIT0;	if (statr & R0_CIP) {		if (last_cmd == SCMD_SEL_ATN) {			/*			 * SELECTION command dead lock ?			 *	save interrupt request			 */			while (sc_statr & R0_MIRQ) {				DMAC_WAIT0;				int_stat1 |= sc_intrq1;				DMAC_WAIT0;				int_stat2 |= sc_intrq2;				DMAC_WAIT0;			}			scsi_chipreset();		}	}	cs = &chan_stat[chan];	if (cs->sc == NULL) {		scsi_hardreset();		return;	}	if ((cs->sc->sc_istatus & INST_WR) == 0) {		scsi_hardreset();		return;	}	ss = &scsi_stat;	if (ss->ipc >= 0) {		scsi_hardreset();		return;	}	ss->ip = cs;	ss->ipc = chan;	sc_intok2 = Rb_FNC|Rb_DCNT|Rb_SRST|Rb_PHC|Rb_SPE;	DMAC_WAIT0;	iloop = 0;	while ((int_stat2 & R3_FNC) == 0) {		/*		 * Max 6 usec wait		 */		if (iloop++ > RSL_LOOP_CNT) {			sel_stat[chan] = SEL_RSL_WAIT;			return;		}		GET_INTR(&int_stat1, &int_stat2);	}	int_stat2 &= ~R3_FNC;		sel_stat[chan] = SEL_SUCCESS;	ss->wrc--;	ss->dma_stat = OFF;	pad_start = 0;	cs->sc->sc_istatus |= INST_IP;	cs->sc->sc_istatus &= ~INST_WR;#ifndef NOT_SUPPORT_SYNCTR	sc_syncr = sync_tr[chan];	DMAC_WAIT0;#endif}/* *	DISCONNECT interrupt service routine *		( Target disconnect / job done ) */sc_discon(){	register VOLATILE struct sc_chan_stat *cs;	register struct scsi_stat *ss;	register int (*handler)();	register VOLATILE int dummy;#ifdef mips	extern struct sc_data sc_data[];	register struct sc_data *scdp;#endif	/*	 * Signal reflection on BSY is occured.	 *	Not Bus Free Phase, ignore.	 *	 *	But, CXD1185Q reset INIT bit of sc_statr.	 *	So, can't issue Transfer Information command.	 *		 *	What shall we do ?  Bus reset ?	 */	if ((int_stat2 & R3_DCNT) && ((sc_intok2 & Rb_DCNT) == 0))		return;	sc_intok2 = Rb_FNC|Rb_SRST|Rb_PHC|Rb_SPE;	DMAC_WAIT0;	min_flag = 0;	dummy = sc_cmonr;	DMAC_WAIT0;	if (dummy & R4_MATN) {		SET_CMD(SCMD_NGT_ATN);		(void) WAIT_STATR_BITSET(R0_MIRQ);		GET_INTR(&int_stat1, &int_stat2);	/* clear interrupt */	}	if ((int_stat1 & R2_RSL) == 0)		int_stat2 &= ~R3_FNC;	ss = &scsi_stat;	cs = ss->ip;	if ((cs == NULL) || (ss->ipc < 0))		goto sc_discon_exit;	if ((sel_stat[cs->chan_num] != SEL_SUCCESS)			&& (sel_stat[cs->chan_num] != SEL_TIMEOUT))		printf("sc_discon: eh!\n");	/*	 * indicate abnormal terminate	 */	if ((cs->sc->sc_istatus & (INST_EP|INST_WR)) == 0)		cs->sc->sc_istatus |= (INST_EP|INST_PRE|INST_LB);	cs->sc->sc_istatus &= ~INST_IP;	ss->dma_stat = OFF;	pad_start = 0;	ss->ip = NULL;	ss->ipc = -1;	if ((cs->sc->sc_istatus & INST_WR) == 0) {		if (perr_flag[cs->chan_num] > 0)			cs->sc->sc_istatus |= INST_EP|INST_PRE;		cs->sc = NULL;#ifdef mips		scdp = &sc_data[cs->chan_num];		MachFlushDCache(scdp->scd_scaddr, sizeof(struct scsi));		if (MACH_IS_USPACE(scdp->scd_vaddr)) {			panic("sc_discon: user address is not supported");		} else if (MACH_IS_CACHED(scdp->scd_vaddr)) {			MachFlushDCache(scdp->scd_vaddr, scdp->scd_count);		} else if (MACH_IS_MAPPED(scdp->scd_vaddr)) {#ifdef notyet /* KU:XXX */			clean_k2dcache(scdp->scd_vaddr, scdp->scd_count);#else			MachFlushCache();#endif		}#endif /* mips */		if ((cs->intr_flg == SCSI_INTEN)		    && (handler = scintsw[cs->chan_num].sci_inthandler)) {#ifdef notyet /* KU:XXX */			intrcnt[INTR_SCSI00 + cs->chan_num]++;#endif			(*handler)(scintsw[cs->chan_num].sci_ctlr);		}	}sc_discon_exit:	sc_start();}/* *	SCSI phase match interrupt service routine */sc_pmatch(){	register VOLATILE struct sc_chan_stat *cs;	register VOLATILE int phase;	register VOLATILE int phase2;	register VOLATILE int cmonr;	int_stat2 &= ~R3_FNC;			/* XXXXXXXX */	cs = scsi_stat.ip;	if (cs == NULL)		return;# if defined(mips) && defined(CPU_SINGLE)	dma_reset(CH_SCSI);# endif	phase = sc_cmonr & SC_PMASK;	DMAC_WAIT0;	for (;;) {		phase2 = phase;		cmonr = sc_cmonr;		DMAC_WAIT0;		phase = cmonr & SC_PMASK;		if (phase == phase2) {			if ((phase == DAT_IN) || (phase == DAT_OUT))				break;			else if (cmonr & R4_MREQ)				break;		}	}	scsi_stat.dma_stat = OFF;	pad_start = 0;	if (phase == COM_OUT) {		min_flag = 0;		if (cs->comflg != CF_SEND)			cs->comflg = CF_SET;		sc_cout(cs);	} else {		cs->comflg = CF_ENOUGH;		sc_intok2 &= ~Rb_FNC;		if (phase == MES_IN) {			min_flag++;			sc_min(cs);		} else {			min_flag = 0;			switch (phase) {			case MES_OUT:				sc_mout(cs);				break;			case DAT_IN:			case DAT_OUT:				sc_dio(cs);				break;			case STAT_IN:				sc_sin(cs);				break;			default:				printf("SCSI%d: unknown phase\n", cs->chan_num);				break;			}		}	}}flush_fifo(){	register VOLATILE int dummy;	VOLATILE int tmp;	VOLATILE int tmp0;	dummy = sc_ffstr;	DMAC_WAIT0;	if (dummy & R5_FIFOREM) {		/*		 * flush FIFO		 */		SET_CMD(SCMD_FLSH_FIFO);		tmp = 0;		do {			do {				dummy = sc_statr;				DMAC_WAIT0;			} while (dummy & R0_CIP);			GET_INTR(&tmp0, &tmp); /* clear interrupt */		} while ((tmp & R3_FNC) == 0);	}}/* *	SCSI command send routine */intsc_cout(cs)	register struct sc_chan_stat *cs;{	register struct scsi *sc;	register int iloop;	register int cdb_bytes;	register VOLATILE int dummy;	register VOLATILE int statr;	if (cs->comflg == CF_SET) {		cs->comflg = CF_SEND;		flush_fifo();		sc = cs->sc;		switch (sc->sc_opcode & CMD_TYPEMASK) {		case CMD_T0:			cdb_bytes = 6;			break;		case CMD_T1:			cdb_bytes = 10;			break;		case CMD_T5:			cdb_bytes = 12;			break;		default:			cdb_bytes = 6;			sc_intok2 |= Rb_FNC;			break;		}		/*		 * set 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;	} else {		cdb_bytes = 1;		iloop = 0;		do {			dummy = sc_cmonr;			DMAC_WAIT0;			if ((dummy & SC_PMASK) != COM_OUT)				return;			statr = sc_statr;			DMAC_WAIT0;			if (statr & R0_MIRQ)				return;		} while ((dummy & R4_MREQ) == 0);		statr = sc_statr;		DMAC_WAIT0;		if (statr & R0_MIRQ)			return;	}	SET_CNT(cdb_bytes);	SET_CMD(SCMD_TR_INFO|R0_TRBE);	for (iloop = 0; iloop < cdb_bytes; iloop++) {		do {			dummy = sc_cmonr;			DMAC_WAIT0;			if ((dummy & SC_PMASK) != COM_OUT)				return;		} while ((dummy & R4_MREQ) == 0);		statr = sc_statr;		DMAC_WAIT0;		if (statr & R0_MIRQ)			return;		sc_datr = *act_cmd_pointer++;		do {			dummy = sc_cmonr;			DMAC_WAIT0;		} while ((dummy & R4_MACK) != 0);	}

⌨️ 快捷键说明

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