|
|
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 "io.h"
7: #include "../port/error.h"
8: #include "devtab.h"
9:
10: enum {
11: Ntypes= 9, /* max number of ethernet packet types */
12: Maxrb= 128, /* max buffers in a ring */
13: };
14: #define RSUCC(x) (((x)+1)%l.nrrb)
15: #define TSUCC(x) (((x)+1)%l.ntrb)
16:
17: /*
18: * Communication with the lance is via a transmit and receive ring of
19: * message descriptors. The Initblock contains pointers to and sizes of
20: * these rings. The rings must be in RAM addressible by the lance
21: */
22: typedef struct {
23: ushort laddr; /* low order piece of address */
24: ushort flags; /* flags and high order piece of address */
25: short size; /* size of buffer */
26: ushort cntflags; /* (rcv)count of bytes in buffer; (xmt) more flags */
27: } Msg;
28:
29: /*
30: * lance memory map
31: */
32: struct Lancemem
33: {
34: /*
35: * initialization block
36: */
37: ushort mode; /* chip control (see below) */
38: ushort etheraddr[3]; /* the ethernet physical address */
39: ushort multi[4]; /* multicast addresses, 1 bit for each of 64 */
40: ushort rdralow; /* receive buffer ring */
41: ushort rdrahigh; /* (top three bits define size of ring) */
42: ushort tdralow; /* transmit buffer ring */
43: ushort tdrahigh; /* (top three bits define size of ring) */
44:
45: /*
46: * ring buffers
47: * first receive, then transmit
48: */
49: Msg rmr[Maxrb]; /* recieve message ring */
50: Msg tmr[Maxrb]; /* transmit message ring */
51: };
52:
53: /*
54: * Some macros for dealing with lance memory addresses. The lance splits
55: * its 24 bit addresses across two 16 bit registers.
56: */
57: #define HADDR(a) ((((ulong)(a))>>16)&0xFF)
58: #define LADDR(a) (((ulong)a)&0xFFFF)
59:
60: /*
61: * The following functions exist to sidestep a quirk in the SGI IO3 lance
62: * interface. In all other processors, the lance's initialization block and
63: * descriptor rings look like normal memory. In the SGI IO3, the CPU sees a
64: * 6 byte pad twixt all lance memory shorts. Therefore, we use the following
65: * macros to compute the address whenever accessing the lance memory to make
66: * the code portable. Sic transit gloria.
67: */
68: #define LANCEMEM ((Lancemem*)0)
69: #define MPs(a) (*(short *)(l.lanceram + l.sep*((ushort*)&a - (ushort*)0)))
70: #define MPus(a) (*(ushort *)(l.lanceram + l.sep*((ushort*)&a - (ushort*)0)))
71:
72: /*
73: * one per ethernet packet type
74: */
75: typedef struct Ethertype Ethertype;
76: struct Ethertype
77: {
78: QLock;
79: Netprot; /* stat info */
80: int type; /* ethernet type */
81: int prom; /* promiscuous mode */
82: Queue *q;
83: int inuse;
84: Rendez rc; /* rendzvous for close */
85: Ethertype *closeline; /* close list */
86: };
87:
88:
89: /*
90: * lance state
91: */
92: typedef struct {
93: QLock;
94:
95: Lance; /* host dependent lance params */
96: int prom; /* number of promiscuous channels */
97: int all; /* number of channels listening to all packets */
98: int wedged; /* the lance is wedged */
99: Network net;
100:
101: int inited;
102: uchar *lmp; /* location of parity test */
103:
104: Rendez rr; /* rendezvous for an input buffer */
105: QLock rlock; /* semaphore on tc */
106: ushort rl; /* first rcv Message belonging to Lance */
107:
108: Rendez tr; /* rendezvous for an output buffer */
109: QLock tlock; /* semaphore on tc */
110: ushort tc; /* next xmt Message CPU will try for */
111:
112: Ethertype *closeline; /* channels waiting to close */
113: Lock closepin; /* lock for closeline */
114: Ethertype e[Ntypes];
115: int debug;
116: int kstarted;
117: uchar bcast[6];
118:
119: Queue self; /* packets turned around at the interface */
120:
121: /* sadistics */
122:
123: int misses;
124: int inpackets;
125: int outpackets;
126: int crcs; /* input crc errors */
127: int oerrs; /* output erros */
128: int frames; /* framing errors */
129: int overflows; /* packet overflows */
130: int buffs; /* buffering errors */
131: } SoftLance;
132: static SoftLance l;
133:
134: /*
135: * mode bits in the lance initialization block
136: */
137: #define PROM 0x8000
138: #define INTL 0x40
139: #define DRTY 0x20
140: #define COLL 0x10
141: #define DTCR 0x8
142: #define LOOP 0x4
143: #define DTX 0x2
144: #define DRX 0x1
145:
146: /*
147: * LANCE CSR0, this is the register we play with most often. We leave
148: * this register pointed to by l.rap in normal operation.
149: */
150: #define ERR0 0x8000
151: #define BABL 0x4000
152: #define CERR 0x2000
153: #define MISS 0x1000
154: #define MERR 0x800
155: #define RINT 0x400
156: #define TINT 0x200
157: #define IDON 0x100
158: #define INTR 0x80
159: #define INEA 0x40
160: #define RXON 0x20
161: #define TXON 0x10
162: #define TDMD 0x8
163: #define STOP 0x4
164: #define STRT 0x2
165: #define INIT 0x1
166:
167: /*
168: * flag bits from a buffer descriptor in the rcv/xmt rings
169: */
170: #define LANCEOWNER 0x8000 /* 1 means that the buffer can be used by the chip */
171: #define ERR 0x4000 /* error summary, the OR of all error bits */
172: #define FRAM 0x2000 /* CRC error and incoming packet not a multiple of 8 bits */
173: #define OFLO 0x1000 /* (receive) lost some of the packet */
174: #define MORE 0x1000 /* (transmit) more than 1 retry to send the packet */
175: #define CRC 0x800 /* (receive) crc error reading packet */
176: #define ONE 0x800 /* (transmit) one retry to transmit the packet */
177: #define BUF 0x400 /* (receive) out of buffers while reading a packet */
178: #define DEF 0x400 /* (transmit) deffered while transmitting packet */
179: #define STP 0x200 /* start of packet */
180: #define ENP 0x100 /* end of packet */
181:
182: /*
183: * cntflags bits from a buffer descriptor in the rcv/xmt rings
184: */
185: #define BUFF 0x8000 /* buffer error (host screwed up?) */
186: #define UFLO 0x4000 /* underflow from memory */
187: #define LCOL 0x1000 /* late collision (ether too long?) */
188: #define LCAR 0x800 /* loss of carrier (ether broken?) */
189: #define RTRY 0x400 /* couldn't transmit (bad station on ether?) */
190: #define TTDR 0x3FF /* time domain reflectometer */
191:
192: /*
193: * predeclared
194: */
195: static void lancekproc(void *);
196: static void lancestart(int);
197: static void lanceup(Etherpkt*, int);
198: static int lanceclonecon(Chan*);
199: static void lancestatsfill(Chan*, char*, int);
200: static void lancetypefill(Chan*, char*, int);
201:
202: /*
203: * lance stream module definition
204: */
205: static void lanceoput(Queue*, Block*);
206: static void lancestopen(Queue*, Stream*);
207: static void lancestclose(Queue*);
208: static void stagerbuf(void);
209: Qinfo lanceinfo = { nullput, lanceoput, lancestopen, lancestclose, "lance" };
210:
211: /*
212: * open a lance line discipline
213: */
214: void
215: lancestopen(Queue *q, Stream *s)
216: {
217: Ethertype *et;
218:
219: et = &l.e[s->id];
220: RD(q)->ptr = WR(q)->ptr = et;
221: et->type = 0;
222: et->q = RD(q);
223: et->inuse = 1;
224: }
225:
226: /*
227: * close lance line discipline
228: *
229: * the lock is to synchronize changing the ethertype with
230: * sending packets up the stream on interrupts.
231: */
232: static int
233: isclosed(void *x)
234: {
235: return ((Ethertype *)x)->q == 0;
236: }
237:
238: static void
239: lancestclose(Queue *q)
240: {
241: Ethertype *et;
242:
243: et = (Ethertype *)(q->ptr);
244: if(et->prom){
245: qlock(&l);
246: l.prom--;
247: if(l.prom == 0)
248: lancestart(0);
249: qunlock(&l);
250: }
251: if(et->type == -1){
252: qlock(&l);
253: l.all--;
254: qunlock(&l);
255: }
256:
257: /*
258: * mark as closing and wait for kproc to close us
259: */
260: lock(&l.closepin);
261: et->closeline = l.closeline;
262: l.closeline = et;
263: unlock(&l.closepin);
264: wakeup(&l.rr);
265: sleep(&et->rc, isclosed, et);
266:
267: et->type = 0;
268: et->q = 0;
269: et->prom = 0;
270: et->inuse = 0;
271: netdisown(et);
272: }
273:
274: /*
275: * the ``connect'' control message specifyies the type
276: */
277: Proc *lanceout;
278: static int
279: isobuf(void *x)
280: {
281: Msg *m;
282:
283: m = x;
284: return l.wedged || (MPus(m->flags)&LANCEOWNER) == 0;
285: }
286:
287: static void
288: lanceoput(Queue *q, Block *bp)
289: {
290: int n, len;
291: Etherpkt *p;
292: Ethertype *e;
293: Msg *m;
294: Block *nbp;
295:
296: if(bp->type == M_CTL){
297: e = q->ptr;
298: qlock(&l);
299: if(streamparse("connect", bp)){
300: if(e->type == -1)
301: l.all--;
302: e->type = strtol((char *)bp->rptr, 0, 0);
303: if(e->type == -1)
304: l.all++;
305: } else if(streamparse("promiscuous", bp)) {
306: e->prom = 1;
307: l.prom++;
308: if(l.prom == 1)
309: lancestart(PROM);/**/
310: }
311: qunlock(&l);
312: freeb(bp);
313: return;
314: }
315:
316: /*
317: * give packet a local address, return upstream if destined for
318: * this machine.
319: */
320: if(BLEN(bp) < ETHERHDRSIZE){
321: bp = pullup(bp, ETHERHDRSIZE);
322: if(bp == 0)
323: return;
324: }
325: p = (Etherpkt *)bp->rptr;
326: memmove(p->s, l.ea, sizeof(l.ea));
327: if(*p->d == 0xff || l.prom || l.all){
328: len = blen(bp);
329: nbp = copyb(bp, len);
330: nbp = expandb(nbp, len >= ETHERMINTU ? len : ETHERMINTU);
331: if(nbp){
332: nbp->wptr = nbp->rptr+len;
333: putq(&l.self, nbp);
334: wakeup(&l.rr);
335: }
336: } else if(*p->d == *l.ea && memcmp(l.ea, p->d, sizeof(l.ea)) == 0){
337: len = blen(bp);
338: bp = expandb(bp, len >= ETHERMINTU ? len : ETHERMINTU);
339: if(bp){
340: putq(&l.self, bp);
341: wakeup(&l.rr);
342: }
343: return;
344: }
345:
346: if(l.wedged) {
347: freeb(bp);
348: return;
349: }
350:
351: /*
352: * only one transmitter at a time
353: */
354: qlock(&l.tlock);
355:
356: if(l.wedged) {
357: qunlock(&l.tlock);
358: freeb(bp);
359: return;
360: }
361:
362: if(waserror()){
363: qunlock(&l.tlock);
364: freeb(bp);
365: nexterror();
366: }
367:
368: /*
369: * Wait till we get an output buffer, complain if input
370: * or output seems wedged.
371: */
372: m = &(LANCEMEM->tmr[l.tc]);
373: p = &l.tp[l.tc];
374: while((MPus(m->flags)&LANCEOWNER) != 0) {
375: tsleep(&l.tr, isobuf, m, 128);
376: if(l.wedged || isobuf(m) == 0){
377: qunlock(&l.tlock);
378: freeb(bp);
379: poperror();
380: print("lance wedged, dumping block & restarting\n");
381: lancestart(0);
382: l.wedged = 0;
383: return;
384: }
385: }
386:
387: /*
388: * copy message into lance RAM
389: */
390: len = 0;
391: for(nbp = bp; nbp; nbp = nbp->next){
392: if(sizeof(Etherpkt) - len >= (n = BLEN(nbp))){
393: memmove(((uchar *)p)+len, nbp->rptr, n);
394: len += n;
395: } else
396: print("no room damn it\n");
397: if(bp->flags & S_DELIM)
398: break;
399: }
400:
401: /*
402: * pad the packet (zero the pad)
403: */
404: if(len < ETHERMINTU){
405: memset(((char*)p)+len, 0, ETHERMINTU-len);
406: len = ETHERMINTU;
407: }
408:
409: /*
410: * set up the ring descriptor and hand to lance
411: */
412: l.outpackets++;
413: MPs(m->size) = -len;
414: MPus(m->cntflags) = 0;
415: MPus(m->laddr) = LADDR(&l.ltp[l.tc]);
416: MPus(m->flags) = LANCEOWNER|STP|ENP|HADDR(&l.ltp[l.tc]);
417: l.tc = TSUCC(l.tc);
418: *l.rdp = INEA|TDMD; /**/
419: wbflush();
420: qunlock(&l.tlock);
421: freeb(bp);
422: poperror();
423: }
424:
425: /*
426: * stop the lance and allocate buffers
427: */
428: void
429: lancereset(void)
430: {
431: static int already;
432: int i;
433:
434: if(already == 0){
435: already = 1;
436: lancesetup(&l);
437:
438: l.net.name = "ether";
439: l.net.nconv = Ntypes;
440: l.net.devp = &lanceinfo;
441: l.net.protop = 0;
442: l.net.listen = 0;
443: l.net.clone = lanceclonecon;
444: l.net.ninfo = 2;
445: l.net.info[0].name = "stats";
446: l.net.info[0].fill = lancestatsfill;
447: l.net.info[1].name = "type";
448: l.net.info[1].fill = lancetypefill;
449: for(i = 0; i < Ntypes; i++)
450: netadd(&l.net, &l.e[i], i);
451:
452: memset(l.bcast, 0xff, sizeof l.bcast);
453: }
454:
455: /*
456: * stop the lance
457: */
458: *l.rap = 0;
459: *l.rdp = STOP;
460: l.wedged = 1;
461: }
462:
463: /*
464: * Initialize and start the lance. This routine can be called only from a process.
465: * It may be used to restart a dead lance.
466: */
467: static void
468: lancestart(int mode)
469: {
470: int i;
471: Lancemem *lm = LANCEMEM;
472: Msg *m;
473:
474: /*
475: * wait till both receiver and transmitter are
476: * quiescent
477: */
478: qlock(&l.tlock);
479: qlock(&l.rlock);
480:
481: lancereset();
482: l.rl = 0;
483: l.tc = 0;
484:
485: /*
486: * create the initialization block
487: */
488: MPus(lm->mode) = mode;
489:
490: /*
491: * set ether addr from the value in the id prom.
492: * the id prom has them in reverse order, the init
493: * structure wants them in byte swapped order
494: */
495: MPus(lm->etheraddr[0]) = (l.ea[1]<<8) | l.ea[0];
496: MPus(lm->etheraddr[1]) = (l.ea[3]<<8) | l.ea[2];
497: MPus(lm->etheraddr[2]) = (l.ea[5]<<8) | l.ea[4];
498:
499: /*
500: * ignore multicast addresses
501: */
502: MPus(lm->multi[0]) = 0;
503: MPus(lm->multi[1]) = 0;
504: MPus(lm->multi[2]) = 0;
505: MPus(lm->multi[3]) = 0;
506:
507: /*
508: * set up rcv message ring
509: */
510: m = lm->rmr;
511: for(i = 0; i < l.nrrb; i++, m++){
512: MPs(m->size) = -sizeof(Etherpkt);
513: MPus(m->cntflags) = 0;
514: MPus(m->laddr) = LADDR(&l.lrp[i]);
515: MPus(m->flags) = HADDR(&l.lrp[i]);
516: }
517: MPus(lm->rdralow) = LADDR(l.lm->rmr);
518: MPus(lm->rdrahigh) = (l.lognrrb<<13)|HADDR(l.lm->rmr);
519:
520:
521: /*
522: * give the lance all the rcv buffers except one (as a sentinel)
523: */
524: m = lm->rmr;
525: for(i = 0; i < l.nrrb; i++, m++)
526: MPus(m->flags) |= LANCEOWNER;
527:
528: /*
529: * set up xmit message ring
530: */
531: m = lm->tmr;
532: for(i = 0; i < l.ntrb; i++, m++){
533: MPs(m->size) = 0;
534: MPus(m->cntflags) = 0;
535: MPus(m->laddr) = LADDR(&l.ltp[i]);
536: MPus(m->flags) = HADDR(&l.ltp[i]);
537: }
538: MPus(lm->tdralow) = LADDR(l.lm->tmr);
539: MPus(lm->tdrahigh) = (l.logntrb<<13)|HADDR(l.lm->tmr);
540:
541: /*
542: * point lance to the initialization block
543: */
544: *l.rap = 1;
545: *l.rdp = LADDR(l.lm);
546: wbflush();
547: *l.rap = 2;
548: *l.rdp = HADDR(l.lm);
549:
550: /*
551: * The lance byte swaps the ethernet packet unless we tell it not to
552: */
553: wbflush();
554: *l.rap = 3;
555: *l.rdp = l.busctl;
556:
557: /*
558: * initialize lance, turn on interrupts, turn on transmit and rcv.
559: */
560: wbflush();
561: *l.rap = 0;
562: *l.rdp = INEA|INIT|STRT; /**/
563:
564: /*
565: * spin for up to a second waiting for the IDON interrupt
566: */
567: for(i = 0; i < 1000; i++){
568: if(l.wedged == 0)
569: break;
570: delay(1);
571: }
572:
573: /*
574: * let in everything else
575: */
576: qunlock(&l.rlock);
577: qunlock(&l.tlock);
578: }
579:
580: void
581: lanceinit(void)
582: {
583: }
584:
585: Chan*
586: lanceattach(char *spec)
587: {
588: if(l.kstarted == 0){
589: kproc("lancekproc", lancekproc, 0);
590: l.kstarted = 1;
591: lancestart(0);
592: print("lance ether: %.2x%.2x%.2x%.2x%.2x%.2x\n",
593: l.ea[0], l.ea[1], l.ea[2], l.ea[3], l.ea[4], l.ea[5]);
594: }
595: return devattach('l', spec);
596: }
597:
598: Chan*
599: lanceclone(Chan *c, Chan *nc)
600: {
601: return devclone(c, nc);
602: }
603:
604: int
605: lancewalk(Chan *c, char *name)
606: {
607: return netwalk(c, name, &l.net);
608: }
609:
610: void
611: lancestat(Chan *c, char *dp)
612: {
613: netstat(c, dp, &l.net);
614: }
615:
616: /*
617: * Pass open's of anything except the directory to streamopen
618: */
619: Chan*
620: lanceopen(Chan *c, int omode)
621: {
622: return netopen(c, omode, &l.net);
623: }
624:
625: void
626: lancecreate(Chan *c, char *name, int omode, ulong perm)
627: {
628: USED(c, name, omode, perm);
629: error(Eperm);
630: }
631:
632: void
633: lanceclose(Chan *c)
634: {
635: if(c->stream)
636: streamclose(c);
637: }
638:
639: long
640: lanceread(Chan *c, void *a, long n, ulong offset)
641: {
642: return netread(c, a, n, offset, &l.net);
643: }
644:
645: long
646: lancewrite(Chan *c, void *a, long n, ulong offset)
647: {
648: USED(offset);
649: return streamwrite(c, a, n, 0);
650: }
651:
652: void
653: lanceremove(Chan *c)
654: {
655: USED(c);
656: error(Eperm);
657: }
658:
659: void
660: lancewstat(Chan *c, char *dp)
661: {
662: netwstat(c, dp, &l.net);
663: }
664:
665: /*
666: * user level network interface routines
667: */
668: static void
669: lancestatsfill(Chan *c, char* p, int n)
670: {
671: char buf[512];
672:
673: USED(c);
674: 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",
675: l.inpackets, l.outpackets, l.crcs,
676: l.overflows, l.frames, l.buffs, l.oerrs,
677: l.ea[0], l.ea[1], l.ea[2], l.ea[3], l.ea[4], l.ea[5]);
678: strncpy(p, buf, n);
679: }
680:
681: static void
682: lancetypefill(Chan *c, char* p, int n)
683: {
684: char buf[16];
685: Ethertype *e;
686:
687: e = &l.e[STREAMID(c->qid.path)];
688: sprint(buf, "%d", e->type);
689: strncpy(p, buf, n);
690: }
691:
692: static int
693: lanceclonecon(Chan *c)
694: {
695: Ethertype *e;
696:
697: USED(c);
698: for(e = l.e; e < &l.e[Ntypes]; e++){
699: qlock(e);
700: if(e->inuse || e->q){
701: qunlock(e);
702: continue;
703: }
704: e->inuse = 1;
705: netown(e, u->p->user, 0);
706: qunlock(e);
707: return e - l.e;
708: }
709: error(Enodev);
710: return -1; /* never reached */
711: }
712:
713: /*
714: * We will:
715: * (1) Clear interrupt cause in the lance
716: * (2) service all current events
717: */
718: void
719: lanceintr(void)
720: {
721: ushort csr;
722:
723: csr = *l.rdp;
724:
725: /*
726: * turn off the interrupt and any error indicators
727: */
728: *l.rdp = IDON|INEA|TINT|RINT|BABL|CERR|MISS|MERR;
729:
730: /*
731: * see if an error occurred
732: */
733: if(csr & (BABL|MISS|MERR)){
734: if(l.misses++ < 4) {
735: print("lance err #%ux\n", csr);
736: } else {
737: print("lance stopped\n");
738: l.wedged = 1;
739: l.misses = 0;
740: lancereset();
741: wakeup(&l.rr);
742: wakeup(&l.tr);
743: return;
744: }
745: }
746:
747: /*
748: * initialization done
749: */
750: if(csr & IDON)
751: l.wedged = 0;
752:
753: /*
754: * the lance turns off if it gets strange output errors
755: */
756: if((csr & (TXON|RXON)) != (TXON|RXON))
757: l.wedged = 1;
758:
759: /*
760: * wakeup the input process
761: */
762: if(csr & RINT)
763: wakeup(&l.rr);
764:
765: /*
766: * wake any process waiting for a transmit buffer
767: */
768: if(csr & TINT)
769: wakeup(&l.tr);
770: }
771:
772: /*
773: * send a packet upstream
774: */
775: static void
776: lanceup(Etherpkt *p, int len)
777: {
778: int t;
779: Block *bp;
780: Ethertype *e;
781:
782: if(len <= 0)
783: return;
784:
785: t = (p->type[0]<<8) | p->type[1];
786: for(e = &l.e[0]; e < &l.e[Ntypes]; e++){
787: /*
788: * check for open, the right type, and flow control
789: */
790: if(e->q==0 || (t!=e->type && e->type!=-1) || e->q->next->len>Streamhi)
791: continue;
792:
793: /*
794: * only a trace channel gets packets destined for other machines
795: */
796: if(e->type!=-1 && p->d[0]!=0xff
797: && (*p->d != *l.ea || memcmp(p->d, l.ea, sizeof(p->d))!=0))
798: continue;
799:
800: if(!waserror()){
801: bp = allocb(len);
802: memmove(bp->rptr, (uchar *)p, len);
803: bp->wptr += len;
804: bp->flags |= S_DELIM;
805: PUTNEXT(e->q, bp);
806: poperror();
807: }
808: }
809: }
810:
811: /*
812: * input process, awakened on each interrupt with rcv buffers filled
813: */
814: static int
815: isinput(void *arg)
816: {
817: Msg *m = arg;
818:
819: return ((MPus(m->flags) & LANCEOWNER)==0) || l.wedged || l.self.first
820: || l.closeline;
821: }
822:
823: static void
824: lancekproc(void *arg)
825: {
826: Etherpkt *p;
827: Ethertype *e;
828: int len;
829: int t;
830: Lancemem *lm = LANCEMEM;
831: Msg *m;
832: Block *bp;
833:
834: USED(arg);
835:
836: while(waserror())
837: print("lancekproc err %s\n", u->error);
838:
839: for(;;){
840: qlock(&l.rlock);
841: while(bp = getq(&l.self)){
842: lanceup((Etherpkt*)bp->rptr, BLEN(bp));
843: freeb(bp);
844: }
845: m = &(lm->rmr[l.rl]);
846: while((MPus(m->flags) & LANCEOWNER)==0){
847: l.inpackets++;
848: t = MPus(m->flags);
849: if(t & ERR){
850: if(t & FRAM)
851: l.frames++;
852: if(t & OFLO)
853: l.overflows++;
854: if(t & CRC)
855: l.crcs++;
856: if(t & BUFF)
857: l.buffs++;
858: } else {
859: /*
860: * stuff packet up each queue that wants it
861: */
862: p = &l.rp[l.rl];
863: len = MPus(m->cntflags) - 4;
864: lanceup(p, len);
865: }
866:
867: /*
868: * stage the next input buffer
869: */
870: MPs(m->size) = -sizeof(Etherpkt);
871: MPus(m->cntflags) = 0;
872: MPus(m->laddr) = LADDR(&l.lrp[l.rl]);
873: MPus(m->flags) = LANCEOWNER|HADDR(&l.lrp[l.rl]);
874: wbflush();
875: l.rl = RSUCC(l.rl);
876: m = &(lm->rmr[l.rl]);
877: }
878: qunlock(&l.rlock);
879: sleep(&l.rr, isinput, m);
880:
881: /*
882: * if the lance is wedged, restart it
883: */
884: if(l.wedged){
885: print("lance wedged, restarting\n");
886: lancestart(0);
887: }
888:
889: /*
890: * close ethertypes requesting it
891: */
892: if(l.closeline){
893: lock(&l.closepin);
894: for(e = l.closeline; e; e = e->closeline){
895: e->q = 0;
896: wakeup(&e->rc);
897: }
898: l.closeline = 0;
899: unlock(&l.closepin);
900: }
901: }
902: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.