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