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

📄 fxp.c

📁 minix3.1.1源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
		return;	/* PCI device is present */	fp->fxp_mode= FM_ENABLED;	fp->fxp_flags= FF_EMPTY;	fp->fxp_got_int= 0;	fp->fxp_send_int= 0;	fp->fxp_ee_addrlen= 0;	/* Unknown */	fp->fxp_need_reset= 0;	fp->fxp_report_link= 0;	fp->fxp_link_up= -1;	/* Unknown */	fp->fxp_mii_busy= 0;	fp->fxp_read_s= 0;	fp->fxp_rx_need_restart= 0;	fp->fxp_need_conf= 0;	fp->fxp_tx_head= 0;	fp->fxp_tx_tail= 0;	fp->fxp_tx_alive= 0;	fp->fxp_tx_threshold= TXTT_MIN;	/* Try to come up with a sensible configuration for the current	 * device. Unfortunately every device is different, defaults are	 * not always zero, and some fields are re-used with a completely	 * different interpretation. We start out with a sensible default	 * for all devices and then add device specific changes.	 */	fp->fxp_conf_bytes[0]= CC_BYTES_NR;	fp->fxp_conf_bytes[1]= CTL_DEFAULT | CRL_DEFAULT;	fp->fxp_conf_bytes[2]= CAI_DEFAULT;	fp->fxp_conf_bytes[3]= 0;	fp->fxp_conf_bytes[4]= 0;	fp->fxp_conf_bytes[5]= 0;	fp->fxp_conf_bytes[6]= CCB6_ESC | CCB6_ETCB | CCB6_RES;	fp->fxp_conf_bytes[7]= CUR_1;	fp->fxp_conf_bytes[8]= CCB8_503_MII;	fp->fxp_conf_bytes[9]= 0;	fp->fxp_conf_bytes[10]= CLB_NORMAL | CPAL_DEFAULT | CCB10_NSAI |				CCB10_RES1;	fp->fxp_conf_bytes[11]= 0;	fp->fxp_conf_bytes[12]= CIS_DEFAULT;	fp->fxp_conf_bytes[13]= CCB13_DEFAULT;	fp->fxp_conf_bytes[14]= CCB14_DEFAULT;	fp->fxp_conf_bytes[15]= CCB15_RES1 | CCB15_RES2;	fp->fxp_conf_bytes[16]= CCB16_DEFAULT;	fp->fxp_conf_bytes[17]= CCB17_DEFAULT;	fp->fxp_conf_bytes[18]= CCB18_RES1 | CCB18_PFCT | CCB18_PE;	fp->fxp_conf_bytes[19]= CCB19_FDPE;	fp->fxp_conf_bytes[20]= CCB20_PFCL | CCB20_RES1;	fp->fxp_conf_bytes[21]= CCB21_RES21;#if VERBOSE	for (i= 0; i<CC_BYTES_NR; i++)		printf("%d: %0x, ", i, fp->fxp_conf_bytes[i]);	printf("\n");#endif	mwi= 0;		/* Do we want "Memory Write and Invalidate"? */	ext_stat1= 0;	/* Do we want extended statistical counters? */	ext_stat2= 0;	/* Do we want even more statistical counters? */	lim_fifo= 0;	/* Limit number of frame in TX FIFO */	i82503= 0;	/* Older 10 Mbps interface on the 82557 */	fc= 0;		/* Flow control */	switch(fp->fxp_type)	{	case FT_82557:		if (i82503)		{			fp->fxp_conf_bytes[8] &= ~CCB8_503_MII;			fp->fxp_conf_bytes[15] |= CCB15_CRSCDT;		}		break;	case FT_82558A:	case FT_82559:		if (mwi)			fp->fxp_conf_bytes[3] |= CCB3_MWIE;		if (ext_stat1)			fp->fxp_conf_bytes[6] &= ~CCB6_ESC;		if (ext_stat2)			fp->fxp_conf_bytes[6] &= ~CCB6_TCOSC;		if (lim_fifo)			fp->fxp_conf_bytes[7] |= CCB7_2FFIFO;		if (fc)		{			/* From FreeBSD driver */			fp->fxp_conf_bytes[16]= 0x1f;			fp->fxp_conf_bytes[17]= 0x01;			fp->fxp_conf_bytes[19] |= CCB19_FDRSTAFC |				CCB19_FDRSTOFC;		}		fp->fxp_conf_bytes[18] |= CCB18_LROK;		break;	default:		panic("FXP","fxp_conf_hw: bad device type", fp->fxp_type);	}#if VERBOSE	for (i= 0; i<CC_BYTES_NR; i++)		printf("%d: %0x, ", i, fp->fxp_conf_bytes[i]);	printf("\n");#endif}/*===========================================================================* *				fxp_init_hw				     * *===========================================================================*/static void fxp_init_hw(fp)fxp_t *fp;{	int i, r, isr;	port_t port;	u32_t bus_addr;	port= fp->fxp_base_port;	fxp_init_buf(fp);	fp->fxp_flags = FF_EMPTY;	fp->fxp_flags |= FF_ENABLED;	/* Set the interrupt handler and policy. Do not automatically 	 * reenable interrupts. Return the IRQ line number on interrupts. 	 */ 	fp->fxp_hook = fp->fxp_irq;	r= sys_irqsetpolicy(fp->fxp_irq, 0, &fp->fxp_hook);	if (r != OK)		panic("FXP","sys_irqsetpolicy failed", r);	fxp_reset_hw(fp);	r= sys_irqenable(&fp->fxp_hook);	if (r != OK)		panic("FXP","sys_irqenable failed", r);	/* Reset PHY? */	fxp_do_conf(fp);	/* Set pointer to statistical counters */	r= sys_umap(SELF, D, (vir_bytes)&fp->fxp_stat, sizeof(fp->fxp_stat),		&bus_addr);	if (r != OK)		panic("FXP","sys_umap failed", r);	fxp_cu_ptr_cmd(fp, SC_CU_LOAD_DCA, bus_addr, TRUE /* check idle */);	/* Ack previous interrupts */	isr= fxp_inb(port, SCB_INT_STAT);	fxp_outb(port, SCB_INT_STAT, isr);	/* Enable interrupts */	fxp_outb(port, SCB_INT_MASK, 0);	fxp_ru_ptr_cmd(fp, SC_RU_START, fp->fxp_rx_busaddr,		TRUE /* check idle */);	fxp_confaddr(fp);	if (debug)	{		printf("%s: Ethernet address ", fp->fxp_name);		for (i= 0; i < 6; i++)		{			printf("%x%c", fp->fxp_address.ea_addr[i],				i < 5 ? ':' : '\n');		}	}}/*===========================================================================* *				fxp_init_buf				     * *===========================================================================*/static void fxp_init_buf(fp)fxp_t *fp;{	size_t rx_totbufsize, tx_totbufsize, tot_bufsize;	phys_bytes buf;	int i, r;	struct rfd *rfdp;	struct tx *txp;	fp->fxp_rx_nbuf= N_RX_BUF;	rx_totbufsize= fp->fxp_rx_nbuf * sizeof(struct rfd);	fp->fxp_rx_bufsize= rx_totbufsize;	fp->fxp_tx_nbuf= N_TX_BUF;	tx_totbufsize= fp->fxp_tx_nbuf * sizeof(struct tx);	fp->fxp_tx_bufsize= tx_totbufsize;	tot_bufsize= tx_totbufsize + rx_totbufsize;	/* What about memory allocation? */	{		static int first_time= 1;		assert(first_time);		first_time= 0;#define BUFALIGN	4096		assert(tot_bufsize <= sizeof(buffer)-BUFALIGN); 		buf= (phys_bytes)buffer;		buf += BUFALIGN - (buf % BUFALIGN);	}	fp->fxp_rx_buf= (struct rfd *)buf;	r= sys_umap(SELF, D, (vir_bytes)buf, rx_totbufsize,		&fp->fxp_rx_busaddr);	if (r != OK)		panic("FXP","sys_umap failed", r);	for (i= 0, rfdp= fp->fxp_rx_buf; i<fp->fxp_rx_nbuf; i++, rfdp++)	{		rfdp->rfd_status= 0;		rfdp->rfd_command= 0;		if (i != fp->fxp_rx_nbuf-1)		{			r= sys_umap(SELF, D, (vir_bytes)&rfdp[1],				sizeof(rfdp[1]), &rfdp->rfd_linkaddr);			if (r != OK)				panic("FXP","sys_umap failed", r);		}		else		{			rfdp->rfd_linkaddr= fp->fxp_rx_busaddr;			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;	fp->fxp_tx_buf= (struct tx *)(buf+rx_totbufsize);	r= sys_umap(SELF, D, (vir_bytes)fp->fxp_tx_buf,		(phys_bytes)tx_totbufsize, &fp->fxp_tx_busaddr);	if (r != OK)		panic("FXP","sys_umap failed", r);	for (i= 0, txp= fp->fxp_tx_buf; i<fp->fxp_tx_nbuf; i++, txp++)	{		txp->tx_status= 0;		txp->tx_command= TXC_EL | CBL_NOP;	/* Just in case */		if (i != fp->fxp_tx_nbuf-1)		{			r= sys_umap(SELF, D, (vir_bytes)&txp[1],				(phys_bytes)sizeof(txp[1]),				&txp->tx_linkaddr);			if (r != OK)				panic("FXP","sys_umap failed", r);		}		else		{			txp->tx_linkaddr= fp->fxp_tx_busaddr;		}		txp->tx_tbda= TX_TBDA_NIL;		txp->tx_size= 0;		txp->tx_tthresh= fp->fxp_tx_threshold;		txp->tx_ntbd= 0;	}	fp->fxp_tx_idle= 1;}/*===========================================================================* *				fxp_reset_hw				     * *===========================================================================*/static void fxp_reset_hw(fp)fxp_t *fp;{/* Inline the function in init? */	port_t port;	port= fp->fxp_base_port;	/* Reset device */	fxp_outl(port, CSR_PORT, CP_CMD_SOFT_RESET);	tickdelay(MICROS_TO_TICKS(CSR_PORT_RESET_DELAY));	/* Disable interrupts */	fxp_outb(port, SCB_INT_MASK, SIM_M);	/* Set CU base to zero */	fxp_cu_ptr_cmd(fp, SC_CU_LOAD_BASE, 0, TRUE /* check idle */);	/* Set RU base to zero */	fxp_ru_ptr_cmd(fp, SC_RU_LOAD_BASE, 0, TRUE /* check idle */);}/*===========================================================================* *				fxp_confaddr				     * *===========================================================================*/static void fxp_confaddr(fp)fxp_t *fp;{	static char eakey[]= FXP_ENVVAR "#_EA";	static char eafmt[]= "x:x:x:x:x:x";	clock_t t0,t1;	int i, r;	port_t port;	u32_t bus_addr;	long v;	struct ias ias;	port= fp->fxp_base_port;	/* User defined ethernet address? */	eakey[sizeof(FXP_ENVVAR)-1]= '0' + (fp-fxp_table);#if 0	for (i= 0; i < 6; i++)	{		if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET)			break;		fp->fxp_address.ea_addr[i]= v;	}#else	i= 0;#endif#if 0	if (i != 0 && i != 6) env_panic(eakey);	/* It's all or nothing */#endif	if (i == 0)	{		/* Get ethernet address from EEPROM */		for (i= 0; i<3; i++)		{			v= eeprom_read(fp, i);			fp->fxp_address.ea_addr[i*2]= (v & 0xff);			fp->fxp_address.ea_addr[i*2+1]= ((v >> 8) & 0xff);		}	}	/* Tell NIC about ethernet address */	ias.ias_status= 0;	ias.ias_command= CBL_C_EL | CBL_AIS;	ias.ias_linkaddr= 0;	memcpy(ias.ias_ethaddr, fp->fxp_address.ea_addr,		sizeof(ias.ias_ethaddr));	r= sys_umap(SELF, D, (vir_bytes)&ias, (phys_bytes)sizeof(ias),		&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 (ias.ias_status & CBL_F_C)			break;	} while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(1000));	if (!(ias.ias_status & CBL_F_C))		panic("FXP","fxp_confaddr: CU command failed to complete", NO_NUM);	if (!(ias.ias_status & CBL_F_OK))		panic("FXP","fxp_confaddr: CU command failed", NO_NUM);#if VERBOSE	printf("%s: hardware ethernet address: ", fp->fxp_name);	for (i= 0; i<6; i++)	{		printf("%02x%s", fp->fxp_address.ea_addr[i], 			i < 5 ? ":" : "");	}	printf("\n");#endif}/*===========================================================================* *				fxp_rec_mode				     * *===========================================================================*/static void fxp_rec_mode(fp)fxp_t *fp;{	fp->fxp_conf_bytes[0]= CC_BYTES_NR;	/* Just to be sure */	fp->fxp_conf_bytes[15] &= ~(CCB15_BD|CCB15_PM);	fp->fxp_conf_bytes[21] &= ~CCB21_MA;	if (fp->fxp_flags & FF_PROMISC)		fp->fxp_conf_bytes[15] |= CCB15_PM;	if (fp->fxp_flags & FF_MULTI)		fp->fxp_conf_bytes[21] |= CCB21_MA;	if (!(fp->fxp_flags & (FF_BROAD|FF_MULTI|FF_PROMISC)))		fp->fxp_conf_bytes[15] |= CCB15_BD;	/* Queue request if not idle */	if (fp->fxp_tx_idle)	{		fxp_do_conf(fp);	}	else	{		printf("fxp_rec_mode: setting fxp_need_conf\n");		fp->fxp_need_conf= TRUE;	}}/*===========================================================================* *				fxp_writev				     * *===========================================================================*/static void fxp_writev(mp, from_int, vectored)message *mp;int from_int;int vectored;{	vir_bytes iov_src;	int i, j, n, o, r, s, dl_port, count, size, prev_head;	int fxp_client, fxp_tx_nbuf, fxp_tx_head;	u16_t tx_command;	fxp_t *fp;	iovec_t *iovp;	struct tx *txp, *prev_txp;	dl_port = mp->DL_PORT;	count = mp->DL_COUNT;	if (dl_port < 0 || dl_port >= FXP_PORT_NR)		panic("FXP","fxp_writev: illegal port", dl_port);	fp= &fxp_table[dl_port];	fxp_client= mp->DL_PROC;	fp->fxp_client= fxp_client;	assert(fp->fxp_mode == FM_ENABLED);	assert(fp->fxp_flags & FF_ENABLED);	if (from_int)	{		assert(fp->fxp_flags & FF_SEND_AVAIL);		fp->fxp_flags &= ~FF_SEND_AVAIL;		fp->fxp_tx_alive= TRUE;	}	if (fp->fxp_tx_idle)	{		txp= fp->fxp_tx_buf;		fxp_tx_head= 0;	/* lint */		prev_txp= NULL;	/* lint */	}	else	{			fxp_tx_nbuf= fp->fxp_tx_nbuf;		prev_head= fp->fxp_tx_head;		fxp_tx_head= prev_head+1;		if (fxp_tx_head == fxp_tx_nbuf)			fxp_tx_head= 0;		assert(fxp_tx_head < fxp_tx_nbuf);		if (fxp_tx_head == fp->fxp_tx_tail)		{			/* Send queue is full */			assert(!(fp->fxp_flags & FF_SEND_AVAIL));			fp->fxp_flags |= FF_SEND_AVAIL;			goto suspend;		}		prev_txp= &fp->fxp_tx_buf[prev_head];		txp= &fp->fxp_tx_buf[fxp_tx_head];	}	assert(!(fp->fxp_flags & FF_SEND_AVAIL));	assert(!(fp->fxp_flags & FF_PACK_SENT));	if (vectored)	{		iov_src = (vir_bytes)mp->DL_ADDR;		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_writev: sys_vircopy failed", r);			for (j= 0, iovp= fp->fxp_iovec; j<n; j++, iovp++)			{				s= iovp->iov_size;				if (size + s > ETH_MAX_PACK_SIZE_TAGGED)				{					panic("FXP","fxp_writev: invalid packet size",						NO_NUM);				}				r= sys_vircopy(fxp_client, D, iovp->iov_addr, 					SELF, D, (vir_bytes)(txp->tx_buf+o),					s);				if (r != OK)				{					panic("FXP","fxp_writev: sys_vircopy failed",						r);				}				size += s;				o += s;			}		}		if (size < ETH_MIN_PACK_SIZE)			panic("FXP","fxp_writev: invalid packet size", size);	}	else	{  		size= mp->DL_COUNT;		if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE_TAGGED)			panic("FXP","fxp_writev: invalid packet size", size);		r= sys_vircopy(fxp_client, D, (vir_bytes)mp->DL_ADDR, 			SELF, D, (vir_bytes)txp->tx_buf, size);		if (r != OK)			panic("FXP","fxp_writev: sys_vircopy failed", r);	}	txp->tx_status= 0;	txp->tx_command= TXC_EL | CBL_XMIT;	txp->tx_tbda= TX_TBDA_NIL;	txp->tx_size= TXSZ_EOF | size;	txp->tx_tthresh= fp->fxp_tx_threshold;	txp->tx_ntbd= 0;	if (fp->fxp_tx_idle)	{		fp->fxp_tx_idle= 0;		fp->fxp_tx_head= fp->fxp_tx_tail= 0;		fxp_cu_ptr_cmd(fp, SC_CU_START, fp->fxp_tx_busaddr,			TRUE /* check idle */);	}	else	{		/* Link new request in transmit list */		tx_command= prev_txp->tx_command;		assert(tx_command == (TXC_EL | CBL_XMIT));		prev_txp->tx_command= CBL_XMIT;		fp->fxp_tx_head= fxp_tx_head;	}	fp->fxp_flags |= FF_PACK_SENT;	/* If the interrupt handler called, don't send a reply. The reply	 * will be sent after all interrupts are handled. 	 */	if (from_int)		return;	reply(fp, OK, FALSE);	return;suspend:	if (from_int)		panic("FXP","fxp: should not be sending\n", NO_NUM);	fp->fxp_tx_mess= *mp;	reply(fp, OK, FALSE);}/*===========================================================================* *				fxp_readv				     * *===========================================================================*/static void fxp_readv(mp, from_int, vectored)message *mp;int from_int;int vectored;{	int i, j, n, o, r, s, dl_port, fxp_client, count, size,		fxp_rx_head, fxp_rx_nbuf;	port_t port;	unsigned packlen;	vir_bytes iov_src;	u16_t rfd_status;	u16_t rfd_res;	u8_t scb_status;	fxp_t *fp;	iovec_t *iovp;	struct rfd *rfdp, *prev_rfdp;	dl_port = mp->DL_PORT;	count = mp->DL_COUNT;	if (dl_port < 0 || dl_port >= FXP_PORT_NR)		panic("FXP","fxp_readv: illegal port", dl_port);	fp= &fxp_table[dl_port];	fxp_client= mp->DL_PROC;	fp->fxp_client= fxp_client;	assert(fp->fxp_mode == FM_ENABLED);	assert(fp->fxp_flags & FF_ENABLED);	port= fp->fxp_base_port;	fxp_rx_head= fp->fxp_rx_head;	rfdp= &fp->fxp_rx_buf[fxp_rx_head];	rfd_status= rfdp->rfd_status;	if (!(rfd_status & RFDS_C))	{		/* Receive buffer is empty, suspend */		goto suspend;	}	if (!rfd_status & RFDS_OK)	{		/* Not OK? What happened? */		assert(0);	}	else	{		assert(!(rfd_status & (RFDS_CRCERR | RFDS_ALIGNERR |			RFDS_OUTOFBUF | RFDS_DMAOVR | RFDS_TOOSHORT | 			RFDS_RXERR)));	}	rfd_res= rfdp->rfd_res;	assert(rfd_res & RFDR_EOF);	assert(rfd_res & RFDR_F);	packlen= rfd_res & RFDSZ_SIZE;	if (vectored)	{		iov_src = (vir_bytes)mp->DL_ADDR;

⌨️ 快捷键说明

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