unstack - fix ipcvecs
[minix.git] / servers / inet / mnx_eth.c
blobd3967eb92c982ea6d6b1d28c52ca494dc5297fad
1 /*
2 inet/mnx_eth.c
4 Created: Jan 2, 1992 by Philip Homburg
6 Copyright 1995 Philip Homburg
7 */
9 #include "inet.h"
10 #include <minix/safecopies.h>
11 #include "proto.h"
12 #include "osdep_eth.h"
13 #include "generic/type.h"
15 #include "generic/assert.h"
16 #include "generic/buf.h"
17 #include "generic/clock.h"
18 #include "generic/eth.h"
19 #include "generic/eth_int.h"
20 #include "generic/sr.h"
22 THIS_FILE
24 static void setup_read(eth_port_t *eth_port);
25 static void read_int(eth_port_t *eth_port, int count);
26 static void eth_issue_send(eth_port_t *eth_port);
27 static void write_int(eth_port_t *eth_port);
28 static void eth_restart(eth_port_t *eth_port, endpoint_t endpoint);
29 static void send_getstat(eth_port_t *eth_port);
31 void osdep_eth_init()
33 int i, j, rport;
34 struct eth_conf *ecp;
35 eth_port_t *eth_port, *rep;
36 cp_grant_id_t gid;
38 /* First initialize normal ethernet interfaces */
39 for (i= 0, ecp= eth_conf, eth_port= eth_port_table;
40 i<eth_conf_nr; i++, ecp++, eth_port++)
42 /* Set all grants to invalid */
43 for (j= 0; j<IOVEC_NR; j++)
44 eth_port->etp_osdep.etp_wr_iovec[j].iov_grant= -1;
45 eth_port->etp_osdep.etp_wr_vec_grant= -1;
46 for (j= 0; j<RD_IOVEC; j++)
47 eth_port->etp_osdep.etp_rd_iovec[j].iov_grant= -1;
48 eth_port->etp_osdep.etp_rd_vec_grant= -1;
50 eth_port->etp_osdep.etp_state= OEPS_INIT;
51 eth_port->etp_osdep.etp_flags= OEPF_EMPTY;
52 eth_port->etp_osdep.etp_stat_gid= -1;
53 eth_port->etp_osdep.etp_stat_buf= NULL;
55 if (eth_is_vlan(ecp))
56 continue;
58 /* Allocate grants */
59 for (j= 0; j<IOVEC_NR; j++)
61 if (cpf_getgrants(&gid, 1) != 1)
63 ip_panic((
64 "osdep_eth_init: cpf_getgrants failed: %d\n",
65 errno));
67 eth_port->etp_osdep.etp_wr_iovec[j].iov_grant= gid;
69 if (cpf_getgrants(&gid, 1) != 1)
71 ip_panic((
72 "osdep_eth_init: cpf_getgrants failed: %d\n",
73 errno));
75 eth_port->etp_osdep.etp_wr_vec_grant= gid;
76 for (j= 0; j<RD_IOVEC; j++)
78 if (cpf_getgrants(&gid, 1) != 1)
80 ip_panic((
81 "osdep_eth_init: cpf_getgrants failed: %d\n",
82 errno));
84 eth_port->etp_osdep.etp_rd_iovec[j].iov_grant= gid;
86 if (cpf_getgrants(&gid, 1) != 1)
88 ip_panic((
89 "osdep_eth_init: cpf_getgrants failed: %d\n",
90 errno));
92 eth_port->etp_osdep.etp_rd_vec_grant= gid;
94 eth_port->etp_osdep.etp_task= NONE;
95 eth_port->etp_osdep.etp_recvconf= 0;
96 ev_init(&eth_port->etp_osdep.etp_recvev);
98 sr_add_minor(if2minor(ecp->ec_ifno, ETH_DEV_OFF),
99 i, eth_open, eth_close, eth_read,
100 eth_write, eth_ioctl, eth_cancel, eth_select);
102 eth_port->etp_flags |= EPF_ENABLED;
103 eth_port->etp_vlan= 0;
104 eth_port->etp_vlan_port= NULL;
105 eth_port->etp_wr_pack= 0;
106 eth_port->etp_rd_pack= 0;
109 /* And now come the VLANs */
110 for (i= 0, ecp= eth_conf, eth_port= eth_port_table;
111 i<eth_conf_nr; i++, ecp++, eth_port++)
113 if (!eth_is_vlan(ecp))
114 continue;
116 eth_port->etp_osdep.etp_task= NONE;
117 ev_init(&eth_port->etp_osdep.etp_recvev);
119 rport= ecp->ec_port;
120 assert(rport >= 0 && rport < eth_conf_nr);
121 rep= &eth_port_table[rport];
122 if (!(rep->etp_flags & EPF_ENABLED))
124 printf(
125 "eth%d: underlying ethernet device %d not enabled",
126 i, rport);
127 continue;
129 if (rep->etp_vlan != 0)
131 printf(
132 "eth%d: underlying ethernet device %d is a VLAN",
133 i, rport);
134 continue;
137 if (rep->etp_flags & EPF_GOT_ADDR)
139 eth_port->etp_ethaddr= rep->etp_ethaddr;
140 printf("osdep_eth_init: setting EPF_GOT_ADDR\n");
141 eth_port->etp_flags |= EPF_GOT_ADDR;
144 sr_add_minor(if2minor(ecp->ec_ifno, ETH_DEV_OFF),
145 i, eth_open, eth_close, eth_read,
146 eth_write, eth_ioctl, eth_cancel, eth_select);
148 eth_port->etp_flags |= EPF_ENABLED;
149 eth_port->etp_vlan= ecp->ec_vlan;
150 eth_port->etp_vlan_port= rep;
151 assert(eth_port->etp_vlan != 0);
152 eth_port->etp_wr_pack= 0;
153 eth_port->etp_rd_pack= 0;
154 eth_reg_vlan(rep, eth_port);
158 void eth_write_port(eth_port, pack)
159 eth_port_t *eth_port;
160 acc_t *pack;
162 assert(!no_ethWritePort);
163 assert(!eth_port->etp_vlan);
165 assert(eth_port->etp_wr_pack == NULL);
166 eth_port->etp_wr_pack= pack;
168 if (eth_port->etp_osdep.etp_state != OEPS_IDLE)
170 eth_port->etp_osdep.etp_flags |= OEPF_NEED_SEND;
171 return;
175 eth_issue_send(eth_port);
178 void eth_rec(message *m)
180 int i, r, m_type, flags;
181 eth_port_t *loc_port, *vlan_port;
183 m_type= m->m_type;
185 assert(m_type == DL_CONF_REPLY || m_type == DL_TASK_REPLY ||
186 m_type == DL_STAT_REPLY);
188 for (i=0, loc_port= eth_port_table; i<eth_conf_nr; i++, loc_port++)
190 if (loc_port->etp_osdep.etp_task == m->m_source)
191 break;
193 if (i >= eth_conf_nr)
195 printf("eth_rec: message 0x%x from unknown driver %d\n",
196 m_type, m->m_source);
197 return;
200 if (loc_port->etp_osdep.etp_state == OEPS_CONF_SENT)
202 if (m_type == DL_TASK_REPLY)
204 flags= m->DL_FLAGS;
206 if (flags & DL_PACK_SEND)
207 write_int(loc_port);
208 if (flags & DL_PACK_RECV)
209 read_int(loc_port, m->DL_COUNT);
210 return;
213 if (m_type != DL_CONF_REPLY)
215 printf(
216 "eth_rec: got bad message type 0x%x from %d in CONF state\n",
217 m_type, m->m_source);
218 return;
221 r= m->DL_STAT;
222 if (r < 0)
224 ip_warning(("eth_rec: DL_CONF returned error %d\n",
225 r));
227 /* Just leave it in limbo. Nothing more we can do. */
228 return;
231 loc_port->etp_osdep.etp_flags &= ~OEPF_NEED_CONF;
232 loc_port->etp_osdep.etp_state= OEPS_IDLE;
233 loc_port->etp_flags |= EPF_ENABLED;
235 loc_port->etp_ethaddr= *(ether_addr_t *)m->DL_HWADDR;
236 if (!(loc_port->etp_flags & EPF_GOT_ADDR))
238 loc_port->etp_flags |= EPF_GOT_ADDR;
239 #if 0
240 printf("eth_rec: calling eth_restart_ioctl\n");
241 #endif
242 eth_restart_ioctl(loc_port);
244 /* Also update any VLANs on this device */
245 for (i=0, vlan_port= eth_port_table; i<eth_conf_nr;
246 i++, vlan_port++)
248 if (!(vlan_port->etp_flags & EPF_ENABLED))
249 continue;
250 if (vlan_port->etp_vlan_port != loc_port)
251 continue;
253 vlan_port->etp_ethaddr= loc_port->etp_ethaddr;
254 vlan_port->etp_flags |= EPF_GOT_ADDR;
255 eth_restart_ioctl(vlan_port);
258 if (!(loc_port->etp_flags & EPF_READ_IP))
259 setup_read (loc_port);
261 #if 0
262 if (loc_port->etp_osdep.etp_flags & OEPF_NEED_SEND)
264 printf("eth_rec(conf): OEPF_NEED_SEND is set\n");
266 if (loc_port->etp_osdep.etp_flags & OEPF_NEED_RECV)
268 printf("eth_rec(conf): OEPF_NEED_RECV is set\n");
270 if (loc_port->etp_osdep.etp_flags & OEPF_NEED_STAT)
272 printf("eth_rec(conf): OEPF_NEED_STAT is set\n");
274 #endif
276 return;
278 if (loc_port->etp_osdep.etp_state == OEPS_GETSTAT_SENT)
280 if (m_type != DL_STAT_REPLY)
282 printf(
283 "eth_rec: got bad message type 0x%x from %d in GETSTAT state\n",
284 m_type, m->m_source);
285 return;
288 loc_port->etp_osdep.etp_state= OEPS_IDLE;
289 loc_port->etp_osdep.etp_flags &= ~OEPF_NEED_STAT;
291 assert(loc_port->etp_osdep.etp_stat_gid != -1);
292 cpf_revoke(loc_port->etp_osdep.etp_stat_gid);
293 loc_port->etp_osdep.etp_stat_gid= -1;
294 loc_port->etp_osdep.etp_stat_buf= NULL;
296 /* Finish ioctl */
297 assert(loc_port->etp_flags & EPF_GOT_ADDR);
298 eth_restart_ioctl(loc_port);
300 #if 0
301 if (loc_port->etp_osdep.etp_flags & OEPF_NEED_SEND)
303 printf("eth_rec(stat): OEPF_NEED_SEND is set\n");
305 if (loc_port->etp_osdep.etp_flags & OEPF_NEED_RECV)
307 printf("eth_rec(stat): OEPF_NEED_RECV is set\n");
309 if (loc_port->etp_osdep.etp_flags & OEPF_NEED_CONF)
311 printf("eth_rec(stat): OEPF_NEED_CONF is set\n");
313 #endif
315 #if 0
316 if (loc_port->etp_osdep.etp_state == OEPS_IDLE &&
317 (loc_port->etp_osdep.etp_flags & OEPF_NEED_CONF))
319 eth_set_rec_conf(loc_port,
320 loc_port->etp_osdep.etp_recvconf);
322 #endif
323 return;
325 assert(loc_port->etp_osdep.etp_state == OEPS_IDLE ||
326 loc_port->etp_osdep.etp_state == OEPS_RECV_SENT ||
327 loc_port->etp_osdep.etp_state == OEPS_SEND_SENT ||
328 (printf("etp_state = %d\n", loc_port->etp_osdep.etp_state), 0));
329 loc_port->etp_osdep.etp_state= OEPS_IDLE;
331 flags= m->DL_FLAGS;
333 if (flags & DL_PACK_SEND)
334 write_int(loc_port);
335 if (flags & DL_PACK_RECV)
336 read_int(loc_port, m->DL_COUNT);
338 if (loc_port->etp_osdep.etp_state == OEPS_IDLE &&
339 loc_port->etp_osdep.etp_flags & OEPF_NEED_SEND)
341 loc_port->etp_osdep.etp_flags &= ~OEPF_NEED_SEND;
342 if (loc_port->etp_wr_pack)
343 eth_issue_send(loc_port);
345 if (loc_port->etp_osdep.etp_state == OEPS_IDLE &&
346 (loc_port->etp_osdep.etp_flags & OEPF_NEED_RECV))
348 loc_port->etp_osdep.etp_flags &= ~OEPF_NEED_RECV;
349 if (!(loc_port->etp_flags & EPF_READ_IP))
350 setup_read (loc_port);
352 if (loc_port->etp_osdep.etp_flags & OEPF_NEED_CONF)
354 #if 0
355 printf("eth_rec: OEPF_NEED_CONF is set\n");
356 #endif
358 if (loc_port->etp_osdep.etp_state == OEPS_IDLE &&
359 (loc_port->etp_osdep.etp_flags & OEPF_NEED_STAT))
361 send_getstat(loc_port);
365 void eth_check_driver(char *label, endpoint_t endpoint)
367 int i;
368 eth_port_t *loc_port;
369 struct eth_conf *ecp;
371 /* Re-init ethernet interface */
372 for (i= 0, ecp= eth_conf, loc_port= eth_port_table;
373 i<eth_conf_nr; i++, ecp++, loc_port++)
375 if (eth_is_vlan(ecp))
376 continue;
378 if (strcmp(ecp->ec_label, label) != 0)
380 /* Wrong driver */
381 continue;
383 eth_restart(loc_port, endpoint);
387 int eth_get_stat(eth_port, eth_stat)
388 eth_port_t *eth_port;
389 eth_stat_t *eth_stat;
391 cp_grant_id_t gid;
393 assert(!eth_port->etp_vlan);
395 if (eth_port->etp_osdep.etp_flags & OEPF_NEED_STAT)
396 ip_panic(( "eth_get_stat: getstat already in progress" ));
398 gid= cpf_grant_direct(eth_port->etp_osdep.etp_task,
399 (vir_bytes)eth_stat, sizeof(*eth_stat), CPF_WRITE);
400 if (gid == -1)
402 ip_panic(( "eth_get_stat: cpf_grant_direct failed: %d\n",
403 errno));
405 assert(eth_port->etp_osdep.etp_stat_gid == -1);
406 eth_port->etp_osdep.etp_stat_gid= gid;
407 eth_port->etp_osdep.etp_stat_buf= eth_stat;
409 if (eth_port->etp_osdep.etp_state != OEPS_IDLE)
411 eth_port->etp_osdep.etp_flags |= OEPF_NEED_STAT;
412 return SUSPEND;
415 send_getstat(eth_port);
417 return SUSPEND;
420 void eth_set_rec_conf (eth_port, flags)
421 eth_port_t *eth_port;
422 u32_t flags;
424 int r;
425 unsigned dl_flags, mask;
426 message mess;
428 assert(!eth_port->etp_vlan);
430 if (!(eth_port->etp_flags & EPF_GOT_ADDR))
432 /* We have never seen the device. */
433 #if 0
434 printf("eth_set_rec_conf: waiting for device to appear\n");
435 #endif
436 return;
439 if (eth_port->etp_osdep.etp_state != OEPS_IDLE)
441 #if 0
442 printf(
443 "eth_set_rec_conf: setting OEPF_NEED_CONF, state = %d\n",
444 eth_port->etp_osdep.etp_state);
445 #endif
446 eth_port->etp_osdep.etp_flags |= OEPF_NEED_CONF;
447 return;
450 mask = NWEO_EN_BROAD | NWEO_EN_MULTI | NWEO_EN_PROMISC;
451 if ((eth_port->etp_osdep.etp_recvconf & mask) == (flags & mask))
453 /* No change for the driver, so don't send an update */
454 return;
457 eth_port->etp_osdep.etp_recvconf= flags;
458 dl_flags= DL_NOMODE;
459 if (flags & NWEO_EN_BROAD)
460 dl_flags |= DL_BROAD_REQ;
461 if (flags & NWEO_EN_MULTI)
462 dl_flags |= DL_MULTI_REQ;
463 if (flags & NWEO_EN_PROMISC)
464 dl_flags |= DL_PROMISC_REQ;
466 mess.m_type= DL_CONF;
467 mess.DL_MODE= dl_flags;
469 assert(eth_port->etp_osdep.etp_state == OEPS_IDLE);
470 r= asynsend(eth_port->etp_osdep.etp_task, &mess);
471 eth_port->etp_osdep.etp_state= OEPS_CONF_SENT;
473 if (r < 0)
475 printf("eth_set_rec_conf: asynsend to %d failed: %d\n",
476 eth_port->etp_osdep.etp_task, r);
477 return;
481 static void eth_issue_send(eth_port)
482 eth_port_t *eth_port;
484 int i, r, pack_size;
485 acc_t *pack, *pack_ptr;
486 iovec_s_t *iovec;
487 message m;
489 iovec= eth_port->etp_osdep.etp_wr_iovec;
490 pack= eth_port->etp_wr_pack;
491 pack_size= 0;
492 for (i=0, pack_ptr= pack; i<IOVEC_NR && pack_ptr; i++,
493 pack_ptr= pack_ptr->acc_next)
495 r= cpf_setgrant_direct(iovec[i].iov_grant,
496 eth_port->etp_osdep.etp_task,
497 (vir_bytes)ptr2acc_data(pack_ptr),
498 (vir_bytes)pack_ptr->acc_length,
499 CPF_READ);
500 if (r != 0)
502 ip_panic((
503 "eth_write_port: cpf_setgrant_direct failed: %d\n",
504 errno));
506 pack_size += iovec[i].iov_size= pack_ptr->acc_length;
508 if (i>= IOVEC_NR)
510 pack= bf_pack(pack); /* packet is too fragmented */
511 eth_port->etp_wr_pack= pack;
512 pack_size= 0;
513 for (i=0, pack_ptr= pack; i<IOVEC_NR && pack_ptr;
514 i++, pack_ptr= pack_ptr->acc_next)
516 r= cpf_setgrant_direct(iovec[i].iov_grant,
517 eth_port->etp_osdep.etp_task,
518 (vir_bytes)ptr2acc_data(pack_ptr),
519 (vir_bytes)pack_ptr->acc_length,
520 CPF_READ);
521 if (r != 0)
523 ip_panic((
524 "eth_write_port: cpf_setgrant_direct failed: %d\n",
525 errno));
527 pack_size += iovec[i].iov_size= pack_ptr->acc_length;
530 assert (i< IOVEC_NR);
531 assert (pack_size >= ETH_MIN_PACK_SIZE);
533 r= cpf_setgrant_direct(eth_port->etp_osdep.etp_wr_vec_grant,
534 eth_port->etp_osdep.etp_task,
535 (vir_bytes)iovec,
536 (vir_bytes)(i * sizeof(iovec[0])),
537 CPF_READ);
538 if (r != 0)
540 ip_panic((
541 "eth_write_port: cpf_setgrant_direct failed: %d\n",
542 errno));
544 m.m_type= DL_WRITEV_S;
545 m.DL_COUNT= i;
546 m.DL_GRANT= eth_port->etp_osdep.etp_wr_vec_grant;
548 assert(eth_port->etp_osdep.etp_state == OEPS_IDLE);
549 r= asynsend(eth_port->etp_osdep.etp_task, &m);
551 if (r < 0)
553 printf("eth_issue_send: send to %d failed: %d\n",
554 eth_port->etp_osdep.etp_task, r);
555 return;
557 eth_port->etp_osdep.etp_state= OEPS_SEND_SENT;
560 static void write_int(eth_port_t *eth_port)
562 acc_t *pack;
563 int multicast;
564 u8_t *eth_dst_ptr;
566 pack= eth_port->etp_wr_pack;
567 if (pack == NULL)
569 printf("write_int: strange no packet on eth port %d\n",
570 (int)(eth_port-eth_port_table));
571 eth_restart_write(eth_port);
572 return;
575 eth_port->etp_wr_pack= NULL;
577 eth_dst_ptr= (u8_t *)ptr2acc_data(pack);
578 multicast= (*eth_dst_ptr & 1); /* low order bit indicates multicast */
579 if (multicast || (eth_port->etp_osdep.etp_recvconf & NWEO_EN_PROMISC))
581 assert(!no_ethWritePort);
582 no_ethWritePort= 1;
583 eth_arrive(eth_port, pack, bf_bufsize(pack));
584 assert(no_ethWritePort);
585 no_ethWritePort= 0;
587 else
588 bf_afree(pack);
590 eth_restart_write(eth_port);
593 static void read_int(eth_port, count)
594 eth_port_t *eth_port;
595 int count;
597 acc_t *pack, *pack_ptr, *cut_pack;
598 iovec_s_t *iovec;
599 int i, r;
601 /* A buggy driver might try to feed us a reply for a request we never
602 * sent. Don't let this cause a crash further up.
604 if (!(eth_port->etp_flags & EPF_READ_IP))
606 printf("mnx_eth`read_int: read reply with no read going on\n");
607 return;
610 pack= eth_port->etp_rd_pack;
611 eth_port->etp_rd_pack= NULL;
613 /* Invalidate the grants first, so that the ethernet driver can no
614 * longer modify the contents of the packet.
616 iovec= eth_port->etp_osdep.etp_rd_iovec;
617 for (i=0, pack_ptr= pack; i<RD_IOVEC && pack_ptr;
618 i++, pack_ptr= pack_ptr->acc_next)
620 r= cpf_setgrant_disable(iovec[i].iov_grant);
621 if (r != 0)
623 ip_panic((
624 "mnx_eth`read_int: cpf_setgrant_disable failed: %d\n",
625 errno));
629 if (count < ETH_MIN_PACK_SIZE)
631 printf("mnx_eth`read_int: packet size too small (%d)\n",
632 count);
633 bf_afree(pack);
635 else if (count > ETH_MAX_PACK_SIZE_TAGGED)
637 printf("mnx_eth`read_int: packet size too big (%d)\n",
638 count);
639 bf_afree(pack);
641 else
643 cut_pack= bf_cut(pack, 0, count);
644 bf_afree(pack);
646 assert(!no_ethWritePort);
647 no_ethWritePort= 1;
648 eth_arrive(eth_port, cut_pack, count);
649 assert(no_ethWritePort);
650 no_ethWritePort= 0;
653 eth_port->etp_flags &= ~(EPF_READ_IP|EPF_READ_SP);
654 setup_read(eth_port);
657 static void setup_read(eth_port)
658 eth_port_t *eth_port;
660 acc_t *pack, *pack_ptr;
661 message mess;
662 iovec_s_t *iovec;
663 int i, r;
665 assert(!eth_port->etp_vlan);
666 assert(!(eth_port->etp_flags & (EPF_READ_IP|EPF_READ_SP)));
668 if (eth_port->etp_osdep.etp_state != OEPS_IDLE)
670 eth_port->etp_osdep.etp_flags |= OEPF_NEED_RECV;
672 return;
675 assert (!eth_port->etp_rd_pack);
677 iovec= eth_port->etp_osdep.etp_rd_iovec;
678 pack= bf_memreq (ETH_MAX_PACK_SIZE_TAGGED);
680 for (i=0, pack_ptr= pack; i<RD_IOVEC && pack_ptr;
681 i++, pack_ptr= pack_ptr->acc_next)
683 r= cpf_setgrant_direct(iovec[i].iov_grant,
684 eth_port->etp_osdep.etp_task,
685 (vir_bytes)ptr2acc_data(pack_ptr),
686 (vir_bytes)pack_ptr->acc_length,
687 CPF_WRITE);
688 if (r != 0)
690 ip_panic((
691 "mnx_eth`setup_read: cpf_setgrant_direct failed: %d\n",
692 errno));
694 iovec[i].iov_size= (vir_bytes)pack_ptr->acc_length;
696 assert (!pack_ptr);
698 r= cpf_setgrant_direct(eth_port->etp_osdep.etp_rd_vec_grant,
699 eth_port->etp_osdep.etp_task,
700 (vir_bytes)iovec,
701 (vir_bytes)(i * sizeof(iovec[0])),
702 CPF_READ);
703 if (r != 0)
705 ip_panic((
706 "mnx_eth`setup_read: cpf_setgrant_direct failed: %d\n",
707 errno));
710 mess.m_type= DL_READV_S;
711 mess.DL_COUNT= i;
712 mess.DL_GRANT= eth_port->etp_osdep.etp_rd_vec_grant;
714 assert(eth_port->etp_osdep.etp_state == OEPS_IDLE);
716 r= asynsend(eth_port->etp_osdep.etp_task, &mess);
717 eth_port->etp_osdep.etp_state= OEPS_RECV_SENT;
719 if (r < 0)
721 printf(
722 "mnx_eth`setup_read: asynsend to %d failed: %d\n",
723 eth_port->etp_osdep.etp_task, r);
725 eth_port->etp_rd_pack= pack;
726 eth_port->etp_flags |= EPF_READ_IP;
727 eth_port->etp_flags |= EPF_READ_SP;
730 static void eth_restart(eth_port_t *eth_port, endpoint_t endpoint)
732 int r;
733 unsigned flags, dl_flags;
734 cp_grant_id_t gid;
735 message mess;
737 eth_port->etp_osdep.etp_task= endpoint;
739 switch(eth_port->etp_osdep.etp_state)
741 case OEPS_INIT:
742 case OEPS_CONF_SENT:
743 case OEPS_RECV_SENT:
744 case OEPS_SEND_SENT:
745 /* We can safely ignore the pending CONF, RECV, and SEND
746 * requests. If this is the first time that we see this
747 * driver at all, that's fine too.
749 eth_port->etp_osdep.etp_state= OEPS_IDLE;
750 break;
751 case OEPS_GETSTAT_SENT:
752 /* Set the OEPF_NEED_STAT to trigger a new request */
753 eth_port->etp_osdep.etp_flags |= OEPF_NEED_STAT;
754 eth_port->etp_osdep.etp_state= OEPS_IDLE;
755 break;
758 /* If there is a pending GETSTAT request then we have to create a
759 * new grant.
761 if (eth_port->etp_osdep.etp_flags & OEPF_NEED_STAT)
763 assert(eth_port->etp_osdep.etp_stat_gid != -1);
764 cpf_revoke(eth_port->etp_osdep.etp_stat_gid);
766 gid= cpf_grant_direct(eth_port->etp_osdep.etp_task,
767 (vir_bytes)eth_port->etp_osdep.etp_stat_buf,
768 sizeof(*eth_port->etp_osdep.etp_stat_buf), CPF_WRITE);
769 if (gid == -1)
771 ip_panic((
772 "eth_restart: cpf_grant_direct failed: %d\n",
773 errno));
775 eth_port->etp_osdep.etp_stat_gid= gid;
778 flags= eth_port->etp_osdep.etp_recvconf;
779 dl_flags= DL_NOMODE;
780 if (flags & NWEO_EN_BROAD)
781 dl_flags |= DL_BROAD_REQ;
782 if (flags & NWEO_EN_MULTI)
783 dl_flags |= DL_MULTI_REQ;
784 if (flags & NWEO_EN_PROMISC)
785 dl_flags |= DL_PROMISC_REQ;
786 mess.m_type= DL_CONF;
787 mess.DL_MODE= dl_flags;
789 compare(eth_port->etp_osdep.etp_state, ==, OEPS_IDLE);
790 r= asynsend(eth_port->etp_osdep.etp_task, &mess);
791 if (r<0)
793 printf(
794 "eth_restart: send to ethernet task %d failed: %d\n",
795 eth_port->etp_osdep.etp_task, r);
796 return;
798 eth_port->etp_osdep.etp_state= OEPS_CONF_SENT;
800 if (eth_port->etp_wr_pack)
802 bf_afree(eth_port->etp_wr_pack);
803 eth_port->etp_wr_pack= NULL;
804 eth_restart_write(eth_port);
806 if (eth_port->etp_rd_pack)
808 bf_afree(eth_port->etp_rd_pack);
809 eth_port->etp_rd_pack= NULL;
810 eth_port->etp_flags &= ~(EPF_READ_IP|EPF_READ_SP);
815 static void send_getstat(eth_port)
816 eth_port_t *eth_port;
818 int r;
819 message mess;
821 mess.m_type= DL_GETSTAT_S;
822 mess.DL_GRANT= eth_port->etp_osdep.etp_stat_gid;
824 assert(eth_port->etp_osdep.etp_state == OEPS_IDLE);
826 r= asynsend(eth_port->etp_osdep.etp_task, &mess);
827 eth_port->etp_osdep.etp_state= OEPS_GETSTAT_SENT;
829 if (r != OK)
830 ip_panic(( "eth_get_stat: asynsend failed: %d", r));
834 * $PchId: mnx_eth.c,v 1.16 2005/06/28 14:24:37 philip Exp $