FreeBSD/Linux Kernel Cross Reference
sys/pc/ether82598.c
1 /*
2 * intel 10gbe pci-express driver
3 * copyright © 2007, coraid, inc.
4 */
5 #include "u.h"
6 #include "../port/lib.h"
7 #include "mem.h"
8 #include "dat.h"
9 #include "fns.h"
10 #include "io.h"
11 #include "../port/error.h"
12 #include "../port/netif.h"
13 #include "etherif.h"
14
15 /*
16 * // comments note conflicts with 82563-style drivers,
17 * and the registers are all different.
18 */
19
20 enum {
21 /* general */
22 Ctrl = 0x00000/4, /* Device Control */
23 Status = 0x00008/4, /* Device Status */
24 Ctrlext = 0x00018/4, /* Extended Device Control */
25 Esdp = 0x00020/4, /* extended sdp control */
26 Esodp = 0x00028/4, /* extended od sdp control */
27 Ledctl = 0x00200/4, /* led control */
28 Tcptimer = 0x0004c/4, /* tcp timer */
29 Ecc = 0x110b0/4, /* errata ecc control magic */
30
31 /* nvm */
32 Eec = 0x10010/4, /* eeprom/flash control */
33 Eerd = 0x10014/4, /* eeprom read */
34 Fla = 0x1001c/4, /* flash access */
35 Flop = 0x1013c/4, /* flash opcode */
36 Grc = 0x10200/4, /* general rx control */
37
38 /* interrupt */
39 Icr = 0x00800/4, /* interrupt cause read */
40 Ics = 0x00808/4, /* " set */
41 Ims = 0x00880/4, /* " mask read/set */
42 Imc = 0x00888/4, /* " mask clear */
43 Iac = 0x00810/4, /* " ayto clear */
44 Iam = 0x00890/4, /* " auto mask enable */
45 Itr = 0x00820/4, /* " throttling rate (0-19) */
46 Ivar = 0x00900/4, /* " vector allocation regs. */
47 /* msi interrupt */
48 Msixt = 0x0000/4, /* msix table (bar3) */
49 Msipba = 0x2000/4, /* msix pending bit array (bar3) */
50 Pbacl = 0x11068/4, /* pba clear */
51 Gpie = 0x00898/4, /* general purpose int enable */
52
53 /* flow control */
54 Pfctop = 0x03008/4, /* priority flow ctl type opcode */
55 Fcttv = 0x03200/4, /* " transmit timer value (0-3) */
56 Fcrtl = 0x03220/4, /* " rx threshold low (0-7) +8n */
57 Fcrth = 0x03260/4, /* " rx threshold high (0-7) +8n */
58 Rcrtv = 0x032a0/4, /* " refresh value threshold */
59 Tfcs = 0x0ce00/4, /* " tx status */
60
61 /* rx dma */
62 Rbal = 0x01000/4, /* rx desc base low (0-63) +0x40n */
63 Rbah = 0x01004/4, /* " high */
64 Rdlen = 0x01008/4, /* " length */
65 Rdh = 0x01010/4, /* " head */
66 Rdt = 0x01018/4, /* " tail */
67 Rxdctl = 0x01028/4, /* " control */
68
69 Srrctl = 0x02100/4, /* split and replication rx ctl. */
70 Dcarxctl = 0x02200/4, /* rx dca control */
71 Rdrxctl = 0x02f00/4, /* rx dma control */
72 Rxpbsize = 0x03c00/4, /* rx packet buffer size */
73 Rxctl = 0x03000/4, /* rx control */
74 Dropen = 0x03d04/4, /* drop enable control */
75
76 /* rx */
77 Rxcsum = 0x05000/4, /* rx checksum control */
78 Rfctl = 0x04008/4, /* rx filter control */
79 Mta = 0x05200/4, /* multicast table array (0-127) */
80 Ral = 0x05400/4, /* rx address low */
81 Rah = 0x05404/4,
82 Psrtype = 0x05480/4, /* packet split rx type. */
83 Vfta = 0x0a000/4, /* vlan filter table array. */
84 Fctrl = 0x05080/4, /* filter control */
85 Vlnctrl = 0x05088/4, /* vlan control */
86 Msctctrl = 0x05090/4, /* multicast control */
87 Mrqc = 0x05818/4, /* multiple rx queues cmd */
88 Vmdctl = 0x0581c/4, /* vmdq control */
89 Imir = 0x05a80/4, /* immediate irq rx (0-7) */
90 Imirext = 0x05aa0/4, /* immediate irq rx ext */
91 Imirvp = 0x05ac0/4, /* immediate irq vlan priority */
92 Reta = 0x05c00/4, /* redirection table */
93 Rssrk = 0x05c80/4, /* rss random key */
94
95 /* tx */
96 Tdbal = 0x06000/4, /* tx desc base low +0x40n */
97 Tdbah = 0x06004/4, /* " high */
98 Tdlen = 0x06008/4, /* " len */
99 Tdh = 0x06010/4, /* " head */
100 Tdt = 0x06018/4, /* " tail */
101 Txdctl = 0x06028/4, /* " control */
102 Tdwbal = 0x06038/4, /* " write-back address low */
103 Tdwbah = 0x0603c/4,
104
105 Dtxctl = 0x07e00/4, /* tx dma control */
106 Tdcatxctrl = 0x07200/4, /* tx dca register (0-15) */
107 Tipg = 0x0cb00/4, /* tx inter-packet gap */
108 Txpbsize = 0x0cc00/4, /* tx packet-buffer size (0-15) */
109
110 /* mac */
111 Hlreg0 = 0x04240/4, /* highlander control reg 0 */
112 Hlreg1 = 0x04244/4, /* highlander control reg 1 (ro) */
113 Msca = 0x0425c/4, /* mdi signal cmd & addr */
114 Msrwd = 0x04260/4, /* mdi single rw data */
115 Mhadd = 0x04268/4, /* mac addr high & max frame */
116 Pcss1 = 0x04288/4, /* xgxs status 1 */
117 Pcss2 = 0x0428c/4,
118 Xpcss = 0x04290/4, /* 10gb-x pcs status */
119 Serdesc = 0x04298/4, /* serdes control */
120 Macs = 0x0429c/4, /* fifo control & report */
121 Autoc = 0x042a0/4, /* autodetect control & status */
122 Links = 0x042a4/4, /* link status */
123 Autoc2 = 0x042a8/4,
124 };
125
126 enum {
127 /* Ctrl */
128 Rst = 1<<26, /* full nic reset */
129
130 /* Txdctl */
131 Ten = 1<<25,
132
133 /* Fctrl */
134 Bam = 1<<10, /* broadcast accept mode */
135 Upe = 1<<9, /* unicast promiscuous */
136 Mpe = 1<<8, /* multicast promiscuous */
137
138 /* Rxdctl */
139 Pthresh = 0, /* prefresh threshold shift in bits */
140 Hthresh = 8, /* host buffer minimum threshold " */
141 Wthresh = 16, /* writeback threshold */
142 Renable = 1<<25,
143
144 /* Rxctl */
145 Rxen = 1<<0,
146 Dmbyps = 1<<1,
147
148 /* Rdrxctl */
149 Rdmt½ = 0,
150 Rdmt¼ = 1,
151 Rdmt⅛ = 2,
152
153 /* Rxcsum */
154 Ippcse = 1<<12, /* ip payload checksum enable */
155
156 /* Eerd */
157 EEstart = 1<<0, /* Start Read */
158 EEdone = 1<<1, /* Read done */
159
160 /* interrupts */
161 Irx0 = 1<<0, /* driver defined */
162 Itx0 = 1<<1, /* driver defined */
163 Lsc = 1<<20, /* link status change */
164
165 /* Links */
166 Lnkup = 1<<30,
167 Lnkspd = 1<<29,
168
169 /* Hlreg0 */
170 Jumboen = 1<<2,
171 };
172
173 typedef struct {
174 uint reg;
175 char *name;
176 } Stat;
177
178 Stat stattab[] = {
179 0x4000, "crc error",
180 0x4004, "illegal byte",
181 0x4008, "short packet",
182 0x3fa0, "missed pkt0",
183 0x4034, "mac local flt",
184 0x4038, "mac rmt flt",
185 0x4040, "rx length err",
186 0x3f60, "xon tx",
187 0xcf60, "xon rx",
188 0x3f68, "xoff tx",
189 0xcf68, "xoff rx",
190 0x405c, "rx 040",
191 0x4060, "rx 07f",
192 0x4064, "rx 100",
193 0x4068, "rx 200",
194 0x406c, "rx 3ff",
195 0x4070, "rx big",
196 0x4074, "rx ok",
197 0x4078, "rx bcast",
198 0x3fc0, "rx no buf0",
199 0x40a4, "rx runt",
200 0x40a8, "rx frag",
201 0x40ac, "rx ovrsz",
202 0x40b0, "rx jab",
203 0x40d0, "rx pkt",
204
205 0x40d4, "tx pkt",
206 0x40d8, "tx 040",
207 0x40dc, "tx 07f",
208 0x40e0, "tx 100",
209 0x40e4, "tx 200",
210 0x40e8, "tx 3ff",
211 0x40ec, "tx big",
212 0x40f4, "tx bcast",
213 0x4120, "xsum err",
214 };
215
216 /* status */
217 enum {
218 Pif = 1<<7, /* past exact filter (sic) */
219 Ipcs = 1<<6, /* ip checksum calcuated */
220 L4cs = 1<<5, /* layer 2 */
221 Tcpcs = 1<<4, /* tcp checksum calcuated */
222 Vp = 1<<3, /* 802.1q packet matched vet */
223 Ixsm = 1<<2, /* ignore checksum */
224 Reop = 1<<1, /* end of packet */
225 Rdd = 1<<0, /* descriptor done */
226 };
227
228 typedef struct {
229 u32int addr[2];
230 ushort length;
231 ushort cksum;
232 uchar status;
233 uchar errors;
234 ushort vlan;
235 } Rd;
236
237 enum {
238 /* Td cmd */
239 Rs = 1<<3,
240 Ic = 1<<2,
241 Ifcs = 1<<1,
242 Teop = 1<<0,
243
244 /* Td status */
245 Tdd = 1<<0,
246 };
247
248 typedef struct {
249 u32int addr[2];
250 ushort length;
251 uchar cso;
252 uchar cmd;
253 uchar status;
254 uchar css;
255 ushort vlan;
256 } Td;
257
258 enum {
259 Factive = 1<<0,
260 Fstarted = 1<<1,
261 };
262
263 typedef struct {
264 Pcidev *p;
265 Ether *edev;
266 u32int *reg;
267 u32int *reg3;
268 uchar flag;
269 int nrd;
270 int ntd;
271 int nrb;
272 int rbsz;
273 QLock slock;
274 QLock alock;
275 QLock tlock;
276 Rendez lrendez;
277 Rendez trendez;
278 Rendez rrendez;
279 uint im;
280 uint lim;
281 uint rim;
282 uint tim;
283 Lock imlock;
284 char *alloc;
285
286 Rd *rdba;
287 Block **rb;
288 uint rdt;
289 uint rdfree;
290
291 Td *tdba;
292 uint tdh;
293 uint tdt;
294 Block **tb;
295
296 uchar ra[Eaddrlen];
297 uchar mta[128];
298 ulong stats[nelem(stattab)];
299 uint speeds[3];
300 } Ctlr;
301
302 /* tweakable paramaters */
303 enum {
304 Rbsz = 12*1024,
305 Nrd = 256,
306 Ntd = 256,
307 Nrb = 256,
308 };
309
310 static Ctlr *ctlrtab[4];
311 static int nctlr;
312 static Lock rblock;
313 static Block *rbpool;
314
315 static void
316 readstats(Ctlr *c)
317 {
318 int i;
319
320 qlock(&c->slock);
321 for(i = 0; i < nelem(c->stats); i++)
322 c->stats[i] += c->reg[stattab[i].reg >> 2];
323 qunlock(&c->slock);
324 }
325
326 static int speedtab[] = {
327 0,
328 1000,
329 10000,
330 };
331
332 static long
333 ifstat(Ether *e, void *a, long n, ulong offset)
334 {
335 uint i, *t;
336 char *s, *p, *q;
337 Ctlr *c;
338
339 c = e->ctlr;
340 p = s = malloc(READSTR);
341 q = p + READSTR;
342
343 readstats(c);
344 for(i = 0; i < nelem(stattab); i++)
345 if(c->stats[i] > 0)
346 p = seprint(p, q, "%.10s %uld\n", stattab[i].name, c->stats[i]);
347 t = c->speeds;
348 p = seprint(p, q, "speeds: 0:%d 1000:%d 10000:%d\n", t[0], t[1], t[2]);
349 seprint(p, q, "rdfree %d rdh %d rdt %d\n", c->rdfree, c->reg[Rdt],
350 c->reg[Rdh]);
351 n = readstr(offset, a, n, s);
352 free(s);
353
354 return n;
355 }
356
357 static void
358 im(Ctlr *c, int i)
359 {
360 ilock(&c->imlock);
361 c->im |= i;
362 c->reg[Ims] = c->im;
363 iunlock(&c->imlock);
364 }
365
366 static int
367 lim(void *v)
368 {
369 return ((Ctlr*)v)->lim != 0;
370 }
371
372 static void
373 lproc(void *v)
374 {
375 int r, i;
376 Ctlr *c;
377 Ether *e;
378
379 e = v;
380 c = e->ctlr;
381 for (;;) {
382 r = c->reg[Links];
383 e->link = (r & Lnkup) != 0;
384 i = 0;
385 if(e->link)
386 i = 1 + ((r & Lnkspd) != 0);
387 c->speeds[i]++;
388 e->mbps = speedtab[i];
389 c->lim = 0;
390 im(c, Lsc);
391 sleep(&c->lrendez, lim, c);
392 c->lim = 0;
393 }
394 }
395
396 static long
397 ctl(Ether *, void *, long)
398 {
399 error(Ebadarg);
400 return -1;
401 }
402
403 static Block*
404 rballoc(void)
405 {
406 Block *b;
407
408 ilock(&rblock);
409 if(b = rbpool){
410 rbpool = b->next;
411 b->next = 0;
412 }
413 iunlock(&rblock);
414 return b;
415 }
416
417 void
418 rbfree(Block *b)
419 {
420 b->rp = b->wp = (uchar*)PGROUND((uintptr)b->base);
421 ilock(&rblock);
422 b->next = rbpool;
423 rbpool = b;
424 iunlock(&rblock);
425 }
426
427 #define Next(x, m) (((x)+1) & (m))
428
429 static int
430 cleanup(Ctlr *c, int tdh)
431 {
432 Block *b;
433 uint m, n;
434
435 m = c->ntd - 1;
436 while(c->tdba[n = Next(tdh, m)].status & Tdd){
437 tdh = n;
438 b = c->tb[tdh];
439 c->tb[tdh] = 0;
440 freeb(b);
441 c->tdba[tdh].status = 0;
442 }
443 return tdh;
444 }
445
446 void
447 transmit(Ether *e)
448 {
449 uint i, m, tdt, tdh;
450 Ctlr *c;
451 Block *b;
452 Td *t;
453
454 c = e->ctlr;
455 // qlock(&c->tlock);
456 if(!canqlock(&c->tlock)){
457 im(c, Itx0);
458 return;
459 }
460 tdh = c->tdh = cleanup(c, c->tdh);
461 tdt = c->tdt;
462 m = c->ntd - 1;
463 for(i = 0; i < 8; i++){
464 if(Next(tdt, m) == tdh){
465 im(c, Itx0);
466 break;
467 }
468 if(!(b = qget(e->oq)))
469 break;
470 t = c->tdba + tdt;
471 t->addr[0] = PCIWADDR(b->rp);
472 t->length = BLEN(b);
473 t->cmd = Rs | Ifcs | Teop;
474 c->tb[tdt] = b;
475 tdt = Next(tdt, m);
476 }
477 if(i){
478 c->tdt = tdt;
479 c->reg[Tdt] = tdt;
480 }
481 qunlock(&c->tlock);
482 }
483
484 static int
485 tim(void *c)
486 {
487 return ((Ctlr*)c)->tim != 0;
488 }
489
490 static void
491 tproc(void *v)
492 {
493 Ctlr *c;
494 Ether *e;
495
496 e = v;
497 c = e->ctlr;
498 for (;;) {
499 sleep(&c->trendez, tim, c); /* transmit kicks us */
500 c->tim = 0;
501 transmit(e);
502 }
503 }
504
505 static void
506 rxinit(Ctlr *c)
507 {
508 int i;
509 Block *b;
510
511 c->reg[Rxctl] &= ~Rxen;
512 for(i = 0; i < c->nrd; i++){
513 b = c->rb[i];
514 c->rb[i] = 0;
515 if(b)
516 freeb(b);
517 }
518 c->rdfree = 0;
519
520 c->reg[Fctrl] |= Bam;
521 c->reg[Rxcsum] |= Ipcs;
522 c->reg[Srrctl] = (c->rbsz + 1023)/1024;
523 c->reg[Mhadd] = c->rbsz << 16;
524 c->reg[Hlreg0] |= Jumboen;
525
526 c->reg[Rbal] = PCIWADDR(c->rdba);
527 c->reg[Rbah] = 0;
528 c->reg[Rdlen] = c->nrd*sizeof(Rd);
529 c->reg[Rdh] = 0;
530 c->reg[Rdt] = c->rdt = 0;
531
532 c->reg[Rdrxctl] = Rdmt¼;
533 c->reg[Rxdctl] = 8<<Wthresh | 8<<Pthresh | 4<<Hthresh | Renable;
534 c->reg[Rxctl] |= Rxen | Dmbyps;
535 }
536
537 static void
538 replenish(Ctlr *c, uint rdh)
539 {
540 int rdt, m, i;
541 Block *b;
542 Rd *r;
543
544 m = c->nrd - 1;
545 i = 0;
546 for(rdt = c->rdt; Next(rdt, m) != rdh; rdt = Next(rdt, m)){
547 r = c->rdba + rdt;
548 if(!(b = rballoc())){
549 print("82598: no buffers\n");
550 break;
551 }
552 c->rb[rdt] = b;
553 r->addr[0] = PCIWADDR(b->rp);
554 r->status = 0;
555 c->rdfree++;
556 i++;
557 }
558 if(i)
559 c->reg[Rdt] = c->rdt = rdt;
560 }
561
562 static int
563 rim(void *v)
564 {
565 return ((Ctlr*)v)->rim != 0;
566 }
567
568 static uchar zeroea[Eaddrlen];
569
570 void
571 rproc(void *v)
572 {
573 uint m, rdh;
574 Block *b;
575 Ctlr *c;
576 Ether *e;
577 Rd *r;
578
579 e = v;
580 c = e->ctlr;
581 m = c->nrd - 1;
582 rdh = 0;
583 loop:
584 replenish(c, rdh);
585 im(c, Irx0);
586 sleep(&c->rrendez, rim, c);
587 loop1:
588 c->rim = 0;
589 if(c->nrd - c->rdfree >= 16)
590 replenish(c, rdh);
591 r = c->rdba + rdh;
592 if(!(r->status & Rdd))
593 goto loop; /* UGH */
594 b = c->rb[rdh];
595 c->rb[rdh] = 0;
596 b->wp += r->length;
597 b->lim = b->wp; /* lie like a dog */
598 if(!(r->status & Ixsm)){
599 if(r->status & Ipcs)
600 b->flag |= Bipck;
601 if(r->status & Tcpcs)
602 b->flag |= Btcpck | Budpck;
603 b->checksum = r->cksum;
604 }
605 // r->status = 0;
606 etheriq(e, b, 1);
607 c->rdfree--;
608 rdh = Next(rdh, m);
609 goto loop1; /* UGH */
610 }
611
612 static void
613 promiscuous(void *a, int on)
614 {
615 Ctlr *c;
616 Ether *e;
617
618 e = a;
619 c = e->ctlr;
620 if(on)
621 c->reg[Fctrl] |= Upe | Mpe;
622 else
623 c->reg[Fctrl] &= ~(Upe | Mpe);
624 }
625
626 static void
627 multicast(void *a, uchar *ea, int on)
628 {
629 int b, i;
630 Ctlr *c;
631 Ether *e;
632
633 e = a;
634 c = e->ctlr;
635
636 /*
637 * multiple ether addresses can hash to the same filter bit,
638 * so it's never safe to clear a filter bit.
639 * if we want to clear filter bits, we need to keep track of
640 * all the multicast addresses in use, clear all the filter bits,
641 * then set the ones corresponding to in-use addresses.
642 */
643 i = ea[5] >> 1;
644 b = (ea[5]&1)<<4 | ea[4]>>4;
645 b = 1 << b;
646 if(on)
647 c->mta[i] |= b;
648 // else
649 // c->mta[i] &= ~b;
650 c->reg[Mta+i] = c->mta[i];
651 }
652
653 static int
654 detach(Ctlr *c)
655 {
656 int i;
657
658 c->reg[Imc] = ~0;
659 c->reg[Ctrl] |= Rst;
660 for(i = 0; i < 100; i++){
661 delay(1);
662 if((c->reg[Ctrl] & Rst) == 0)
663 break;
664 }
665 if (i >= 100)
666 return -1;
667 /* errata */
668 delay(50);
669 c->reg[Ecc] &= ~(1<<21 | 1<<18 | 1<<9 | 1<<6);
670
671 /* not cleared by reset; kill it manually. */
672 for(i = 1; i < 16; i++)
673 c->reg[Rah] &= ~(1 << 31);
674 for(i = 0; i < 128; i++)
675 c->reg[Mta + i] = 0;
676 for(i = 1; i < 640; i++)
677 c->reg[Vfta + i] = 0;
678 return 0;
679 }
680
681 static void
682 shutdown(Ether *e)
683 {
684 detach(e->ctlr);
685 }
686
687 /* ≤ 20ms */
688 static ushort
689 eeread(Ctlr *c, int i)
690 {
691 c->reg[Eerd] = EEstart | i<<2;
692 while((c->reg[Eerd] & EEdone) == 0)
693 ;
694 return c->reg[Eerd] >> 16;
695 }
696
697 static int
698 eeload(Ctlr *c)
699 {
700 ushort u, v, p, l, i, j;
701
702 if((eeread(c, 0) & 0xc0) != 0x40)
703 return -1;
704 u = 0;
705 for(i = 0; i < 0x40; i++)
706 u += eeread(c, i);
707 for(i = 3; i < 0xf; i++){
708 p = eeread(c, i);
709 l = eeread(c, p++);
710 if((int)p + l + 1 > 0xffff)
711 continue;
712 for(j = p; j < p + l; j++)
713 u += eeread(c, j);
714 }
715 if(u != 0xbaba)
716 return -1;
717 if(c->reg[Status] & (1<<3))
718 u = eeread(c, 10);
719 else
720 u = eeread(c, 9);
721 u++;
722 for(i = 0; i < Eaddrlen;){
723 v = eeread(c, u + i/2);
724 c->ra[i++] = v;
725 c->ra[i++] = v>>8;
726 }
727 c->ra[5] += (c->reg[Status] & 0xc) >> 2;
728 return 0;
729 }
730
731 static int
732 reset(Ctlr *c)
733 {
734 int i;
735 uchar *p;
736
737 if(detach(c)){
738 print("82598: reset timeout\n");
739 return -1;
740 }
741 if(eeload(c)){
742 print("82598: eeprom failure\n");
743 return -1;
744 }
745 p = c->ra;
746 c->reg[Ral] = p[3]<<24 | p[2]<<16 | p[1]<<8 | p[0];
747 c->reg[Rah] = p[5]<<8 | p[4] | 1<<31;
748
749 readstats(c);
750 for(i = 0; i<nelem(c->stats); i++)
751 c->stats[i] = 0;
752
753 c->reg[Ctrlext] |= 1 << 16;
754 /* make some guesses for flow control */
755 c->reg[Fcrtl] = 0x10000 | 1<<31;
756 c->reg[Fcrth] = 0x40000 | 1<<31;
757 c->reg[Rcrtv] = 0x6000;
758
759 /* configure interrupt mapping (don't ask) */
760 c->reg[Ivar+0] = 0 | 1<<7;
761 c->reg[Ivar+64/4] = 1 | 1<<7;
762 // c->reg[Ivar+97/4] = (2 | 1<<7) << (8*(97%4));
763
764 /* interrupt throttling goes here. */
765 for(i = Itr; i < Itr + 20; i++)
766 c->reg[i] = 128; /* ¼µs intervals */
767 c->reg[Itr + Itx0] = 256;
768 return 0;
769 }
770
771 static void
772 txinit(Ctlr *c)
773 {
774 Block *b;
775 int i;
776
777 c->reg[Txdctl] = 16<<Wthresh | 16<<Pthresh;
778 for(i = 0; i < c->ntd; i++){
779 b = c->tb[i];
780 c->tb[i] = 0;
781 if(b)
782 freeb(b);
783 }
784 memset(c->tdba, 0, c->ntd * sizeof(Td));
785 c->reg[Tdbal] = PCIWADDR(c->tdba);
786 c->reg[Tdbah] = 0;
787 c->reg[Tdlen] = c->ntd*sizeof(Td);
788 c->reg[Tdh] = 0;
789 c->reg[Tdt] = 0;
790 c->tdh = c->ntd - 1;
791 c->tdt = 0;
792 c->reg[Txdctl] |= Ten;
793 }
794
795 static void
796 attach(Ether *e)
797 {
798 Block *b;
799 Ctlr *c;
800 int t;
801 char buf[KNAMELEN];
802
803 c = e->ctlr;
804 c->edev = e; /* point back to Ether* */
805 qlock(&c->alock);
806 if(c->alloc){
807 qunlock(&c->alock);
808 return;
809 }
810
811 c->nrd = Nrd;
812 c->ntd = Ntd;
813 t = c->nrd * sizeof *c->rdba + 255;
814 t += c->ntd * sizeof *c->tdba + 255;
815 t += (c->ntd + c->nrd) * sizeof(Block*);
816 c->alloc = malloc(t);
817 qunlock(&c->alock);
818 if(c->alloc == nil)
819 error(Enomem);
820
821 c->rdba = (Rd*)ROUNDUP((uintptr)c->alloc, 256);
822 c->tdba = (Td*)ROUNDUP((uintptr)(c->rdba + c->nrd), 256);
823 c->rb = (Block**)(c->tdba + c->ntd);
824 c->tb = (Block**)(c->rb + c->nrd);
825
826 if(waserror()){
827 while(b = rballoc()){
828 b->free = 0;
829 freeb(b);
830 }
831 free(c->alloc);
832 c->alloc = nil;
833 nexterror();
834 }
835 for(c->nrb = 0; c->nrb < 2*Nrb; c->nrb++){
836 if(!(b = allocb(c->rbsz+BY2PG)))
837 error(Enomem);
838 b->free = rbfree;
839 freeb(b);
840 }
841 poperror();
842
843 rxinit(c);
844 txinit(c);
845
846 sprint(buf, "#l%dl", e->ctlrno);
847 kproc(buf, lproc, e);
848 sprint(buf, "#l%dr", e->ctlrno);
849 kproc(buf, rproc, e);
850 sprint(buf, "#l%dt", e->ctlrno);
851 kproc(buf, tproc, e);
852 }
853
854 static void
855 interrupt(Ureg*, void *v)
856 {
857 int icr, im;
858 Ctlr *c;
859 Ether *e;
860
861 e = v;
862 c = e->ctlr;
863 ilock(&c->imlock);
864 c->reg[Imc] = ~0;
865 im = c->im;
866 while((icr = c->reg[Icr] & c->im) != 0){
867 if(icr & Lsc){
868 im &= ~Lsc;
869 c->lim = icr & Lsc;
870 wakeup(&c->lrendez);
871 }
872 if(icr & Irx0){
873 im &= ~Irx0;
874 c->rim = icr & Irx0;
875 wakeup(&c->rrendez);
876 }
877 if(icr & Itx0){
878 im &= ~Itx0;
879 c->tim = icr & Itx0;
880 wakeup(&c->trendez);
881 }
882 }
883 c->reg[Ims] = c->im = im;
884 iunlock(&c->imlock);
885 }
886
887 static void
888 scan(void)
889 {
890 ulong io, io3;
891 void *mem, *mem3;
892 Ctlr *c;
893 Pcidev *p;
894
895 p = 0;
896 while(p = pcimatch(p, 0x8086, 0)){
897 switch(p->did){
898 case 0x10c6: /* 82598 af dual port */
899 case 0x10c7: /* 82598 af single port */
900 case 0x10b6: /* 82598 backplane */
901 case 0x10dd: /* 82598 at cx4 */
902 break;
903 default:
904 continue;
905 }
906 if(nctlr == nelem(ctlrtab)){
907 print("i82598: too many controllers\n");
908 return;
909 }
910 io = p->mem[0].bar & ~0xf;
911 mem = vmap(io, p->mem[0].size);
912 if(mem == nil){
913 print("i82598: can't map %#p\n", p->mem[0].bar);
914 continue;
915 }
916 io3 = p->mem[3].bar & ~0xf;
917 mem3 = vmap(io3, p->mem[3].size);
918 if(mem3 == nil){
919 print("i82598: can't map %#p\n", p->mem[3].bar);
920 vunmap(mem, p->mem[0].size);
921 continue;
922 }
923 c = malloc(sizeof *c);
924 c->p = p;
925 c->reg = (u32int*)mem;
926 c->reg3 = (u32int*)mem3;
927 c->rbsz = Rbsz;
928 if(reset(c)){
929 print("i82598: can't reset\n");
930 free(c);
931 vunmap(mem, p->mem[0].size);
932 vunmap(mem3, p->mem[3].size);
933 continue;
934 }
935 pcisetbme(p);
936 ctlrtab[nctlr++] = c;
937 }
938 }
939
940 static int
941 pnp(Ether *e)
942 {
943 int i;
944 Ctlr *c = nil;
945
946 if(nctlr == 0)
947 scan();
948 for(i = 0; i < nctlr; i++){
949 c = ctlrtab[i];
950 if(c == nil || c->flag & Factive)
951 continue;
952 if(e->port == 0 || e->port == (ulong)c->reg)
953 break;
954 }
955 if (i >= nctlr)
956 return -1;
957 c->flag |= Factive;
958 e->ctlr = c;
959 e->port = (uintptr)c->reg;
960 e->irq = c->p->intl;
961 e->tbdf = c->p->tbdf;
962 e->mbps = 10000;
963 e->maxmtu = c->rbsz;
964 memmove(e->ea, c->ra, Eaddrlen);
965 e->arg = e;
966 e->attach = attach;
967 e->ctl = ctl;
968 e->ifstat = ifstat;
969 e->interrupt = interrupt;
970 e->multicast = multicast;
971 e->promiscuous = promiscuous;
972 e->shutdown = shutdown;
973 e->transmit = transmit;
974
975 return 0;
976 }
977
978 void
979 ether82598link(void)
980 {
981 addethercard("i82598", pnp);
982 }
Cache object: 879b8331a4d7c1ea1c76d6d72b42c3d0
|