Browse Source

Plan 9 from Bell Labs 2005-04-28

David du Colombier 19 years ago
parent
commit
be9887e5fc
5 changed files with 293 additions and 203 deletions
  1. 8 2
      dist/replica/_plan9.db
  2. 8 8
      dist/replica/plan9.db
  3. 9 0
      dist/replica/plan9.log
  4. 143 106
      sys/src/9/pc/etherigbe.c
  5. 125 87
      sys/src/boot/pc/etherigbe.c

+ 8 - 2
dist/replica/_plan9.db

@@ -5880,7 +5880,7 @@ sys/src/9/pc/etherelnk3.c - 664 sys sys 1081706477 48724
 sys/src/9/pc/etherga620.c - 664 sys sys 1074785126 28754
 sys/src/9/pc/etherga620fw.h - 644 sys sys 1026847642 222295
 sys/src/9/pc/etherif.h - 664 sys sys 1088178711 961
-sys/src/9/pc/etherigbe.c - 664 sys sys 1113426389 43714
+sys/src/9/pc/etherigbe.c - 664 sys sys 1114632111 43779
 sys/src/9/pc/ethermii.c - 664 sys sys 1084331434 4612
 sys/src/9/pc/ethermii.h - 664 sys sys 1086873891 3258
 sys/src/9/pc/etherrhine.c - 664 sys sys 1081706478 13799
@@ -7023,7 +7023,7 @@ sys/src/boot/pc/etherec2t.c - 664 sys sys 1015007951 3598
 sys/src/boot/pc/etherelnk3.c - 664 sys sys 1034454878 44068
 sys/src/boot/pc/etherelnk3x.c - 664 sys sys 1015007951 24989
 sys/src/boot/pc/etherif.h - 664 sys sys 1107882190 1255
-sys/src/boot/pc/etherigbe.c - 664 sys sys 1096379796 39825
+sys/src/boot/pc/etherigbe.c - 664 sys sys 1114632096 40106
 sys/src/boot/pc/ethermii.c - 664 sys sys 1103641771 4413
 sys/src/boot/pc/ethermii.h - 664 sys sys 1071175087 3259
 sys/src/boot/pc/etherrhine.c - 664 sys sys 1071175087 12403
@@ -12974,3 +12974,9 @@ usr/glenda/lib/profile - 664 glenda glenda 1105128663 890
 usr/glenda/readme.acme - 664 glenda glenda 1019860628 4753
 usr/glenda/readme.rio - 664 glenda glenda 1019860628 6370
 usr/glenda/tmp - 20000000775 glenda glenda 1018802620 0
+386/9loaddebug - 775 sys sys 1114657876 310562
+386/9loadlitedebug - 775 sys sys 1114657877 199052
+386/9pc - 775 sys sys 1114657881 1834137
+386/9pccpu - 775 sys sys 1114657884 1488687
+386/9pcdisk - 775 sys sys 1114657888 2039839
+386/9pcf - 775 sys sys 1114657893 2382671

+ 8 - 8
dist/replica/plan9.db

@@ -1,15 +1,15 @@
 386 - 20000000775 sys sys 1010957353 0
 386/9load - 775 sys sys 1112757508 215872
-386/9loaddebug - 775 sys sys 1112757509 310076
+386/9loaddebug - 775 sys sys 1114657876 310562
 386/9loadlite - 775 sys sys 1112757508 135244
-386/9loadlitedebug - 775 sys sys 1112757509 199047
-386/9pc - 775 sys sys 1113448331 1833665
+386/9loadlitedebug - 775 sys sys 1114657877 199052
+386/9pc - 775 sys sys 1114657881 1834137
 386/9pc.gz - 664 sys sys 1112757510 643423
-386/9pccpu - 775 sys sys 1113448335 1488215
+386/9pccpu - 775 sys sys 1114657884 1488687
 386/9pccpu.gz - 664 sys sys 1112757511 529529
-386/9pcdisk - 775 sys sys 1113448340 2039367
+386/9pcdisk - 775 sys sys 1114657888 2039839
 386/9pcdisk.gz - 664 sys sys 1112757513 733576
-386/9pcf - 775 sys sys 1113448345 2382199
+386/9pcf - 775 sys sys 1114657893 2382671
 386/9pcf.gz - 664 sys sys 1112757515 886966
 386/9pxeload - 775 sys sys 1112757508 215872
 386/_9pcdisk.gz - 664 sys sys 1039764191 695837
@@ -5880,7 +5880,7 @@ sys/src/9/pc/etherelnk3.c - 664 sys sys 1081706477 48724
 sys/src/9/pc/etherga620.c - 664 sys sys 1074785126 28754
 sys/src/9/pc/etherga620fw.h - 644 sys sys 1026847642 222295
 sys/src/9/pc/etherif.h - 664 sys sys 1088178711 961
-sys/src/9/pc/etherigbe.c - 664 sys sys 1113426389 43714
+sys/src/9/pc/etherigbe.c - 664 sys sys 1114632111 43779
 sys/src/9/pc/ethermii.c - 664 sys sys 1084331434 4612
 sys/src/9/pc/ethermii.h - 664 sys sys 1086873891 3258
 sys/src/9/pc/etherrhine.c - 664 sys sys 1081706478 13799
@@ -7023,7 +7023,7 @@ sys/src/boot/pc/etherec2t.c - 664 sys sys 1015007951 3598
 sys/src/boot/pc/etherelnk3.c - 664 sys sys 1034454878 44068
 sys/src/boot/pc/etherelnk3x.c - 664 sys sys 1015007951 24989
 sys/src/boot/pc/etherif.h - 664 sys sys 1107882190 1255
-sys/src/boot/pc/etherigbe.c - 664 sys sys 1096379796 39825
+sys/src/boot/pc/etherigbe.c - 664 sys sys 1114632096 40106
 sys/src/boot/pc/ethermii.c - 664 sys sys 1103641771 4413
 sys/src/boot/pc/ethermii.h - 664 sys sys 1071175087 3259
 sys/src/boot/pc/etherrhine.c - 664 sys sys 1071175087 12403

+ 9 - 0
dist/replica/plan9.log

@@ -14810,3 +14810,12 @@
 1114486320 13 c 386/bin/tprof - 775 sys sys 1114484873 289115
 1114486320 14 c 386/lib/libmach.a - 664 sys sys 1114484874 755168
 1114525929 0 a sys/lib/acid/sparc64 - 664 sys sys 1114524607 5441
+1114624949 0 c sys/src/9/pc/etherigbe.c - 664 sys sys 1114623712 43793
+1114632150 0 c sys/src/9/pc/etherigbe.c - 664 sys sys 1114632111 43779
+1114632150 1 c sys/src/boot/pc/etherigbe.c - 664 sys sys 1114632096 40106
+1114659155 0 c 386/9loaddebug - 775 sys sys 1114657876 310562
+1114659155 1 c 386/9loadlitedebug - 775 sys sys 1114657877 199052
+1114659155 2 c 386/9pc - 775 sys sys 1114657881 1834137
+1114659155 3 c 386/9pccpu - 775 sys sys 1114657884 1488687
+1114659155 4 c 386/9pcdisk - 775 sys sys 1114657888 2039839
+1114659155 5 c 386/9pcf - 775 sys sys 1114657893 2382671

+ 143 - 106
sys/src/9/pc/etherigbe.c

@@ -4,8 +4,9 @@
  *	82543GC	Intel PRO/1000 T
  *	82544EI Intel PRO/1000 XT
  *	82540EM Intel PRO/1000 MT
- *	82541GI (unfinished)
- *
+ *	82541GI
+ *	82547GI
+ *	82546GB
  * To Do:
  *	finish autonegotiation code;
  *	integrate fiber stuff back in (this ONLY handles
@@ -26,6 +27,18 @@
 #include "etherif.h"
 #include "ethermii.h"
 
+enum {
+	i82542     = (0x1000<<16)|0x8086,
+	i82543gc   = (0x1004<<16)|0x8086,
+	i82544ei   = (0x1008<<16)|0x8086,
+	i82547ei   = (0x1019<<16)|0x8086,
+	i82540em   = (0x100E<<16)|0x8086,
+	i82540eplp = (0x101E<<16)|0x8086,
+	i82547gi   = (0x1075<<16)|0x8086,
+	i82541gi   = (0x1076<<16)|0x8086,
+	i82546gb   = (0x1079<<16)|0x8086,
+};
+
 enum {
 	Ctrl		= 0x00000000,	/* Device Control */
 	Status		= 0x00000008,	/* Device Status */
@@ -361,7 +374,7 @@ enum {					/* Rd errors */
 };
 
 typedef struct Td Td;
-struct Td {			/* Transmit Descriptor */
+struct Td {				/* Transmit Descriptor */
 	union {
 		uint	addr[2];	/* Data */
 		struct {		/* Context */
@@ -613,6 +626,7 @@ igbeifstat(Ether* edev, void* a, long n, ulong offset)
 	l += snprint(p+l, 2*READSTR-l, "ixcs: %ud %ud %ud\n",
 		ctlr->ixsm, ctlr->ipcs, ctlr->tcpcs);
 	l += snprint(p+l, 2*READSTR-l, "rdtr: %ud\n", ctlr->rdtr);
+	l += snprint(p+l, 2*READSTR-l, "Ctrlext: %08x\n", csr32r(ctlr, Ctrlext));
 
 	l += snprint(p+l, 2*READSTR-l, "eeprom:");
 	for(i = 0; i < 0x40; i++){
@@ -788,14 +802,13 @@ igbelproc(void* arg)
 		if(miistatus(ctlr->mii) < 0)
 			//continue;
 			goto enable;
-print("lproc status ok\n");
 
 		phy = ctlr->mii->curphy;
 		ctrl = csr32r(ctlr, Ctrl);
 
 		switch(ctlr->id){
-		case (0x1004<<16)|0x8086:	/* 82543GC */
-		case (0x1008<<16)|0x8086:	/* 82544EI */
+		case i82543gc:
+		case i82544ei:
 		default:
 			if(!(ctrl & Asde)){
 				ctrl &= ~(SspeedMASK|Ilos|Fd);
@@ -808,9 +821,11 @@ print("lproc status ok\n");
 					ctrl |= Fd;
 			}
 			break;
-		case (0x100E<<16)|0x8086:	/* 82540EM */
-		case (0x101E<<16)|0x8086:	/* 82540EPLP */
-//check		case (0x1076<<16)|0x8086:	/* 82541GI */
+
+		case i82540em:
+		case i82540eplp:
+		case i82547gi:
+		case i82541gi:
 			break;
 		}
 
@@ -833,7 +848,6 @@ print("lproc status ok\n");
 		if(phy->tfc)
 			ctrl |= Tfce;
 		csr32w(ctlr, Ctrl, ctrl);
-print("ctrl %8.8uX\n", ctrl);
 
 enable:
 		ctlr->lim = 0;
@@ -855,11 +869,14 @@ igbetxinit(Ctlr* ctlr)
 	default:
 		r = 6;
 		break;
-	case (0x1004<<16)|0x8086:	/* 82543GC */
-	case (0x1008<<16)|0x8086:	/* 82544EI */
-	case (0x100E<<16)|0x8086:	/* 82440EM */
-	case (0x101E<<16)|0x8086:	/* 82540EPLP */
-//check	case (0x1076<<16)|0x8086:	/* 82541GI */
+	case i82543gc:
+	case i82544ei:
+	case i82547ei:
+	case i82540em:
+	case i82540eplp:
+	case i82541gi:
+	case i82546gb:
+	case i82547gi:
 		r = 8;
 		break;
 	}
@@ -890,9 +907,11 @@ igbetxinit(Ctlr* ctlr)
 	switch(ctlr->id){
 	default:
 		break;
-	case (0x100E<<16)|0x8086:	/* 82540EM */
-	case (0x101E<<16)|0x8086:	/* 82540EPLP */
-//check	case (0x1076<<16)|0x8086:	/* 82541GI */
+	case i82540em:
+	case i82540eplp:
+	case i82547gi:
+	case i82546gb:
+	case i82541gi:
 		r = csr32r(ctlr, Txdctl);
 		r &= ~WthreshMASK;
 		r |= Gran|(4<<WthreshSHIFT);
@@ -1018,9 +1037,11 @@ igberxinit(Ctlr* ctlr)
 	igbereplenish(ctlr);
 
 	switch(ctlr->id){
-	case (0x100E<<16)|0x8086:		/* 82540EM */
-	case (0x101E<<16)|0x8086:		/* 82540EPLP */
-//check	case (0x1076<<16)|0x8086:		/* 82541GI */
+	case i82540em:
+	case i82540eplp:
+	case i82541gi:
+	case i82546gb:
+	case i82547gi:
 		csr32w(ctlr, Radv, 64);
 		break;
 	}
@@ -1379,7 +1400,7 @@ igbemii(Ctlr* ctlr)
 	ctrl |= Slu;
 
 	switch(ctlr->id){
-	case (0x1004<<16)|0x8086:		/* 82543GC */
+	case i82543gc:
 		ctrl |= Frcdplx|Frcspd;
 		csr32w(ctlr, Ctrl, ctrl);
 
@@ -1406,10 +1427,13 @@ igbemii(Ctlr* ctlr)
 		ctlr->mii->mir = i82543miimir;
 		ctlr->mii->miw = i82543miimiw;
 		break;
-	case (0x1008<<16)|0x8086:		/* 82544EI*/
-	case (0x100E<<16)|0x8086:		/* 82540EM */
-	case (0x101E<<16)|0x8086:		/* 82540EPLP */
-//check	case (0x1076<<16)|0x8086:		/* 82541GI */
+	case i82544ei:
+	case i82547ei:
+	case i82540em:
+	case i82540eplp:
+	case i82547gi:
+	case i82541gi:
+	case i82546gb:
 		ctrl &= ~(Frcdplx|Frcspd);
 		csr32w(ctlr, Ctrl, ctrl);
 		ctlr->mii->mir = igbemiimir;
@@ -1435,27 +1459,28 @@ igbemii(Ctlr* ctlr)
 	 * Set appropriate values then reset the PHY to have
 	 * changes noted.
 	 */
-	r = miimir(ctlr->mii, 0x10);
-	r |= 0x0800;				/* assert CRS on Tx */
-	r |= 0x0060;				/* auto-crossover all speeds */
-	r |= 0x0002;				/* polarity reversal enabled */
-	miimiw(ctlr->mii, 0x10, r);
-
-	r = miimir(ctlr->mii, 0x14);
-	r |= 0x0070;				/* +25MHz clock */
-	r &= ~0x0F00;
-	r |= 0x0100;				/* 1x downshift */
-	miimiw(ctlr->mii, 0x14, r);
-
-	miireset(ctlr->mii);
-
-	p = 0;
-	if(ctlr->txcw & TxcwPs)
-		p |= AnaP;
-	if(ctlr->txcw & TxcwAs)
-		p |= AnaAP;
-	miiane(ctlr->mii, ~0, p, ~0);
+	if (ctlr->id != i82547gi && ctlr->id != i82541gi && ctlr->id != i82546gb) {
+		r = miimir(ctlr->mii, 16);
+		r |= 0x0800;			/* assert CRS on Tx */
+		r |= 0x0060;			/* auto-crossover all speeds */
+		r |= 0x0002;			/* polarity reversal enabled */
+		miimiw(ctlr->mii, 16, r);
+	
+		r = miimir(ctlr->mii, 20);
+		r |= 0x0070;			/* +25MHz clock */
+		r &= ~0x0F00;
+		r |= 0x0100;			/* 1x downshift */
+		miimiw(ctlr->mii, 20, r);
+	
+		miireset(ctlr->mii);
+		p = 0;
+		if(ctlr->txcw & TxcwPs)
+			p |= AnaP;
+		if(ctlr->txcw & TxcwAs)
+			p |= AnaAP;
+		miiane(ctlr->mii, ~0, p, ~0);
 
+	}
 	return 0;
 }
 
@@ -1558,9 +1583,11 @@ at93c46r(Ctlr* ctlr)
 	default:
 		areq = 0;
 		break;
-	case (0x100E<<16)|0x8086:		/* 82540EM */
-	case (0x101E<<16)|0x8086:		/* 82540EPLP */
-//check	case (0x1076<<16)|0x8086:		/* 82541GI */
+	case i82540em:
+	case i82540eplp:
+	case i82541gi:
+	case i82547gi:
+	case i82546gb:
 		areq = 1;
 		csr32w(ctlr, Eecd, eecd|Areq);
 		for(i = 0; i < 1000; i++){
@@ -1623,8 +1650,8 @@ igbedetach(Ctlr* ctlr)
 	}
 	if(csr32r(ctlr, Ctrl) & Devrst)
 		return -1;
-
-	csr32w(ctlr, Ctrlext, Eerst);
+	r = csr32r(ctlr, Ctrlext);
+	csr32w(ctlr, Ctrlext, r|Eerst);
 	delay(1);
 	for(timeo = 0; timeo < 1000; timeo++){
 		if(!(csr32r(ctlr, Ctrlext) & Eerst))
@@ -1637,9 +1664,11 @@ igbedetach(Ctlr* ctlr)
 	switch(ctlr->id){
 	default:
 		break;
-	case (0x100E<<16)|0x8086:		/* 82540EM */
-	case (0x101E<<16)|0x8086:		/* 82540EPLP */
-//check	case (0x1076<<16)|0x8086:		/* 82541GI */
+	case i82540em:
+	case i82540eplp:
+	case i82541gi:
+	case i82547gi:
+	case i82546gb:
 		r = csr32r(ctlr, Manc);
 		r &= ~Arpen;
 		csr32w(ctlr, Manc, r);
@@ -1687,6 +1716,8 @@ igbereset(Ctlr* ctlr)
 	 * There are 16 addresses. The first should be the MAC address.
 	 * The others are cleared and not marked valid (MS bit of Rah).
 	 */
+	if (ctlr->id == i82546gb && BUSFNO(ctlr->pcidev->tbdf) == 1)
+		ctlr->eeprom[Ea+2] += 0x100;	// second interface
 	for(i = Ea; i < Eaddrlen/2; i++){
 		ctlr->ra[2*i] = ctlr->eeprom[i];
 		ctlr->ra[2*i+1] = ctlr->eeprom[i]>>8;
@@ -1712,56 +1743,59 @@ igbereset(Ctlr* ctlr)
 	 * Just in case the Eerst didn't load the defaults
 	 * (doesn't appear to fully on the 8243GC), do it manually.
 	 */
-	txcw = csr32r(ctlr, Txcw);
-	txcw &= ~(TxcwAne|TxcwPauseMASK|TxcwFd);
-	ctrl = csr32r(ctlr, Ctrl);
-	ctrl &= ~(SwdpioloMASK|Frcspd|Ilos|Lrst|Fd);
-
-	if(ctlr->eeprom[Icw1] & 0x0400){
-		ctrl |= Fd;
-		txcw |= TxcwFd;
-	}
-	if(ctlr->eeprom[Icw1] & 0x0200)
-		ctrl |= Lrst;
-	if(ctlr->eeprom[Icw1] & 0x0010)
-		ctrl |= Ilos;
-	if(ctlr->eeprom[Icw1] & 0x0800)
-		ctrl |= Frcspd;
-	swdpio = (ctlr->eeprom[Icw1] & 0x01E0)>>5;
-	ctrl |= swdpio<<SwdpioloSHIFT;
-	csr32w(ctlr, Ctrl, ctrl);
+	if (ctlr->id == i82543gc) {	// 82543
+		txcw = csr32r(ctlr, Txcw);
+		txcw &= ~(TxcwAne|TxcwPauseMASK|TxcwFd);
+		ctrl = csr32r(ctlr, Ctrl);
+		ctrl &= ~(SwdpioloMASK|Frcspd|Ilos|Lrst|Fd);
 	
-	ctrl = csr32r(ctlr, Ctrlext);
-	ctrl &= ~(Ips|SwdpiohiMASK);
-	swdpio = (ctlr->eeprom[Icw2] & 0x00F0)>>4;
-	if(ctlr->eeprom[Icw1] & 0x1000)
-		ctrl |= Ips;
-	ctrl |= swdpio<<SwdpiohiSHIFT;
-	csr32w(ctlr, Ctrlext, ctrl);
-
-	if(ctlr->eeprom[Icw2] & 0x0800)
-		txcw |= TxcwAne;
-	pause = (ctlr->eeprom[Icw2] & 0x3000)>>12;
-	txcw |= pause<<TxcwPauseSHIFT;
-	switch(pause){
-	default:
-		ctlr->fcrtl = 0x00002000;
-		ctlr->fcrth = 0x00004000;
-		txcw |= TxcwAs|TxcwPs;
-		break;
-	case 0:
-		ctlr->fcrtl = 0x00002000;
-		ctlr->fcrth = 0x00004000;
-		break;
-	case 2:
-		ctlr->fcrtl = 0;
-		ctlr->fcrth = 0;
-		txcw |= TxcwAs;
-		break;
+		if(ctlr->eeprom[Icw1] & 0x0400){
+			ctrl |= Fd;
+			txcw |= TxcwFd;
+		}
+		if(ctlr->eeprom[Icw1] & 0x0200)
+			ctrl |= Lrst;
+		if(ctlr->eeprom[Icw1] & 0x0010)
+			ctrl |= Ilos;
+		if(ctlr->eeprom[Icw1] & 0x0800)
+			ctrl |= Frcspd;
+		swdpio = (ctlr->eeprom[Icw1] & 0x01E0)>>5;
+		ctrl |= swdpio<<SwdpioloSHIFT;
+		csr32w(ctlr, Ctrl, ctrl);
+		
+		ctrl = csr32r(ctlr, Ctrlext);
+		ctrl &= ~(Ips|SwdpiohiMASK);
+		swdpio = (ctlr->eeprom[Icw2] & 0x00F0)>>4;
+		if(ctlr->eeprom[Icw1] & 0x1000)
+			ctrl |= Ips;
+		ctrl |= swdpio<<SwdpiohiSHIFT;
+		csr32w(ctlr, Ctrlext, ctrl);
+	
+		if(ctlr->eeprom[Icw2] & 0x0800)
+			txcw |= TxcwAne;
+		pause = (ctlr->eeprom[Icw2] & 0x3000)>>12;
+		txcw |= pause<<TxcwPauseSHIFT;
+		switch(pause){
+		default:
+			ctlr->fcrtl = 0x00002000;
+			ctlr->fcrth = 0x00004000;
+			txcw |= TxcwAs|TxcwPs;
+			break;
+		case 0:
+			ctlr->fcrtl = 0x00002000;
+			ctlr->fcrth = 0x00004000;
+			break;
+		case 2:
+			ctlr->fcrtl = 0;
+			ctlr->fcrth = 0;
+			txcw |= TxcwAs;
+			break;
+		}
+		ctlr->txcw = txcw;
+		csr32w(ctlr, Txcw, txcw);
 	}
-	ctlr->txcw = txcw;
-	csr32w(ctlr, Txcw, txcw);
 
+		
 	/*
 	 * Flow control - values from the datasheet.
 	 */
@@ -1794,11 +1828,14 @@ igbepci(void)
 		switch((p->did<<16)|p->vid){
 		default:
 			continue;
-		case (0x1004<<16)|0x8086:	/* 82543GC - copper */
-		case (0x1008<<16)|0x8086:	/* 82544EI - copper */
-		case (0x100E<<16)|0x8086:	/* 82540EM - copper */
-		case (0x101E<<16)|0x8086:	/* 82540EPLP - copper */
-		case (0x1076<<16)|0x8086:	/* 82541GI */
+		case i82543gc:
+		case i82544ei:
+		case i82547ei:
+		case i82540em:
+		case i82540eplp:
+		case i82547gi:
+		case i82541gi:
+		case i82546gb:
 			break;
 		}
 

+ 125 - 87
sys/src/boot/pc/etherigbe.c

@@ -30,6 +30,18 @@
 #include "etherif.h"
 #include "ethermii.h"
 
+enum {
+	i82542     = (0x1000<<16)|0x8086,
+	i82543gc   = (0x1004<<16)|0x8086,
+	i82544ei   = (0x1008<<16)|0x8086,
+	i82547ei   = (0x1019<<16)|0x8086,
+	i82540em   = (0x100E<<16)|0x8086,
+	i82540eplp = (0x101E<<16)|0x8086,
+	i82547gi   = (0x1075<<16)|0x8086,
+	i82541gi   = (0x1076<<16)|0x8086,
+	i82546gb   = (0x1079<<16)|0x8086,
+};
+
 /* compatibility with cpu kernels */
 #define iallocb allocb
 #ifndef CACHELINESZ
@@ -828,8 +840,11 @@ igbeinit(Ether* edev)
 	 */
 	csr32w(ctlr, Rdtr, 0);
 	switch(ctlr->id){
-	case (0x100E<<16)|0x8086:		/* 82540EM */
-	case (0x101E<<16)|0x8086:		/* 82540EPLP */
+	case i82540em:
+	case i82540eplp:
+	case i82541gi:
+	case i82546gb:
+	case i82547gi:
 		csr32w(ctlr, Radv, 64);
 		break;
 	}
@@ -862,11 +877,14 @@ igbeinit(Ether* edev)
 	default:
 		r = 6;
 		break;
-	case (0x1004<<16)|0x8086:	/* 82543GC */
-	case (0x1008<<16)|0x8086:	/* 82544EI */
-	case (0x1019<<16)|0x8086:	/* 82547EI */
-	case (0x100E<<16)|0x8086:	/* 82440EM */
-	case (0x101E<<16)|0x8086:	/* 82540EPLP */
+	case i82543gc:
+	case i82544ei:
+	case i82547ei:
+	case i82540em:
+	case i82540eplp:
+	case i82541gi:
+	case i82546gb:
+	case i82547gi:
 		r = 8;
 		break;
 	}
@@ -898,8 +916,11 @@ igbeinit(Ether* edev)
 	switch(ctlr->id){
 	default:
 		break;
-	case (0x100E<<16)|0x8086:	/* 82540EM */
-	case (0x101E<<16)|0x8086:	/* 82540EPLP */
+	case i82540em:
+	case i82540eplp:
+	case i82547gi:
+	case i82546gb:
+	case i82541gi:
 		r = csr32r(ctlr, Txdctl);
 		r &= ~WthreshMASK;
 		r |= Gran|(4<<WthreshSHIFT);
@@ -1095,7 +1116,7 @@ igbemii(Ctlr* ctlr)
 	ctrl |= Slu;
 
 	switch(ctlr->id){
-	case (0x1004<<16)|0x8086:		/* 82543GC */
+	case i82543gc:
 		ctrl |= Frcdplx|Frcspd;
 		csr32w(ctlr, Ctrl, ctrl);
 
@@ -1122,10 +1143,13 @@ igbemii(Ctlr* ctlr)
 		ctlr->mii->mir = i82543miimir;
 		ctlr->mii->miw = i82543miimiw;
 		break;
-	case (0x1008<<16)|0x8086:		/* 82544EI*/
-	case (0x1019<<16)|0x8086:		/* 82547EI*/
-	case (0x100E<<16)|0x8086:		/* 82540EM */
-	case (0x101E<<16)|0x8086:		/* 82540EPLP */
+	case i82544ei:
+	case i82547ei:
+	case i82540em:
+	case i82540eplp:
+	case i82547gi:
+	case i82541gi:
+	case i82546gb:
 		ctrl &= ~(Frcdplx|Frcspd);
 		csr32w(ctlr, Ctrl, ctrl);
 		ctlr->mii->mir = igbemiimir;
@@ -1153,20 +1177,21 @@ igbemii(Ctlr* ctlr)
 	 * Set appropriate values then reset the PHY to have
 	 * changes noted.
 	 */
-	r = miimir(ctlr->mii, 0x10);
-	r |= 0x0800;				/* assert CRS on Tx */
-	r |= 0x0060;				/* auto-crossover all speeds */
-	r |= 0x0002;				/* polarity reversal enabled */
-	miimiw(ctlr->mii, 0x10, r);
-
-	r = miimir(ctlr->mii, 0x14);
-	r |= 0x0070;				/* +25MHz clock */
-	r &= ~0x0F00;
-	r |= 0x0100;				/* 1x downshift */
-	miimiw(ctlr->mii, 0x14, r);
-
-	miireset(ctlr->mii);
-
+	if (ctlr->id != i82547gi && ctlr->id != i82541gi && ctlr->id != i82546gb) {
+		r = miimir(ctlr->mii, 16);
+		r |= 0x0800;				/* assert CRS on Tx */
+		r |= 0x0060;			/* auto-crossover all speeds */
+		r |= 0x0002;			/* polarity reversal enabled */
+		miimiw(ctlr->mii, 16, r);
+	
+		r = miimir(ctlr->mii, 20);
+		r |= 0x0070;			/* +25MHz clock */
+		r &= ~0x0F00;
+		r |= 0x0100;			/* 1x downshift */
+		miimiw(ctlr->mii, 20, r);
+	
+		miireset(ctlr->mii);
+	}
 	p = 0;
 	if(ctlr->txcw & TxcwPs)
 		p |= AnaP;
@@ -1276,8 +1301,11 @@ at93c46r(Ctlr* ctlr)
 	default:
 		areq = 0;
 		break;
-	case (0x100E<<16)|0x8086:		/* 82540EM */
-	case (0x101E<<16)|0x8086:		/* 82540EPLP */
+	case i82540em:
+	case i82540eplp:
+	case i82541gi:
+	case i82547gi:
+	case i82546gb:
 		areq = 1;
 		csr32w(ctlr, Eecd, eecd|Areq);
 		for(i = 0; i < 1000; i++){
@@ -1337,7 +1365,7 @@ detach(Ctlr *ctlr)
 	while(csr32r(ctlr, Ctrl) & Devrst)
 		;
 
-	csr32w(ctlr, Ctrlext, Eerst);
+	csr32w(ctlr, Ctrlext, Eerst | csr32r(ctlr, Ctrlext));
 	delay(1);
 	while(csr32r(ctlr, Ctrlext) & Eerst)
 		;
@@ -1345,8 +1373,11 @@ detach(Ctlr *ctlr)
 	switch(ctlr->id){
 	default:
 		break;
-	case (0x100E<<16)|0x8086:		/* 82540EM */
-	case (0x101E<<16)|0x8086:		/* 82540EPLP */
+	case i82540em:
+	case i82540eplp:
+	case i82541gi:
+	case i82547gi:
+	case i82546gb:
 		r = csr32r(ctlr, Manc);
 		r &= ~Arpen;
 		csr32w(ctlr, Manc, r);
@@ -1395,6 +1426,8 @@ igbereset(Ctlr* ctlr)
 	 * There are 16 addresses. The first should be the MAC address.
 	 * The others are cleared and not marked valid (MS bit of Rah).
 	 */
+	if (ctlr->id == i82546gb && BUSFNO(ctlr->pcidev->tbdf) == 1)
+		ctlr->eeprom[Ea+2] += 0x100;	// second interface
 	for(i = Ea; i < Eaddrlen/2; i++){
 		ctlr->ra[2*i] = ctlr->eeprom[i];
 		ctlr->ra[2*i+1] = ctlr->eeprom[i]>>8;
@@ -1420,56 +1453,57 @@ igbereset(Ctlr* ctlr)
 	 * Just in case the Eerst didn't load the defaults
 	 * (doesn't appear to fully on the 8243GC), do it manually.
 	 */
-	txcw = csr32r(ctlr, Txcw);
-	txcw &= ~(TxcwAne|TxcwPauseMASK|TxcwFd);
-	ctrl = csr32r(ctlr, Ctrl);
-	ctrl &= ~(SwdpioloMASK|Frcspd|Ilos|Lrst|Fd);
-
-	if(ctlr->eeprom[Icw1] & 0x0400){
-		ctrl |= Fd;
-		txcw |= TxcwFd;
-	}
-	if(ctlr->eeprom[Icw1] & 0x0200)
-		ctrl |= Lrst;
-	if(ctlr->eeprom[Icw1] & 0x0010)
-		ctrl |= Ilos;
-	if(ctlr->eeprom[Icw1] & 0x0800)
-		ctrl |= Frcspd;
-	swdpio = (ctlr->eeprom[Icw1] & 0x01E0)>>5;
-	ctrl |= swdpio<<SwdpioloSHIFT;
-	csr32w(ctlr, Ctrl, ctrl);
+	if (ctlr->id == i82543gc) {
+		txcw = csr32r(ctlr, Txcw);
+		txcw &= ~(TxcwAne|TxcwPauseMASK|TxcwFd);
+		ctrl = csr32r(ctlr, Ctrl);
+		ctrl &= ~(SwdpioloMASK|Frcspd|Ilos|Lrst|Fd);
+	
+		if(ctlr->eeprom[Icw1] & 0x0400){
+			ctrl |= Fd;
+			txcw |= TxcwFd;
+		}
+		if(ctlr->eeprom[Icw1] & 0x0200)
+			ctrl |= Lrst;
+		if(ctlr->eeprom[Icw1] & 0x0010)
+			ctrl |= Ilos;
+		if(ctlr->eeprom[Icw1] & 0x0800)
+			ctrl |= Frcspd;
+		swdpio = (ctlr->eeprom[Icw1] & 0x01E0)>>5;
+		ctrl |= swdpio<<SwdpioloSHIFT;
+		csr32w(ctlr, Ctrl, ctrl);
 
-	ctrl = csr32r(ctlr, Ctrlext);
-	ctrl &= ~(Ips|SwdpiohiMASK);
-	swdpio = (ctlr->eeprom[Icw2] & 0x00F0)>>4;
-	if(ctlr->eeprom[Icw1] & 0x1000)
-		ctrl |= Ips;
-	ctrl |= swdpio<<SwdpiohiSHIFT;
-	csr32w(ctlr, Ctrlext, ctrl);
-
-	if(ctlr->eeprom[Icw2] & 0x0800)
-		txcw |= TxcwAne;
-	pause = (ctlr->eeprom[Icw2] & 0x3000)>>12;
-	txcw |= pause<<TxcwPauseSHIFT;
-	switch(pause){
-	default:
-		ctlr->fcrtl = 0x00002000;
-		ctlr->fcrth = 0x00004000;
-		txcw |= TxcwAs|TxcwPs;
-		break;
-	case 0:
-		ctlr->fcrtl = 0x00002000;
-		ctlr->fcrth = 0x00004000;
-		break;
-	case 2:
-		ctlr->fcrtl = 0;
-		ctlr->fcrth = 0;
-		txcw |= TxcwAs;
-		break;
+		ctrl = csr32r(ctlr, Ctrlext);
+		ctrl &= ~(Ips|SwdpiohiMASK);
+		swdpio = (ctlr->eeprom[Icw2] & 0x00F0)>>4;
+		if(ctlr->eeprom[Icw1] & 0x1000)
+			ctrl |= Ips;
+		ctrl |= swdpio<<SwdpiohiSHIFT;
+		csr32w(ctlr, Ctrlext, ctrl);
+	
+		if(ctlr->eeprom[Icw2] & 0x0800)
+			txcw |= TxcwAne;
+		pause = (ctlr->eeprom[Icw2] & 0x3000)>>12;
+		txcw |= pause<<TxcwPauseSHIFT;
+		switch(pause){
+		default:
+			ctlr->fcrtl = 0x00002000;
+			ctlr->fcrth = 0x00004000;
+			txcw |= TxcwAs|TxcwPs;
+			break;
+		case 0:
+			ctlr->fcrtl = 0x00002000;
+			ctlr->fcrth = 0x00004000;
+			break;
+		case 2:
+			ctlr->fcrtl = 0;
+			ctlr->fcrth = 0;
+			txcw |= TxcwAs;
+			break;
+		}
+		ctlr->txcw = txcw;
+		csr32w(ctlr, Txcw, txcw);
 	}
-	ctlr->txcw = txcw;
-	csr32w(ctlr, Txcw, txcw);
-
 	/*
 	 * Flow control - values from the datasheet.
 	 */
@@ -1514,16 +1548,20 @@ igbepci(void)
 			continue;
 
 		switch((p->did<<16)|p->vid){
-		case (0x1000<<16)|0x8086:	/* LSI L2A1157 (82542) */
+		case i82542:
 		default:
 			continue;
+
 		case (0x1001<<16)|0x8086:	/* Intel PRO/1000 F */
 			break;
-		case (0x1004<<16)|0x8086:	/* 82543GC - copper (PRO/1000 T) */
-		case (0x1008<<16)|0x8086:	/* 82544EI - copper */
-		case (0x1019<<16)|0x8086:	/* 82547EI - copper */
-		case (0x100E<<16)|0x8086:	/* 82540EM - copper */
-		case (0x101E<<16)|0x8086:	/* 82540EPLP - copper */
+		case i82543gc:
+		case i82544ei:
+		case i82547ei:
+		case i82540em:
+		case i82540eplp:
+		case i82547gi:
+		case i82541gi:
+		case i82546gb:
 			break;
 		}