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