From 9d8b27a2b1501a0d28bad59f7259d916c3d771fa Mon Sep 17 00:00:00 2001 From: Philip Homburg Date: Fri, 9 Dec 2005 13:25:30 +0000 Subject: [PATCH] Support for starting ethernet driver after inet has been started --- servers/inet/generic/eth.c | 52 +++++++++++++- servers/inet/generic/eth_int.h | 2 + servers/inet/mnx_eth.c | 120 +++++++++++++++++++++++---------- 3 files changed, 135 insertions(+), 39 deletions(-) diff --git a/servers/inet/generic/eth.c b/servers/inet/generic/eth.c index a4f677394..e1aa97801 100644 --- a/servers/inet/generic/eth.c +++ b/servers/inet/generic/eth.c @@ -38,15 +38,17 @@ typedef struct eth_fd put_pkt_t ef_put_pkt; time_t ef_exp_time; size_t ef_write_count; + ioreq_t ef_ioctl_req; } eth_fd_t; #define EFF_FLAGS 0xf # define EFF_EMPTY 0x0 # define EFF_INUSE 0x1 -# define EFF_BUSY 0x6 +# define EFF_BUSY 0xE # define EFF_READ_IP 0x2 # define EFF_WRITE_IP 0x4 -# define EFF_OPTSET 0x8 +# define EFF_IOCTL_IP 0x8 +# define EFF_OPTSET 0x10 /* Note that the vh_type field is normally considered part of the ethernet * header. @@ -335,6 +337,17 @@ ioreq_t req; acc= bf_memreq(sizeof(nwio_ethstat_t)); compare (bf_bufsize(acc), ==, sizeof(*ethstat)); + if (!(eth_port->etp_flags & EPF_GOT_ADDR)) + { + printf( + "eth_ioctl: suspending NWIOGETHSTAT ioctl\n"); + + eth_fd->ef_ioctl_req= req; + assert(!(eth_fd->ef_flags & EFF_IOCTL_IP)); + eth_fd->ef_flags |= EFF_IOCTL_IP; + return NW_SUSPEND; + } + ethstat= (nwio_ethstat_t *)ptr2acc_data(acc); ethstat->nwes_addr= eth_port->etp_ethaddr; @@ -481,6 +494,13 @@ size_t data_len; if (nweo_flags & NWEO_REMSPEC) eth_hdr->eh_dst= eth_fd->ef_ethopt.nweo_rem; + if (!(eth_port->etp_flags & EPF_GOT_ADDR)) + { + /* No device, discard packet */ + bf_afree(eth_pack); + return NW_OK; + } + if (!(nweo_flags & NWEO_EN_PROMISC)) eth_hdr->eh_src= eth_port->etp_ethaddr; @@ -569,6 +589,11 @@ int which_operation; eth_fd->ef_flags &= ~EFF_WRITE_IP; reply_thr_get(eth_fd, EINTR, FALSE); break; + case SR_CANCEL_IOCTL: + assert (eth_fd->ef_flags & EFF_IOCTL_IP); + eth_fd->ef_flags &= ~EFF_IOCTL_IP; + reply_thr_get(eth_fd, EINTR, TRUE); + break; default: ip_panic(( "got unknown cancel request" )); } @@ -784,6 +809,7 @@ size_t pack_size; } else { + assert(eth_port->etp_flags & EPF_GOT_ADDR); if (eth_addrcmp (*dst_addr, eth_port->etp_ethaddr) == 0) pack_stat= NWEO_EN_LOC; else @@ -942,6 +968,28 @@ eth_port_t *vlan_port; eth_port->etp_vlan_tab[h]= vlan_port; } +PUBLIC void eth_restart_ioctl(eth_port) +eth_port_t *eth_port; +{ + int i; + eth_fd_t *eth_fd; + + for (i= 0, eth_fd= eth_fd_table; ief_flags & EFF_INUSE)) + continue; + if (eth_fd->ef_port != eth_port) + continue; + if (!(eth_fd->ef_flags & EFF_IOCTL_IP)) + continue; + if (eth_fd->ef_ioctl_req != NWIOGETHSTAT) + continue; + + eth_fd->ef_flags &= ~EFF_IOCTL_IP; + eth_ioctl(i, eth_fd->ef_ioctl_req); + } +} + PRIVATE void packet2user (eth_fd, pack, exp_time) eth_fd_t *eth_fd; acc_t *pack; diff --git a/servers/inet/generic/eth_int.h b/servers/inet/generic/eth_int.h index d9fc74d90..d5a4c28b3 100644 --- a/servers/inet/generic/eth_int.h +++ b/servers/inet/generic/eth_int.h @@ -38,6 +38,7 @@ typedef struct eth_port #define EPF_EMPTY 0x0 #define EPF_ENABLED 0x1 +#define EPF_GOT_ADDR 0x2 /* Got ethernet address from device */ #define EPF_READ_IP 0x20 #define EPF_READ_SP 0x40 @@ -53,6 +54,7 @@ void eth_set_rec_conf ARGS(( eth_port_t *eth_port, u32_t flags )); void eth_restart_write ARGS(( eth_port_t *eth_port )); void eth_loop_ev ARGS(( event_t *ev, ev_arg_t ev_arg )); void eth_reg_vlan ARGS(( eth_port_t *eth_port, eth_port_t *vlan_port )); +void eth_restart_ioctl ARGS(( eth_port_t *eth_port )); #endif /* ETH_INT_H */ diff --git a/servers/inet/mnx_eth.c b/servers/inet/mnx_eth.c index e76f890af..50dbb7de6 100644 --- a/servers/inet/mnx_eth.c +++ b/servers/inet/mnx_eth.c @@ -50,9 +50,13 @@ PUBLIC void osdep_eth_init() #endif if (r != OK) { + /* Eventually, we expect ethernet drivers to be + * started after INET. So we always end up here. And + * the findproc can be removed. + */ printf("eth%d: unable to find task %s: %d\n", i, ecp->ec_task, r); - continue; + tasknr= ANY; } eth_port->etp_osdep.etp_port= ecp->ec_port; @@ -64,45 +68,55 @@ PUBLIC void osdep_eth_init() mess.DL_PROC= this_proc; mess.DL_MODE= DL_NOMODE; - r= send(eth_port->etp_osdep.etp_task, &mess); - if (r<0) + if (tasknr == ANY) + r= ENXIO; + else { - printf( + 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); + } } - r= receive(eth_port->etp_osdep.etp_task, &mess); - if (r<0) + if (r == OK) { - printf( + 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; + r); + } } - if (mess.m3_i1 == ENXIO) + if (r == OK) { - printf( + r= mess.m3_i1; + if (r == 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(( + eth_port->etp_osdep.etp_task, + eth_port->etp_osdep.etp_port); + } + else if (r < 0) + { + ip_panic(( + "osdep_eth_init: DL_INIT returned error %d\n", + r)); + } + else 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)); + 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); @@ -112,7 +126,12 @@ PUBLIC void osdep_eth_init() eth_port->etp_vlan_port= NULL; eth_port->etp_wr_pack= 0; eth_port->etp_rd_pack= 0; - setup_read (eth_port); + if (r == OK) + { + eth_port->etp_ethaddr= *(ether_addr_t *)mess.m3_ca1; + eth_port->etp_flags |= EPF_GOT_ADDR; + setup_read (eth_port); + } } /* And now come the VLANs */ @@ -144,7 +163,11 @@ PUBLIC void osdep_eth_init() continue; } - eth_port->etp_ethaddr= rep->etp_ethaddr; + if (rep->etp_flags & EPF_GOT_ADDR) + { + eth_port->etp_ethaddr= rep->etp_ethaddr; + eth_port->etp_flags |= EPF_GOT_ADDR; + } sr_add_minor(if2minor(ecp->ec_ifno, ETH_DEV_OFF), i, eth_open, eth_close, eth_read, @@ -454,6 +477,13 @@ u32_t flags; assert(!eth_port->etp_vlan); + if (!(eth_port->etp_flags & EPF_GOT_ADDR)) + { + /* We have never seen the device. */ + printf("eth_set_rec_conf: waiting for device to appear\n"); + return; + } + eth_port->etp_osdep.etp_recvconf= flags; dl_flags= DL_NOMODE; if (flags & NWEO_EN_BROAD) @@ -746,14 +776,10 @@ static void eth_restart(eth_port, tasknr) eth_port_t *eth_port; int tasknr; { - int r; + int i, r; unsigned flags, dl_flags; message mess; -#if 0 - int i, r, rport; - struct eth_conf *ecp; - eth_port_t *rep; -#endif + eth_port_t *loc_port; printf("eth_restart: restarting eth%d, task %d, port %d\n", eth_port-eth_port_table, tasknr, @@ -803,9 +829,29 @@ int tasknr; mess.m3_i1, eth_port->etp_osdep.etp_port)); } + eth_port->etp_flags |= EPF_ENABLED; + eth_port->etp_ethaddr= *(ether_addr_t *)mess.m3_ca1; + if (!(eth_port->etp_flags & EPF_GOT_ADDR)) + { + eth_port->etp_flags |= EPF_GOT_ADDR; + eth_restart_ioctl(eth_port); + + /* Also update any VLANs on this device */ + for (i=0, loc_port= eth_port_table; ietp_flags & EPF_ENABLED)) + continue; + if (loc_port->etp_vlan_port != eth_port) + continue; + + loc_port->etp_ethaddr= eth_port->etp_ethaddr; + loc_port->etp_flags |= EPF_GOT_ADDR; + eth_restart_ioctl(loc_port); + } + } - eth_port->etp_flags |= EPF_ENABLED; if (eth_port->etp_wr_pack) { bf_afree(eth_port->etp_wr_pack); -- 2.44.0