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

📄 fxp.c

📁 minix3.1.1源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
		size= 0;		o= 0;		for (i= 0; i<count; i += IOVEC_NR,			iov_src += IOVEC_NR * sizeof(fp->fxp_iovec[0]))		{			n= IOVEC_NR;			if (i+n > count)				n= count-i;			r= sys_vircopy(fxp_client, D, iov_src, 				SELF, D, (vir_bytes)fp->fxp_iovec,				n * sizeof(fp->fxp_iovec[0]));			if (r != OK)				panic("FXP","fxp_readv: sys_vircopy failed", r);			for (j= 0, iovp= fp->fxp_iovec; j<n; j++, iovp++)			{				s= iovp->iov_size;				if (size + s > packlen)				{					assert(packlen > size);					s= packlen-size;				}				r= sys_vircopy(SELF, D,					(vir_bytes)(rfdp->rfd_buf+o),					fxp_client, D, iovp->iov_addr, s);				if (r != OK)				{					panic("FXP","fxp_readv: sys_vircopy failed",						r);				}				size += s;				if (size == packlen)					break;				o += s;			}			if (size == packlen)				break;		}		if (size < packlen)		{			assert(0);		}	}	else	{  		assert(0);	}	fp->fxp_read_s= packlen;	fp->fxp_flags= (fp->fxp_flags & ~FF_READING) | FF_PACK_RECV;	/* Re-init the current buffer */	rfdp->rfd_status= 0;	rfdp->rfd_command= RFDC_EL;	rfdp->rfd_reserved= 0;	rfdp->rfd_res= 0;	rfdp->rfd_size= sizeof(rfdp->rfd_buf);	fxp_rx_nbuf= fp->fxp_rx_nbuf;	if (fxp_rx_head == 0)	{		prev_rfdp= &fp->fxp_rx_buf[fxp_rx_nbuf-1];	}	else		prev_rfdp= &rfdp[-1];	assert(prev_rfdp->rfd_command & RFDC_EL);	prev_rfdp->rfd_command &= ~RFDC_EL;	fxp_rx_head++;	if (fxp_rx_head == fxp_rx_nbuf)		fxp_rx_head= 0;	assert(fxp_rx_head < fxp_rx_nbuf);	fp->fxp_rx_head= fxp_rx_head;	if (!from_int)		reply(fp, OK, FALSE);	return;suspend:	if (fp->fxp_rx_need_restart)	{		fp->fxp_rx_need_restart= 0;		/* Check the status of the RU */		scb_status= fxp_inb(port, SCB_STATUS);		if ((scb_status & SS_RUS_MASK) != SS_RU_NORES)		{			/* Race condition? */			printf("fxp_readv: restart race: 0x%x\n",				scb_status);			assert((scb_status & SS_RUS_MASK) == SS_RU_READY);		}		else		{			fxp_restart_ru(fp);		}	}	if (from_int)	{		assert(fp->fxp_flags & FF_READING);		/* No need to store any state */		return;	}	fp->fxp_rx_mess= *mp;	assert(!(fp->fxp_flags & FF_READING));	fp->fxp_flags |= FF_READING;	reply(fp, OK, FALSE);}/*===========================================================================* *				fxp_do_conf				     * *===========================================================================*/static void fxp_do_conf(fp)fxp_t *fp;{	int r;	u32_t bus_addr;	struct cbl_conf cc;	clock_t t0,t1;	/* Configure device */	cc.cc_status= 0;	cc.cc_command= CBL_C_EL | CBL_CONF;	cc.cc_linkaddr= 0;	memcpy(cc.cc_bytes, fp->fxp_conf_bytes, sizeof(cc.cc_bytes));	r= sys_umap(SELF, D, (vir_bytes)&cc, (phys_bytes)sizeof(cc),		&bus_addr);	if (r != OK)		panic("FXP","sys_umap failed", r);	fxp_cu_ptr_cmd(fp, SC_CU_START, bus_addr, TRUE /* check idle */);	getuptime(&t0);	do {		/* Wait for CU command to complete */		if (cc.cc_status & CBL_F_C)			break;	} while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(100000));	if (!(cc.cc_status & CBL_F_C))		panic("FXP","fxp_do_conf: CU command failed to complete", NO_NUM);	if (!(cc.cc_status & CBL_F_OK))		panic("FXP","fxp_do_conf: CU command failed", NO_NUM);}/*===========================================================================* *				fxp_cu_ptr_cmd				     * *===========================================================================*/static void fxp_cu_ptr_cmd(fp, cmd, bus_addr, check_idle)fxp_t *fp;int cmd;phys_bytes bus_addr;int check_idle;{	clock_t t0,t1;	port_t port;	u8_t scb_cmd;	port= fp->fxp_base_port;	if (check_idle)	{		/* Consistency check. Make sure that CU is idle */		if ((fxp_inb(port, SCB_STATUS) & SS_CUS_MASK) != SS_CU_IDLE)			panic("FXP","fxp_cu_ptr_cmd: CU is not idle", NO_NUM);	}	fxp_outl(port, SCB_POINTER, bus_addr);	fxp_outb(port, SCB_CMD, cmd);	/* What is a reasonable time-out? There is nothing in the	 * documentation. 1 ms should be enough.	 */	getuptime(&t0);	do {		/* Wait for CU command to be accepted */		scb_cmd= fxp_inb(port, SCB_CMD);		if ((scb_cmd & SC_CUC_MASK) == SC_CU_NOP)			break;	} while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(100000));	if ((scb_cmd & SC_CUC_MASK) != SC_CU_NOP)		panic("FXP","fxp_cu_ptr_cmd: CU does not accept command", NO_NUM);}/*===========================================================================* *				fxp_ru_ptr_cmd				     * *===========================================================================*/static void fxp_ru_ptr_cmd(fp, cmd, bus_addr, check_idle)fxp_t *fp;int cmd;phys_bytes bus_addr;int check_idle;{	clock_t t0,t1;	port_t port;	u8_t scb_cmd;	port= fp->fxp_base_port;	if (check_idle)	{		/* Consistency check, make sure that RU is idle */		if ((fxp_inb(port, SCB_STATUS) & SS_RUS_MASK) != SS_RU_IDLE)			panic("FXP","fxp_ru_ptr_cmd: RU is not idle", NO_NUM);	}	fxp_outl(port, SCB_POINTER, bus_addr);	fxp_outb(port, SCB_CMD, cmd);	getuptime(&t0);	do {		/* Wait for RU command to be accepted */		scb_cmd= fxp_inb(port, SCB_CMD);		if ((scb_cmd & SC_RUC_MASK) == SC_RU_NOP)			break;	} while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(1000));	if ((scb_cmd & SC_RUC_MASK) != SC_RU_NOP)		panic("FXP","fxp_ru_ptr_cmd: RU does not accept command", NO_NUM);}/*===========================================================================* *				fxp_restart_ru				     * *===========================================================================*/static void fxp_restart_ru(fp)fxp_t *fp;{	int i, fxp_rx_nbuf;	port_t port;	struct rfd *rfdp;	port= fp->fxp_base_port;	fxp_rx_nbuf= fp->fxp_rx_nbuf;	for (i= 0, rfdp= fp->fxp_rx_buf; i<fxp_rx_nbuf; i++, rfdp++)	{		rfdp->rfd_status= 0;		rfdp->rfd_command= 0;		if (i == fp->fxp_rx_nbuf-1)			rfdp->rfd_command= RFDC_EL;		rfdp->rfd_reserved= 0;		rfdp->rfd_res= 0;		rfdp->rfd_size= sizeof(rfdp->rfd_buf);	}	fp->fxp_rx_head= 0;	/* Make sure that RU is in the 'No resources' state */	if ((fxp_inb(port, SCB_STATUS) & SS_RUS_MASK) != SS_RU_NORES)		panic("FXP","fxp_restart_ru: RU is in an unexpected state", NO_NUM);	fxp_ru_ptr_cmd(fp, SC_RU_START, fp->fxp_rx_busaddr,		FALSE /* do not check idle */);}/*===========================================================================* *				fxp_getstat				     * *===========================================================================*/static void fxp_getstat(mp)message *mp;{	clock_t t0,t1;	int dl_port;	port_t port;	fxp_t *fp;	u32_t *p;	eth_stat_t stats;	dl_port = mp->DL_PORT;	if (dl_port < 0 || dl_port >= FXP_PORT_NR)		panic("FXP","fxp_getstat: illegal port", dl_port);	fp= &fxp_table[dl_port];	fp->fxp_client= mp->DL_PROC;	assert(fp->fxp_mode == FM_ENABLED);	assert(fp->fxp_flags & FF_ENABLED);	port= fp->fxp_base_port;	p= &fp->fxp_stat.sc_tx_fcp;	*p= 0;	/* The dump commmand doesn't take a pointer. Setting a pointer	 * doesn't hard though.	 */	fxp_cu_ptr_cmd(fp, SC_CU_DUMP_SC, 0, FALSE /* do not check idle */);	getuptime(&t0);	do {		/* Wait for CU command to complete */		if (*p != 0)			break;	} while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(1000));	if (*p == 0)		panic("FXP","fxp_getstat: CU command failed to complete", NO_NUM);	if (*p != SCM_DSC)		panic("FXP","fxp_getstat: bad magic", NO_NUM);	stats.ets_recvErr=		fp->fxp_stat.sc_rx_crc +		fp->fxp_stat.sc_rx_align +		fp->fxp_stat.sc_rx_resource +		fp->fxp_stat.sc_rx_overrun +		fp->fxp_stat.sc_rx_cd +		fp->fxp_stat.sc_rx_short;	stats.ets_sendErr=		fp->fxp_stat.sc_tx_maxcol +		fp->fxp_stat.sc_tx_latecol +		fp->fxp_stat.sc_tx_crs;	stats.ets_OVW= fp->fxp_stat.sc_rx_overrun;	stats.ets_CRCerr= fp->fxp_stat.sc_rx_crc;	stats.ets_frameAll= fp->fxp_stat.sc_rx_align;	stats.ets_missedP= fp->fxp_stat.sc_rx_resource;	stats.ets_packetR= fp->fxp_stat.sc_rx_good;	stats.ets_packetT= fp->fxp_stat.sc_tx_good;	stats.ets_transDef= fp->fxp_stat.sc_tx_defered;	stats.ets_collision= fp->fxp_stat.sc_tx_totcol;	stats.ets_transAb= fp->fxp_stat.sc_tx_maxcol;	stats.ets_carrSense= fp->fxp_stat.sc_tx_crs;	stats.ets_fifoUnder= fp->fxp_stat.sc_tx_underrun;	stats.ets_fifoOver= fp->fxp_stat.sc_rx_overrun;	stats.ets_CDheartbeat= 0;	stats.ets_OWC= fp->fxp_stat.sc_tx_latecol;	put_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,		(vir_bytes) sizeof(stats), &stats);	reply(fp, OK, FALSE);}/*===========================================================================* *				fxp_getname				     * *===========================================================================*/static void fxp_getname(mp)message *mp;{	int r;	strncpy(mp->DL_NAME, progname, sizeof(mp->DL_NAME));	mp->DL_NAME[sizeof(mp->DL_NAME)-1]= '\0';	mp->m_type= DL_NAME_REPLY;	r= send(mp->m_source, mp);	if (r != OK)		panic("FXP", "fxp_getname: send failed", r);}/*===========================================================================* *				fxp_handler				     * *===========================================================================*/static int fxp_handler(fp)fxp_t *fp;{	int port;	u16_t isr;	RAND_UPDATE	port= fp->fxp_base_port;	/* Ack interrupt */	isr= fxp_inb(port, SCB_INT_STAT);	fxp_outb(port, SCB_INT_STAT, isr);	if (isr & SIS_FR)	{		isr &= ~SIS_FR;		if (!fp->fxp_got_int && (fp->fxp_flags & FF_READING))		{			fp->fxp_got_int= TRUE;			interrupt(fxp_tasknr);		}	}	if (isr & SIS_CNA)	{		isr &= ~SIS_CNA;		if (!fp->fxp_tx_idle)		{			fp->fxp_send_int= TRUE;			if (!fp->fxp_got_int)			{				fp->fxp_got_int= TRUE;				interrupt(fxp_tasknr);			}		}	}	if (isr & SIS_RNR)	{		isr &= ~SIS_RNR;		/* Assume that receive buffer is full of packets. fxp_readv		 * will restart the RU.		 */		fp->fxp_rx_need_restart= 1;	}	if (isr)	{		printf("fxp_handler: unhandled interrupt: isr = 0x%02x\n",			isr);	}	return 1;}/*===========================================================================* *				fxp_check_ints				     * *===========================================================================*/static void fxp_check_ints(fp)fxp_t *fp;{	int n, fxp_flags, prev_tail;	int fxp_tx_tail, fxp_tx_nbuf, fxp_tx_threshold;	port_t port;	u32_t busaddr;	u16_t tx_status;	u8_t scb_status;	struct tx *txp;	fxp_flags= fp->fxp_flags;	if (fxp_flags & FF_READING)	{		if (!(fp->fxp_rx_buf[fp->fxp_rx_head].rfd_status & RFDS_C))			; /* Nothing */		else if (fp->fxp_rx_mess.m_type == DL_READV)		{			fxp_readv(&fp->fxp_rx_mess, TRUE /* from int */,				TRUE /* vectored */);		}		else		{			assert(fp->fxp_rx_mess.m_type == DL_READ);			fxp_readv(&fp->fxp_rx_mess, TRUE /* from int */,				FALSE /* !vectored */);		}	}	if (fp->fxp_tx_idle)		;	/* Nothing to do */	else if (fp->fxp_send_int)	{		fp->fxp_send_int= FALSE;		fxp_tx_tail= fp->fxp_tx_tail;		fxp_tx_nbuf= fp->fxp_tx_nbuf;		n= 0;		for (;;)		{			txp= &fp->fxp_tx_buf[fxp_tx_tail];			tx_status= txp->tx_status;			if (!(tx_status & TXS_C))				break;			n++;			assert(tx_status & TXS_OK);			if (tx_status & TXS_U)			{				fxp_tx_threshold= fp->fxp_tx_threshold;				if (fxp_tx_threshold < TXTT_MAX)				{					fxp_tx_threshold++;					fp->fxp_tx_threshold= fxp_tx_threshold;				}				printf(			"fxp_check_ints: fxp_tx_threshold = 0x%x\n",					fxp_tx_threshold);			}			if (txp->tx_command & TXC_EL)			{				fp->fxp_tx_idle= 1;				break;			}			fxp_tx_tail++;			if (fxp_tx_tail == fxp_tx_nbuf)				fxp_tx_tail= 0;			assert(fxp_tx_tail < fxp_tx_nbuf);		}		if (fp->fxp_need_conf)		{			/* Check the status of the CU */			port= fp->fxp_base_port;			scb_status= fxp_inb(port, SCB_STATUS);			if ((scb_status & SS_CUS_MASK) != SS_CU_IDLE)			{				/* Nothing to do */				printf("scb_status = 0x%x\n", scb_status);			}			else			{				printf("fxp_check_ints: fxp_need_conf\n");				fp->fxp_need_conf= FALSE;				fxp_do_conf(fp);			}		}		if (n)		{			if (!fp->fxp_tx_idle)			{				fp->fxp_tx_tail= fxp_tx_tail;								/* Check the status of the CU */				port= fp->fxp_base_port;				scb_status= fxp_inb(port, SCB_STATUS);				if ((scb_status & SS_CUS_MASK) != SS_CU_IDLE)				{					/* Nothing to do */					printf("scb_status = 0x%x\n",						scb_status);				}				else				{					if (fxp_tx_tail == 0)						prev_tail= fxp_tx_nbuf-1;					else						prev_tail= fxp_tx_tail-1;					busaddr= fp->fxp_tx_buf[prev_tail].						tx_linkaddr;					fxp_cu_ptr_cmd(fp, SC_CU_START,						busaddr, 1 /* check idle */);				}			}			if (fp->fxp_flags & FF_SEND_AVAIL)			{				if (fp->fxp_tx_mess.m_type == DL_WRITEV)				{					fxp_writev(&fp->fxp_tx_mess,						TRUE /* from int */,						TRUE /* vectored */);				}				else				{					assert(fp->fxp_tx_mess.m_type ==						DL_WRITE);					fxp_writev(&fp->fxp_tx_mess,						TRUE /* from int */,						FALSE /* !vectored */);				}			}		}			}	if (fp->fxp_report_link)		fxp_report_link(fp);	if (fp->fxp_flags & (FF_PACK_SENT | FF_PACK_RECV))		reply(fp, OK, TRUE);}/*===========================================================================* *				fxp_watchdog_f				     * *===========================================================================*/static void fxp_watchdog_f(tp)timer_t *tp;{	int i;	fxp_t *fp;	tmr_arg(&fxp_watchdog)->ta_int= 0;	fxp_set_timer(&fxp_watchdog, HZ, fxp_watchdog_f);	for (i= 0, fp = &fxp_table[0]; i<FXP_PORT_NR; i++, fp++)	{		if (fp->fxp_mode != FM_ENABLED)			continue;		/* Handle race condition, MII interface mgith be busy */		if(!fp->fxp_mii_busy)		{			/* Check the link status. */			if (fxp_link_changed(fp))			{#if VERBOSE				printf("fxp_watchdog_f: link changed\n");#endif				fp->fxp_report_link= TRUE;				fp->fxp_got_int= TRUE;				interrupt(fxp_tasknr);			}		}				if (!(fp->fxp_flags & FF_SEND_AVAIL))		{			/* Assume that an idle system is alive */			fp->fxp_tx_alive= TRUE;			continue;		}		if (fp->fxp_tx_alive)		{			fp->fxp_tx_alive= FALSE;			continue;		}		fp->fxp_need_reset= TRUE;		fp->fxp_got_int= TRUE;		interrupt(fxp_tasknr);	}}/*===========================================================================* *				fxp_link_changed			     * *===========================================================================*/static int fxp_link_changed(fp)fxp_t *fp;{	u16_t scr;

⌨️ 快捷键说明

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