1 #include "u.h"
2 #include "../port/lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "fns.h"
6 #include "../port/error.h"
7
8 #include "../port/netif.h"
9
10 #include "etherif.h"
11
12 /* 9k compatibility */
13 #define devno dev
14 #define iq in
15
16 static Ether *etherxx[MaxEther];
17
18 Chan*
etherattach(char * spec)19 etherattach(char* spec)
20 {
21 int ctlrno;
22 char *p;
23 Chan *chan;
24
25 ctlrno = 0;
26 if(spec && *spec){
27 ctlrno = strtoul(spec, &p, 0);
28 if((ctlrno == 0 && p == spec) || *p != 0)
29 error(Ebadarg);
30 if(ctlrno < 0 || ctlrno >= MaxEther)
31 error(Ebadarg);
32 }
33 if(etherxx[ctlrno] == 0)
34 error(Enodev);
35
36 chan = devattach('l', spec);
37 if(waserror()){
38 chanfree(chan);
39 nexterror();
40 }
41 chan->devno = ctlrno;
42 if(etherxx[ctlrno]->attach)
43 etherxx[ctlrno]->attach(etherxx[ctlrno]);
44 poperror();
45 return chan;
46 }
47
48 static Walkqid*
etherwalk(Chan * chan,Chan * nchan,char ** name,int nname)49 etherwalk(Chan* chan, Chan* nchan, char** name, int nname)
50 {
51 return netifwalk(etherxx[chan->devno], chan, nchan, name, nname);
52 }
53
54 static int
etherstat(Chan * chan,uchar * dp,int n)55 etherstat(Chan* chan, uchar* dp, int n)
56 {
57 return netifstat(etherxx[chan->devno], chan, dp, n);
58 }
59
60 static Chan*
etheropen(Chan * chan,int omode)61 etheropen(Chan* chan, int omode)
62 {
63 return netifopen(etherxx[chan->devno], chan, omode);
64 }
65
66 static void
ethercreate(Chan *,char *,int,ulong)67 ethercreate(Chan*, char*, int, ulong)
68 {
69 }
70
71 static void
etherclose(Chan * chan)72 etherclose(Chan* chan)
73 {
74 netifclose(etherxx[chan->devno], chan);
75 }
76
77 static long
etherread(Chan * chan,void * buf,long n,vlong off)78 etherread(Chan* chan, void* buf, long n, vlong off)
79 {
80 Ether *ether;
81 ulong offset = off;
82
83 ether = etherxx[chan->devno];
84 if((chan->qid.type & QTDIR) == 0 && ether->ifstat){
85 /*
86 * With some controllers it is necessary to reach
87 * into the chip to extract statistics.
88 */
89 if(NETTYPE(chan->qid.path) == Nifstatqid)
90 return ether->ifstat(ether, buf, n, offset);
91 else if(NETTYPE(chan->qid.path) == Nstatqid)
92 ether->ifstat(ether, buf, 0, offset);
93 }
94
95 return netifread(ether, chan, buf, n, offset);
96 }
97
98 static Block*
etherbread(Chan * chan,long n,ulong offset)99 etherbread(Chan* chan, long n, ulong offset)
100 {
101 return netifbread(etherxx[chan->devno], chan, n, offset);
102 }
103
104 static int
etherwstat(Chan * chan,uchar * dp,int n)105 etherwstat(Chan* chan, uchar* dp, int n)
106 {
107 return netifwstat(etherxx[chan->devno], chan, dp, n);
108 }
109
110 static void
etherrtrace(Netfile * f,Etherpkt * pkt,int len)111 etherrtrace(Netfile* f, Etherpkt* pkt, int len)
112 {
113 int i, n;
114 Block *bp;
115
116 if(qwindow(f->iq) <= 0)
117 return;
118 if(len > 58)
119 n = 58;
120 else
121 n = len;
122 bp = iallocb(64);
123 if(bp == nil)
124 return;
125 memmove(bp->wp, pkt->d, n);
126 i = TK2MS(MACHP(0)->ticks);
127 bp->wp[58] = len>>8;
128 bp->wp[59] = len;
129 bp->wp[60] = i>>24;
130 bp->wp[61] = i>>16;
131 bp->wp[62] = i>>8;
132 bp->wp[63] = i;
133 bp->wp += 64;
134 qpass(f->iq, bp);
135 }
136
137 Block*
etheriq(Ether * ether,Block * bp,int fromwire)138 etheriq(Ether* ether, Block* bp, int fromwire)
139 {
140 Etherpkt *pkt;
141 ushort type;
142 int len, multi, tome, fromme;
143 Netfile **ep, *f, **fp, *fx;
144 Block *xbp;
145
146 ether->inpackets++;
147
148 pkt = (Etherpkt*)bp->rp;
149 len = BLEN(bp);
150 type = (pkt->type[0]<<8)|pkt->type[1];
151 fx = 0;
152 ep = ðer->f[Ntypes];
153
154 multi = pkt->d[0] & 1;
155 /* check for valid multicast addresses */
156 if(multi && memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) != 0 && ether->prom == 0){
157 if(!activemulti(ether, pkt->d, sizeof(pkt->d))){
158 if(fromwire){
159 freeb(bp);
160 bp = 0;
161 }
162 return bp;
163 }
164 }
165
166 /* is it for me? */
167 tome = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
168 fromme = memcmp(pkt->s, ether->ea, sizeof(pkt->s)) == 0;
169
170 /*
171 * Multiplex the packet to all the connections which want it.
172 * If the packet is not to be used subsequently (fromwire != 0),
173 * attempt to simply pass it into one of the connections, thereby
174 * saving a copy of the data (usual case hopefully).
175 */
176 for(fp = ether->f; fp < ep; fp++){
177 if(f = *fp)
178 if(f->type == type || f->type < 0)
179 if(tome || multi || f->prom){
180 /* Don't want to hear bridged packets */
181 if(f->bridge && !fromwire && !fromme)
182 continue;
183 if(!f->headersonly){
184 if(fromwire && fx == 0)
185 fx = f;
186 else if(xbp = iallocb(len)){
187 memmove(xbp->wp, pkt, len);
188 xbp->wp += len;
189 if(qpass(f->iq, xbp) < 0)
190 ether->soverflows++;
191 }
192 else
193 ether->soverflows++;
194 }
195 else
196 etherrtrace(f, pkt, len);
197 }
198 }
199
200 if(fx){
201 if(qpass(fx->iq, bp) < 0)
202 ether->soverflows++;
203 return 0;
204 }
205 if(fromwire){
206 freeb(bp);
207 return 0;
208 }
209
210 return bp;
211 }
212
213 static int
etheroq(Ether * ether,Block * bp)214 etheroq(Ether* ether, Block* bp)
215 {
216 int len, loopback, s;
217 Etherpkt *pkt;
218
219 ether->outpackets++;
220
221 /*
222 * Check if the packet has to be placed back onto the input queue,
223 * i.e. if it's a loopback or broadcast packet or the interface is
224 * in promiscuous mode.
225 * If it's a loopback packet indicate to etheriq that the data isn't
226 * needed and return, etheriq will pass-on or free the block.
227 * To enable bridging to work, only packets that were originated
228 * by this interface are fed back.
229 */
230 pkt = (Etherpkt*)bp->rp;
231 len = BLEN(bp);
232 loopback = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
233 if(loopback || memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) == 0 || ether->prom){
234 s = splhi();
235 etheriq(ether, bp, 0);
236 splx(s);
237 }
238
239 if(!loopback){
240 qbwrite(ether->oq, bp);
241 if(ether->transmit != nil)
242 ether->transmit(ether);
243 } else
244 freeb(bp);
245
246 return len;
247 }
248
249 static long
etherwrite(Chan * chan,void * buf,long n,vlong)250 etherwrite(Chan* chan, void* buf, long n, vlong)
251 {
252 Ether *ether;
253 Block *bp;
254 int nn, onoff;
255 Cmdbuf *cb;
256
257 ether = etherxx[chan->devno];
258 if(NETTYPE(chan->qid.path) != Ndataqid) {
259 nn = netifwrite(ether, chan, buf, n);
260 if(nn >= 0)
261 return nn;
262 cb = parsecmd(buf, n);
263 if(strcmp(cb->f[0], "nonblocking") == 0){
264 if(cb->nf <= 1)
265 onoff = 1;
266 else
267 onoff = atoi(cb->f[1]);
268 qnoblock(ether->oq, onoff);
269 free(cb);
270 return n;
271 }
272 free(cb);
273 if(ether->ctl!=nil)
274 return ether->ctl(ether,buf,n);
275
276 error(Ebadctl);
277 }
278
279 if(n > ether->maxmtu)
280 error(Etoobig);
281 if(n < ether->minmtu)
282 error(Etoosmall);
283
284 bp = allocb(n);
285 if(waserror()){
286 freeb(bp);
287 nexterror();
288 }
289 memmove(bp->rp, buf, n);
290 memmove(bp->rp+Eaddrlen, ether->ea, Eaddrlen);
291 poperror();
292 bp->wp += n;
293
294 return etheroq(ether, bp);
295 }
296
297 static long
etherbwrite(Chan * chan,Block * bp,ulong)298 etherbwrite(Chan* chan, Block* bp, ulong)
299 {
300 Ether *ether;
301 long n;
302
303 n = BLEN(bp);
304 if(NETTYPE(chan->qid.path) != Ndataqid){
305 if(waserror()) {
306 freeb(bp);
307 nexterror();
308 }
309 n = etherwrite(chan, bp->rp, n, 0);
310 poperror();
311 freeb(bp);
312 return n;
313 }
314 ether = etherxx[chan->devno];
315
316 if(n > ether->maxmtu){
317 freeb(bp);
318 error(Etoobig);
319 }
320 if(n < ether->minmtu){
321 freeb(bp);
322 error(Etoosmall);
323 }
324
325 return etheroq(ether, bp);
326 }
327
328 static struct {
329 char* type;
330 int (*reset)(Ether*);
331 } cards[MaxEther+1];
332
333 void
addethercard(char * t,int (* r)(Ether *))334 addethercard(char* t, int (*r)(Ether*))
335 {
336 static int ncard;
337
338 if(ncard == MaxEther)
339 panic("too many ether cards");
340 cards[ncard].type = t;
341 cards[ncard].reset = r;
342 ncard++;
343 }
344
345 int
parseether(uchar * to,char * from)346 parseether(uchar *to, char *from)
347 {
348 char nip[4];
349 char *p;
350 int i;
351
352 p = from;
353 for(i = 0; i < Eaddrlen; i++){
354 if(*p == 0)
355 return -1;
356 nip[0] = *p++;
357 if(*p == 0)
358 return -1;
359 nip[1] = *p++;
360 nip[2] = 0;
361 to[i] = strtoul(nip, 0, 16);
362 if(*p == ':')
363 p++;
364 }
365 return 0;
366 }
367
368 static void
etherreset(void)369 etherreset(void)
370 {
371 Ether *ether;
372 int i, n, ctlrno;
373 char name[KNAMELEN], buf[128];
374
375 for(ether = 0, ctlrno = 0; ctlrno < MaxEther; ctlrno++){
376 if(ether == 0)
377 ether = malloc(sizeof(Ether));
378 memset(ether, 0, sizeof(Ether));
379 ether->ctlrno = ctlrno;
380 ether->mbps = 10;
381 ether->minmtu = ETHERMINTU;
382 ether->maxmtu = ETHERMAXTU;
383
384 if(archether(ctlrno, ether) <= 0)
385 continue;
386
387 for(n = 0; cards[n].type; n++){
388 if(cistrcmp(cards[n].type, ether->type))
389 continue;
390 for(i = 0; i < ether->nopt; i++){
391 if(cistrncmp(ether->opt[i], "ea=", 3) == 0){
392 if(parseether(ether->ea, ðer->opt[i][3]) == -1)
393 memset(ether->ea, 0, Eaddrlen);
394 }else if(cistrcmp(ether->opt[i], "fullduplex") == 0 ||
395 cistrcmp(ether->opt[i], "10BASE-TFD") == 0)
396 ether->fullduplex = 1;
397 else if(cistrcmp(ether->opt[i], "100BASE-TXFD") == 0)
398 ether->mbps = 100;
399 }
400 if(cards[n].reset(ether))
401 break;
402 snprint(name, sizeof(name), "ether%d", ctlrno);
403
404 // if(ether->interrupt != nil)
405 // intrenable(ether->irq, ether->interrupt, ether,
406 // ether->tbdf, name);
407 /* done by the driver */
408 // intrenable(Inttemac, ether->interrupt, "ether");
409
410 i = sprint(buf, "#l%d: %s: %dMbps port %#lux irq %d",
411 ctlrno, ether->type, ether->mbps, ether->port, ether->irq);
412 if(ether->mem)
413 i += sprint(buf+i, " addr %#lux", PADDR(ether->mem));
414 if(ether->size)
415 i += sprint(buf+i, " size 0x%luX", ether->size);
416 i += sprint(buf+i, ": %2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux",
417 ether->ea[0], ether->ea[1], ether->ea[2],
418 ether->ea[3], ether->ea[4], ether->ea[5]);
419 sprint(buf+i, "\n");
420 print(buf);
421
422 if(ether->mbps == 100){
423 /*
424 * our ether has no ring buffers, so make sure
425 * that we have adequate buffering.
426 */
427 netifinit(ether, name, Ntypes, 1024*1024);
428 if(ether->oq == 0)
429 ether->oq = qopen(1024*1024, Qmsg, 0, 0);
430 }
431 else{
432 netifinit(ether, name, Ntypes, 65*1024);
433 if(ether->oq == 0)
434 ether->oq = qopen(65*1024, Qmsg, 0, 0);
435 }
436 if(ether->oq == 0)
437 panic("etherreset %s", name);
438 ether->alen = Eaddrlen;
439 memmove(ether->addr, ether->ea, Eaddrlen);
440 memset(ether->bcast, 0xFF, Eaddrlen);
441
442 etherxx[ctlrno] = ether;
443 ether = 0;
444 break;
445 }
446 }
447 if(ether)
448 free(ether);
449 }
450
451 static void
ethershutdown(void)452 ethershutdown(void)
453 {
454 Ether *ether;
455 int i;
456
457 for(i = 0; i < MaxEther; i++){
458 ether = etherxx[i];
459 if(ether == nil)
460 continue;
461 if(ether->shutdown == nil) {
462 print("#l%d: no shutdown function\n", i);
463 continue;
464 }
465 (*ether->shutdown)(ether);
466 }
467 }
468
469
470 enum {
471 Pktwin = 60, /* must be ether activity within this interval, in sec.s */
472 };
473
474 /* called from clock.c once per second */
475 void
etherclock(void)476 etherclock(void)
477 {
478 Ether *ether = etherxx[0];
479 static int cnt, oldin, oldout;
480
481 if (++cnt < Pktwin)
482 return;
483 cnt = 0;
484 if ((ether->inpackets == oldin || ether->outpackets == oldout) &&
485 ether->inpackets && ether->outpackets) {
486 print("no ether pkts in last %d s. ", Pktwin);
487 /*
488 * this is really unlikely, so probably the ethernet controller
489 * has silently wedged. whack it hard.
490 */
491 whackether(ether);
492 }
493 oldin = ether->inpackets;
494 oldout = ether->outpackets;
495 }
496
497 #define POLY 0xedb88320
498
499 /* really slow 32 bit crc for ethers */
500 ulong
ethercrc(uchar * p,int len)501 ethercrc(uchar *p, int len)
502 {
503 int i, j;
504 ulong crc, b;
505
506 crc = 0xffffffff;
507 for(i = 0; i < len; i++){
508 b = *p++;
509 for(j = 0; j < 8; j++){
510 crc = (crc>>1) ^ (((crc^b) & 1) ? POLY : 0);
511 b >>= 1;
512 }
513 }
514 return crc;
515 }
516
517 void
dumpoq(Queue * oq)518 dumpoq(Queue *oq)
519 {
520 if (oq == nil)
521 print("no outq! ");
522 else if (qisclosed(oq))
523 print("outq closed ");
524 else if (qfull(oq))
525 print("outq full ");
526 else
527 print("outq %d ", qlen(oq));
528 }
529
530 void
dumpnetif(Netif * netif)531 dumpnetif(Netif *netif)
532 {
533 print("netif %s ", netif->name);
534 print("limit %d mbps %d link %d ",
535 netif->limit, netif->mbps, netif->link);
536 print("inpkts %lld outpkts %lld errs %d\n",
537 netif->inpackets, netif->outpackets,
538 netif->crcs + netif->oerrs + netif->frames + netif->overflows +
539 netif->buffs + netif->soverflows);
540 }
541
542 Dev etherdevtab = {
543 'l',
544 "ether",
545
546 etherreset,
547 devinit,
548 ethershutdown,
549 etherattach,
550 etherwalk,
551 etherstat,
552 etheropen,
553 ethercreate,
554 etherclose,
555 etherread,
556 etherbread,
557 etherwrite,
558 etherbwrite,
559 devremove,
560 etherwstat,
561 };
562