debug buffer slightly usabler.
[minix.git] / servers / inet / mnx_eth.c
blob88d03068117e6d061087960f1396eea37620232b
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/ds.h>
11 #include <minix/safecopies.h>
12 #include "proto.h"
13 #include "osdep_eth.h"
14 #include "generic/type.h"
16 #include "generic/assert.h"
17 #include "generic/buf.h"
18 #include "generic/clock.h"
19 #include "generic/eth.h"
20 #include "generic/eth_int.h"
21 #include "generic/sr.h"
23 THIS_FILE
25 static int recv_debug= 0;
27 FORWARD _PROTOTYPE( void setup_read, (eth_port_t *eth_port) );
28 FORWARD _PROTOTYPE( void read_int, (eth_port_t *eth_port, int count) );
29 FORWARD _PROTOTYPE( void eth_issue_send, (eth_port_t *eth_port) );
30 FORWARD _PROTOTYPE( void write_int, (eth_port_t *eth_port) );
31 FORWARD _PROTOTYPE( void eth_recvev, (event_t *ev, ev_arg_t ev_arg) );
32 FORWARD _PROTOTYPE( void eth_sendev, (event_t *ev, ev_arg_t ev_arg) );
33 FORWARD _PROTOTYPE( eth_port_t *find_port, (message *m) );
34 FORWARD _PROTOTYPE( void eth_restart, (eth_port_t *eth_port, int tasknr) );
35 FORWARD _PROTOTYPE( void send_getstat, (eth_port_t *eth_port) );
37 #if 0
38 FORWARD _PROTOTYPE( int asynsend, (endpoint_t dst, message *mp) );
39 #endif
41 PUBLIC void osdep_eth_init()
43 int i, j, r, rport;
44 u32_t tasknr;
45 struct eth_conf *ecp;
46 eth_port_t *eth_port, *rep;
47 message mess;
48 cp_grant_id_t gid;
50 /* First initialize normal ethernet interfaces */
51 for (i= 0, ecp= eth_conf, eth_port= eth_port_table;
52 i<eth_conf_nr; i++, ecp++, eth_port++)
54 /* Set all grants to invalid */
55 for (j= 0; j<IOVEC_NR; j++)
56 eth_port->etp_osdep.etp_wr_iovec[j].iov_grant= -1;
57 eth_port->etp_osdep.etp_wr_vec_grant= -1;
58 for (j= 0; j<RD_IOVEC; j++)
59 eth_port->etp_osdep.etp_rd_iovec[j].iov_grant= -1;
60 eth_port->etp_osdep.etp_rd_vec_grant= -1;
62 eth_port->etp_osdep.etp_state= OEPS_INIT;
63 eth_port->etp_osdep.etp_flags= OEPF_EMPTY;
64 eth_port->etp_osdep.etp_stat_gid= -1;
65 eth_port->etp_osdep.etp_stat_buf= NULL;
67 if (eth_is_vlan(ecp))
68 continue;
70 /* Allocate grants */
71 for (j= 0; j<IOVEC_NR; j++)
73 if (cpf_getgrants(&gid, 1) != 1)
75 ip_panic((
76 "osdep_eth_init: cpf_getgrants failed: %d\n",
77 errno));
79 eth_port->etp_osdep.etp_wr_iovec[j].iov_grant= gid;
81 if (cpf_getgrants(&gid, 1) != 1)
83 ip_panic((
84 "osdep_eth_init: cpf_getgrants failed: %d\n",
85 errno));
87 eth_port->etp_osdep.etp_wr_vec_grant= gid;
88 for (j= 0; j<RD_IOVEC; j++)
90 if (cpf_getgrants(&gid, 1) != 1)
92 ip_panic((
93 "osdep_eth_init: cpf_getgrants failed: %d\n",
94 errno));
96 eth_port->etp_osdep.etp_rd_iovec[j].iov_grant= gid;
98 if (cpf_getgrants(&gid, 1) != 1)
100 ip_panic((
101 "osdep_eth_init: cpf_getgrants failed: %d\n",
102 errno));
104 eth_port->etp_osdep.etp_rd_vec_grant= gid;
106 #ifdef __minix_vmd
107 r= sys_findproc(ecp->ec_task, &tasknr, 0);
108 #else /* Minix 3 */
109 r= ds_retrieve_u32(ecp->ec_task, &tasknr);
110 if (r != OK && r != ESRCH)
112 printf("inet: ds_retrieve_u32 failed for '%s': %d\n",
113 ecp->ec_task, r);
115 #endif
116 if (r != OK)
118 /* Eventually, we expect ethernet drivers to be
119 * started after INET. So we always end up here. And
120 * the findproc can be removed.
122 printf("eth%d: unable to find task %s: %d\n",
123 i, ecp->ec_task, r);
124 tasknr= ANY;
127 eth_port->etp_osdep.etp_port= ecp->ec_port;
128 eth_port->etp_osdep.etp_task= tasknr;
129 eth_port->etp_osdep.etp_send_ev= 0;
130 ev_init(&eth_port->etp_osdep.etp_recvev);
132 mess.m_type= DL_CONF;
133 mess.DL_PORT= eth_port->etp_osdep.etp_port;
134 mess.DL_PROC= this_proc;
135 mess.DL_MODE= DL_NOMODE;
137 if (tasknr == ANY)
138 r= ENXIO;
139 else
141 assert(eth_port->etp_osdep.etp_state == OEPS_INIT);
142 r= asynsend(eth_port->etp_osdep.etp_task, &mess);
143 if (r == OK)
144 eth_port->etp_osdep.etp_state= OEPS_CONF_SENT;
145 else
147 printf(
148 "osdep_eth_init: unable to send to ethernet task, error= %d\n",
153 r= ENXIO;
155 sr_add_minor(if2minor(ecp->ec_ifno, ETH_DEV_OFF),
156 i, eth_open, eth_close, eth_read,
157 eth_write, eth_ioctl, eth_cancel, eth_select);
159 eth_port->etp_flags |= EPF_ENABLED;
160 eth_port->etp_vlan= 0;
161 eth_port->etp_vlan_port= NULL;
162 eth_port->etp_wr_pack= 0;
163 eth_port->etp_rd_pack= 0;
164 if (r == OK)
166 eth_port->etp_ethaddr= *(ether_addr_t *)mess.m3_ca1;
167 printf("osdep_eth_init: setting EPF_GOT_ADDR\n");
168 eth_port->etp_flags |= EPF_GOT_ADDR;
169 setup_read (eth_port);
173 /* And now come the VLANs */
174 for (i= 0, ecp= eth_conf, eth_port= eth_port_table;
175 i<eth_conf_nr; i++, ecp++, eth_port++)
177 if (!eth_is_vlan(ecp))
178 continue;
180 eth_port->etp_osdep.etp_port= ecp->ec_port;
181 eth_port->etp_osdep.etp_task= ANY;
182 ev_init(&eth_port->etp_osdep.etp_recvev);
184 rport= eth_port->etp_osdep.etp_port;
185 assert(rport >= 0 && rport < eth_conf_nr);
186 rep= &eth_port_table[rport];
187 if (!(rep->etp_flags & EPF_ENABLED))
189 printf(
190 "eth%d: underlying ethernet device %d not enabled",
191 i, rport);
192 continue;
194 if (rep->etp_vlan != 0)
196 printf(
197 "eth%d: underlying ethernet device %d is a VLAN",
198 i, rport);
199 continue;
202 if (rep->etp_flags & EPF_GOT_ADDR)
204 eth_port->etp_ethaddr= rep->etp_ethaddr;
205 printf("osdep_eth_init: setting EPF_GOT_ADDR\n");
206 eth_port->etp_flags |= EPF_GOT_ADDR;
209 sr_add_minor(if2minor(ecp->ec_ifno, ETH_DEV_OFF),
210 i, eth_open, eth_close, eth_read,
211 eth_write, eth_ioctl, eth_cancel, eth_select);
213 eth_port->etp_flags |= EPF_ENABLED;
214 eth_port->etp_vlan= ecp->ec_vlan;
215 eth_port->etp_vlan_port= rep;
216 assert(eth_port->etp_vlan != 0);
217 eth_port->etp_wr_pack= 0;
218 eth_port->etp_rd_pack= 0;
219 eth_reg_vlan(rep, eth_port);
223 PUBLIC void eth_write_port(eth_port, pack)
224 eth_port_t *eth_port;
225 acc_t *pack;
227 eth_port_t *loc_port;
228 message mess1, block_msg;
229 u8_t *eth_dst_ptr;
230 int multicast, r;
231 ev_arg_t ev_arg;
233 assert(!no_ethWritePort);
234 assert(!eth_port->etp_vlan);
236 assert(eth_port->etp_wr_pack == NULL);
237 eth_port->etp_wr_pack= pack;
239 if (eth_port->etp_osdep.etp_state != OEPS_IDLE)
241 eth_port->etp_osdep.etp_flags |= OEPF_NEED_SEND;
242 return;
246 eth_issue_send(eth_port);
249 PRIVATE int notification_count;
251 PUBLIC void eth_rec(m)
252 message *m;
254 int i, r, m_type, stat;
255 eth_port_t *loc_port, *vlan_port;
256 char *drivername;
257 struct eth_conf *ecp;
259 m_type= m->m_type;
260 if (m_type == DL_NAME_REPLY)
262 drivername= m->m3_ca1;
263 printf("eth_rec: got name: %s\n", drivername);
265 notification_count= 0;
267 /* Re-init ethernet interfaces */
268 for (i= 0, ecp= eth_conf, loc_port= eth_port_table;
269 i<eth_conf_nr; i++, ecp++, loc_port++)
271 if (eth_is_vlan(ecp))
272 continue;
274 if (strcmp(ecp->ec_task, drivername) != 0)
276 /* Wrong driver */
277 continue;
279 eth_restart(loc_port, m->m_source);
281 return;
284 assert(m_type == DL_CONF_REPLY || m_type == DL_TASK_REPLY ||
285 m_type == DL_STAT_REPLY);
287 for (i=0, loc_port= eth_port_table; i<eth_conf_nr; i++, loc_port++)
289 if (loc_port->etp_osdep.etp_port == m->DL_PORT &&
290 loc_port->etp_osdep.etp_task == m->m_source)
291 break;
293 if (i >= eth_conf_nr)
295 printf("eth_rec: bad port %d in message type 0x%x from %d\n",
296 m->DL_PORT, m_type, m->m_source);
297 return;
300 if (loc_port->etp_osdep.etp_state == OEPS_CONF_SENT)
302 if (m_type == DL_TASK_REPLY)
304 stat= m->DL_STAT & 0xffff;
306 if (stat & DL_PACK_SEND)
307 write_int(loc_port);
308 if (stat & DL_PACK_RECV)
309 read_int(loc_port, m->DL_COUNT);
310 return;
313 if (m_type != DL_CONF_REPLY)
315 printf(
316 "eth_rec: got bad message type 0x%x from %d in CONF state\n",
317 m_type, m->m_source);
318 return;
321 r= m->m3_i1;
322 if (r == ENXIO)
324 printf(
325 "eth_rec(conf_reply): no ethernet device at task=%d,port=%d\n",
326 loc_port->etp_osdep.etp_task,
327 loc_port->etp_osdep.etp_port);
328 return;
330 if (r < 0)
332 ip_panic(("eth_rec: DL_INIT returned error %d\n", r));
333 return;
336 loc_port->etp_osdep.etp_flags &= ~OEPF_NEED_CONF;
337 loc_port->etp_osdep.etp_state= OEPS_IDLE;
338 loc_port->etp_flags |= EPF_ENABLED;
340 loc_port->etp_ethaddr= *(ether_addr_t *)m->m3_ca1;
341 if (!(loc_port->etp_flags & EPF_GOT_ADDR))
343 loc_port->etp_flags |= EPF_GOT_ADDR;
344 #if 0
345 printf("eth_rec: calling eth_restart_ioctl\n");
346 #endif
347 eth_restart_ioctl(loc_port);
349 /* Also update any VLANs on this device */
350 for (i=0, vlan_port= eth_port_table; i<eth_conf_nr;
351 i++, vlan_port++)
353 if (!(vlan_port->etp_flags & EPF_ENABLED))
354 continue;
355 if (vlan_port->etp_vlan_port != loc_port)
356 continue;
358 vlan_port->etp_ethaddr= loc_port->etp_ethaddr;
359 vlan_port->etp_flags |= EPF_GOT_ADDR;
360 eth_restart_ioctl(vlan_port);
363 if (!(loc_port->etp_flags & EPF_READ_IP))
364 setup_read (loc_port);
366 #if 0
367 if (loc_port->etp_osdep.etp_flags & OEPF_NEED_SEND)
369 printf("eth_rec(conf): OEPF_NEED_SEND is set\n");
371 if (loc_port->etp_osdep.etp_flags & OEPF_NEED_RECV)
373 printf("eth_rec(conf): OEPF_NEED_RECV is set\n");
375 if (loc_port->etp_osdep.etp_flags & OEPF_NEED_STAT)
377 printf("eth_rec(conf): OEPF_NEED_STAT is set\n");
379 #endif
381 return;
383 if (loc_port->etp_osdep.etp_state == OEPS_GETSTAT_SENT)
385 if (m_type != DL_STAT_REPLY)
387 printf(
388 "eth_rec: got bad message type 0x%x from %d in GETSTAT state\n",
389 m_type, m->m_source);
390 return;
393 r= m->DL_STAT;
394 if (r != OK)
396 ip_warning(("eth_rec: DL_STAT returned error %d\n",
397 r));
398 return;
401 loc_port->etp_osdep.etp_state= OEPS_IDLE;
402 loc_port->etp_osdep.etp_flags &= ~OEPF_NEED_STAT;
404 assert(loc_port->etp_osdep.etp_stat_gid != -1);
405 cpf_revoke(loc_port->etp_osdep.etp_stat_gid);
406 loc_port->etp_osdep.etp_stat_gid= -1;
407 loc_port->etp_osdep.etp_stat_buf= NULL;
409 /* Finish ioctl */
410 assert(loc_port->etp_flags & EPF_GOT_ADDR);
411 eth_restart_ioctl(loc_port);
413 #if 0
414 if (loc_port->etp_osdep.etp_flags & OEPF_NEED_SEND)
416 printf("eth_rec(stat): OEPF_NEED_SEND is set\n");
418 if (loc_port->etp_osdep.etp_flags & OEPF_NEED_RECV)
420 printf("eth_rec(stat): OEPF_NEED_RECV is set\n");
422 if (loc_port->etp_osdep.etp_flags & OEPF_NEED_CONF)
424 printf("eth_rec(stat): OEPF_NEED_CONF is set\n");
426 #endif
428 #if 0
429 if (loc_port->etp_osdep.etp_state == OEPS_IDLE &&
430 (loc_port->etp_osdep.etp_flags & OEPF_NEED_CONF))
432 eth_set_rec_conf(loc_port,
433 loc_port->etp_osdep.etp_recvconf);
435 #endif
436 return;
438 assert(loc_port->etp_osdep.etp_state == OEPS_IDLE ||
439 loc_port->etp_osdep.etp_state == OEPS_RECV_SENT ||
440 loc_port->etp_osdep.etp_state == OEPS_SEND_SENT ||
441 (printf("etp_state = %d\n", loc_port->etp_osdep.etp_state), 0));
442 loc_port->etp_osdep.etp_state= OEPS_IDLE;
444 #if 0 /* Ethernet driver is not trusted */
445 set_time (m->DL_CLCK);
446 #endif
448 stat= m->DL_STAT & 0xffff;
450 #if 0
451 if (!(stat & (DL_PACK_SEND|DL_PACK_RECV)))
452 printf("eth_rec: neither DL_PACK_SEND nor DL_PACK_RECV\n");
453 #endif
454 if (stat & DL_PACK_SEND)
455 write_int(loc_port);
456 if (stat & DL_PACK_RECV)
458 if (recv_debug)
460 printf("eth_rec: eth%d got DL_PACK_RECV\n",
461 m->DL_PORT);
463 read_int(loc_port, m->DL_COUNT);
466 if (loc_port->etp_osdep.etp_state == OEPS_IDLE &&
467 loc_port->etp_osdep.etp_flags & OEPF_NEED_SEND)
469 loc_port->etp_osdep.etp_flags &= ~OEPF_NEED_SEND;
470 if (loc_port->etp_wr_pack)
471 eth_issue_send(loc_port);
473 if (loc_port->etp_osdep.etp_state == OEPS_IDLE &&
474 (loc_port->etp_osdep.etp_flags & OEPF_NEED_RECV))
476 loc_port->etp_osdep.etp_flags &= ~OEPF_NEED_RECV;
477 if (!(loc_port->etp_flags & EPF_READ_IP))
478 setup_read (loc_port);
480 if (loc_port->etp_osdep.etp_flags & OEPF_NEED_CONF)
482 printf("eth_rec: OEPF_NEED_CONF is set\n");
484 if (loc_port->etp_osdep.etp_state == OEPS_IDLE &&
485 (loc_port->etp_osdep.etp_flags & OEPF_NEED_STAT))
487 send_getstat(loc_port);
491 PUBLIC void eth_check_drivers(m)
492 message *m;
494 int i, r, tasknr;
496 tasknr= m->m_source;
497 if (notification_count < 100)
499 notification_count++;
500 printf("eth_check_drivers: got a notification #%d from %d\n",
501 notification_count, tasknr);
504 m->m_type= DL_GETNAME;
505 r= asynsend(tasknr, m);
506 if (r != OK)
508 printf("eth_check_drivers: asynsend to %d failed: %d\n",
509 tasknr, r);
510 return;
514 PUBLIC int eth_get_stat(eth_port, eth_stat)
515 eth_port_t *eth_port;
516 eth_stat_t *eth_stat;
518 int r;
519 cp_grant_id_t gid;
521 assert(!eth_port->etp_vlan);
523 if (eth_port->etp_osdep.etp_flags & OEPF_NEED_STAT)
524 ip_panic(( "eth_get_stat: getstat already in progress" ));
526 gid= cpf_grant_direct(eth_port->etp_osdep.etp_task,
527 (vir_bytes)eth_stat, sizeof(*eth_stat), CPF_WRITE);
528 if (gid == -1)
530 ip_panic(( "eth_get_stat: cpf_grant_direct failed: %d\n",
531 errno));
533 assert(eth_port->etp_osdep.etp_stat_gid == -1);
534 eth_port->etp_osdep.etp_stat_gid= gid;
535 eth_port->etp_osdep.etp_stat_buf= eth_stat;
537 if (eth_port->etp_osdep.etp_state != OEPS_IDLE)
539 eth_port->etp_osdep.etp_flags |= OEPF_NEED_STAT;
540 return SUSPEND;
543 send_getstat(eth_port);
545 return SUSPEND;
548 PUBLIC void eth_set_rec_conf (eth_port, flags)
549 eth_port_t *eth_port;
550 u32_t flags;
552 int r;
553 unsigned dl_flags;
554 message mess, repl_mess;
556 assert(!eth_port->etp_vlan);
558 if (!(eth_port->etp_flags & EPF_GOT_ADDR))
560 /* We have never seen the device. */
561 #if 0
562 printf("eth_set_rec_conf: waiting for device to appear\n");
563 #endif
564 return;
567 if (eth_port->etp_osdep.etp_state != OEPS_IDLE)
569 printf(
570 "eth_set_rec_conf: setting OEPF_NEED_CONF, state = %d\n",
571 eth_port->etp_osdep.etp_state);
572 eth_port->etp_osdep.etp_flags |= OEPF_NEED_CONF;
573 return;
576 eth_port->etp_osdep.etp_recvconf= flags;
577 dl_flags= DL_NOMODE;
578 if (flags & NWEO_EN_BROAD)
579 dl_flags |= DL_BROAD_REQ;
580 if (flags & NWEO_EN_MULTI)
581 dl_flags |= DL_MULTI_REQ;
582 if (flags & NWEO_EN_PROMISC)
583 dl_flags |= DL_PROMISC_REQ;
585 mess.m_type= DL_CONF;
586 mess.DL_PORT= eth_port->etp_osdep.etp_port;
587 mess.DL_PROC= this_proc;
588 mess.DL_MODE= dl_flags;
590 assert(eth_port->etp_osdep.etp_state == OEPS_IDLE);
591 r= asynsend(eth_port->etp_osdep.etp_task, &mess);
592 eth_port->etp_osdep.etp_state= OEPS_CONF_SENT;
594 if (r < 0)
596 printf("eth_set_rec_conf: asynsend to %d failed: %d\n",
597 eth_port->etp_osdep.etp_task, r);
598 return;
602 PRIVATE void eth_issue_send(eth_port)
603 eth_port_t *eth_port;
605 int i, r, pack_size;
606 acc_t *pack, *pack_ptr;
607 iovec_s_t *iovec;
608 message m;
610 iovec= eth_port->etp_osdep.etp_wr_iovec;
611 pack= eth_port->etp_wr_pack;
612 pack_size= 0;
613 for (i=0, pack_ptr= pack; i<IOVEC_NR && pack_ptr; i++,
614 pack_ptr= pack_ptr->acc_next)
616 r= cpf_setgrant_direct(iovec[i].iov_grant,
617 eth_port->etp_osdep.etp_task,
618 (vir_bytes)ptr2acc_data(pack_ptr),
619 (vir_bytes)pack_ptr->acc_length,
620 CPF_READ);
621 if (r != 0)
623 ip_panic((
624 "eth_write_port: cpf_setgrant_direct failed: %d\n",
625 errno));
627 pack_size += iovec[i].iov_size= pack_ptr->acc_length;
629 if (i>= IOVEC_NR)
631 pack= bf_pack(pack); /* packet is too fragmented */
632 eth_port->etp_wr_pack= pack;
633 pack_size= 0;
634 for (i=0, pack_ptr= pack; i<IOVEC_NR && pack_ptr;
635 i++, pack_ptr= pack_ptr->acc_next)
637 r= cpf_setgrant_direct(iovec[i].iov_grant,
638 eth_port->etp_osdep.etp_task,
639 (vir_bytes)ptr2acc_data(pack_ptr),
640 (vir_bytes)pack_ptr->acc_length,
641 CPF_READ);
642 if (r != 0)
644 ip_panic((
645 "eth_write_port: cpf_setgrant_direct failed: %d\n",
646 errno));
648 pack_size += iovec[i].iov_size= pack_ptr->acc_length;
651 assert (i< IOVEC_NR);
652 assert (pack_size >= ETH_MIN_PACK_SIZE);
654 r= cpf_setgrant_direct(eth_port->etp_osdep.etp_wr_vec_grant,
655 eth_port->etp_osdep.etp_task,
656 (vir_bytes)iovec,
657 (vir_bytes)(i * sizeof(iovec[0])),
658 CPF_READ);
659 if (r != 0)
661 ip_panic((
662 "eth_write_port: cpf_setgrant_direct failed: %d\n",
663 errno));
665 m.DL_COUNT= i;
666 m.DL_GRANT= eth_port->etp_osdep.etp_wr_vec_grant;
667 m.m_type= DL_WRITEV_S;
669 m.DL_PORT= eth_port->etp_osdep.etp_port;
670 m.DL_PROC= this_proc;
671 m.DL_MODE= DL_NOMODE;
673 assert(eth_port->etp_osdep.etp_state == OEPS_IDLE);
674 r= asynsend(eth_port->etp_osdep.etp_task, &m);
676 if (r < 0)
678 printf("eth_issue_send: send to %d failed: %d\n",
679 eth_port->etp_osdep.etp_task, r);
680 return;
682 eth_port->etp_osdep.etp_state= OEPS_SEND_SENT;
685 PRIVATE void write_int(eth_port)
686 eth_port_t *eth_port;
688 acc_t *pack;
689 int multicast;
690 u8_t *eth_dst_ptr;
692 pack= eth_port->etp_wr_pack;
693 if (pack == NULL)
695 printf("write_int: strange no packet on eth port %d\n",
696 eth_port-eth_port_table);
697 eth_restart_write(eth_port);
698 return;
701 eth_port->etp_wr_pack= NULL;
703 eth_dst_ptr= (u8_t *)ptr2acc_data(pack);
704 multicast= (*eth_dst_ptr & 1); /* low order bit indicates multicast */
705 if (multicast || (eth_port->etp_osdep.etp_recvconf & NWEO_EN_PROMISC))
707 assert(!no_ethWritePort);
708 no_ethWritePort= 1;
709 eth_arrive(eth_port, pack, bf_bufsize(pack));
710 assert(no_ethWritePort);
711 no_ethWritePort= 0;
713 else
714 bf_afree(pack);
716 eth_restart_write(eth_port);
719 PRIVATE void read_int(eth_port, count)
720 eth_port_t *eth_port;
721 int count;
723 acc_t *pack, *cut_pack;
725 pack= eth_port->etp_rd_pack;
726 eth_port->etp_rd_pack= NULL;
728 if (count < ETH_MIN_PACK_SIZE)
730 printf("mnx_eth`read_int: packet size too small (%d)\n",
731 count);
732 bf_afree(pack);
734 else if (count > ETH_MAX_PACK_SIZE_TAGGED)
736 printf("mnx_eth`read_int: packet size too big (%d)\n",
737 count);
738 bf_afree(pack);
740 else
742 cut_pack= bf_cut(pack, 0, count);
743 bf_afree(pack);
745 assert(!no_ethWritePort);
746 no_ethWritePort= 1;
747 eth_arrive(eth_port, cut_pack, count);
748 assert(no_ethWritePort);
749 no_ethWritePort= 0;
752 eth_port->etp_flags &= ~(EPF_READ_IP|EPF_READ_SP);
753 setup_read(eth_port);
756 PRIVATE void setup_read(eth_port)
757 eth_port_t *eth_port;
759 eth_port_t *loc_port;
760 acc_t *pack, *pack_ptr;
761 message mess1, block_msg;
762 iovec_s_t *iovec;
763 ev_arg_t ev_arg;
764 int i, r;
766 assert(!eth_port->etp_vlan);
767 assert(!(eth_port->etp_flags & (EPF_READ_IP|EPF_READ_SP)));
769 if (eth_port->etp_osdep.etp_state != OEPS_IDLE)
771 eth_port->etp_osdep.etp_flags |= OEPF_NEED_RECV;
773 return;
776 assert (!eth_port->etp_rd_pack);
778 iovec= eth_port->etp_osdep.etp_rd_iovec;
779 pack= bf_memreq (ETH_MAX_PACK_SIZE_TAGGED);
781 for (i=0, pack_ptr= pack; i<RD_IOVEC && pack_ptr;
782 i++, pack_ptr= pack_ptr->acc_next)
784 r= cpf_setgrant_direct(iovec[i].iov_grant,
785 eth_port->etp_osdep.etp_task,
786 (vir_bytes)ptr2acc_data(pack_ptr),
787 (vir_bytes)pack_ptr->acc_length,
788 CPF_WRITE);
789 if (r != 0)
791 ip_panic((
792 "mnx_eth`setup_read: cpf_setgrant_direct failed: %d\n",
793 errno));
795 iovec[i].iov_size= (vir_bytes)pack_ptr->acc_length;
797 assert (!pack_ptr);
799 r= cpf_setgrant_direct(eth_port->etp_osdep.etp_rd_vec_grant,
800 eth_port->etp_osdep.etp_task,
801 (vir_bytes)iovec,
802 (vir_bytes)(i * sizeof(iovec[0])),
803 CPF_READ);
804 if (r != 0)
806 ip_panic((
807 "mnx_eth`setup_read: cpf_setgrant_direct failed: %d\n",
808 errno));
811 mess1.m_type= DL_READV_S;
812 mess1.DL_PORT= eth_port->etp_osdep.etp_port;
813 mess1.DL_PROC= this_proc;
814 mess1.DL_COUNT= i;
815 mess1.DL_GRANT= eth_port->etp_osdep.etp_rd_vec_grant;
817 assert(eth_port->etp_osdep.etp_state == OEPS_IDLE);
819 r= asynsend(eth_port->etp_osdep.etp_task, &mess1);
820 eth_port->etp_osdep.etp_state= OEPS_RECV_SENT;
822 if (r < 0)
824 printf(
825 "mnx_eth`setup_read: asynsend to %d failed: %d\n",
826 eth_port->etp_osdep.etp_task, r);
828 eth_port->etp_rd_pack= pack;
829 eth_port->etp_flags |= EPF_READ_IP;
830 eth_port->etp_flags |= EPF_READ_SP;
833 PRIVATE void eth_recvev(ev, ev_arg)
834 event_t *ev;
835 ev_arg_t ev_arg;
837 eth_port_t *eth_port;
838 message *m_ptr;
840 eth_port= ev_arg.ev_ptr;
841 assert(ev == &eth_port->etp_osdep.etp_recvev);
842 m_ptr= &eth_port->etp_osdep.etp_recvrepl;
844 assert(m_ptr->m_type == DL_TASK_REPLY);
845 assert(eth_port->etp_osdep.etp_port == m_ptr->DL_PORT &&
846 eth_port->etp_osdep.etp_task == m_ptr->m_source);
848 assert(m_ptr->DL_STAT & DL_PACK_RECV);
849 m_ptr->DL_STAT &= ~DL_PACK_RECV;
851 if (recv_debug)
853 printf("eth_recvev: eth%d got DL_PACK_RECV\n", m_ptr->DL_PORT);
856 read_int(eth_port, m_ptr->DL_COUNT);
859 PRIVATE void eth_sendev(ev, ev_arg)
860 event_t *ev;
861 ev_arg_t ev_arg;
863 eth_port_t *eth_port;
864 message *m_ptr;
866 eth_port= ev_arg.ev_ptr;
867 assert(ev == &eth_port->etp_sendev);
868 m_ptr= &eth_port->etp_osdep.etp_sendrepl;
870 assert (m_ptr->m_type == DL_TASK_REPLY);
871 assert(eth_port->etp_osdep.etp_port == m_ptr->DL_PORT &&
872 eth_port->etp_osdep.etp_task == m_ptr->m_source);
874 assert(m_ptr->DL_STAT & DL_PACK_SEND);
875 m_ptr->DL_STAT &= ~DL_PACK_SEND;
876 assert(eth_port->etp_osdep.etp_send_ev);
877 eth_port->etp_osdep.etp_send_ev= 0;
879 /* packet is sent */
880 write_int(eth_port);
883 PRIVATE eth_port_t *find_port(m)
884 message *m;
886 eth_port_t *loc_port;
887 int i;
889 for (i=0, loc_port= eth_port_table; i<eth_conf_nr; i++, loc_port++)
891 if (loc_port->etp_osdep.etp_port == m->DL_PORT &&
892 loc_port->etp_osdep.etp_task == m->m_source)
893 break;
895 assert (i<eth_conf_nr);
896 return loc_port;
899 static void eth_restart(eth_port, tasknr)
900 eth_port_t *eth_port;
901 int tasknr;
903 int i, r;
904 unsigned flags, dl_flags;
905 cp_grant_id_t gid;
906 message mess;
908 printf("eth_restart: restarting eth%d, task %d, port %d\n",
909 eth_port-eth_port_table, tasknr,
910 eth_port->etp_osdep.etp_port);
912 if (eth_port->etp_osdep.etp_task == tasknr)
914 printf(
915 "eth_restart: task number did not change. Aborting restart\n");
916 return;
918 eth_port->etp_osdep.etp_task= tasknr;
920 switch(eth_port->etp_osdep.etp_state)
922 case OEPS_CONF_SENT:
923 case OEPS_RECV_SENT:
924 case OEPS_SEND_SENT:
925 /* We can safely ignore the pending CONF, RECV, and SEND
926 * requests.
928 eth_port->etp_osdep.etp_state= OEPS_IDLE;
929 break;
930 case OEPS_GETSTAT_SENT:
931 /* Set the OEPF_NEED_STAT to trigger a new request */
932 eth_port->etp_osdep.etp_flags |= OEPF_NEED_STAT;
933 eth_port->etp_osdep.etp_state= OEPS_IDLE;
934 break;
937 /* If there is a pending GETSTAT request then we have to create a
938 * new grant.
940 if (eth_port->etp_osdep.etp_flags & OEPF_NEED_STAT)
942 assert(eth_port->etp_osdep.etp_stat_gid != -1);
943 cpf_revoke(eth_port->etp_osdep.etp_stat_gid);
945 gid= cpf_grant_direct(eth_port->etp_osdep.etp_task,
946 (vir_bytes)eth_port->etp_osdep.etp_stat_buf,
947 sizeof(*eth_port->etp_osdep.etp_stat_buf), CPF_WRITE);
948 if (gid == -1)
950 ip_panic((
951 "eth_restart: cpf_grant_direct failed: %d\n",
952 errno));
954 eth_port->etp_osdep.etp_stat_gid= gid;
957 flags= eth_port->etp_osdep.etp_recvconf;
958 dl_flags= DL_NOMODE;
959 if (flags & NWEO_EN_BROAD)
960 dl_flags |= DL_BROAD_REQ;
961 if (flags & NWEO_EN_MULTI)
962 dl_flags |= DL_MULTI_REQ;
963 if (flags & NWEO_EN_PROMISC)
964 dl_flags |= DL_PROMISC_REQ;
965 mess.m_type= DL_CONF;
966 mess.DL_PORT= eth_port->etp_osdep.etp_port;
967 mess.DL_PROC= this_proc;
968 mess.DL_MODE= dl_flags;
970 compare(eth_port->etp_osdep.etp_state, ==, OEPS_IDLE);
971 r= asynsend(eth_port->etp_osdep.etp_task, &mess);
972 if (r<0)
974 printf(
975 "eth_restart: send to ethernet task %d failed: %d\n",
976 eth_port->etp_osdep.etp_task, r);
977 return;
979 eth_port->etp_osdep.etp_state= OEPS_CONF_SENT;
981 if (eth_port->etp_wr_pack)
983 bf_afree(eth_port->etp_wr_pack);
984 eth_port->etp_wr_pack= NULL;
985 eth_restart_write(eth_port);
987 if (eth_port->etp_rd_pack)
989 bf_afree(eth_port->etp_rd_pack);
990 eth_port->etp_rd_pack= NULL;
991 eth_port->etp_flags &= ~(EPF_READ_IP|EPF_READ_SP);
996 PRIVATE void send_getstat(eth_port)
997 eth_port_t *eth_port;
999 int r;
1000 message mess;
1002 mess.m_type= DL_GETSTAT_S;
1003 mess.DL_PORT= eth_port->etp_osdep.etp_port;
1004 mess.DL_PROC= this_proc;
1005 mess.DL_GRANT= eth_port->etp_osdep.etp_stat_gid;
1007 assert(eth_port->etp_osdep.etp_state == OEPS_IDLE);
1009 r= asynsend(eth_port->etp_osdep.etp_task, &mess);
1010 eth_port->etp_osdep.etp_state= OEPS_GETSTAT_SENT;
1012 if (r != OK)
1013 ip_panic(( "eth_get_stat: asynsend failed: %d", r));
1016 #if 0
1017 PRIVATE asynmsg_t *msgtable= NULL;
1018 PRIVATE size_t msgtable_n= 0;
1020 PRIVATE int asynsend(dst, mp)
1021 endpoint_t dst;
1022 message *mp;
1024 int i;
1025 unsigned flags;
1027 if (msgtable == NULL)
1029 printf("asynsend: allocating msg table\n");
1030 msgtable_n= 5;
1031 msgtable= malloc(msgtable_n * sizeof(msgtable[0]));
1032 for (i= 0; i<msgtable_n; i++)
1033 msgtable[i].flags= AMF_EMPTY;
1036 /* Find slot in table */
1037 for (i= 0; i<msgtable_n; i++)
1039 flags= msgtable[i].flags;
1040 if ((flags & (AMF_VALID|AMF_DONE)) == (AMF_VALID|AMF_DONE))
1042 if (msgtable[i].result != OK)
1044 printf(
1045 "asynsend: found completed entry %d with error %d\n",
1046 i, msgtable[i].result);
1048 break;
1050 if (flags == AMF_EMPTY)
1051 break;
1053 if (i >= msgtable_n)
1054 ip_panic(( "asynsend: should resize table" ));
1055 msgtable[i].dst= dst;
1056 msgtable[i].msg= *mp;
1057 msgtable[i].flags= AMF_VALID; /* Has to be last. The kernel
1058 * scans this table while we are
1059 * sleeping.
1062 /* Tell the kernel to rescan the table */
1063 return senda(msgtable, msgtable_n);
1065 #endif
1068 * $PchId: mnx_eth.c,v 1.16 2005/06/28 14:24:37 philip Exp $