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