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