cleanup: remove redundant includes left over from script.
[akaros.git] / kern / drivers / dev / ether.c
1 // INFERNO
2 #include <vfs.h>
3 #include <kfs.h>
4 #include <slab.h>
5 #include <kmalloc.h>
6 #include <kref.h>
7 #include <string.h>
8 #include <stdio.h>
9 #include <assert.h>
10 #include <error.h>
11 #include <cpio.h>
12 #include <pmap.h>
13 #include <smp.h>
14 #include <ip.h>
15
16 enum {
17         Type8021Q = 0x8100,                     /* value of type field for 802.1[pQ] tags */
18 };
19
20 static struct ether *etherxx[MaxEther]; /* real controllers */
21 static struct ether *vlanalloc(struct ether *, int);
22 static void vlanoq(struct ether *, struct block *);
23
24 struct chan *etherattach(char *spec)
25 {
26         ERRSTACK(1);
27         uint32_t ctlrno;
28         char *p;
29         struct chan *chan;
30         struct ether *ether, *vlan;
31         int vlanid;
32
33         ctlrno = 0;
34         vlanid = 0;
35         if (spec && *spec) {
36                 ctlrno = strtoul(spec, &p, 0);
37                 /* somebody interpret this for me. */
38                 if (((ctlrno == 0) && (p == spec)) ||
39                         (ctlrno >= MaxEther) || ((*p) && (*p != '.')))
40                         error(Ebadarg);
41                 if (*p == '.') {        /* vlan */
42                         vlanid = strtoul(p + 1, &p, 0);
43                         if (vlanid <= 0 || vlanid > 0xFFF || *p)
44                                 error(Ebadarg);
45                 }
46         }
47         if ((ether = etherxx[ctlrno]) == 0)
48                 error(Enodev);
49         rlock(&ether->rwlock);
50         if (waserror()) {
51                 runlock(&ether->rwlock);
52                 nexterror();
53         }
54         if (vlanid) {
55                 if (ether->maxmtu < ETHERMAXTU + 4)
56                         error("interface cannot support 802.1 tags");
57                 vlan = vlanalloc(ether, vlanid);
58                 chan = devattach('l', spec);
59                 chan->dev = ctlrno + (vlanid << 8);
60                 chan->aux = vlan;
61                 poperror();
62                 runlock(&ether->rwlock);
63                 return chan;
64         }
65         chan = devattach('l', spec);
66         chan->dev = ctlrno;
67         chan->aux = ether;
68         if (ether->attach)
69                 ether->attach(ether);
70         poperror();
71         runlock(&ether->rwlock);
72         return chan;
73 }
74
75 static void ethershutdown(void)
76 {
77         struct ether *ether;
78         int i;
79
80         for (i = 0; i < MaxEther; i++) {
81                 ether = etherxx[i];
82                 if (ether != NULL && ether->detach != NULL)
83                         ether->detach(ether);
84         }
85 }
86
87 static struct walkqid *etherwalk(struct chan *chan, struct chan *nchan,
88                                                                  char **name, int nname)
89 {
90         ERRSTACK(1);
91         struct walkqid *wq;
92         struct ether *ether;
93
94         ether = chan->aux;
95         rlock(&ether->rwlock);
96         if (waserror()) {
97                 runlock(&ether->rwlock);
98                 nexterror();
99         }
100         wq = netifwalk(&ether->netif, chan, nchan, name, nname);
101         if (wq && wq->clone != NULL && wq->clone != chan)
102                 wq->clone->aux = ether;
103         poperror();
104         runlock(&ether->rwlock);
105         return wq;
106 }
107
108 static int etherstat(struct chan *chan, uint8_t * dp, int n)
109 {
110         ERRSTACK(1);
111         int s;
112         struct ether *ether;
113
114         ether = chan->aux;
115         rlock(&ether->rwlock);
116         if (waserror()) {
117                 runlock(&ether->rwlock);
118                 nexterror();
119         }
120         s = netifstat(&ether->netif, chan, dp, n);
121         poperror();
122         runlock(&ether->rwlock);
123         return s;
124 }
125
126 static struct chan *etheropen(struct chan *chan, int omode)
127 {
128         ERRSTACK(1);
129         struct chan *c;
130         struct ether *ether;
131
132         ether = chan->aux;
133         rlock(&ether->rwlock);
134         if (waserror()) {
135                 runlock(&ether->rwlock);
136                 nexterror();
137         }
138         c = netifopen(&ether->netif, chan, omode);
139         poperror();
140         runlock(&ether->rwlock);
141         return c;
142 }
143
144 static void etherclose(struct chan *chan)
145 {
146         ERRSTACK(1);
147         struct ether *ether;
148
149         ether = chan->aux;
150         rlock(&ether->rwlock);
151         if (waserror()) {
152                 runlock(&ether->rwlock);
153                 nexterror();
154         }
155         netifclose(&ether->netif, chan);
156         poperror();
157         runlock(&ether->rwlock);
158 }
159
160 static long etherread(struct chan *chan, void *buf, long n, int64_t off)
161 {
162         ERRSTACK(1);
163         struct ether *ether;
164         uint32_t offset = off;
165         long r;
166
167         ether = chan->aux;
168         rlock(&ether->rwlock);
169         if (waserror()) {
170                 runlock(&ether->rwlock);
171                 nexterror();
172         }
173         if ((chan->qid.type & QTDIR) == 0 && ether->ifstat) {
174                 /*
175                  * With some controllers it is necessary to reach
176                  * into the chip to extract statistics.
177                  */
178                 if (NETTYPE(chan->qid.path) == Nifstatqid) {
179                         r = ether->ifstat(ether, buf, n, offset);
180                         goto out;
181                 }
182                 if (NETTYPE(chan->qid.path) == Nstatqid)
183                         ether->ifstat(ether, buf, 0, offset);
184         }
185         r = netifread(&ether->netif, chan, buf, n, offset);
186 out:
187         poperror();
188         runlock(&ether->rwlock);
189         return r;
190 }
191
192 static struct block *etherbread(struct chan *chan, long n, uint32_t offset)
193 {
194         ERRSTACK(1);
195         struct block *b;
196         struct ether *ether;
197
198         ether = chan->aux;
199         rlock(&ether->rwlock);
200         if (waserror()) {
201                 runlock(&ether->rwlock);
202                 nexterror();
203         }
204         b = netifbread(&ether->netif, chan, n, offset);
205         poperror();
206         runlock(&ether->rwlock);
207         return b;
208 }
209
210 static int etherwstat(struct chan *chan, uint8_t * dp, int n)
211 {
212         ERRSTACK(1);
213         struct ether *ether;
214         int r;
215
216         ether = chan->aux;
217         rlock(&ether->rwlock);
218         if (waserror()) {
219                 runlock(&ether->rwlock);
220                 nexterror();
221         }
222         r = netifwstat(&ether->netif, chan, dp, n);
223         poperror();
224         runlock(&ether->rwlock);
225         return r;
226 }
227
228 static void etherrtrace(struct netfile *f, struct etherpkt *pkt, int len)
229 {
230         int i, n;
231         struct block *bp;
232
233         if (qwindow(f->in) <= 0)
234                 return;
235         if (len > 58)
236                 n = 58;
237         else
238                 n = len;
239         bp = iallocb(64);
240         if (bp == NULL)
241                 return;
242         memmove(bp->wp, pkt->d, n);
243         i = milliseconds();
244         bp->wp[58] = len >> 8;
245         bp->wp[59] = len;
246         bp->wp[60] = i >> 24;
247         bp->wp[61] = i >> 16;
248         bp->wp[62] = i >> 8;
249         bp->wp[63] = i;
250         bp->wp += 64;
251         qpass(f->in, bp);
252 }
253
254 struct block *etheriq(struct ether *ether, struct block *bp, int fromwire)
255 {
256         struct etherpkt *pkt;
257         uint16_t type;
258         int len, multi, tome, fromme, vlanid, i;
259         struct netfile **ep, *f, **fp, *fx;
260         struct block *xbp;
261         struct ether *vlan;
262
263         ether->netif.inpackets++;
264
265         pkt = (struct etherpkt *)bp->rp;
266         len = BLEN(bp);
267         type = (pkt->type[0] << 8) | pkt->type[1];
268         if (type == Type8021Q && ether->nvlan) {
269                 vlanid = nhgets(bp->rp + 2 * Eaddrlen + 2) & 0xFFF;
270                 if (vlanid) {
271                         for (i = 0; i < ARRAY_SIZE(ether->vlans); i++) {
272                                 vlan = ether->vlans[i];
273                                 if (vlan != NULL && vlan->vlanid == vlanid) {
274                                         memmove(bp->rp + 4, bp->rp, 2 * Eaddrlen);
275                                         bp->rp += 4;
276                                         return etheriq(vlan, bp, fromwire);
277                                 }
278                         }
279                         /* allow normal type handling to accept or discard it */
280                 }
281         }
282
283         fx = 0;
284         ep = &ether->netif.f[Ntypes];
285
286         multi = pkt->d[0] & 1;
287         /* check for valid multcast addresses */
288         if (multi && memcmp(pkt->d, ether->netif.bcast, sizeof(pkt->d)) != 0
289                 && ether->netif.prom == 0) {
290                 if (!activemulti(&ether->netif, pkt->d, sizeof(pkt->d))) {
291                         if (fromwire) {
292                                 freeb(bp);
293                                 bp = 0;
294                         }
295                         return bp;
296                 }
297         }
298
299         /* is it for me? */
300         tome = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
301         fromme = memcmp(pkt->s, ether->ea, sizeof(pkt->s)) == 0;
302
303         /*
304          * Multiplex the packet to all the connections which want it.
305          * If the packet is not to be used subsequently (fromwire != 0),
306          * attempt to simply pass it into one of the connections, thereby
307          * saving a copy of the data (usual case hopefully).
308          */
309         for (fp = ether->netif.f; fp < ep; fp++) {
310                 if ((f = *fp) && (f->type == type || f->type < 0))
311                         if (tome || multi || f->prom) {
312                                 /* Don't want to hear bridged packets */
313                                 if (f->bridge && !fromwire && !fromme)
314                                         continue;
315                                 if (!f->headersonly) {
316                                         if (fromwire && fx == 0)
317                                                 fx = f;
318                                         else if ((xbp = iallocb(len))) {
319                                                 memmove(xbp->wp, pkt, len);
320                                                 xbp->wp += len;
321                                                 if (qpass(f->in, xbp) < 0)
322                                                         ether->netif.soverflows++;
323                                         } else
324                                                 ether->netif.soverflows++;
325                                 } else
326                                         etherrtrace(f, pkt, len);
327                         }
328         }
329
330         if (fx) {
331                 if (qpass(fx->in, bp) < 0)
332                         ether->netif.soverflows++;
333                 return 0;
334         }
335         if (fromwire) {
336                 freeb(bp);
337                 return 0;
338         }
339
340         return bp;
341 }
342
343 static int etheroq(struct ether *ether, struct block *bp)
344 {
345         int len, loopback;
346         struct etherpkt *pkt;
347         int8_t irq_state = 0;
348
349         ether->netif.outpackets++;
350
351         /*
352          * Check if the packet has to be placed back onto the input queue,
353          * i.e. if it's a loopback or broadcast packet or the interface is
354          * in promiscuous mode.
355          * If it's a loopback packet indicate to etheriq that the data isn't
356          * needed and return, etheriq will pass-on or free the block.
357          * To enable bridging to work, only packets that were originated
358          * by this interface are fed back.
359          */
360         pkt = (struct etherpkt *)bp->rp;
361         len = BLEN(bp);
362         loopback = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
363         if (loopback || memcmp(pkt->d, ether->netif.bcast, sizeof(pkt->d)) == 0
364                 || ether->netif.prom) {
365                 disable_irqsave(&irq_state);
366                 etheriq(ether, bp, 0);
367                 enable_irqsave(&irq_state);
368         }
369
370         if (!loopback) {
371                 if (ether->vlanid) {
372                         /* add tag */
373                         bp = padblock(bp, 2 + 2);
374                         memmove(bp->rp, bp->rp + 4, 2 * Eaddrlen);
375                         hnputs(bp->rp + 2 * Eaddrlen, Type8021Q);
376                         hnputs(bp->rp + 2 * Eaddrlen + 2, ether->vlanid & 0xFFF);       /* prio:3 0:1 vid:12 */
377                         ether = ether->ctlr;
378                 }
379                 qbwrite(ether->oq, bp);
380                 if (ether->transmit != NULL)
381                         ether->transmit(ether);
382         } else
383                 freeb(bp);
384
385         return len;
386 }
387
388 static long etherwrite(struct chan *chan, void *buf, long n, int64_t unused)
389 {
390         ERRSTACK(2);
391         struct ether *ether;
392         struct block *bp;
393         int onoff;
394         struct cmdbuf *cb;
395         long l;
396
397         ether = chan->aux;
398         rlock(&ether->rwlock);
399         if (waserror()) {
400                 runlock(&ether->rwlock);
401                 nexterror();
402         }
403         if (NETTYPE(chan->qid.path) != Ndataqid) {
404                 l = netifwrite(&ether->netif, chan, buf, n);
405                 if (l >= 0)
406                         goto out;
407                 cb = parsecmd(buf, n);
408                 if (strcmp(cb->f[0], "nonblocking") == 0) {
409                         if (cb->nf <= 1)
410                                 onoff = 1;
411                         else
412                                 onoff = atoi(cb->f[1]);
413                         if (ether->oq != NULL)
414                                 qnoblock(ether->oq, onoff);
415                         kfree(cb);
416                         goto out;
417                 }
418                 kfree(cb);
419                 if (ether->ctl != NULL) {
420                         l = ether->ctl(ether, buf, n);
421                         goto out;
422                 }
423                 error(Ebadctl);
424         }
425
426         if (n > ether->maxmtu)
427                 error(Etoobig);
428         if (n < ether->minmtu)
429                 error(Etoosmall);
430         bp = allocb(n);
431         if (waserror()) {
432                 freeb(bp);
433                 nexterror();
434         }
435         memmove(bp->rp, buf, n);
436         memmove(bp->rp + Eaddrlen, ether->ea, Eaddrlen);
437         bp->wp += n;
438         poperror();
439
440         l = etheroq(ether, bp);
441 out:
442         poperror();
443         runlock(&ether->rwlock);
444         return l;
445 }
446
447 static long etherbwrite(struct chan *chan, struct block *bp, uint32_t unused)
448 {
449         ERRSTACK(1);
450         struct ether *ether;
451         long n;
452
453         n = BLEN(bp);
454         if (NETTYPE(chan->qid.path) != Ndataqid) {
455                 if (waserror()) {
456                         freeb(bp);
457                         nexterror();
458                 }
459                 n = etherwrite(chan, bp->rp, n, 0);
460                 poperror();
461                 freeb(bp);
462                 return n;
463         }
464         ether = chan->aux;
465         rlock(&ether->rwlock);
466         if (waserror()) {
467                 runlock(&ether->rwlock);
468                 nexterror();
469         }
470         if (n > ether->maxmtu) {
471                 freeb(bp);
472                 error(Etoobig);
473         }
474         if (n < ether->minmtu) {
475                 freeb(bp);
476                 error(Etoosmall);
477         }
478         n = etheroq(ether, bp);
479         poperror();
480         runlock(&ether->rwlock);
481         return n;
482 }
483
484 static void nop(struct ether *unused)
485 {
486 }
487
488 static long vlanctl(struct ether *ether, void *buf, long n)
489 {
490         uint8_t ea[Eaddrlen];
491         struct ether *master;
492         struct cmdbuf *cb;
493         int i;
494
495         cb = parsecmd(buf, n);
496         if (cb->nf >= 2
497                 && strcmp(cb->f[0], "ea") == 0 && parseether(ea, cb->f[1]) == 0) {
498                 kfree(cb);
499                 memmove(ether->ea, ea, Eaddrlen);
500                 memmove(ether->netif.addr, ether->ea, Eaddrlen);
501                 return 0;
502         }
503         if (cb->nf == 1 && strcmp(cb->f[0], "disable") == 0) {
504                 master = ether->ctlr;
505                 qlock(&master->vlq);
506                 for (i = 0; i < ARRAY_SIZE(master->vlans); i++)
507                         if (master->vlans[i] == ether) {
508                                 ether->vlanid = 0;
509                                 master->nvlan--;
510                                 break;
511                         }
512                 qunlock(&master->vlq);
513                 kfree(cb);
514                 return 0;
515         }
516         kfree(cb);
517         error(Ebadctl);
518         return -1;      /* not reached */
519 }
520
521 static struct ether *vlanalloc(struct ether *ether, int id)
522 {
523         ERRSTACK(1);
524         struct ether *vlan;
525         int i, fid;
526         char name[KNAMELEN];
527
528         qlock(&ether->vlq);
529         if (waserror()) {
530                 qunlock(&ether->vlq);
531                 nexterror();
532         }
533         fid = -1;
534         for (i = 0; i < ARRAY_SIZE(ether->vlans); i++) {
535                 vlan = ether->vlans[i];
536                 if (vlan != NULL && vlan->vlanid == id) {
537                         poperror();
538                         qunlock(&ether->vlq);
539                         return vlan;
540                 }
541                 if (fid < 0 && (vlan == NULL || vlan->vlanid == 0))
542                         fid = i;
543         }
544         if (fid < 0)
545                 error(Enoifc);
546         snprintf(name, sizeof(name), "ether%d.%d", ether->ctlrno, id);
547         vlan = ether->vlans[fid];
548         if (vlan == NULL) {
549                 vlan = kzmalloc(sizeof(struct ether), 1);
550                 if (vlan == NULL)
551                         error(Enovmem);
552                 rwinit(&vlan->rwlock);
553                 qlock_init(&vlan->vlq);
554                 netifinit(&vlan->netif, name, Ntypes, ether->netif.limit);
555                 ether->vlans[fid] = vlan;       /* id is still zero, can't be matched */
556                 ether->nvlan++;
557         } else
558                 memmove(vlan->netif.name, name, KNAMELEN - 1);
559         vlan->attach = nop;
560         vlan->transmit = NULL;
561         vlan->ctl = vlanctl;
562         vlan->irq = -1;
563         vlan->netif.promiscuous = ether->netif.promiscuous;
564         vlan->netif.multicast = ether->netif.multicast;
565         vlan->netif.arg = vlan;
566         vlan->netif.mbps = ether->netif.mbps;
567         vlan->fullduplex = ether->fullduplex;
568         vlan->encry = ether->encry;
569         vlan->minmtu = ether->minmtu;
570         vlan->maxmtu = ether->maxmtu;
571         vlan->ctlrno = ether->ctlrno;
572         vlan->vlanid = id;
573         vlan->netif.alen = Eaddrlen;
574         memmove(vlan->netif.addr, ether->netif.addr, sizeof(vlan->netif.addr));
575         memmove(vlan->netif.bcast, ether->netif.bcast, sizeof(ether->netif.bcast));
576         vlan->oq = NULL;
577         vlan->ctlr = ether;
578         vlan->vlanid = id;
579         poperror();
580         qunlock(&ether->vlq);
581         return vlan;
582 }
583
584 static struct {
585         char *type;
586         int (*reset) (struct ether *);
587 } cards[MaxEther + 1];
588
589 void addethercard(char *t, int (*r) (struct ether *))
590 {
591         static int ncard;
592
593         if (ncard == MaxEther)
594                 panic("too many ether cards");
595         cards[ncard].type = t;
596         cards[ncard].reset = r;
597         ncard++;
598 }
599
600 int parseether(uint8_t * to, char *from)
601 {
602         char nip[4];
603         char *p;
604         int i;
605
606         p = from;
607         for (i = 0; i < Eaddrlen; i++) {
608                 if (*p == 0)
609                         return -1;
610                 nip[0] = *p++;
611                 if (*p == 0)
612                         return -1;
613                 nip[1] = *p++;
614                 nip[2] = 0;
615                 to[i] = strtoul(nip, 0, 16);
616                 if (*p == ':')
617                         p++;
618         }
619         return 0;
620 }
621
622 static void etherreset(void)
623 {
624         struct ether *ether;
625         int i, n, ctlrno, qsize;
626         char name[KNAMELEN], buf[128];
627
628         for (ether = 0, ctlrno = 0; ctlrno < MaxEther; ctlrno++) {
629                 if (ether == 0)
630                         ether = kzmalloc(sizeof(struct ether), 0);
631                 memset(ether, 0, sizeof(struct ether));
632                 rwinit(&ether->rwlock);
633                 qlock_init(&ether->vlq);
634                 ether->ctlrno = ctlrno;
635                 ether->netif.mbps = 10;
636                 ether->minmtu = ETHERMINTU;
637                 ether->maxmtu = ETHERMAXTU;
638                 /* looked like irq type, we don't have these yet */
639                 //ether->netif.itype = -1;
640
641                 /* TODO: looks like they expected some init to be done here.  at the
642                  * very least, ether->type is 0 right now, and needs to be set.  looking
643                  * around online, it seems to find out ether config settings, so that we
644                  * can set some flags in the opt parseing below. */
645                 //if(archether(ctlrno, ether) <= 0)
646                 //  continue;
647
648                 for (n = 0; cards[n].type; n++) {
649 #if 0
650                         if (cistrcmp(cards[n].type, ether->type))
651                                 continue;
652                         for (i = 0; i < ether->nopt; i++) {
653                                 if (cistrncmp(ether->opt[i], "ea=", 3) == 0) {
654                                         if (parseether(ether->ea, &ether->opt[i][3]) == -1)
655                                                 memset(ether->ea, 0, Eaddrlen);
656                                 } else if (cistrcmp(ether->opt[i], "fullduplex") == 0 ||
657                                                    cistrcmp(ether->opt[i], "10BASE-TFD") == 0)
658                                         ether->fullduplex = 1;
659                                 else if (cistrcmp(ether->opt[i], "100BASE-TXFD") == 0)
660                                         ether->mbps = 100;
661                         }
662 #endif
663                         if (cards[n].reset(ether))
664                                 continue;
665                         /* might be fucked a bit - reset() doesn't know the type.  might not
666                          * even matter, except for debugging. */
667                         ether->type = cards[n].type;
668                         snprintf(name, sizeof(name), "ether%d", ctlrno);
669
670                         i = snprintf(buf, sizeof(buf),
671                                                  "#l%d: %s: %dMbps port 0x%x irq %u", ctlrno,
672                                                  ether->type, ether->netif.mbps, ether->port,
673                                                  ether->irq);
674                         /* Looks like this is for printing MMIO addrs */
675 #if 0
676                         if (ether->mem)
677                                 i += snprintf(buf + i, sizeof(buf) - i, " addr 0x%lx",
678                                                           PADDR(ether->mem));
679                         if (ether->size)
680                                 i += snprintf(buf + i, sizeof(buf) - i, " size 0x%lx",
681                                                           ether->size);
682 #endif
683                         i += snprintf(buf + i, sizeof(buf) - i,
684                                                   ": %02.2x:%02.2x:%02.2x:%02.2x:%02.2x:%02.2x",
685                                                   ether->ea[0], ether->ea[1], ether->ea[2],
686                                                   ether->ea[3], ether->ea[4], ether->ea[5]);
687                         snprintf(buf + i, sizeof(buf) - i, "\n");
688                         printk(buf);
689
690                         switch (ether->netif.mbps) {
691
692                         case 1 ... 99:
693                                 qsize = 64 * 1024;
694                                 break;
695                         case 100 ... 999:
696                                 qsize = 256 * 1024;
697                                 break;
698                         case 1000 ... 9999:
699                                 qsize = 1024 * 1024;
700                                 break;
701                         default:
702                                 qsize = 8 * 1024 * 1024;
703                         }
704                         netifinit(&ether->netif, name, Ntypes, qsize);
705                         if (ether->oq == 0)
706                                 ether->oq = qopen(qsize, Qmsg, 0, 0);
707                         if (ether->oq == 0)
708                                 panic("etherreset %s", name);
709                         ether->netif.alen = Eaddrlen;
710                         memmove(ether->netif.addr, ether->ea, Eaddrlen);
711                         memset(ether->netif.bcast, 0xFF, Eaddrlen);
712
713                         etherxx[ctlrno] = ether;
714                         ether = 0;
715                         break;
716                 }
717         }
718         if (ether)
719                 kfree(ether);
720 }
721
722 static void etherpower(int on)
723 {
724         int i;
725         struct ether *ether;
726
727         /* TODO: fix etherpower.  locking and ether->readers are broken. */
728         warn("%s needs attention.  had a rough porting from inferno", __FUNCTION__);
729         for (i = 0; i < MaxEther; i++) {
730                 if ((ether = etherxx[i]) == NULL || ether->power == NULL)
731                         continue;
732                 if (on) {
733                         /* brho: not sure what they are doing.  there seem to be certain
734                          * assumptions about calling etherpower.  i think they are using
735                          * canrlock to see if the lock is currently writelocked.  and if it
736                          * was not lockable, they would assume they had the write lock and
737                          * could unlock.  this is super fucked up. */
738                         if (canrlock(&ether->rwlock)) {
739                                 runlock(&ether->rwlock);        // brho added this
740                                 continue;
741                         }
742                         if (ether->power != NULL)
743                                 ether->power(ether, on);
744                         wunlock(&ether->rwlock);
745                 } else {
746                         /* readers isn't in the ether struct...
747                            if(ether->readers)
748                            continue;
749                          */
750                         wlock(&ether->rwlock);
751                         if (ether->power != NULL)
752                                 ether->power(ether, on);
753                         /* Keep locked until power goes back on */
754                 }
755         }
756 }
757
758 #define ETHERPOLY 0xedb88320
759
760 /* really slow 32 bit crc for ethers */
761 uint32_t ethercrc(uint8_t * p, int len)
762 {
763         int i, j;
764         uint32_t crc, b;
765
766         crc = 0xffffffff;
767         for (i = 0; i < len; i++) {
768                 b = *p++;
769                 for (j = 0; j < 8; j++) {
770                         crc = (crc >> 1) ^ (((crc ^ b) & 1) ? ETHERPOLY : 0);
771                         b >>= 1;
772                 }
773         }
774         return crc;
775 }
776
777 struct dev etherdevtab __devtab = {
778         'l',
779         "ether",
780
781         etherreset,
782         devinit,
783         ethershutdown,
784         etherattach,
785         etherwalk,
786         etherstat,
787         etheropen,
788         devcreate,
789         etherclose,
790         etherread,
791         etherbread,
792         etherwrite,
793         etherbwrite,
794         devremove,
795         etherwstat,
796         etherpower,
797         devchaninfo,
798 };