xref: /plan9/sys/src/9/pc/etherm10g.c (revision 217e9e83c7f9cc6fb27d97dda90c8339b6f98728)
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