4 Created: Jan 2, 1992 by Philip Homburg
6 Copyright 1995 Philip Homburg
11 #include <minix/safecopies.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"
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
) );
38 FORWARD
_PROTOTYPE( int asynsend
, (endpoint_t dst
, message
*mp
) );
41 PUBLIC
void osdep_eth_init()
46 eth_port_t
*eth_port
, *rep
;
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
;
71 for (j
= 0; j
<IOVEC_NR
; j
++)
73 if (cpf_getgrants(&gid
, 1) != 1)
76 "osdep_eth_init: cpf_getgrants failed: %d\n",
79 eth_port
->etp_osdep
.etp_wr_iovec
[j
].iov_grant
= gid
;
81 if (cpf_getgrants(&gid
, 1) != 1)
84 "osdep_eth_init: cpf_getgrants failed: %d\n",
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)
93 "osdep_eth_init: cpf_getgrants failed: %d\n",
96 eth_port
->etp_osdep
.etp_rd_iovec
[j
].iov_grant
= gid
;
98 if (cpf_getgrants(&gid
, 1) != 1)
101 "osdep_eth_init: cpf_getgrants failed: %d\n",
104 eth_port
->etp_osdep
.etp_rd_vec_grant
= gid
;
107 r
= sys_findproc(ecp
->ec_task
, &tasknr
, 0);
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",
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",
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(ð_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
;
141 assert(eth_port
->etp_osdep
.etp_state
== OEPS_INIT
);
142 r
= asynsend(eth_port
->etp_osdep
.etp_task
, &mess
);
144 eth_port
->etp_osdep
.etp_state
= OEPS_CONF_SENT
;
148 "osdep_eth_init: unable to send to ethernet task, error= %d\n",
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;
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
))
180 eth_port
->etp_osdep
.etp_port
= ecp
->ec_port
;
181 eth_port
->etp_osdep
.etp_task
= ANY
;
182 ev_init(ð_port
->etp_osdep
.etp_recvev
);
184 rport
= eth_port
->etp_osdep
.etp_port
;
185 assert(rport
>= 0 && rport
< eth_conf_nr
);
186 rep
= ð_port_table
[rport
];
187 if (!(rep
->etp_flags
& EPF_ENABLED
))
190 "eth%d: underlying ethernet device %d not enabled",
194 if (rep
->etp_vlan
!= 0)
197 "eth%d: underlying ethernet device %d is a VLAN",
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
;
227 eth_port_t
*loc_port
;
228 message mess1
, block_msg
;
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
;
246 eth_issue_send(eth_port
);
249 PRIVATE
int notification_count
;
251 PUBLIC
void eth_rec(m
)
254 int i
, r
, m_type
, stat
;
255 eth_port_t
*loc_port
, *vlan_port
;
257 struct eth_conf
*ecp
;
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
))
274 if (strcmp(ecp
->ec_task
, drivername
) != 0)
279 eth_restart(loc_port
, m
->m_source
);
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
)
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
);
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
)
308 if (stat
& DL_PACK_RECV
)
309 read_int(loc_port
, m
->DL_COUNT
);
313 if (m_type
!= DL_CONF_REPLY
)
316 "eth_rec: got bad message type 0x%x from %d in CONF state\n",
317 m_type
, m
->m_source
);
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
);
332 ip_panic(("eth_rec: DL_INIT returned error %d\n", r
));
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
;
345 printf("eth_rec: calling eth_restart_ioctl\n");
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
;
353 if (!(vlan_port
->etp_flags
& EPF_ENABLED
))
355 if (vlan_port
->etp_vlan_port
!= loc_port
)
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
);
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");
383 if (loc_port
->etp_osdep
.etp_state
== OEPS_GETSTAT_SENT
)
385 if (m_type
!= DL_STAT_REPLY
)
388 "eth_rec: got bad message type 0x%x from %d in GETSTAT state\n",
389 m_type
, m
->m_source
);
396 ip_warning(("eth_rec: DL_STAT returned error %d\n",
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
;
410 assert(loc_port
->etp_flags
& EPF_GOT_ADDR
);
411 eth_restart_ioctl(loc_port
);
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");
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
);
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
);
448 stat
= m
->DL_STAT
& 0xffff;
451 if (!(stat
& (DL_PACK_SEND
|DL_PACK_RECV
)))
452 printf("eth_rec: neither DL_PACK_SEND nor DL_PACK_RECV\n");
454 if (stat
& DL_PACK_SEND
)
456 if (stat
& DL_PACK_RECV
)
460 printf("eth_rec: eth%d got DL_PACK_RECV\n",
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
)
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
);
508 printf("eth_check_drivers: asynsend to %d failed: %d\n",
514 PUBLIC
int eth_get_stat(eth_port
, eth_stat
)
515 eth_port_t
*eth_port
;
516 eth_stat_t
*eth_stat
;
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
);
530 ip_panic(( "eth_get_stat: cpf_grant_direct failed: %d\n",
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
;
543 send_getstat(eth_port
);
548 PUBLIC
void eth_set_rec_conf (eth_port
, flags
)
549 eth_port_t
*eth_port
;
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. */
562 printf("eth_set_rec_conf: waiting for device to appear\n");
567 if (eth_port
->etp_osdep
.etp_state
!= OEPS_IDLE
)
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
;
576 eth_port
->etp_osdep
.etp_recvconf
= flags
;
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
;
596 printf("eth_set_rec_conf: asynsend to %d failed: %d\n",
597 eth_port
->etp_osdep
.etp_task
, r
);
602 PRIVATE
void eth_issue_send(eth_port
)
603 eth_port_t
*eth_port
;
606 acc_t
*pack
, *pack_ptr
;
610 iovec
= eth_port
->etp_osdep
.etp_wr_iovec
;
611 pack
= eth_port
->etp_wr_pack
;
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
,
624 "eth_write_port: cpf_setgrant_direct failed: %d\n",
627 pack_size
+= iovec
[i
].iov_size
= pack_ptr
->acc_length
;
631 pack
= bf_pack(pack
); /* packet is too fragmented */
632 eth_port
->etp_wr_pack
= pack
;
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
,
645 "eth_write_port: cpf_setgrant_direct failed: %d\n",
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
,
657 (vir_bytes
)(i
* sizeof(iovec
[0])),
662 "eth_write_port: cpf_setgrant_direct failed: %d\n",
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
);
678 printf("eth_issue_send: send to %d failed: %d\n",
679 eth_port
->etp_osdep
.etp_task
, r
);
682 eth_port
->etp_osdep
.etp_state
= OEPS_SEND_SENT
;
685 PRIVATE
void write_int(eth_port
)
686 eth_port_t
*eth_port
;
692 pack
= eth_port
->etp_wr_pack
;
695 printf("write_int: strange no packet on eth port %d\n",
696 eth_port
-eth_port_table
);
697 eth_restart_write(eth_port
);
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
);
709 eth_arrive(eth_port
, pack
, bf_bufsize(pack
));
710 assert(no_ethWritePort
);
716 eth_restart_write(eth_port
);
719 PRIVATE
void read_int(eth_port
, count
)
720 eth_port_t
*eth_port
;
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",
734 else if (count
> ETH_MAX_PACK_SIZE_TAGGED
)
736 printf("mnx_eth`read_int: packet size too big (%d)\n",
742 cut_pack
= bf_cut(pack
, 0, count
);
745 assert(!no_ethWritePort
);
747 eth_arrive(eth_port
, cut_pack
, count
);
748 assert(no_ethWritePort
);
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
;
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
;
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
,
792 "mnx_eth`setup_read: cpf_setgrant_direct failed: %d\n",
795 iovec
[i
].iov_size
= (vir_bytes
)pack_ptr
->acc_length
;
799 r
= cpf_setgrant_direct(eth_port
->etp_osdep
.etp_rd_vec_grant
,
800 eth_port
->etp_osdep
.etp_task
,
802 (vir_bytes
)(i
* sizeof(iovec
[0])),
807 "mnx_eth`setup_read: cpf_setgrant_direct failed: %d\n",
811 mess1
.m_type
= DL_READV_S
;
812 mess1
.DL_PORT
= eth_port
->etp_osdep
.etp_port
;
813 mess1
.DL_PROC
= this_proc
;
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
;
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
)
837 eth_port_t
*eth_port
;
840 eth_port
= ev_arg
.ev_ptr
;
841 assert(ev
== ð_port
->etp_osdep
.etp_recvev
);
842 m_ptr
= ð_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
;
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
)
863 eth_port_t
*eth_port
;
866 eth_port
= ev_arg
.ev_ptr
;
867 assert(ev
== ð_port
->etp_sendev
);
868 m_ptr
= ð_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;
883 PRIVATE eth_port_t
*find_port(m
)
886 eth_port_t
*loc_port
;
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
)
895 assert (i
<eth_conf_nr
);
899 static void eth_restart(eth_port
, tasknr
)
900 eth_port_t
*eth_port
;
904 unsigned flags
, dl_flags
;
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
)
915 "eth_restart: task number did not change. Aborting restart\n");
918 eth_port
->etp_osdep
.etp_task
= tasknr
;
920 switch(eth_port
->etp_osdep
.etp_state
)
925 /* We can safely ignore the pending CONF, RECV, and SEND
928 eth_port
->etp_osdep
.etp_state
= OEPS_IDLE
;
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
;
937 /* If there is a pending GETSTAT request then we have to create a
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
);
951 "eth_restart: cpf_grant_direct failed: %d\n",
954 eth_port
->etp_osdep
.etp_stat_gid
= gid
;
957 flags
= eth_port
->etp_osdep
.etp_recvconf
;
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
);
975 "eth_restart: send to ethernet task %d failed: %d\n",
976 eth_port
->etp_osdep
.etp_task
, r
);
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
;
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
;
1013 ip_panic(( "eth_get_stat: asynsend failed: %d", r
));
1017 PRIVATE asynmsg_t
*msgtable
= NULL
;
1018 PRIVATE
size_t msgtable_n
= 0;
1020 PRIVATE
int asynsend(dst
, mp
)
1027 if (msgtable
== NULL
)
1029 printf("asynsend: allocating msg table\n");
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
)
1045 "asynsend: found completed entry %d with error %d\n",
1046 i
, msgtable
[i
].result
);
1050 if (flags
== AMF_EMPTY
)
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
1062 /* Tell the kernel to rescan the table */
1063 return senda(msgtable
, msgtable_n
);
1068 * $PchId: mnx_eth.c,v 1.16 2005/06/28 14:24:37 philip Exp $