Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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 "../port/error.h"
8
 
9
#include "../port/netif.h"
10
#include "etherif.h"
11
 
12
static Ether *etherxx[MaxEther];
13
 
14
Chan*
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->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 &&
153
	    ether->prom == 0){
154
		if(!activemulti(ether, pkt->d, sizeof(pkt->d))){
155
			if(fromwire){
156
				freeb(bp);
157
				bp = 0;
158
			}
159
			return bp;
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) != nil && (f->type == type || f->type < 0) &&
174
		    (tome || multi || f->prom)){
175
			/* Don't want to hear bridged packets */
176
			if(f->bridge && !fromwire && !fromme)
177
				continue;
178
			if(!f->headersonly){
179
				if(fromwire && fx == 0)
180
					fx = f;
181
				else if(xbp = iallocb(len)){
182
					memmove(xbp->wp, pkt, len);
183
					xbp->wp += len;
184
					if(qpass(f->in, xbp) < 0)
185
						ether->soverflows++;
186
				}
187
				else
188
					ether->soverflows++;
189
			}
190
			else
191
				etherrtrace(f, pkt, len);
192
		}
193
	}
194
 
195
	if(fx){
196
		if(qpass(fx->in, bp) < 0)
197
			ether->soverflows++;
198
		return 0;
199
	}
200
	if(fromwire){
201
		freeb(bp);
202
		return 0;
203
	}
204
	return bp;
205
}
206
 
207
static int
208
etheroq(Ether* ether, Block* bp)
209
{
210
	int len, loopback, s;
211
	Etherpkt *pkt;
212
 
213
	ether->outpackets++;
214
 
215
	/*
216
	 * Check if the packet has to be placed back onto the input queue,
217
	 * i.e. if it's a loopback or broadcast packet or the interface is
218
	 * in promiscuous mode.
219
	 * If it's a loopback packet indicate to etheriq that the data isn't
220
	 * needed and return, etheriq will pass-on or free the block.
221
	 * To enable bridging to work, only packets that were originated
222
	 * by this interface are fed back.
223
	 */
224
	pkt = (Etherpkt*)bp->rp;
225
	len = BLEN(bp);
226
	loopback = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
227
	if(loopback || memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) == 0 || ether->prom){
228
		s = splhi();
229
		etheriq(ether, bp, 0);
230
		splx(s);
231
	}
232
 
233
	if(!loopback){
234
		qbwrite(ether->oq, bp);
235
		if(ether->transmit != nil)
236
			ether->transmit(ether);
237
	} else
238
		freeb(bp);
239
 
240
	return len;
241
}
242
 
243
static long
244
etherwrite(Chan* chan, void* buf, long n, vlong)
245
{
246
	Ether *ether;
247
	Block *bp;
248
	int nn, onoff;
249
	Cmdbuf *cb;
250
 
251
	ether = etherxx[chan->dev];
252
	if(NETTYPE(chan->qid.path) != Ndataqid) {
253
		nn = netifwrite(ether, chan, buf, n);
254
		if(nn >= 0)
255
			return nn;
256
		cb = parsecmd(buf, n);
257
		if(cb->f[0] && strcmp(cb->f[0], "nonblocking") == 0){
258
			if(cb->nf <= 1)
259
				onoff = 1;
260
			else
261
				onoff = atoi(cb->f[1]);
262
			qnoblock(ether->oq, onoff);
263
			free(cb);
264
			return n;
265
		}
266
		free(cb);
267
		if(ether->ctl!=nil)
268
			return ether->ctl(ether,buf,n);
269
 
270
		error(Ebadctl);
271
	}
272
 
273
	if(n > ether->maxmtu)
274
		error(Etoobig);
275
	if(n < ether->minmtu)
276
		error(Etoosmall);
277
 
278
	bp = allocb(n);
279
	if(waserror()){
280
		freeb(bp);
281
		nexterror();
282
	}
283
	memmove(bp->rp, buf, n);
284
	memmove(bp->rp+Eaddrlen, ether->ea, Eaddrlen);
285
	poperror();
286
	bp->wp += n;
287
 
288
	return etheroq(ether, bp);
289
}
290
 
291
static long
292
etherbwrite(Chan* chan, Block* bp, ulong)
293
{
294
	Ether *ether;
295
	long n;
296
 
297
	n = BLEN(bp);
298
	if(NETTYPE(chan->qid.path) != Ndataqid){
299
		if(waserror()) {
300
			freeb(bp);
301
			nexterror();
302
		}
303
		n = etherwrite(chan, bp->rp, n, 0);
304
		poperror();
305
		freeb(bp);
306
		return n;
307
	}
308
	ether = etherxx[chan->dev];
309
 
310
	if(n > ether->maxmtu){
311
		freeb(bp);
312
		error(Etoobig);
313
	}
314
	if(n < ether->minmtu){
315
		freeb(bp);
316
		error(Etoosmall);
317
	}
318
 
319
	return etheroq(ether, bp);
320
}
321
 
322
static struct {
323
	char*	type;
324
	int	(*reset)(Ether*);
325
} cards[MaxEther+1];
326
 
327
void
328
addethercard(char* t, int (*r)(Ether*))
329
{
330
	static int ncard;
331
 
332
	if(ncard == MaxEther)
333
		panic("too many ether cards");
334
	cards[ncard].type = t;
335
	cards[ncard].reset = r;
336
	ncard++;
337
}
338
 
339
int
340
parseether(uchar *to, char *from)
341
{
342
	char nip[4];
343
	char *p;
344
	int i;
345
 
346
	p = from;
347
	for(i = 0; i < Eaddrlen; i++){
348
		if(*p == 0)
349
			return -1;
350
		nip[0] = *p++;
351
		if(*p == 0)
352
			return -1;
353
		nip[1] = *p++;
354
		nip[2] = 0;
355
		to[i] = strtoul(nip, 0, 16);
356
		if(*p == ':')
357
			p++;
358
	}
359
	return 0;
360
}
361
 
362
static void
363
etherreset(void)
364
{
365
	Ether *ether;
366
	int i, n, ctlrno;
367
	char name[KNAMELEN], buf[128];
368
 
369
	for(ether = 0, ctlrno = 0; ctlrno < MaxEther; ctlrno++){
370
		if(ether == 0)
371
			ether = malloc(sizeof(Ether));
372
		memset(ether, 0, sizeof(Ether));
373
		ether->ctlrno = ctlrno;
374
		ether->mbps = 10;
375
		ether->minmtu = ETHERMINTU;
376
		ether->maxmtu = ETHERMAXTU;
377
 
378
		if(archether(ctlrno, ether) <= 0)
379
			continue;
380
 
381
		if(isaconfig("ether", ctlrno, ether) == 0){
382
//			free(ether);
383
//			return nil;
384
			continue;
385
		}
386
		for(n = 0; cards[n].type; n++){
387
			if(cistrcmp(cards[n].type, ether->type))
388
				continue;
389
			for(i = 0; i < ether->nopt; i++)
390
				if(cistrncmp(ether->opt[i], "ea=", 3) == 0){
391
					if(parseether(ether->ea,
392
					    &ether->opt[i][3]) == -1)
393
						memset(ether->ea, 0, Eaddrlen);
394
				} else if(cistrcmp(ether->opt[i],
395
				    "100BASE-TXFD") == 0)
396
					ether->mbps = 100;
397
			if(cards[n].reset(ether))
398
				break;
399
			snprint(name, sizeof(name), "ether%d", ctlrno);
400
 
401
			if(ether->interrupt != nil && ether->irq >= 0)
402
				intrenable(ether->irq, ether->interrupt,
403
					ether, 0, name);
404
 
405
			i = snprint(buf, sizeof buf,
406
				"#l%d: %s: %dMbps port %#lux irq %d",
407
				ctlrno, ether->type, ether->mbps, ether->port,
408
				ether->irq);
409
			if(ether->mem)
410
				i += snprint(buf+i, sizeof buf - i,
411
					" addr %#lux", PADDR(ether->mem));
412
			if(ether->size)
413
				i += snprint(buf+i, sizeof buf - i,
414
					" size %#luX", ether->size);
415
			i += snprint(buf+i, sizeof buf - i,
416
				": %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
			snprint(buf+i, sizeof buf - i, "\n");
420
			iprint("%s", buf);  /* it may be too early for print */
421
 
422
			if(ether->mbps >= 1000)
423
				netifinit(ether, name, Ntypes, 4*1024*1024);
424
			else if(ether->mbps >= 100)
425
				netifinit(ether, name, Ntypes, 1024*1024);
426
			else
427
				netifinit(ether, name, Ntypes, 65*1024);
428
			if(ether->oq == 0)
429
				ether->oq = qopen(ether->limit, Qmsg, 0, 0);
430
			if(ether->oq == 0)
431
				panic("etherreset %s", name);
432
			ether->alen = Eaddrlen;
433
			memmove(ether->addr, ether->ea, Eaddrlen);
434
			memset(ether->bcast, 0xFF, Eaddrlen);
435
 
436
			etherxx[ctlrno] = ether;
437
			ether = 0;
438
			break;
439
		}
440
	}
441
	if(ether)
442
		free(ether);
443
}
444
 
445
static void
446
ethershutdown(void)
447
{
448
	Ether *ether;
449
	int i;
450
 
451
	for(i = 0; i < MaxEther; i++){
452
		ether = etherxx[i];
453
		if(ether == nil)
454
			continue;
455
		if(ether->shutdown == nil) {
456
			print("#l%d: no shutdown function\n", i);
457
			continue;
458
		}
459
		(*ether->shutdown)(ether);
460
	}
461
}
462
 
463
 
464
#define POLY 0xedb88320
465
 
466
/* really slow 32 bit crc for ethers */
467
ulong
468
ethercrc(uchar *p, int len)
469
{
470
	int i, j;
471
	ulong crc, b;
472
 
473
	crc = 0xffffffff;
474
	for(i = 0; i < len; i++){
475
		b = *p++;
476
		for(j = 0; j < 8; j++){
477
			crc = (crc>>1) ^ (((crc^b) & 1) ? POLY : 0);
478
			b >>= 1;
479
		}
480
	}
481
	return crc;
482
}
483
 
484
void
485
dumpoq(Queue *oq)
486
{
487
	if (oq == nil)
488
		print("no outq! ");
489
	else if (qisclosed(oq))
490
		print("outq closed ");
491
	else if (qfull(oq))
492
		print("outq full ");
493
	else
494
		print("outq %d ", qlen(oq));
495
}
496
 
497
void
498
dumpnetif(Netif *netif)
499
{
500
	print("netif %s ", netif->name);
501
	print("limit %d mbps %d link %d ",
502
		netif->limit, netif->mbps, netif->link);
503
	print("inpkts %lld outpkts %lld errs %d\n",
504
		netif->inpackets, netif->outpackets,
505
		netif->crcs + netif->oerrs + netif->frames + netif->overflows +
506
		netif->buffs + netif->soverflows);
507
}
508
 
509
Dev etherdevtab = {
510
	'l',
511
	"ether",
512
 
513
	etherreset,
514
	devinit,
515
	ethershutdown,
516
	etherattach,
517
	etherwalk,
518
	etherstat,
519
	etheropen,
520
	ethercreate,
521
	etherclose,
522
	etherread,
523
	etherbread,
524
	etherwrite,
525
	etherbwrite,
526
	devremove,
527
	etherwstat,
528
};