X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=sys%2Fsrc%2F9%2Fpc%2Fether82563.c;h=7d62e735b1cb650a6fbd34c63b47857fdfc24fcf;hb=e38f75fc45bba789ceea05d5e62f1d8662bf508b;hp=4769a3a37d10f3b7737fd2a6fd7f61c85626538e;hpb=a5efa0e252692b888a5de679cfc901a0421ffe73;p=plan9front.git diff --git a/sys/src/9/pc/ether82563.c b/sys/src/9/pc/ether82563.c index 4769a3a37..7d62e735b 100644 --- a/sys/src/9/pc/ether82563.c +++ b/sys/src/9/pc/ether82563.c @@ -11,8 +11,7 @@ #include "io.h" #include "../port/error.h" #include "../port/netif.h" - -#include "etherif.h" +#include "../port/etherif.h" /* * note: the 82575, 82576 and 82580 are operated using registers aliased @@ -105,6 +104,9 @@ enum { Torl = 0xC0/4, /* Total Octets Received */ Totl = 0xC8/4, /* Total Octets Transmitted */ Nstatistics = 0x124/4, + + /* iNVM (i211) */ + Invmdata0 = 0x12120, }; enum { /* Ctrl */ @@ -128,6 +130,7 @@ enum { /* Status */ enum { /* Eec */ Nvpres = 1<<8, Autord = 1<<9, + Flupd = 1<<19, Sec1val = 1<<22, }; @@ -443,7 +446,10 @@ enum { i82579, i82580, i82583, + i210, + i217, i218, + i219, i350, Nctlrtype, }; @@ -457,6 +463,7 @@ enum { F79phy = 1<<5, Fnofct = 1<<6, Fbadcsum= 1<<7, + Fnofca = 1<<8, }; typedef struct Ctlrtype Ctlrtype; @@ -473,7 +480,7 @@ static Ctlrtype cttab[Nctlrtype] = { [i82567m] "i82567m", 1514, Fload, [i82571] "i82571", 9234, Fpba, [i82572] "i82572", 9234, Fpba, -[i82573] "i82573", 8192, Fert, /* terrible perf above 8k */ +[i82573] "i82573", 8192, Fert|Fbadcsum, /* terrible perf above 8k */ [i82574] "i82574", 9018, 0, [i82575] "i82575", 9728, F75|Fflashea, [i82576] "i82576", 9728, F75, @@ -484,7 +491,10 @@ static Ctlrtype cttab[Nctlrtype] = { [i82579] "i82579", 9018, Fload|Fert|F79phy|Fnofct, [i82580] "i82580", 9728, F75|F79phy, [i82583] "i82583", 1514, 0, -[i218] "i218", 9728, Fload|Fert|F79phy|Fnofct|Fbadcsum, +[i210] "i210", 9728, F75|Fnofct|Fert, +[i217] "i217", 2048, Fload|Fert|F79phy|Fnofct|Fnofca|Fbadcsum,/* 9018, but unstable above 2k */ +[i218] "i218", 9018, Fload|Fert|F79phy|Fnofct|Fnofca|Fbadcsum, +[i219] "i219", 9018, Fload|Fert|F79phy|Fnofct|Fnofca|Fbadcsum, [i350] "i350", 9728, F75|F79phy|Fnofct, }; @@ -503,7 +513,7 @@ struct Ctlr { void *alloc; /* receive/transmit descriptors */ int nrd; int ntd; - uint rbsz; + int rbsz; u32int *nic; Lock imlock; @@ -704,13 +714,13 @@ i82563ifstat(Ether *edev, void *a, long n, ulong offset) ctlr->speeds[0], ctlr->speeds[1], ctlr->speeds[2], ctlr->speeds[3]); p = seprint(p, e, "type: %s\n", cname(ctlr)); -// p = seprint(p, e, "eeprom:"); -// for(i = 0; i < 0x40; i++){ -// if(i && ((i & 7) == 0)) -// p = seprint(p, e, "\n "); -// p = seprint(p, e, " %4.4ux", ctlr->eeprom[i]); -// } -// p = seprint(p, e, "\n"); + p = seprint(p, e, "eeprom:"); + for(i = 0; i < 0x40; i++){ + if(i && ((i & 7) == 0)) + p = seprint(p, e, "\n "); + p = seprint(p, e, " %4.4ux", ctlr->eeprom[i]); + } + p = seprint(p, e, "\n"); USED(p); n = readstr(offset, a, n, s); @@ -756,7 +766,9 @@ i82563multicast(void *arg, uchar *addr, int on) case i82577: case i82577m: case i82579: + case i217: case i218: + case i219: bit = (addr[5]<<2)|(addr[4]>>6); x = (bit>>5) & 31; break; @@ -930,8 +942,6 @@ i82563rxinit(Ctlr *ctlr) csr32w(ctlr, Rctl, Dpf|Bsize2048|Bam|RdtmsHALF); else{ i = ctlr->rbsz / 1024; - if(ctlr->rbsz % 1024) - i++; if(cttab[ctlr->type].flag & F75){ csr32w(ctlr, Rctl, Lpe|Dpf|Bsize2048|Bam|RdtmsHALF|Secrc); if(ctlr->type != i82575) @@ -1050,7 +1060,7 @@ i82563rproc(void *arg) bp->checksum = rd->checksum; bp->flag |= Bpktck; } - etheriq(edev, bp, 1); + etheriq(edev, bp); } else freeb(bp); ctlr->rb[rdh] = nil; @@ -1086,7 +1096,7 @@ phyread(Ctlr *c, int phyno, int reg) microdelay(1); } if((phy & (MDIe|MDIready)) != MDIready){ - print("%s: phy %d wedged %.8ux\n", cttab[c->type].name, phyno, phy); + print("%s: phy %d wedged %.8ux\n", cname(c), phyno, phy); return ~0; } return phy & 0xffff; @@ -1170,47 +1180,52 @@ phyprobe(Ctlr *c, uint mask) return ~0; } +static void +lsleep(Ctlr *c, uint m) +{ + c->lim = 0; + i82563im(c, m); + c->lsleep++; + sleep(&c->lrendez, i82563lim, c); +} + static void phyl79proc(void *v) { - uint a, i, r, phy, phyno; + uint i, r, phy, phyno; Ctlr *c; Ether *e; e = v; c = e->ctlr; - - phyno = phyprobe(c, 3<<1); - if(phyno == ~0){ - print("%s: no phy, exiting\n", up->text); - pexit("no phy", 1); - } - while(waserror()) ; + + while((phyno = phyprobe(c, 3<<1)) == ~0) + lsleep(c, Lsc); + for(;;){ - phy = phyread(c, phyno, Phystat); - if(phy == ~0){ - phy = 0; - i = 3; - goto next; + phy = 0; + for(i=0; i<4; i++){ + tsleep(&up->sleep, return0, 0, 150); + phy = phyread(c, phyno, Phystat); + if(phy == ~0) + continue; + if(phy & Ans){ + r = phyread(c, phyno, Phyctl); + if(r == ~0) + continue; + phywrite(c, phyno, Phyctl, r | Ran | Ean); + } + break; } i = (phy>>8) & 3; - a = phy & Ans; - if(a){ - r = phyread(c, phyno, Phyctl); - phywrite(c, phyno, Phyctl, r | Ran | Ean); - } -next: e->link = i != 3 && (phy & Link) != 0; if(e->link == 0) i = 3; c->speeds[i]++; e->mbps = speedtab[i]; - c->lim = 0; - i82563im(c, Lsc); - c->lsleep++; - sleep(&c->lrendez, i82563lim, c); + lsleep(c, Lsc); } } @@ -1223,18 +1238,15 @@ phylproc(void *v) e = v; c = e->ctlr; + while(waserror()) + ; - phyno = phyprobe(c, 3<<1); - if(phyno == ~0){ - print("%s: no phy, exiting\n", up->text); - pexit("no phy", 1); - } + while((phyno = phyprobe(c, 3<<1)) == ~0) + lsleep(c, Lsc); if(c->type == i82573 && (phy = phyread(c, phyno, Phyier)) != ~0) phywrite(c, phyno, Phyier, phy | Lscie | Ancie | Spdie | Panie); - while(waserror()) - ; for(;;){ phy = phyread(c, phyno, Physsr); if(phy == ~0){ @@ -1271,10 +1283,7 @@ next: e->mbps = speedtab[i]; if(c->type == i82563) phyerrata(e, c, phyno); - c->lim = 0; - i82563im(c, Lsc); - c->lsleep++; - sleep(&c->lrendez, i82563lim, c); + lsleep(c, Lsc); } } @@ -1287,11 +1296,11 @@ pcslproc(void *v) e = v; c = e->ctlr; + while(waserror()) + ; if(c->type == i82575 || c->type == i82576) csr32w(c, Connsw, Enrgirq); - while(waserror()) - ; for(;;){ phy = csr32r(c, Pcsstat); e->link = phy & Linkok; @@ -1302,10 +1311,7 @@ pcslproc(void *v) csr32w(c, Pcsctl, csr32r(c, Pcsctl) | Pan | Prestart); c->speeds[i]++; e->mbps = speedtab[i]; - c->lim = 0; - i82563im(c, Lsc | Omed); - c->lsleep++; - sleep(&c->lrendez, i82563lim, c); + lsleep(c, Lsc | Omed); } } @@ -1318,7 +1324,6 @@ serdeslproc(void *v) e = v; c = e->ctlr; - while(waserror()) ; for(;;){ @@ -1332,10 +1337,7 @@ serdeslproc(void *v) i = 2; c->speeds[i]++; e->mbps = speedtab[i]; - c->lim = 0; - i82563im(c, Lsc); - c->lsleep++; - sleep(&c->lrendez, i82563lim, c); + lsleep(c, Lsc); } } @@ -1552,49 +1554,105 @@ eeload(Ctlr *ctlr) } static int -fcycle(Ctlr *, Flash *f) +fread16(Ctlr *c, Flash *f, int ladr) { u16int s; - int i; + int timeout; + delay(1); s = f->reg[Fsts]; if((s&Fvalid) == 0) return -1; f->reg[Fsts] |= Fcerr | Ael; - for(i = 0; i < 10; i++){ + for(timeout = 0; timeout < 10; timeout++){ if((s&Scip) == 0) - return 0; + goto done; delay(1); s = f->reg[Fsts]; } return -1; +done: + f->reg[Fsts] |= Fdone; + f->reg32[Faddr] = ladr; + + /* setup flash control register */ + s = f->reg[Fctl] & ~0x3ff; + f->reg[Fctl] = s | 1<<8 | Fgo; /* 2 byte read */ + timeout = 1000; + while((f->reg[Fsts] & Fdone) == 0 && timeout--) + microdelay(5); + if(timeout < 0){ + print("%s: fread timeout\n", cname(c)); + return -1; + } + if(f->reg[Fsts] & (Fcerr|Ael)) + return -1; + return f->reg32[Fdata] & 0xffff; } static int -fread(Ctlr *c, Flash *f, int ladr) +fread32(Ctlr *c, Flash *f, int ladr, u32int *data) { - u16int s; + u32int s; int timeout; delay(1); - if(fcycle(c, f) == -1) + s = f->reg32[Fsts/2]; + if((s&Fvalid) == 0) return -1; - f->reg[Fsts] |= Fdone; + f->reg32[Fsts/2] |= Fcerr | Ael; + for(timeout = 0; timeout < 10; timeout++){ + if((s&Scip) == 0) + goto done; + delay(1); + s = f->reg32[Fsts/2]; + } + return -1; +done: + f->reg32[Fsts/2] |= Fdone; f->reg32[Faddr] = ladr; /* setup flash control register */ - s = f->reg[Fctl] & ~0x3ff; - f->reg[Fctl] = s | 1<<8 | Fgo; /* 2 byte read */ + s = (f->reg32[Fctl/2] >> 16) & ~0x3ff; + f->reg32[Fctl/2] = (s | 3<<8 | Fgo) << 16; /* 4 byte read */ timeout = 1000; - while((f->reg[Fsts] & Fdone) == 0 && timeout--) + while((f->reg32[Fsts/2] & Fdone) == 0 && timeout--) microdelay(5); if(timeout < 0){ print("%s: fread timeout\n", cname(c)); return -1; } - if(f->reg[Fsts] & (Fcerr|Ael)) + if(f->reg32[Fsts/2] & (Fcerr|Ael)) return -1; - return f->reg32[Fdata] & 0xffff; + *data = f->reg32[Fdata]; + return 0; +} + +static int +fload32(Ctlr *c) +{ + int r, adr; + u16int sum; + u32int w; + Flash f; + + f.reg32 = &c->nic[0xe000/4]; + f.reg = nil; + f.base = 0; + f.lim = (((csr32r(c, 0xC) >> 1) & 0x1F) + 1) << 12; + r = f.lim >> 1; + if(fread32(c, &f, r + 0x24, &w) == -1 || (w & 0xC000) != 0x8000) + r = 0; + sum = 0; + for(adr = 0; adr < 0x20; adr++) { + if(fread32(c, &f, r + adr*4, &w) == -1) + return -1; + c->eeprom[adr*2+0] = w; + c->eeprom[adr*2+1] = w>>16; + sum += w & 0xFFFF; + sum += w >> 16; + } + return sum; } static int @@ -1605,6 +1663,10 @@ fload(Ctlr *c) void *va; Flash f; + memset(c->eeprom, 0xFF, sizeof(c->eeprom)); + if(c->pcidev->mem[1].bar == 0) + return fload32(c); /* i219 */ + va = vmap(c->pcidev->mem[1].bar & ~0x0f, c->pcidev->mem[1].size); if(va == nil) return -1; @@ -1617,16 +1679,51 @@ fload(Ctlr *c) r = f.base << 12; sum = 0; for(adr = 0; adr < 0x40; adr++) { - data = fread(c, &f, r + adr*2); + data = fread16(c, &f, r + adr*2); if(data == -1) - return -1; + goto out; c->eeprom[adr] = data; sum += data; } +out: vunmap(va, c->pcidev->mem[1].size); return sum; } +static int +invmload(Ctlr *c) +{ + int i, a; + u32int w; + + memset(c->eeprom, 0xFF, sizeof(c->eeprom)); + for(i=0; i<64; i++){ + w = csr32r(c, Invmdata0 + i*4); + switch(w & 7){ + case 0: // uninitialized structure + break; + case 1: // word auto load + a = (w & 0xFE00) >> 9; + if(a < nelem(c->eeprom)) + c->eeprom[a] = w >> 16; + continue; + case 2: // csr auto load + i++; + case 3: // phy auto load + continue; + case 4: // rsa key sha256 + i += 256/32; + case 5: // invalidated structure + continue; + default: + print("invm: %.2x %.8ux\n", i, w); + continue; + } + break; + } + return 0; +} + static void defaultea(Ctlr *ctlr, uchar *ra) { @@ -1656,17 +1753,22 @@ static int i82563reset(Ctlr *ctlr) { uchar *ra; - int i, r; + int i, r, flag; if(i82563detach(ctlr)) return -1; - if(cttab[ctlr->type].flag & Fload) + flag = cttab[ctlr->type].flag; + + if(ctlr->type == i210 && (csr32r(ctlr, Eec) & Flupd) == 0) + r = invmload(ctlr); + else if(flag & Fload) r = fload(ctlr); else r = eeload(ctlr); + if(r != 0 && r != 0xbaba){ print("%s: bad eeprom checksum - %#.4ux", cname(ctlr), r); - if(cttab[ctlr->type].flag & Fbadcsum) + if(flag & Fbadcsum) print("; ignored\n"); else { print("\n"); @@ -1685,14 +1787,16 @@ i82563reset(Ctlr *ctlr) memset(ctlr->mta, 0, sizeof(ctlr->mta)); for(i = 0; i < 128; i++) csr32w(ctlr, Mta + i*4, 0); - csr32w(ctlr, Fcal, 0x00C28001); - csr32w(ctlr, Fcah, 0x0100); - if((cttab[ctlr->type].flag & Fnofct) == 0) + if((flag & Fnofca) == 0){ + csr32w(ctlr, Fcal, 0x00C28001); + csr32w(ctlr, Fcah, 0x0100); + } + if((flag & Fnofct) == 0) csr32w(ctlr, Fct, 0x8808); csr32w(ctlr, Fcttv, 0x0100); csr32w(ctlr, Fcrtl, ctlr->fcrtl); csr32w(ctlr, Fcrth, ctlr->fcrth); - if(cttab[ctlr->type].flag & F75) + if(flag & F75) csr32w(ctlr, Eitr, 128<<2); /* 128 ¼ microsecond intervals */ return 0; } @@ -1858,6 +1962,18 @@ didtype(int d) case 0x1506: /* v */ case 0x150c: /* untested */ return i82583; + case 0x1533: /* i210-t1 */ + case 0x1534: /* i210 */ + case 0x1536: /* i210-fiber */ + case 0x1537: /* i210-backplane */ + case 0x1538: /* i210 sgmii */ + case 0x1539: /* i211 copper */ + case 0x157b: /* i210 copper flashless */ + case 0x157c: /* i210 serdes flashless */ + return i210; + case 0x153a: /* i217-lm */ + case 0x153b: /* i217-v */ + return i217; case 0x1559: /* i218-v */ case 0x155a: /* i218-lm */ case 0x15a0: /* i218-lm */ @@ -1865,12 +1981,26 @@ didtype(int d) case 0x15a2: /* i218-lm */ case 0x15a3: /* i218-v */ return i218; - case 0x151f: /* “powerville” eeprom-less */ - case 0x1521: /* copper */ - case 0x1522: /* fiber */ - case 0x1523: /* serdes */ - case 0x1524: /* sgmii */ - case 0x1546: /* untested */ + case 0x156f: /* i219-lm */ + case 0x15b7: /* i219-lm */ + case 0x1570: /* i219-v */ + case 0x15b8: /* i219-v */ + case 0x15b9: /* i219-lm */ + case 0x15d6: /* i219-v */ + case 0x15d7: /* i219-lm */ + case 0x15d8: /* i219-v */ + case 0x15e3: /* i219-lm */ + return i219; + case 0x151f: /* i350 “powerville” eeprom-less */ + case 0x1521: /* i350 copper */ + case 0x1522: /* i350 fiber */ + case 0x1523: /* i350 serdes */ + case 0x1524: /* i350 sgmii */ + case 0x1546: /* i350 DA4 (untested) */ + case 0x1f40: /* i354 backplane */ + case 0x1f41: /* i354 sgmii */ + case 0x1f42: /* i354 sgmii (c2000) */ + case 0x1f45: /* i354 backplane 2.5 */ return i350; } return -1; @@ -1904,7 +2034,7 @@ i82563pci(void) } ctlr->type = type; ctlr->pcidev = p; - ctlr->rbsz = cttab[type].mtu; + ctlr->rbsz = ROUND(cttab[type].mtu, 1024); ctlr->port = p->mem[0].bar & ~0x0F; if(i82563ctlrhead != nil) i82563ctlrtail->next = ctlr; @@ -1925,11 +2055,13 @@ setup(Ctlr *ctlr) print("%s: can't map 0x%lux\n", cname(ctlr), ctlr->port); return -1; } + pcienable(p); if(i82563reset(ctlr)){ + pcidisable(p); vunmap(ctlr->nic, p->mem[0].size); return -1; } - pcisetbme(ctlr->pcidev); + pcisetbme(p); return 0; } @@ -1968,7 +2100,7 @@ pnp(Ether *edev, int type) edev->irq = ctlr->pcidev->intl; edev->tbdf = ctlr->pcidev->tbdf; edev->mbps = 1000; - edev->maxmtu = ctlr->rbsz; + edev->maxmtu = cttab[ctlr->type].mtu; memmove(edev->ea, ctlr->ra, Eaddrlen); /* @@ -1976,7 +2108,6 @@ pnp(Ether *edev, int type) */ edev->attach = i82563attach; // edev->transmit = i82563transmit; - edev->interrupt = i82563interrupt; edev->ifstat = i82563ifstat; edev->ctl = i82563ctl; @@ -1985,6 +2116,8 @@ pnp(Ether *edev, int type) edev->shutdown = i82563shutdown; edev->multicast = i82563multicast; + intrenable(edev->irq, i82563interrupt, edev, edev->tbdf, edev->name); + return 0; } @@ -2078,12 +2211,30 @@ i82583pnp(Ether *e) return pnp(e, i82583); } +static int +i210pnp(Ether *e) +{ + return pnp(e, i210); +} + +static int +i217pnp(Ether *e) +{ + return pnp(e, i217); +} + static int i218pnp(Ether *e) { return pnp(e, i218); } +static int +i219pnp(Ether *e) +{ + return pnp(e, i219); +} + static int i350pnp(Ether *e) { @@ -2113,7 +2264,10 @@ ether82563link(void) addethercard("i82579", i82579pnp); addethercard("i82580", i82580pnp); addethercard("i82583", i82583pnp); + addethercard("i210", i210pnp); + addethercard("i217", i217pnp); addethercard("i218", i218pnp); + addethercard("i219", i219pnp); addethercard("i350", i350pnp); addethercard("igbepcie", anypnp); }