2 * intel 10GB ethernet pci-express driver
3 * 6.0.0: net 02.00.00 8086/15c8 11 0:dfc0000c 2097152 4:dfe0400c 16384
4 * Intel Corporation Ethernet Connection X553/X550-AT 10GBASE-T
7 #include "../port/lib.h"
12 #include "../port/error.h"
13 #include "../port/netif.h"
14 #include "../port/etherif.h"
19 Ctrl = 0x00000/4, /* Device Control */
20 Status = 0x00008/4, /* Device Status */
21 Ctrlext = 0x00018/4, /* Extended Device Control */
22 Tcptimer = 0x0004c/4, /* tcp timer */
25 Eec = 0x10010/4, /* eeprom/flash control */
26 Eemngctl = 0x10110/4, /* Manageability EEPROM-Mode Control */
29 Icr = 0x00800/4, /* interrupt cause read */
30 Ics = 0x00808/4, /* " set */
31 Ims = 0x00880/4, /* " mask read/set */
32 Imc = 0x00888/4, /* " mask clear */
33 Iac = 0x00810/4, /* " auto clear */
34 Iam = 0x00890/4, /* " auto mask enable */
35 Itr = 0x00820/4, /* " throttling rate (0-19) */
36 Ivar = 0x00900/4, /* " vector allocation regs. */
39 Rdbal = 0x01000/4, /* rx desc base low (0-63) +0x40n */
40 Rdbah = 0x01004/4, /* " high */
41 Rdlen = 0x01008/4, /* " length */
42 Rdh = 0x01010/4, /* " head */
43 Rdt = 0x01018/4, /* " tail */
44 Rxdctl = 0x01028/4, /* " control */
46 Srrctl = 0x02100/4, /* split and replication rx ctl. */
47 Rdrxctl = 0x02f00/4, /* rx dma control */
48 Rxpbsize = 0x03c00/4, /* rx packet buffer size */
49 Rxctrl = 0x03000/4, /* rx control */
52 Rxcsum = 0x05000/4, /* rx checksum control */
53 Mcstctrl = 0x05090/4, /* multicast control register */
54 Mta = 0x05200/4, /* multicast table array (0-127) */
55 Ral = 0x05400/4, /* rx address low */
57 Vfta = 0x0a000/4, /* vlan filter table array. */
58 Fctrl = 0x05080/4, /* filter control */
61 Tdbal = 0x06000/4, /* tx desc base low +0x40n */
62 Tdbah = 0x06004/4, /* " high */
63 Tdlen = 0x06008/4, /* " len */
64 Tdh = 0x06010/4, /* " head */
65 Tdt = 0x06018/4, /* " tail */
66 Txdctl = 0x06028/4, /* " control */
70 Hlreg0 = 0x04240/4, /* highlander control reg 0 */
71 Hlreg1 = 0x04244/4, /* highlander control reg 1 (ro) */
72 Maxfrs = 0x04268/4, /* max frame size */
73 Links = 0x042a4/4, /* link status */
78 Rst = 1<<26, /* full nic reset */
81 Drvload = 1<<28, /* Driver Load */
84 AutoRd = 1<<9, /* NVM auto read done */
87 CfgDone0 = 1<<18, /* Configuration Done Port 0 */
88 CfgDone1 = 1<<19, /* Configuration Done Port 1 */
91 Pthresh = 0, /* prefresh threshold shift in bits */
92 Hthresh = 8, /* host buffer minimum threshold */
93 Wthresh = 16, /* writeback threshold */
97 Bam = 1<<10, /* broadcast accept mode */
98 Upe = 1<<9, /* unicast promiscuous */
99 Mpe = 1<<8, /* multicast promiscuous */
114 Ippcse = 1<<12, /* ip payload checksum enable */
117 Mo = 0, /* multicast offset 47:36 */
118 Mfe = 1<<2, /* multicast filter enable */
124 Irx0 = 1<<0, /* driver defined - rx interrupt */
125 Itx0 = 1<<1, /* driver defined - tx interrupt */
126 Lsc = 1<<20, /* link status change */
128 /* Ivar Interrupt Vector Allocation Register */
129 Intalloc0 = 0, /* Map the 0th queue Rx interrupt to the 0th bit of EICR register */
131 intalloc1 = 1<<8, /* Map the 0th queue Tx interrupt to the 1st bit of EICR register */
132 Intallocval1 = 1<<15,
150 0x4004, "illegal byte",
151 0x4008, "short packet",
152 0x3fa0, "missed pkt0",
153 0x4034, "mac local flt",
154 0x4038, "mac rmt flt",
155 0x4040, "rx length err",
185 Pif = 1<<7, /* past exact filter (sic) */
186 Ipcs = 1<<6, /* ip checksum calcuated */
187 L4cs = 1<<5, /* layer 2 */
188 Udpcs = 1<<4, /* udp checksum calcuated */
189 Vp = 1<<3, /* 802.1q packet matched vet */
190 Reop = 1<<1, /* end of packet */
191 Rdd = 1<<0, /* descriptor done */
264 ulong stats[nelem(stattab)];
268 /* tweakable paramaters */
276 static Ctlr *ctlrtab[4];
285 for(i = 0; i < nelem(c->stats); i++)
286 c->stats[i] += c->reg[stattab[i].reg >> 2];
290 static int speedtab[] = {
297 ifstat(Ether *e, void *a, long n, ulong offset)
303 p = s = smalloc(READSTR);
308 for(i = 0; i < nelem(stattab); i++)
310 p = seprint(p, q, "%.10s %uld\n", stattab[i].name,
313 p = seprint(p, q, "speeds: 0:%d 1000:%d 10000:%d\n", t[0], t[1], t[2]);
314 seprint(p, q, "rdfree %d rdh %d rdt %d\n", c->rdfree, c->reg[Rdt],
316 n = readstr(offset, a, n, s);
334 return ((Ctlr*)v)->lim != 0;
350 e->link = (r & Lnkup) != 0;
353 i = 1 + ((r & Lnkspd) != 0);
355 e->mbps = speedtab[i];
358 sleep(&c->lrendez, lim, c);
364 ctl(Ether *, void *, long)
370 #define Next(x, m) (((x)+1) & (m))
373 cleanup(Ctlr *c, int tdh)
379 while(c->tdba[n = Next(tdh, m)].status & Tdd){
384 c->tdba[tdh].status = 0;
398 if(!canqlock(&c->tlock)){
402 tdh = c->tdh = cleanup(c, c->tdh);
405 for(i = 0; i < 8; i++){
406 if(Next(tdt, m) == tdh){
410 if(!(b = qget(e->oq)))
413 t->addr[0] = PCIWADDR(b->rp);
415 t->cmd = Rs | Ifcs | Teop;
429 return ((Ctlr*)c)->tim != 0;
443 sleep(&c->trendez, tim, c); /* transmit kicks us */
455 c->reg[Rxctrl] &= ~Rxen;
457 Receive buffers of appropriate size should be allocated
458 and pointers to these buffers should be stored in the
459 descriptor ring - replinish() does this? */
460 for(i = 0; i < c->nrd; i++){
468 c->reg[Fctrl] |= Bam;
469 c->reg[Rxcsum] |= Ippcse;
470 c->reg[Srrctl] = c->rbsz / 1024;
471 c->reg[Maxfrs] = c->rbsz << 16;
472 c->reg[Hlreg0] |= Jumboen;
474 c->reg[Rdbal] = PCIWADDR(c->rdba);
476 c->reg[Rdlen] = c->nrd*sizeof(Rd);
478 c->reg[Rdt] = c->rdt = 0;
480 c->reg[Rxdctl] = Renable;
481 while((c->reg[Rxdctl] & Renable) == 0)
483 /* TODO? bump the tail pointer RDT to enable descriptors
484 fetching by setting it to the ring length minus 1. Pg 145 */
485 c->reg[Rxctrl] |= Rxen;
489 replenish(Ctlr *c, uint rdh)
497 for(rdt = c->rdt; Next(rdt, m) != rdh; rdt = Next(rdt, m)){
498 b = allocb(c->rbsz+BY2PG);
499 b->rp = (uchar*)PGROUND((uintptr)b->base);
503 r->addr[0] = PCIWADDR(b->rp);
509 c->reg[Rdt] = c->rdt = rdt;
515 return ((Ctlr*)v)->rim != 0;
518 static uchar zeroea[Eaddrlen];
538 sleep(&c->rrendez, rim, c);
541 if(c->nrd - c->rdfree >= 16)
544 if(!(r->status & Rdd))
552 b->checksum = r->cksum;
558 goto loop1; /* UGH */
562 promiscuous(void *a, int on)
570 c->reg[Fctrl] |= Upe | Mpe;
572 c->reg[Fctrl] &= ~(Upe | Mpe);
576 multicast(void *a, uchar *ea, int on)
586 * multiple ether addresses can hash to the same filter bit,
587 * so it's never safe to clear a filter bit.
588 * if we want to clear filter bits, we need to keep track of
589 * all the multicast addresses in use, clear all the filter bits,
590 * then set the ones corresponding to in-use addresses.
592 * Extracts the 12 bits, from a multicast address, to determine which
593 * bit-vector to set in the multicast table. The hardware uses 12 bits, from
594 * incoming rx multicast addresses, to determine the bit-vector to check in
595 * the MTA. Which of the 4 combination, of 12-bits, the hardware uses is set
596 * by the MO field of the MCSTCTRL. The MO field is set during initialization
599 * The MTA is a register array of 128 32-bit registers. It is treated
600 * like an array of 4096 bits. We want to set bit
601 * BitArray[vector_value]. So we figure out what register the bit is
602 * in, read it, OR in the new bit, then write back the new value. The
603 * register is determined by the upper 7 bits of the vector value and
604 * the bit within that register are determined by the lower 5 bits of
607 * when Mcstctrl.Mo == 0, use bits [47:36] of the address
608 * register index = bits [47:41]
609 * which bit in the above register = bits [40:36]
611 i = ea[5] >> 1; /* register index = 47:41 (7 bits) */
612 b = (ea[5]&1)<<4 | ea[4]>>4; /* which bit in the above register = 40:36 (5 bits) */
618 c->reg[Mta+i] = c->mta[i];
619 c->reg[Mcstctrl] = Mfe;
620 /* for(i = 0; i < 128; i++) c->reg[Mta + i] = -1; brute force it to work for testing */
633 c->ra[1] = l>>8 & 0xFF;
634 c->ra[2] = l>>16 & 0xFF;
635 c->ra[3] = l>>24 & 0xFF;
637 c->ra[5] = h>>8 & 0xFF;
641 for(i = 0; i < 100; i++){
643 if((c->reg[Ctrl] & Rst) == 0)
650 /* not cleared by reset; kill it manually. */
651 for(i = 1; i < 16; i++)
652 c->reg[Rah + i] &= ~(1 << 31);
653 for(i = 0; i < 128; i++)
655 for(i = 1; i < 640; i++)
656 c->reg[Vfta + i] = 0;
657 c->reg[Ctrlext] &= ~Drvload; /* driver works without this */
672 while((c->reg[Eec] & AutoRd) == 0)
674 while((c->reg[Eemngctl] & CfgDone0) == 0)
676 while((c->reg[Eemngctl] & CfgDone1) == 0)
678 while((c->reg[Rdrxctl] & Dmaidone) == 0)
681 print("iX550: reset timeout\n");
684 while((c->reg[Eec] & AutoRd) == 0)
686 while((c->reg[Eemngctl] & CfgDone0) == 0)
688 while((c->reg[Eemngctl] & CfgDone1) == 0)
690 while((c->reg[Rdrxctl] & Dmaidone) == 0)
693 for(i = 0; i<nelem(c->stats); i++)
696 /* configure interrupt mapping */
697 c->reg[Ivar] = Intalloc0 | Intallocval0 | intalloc1 | Intallocval1;
699 /* interrupt throttling goes here. */
700 for(i = Itr; i < Itr + 20; i++)
701 c->reg[i] = 1<<3; /* 1 interval */
711 c->reg[Txdctl] = 16<<Wthresh | 16<<Pthresh;
712 for(i = 0; i < c->ntd; i++){
718 memset(c->tdba, 0, c->ntd * sizeof(Td));
719 c->reg[Tdbal] = PCIWADDR(c->tdba);
721 c->reg[Tdlen] = c->ntd*sizeof(Td);
727 c->reg[Txdctl] |= Ten;
728 c->reg[Dmatxctl] |= Txen;
740 c->edev = e; /* point back to Ether* */
749 t = c->nrd * sizeof *c->rdba + 255;
750 t += c->ntd * sizeof *c->tdba + 255;
751 t += (c->ntd + c->nrd) * sizeof(Block*);
752 c->alloc = malloc(t);
757 c->rdba = (Rd*)ROUNDUP((uintptr)c->alloc, 256);
758 c->tdba = (Td*)ROUNDUP((uintptr)(c->rdba + c->nrd), 256);
759 c->rb = (Block**)(c->tdba + c->ntd);
760 c->tb = (Block**)(c->rb + c->nrd);
765 c->reg[Ctrlext] |= Drvload; /* driver works without this */
766 snprint(buf, sizeof buf, "#l%dl", e->ctlrno);
767 kproc(buf, lproc, e);
768 snprint(buf, sizeof buf, "#l%dr", e->ctlrno);
769 kproc(buf, rproc, e);
770 snprint(buf, sizeof buf, "#l%dt", e->ctlrno);
771 kproc(buf, tproc, e);
775 interrupt(Ureg*, void *v)
786 while((icr = c->reg[Icr] & c->im) != 0){
803 c->reg[Ims] = c->im = im;
807 extern void addvgaseg(char*, ulong, ulong);
814 int pciregs, pcimsix;
819 while(p = pcimatch(p, 0x8086, 0x15c8)){ /* X553/X550-AT 10GBASE-T */
822 if(nctlr == nelem(ctlrtab)){
823 print("iX550: too many controllers\n");
826 c = malloc(sizeof *c);
828 print("iX550: can't allocate memory\n");
831 io = p->mem[pciregs].bar & ~0xf;
832 mem = vmap(io, p->mem[pciregs].size);
834 print("iX550: can't map regs %#p\n", io);
839 addvgaseg("pci.ctlr0.bar0", p->mem[pciregs].bar & ~0xf, p->mem[pciregs].size);
841 addvgaseg("pci.ctlr1.bar0", p->mem[pciregs].bar & ~0xf, p->mem[pciregs].size);
842 iomsi = p->mem[pcimsix].bar & ~0xf;
843 memmsi = vmap(iomsi, p->mem[pcimsix].size);
845 print("iX550: can't map msi-x regs %#p\n", iomsi);
846 vunmap(mem, p->mem[pciregs].size);
853 c->reg = (u32int*)mem;
854 c->regmsi = (u32int*)memmsi;
855 c->rbsz = ROUND(Mtu, 1024);
857 print("iX550: can't reset\n");
859 vunmap(mem, p->mem[pciregs].size);
860 vunmap(memmsi, p->mem[pcimsix].size);
864 ctlrtab[nctlr++] = c;
871 static uchar zeros[Eaddrlen];
878 for(i = 0; i < nctlr; i++){
880 if(c == nil || c->flag & Factive)
882 if(e->port == 0 || e->port == c->io)
888 if(memcmp(c->ra, zeros, Eaddrlen) != 0)
889 memmove(e->ea, c->ra, Eaddrlen);
892 c->reg[Ral] = p[3]<<24 | p[2]<<16 | p[1]<<8 | p[0];
893 c->reg[Rah] = p[5]<<8 | p[4] | 1<<31;
897 e->port = (uintptr)c->reg;
899 e->tbdf = c->p->tbdf;
907 e->multicast = multicast;
908 e->promiscuous = promiscuous;
909 e->shutdown = shutdown;
910 e->transmit = transmit;
912 intrenable(e->irq, interrupt, e, e->tbdf, e->name);
920 addethercard("iX550", pnp);