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