Fixed extern declaration from pointer to array
[minix.git] / servers / inet / mnx_eth.c
blob9da1f0ddccde710d07ec46c1d179f55bbfcd1007
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 PUBLIC void osdep_eth_init()
39 int i, j, r, rport;
40 u32_t tasknr;
41 struct eth_conf *ecp;
42 eth_port_t *eth_port, *rep;
43 message mess;
44 cp_grant_id_t gid;
46 /* First initialize normal ethernet interfaces */
47 for (i= 0, ecp= eth_conf, eth_port= eth_port_table;
48 i<eth_conf_nr; i++, ecp++, eth_port++)
50 /* Set all grants to invalid */
51 for (j= 0; j<IOVEC_NR; j++)
52 eth_port->etp_osdep.etp_wr_iovec[j].iov_grant= -1;
53 eth_port->etp_osdep.etp_wr_vec_grant= -1;
54 for (j= 0; j<RD_IOVEC; j++)
55 eth_port->etp_osdep.etp_rd_iovec[j].iov_grant= -1;
56 eth_port->etp_osdep.etp_rd_vec_grant= -1;
58 eth_port->etp_osdep.etp_state= OEPS_INIT;
59 eth_port->etp_osdep.etp_flags= OEPF_EMPTY;
60 eth_port->etp_osdep.etp_stat_gid= -1;
61 eth_port->etp_osdep.etp_stat_buf= NULL;
63 if (eth_is_vlan(ecp))
64 continue;
66 /* Allocate grants */
67 for (j= 0; j<IOVEC_NR; j++)
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_iovec[j].iov_grant= gid;
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_wr_vec_grant= gid;
84 for (j= 0; j<RD_IOVEC; j++)
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_iovec[j].iov_grant= gid;
94 if (cpf_getgrants(&gid, 1) != 1)
96 ip_panic((
97 "osdep_eth_init: cpf_getgrants failed: %d\n",
98 errno));
100 eth_port->etp_osdep.etp_rd_vec_grant= gid;
102 r= ds_retrieve_label_num(ecp->ec_task, &tasknr);
103 if (r != OK && r != ESRCH)
105 printf("inet: ds_retrieve_label_num failed for '%s': %d\n",
106 ecp->ec_task, r);
108 if (r != OK)
110 /* Eventually, we expect ethernet drivers to be
111 * started after INET. So we always end up here. And
112 * the findproc can be removed.
114 #if 0
115 printf("eth%d: unable to find task %s: %d\n",
116 i, ecp->ec_task, r);
117 #endif
118 tasknr= ANY;
121 eth_port->etp_osdep.etp_port= ecp->ec_port;
122 eth_port->etp_osdep.etp_task= tasknr;
123 eth_port->etp_osdep.etp_recvconf= 0;
124 eth_port->etp_osdep.etp_send_ev= 0;
125 ev_init(&eth_port->etp_osdep.etp_recvev);
127 mess.m_type= DL_CONF;
128 mess.DL_PORT= eth_port->etp_osdep.etp_port;
129 mess.DL_PROC= this_proc;
130 mess.DL_MODE= DL_NOMODE;
132 if (tasknr == ANY)
133 r= ENXIO;
134 else
136 assert(eth_port->etp_osdep.etp_state == OEPS_INIT);
137 r= asynsend(eth_port->etp_osdep.etp_task, &mess);
138 if (r == OK)
139 eth_port->etp_osdep.etp_state= OEPS_CONF_SENT;
140 else
142 printf(
143 "osdep_eth_init: unable to send to ethernet task, error= %d\n",
148 r= ENXIO;
150 sr_add_minor(if2minor(ecp->ec_ifno, ETH_DEV_OFF),
151 i, eth_open, eth_close, eth_read,
152 eth_write, eth_ioctl, eth_cancel, eth_select);
154 eth_port->etp_flags |= EPF_ENABLED;
155 eth_port->etp_vlan= 0;
156 eth_port->etp_vlan_port= NULL;
157 eth_port->etp_wr_pack= 0;
158 eth_port->etp_rd_pack= 0;
159 if (r == OK)
161 eth_port->etp_ethaddr= *(ether_addr_t *)mess.m3_ca1;
162 printf("osdep_eth_init: setting EPF_GOT_ADDR\n");
163 eth_port->etp_flags |= EPF_GOT_ADDR;
164 setup_read (eth_port);
168 /* And now come the VLANs */
169 for (i= 0, ecp= eth_conf, eth_port= eth_port_table;
170 i<eth_conf_nr; i++, ecp++, eth_port++)
172 if (!eth_is_vlan(ecp))
173 continue;
175 eth_port->etp_osdep.etp_port= ecp->ec_port;
176 eth_port->etp_osdep.etp_task= ANY;
177 ev_init(&eth_port->etp_osdep.etp_recvev);
179 rport= eth_port->etp_osdep.etp_port;
180 assert(rport >= 0 && rport < eth_conf_nr);
181 rep= &eth_port_table[rport];
182 if (!(rep->etp_flags & EPF_ENABLED))
184 printf(
185 "eth%d: underlying ethernet device %d not enabled",
186 i, rport);
187 continue;
189 if (rep->etp_vlan != 0)
191 printf(
192 "eth%d: underlying ethernet device %d is a VLAN",
193 i, rport);
194 continue;
197 if (rep->etp_flags & EPF_GOT_ADDR)
199 eth_port->etp_ethaddr= rep->etp_ethaddr;
200 printf("osdep_eth_init: setting EPF_GOT_ADDR\n");
201 eth_port->etp_flags |= EPF_GOT_ADDR;
204 sr_add_minor(if2minor(ecp->ec_ifno, ETH_DEV_OFF),
205 i, eth_open, eth_close, eth_read,
206 eth_write, eth_ioctl, eth_cancel, eth_select);
208 eth_port->etp_flags |= EPF_ENABLED;
209 eth_port->etp_vlan= ecp->ec_vlan;
210 eth_port->etp_vlan_port= rep;
211 assert(eth_port->etp_vlan != 0);
212 eth_port->etp_wr_pack= 0;
213 eth_port->etp_rd_pack= 0;
214 eth_reg_vlan(rep, eth_port);
218 PUBLIC void eth_write_port(eth_port, pack)
219 eth_port_t *eth_port;
220 acc_t *pack;
222 assert(!no_ethWritePort);
223 assert(!eth_port->etp_vlan);
225 assert(eth_port->etp_wr_pack == NULL);
226 eth_port->etp_wr_pack= pack;
228 if (eth_port->etp_osdep.etp_state != OEPS_IDLE)
230 eth_port->etp_osdep.etp_flags |= OEPF_NEED_SEND;
231 return;
235 eth_issue_send(eth_port);
238 #if 0
239 PRIVATE int notification_count;
240 #endif
242 PUBLIC void eth_rec(message *m)
244 int i, r, m_type, stat;
245 eth_port_t *loc_port, *vlan_port;
246 char *drivername;
247 struct eth_conf *ecp;
249 m_type= m->m_type;
250 if (m_type == DL_NAME_REPLY)
252 drivername= m->m3_ca1;
253 #if 0
254 printf("eth_rec: got name: %s\n", drivername);
256 notification_count= 0;
257 #endif
259 /* Re-init ethernet interfaces */
260 for (i= 0, ecp= eth_conf, loc_port= eth_port_table;
261 i<eth_conf_nr; i++, ecp++, loc_port++)
263 if (eth_is_vlan(ecp))
264 continue;
266 if (strcmp(ecp->ec_task, drivername) != 0)
268 /* Wrong driver */
269 continue;
271 eth_restart(loc_port, m->m_source);
273 return;
276 assert(m_type == DL_CONF_REPLY || m_type == DL_TASK_REPLY ||
277 m_type == DL_STAT_REPLY);
279 for (i=0, loc_port= eth_port_table; i<eth_conf_nr; i++, loc_port++)
281 if (loc_port->etp_osdep.etp_port == m->DL_PORT &&
282 loc_port->etp_osdep.etp_task == m->m_source)
283 break;
285 if (i >= eth_conf_nr)
287 printf("eth_rec: bad port %d in message type 0x%x from %d\n",
288 m->DL_PORT, m_type, m->m_source);
289 return;
292 if (loc_port->etp_osdep.etp_state == OEPS_CONF_SENT)
294 if (m_type == DL_TASK_REPLY)
296 stat= m->DL_STAT & 0xffff;
298 if (stat & DL_PACK_SEND)
299 write_int(loc_port);
300 if (stat & DL_PACK_RECV)
301 read_int(loc_port, m->DL_COUNT);
302 return;
305 if (m_type != DL_CONF_REPLY)
307 printf(
308 "eth_rec: got bad message type 0x%x from %d in CONF state\n",
309 m_type, m->m_source);
310 return;
313 r= m->m3_i1;
314 if (r == ENXIO)
316 printf(
317 "eth_rec(conf_reply): no ethernet device at task=%d,port=%d\n",
318 loc_port->etp_osdep.etp_task,
319 loc_port->etp_osdep.etp_port);
320 return;
322 if (r < 0)
324 ip_panic(("eth_rec: DL_INIT returned error %d\n", r));
325 return;
328 loc_port->etp_osdep.etp_flags &= ~OEPF_NEED_CONF;
329 loc_port->etp_osdep.etp_state= OEPS_IDLE;
330 loc_port->etp_flags |= EPF_ENABLED;
332 loc_port->etp_ethaddr= *(ether_addr_t *)m->m3_ca1;
333 if (!(loc_port->etp_flags & EPF_GOT_ADDR))
335 loc_port->etp_flags |= EPF_GOT_ADDR;
336 #if 0
337 printf("eth_rec: calling eth_restart_ioctl\n");
338 #endif
339 eth_restart_ioctl(loc_port);
341 /* Also update any VLANs on this device */
342 for (i=0, vlan_port= eth_port_table; i<eth_conf_nr;
343 i++, vlan_port++)
345 if (!(vlan_port->etp_flags & EPF_ENABLED))
346 continue;
347 if (vlan_port->etp_vlan_port != loc_port)
348 continue;
350 vlan_port->etp_ethaddr= loc_port->etp_ethaddr;
351 vlan_port->etp_flags |= EPF_GOT_ADDR;
352 eth_restart_ioctl(vlan_port);
355 if (!(loc_port->etp_flags & EPF_READ_IP))
356 setup_read (loc_port);
358 #if 0
359 if (loc_port->etp_osdep.etp_flags & OEPF_NEED_SEND)
361 printf("eth_rec(conf): OEPF_NEED_SEND is set\n");
363 if (loc_port->etp_osdep.etp_flags & OEPF_NEED_RECV)
365 printf("eth_rec(conf): OEPF_NEED_RECV is set\n");
367 if (loc_port->etp_osdep.etp_flags & OEPF_NEED_STAT)
369 printf("eth_rec(conf): OEPF_NEED_STAT is set\n");
371 #endif
373 return;
375 if (loc_port->etp_osdep.etp_state == OEPS_GETSTAT_SENT)
377 if (m_type != DL_STAT_REPLY)
379 printf(
380 "eth_rec: got bad message type 0x%x from %d in GETSTAT state\n",
381 m_type, m->m_source);
382 return;
385 r= m->DL_STAT;
386 if (r != OK)
388 ip_warning(("eth_rec: DL_STAT returned error %d\n",
389 r));
390 return;
393 loc_port->etp_osdep.etp_state= OEPS_IDLE;
394 loc_port->etp_osdep.etp_flags &= ~OEPF_NEED_STAT;
396 assert(loc_port->etp_osdep.etp_stat_gid != -1);
397 cpf_revoke(loc_port->etp_osdep.etp_stat_gid);
398 loc_port->etp_osdep.etp_stat_gid= -1;
399 loc_port->etp_osdep.etp_stat_buf= NULL;
401 /* Finish ioctl */
402 assert(loc_port->etp_flags & EPF_GOT_ADDR);
403 eth_restart_ioctl(loc_port);
405 #if 0
406 if (loc_port->etp_osdep.etp_flags & OEPF_NEED_SEND)
408 printf("eth_rec(stat): OEPF_NEED_SEND is set\n");
410 if (loc_port->etp_osdep.etp_flags & OEPF_NEED_RECV)
412 printf("eth_rec(stat): OEPF_NEED_RECV is set\n");
414 if (loc_port->etp_osdep.etp_flags & OEPF_NEED_CONF)
416 printf("eth_rec(stat): OEPF_NEED_CONF is set\n");
418 #endif
420 #if 0
421 if (loc_port->etp_osdep.etp_state == OEPS_IDLE &&
422 (loc_port->etp_osdep.etp_flags & OEPF_NEED_CONF))
424 eth_set_rec_conf(loc_port,
425 loc_port->etp_osdep.etp_recvconf);
427 #endif
428 return;
430 assert(loc_port->etp_osdep.etp_state == OEPS_IDLE ||
431 loc_port->etp_osdep.etp_state == OEPS_RECV_SENT ||
432 loc_port->etp_osdep.etp_state == OEPS_SEND_SENT ||
433 (printf("etp_state = %d\n", loc_port->etp_osdep.etp_state), 0));
434 loc_port->etp_osdep.etp_state= OEPS_IDLE;
436 #if 0 /* Ethernet driver is not trusted */
437 set_time (m->DL_CLCK);
438 #endif
440 stat= m->DL_STAT & 0xffff;
442 #if 0
443 if (!(stat & (DL_PACK_SEND|DL_PACK_RECV)))
444 printf("eth_rec: neither DL_PACK_SEND nor DL_PACK_RECV\n");
445 #endif
446 if (stat & DL_PACK_SEND)
447 write_int(loc_port);
448 if (stat & DL_PACK_RECV)
450 if (recv_debug)
452 printf("eth_rec: eth%d got DL_PACK_RECV\n",
453 m->DL_PORT);
455 read_int(loc_port, m->DL_COUNT);
458 if (loc_port->etp_osdep.etp_state == OEPS_IDLE &&
459 loc_port->etp_osdep.etp_flags & OEPF_NEED_SEND)
461 loc_port->etp_osdep.etp_flags &= ~OEPF_NEED_SEND;
462 if (loc_port->etp_wr_pack)
463 eth_issue_send(loc_port);
465 if (loc_port->etp_osdep.etp_state == OEPS_IDLE &&
466 (loc_port->etp_osdep.etp_flags & OEPF_NEED_RECV))
468 loc_port->etp_osdep.etp_flags &= ~OEPF_NEED_RECV;
469 if (!(loc_port->etp_flags & EPF_READ_IP))
470 setup_read (loc_port);
472 if (loc_port->etp_osdep.etp_flags & OEPF_NEED_CONF)
474 printf("eth_rec: OEPF_NEED_CONF is set\n");
476 if (loc_port->etp_osdep.etp_state == OEPS_IDLE &&
477 (loc_port->etp_osdep.etp_flags & OEPF_NEED_STAT))
479 send_getstat(loc_port);
483 PUBLIC void eth_check_drivers(message *m)
485 int r, tasknr;
487 tasknr= m->m_source;
488 #if 0
489 if (notification_count < 100)
491 notification_count++;
492 printf("eth_check_drivers: got a notification #%d from %d\n",
493 notification_count, tasknr);
495 #endif
497 m->m_type= DL_GETNAME;
498 r= asynsend(tasknr, m);
499 if (r != OK)
501 printf("eth_check_drivers: asynsend to %d failed: %d\n",
502 tasknr, r);
503 return;
507 PUBLIC int eth_get_stat(eth_port, eth_stat)
508 eth_port_t *eth_port;
509 eth_stat_t *eth_stat;
511 cp_grant_id_t gid;
513 assert(!eth_port->etp_vlan);
515 if (eth_port->etp_osdep.etp_flags & OEPF_NEED_STAT)
516 ip_panic(( "eth_get_stat: getstat already in progress" ));
518 gid= cpf_grant_direct(eth_port->etp_osdep.etp_task,
519 (vir_bytes)eth_stat, sizeof(*eth_stat), CPF_WRITE);
520 if (gid == -1)
522 ip_panic(( "eth_get_stat: cpf_grant_direct failed: %d\n",
523 errno));
525 assert(eth_port->etp_osdep.etp_stat_gid == -1);
526 eth_port->etp_osdep.etp_stat_gid= gid;
527 eth_port->etp_osdep.etp_stat_buf= eth_stat;
529 if (eth_port->etp_osdep.etp_state != OEPS_IDLE)
531 eth_port->etp_osdep.etp_flags |= OEPF_NEED_STAT;
532 return SUSPEND;
535 send_getstat(eth_port);
537 return SUSPEND;
540 PUBLIC void eth_set_rec_conf (eth_port, flags)
541 eth_port_t *eth_port;
542 u32_t flags;
544 int r;
545 unsigned dl_flags, mask;
546 message mess;
548 assert(!eth_port->etp_vlan);
550 if (!(eth_port->etp_flags & EPF_GOT_ADDR))
552 /* We have never seen the device. */
553 #if 0
554 printf("eth_set_rec_conf: waiting for device to appear\n");
555 #endif
556 return;
559 if (eth_port->etp_osdep.etp_state != OEPS_IDLE)
561 printf(
562 "eth_set_rec_conf: setting OEPF_NEED_CONF, state = %d\n",
563 eth_port->etp_osdep.etp_state);
564 eth_port->etp_osdep.etp_flags |= OEPF_NEED_CONF;
565 return;
568 mask = NWEO_EN_BROAD | NWEO_EN_MULTI | NWEO_EN_PROMISC;
569 if ((eth_port->etp_osdep.etp_recvconf & mask) == (flags & mask))
571 /* No change for the driver, so don't send an update */
572 return;
575 eth_port->etp_osdep.etp_recvconf= flags;
576 dl_flags= DL_NOMODE;
577 if (flags & NWEO_EN_BROAD)
578 dl_flags |= DL_BROAD_REQ;
579 if (flags & NWEO_EN_MULTI)
580 dl_flags |= DL_MULTI_REQ;
581 if (flags & NWEO_EN_PROMISC)
582 dl_flags |= DL_PROMISC_REQ;
584 mess.m_type= DL_CONF;
585 mess.DL_PORT= eth_port->etp_osdep.etp_port;
586 mess.DL_PROC= this_proc;
587 mess.DL_MODE= dl_flags;
589 assert(eth_port->etp_osdep.etp_state == OEPS_IDLE);
590 r= asynsend(eth_port->etp_osdep.etp_task, &mess);
591 eth_port->etp_osdep.etp_state= OEPS_CONF_SENT;
593 if (r < 0)
595 printf("eth_set_rec_conf: asynsend to %d failed: %d\n",
596 eth_port->etp_osdep.etp_task, r);
597 return;
601 PRIVATE void eth_issue_send(eth_port)
602 eth_port_t *eth_port;
604 int i, r, pack_size;
605 acc_t *pack, *pack_ptr;
606 iovec_s_t *iovec;
607 message m;
609 iovec= eth_port->etp_osdep.etp_wr_iovec;
610 pack= eth_port->etp_wr_pack;
611 pack_size= 0;
612 for (i=0, pack_ptr= pack; i<IOVEC_NR && pack_ptr; i++,
613 pack_ptr= pack_ptr->acc_next)
615 r= cpf_setgrant_direct(iovec[i].iov_grant,
616 eth_port->etp_osdep.etp_task,
617 (vir_bytes)ptr2acc_data(pack_ptr),
618 (vir_bytes)pack_ptr->acc_length,
619 CPF_READ);
620 if (r != 0)
622 ip_panic((
623 "eth_write_port: cpf_setgrant_direct failed: %d\n",
624 errno));
626 pack_size += iovec[i].iov_size= pack_ptr->acc_length;
628 if (i>= IOVEC_NR)
630 pack= bf_pack(pack); /* packet is too fragmented */
631 eth_port->etp_wr_pack= pack;
632 pack_size= 0;
633 for (i=0, pack_ptr= pack; i<IOVEC_NR && pack_ptr;
634 i++, pack_ptr= pack_ptr->acc_next)
636 r= cpf_setgrant_direct(iovec[i].iov_grant,
637 eth_port->etp_osdep.etp_task,
638 (vir_bytes)ptr2acc_data(pack_ptr),
639 (vir_bytes)pack_ptr->acc_length,
640 CPF_READ);
641 if (r != 0)
643 ip_panic((
644 "eth_write_port: cpf_setgrant_direct failed: %d\n",
645 errno));
647 pack_size += iovec[i].iov_size= pack_ptr->acc_length;
650 assert (i< IOVEC_NR);
651 assert (pack_size >= ETH_MIN_PACK_SIZE);
653 r= cpf_setgrant_direct(eth_port->etp_osdep.etp_wr_vec_grant,
654 eth_port->etp_osdep.etp_task,
655 (vir_bytes)iovec,
656 (vir_bytes)(i * sizeof(iovec[0])),
657 CPF_READ);
658 if (r != 0)
660 ip_panic((
661 "eth_write_port: cpf_setgrant_direct failed: %d\n",
662 errno));
664 m.DL_COUNT= i;
665 m.DL_GRANT= eth_port->etp_osdep.etp_wr_vec_grant;
666 m.m_type= DL_WRITEV_S;
668 m.DL_PORT= eth_port->etp_osdep.etp_port;
669 m.DL_PROC= this_proc;
670 m.DL_MODE= DL_NOMODE;
672 assert(eth_port->etp_osdep.etp_state == OEPS_IDLE);
673 r= asynsend(eth_port->etp_osdep.etp_task, &m);
675 if (r < 0)
677 printf("eth_issue_send: send to %d failed: %d\n",
678 eth_port->etp_osdep.etp_task, r);
679 return;
681 eth_port->etp_osdep.etp_state= OEPS_SEND_SENT;
684 PRIVATE void write_int(eth_port)
685 eth_port_t *eth_port;
687 acc_t *pack;
688 int multicast;
689 u8_t *eth_dst_ptr;
691 pack= eth_port->etp_wr_pack;
692 if (pack == NULL)
694 printf("write_int: strange no packet on eth port %d\n",
695 eth_port-eth_port_table);
696 eth_restart_write(eth_port);
697 return;
700 eth_port->etp_wr_pack= NULL;
702 eth_dst_ptr= (u8_t *)ptr2acc_data(pack);
703 multicast= (*eth_dst_ptr & 1); /* low order bit indicates multicast */
704 if (multicast || (eth_port->etp_osdep.etp_recvconf & NWEO_EN_PROMISC))
706 assert(!no_ethWritePort);
707 no_ethWritePort= 1;
708 eth_arrive(eth_port, pack, bf_bufsize(pack));
709 assert(no_ethWritePort);
710 no_ethWritePort= 0;
712 else
713 bf_afree(pack);
715 eth_restart_write(eth_port);
718 PRIVATE void read_int(eth_port, count)
719 eth_port_t *eth_port;
720 int count;
722 acc_t *pack, *cut_pack;
724 pack= eth_port->etp_rd_pack;
725 eth_port->etp_rd_pack= NULL;
727 if (count < ETH_MIN_PACK_SIZE)
729 printf("mnx_eth`read_int: packet size too small (%d)\n",
730 count);
731 bf_afree(pack);
733 else if (count > ETH_MAX_PACK_SIZE_TAGGED)
735 printf("mnx_eth`read_int: packet size too big (%d)\n",
736 count);
737 bf_afree(pack);
739 else
741 cut_pack= bf_cut(pack, 0, count);
742 bf_afree(pack);
744 assert(!no_ethWritePort);
745 no_ethWritePort= 1;
746 eth_arrive(eth_port, cut_pack, count);
747 assert(no_ethWritePort);
748 no_ethWritePort= 0;
751 eth_port->etp_flags &= ~(EPF_READ_IP|EPF_READ_SP);
752 setup_read(eth_port);
755 PRIVATE void setup_read(eth_port)
756 eth_port_t *eth_port;
758 acc_t *pack, *pack_ptr;
759 message mess1;
760 iovec_s_t *iovec;
761 int i, r;
763 assert(!eth_port->etp_vlan);
764 assert(!(eth_port->etp_flags & (EPF_READ_IP|EPF_READ_SP)));
766 if (eth_port->etp_osdep.etp_state != OEPS_IDLE)
768 eth_port->etp_osdep.etp_flags |= OEPF_NEED_RECV;
770 return;
773 assert (!eth_port->etp_rd_pack);
775 iovec= eth_port->etp_osdep.etp_rd_iovec;
776 pack= bf_memreq (ETH_MAX_PACK_SIZE_TAGGED);
778 for (i=0, pack_ptr= pack; i<RD_IOVEC && pack_ptr;
779 i++, pack_ptr= pack_ptr->acc_next)
781 r= cpf_setgrant_direct(iovec[i].iov_grant,
782 eth_port->etp_osdep.etp_task,
783 (vir_bytes)ptr2acc_data(pack_ptr),
784 (vir_bytes)pack_ptr->acc_length,
785 CPF_WRITE);
786 if (r != 0)
788 ip_panic((
789 "mnx_eth`setup_read: cpf_setgrant_direct failed: %d\n",
790 errno));
792 iovec[i].iov_size= (vir_bytes)pack_ptr->acc_length;
794 assert (!pack_ptr);
796 r= cpf_setgrant_direct(eth_port->etp_osdep.etp_rd_vec_grant,
797 eth_port->etp_osdep.etp_task,
798 (vir_bytes)iovec,
799 (vir_bytes)(i * sizeof(iovec[0])),
800 CPF_READ);
801 if (r != 0)
803 ip_panic((
804 "mnx_eth`setup_read: cpf_setgrant_direct failed: %d\n",
805 errno));
808 mess1.m_type= DL_READV_S;
809 mess1.DL_PORT= eth_port->etp_osdep.etp_port;
810 mess1.DL_PROC= this_proc;
811 mess1.DL_COUNT= i;
812 mess1.DL_GRANT= eth_port->etp_osdep.etp_rd_vec_grant;
814 assert(eth_port->etp_osdep.etp_state == OEPS_IDLE);
816 r= asynsend(eth_port->etp_osdep.etp_task, &mess1);
817 eth_port->etp_osdep.etp_state= OEPS_RECV_SENT;
819 if (r < 0)
821 printf(
822 "mnx_eth`setup_read: asynsend to %d failed: %d\n",
823 eth_port->etp_osdep.etp_task, r);
825 eth_port->etp_rd_pack= pack;
826 eth_port->etp_flags |= EPF_READ_IP;
827 eth_port->etp_flags |= EPF_READ_SP;
830 PRIVATE void eth_recvev(ev, ev_arg)
831 event_t *ev;
832 ev_arg_t ev_arg;
834 eth_port_t *eth_port;
835 message *m_ptr;
837 eth_port= ev_arg.ev_ptr;
838 assert(ev == &eth_port->etp_osdep.etp_recvev);
839 m_ptr= &eth_port->etp_osdep.etp_recvrepl;
841 assert(m_ptr->m_type == DL_TASK_REPLY);
842 assert(eth_port->etp_osdep.etp_port == m_ptr->DL_PORT &&
843 eth_port->etp_osdep.etp_task == m_ptr->m_source);
845 assert(m_ptr->DL_STAT & DL_PACK_RECV);
846 m_ptr->DL_STAT &= ~DL_PACK_RECV;
848 if (recv_debug)
850 printf("eth_recvev: eth%d got DL_PACK_RECV\n", m_ptr->DL_PORT);
853 read_int(eth_port, m_ptr->DL_COUNT);
856 PRIVATE void eth_sendev(ev, ev_arg)
857 event_t *ev;
858 ev_arg_t ev_arg;
860 eth_port_t *eth_port;
861 message *m_ptr;
863 eth_port= ev_arg.ev_ptr;
864 assert(ev == &eth_port->etp_sendev);
865 m_ptr= &eth_port->etp_osdep.etp_sendrepl;
867 assert (m_ptr->m_type == DL_TASK_REPLY);
868 assert(eth_port->etp_osdep.etp_port == m_ptr->DL_PORT &&
869 eth_port->etp_osdep.etp_task == m_ptr->m_source);
871 assert(m_ptr->DL_STAT & DL_PACK_SEND);
872 m_ptr->DL_STAT &= ~DL_PACK_SEND;
873 assert(eth_port->etp_osdep.etp_send_ev);
874 eth_port->etp_osdep.etp_send_ev= 0;
876 /* packet is sent */
877 write_int(eth_port);
880 PRIVATE eth_port_t *find_port(m)
881 message *m;
883 eth_port_t *loc_port;
884 int i;
886 for (i=0, loc_port= eth_port_table; i<eth_conf_nr; i++, loc_port++)
888 if (loc_port->etp_osdep.etp_port == m->DL_PORT &&
889 loc_port->etp_osdep.etp_task == m->m_source)
890 break;
892 assert (i<eth_conf_nr);
893 return loc_port;
896 static void eth_restart(eth_port, tasknr)
897 eth_port_t *eth_port;
898 int tasknr;
900 int r;
901 unsigned flags, dl_flags;
902 cp_grant_id_t gid;
903 message mess;
905 if (eth_port->etp_osdep.etp_state != OEPS_INIT) {
906 printf("eth_restart: restarting eth%d, task %d, port %d\n",
907 eth_port-eth_port_table, tasknr,
908 eth_port->etp_osdep.etp_port);
911 if (eth_port->etp_osdep.etp_task == tasknr)
913 printf(
914 "eth_restart: task number did not change. Aborting restart\n");
915 return;
917 eth_port->etp_osdep.etp_task= tasknr;
919 switch(eth_port->etp_osdep.etp_state)
921 case OEPS_INIT:
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. If this is the first time that we see this
927 * driver at all, that's fine too.
929 eth_port->etp_osdep.etp_state= OEPS_IDLE;
930 break;
931 case OEPS_GETSTAT_SENT:
932 /* Set the OEPF_NEED_STAT to trigger a new request */
933 eth_port->etp_osdep.etp_flags |= OEPF_NEED_STAT;
934 eth_port->etp_osdep.etp_state= OEPS_IDLE;
935 break;
938 /* If there is a pending GETSTAT request then we have to create a
939 * new grant.
941 if (eth_port->etp_osdep.etp_flags & OEPF_NEED_STAT)
943 assert(eth_port->etp_osdep.etp_stat_gid != -1);
944 cpf_revoke(eth_port->etp_osdep.etp_stat_gid);
946 gid= cpf_grant_direct(eth_port->etp_osdep.etp_task,
947 (vir_bytes)eth_port->etp_osdep.etp_stat_buf,
948 sizeof(*eth_port->etp_osdep.etp_stat_buf), CPF_WRITE);
949 if (gid == -1)
951 ip_panic((
952 "eth_restart: cpf_grant_direct failed: %d\n",
953 errno));
955 eth_port->etp_osdep.etp_stat_gid= gid;
958 flags= eth_port->etp_osdep.etp_recvconf;
959 dl_flags= DL_NOMODE;
960 if (flags & NWEO_EN_BROAD)
961 dl_flags |= DL_BROAD_REQ;
962 if (flags & NWEO_EN_MULTI)
963 dl_flags |= DL_MULTI_REQ;
964 if (flags & NWEO_EN_PROMISC)
965 dl_flags |= DL_PROMISC_REQ;
966 mess.m_type= DL_CONF;
967 mess.DL_PORT= eth_port->etp_osdep.etp_port;
968 mess.DL_PROC= this_proc;
969 mess.DL_MODE= dl_flags;
971 compare(eth_port->etp_osdep.etp_state, ==, OEPS_IDLE);
972 r= asynsend(eth_port->etp_osdep.etp_task, &mess);
973 if (r<0)
975 printf(
976 "eth_restart: send to ethernet task %d failed: %d\n",
977 eth_port->etp_osdep.etp_task, r);
978 return;
980 eth_port->etp_osdep.etp_state= OEPS_CONF_SENT;
982 if (eth_port->etp_wr_pack)
984 bf_afree(eth_port->etp_wr_pack);
985 eth_port->etp_wr_pack= NULL;
986 eth_restart_write(eth_port);
988 if (eth_port->etp_rd_pack)
990 bf_afree(eth_port->etp_rd_pack);
991 eth_port->etp_rd_pack= NULL;
992 eth_port->etp_flags &= ~(EPF_READ_IP|EPF_READ_SP);
997 PRIVATE void send_getstat(eth_port)
998 eth_port_t *eth_port;
1000 int r;
1001 message mess;
1003 mess.m_type= DL_GETSTAT_S;
1004 mess.DL_PORT= eth_port->etp_osdep.etp_port;
1005 mess.DL_PROC= this_proc;
1006 mess.DL_GRANT= eth_port->etp_osdep.etp_stat_gid;
1008 assert(eth_port->etp_osdep.etp_state == OEPS_IDLE);
1010 r= asynsend(eth_port->etp_osdep.etp_task, &mess);
1011 eth_port->etp_osdep.etp_state= OEPS_GETSTAT_SENT;
1013 if (r != OK)
1014 ip_panic(( "eth_get_stat: asynsend failed: %d", r));
1018 * $PchId: mnx_eth.c,v 1.16 2005/06/28 14:24:37 philip Exp $