add/re-enable at_wini debug output
[minix3.git] / servers / inet / mnx_eth.c
blob44bb82e3fca61d80cb2cc3e05fe1b1ab9ea33e01
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 int recv_debug= 0;
26 FORWARD _PROTOTYPE( void setup_read, (eth_port_t *eth_port) );
27 FORWARD _PROTOTYPE( void read_int, (eth_port_t *eth_port, int count) );
28 FORWARD _PROTOTYPE( void write_int, (eth_port_t *eth_port) );
29 FORWARD _PROTOTYPE( void eth_recvev, (event_t *ev, ev_arg_t ev_arg) );
30 FORWARD _PROTOTYPE( void eth_sendev, (event_t *ev, ev_arg_t ev_arg) );
31 FORWARD _PROTOTYPE( eth_port_t *find_port, (message *m) );
32 FORWARD _PROTOTYPE( void eth_restart, (eth_port_t *eth_port, int tasknr) );
34 PUBLIC void osdep_eth_init()
36 int i, j, r, tasknr, rport;
37 struct eth_conf *ecp;
38 eth_port_t *eth_port, *rep;
39 message mess;
40 cp_grant_id_t gid;
42 /* First initialize normal ethernet interfaces */
43 for (i= 0, ecp= eth_conf, eth_port= eth_port_table;
44 i<eth_conf_nr; i++, ecp++, eth_port++)
46 /* Set all grants to invalid */
47 for (j= 0; j<IOVEC_NR; j++)
48 eth_port->etp_osdep.etp_wr_iovec[j].iov_grant= -1;
49 eth_port->etp_osdep.etp_wr_vec_grant= -1;
50 for (j= 0; j<RD_IOVEC; j++)
51 eth_port->etp_osdep.etp_rd_iovec[j].iov_grant= -1;
52 eth_port->etp_osdep.etp_rd_vec_grant= -1;
54 if (eth_is_vlan(ecp))
55 continue;
57 /* Allocate grants */
58 for (j= 0; j<IOVEC_NR; j++)
60 if (cpf_getgrants(&gid, 1) != 1)
62 ip_panic((
63 "osdep_eth_init: cpf_getgrants failed: %d\n",
64 errno));
66 eth_port->etp_osdep.etp_wr_iovec[j].iov_grant= gid;
68 if (cpf_getgrants(&gid, 1) != 1)
70 ip_panic((
71 "osdep_eth_init: cpf_getgrants failed: %d\n",
72 errno));
74 eth_port->etp_osdep.etp_wr_vec_grant= gid;
75 for (j= 0; j<RD_IOVEC; j++)
77 if (cpf_getgrants(&gid, 1) != 1)
79 ip_panic((
80 "osdep_eth_init: cpf_getgrants failed: %d\n",
81 errno));
83 eth_port->etp_osdep.etp_rd_iovec[j].iov_grant= gid;
85 if (cpf_getgrants(&gid, 1) != 1)
87 ip_panic((
88 "osdep_eth_init: cpf_getgrants failed: %d\n",
89 errno));
91 eth_port->etp_osdep.etp_rd_vec_grant= gid;
93 #ifdef __minix_vmd
94 r= sys_findproc(ecp->ec_task, &tasknr, 0);
95 #else /* Minix 3 */
96 r = _pm_findproc(ecp->ec_task, &tasknr);
97 #endif
98 if (r != OK)
100 /* Eventually, we expect ethernet drivers to be
101 * started after INET. So we always end up here. And
102 * the findproc can be removed.
104 printf("eth%d: unable to find task %s: %d\n",
105 i, ecp->ec_task, r);
106 tasknr= ANY;
109 eth_port->etp_osdep.etp_port= ecp->ec_port;
110 eth_port->etp_osdep.etp_task= tasknr;
111 eth_port->etp_osdep.etp_send_ev= 0;
112 ev_init(&eth_port->etp_osdep.etp_recvev);
114 mess.m_type= DL_CONF;
115 mess.DL_PORT= eth_port->etp_osdep.etp_port;
116 mess.DL_PROC= this_proc;
117 mess.DL_MODE= DL_NOMODE;
119 if (tasknr == ANY)
120 r= ENXIO;
121 else
123 r= send(eth_port->etp_osdep.etp_task, &mess);
124 if (r<0)
126 printf(
127 "osdep_eth_init: unable to send to ethernet task, error= %d\n",
132 if (r == OK)
134 r= receive(eth_port->etp_osdep.etp_task, &mess);
135 if (r<0)
137 printf(
138 "osdep_eth_init: unable to receive from ethernet task, error= %d\n",
143 if (r == OK)
145 r= mess.m3_i1;
146 if (r == ENXIO)
148 printf(
149 "osdep_eth_init: no ethernet device at task=%d,port=%d\n",
150 eth_port->etp_osdep.etp_task,
151 eth_port->etp_osdep.etp_port);
153 else if (r < 0)
155 ip_panic((
156 "osdep_eth_init: DL_INIT returned error %d\n",
157 r));
159 else if (mess.m3_i1 != eth_port->etp_osdep.etp_port)
161 ip_panic((
162 "osdep_eth_init: got reply for wrong port (got %d, expected %d)\n",
163 mess.m3_i1,
164 eth_port->etp_osdep.etp_port));
168 sr_add_minor(if2minor(ecp->ec_ifno, ETH_DEV_OFF),
169 i, eth_open, eth_close, eth_read,
170 eth_write, eth_ioctl, eth_cancel, eth_select);
172 eth_port->etp_flags |= EPF_ENABLED;
173 eth_port->etp_vlan= 0;
174 eth_port->etp_vlan_port= NULL;
175 eth_port->etp_wr_pack= 0;
176 eth_port->etp_rd_pack= 0;
177 if (r == OK)
179 eth_port->etp_ethaddr= *(ether_addr_t *)mess.m3_ca1;
180 eth_port->etp_flags |= EPF_GOT_ADDR;
181 setup_read (eth_port);
185 /* And now come the VLANs */
186 for (i= 0, ecp= eth_conf, eth_port= eth_port_table;
187 i<eth_conf_nr; i++, ecp++, eth_port++)
189 if (!eth_is_vlan(ecp))
190 continue;
192 eth_port->etp_osdep.etp_port= ecp->ec_port;
193 eth_port->etp_osdep.etp_task= ANY;
194 ev_init(&eth_port->etp_osdep.etp_recvev);
196 rport= eth_port->etp_osdep.etp_port;
197 assert(rport >= 0 && rport < eth_conf_nr);
198 rep= &eth_port_table[rport];
199 if (!(rep->etp_flags & EPF_ENABLED))
201 printf(
202 "eth%d: underlying ethernet device %d not enabled",
203 i, rport);
204 continue;
206 if (rep->etp_vlan != 0)
208 printf(
209 "eth%d: underlying ethernet device %d is a VLAN",
210 i, rport);
211 continue;
214 if (rep->etp_flags & EPF_GOT_ADDR)
216 eth_port->etp_ethaddr= rep->etp_ethaddr;
217 eth_port->etp_flags |= EPF_GOT_ADDR;
220 sr_add_minor(if2minor(ecp->ec_ifno, ETH_DEV_OFF),
221 i, eth_open, eth_close, eth_read,
222 eth_write, eth_ioctl, eth_cancel, eth_select);
224 eth_port->etp_flags |= EPF_ENABLED;
225 eth_port->etp_vlan= ecp->ec_vlan;
226 eth_port->etp_vlan_port= rep;
227 assert(eth_port->etp_vlan != 0);
228 eth_port->etp_wr_pack= 0;
229 eth_port->etp_rd_pack= 0;
230 eth_reg_vlan(rep, eth_port);
234 PUBLIC void eth_write_port(eth_port, pack)
235 eth_port_t *eth_port;
236 acc_t *pack;
238 eth_port_t *loc_port;
239 message mess1, block_msg;
240 int i, pack_size;
241 acc_t *pack_ptr;
242 iovec_s_t *iovec;
243 u8_t *eth_dst_ptr;
244 int multicast, r;
245 ev_arg_t ev_arg;
247 assert(!no_ethWritePort);
248 assert(!eth_port->etp_vlan);
250 assert(eth_port->etp_wr_pack == NULL);
251 eth_port->etp_wr_pack= pack;
253 iovec= eth_port->etp_osdep.etp_wr_iovec;
254 pack_size= 0;
255 for (i=0, pack_ptr= pack; i<IOVEC_NR && pack_ptr; i++,
256 pack_ptr= pack_ptr->acc_next)
258 r= cpf_setgrant_direct(iovec[i].iov_grant,
259 eth_port->etp_osdep.etp_task,
260 (vir_bytes)ptr2acc_data(pack_ptr),
261 (vir_bytes)pack_ptr->acc_length,
262 CPF_READ);
263 if (r != 0)
265 ip_panic((
266 "eth_write_port: cpf_setgrant_direct failed: %d\n",
267 errno));
269 pack_size += iovec[i].iov_size= pack_ptr->acc_length;
271 if (i>= IOVEC_NR)
273 pack= bf_pack(pack); /* packet is too fragmented */
274 eth_port->etp_wr_pack= pack;
275 pack_size= 0;
276 for (i=0, pack_ptr= pack; i<IOVEC_NR && pack_ptr;
277 i++, pack_ptr= pack_ptr->acc_next)
279 r= cpf_setgrant_direct(iovec[i].iov_grant,
280 eth_port->etp_osdep.etp_task,
281 (vir_bytes)ptr2acc_data(pack_ptr),
282 (vir_bytes)pack_ptr->acc_length,
283 CPF_READ);
284 if (r != 0)
286 ip_panic((
287 "eth_write_port: cpf_setgrant_direct failed: %d\n",
288 errno));
290 pack_size += iovec[i].iov_size= pack_ptr->acc_length;
293 assert (i< IOVEC_NR);
294 assert (pack_size >= ETH_MIN_PACK_SIZE);
297 r= cpf_setgrant_direct(eth_port->etp_osdep.etp_wr_vec_grant,
298 eth_port->etp_osdep.etp_task,
299 (vir_bytes)iovec,
300 (vir_bytes)(i * sizeof(iovec[0])),
301 CPF_READ);
302 if (r != 0)
304 ip_panic((
305 "eth_write_port: cpf_setgrant_direct failed: %d\n",
306 errno));
308 mess1.DL_COUNT= i;
309 mess1.DL_GRANT= eth_port->etp_osdep.etp_wr_vec_grant;
310 mess1.m_type= DL_WRITEV_S;
312 mess1.DL_PORT= eth_port->etp_osdep.etp_port;
313 mess1.DL_PROC= this_proc;
314 mess1.DL_MODE= DL_NOMODE;
316 for (;;)
318 r= sendrec(eth_port->etp_osdep.etp_task, &mess1);
319 if (r != ELOCKED)
320 break;
322 /* ethernet task is sending to this task, I hope */
323 r= receive(eth_port->etp_osdep.etp_task, &block_msg);
324 if (r < 0)
325 ip_panic(("unable to receive"));
327 loc_port= eth_port;
328 if (loc_port->etp_osdep.etp_port != block_msg.DL_PORT ||
329 loc_port->etp_osdep.etp_task != block_msg.m_source)
331 loc_port= find_port(&block_msg);
333 assert(block_msg.DL_STAT & (DL_PACK_SEND|DL_PACK_RECV));
334 if (block_msg.DL_STAT & DL_PACK_SEND)
336 assert(loc_port != eth_port);
337 loc_port->etp_osdep.etp_sendrepl= block_msg;
338 ev_arg.ev_ptr= loc_port;
339 assert(!loc_port->etp_osdep.etp_send_ev);
340 loc_port->etp_osdep.etp_send_ev= 1;
341 ev_enqueue(&loc_port->etp_sendev, eth_sendev, ev_arg);
343 if (block_msg.DL_STAT & DL_PACK_RECV)
345 if (recv_debug)
347 printf(
348 "eth_write_port(block_msg): eth%d got DL_PACK_RECV\n",
349 loc_port-eth_port_table);
351 loc_port->etp_osdep.etp_recvrepl= block_msg;
352 ev_arg.ev_ptr= loc_port;
353 ev_enqueue(&loc_port->etp_osdep.etp_recvev,
354 eth_recvev, ev_arg);
358 if (r < 0)
360 printf("eth_write_port: sendrec to %d failed: %d\n",
361 eth_port->etp_osdep.etp_task, r);
362 return;
365 if (mess1.m_type != DL_TASK_REPLY ||
366 mess1.DL_PORT != eth_port->etp_osdep.etp_port ||
367 mess1.DL_PROC != this_proc)
369 printf(
370 "eth_write_port: ignoring bad message (type = 0x%x, port = %d, proc = %d) from %d\n",
371 mess1.m_type, mess1.DL_PORT, mess1.DL_PROC,
372 mess1.m_source);
373 return;
376 assert(mess1.m_type == DL_TASK_REPLY &&
377 mess1.DL_PORT == eth_port->etp_osdep.etp_port &&
378 mess1.DL_PROC == this_proc);
379 assert((mess1.DL_STAT >> 16) == OK);
381 if (mess1.DL_STAT & DL_PACK_RECV)
383 if (recv_debug)
385 printf(
386 "eth_write_port(mess1): eth%d got DL_PACK_RECV\n",
387 mess1.DL_PORT);
389 eth_port->etp_osdep.etp_recvrepl= mess1;
390 ev_arg.ev_ptr= eth_port;
391 ev_enqueue(&eth_port->etp_osdep.etp_recvev, eth_recvev,
392 ev_arg);
394 if (!(mess1.DL_STAT & DL_PACK_SEND))
396 /* Packet is not yet sent. */
397 return;
400 /* If the port is in promiscuous mode or the packet is
401 * broad- or multicast, enqueue the reply packet.
403 eth_dst_ptr= (u8_t *)ptr2acc_data(pack);
404 multicast= (*eth_dst_ptr & 1); /* low order bit indicates multicast */
405 if (multicast || (eth_port->etp_osdep.etp_recvconf & NWEO_EN_PROMISC))
407 eth_port->etp_osdep.etp_sendrepl= mess1;
408 ev_arg.ev_ptr= eth_port;
409 assert(!eth_port->etp_osdep.etp_send_ev);
410 eth_port->etp_osdep.etp_send_ev= 1;
411 ev_enqueue(&eth_port->etp_sendev, eth_sendev, ev_arg);
413 /* Pretend that we didn't get a reply. */
414 return;
417 /* packet is sent */
418 bf_afree(eth_port->etp_wr_pack);
419 eth_port->etp_wr_pack= NULL;
422 PUBLIC void eth_rec(m)
423 message *m;
425 int i;
426 eth_port_t *loc_port;
427 int stat;
429 assert(m->m_type == DL_TASK_REPLY);
431 set_time (m->DL_CLCK);
433 for (i=0, loc_port= eth_port_table; i<eth_conf_nr; i++, loc_port++)
435 if (loc_port->etp_osdep.etp_port == m->DL_PORT &&
436 loc_port->etp_osdep.etp_task == m->m_source)
437 break;
439 if (i == eth_conf_nr)
441 ip_panic(("message from unknown source: %d:%d",
442 m->m_source, m->DL_PORT));
445 stat= m->DL_STAT & 0xffff;
447 if (!(stat & (DL_PACK_SEND|DL_PACK_RECV)))
448 printf("eth_rec: neither DL_PACK_SEND nor DL_PACK_RECV\n");
449 if (stat & DL_PACK_SEND)
450 write_int(loc_port);
451 if (stat & DL_PACK_RECV)
453 if (recv_debug)
455 printf("eth_rec: eth%d got DL_PACK_RECV\n",
456 m->DL_PORT);
458 read_int(loc_port, m->DL_COUNT);
462 PUBLIC void eth_check_drivers(m)
463 message *m;
465 int i, r, tasknr;
466 struct eth_conf *ecp;
467 eth_port_t *eth_port;
468 char *drivername;
470 tasknr= m->m_source;
471 printf("eth_check_drivers: got a notification from %d\n", tasknr);
473 m->m_type= DL_GETNAME;
474 r= sendrec(tasknr, m);
475 if (r != OK)
477 printf("eth_check_drivers: sendrec to %d failed: %d\n",
478 tasknr, r);
479 return;
481 if (m->m_type != DL_NAME_REPLY)
483 printf(
484 "eth_check_drivers: got bad getname reply (%d) from %d\n",
485 m->m_type, tasknr);
486 return;
489 drivername= m->m3_ca1;
490 printf("eth_check_drivers: got name: %s\n", drivername);
492 /* Re-init ethernet interfaces */
493 for (i= 0, ecp= eth_conf, eth_port= eth_port_table;
494 i<eth_conf_nr; i++, ecp++, eth_port++)
496 if (eth_is_vlan(ecp))
497 continue;
499 if (strcmp(ecp->ec_task, drivername) != 0)
501 /* Wrong driver */
502 continue;
505 eth_restart(eth_port, tasknr);
509 PUBLIC int eth_get_stat(eth_port, eth_stat)
510 eth_port_t *eth_port;
511 eth_stat_t *eth_stat;
513 int r;
514 cp_grant_id_t gid;
515 message mess, mlocked;
517 assert(!eth_port->etp_vlan);
519 gid= cpf_grant_direct(eth_port->etp_osdep.etp_task,
520 (vir_bytes)eth_stat, sizeof(*eth_stat), CPF_WRITE);
521 if (gid == -1)
523 ip_panic(( "eth_get_stat: cpf_grant_direct failed: %d\n",
524 errno));
527 mess.m_type= DL_GETSTAT_S;
528 mess.DL_PORT= eth_port->etp_osdep.etp_port;
529 mess.DL_PROC= this_proc;
530 mess.DL_GRANT= gid;
532 for (;;)
534 r= sendrec(eth_port->etp_osdep.etp_task, &mess);
535 if (r != ELOCKED)
536 break;
538 r= receive(eth_port->etp_osdep.etp_task, &mlocked);
539 assert(r == OK);
541 compare(mlocked.m_type, ==, DL_TASK_REPLY);
542 eth_rec(&mlocked);
544 cpf_revoke(gid);
546 if (r != OK)
548 printf("eth_get_stat: sendrec to %d failed: %d\n",
549 eth_port->etp_osdep.etp_task, r);
550 return EIO;
553 assert(mess.m_type == DL_TASK_REPLY);
555 r= mess.DL_STAT >> 16;
556 assert (r == 0);
558 if (mess.DL_STAT)
560 eth_rec(&mess);
562 return OK;
565 PUBLIC void eth_set_rec_conf (eth_port, flags)
566 eth_port_t *eth_port;
567 u32_t flags;
569 int r;
570 unsigned dl_flags;
571 message mess, repl_mess;
573 assert(!eth_port->etp_vlan);
575 if (!(eth_port->etp_flags & EPF_GOT_ADDR))
577 /* We have never seen the device. */
578 printf("eth_set_rec_conf: waiting for device to appear\n");
579 return;
582 eth_port->etp_osdep.etp_recvconf= flags;
583 dl_flags= DL_NOMODE;
584 if (flags & NWEO_EN_BROAD)
585 dl_flags |= DL_BROAD_REQ;
586 if (flags & NWEO_EN_MULTI)
587 dl_flags |= DL_MULTI_REQ;
588 if (flags & NWEO_EN_PROMISC)
589 dl_flags |= DL_PROMISC_REQ;
591 mess.m_type= DL_CONF;
592 mess.DL_PORT= eth_port->etp_osdep.etp_port;
593 mess.DL_PROC= this_proc;
594 mess.DL_MODE= dl_flags;
598 r= sendrec(eth_port->etp_osdep.etp_task, &mess);
599 if (r == ELOCKED) /* etp_task is sending to this task,
600 I hope */
602 if (receive (eth_port->etp_osdep.etp_task,
603 &repl_mess)< 0)
605 ip_panic(("unable to receive"));
608 compare(repl_mess.m_type, ==, DL_TASK_REPLY);
609 eth_rec(&repl_mess);
611 } while (r == ELOCKED);
613 if (r < 0)
615 printf("eth_set_rec_conf: sendrec to %d failed: %d\n",
616 eth_port->etp_osdep.etp_task, r);
617 return;
620 assert (mess.m_type == DL_CONF_REPLY);
621 if (mess.m3_i1 != eth_port->etp_osdep.etp_port)
623 ip_panic(("got reply for wrong port"));
627 PRIVATE void write_int(eth_port)
628 eth_port_t *eth_port;
630 acc_t *pack;
631 int multicast;
632 u8_t *eth_dst_ptr;
634 pack= eth_port->etp_wr_pack;
635 if (pack == NULL)
637 printf("write_int: strange no packet on eth port %d\n",
638 eth_port-eth_port_table);
639 eth_restart_write(eth_port);
640 return;
643 eth_port->etp_wr_pack= NULL;
645 eth_dst_ptr= (u8_t *)ptr2acc_data(pack);
646 multicast= (*eth_dst_ptr & 1); /* low order bit indicates multicast */
647 if (multicast || (eth_port->etp_osdep.etp_recvconf & NWEO_EN_PROMISC))
649 assert(!no_ethWritePort);
650 no_ethWritePort= 1;
651 eth_arrive(eth_port, pack, bf_bufsize(pack));
652 assert(no_ethWritePort);
653 no_ethWritePort= 0;
655 else
656 bf_afree(pack);
658 eth_restart_write(eth_port);
661 PRIVATE void read_int(eth_port, count)
662 eth_port_t *eth_port;
663 int count;
665 acc_t *pack, *cut_pack;
667 pack= eth_port->etp_rd_pack;
668 eth_port->etp_rd_pack= NULL;
670 if (count < ETH_MIN_PACK_SIZE)
672 printf("mnx_eth`read_int: packet size too small (%d)\n",
673 count);
674 bf_afree(pack);
676 else if (count > ETH_MAX_PACK_SIZE_TAGGED)
678 printf("mnx_eth`read_int: packet size too big (%d)\n",
679 count);
680 bf_afree(pack);
682 else
684 cut_pack= bf_cut(pack, 0, count);
685 bf_afree(pack);
687 assert(!no_ethWritePort);
688 no_ethWritePort= 1;
689 eth_arrive(eth_port, cut_pack, count);
690 assert(no_ethWritePort);
691 no_ethWritePort= 0;
694 eth_port->etp_flags &= ~(EPF_READ_IP|EPF_READ_SP);
695 setup_read(eth_port);
698 PRIVATE void setup_read(eth_port)
699 eth_port_t *eth_port;
701 eth_port_t *loc_port;
702 acc_t *pack, *pack_ptr;
703 message mess1, block_msg;
704 iovec_s_t *iovec;
705 ev_arg_t ev_arg;
706 int i, r;
708 assert(!eth_port->etp_vlan);
709 assert(!(eth_port->etp_flags & (EPF_READ_IP|EPF_READ_SP)));
713 assert (!eth_port->etp_rd_pack);
715 iovec= eth_port->etp_osdep.etp_rd_iovec;
716 pack= bf_memreq (ETH_MAX_PACK_SIZE_TAGGED);
718 for (i=0, pack_ptr= pack; i<RD_IOVEC && pack_ptr;
719 i++, pack_ptr= pack_ptr->acc_next)
721 r= cpf_setgrant_direct(iovec[i].iov_grant,
722 eth_port->etp_osdep.etp_task,
723 (vir_bytes)ptr2acc_data(pack_ptr),
724 (vir_bytes)pack_ptr->acc_length,
725 CPF_WRITE);
726 if (r != 0)
728 ip_panic((
729 "mnx_eth`setup_read: cpf_setgrant_direct failed: %d\n",
730 errno));
732 iovec[i].iov_size= (vir_bytes)pack_ptr->acc_length;
734 assert (!pack_ptr);
736 r= cpf_setgrant_direct(eth_port->etp_osdep.etp_rd_vec_grant,
737 eth_port->etp_osdep.etp_task,
738 (vir_bytes)iovec,
739 (vir_bytes)(i * sizeof(iovec[0])),
740 CPF_READ);
741 if (r != 0)
743 ip_panic((
744 "mnx_eth`setup_read: cpf_setgrant_direct failed: %d\n",
745 errno));
748 mess1.m_type= DL_READV_S;
749 mess1.DL_PORT= eth_port->etp_osdep.etp_port;
750 mess1.DL_PROC= this_proc;
751 mess1.DL_COUNT= i;
752 mess1.DL_GRANT= eth_port->etp_osdep.etp_rd_vec_grant;
754 for (;;)
756 if (recv_debug)
758 printf("eth%d: sending DL_READV_S\n",
759 mess1.DL_PORT);
761 r= sendrec(eth_port->etp_osdep.etp_task, &mess1);
762 if (r != ELOCKED)
763 break;
765 /* ethernet task is sending to this task, I hope */
766 r= receive(eth_port->etp_osdep.etp_task, &block_msg);
767 if (r < 0)
768 ip_panic(("unable to receive"));
770 loc_port= eth_port;
771 if (loc_port->etp_osdep.etp_port != block_msg.DL_PORT ||
772 loc_port->etp_osdep.etp_task !=
773 block_msg.m_source)
775 loc_port= find_port(&block_msg);
777 assert(block_msg.DL_STAT &
778 (DL_PACK_SEND|DL_PACK_RECV));
779 if (block_msg.DL_STAT & DL_PACK_SEND)
781 loc_port->etp_osdep.etp_sendrepl=
782 block_msg;
783 ev_arg.ev_ptr= loc_port;
784 assert(!loc_port->etp_osdep.etp_send_ev);
785 loc_port->etp_osdep.etp_send_ev= 1;
786 ev_enqueue(&loc_port->etp_sendev,
787 eth_sendev, ev_arg);
789 if (block_msg.DL_STAT & DL_PACK_RECV)
791 if (recv_debug)
793 printf(
794 "setup_read(block_msg): eth%d got DL_PACK_RECV\n",
795 block_msg.DL_PORT);
797 assert(loc_port != eth_port);
798 loc_port->etp_osdep.etp_recvrepl= block_msg;
799 ev_arg.ev_ptr= loc_port;
800 ev_enqueue(&loc_port->etp_osdep.etp_recvev,
801 eth_recvev, ev_arg);
805 if (r < 0)
807 printf("mnx_eth`setup_read: sendrec to %d failed: %d\n",
808 eth_port->etp_osdep.etp_task, r);
809 eth_port->etp_rd_pack= pack;
810 eth_port->etp_flags |= EPF_READ_IP;
811 continue;
814 if (mess1.m_type != DL_TASK_REPLY ||
815 mess1.DL_PORT != eth_port->etp_osdep.etp_port ||
816 mess1.DL_PROC != this_proc)
818 printf("mnx_eth`setup_read: bad type, port or proc\n");
819 printf("got type %d, port %d, proc %d\n",
820 mess1.m_type, mess1.DL_PORT, mess1.DL_PROC);
821 continue;
824 if ((mess1.DL_STAT >> 16) != OK)
826 printf(
827 "mnx_eth`setup_read: bad value in DL_STAT: 0x%x\n",
828 mess1.DL_STAT);
829 mess1.DL_STAT= 0;
832 if (mess1.DL_STAT & DL_PACK_RECV)
834 if (recv_debug)
836 printf(
837 "setup_read(mess1): eth%d: got DL_PACK_RECV\n",
838 mess1.DL_PORT);
841 if (mess1.DL_COUNT < ETH_MIN_PACK_SIZE)
843 printf(
844 "mnx_eth`setup_read: packet size too small (%d)\n",
845 mess1.DL_COUNT);
846 bf_afree(pack);
848 else
850 /* packet received */
851 pack_ptr= bf_cut(pack, 0, mess1.DL_COUNT);
852 bf_afree(pack);
854 assert(!no_ethWritePort);
855 no_ethWritePort= 1;
856 eth_arrive(eth_port, pack_ptr, mess1.DL_COUNT);
857 assert(no_ethWritePort);
858 no_ethWritePort= 0;
861 else
863 /* no packet received */
864 eth_port->etp_rd_pack= pack;
865 eth_port->etp_flags |= EPF_READ_IP;
868 if (mess1.DL_STAT & DL_PACK_SEND)
870 if (eth_port->etp_osdep.etp_send_ev)
872 printf(
873 "mnx_eth`setup_read: etp_send_ev is set, ignoring DL_PACK_SEND\n");
875 else
877 eth_port->etp_osdep.etp_sendrepl= mess1;
878 ev_arg.ev_ptr= eth_port;
879 assert(!eth_port->etp_osdep.etp_send_ev);
880 eth_port->etp_osdep.etp_send_ev= 1;
881 ev_enqueue(&eth_port->etp_sendev, eth_sendev,
882 ev_arg);
885 } while (!(eth_port->etp_flags & EPF_READ_IP));
886 eth_port->etp_flags |= EPF_READ_SP;
889 PRIVATE void eth_recvev(ev, ev_arg)
890 event_t *ev;
891 ev_arg_t ev_arg;
893 eth_port_t *eth_port;
894 message *m_ptr;
896 eth_port= ev_arg.ev_ptr;
897 assert(ev == &eth_port->etp_osdep.etp_recvev);
898 m_ptr= &eth_port->etp_osdep.etp_recvrepl;
900 assert(m_ptr->m_type == DL_TASK_REPLY);
901 assert(eth_port->etp_osdep.etp_port == m_ptr->DL_PORT &&
902 eth_port->etp_osdep.etp_task == m_ptr->m_source);
904 assert(m_ptr->DL_STAT & DL_PACK_RECV);
905 m_ptr->DL_STAT &= ~DL_PACK_RECV;
907 if (recv_debug)
909 printf("eth_recvev: eth%d got DL_PACK_RECV\n", m_ptr->DL_PORT);
912 read_int(eth_port, m_ptr->DL_COUNT);
915 PRIVATE void eth_sendev(ev, ev_arg)
916 event_t *ev;
917 ev_arg_t ev_arg;
919 eth_port_t *eth_port;
920 message *m_ptr;
922 eth_port= ev_arg.ev_ptr;
923 assert(ev == &eth_port->etp_sendev);
924 m_ptr= &eth_port->etp_osdep.etp_sendrepl;
926 assert (m_ptr->m_type == DL_TASK_REPLY);
927 assert(eth_port->etp_osdep.etp_port == m_ptr->DL_PORT &&
928 eth_port->etp_osdep.etp_task == m_ptr->m_source);
930 assert(m_ptr->DL_STAT & DL_PACK_SEND);
931 m_ptr->DL_STAT &= ~DL_PACK_SEND;
932 assert(eth_port->etp_osdep.etp_send_ev);
933 eth_port->etp_osdep.etp_send_ev= 0;
935 /* packet is sent */
936 write_int(eth_port);
939 PRIVATE eth_port_t *find_port(m)
940 message *m;
942 eth_port_t *loc_port;
943 int i;
945 for (i=0, loc_port= eth_port_table; i<eth_conf_nr; i++, loc_port++)
947 if (loc_port->etp_osdep.etp_port == m->DL_PORT &&
948 loc_port->etp_osdep.etp_task == m->m_source)
949 break;
951 assert (i<eth_conf_nr);
952 return loc_port;
955 static void eth_restart(eth_port, tasknr)
956 eth_port_t *eth_port;
957 int tasknr;
959 int i, r;
960 unsigned flags, dl_flags;
961 message mess;
962 eth_port_t *loc_port;
964 printf("eth_restart: restarting eth%d, task %d, port %d\n",
965 eth_port-eth_port_table, tasknr,
966 eth_port->etp_osdep.etp_port);
968 eth_port->etp_osdep.etp_task= tasknr;
970 flags= eth_port->etp_osdep.etp_recvconf;
971 dl_flags= DL_NOMODE;
972 if (flags & NWEO_EN_BROAD)
973 dl_flags |= DL_BROAD_REQ;
974 if (flags & NWEO_EN_MULTI)
975 dl_flags |= DL_MULTI_REQ;
976 if (flags & NWEO_EN_PROMISC)
977 dl_flags |= DL_PROMISC_REQ;
978 mess.m_type= DL_CONF;
979 mess.DL_PORT= eth_port->etp_osdep.etp_port;
980 mess.DL_PROC= this_proc;
981 mess.DL_MODE= dl_flags;
983 r= sendrec(eth_port->etp_osdep.etp_task, &mess);
984 /* YYY */
985 if (r<0)
987 printf(
988 "eth_restart: sendrec to ethernet task %d failed: %d\n",
989 eth_port->etp_osdep.etp_task, r);
990 return;
993 if (mess.m3_i1 == ENXIO)
995 printf(
996 "osdep_eth_init: no ethernet device at task=%d,port=%d\n",
997 eth_port->etp_osdep.etp_task,
998 eth_port->etp_osdep.etp_port);
999 return;
1001 if (mess.m3_i1 < 0)
1002 ip_panic(("osdep_eth_init: DL_INIT returned error %d\n",
1003 mess.m3_i1));
1005 if (mess.m3_i1 != eth_port->etp_osdep.etp_port)
1007 ip_panic((
1008 "osdep_eth_init: got reply for wrong port (got %d, expected %d)\n",
1009 mess.m3_i1, eth_port->etp_osdep.etp_port));
1012 eth_port->etp_flags |= EPF_ENABLED;
1014 eth_port->etp_ethaddr= *(ether_addr_t *)mess.m3_ca1;
1015 if (!(eth_port->etp_flags & EPF_GOT_ADDR))
1017 eth_port->etp_flags |= EPF_GOT_ADDR;
1018 eth_restart_ioctl(eth_port);
1020 /* Also update any VLANs on this device */
1021 for (i=0, loc_port= eth_port_table; i<eth_conf_nr;
1022 i++, loc_port++)
1024 if (!(loc_port->etp_flags & EPF_ENABLED))
1025 continue;
1026 if (loc_port->etp_vlan_port != eth_port)
1027 continue;
1029 loc_port->etp_ethaddr= eth_port->etp_ethaddr;
1030 loc_port->etp_flags |= EPF_GOT_ADDR;
1031 eth_restart_ioctl(loc_port);
1035 if (eth_port->etp_wr_pack)
1037 bf_afree(eth_port->etp_wr_pack);
1038 eth_port->etp_wr_pack= NULL;
1039 eth_restart_write(eth_port);
1041 if (eth_port->etp_rd_pack)
1043 bf_afree(eth_port->etp_rd_pack);
1044 eth_port->etp_rd_pack= NULL;
1045 eth_port->etp_flags &= ~(EPF_READ_IP|EPF_READ_SP);
1047 setup_read (eth_port);
1051 * $PchId: mnx_eth.c,v 1.16 2005/06/28 14:24:37 philip Exp $