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
) );
37 PUBLIC
void osdep_eth_init()
42 eth_port_t
*eth_port
, *rep
;
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
;
67 for (j
= 0; j
<IOVEC_NR
; j
++)
69 if (cpf_getgrants(&gid
, 1) != 1)
72 "osdep_eth_init: cpf_getgrants failed: %d\n",
75 eth_port
->etp_osdep
.etp_wr_iovec
[j
].iov_grant
= gid
;
77 if (cpf_getgrants(&gid
, 1) != 1)
80 "osdep_eth_init: cpf_getgrants failed: %d\n",
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)
89 "osdep_eth_init: cpf_getgrants failed: %d\n",
92 eth_port
->etp_osdep
.etp_rd_iovec
[j
].iov_grant
= gid
;
94 if (cpf_getgrants(&gid
, 1) != 1)
97 "osdep_eth_init: cpf_getgrants failed: %d\n",
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",
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.
115 printf("eth%d: unable to find task %s: %d\n",
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(ð_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
;
136 assert(eth_port
->etp_osdep
.etp_state
== OEPS_INIT
);
137 r
= asynsend(eth_port
->etp_osdep
.etp_task
, &mess
);
139 eth_port
->etp_osdep
.etp_state
= OEPS_CONF_SENT
;
143 "osdep_eth_init: unable to send to ethernet task, error= %d\n",
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;
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
))
175 eth_port
->etp_osdep
.etp_port
= ecp
->ec_port
;
176 eth_port
->etp_osdep
.etp_task
= ANY
;
177 ev_init(ð_port
->etp_osdep
.etp_recvev
);
179 rport
= eth_port
->etp_osdep
.etp_port
;
180 assert(rport
>= 0 && rport
< eth_conf_nr
);
181 rep
= ð_port_table
[rport
];
182 if (!(rep
->etp_flags
& EPF_ENABLED
))
185 "eth%d: underlying ethernet device %d not enabled",
189 if (rep
->etp_vlan
!= 0)
192 "eth%d: underlying ethernet device %d is a VLAN",
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
;
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
;
235 eth_issue_send(eth_port
);
239 PRIVATE
int notification_count
;
242 PUBLIC
void eth_rec(message
*m
)
244 int i
, r
, m_type
, stat
;
245 eth_port_t
*loc_port
, *vlan_port
;
247 struct eth_conf
*ecp
;
250 if (m_type
== DL_NAME_REPLY
)
252 drivername
= m
->m3_ca1
;
254 printf("eth_rec: got name: %s\n", drivername
);
256 notification_count
= 0;
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
))
266 if (strcmp(ecp
->ec_task
, drivername
) != 0)
271 eth_restart(loc_port
, m
->m_source
);
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
)
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
);
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
)
300 if (stat
& DL_PACK_RECV
)
301 read_int(loc_port
, m
->DL_COUNT
);
305 if (m_type
!= DL_CONF_REPLY
)
308 "eth_rec: got bad message type 0x%x from %d in CONF state\n",
309 m_type
, m
->m_source
);
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
);
324 ip_panic(("eth_rec: DL_INIT returned error %d\n", r
));
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
;
337 printf("eth_rec: calling eth_restart_ioctl\n");
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
;
345 if (!(vlan_port
->etp_flags
& EPF_ENABLED
))
347 if (vlan_port
->etp_vlan_port
!= loc_port
)
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
);
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");
375 if (loc_port
->etp_osdep
.etp_state
== OEPS_GETSTAT_SENT
)
377 if (m_type
!= DL_STAT_REPLY
)
380 "eth_rec: got bad message type 0x%x from %d in GETSTAT state\n",
381 m_type
, m
->m_source
);
388 ip_warning(("eth_rec: DL_STAT returned error %d\n",
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
;
402 assert(loc_port
->etp_flags
& EPF_GOT_ADDR
);
403 eth_restart_ioctl(loc_port
);
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");
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
);
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
);
440 stat
= m
->DL_STAT
& 0xffff;
443 if (!(stat
& (DL_PACK_SEND
|DL_PACK_RECV
)))
444 printf("eth_rec: neither DL_PACK_SEND nor DL_PACK_RECV\n");
446 if (stat
& DL_PACK_SEND
)
448 if (stat
& DL_PACK_RECV
)
452 printf("eth_rec: eth%d got DL_PACK_RECV\n",
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
)
489 if (notification_count
< 100)
491 notification_count
++;
492 printf("eth_check_drivers: got a notification #%d from %d\n",
493 notification_count
, tasknr
);
497 m
->m_type
= DL_GETNAME
;
498 r
= asynsend(tasknr
, m
);
501 printf("eth_check_drivers: asynsend to %d failed: %d\n",
507 PUBLIC
int eth_get_stat(eth_port
, eth_stat
)
508 eth_port_t
*eth_port
;
509 eth_stat_t
*eth_stat
;
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
);
522 ip_panic(( "eth_get_stat: cpf_grant_direct failed: %d\n",
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
;
535 send_getstat(eth_port
);
540 PUBLIC
void eth_set_rec_conf (eth_port
, flags
)
541 eth_port_t
*eth_port
;
545 unsigned dl_flags
, mask
;
548 assert(!eth_port
->etp_vlan
);
550 if (!(eth_port
->etp_flags
& EPF_GOT_ADDR
))
552 /* We have never seen the device. */
554 printf("eth_set_rec_conf: waiting for device to appear\n");
559 if (eth_port
->etp_osdep
.etp_state
!= OEPS_IDLE
)
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
;
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 */
575 eth_port
->etp_osdep
.etp_recvconf
= flags
;
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
;
595 printf("eth_set_rec_conf: asynsend to %d failed: %d\n",
596 eth_port
->etp_osdep
.etp_task
, r
);
601 PRIVATE
void eth_issue_send(eth_port
)
602 eth_port_t
*eth_port
;
605 acc_t
*pack
, *pack_ptr
;
609 iovec
= eth_port
->etp_osdep
.etp_wr_iovec
;
610 pack
= eth_port
->etp_wr_pack
;
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
,
623 "eth_write_port: cpf_setgrant_direct failed: %d\n",
626 pack_size
+= iovec
[i
].iov_size
= pack_ptr
->acc_length
;
630 pack
= bf_pack(pack
); /* packet is too fragmented */
631 eth_port
->etp_wr_pack
= pack
;
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
,
644 "eth_write_port: cpf_setgrant_direct failed: %d\n",
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
,
656 (vir_bytes
)(i
* sizeof(iovec
[0])),
661 "eth_write_port: cpf_setgrant_direct failed: %d\n",
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
);
677 printf("eth_issue_send: send to %d failed: %d\n",
678 eth_port
->etp_osdep
.etp_task
, r
);
681 eth_port
->etp_osdep
.etp_state
= OEPS_SEND_SENT
;
684 PRIVATE
void write_int(eth_port
)
685 eth_port_t
*eth_port
;
691 pack
= eth_port
->etp_wr_pack
;
694 printf("write_int: strange no packet on eth port %d\n",
695 eth_port
-eth_port_table
);
696 eth_restart_write(eth_port
);
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
);
708 eth_arrive(eth_port
, pack
, bf_bufsize(pack
));
709 assert(no_ethWritePort
);
715 eth_restart_write(eth_port
);
718 PRIVATE
void read_int(eth_port
, count
)
719 eth_port_t
*eth_port
;
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",
733 else if (count
> ETH_MAX_PACK_SIZE_TAGGED
)
735 printf("mnx_eth`read_int: packet size too big (%d)\n",
741 cut_pack
= bf_cut(pack
, 0, count
);
744 assert(!no_ethWritePort
);
746 eth_arrive(eth_port
, cut_pack
, count
);
747 assert(no_ethWritePort
);
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
;
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
;
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
,
789 "mnx_eth`setup_read: cpf_setgrant_direct failed: %d\n",
792 iovec
[i
].iov_size
= (vir_bytes
)pack_ptr
->acc_length
;
796 r
= cpf_setgrant_direct(eth_port
->etp_osdep
.etp_rd_vec_grant
,
797 eth_port
->etp_osdep
.etp_task
,
799 (vir_bytes
)(i
* sizeof(iovec
[0])),
804 "mnx_eth`setup_read: cpf_setgrant_direct failed: %d\n",
808 mess1
.m_type
= DL_READV_S
;
809 mess1
.DL_PORT
= eth_port
->etp_osdep
.etp_port
;
810 mess1
.DL_PROC
= this_proc
;
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
;
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
)
834 eth_port_t
*eth_port
;
837 eth_port
= ev_arg
.ev_ptr
;
838 assert(ev
== ð_port
->etp_osdep
.etp_recvev
);
839 m_ptr
= ð_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
;
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
)
860 eth_port_t
*eth_port
;
863 eth_port
= ev_arg
.ev_ptr
;
864 assert(ev
== ð_port
->etp_sendev
);
865 m_ptr
= ð_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;
880 PRIVATE eth_port_t
*find_port(m
)
883 eth_port_t
*loc_port
;
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
)
892 assert (i
<eth_conf_nr
);
896 static void eth_restart(eth_port
, tasknr
)
897 eth_port_t
*eth_port
;
901 unsigned flags
, dl_flags
;
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
)
914 "eth_restart: task number did not change. Aborting restart\n");
917 eth_port
->etp_osdep
.etp_task
= tasknr
;
919 switch(eth_port
->etp_osdep
.etp_state
)
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
;
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
;
938 /* If there is a pending GETSTAT request then we have to create a
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
);
952 "eth_restart: cpf_grant_direct failed: %d\n",
955 eth_port
->etp_osdep
.etp_stat_gid
= gid
;
958 flags
= eth_port
->etp_osdep
.etp_recvconf
;
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
);
976 "eth_restart: send to ethernet task %d failed: %d\n",
977 eth_port
->etp_osdep
.etp_task
, r
);
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
;
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
;
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 $