1 /*
2 * myricom 10g-pcie-8a 10 Gb ethernet driver
3 * © 2007 erik quanstrom, coraid
4 *
5 * the card is big endian.
6 * we use uvlong rather than uintptr to hold addresses so that
7 * we don't get "warning: stupid shift" on 32-bit architectures.
8 *
9 * appears to have massively-bloated buffers.
10 */
11 #include "u.h"
12 #include "../port/lib.h"
13 #include "mem.h"
14 #include "dat.h"
15 #include "fns.h"
16 #include "io.h"
17 #include "../port/error.h"
18 #include "../port/netif.h"
19
20 #include "../pc/etherif.h"
21
22 #ifndef KiB
23 #define KiB 1024u /* Kibi 0x0000000000000400 */
24 #define MiB 1048576u /* Mebi 0x0000000000100000 */
25 #endif /* KiB */
26
27 #define dprint(...) if(debug) print(__VA_ARGS__)
28 #define pcicapdbg(...)
29 #define malign(n) mallocalign((n), 4*KiB, 0, 0)
30
31 #include "etherm10g2k.i"
32 #include "etherm10g4k.i"
33
34 static int debug = 0;
35 static char Etimeout[] = "timeout";
36
37 enum {
38 Epromsz = 256,
39 Maxslots= 1024, /* rcv descriptors; wasteful: only 9 needed */
40 Align = 4096,
41 Maxmtu = 9000, /* jumbos; bad idea */
42 Noconf = 0xffffffff,
43
44 Fwoffset= 1*MiB,
45 Cmdoff = 0xf80000, /* command port offset */
46 Fwsubmt = 0xfc0000, /* firmware submission command port offset */
47 Rdmaoff = 0xfc01c0, /* rdma command port offset */
48 };
49
50 enum {
51 CZero,
52 Creset,
53 Cversion,
54
55 CSintrqdma, /* issue these before Cetherup */
56 CSbigsz, /* in bytes bigsize = 2^n */
57 CSsmallsz,
58
59 CGsendoff,
60 CGsmallrxoff,
61 CGbigrxoff,
62 CGirqackoff,
63 CGirqdeassoff,
64 CGsendrgsz,
65 CGrxrgsz,
66
67 CSintrqsz, /* 2^n */
68 Cetherup, /* above parameters + mtu/mac addr must be set first. */
69 Cetherdn,
70
71 CSmtu, /* below may be issued live */
72 CGcoaloff, /* in µs */
73 CSstatsrate, /* in µs */
74 CSstatsdma,
75
76 Cpromisc,
77 Cnopromisc,
78 CSmac,
79
80 Cenablefc,
81 Cdisablefc,
82
83 Cdmatest, /* address in d[0-1], d[2]=length */
84
85 Cenableallmc,
86 Cdisableallmc,
87
88 CSjoinmc,
89 CSleavemc,
90 Cleaveallmc,
91
92 CSstatsdma2, /* adds (unused) multicast stats */
93 };
94
95 typedef union {
96 uint i[2];
97 uchar c[8];
98 } Cmd;
99
100 typedef ulong Slot;
101 typedef struct {
102 ushort cksum;
103 ushort len;
104 } Slotparts;
105
106 enum {
107 SFsmall = 1,
108 SFfirst = 2,
109 SFalign = 4,
110 SFnotso = 16,
111 };
112
113 typedef struct {
114 ulong high;
115 ulong low;
116 ushort hdroff;
117 ushort len;
118 uchar pad;
119 uchar nrdma;
120 uchar chkoff;
121 uchar flags;
122 } Send;
123
124 typedef struct {
125 QLock;
126 Send *lanai; /* tx ring (cksum+len in lanai memory) */
127 Send *host; /* tx ring (data in our memory) */
128 Block **bring;
129 // uchar *wcfifo; /* what the heck is a w/c fifo? */
130 int size; /* of buffers in the z8's memory */
131 ulong segsz;
132 uint n; /* rxslots */
133 uint m; /* mask; rxslots must be a power of two */
134 uint i; /* number of segments (not frames) queued */
135 uint cnt; /* number of segments sent by the card */
136
137 ulong npkt;
138 vlong nbytes;
139 } Tx;
140
141 typedef struct {
142 Lock;
143 Block *head;
144 uint size; /* buffer size of each block */
145 uint n; /* n free buffers */
146 uint cnt;
147 } Bpool;
148
149 static Bpool smpool = { .size = 128, };
150 static Bpool bgpool = { .size = Maxmtu, };
151
152 typedef struct {
153 Bpool *pool; /* free buffers */
154 ulong *lanai; /* rx ring; we have no permanent host shadow */
155 Block **host; /* called "info" in myricom driver */
156 // uchar *wcfifo; /* cmd submission fifo */
157 uint m;
158 uint n; /* rxslots */
159 uint i;
160 uint cnt; /* number of buffers allocated (lifetime) */
161 uint allocfail;
162 } Rx;
163
164 /* dma mapped. unix network byte order. */
165 typedef struct {
166 uchar txcnt[4];
167 uchar linkstat[4];
168 uchar dlink[4];
169 uchar derror[4];
170 uchar drunt[4];
171 uchar doverrun[4];
172 uchar dnosm[4];
173 uchar dnobg[4];
174 uchar nrdma[4];
175 uchar txstopped;
176 uchar down;
177 uchar updated;
178 uchar valid;
179 } Stats;
180
181 enum {
182 Detached,
183 Attached,
184 Runed,
185 };
186
187 typedef struct {
188 Slot *entry;
189 uvlong busaddr;
190 uint m;
191 uint n;
192 uint i;
193 } Done;
194
195 typedef struct Ctlr Ctlr;
196 typedef struct Ctlr {
197 QLock;
198 int state;
199 int kprocs;
200 uvlong port;
201 Pcidev* pcidev;
202 Ctlr* next;
203 int active;
204 int id; /* do we need this? */
205
206 uchar ra[Eaddrlen];
207
208 int ramsz;
209 uchar *ram;
210
211 ulong *irqack;
212 ulong *irqdeass;
213 ulong *coal;
214
215 char eprom[Epromsz];
216 ulong serial; /* unit serial number */
217
218 QLock cmdl;
219 Cmd *cmd; /* address of command return */
220 uvlong cprt; /* bus address of command */
221
222 uvlong boot; /* boot address */
223
224 Done done;
225 Tx tx;
226 Rx sm;
227 Rx bg;
228 Stats *stats;
229 uvlong statsprt;
230
231 Rendez rxrendez;
232 Rendez txrendez;
233
234 int msi;
235 ulong linkstat;
236 ulong nrdma;
237 } Ctlr;
238
239 static Ctlr *ctlrs;
240
241 enum {
242 PciCapPMG = 0x01, /* power management */
243 PciCapAGP = 0x02,
244 PciCapVPD = 0x03, /* vital product data */
245 PciCapSID = 0x04, /* slot id */
246 PciCapMSI = 0x05,
247 PciCapCHS = 0x06, /* compact pci hot swap */
248 PciCapPCIX = 0x07,
249 PciCapHTC = 0x08, /* hypertransport irq conf */
250 PciCapVND = 0x09, /* vendor specific information */
251 PciCapHSW = 0x0C, /* hot swap */
252 PciCapPCIe = 0x10,
253 PciCapMSIX = 0x11,
254 };
255
256 enum {
257 PcieAERC = 1,
258 PcieVC,
259 PcieSNC,
260 PciePBC,
261 };
262
263 enum {
264 AercCCR = 0x18, /* control register */
265 };
266
267 enum {
268 PcieCTL = 8,
269 PcieLCR = 12,
270 PcieMRD = 0x7000, /* maximum read size */
271 };
272
273 static int
pcicap(Pcidev * p,int cap)274 pcicap(Pcidev *p, int cap)
275 {
276 int i, c, off;
277
278 pcicapdbg("pcicap: %x:%d\n", p->vid, p->did);
279 off = 0x34; /* 0x14 for cardbus */
280 for(i = 48; i--; ){
281 pcicapdbg("\t" "loop %x\n", off);
282 off = pcicfgr8(p, off);
283 pcicapdbg("\t" "pcicfgr8 %x\n", off);
284 if(off < 0x40)
285 break;
286 off &= ~3;
287 c = pcicfgr8(p, off);
288 pcicapdbg("\t" "pcicfgr8 %x\n", c);
289 if(c == 0xff)
290 break;
291 if(c == cap)
292 return off;
293 off++;
294 }
295 return 0;
296 }
297
298 /*
299 * this function doesn't work because pcicgr32 doesn't have access
300 * to the pcie extended configuration space.
301 */
302 static int
pciecap(Pcidev * p,int cap)303 pciecap(Pcidev *p, int cap)
304 {
305 uint off, i;
306
307 off = 0x100;
308 while(((i = pcicfgr32(p, off)) & 0xffff) != cap){
309 off = i >> 20;
310 print("m10g: pciecap offset = %ud", off);
311 if(off < 0x100 || off >= 4*KiB - 1)
312 return 0;
313 }
314 print("m10g: pciecap found = %ud", off);
315 return off;
316 }
317
318 static int
setpcie(Pcidev * p)319 setpcie(Pcidev *p)
320 {
321 int off;
322
323 /* set 4k writes */
324 off = pcicap(p, PciCapPCIe);
325 if(off < 64)
326 return -1;
327 off += PcieCTL;
328 pcicfgw16(p, off, (pcicfgr16(p, off) & ~PcieMRD) | 5<<12);
329 return 0;
330 }
331
332 static int
whichfw(Pcidev * p)333 whichfw(Pcidev *p)
334 {
335 char *s;
336 int i, off, lanes, ecrc;
337 ulong cap;
338
339 /* check the number of configured lanes. */
340 off = pcicap(p, PciCapPCIe);
341 if(off < 64)
342 return -1;
343 off += PcieLCR;
344 cap = pcicfgr16(p, off);
345 lanes = (cap>>4) & 0x3f;
346
347 /* check AERC register. we need it on. */
348 off = pciecap(p, PcieAERC);
349 print("; offset %d returned\n", off);
350 cap = 0;
351 if(off != 0){
352 off += AercCCR;
353 cap = pcicfgr32(p, off);
354 print("m10g: %lud cap\n", cap);
355 }
356 ecrc = (cap>>4) & 0xf;
357 /* if we don't like the aerc, kick it here. */
358
359 print("m10g: %d lanes; ecrc=%d; ", lanes, ecrc);
360 if(s = getconf("myriforce")){
361 i = atoi(s);
362 if(i != 4*KiB || i != 2*KiB)
363 i = 2*KiB;
364 print("fw = %d [forced]\n", i);
365 return i;
366 }
367 if(lanes <= 4)
368 print("fw = 4096 [lanes]\n");
369 else if(ecrc & 10)
370 print("fw = 4096 [ecrc set]\n");
371 else
372 print("fw = 4096 [default]\n");
373 return 4*KiB;
374 }
375
376 static int
parseeprom(Ctlr * c)377 parseeprom(Ctlr *c)
378 {
379 int i, j, k, l, bits;
380 char *s;
381
382 dprint("m10g eprom:\n");
383 s = c->eprom;
384 bits = 3;
385 for(i = 0; s[i] && i < Epromsz; i++){
386 l = strlen(s+i);
387 dprint("\t%s\n", s+i);
388 if(strncmp(s+i, "MAC=", 4) == 0 && l == 4+12+5){
389 bits ^= 1;
390 j = i + 4;
391 for(k = 0; k < 6; k++)
392 c->ra[k] = strtoul(s+j+3*k, 0, 16);
393 }else if(strncmp(s+i, "SN=", 3) == 0){
394 bits ^= 2;
395 c->serial = atoi(s+i+3);
396 }
397 i += l;
398 }
399 if(bits)
400 return -1;
401 return 0;
402 }
403
404 static ushort
pbit16(ushort i)405 pbit16(ushort i)
406 {
407 ushort j;
408 uchar *p;
409
410 p = (uchar*)&j;
411 p[1] = i;
412 p[0] = i>>8;
413 return j;
414 }
415
416 static ushort
gbit16(uchar i[2])417 gbit16(uchar i[2])
418 {
419 ushort j;
420
421 j = i[1];
422 j |= i[0]<<8;
423 return j;
424 }
425
426 static ulong
pbit32(ulong i)427 pbit32(ulong i)
428 {
429 ulong j;
430 uchar *p;
431
432 p = (uchar*)&j;
433 p[3] = i;
434 p[2] = i>>8;
435 p[1] = i>>16;
436 p[0] = i>>24;
437 return j;
438 }
439
440 static ulong
gbit32(uchar i[4])441 gbit32(uchar i[4])
442 {
443 ulong j;
444
445 j = i[3];
446 j |= i[2]<<8;
447 j |= i[1]<<16;
448 j |= i[0]<<24;
449 return j;
450 }
451
452 static void
prepcmd(ulong * cmd,int i)453 prepcmd(ulong *cmd, int i)
454 {
455 while(i-- > 0)
456 cmd[i] = pbit32(cmd[i]);
457 }
458
459 /*
460 * the command looks like this (int 32bit integers)
461 * cmd type
462 * addr (low)
463 * addr (high)
464 * pad (used for dma testing)
465 * response (high)
466 * response (low)
467 * 40 byte = 5 int pad.
468 */
469
470 ulong
cmd(Ctlr * c,int type,uvlong data)471 cmd(Ctlr *c, int type, uvlong data)
472 {
473 ulong buf[16], i;
474 Cmd *cmd;
475
476 qlock(&c->cmdl);
477 cmd = c->cmd;
478 cmd->i[1] = Noconf;
479 memset(buf, 0, sizeof buf);
480 buf[0] = type;
481 buf[1] = data;
482 buf[2] = data >> 32;
483 buf[4] = c->cprt >> 32;
484 buf[5] = c->cprt;
485 prepcmd(buf, 6);
486 coherence();
487 memmove(c->ram + Cmdoff, buf, sizeof buf);
488
489 if(waserror()){
490 qunlock(&c->cmdl);
491 nexterror();
492 }
493 for(i = 0; i < 15; i++){
494 if(cmd->i[1] != Noconf){
495 poperror();
496 i = gbit32(cmd->c);
497 qunlock(&c->cmdl);
498 if(cmd->i[1] != 0)
499 dprint("[%lux]", i);
500 return i; /* normal return */
501 }
502 tsleep(&up->sleep, return0, 0, 1);
503 }
504 iprint("m10g: cmd timeout [%ux %ux] cmd=%d\n",
505 cmd->i[0], cmd->i[1], type);
506 error(Etimeout);
507 return ~0; /* silence! */
508 }
509
510 ulong
maccmd(Ctlr * c,int type,uchar * m)511 maccmd(Ctlr *c, int type, uchar *m)
512 {
513 ulong buf[16], i;
514 Cmd *cmd;
515
516 qlock(&c->cmdl);
517 cmd = c->cmd;
518 cmd->i[1] = Noconf;
519 memset(buf, 0, sizeof buf);
520 buf[0] = type;
521 buf[1] = m[0]<<24 | m[1]<<16 | m[2]<<8 | m[3];
522 buf[2] = m[4]<< 8 | m[5];
523 buf[4] = c->cprt >> 32;
524 buf[5] = c->cprt;
525 prepcmd(buf, 6);
526 coherence();
527 memmove(c->ram + Cmdoff, buf, sizeof buf);
528
529 if(waserror()){
530 qunlock(&c->cmdl);
531 nexterror();
532 }
533 for(i = 0; i < 15; i++){
534 if(cmd->i[1] != Noconf){
535 poperror();
536 i = gbit32(cmd->c);
537 qunlock(&c->cmdl);
538 if(cmd->i[1] != 0)
539 dprint("[%lux]", i);
540 return i; /* normal return */
541 }
542 tsleep(&up->sleep, return0, 0, 1);
543 }
544 iprint("m10g: maccmd timeout [%ux %ux] cmd=%d\n",
545 cmd->i[0], cmd->i[1], type);
546 error(Etimeout);
547 return ~0; /* silence! */
548 }
549
550 /* remove this garbage after testing */
551 enum {
552 DMAread = 0x10000,
553 DMAwrite= 0x1,
554 };
555
556 ulong
dmatestcmd(Ctlr * c,int type,uvlong addr,int len)557 dmatestcmd(Ctlr *c, int type, uvlong addr, int len)
558 {
559 ulong buf[16], i;
560
561 memset(buf, 0, sizeof buf);
562 memset(c->cmd, Noconf, sizeof *c->cmd);
563 buf[0] = Cdmatest;
564 buf[1] = addr;
565 buf[2] = addr >> 32;
566 buf[3] = len * type;
567 buf[4] = c->cprt >> 32;
568 buf[5] = c->cprt;
569 prepcmd(buf, 6);
570 coherence();
571 memmove(c->ram + Cmdoff, buf, sizeof buf);
572
573 for(i = 0; i < 15; i++){
574 if(c->cmd->i[1] != Noconf){
575 i = gbit32(c->cmd->c);
576 if(i == 0)
577 error(Eio);
578 return i; /* normal return */
579 }
580 tsleep(&up->sleep, return0, 0, 5);
581 }
582 error(Etimeout);
583 return ~0; /* silence! */
584 }
585
586 ulong
rdmacmd(Ctlr * c,int on)587 rdmacmd(Ctlr *c, int on)
588 {
589 ulong buf[16], i;
590
591 memset(buf, 0, sizeof buf);
592 c->cmd->i[0] = 0;
593 coherence();
594 buf[0] = c->cprt >> 32;
595 buf[1] = c->cprt;
596 buf[2] = Noconf;
597 buf[3] = c->cprt >> 32;
598 buf[4] = c->cprt;
599 buf[5] = on;
600 prepcmd(buf, 6);
601 memmove(c->ram + Rdmaoff, buf, sizeof buf);
602
603 for(i = 0; i < 20; i++){
604 if(c->cmd->i[0] == Noconf)
605 return gbit32(c->cmd->c); /* normal return */
606 tsleep(&up->sleep, return0, 0, 1);
607 }
608 iprint("m10g: rdmacmd timeout\n");
609 error(Etimeout);
610 return ~0; /* silence! */
611 }
612
613 static int
loadfw(Ctlr * c,int * align)614 loadfw(Ctlr *c, int *align)
615 {
616 ulong *f, *s, sz;
617 int i;
618
619 if((*align = whichfw(c->pcidev)) == 4*KiB){
620 f = (ulong*)fw4k;
621 sz = sizeof fw4k;
622 }else{
623 f = (ulong*)fw2k;
624 sz = sizeof fw2k;
625 }
626
627 s = (ulong*)(c->ram + Fwoffset);
628 for(i = 0; i < sz / 4; i++)
629 s[i] = f[i];
630 return sz & ~3;
631 }
632
633 static int
bootfw(Ctlr * c)634 bootfw(Ctlr *c)
635 {
636 int i, sz, align;
637 ulong buf[16];
638 Cmd* cmd;
639
640 if((sz = loadfw(c, &align)) == 0)
641 return 0;
642 dprint("bootfw %d bytes ... ", sz);
643 cmd = c->cmd;
644
645 memset(buf, 0, sizeof buf);
646 c->cmd->i[0] = 0;
647 coherence();
648 buf[0] = c->cprt >> 32; /* upper dma target address */
649 buf[1] = c->cprt; /* lower */
650 buf[2] = Noconf; /* writeback */
651 buf[3] = Fwoffset + 8,
652 buf[4] = sz - 8;
653 buf[5] = 8;
654 buf[6] = 0;
655 prepcmd(buf, 7);
656 coherence();
657 memmove(c->ram + Fwsubmt, buf, sizeof buf);
658
659 for(i = 0; i < 20; i++){
660 if(cmd->i[0] == Noconf)
661 break;
662 delay(1);
663 }
664 dprint("[%lux %lux]", gbit32(cmd->c), gbit32(cmd->c+4));
665 if(i == 20){
666 print("m10g: cannot load fw\n");
667 return -1;
668 }
669 dprint("\n");
670 c->tx.segsz = align;
671 return 0;
672 }
673
674 static int
kickthebaby(Pcidev * p,Ctlr * c)675 kickthebaby(Pcidev *p, Ctlr *c)
676 {
677 /* don't kick the baby! */
678 ulong code;
679
680 pcicfgw8(p, 0x10 + c->boot, 0x3);
681 pcicfgw32(p, 0x18 + c->boot, 0xfffffff0);
682 code = pcicfgr32(p, 0x14 + c->boot);
683
684 dprint("reboot status = %lux\n", code);
685 if(code != 0xfffffff0)
686 return -1;
687 return 0;
688 }
689
690 typedef struct {
691 uchar len[4];
692 uchar type[4];
693 char version[128];
694 uchar globals[4];
695 uchar ramsz[4];
696 uchar specs[4];
697 uchar specssz[4];
698 } Fwhdr;
699
700 enum {
701 Tmx = 0x4d582020,
702 Tpcie = 0x70636965,
703 Teth = 0x45544820,
704 Tmcp0 = 0x4d435030,
705 };
706
707 static char *
fwtype(ulong type)708 fwtype(ulong type)
709 {
710 switch(type){
711 case Tmx:
712 return "mx";
713 case Tpcie:
714 return "PCIe";
715 case Teth:
716 return "eth";
717 case Tmcp0:
718 return "mcp0";
719 }
720 return "*GOK*";
721 }
722
723 static int
chkfw(Ctlr * c)724 chkfw(Ctlr *c)
725 {
726 ulong off, type;
727 Fwhdr *h;
728
729 off = gbit32(c->ram+0x3c);
730 dprint("firmware %lux\n", off);
731 if((off&3) || off + sizeof *h > c->ramsz){
732 print("!m10g: bad firmware %lux\n", off);
733 return -1;
734 }
735 h = (Fwhdr*)(c->ram + off);
736 type = gbit32(h->type);
737 dprint("\t" "type %s\n", fwtype(type));
738 dprint("\t" "vers %s\n", h->version);
739 dprint("\t" "ramsz %lux\n", gbit32(h->ramsz));
740 if(type != Teth){
741 print("!m10g: bad card type %s\n", fwtype(type));
742 return -1;
743 }
744
745 return bootfw(c) || rdmacmd(c, 0);
746 }
747
748 static int
reset(Ether * e,Ctlr * c)749 reset(Ether *e, Ctlr *c)
750 {
751 ulong i, sz;
752
753 if(waserror()){
754 print("m10g: reset error\n");
755 nexterror();
756 return -1;
757 }
758
759 chkfw(c);
760 cmd(c, Creset, 0);
761
762 cmd(c, CSintrqsz, c->done.n * sizeof *c->done.entry);
763 cmd(c, CSintrqdma, c->done.busaddr);
764 c->irqack = (ulong*)(c->ram + cmd(c, CGirqackoff, 0));
765 /* required only if we're not doing msi? */
766 c->irqdeass = (ulong*)(c->ram + cmd(c, CGirqdeassoff, 0));
767 /* this is the driver default, why fiddle with this? */
768 c->coal = (ulong*)(c->ram + cmd(c, CGcoaloff, 0));
769 *c->coal = pbit32(25);
770
771 dprint("dma stats:\n");
772 rdmacmd(c, 1);
773 sz = c->tx.segsz;
774 i = dmatestcmd(c, DMAread, c->done.busaddr, sz);
775 print("m10g: read %lud MB/s;", ((i>>16)*sz*2) / (i&0xffff));
776 i = dmatestcmd(c, DMAwrite, c->done.busaddr, sz);
777 print(" write %lud MB/s;", ((i>>16)*sz*2) / (i&0xffff));
778 i = dmatestcmd(c, DMAwrite|DMAread, c->done.busaddr, sz);
779 print(" r/w %lud MB/s\n", ((i>>16)*sz*2*2) / (i&0xffff));
780 memset(c->done.entry, 0, c->done.n * sizeof *c->done.entry);
781
782 maccmd(c, CSmac, c->ra);
783 // cmd(c, Cnopromisc, 0);
784 cmd(c, Cenablefc, 0);
785 e->maxmtu = Maxmtu;
786 cmd(c, CSmtu, e->maxmtu);
787 dprint("CSmtu %d...\n", e->maxmtu);
788
789 poperror();
790 return 0;
791 }
792
793 static void
ctlrfree(Ctlr * c)794 ctlrfree(Ctlr *c)
795 {
796 /* free up all the Block*s, too */
797 free(c->tx.host);
798 free(c->sm.host);
799 free(c->bg.host);
800 free(c->cmd);
801 free(c->done.entry);
802 free(c->stats);
803 free(c);
804 }
805
806 static int
setmem(Pcidev * p,Ctlr * c)807 setmem(Pcidev *p, Ctlr *c)
808 {
809 ulong i;
810 uvlong raddr;
811 Done *d;
812 void *mem;
813
814 c->tx.segsz = 2048;
815 c->ramsz = 2*MiB - (2*48*KiB + 32*KiB) - 0x100;
816 if(c->ramsz > p->mem[0].size)
817 return -1;
818
819 raddr = p->mem[0].bar & ~0x0F;
820 mem = vmap(raddr, p->mem[0].size);
821 if(mem == nil){
822 print("m10g: can't map %8.8lux\n", p->mem[0].bar);
823 return -1;
824 }
825 dprint("%llux <- vmap(mem[0].size = %ux)\n", raddr, p->mem[0].size);
826 c->port = raddr;
827 c->ram = mem;
828 c->cmd = malign(sizeof *c->cmd);
829 c->cprt = PCIWADDR(c->cmd);
830
831 d = &c->done;
832 d->n = Maxslots;
833 d->m = d->n - 1;
834 i = d->n * sizeof *d->entry;
835 d->entry = malign(i);
836 memset(d->entry, 0, i);
837 d->busaddr = PCIWADDR(d->entry);
838
839 c->stats = malign(sizeof *c->stats);
840 memset(c->stats, 0, sizeof *c->stats);
841 c->statsprt = PCIWADDR(c->stats);
842
843 memmove(c->eprom, c->ram + c->ramsz - Epromsz, Epromsz-2);
844 return setpcie(p) || parseeprom(c);
845 }
846
847 static Rx*
whichrx(Ctlr * c,int sz)848 whichrx(Ctlr *c, int sz)
849 {
850 if(sz <= smpool.size)
851 return &c->sm;
852 return &c->bg;
853 }
854
855 static Block*
balloc(Rx * rx)856 balloc(Rx* rx)
857 {
858 Block *bp;
859
860 ilock(rx->pool);
861 if((bp = rx->pool->head) != nil){
862 rx->pool->head = bp->next;
863 bp->next = nil;
864 _xinc(&bp->ref); /* prevent bp from being freed */
865 rx->pool->n--;
866 }
867 iunlock(rx->pool);
868 return bp;
869 }
870
871 static void
rbfree(Block * b,Bpool * p)872 rbfree(Block *b, Bpool *p)
873 {
874 b->rp = b->wp = (uchar*)PGROUND((uintptr)b->base);
875 b->flag &= ~(Bipck | Budpck | Btcpck | Bpktck);
876
877 ilock(p);
878 b->next = p->head;
879 p->head = b;
880 p->n++;
881 p->cnt++;
882 iunlock(p);
883 }
884
885 static void
smbfree(Block * b)886 smbfree(Block *b)
887 {
888 rbfree(b, &smpool);
889 }
890
891 static void
bgbfree(Block * b)892 bgbfree(Block *b)
893 {
894 rbfree(b, &bgpool);
895 }
896
897 static void
replenish(Rx * rx)898 replenish(Rx *rx)
899 {
900 ulong buf[16], i, idx, e;
901 Bpool *p;
902 Block *b;
903
904 p = rx->pool;
905 if(p->n < 8)
906 return;
907 memset(buf, 0, sizeof buf);
908 e = (rx->i - rx->cnt) & ~7;
909 e += rx->n;
910 while(p->n >= 8 && e){
911 idx = rx->cnt & rx->m;
912 for(i = 0; i < 8; i++){
913 b = balloc(rx);
914 buf[i*2] = pbit32((uvlong)PCIWADDR(b->wp) >> 32);
915 buf[i*2+1] = pbit32(PCIWADDR(b->wp));
916 rx->host[idx+i] = b;
917 assert(b);
918 }
919 memmove(rx->lanai + 2*idx, buf, sizeof buf);
920 coherence();
921 rx->cnt += 8;
922 e -= 8;
923 }
924 if(e && p->n > 7+1)
925 print("m10g: should panic? pool->n = %d\n", p->n);
926 }
927
928 /*
929 * future:
930 * if (c->mtrr >= 0) {
931 * c->tx.wcfifo = c->ram+0x200000;
932 * c->sm.wcfifo = c->ram+0x300000;
933 * c->bg.wcfifo = c->ram+0x340000;
934 * }
935 */
936
937 static int
nextpow(int j)938 nextpow(int j)
939 {
940 int i;
941
942 for(i = 0; j > (1 << i); i++)
943 ;
944 return 1 << i;
945 }
946
947 static void*
emalign(int sz)948 emalign(int sz)
949 {
950 void *v;
951
952 v = malign(sz);
953 if(v == nil)
954 error(Enomem);
955 memset(v, 0, sz);
956 return v;
957 }
958
959 static void
open0(Ether * e,Ctlr * c)960 open0(Ether *e, Ctlr *c)
961 {
962 Block *b;
963 int i, sz, entries;
964
965 entries = cmd(c, CGsendrgsz, 0) / sizeof *c->tx.lanai;
966 c->tx.lanai = (Send*)(c->ram + cmd(c, CGsendoff, 0));
967 c->tx.host = emalign(entries * sizeof *c->tx.host);
968 c->tx.bring = emalign(entries * sizeof *c->tx.bring);
969 c->tx.n = entries;
970 c->tx.m = entries-1;
971
972 entries = cmd(c, CGrxrgsz, 0)/8;
973 c->sm.pool = &smpool;
974 cmd(c, CSsmallsz, c->sm.pool->size);
975 c->sm.lanai = (ulong*)(c->ram + cmd(c, CGsmallrxoff, 0));
976 c->sm.n = entries;
977 c->sm.m = entries-1;
978 c->sm.host = emalign(entries * sizeof *c->sm.host);
979
980 c->bg.pool = &bgpool;
981 c->bg.pool->size = nextpow(2 + e->maxmtu); /* 2-byte alignment pad */
982 cmd(c, CSbigsz, c->bg.pool->size);
983 c->bg.lanai = (ulong*)(c->ram + cmd(c, CGbigrxoff, 0));
984 c->bg.n = entries;
985 c->bg.m = entries-1;
986 c->bg.host = emalign(entries * sizeof *c->bg.host);
987
988 sz = c->sm.pool->size + BY2PG;
989 for(i = 0; i < c->sm.n; i++){
990 if((b = allocb(sz)) == 0)
991 break;
992 b->free = smbfree;
993 freeb(b);
994 }
995 sz = c->bg.pool->size + BY2PG;
996 for(i = 0; i < c->bg.n; i++){
997 if((b = allocb(sz)) == 0)
998 break;
999 b->free = bgbfree;
1000 freeb(b);
1001 }
1002
1003 cmd(c, CSstatsdma, c->statsprt);
1004 c->linkstat = ~0;
1005 c->nrdma = 15;
1006
1007 cmd(c, Cetherup, 0);
1008 }
1009
1010 static Block*
nextblock(Ctlr * c)1011 nextblock(Ctlr *c)
1012 {
1013 uint i;
1014 ushort l, k;
1015 Block *b;
1016 Done *d;
1017 Rx *rx;
1018 Slot *s;
1019 Slotparts *sp;
1020
1021 d = &c->done;
1022 s = d->entry;
1023 i = d->i & d->m;
1024 sp = (Slotparts *)(s + i);
1025 l = sp->len;
1026 if(l == 0)
1027 return 0;
1028 k = sp->cksum;
1029 s[i] = 0;
1030 d->i++;
1031 l = gbit16((uchar*)&l);
1032 //dprint("nextb: i=%d l=%d\n", d->i, l);
1033 rx = whichrx(c, l);
1034 if(rx->i >= rx->cnt){
1035 iprint("m10g: overrun\n");
1036 return 0;
1037 }
1038 i = rx->i & rx->m;
1039 b = rx->host[i];
1040 rx->host[i] = 0;
1041 if(b == 0){
1042 iprint("m10g: error rx to no block. memory is hosed.\n");
1043 return 0;
1044 }
1045 rx->i++;
1046
1047 b->flag |= Bipck|Btcpck|Budpck;
1048 b->checksum = k;
1049 b->rp += 2;
1050 b->wp += 2+l;
1051 b->lim = b->wp; /* lie like a dog. */
1052 return b;
1053 }
1054
1055 static int
rxcansleep(void * v)1056 rxcansleep(void *v)
1057 {
1058 Ctlr *c;
1059 Slot *s;
1060 Slotparts *sp;
1061 Done *d;
1062
1063 c = v;
1064 d = &c->done;
1065 s = c->done.entry;
1066 sp = (Slotparts *)(s + (d->i & d->m));
1067 if(sp->len != 0)
1068 return -1;
1069 c->irqack[0] = pbit32(3);
1070 return 0;
1071 }
1072
1073 static void
m10rx(void * v)1074 m10rx(void *v)
1075 {
1076 Ether *e;
1077 Ctlr *c;
1078 Block *b;
1079
1080 e = v;
1081 c = e->ctlr;
1082 for(;;){
1083 replenish(&c->sm);
1084 replenish(&c->bg);
1085 sleep(&c->rxrendez, rxcansleep, c);
1086 while(b = nextblock(c))
1087 etheriq(e, b, 1);
1088 }
1089 }
1090
1091 static void
txcleanup(Tx * tx,ulong n)1092 txcleanup(Tx *tx, ulong n)
1093 {
1094 Block *b;
1095 uint j, l, m;
1096
1097 if(tx->npkt == n)
1098 return;
1099 l = 0;
1100 m = tx->m;
1101 /*
1102 * if tx->cnt == tx->i, yet tx->npkt == n-1, we just
1103 * caught ourselves and myricom card updating.
1104 */
1105 for(;; tx->cnt++){
1106 j = tx->cnt & tx->m;
1107 if(b = tx->bring[j]){
1108 tx->bring[j] = 0;
1109 tx->nbytes += BLEN(b);
1110 freeb(b);
1111 if(++tx->npkt == n)
1112 return;
1113 }
1114 if(tx->cnt == tx->i)
1115 return;
1116 if(l++ == m){
1117 iprint("m10g: tx ovrun: %lud %lud\n", n, tx->npkt);
1118 return;
1119 }
1120 }
1121 }
1122
1123 static int
txcansleep(void * v)1124 txcansleep(void *v)
1125 {
1126 Ctlr *c;
1127
1128 c = v;
1129 if(c->tx.cnt != c->tx.i && c->tx.npkt != gbit32(c->stats->txcnt))
1130 return -1;
1131 return 0;
1132 }
1133
1134 static void
txproc(void * v)1135 txproc(void *v)
1136 {
1137 Ether *e;
1138 Ctlr *c;
1139 Tx *tx;
1140
1141 e = v;
1142 c = e->ctlr;
1143 tx = &c->tx;
1144 for(;;){
1145 sleep(&c->txrendez, txcansleep, c);
1146 txcleanup(tx, gbit32(c->stats->txcnt));
1147 }
1148 }
1149
1150 static void
submittx(Tx * tx,int n)1151 submittx(Tx *tx, int n)
1152 {
1153 Send *l, *h;
1154 int i0, i, m;
1155
1156 m = tx->m;
1157 i0 = tx->i & m;
1158 l = tx->lanai;
1159 h = tx->host;
1160 for(i = n-1; i >= 0; i--)
1161 memmove(l+(i + i0 & m), h+(i + i0 & m), sizeof *h);
1162 tx->i += n;
1163 // coherence();
1164 }
1165
1166 static int
nsegments(Block * b,int segsz)1167 nsegments(Block *b, int segsz)
1168 {
1169 uintptr bus, end, slen, len;
1170 int i;
1171
1172 bus = PCIWADDR(b->rp);
1173 i = 0;
1174 for(len = BLEN(b); len; len -= slen){
1175 end = bus + segsz & ~(segsz-1);
1176 slen = end - bus;
1177 if(slen > len)
1178 slen = len;
1179 bus += slen;
1180 i++;
1181 }
1182 return i;
1183 }
1184
1185 static void
m10gtransmit(Ether * e)1186 m10gtransmit(Ether *e)
1187 {
1188 ushort slen;
1189 ulong i, cnt, rdma, nseg, count, end, bus, len, segsz;
1190 uchar flags;
1191 Block *b;
1192 Ctlr *c;
1193 Send *s, *s0, *s0m8;
1194 Tx *tx;
1195
1196 c = e->ctlr;
1197 tx = &c->tx;
1198 segsz = tx->segsz;
1199
1200 qlock(tx);
1201 count = 0;
1202 s = tx->host + (tx->i & tx->m);
1203 cnt = tx->cnt;
1204 s0 = tx->host + (cnt & tx->m);
1205 s0m8 = tx->host + ((cnt - 8) & tx->m);
1206 i = tx->i;
1207 for(; s >= s0 || s < s0m8; i += nseg){
1208 if((b = qget(e->oq)) == nil)
1209 break;
1210 flags = SFfirst|SFnotso;
1211 if((len = BLEN(b)) < 1520)
1212 flags |= SFsmall;
1213 rdma = nseg = nsegments(b, segsz);
1214 bus = PCIWADDR(b->rp);
1215 for(; len; len -= slen){
1216 end = (bus + segsz) & ~(segsz-1);
1217 slen = end - bus;
1218 if(slen > len)
1219 slen = len;
1220 s->low = pbit32(bus);
1221 s->len = pbit16(slen);
1222 s->nrdma = rdma;
1223 s->flags = flags;
1224
1225 bus += slen;
1226 if(++s == tx->host + tx->n)
1227 s = tx->host;
1228 count++;
1229 flags &= ~SFfirst;
1230 rdma = 1;
1231 }
1232 tx->bring[(i + nseg - 1) & tx->m] = b;
1233 if(1 || count > 0){
1234 submittx(tx, count);
1235 count = 0;
1236 cnt = tx->cnt;
1237 s0 = tx->host + (cnt & tx->m);
1238 s0m8 = tx->host + ((cnt - 8) & tx->m);
1239 }
1240 }
1241 qunlock(tx);
1242 }
1243
1244 static void
checkstats(Ether * e,Ctlr * c,Stats * s)1245 checkstats(Ether *e, Ctlr *c, Stats *s)
1246 {
1247 ulong i;
1248
1249 if(s->updated == 0)
1250 return;
1251
1252 i = gbit32(s->linkstat);
1253 if(c->linkstat != i){
1254 e->link = i;
1255 if(c->linkstat = i)
1256 dprint("m10g: link up\n");
1257 else
1258 dprint("m10g: link down\n");
1259 }
1260 i = gbit32(s->nrdma);
1261 if(i != c->nrdma){
1262 dprint("m10g: rdma timeout %ld\n", i);
1263 c->nrdma = i;
1264 }
1265 }
1266
1267 static void
waitintx(Ctlr * c)1268 waitintx(Ctlr *c)
1269 {
1270 int i;
1271
1272 for(i = 0; i < 1024*1024; i++){
1273 if(c->stats->valid == 0)
1274 break;
1275 coherence();
1276 }
1277 }
1278
1279 static void
m10ginterrupt(Ureg *,void * v)1280 m10ginterrupt(Ureg *, void *v)
1281 {
1282 Ether *e;
1283 Ctlr *c;
1284
1285 e = v;
1286 c = e->ctlr;
1287
1288 if(c->state != Runed || c->stats->valid == 0) /* not ready for us? */
1289 return;
1290
1291 if(c->stats->valid & 1)
1292 wakeup(&c->rxrendez);
1293 if(gbit32(c->stats->txcnt) != c->tx.npkt)
1294 wakeup(&c->txrendez);
1295 if(c->msi == 0)
1296 *c->irqdeass = 0;
1297 else
1298 c->stats->valid = 0;
1299 waitintx(c);
1300 checkstats(e, c, c->stats);
1301 c->irqack[1] = pbit32(3);
1302 }
1303
1304 static void
m10gattach(Ether * e)1305 m10gattach(Ether *e)
1306 {
1307 Ctlr *c;
1308 char name[12];
1309
1310 dprint("m10gattach\n");
1311
1312 qlock(e->ctlr);
1313 c = e->ctlr;
1314 if(c->state != Detached){
1315 qunlock(c);
1316 return;
1317 }
1318 if(waserror()){
1319 c->state = Detached;
1320 qunlock(c);
1321 nexterror();
1322 }
1323 reset(e, c);
1324 c->state = Attached;
1325 open0(e, c);
1326 if(c->kprocs == 0){
1327 c->kprocs++;
1328 snprint(name, sizeof name, "#l%drxproc", e->ctlrno);
1329 kproc(name, m10rx, e);
1330 snprint(name, sizeof name, "#l%dtxproc", e->ctlrno);
1331 kproc(name, txproc, e);
1332 }
1333 c->state = Runed;
1334 qunlock(c);
1335 poperror();
1336 }
1337
1338 static int
m10gdetach(Ctlr * c)1339 m10gdetach(Ctlr *c)
1340 {
1341 dprint("m10gdetach\n");
1342 // reset(e->ctlr);
1343 vunmap(c->ram, c->pcidev->mem[0].size);
1344 ctlrfree(c); /* this is a bad idea: don't free c */
1345 return -1;
1346 }
1347
1348 static int
lstcount(Block * b)1349 lstcount(Block *b)
1350 {
1351 int i;
1352
1353 i = 0;
1354 for(; b; b = b->next)
1355 i++;
1356 return i;
1357 }
1358
1359 static long
m10gifstat(Ether * e,void * v,long n,ulong off)1360 m10gifstat(Ether *e, void *v, long n, ulong off)
1361 {
1362 char *p;
1363 Ctlr *c;
1364 Stats s;
1365
1366 c = e->ctlr;
1367 p = malloc(READSTR+1);
1368 if(p == nil)
1369 error(Enomem);
1370 /* no point in locking this because this is done via dma. */
1371 memmove(&s, c->stats, sizeof s);
1372
1373 snprint(p, READSTR,
1374 "txcnt = %lud\n" "linkstat = %lud\n" "dlink = %lud\n"
1375 "derror = %lud\n" "drunt = %lud\n" "doverrun = %lud\n"
1376 "dnosm = %lud\n" "dnobg = %lud\n" "nrdma = %lud\n"
1377 "txstopped = %ud\n" "down = %ud\n" "updated = %ud\n"
1378 "valid = %ud\n\n"
1379 "tx pkt = %lud\n" "tx bytes = %lld\n"
1380 "tx cnt = %ud\n" "tx n = %ud\n" "tx i = %ud\n"
1381 "sm cnt = %ud\n" "sm i = %ud\n" "sm n = %ud\n"
1382 "sm lst = %ud\n"
1383 "bg cnt = %ud\n" "bg i = %ud\n" "bg n = %ud\n"
1384 "bg lst = %ud\n"
1385 "segsz = %lud\n" "coal = %lud\n",
1386 gbit32(s.txcnt), gbit32(s.linkstat), gbit32(s.dlink),
1387 gbit32(s.derror), gbit32(s.drunt), gbit32(s.doverrun),
1388 gbit32(s.dnosm), gbit32(s.dnobg), gbit32(s.nrdma),
1389 s.txstopped, s.down, s.updated, s.valid,
1390 c->tx.npkt, c->tx.nbytes,
1391 c->tx.cnt, c->tx.n, c->tx.i,
1392 c->sm.cnt, c->sm.i, c->sm.pool->n, lstcount(c->sm.pool->head),
1393 c->bg.cnt, c->bg.i, c->bg.pool->n, lstcount(c->bg.pool->head),
1394 c->tx.segsz, gbit32((uchar*)c->coal));
1395
1396 n = readstr(off, v, n, p);
1397 free(p);
1398 return n;
1399 }
1400
1401 //static void
1402 //summary(Ether *e)
1403 //{
1404 // char *buf;
1405 // int n, i, j;
1406 //
1407 // if(e == 0)
1408 // return;
1409 // buf = malloc(n=250);
1410 // if(buf == 0)
1411 // return;
1412 //
1413 // snprint(buf, n, "oq\n");
1414 // qsummary(e->oq, buf+3, n-3-1);
1415 // iprint("%s", buf);
1416 //
1417 // if(e->f) for(i = 0; e->f[i]; i++){
1418 // j = snprint(buf, n, "f%d %d\n", i, e->f[i]->type);
1419 // qsummary(e->f[i]->in, buf+j, n-j-1);
1420 // print("%s", buf);
1421 // }
1422 //
1423 // free(buf);
1424 //}
1425
1426 static void
rxring(Ctlr * c)1427 rxring(Ctlr *c)
1428 {
1429 Done *d;
1430 Slot *s;
1431 Slotparts *sp;
1432 int i;
1433
1434 d = &c->done;
1435 s = d->entry;
1436 for(i = 0; i < d->n; i++) {
1437 sp = (Slotparts *)(s + i);
1438 if(sp->len)
1439 iprint("s[%d] = %d\n", i, sp->len);
1440 }
1441 }
1442
1443 enum {
1444 CMdebug,
1445 CMcoal,
1446 CMwakeup,
1447 CMtxwakeup,
1448 CMqsummary,
1449 CMrxring,
1450 };
1451
1452 static Cmdtab ctab[] = {
1453 CMdebug, "debug", 2,
1454 CMcoal, "coal", 2,
1455 CMwakeup, "wakeup", 1,
1456 CMtxwakeup, "txwakeup", 1,
1457 // CMqsummary, "q", 1,
1458 CMrxring, "rxring", 1,
1459 };
1460
1461 static long
m10gctl(Ether * e,void * v,long n)1462 m10gctl(Ether *e, void *v, long n)
1463 {
1464 int i;
1465 Cmdbuf *c;
1466 Cmdtab *t;
1467
1468 dprint("m10gctl\n");
1469 if(e->ctlr == nil)
1470 error(Enonexist);
1471
1472 c = parsecmd(v, n);
1473 if(waserror()){
1474 free(c);
1475 nexterror();
1476 }
1477 t = lookupcmd(c, ctab, nelem(ctab));
1478 switch(t->index){
1479 case CMdebug:
1480 debug = (strcmp(c->f[1], "on") == 0);
1481 break;
1482 case CMcoal:
1483 i = atoi(c->f[1]);
1484 if(i < 0 || i > 1000)
1485 error(Ebadarg);
1486 *((Ctlr*)e->ctlr)->coal = pbit32(i);
1487 break;
1488 case CMwakeup:
1489 wakeup(&((Ctlr*)e->ctlr)->rxrendez); /* you're kidding, right? */
1490 break;
1491 case CMtxwakeup:
1492 wakeup(&((Ctlr*)e->ctlr)->txrendez); /* you're kidding, right? */
1493 break;
1494 // case CMqsummary:
1495 // summary(e);
1496 // break;
1497 case CMrxring:
1498 rxring(e->ctlr);
1499 break;
1500 default:
1501 error(Ebadarg);
1502 }
1503 free(c);
1504 poperror();
1505 return n;
1506 }
1507
1508 static void
m10gshutdown(Ether * e)1509 m10gshutdown(Ether *e)
1510 {
1511 dprint("m10gshutdown\n");
1512 m10gdetach(e->ctlr);
1513 }
1514
1515 static void
m10gpromiscuous(void * v,int on)1516 m10gpromiscuous(void *v, int on)
1517 {
1518 Ether *e;
1519 int i;
1520
1521 dprint("m10gpromiscuous\n");
1522 e = v;
1523 if(on)
1524 i = Cpromisc;
1525 else
1526 i = Cnopromisc;
1527 cmd(e->ctlr, i, 0);
1528 }
1529
1530 static int mcctab[] = { CSleavemc, CSjoinmc };
1531 static char *mcntab[] = { "leave", "join" };
1532
1533 static void
m10gmulticast(void * v,uchar * ea,int on)1534 m10gmulticast(void *v, uchar *ea, int on)
1535 {
1536 Ether *e;
1537 int i;
1538
1539 dprint("m10gmulticast\n");
1540 e = v;
1541 if((i = maccmd(e->ctlr, mcctab[on], ea)) != 0)
1542 print("m10g: can't %s %E: %d\n", mcntab[on], ea, i);
1543 }
1544
1545 static void
m10gpci(void)1546 m10gpci(void)
1547 {
1548 Pcidev *p;
1549 Ctlr *t, *c;
1550
1551 t = 0;
1552 for(p = 0; p = pcimatch(p, Vmyricom, 0); ){
1553 switch(p->did){
1554 case 0x8: /* 8a */
1555 break;
1556 case 0x9: /* 8a with msi-x fw */
1557 case 0xa: /* 8b */
1558 case 0xb: /* 8b2 */
1559 case 0xc: /* 2-8b2 */
1560 /* untested */
1561 break;
1562 default:
1563 print("etherm10g: unknown myricom did %#ux\n", p->did);
1564 continue;
1565 }
1566 c = malloc(sizeof *c);
1567 if(c == nil)
1568 break;
1569 c->pcidev = p;
1570 c->id = p->did<<16 | p->vid;
1571 c->boot = pcicap(p, PciCapVND);
1572 // kickthebaby(p, c);
1573 pcisetbme(p);
1574 if(setmem(p, c) == -1){
1575 print("m10g: setmem failed\n");
1576 free(c);
1577 /* cleanup */
1578 continue;
1579 }
1580 if(t)
1581 t->next = c;
1582 else
1583 ctlrs = c;
1584 t = c;
1585 }
1586 }
1587
1588 static int
m10gpnp(Ether * e)1589 m10gpnp(Ether *e)
1590 {
1591 Ctlr *c;
1592
1593 if(ctlrs == nil)
1594 m10gpci();
1595
1596 for(c = ctlrs; c != nil; c = c->next)
1597 if(c->active)
1598 continue;
1599 else if(e->port == 0 || e->port == c->port)
1600 break;
1601 if(c == nil)
1602 return -1;
1603 c->active = 1;
1604
1605 e->ctlr = c;
1606 e->port = c->port;
1607 e->irq = c->pcidev->intl;
1608 e->tbdf = c->pcidev->tbdf;
1609 e->mbps = 10000;
1610 memmove(e->ea, c->ra, Eaddrlen);
1611
1612 e->attach = m10gattach;
1613 e->detach = m10gshutdown;
1614 e->transmit = m10gtransmit;
1615 e->interrupt = m10ginterrupt;
1616 e->ifstat = m10gifstat;
1617 e->ctl = m10gctl;
1618 e->shutdown = m10gshutdown;
1619
1620 e->arg = e;
1621 e->promiscuous = m10gpromiscuous;
1622 e->multicast = m10gmulticast;
1623 return 0;
1624 }
1625
1626 void
etherm10glink(void)1627 etherm10glink(void)
1628 {
1629 addethercard("m10g", m10gpnp);
1630 }
1631