Support for starting ethernet driver after inet has been started

This commit is contained in:
Philip Homburg 2005-12-09 13:25:30 +00:00
parent e0634c0b47
commit 9d8b27a2b1
3 changed files with 136 additions and 40 deletions

View file

@ -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; i<ETH_FD_NR; i++, eth_fd++)
{
if (!(eth_fd->ef_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;

View file

@ -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 */

View file

@ -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_ethaddr= *(ether_addr_t *)mess.m3_ca1;
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; i<eth_conf_nr;
i++, loc_port++)
{
if (!(loc_port->etp_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);
}
}
if (eth_port->etp_wr_pack)
{
bf_afree(eth_port->etp_wr_pack);