Browse Source

Plan 9 from Bell Labs 2006-07-20

David du Colombier 14 years ago
parent
commit
4ad2bb7e04

+ 7 - 7
dist/replica/_plan9.db

@@ -1,8 +1,8 @@
 386 - 20000000775 sys sys 1010957353 0
 386/9load - 775 sys sys 1146095338 217880
-386/9loaddebug - 775 sys sys 1148576273 313752
+386/9loaddebug - 775 sys sys 1153337893 313752
 386/9loadlite - 775 sys sys 1146095338 136160
-386/9loadlitedebug - 775 sys sys 1148576273 201058
+386/9loadlitedebug - 775 sys sys 1153337893 201058
 386/9pc - 775 sys sys 1143137104 1913157
 386/9pc.gz - 664 sys sys 1141258202 668936
 386/9pccpu - 775 sys sys 1141258205 1583315
@@ -9015,7 +9015,7 @@ sys/src/boot/pc/dat.h - 664 sys sys 1144961189 3597
 sys/src/boot/pc/devfloppy.c - 664 sys sys 1032215913 15505
 sys/src/boot/pc/devfloppy.h - 664 sys sys 1032409559 4081
 sys/src/boot/pc/devi82365.c - 664 sys sys 1144961189 15051
-sys/src/boot/pc/devpccard.c - 664 sys sys 1145459731 33937
+sys/src/boot/pc/devpccard.c - 664 sys sys 1153333456 33897
 sys/src/boot/pc/devsd.c - 664 sys sys 1077033681 11262
 sys/src/boot/pc/dma.c - 664 sys sys 1015007949 4972
 sys/src/boot/pc/dosboot.c - 664 sys sys 1097716791 11240
@@ -9029,7 +9029,7 @@ sys/src/boot/pc/ether589.c - 664 sys sys 1144961189 4624
 sys/src/boot/pc/ether79c970.c - 664 sys sys 1015007950 11717
 sys/src/boot/pc/ether8003.c - 664 sys sys 1015007950 6446
 sys/src/boot/pc/ether8139.c - 664 sys sys 1121393459 14823
-sys/src/boot/pc/ether8169.c - 664 sys sys 1144961385 18634
+sys/src/boot/pc/ether8169.c - 664 sys sys 1153333456 21470
 sys/src/boot/pc/ether82557.c - 664 sys sys 1140802406 19090
 sys/src/boot/pc/ether83815.c - 664 sys sys 1144961190 21993
 sys/src/boot/pc/ether8390.c - 664 sys sys 1112382847 16209
@@ -9042,7 +9042,7 @@ sys/src/boot/pc/etherigbe.c - 664 sys sys 1140710606 40769
 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 1144961190 12383
-sys/src/boot/pc/fns.h - 664 sys sys 1144961190 4457
+sys/src/boot/pc/fns.h - 664 sys sys 1153333456 4667
 sys/src/boot/pc/fs.c - 664 sys sys 1094674483 1509
 sys/src/boot/pc/fs.h - 664 sys sys 1094674488 653
 sys/src/boot/pc/ilock.c - 664 sys sys 1015007952 303
@@ -9067,10 +9067,10 @@ sys/src/boot/pc/pbsdisk.s - 664 sys sys 1017854325 6371
 sys/src/boot/pc/pbsdisklba - 775 sys sys 1015007954 509
 sys/src/boot/pc/pbsdisklba.s - 664 sys sys 1015007954 6022
 sys/src/boot/pc/pbslba.s - 664 sys sys 1143465392 8158
-sys/src/boot/pc/pci.c - 664 sys sys 1121366869 17898
+sys/src/boot/pc/pci.c - 664 sys sys 1153333456 20363
 sys/src/boot/pc/print.c - 664 sys sys 1094674483 219
 sys/src/boot/pc/queue.c - 664 sys sys 1015007954 566
-sys/src/boot/pc/sd.h - 664 sys sys 1094674489 2271
+sys/src/boot/pc/sd.h - 664 sys sys 1153333456 2244
 sys/src/boot/pc/sd53c8xx.c - 664 sys sys 1144961191 52127
 sys/src/boot/pc/sd53c8xx.i - 664 sys sys 1015007955 27245
 sys/src/boot/pc/sdata.c - 664 sys sys 1144961191 38221

+ 7 - 7
dist/replica/plan9.db

@@ -1,8 +1,8 @@
 386 - 20000000775 sys sys 1010957353 0
 386/9load - 775 sys sys 1146095338 217880
-386/9loaddebug - 775 sys sys 1148576273 313752
+386/9loaddebug - 775 sys sys 1153337893 313752
 386/9loadlite - 775 sys sys 1146095338 136160
-386/9loadlitedebug - 775 sys sys 1148576273 201058
+386/9loadlitedebug - 775 sys sys 1153337893 201058
 386/9pc - 775 sys sys 1143137104 1913157
 386/9pc.gz - 664 sys sys 1141258202 668936
 386/9pccpu - 775 sys sys 1141258205 1583315
@@ -9015,7 +9015,7 @@ sys/src/boot/pc/dat.h - 664 sys sys 1144961189 3597
 sys/src/boot/pc/devfloppy.c - 664 sys sys 1032215913 15505
 sys/src/boot/pc/devfloppy.h - 664 sys sys 1032409559 4081
 sys/src/boot/pc/devi82365.c - 664 sys sys 1144961189 15051
-sys/src/boot/pc/devpccard.c - 664 sys sys 1145459731 33937
+sys/src/boot/pc/devpccard.c - 664 sys sys 1153333456 33897
 sys/src/boot/pc/devsd.c - 664 sys sys 1077033681 11262
 sys/src/boot/pc/dma.c - 664 sys sys 1015007949 4972
 sys/src/boot/pc/dosboot.c - 664 sys sys 1097716791 11240
@@ -9029,7 +9029,7 @@ sys/src/boot/pc/ether589.c - 664 sys sys 1144961189 4624
 sys/src/boot/pc/ether79c970.c - 664 sys sys 1015007950 11717
 sys/src/boot/pc/ether8003.c - 664 sys sys 1015007950 6446
 sys/src/boot/pc/ether8139.c - 664 sys sys 1121393459 14823
-sys/src/boot/pc/ether8169.c - 664 sys sys 1144961385 18634
+sys/src/boot/pc/ether8169.c - 664 sys sys 1153333456 21470
 sys/src/boot/pc/ether82557.c - 664 sys sys 1140802406 19090
 sys/src/boot/pc/ether83815.c - 664 sys sys 1144961190 21993
 sys/src/boot/pc/ether8390.c - 664 sys sys 1112382847 16209
@@ -9042,7 +9042,7 @@ sys/src/boot/pc/etherigbe.c - 664 sys sys 1140710606 40769
 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 1144961190 12383
-sys/src/boot/pc/fns.h - 664 sys sys 1144961190 4457
+sys/src/boot/pc/fns.h - 664 sys sys 1153333456 4667
 sys/src/boot/pc/fs.c - 664 sys sys 1094674483 1509
 sys/src/boot/pc/fs.h - 664 sys sys 1094674488 653
 sys/src/boot/pc/ilock.c - 664 sys sys 1015007952 303
@@ -9067,10 +9067,10 @@ sys/src/boot/pc/pbsdisk.s - 664 sys sys 1017854325 6371
 sys/src/boot/pc/pbsdisklba - 775 sys sys 1015007954 509
 sys/src/boot/pc/pbsdisklba.s - 664 sys sys 1015007954 6022
 sys/src/boot/pc/pbslba.s - 664 sys sys 1143465392 8158
-sys/src/boot/pc/pci.c - 664 sys sys 1121366869 17898
+sys/src/boot/pc/pci.c - 664 sys sys 1153333456 20363
 sys/src/boot/pc/print.c - 664 sys sys 1094674483 219
 sys/src/boot/pc/queue.c - 664 sys sys 1015007954 566
-sys/src/boot/pc/sd.h - 664 sys sys 1094674489 2271
+sys/src/boot/pc/sd.h - 664 sys sys 1153333456 2244
 sys/src/boot/pc/sd53c8xx.c - 664 sys sys 1144961191 52127
 sys/src/boot/pc/sd53c8xx.i - 664 sys sys 1015007955 27245
 sys/src/boot/pc/sdata.c - 664 sys sys 1144961191 38221

+ 7 - 0
dist/replica/plan9.log

@@ -30209,3 +30209,10 @@
 1153173604 1 c sys/src/9/pc/memory.c - 664 sys sys 1153172671 18773
 1153195206 0 c sys/src/9/pc/mp.h - 664 sys sys 1153193597 6795
 1153251006 0 c sys/src/9/pc/devpccard.c - 664 sys sys 1153250455 39299
+1153333810 0 c sys/src/boot/pc/devpccard.c - 664 sys sys 1153333456 33897
+1153333810 1 c sys/src/boot/pc/ether8169.c - 664 sys sys 1153333456 21470
+1153333810 2 c sys/src/boot/pc/fns.h - 664 sys sys 1153333456 4667
+1153333810 3 c sys/src/boot/pc/pci.c - 664 sys sys 1153333456 20363
+1153333810 4 c sys/src/boot/pc/sd.h - 664 sys sys 1153333456 2244
+1153339205 0 c 386/9loaddebug - 775 sys sys 1153337893 313752
+1153339205 1 c 386/9loadlitedebug - 775 sys sys 1153337893 201058

+ 0 - 1
sys/src/boot/pc/devpccard.c

@@ -10,7 +10,6 @@
 #include "io.h"
 
 extern int pciscan(int, Pcidev **);
-extern ulong pcibarsize(Pcidev *, int);
 
 int (*_pcmspecial)(char *, ISAConf *);
 void (*_pcmspecialclose)(int);

+ 242 - 132
sys/src/boot/pc/ether8169.c

@@ -17,7 +17,6 @@
 #include "fns.h"
 #include "io.h"
 
-
 typedef struct QLock { int r; } QLock;
 #define qlock(i)	while(0)
 #define qunlock(i)	while(0)
@@ -106,6 +105,16 @@ enum {					/* Tcr */
 	Ifg2		= 0x00080000,	/* Interframe Gap 2 */
 	HwveridSHIFT	= 23,		/* Hardware Version ID */
 	HwveridMASK	= 0x7C800000,
+	Macv01		= 0x00000000,	/* RTL8169 */
+	Macv02		= 0x00800000,	/* RTL8169S/8110S */
+	Macv03		= 0x04000000,	/* RTL8169S/8110S */
+	Macv04		= 0x10000000,	/* RTL8169SB/8110SB */
+	Macv05		= 0x18000000,	/* RTL8169SC/8110SC */
+	Macv11		= 0x30000000,	/* RTL8168B/8111B */
+	Macv12		= 0x38000000,	/* RTL8169B/8111B */
+	Macv13		= 0x34000000,	/* RTL8101E */
+	Macv14		= 0x30800000,	/* RTL8100E */
+	Macv15		= 0x38800000,	/* RTL8100E */
 	Ifg0		= 0x01000000,	/* Interframe Gap 0 */
 	Ifg1		= 0x02000000,	/* Interframe Gap 1 */
 };
@@ -234,18 +243,30 @@ struct Dtcc {
 	u16int	txundrn;
 };
 
+enum {						/* Variants */
+	Rtl8100e	= (0x8136<<16)|0x10EC,	/* RTL810[01]E ? */
+	Rtl8169sc	= (0x8167<<16)|0x10EC,	/* RTL8169SC */
+	Rtl8168b	= (0x8168<<16)|0x10EC,	/* RTL8168B */
+	Rtl8169		= (0x8169<<16)|0x10EC,	/* RTL8169 */
+};
+
 typedef struct Ctlr Ctlr;
 typedef struct Ctlr {
 	int	port;
 	Pcidev*	pcidev;
 	Ctlr*	next;
 	int	active;
-	uint	id;
+
+	void*	nic;
 
 	QLock	alock;			/* attach */
 	Lock	ilock;			/* init */
 	int	init;			/*  */
 
+	int	pciv;			/*  */
+	int	macv;			/* MAC version */
+	int	phyv;			/* PHY version */
+
 	Mii*	mii;
 
 	Lock	tlock;			/* transmit */
@@ -285,8 +306,8 @@ typedef struct Ctlr {
 	uint	fovw;
 } Ctlr;
 
-static Ctlr* ctlrhead;
-static Ctlr* ctlrtail;
+static Ctlr* rtl8169ctlrhead;
+static Ctlr* rtl8169ctlrtail;
 
 #define csr8r(c, r)	(inb((c)->port+(r)))
 #define csr16r(c, r)	(ins((c)->port+(r)))
@@ -358,36 +379,59 @@ rtl8169mii(Ctlr* ctlr)
 	ctlr->mii->mir = rtl8169miimir;
 	ctlr->mii->miw = rtl8169miimiw;
 	ctlr->mii->ctlr = ctlr;
-	rtl8169miimiw(ctlr->mii, 1, 0x0B, 0x0000);	/* magic */
 
-	if(mii(ctlr->mii, ~0) == 0 || (phy = ctlr->mii->curphy) == nil){
+	/*
+	 * Get rev number out of Phyidr2 so can config properly.
+	 * There's probably more special stuff for Macv0[234] needed here.
+	 */
+	ctlr->phyv = rtl8169miimir(ctlr->mii, 1, Phyidr2) & 0x0F;
+	if(ctlr->macv == Macv02){
+		csr8w(ctlr, 0x82, 1);				/* magic */
+		rtl8169miimiw(ctlr->mii, 1, 0x0B, 0x0000);	/* magic */
+	}
+
+	if(mii(ctlr->mii, (1<<1)) == 0 || (phy = ctlr->mii->curphy) == nil){
 		free(ctlr->mii);
 		ctlr->mii = nil;
 		return -1;
 	}
-	print("oui %X phyno %d\n", phy->oui, phy->phyno);
+	print("oui %#ux phyno %d, macv = %#8.8ux phyv = %#4.4ux\n",
+		phy->oui, phy->phyno, ctlr->macv, ctlr->phyv);
 
 	miiane(ctlr->mii, ~0, ~0, ~0);
 
 	return 0;
 }
 
+static void
+rtl8169halt(Ctlr* ctlr)
+{
+	csr8w(ctlr, Cr, 0);
+	csr16w(ctlr, Imr, 0);
+	csr16w(ctlr, Isr, ~0);
+}
+
 static int
 rtl8169reset(Ctlr* ctlr)
 {
+	u32int r;
 	int timeo;
 
 	/*
 	 * Soft reset the controller.
 	 */
 	csr8w(ctlr, Cr, Rst);
-	for(timeo = 0; timeo < 1000; timeo++){
-		if(!(csr8r(ctlr, Cr) & Rst))
-			return 0;
+	for(r = timeo = 0; timeo < 1000; timeo++){
+		r = csr8r(ctlr, Cr);
+		if(!(r & Rst))
+			break;
 		delay(1);
 	}
+	rtl8169halt(ctlr);
 
-	return -1;
+	if(r & Rst)
+		return -1;
+	return 0;
 }
 
 static void
@@ -396,14 +440,6 @@ rtl8169detach(Ether* edev)
 	rtl8169reset(edev->ctlr);
 }
 
-static void
-rtl8169halt(Ctlr* ctlr)
-{
-	csr8w(ctlr, Cr, 0);
-	csr16w(ctlr, Imr, 0);
-	csr16w(ctlr, Isr, ~0);
-}
-
 static void
 rtl8169replenish(Ctlr* ctlr)
 {
@@ -418,7 +454,7 @@ rtl8169replenish(Ctlr* ctlr)
 			/*
 			 * simple allocation for now
 			 */
-			bp = malloc(Mps);
+			bp = mallocalign(Mps, 8, 0, 0);
 			ctlr->rb[rdt] = bp;
 			d->addrlo = PCIWADDR(bp);
 			d->addrhi = 0;
@@ -431,23 +467,18 @@ rtl8169replenish(Ctlr* ctlr)
 	ctlr->rdt = rdt;
 }
 
-static void
+static int
 rtl8169init(Ether* edev)
 {
-	uint r;
+	u32int r;
 	Ctlr *ctlr;
+	u8int cplusc;
 
 	ctlr = edev->ctlr;
 	ilock(&ctlr->ilock);
 
 	rtl8169halt(ctlr);
 
-	/*
-	 * Setting Mulrw in Cplusc disables the Tx/Rx DMA burst settings
-	 * in Tcr/Rcr.
-	 */
-	csr16w(ctlr, Cplusc, (1<<14)|Rxchksum|Mulrw);	/* magic (1<<14) */
-
 	/*
 	 * MAC Address.
 	 * Must put chip into config register write enable mode.
@@ -458,46 +489,96 @@ rtl8169init(Ether* edev)
 	r = (edev->ea[5]<<8)|edev->ea[4];
 	csr32w(ctlr, Idr0+4, r);
 
-	/*
-	 * Enable receiver/transmitter.
-	 * Need to do this first or some of the settings below
-	 * won't take.
-	 */
-	csr8w(ctlr, Cr, Te|Re);
-
 	/*
 	 * Transmitter.
-	 * Mtps is in units of 128.
 	 */
 	memset(ctlr->td, 0, sizeof(D)*ctlr->ntd);
 	ctlr->tdh = ctlr->tdt = 0;
 	ctlr->td[ctlr->ntd-1].control = Eor;
-	ctlr->mtps = HOWMANY(Mps, 128);
 
 	/*
 	 * Receiver.
+	 * Need to do something here about the multicast filter.
 	 */
 	memset(ctlr->rd, 0, sizeof(D)*ctlr->nrd);
 	ctlr->rdh = ctlr->rdt = 0;
 	ctlr->rd[ctlr->nrd-1].control = Eor;
-
-	//for(i = 0; i < ctlr->nrd; i++){
-	//	if((bp = ctlr->rb[i]) != nil){
-	//		ctlr->rb[i] = nil;
-	//		freeb(bp);
-	//	}
-	//}
 	rtl8169replenish(ctlr);
-	ctlr->rcr = Rxfth256|Mrxdmaunlimited|Ab|Apm;
+	ctlr->rcr = Rxfthnone|Mrxdmaunlimited|Ab|Apm;
+
+	/*
+	 * Mtps is in units of 128 except for the RTL8169
+	 * where is is 32. If using jumbo frames should be
+	 * set to 0x3F.
+	 * Setting Mulrw in Cplusc disables the Tx/Rx DMA burst
+	 * settings in Tcr/Rcr; the (1<<14) is magic.
+	 */
+	ctlr->mtps = HOWMANY(Mps, 128);
+	cplusc = csr16r(ctlr, Cplusc) & ~(1<<14);
+	cplusc |= Rxchksum|Mulrw;
+	switch(ctlr->macv){
+	default:
+		return -1;
+	case Macv01:
+		ctlr->mtps = HOWMANY(Mps, 32);
+		break;
+	case Macv02:
+	case Macv03:
+		cplusc |= (1<<14);			/* magic */
+		break;
+	case Macv05:
+		/*
+		 * This is interpreted from clearly bogus code
+		 * in the manufacturer-supplied driver, it could
+		 * be wrong. Untested.
+		 */
+		r = csr8r(ctlr, Config2) & 0x07;
+		if(r == 0x01)				/* 66MHz PCI */
+			csr32w(ctlr, 0x7C, 0x0007FFFF);	/* magic */
+		else
+			csr32w(ctlr, 0x7C, 0x0007FF00);	/* magic */
+		pciclrmwi(ctlr->pcidev);
+		break;
+	case Macv13:
+		/*
+		 * This is interpreted from clearly bogus code
+		 * in the manufacturer-supplied driver, it could
+		 * be wrong. Untested.
+		 */
+		pcicfgw8(ctlr->pcidev, 0x68, 0x00);	/* magic */
+		pcicfgw8(ctlr->pcidev, 0x69, 0x08);	/* magic */
+		break;
+	case Macv04:
+	case Macv11:
+	case Macv12:
+	case Macv14:
+	case Macv15:
+		break;
+	}
+
+	/*
+	 * Enable receiver/transmitter.
+	 * Need to do this first or some of the settings below
+	 * won't take.
+	 */
+	switch(ctlr->pciv){
+	default:
+		csr8w(ctlr, Cr, Te|Re);
+		csr32w(ctlr, Tcr, Ifg1|Ifg0|Mtxdmaunlimited);
+		csr32w(ctlr, Rcr, ctlr->rcr);
+	case Rtl8169sc:
+	case Rtl8168b:
+		break;
+	}
 
 	/*
 	 * Interrupts.
 	 * Disable Tdu|Tok for now, the transmit routine will tidy.
-	 * Tdu means the NIC ran out of descritors to send, so it
+	 * Tdu means the NIC ran out of descriptors to send, so it
 	 * doesn't really need to ever be on.
 	 */
 	csr32w(ctlr, Timerint, 0);
-	csr16w(ctlr, Imr, Serr|Timeout/*|Tdu*/|Fovw|Punlc|Rdu|Ter/*|Tok*/|Rer|Rok);
+	csr16w(ctlr, Imr, Serr|Timeout|Fovw|Punlc|Rdu|Ter|Rer|Rok);
 
 	/*
 	 * Clear missed-packet counter;
@@ -513,20 +594,40 @@ rtl8169init(Ether* edev)
 	csr32w(ctlr, Rdsar+4, 0);
 	csr32w(ctlr, Rdsar, PCIWADDR(ctlr->rd));
 	csr16w(ctlr, Rms, Mps);
-	csr16w(ctlr, Mulint, 0);
+	r = csr16r(ctlr, Mulint) & 0xF000;
+	csr16w(ctlr, Mulint, r);
+	csr16w(ctlr, Cplusc, cplusc);
 
 	/*
 	 * Set configuration.
 	 */
-	csr32w(ctlr, Tcr, Ifg1|Ifg0|Mtxdmaunlimited);
-	csr32w(ctlr, Rcr, ctlr->rcr);
-	csr16w(ctlr, 0xE2, 0);			/* magic */
+	switch(ctlr->pciv){
+	default:
+		break;
+	case Rtl8169sc:
+		csr16w(ctlr, 0xE2, 0);			/* magic */
+		csr8w(ctlr, Cr, Te|Re);
+		csr32w(ctlr, Tcr, Ifg1|Ifg0|Mtxdmaunlimited);
+		csr32w(ctlr, Rcr, ctlr->rcr);
+		break;
+	case Rtl8168b:
+		csr16w(ctlr, 0xE2, 0);			/* magic */
+		csr16w(ctlr, Cplusc, 0x2000);		/* magic */
+		csr8w(ctlr, Cr, Te|Re);
+		csr32w(ctlr, Tcr, Ifg1|Ifg0|Mtxdmaunlimited);
+		csr32w(ctlr, Rcr, ctlr->rcr);
+		csr16w(ctlr, Rms, 0x0800);
+		csr8w(ctlr, Mtps, 0x3F);
+		break;
+	}
 
 	csr8w(ctlr, Cr9346, 0);
 
 	iunlock(&ctlr->ilock);
 
-	//rtl8169mii(ctlr);
+//	rtl8169mii(ctlr);
+
+	return 0;
 }
 
 static void
@@ -663,7 +764,7 @@ rtl8169receive(Ether* edev)
 		else{
 			/*
 			 * Error stuff here.
-			print("control %8.8uX\n", control);
+			print("control %#8.8ux\n", control);
 			 */
 		}
 		d->control &= Eor;
@@ -686,7 +787,7 @@ rtl8169interrupt(Ureg*, void* arg)
 	edev = arg;
 	ctlr = edev->ctlr;
 
-	while((isr = csr16r(ctlr, Isr)) != 0){
+	while((isr = csr16r(ctlr, Isr)) != 0 && isr != 0xFFFF){
 		csr16w(ctlr, Isr, isr);
 		if(isr & (Fovw|Punlc|Rdu|Rer|Rok)){
 			rtl8169receive(edev);
@@ -709,7 +810,7 @@ rtl8169interrupt(Ureg*, void* arg)
 		}
 
 		if(isr & Punlc){
-			//rtl8169link(edev);
+//			rtl8169link(edev);
 			isr &= ~Punlc;
 		}
 
@@ -717,104 +818,103 @@ rtl8169interrupt(Ureg*, void* arg)
 		 * Some of the reserved bits get set sometimes...
 		 */
 		if(isr & (Serr|Timeout|Tdu|Fovw|Punlc|Rdu|Ter|Tok|Rer|Rok))
-			panic("rtl8169interrupt: imr %4.4uX isr %4.4uX\n",
+			panic("rtl8169interrupt: imr %#4.4ux isr %#4.4ux\n",
 				csr16r(ctlr, Imr), isr);
 	}
 }
 
-static Ctlr*
-rtl8169match(Ether* edev, int id)
+static void
+rtl8169pci(void)
 {
 	Pcidev *p;
 	Ctlr *ctlr;
-	int port;
+	int i, port;
+	u32int bar;
 
-	/*
-	 * Any adapter matches if no edev->port is supplied,
-	 * otherwise the ports must match.
-	 */
-	for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
-		if(ctlr->active)
+	p = nil;
+	while(p = pcimatch(p, 0, 0)){
+		if(p->ccrb != 0x02 || p->ccru != 0)
 			continue;
-		p = ctlr->pcidev;
-		if(((p->did<<16)|p->vid) != id)
-			continue;
-		port = p->mem[0].bar & ~0x01;
-		if(edev->port != 0 && edev->port != port)
+
+		switch(i = ((p->did<<16)|p->vid)){
+		default:
 			continue;
+		case Rtl8100e:			/* RTL810[01]E ? */
+		case Rtl8169sc:			/* RTL8169SC */
+		case Rtl8168b:			/* RTL8168B */
+		case Rtl8169:			/* RTL8169 */
+			break;
+		case (0xC107<<16)|0x1259:	/* Corega CG-LAPCIGT */
+			i = Rtl8169;
+			break;
+		}
 
+		bar = p->mem[0].bar;
+		port = bar & ~0x01;
+		if(ioalloc(port, p->mem[0].size, 0, "rtl8169") < 0){
+			print("rtl8169: port %#ux in use\n", port);
+			continue;
+		}
+		ctlr = malloc(sizeof(Ctlr));
 		ctlr->port = port;
-		if(rtl8169reset(ctlr))
+		ctlr->pcidev = p;
+		ctlr->pciv = i;
+
+		if(pcigetpms(p) > 0){
+			pcisetpms(p, 0);
+	
+			for(i = 0; i < 6; i++)
+				pcicfgw32(p, PciBAR0+i*4, p->mem[i].bar);
+			pcicfgw8(p, PciINTL, p->intl);
+			pcicfgw8(p, PciLTR, p->ltr);
+			pcicfgw8(p, PciCLS, p->cls);
+			pcicfgw16(p, PciPCR, p->pcr);
+		}
+
+		if(rtl8169reset(ctlr)){
+			iofree(port);
+			free(ctlr);
 			continue;
+		}
 
-		csr8w(ctlr, 0x82, 1);		/* magic */
+		/*
+		 * Extract the chip hardware version,
+		 * needed to configure each properly.
+		 */
+		ctlr->macv = csr32r(ctlr, Tcr) & HwveridMASK;
 
 		rtl8169mii(ctlr);
 
 		pcisetbme(p);
-		ctlr->active = 1;
-		return ctlr;
+
+		if(rtl8169ctlrhead != nil)
+			rtl8169ctlrtail->next = ctlr;
+		else
+			rtl8169ctlrhead = ctlr;
+		rtl8169ctlrtail = ctlr;
 	}
-	return nil;
 }
 
-static struct {
-	char*	name;
-	int	id;
-} rtl8169pci[] = {
-	{ "rtl8169",	(0x8169<<16)|0x10EC, },	/* generic */
-	{ "CG-LAPCIGT",	(0xC107<<16)|0x1259, },	/* Corega CG-LAPCIGT */
-	{ nil },
-};
-
 int
 rtl8169pnp(Ether* edev)
 {
-	Pcidev *p;
+	u32int r;
 	Ctlr *ctlr;
-	int i, id;
-	uchar ea[Eaddrlen];
 
-	/*
-	 * Make a list of all ethernet controllers
-	 * if not already done.
-	 */
-	if(ctlrhead == nil){
-		p = nil;
-		while(p = pcimatch(p, 0, 0)){
-			if(p->ccrb != 0x02 || p->ccru != 0)
-				continue;
-			ctlr = malloc(sizeof(Ctlr));
-			ctlr->pcidev = p;
-			ctlr->id = (p->did<<16)|p->vid;
-
-			if(ctlrhead != nil)
-				ctlrtail->next = ctlr;
-			else
-				ctlrhead = ctlr;
-			ctlrtail = ctlr;
-		}
-	}
+	if(rtl8169ctlrhead == nil)
+		rtl8169pci();
 
 	/*
-	 * Is it an RTL8169 under a different name?
-	 * Normally a search is made through all the found controllers
-	 * for one which matches any of the known vid+did pairs.
-	 * If a vid+did pair is specified a search is made for that
-	 * specific controller only.
+	 * Any adapter matches if no edev->port is supplied,
+	 * otherwise the ports must match.
 	 */
-	id = 0;
-	for(i = 0; i < edev->nopt; i++){
-		if(cistrncmp(edev->opt[i], "id=", 3) == 0)
-			id = strtol(&edev->opt[i][3], nil, 0);
-	}
-
-	ctlr = nil;
-	if(id != 0)
-		ctlr = rtl8169match(edev, id);
-	else for(i = 0; rtl8169pci[i].name; i++){
-		if((ctlr = rtl8169match(edev, rtl8169pci[i].id)) != nil)
+	for(ctlr = rtl8169ctlrhead; ctlr != nil; ctlr = ctlr->next){
+		if(ctlr->active)
+			continue;
+		if(edev->port == 0 || edev->port == ctlr->port){
+			ctlr->active = 1;
 			break;
+		}
 	}
 	if(ctlr == nil)
 		return -1;
@@ -823,23 +923,33 @@ rtl8169pnp(Ether* edev)
 	edev->port = ctlr->port;
 	edev->irq = ctlr->pcidev->intl;
 	edev->tbdf = ctlr->pcidev->tbdf;
+//	edev->mbps = 100;
 
 	/*
+	 * Pull the MAC address out of the chip.
 	 */
-	memset(ea, 0, Eaddrlen);
-	i = csr32r(ctlr, Idr0);
-	edev->ea[0] = i;
-	edev->ea[1] = i>>8;
-	edev->ea[2] = i>>16;
-	edev->ea[3] = i>>24;
-	i = csr32r(ctlr, Idr0+4);
-	edev->ea[4] = i;
-	edev->ea[5] = i>>8;
+	r = csr32r(ctlr, Idr0);
+	edev->ea[0] = r;
+	edev->ea[1] = r>>8;
+	edev->ea[2] = r>>16;
+	edev->ea[3] = r>>24;
+	r = csr32r(ctlr, Idr0+4);
+	edev->ea[4] = r;
+	edev->ea[5] = r>>8;
 
+	/*
+	 * Linkage to the generic ethernet driver.
+	 */
 	edev->attach = rtl8169attach;
 	edev->transmit = rtl8169transmit;
 	edev->interrupt = rtl8169interrupt;
 	edev->detach = rtl8169detach;
+//	edev->ifstat = rtl8169ifstat;
+//	edev->ctl = nil;
+//
+//	edev->arg = edev;
+//	edev->promiscuous = rtl8169promiscuous;
+//	edev->multicast = rtl8169multicast;
 
 	return 0;
 }

+ 8 - 0
sys/src/boot/pc/fns.h

@@ -75,18 +75,26 @@ void	outsb(int, void*, int);
 void	outss(int, void*, int);
 void	outsl(int, void*, int);
 void	panic(char*, ...);
+ulong	pcibarsize(Pcidev*, int);
 int	pcicfgr8(Pcidev*, int);
 int	pcicfgr16(Pcidev*, int);
 int	pcicfgr32(Pcidev*, int);
 void	pcicfgw8(Pcidev*, int, int);
 void	pcicfgw16(Pcidev*, int, int);
 void	pcicfgw32(Pcidev*, int, int);
+void	pciclrbme(Pcidev*);
+void	pciclrioe(Pcidev*);
+void	pciclrmwi(Pcidev*);
+int	pcigetpms(Pcidev*);
 void	pcihinv(Pcidev*);
 Pcidev*	pcimatch(Pcidev*, int, int);
 uchar	pciintl(Pcidev *);
 uchar	pciipin(Pcidev *, uchar);
 void	pcireset(void);
 void	pcisetbme(Pcidev*);
+void	pcisetioe(Pcidev*);
+void	pcisetmwi(Pcidev*);
+int	pcisetpms(Pcidev*, int);
 void	pcmcisread(PCMslot*);
 int	pcmcistuple(int, int, int, void*, int);
 PCMmap*	pcmmap(int, ulong, int, int);

+ 163 - 6
sys/src/boot/pc/pci.c

@@ -23,6 +23,16 @@ enum {					/* configuration mechanism #1 */
 	MaxUBN		= 255,
 };
 
+enum
+{					/* command register */
+	IOen		= (1<<0),
+	MEMen		= (1<<1),
+	MASen		= (1<<2),
+	MemWrInv	= (1<<4),
+	PErrEn		= (1<<6),
+	SErrEn		= (1<<8),
+};
+
 static Lock pcicfglock;
 static Lock pcicfginitlock;
 static int pcicfgmode = -1;
@@ -145,7 +155,8 @@ pciscan(int bno, Pcidev** list)
 	*list = head;
 	for(p = head; p != nil; p = p->link){
 		/*
-		 * Find PCI-PCI and PCI-Cardbus bridges and recursively descend the tree.
+		 * Find PCI-PCI and PCI-Cardbus bridges
+		 * and recursively descend the tree.
 		 */
 		if(p->ccrb != 0x06 || p->ccru != 0x04)
 			continue;
@@ -181,7 +192,16 @@ pciscan(int bno, Pcidev** list)
 			pcicfgw32(p, PciPBN, l);
 		}
 		else{
-			maxubn = ubn;
+			/*
+			 * You can't go back.
+			 * This shouldn't be possible, but the
+			 * Iwill DK8-HTX seems to have subordinate
+			 * bus numbers which get smaller on the
+			 * way down. Need to look more closely at
+			 * this.
+			 */
+			if(ubn > maxubn)
+				maxubn = ubn;
 			pciscan(sbn, &p->bridge);
 		}
 	}
@@ -840,13 +860,150 @@ pcireset(void)
 	}
 }
 
+void
+pcisetioe(Pcidev* p)
+{
+	p->pcr |= IOen;
+	pcicfgw16(p, PciPCR, p->pcr);
+}
+
+void
+pciclrioe(Pcidev* p)
+{
+	p->pcr &= ~IOen;
+	pcicfgw16(p, PciPCR, p->pcr);
+}
+
 void
 pcisetbme(Pcidev* p)
 {
-	int pcr;
+	p->pcr |= MASen;
+	pcicfgw16(p, PciPCR, p->pcr);
+}
 
-	pcr = pcicfgr16(p, PciPCR);
-	pcr |= 0x0004;
-	pcicfgw16(p, PciPCR, pcr);
+void
+pciclrbme(Pcidev* p)
+{
+	p->pcr &= ~MASen;
+	pcicfgw16(p, PciPCR, p->pcr);
 }
 
+void
+pcisetmwi(Pcidev* p)
+{
+	p->pcr |= MemWrInv;
+	pcicfgw16(p, PciPCR, p->pcr);
+}
+
+void
+pciclrmwi(Pcidev* p)
+{
+	p->pcr &= ~MemWrInv;
+	pcicfgw16(p, PciPCR, p->pcr);
+}
+
+static int
+pcigetpmrb(Pcidev* p)
+{
+	int ptr;
+
+	if(p->pmrb != 0)
+		return p->pmrb;
+	p->pmrb = -1;
+
+	/*
+	 * If there are no extended capabilities implemented,
+	 * (bit 4 in the status register) assume there's no standard
+	 * power management method.
+	 * Find the capabilities pointer based on PCI header type.
+	 */
+	if(!(p->pcr & 0x0010))
+		return -1;
+	switch(pcicfgr8(p, PciHDT)){
+	default:
+		return -1;
+	case 0:					/* all other */
+	case 1:					/* PCI to PCI bridge */
+		ptr = 0x34;
+		break;
+	case 2:					/* CardBus bridge */
+		ptr = 0x14;
+		break;
+	}
+	ptr = pcicfgr32(p, ptr);
+
+	while(ptr != 0){
+		/*
+		 * Check for validity.
+		 * Can't be in standard header and must be double
+		 * word aligned.
+		 */
+		if(ptr < 0x40 || (ptr & ~0xFC))
+			return -1;
+		if(pcicfgr8(p, ptr) == 0x01){
+			p->pmrb = ptr;
+			return ptr;
+		}
+
+		ptr = pcicfgr8(p, ptr+1);
+	}
+
+	return -1;
+}
+
+int
+pcigetpms(Pcidev* p)
+{
+	int pmcsr, ptr;
+
+	if((ptr = pcigetpmrb(p)) == -1)
+		return -1;
+
+	/*
+	 * Power Management Register Block:
+	 *  offset 0:	Capability ID
+	 *	   1:	next item pointer
+	 *	   2:	capabilities
+	 *	   4:	control/status
+	 *	   6:	bridge support extensions
+	 *	   7:	data
+	 */
+	pmcsr = pcicfgr16(p, ptr+4);
+
+	return pmcsr & 0x0003;
+}
+
+int
+pcisetpms(Pcidev* p, int state)
+{
+	int ostate, pmc, pmcsr, ptr;
+
+	if((ptr = pcigetpmrb(p)) == -1)
+		return -1;
+
+	pmc = pcicfgr16(p, ptr+2);
+	pmcsr = pcicfgr16(p, ptr+4);
+	ostate = pmcsr & 0x0003;
+	pmcsr &= ~0x0003;
+
+	switch(state){
+	default:
+		return -1;
+	case 0:
+		break;
+	case 1:
+		if(!(pmc & 0x0200))
+			return -1;
+		break;
+	case 2:
+		if(!(pmc & 0x0400))
+			return -1;
+		break;
+	case 3:
+		break;
+	}
+	pmcsr |= state;
+	pcicfgw16(p, ptr+4, pmcsr);
+
+	return ostate;
+}

+ 0 - 1
sys/src/boot/pc/sd.h

@@ -121,7 +121,6 @@ void tsleep(void*, int(*)(void*), void*, int);
 #define wakeup(x) while(0)
 extern long sdbio(SDunit *unit, SDpart *pp, void *a, long len, vlong off);
 void	partition(SDunit*);
-void	addpartconf(SDunit*);
 SDpart* sdfindpart(SDunit*, char*);
 void	sdaddpart(SDunit*, char*, ulong, ulong);
 void*	sdmalloc(void*, ulong);