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