git: plan9front

Download patch

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);
 }
--