📄 mnx_eth.c
字号:
/*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(ð_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(ð_port->etp_osdep.etp_recvev); rport= eth_port->etp_osdep.etp_port; assert(rport >= 0 && rport < eth_conf_nr); rep= ð_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(ð_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(ð_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 + -