source: trunk/minix/servers/inet/mnx_eth.c@ 15

Last change on this file since 15 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 19.1 KB
RevLine 
[9]1/*
2inet/mnx_eth.c
3
4Created: Jan 2, 1992 by Philip Homburg
5
6Copyright 1995 Philip Homburg
7*/
8
9#include "inet.h"
10#include "proto.h"
11#include "osdep_eth.h"
12#include "generic/type.h"
13
14#include "generic/assert.h"
15#include "generic/buf.h"
16#include "generic/clock.h"
17#include "generic/eth.h"
18#include "generic/eth_int.h"
19#include "generic/sr.h"
20
21THIS_FILE
22
23static int recv_debug= 0;
24
25FORWARD _PROTOTYPE( void setup_read, (eth_port_t *eth_port) );
26FORWARD _PROTOTYPE( void read_int, (eth_port_t *eth_port, int count) );
27FORWARD _PROTOTYPE( void write_int, (eth_port_t *eth_port) );
28FORWARD _PROTOTYPE( void eth_recvev, (event_t *ev, ev_arg_t ev_arg) );
29FORWARD _PROTOTYPE( void eth_sendev, (event_t *ev, ev_arg_t ev_arg) );
30FORWARD _PROTOTYPE( eth_port_t *find_port, (message *m) );
31FORWARD _PROTOTYPE( void eth_restart, (eth_port_t *eth_port, int tasknr) );
32
33PUBLIC void osdep_eth_init()
34{
35 int i, r, tasknr, rport;
36 struct eth_conf *ecp;
37 eth_port_t *eth_port, *rep;
38 message mess;
39
40 /* First initialize normal ethernet interfaces */
41 for (i= 0, ecp= eth_conf, eth_port= eth_port_table;
42 i<eth_conf_nr; i++, ecp++, eth_port++)
43 {
44 if (eth_is_vlan(ecp))
45 continue;
46#ifdef __minix_vmd
47 r= sys_findproc(ecp->ec_task, &tasknr, 0);
48#else /* Minix 3 */
49 r = _pm_findproc(ecp->ec_task, &tasknr);
50#endif
51 if (r != OK)
52 {
53 /* Eventually, we expect ethernet drivers to be
54 * started after INET. So we always end up here. And
55 * the findproc can be removed.
56 */
57 printf("eth%d: unable to find task %s: %d\n",
58 i, ecp->ec_task, r);
59 tasknr= ANY;
60 }
61
62 eth_port->etp_osdep.etp_port= ecp->ec_port;
63 eth_port->etp_osdep.etp_task= tasknr;
64 ev_init(&eth_port->etp_osdep.etp_recvev);
65
66 mess.m_type= DL_INIT;
67 mess.DL_PORT= eth_port->etp_osdep.etp_port;
68 mess.DL_PROC= this_proc;
69 mess.DL_MODE= DL_NOMODE;
70
71 if (tasknr == ANY)
72 r= ENXIO;
73 else
74 {
75 r= send(eth_port->etp_osdep.etp_task, &mess);
76 if (r<0)
77 {
78 printf(
79 "osdep_eth_init: unable to send to ethernet task, error= %d\n",
80 r);
81 }
82 }
83
84 if (r == OK)
85 {
86 r= receive(eth_port->etp_osdep.etp_task, &mess);
87 if (r<0)
88 {
89 printf(
90 "osdep_eth_init: unable to receive from ethernet task, error= %d\n",
91 r);
92 }
93 }
94
95 if (r == OK)
96 {
97 r= mess.m3_i1;
98 if (r == ENXIO)
99 {
100 printf(
101 "osdep_eth_init: no ethernet device at task=%d,port=%d\n",
102 eth_port->etp_osdep.etp_task,
103 eth_port->etp_osdep.etp_port);
104 }
105 else if (r < 0)
106 {
107 ip_panic((
108 "osdep_eth_init: DL_INIT returned error %d\n",
109 r));
110 }
111 else if (mess.m3_i1 != eth_port->etp_osdep.etp_port)
112 {
113 ip_panic((
114 "osdep_eth_init: got reply for wrong port (got %d, expected %d)\n",
115 mess.m3_i1,
116 eth_port->etp_osdep.etp_port));
117 }
118 }
119
120 sr_add_minor(if2minor(ecp->ec_ifno, ETH_DEV_OFF),
121 i, eth_open, eth_close, eth_read,
122 eth_write, eth_ioctl, eth_cancel, eth_select);
123
124 eth_port->etp_flags |= EPF_ENABLED;
125 eth_port->etp_vlan= 0;
126 eth_port->etp_vlan_port= NULL;
127 eth_port->etp_wr_pack= 0;
128 eth_port->etp_rd_pack= 0;
129 if (r == OK)
130 {
131 eth_port->etp_ethaddr= *(ether_addr_t *)mess.m3_ca1;
132 eth_port->etp_flags |= EPF_GOT_ADDR;
133 setup_read (eth_port);
134 }
135 }
136
137 /* And now come the VLANs */
138 for (i= 0, ecp= eth_conf, eth_port= eth_port_table;
139 i<eth_conf_nr; i++, ecp++, eth_port++)
140 {
141 if (!eth_is_vlan(ecp))
142 continue;
143
144 eth_port->etp_osdep.etp_port= ecp->ec_port;
145 eth_port->etp_osdep.etp_task= ANY;
146 ev_init(&eth_port->etp_osdep.etp_recvev);
147
148 rport= eth_port->etp_osdep.etp_port;
149 assert(rport >= 0 && rport < eth_conf_nr);
150 rep= &eth_port_table[rport];
151 if (!(rep->etp_flags & EPF_ENABLED))
152 {
153 printf(
154 "eth%d: underlying ethernet device %d not enabled",
155 i, rport);
156 continue;
157 }
158 if (rep->etp_vlan != 0)
159 {
160 printf(
161 "eth%d: underlying ethernet device %d is a VLAN",
162 i, rport);
163 continue;
164 }
165
166 if (rep->etp_flags & EPF_GOT_ADDR)
167 {
168 eth_port->etp_ethaddr= rep->etp_ethaddr;
169 eth_port->etp_flags |= EPF_GOT_ADDR;
170 }
171
172 sr_add_minor(if2minor(ecp->ec_ifno, ETH_DEV_OFF),
173 i, eth_open, eth_close, eth_read,
174 eth_write, eth_ioctl, eth_cancel, eth_select);
175
176 eth_port->etp_flags |= EPF_ENABLED;
177 eth_port->etp_vlan= ecp->ec_vlan;
178 eth_port->etp_vlan_port= rep;
179 assert(eth_port->etp_vlan != 0);
180 eth_port->etp_wr_pack= 0;
181 eth_port->etp_rd_pack= 0;
182 eth_reg_vlan(rep, eth_port);
183 }
184}
185
186PUBLIC void eth_write_port(eth_port, pack)
187eth_port_t *eth_port;
188acc_t *pack;
189{
190 eth_port_t *loc_port;
191 message mess1, block_msg;
192 int i, pack_size;
193 acc_t *pack_ptr;
194 iovec_t *iovec;
195 u8_t *eth_dst_ptr;
196 int multicast, r;
197 ev_arg_t ev_arg;
198
199 assert(!no_ethWritePort);
200 assert(!eth_port->etp_vlan);
201
202 assert(eth_port->etp_wr_pack == NULL);
203 eth_port->etp_wr_pack= pack;
204
205 iovec= eth_port->etp_osdep.etp_wr_iovec;
206 pack_size= 0;
207 for (i=0, pack_ptr= pack; i<IOVEC_NR && pack_ptr; i++,
208 pack_ptr= pack_ptr->acc_next)
209 {
210 iovec[i].iov_addr= (vir_bytes)ptr2acc_data(pack_ptr);
211 pack_size += iovec[i].iov_size= pack_ptr->acc_length;
212 }
213 if (i>= IOVEC_NR)
214 {
215 pack= bf_pack(pack); /* packet is too fragmented */
216 eth_port->etp_wr_pack= pack;
217 pack_size= 0;
218 for (i=0, pack_ptr= pack; i<IOVEC_NR && pack_ptr;
219 i++, pack_ptr= pack_ptr->acc_next)
220 {
221 iovec[i].iov_addr= (vir_bytes)ptr2acc_data(pack_ptr);
222 pack_size += iovec[i].iov_size= pack_ptr->acc_length;
223 }
224 }
225 assert (i< IOVEC_NR);
226 assert (pack_size >= ETH_MIN_PACK_SIZE);
227
228 if (i == 1)
229 {
230 /* simple packets can be sent using DL_WRITE instead of
231 * DL_WRITEV.
232 */
233 mess1.DL_COUNT= iovec[0].iov_size;
234 mess1.DL_ADDR= (char *)iovec[0].iov_addr;
235 mess1.m_type= DL_WRITE;
236 }
237 else
238 {
239 mess1.DL_COUNT= i;
240 mess1.DL_ADDR= (char *)iovec;
241 mess1.m_type= DL_WRITEV;
242 }
243 mess1.DL_PORT= eth_port->etp_osdep.etp_port;
244 mess1.DL_PROC= this_proc;
245 mess1.DL_MODE= DL_NOMODE;
246
247 for (;;)
248 {
249 r= sendrec(eth_port->etp_osdep.etp_task, &mess1);
250 if (r != ELOCKED)
251 break;
252
253 /* ethernet task is sending to this task, I hope */
254 r= receive(eth_port->etp_osdep.etp_task, &block_msg);
255 if (r < 0)
256 ip_panic(("unable to receive"));
257
258 loc_port= eth_port;
259 if (loc_port->etp_osdep.etp_port != block_msg.DL_PORT ||
260 loc_port->etp_osdep.etp_task != block_msg.m_source)
261 {
262 loc_port= find_port(&block_msg);
263 }
264 assert(block_msg.DL_STAT & (DL_PACK_SEND|DL_PACK_RECV));
265 if (block_msg.DL_STAT & DL_PACK_SEND)
266 {
267 assert(loc_port != eth_port);
268 loc_port->etp_osdep.etp_sendrepl= block_msg;
269 ev_arg.ev_ptr= loc_port;
270 ev_enqueue(&loc_port->etp_sendev, eth_sendev, ev_arg);
271 }
272 if (block_msg.DL_STAT & DL_PACK_RECV)
273 {
274 if (recv_debug)
275 {
276 printf(
277 "eth_write_port(block_msg): eth%d got DL_PACK_RECV\n",
278 loc_port-eth_port_table);
279 }
280 loc_port->etp_osdep.etp_recvrepl= block_msg;
281 ev_arg.ev_ptr= loc_port;
282 ev_enqueue(&loc_port->etp_osdep.etp_recvev,
283 eth_recvev, ev_arg);
284 }
285 }
286
287 if (r < 0)
288 {
289 printf("eth_write_port: sendrec to %d failed: %d\n",
290 eth_port->etp_osdep.etp_task, r);
291 return;
292 }
293
294 assert(mess1.m_type == DL_TASK_REPLY &&
295 mess1.DL_PORT == eth_port->etp_osdep.etp_port &&
296 mess1.DL_PROC == this_proc);
297 assert((mess1.DL_STAT >> 16) == OK);
298
299 if (mess1.DL_STAT & DL_PACK_RECV)
300 {
301 if (recv_debug)
302 {
303 printf(
304 "eth_write_port(mess1): eth%d got DL_PACK_RECV\n",
305 mess1.DL_PORT);
306 }
307 eth_port->etp_osdep.etp_recvrepl= mess1;
308 ev_arg.ev_ptr= eth_port;
309 ev_enqueue(&eth_port->etp_osdep.etp_recvev, eth_recvev,
310 ev_arg);
311 }
312 if (!(mess1.DL_STAT & DL_PACK_SEND))
313 {
314 /* Packet is not yet sent. */
315 return;
316 }
317
318 /* If the port is in promiscuous mode or the packet is
319 * broad- or multicast, enqueue the reply packet.
320 */
321 eth_dst_ptr= (u8_t *)ptr2acc_data(pack);
322 multicast= (*eth_dst_ptr & 1); /* low order bit indicates multicast */
323 if (multicast || (eth_port->etp_osdep.etp_recvconf & NWEO_EN_PROMISC))
324 {
325 eth_port->etp_osdep.etp_sendrepl= mess1;
326 ev_arg.ev_ptr= eth_port;
327 ev_enqueue(&eth_port->etp_sendev, eth_sendev, ev_arg);
328
329 /* Pretend that we didn't get a reply. */
330 return;
331 }
332
333 /* packet is sent */
334 bf_afree(eth_port->etp_wr_pack);
335 eth_port->etp_wr_pack= NULL;
336}
337
338PUBLIC void eth_rec(m)
339message *m;
340{
341 int i;
342 eth_port_t *loc_port;
343 int stat;
344
345 assert(m->m_type == DL_TASK_REPLY);
346
347 set_time (m->DL_CLCK);
348
349 for (i=0, loc_port= eth_port_table; i<eth_conf_nr; i++, loc_port++)
350 {
351 if (loc_port->etp_osdep.etp_port == m->DL_PORT &&
352 loc_port->etp_osdep.etp_task == m->m_source)
353 break;
354 }
355 if (i == eth_conf_nr)
356 {
357 ip_panic(("message from unknown source: %d:%d",
358 m->m_source, m->DL_PORT));
359 }
360
361 stat= m->DL_STAT & 0xffff;
362
363 assert(stat & (DL_PACK_SEND|DL_PACK_RECV));
364 if (stat & DL_PACK_SEND)
365 write_int(loc_port);
366 if (stat & DL_PACK_RECV)
367 {
368 if (recv_debug)
369 {
370 printf("eth_rec: eth%d got DL_PACK_RECV\n",
371 m->DL_PORT);
372 }
373 read_int(loc_port, m->DL_COUNT);
374 }
375}
376
377PUBLIC void eth_check_drivers(m)
378message *m;
379{
380 int i, r, tasknr;
381 struct eth_conf *ecp;
382 eth_port_t *eth_port;
383 char *drivername;
384
385 tasknr= m->m_source;
386 printf("eth_check_drivers: got a notification from %d\n", tasknr);
387
388 m->m_type= DL_GETNAME;
389 r= sendrec(tasknr, m);
390 if (r != OK)
391 {
392 printf("eth_check_drivers: sendrec to %d failed: %d\n",
393 tasknr, r);
394 return;
395 }
396 if (m->m_type != DL_NAME_REPLY)
397 {
398 printf(
399 "eth_check_drivers: got bad getname reply (%d) from %d\n",
400 m->m_type, tasknr);
401 return;
402 }
403
404 drivername= m->m3_ca1;
405 printf("eth_check_drivers: got name: %s\n", drivername);
406
407 /* Re-init ethernet interfaces */
408 for (i= 0, ecp= eth_conf, eth_port= eth_port_table;
409 i<eth_conf_nr; i++, ecp++, eth_port++)
410 {
411 if (eth_is_vlan(ecp))
412 continue;
413
414 if (strcmp(ecp->ec_task, drivername) != 0)
415 {
416 /* Wrong driver */
417 continue;
418 }
419
420 eth_restart(eth_port, tasknr);
421 }
422}
423
424PUBLIC int eth_get_stat(eth_port, eth_stat)
425eth_port_t *eth_port;
426eth_stat_t *eth_stat;
427{
428 int r;
429 message mess, mlocked;
430
431 assert(!eth_port->etp_vlan);
432
433 mess.m_type= DL_GETSTAT;
434 mess.DL_PORT= eth_port->etp_osdep.etp_port;
435 mess.DL_PROC= this_proc;
436 mess.DL_ADDR= (char *)eth_stat;
437
438 for (;;)
439 {
440 r= sendrec(eth_port->etp_osdep.etp_task, &mess);
441 if (r != ELOCKED)
442 break;
443
444 r= receive(eth_port->etp_osdep.etp_task, &mlocked);
445 assert(r == OK);
446
447 compare(mlocked.m_type, ==, DL_TASK_REPLY);
448 eth_rec(&mlocked);
449 }
450
451 if (r != OK)
452 {
453 printf("eth_get_stat: sendrec to %d failed: %d\n",
454 eth_port->etp_osdep.etp_task, r);
455 return EIO;
456 }
457
458 assert(mess.m_type == DL_TASK_REPLY);
459
460 r= mess.DL_STAT >> 16;
461 assert (r == 0);
462
463 if (mess.DL_STAT)
464 {
465 eth_rec(&mess);
466 }
467 return OK;
468}
469
470PUBLIC void eth_set_rec_conf (eth_port, flags)
471eth_port_t *eth_port;
472u32_t flags;
473{
474 int r;
475 unsigned dl_flags;
476 message mess, repl_mess;
477
478 assert(!eth_port->etp_vlan);
479
480 if (!(eth_port->etp_flags & EPF_GOT_ADDR))
481 {
482 /* We have never seen the device. */
483 printf("eth_set_rec_conf: waiting for device to appear\n");
484 return;
485 }
486
487 eth_port->etp_osdep.etp_recvconf= flags;
488 dl_flags= DL_NOMODE;
489 if (flags & NWEO_EN_BROAD)
490 dl_flags |= DL_BROAD_REQ;
491 if (flags & NWEO_EN_MULTI)
492 dl_flags |= DL_MULTI_REQ;
493 if (flags & NWEO_EN_PROMISC)
494 dl_flags |= DL_PROMISC_REQ;
495
496 mess.m_type= DL_INIT;
497 mess.DL_PORT= eth_port->etp_osdep.etp_port;
498 mess.DL_PROC= this_proc;
499 mess.DL_MODE= dl_flags;
500
501 do
502 {
503 r= sendrec(eth_port->etp_osdep.etp_task, &mess);
504 if (r == ELOCKED) /* etp_task is sending to this task,
505 I hope */
506 {
507 if (receive (eth_port->etp_osdep.etp_task,
508 &repl_mess)< 0)
509 {
510 ip_panic(("unable to receive"));
511 }
512
513 compare(repl_mess.m_type, ==, DL_TASK_REPLY);
514 eth_rec(&repl_mess);
515 }
516 } while (r == ELOCKED);
517
518 if (r < 0)
519 {
520 printf("eth_set_rec_conf: sendrec to %d failed: %d\n",
521 eth_port->etp_osdep.etp_task, r);
522 return;
523 }
524
525 assert (mess.m_type == DL_INIT_REPLY);
526 if (mess.m3_i1 != eth_port->etp_osdep.etp_port)
527 {
528 ip_panic(("got reply for wrong port"));
529 }
530}
531
532PRIVATE void write_int(eth_port)
533eth_port_t *eth_port;
534{
535 acc_t *pack;
536 int multicast;
537 u8_t *eth_dst_ptr;
538
539 pack= eth_port->etp_wr_pack;
540 eth_port->etp_wr_pack= NULL;
541
542 eth_dst_ptr= (u8_t *)ptr2acc_data(pack);
543 multicast= (*eth_dst_ptr & 1); /* low order bit indicates multicast */
544 if (multicast || (eth_port->etp_osdep.etp_recvconf & NWEO_EN_PROMISC))
545 {
546 assert(!no_ethWritePort);
547 no_ethWritePort= 1;
548 eth_arrive(eth_port, pack, bf_bufsize(pack));
549 assert(no_ethWritePort);
550 no_ethWritePort= 0;
551 }
552 else
553 bf_afree(pack);
554
555 eth_restart_write(eth_port);
556}
557
558PRIVATE void read_int(eth_port, count)
559eth_port_t *eth_port;
560int count;
561{
562 acc_t *pack, *cut_pack;
563
564 pack= eth_port->etp_rd_pack;
565 eth_port->etp_rd_pack= NULL;
566
567 cut_pack= bf_cut(pack, 0, count);
568 bf_afree(pack);
569
570 assert(!no_ethWritePort);
571 no_ethWritePort= 1;
572 eth_arrive(eth_port, cut_pack, count);
573 assert(no_ethWritePort);
574 no_ethWritePort= 0;
575
576 eth_port->etp_flags &= ~(EPF_READ_IP|EPF_READ_SP);
577 setup_read(eth_port);
578}
579
580PRIVATE void setup_read(eth_port)
581eth_port_t *eth_port;
582{
583 eth_port_t *loc_port;
584 acc_t *pack, *pack_ptr;
585 message mess1, block_msg;
586 iovec_t *iovec;
587 ev_arg_t ev_arg;
588 int i, r;
589
590 assert(!eth_port->etp_vlan);
591 assert(!(eth_port->etp_flags & (EPF_READ_IP|EPF_READ_SP)));
592
593 do
594 {
595 assert (!eth_port->etp_rd_pack);
596
597 iovec= eth_port->etp_osdep.etp_rd_iovec;
598 pack= bf_memreq (ETH_MAX_PACK_SIZE_TAGGED);
599
600 for (i=0, pack_ptr= pack; i<RD_IOVEC && pack_ptr;
601 i++, pack_ptr= pack_ptr->acc_next)
602 {
603 iovec[i].iov_addr= (vir_bytes)ptr2acc_data(pack_ptr);
604 iovec[i].iov_size= (vir_bytes)pack_ptr->acc_length;
605 }
606 assert (!pack_ptr);
607
608 mess1.m_type= DL_READV;
609 mess1.DL_PORT= eth_port->etp_osdep.etp_port;
610 mess1.DL_PROC= this_proc;
611 mess1.DL_COUNT= i;
612 mess1.DL_ADDR= (char *)iovec;
613
614 for (;;)
615 {
616 if (recv_debug)
617 {
618 printf("eth%d: sending DL_READV\n",
619 mess1.DL_PORT);
620 }
621 r= sendrec(eth_port->etp_osdep.etp_task, &mess1);
622 if (r != ELOCKED)
623 break;
624
625 /* ethernet task is sending to this task, I hope */
626 r= receive(eth_port->etp_osdep.etp_task, &block_msg);
627 if (r < 0)
628 ip_panic(("unable to receive"));
629
630 loc_port= eth_port;
631 if (loc_port->etp_osdep.etp_port != block_msg.DL_PORT ||
632 loc_port->etp_osdep.etp_task !=
633 block_msg.m_source)
634 {
635 loc_port= find_port(&block_msg);
636 }
637 assert(block_msg.DL_STAT &
638 (DL_PACK_SEND|DL_PACK_RECV));
639 if (block_msg.DL_STAT & DL_PACK_SEND)
640 {
641 loc_port->etp_osdep.etp_sendrepl= block_msg;
642 ev_arg.ev_ptr= loc_port;
643 ev_enqueue(&loc_port->etp_sendev, eth_sendev,
644 ev_arg);
645 }
646 if (block_msg.DL_STAT & DL_PACK_RECV)
647 {
648 if (recv_debug)
649 {
650 printf(
651 "setup_read(block_msg): eth%d got DL_PACK_RECV\n",
652 block_msg.DL_PORT);
653 }
654 assert(loc_port != eth_port);
655 loc_port->etp_osdep.etp_recvrepl= block_msg;
656 ev_arg.ev_ptr= loc_port;
657 ev_enqueue(&loc_port->etp_osdep.etp_recvev,
658 eth_recvev, ev_arg);
659 }
660 }
661
662 if (r < 0)
663 {
664 printf("mnx_eth`setup_read: sendrec to %d failed: %d\n",
665 eth_port->etp_osdep.etp_task, r);
666 eth_port->etp_rd_pack= pack;
667 eth_port->etp_flags |= EPF_READ_IP;
668 continue;
669 }
670
671 assert (mess1.m_type == DL_TASK_REPLY &&
672 mess1.DL_PORT == mess1.DL_PORT &&
673 mess1.DL_PROC == this_proc);
674 compare((mess1.DL_STAT >> 16), ==, OK);
675
676 if (mess1.DL_STAT & DL_PACK_RECV)
677 {
678 if (recv_debug)
679 {
680 printf(
681 "setup_read(mess1): eth%d: got DL_PACK_RECV\n",
682 mess1.DL_PORT);
683 }
684 /* packet received */
685 pack_ptr= bf_cut(pack, 0, mess1.DL_COUNT);
686 bf_afree(pack);
687
688 assert(!no_ethWritePort);
689 no_ethWritePort= 1;
690 eth_arrive(eth_port, pack_ptr, mess1.DL_COUNT);
691 assert(no_ethWritePort);
692 no_ethWritePort= 0;
693 }
694 else
695 {
696 /* no packet received */
697 eth_port->etp_rd_pack= pack;
698 eth_port->etp_flags |= EPF_READ_IP;
699 }
700
701 if (mess1.DL_STAT & DL_PACK_SEND)
702 {
703 eth_port->etp_osdep.etp_sendrepl= mess1;
704 ev_arg.ev_ptr= eth_port;
705 ev_enqueue(&eth_port->etp_sendev, eth_sendev, ev_arg);
706 }
707 } while (!(eth_port->etp_flags & EPF_READ_IP));
708 eth_port->etp_flags |= EPF_READ_SP;
709}
710
711PRIVATE void eth_recvev(ev, ev_arg)
712event_t *ev;
713ev_arg_t ev_arg;
714{
715 eth_port_t *eth_port;
716 message *m_ptr;
717
718 eth_port= ev_arg.ev_ptr;
719 assert(ev == &eth_port->etp_osdep.etp_recvev);
720 m_ptr= &eth_port->etp_osdep.etp_recvrepl;
721
722 assert(m_ptr->m_type == DL_TASK_REPLY);
723 assert(eth_port->etp_osdep.etp_port == m_ptr->DL_PORT &&
724 eth_port->etp_osdep.etp_task == m_ptr->m_source);
725
726 assert(m_ptr->DL_STAT & DL_PACK_RECV);
727 m_ptr->DL_STAT &= ~DL_PACK_RECV;
728
729 if (recv_debug)
730 {
731 printf("eth_recvev: eth%d got DL_PACK_RECV\n", m_ptr->DL_PORT);
732 }
733
734 read_int(eth_port, m_ptr->DL_COUNT);
735}
736
737PRIVATE void eth_sendev(ev, ev_arg)
738event_t *ev;
739ev_arg_t ev_arg;
740{
741 eth_port_t *eth_port;
742 message *m_ptr;
743
744 eth_port= ev_arg.ev_ptr;
745 assert(ev == &eth_port->etp_sendev);
746 m_ptr= &eth_port->etp_osdep.etp_sendrepl;
747
748 assert (m_ptr->m_type == DL_TASK_REPLY);
749 assert(eth_port->etp_osdep.etp_port == m_ptr->DL_PORT &&
750 eth_port->etp_osdep.etp_task == m_ptr->m_source);
751
752 assert(m_ptr->DL_STAT & DL_PACK_SEND);
753 m_ptr->DL_STAT &= ~DL_PACK_SEND;
754
755 /* packet is sent */
756 write_int(eth_port);
757}
758
759PRIVATE eth_port_t *find_port(m)
760message *m;
761{
762 eth_port_t *loc_port;
763 int i;
764
765 for (i=0, loc_port= eth_port_table; i<eth_conf_nr; i++, loc_port++)
766 {
767 if (loc_port->etp_osdep.etp_port == m->DL_PORT &&
768 loc_port->etp_osdep.etp_task == m->m_source)
769 break;
770 }
771 assert (i<eth_conf_nr);
772 return loc_port;
773}
774
775static void eth_restart(eth_port, tasknr)
776eth_port_t *eth_port;
777int tasknr;
778{
779 int i, r;
780 unsigned flags, dl_flags;
781 message mess;
782 eth_port_t *loc_port;
783
784 printf("eth_restart: restarting eth%d, task %d, port %d\n",
785 eth_port-eth_port_table, tasknr,
786 eth_port->etp_osdep.etp_port);
787
788 eth_port->etp_osdep.etp_task= tasknr;
789
790 flags= eth_port->etp_osdep.etp_recvconf;
791 dl_flags= DL_NOMODE;
792 if (flags & NWEO_EN_BROAD)
793 dl_flags |= DL_BROAD_REQ;
794 if (flags & NWEO_EN_MULTI)
795 dl_flags |= DL_MULTI_REQ;
796 if (flags & NWEO_EN_PROMISC)
797 dl_flags |= DL_PROMISC_REQ;
798 mess.m_type= DL_INIT;
799 mess.DL_PORT= eth_port->etp_osdep.etp_port;
800 mess.DL_PROC= this_proc;
801 mess.DL_MODE= dl_flags;
802
803 r= sendrec(eth_port->etp_osdep.etp_task, &mess);
804 /* YYY */
805 if (r<0)
806 {
807 printf(
808 "eth_restart: sendrec to ethernet task %d failed: %d\n",
809 eth_port->etp_osdep.etp_task, r);
810 return;
811 }
812
813 if (mess.m3_i1 == ENXIO)
814 {
815 printf(
816 "osdep_eth_init: no ethernet device at task=%d,port=%d\n",
817 eth_port->etp_osdep.etp_task,
818 eth_port->etp_osdep.etp_port);
819 return;
820 }
821 if (mess.m3_i1 < 0)
822 ip_panic(("osdep_eth_init: DL_INIT returned error %d\n",
823 mess.m3_i1));
824
825 if (mess.m3_i1 != eth_port->etp_osdep.etp_port)
826 {
827 ip_panic((
828"osdep_eth_init: got reply for wrong port (got %d, expected %d)\n",
829 mess.m3_i1, eth_port->etp_osdep.etp_port));
830 }
831
832 eth_port->etp_flags |= EPF_ENABLED;
833
834 eth_port->etp_ethaddr= *(ether_addr_t *)mess.m3_ca1;
835 if (!(eth_port->etp_flags & EPF_GOT_ADDR))
836 {
837 eth_port->etp_flags |= EPF_GOT_ADDR;
838 eth_restart_ioctl(eth_port);
839
840 /* Also update any VLANs on this device */
841 for (i=0, loc_port= eth_port_table; i<eth_conf_nr;
842 i++, loc_port++)
843 {
844 if (!(loc_port->etp_flags & EPF_ENABLED))
845 continue;
846 if (loc_port->etp_vlan_port != eth_port)
847 continue;
848
849 loc_port->etp_ethaddr= eth_port->etp_ethaddr;
850 loc_port->etp_flags |= EPF_GOT_ADDR;
851 eth_restart_ioctl(loc_port);
852 }
853 }
854
855 if (eth_port->etp_wr_pack)
856 {
857 bf_afree(eth_port->etp_wr_pack);
858 eth_port->etp_wr_pack= NULL;
859 eth_restart_write(eth_port);
860 }
861 if (eth_port->etp_rd_pack)
862 {
863 bf_afree(eth_port->etp_rd_pack);
864 eth_port->etp_rd_pack= NULL;
865 eth_port->etp_flags &= ~(EPF_READ_IP|EPF_READ_SP);
866 }
867 setup_read (eth_port);
868}
869
870/*
871 * $PchId: mnx_eth.c,v 1.16 2005/06/28 14:24:37 philip Exp $
872 */
Note: See TracBrowser for help on using the repository browser.