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

📄 scsi_1185.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (c) 1992, 1993 *	The Regents of the University of California.  All rights reserved. * * This code is derived from software contributed to Berkeley by * Sony Corp. and Kazumasa Utashiro of Software Research Associates, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: $Hdr: scsi_1185.c,v 4.300 91/06/09 06:22:20 root Rel41 $ SONY * *	@(#)scsi_1185.c	8.1 (Berkeley) 6/11/93 *//* * Copyright (c) 1989- by SONY Corporation. *//* *	scsi_1185.c * *	CXD1185Q *	SCSI bus low level common routines *				for one cpu machine *//* * MODIFY HISTORY: * *	DMAC_WAIT	--- DMAC_0266 wo tukau-baai, DMAC mata-wa SCSI-chip ni *				tuzukete access suru-baai, *				kanarazu wait wo ireru-beshi ! * */#include <sys/types.h>#include <machine/pte.h>#include <machine/cpu.h>#include <sys/param.h>#include <sys/systm.h>#include <sys/map.h>#include <sys/buf.h>#include <vm/vm.h>#include <sys/proc.h>#include <sys/user.h>#include <sys/conf.h>#include <sys/dkstat.h>#include <sys/kernel.h>#include <news3400/hbdev/hbvar.h>#include <news3400/hbdev/screg_1185.h>#include <news3400/hbdev/scsic.h>#ifdef news3400# include <news3400/hbdev/dmac_0448.h># ifndef NDMACMAP# define NDMACMAP	144# endif#endif#include <news3400/iodev/scsireg.h>#ifdef mips#define	VOLATILE	volatile#else#define	VOLATILE#endif#define ABORT_SYNCTR_MES_FROM_TARGET#define SCSI_1185AQ#define RESET_RECOVER#define DMAC_MAP_INIT			/* for nws-3700 parity error */#define APAD_ALWAYS_ON# define	CHECK_LOOP_CNT	60# define	RSL_LOOP_CNT	60#ifndef DMAC_MAP_INIT# define MAP_OVER_ACCESS		/* for nws-3700 parity error */#endif#undef	CHECK_MRQ#ifdef NOT_SUPPORT_SYNCTR# define	MAX_OFFSET_BYTES	0#else# define	MAX_OFFSET_BYTES	MAX_OFFSET#endif#define	NTARGET		8#define	act_point	spoint#define	act_trcnt	stcnt#define	act_tag		stag#define	act_offset	soffset#define	splscsi		splsc#if defined(mips) && defined(CPU_SINGLE)#define nops(x)		{ int i; for (i = 0; i < (x); i++) ; }#define	vtophys(v)	MACH_UNMAPPED_TO_PHYS(v)#define	DMAC_WAIT0	;#else#define	DMAC_WAIT0	DMAC_WAIT#endifint	perr_flag[NTARGET];#ifndef NOT_SUPPORT_SYNCTRVOLATILE char sync_tr[NTARGET];#endif#ifdef DMAC_MAP_INITint	dmac_map_init = 0;#endif#ifdef SCSI_1185AQint	scsi_1185AQ = 0;#endifstruct sc_chan_stat chan_stat[NTARGET];	/* SCSI channel status */int	sel_stat[NTARGET];		/* target select status */#define	SEL_WAIT	0#define	SEL_START	1#define	SEL_TIMEOUT	2#define	SEL_ARBF	3#define	SEL_SUCCESS	4#define	SEL_RSLD	5#define	SEL_RSL_WAIT	6/* *	command flag status */#define	CF_SET		1#define	CF_SEND		2#define	CF_ENOUGH	3#define	CF_EXEC		4#define	SEL_TIMEOUT_VALUE	0x7aVOLATILE int int_stat1;VOLATILE int int_stat2;VOLATILE int min_flag;VOLATILE char mout_flag[NTARGET];#define MOUT_IDENTIFY	1#define MOUT_SYNC_TR	2VOLATILE int	last_cmd;VOLATILE char	min_cnt[NTARGET];VOLATILE u_char	*min_point[NTARGET];VOLATILE int	pad_cnt[NTARGET];VOLATILE static u_char *act_cmd_pointer;static VOLATILE struct sc_chan_stat *wbq_actf = 0; /* forword active pointer */static VOLATILE struct sc_chan_stat *wbq_actl = 0; /* last active pointer */static char ScsiSoftError[] = "SCSI soft error";static int pad_start;#if defined(mips) && defined(CPU_SINGLE)#define dma_reset(x) { \	int s = splscsi(); \	dmac_gsel = (x); dmac_cctl = DM_RST; dmac_cctl = 0; \	splx(s); \}#endifWAIT_STATR_BITCLR(bitmask)	register int bitmask;{	register int iloop;	register VOLATILE int dummy;	iloop = 0;	do {		dummy = sc_statr;		DMAC_WAIT0;		if (iloop++ > CHECK_LOOP_CNT)			return (-1);	} while (dummy & bitmask);	return (0);}WAIT_STATR_BITSET(bitmask)	register int bitmask;{	register int iloop;	register VOLATILE int dummy;	iloop = 0;	do {		dummy = sc_statr;		DMAC_WAIT0;		if (iloop++ > CHECK_LOOP_CNT)			return (-1);	} while ((dummy & bitmask) == 0);	return (0);}SET_CMD(CMD)	register int CMD;{	(void) WAIT_STATR_BITCLR(R0_CIP);	last_cmd = (CMD);	sc_comr = (CMD);	DMAC_WAIT0;}SET_CNT(COUNT)	register int COUNT;{	sc_tclow = (COUNT) & 0xff;	DMAC_WAIT0;	sc_tcmid = ((COUNT) >> 8) & 0xff;	DMAC_WAIT0;	sc_tchi = ((COUNT) >> 16) & 0xff;	DMAC_WAIT0;}GET_CNT(){	register VOLATILE int COUNT;	COUNT = sc_tclow;	DMAC_WAIT0;	COUNT += (sc_tcmid << 8) & 0xff00;	DMAC_WAIT0;	COUNT += (sc_tchi << 16) & 0xff0000;	DMAC_WAIT0;	return (COUNT);}GET_INTR(DATA1, DATA2)	register VOLATILE int *DATA1;	register VOLATILE int *DATA2;{	register VOLATILE int dummy;	(void) WAIT_STATR_BITCLR(R0_CIP);	while (sc_statr & R0_MIRQ) {		DMAC_WAIT0;		*DATA1 |= sc_intrq1;		DMAC_WAIT0;		*DATA2 |= sc_intrq2;		DMAC_WAIT0;	}}sc_send(chan, ie, sc)	register int chan;	register int ie;	register struct scsi *sc;{	register VOLATILE struct sc_chan_stat *cs;	register struct scsi_stat *ss;	register int i;	cs = &chan_stat[chan];	ss = &scsi_stat;	if (sc == NULL || cs->sc != NULL) {		printf("SCSI%d:sc_send() NULL sc or NOT NULL cs->sc\n", chan);		printf("ie=0x%x sc=0x%x cs->sc=0x%x\n", ie, sc, cs->sc);		if (sc) {			printf("cdb=");			for (i = 0; i < 6; i++)				printf("0x%x ", sc->sc_cdb.un_reserved[i]);			printf("\n");		}		panic(ScsiSoftError);		/*NOTREACHED*/	}	if ((sc->sc_cdb.un_reserved[0] == SCOP_RESET)			&& (sc->sc_cdb.un_reserved[1] == SCOP_RESET)) {		/*		 * SCSI bus reset command procedure		 *	(vender unique by Sony Corp.)		 */#ifdef SCSI_1185AQ		if (sc_idenr & 0x08) {			scsi_1185AQ = 1;		}#endif		cs->sc = sc;		scsi_hardreset();		sc->sc_istatus = INST_EP;		cs->sc = NULL;		return;	}	if (sc->sc_map && (sc->sc_map->mp_pages > 0)) {		/*		 * use map table		 */		sc->sc_coffset = sc->sc_map->mp_offset & PGOFSET;		if (sc->sc_map->mp_pages > NSCMAP) {			printf("SCSI%d: map table overflow\n", chan);			sc->sc_istatus = INST_EP|INST_LB|INST_PRE;			return;		}	} else {		/*		 * no use map table		 */		sc->sc_coffset = (u_int)sc->sc_cpoint & PGOFSET;	}	sc->sc_ctag = 0;	cs->sc = sc;	cs->comflg = OFF;	cs->intr_flg = ie;	cs->chan_num = chan;	perr_flag[chan] = 0;	mout_flag[chan] = 0;	min_cnt[chan] = 0;	sel_stat[chan] = SEL_WAIT;	append_wb(cs);	sc_start();}/* *	SCSI start up routine */sc_start(){	register VOLATILE struct sc_chan_stat *cs;	register struct scsi_stat *ss;	register int s;	register VOLATILE int chan;	register VOLATILE int dummy;	ss = &scsi_stat;	s = splclock();	chan = get_wb_chan();	if ((chan < 0) || (ss->ipc >= 0))		goto sc_start_exit;	if (sel_stat[chan] != SEL_WAIT) {		/*		 * already started		 */		goto sc_start_exit;	}	sel_stat[chan] = SEL_START;	(void) splscsi();	cs = &chan_stat[chan];	dummy = sc_cmonr;	DMAC_WAIT0;	if (dummy & (R4_MBSY|R4_MSEL)) {		sel_stat[chan] = SEL_WAIT;		goto sc_start_exit;	}	/*	 *	send SELECT with ATN command	 */	ss->dma_stat = OFF;	pad_start = 0;	dummy = sc_statr;	DMAC_WAIT0;	if (dummy & R0_CIP) {		sel_stat[chan] = SEL_WAIT;		goto sc_start_exit;	}	sc_idenr = (chan << SC_TG_SHIFT) | SC_OWNID;	DMAC_WAIT0;#ifdef SCSI_1185AQ	if (scsi_1185AQ)		sc_intok1 = Ra_STO|Ra_ARBF;	else		sc_intok1 = Ra_STO|Ra_RSL|Ra_ARBF;#else	sc_intok1 = Ra_STO|Ra_RSL|Ra_ARBF;#endif	DMAC_WAIT0;	/*	 * BUGFIX for signal reflection on BSY	 *	!Rb_DCNT	 */	sc_intok2 = Rb_FNC|Rb_SRST|Rb_PHC|Rb_SPE;	DMAC_WAIT0;	dummy = sc_cmonr;	DMAC_WAIT0;	if (dummy & (R4_MBSY|R4_MSEL)) {		sel_stat[chan] = SEL_WAIT;		goto sc_start_exit;	}	SET_CMD(SCMD_SEL_ATN);sc_start_exit:	splx(s);}/* *	SCSI interrupt service routine */scintr(){	register struct scsi_stat *ss;	register int iloop;	register VOLATILE int chan;	register VOLATILE int dummy;	int s_int1, s_int2;scintr_loop:#if defined(CHECK_MRQ) && defined(news3400)	while (dmac_gstat & CH_MRQ(CH_SCSI))		DMAC_WAIT;#endif	for (iloop = 0; iloop < 100; iloop++) {		dummy = sc_statr;		DMAC_WAIT;		if ((dummy & R0_CIP) == 0)			break;	}	/*	 * get SCSI interrupt request	 */	while (sc_statr & R0_MIRQ) {		DMAC_WAIT0;		s_int1 = sc_intrq1;		DMAC_WAIT0;		s_int2 = sc_intrq2;		DMAC_WAIT0;		int_stat1 |= s_int1;		int_stat2 |= s_int2;	}	if (int_stat2 & R3_SRST) {		/*		 * RST signal is drived		 */		int_stat2 &= ~R3_SRST;		scsi_softreset();		goto scintr_exit;	}	ss = &scsi_stat;	if ((ss->ipc < 0) && (ss->wrc <= 0) && (ss->wbc <= 0)) {		int_stat1 = 0;		int_stat2 = 0;		goto scintr_exit;	}	chan = get_wb_chan();	if ((chan >= 0) && (sel_stat[chan] == SEL_START) &&		(last_cmd == SCMD_SEL_ATN)) {		/*		 *	Check the result of SELECTION command		 */		if (int_stat1 & R2_RSL) {			/*			 * RESELECTION occur			 */			if (ss->wrc > 0) {				sel_stat[chan] = SEL_RSLD;			} else {				/*				 * Ghost RESELECTION ???				 */				int_stat1 &= ~R2_RSL;			}		}		if (int_stat1 & R2_ARBF) {			/*			 * ARBITRATION fault			 */			int_stat1 &= ~R2_ARBF;			sel_stat[chan] = SEL_ARBF;		}		if (int_stat1 & R2_STO) {			/*			 * SELECTION timeout			 */			int_stat1 &= ~R2_STO;			if ((int_stat2&(R3_PHC|R3_RMSG)) != (R3_PHC|R3_RMSG)) {				ss->ipc = chan;				ss->ip = &chan_stat[chan];				sel_stat[chan] = SEL_TIMEOUT;				chan_stat[chan].sc->sc_istatus					= INST_EP|INST_TO;				release_wb();			}		}		/*		 *	SELECTION command done		 */		switch (sel_stat[chan]) {		case SEL_START:			if ((int_stat2 & R3_FNC) == 0)				break;			/*			 * SELECTION success			 */			sc_intok2 = Rb_FNC|Rb_DCNT|Rb_SRST|Rb_PHC|Rb_SPE;			ss->ipc = chan;			ss->ip = &chan_stat[chan];			ss->ip->sc->sc_istatus |= INST_IP;			ss->dma_stat = OFF;			pad_start = 0;			sel_stat[chan] = SEL_SUCCESS;			release_wb();#ifndef NOT_SUPPORT_SYNCTR			sc_syncr = sync_tr[chan];			DMAC_WAIT0;#endif			DMAC_WAIT0;			break;		case SEL_TIMEOUT:			/*			 * SELECTION time out			 */			sc_discon();			goto scintr_exit;		/* case SEL_RSLD: */		/* case SEL_ARBF: */		default:			/*			 * SELECTION failed			 */			sel_stat[chan] = SEL_WAIT;			break;		}		if ((int_stat1 & R2_RSL) == 0)			int_stat2 &= ~R3_FNC;	}	if (ss->ip != NULL) {		/*		 * check In Process channel's request		 */		if (ss->dma_stat != OFF) {			/*			 * adjust pointer & counter			 */			adjust_transfer(ss->ip);		}		if (int_stat2 & R3_SPE) {			register int VOLATILE statr;			register int VOLATILE cmonr;			statr = sc_statr;			DMAC_WAIT0;			cmonr = sc_cmonr;			int_stat2 &= ~R3_SPE;			perr_flag[ss->ip->chan_num] = 1;		}	}	if (int_stat2 & R3_DCNT) {		/*		 * Bus Free		 */		sc_discon();		int_stat2 &= ~R3_DCNT;	}	if ((ss->ipc >= 0) && (sel_stat[ss->ipc] == SEL_RSL_WAIT)) {

⌨️ 快捷键说明

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