1 /*
2 inet/mnx_eth.c
3
4 Created: Jan 2, 1992 by Philip Homburg
5 */
6
7 #include "inet.h"
8 #include "proto.h"
9 #include "generic/assert.h"
10 #include "generic/buf.h"
11 #include "osdep_eth.h"
12 #include "generic/clock.h"
13 #include "generic/eth.h"
14 #include "generic/eth_int.h"
15 #include "generic/sr.h"
16
17 INIT_PANIC();
18
19 FORWARD _PROTOTYPE( void setup_read, (eth_port_t *eth_port) );
20 FORWARD _PROTOTYPE( int do_sendrec, (int task, message *m1, message *m2) );
21 FORWARD _PROTOTYPE( void read_int, (eth_port_t *eth_port, int count) );
22 FORWARD _PROTOTYPE( void write_int, (eth_port_t *eth_port) );
23
24 PUBLIC void eth_init0()
25 {
26 int result;
27 eth_port_t *eth_port;
28 static message mess, repl_mess;
29
30 eth_port= ð_port_table[0];
31
32 eth_port->etp_osdep.etp_port= 0;
33 eth_port->etp_osdep.etp_task= DL_ETH;
34 eth_port->etp_osdep.etp_minor= ETH_DEV;
35
36 #if XXX
37 mess.m_type= DL_STOP;
38 mess.DL_PORT= eth_port->etp_osdep.etp_port;
39 #if DEBUG & 256
40 { where(); printf("sending DL_STOP\n"); }
41 #endif
42 assert (eth_port->etp_osdep.etp_task != MM_PROC_NR);
43 result= send(eth_port->etp_osdep.etp_task, &mess);
44 if (result < 0)
45 {
46 printf("send failed with error %d\n",result);
47 printf("eth_init0: unable to stop ethernet task\n");
48 return;
49 }
50 #endif
51
52 #if DEBUG & 256
53 { where(); printf("sending DL_INIT\n"); }
54 #endif
55 mess.m_type= DL_INIT;
56 mess.DL_PORT= eth_port->etp_osdep.etp_port;
57 mess.DL_PROC= THIS_PROC;
58 mess.DL_MODE= DL_NOMODE;
59 assert (eth_port->etp_osdep.etp_task != MM_PROC_NR);
60 result= send(eth_port->etp_osdep.etp_task, &mess);
61 if (result<0)
62 {
63 printf(
64 "eth_init0: unable to send to ethernet task, error= %d\n",
65 result);
66 return;
67 }
68
69 if (receive(eth_port->etp_osdep.etp_task, &mess)<0)
70 ip_panic(("unable to receive"));
71
72 if (mess.m3_i1 != eth_port->etp_osdep.etp_port)
73 {
74 printf("eth_init0: got reply for wrong port\n");
75 return;
76 }
77
78 eth_port->etp_ethaddr= *(ether_addr_t *)mess.m3_ca1;
79
80 if (sr_add_minor (eth_port->etp_osdep.etp_minor,
81 eth_port- eth_port_table, eth_open, eth_close, eth_read,
82 eth_write, eth_ioctl, eth_cancel)<0)
83 ip_panic(("can't sr_init"));
84
85 eth_port->etp_flags |= EPF_ENABLED;
86 eth_port->etp_wr_pack= 0;
87 eth_port->etp_rd_pack= 0;
88 setup_read (eth_port);
89 }
90
91 PUBLIC void eth_write_port(eth_port)
92 eth_port_t *eth_port;
93 {
94 static message mess1, mess2;
95 int i, pack_size, result;
96 acc_t *pack, *pack_ptr;
97 iovec_t *iovec;
98
99 #if DEBUG & 256
100 { where(); bf_check_all_bufs(); }
101 #endif
102 #if DEBUG & 256
103 { where(); printf("send_packet(ð_port_table[%d], ..) called\n",
104 eth_port-eth_port_table); }
105 #endif
106 assert (!(eth_port->etp_flags & EPF_WRITE_IP));
107
108 eth_port->etp_flags |= EPF_WRITE_IP;
109
110 pack= eth_port->etp_wr_pack;
111 eth_port->etp_wr_pack= 0;
112
113 iovec= eth_port->etp_osdep.etp_wr_iovec;
114 pack_size= 0;
115 #if DEBUG & 256
116 { where(); printf("bf_bufsize= %d\n", bf_bufsize(pack)); }
117 #endif
118 for (i=0, pack_ptr= pack; i<IOVEC_NR && pack_ptr; i++,
119 pack_ptr= pack_ptr->acc_next)
120 {
121 iovec[i].iov_addr= (vir_bytes)ptr2acc_data(
122 pack_ptr);
123 pack_size += iovec[i].iov_size=
124 pack_ptr->acc_length;
125 }
126 if (i>= IOVEC_NR)
127 {
128 #if DEBUG
129 { where(); printf("compacting fragment\n"); }
130 #endif
131 pack= bf_pack(pack); /* packet is too fragmented */
132 pack_size= 0;
133 for (i=0, pack_ptr= pack; i<IOVEC_NR &&
134 pack_ptr; i++, pack_ptr= pack_ptr->
135 acc_next)
136 {
137 iovec[i].iov_addr= (vir_bytes)
138 ptr2acc_data(pack_ptr);
139 pack_size += iovec[i].iov_size=
140 pack_ptr->acc_length;
141 }
142 }
143 #if DEBUG & 256
144 { where(); printf("bf_bufsize= %d\n", bf_bufsize(pack));
145 where(); printf("i= %d\n", i); }
146 #endif
147 assert (i< IOVEC_NR);
148 assert (pack_size >= ETH_MIN_PACK_SIZE);
149
150 if (i==1)
151 /* simple packets can be sent using DL_WRITE instead of DL_WRITEV */
152 {
153 mess1.DL_COUNT= iovec[0].iov_size;
154 mess1.DL_ADDR= (char *)iovec[0].iov_addr;
155 mess1.m_type= DL_WRITE;
156 }
157 else
158 {
159 mess1.DL_COUNT= i;
160 mess1.DL_ADDR= (char *)iovec;
161 mess1.m_type= DL_WRITEV;
162 }
163 mess1.DL_PORT= eth_port->etp_osdep.etp_port;
164 mess1.DL_PROC= THIS_PROC;
165 mess1.DL_MODE= DL_NOMODE;
166
167 #if DEBUG & 256
168 { where(); printf("calling do_sendrec\n"); }
169 #endif
170 assert (eth_port->etp_osdep.etp_task != MM_PROC_NR);
171 result= do_sendrec (eth_port->etp_osdep.etp_task, &mess1, &mess2);
172 #if DEBUG & 256
173 { where(); printf("do_sendrec done\n"); }
174 #endif
175
176 #if DEBUG & 256
177 { where(); printf("got reply from DLL\n"); }
178 #endif
179 #if DEBUG
180 if (mess1.m_type != DL_TASK_REPLY)
181 { where(); printf("wrong m_type (=%d)\n", mess1.m_type); }
182 if (mess1.DL_PORT != eth_port->etp_osdep.etp_port)
183 { where(); printf("wrong DL_PORT (=%d)\n", mess1.DL_PORT); }
184 if (mess1.DL_PROC != THIS_PROC)
185 { where(); printf("wrong DL_PROC (=%d)\n", mess1.DL_PROC); }
186 #endif
187
188 assert (mess1.m_type == DL_TASK_REPLY && mess1.DL_PORT == mess1.DL_PORT &&
189 mess1.DL_PROC == THIS_PROC);
190
191 assert((mess1.DL_STAT >> 16) == OK);
192
193 if (!(mess1.DL_STAT & DL_PACK_SEND))
194 /* packet is not sent, suspend */
195 {
196 #if DEBUG & 256
197 { where(); printf("setting EPF_WRITE_SP\n"); }
198 #endif
199 eth_port->etp_flags |= EPF_WRITE_SP;
200 eth_port->etp_wr_pack= pack;
201 }
202 else
203 /* packet is sent */
204 {
205 eth_port->etp_flags &= ~EPF_WRITE_IP;
206 eth_arrive(eth_port, pack);
207 #if DEBUG & 256
208 { where(); printf("write done\n"); }
209 #endif
210 }
211
212 if (result == 1) /* got an INT_TASK */
213 {
214 assert(mess2.DL_STAT == DL_PACK_RECV);
215 assert(!(mess1.DL_STAT & DL_PACK_RECV));
216 compare(mess2.DL_PORT, ==, eth_port->etp_osdep.etp_port);
217 compare(mess2.DL_PROC, ==, THIS_PROC);
218 read_int(eth_port, mess2.DL_COUNT);
219 }
220 else if (mess1.DL_STAT & DL_PACK_RECV)
221 {
222 read_int(eth_port, mess1.DL_COUNT);
223 }
224 }
225
226 PUBLIC void eth_rec(m)
227 message *m;
228 {
229 int i;
230 eth_port_t *loc_port;
231 int stat;
232
233 assert (m->m_source == DL_ETH);
234
235 set_time (m->DL_CLCK);
236
237 for (i=0, loc_port= eth_port_table; i<ETH_PORT_NR; i++, loc_port++)
238 {
239 if (loc_port->etp_osdep.etp_port == m->DL_PORT &&
240 loc_port->etp_osdep.etp_task == m->m_source)
241 break;
242 }
243
244 assert (i<ETH_PORT_NR);
245
246 stat= m->DL_STAT & 0xffff;
247
248 assert(stat & (DL_PACK_SEND|DL_PACK_RECV));
249 if (stat & DL_PACK_SEND)
250 {
251 write_int(loc_port);
252 }
253 if (stat & DL_PACK_RECV)
254 {
255 read_int(loc_port, m->DL_COUNT);
256 }
257 }
258
259 PUBLIC int eth_get_stat(eth_port, eth_stat)
260 eth_port_t *eth_port;
261 eth_stat_t *eth_stat;
262 {
263 acc_t *acc;
264 int result;
265 static message mess, mlocked;
266
267 #if DEBUG
268 { where(); printf("eth_get_stat called\n"); }
269 #endif
270 mess.m_type= DL_GETSTAT;
271 mess.DL_PORT= eth_port->etp_osdep.etp_port;
272 mess.DL_PROC= THIS_PROC;
273 mess.DL_ADDR= (char *)eth_stat;
274
275 for (;;)
276 {
277 assert (eth_port->etp_osdep.etp_task != MM_PROC_NR);
278 result= send(eth_port->etp_osdep.etp_task, &mess);
279 if (result != ELOCKED)
280 break;
281 result= receive(eth_port->etp_osdep.etp_task, &mlocked);
282 assert(result == OK);
283 #if DEBUG
284 { where(); printf("calling eth_rec()\n"); }
285 #endif
286 eth_rec(&mlocked);
287 }
288 assert(result == OK);
289
290 result= receive(eth_port->etp_osdep.etp_task, &mess);
291 assert(result == OK);
292 assert(mess.m_type == DL_TASK_REPLY);
293
294 result= mess.DL_STAT >> 16;
295 assert (result == 0);
296
297 if (mess.DL_STAT)
298 {
299 #if DEBUG
300 { where(); printf("calling eth_rec()\n"); }
301 #endif
302 eth_rec(&mess);
303 }
304 return OK;
305 }
306
307 PUBLIC void eth_set_rec_conf (eth_port, flags)
308 eth_port_t *eth_port;
309 u32_t flags;
310 {
311 int result;
312 unsigned dl_flags;
313 static message mess, repl_mess;
314
315 #if DEBUG
316 { where(); printf("eth_chk_rec_conf(ð_port_table[%d])\n",
317 eth_port-eth_port_table); }
318 #endif
319 dl_flags= DL_NOMODE;
320 if (flags & NWEO_EN_BROAD)
321 dl_flags |= DL_BROAD_REQ;
322 if (flags & NWEO_EN_MULTI)
323 dl_flags |= DL_MULTI_REQ;
324 if (flags & NWEO_EN_PROMISC)
325 dl_flags |= DL_PROMISC_REQ;
326
327 mess.m_type= DL_INIT;
328 mess.DL_PORT= eth_port->etp_osdep.etp_port;
329 mess.DL_PROC= THIS_PROC;
330 mess.DL_MODE= dl_flags;
331
332 do
333 {
334 assert (eth_port->etp_osdep.etp_task != MM_PROC_NR);
335 result= send (eth_port->etp_osdep.etp_task, &mess);
336 if (result == ELOCKED) /* etp_task is sending to this task,
337 I hope */
338 {
339 if (receive (eth_port->etp_osdep.etp_task,
340 &repl_mess)< 0)
341 ip_panic(("unable to receive"));
342 #if DEBUG
343 { where(); printf("calling eth_rec\n"); }
344 #endif
345 eth_rec(&repl_mess);
346 }
347 } while (result == ELOCKED);
348
349 if (result < 0)
350 ip_panic(("unable to send(%d)", result));
351
352 if (receive (eth_port->etp_osdep.etp_task, &repl_mess) < 0)
353 ip_panic(("unable to receive"));
354
355 assert (repl_mess.m_type == DL_INIT_REPLY);
356 if (repl_mess.m3_i1 != eth_port->etp_osdep.etp_port)
357 {
358 ip_panic(("got reply for wrong port"));
359 return;
360 }
361 }
362
363 PRIVATE int do_sendrec (tofrom, mptr1, mptr2)
364 int tofrom;
365 message *mptr1;
366 message *mptr2;
367 {
368 int result;
369 int extra;
370
371 assert (tofrom != MM_PROC_NR);
372 result= send (tofrom, mptr1);
373 if (result == ELOCKED)
374 {
375 /* ethernet task is sending to this task, I hope */
376 result= receive(tofrom, mptr2);
377
378 if (result < 0)
379 ip_panic(("unable to receive"));
380 extra= 1;
381 assert (tofrom != MM_PROC_NR);
382 result= send (tofrom, mptr1);
383 }
384 else
385 extra= 0;
386
387 if (result < 0)
388 ip_panic(("unable to send"));
389
390 result= receive (tofrom, mptr1);
391 if (result < 0)
392 ip_panic(("unable to receive"));
393
394 assert (mptr1->m_type == DL_TASK_REPLY);
395 return extra;
396 }
397
398 PRIVATE void write_int(eth_port)
399 eth_port_t *eth_port;
400 {
401 acc_t *pack;
402
403 #if DEBUG & 256
404 { where(); printf("write_int called\n"); }
405 #endif
406
407 assert(eth_port->etp_flags & (EPF_WRITE_IP|EPF_WRITE_SP) ==
408 (EPF_WRITE_IP|EPF_WRITE_SP));
409
410 pack= eth_port->etp_wr_pack;
411 eth_port->etp_wr_pack= NULL;
412 eth_arrive(eth_port, pack);
413 eth_port->etp_flags &= ~(EPF_WRITE_IP|EPF_WRITE_SP);
414 while (eth_get_work(eth_port))
415 ;
416 }
417
418 PRIVATE void read_int(eth_port, count)
419 eth_port_t *eth_port;
420 int count;
421 {
422 acc_t *pack, *cut_pack;
423
424 pack= eth_port->etp_rd_pack;
425 eth_port->etp_rd_pack= NULL;
426
427 cut_pack= bf_cut(pack, 0, count);
428 bf_afree(pack);
429
430 eth_arrive(eth_port, cut_pack);
431
432 if (!(eth_port->etp_flags & EPF_READ_SP))
433 {
434 eth_port->etp_flags &= ~EPF_READ_IP;
435 return;
436 }
437 eth_port->etp_flags &= ~(EPF_READ_IP|EPF_READ_SP);
438 setup_read(eth_port);
439 }
440
441 PRIVATE void setup_read(eth_port)
442 eth_port_t *eth_port;
443 {
444 acc_t *pack, *pack_ptr;
445 static message mess1, mess2;
446 iovec_t *iovec;
447 int i, result;
448
449 assert(!(eth_port->etp_flags & (EPF_READ_IP|EPF_READ_SP)));
450
451 do
452 {
453
454 assert (!eth_port->etp_rd_pack);
455
456 iovec= eth_port->etp_osdep.etp_rd_iovec;
457 pack= bf_memreq (ETH_MAX_PACK_SIZE);
458
459 for (i=0, pack_ptr= pack; i<RD_IOVEC && pack_ptr;
460 i++, pack_ptr= pack_ptr->acc_next)
461 {
462 iovec[i].iov_addr= (vir_bytes)ptr2acc_data(pack_ptr);
463 iovec[i].iov_size= (vir_bytes)pack_ptr->acc_length;
464 #if DEBUG & 256
465 { where(); printf("filling iovec[%d] with iov_addr= %x, iov_size= %x\n",
466 i, iovec[i].iov_addr, iovec[i].iov_size); }
467 #endif
468 }
469
470 assert (!pack_ptr);
471
472 mess1.m_type= DL_READV;
473 mess1.DL_PORT= eth_port->etp_osdep.etp_port;
474 mess1.DL_PROC= THIS_PROC;
475 mess1.DL_COUNT= i;
476 mess1.DL_ADDR= (char *)iovec;
477
478 result= do_sendrec (eth_port->etp_osdep.etp_task, &mess1,
479 &mess2);
480
481 #if DEBUG
482 if (mess1.m_type != DL_TASK_REPLY)
483 { where(); printf("wrong m_type (=%d)\n", mess1.m_type); }
484 if (mess1.DL_PORT != mess1.DL_PORT)
485 { where(); printf("wrong DL_PORT (=%d)\n", mess1.DL_PORT); }
486 if (mess1.DL_PROC != THIS_PROC)
487 { where(); printf("wrong DL_PROC (=%d)\n", mess1.DL_PROC); }
488 #endif
489
490 assert (mess1.m_type == DL_TASK_REPLY && mess1.DL_PORT == mess1.DL_PORT &&
491 mess1.DL_PROC == THIS_PROC);
492 compare((mess1.DL_STAT >> 16), ==, OK);
493
494 if (mess1.DL_STAT & DL_PACK_RECV)
495 /* packet received */
496 {
497 pack_ptr= bf_cut(pack, 0, mess1.DL_COUNT);
498 bf_afree(pack);
499
500 assert(!(eth_port->etp_flags & EPF_READ_IP));
501 eth_arrive(eth_port, pack_ptr);
502 assert(!(eth_port->etp_flags & EPF_READ_IP));
503 }
504 else
505 /* no packet received */
506 {
507 eth_port->etp_rd_pack= pack;
508 eth_port->etp_flags |= EPF_READ_IP;
509 }
510
511 if (result == 1) /* got an INT_TASK */
512 {
513 assert(mess2.DL_STAT == DL_PACK_SEND);
514 assert(!(mess1.DL_STAT & DL_PACK_SEND));
515 assert (mess2.DL_PORT == mess2.DL_PORT &&
516 mess2.DL_PROC == THIS_PROC);
517 write_int(eth_port);
518 }
519 else if (mess1.DL_STAT & DL_PACK_SEND)
520 {
521 write_int(eth_port);
522 }
523 } while (!(eth_port->etp_flags & EPF_READ_IP));
524 eth_port->etp_flags |= EPF_READ_SP;
525 }
526
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.