Add the Inferno license to files we got from Inferno
[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, NULL);
75                 if (*p == '.') {        /* vlan */
76                         vlanid = strtoul(p + 1, &p, 0);
77                         if (vlanid <= 0 || vlanid > 0xFFF || *p)
78                                 error(EINVAL, NULL);
79                 }
80         }
81         if ((ether = etherxx[ctlrno]) == 0)
82                 error(ENODEV, NULL);
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 = iallocb(68);
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 = iallocb(len);
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, NULL);
491         }
492
493         if (n > ether->maxmtu + ETHERHDRSIZE)
494                 error(E2BIG, NULL);
495         bp = allocb(n);
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, NULL);
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, NULL);
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, NULL);
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, NULL);
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         "ether",
841
842         etherreset,
843         devinit,
844         ethershutdown,
845         etherattach,
846         etherwalk,
847         etherstat,
848         etheropen,
849         devcreate,
850         etherclose,
851         etherread,
852         etherbread,
853         etherwrite,
854         etherbwrite,
855         devremove,
856         etherwstat,
857         etherpower,
858         devchaninfo,
859 };