ref: cf4c3e7c5c354cefe62a02d6dd7ff5ad3bbe893f
parent: 69470de37d11d50d9f1b6a6d2af1869b08cd2e53
author: cinap_lenrek <cinap_lenrek@gmx.de>
date: Wed Jun 20 21:06:17 EDT 2012
ether82563: sync with erik (fixed 82579 eeprom checksum error, adds i350 support)
--- a/sys/src/9/pc/ether82563.c
+++ b/sys/src/9/pc/ether82563.c
@@ -1,5 +1,5 @@
/*
- * Intel 8256[367], 8257[1-9], 8258[03]
+ * Intel 8256[367], 8257[1-9], 8258[03], i350
* Gigabit Ethernet PCI-Express Controllers
* Coraid EtherDrive® hba
*/
@@ -34,6 +34,7 @@
Fcah = 0x002C, /* Flow Control Address High */
Fct = 0x0030, /* Flow Control Type */
Kumctrlsta = 0x0034, /* Kumeran Control and Status Register */
+ Connsw = 0x0034, /* copper / fiber switch control; 82575/82576 */
Vet = 0x0038, /* VLAN EtherType */
Fcttv = 0x0170, /* Flow Control Transmit Timer Value */
Txcw = 0x0178, /* Transmit Configuration Word */
@@ -124,6 +125,12 @@
GIOme = 1<<19, /* GIO Master Enable Status */
};
+enum { /* Eec */
+ Nvpres = 1<<8,
+ Autord = 1<<9,
+ Sec1val = 1<<22,
+};
+
enum { /* Eerd */
EEstart = 1<<0, /* Start Read */
EEdone = 1<<1, /* Read done */
@@ -131,10 +138,17 @@
enum { /* Ctrlext */
Eerst = 1<<13, /* EEPROM Reset */
- Linkmode = 3<<23, /* linkmode */
- Serdes = 3<<23, /* " serdes */
+ Linkmode = 3<<22, /* linkmode */
+ Internalphy = 0<<22, /* " internal phy (copper) */
+ Sgmii = 2<<22, /* " sgmii */
+ Serdes = 3<<22, /* " serdes */
};
+enum {
+ /* Connsw */
+ Enrgirq = 1<<2, /* interrupt on power detect (enrgsrc) */
+};
+
enum { /* EEPROM content offsets */
Ea = 0x00, /* Ethernet Address */
};
@@ -226,6 +240,7 @@
Mdac = 0x00000200, /* MDIO Access Completed */
Rxcfgset = 0x00000400, /* Receiving /C/ ordered sets */
Ack = 0x00020000, /* Receive ACK frame */
+ Omed = 1<<20, /* media change; pcs interface */
};
enum { /* Txcw */
@@ -308,12 +323,12 @@
};
typedef struct Rd { /* Receive Descriptor */
- uint addr[2];
- ushort length;
- ushort checksum;
+ u32int addr[2];
+ u16int length;
+ u16int checksum;
uchar status;
uchar errors;
- ushort special;
+ u16int special;
} Rd;
enum { /* Rd status */
@@ -337,9 +352,9 @@
};
typedef struct { /* Transmit Descriptor */
- uint addr[2]; /* Data */
- uint control;
- uint status;
+ u32int addr[2]; /* Data */
+ u32int control;
+ u32int status;
} Td;
enum { /* Tdesc control */
@@ -369,9 +384,10 @@
};
typedef struct {
- ushort *reg;
- ulong *reg32;
- int sz;
+ u16int *reg;
+ u32int *reg32;
+ uint base;
+ uint lim;
} Flash;
enum {
@@ -425,6 +441,7 @@
i82579,
i82580,
i82583,
+ i350,
Nctlrtype,
};
@@ -433,7 +450,8 @@
Fert = 1<<1,
F75 = 1<<2,
Fpba = 1<<3,
- Fflashea = 1<<4,
+ Fflashea= 1<<4,
+ F79phy = 1<<5,
};
typedef struct Ctlrtype Ctlrtype;
@@ -459,9 +477,10 @@
i82577m, 1514, Fload|Fert, "i82577",
i82578, 4096, Fload|Fert, "i82578",
i82578m, 1514, Fload|Fert, "i82578",
- i82579, 9018, Fload|Fert, "i82579",
- i82580, 9728, F75, "i82580",
+ i82579, 9018, Fload|Fert|F79phy, "i82579",
+ i82580, 9728, F75|F79phy, "i82580",
i82583, 1514, 0, "i82583",
+ i350, 9728, F75|F79phy, "i350",
};
typedef void (*Freefn)(Block*);
@@ -474,7 +493,7 @@
int active;
int type;
int pool;
- ushort eeprom[0x40];
+ u16int eeprom[0x40];
QLock alock; /* attach */
void *alloc; /* receive/transmit descriptors */
@@ -482,7 +501,7 @@
int ntd;
uint rbsz;
- int *nic;
+ u32int *nic;
Lock imlock;
int im; /* interrupt mask */
@@ -490,7 +509,7 @@
int lim;
QLock slock;
- uint statistics[Nstatistics];
+ u32int statistics[Nstatistics];
uint lsleep;
uint lintr;
uint rsleep;
@@ -504,7 +523,7 @@
uint phyerrata;
uchar ra[Eaddrlen]; /* receive address */
- ulong mta[128]; /* multicast table array */
+ u32int mta[128]; /* multicast table array */
Rendez rrendez;
int rim;
@@ -527,7 +546,7 @@
int fcrtl;
int fcrth;
- uint pba; /* packet buffer allocation */
+ u32int pba; /* packet buffer allocation */
};
typedef struct Rbpool Rbpool;
@@ -918,8 +937,9 @@
static void
i82563txinit(Ctlr *ctlr)
{
- uint i, r;
+ u32int r;
Block *b;
+ int i;
if(cttab[ctlr->type].flag & F75)
csr32w(ctlr, Tctl, 0x0F<<CtSHIFT | Psp);
@@ -1305,8 +1325,11 @@
for(;;){
phy = phyread(c, phyno, Phystat);
- if(phy == ~0)
+ if(phy == ~0){
+ phy = 0;
+ i = 3;
goto next;
+ }
i = (phy>>8) & 3;
a = phy & Ans;
if(a){
@@ -1313,12 +1336,12 @@
r = phyread(c, phyno, Phyctl);
phywrite(c, phyno, Phyctl, r | Ran | Ean);
}
- e->link = (phy & Link) != 0;
+next:
+ e->link = i != 3 && (phy & Link) != 0;
if(e->link == 0)
i = 3;
c->speeds[i]++;
e->mbps = speedtab[i];
-next:
c->lim = 0;
i82563im(c, Lsc);
c->lsleep++;
@@ -1340,8 +1363,11 @@
phywrite(c, 1, Phyier, phy | Lscie | Ancie | Spdie | Panie);
for(;;){
phy = phyread(c, 1, Physsr);
- if(phy == ~0)
+ if(phy == ~0){
+ phy = 0;
+ i = 3;
goto next;
+ }
i = (phy>>14) & 3;
switch(c->type){
default:
@@ -1363,6 +1389,7 @@
}
if(a)
phywrite(c, 1, Phyctl, phyread(c, 1, Phyctl) | Ran | Ean);
+next:
e->link = (phy & Rtlink) != 0;
if(e->link == 0)
i = 3;
@@ -1370,7 +1397,6 @@
e->mbps = speedtab[i];
if(c->type == i82563)
phyerrata(e, c);
-next:
c->lim = 0;
i82563im(c, Lsc);
c->lsleep++;
@@ -1388,6 +1414,8 @@
e = v;
c = e->ctlr;
+ if(c->type == i82575 || c->type == i82576)
+ csr32w(c, Connsw, Enrgirq);
for(;;){
phy = csr32r(c, Pcsstat);
e->link = phy & Linkok;
@@ -1399,7 +1427,7 @@
c->speeds[i]++;
e->mbps = speedtab[i];
c->lim = 0;
- i82563im(c, Lsc);
+ i82563im(c, Lsc | Omed);
c->lsleep++;
sleep(&c->lrendez, i82563lim, c);
}
@@ -1488,11 +1516,11 @@
}
snprint(name, sizeof name, "#l%dl", edev->ctlrno);
- if((csr32r(ctlr, Ctrlext) & Linkmode) == Serdes)
- kproc(name, pcslproc, edev); /* phy based serdes */
- else if(csr32r(ctlr, Status) & Tbimode)
+ if(csr32r(ctlr, Status) & Tbimode)
kproc(name, serdeslproc, edev); /* mac based serdes */
- else if(ctlr->type == i82579 || ctlr->type == i82580)
+ else if((csr32r(ctlr, Ctrlext) & Linkmode) == Serdes)
+ kproc(name, pcslproc, edev); /* phy based serdes */
+ else if(cttab[ctlr->type].flag & F79phy)
kproc(name, phyl79proc, edev);
else
kproc(name, phylproc, edev);
@@ -1522,9 +1550,9 @@
im = ctlr->im;
while(icr = csr32r(ctlr, Icr) & ctlr->im){
- if(icr & Lsc){
- im &= ~Lsc;
- ctlr->lim = icr & Lsc;
+ if(icr & (Lsc | Omed)){
+ im &= ~(Lsc | Omed);
+ ctlr->lim = icr & (Lsc | Omed);
wakeup(&ctlr->lrendez);
ctlr->lintr++;
}
@@ -1619,7 +1647,7 @@
i82563detach(edev->ctlr);
}
-static ushort
+static int
eeread(Ctlr *ctlr, int adr)
{
csr32w(ctlr, Eerd, EEstart | adr << 2);
@@ -1631,7 +1659,7 @@
static int
eeload(Ctlr *ctlr)
{
- ushort sum;
+ u16int sum;
int data, adr;
sum = 0;
@@ -1646,7 +1674,8 @@
static int
fcycle(Ctlr *, Flash *f)
{
- ushort s, i;
+ u16int s;
+ int i;
s = f->reg[Fsts];
if((s&Fvalid) == 0)
@@ -1664,7 +1693,7 @@
static int
fread(Ctlr *c, Flash *f, int ladr)
{
- ushort s;
+ u16int s;
delay(1);
if(fcycle(c, f) == -1)
@@ -1686,23 +1715,21 @@
static int
fload(Ctlr *c)
{
- ulong data, io, r, adr;
- ushort sum;
+ int data, r, adr;
+ u16int sum;
+ void *va;
Flash f;
- io = c->pcidev->mem[1].bar & ~0x0f;
- f.reg = vmap(io, c->pcidev->mem[1].size);
- if(f.reg == nil)
+ va = vmap(c->pcidev->mem[1].bar & ~0x0f, c->pcidev->mem[1].size);
+ if(va == nil)
return -1;
- f.reg32 = (ulong*)f.reg;
- f.sz = f.reg32[Bfpr];
- if(csr32r(c, Eec) & 1<<22){
- if(c->type == i82579)
- f.sz += 16; /* sector size: 64k */
- else
- f.sz += 1; /* sector size: 4k */
- }
- r = (f.sz & 0x1fff) << 12;
+ f.reg = va;
+ f.reg32 = va;
+ f.base = f.reg32[Bfpr] & 0x1fff;
+ f.lim = f.reg32[Bfpr]>>16 & 0x1fff;
+ if(csr32r(c, Eec) & Sec1val)
+ f.base += f.lim+1 - f.base >> 1;
+ r = f.base << 12;
sum = 0;
for(adr = 0; adr < 0x40; adr++) {
data = fread(c, &f, r + adr*2);
@@ -1711,7 +1738,7 @@
c->eeprom[adr] = data;
sum += data;
}
- vunmap(f.reg, c->pcidev->mem[1].size);
+ vunmap(va, c->pcidev->mem[1].size);
return sum;
}
@@ -1830,7 +1857,7 @@
csr32w(ctlr, Radv, v);
break;
case CMpause:
- csr32w(ctlr, Ctrl, csr32r(ctlr, Ctrl) ^ (1<<27 | 1<<28));
+ csr32w(ctlr, Ctrl, csr32r(ctlr, Ctrl) ^ (Rfce | Tfce));
break;
case CMan:
csr32w(ctlr, Ctrl, csr32r(ctlr, Ctrl) | Lrst | Phyrst);
@@ -1848,8 +1875,8 @@
switch(d){
case 0x1096:
case 0x10ba: /* “gilgal” */
- // case 0x1098: /* serdes; not seen */
- // case 0x10bb: /* serdes */
+ case 0x1098: /* serdes; not seen */
+ case 0x10bb: /* serdes */
return i82563;
case 0x1049: /* mm */
case 0x104a: /* dm */
@@ -1895,6 +1922,7 @@
case 0x10c9: /* copper */
case 0x10e6: /* fiber */
case 0x10e7: /* serdes; “kawela” */
+ case 0x150d: /* backplane */
return i82576;
case 0x10ea: /* lc “calpella”; aka pch lan */
return i82577;
@@ -1903,7 +1931,7 @@
case 0x10ef: /* dc “piketon” */
return i82578;
case 0x1502: /* lm */
- case 0x1503: /* v */
+ case 0x1503: /* v “lewisville” */
return i82579;
case 0x10f0: /* dm “king's creek” */
return i82578m;
@@ -1915,6 +1943,12 @@
return i82580;
case 0x1506: /* v */
return i82583;
+ case 0x151f: /* “powerville” eeprom-less */
+ case 0x1521: /* copper */
+ case 0x1522: /* fiber */
+ case 0x1523: /* serdes */
+ case 0x1524: /* sgmii */
+ return i350;
}
return -1;
}
@@ -2125,6 +2159,12 @@
return pnp(e, i82583);
}
+static int
+i350pnp(Ether *e)
+{
+ return pnp(e, i350);
+}
+
void
ether82563link(void)
{
@@ -2148,5 +2188,6 @@
addethercard("i82579", i82579pnp);
addethercard("i82580", i82580pnp);
addethercard("i82583", i82583pnp);
+ addethercard("i350", i350pnp);
addethercard("igbepcie", anypnp);
}
--
⑨