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

📄 mnx_eth.c

📁 Minix3.11的源码。[MINIX 3是一个为高可靠性应用而设计的自由且简洁的类UNIX系统。]
💻 C
📖 第 1 页 / 共 2 页
字号:
/*inet/mnx_eth.cCreated:	Jan 2, 1992 by Philip HomburgCopyright 1995 Philip Homburg*/#include "inet.h"#include "proto.h"#include "osdep_eth.h"#include "generic/type.h"#include "generic/assert.h"#include "generic/buf.h"#include "generic/clock.h"#include "generic/eth.h"#include "generic/eth_int.h"#include "generic/sr.h"THIS_FILEstatic int recv_debug= 0;FORWARD _PROTOTYPE( void setup_read, (eth_port_t *eth_port) );FORWARD _PROTOTYPE( void read_int, (eth_port_t *eth_port, int count) );FORWARD _PROTOTYPE( void write_int, (eth_port_t *eth_port) );FORWARD _PROTOTYPE( void eth_recvev, (event_t *ev, ev_arg_t ev_arg) );FORWARD _PROTOTYPE( void eth_sendev, (event_t *ev, ev_arg_t ev_arg) );FORWARD _PROTOTYPE( eth_port_t *find_port, (message *m) );FORWARD _PROTOTYPE( void eth_restart, (eth_port_t *eth_port, int tasknr) );PUBLIC void osdep_eth_init(){	int i, r, tasknr, rport;	struct eth_conf *ecp;	eth_port_t *eth_port, *rep;	message mess;	/* First initialize normal ethernet interfaces */	for (i= 0, ecp= eth_conf, eth_port= eth_port_table;		i<eth_conf_nr; i++, ecp++, eth_port++)	{		if (eth_is_vlan(ecp))			continue;#ifdef __minix_vmd		r= sys_findproc(ecp->ec_task, &tasknr, 0);#else /* Minix 3 */		r = findproc(ecp->ec_task, &tasknr);#endif 		if (r != OK)		{			printf("eth%d: unable to find task %s: %d\n",				i, ecp->ec_task, r);			continue;		} 		eth_port->etp_osdep.etp_port= ecp->ec_port;		eth_port->etp_osdep.etp_task= tasknr;		ev_init(&eth_port->etp_osdep.etp_recvev);		mess.m_type= DL_INIT;		mess.DL_PORT= eth_port->etp_osdep.etp_port;		mess.DL_PROC= this_proc;		mess.DL_MODE= DL_NOMODE;		r= send(eth_port->etp_osdep.etp_task, &mess);		if (r<0)		{			printf(		"osdep_eth_init: unable to send to ethernet task, error= %d\n",				r);			continue;		}		r= receive(eth_port->etp_osdep.etp_task, &mess);		if (r<0)		{			printf(	"osdep_eth_init: unable to receive from ethernet task, error= %d\n",				r);			continue;		}		if (mess.m3_i1 == ENXIO)		{			printf(		"osdep_eth_init: no ethernet device at task=%d,port=%d\n",				eth_port->etp_osdep.etp_task, 				eth_port->etp_osdep.etp_port);			continue;		}		if (mess.m3_i1 < 0)			ip_panic(("osdep_eth_init: DL_INIT returned error %d\n",				mess.m3_i1));					if (mess.m3_i1 != eth_port->etp_osdep.etp_port)		{			ip_panic((	"osdep_eth_init: got reply for wrong port (got %d, expected %d)\n",				mess.m3_i1, eth_port->etp_osdep.etp_port));		}		eth_port->etp_ethaddr= *(ether_addr_t *)mess.m3_ca1;		sr_add_minor(if2minor(ecp->ec_ifno, ETH_DEV_OFF),			i, eth_open, eth_close, eth_read, 			eth_write, eth_ioctl, eth_cancel, eth_select);		eth_port->etp_flags |= EPF_ENABLED;		eth_port->etp_vlan= 0;		eth_port->etp_vlan_port= NULL;		eth_port->etp_wr_pack= 0;		eth_port->etp_rd_pack= 0;		setup_read (eth_port);	}	/* And now come the VLANs */	for (i= 0, ecp= eth_conf, eth_port= eth_port_table;		i<eth_conf_nr; i++, ecp++, eth_port++)	{		if (!eth_is_vlan(ecp))			continue; 		eth_port->etp_osdep.etp_port= ecp->ec_port;		eth_port->etp_osdep.etp_task= ANY;		ev_init(&eth_port->etp_osdep.etp_recvev);		rport= eth_port->etp_osdep.etp_port;		assert(rport >= 0 && rport < eth_conf_nr);		rep= &eth_port_table[rport];		if (!(rep->etp_flags & EPF_ENABLED))		{			printf(			"eth%d: underlying ethernet device %d not enabled",				i, rport);			continue;		}		if (rep->etp_vlan != 0)		{			printf(			"eth%d: underlying ethernet device %d is a VLAN",				i, rport);			continue;		}				eth_port->etp_ethaddr= rep->etp_ethaddr;		sr_add_minor(if2minor(ecp->ec_ifno, ETH_DEV_OFF),			i, eth_open, eth_close, eth_read, 			eth_write, eth_ioctl, eth_cancel, eth_select);		eth_port->etp_flags |= EPF_ENABLED;		eth_port->etp_vlan= ecp->ec_vlan;		eth_port->etp_vlan_port= rep;		assert(eth_port->etp_vlan != 0);		eth_port->etp_wr_pack= 0;		eth_port->etp_rd_pack= 0;		eth_reg_vlan(rep, eth_port);	}}PUBLIC void eth_write_port(eth_port, pack)eth_port_t *eth_port;acc_t *pack;{	eth_port_t *loc_port;	message mess1, block_msg;	int i, pack_size;	acc_t *pack_ptr;	iovec_t *iovec;	u8_t *eth_dst_ptr;	int multicast, r;	ev_arg_t ev_arg;	assert(!no_ethWritePort);	assert(!eth_port->etp_vlan);	assert(eth_port->etp_wr_pack == NULL);	eth_port->etp_wr_pack= pack;	iovec= eth_port->etp_osdep.etp_wr_iovec;	pack_size= 0;	for (i=0, pack_ptr= pack; i<IOVEC_NR && pack_ptr; i++,		pack_ptr= pack_ptr->acc_next)	{		iovec[i].iov_addr= (vir_bytes)ptr2acc_data(pack_ptr);		pack_size += iovec[i].iov_size= pack_ptr->acc_length;	}	if (i>= IOVEC_NR)	{		pack= bf_pack(pack);		/* packet is too fragmented */		eth_port->etp_wr_pack= pack;		pack_size= 0;		for (i=0, pack_ptr= pack; i<IOVEC_NR && pack_ptr;			i++, pack_ptr= pack_ptr->acc_next)		{			iovec[i].iov_addr= (vir_bytes)ptr2acc_data(pack_ptr);			pack_size += iovec[i].iov_size= pack_ptr->acc_length;		}	}	assert (i< IOVEC_NR);	assert (pack_size >= ETH_MIN_PACK_SIZE);	if (i == 1)	{		/* simple packets can be sent using DL_WRITE instead of 		 * DL_WRITEV.		 */		mess1.DL_COUNT= iovec[0].iov_size;		mess1.DL_ADDR= (char *)iovec[0].iov_addr;		mess1.m_type= DL_WRITE;	}	else	{		mess1.DL_COUNT= i;		mess1.DL_ADDR= (char *)iovec;		mess1.m_type= DL_WRITEV;	}	mess1.DL_PORT= eth_port->etp_osdep.etp_port;	mess1.DL_PROC= this_proc;	mess1.DL_MODE= DL_NOMODE;	for (;;)	{		r= sendrec(eth_port->etp_osdep.etp_task, &mess1);		if (r != ELOCKED)			break;		/* ethernet task is sending to this task, I hope */		r= receive(eth_port->etp_osdep.etp_task, &block_msg);		if (r < 0)			ip_panic(("unable to receive"));		loc_port= eth_port;		if (loc_port->etp_osdep.etp_port != block_msg.DL_PORT ||			loc_port->etp_osdep.etp_task != block_msg.m_source)		{			loc_port= find_port(&block_msg);		}		assert(block_msg.DL_STAT & (DL_PACK_SEND|DL_PACK_RECV));		if (block_msg.DL_STAT & DL_PACK_SEND)		{			assert(loc_port != eth_port);			loc_port->etp_osdep.etp_sendrepl= block_msg;			ev_arg.ev_ptr= loc_port;			ev_enqueue(&loc_port->etp_sendev, eth_sendev, ev_arg);		}		if (block_msg.DL_STAT & DL_PACK_RECV)		{			if (recv_debug)			{				printf(			"eth_write_port(block_msg): eth%d got DL_PACK_RECV\n",					loc_port-eth_port_table);			}			loc_port->etp_osdep.etp_recvrepl= block_msg;			ev_arg.ev_ptr= loc_port;			ev_enqueue(&loc_port->etp_osdep.etp_recvev,				eth_recvev, ev_arg);		}	}	if (r < 0)	{		printf("eth_write_port: sendrec to %d failed: %d\n",			eth_port->etp_osdep.etp_task, r);		return;	}	assert(mess1.m_type == DL_TASK_REPLY &&		mess1.DL_PORT == eth_port->etp_osdep.etp_port &&		mess1.DL_PROC == this_proc);	assert((mess1.DL_STAT >> 16) == OK);	if (mess1.DL_STAT & DL_PACK_RECV)	{		if (recv_debug)		{			printf(			"eth_write_port(mess1): eth%d got DL_PACK_RECV\n",				mess1.DL_PORT);		}		eth_port->etp_osdep.etp_recvrepl= mess1;		ev_arg.ev_ptr= eth_port;		ev_enqueue(&eth_port->etp_osdep.etp_recvev, eth_recvev,			ev_arg);	}	if (!(mess1.DL_STAT & DL_PACK_SEND))	{		/* Packet is not yet sent. */		return;	}	/* If the port is in promiscuous mode or the packet is	 * broad- or multicast, enqueue the reply packet.	 */	eth_dst_ptr= (u8_t *)ptr2acc_data(pack);	multicast= (*eth_dst_ptr & 1);	/* low order bit indicates multicast */	if (multicast || (eth_port->etp_osdep.etp_recvconf & NWEO_EN_PROMISC))	{		eth_port->etp_osdep.etp_sendrepl= mess1;		ev_arg.ev_ptr= eth_port;		ev_enqueue(&eth_port->etp_sendev, eth_sendev, ev_arg);		/* Pretend that we didn't get a reply. */		return;	}	/* packet is sent */	bf_afree(eth_port->etp_wr_pack);	eth_port->etp_wr_pack= NULL;}PUBLIC void eth_rec(m)message *m;{	int i;	eth_port_t *loc_port;	int stat;	assert(m->m_type == DL_TASK_REPLY);	set_time (m->DL_CLCK);	for (i=0, loc_port= eth_port_table; i<eth_conf_nr; i++, loc_port++)	{		if (loc_port->etp_osdep.etp_port == m->DL_PORT &&			loc_port->etp_osdep.etp_task == m->m_source)			break;	}	if (i == eth_conf_nr)	{		ip_panic(("message from unknown source: %d:%d",			m->m_source, m->DL_PORT));	}	stat= m->DL_STAT & 0xffff;	assert(stat & (DL_PACK_SEND|DL_PACK_RECV));	if (stat & DL_PACK_SEND)		write_int(loc_port);	if (stat & DL_PACK_RECV)	{		if (recv_debug)		{			printf("eth_rec: eth%d got DL_PACK_RECV\n",				m->DL_PORT);		}		read_int(loc_port, m->DL_COUNT);	}}PUBLIC void eth_check_drivers(m)message *m;{	int i, r, tasknr;	struct eth_conf *ecp;	eth_port_t *eth_port;	char *drivername;	tasknr= m->m_source;	printf("eth_check_drivers: got a notification from %d\n", tasknr);	m->m_type= DL_GETNAME;	r= sendrec(tasknr, m);	if (r != OK)	{		printf("eth_check_drivers: sendrec to %d failed: %d\n",			tasknr, r);		return;	}	if (m->m_type != DL_NAME_REPLY)	{		printf(		"eth_check_drivers: got bad getname reply (%d) from %d\n",			m->m_type, tasknr);		return;	}	drivername= m->m3_ca1;	printf("eth_check_drivers: got name: %s\n", drivername);	/* Re-init ethernet interfaces */	for (i= 0, ecp= eth_conf, eth_port= eth_port_table;		i<eth_conf_nr; i++, ecp++, eth_port++)	{		if (eth_is_vlan(ecp))			continue;		if (strcmp(ecp->ec_task, drivername) != 0)		{			/* Wrong driver */			continue;		}		eth_restart(eth_port, tasknr);	}}PUBLIC int eth_get_stat(eth_port, eth_stat)eth_port_t *eth_port;eth_stat_t *eth_stat;{	int r;	message mess, mlocked;	assert(!eth_port->etp_vlan);	mess.m_type= DL_GETSTAT;	mess.DL_PORT= eth_port->etp_osdep.etp_port;	mess.DL_PROC= this_proc;	mess.DL_ADDR= (char *)eth_stat;

⌨️ 快捷键说明

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