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