|
|
1.1 root 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: #include "io.h"
8: #include "devtab.h"
9:
10: #include "ether.h"
11:
12: /*
13: * Half-arsed attempt at a general top-level
14: * ethernet driver. Needs work:
15: * handle multiple controllers
16: * much tidying
17: * set ethernet address
18: * need a ctl file passed down to card drivers
19: * so we can set options.
20: */
21:
22: struct Ctlr *softctlr;
23:
24: Chan*
25: etherclone(Chan *c, Chan *nc)
26: {
27: return devclone(c, nc);
28: }
29:
30: int
31: etherwalk(Chan *c, char *name)
32: {
33: return netwalk(c, name, &softctlr->net);
34: }
35:
36: void
37: etherstat(Chan *c, char *dp)
38: {
39: netstat(c, dp, &softctlr->net);
40: }
41:
42: Chan*
43: etheropen(Chan *c, int omode)
44: {
45: return netopen(c, omode, &softctlr->net);
46: }
47:
48: void
49: ethercreate(Chan *c, char *name, int omode, ulong perm)
50: {
51: USED(c, name, omode, perm);
52: error(Eperm);
53: }
54:
55: void
56: etherclose(Chan *c)
57: {
58: if(c->stream)
59: streamclose(c);
60: }
61:
62: long
63: etherread(Chan *c, void *a, long n, ulong offset)
64: {
65: return netread(c, a, n, offset, &softctlr->net);
66: }
67:
68: long
69: etherwrite(Chan *c, char *a, long n, ulong offset)
70: {
71: USED(offset);
72: return streamwrite(c, a, n, 0);
73: }
74:
75: void
76: etherremove(Chan *c)
77: {
78: USED(c);
79: error(Eperm);
80: }
81:
82: void
83: etherwstat(Chan *c, char *dp)
84: {
85: netwstat(c, dp, &softctlr->net);
86: }
87:
88: static int
89: isobuf(void *arg)
90: {
91: Ctlr *ctlr = arg;
92:
93: return ctlr->tb[ctlr->th].owner == Host;
94: }
95:
96: static void
97: etheroput(Queue *q, Block *bp)
98: {
99: Ctlr *ctlr;
100: Type *type;
101: Etherpkt *pkt;
102: RingBuf *ring;
103: int len, n, s;
104: Block *nbp;
105: uchar ea[6];
106: char *err;
107:
108: type = q->ptr;
109: ctlr = type->ctlr;
110: if(bp->type == M_CTL){
111: err = 0;
112: qlock(ctlr);
113: if(streamparse("connect", bp)){
114: if(type->type == -1)
115: ctlr->all--;
116: type->type = strtol((char*)bp->rptr, 0, 0);
117: if(type->type == -1)
118: ctlr->all++;
119: }
120: else if(streamparse("promiscuous", bp)) {
121: if(type->prom)
122: goto ctlout;
123: if(type->filter){
124: err = "address already set";
125: goto ctlout;
126: }
127: type->prom = 1;
128: ctlr->prom++;
129: if(ctlr->prom+ctlr->filter == 1)
130: (*ctlr->card.mode)(ctlr, 1);
131: }
132: else if(streamparse("address", bp)) {
133: if(type->prom){
134: err = "already promiscuous";
135: goto ctlout;
136: }
137: if(parseether(ea, bp->rptr) < 0){
138: err = "bad ether address";
139: goto ctlout;
140: }
141: memmove(type->ea, ea, sizeof(ea));
142: if(!type->filter){
143: type->filter = 1;
144: ctlr->filter++;
145: if(ctlr->filter == 1)
146: (*ctlr->card.mode)(ctlr, 3);
147: }
148: }
149: ctlout:
150: qunlock(ctlr);
151: freeb(bp);
152: if(err)
153: error(err);
154: return;
155: }
156:
157: /*
158: * Give packet a local address, return upstream if destined for
159: * this machine.
160: */
161: if(BLEN(bp) < ETHERHDRSIZE && (bp = pullup(bp, ETHERHDRSIZE)) == 0)
162: return;
163: pkt = (Etherpkt*)bp->rptr;
164: memmove(pkt->s, type->ea, sizeof(type->ea));
165: if(memcmp(ctlr->ea, pkt->d, sizeof(ctlr->ea)) == 0){
166: len = blen(bp);
167: if(bp = expandb(bp, len >= ETHERMINTU ? len: ETHERMINTU)){
168: putq(&ctlr->lbq, bp);
169: wakeup(&ctlr->rr);
170: }
171: return;
172: }
173: if(memcmp(ctlr->ba, pkt->d, sizeof(ctlr->ba)) == 0 || ctlr->prom || ctlr->all){
174: len = blen(bp);
175: nbp = copyb(bp, len);
176: if(nbp = expandb(nbp, len >= ETHERMINTU ? len: ETHERMINTU)){
177: nbp->wptr = nbp->rptr+len;
178: putq(&ctlr->lbq, nbp);
179: wakeup(&ctlr->rr);
180: }
181: }
182:
183: /*
184: * Only one transmitter at a time.
185: */
186: qlock(&ctlr->tlock);
187: if(waserror()){
188: qunlock(&ctlr->tlock);
189: freeb(bp);
190: nexterror();
191: }
192:
193: /*
194: * Wait till we get an output buffer.
195: * should try to restart.
196: */
197: if(isobuf(ctlr) == 0){
198: tsleep(&ctlr->tr, isobuf, ctlr, 3*1000);
199: if(isobuf(ctlr) == 0){
200: qunlock(&ctlr->tlock);
201: freeb(bp);
202: poperror();
203: return;
204: }
205: }
206:
207: ring = &ctlr->tb[ctlr->th];
208:
209: /*
210: * Copy message into buffer.
211: */
212: len = 0;
213: for(nbp = bp; nbp; nbp = nbp->next){
214: if(sizeof(Etherpkt) - len >= (n = BLEN(nbp))){
215: memmove(ring->pkt+len, nbp->rptr, n);
216: len += n;
217: }
218: if(bp->flags & S_DELIM)
219: break;
220: }
221:
222: /*
223: * Pad the packet (zero the pad).
224: */
225: if(len < ETHERMINTU){
226: memset(ring->pkt+len, 0, ETHERMINTU-len);
227: len = ETHERMINTU;
228: }
229:
230: /*
231: * Set up the transmit buffer and
232: * start the transmission.
233: */
234: s = splhi();
235: ring->len = len;
236: ring->owner = Interface;
237: ctlr->th = NEXT(ctlr->th, ctlr->ntb);
238: (*ctlr->card.transmit)(ctlr);
239: ctlr->outpackets++;
240: splx(s);
241:
242: qunlock(&ctlr->tlock);
243: freeb(bp);
244: poperror();
245: }
246:
247: /*
248: * Open an ether line discipline.
249: */
250: static void
251: etherstopen(Queue *q, Stream *s)
252: {
253: Ctlr *ctlr = softctlr;
254: Type *type;
255:
256: type = &ctlr->type[s->id];
257: RD(q)->ptr = WR(q)->ptr = type;
258: type->type = 0;
259: type->q = RD(q);
260: type->inuse = 1;
261: memmove(type->ea, ctlr->ea, sizeof(type->ea));
262: type->ctlr = ctlr;
263: }
264:
265: /*
266: * Close ether line discipline.
267: *
268: * The locking is to synchronize changing the ethertype with
269: * sending packets up the stream on interrupts.
270: */
271: static int
272: isclosed(void *arg)
273: {
274: return ((Type*)arg)->q == 0;
275: }
276:
277: static void
278: etherstclose(Queue *q)
279: {
280: Type *type = (Type*)(q->ptr);
281: Ctlr *ctlr = type->ctlr;
282:
283: if(type->prom){
284: qlock(ctlr);
285: ctlr->prom--;
286: if(ctlr->prom+ctlr->filter == 0)
287: (*ctlr->card.mode)(ctlr, 0);
288: qunlock(ctlr);
289: }
290: if(type->filter){
291: qlock(ctlr);
292: ctlr->filter--;
293: if(ctlr->filter == 0)
294: (*ctlr->card.mode)(ctlr, ctlr->prom ? 1 : 0);
295: qunlock(ctlr);
296: }
297: if(type->type == -1){
298: qlock(ctlr);
299: ctlr->all--;
300: qunlock(ctlr);
301: }
302:
303: /*
304: * Mark as closing and wait for kproc
305: * to close us.
306: */
307: lock(&ctlr->clock);
308: type->clist = ctlr->clist;
309: ctlr->clist = type;
310: unlock(&ctlr->clock);
311: wakeup(&ctlr->rr);
312: sleep(&type->cr, isclosed, type);
313:
314: type->type = 0;
315: type->prom = 0;
316: type->filter = 0;
317: type->inuse = 0;
318: netdisown(type);
319: type->ctlr = 0;
320: }
321:
322: static Qinfo info = {
323: nullput,
324: etheroput,
325: etherstopen,
326: etherstclose,
327: "ether"
328: };
329:
330: static int
331: clonecon(Chan *c)
332: {
333: Ctlr *ctlr = softctlr;
334: Type *type;
335:
336: USED(c);
337: for(type = ctlr->type; type < &ctlr->type[NType]; type++){
338: qlock(type);
339: if(type->inuse || type->q){
340: qunlock(type);
341: continue;
342: }
343: type->inuse = 1;
344: memmove(type->ea, ctlr->ea, sizeof(type->ea));
345: netown(type, u->p->user, 0);
346: qunlock(type);
347: return type - ctlr->type;
348: }
349: exhausted("ether channels");
350: return 0;
351: }
352:
353: static void
354: statsfill(Chan *c, char *p, int n)
355: {
356: Ctlr *ctlr = softctlr;
357: char buf[256];
358:
359: USED(c);
360: sprint(buf, "in: %d\nout: %d\ncrc errs %d\noverflows: %d\nframe errs %d\nbuff errs: %d\noerrs %d\naddr: %.02x:%.02x:%.02x:%.02x:%.02x:%.02x\n",
361: ctlr->inpackets, ctlr->outpackets, ctlr->crcs,
362: ctlr->overflows, ctlr->frames, ctlr->buffs, ctlr->oerrs,
363: ctlr->ea[0], ctlr->ea[1], ctlr->ea[2],
364: ctlr->ea[3], ctlr->ea[4], ctlr->ea[5]);
365: strncpy(p, buf, n);
366: }
367:
368: static void
369: typefill(Chan *c, char *p, int n)
370: {
371: char buf[16];
372: Type *type;
373:
374: type = &softctlr->type[STREAMID(c->qid.path)];
375: sprint(buf, "%d", type->type);
376: strncpy(p, buf, n);
377: }
378:
379: int
380: eaddrmatch(Ctlr *ctlr, uchar *ea)
381: {
382: Type *type;
383:
384: for(type = &ctlr->type[0]; type < &ctlr->type[NType]; type++){
385: if(type->q == 0 || ea[0] != type->ea[0])
386: continue;
387: if(memcmp(ea, type->ea, sizeof(type->ea)) == 0)
388: return 1;
389: }
390: return 0;
391: }
392:
393: static void
394: etherup(Ctlr *ctlr, Etherpkt *pkt, int len)
395: {
396: int t;
397: Type *type;
398: Block *bp;
399:
400: t = (pkt->type[0]<<8)|pkt->type[1];
401: for(type = &ctlr->type[0]; type < &ctlr->type[NType]; type++){
402:
403: /*
404: * Check for open, the right type, and flow control.
405: */
406: if(type->q == 0)
407: continue;
408: if(t != type->type && type->type >= 0)
409: continue;
410: if(type->q->next->len > Streamhi)
411: continue;
412:
413: /*
414: * Only a trace channel gets packets destined for other machines.
415: */
416: if(type->type != -1 && pkt->d[0] != 0xFF
417: && (*pkt->d != *type->ea || memcmp(pkt->d, type->ea, sizeof(pkt->d))))
418: continue;
419:
420: if(waserror() == 0){
421: bp = allocb(len);
422: memmove(bp->rptr, pkt, len);
423: bp->wptr += len;
424: bp->flags |= S_DELIM;
425: PUTNEXT(type->q, bp);
426: poperror();
427: }
428: }
429: }
430:
431: static int
432: isinput(void *arg)
433: {
434: Ctlr *ctlr = arg;
435:
436: return ctlr->lbq.first || ctlr->rb[ctlr->rh].owner == Host || ctlr->clist;
437: }
438:
439: static void
440: etherkproc(void *arg)
441: {
442: Ctlr *ctlr = arg;
443: RingBuf *ring;
444: Block *bp;
445: Type *type;
446:
447: if(waserror()){
448: print("%s noted\n", ctlr->name);
449: /* fix
450: if(ctlr->card.reset)
451: (*ctlr->card.reset)(ctlr);
452: */
453: ctlr->kproc = 0;
454: nexterror();
455: }
456:
457: for(;;){
458: tsleep(&ctlr->rr, isinput, ctlr, 500);
459: if(ctlr->card.watch)
460: (*ctlr->card.watch)(ctlr);
461:
462: /*
463: * Process any internal loopback packets.
464: */
465: while(bp = getq(&ctlr->lbq)){
466: ctlr->inpackets++;
467: etherup(ctlr, (Etherpkt*)bp->rptr, BLEN(bp));
468: freeb(bp);
469: }
470:
471: /*
472: * Process any received packets.
473: */
474: while(ctlr->rb[ctlr->rh].owner == Host){
475: ctlr->inpackets++;
476: ring = &ctlr->rb[ctlr->rh];
477: etherup(ctlr, (Etherpkt*)ring->pkt, ring->len);
478: ring->owner = Interface;
479: ctlr->rh = NEXT(ctlr->rh, ctlr->nrb);
480: }
481:
482: /*
483: * Close Types requesting it.
484: */
485: if(ctlr->clist){
486: lock(&ctlr->clock);
487: for(type = ctlr->clist; type; type = type->clist){
488: type->q = 0;
489: wakeup(&type->cr);
490: }
491: ctlr->clist = 0;
492: unlock(&ctlr->clock);
493: }
494: }
495: }
496:
497: static void
498: etherintr(Ureg *ur, void *a)
499: {
500: Ctlr *ctlr = softctlr;
501:
502: USED(ur, a);
503: (*ctlr->card.intr)(ctlr);
504: }
505:
506: static void
507: reset(Ctlr *ctlr)
508: {
509: int i;
510:
511: if(ctlr->nrb == 0)
512: ctlr->nrb = Nrb;
513: ctlr->rb = xalloc(sizeof(RingBuf)*ctlr->nrb);
514: if(ctlr->ntb == 0)
515: ctlr->ntb = Ntb;
516: ctlr->tb = xalloc(sizeof(RingBuf)*ctlr->ntb);
517:
518: memset(ctlr->ba, 0xFF, sizeof(ctlr->ba));
519:
520: ctlr->net.name = "ether";
521: ctlr->net.nconv = NType;
522: ctlr->net.devp = &info;
523: ctlr->net.protop = 0;
524: ctlr->net.listen = 0;
525: ctlr->net.clone = clonecon;
526: ctlr->net.ninfo = 2;
527: ctlr->net.info[0].name = "stats";
528: ctlr->net.info[0].fill = statsfill;
529: ctlr->net.info[1].name = "type";
530: ctlr->net.info[1].fill = typefill;
531: for(i = 0; i < NType; i++)
532: netadd(&ctlr->net, &ctlr->type[i], i);
533: }
534:
535: extern int wd8003reset(Ctlr*);
536: extern int ne2000reset(Ctlr*);
537: extern int ccc509reset(Ctlr*);
538: extern int nsciareset(Ctlr*);
539: extern int ne2000PCMreset(Ctlr*);
540:
541: #define NCARD 32
542: struct {
543: char *type;
544: int (*reset)(Ctlr*);
545: } cards[NCARD+1];
546:
547: void
548: addethercard(char *t, int (*r)(Ctlr*))
549: {
550: static int ncard;
551:
552: if(ncard == NCARD)
553: panic("too many ether cards");
554: cards[ncard].type = t;
555: cards[ncard].reset = r;
556: ncard++;
557: }
558:
559: void
560: etherreset(void)
561: {
562: Ctlr *ctlr;
563: int i, n, ctlrno;
564:
565: if(softctlr == 0)
566: softctlr = xalloc(sizeof(Ctlr));
567: else
568: memset(softctlr, 0, sizeof(Ctlr));
569: ctlr = softctlr;
570:
571: for(ctlrno = i = 0; isaconfig("ether", i, &ctlr->card); i++){
572: for(n = 0; cards[n].type; n++){
573: if(strcmp(cards[n].type, ctlr->card.type))
574: continue;
575: ctlr->ctlrno = ctlrno;
576: memmove(ctlr->ea, ctlr->card.ea, sizeof(ctlr->ea));
577: if((*cards[n].reset)(ctlr))
578: break;
579:
580: /*ctlrno++;*/
581: ctlr->present = 1;
582: /*
583: * IRQ2 doesn't really exist, it's used to gang the interrupt
584: * controllers together. A device set to IRQ2 will appear on
585: * the second interrupt controller as IRQ9.
586: */
587: if(ctlr->card.irq == 2)
588: ctlr->card.irq = 9;
589: setvec(Int0vec + ctlr->card.irq, etherintr, 0);
590:
591: print("ether%d:%s: port %lux irq %d addr %lux size %d width %d:",
592: ctlr->ctlrno, ctlr->card.type, ctlr->card.port, ctlr->card.irq,
593: ctlr->card.mem, ctlr->card.size, ctlr->card.bit16 ? 16: 8);
594: for(i = 0; i < sizeof(ctlr->ea); i++)
595: print("%2.2ux", ctlr->ea[i]);
596: print("\n");
597:
598: reset(ctlr);
599: return;
600: }
601: memset(softctlr, 0, sizeof(Ctlr));
602: }
603: }
604:
605: void
606: etherinit(void)
607: {
608: Ctlr *ctlr = softctlr;
609: int i;
610:
611: if(ctlr->present == 0)
612: return;
613:
614: ctlr->rh = 0;
615: ctlr->ri = 0;
616: for(i = 0; i < ctlr->nrb; i++)
617: ctlr->rb[i].owner = Interface;
618:
619: ctlr->th = 0;
620: ctlr->ti = 0;
621: for(i = 0; i < ctlr->ntb; i++)
622: ctlr->tb[i].owner = Host;
623: }
624:
625: Chan*
626: etherattach(char *spec)
627: {
628: Ctlr *ctlr = softctlr;
629:
630: if(ctlr->present == 0)
631: error(Enodev);
632:
633: /*
634: * Enable the interface
635: * and start the kproc.
636: */
637: (*ctlr->card.attach)(ctlr);
638: if(ctlr->kproc == 0){
639: sprint(ctlr->name, "ether%dkproc", 0);
640: ctlr->kproc = 1;
641: kproc(ctlr->name, etherkproc, ctlr);
642: }
643: return devattach('l', spec);
644: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.