Assume natural alignment for IP & ether addrs
[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 #ifdef CONFIG_RISCV
255 #warning "Potentially unaligned ethernet addrs!"
256 #endif
257
258 static inline int eaddrcmp(uint8_t *x, uint8_t *y)
259 {
260         uint16_t *a = (uint16_t *)x;
261         uint16_t *b = (uint16_t *)y;
262
263         return (a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]);
264 }
265
266 struct block *etheriq(struct ether *ether, struct block *bp, int fromwire)
267 {
268         struct etherpkt *pkt;
269         uint16_t type;
270         int len, multi, tome, fromme, vlanid, i;
271         struct netfile **ep, *f, **fp, *fx;
272         struct block *xbp;
273         struct ether *vlan;
274
275         ether->netif.inpackets++;
276
277         pkt = (struct etherpkt *)bp->rp;
278         len = BLEN(bp);
279         type = (pkt->type[0] << 8) | pkt->type[1];
280         if (type == Type8021Q && ether->nvlan) {
281                 vlanid = nhgets(bp->rp + 2 * Eaddrlen + 2) & 0xFFF;
282                 if (vlanid) {
283                         for (i = 0; i < ARRAY_SIZE(ether->vlans); i++) {
284                                 vlan = ether->vlans[i];
285                                 if (vlan != NULL && vlan->vlanid == vlanid) {
286                                         memmove(bp->rp + 4, bp->rp, 2 * Eaddrlen);
287                                         bp->rp += 4;
288                                         return etheriq(vlan, bp, fromwire);
289                                 }
290                         }
291                         /* allow normal type handling to accept or discard it */
292                 }
293         }
294
295         fx = 0;
296         ep = &ether->netif.f[Ntypes];
297
298         multi = pkt->d[0] & 1;
299         /* check for valid multcast addresses */
300         if (multi && eaddrcmp(pkt->d, ether->netif.bcast) != 0
301                 && ether->netif.prom == 0) {
302                 if (!activemulti(&ether->netif, pkt->d, sizeof(pkt->d))) {
303                         if (fromwire) {
304                                 freeb(bp);
305                                 bp = 0;
306                         }
307                         return bp;
308                 }
309         }
310
311         /* is it for me? */
312         tome = eaddrcmp(pkt->d, ether->ea) == 0;
313         fromme = eaddrcmp(pkt->s, ether->ea) == 0;
314
315         /*
316          * Multiplex the packet to all the connections which want it.
317          * If the packet is not to be used subsequently (fromwire != 0),
318          * attempt to simply pass it into one of the connections, thereby
319          * saving a copy of the data (usual case hopefully).
320          */
321         for (fp = ether->netif.f; fp < ep; fp++) {
322                 if ((f = *fp) && (f->type == type || f->type < 0))
323                         if (tome || multi || f->prom) {
324                                 /* Don't want to hear bridged packets */
325                                 if (f->bridge && !fromwire && !fromme)
326                                         continue;
327                                 if (!f->headersonly) {
328                                         if (fromwire && fx == 0)
329                                                 fx = f;
330                                         else if ((xbp = iallocb(len))) {
331                                                 memmove(xbp->wp, pkt, len);
332                                                 xbp->wp += len;
333                                                 if (qpass(f->in, xbp) < 0)
334                                                         ether->netif.soverflows++;
335                                         } else
336                                                 ether->netif.soverflows++;
337                                 } else
338                                         etherrtrace(f, pkt, len);
339                         }
340         }
341
342         if (fx) {
343                 if (qpass(fx->in, bp) < 0)
344                         ether->netif.soverflows++;
345                 return 0;
346         }
347         if (fromwire) {
348                 freeb(bp);
349                 return 0;
350         }
351
352         return bp;
353 }
354
355 static int etheroq(struct ether *ether, struct block *bp)
356 {
357         int len, loopback;
358         struct etherpkt *pkt;
359         int8_t irq_state = 0;
360
361         ether->netif.outpackets++;
362
363         /*
364          * Check if the packet has to be placed back onto the input queue,
365          * i.e. if it's a loopback or broadcast packet or the interface is
366          * in promiscuous mode.
367          * If it's a loopback packet indicate to etheriq that the data isn't
368          * needed and return, etheriq will pass-on or free the block.
369          * To enable bridging to work, only packets that were originated
370          * by this interface are fed back.
371          */
372         pkt = (struct etherpkt *)bp->rp;
373         len = BLEN(bp);
374         loopback = eaddrcmp(pkt->d, ether->ea) == 0;
375         if (loopback || eaddrcmp(pkt->d, ether->netif.bcast) == 0
376                 || ether->netif.prom) {
377                 disable_irqsave(&irq_state);
378                 etheriq(ether, bp, 0);
379                 enable_irqsave(&irq_state);
380         }
381
382         if (!loopback) {
383                 if (ether->vlanid) {
384                         /* add tag */
385                         bp = padblock(bp, 2 + 2);
386                         memmove(bp->rp, bp->rp + 4, 2 * Eaddrlen);
387                         hnputs(bp->rp + 2 * Eaddrlen, Type8021Q);
388                         hnputs(bp->rp + 2 * Eaddrlen + 2, ether->vlanid & 0xFFF);       /* prio:3 0:1 vid:12 */
389                         ether = ether->ctlr;
390                 }
391
392                 if ((ether->netif.feat & NETF_PADMIN) == 0 && BLEN(bp) < ether->minmtu)
393                         bp = adjustblock(bp, ether->minmtu);
394
395                 ptclcsum_finalize(bp, ether->netif.feat);
396                 qbwrite(ether->oq, bp);
397                 if (ether->transmit != NULL)
398                         ether->transmit(ether);
399         } else
400                 freeb(bp);
401
402         return len;
403 }
404
405 static long etherwrite(struct chan *chan, void *buf, long n, int64_t unused)
406 {
407         ERRSTACK(2);
408         struct ether *ether;
409         struct block *bp;
410         int onoff;
411         struct cmdbuf *cb;
412         long l;
413
414         ether = chan->aux;
415         rlock(&ether->rwlock);
416         if (waserror()) {
417                 runlock(&ether->rwlock);
418                 nexterror();
419         }
420         if (NETTYPE(chan->qid.path) != Ndataqid) {
421                 l = netifwrite(&ether->netif, chan, buf, n);
422                 if (l >= 0)
423                         goto out;
424                 cb = parsecmd(buf, n);
425                 if (strcmp(cb->f[0], "nonblocking") == 0) {
426                         if (cb->nf <= 1)
427                                 onoff = 1;
428                         else
429                                 onoff = atoi(cb->f[1]);
430                         if (ether->oq != NULL)
431                                 qnoblock(ether->oq, onoff);
432                         kfree(cb);
433                         goto out;
434                 }
435                 kfree(cb);
436                 if (ether->ctl != NULL) {
437                         l = ether->ctl(ether, buf, n);
438                         goto out;
439                 }
440                 error(Ebadctl);
441         }
442
443         if (n > ether->maxmtu)
444                 error(Etoobig);
445         bp = allocb(n);
446         if (waserror()) {
447                 freeb(bp);
448                 nexterror();
449         }
450         memmove(bp->rp, buf, n);
451         memmove(bp->rp + Eaddrlen, ether->ea, Eaddrlen);
452         bp->wp += n;
453         poperror();
454
455         l = etheroq(ether, bp);
456 out:
457         poperror();
458         runlock(&ether->rwlock);
459         return l;
460 }
461
462 static long etherbwrite(struct chan *chan, struct block *bp, uint32_t unused)
463 {
464         ERRSTACK(1);
465         struct ether *ether;
466         long n;
467
468         n = BLEN(bp);
469         if (NETTYPE(chan->qid.path) != Ndataqid) {
470                 if (waserror()) {
471                         freeb(bp);
472                         nexterror();
473                 }
474                 n = etherwrite(chan, bp->rp, n, 0);
475                 poperror();
476                 freeb(bp);
477                 return n;
478         }
479         ether = chan->aux;
480         rlock(&ether->rwlock);
481         if (waserror()) {
482                 runlock(&ether->rwlock);
483                 nexterror();
484         }
485         if (n > ether->maxmtu) {
486                 freeb(bp);
487                 error(Etoobig);
488         }
489         n = etheroq(ether, bp);
490         poperror();
491         runlock(&ether->rwlock);
492         return n;
493 }
494
495 static void nop(struct ether *unused)
496 {
497 }
498
499 static long vlanctl(struct ether *ether, void *buf, long n)
500 {
501         uint8_t ea[Eaddrlen];
502         struct ether *master;
503         struct cmdbuf *cb;
504         int i;
505
506         cb = parsecmd(buf, n);
507         if (cb->nf >= 2
508                 && strcmp(cb->f[0], "ea") == 0 && parseether(ea, cb->f[1]) == 0) {
509                 kfree(cb);
510                 memmove(ether->ea, ea, Eaddrlen);
511                 memmove(ether->netif.addr, ether->ea, Eaddrlen);
512                 return 0;
513         }
514         if (cb->nf == 1 && strcmp(cb->f[0], "disable") == 0) {
515                 master = ether->ctlr;
516                 qlock(&master->vlq);
517                 for (i = 0; i < ARRAY_SIZE(master->vlans); i++)
518                         if (master->vlans[i] == ether) {
519                                 ether->vlanid = 0;
520                                 master->nvlan--;
521                                 break;
522                         }
523                 qunlock(&master->vlq);
524                 kfree(cb);
525                 return 0;
526         }
527         kfree(cb);
528         error(Ebadctl);
529         return -1;      /* not reached */
530 }
531
532 static struct ether *vlanalloc(struct ether *ether, int id)
533 {
534         ERRSTACK(1);
535         struct ether *vlan;
536         int i, fid;
537         char name[KNAMELEN];
538
539         qlock(&ether->vlq);
540         if (waserror()) {
541                 qunlock(&ether->vlq);
542                 nexterror();
543         }
544         fid = -1;
545         for (i = 0; i < ARRAY_SIZE(ether->vlans); i++) {
546                 vlan = ether->vlans[i];
547                 if (vlan != NULL && vlan->vlanid == id) {
548                         poperror();
549                         qunlock(&ether->vlq);
550                         return vlan;
551                 }
552                 if (fid < 0 && (vlan == NULL || vlan->vlanid == 0))
553                         fid = i;
554         }
555         if (fid < 0)
556                 error(Enoifc);
557         snprintf(name, sizeof(name), "ether%d.%d", ether->ctlrno, id);
558         vlan = ether->vlans[fid];
559         if (vlan == NULL) {
560                 vlan = kzmalloc(sizeof(struct ether), 1);
561                 if (vlan == NULL)
562                         error(Enovmem);
563                 rwinit(&vlan->rwlock);
564                 qlock_init(&vlan->vlq);
565                 netifinit(&vlan->netif, name, Ntypes, ether->netif.limit);
566                 ether->vlans[fid] = vlan;       /* id is still zero, can't be matched */
567                 ether->nvlan++;
568         } else
569                 memmove(vlan->netif.name, name, KNAMELEN - 1);
570         vlan->attach = nop;
571         vlan->transmit = NULL;
572         vlan->ctl = vlanctl;
573         vlan->irq = -1;
574         vlan->netif.promiscuous = ether->netif.promiscuous;
575         vlan->netif.multicast = ether->netif.multicast;
576         vlan->netif.arg = vlan;
577         vlan->netif.mbps = ether->netif.mbps;
578         vlan->fullduplex = ether->fullduplex;
579         vlan->encry = ether->encry;
580         vlan->minmtu = ether->minmtu;
581         vlan->maxmtu = ether->maxmtu;
582         vlan->ctlrno = ether->ctlrno;
583         vlan->vlanid = id;
584         vlan->netif.alen = Eaddrlen;
585         memmove(vlan->netif.addr, ether->netif.addr, sizeof(vlan->netif.addr));
586         memmove(vlan->netif.bcast, ether->netif.bcast, sizeof(ether->netif.bcast));
587         vlan->oq = NULL;
588         vlan->ctlr = ether;
589         vlan->vlanid = id;
590         poperror();
591         qunlock(&ether->vlq);
592         return vlan;
593 }
594
595 static struct {
596         char *type;
597         int (*reset) (struct ether *);
598 } cards[MaxEther + 1];
599
600 void addethercard(char *t, int (*r) (struct ether *))
601 {
602         static int ncard;
603
604         if (ncard == MaxEther)
605                 panic("too many ether cards");
606         cards[ncard].type = t;
607         cards[ncard].reset = r;
608         ncard++;
609 }
610
611 int parseether(uint8_t * to, char *from)
612 {
613         char nip[4];
614         char *p;
615         int i;
616
617         p = from;
618         for (i = 0; i < Eaddrlen; i++) {
619                 if (*p == 0)
620                         return -1;
621                 nip[0] = *p++;
622                 if (*p == 0)
623                         return -1;
624                 nip[1] = *p++;
625                 nip[2] = 0;
626                 to[i] = strtoul(nip, 0, 16);
627                 if (*p == ':')
628                         p++;
629         }
630         return 0;
631 }
632
633 static void etherreset(void)
634 {
635         struct ether *ether;
636         int i, n, ctlrno, qsize;
637         char name[KNAMELEN], buf[128];
638
639         for (ether = 0, ctlrno = 0; ctlrno < MaxEther; ctlrno++) {
640                 if (ether == 0)
641                         ether = kzmalloc(sizeof(struct ether), 0);
642                 memset(ether, 0, sizeof(struct ether));
643                 rwinit(&ether->rwlock);
644                 qlock_init(&ether->vlq);
645                 ether->ctlrno = ctlrno;
646                 ether->netif.mbps = 10;
647                 ether->minmtu = ETHERMINTU;
648                 ether->maxmtu = ETHERMAXTU;
649                 /* looked like irq type, we don't have these yet */
650                 //ether->netif.itype = -1;
651
652                 /* TODO: looks like they expected some init to be done here.  at the
653                  * very least, ether->type is 0 right now, and needs to be set.  looking
654                  * around online, it seems to find out ether config settings, so that we
655                  * can set some flags in the opt parseing below. */
656                 //if(archether(ctlrno, ether) <= 0)
657                 //  continue;
658
659                 for (n = 0; cards[n].type; n++) {
660 #if 0
661                         if (cistrcmp(cards[n].type, ether->type))
662                                 continue;
663                         for (i = 0; i < ether->nopt; i++) {
664                                 if (cistrncmp(ether->opt[i], "ea=", 3) == 0) {
665                                         if (parseether(ether->ea, &ether->opt[i][3]) == -1)
666                                                 memset(ether->ea, 0, Eaddrlen);
667                                 } else if (cistrcmp(ether->opt[i], "fullduplex") == 0 ||
668                                                    cistrcmp(ether->opt[i], "10BASE-TFD") == 0)
669                                         ether->fullduplex = 1;
670                                 else if (cistrcmp(ether->opt[i], "100BASE-TXFD") == 0)
671                                         ether->mbps = 100;
672                         }
673 #endif
674                         if (cards[n].reset(ether))
675                                 continue;
676                         /* might be fucked a bit - reset() doesn't know the type.  might not
677                          * even matter, except for debugging. */
678                         ether->type = cards[n].type;
679                         snprintf(name, sizeof(name), "ether%d", ctlrno);
680
681                         i = snprintf(buf, sizeof(buf),
682                                                  "#l%d: %s: %dMbps port 0x%x irq %u", ctlrno,
683                                                  ether->type, ether->netif.mbps, ether->port,
684                                                  ether->irq);
685                         /* Looks like this is for printing MMIO addrs */
686 #if 0
687                         if (ether->mem)
688                                 i += snprintf(buf + i, sizeof(buf) - i, " addr 0x%lx",
689                                                           PADDR(ether->mem));
690                         if (ether->size)
691                                 i += snprintf(buf + i, sizeof(buf) - i, " size 0x%lx",
692                                                           ether->size);
693 #endif
694                         i += snprintf(buf + i, sizeof(buf) - i,
695                                                   ": %02.2x:%02.2x:%02.2x:%02.2x:%02.2x:%02.2x",
696                                                   ether->ea[0], ether->ea[1], ether->ea[2],
697                                                   ether->ea[3], ether->ea[4], ether->ea[5]);
698                         snprintf(buf + i, sizeof(buf) - i, "\n");
699                         printk(buf);
700
701                         switch (ether->netif.mbps) {
702
703                         case 1 ... 99:
704                                 qsize = 64 * 1024;
705                                 break;
706                         case 100 ... 999:
707                                 qsize = 256 * 1024;
708                                 break;
709                         case 1000 ... 9999:
710                                 qsize = 1024 * 1024;
711                                 break;
712                         default:
713                                 qsize = 8 * 1024 * 1024;
714                         }
715                         netifinit(&ether->netif, name, Ntypes, qsize);
716                         if (ether->oq == 0)
717                                 ether->oq = qopen(qsize, Qmsg, 0, 0);
718                         if (ether->oq == 0)
719                                 panic("etherreset %s", name);
720                         ether->netif.alen = Eaddrlen;
721                         memmove(ether->netif.addr, ether->ea, Eaddrlen);
722                         memset(ether->netif.bcast, 0xFF, Eaddrlen);
723
724                         etherxx[ctlrno] = ether;
725                         ether = 0;
726                         break;
727                 }
728         }
729         if (ether)
730                 kfree(ether);
731 }
732
733 static void etherpower(int on)
734 {
735         int i;
736         struct ether *ether;
737
738         /* TODO: fix etherpower.  locking and ether->readers are broken. */
739         warn("%s needs attention.  had a rough porting from inferno", __FUNCTION__);
740         for (i = 0; i < MaxEther; i++) {
741                 if ((ether = etherxx[i]) == NULL || ether->power == NULL)
742                         continue;
743                 if (on) {
744                         /* brho: not sure what they are doing.  there seem to be certain
745                          * assumptions about calling etherpower.  i think they are using
746                          * canrlock to see if the lock is currently writelocked.  and if it
747                          * was not lockable, they would assume they had the write lock and
748                          * could unlock.  this is super fucked up. */
749                         if (canrlock(&ether->rwlock)) {
750                                 runlock(&ether->rwlock);        // brho added this
751                                 continue;
752                         }
753                         if (ether->power != NULL)
754                                 ether->power(ether, on);
755                         wunlock(&ether->rwlock);
756                 } else {
757                         /* readers isn't in the ether struct...
758                            if(ether->readers)
759                            continue;
760                          */
761                         wlock(&ether->rwlock);
762                         if (ether->power != NULL)
763                                 ether->power(ether, on);
764                         /* Keep locked until power goes back on */
765                 }
766         }
767 }
768
769 #define ETHERPOLY 0xedb88320
770
771 /* really slow 32 bit crc for ethers */
772 uint32_t ethercrc(uint8_t * p, int len)
773 {
774         int i, j;
775         uint32_t crc, b;
776
777         crc = 0xffffffff;
778         for (i = 0; i < len; i++) {
779                 b = *p++;
780                 for (j = 0; j < 8; j++) {
781                         crc = (crc >> 1) ^ (((crc ^ b) & 1) ? ETHERPOLY : 0);
782                         b >>= 1;
783                 }
784         }
785         return crc;
786 }
787
788 struct dev etherdevtab __devtab = {
789         'l',
790         "ether",
791
792         etherreset,
793         devinit,
794         ethershutdown,
795         etherattach,
796         etherwalk,
797         etherstat,
798         etheropen,
799         devcreate,
800         etherclose,
801         etherread,
802         etherbread,
803         etherwrite,
804         etherbwrite,
805         devremove,
806         etherwstat,
807         etherpower,
808         devchaninfo,
809 };