xref: /plan9/sys/src/9/pc/devether.c (revision 7d7728c9ff780bb29e70ac5c0f1bb4c0d6187a9b)
1 #include "u.h"
2 #include "../port/lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "fns.h"
6 #include "io.h"
7 #include "pool.h"
8 #include "ureg.h"
9 #include "../port/error.h"
10 #include "../port/netif.h"
11 
12 #include "etherif.h"
13 
14 static Ether *etherxx[MaxEther];
15 
16 Chan*
17 etherattach(char* spec)
18 {
19 	ulong ctlrno;
20 	char *p;
21 	Chan *chan;
22 
23 	ctlrno = 0;
24 	if(spec && *spec){
25 		ctlrno = strtoul(spec, &p, 0);
26 		if((ctlrno == 0 && p == spec) || *p || (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->dev = ctlrno;
38 	if(etherxx[ctlrno]->attach)
39 		etherxx[ctlrno]->attach(etherxx[ctlrno]);
40 	poperror();
41 	return chan;
42 }
43 
44 static Walkqid*
45 etherwalk(Chan* chan, Chan* nchan, char** name, int nname)
46 {
47 	return netifwalk(etherxx[chan->dev], chan, nchan, name, nname);
48 }
49 
50 static int
51 etherstat(Chan* chan, uchar* dp, int n)
52 {
53 	return netifstat(etherxx[chan->dev], chan, dp, n);
54 }
55 
56 static Chan*
57 etheropen(Chan* chan, int omode)
58 {
59 	return netifopen(etherxx[chan->dev], chan, omode);
60 }
61 
62 static void
63 ethercreate(Chan*, char*, int, ulong)
64 {
65 }
66 
67 static void
68 etherclose(Chan* chan)
69 {
70 	netifclose(etherxx[chan->dev], chan);
71 }
72 
73 static long
74 etherread(Chan* chan, void* buf, long n, vlong off)
75 {
76 	Ether *ether;
77 	ulong offset = off;
78 
79 	ether = etherxx[chan->dev];
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*
95 etherbread(Chan* chan, long n, ulong offset)
96 {
97 	return netifbread(etherxx[chan->dev], chan, n, offset);
98 }
99 
100 static int
101 etherwstat(Chan* chan, uchar* dp, int n)
102 {
103 	return netifwstat(etherxx[chan->dev], chan, dp, n);
104 }
105 
106 static void
107 etherrtrace(Netfile* f, Etherpkt* pkt, int len)
108 {
109 	int i, n;
110 	Block *bp;
111 
112 	if(qwindow(f->in) <= 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(MACHP(0)->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->in, bp);
131 }
132 
133 Block*
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 = &ether->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->in, xbp) < 0) {
186 						// print("soverflow for f->in\n");
187 						ether->soverflows++;
188 					}
189 				}
190 				else {
191 					// print("soverflow iallocb\n");
192 					ether->soverflows++;
193 				}
194 			}
195 			else
196 				etherrtrace(f, pkt, len);
197 		}
198 	}
199 
200 	if(fx){
201 		if(qpass(fx->in, bp) < 0) {
202 			// print("soverflow for fx->in\n");
203 			ether->soverflows++;
204 		}
205 		return 0;
206 	}
207 	if(fromwire){
208 		freeb(bp);
209 		return 0;
210 	}
211 
212 	return bp;
213 }
214 
215 static int
216 etheroq(Ether* ether, Block* bp)
217 {
218 	int len, loopback, s;
219 	Etherpkt *pkt;
220 
221 	ether->outpackets++;
222 
223 	/*
224 	 * Check if the packet has to be placed back onto the input queue,
225 	 * i.e. if it's a loopback or broadcast packet or the interface is
226 	 * in promiscuous mode.
227 	 * If it's a loopback packet indicate to etheriq that the data isn't
228 	 * needed and return, etheriq will pass-on or free the block.
229 	 * To enable bridging to work, only packets that were originated
230 	 * by this interface are fed back.
231 	 */
232 	pkt = (Etherpkt*)bp->rp;
233 	len = BLEN(bp);
234 	loopback = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
235 	if(loopback || memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) == 0 || ether->prom){
236 		s = splhi();
237 		etheriq(ether, bp, 0);
238 		splx(s);
239 	}
240 
241 	if(!loopback){
242 		if(qfull(ether->oq))
243 			print("etheroq: WARNING: ether->oq full!\n");
244 		qbwrite(ether->oq, bp);
245 		if(ether->transmit != nil)
246 			ether->transmit(ether);
247 	} else
248 		freeb(bp);
249 
250 	return len;
251 }
252 
253 static long
254 etherwrite(Chan* chan, void* buf, long n, vlong)
255 {
256 	Ether *ether;
257 	Block *bp;
258 	int nn, onoff;
259 	Cmdbuf *cb;
260 
261 	ether = etherxx[chan->dev];
262 	if(NETTYPE(chan->qid.path) != Ndataqid) {
263 		nn = netifwrite(ether, chan, buf, n);
264 		if(nn >= 0)
265 			return nn;
266 		cb = parsecmd(buf, n);
267 		if(cb->f[0] && strcmp(cb->f[0], "nonblocking") == 0){
268 			if(cb->nf <= 1)
269 				onoff = 1;
270 			else
271 				onoff = atoi(cb->f[1]);
272 			qnoblock(ether->oq, onoff);
273 			free(cb);
274 			return n;
275 		}
276 		free(cb);
277 		if(ether->ctl!=nil)
278 			return ether->ctl(ether,buf,n);
279 
280 		error(Ebadctl);
281 	}
282 
283 	if(n > ether->maxmtu)
284 		error(Etoobig);
285 	if(n < ether->minmtu)
286 		error(Etoosmall);
287 
288 	bp = allocb(n);
289 	if(waserror()){
290 		freeb(bp);
291 		nexterror();
292 	}
293 	memmove(bp->rp, buf, n);
294 	memmove(bp->rp+Eaddrlen, ether->ea, Eaddrlen);
295 	poperror();
296 	bp->wp += n;
297 
298 	return etheroq(ether, bp);
299 }
300 
301 static long
302 etherbwrite(Chan* chan, Block* bp, ulong)
303 {
304 	Ether *ether;
305 	long n;
306 
307 	n = BLEN(bp);
308 	if(NETTYPE(chan->qid.path) != Ndataqid){
309 		if(waserror()) {
310 			freeb(bp);
311 			nexterror();
312 		}
313 		n = etherwrite(chan, bp->rp, n, 0);
314 		poperror();
315 		freeb(bp);
316 		return n;
317 	}
318 	ether = etherxx[chan->dev];
319 
320 	if(n > ether->maxmtu){
321 		freeb(bp);
322 		error(Etoobig);
323 	}
324 	if(n < ether->minmtu){
325 		freeb(bp);
326 		error(Etoosmall);
327 	}
328 
329 	return etheroq(ether, bp);
330 }
331 
332 static struct {
333 	char*	type;
334 	int	(*reset)(Ether*);
335 } cards[MaxEther+1];
336 
337 void
338 addethercard(char* t, int (*r)(Ether*))
339 {
340 	static int ncard;
341 
342 	if(ncard == MaxEther)
343 		panic("too many ether cards");
344 	cards[ncard].type = t;
345 	cards[ncard].reset = r;
346 	ncard++;
347 }
348 
349 int
350 parseether(uchar *to, char *from)
351 {
352 	char nip[4];
353 	char *p;
354 	int i;
355 
356 	p = from;
357 	for(i = 0; i < Eaddrlen; i++){
358 		if(*p == 0)
359 			return -1;
360 		nip[0] = *p++;
361 		if(*p == 0)
362 			return -1;
363 		nip[1] = *p++;
364 		nip[2] = 0;
365 		to[i] = strtoul(nip, 0, 16);
366 		if(*p == ':')
367 			p++;
368 	}
369 	return 0;
370 }
371 
372 static Ether*
373 etherprobe(int cardno, int ctlrno)
374 {
375 	int i, lg;
376 	ulong mb, bsz;
377 	Ether *ether;
378 	char buf[128], name[32];
379 
380 	ether = malloc(sizeof(Ether));
381 	memset(ether, 0, sizeof(Ether));
382 	ether->ctlrno = ctlrno;
383 	ether->tbdf = BUSUNKNOWN;
384 	ether->mbps = 10;
385 	ether->minmtu = ETHERMINTU;
386 	ether->maxmtu = ETHERMAXTU;
387 
388 	if(cardno < 0){
389 		if(isaconfig("ether", ctlrno, ether) == 0){
390 			free(ether);
391 			return nil;
392 		}
393 		for(cardno = 0; cards[cardno].type; cardno++){
394 			if(cistrcmp(cards[cardno].type, ether->type))
395 				continue;
396 			for(i = 0; i < ether->nopt; i++){
397 				if(strncmp(ether->opt[i], "ea=", 3))
398 					continue;
399 				if(parseether(ether->ea, &ether->opt[i][3]))
400 					memset(ether->ea, 0, Eaddrlen);
401 			}
402 			break;
403 		}
404 	}
405 
406 	if(cardno >= MaxEther || cards[cardno].type == nil){
407 		free(ether);
408 		return nil;
409 	}
410 	if(cards[cardno].reset(ether) < 0){
411 		free(ether);
412 		return nil;
413 	}
414 
415 	/*
416 	 * IRQ2 doesn't really exist, it's used to gang the interrupt
417 	 * controllers together. A device set to IRQ2 will appear on
418 	 * the second interrupt controller as IRQ9.
419 	 */
420 	if(ether->irq == 2)
421 		ether->irq = 9;
422 	snprint(name, sizeof(name), "ether%d", ctlrno);
423 
424 	/*
425 	 * If ether->irq is <0, it is a hack to indicate no interrupt
426 	 * used by ethersink.
427 	 */
428 	if(ether->irq >= 0)
429 		intrenable(ether->irq, ether->interrupt, ether, ether->tbdf, name);
430 
431 	i = sprint(buf, "#l%d: %s: %dMbps port 0x%luX irq %d",
432 		ctlrno, cards[cardno].type, ether->mbps, ether->port, ether->irq);
433 	if(ether->mem)
434 		i += sprint(buf+i, " addr 0x%luX", ether->mem);
435 	if(ether->size)
436 		i += sprint(buf+i, " size 0x%luX", ether->size);
437 	i += sprint(buf+i, ": %2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux",
438 		ether->ea[0], ether->ea[1], ether->ea[2],
439 		ether->ea[3], ether->ea[4], ether->ea[5]);
440 	sprint(buf+i, "\n");
441 	print(buf);
442 
443 	/* compute log10(ether->mbps) into lg */
444 	for(lg = 0, mb = ether->mbps; mb >= 10; lg++)
445 		mb /= 10;
446 	if (lg > 0)
447 		lg--;
448 	if (lg > 14)			/* 2^(14+17) = 2⁳ⁱ */
449 		lg = 14;
450 	/* allocate larger output queues for higher-speed interfaces */
451 	bsz = 1UL << (lg + 17);		/* 2ⁱ⁷ = 128K, bsz = 2ⁿ × 128K */
452 	while (bsz > mainmem->maxsize / 8 && bsz > 128*1024)
453 		bsz /= 2;
454 
455 	netifinit(ether, name, Ntypes, bsz);
456 	if(ether->oq == nil) {
457 		ether->oq = qopen(bsz, Qmsg, 0, 0);
458 		ether->limit = bsz;
459 	}
460 	if(ether->oq == nil)
461 		panic("etherreset %s: can't allocate output queue of %ld bytes",
462 			name, bsz);
463 	ether->alen = Eaddrlen;
464 	memmove(ether->addr, ether->ea, Eaddrlen);
465 	memset(ether->bcast, 0xFF, Eaddrlen);
466 
467 	return ether;
468 }
469 
470 static void
471 etherreset(void)
472 {
473 	Ether *ether;
474 	int cardno, ctlrno;
475 
476 	for(ctlrno = 0; ctlrno < MaxEther; ctlrno++){
477 		if((ether = etherprobe(-1, ctlrno)) == nil)
478 			continue;
479 		etherxx[ctlrno] = ether;
480 	}
481 
482 	if(getconf("*noetherprobe"))
483 		return;
484 
485 	cardno = ctlrno = 0;
486 	while(cards[cardno].type != nil && ctlrno < MaxEther){
487 		if(etherxx[ctlrno] != nil){
488 			ctlrno++;
489 			continue;
490 		}
491 		if((ether = etherprobe(cardno, ctlrno)) == nil){
492 			cardno++;
493 			continue;
494 		}
495 		etherxx[ctlrno] = ether;
496 		ctlrno++;
497 	}
498 }
499 
500 static void
501 ethershutdown(void)
502 {
503 	Ether *ether;
504 	int i;
505 
506 	for(i = 0; i < MaxEther; i++){
507 		ether = etherxx[i];
508 		if(ether == nil)
509 			continue;
510 		if(ether->shutdown == nil) {
511 			print("#l%d: no shutdown fuction\n", i);
512 			continue;
513 		}
514 		(*ether->shutdown)(ether);
515 	}
516 }
517 
518 
519 #define POLY 0xedb88320
520 
521 /* really slow 32 bit crc for ethers */
522 ulong
523 ethercrc(uchar *p, int len)
524 {
525 	int i, j;
526 	ulong crc, b;
527 
528 	crc = 0xffffffff;
529 	for(i = 0; i < len; i++){
530 		b = *p++;
531 		for(j = 0; j < 8; j++){
532 			crc = (crc>>1) ^ (((crc^b) & 1) ? POLY : 0);
533 			b >>= 1;
534 		}
535 	}
536 	return crc;
537 }
538 
539 Dev etherdevtab = {
540 	'l',
541 	"ether",
542 
543 	etherreset,
544 	devinit,
545 	ethershutdown,
546 	etherattach,
547 	etherwalk,
548 	etherstat,
549 	etheropen,
550 	ethercreate,
551 	etherclose,
552 	etherread,
553 	etherbread,
554 	etherwrite,
555 	etherbwrite,
556 	devremove,
557 	etherwstat,
558 };
559