Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 *
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
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
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
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
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*
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*
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
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
886
smbfree(Block *b)
887
{
888
	rbfree(b, &smpool);
889
}
890
 
891
static void
892
bgbfree(Block *b)
893
{
894
	rbfree(b, &bgpool);
895
}
896
 
897
static void
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
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*
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
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*
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
1509
m10gshutdown(Ether *e)
1510
{
1511
	dprint("m10gshutdown\n");
1512
	m10gdetach(e->ctlr);
1513
}
1514
 
1515
static void
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
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
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
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
1627
etherm10glink(void)
1628
{
1629
	addethercard("m10g", m10gpnp);
1630
}