4 Created: Jan 2, 1992 by Philip Homburg
6 Copyright 1995 Philip Homburg
10 #include <minix/safecopies.h>
12 #include "osdep_eth.h"
13 #include "generic/type.h"
15 #include "generic/assert.h"
16 #include "generic/buf.h"
17 #include "generic/clock.h"
18 #include "generic/eth.h"
19 #include "generic/eth_int.h"
20 #include "generic/sr.h"
24 static int recv_debug
= 0;
26 FORWARD
_PROTOTYPE( void setup_read
, (eth_port_t
*eth_port
) );
27 FORWARD
_PROTOTYPE( void read_int
, (eth_port_t
*eth_port
, int count
) );
28 FORWARD
_PROTOTYPE( void write_int
, (eth_port_t
*eth_port
) );
29 FORWARD
_PROTOTYPE( void eth_recvev
, (event_t
*ev
, ev_arg_t ev_arg
) );
30 FORWARD
_PROTOTYPE( void eth_sendev
, (event_t
*ev
, ev_arg_t ev_arg
) );
31 FORWARD
_PROTOTYPE( eth_port_t
*find_port
, (message
*m
) );
32 FORWARD
_PROTOTYPE( void eth_restart
, (eth_port_t
*eth_port
, int tasknr
) );
34 PUBLIC
void osdep_eth_init()
36 int i
, j
, r
, tasknr
, rport
;
38 eth_port_t
*eth_port
, *rep
;
42 /* First initialize normal ethernet interfaces */
43 for (i
= 0, ecp
= eth_conf
, eth_port
= eth_port_table
;
44 i
<eth_conf_nr
; i
++, ecp
++, eth_port
++)
46 /* Set all grants to invalid */
47 for (j
= 0; j
<IOVEC_NR
; j
++)
48 eth_port
->etp_osdep
.etp_wr_iovec
[j
].iov_grant
= -1;
49 eth_port
->etp_osdep
.etp_wr_vec_grant
= -1;
50 for (j
= 0; j
<RD_IOVEC
; j
++)
51 eth_port
->etp_osdep
.etp_rd_iovec
[j
].iov_grant
= -1;
52 eth_port
->etp_osdep
.etp_rd_vec_grant
= -1;
58 for (j
= 0; j
<IOVEC_NR
; j
++)
60 if (cpf_getgrants(&gid
, 1) != 1)
63 "osdep_eth_init: cpf_getgrants failed: %d\n",
66 eth_port
->etp_osdep
.etp_wr_iovec
[j
].iov_grant
= gid
;
68 if (cpf_getgrants(&gid
, 1) != 1)
71 "osdep_eth_init: cpf_getgrants failed: %d\n",
74 eth_port
->etp_osdep
.etp_wr_vec_grant
= gid
;
75 for (j
= 0; j
<RD_IOVEC
; j
++)
77 if (cpf_getgrants(&gid
, 1) != 1)
80 "osdep_eth_init: cpf_getgrants failed: %d\n",
83 eth_port
->etp_osdep
.etp_rd_iovec
[j
].iov_grant
= gid
;
85 if (cpf_getgrants(&gid
, 1) != 1)
88 "osdep_eth_init: cpf_getgrants failed: %d\n",
91 eth_port
->etp_osdep
.etp_rd_vec_grant
= gid
;
94 r
= sys_findproc(ecp
->ec_task
, &tasknr
, 0);
96 r
= _pm_findproc(ecp
->ec_task
, &tasknr
);
100 /* Eventually, we expect ethernet drivers to be
101 * started after INET. So we always end up here. And
102 * the findproc can be removed.
104 printf("eth%d: unable to find task %s: %d\n",
109 eth_port
->etp_osdep
.etp_port
= ecp
->ec_port
;
110 eth_port
->etp_osdep
.etp_task
= tasknr
;
111 eth_port
->etp_osdep
.etp_send_ev
= 0;
112 ev_init(ð_port
->etp_osdep
.etp_recvev
);
114 mess
.m_type
= DL_CONF
;
115 mess
.DL_PORT
= eth_port
->etp_osdep
.etp_port
;
116 mess
.DL_PROC
= this_proc
;
117 mess
.DL_MODE
= DL_NOMODE
;
123 r
= send(eth_port
->etp_osdep
.etp_task
, &mess
);
127 "osdep_eth_init: unable to send to ethernet task, error= %d\n",
134 r
= receive(eth_port
->etp_osdep
.etp_task
, &mess
);
138 "osdep_eth_init: unable to receive from ethernet task, error= %d\n",
149 "osdep_eth_init: no ethernet device at task=%d,port=%d\n",
150 eth_port
->etp_osdep
.etp_task
,
151 eth_port
->etp_osdep
.etp_port
);
156 "osdep_eth_init: DL_INIT returned error %d\n",
159 else if (mess
.m3_i1
!= eth_port
->etp_osdep
.etp_port
)
162 "osdep_eth_init: got reply for wrong port (got %d, expected %d)\n",
164 eth_port
->etp_osdep
.etp_port
));
168 sr_add_minor(if2minor(ecp
->ec_ifno
, ETH_DEV_OFF
),
169 i
, eth_open
, eth_close
, eth_read
,
170 eth_write
, eth_ioctl
, eth_cancel
, eth_select
);
172 eth_port
->etp_flags
|= EPF_ENABLED
;
173 eth_port
->etp_vlan
= 0;
174 eth_port
->etp_vlan_port
= NULL
;
175 eth_port
->etp_wr_pack
= 0;
176 eth_port
->etp_rd_pack
= 0;
179 eth_port
->etp_ethaddr
= *(ether_addr_t
*)mess
.m3_ca1
;
180 eth_port
->etp_flags
|= EPF_GOT_ADDR
;
181 setup_read (eth_port
);
185 /* And now come the VLANs */
186 for (i
= 0, ecp
= eth_conf
, eth_port
= eth_port_table
;
187 i
<eth_conf_nr
; i
++, ecp
++, eth_port
++)
189 if (!eth_is_vlan(ecp
))
192 eth_port
->etp_osdep
.etp_port
= ecp
->ec_port
;
193 eth_port
->etp_osdep
.etp_task
= ANY
;
194 ev_init(ð_port
->etp_osdep
.etp_recvev
);
196 rport
= eth_port
->etp_osdep
.etp_port
;
197 assert(rport
>= 0 && rport
< eth_conf_nr
);
198 rep
= ð_port_table
[rport
];
199 if (!(rep
->etp_flags
& EPF_ENABLED
))
202 "eth%d: underlying ethernet device %d not enabled",
206 if (rep
->etp_vlan
!= 0)
209 "eth%d: underlying ethernet device %d is a VLAN",
214 if (rep
->etp_flags
& EPF_GOT_ADDR
)
216 eth_port
->etp_ethaddr
= rep
->etp_ethaddr
;
217 eth_port
->etp_flags
|= EPF_GOT_ADDR
;
220 sr_add_minor(if2minor(ecp
->ec_ifno
, ETH_DEV_OFF
),
221 i
, eth_open
, eth_close
, eth_read
,
222 eth_write
, eth_ioctl
, eth_cancel
, eth_select
);
224 eth_port
->etp_flags
|= EPF_ENABLED
;
225 eth_port
->etp_vlan
= ecp
->ec_vlan
;
226 eth_port
->etp_vlan_port
= rep
;
227 assert(eth_port
->etp_vlan
!= 0);
228 eth_port
->etp_wr_pack
= 0;
229 eth_port
->etp_rd_pack
= 0;
230 eth_reg_vlan(rep
, eth_port
);
234 PUBLIC
void eth_write_port(eth_port
, pack
)
235 eth_port_t
*eth_port
;
238 eth_port_t
*loc_port
;
239 message mess1
, block_msg
;
247 assert(!no_ethWritePort
);
248 assert(!eth_port
->etp_vlan
);
250 assert(eth_port
->etp_wr_pack
== NULL
);
251 eth_port
->etp_wr_pack
= pack
;
253 iovec
= eth_port
->etp_osdep
.etp_wr_iovec
;
255 for (i
=0, pack_ptr
= pack
; i
<IOVEC_NR
&& pack_ptr
; i
++,
256 pack_ptr
= pack_ptr
->acc_next
)
258 r
= cpf_setgrant_direct(iovec
[i
].iov_grant
,
259 eth_port
->etp_osdep
.etp_task
,
260 (vir_bytes
)ptr2acc_data(pack_ptr
),
261 (vir_bytes
)pack_ptr
->acc_length
,
266 "eth_write_port: cpf_setgrant_direct failed: %d\n",
269 pack_size
+= iovec
[i
].iov_size
= pack_ptr
->acc_length
;
273 pack
= bf_pack(pack
); /* packet is too fragmented */
274 eth_port
->etp_wr_pack
= pack
;
276 for (i
=0, pack_ptr
= pack
; i
<IOVEC_NR
&& pack_ptr
;
277 i
++, pack_ptr
= pack_ptr
->acc_next
)
279 r
= cpf_setgrant_direct(iovec
[i
].iov_grant
,
280 eth_port
->etp_osdep
.etp_task
,
281 (vir_bytes
)ptr2acc_data(pack_ptr
),
282 (vir_bytes
)pack_ptr
->acc_length
,
287 "eth_write_port: cpf_setgrant_direct failed: %d\n",
290 pack_size
+= iovec
[i
].iov_size
= pack_ptr
->acc_length
;
293 assert (i
< IOVEC_NR
);
294 assert (pack_size
>= ETH_MIN_PACK_SIZE
);
297 r
= cpf_setgrant_direct(eth_port
->etp_osdep
.etp_wr_vec_grant
,
298 eth_port
->etp_osdep
.etp_task
,
300 (vir_bytes
)(i
* sizeof(iovec
[0])),
305 "eth_write_port: cpf_setgrant_direct failed: %d\n",
309 mess1
.DL_GRANT
= eth_port
->etp_osdep
.etp_wr_vec_grant
;
310 mess1
.m_type
= DL_WRITEV_S
;
312 mess1
.DL_PORT
= eth_port
->etp_osdep
.etp_port
;
313 mess1
.DL_PROC
= this_proc
;
314 mess1
.DL_MODE
= DL_NOMODE
;
318 r
= sendrec(eth_port
->etp_osdep
.etp_task
, &mess1
);
322 /* ethernet task is sending to this task, I hope */
323 r
= receive(eth_port
->etp_osdep
.etp_task
, &block_msg
);
325 ip_panic(("unable to receive"));
328 if (loc_port
->etp_osdep
.etp_port
!= block_msg
.DL_PORT
||
329 loc_port
->etp_osdep
.etp_task
!= block_msg
.m_source
)
331 loc_port
= find_port(&block_msg
);
333 assert(block_msg
.DL_STAT
& (DL_PACK_SEND
|DL_PACK_RECV
));
334 if (block_msg
.DL_STAT
& DL_PACK_SEND
)
336 assert(loc_port
!= eth_port
);
337 loc_port
->etp_osdep
.etp_sendrepl
= block_msg
;
338 ev_arg
.ev_ptr
= loc_port
;
339 assert(!loc_port
->etp_osdep
.etp_send_ev
);
340 loc_port
->etp_osdep
.etp_send_ev
= 1;
341 ev_enqueue(&loc_port
->etp_sendev
, eth_sendev
, ev_arg
);
343 if (block_msg
.DL_STAT
& DL_PACK_RECV
)
348 "eth_write_port(block_msg): eth%d got DL_PACK_RECV\n",
349 loc_port
-eth_port_table
);
351 loc_port
->etp_osdep
.etp_recvrepl
= block_msg
;
352 ev_arg
.ev_ptr
= loc_port
;
353 ev_enqueue(&loc_port
->etp_osdep
.etp_recvev
,
360 printf("eth_write_port: sendrec to %d failed: %d\n",
361 eth_port
->etp_osdep
.etp_task
, r
);
365 if (mess1
.m_type
!= DL_TASK_REPLY
||
366 mess1
.DL_PORT
!= eth_port
->etp_osdep
.etp_port
||
367 mess1
.DL_PROC
!= this_proc
)
370 "eth_write_port: ignoring bad message (type = 0x%x, port = %d, proc = %d) from %d\n",
371 mess1
.m_type
, mess1
.DL_PORT
, mess1
.DL_PROC
,
376 assert(mess1
.m_type
== DL_TASK_REPLY
&&
377 mess1
.DL_PORT
== eth_port
->etp_osdep
.etp_port
&&
378 mess1
.DL_PROC
== this_proc
);
379 assert((mess1
.DL_STAT
>> 16) == OK
);
381 if (mess1
.DL_STAT
& DL_PACK_RECV
)
386 "eth_write_port(mess1): eth%d got DL_PACK_RECV\n",
389 eth_port
->etp_osdep
.etp_recvrepl
= mess1
;
390 ev_arg
.ev_ptr
= eth_port
;
391 ev_enqueue(ð_port
->etp_osdep
.etp_recvev
, eth_recvev
,
394 if (!(mess1
.DL_STAT
& DL_PACK_SEND
))
396 /* Packet is not yet sent. */
400 /* If the port is in promiscuous mode or the packet is
401 * broad- or multicast, enqueue the reply packet.
403 eth_dst_ptr
= (u8_t
*)ptr2acc_data(pack
);
404 multicast
= (*eth_dst_ptr
& 1); /* low order bit indicates multicast */
405 if (multicast
|| (eth_port
->etp_osdep
.etp_recvconf
& NWEO_EN_PROMISC
))
407 eth_port
->etp_osdep
.etp_sendrepl
= mess1
;
408 ev_arg
.ev_ptr
= eth_port
;
409 assert(!eth_port
->etp_osdep
.etp_send_ev
);
410 eth_port
->etp_osdep
.etp_send_ev
= 1;
411 ev_enqueue(ð_port
->etp_sendev
, eth_sendev
, ev_arg
);
413 /* Pretend that we didn't get a reply. */
418 bf_afree(eth_port
->etp_wr_pack
);
419 eth_port
->etp_wr_pack
= NULL
;
422 PUBLIC
void eth_rec(m
)
426 eth_port_t
*loc_port
;
429 assert(m
->m_type
== DL_TASK_REPLY
);
431 set_time (m
->DL_CLCK
);
433 for (i
=0, loc_port
= eth_port_table
; i
<eth_conf_nr
; i
++, loc_port
++)
435 if (loc_port
->etp_osdep
.etp_port
== m
->DL_PORT
&&
436 loc_port
->etp_osdep
.etp_task
== m
->m_source
)
439 if (i
== eth_conf_nr
)
441 ip_panic(("message from unknown source: %d:%d",
442 m
->m_source
, m
->DL_PORT
));
445 stat
= m
->DL_STAT
& 0xffff;
447 if (!(stat
& (DL_PACK_SEND
|DL_PACK_RECV
)))
448 printf("eth_rec: neither DL_PACK_SEND nor DL_PACK_RECV\n");
449 if (stat
& DL_PACK_SEND
)
451 if (stat
& DL_PACK_RECV
)
455 printf("eth_rec: eth%d got DL_PACK_RECV\n",
458 read_int(loc_port
, m
->DL_COUNT
);
462 PUBLIC
void eth_check_drivers(m
)
466 struct eth_conf
*ecp
;
467 eth_port_t
*eth_port
;
471 printf("eth_check_drivers: got a notification from %d\n", tasknr
);
473 m
->m_type
= DL_GETNAME
;
474 r
= sendrec(tasknr
, m
);
477 printf("eth_check_drivers: sendrec to %d failed: %d\n",
481 if (m
->m_type
!= DL_NAME_REPLY
)
484 "eth_check_drivers: got bad getname reply (%d) from %d\n",
489 drivername
= m
->m3_ca1
;
490 printf("eth_check_drivers: got name: %s\n", drivername
);
492 /* Re-init ethernet interfaces */
493 for (i
= 0, ecp
= eth_conf
, eth_port
= eth_port_table
;
494 i
<eth_conf_nr
; i
++, ecp
++, eth_port
++)
496 if (eth_is_vlan(ecp
))
499 if (strcmp(ecp
->ec_task
, drivername
) != 0)
505 eth_restart(eth_port
, tasknr
);
509 PUBLIC
int eth_get_stat(eth_port
, eth_stat
)
510 eth_port_t
*eth_port
;
511 eth_stat_t
*eth_stat
;
515 message mess
, mlocked
;
517 assert(!eth_port
->etp_vlan
);
519 gid
= cpf_grant_direct(eth_port
->etp_osdep
.etp_task
,
520 (vir_bytes
)eth_stat
, sizeof(*eth_stat
), CPF_WRITE
);
523 ip_panic(( "eth_get_stat: cpf_grant_direct failed: %d\n",
527 mess
.m_type
= DL_GETSTAT_S
;
528 mess
.DL_PORT
= eth_port
->etp_osdep
.etp_port
;
529 mess
.DL_PROC
= this_proc
;
534 r
= sendrec(eth_port
->etp_osdep
.etp_task
, &mess
);
538 r
= receive(eth_port
->etp_osdep
.etp_task
, &mlocked
);
541 compare(mlocked
.m_type
, ==, DL_TASK_REPLY
);
548 printf("eth_get_stat: sendrec to %d failed: %d\n",
549 eth_port
->etp_osdep
.etp_task
, r
);
553 assert(mess
.m_type
== DL_TASK_REPLY
);
555 r
= mess
.DL_STAT
>> 16;
565 PUBLIC
void eth_set_rec_conf (eth_port
, flags
)
566 eth_port_t
*eth_port
;
571 message mess
, repl_mess
;
573 assert(!eth_port
->etp_vlan
);
575 if (!(eth_port
->etp_flags
& EPF_GOT_ADDR
))
577 /* We have never seen the device. */
578 printf("eth_set_rec_conf: waiting for device to appear\n");
582 eth_port
->etp_osdep
.etp_recvconf
= flags
;
584 if (flags
& NWEO_EN_BROAD
)
585 dl_flags
|= DL_BROAD_REQ
;
586 if (flags
& NWEO_EN_MULTI
)
587 dl_flags
|= DL_MULTI_REQ
;
588 if (flags
& NWEO_EN_PROMISC
)
589 dl_flags
|= DL_PROMISC_REQ
;
591 mess
.m_type
= DL_CONF
;
592 mess
.DL_PORT
= eth_port
->etp_osdep
.etp_port
;
593 mess
.DL_PROC
= this_proc
;
594 mess
.DL_MODE
= dl_flags
;
598 r
= sendrec(eth_port
->etp_osdep
.etp_task
, &mess
);
599 if (r
== ELOCKED
) /* etp_task is sending to this task,
602 if (receive (eth_port
->etp_osdep
.etp_task
,
605 ip_panic(("unable to receive"));
608 compare(repl_mess
.m_type
, ==, DL_TASK_REPLY
);
611 } while (r
== ELOCKED
);
615 printf("eth_set_rec_conf: sendrec to %d failed: %d\n",
616 eth_port
->etp_osdep
.etp_task
, r
);
620 assert (mess
.m_type
== DL_CONF_REPLY
);
621 if (mess
.m3_i1
!= eth_port
->etp_osdep
.etp_port
)
623 ip_panic(("got reply for wrong port"));
627 PRIVATE
void write_int(eth_port
)
628 eth_port_t
*eth_port
;
634 pack
= eth_port
->etp_wr_pack
;
637 printf("write_int: strange no packet on eth port %d\n",
638 eth_port
-eth_port_table
);
639 eth_restart_write(eth_port
);
643 eth_port
->etp_wr_pack
= NULL
;
645 eth_dst_ptr
= (u8_t
*)ptr2acc_data(pack
);
646 multicast
= (*eth_dst_ptr
& 1); /* low order bit indicates multicast */
647 if (multicast
|| (eth_port
->etp_osdep
.etp_recvconf
& NWEO_EN_PROMISC
))
649 assert(!no_ethWritePort
);
651 eth_arrive(eth_port
, pack
, bf_bufsize(pack
));
652 assert(no_ethWritePort
);
658 eth_restart_write(eth_port
);
661 PRIVATE
void read_int(eth_port
, count
)
662 eth_port_t
*eth_port
;
665 acc_t
*pack
, *cut_pack
;
667 pack
= eth_port
->etp_rd_pack
;
668 eth_port
->etp_rd_pack
= NULL
;
670 if (count
< ETH_MIN_PACK_SIZE
)
672 printf("mnx_eth`read_int: packet size too small (%d)\n",
676 else if (count
> ETH_MAX_PACK_SIZE_TAGGED
)
678 printf("mnx_eth`read_int: packet size too big (%d)\n",
684 cut_pack
= bf_cut(pack
, 0, count
);
687 assert(!no_ethWritePort
);
689 eth_arrive(eth_port
, cut_pack
, count
);
690 assert(no_ethWritePort
);
694 eth_port
->etp_flags
&= ~(EPF_READ_IP
|EPF_READ_SP
);
695 setup_read(eth_port
);
698 PRIVATE
void setup_read(eth_port
)
699 eth_port_t
*eth_port
;
701 eth_port_t
*loc_port
;
702 acc_t
*pack
, *pack_ptr
;
703 message mess1
, block_msg
;
708 assert(!eth_port
->etp_vlan
);
709 assert(!(eth_port
->etp_flags
& (EPF_READ_IP
|EPF_READ_SP
)));
713 assert (!eth_port
->etp_rd_pack
);
715 iovec
= eth_port
->etp_osdep
.etp_rd_iovec
;
716 pack
= bf_memreq (ETH_MAX_PACK_SIZE_TAGGED
);
718 for (i
=0, pack_ptr
= pack
; i
<RD_IOVEC
&& pack_ptr
;
719 i
++, pack_ptr
= pack_ptr
->acc_next
)
721 r
= cpf_setgrant_direct(iovec
[i
].iov_grant
,
722 eth_port
->etp_osdep
.etp_task
,
723 (vir_bytes
)ptr2acc_data(pack_ptr
),
724 (vir_bytes
)pack_ptr
->acc_length
,
729 "mnx_eth`setup_read: cpf_setgrant_direct failed: %d\n",
732 iovec
[i
].iov_size
= (vir_bytes
)pack_ptr
->acc_length
;
736 r
= cpf_setgrant_direct(eth_port
->etp_osdep
.etp_rd_vec_grant
,
737 eth_port
->etp_osdep
.etp_task
,
739 (vir_bytes
)(i
* sizeof(iovec
[0])),
744 "mnx_eth`setup_read: cpf_setgrant_direct failed: %d\n",
748 mess1
.m_type
= DL_READV_S
;
749 mess1
.DL_PORT
= eth_port
->etp_osdep
.etp_port
;
750 mess1
.DL_PROC
= this_proc
;
752 mess1
.DL_GRANT
= eth_port
->etp_osdep
.etp_rd_vec_grant
;
758 printf("eth%d: sending DL_READV_S\n",
761 r
= sendrec(eth_port
->etp_osdep
.etp_task
, &mess1
);
765 /* ethernet task is sending to this task, I hope */
766 r
= receive(eth_port
->etp_osdep
.etp_task
, &block_msg
);
768 ip_panic(("unable to receive"));
771 if (loc_port
->etp_osdep
.etp_port
!= block_msg
.DL_PORT
||
772 loc_port
->etp_osdep
.etp_task
!=
775 loc_port
= find_port(&block_msg
);
777 assert(block_msg
.DL_STAT
&
778 (DL_PACK_SEND
|DL_PACK_RECV
));
779 if (block_msg
.DL_STAT
& DL_PACK_SEND
)
781 loc_port
->etp_osdep
.etp_sendrepl
=
783 ev_arg
.ev_ptr
= loc_port
;
784 assert(!loc_port
->etp_osdep
.etp_send_ev
);
785 loc_port
->etp_osdep
.etp_send_ev
= 1;
786 ev_enqueue(&loc_port
->etp_sendev
,
789 if (block_msg
.DL_STAT
& DL_PACK_RECV
)
794 "setup_read(block_msg): eth%d got DL_PACK_RECV\n",
797 assert(loc_port
!= eth_port
);
798 loc_port
->etp_osdep
.etp_recvrepl
= block_msg
;
799 ev_arg
.ev_ptr
= loc_port
;
800 ev_enqueue(&loc_port
->etp_osdep
.etp_recvev
,
807 printf("mnx_eth`setup_read: sendrec to %d failed: %d\n",
808 eth_port
->etp_osdep
.etp_task
, r
);
809 eth_port
->etp_rd_pack
= pack
;
810 eth_port
->etp_flags
|= EPF_READ_IP
;
814 if (mess1
.m_type
!= DL_TASK_REPLY
||
815 mess1
.DL_PORT
!= eth_port
->etp_osdep
.etp_port
||
816 mess1
.DL_PROC
!= this_proc
)
818 printf("mnx_eth`setup_read: bad type, port or proc\n");
819 printf("got type %d, port %d, proc %d\n",
820 mess1
.m_type
, mess1
.DL_PORT
, mess1
.DL_PROC
);
824 if ((mess1
.DL_STAT
>> 16) != OK
)
827 "mnx_eth`setup_read: bad value in DL_STAT: 0x%x\n",
832 if (mess1
.DL_STAT
& DL_PACK_RECV
)
837 "setup_read(mess1): eth%d: got DL_PACK_RECV\n",
841 if (mess1
.DL_COUNT
< ETH_MIN_PACK_SIZE
)
844 "mnx_eth`setup_read: packet size too small (%d)\n",
850 /* packet received */
851 pack_ptr
= bf_cut(pack
, 0, mess1
.DL_COUNT
);
854 assert(!no_ethWritePort
);
856 eth_arrive(eth_port
, pack_ptr
, mess1
.DL_COUNT
);
857 assert(no_ethWritePort
);
863 /* no packet received */
864 eth_port
->etp_rd_pack
= pack
;
865 eth_port
->etp_flags
|= EPF_READ_IP
;
868 if (mess1
.DL_STAT
& DL_PACK_SEND
)
870 if (eth_port
->etp_osdep
.etp_send_ev
)
873 "mnx_eth`setup_read: etp_send_ev is set, ignoring DL_PACK_SEND\n");
877 eth_port
->etp_osdep
.etp_sendrepl
= mess1
;
878 ev_arg
.ev_ptr
= eth_port
;
879 assert(!eth_port
->etp_osdep
.etp_send_ev
);
880 eth_port
->etp_osdep
.etp_send_ev
= 1;
881 ev_enqueue(ð_port
->etp_sendev
, eth_sendev
,
885 } while (!(eth_port
->etp_flags
& EPF_READ_IP
));
886 eth_port
->etp_flags
|= EPF_READ_SP
;
889 PRIVATE
void eth_recvev(ev
, ev_arg
)
893 eth_port_t
*eth_port
;
896 eth_port
= ev_arg
.ev_ptr
;
897 assert(ev
== ð_port
->etp_osdep
.etp_recvev
);
898 m_ptr
= ð_port
->etp_osdep
.etp_recvrepl
;
900 assert(m_ptr
->m_type
== DL_TASK_REPLY
);
901 assert(eth_port
->etp_osdep
.etp_port
== m_ptr
->DL_PORT
&&
902 eth_port
->etp_osdep
.etp_task
== m_ptr
->m_source
);
904 assert(m_ptr
->DL_STAT
& DL_PACK_RECV
);
905 m_ptr
->DL_STAT
&= ~DL_PACK_RECV
;
909 printf("eth_recvev: eth%d got DL_PACK_RECV\n", m_ptr
->DL_PORT
);
912 read_int(eth_port
, m_ptr
->DL_COUNT
);
915 PRIVATE
void eth_sendev(ev
, ev_arg
)
919 eth_port_t
*eth_port
;
922 eth_port
= ev_arg
.ev_ptr
;
923 assert(ev
== ð_port
->etp_sendev
);
924 m_ptr
= ð_port
->etp_osdep
.etp_sendrepl
;
926 assert (m_ptr
->m_type
== DL_TASK_REPLY
);
927 assert(eth_port
->etp_osdep
.etp_port
== m_ptr
->DL_PORT
&&
928 eth_port
->etp_osdep
.etp_task
== m_ptr
->m_source
);
930 assert(m_ptr
->DL_STAT
& DL_PACK_SEND
);
931 m_ptr
->DL_STAT
&= ~DL_PACK_SEND
;
932 assert(eth_port
->etp_osdep
.etp_send_ev
);
933 eth_port
->etp_osdep
.etp_send_ev
= 0;
939 PRIVATE eth_port_t
*find_port(m
)
942 eth_port_t
*loc_port
;
945 for (i
=0, loc_port
= eth_port_table
; i
<eth_conf_nr
; i
++, loc_port
++)
947 if (loc_port
->etp_osdep
.etp_port
== m
->DL_PORT
&&
948 loc_port
->etp_osdep
.etp_task
== m
->m_source
)
951 assert (i
<eth_conf_nr
);
955 static void eth_restart(eth_port
, tasknr
)
956 eth_port_t
*eth_port
;
960 unsigned flags
, dl_flags
;
962 eth_port_t
*loc_port
;
964 printf("eth_restart: restarting eth%d, task %d, port %d\n",
965 eth_port
-eth_port_table
, tasknr
,
966 eth_port
->etp_osdep
.etp_port
);
968 eth_port
->etp_osdep
.etp_task
= tasknr
;
970 flags
= eth_port
->etp_osdep
.etp_recvconf
;
972 if (flags
& NWEO_EN_BROAD
)
973 dl_flags
|= DL_BROAD_REQ
;
974 if (flags
& NWEO_EN_MULTI
)
975 dl_flags
|= DL_MULTI_REQ
;
976 if (flags
& NWEO_EN_PROMISC
)
977 dl_flags
|= DL_PROMISC_REQ
;
978 mess
.m_type
= DL_CONF
;
979 mess
.DL_PORT
= eth_port
->etp_osdep
.etp_port
;
980 mess
.DL_PROC
= this_proc
;
981 mess
.DL_MODE
= dl_flags
;
983 r
= sendrec(eth_port
->etp_osdep
.etp_task
, &mess
);
988 "eth_restart: sendrec to ethernet task %d failed: %d\n",
989 eth_port
->etp_osdep
.etp_task
, r
);
993 if (mess
.m3_i1
== ENXIO
)
996 "osdep_eth_init: no ethernet device at task=%d,port=%d\n",
997 eth_port
->etp_osdep
.etp_task
,
998 eth_port
->etp_osdep
.etp_port
);
1002 ip_panic(("osdep_eth_init: DL_INIT returned error %d\n",
1005 if (mess
.m3_i1
!= eth_port
->etp_osdep
.etp_port
)
1008 "osdep_eth_init: got reply for wrong port (got %d, expected %d)\n",
1009 mess
.m3_i1
, eth_port
->etp_osdep
.etp_port
));
1012 eth_port
->etp_flags
|= EPF_ENABLED
;
1014 eth_port
->etp_ethaddr
= *(ether_addr_t
*)mess
.m3_ca1
;
1015 if (!(eth_port
->etp_flags
& EPF_GOT_ADDR
))
1017 eth_port
->etp_flags
|= EPF_GOT_ADDR
;
1018 eth_restart_ioctl(eth_port
);
1020 /* Also update any VLANs on this device */
1021 for (i
=0, loc_port
= eth_port_table
; i
<eth_conf_nr
;
1024 if (!(loc_port
->etp_flags
& EPF_ENABLED
))
1026 if (loc_port
->etp_vlan_port
!= eth_port
)
1029 loc_port
->etp_ethaddr
= eth_port
->etp_ethaddr
;
1030 loc_port
->etp_flags
|= EPF_GOT_ADDR
;
1031 eth_restart_ioctl(loc_port
);
1035 if (eth_port
->etp_wr_pack
)
1037 bf_afree(eth_port
->etp_wr_pack
);
1038 eth_port
->etp_wr_pack
= NULL
;
1039 eth_restart_write(eth_port
);
1041 if (eth_port
->etp_rd_pack
)
1043 bf_afree(eth_port
->etp_rd_pack
);
1044 eth_port
->etp_rd_pack
= NULL
;
1045 eth_port
->etp_flags
&= ~(EPF_READ_IP
|EPF_READ_SP
);
1047 setup_read (eth_port
);
1051 * $PchId: mnx_eth.c,v 1.16 2005/06/28 14:24:37 philip Exp $