vm: util.S not used currently; leave it out.
[minix.git] / servers / inet / mnx_eth.c
bloba04253ebb53caa6982ac24d2ed13555a15ca0b1a
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,
35 endpoint_t endpoint) );
36 FORWARD _PROTOTYPE( void send_getstat, (eth_port_t *eth_port) );
38 PUBLIC void osdep_eth_init()
40 int i, j, r, rport;
41 struct eth_conf *ecp;
42 eth_port_t *eth_port, *rep;
43 cp_grant_id_t gid;
45 /* First initialize normal ethernet interfaces */
46 for (i= 0, ecp= eth_conf, eth_port= eth_port_table;
47 i<eth_conf_nr; i++, ecp++, eth_port++)
49 /* Set all grants to invalid */
50 for (j= 0; j<IOVEC_NR; j++)
51 eth_port->etp_osdep.etp_wr_iovec[j].iov_grant= -1;
52 eth_port->etp_osdep.etp_wr_vec_grant= -1;
53 for (j= 0; j<RD_IOVEC; j++)
54 eth_port->etp_osdep.etp_rd_iovec[j].iov_grant= -1;
55 eth_port->etp_osdep.etp_rd_vec_grant= -1;
57 eth_port->etp_osdep.etp_state= OEPS_INIT;
58 eth_port->etp_osdep.etp_flags= OEPF_EMPTY;
59 eth_port->etp_osdep.etp_stat_gid= -1;
60 eth_port->etp_osdep.etp_stat_buf= NULL;
62 if (eth_is_vlan(ecp))
63 continue;
65 /* Allocate grants */
66 for (j= 0; j<IOVEC_NR; j++)
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_iovec[j].iov_grant= gid;
76 if (cpf_getgrants(&gid, 1) != 1)
78 ip_panic((
79 "osdep_eth_init: cpf_getgrants failed: %d\n",
80 errno));
82 eth_port->etp_osdep.etp_wr_vec_grant= gid;
83 for (j= 0; j<RD_IOVEC; j++)
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_iovec[j].iov_grant= gid;
93 if (cpf_getgrants(&gid, 1) != 1)
95 ip_panic((
96 "osdep_eth_init: cpf_getgrants failed: %d\n",
97 errno));
99 eth_port->etp_osdep.etp_rd_vec_grant= gid;
101 eth_port->etp_osdep.etp_port= ecp->ec_port;
102 eth_port->etp_osdep.etp_task= ANY;
103 eth_port->etp_osdep.etp_recvconf= 0;
104 eth_port->etp_osdep.etp_send_ev= 0;
105 ev_init(&eth_port->etp_osdep.etp_recvev);
107 sr_add_minor(if2minor(ecp->ec_ifno, ETH_DEV_OFF),
108 i, eth_open, eth_close, eth_read,
109 eth_write, eth_ioctl, eth_cancel, eth_select);
111 eth_port->etp_flags |= EPF_ENABLED;
112 eth_port->etp_vlan= 0;
113 eth_port->etp_vlan_port= NULL;
114 eth_port->etp_wr_pack= 0;
115 eth_port->etp_rd_pack= 0;
118 /* And now come the VLANs */
119 for (i= 0, ecp= eth_conf, eth_port= eth_port_table;
120 i<eth_conf_nr; i++, ecp++, eth_port++)
122 if (!eth_is_vlan(ecp))
123 continue;
125 eth_port->etp_osdep.etp_port= ecp->ec_port;
126 eth_port->etp_osdep.etp_task= ANY;
127 ev_init(&eth_port->etp_osdep.etp_recvev);
129 rport= eth_port->etp_osdep.etp_port;
130 assert(rport >= 0 && rport < eth_conf_nr);
131 rep= &eth_port_table[rport];
132 if (!(rep->etp_flags & EPF_ENABLED))
134 printf(
135 "eth%d: underlying ethernet device %d not enabled",
136 i, rport);
137 continue;
139 if (rep->etp_vlan != 0)
141 printf(
142 "eth%d: underlying ethernet device %d is a VLAN",
143 i, rport);
144 continue;
147 if (rep->etp_flags & EPF_GOT_ADDR)
149 eth_port->etp_ethaddr= rep->etp_ethaddr;
150 printf("osdep_eth_init: setting EPF_GOT_ADDR\n");
151 eth_port->etp_flags |= EPF_GOT_ADDR;
154 sr_add_minor(if2minor(ecp->ec_ifno, ETH_DEV_OFF),
155 i, eth_open, eth_close, eth_read,
156 eth_write, eth_ioctl, eth_cancel, eth_select);
158 eth_port->etp_flags |= EPF_ENABLED;
159 eth_port->etp_vlan= ecp->ec_vlan;
160 eth_port->etp_vlan_port= rep;
161 assert(eth_port->etp_vlan != 0);
162 eth_port->etp_wr_pack= 0;
163 eth_port->etp_rd_pack= 0;
164 eth_reg_vlan(rep, eth_port);
168 PUBLIC void eth_write_port(eth_port, pack)
169 eth_port_t *eth_port;
170 acc_t *pack;
172 assert(!no_ethWritePort);
173 assert(!eth_port->etp_vlan);
175 assert(eth_port->etp_wr_pack == NULL);
176 eth_port->etp_wr_pack= pack;
178 if (eth_port->etp_osdep.etp_state != OEPS_IDLE)
180 eth_port->etp_osdep.etp_flags |= OEPF_NEED_SEND;
181 return;
185 eth_issue_send(eth_port);
188 #if 0
189 PRIVATE int notification_count;
190 #endif
192 PUBLIC void eth_rec(message *m)
194 int i, r, m_type, stat;
195 eth_port_t *loc_port, *vlan_port;
196 char *drivername;
197 struct eth_conf *ecp;
199 m_type= m->m_type;
200 if (m_type == DL_NAME_REPLY)
202 drivername= m->m3_ca1;
203 #if 0
204 printf("eth_rec: got name: %s\n", drivername);
206 notification_count= 0;
207 #endif
209 /* Re-init ethernet interfaces */
210 for (i= 0, ecp= eth_conf, loc_port= eth_port_table;
211 i<eth_conf_nr; i++, ecp++, loc_port++)
213 if (eth_is_vlan(ecp))
214 continue;
216 if (strcmp(ecp->ec_task, drivername) != 0)
218 /* Wrong driver */
219 continue;
221 eth_restart(loc_port, m->m_source);
223 return;
226 assert(m_type == DL_CONF_REPLY || m_type == DL_TASK_REPLY ||
227 m_type == DL_STAT_REPLY);
229 for (i=0, loc_port= eth_port_table; i<eth_conf_nr; i++, loc_port++)
231 if (loc_port->etp_osdep.etp_port == m->DL_PORT &&
232 loc_port->etp_osdep.etp_task == m->m_source)
233 break;
235 if (i >= eth_conf_nr)
237 printf("eth_rec: bad port %d in message type 0x%x from %d\n",
238 m->DL_PORT, m_type, m->m_source);
239 return;
242 if (loc_port->etp_osdep.etp_state == OEPS_CONF_SENT)
244 if (m_type == DL_TASK_REPLY)
246 stat= m->DL_STAT & 0xffff;
248 if (stat & DL_PACK_SEND)
249 write_int(loc_port);
250 if (stat & DL_PACK_RECV)
251 read_int(loc_port, m->DL_COUNT);
252 return;
255 if (m_type != DL_CONF_REPLY)
257 printf(
258 "eth_rec: got bad message type 0x%x from %d in CONF state\n",
259 m_type, m->m_source);
260 return;
263 r= m->m3_i1;
264 if (r == ENXIO)
266 printf(
267 "eth_rec(conf_reply): no ethernet device at task=%d,port=%d\n",
268 loc_port->etp_osdep.etp_task,
269 loc_port->etp_osdep.etp_port);
270 return;
272 if (r < 0)
274 ip_panic(("eth_rec: DL_INIT returned error %d\n", r));
275 return;
278 loc_port->etp_osdep.etp_flags &= ~OEPF_NEED_CONF;
279 loc_port->etp_osdep.etp_state= OEPS_IDLE;
280 loc_port->etp_flags |= EPF_ENABLED;
282 loc_port->etp_ethaddr= *(ether_addr_t *)m->m3_ca1;
283 if (!(loc_port->etp_flags & EPF_GOT_ADDR))
285 loc_port->etp_flags |= EPF_GOT_ADDR;
286 #if 0
287 printf("eth_rec: calling eth_restart_ioctl\n");
288 #endif
289 eth_restart_ioctl(loc_port);
291 /* Also update any VLANs on this device */
292 for (i=0, vlan_port= eth_port_table; i<eth_conf_nr;
293 i++, vlan_port++)
295 if (!(vlan_port->etp_flags & EPF_ENABLED))
296 continue;
297 if (vlan_port->etp_vlan_port != loc_port)
298 continue;
300 vlan_port->etp_ethaddr= loc_port->etp_ethaddr;
301 vlan_port->etp_flags |= EPF_GOT_ADDR;
302 eth_restart_ioctl(vlan_port);
305 if (!(loc_port->etp_flags & EPF_READ_IP))
306 setup_read (loc_port);
308 #if 0
309 if (loc_port->etp_osdep.etp_flags & OEPF_NEED_SEND)
311 printf("eth_rec(conf): OEPF_NEED_SEND is set\n");
313 if (loc_port->etp_osdep.etp_flags & OEPF_NEED_RECV)
315 printf("eth_rec(conf): OEPF_NEED_RECV is set\n");
317 if (loc_port->etp_osdep.etp_flags & OEPF_NEED_STAT)
319 printf("eth_rec(conf): OEPF_NEED_STAT is set\n");
321 #endif
323 return;
325 if (loc_port->etp_osdep.etp_state == OEPS_GETSTAT_SENT)
327 if (m_type != DL_STAT_REPLY)
329 printf(
330 "eth_rec: got bad message type 0x%x from %d in GETSTAT state\n",
331 m_type, m->m_source);
332 return;
335 r= m->DL_STAT;
336 if (r != OK)
338 ip_warning(("eth_rec: DL_STAT returned error %d\n",
339 r));
340 return;
343 loc_port->etp_osdep.etp_state= OEPS_IDLE;
344 loc_port->etp_osdep.etp_flags &= ~OEPF_NEED_STAT;
346 assert(loc_port->etp_osdep.etp_stat_gid != -1);
347 cpf_revoke(loc_port->etp_osdep.etp_stat_gid);
348 loc_port->etp_osdep.etp_stat_gid= -1;
349 loc_port->etp_osdep.etp_stat_buf= NULL;
351 /* Finish ioctl */
352 assert(loc_port->etp_flags & EPF_GOT_ADDR);
353 eth_restart_ioctl(loc_port);
355 #if 0
356 if (loc_port->etp_osdep.etp_flags & OEPF_NEED_SEND)
358 printf("eth_rec(stat): OEPF_NEED_SEND is set\n");
360 if (loc_port->etp_osdep.etp_flags & OEPF_NEED_RECV)
362 printf("eth_rec(stat): OEPF_NEED_RECV is set\n");
364 if (loc_port->etp_osdep.etp_flags & OEPF_NEED_CONF)
366 printf("eth_rec(stat): OEPF_NEED_CONF is set\n");
368 #endif
370 #if 0
371 if (loc_port->etp_osdep.etp_state == OEPS_IDLE &&
372 (loc_port->etp_osdep.etp_flags & OEPF_NEED_CONF))
374 eth_set_rec_conf(loc_port,
375 loc_port->etp_osdep.etp_recvconf);
377 #endif
378 return;
380 assert(loc_port->etp_osdep.etp_state == OEPS_IDLE ||
381 loc_port->etp_osdep.etp_state == OEPS_RECV_SENT ||
382 loc_port->etp_osdep.etp_state == OEPS_SEND_SENT ||
383 (printf("etp_state = %d\n", loc_port->etp_osdep.etp_state), 0));
384 loc_port->etp_osdep.etp_state= OEPS_IDLE;
386 #if 0 /* Ethernet driver is not trusted */
387 set_time (m->DL_CLCK);
388 #endif
390 stat= m->DL_STAT & 0xffff;
392 #if 0
393 if (!(stat & (DL_PACK_SEND|DL_PACK_RECV)))
394 printf("eth_rec: neither DL_PACK_SEND nor DL_PACK_RECV\n");
395 #endif
396 if (stat & DL_PACK_SEND)
397 write_int(loc_port);
398 if (stat & DL_PACK_RECV)
400 if (recv_debug)
402 printf("eth_rec: eth%d got DL_PACK_RECV\n",
403 m->DL_PORT);
405 read_int(loc_port, m->DL_COUNT);
408 if (loc_port->etp_osdep.etp_state == OEPS_IDLE &&
409 loc_port->etp_osdep.etp_flags & OEPF_NEED_SEND)
411 loc_port->etp_osdep.etp_flags &= ~OEPF_NEED_SEND;
412 if (loc_port->etp_wr_pack)
413 eth_issue_send(loc_port);
415 if (loc_port->etp_osdep.etp_state == OEPS_IDLE &&
416 (loc_port->etp_osdep.etp_flags & OEPF_NEED_RECV))
418 loc_port->etp_osdep.etp_flags &= ~OEPF_NEED_RECV;
419 if (!(loc_port->etp_flags & EPF_READ_IP))
420 setup_read (loc_port);
422 if (loc_port->etp_osdep.etp_flags & OEPF_NEED_CONF)
424 #if 0
425 printf("eth_rec: OEPF_NEED_CONF is set\n");
426 #endif
428 if (loc_port->etp_osdep.etp_state == OEPS_IDLE &&
429 (loc_port->etp_osdep.etp_flags & OEPF_NEED_STAT))
431 send_getstat(loc_port);
435 PUBLIC void eth_check_driver(endpoint_t endpoint)
437 int r;
438 message m;
440 m.m_type = DL_GETNAME;
441 r= asynsend(endpoint, &m);
442 if (r != OK)
444 printf("eth_check_driver: asynsend to %d failed: %d\n",
445 endpoint, r);
446 return;
450 PUBLIC int eth_get_stat(eth_port, eth_stat)
451 eth_port_t *eth_port;
452 eth_stat_t *eth_stat;
454 cp_grant_id_t gid;
456 assert(!eth_port->etp_vlan);
458 if (eth_port->etp_osdep.etp_flags & OEPF_NEED_STAT)
459 ip_panic(( "eth_get_stat: getstat already in progress" ));
461 gid= cpf_grant_direct(eth_port->etp_osdep.etp_task,
462 (vir_bytes)eth_stat, sizeof(*eth_stat), CPF_WRITE);
463 if (gid == -1)
465 ip_panic(( "eth_get_stat: cpf_grant_direct failed: %d\n",
466 errno));
468 assert(eth_port->etp_osdep.etp_stat_gid == -1);
469 eth_port->etp_osdep.etp_stat_gid= gid;
470 eth_port->etp_osdep.etp_stat_buf= eth_stat;
472 if (eth_port->etp_osdep.etp_state != OEPS_IDLE)
474 eth_port->etp_osdep.etp_flags |= OEPF_NEED_STAT;
475 return SUSPEND;
478 send_getstat(eth_port);
480 return SUSPEND;
483 PUBLIC void eth_set_rec_conf (eth_port, flags)
484 eth_port_t *eth_port;
485 u32_t flags;
487 int r;
488 unsigned dl_flags, mask;
489 message mess;
491 assert(!eth_port->etp_vlan);
493 if (!(eth_port->etp_flags & EPF_GOT_ADDR))
495 /* We have never seen the device. */
496 #if 0
497 printf("eth_set_rec_conf: waiting for device to appear\n");
498 #endif
499 return;
502 if (eth_port->etp_osdep.etp_state != OEPS_IDLE)
504 printf(
505 "eth_set_rec_conf: setting OEPF_NEED_CONF, state = %d\n",
506 eth_port->etp_osdep.etp_state);
507 eth_port->etp_osdep.etp_flags |= OEPF_NEED_CONF;
508 return;
511 mask = NWEO_EN_BROAD | NWEO_EN_MULTI | NWEO_EN_PROMISC;
512 if ((eth_port->etp_osdep.etp_recvconf & mask) == (flags & mask))
514 /* No change for the driver, so don't send an update */
515 return;
518 eth_port->etp_osdep.etp_recvconf= flags;
519 dl_flags= DL_NOMODE;
520 if (flags & NWEO_EN_BROAD)
521 dl_flags |= DL_BROAD_REQ;
522 if (flags & NWEO_EN_MULTI)
523 dl_flags |= DL_MULTI_REQ;
524 if (flags & NWEO_EN_PROMISC)
525 dl_flags |= DL_PROMISC_REQ;
527 mess.m_type= DL_CONF;
528 mess.DL_PORT= eth_port->etp_osdep.etp_port;
529 mess.DL_PROC= this_proc;
530 mess.DL_MODE= dl_flags;
532 assert(eth_port->etp_osdep.etp_state == OEPS_IDLE);
533 r= asynsend(eth_port->etp_osdep.etp_task, &mess);
534 eth_port->etp_osdep.etp_state= OEPS_CONF_SENT;
536 if (r < 0)
538 printf("eth_set_rec_conf: asynsend to %d failed: %d\n",
539 eth_port->etp_osdep.etp_task, r);
540 return;
544 PRIVATE void eth_issue_send(eth_port)
545 eth_port_t *eth_port;
547 int i, r, pack_size;
548 acc_t *pack, *pack_ptr;
549 iovec_s_t *iovec;
550 message m;
552 iovec= eth_port->etp_osdep.etp_wr_iovec;
553 pack= eth_port->etp_wr_pack;
554 pack_size= 0;
555 for (i=0, pack_ptr= pack; i<IOVEC_NR && pack_ptr; i++,
556 pack_ptr= pack_ptr->acc_next)
558 r= cpf_setgrant_direct(iovec[i].iov_grant,
559 eth_port->etp_osdep.etp_task,
560 (vir_bytes)ptr2acc_data(pack_ptr),
561 (vir_bytes)pack_ptr->acc_length,
562 CPF_READ);
563 if (r != 0)
565 ip_panic((
566 "eth_write_port: cpf_setgrant_direct failed: %d\n",
567 errno));
569 pack_size += iovec[i].iov_size= pack_ptr->acc_length;
571 if (i>= IOVEC_NR)
573 pack= bf_pack(pack); /* packet is too fragmented */
574 eth_port->etp_wr_pack= pack;
575 pack_size= 0;
576 for (i=0, pack_ptr= pack; i<IOVEC_NR && pack_ptr;
577 i++, pack_ptr= pack_ptr->acc_next)
579 r= cpf_setgrant_direct(iovec[i].iov_grant,
580 eth_port->etp_osdep.etp_task,
581 (vir_bytes)ptr2acc_data(pack_ptr),
582 (vir_bytes)pack_ptr->acc_length,
583 CPF_READ);
584 if (r != 0)
586 ip_panic((
587 "eth_write_port: cpf_setgrant_direct failed: %d\n",
588 errno));
590 pack_size += iovec[i].iov_size= pack_ptr->acc_length;
593 assert (i< IOVEC_NR);
594 assert (pack_size >= ETH_MIN_PACK_SIZE);
596 r= cpf_setgrant_direct(eth_port->etp_osdep.etp_wr_vec_grant,
597 eth_port->etp_osdep.etp_task,
598 (vir_bytes)iovec,
599 (vir_bytes)(i * sizeof(iovec[0])),
600 CPF_READ);
601 if (r != 0)
603 ip_panic((
604 "eth_write_port: cpf_setgrant_direct failed: %d\n",
605 errno));
607 m.DL_COUNT= i;
608 m.DL_GRANT= eth_port->etp_osdep.etp_wr_vec_grant;
609 m.m_type= DL_WRITEV_S;
611 m.DL_PORT= eth_port->etp_osdep.etp_port;
612 m.DL_PROC= this_proc;
613 m.DL_MODE= DL_NOMODE;
615 assert(eth_port->etp_osdep.etp_state == OEPS_IDLE);
616 r= asynsend(eth_port->etp_osdep.etp_task, &m);
618 if (r < 0)
620 printf("eth_issue_send: send to %d failed: %d\n",
621 eth_port->etp_osdep.etp_task, r);
622 return;
624 eth_port->etp_osdep.etp_state= OEPS_SEND_SENT;
627 PRIVATE void write_int(eth_port_t *eth_port)
629 acc_t *pack;
630 int multicast;
631 u8_t *eth_dst_ptr;
633 pack= eth_port->etp_wr_pack;
634 if (pack == NULL)
636 printf("write_int: strange no packet on eth port %d\n",
637 eth_port-eth_port_table);
638 eth_restart_write(eth_port);
639 return;
642 eth_port->etp_wr_pack= NULL;
644 eth_dst_ptr= (u8_t *)ptr2acc_data(pack);
645 multicast= (*eth_dst_ptr & 1); /* low order bit indicates multicast */
646 if (multicast || (eth_port->etp_osdep.etp_recvconf & NWEO_EN_PROMISC))
648 assert(!no_ethWritePort);
649 no_ethWritePort= 1;
650 eth_arrive(eth_port, pack, bf_bufsize(pack));
651 assert(no_ethWritePort);
652 no_ethWritePort= 0;
654 else
655 bf_afree(pack);
657 eth_restart_write(eth_port);
660 PRIVATE void read_int(eth_port, count)
661 eth_port_t *eth_port;
662 int count;
664 acc_t *pack, *cut_pack;
666 pack= eth_port->etp_rd_pack;
667 eth_port->etp_rd_pack= NULL;
669 if (count < ETH_MIN_PACK_SIZE)
671 printf("mnx_eth`read_int: packet size too small (%d)\n",
672 count);
673 bf_afree(pack);
675 else if (count > ETH_MAX_PACK_SIZE_TAGGED)
677 printf("mnx_eth`read_int: packet size too big (%d)\n",
678 count);
679 bf_afree(pack);
681 else
683 cut_pack= bf_cut(pack, 0, count);
684 bf_afree(pack);
686 assert(!no_ethWritePort);
687 no_ethWritePort= 1;
688 eth_arrive(eth_port, cut_pack, count);
689 assert(no_ethWritePort);
690 no_ethWritePort= 0;
693 eth_port->etp_flags &= ~(EPF_READ_IP|EPF_READ_SP);
694 setup_read(eth_port);
697 PRIVATE void setup_read(eth_port)
698 eth_port_t *eth_port;
700 acc_t *pack, *pack_ptr;
701 message mess1;
702 iovec_s_t *iovec;
703 int i, r;
705 assert(!eth_port->etp_vlan);
706 assert(!(eth_port->etp_flags & (EPF_READ_IP|EPF_READ_SP)));
708 if (eth_port->etp_osdep.etp_state != OEPS_IDLE)
710 eth_port->etp_osdep.etp_flags |= OEPF_NEED_RECV;
712 return;
715 assert (!eth_port->etp_rd_pack);
717 iovec= eth_port->etp_osdep.etp_rd_iovec;
718 pack= bf_memreq (ETH_MAX_PACK_SIZE_TAGGED);
720 for (i=0, pack_ptr= pack; i<RD_IOVEC && pack_ptr;
721 i++, pack_ptr= pack_ptr->acc_next)
723 r= cpf_setgrant_direct(iovec[i].iov_grant,
724 eth_port->etp_osdep.etp_task,
725 (vir_bytes)ptr2acc_data(pack_ptr),
726 (vir_bytes)pack_ptr->acc_length,
727 CPF_WRITE);
728 if (r != 0)
730 ip_panic((
731 "mnx_eth`setup_read: cpf_setgrant_direct failed: %d\n",
732 errno));
734 iovec[i].iov_size= (vir_bytes)pack_ptr->acc_length;
736 assert (!pack_ptr);
738 r= cpf_setgrant_direct(eth_port->etp_osdep.etp_rd_vec_grant,
739 eth_port->etp_osdep.etp_task,
740 (vir_bytes)iovec,
741 (vir_bytes)(i * sizeof(iovec[0])),
742 CPF_READ);
743 if (r != 0)
745 ip_panic((
746 "mnx_eth`setup_read: cpf_setgrant_direct failed: %d\n",
747 errno));
750 mess1.m_type= DL_READV_S;
751 mess1.DL_PORT= eth_port->etp_osdep.etp_port;
752 mess1.DL_PROC= this_proc;
753 mess1.DL_COUNT= i;
754 mess1.DL_GRANT= eth_port->etp_osdep.etp_rd_vec_grant;
756 assert(eth_port->etp_osdep.etp_state == OEPS_IDLE);
758 r= asynsend(eth_port->etp_osdep.etp_task, &mess1);
759 eth_port->etp_osdep.etp_state= OEPS_RECV_SENT;
761 if (r < 0)
763 printf(
764 "mnx_eth`setup_read: asynsend to %d failed: %d\n",
765 eth_port->etp_osdep.etp_task, r);
767 eth_port->etp_rd_pack= pack;
768 eth_port->etp_flags |= EPF_READ_IP;
769 eth_port->etp_flags |= EPF_READ_SP;
772 PRIVATE void eth_recvev(ev, ev_arg)
773 event_t *ev;
774 ev_arg_t ev_arg;
776 eth_port_t *eth_port;
777 message *m_ptr;
779 eth_port= ev_arg.ev_ptr;
780 assert(ev == &eth_port->etp_osdep.etp_recvev);
781 m_ptr= &eth_port->etp_osdep.etp_recvrepl;
783 assert(m_ptr->m_type == DL_TASK_REPLY);
784 assert(eth_port->etp_osdep.etp_port == m_ptr->DL_PORT &&
785 eth_port->etp_osdep.etp_task == m_ptr->m_source);
787 assert(m_ptr->DL_STAT & DL_PACK_RECV);
788 m_ptr->DL_STAT &= ~DL_PACK_RECV;
790 if (recv_debug)
792 printf("eth_recvev: eth%d got DL_PACK_RECV\n", m_ptr->DL_PORT);
795 read_int(eth_port, m_ptr->DL_COUNT);
798 PRIVATE void eth_sendev(ev, ev_arg)
799 event_t *ev;
800 ev_arg_t ev_arg;
802 eth_port_t *eth_port;
803 message *m_ptr;
805 eth_port= ev_arg.ev_ptr;
806 assert(ev == &eth_port->etp_sendev);
807 m_ptr= &eth_port->etp_osdep.etp_sendrepl;
809 assert (m_ptr->m_type == DL_TASK_REPLY);
810 assert(eth_port->etp_osdep.etp_port == m_ptr->DL_PORT &&
811 eth_port->etp_osdep.etp_task == m_ptr->m_source);
813 assert(m_ptr->DL_STAT & DL_PACK_SEND);
814 m_ptr->DL_STAT &= ~DL_PACK_SEND;
815 assert(eth_port->etp_osdep.etp_send_ev);
816 eth_port->etp_osdep.etp_send_ev= 0;
818 /* packet is sent */
819 write_int(eth_port);
822 PRIVATE eth_port_t *find_port(m)
823 message *m;
825 eth_port_t *loc_port;
826 int i;
828 for (i=0, loc_port= eth_port_table; i<eth_conf_nr; i++, loc_port++)
830 if (loc_port->etp_osdep.etp_port == m->DL_PORT &&
831 loc_port->etp_osdep.etp_task == m->m_source)
832 break;
834 assert (i<eth_conf_nr);
835 return loc_port;
838 static void eth_restart(eth_port_t *eth_port, endpoint_t endpoint)
840 int r;
841 unsigned flags, dl_flags;
842 cp_grant_id_t gid;
843 message mess;
845 eth_port->etp_osdep.etp_task= endpoint;
847 switch(eth_port->etp_osdep.etp_state)
849 case OEPS_INIT:
850 case OEPS_CONF_SENT:
851 case OEPS_RECV_SENT:
852 case OEPS_SEND_SENT:
853 /* We can safely ignore the pending CONF, RECV, and SEND
854 * requests. If this is the first time that we see this
855 * driver at all, that's fine too.
857 eth_port->etp_osdep.etp_state= OEPS_IDLE;
858 break;
859 case OEPS_GETSTAT_SENT:
860 /* Set the OEPF_NEED_STAT to trigger a new request */
861 eth_port->etp_osdep.etp_flags |= OEPF_NEED_STAT;
862 eth_port->etp_osdep.etp_state= OEPS_IDLE;
863 break;
866 /* If there is a pending GETSTAT request then we have to create a
867 * new grant.
869 if (eth_port->etp_osdep.etp_flags & OEPF_NEED_STAT)
871 assert(eth_port->etp_osdep.etp_stat_gid != -1);
872 cpf_revoke(eth_port->etp_osdep.etp_stat_gid);
874 gid= cpf_grant_direct(eth_port->etp_osdep.etp_task,
875 (vir_bytes)eth_port->etp_osdep.etp_stat_buf,
876 sizeof(*eth_port->etp_osdep.etp_stat_buf), CPF_WRITE);
877 if (gid == -1)
879 ip_panic((
880 "eth_restart: cpf_grant_direct failed: %d\n",
881 errno));
883 eth_port->etp_osdep.etp_stat_gid= gid;
886 flags= eth_port->etp_osdep.etp_recvconf;
887 dl_flags= DL_NOMODE;
888 if (flags & NWEO_EN_BROAD)
889 dl_flags |= DL_BROAD_REQ;
890 if (flags & NWEO_EN_MULTI)
891 dl_flags |= DL_MULTI_REQ;
892 if (flags & NWEO_EN_PROMISC)
893 dl_flags |= DL_PROMISC_REQ;
894 mess.m_type= DL_CONF;
895 mess.DL_PORT= eth_port->etp_osdep.etp_port;
896 mess.DL_PROC= this_proc;
897 mess.DL_MODE= dl_flags;
899 compare(eth_port->etp_osdep.etp_state, ==, OEPS_IDLE);
900 r= asynsend(eth_port->etp_osdep.etp_task, &mess);
901 if (r<0)
903 printf(
904 "eth_restart: send to ethernet task %d failed: %d\n",
905 eth_port->etp_osdep.etp_task, r);
906 return;
908 eth_port->etp_osdep.etp_state= OEPS_CONF_SENT;
910 if (eth_port->etp_wr_pack)
912 bf_afree(eth_port->etp_wr_pack);
913 eth_port->etp_wr_pack= NULL;
914 eth_restart_write(eth_port);
916 if (eth_port->etp_rd_pack)
918 bf_afree(eth_port->etp_rd_pack);
919 eth_port->etp_rd_pack= NULL;
920 eth_port->etp_flags &= ~(EPF_READ_IP|EPF_READ_SP);
925 PRIVATE void send_getstat(eth_port)
926 eth_port_t *eth_port;
928 int r;
929 message mess;
931 mess.m_type= DL_GETSTAT_S;
932 mess.DL_PORT= eth_port->etp_osdep.etp_port;
933 mess.DL_PROC= this_proc;
934 mess.DL_GRANT= eth_port->etp_osdep.etp_stat_gid;
936 assert(eth_port->etp_osdep.etp_state == OEPS_IDLE);
938 r= asynsend(eth_port->etp_osdep.etp_task, &mess);
939 eth_port->etp_osdep.etp_state= OEPS_GETSTAT_SENT;
941 if (r != OK)
942 ip_panic(( "eth_get_stat: asynsend failed: %d", r));
946 * $PchId: mnx_eth.c,v 1.16 2005/06/28 14:24:37 philip Exp $