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
,
35 endpoint_t endpoint
) );
36 FORWARD
_PROTOTYPE( void send_getstat
, (eth_port_t
*eth_port
) );
38 PUBLIC
void osdep_eth_init()
42 eth_port_t
*eth_port
, *rep
;
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
;
66 for (j
= 0; j
<IOVEC_NR
; j
++)
68 if (cpf_getgrants(&gid
, 1) != 1)
71 "osdep_eth_init: cpf_getgrants failed: %d\n",
74 eth_port
->etp_osdep
.etp_wr_iovec
[j
].iov_grant
= gid
;
76 if (cpf_getgrants(&gid
, 1) != 1)
79 "osdep_eth_init: cpf_getgrants failed: %d\n",
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)
88 "osdep_eth_init: cpf_getgrants failed: %d\n",
91 eth_port
->etp_osdep
.etp_rd_iovec
[j
].iov_grant
= gid
;
93 if (cpf_getgrants(&gid
, 1) != 1)
96 "osdep_eth_init: cpf_getgrants failed: %d\n",
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(ð_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
))
125 eth_port
->etp_osdep
.etp_port
= ecp
->ec_port
;
126 eth_port
->etp_osdep
.etp_task
= ANY
;
127 ev_init(ð_port
->etp_osdep
.etp_recvev
);
129 rport
= eth_port
->etp_osdep
.etp_port
;
130 assert(rport
>= 0 && rport
< eth_conf_nr
);
131 rep
= ð_port_table
[rport
];
132 if (!(rep
->etp_flags
& EPF_ENABLED
))
135 "eth%d: underlying ethernet device %d not enabled",
139 if (rep
->etp_vlan
!= 0)
142 "eth%d: underlying ethernet device %d is a VLAN",
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
;
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
;
185 eth_issue_send(eth_port
);
189 PRIVATE
int notification_count
;
192 PUBLIC
void eth_rec(message
*m
)
194 int i
, r
, m_type
, stat
;
195 eth_port_t
*loc_port
, *vlan_port
;
197 struct eth_conf
*ecp
;
200 if (m_type
== DL_NAME_REPLY
)
202 drivername
= m
->m3_ca1
;
204 printf("eth_rec: got name: %s\n", drivername
);
206 notification_count
= 0;
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
))
216 if (strcmp(ecp
->ec_task
, drivername
) != 0)
221 eth_restart(loc_port
, m
->m_source
);
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
)
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
);
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
)
250 if (stat
& DL_PACK_RECV
)
251 read_int(loc_port
, m
->DL_COUNT
);
255 if (m_type
!= DL_CONF_REPLY
)
258 "eth_rec: got bad message type 0x%x from %d in CONF state\n",
259 m_type
, m
->m_source
);
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
);
274 ip_panic(("eth_rec: DL_INIT returned error %d\n", r
));
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
;
287 printf("eth_rec: calling eth_restart_ioctl\n");
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
;
295 if (!(vlan_port
->etp_flags
& EPF_ENABLED
))
297 if (vlan_port
->etp_vlan_port
!= loc_port
)
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
);
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");
325 if (loc_port
->etp_osdep
.etp_state
== OEPS_GETSTAT_SENT
)
327 if (m_type
!= DL_STAT_REPLY
)
330 "eth_rec: got bad message type 0x%x from %d in GETSTAT state\n",
331 m_type
, m
->m_source
);
338 ip_warning(("eth_rec: DL_STAT returned error %d\n",
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
;
352 assert(loc_port
->etp_flags
& EPF_GOT_ADDR
);
353 eth_restart_ioctl(loc_port
);
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");
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
);
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
);
390 stat
= m
->DL_STAT
& 0xffff;
393 if (!(stat
& (DL_PACK_SEND
|DL_PACK_RECV
)))
394 printf("eth_rec: neither DL_PACK_SEND nor DL_PACK_RECV\n");
396 if (stat
& DL_PACK_SEND
)
398 if (stat
& DL_PACK_RECV
)
402 printf("eth_rec: eth%d got DL_PACK_RECV\n",
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
)
425 printf("eth_rec: OEPF_NEED_CONF is set\n");
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
)
440 m
.m_type
= DL_GETNAME
;
441 r
= asynsend(endpoint
, &m
);
444 printf("eth_check_driver: asynsend to %d failed: %d\n",
450 PUBLIC
int eth_get_stat(eth_port
, eth_stat
)
451 eth_port_t
*eth_port
;
452 eth_stat_t
*eth_stat
;
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
);
465 ip_panic(( "eth_get_stat: cpf_grant_direct failed: %d\n",
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
;
478 send_getstat(eth_port
);
483 PUBLIC
void eth_set_rec_conf (eth_port
, flags
)
484 eth_port_t
*eth_port
;
488 unsigned dl_flags
, mask
;
491 assert(!eth_port
->etp_vlan
);
493 if (!(eth_port
->etp_flags
& EPF_GOT_ADDR
))
495 /* We have never seen the device. */
497 printf("eth_set_rec_conf: waiting for device to appear\n");
502 if (eth_port
->etp_osdep
.etp_state
!= OEPS_IDLE
)
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
;
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 */
518 eth_port
->etp_osdep
.etp_recvconf
= flags
;
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
;
538 printf("eth_set_rec_conf: asynsend to %d failed: %d\n",
539 eth_port
->etp_osdep
.etp_task
, r
);
544 PRIVATE
void eth_issue_send(eth_port
)
545 eth_port_t
*eth_port
;
548 acc_t
*pack
, *pack_ptr
;
552 iovec
= eth_port
->etp_osdep
.etp_wr_iovec
;
553 pack
= eth_port
->etp_wr_pack
;
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
,
566 "eth_write_port: cpf_setgrant_direct failed: %d\n",
569 pack_size
+= iovec
[i
].iov_size
= pack_ptr
->acc_length
;
573 pack
= bf_pack(pack
); /* packet is too fragmented */
574 eth_port
->etp_wr_pack
= pack
;
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
,
587 "eth_write_port: cpf_setgrant_direct failed: %d\n",
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
,
599 (vir_bytes
)(i
* sizeof(iovec
[0])),
604 "eth_write_port: cpf_setgrant_direct failed: %d\n",
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
);
620 printf("eth_issue_send: send to %d failed: %d\n",
621 eth_port
->etp_osdep
.etp_task
, r
);
624 eth_port
->etp_osdep
.etp_state
= OEPS_SEND_SENT
;
627 PRIVATE
void write_int(eth_port_t
*eth_port
)
633 pack
= eth_port
->etp_wr_pack
;
636 printf("write_int: strange no packet on eth port %d\n",
637 eth_port
-eth_port_table
);
638 eth_restart_write(eth_port
);
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
);
650 eth_arrive(eth_port
, pack
, bf_bufsize(pack
));
651 assert(no_ethWritePort
);
657 eth_restart_write(eth_port
);
660 PRIVATE
void read_int(eth_port
, count
)
661 eth_port_t
*eth_port
;
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",
675 else if (count
> ETH_MAX_PACK_SIZE_TAGGED
)
677 printf("mnx_eth`read_int: packet size too big (%d)\n",
683 cut_pack
= bf_cut(pack
, 0, count
);
686 assert(!no_ethWritePort
);
688 eth_arrive(eth_port
, cut_pack
, count
);
689 assert(no_ethWritePort
);
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
;
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
;
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
,
731 "mnx_eth`setup_read: cpf_setgrant_direct failed: %d\n",
734 iovec
[i
].iov_size
= (vir_bytes
)pack_ptr
->acc_length
;
738 r
= cpf_setgrant_direct(eth_port
->etp_osdep
.etp_rd_vec_grant
,
739 eth_port
->etp_osdep
.etp_task
,
741 (vir_bytes
)(i
* sizeof(iovec
[0])),
746 "mnx_eth`setup_read: cpf_setgrant_direct failed: %d\n",
750 mess1
.m_type
= DL_READV_S
;
751 mess1
.DL_PORT
= eth_port
->etp_osdep
.etp_port
;
752 mess1
.DL_PROC
= this_proc
;
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
;
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
)
776 eth_port_t
*eth_port
;
779 eth_port
= ev_arg
.ev_ptr
;
780 assert(ev
== ð_port
->etp_osdep
.etp_recvev
);
781 m_ptr
= ð_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
;
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
)
802 eth_port_t
*eth_port
;
805 eth_port
= ev_arg
.ev_ptr
;
806 assert(ev
== ð_port
->etp_sendev
);
807 m_ptr
= ð_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;
822 PRIVATE eth_port_t
*find_port(m
)
825 eth_port_t
*loc_port
;
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
)
834 assert (i
<eth_conf_nr
);
838 static void eth_restart(eth_port_t
*eth_port
, endpoint_t endpoint
)
841 unsigned flags
, dl_flags
;
845 eth_port
->etp_osdep
.etp_task
= endpoint
;
847 switch(eth_port
->etp_osdep
.etp_state
)
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
;
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
;
866 /* If there is a pending GETSTAT request then we have to create a
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
);
880 "eth_restart: cpf_grant_direct failed: %d\n",
883 eth_port
->etp_osdep
.etp_stat_gid
= gid
;
886 flags
= eth_port
->etp_osdep
.etp_recvconf
;
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
);
904 "eth_restart: send to ethernet task %d failed: %d\n",
905 eth_port
->etp_osdep
.etp_task
, r
);
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
;
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
;
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 $