Просмотр исходного кода

Plan 9 from Bell Labs Fourth Edition 2004-11-18

David du Colombier 19 лет назад
Родитель
Сommit
06578a4f37

+ 10 - 11
dist/replica/_plan9.db

@@ -458,7 +458,7 @@
 386/bin/upas/unspam - 775 sys sys 1064598367 38
 386/bin/upas/vf - 775 sys sys 1087873352 90619
 386/bin/usb - 20000000775 sys sys 1019538890 0
-386/bin/usb/usbaudio - 775 sys sys 1100579340 183269
+386/bin/usb/usbaudio - 775 sys sys 1100664617 183278
 386/bin/usb/usbd - 775 sys sys 1099800617 127661
 386/bin/usb/usbmouse - 775 sys sys 1099800618 138206
 386/bin/usb/usbprinter - 775 sys sys 1089408719 222
@@ -4417,7 +4417,7 @@ sys/lib/sysconfig/auth/files/tcp566 - 775 sys sys 1016833537 36
 sys/lib/sysconfig/auth/files/tcp567 - 775 sys sys 1016833537 34
 sys/lib/sysconfig/auth/mkfile - 664 sys sys 1016833657 2937
 sys/lib/sysconfig/blast - 20000000775 sys sys 1059490895 0
-sys/lib/sysconfig/blast/boot - 775 sys sys 1059490900 571
+sys/lib/sysconfig/blast/boot - 775 sys sys 1100701674 568
 sys/lib/sysconfig/proto - 20000000775 sys sys 959740591 0
 sys/lib/sysconfig/proto/allproto - 664 sys sys 945018241 2
 sys/lib/sysconfig/proto/armpaqproto - 664 sys sys 1089299189 2230
@@ -5546,16 +5546,16 @@ sys/src/9/port/tod.c - 664 sys sys 1067722762 4856
 sys/src/9/port/unthwack.c - 664 sys sys 1057323394 5249
 sys/src/9/port/xalloc.c - 664 sys sys 1097074047 4030
 sys/src/9/ppc - 20000000775 sys sys 1059490838 0
-sys/src/9/ppc/blast - 664 sys sys 1067722850 659
+sys/src/9/ppc/blast - 664 sys sys 1100701674 685
 sys/src/9/ppc/blast.h - 664 sys sys 1059490750 3109
-sys/src/9/ppc/clock.c - 664 sys sys 1068135488 1032
+sys/src/9/ppc/clock.c - 664 sys sys 1100701675 1036
 sys/src/9/ppc/dat.h - 664 sys sys 1097073353 4712
 sys/src/9/ppc/devether.c - 664 sys sys 1059490750 9264
 sys/src/9/ppc/devflash.c - 664 sys sys 1059490750 19885
-sys/src/9/ppc/devirq.c - 664 sys sys 1077376394 6053
+sys/src/9/ppc/devirq.c - 664 sys sys 1100701675 6314
 sys/src/9/ppc/devtls.c - 664 sys sys 1059490751 43721
 sys/src/9/ppc/errstr.h - 664 sys sys 1059490751 2137
-sys/src/9/ppc/etherfcc.c - 664 sys sys 1068135488 14307
+sys/src/9/ppc/etherfcc.c - 664 sys sys 1100701674 19690
 sys/src/9/ppc/etherif.h - 664 sys sys 1059490751 785
 sys/src/9/ppc/ethersaturn.c - 664 sys sys 1059490751 4321
 sys/src/9/ppc/fns.h - 664 sys sys 1067722798 4211
@@ -5565,8 +5565,8 @@ sys/src/9/ppc/io.h - 664 sys sys 1059490752 1017
 sys/src/9/ppc/l.s - 664 sys sys 1089299185 20371
 sys/src/9/ppc/lblast.h - 664 sys sys 1059490752 1694
 sys/src/9/ppc/lucu.h - 664 sys sys 1059490752 935
-sys/src/9/ppc/m8260.c - 664 sys sys 1097073366 14480
-sys/src/9/ppc/m8260.h - 664 sys sys 1068135488 20913
+sys/src/9/ppc/m8260.c - 664 sys sys 1100701674 14498
+sys/src/9/ppc/m8260.h - 664 sys sys 1100701674 20899
 sys/src/9/ppc/main.c - 664 sys sys 1097073343 9041
 sys/src/9/ppc/mcc.c - 664 sys sys 1059490752 9667
 sys/src/9/ppc/mem.h - 664 sys sys 1091021860 7002
@@ -5577,7 +5577,7 @@ sys/src/9/ppc/msaturn.h - 664 sys sys 1059490753 99
 sys/src/9/ppc/mtx.c - 664 sys sys 1059490753 177
 sys/src/9/ppc/random.c - 664 sys sys 1059490753 1983
 sys/src/9/ppc/saturntimer.c - 664 sys sys 1072705482 1737
-sys/src/9/ppc/trap.c - 664 sys sys 1084475129 17554
+sys/src/9/ppc/trap.c - 664 sys sys 1100701675 18357
 sys/src/9/ppc/uartsaturn.c - 664 sys sys 1059490754 7151
 sys/src/9/ppc/uartsmc.c - 664 sys sys 1068135489 11462
 sys/src/9/ppc/ucu - 664 sys sys 1067722849 672
@@ -11757,7 +11757,7 @@ sys/src/libc/port/utfrune.c - 664 sys sys 1014927408 401
 sys/src/libc/port/utfutf.c - 664 sys sys 1014927408 389
 sys/src/libc/power - 20000000775 sys sys 984709299 0
 sys/src/libc/power/argv0.s - 664 sys sys 1067719057 88
-sys/src/libc/power/cycles.s - 664 sys sys 1067719057 268
+sys/src/libc/power/cycles.s - 664 sys sys 1100701675 322
 sys/src/libc/power/getcallerpc.s - 664 sys sys 944961720 51
 sys/src/libc/power/getfcr.s - 664 sys sys 944961719 352
 sys/src/libc/power/main9.s - 664 sys sys 1067719057 415
@@ -12391,4 +12391,3 @@ usr/glenda/lib/profile - 664 glenda glenda 1021580005 847
 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/bin/usb/usbaudio - 775 sys sys 1100664617 183278

+ 9 - 9
dist/replica/plan9.db

@@ -4417,7 +4417,7 @@ sys/lib/sysconfig/auth/files/tcp566 - 775 sys sys 1016833537 36
 sys/lib/sysconfig/auth/files/tcp567 - 775 sys sys 1016833537 34
 sys/lib/sysconfig/auth/mkfile - 664 sys sys 1016833657 2937
 sys/lib/sysconfig/blast - 20000000775 sys sys 1059490895 0
-sys/lib/sysconfig/blast/boot - 775 sys sys 1059490900 571
+sys/lib/sysconfig/blast/boot - 775 sys sys 1100701674 568
 sys/lib/sysconfig/proto - 20000000775 sys sys 959740591 0
 sys/lib/sysconfig/proto/allproto - 664 sys sys 945018241 2
 sys/lib/sysconfig/proto/armpaqproto - 664 sys sys 1089299189 2230
@@ -5546,16 +5546,16 @@ sys/src/9/port/tod.c - 664 sys sys 1067722762 4856
 sys/src/9/port/unthwack.c - 664 sys sys 1057323394 5249
 sys/src/9/port/xalloc.c - 664 sys sys 1097074047 4030
 sys/src/9/ppc - 20000000775 sys sys 1059490838 0
-sys/src/9/ppc/blast - 664 sys sys 1067722850 659
+sys/src/9/ppc/blast - 664 sys sys 1100701674 685
 sys/src/9/ppc/blast.h - 664 sys sys 1059490750 3109
-sys/src/9/ppc/clock.c - 664 sys sys 1068135488 1032
+sys/src/9/ppc/clock.c - 664 sys sys 1100701675 1036
 sys/src/9/ppc/dat.h - 664 sys sys 1097073353 4712
 sys/src/9/ppc/devether.c - 664 sys sys 1059490750 9264
 sys/src/9/ppc/devflash.c - 664 sys sys 1059490750 19885
-sys/src/9/ppc/devirq.c - 664 sys sys 1077376394 6053
+sys/src/9/ppc/devirq.c - 664 sys sys 1100701675 6314
 sys/src/9/ppc/devtls.c - 664 sys sys 1059490751 43721
 sys/src/9/ppc/errstr.h - 664 sys sys 1059490751 2137
-sys/src/9/ppc/etherfcc.c - 664 sys sys 1068135488 14307
+sys/src/9/ppc/etherfcc.c - 664 sys sys 1100701674 19690
 sys/src/9/ppc/etherif.h - 664 sys sys 1059490751 785
 sys/src/9/ppc/ethersaturn.c - 664 sys sys 1059490751 4321
 sys/src/9/ppc/fns.h - 664 sys sys 1067722798 4211
@@ -5565,8 +5565,8 @@ sys/src/9/ppc/io.h - 664 sys sys 1059490752 1017
 sys/src/9/ppc/l.s - 664 sys sys 1089299185 20371
 sys/src/9/ppc/lblast.h - 664 sys sys 1059490752 1694
 sys/src/9/ppc/lucu.h - 664 sys sys 1059490752 935
-sys/src/9/ppc/m8260.c - 664 sys sys 1097073366 14480
-sys/src/9/ppc/m8260.h - 664 sys sys 1068135488 20913
+sys/src/9/ppc/m8260.c - 664 sys sys 1100701674 14498
+sys/src/9/ppc/m8260.h - 664 sys sys 1100701674 20899
 sys/src/9/ppc/main.c - 664 sys sys 1097073343 9041
 sys/src/9/ppc/mcc.c - 664 sys sys 1059490752 9667
 sys/src/9/ppc/mem.h - 664 sys sys 1091021860 7002
@@ -5577,7 +5577,7 @@ sys/src/9/ppc/msaturn.h - 664 sys sys 1059490753 99
 sys/src/9/ppc/mtx.c - 664 sys sys 1059490753 177
 sys/src/9/ppc/random.c - 664 sys sys 1059490753 1983
 sys/src/9/ppc/saturntimer.c - 664 sys sys 1072705482 1737
-sys/src/9/ppc/trap.c - 664 sys sys 1084475129 17554
+sys/src/9/ppc/trap.c - 664 sys sys 1100701675 18357
 sys/src/9/ppc/uartsaturn.c - 664 sys sys 1059490754 7151
 sys/src/9/ppc/uartsmc.c - 664 sys sys 1068135489 11462
 sys/src/9/ppc/ucu - 664 sys sys 1067722849 672
@@ -11757,7 +11757,7 @@ sys/src/libc/port/utfrune.c - 664 sys sys 1014927408 401
 sys/src/libc/port/utfutf.c - 664 sys sys 1014927408 389
 sys/src/libc/power - 20000000775 sys sys 984709299 0
 sys/src/libc/power/argv0.s - 664 sys sys 1067719057 88
-sys/src/libc/power/cycles.s - 664 sys sys 1067719057 268
+sys/src/libc/power/cycles.s - 664 sys sys 1100701675 322
 sys/src/libc/power/getcallerpc.s - 664 sys sys 944961720 51
 sys/src/libc/power/getfcr.s - 664 sys sys 944961719 352
 sys/src/libc/power/main9.s - 664 sys sys 1067719057 415

+ 9 - 0
dist/replica/plan9.log

@@ -17056,3 +17056,12 @@
 1100620895 0 c sys/src/cmd/usb/audio/usbaudio.c - 664 sys sys 1100619443 9818
 1100638788 0 c mail/lib/qmail - 775 upas upas 1100638780 182
 1100665904 0 c 386/bin/usb/usbaudio - 775 sys sys 1100664617 183278
+1100701911 0 c sys/lib/sysconfig/blast/boot - 775 sys sys 1100701674 568
+1100701911 1 c sys/src/9/ppc/blast - 664 sys sys 1100701674 685
+1100701911 2 c sys/src/9/ppc/clock.c - 664 sys sys 1100701675 1036
+1100701911 3 c sys/src/9/ppc/devirq.c - 664 sys sys 1100701675 6314
+1100701911 4 c sys/src/9/ppc/etherfcc.c - 664 sys sys 1100701674 19690
+1100701911 5 c sys/src/9/ppc/m8260.c - 664 sys sys 1100701674 14498
+1100701911 6 c sys/src/9/ppc/m8260.h - 664 sys sys 1100701674 20899
+1100701911 7 c sys/src/9/ppc/trap.c - 664 sys sys 1100701675 18357
+1100701911 8 c sys/src/libc/power/cycles.s - 664 sys sys 1100701675 322

+ 1 - 1
sys/lib/sysconfig/blast/boot

@@ -10,7 +10,7 @@ bind '#p' /proc
 bind '#d' /fd
 bind -a /boot /
 
-ipconfig -D
+ipconfig
 
 authaddr=`{sed -n 's/	auth=(.*)/\1/p' /net/ndb|sed 1q}
 fsaddr=`{sed -n 's/	fs=(.*)/\1/p' /net/ndb|sed 1q}

+ 2 - 1
sys/src/9/ppc/blast

@@ -18,9 +18,10 @@ dev
 	ip		arp chandial ip ipv6 ipaux iproute netif netlog nullmedium pktmedium ptclbsum inferno
 
 link
-	etherfcc
+	etherfcc		ethermii
 	ethermedium
 	netdevmedium
+	loopbackmedium
 
 misc
 	uartsmc

+ 2 - 2
sys/src/9/ppc/clock.c

@@ -30,7 +30,7 @@ void
 clockinit(void)
 {
 	m->dechz = m->bushz/4;	/* true for all 604e */
-	m->tbhz = m->dechz;		/* conjecture; manual doesn't say */
+	m->tbhz = m->dechz;	/* conjecture; manual doesn't say */
 
 	delayloopinit();
 
@@ -44,7 +44,7 @@ clockintr(Ureg *)
 	long v;
 
 	v = -getdec();
-	if(v > clkreload/2){
+	if(v > (clkreload >> 1)){
 		if(v > clkreload)
 			m->ticks += v/clkreload;
 		v = 0;

+ 38 - 24
sys/src/9/ppc/devirq.c

@@ -27,16 +27,16 @@ enum{
 };
 
 static Dirtab irqdir[]={
-	".",			{Qdir, 0, QTDIR},	0,		DMDIR|0555,
-	"irq1",		{Qirq1},			0,		0666,
-	"irq2",		{Qirq2},			0,		0666,
-	"irq3",		{Qirq1},			0,		0666,
-	"irq4",		{Qirq1},			0,		0666,
-	"irq5",		{Qirq1},			0,		0666,
-	"irq6",		{Qirq1},			0,		0666,
-	"irq7",		{Qirq1},			0,		0666,
-	"mstimer",	{Qmstimer},		0,		0666,
-	"fpgareset",	{Qfpgareset},		0,		0222,
+	".",		{Qdir, 0, QTDIR},	0,	DMDIR|0555,
+	"irq1",		{Qirq1},		0,	0666,
+	"irq2",		{Qirq2},		0,	0666,
+	"irq3",		{Qirq1},		0,	0666,
+	"irq4",		{Qirq1},		0,	0666,
+	"irq5",		{Qirq1},		0,	0666,
+	"irq6",		{Qirq1},		0,	0666,
+	"irq7",		{Qirq1},		0,	0666,
+	"mstimer",	{Qmstimer},		0,	0666,
+	"fpgareset",	{Qfpgareset},		0,	0222,
 };
 
 enum
@@ -52,17 +52,18 @@ Cmdtab irqmsg[] =
 {
 	CMinterrupt,	"interrupt",	2,
 	CMmode,		"mode",		2,
-	CMreset,		"reset",		1,
+	CMreset,	"reset",	1,
 	CMwait,		"wait",		1,
-	CMdebug,		"debug",		1,
+	CMdebug,	"debug",	1,
 };
 
 typedef struct Irqconfig Irqconfig;
 struct Irqconfig {
-	int		intenable;		/* Interrupts are enabled */
+	int		intenable;	/* Interrupts are enabled */
 	int		mode;		/* level == 0; edge == 1 */
-	ulong	interrupts;	/* Count interrupts */
-	Rendez	r;			/* Rendez-vous point for interrupt waiting */
+	ulong		interrupts;	/* Count interrupts */
+	ulong		sleepints;	/* interrupt count when waiting */
+	Rendez		r;		/* Rendez-vous point for interrupt waiting */
 	Irqconfig	*next;
 	Timer;
 };
@@ -71,7 +72,7 @@ Irqconfig *irqconfig[NIRQ];	/* irqconfig[0] is not used */
 Lock irqlock;
 
 static void interrupt(Ureg*, void*);
-static void ticmstimer(Ureg*, Timer*);
+void dumpvno(void);
 
 static void
 ticmstimer(Ureg*, Timer *t)
@@ -183,6 +184,15 @@ irqclose(Chan *c)
 	free(ic);
 }
 
+static int
+irqtfn(void *arg)
+{
+	Irqconfig *ic;
+
+	ic = arg;
+	return ic->sleepints != ic->interrupts;
+}
+
 static long
 irqread(Chan *c, void *buf, long n, vlong)
 {
@@ -195,18 +205,19 @@ irqread(Chan *c, void *buf, long n, vlong)
 	irq = (ulong)c->qid.path;
 	if(irq == Qdir)
 		return devdirread(c, buf, n, irqdir, nelem(irqdir), devgen);
-	if(irq >= Qmstimer){
+	if(irq > Qmstimer){
 		print("irqread 0x%llux\n", c->qid.path);
 		error(Egreg);
 	}
 	ic = c->aux;
 	if (ic->intenable == 0)
 		error("disabled");
-	sleep(&ic->r, return0, 0);
+	ic->sleepints = ic->interrupts;
+	sleep(&ic->r, irqtfn, ic);
 	if (irq == Qmstimer)
 		snprint(tmp, sizeof tmp, "%11lud %d", ic->interrupts, ic->mode);
 	else
-		snprint(tmp, sizeof tmp, "%11lud %s", ic->interrupts, ic->mode?"edge":"level");
+		snprint(tmp, sizeof tmp, "%11lud %s", ic->interrupts, ic->mode ?"edge":"level");
 	n = readstr(0, buf, n, tmp);
 	return n;
 }
@@ -249,6 +260,7 @@ irqwrite(Chan *c, void *a, long n, vlong)
 		if (strcmp(cb->f[1], "on") == 0){
 			ilock(&irqlock);
 			irqenable(ic, irq);
+			iomem->siprr = 0x65009770;
 			iunlock(&irqlock);
 		}else if (strcmp(cb->f[1], "off") == 0){
 			ilock(&irqlock);
@@ -268,10 +280,10 @@ irqwrite(Chan *c, void *a, long n, vlong)
 			}
 			ic->tns = MS2NS(ic->mode);
 		}else if (strcmp(cb->f[1], "level") == 0){
-			ic->mode = 0;
+			ic->mode = Level;
 			iomem->siexr &= ~(0x8000 >> irq);
 		}else if (strcmp(cb->f[1], "edge") == 0){
-			ic->mode = 1;
+			ic->mode = Edge;
 			iomem->siexr |= 0x8000 >> irq;
 		}else
 			error(Ebadarg);
@@ -282,13 +294,15 @@ irqwrite(Chan *c, void *a, long n, vlong)
 	case CMwait:
 		if (ic->intenable == 0)
 			error("interrupts are off");
-		sleep(&ic->r, return0, 0);
+		ic->sleepints = ic->interrupts;
+		sleep(&ic->r, irqtfn, ic);
 		break;
 	case CMdebug:
-		print("simr h/l 0x%lux/0x%lux, sipnr h/l 0x%lux/0x%lux, siexr 0x%lux\n",
+		print("simr h/l 0x%lux/0x%lux, sipnr h/l 0x%lux/0x%lux, siexr 0x%lux, siprr 0x%lux\n",
 			iomem->simr_h, iomem->simr_l,
 			iomem->sipnr_h, iomem->sipnr_l,
-			iomem->siexr);
+			iomem->siexr, iomem->siprr);
+		dumpvno();
 	}
 	poperror();
 	free(cb);

+ 324 - 61
sys/src/9/ppc/etherfcc.c

@@ -13,13 +13,16 @@
 #include "../port/netif.h"
 
 #include "etherif.h"
+#include "ethermii.h"
+
+#define DBG 1
 
 enum {
-	Nrdre		= 128,	/* receive descriptor ring entries */
-	Ntdre		= 128,	/* transmit descriptor ring entries */
+	Nrdre		= 128,			/* receive descriptor ring entries */
+	Ntdre		= 128,			/* transmit descriptor ring entries */
 
 	Rbsize		= ETHERMAXTU+4,		/* ring buffer size (+4 for CRC) */
-	Bufsize		= (Rbsize+7)&~7,		/* aligned */
+	Bufsize		= Rbsize+CACHELINESZ,	/* extra room for alignment */
 };
 
 enum {
@@ -32,7 +35,7 @@ enum {
 	RxeCR=		SBIT(13),
 	RxeOV=		SBIT(14),
 	RxeCL=		SBIT(15),
-	RxError=		(RxeLG|RxeNO|RxeSH|RxeCR|RxeOV|RxeCL),	/* various error flags */
+	RxError=	(RxeLG|RxeNO|RxeSH|RxeCR|RxeOV|RxeCL),	/* various error flags */
 
 	/* ether-specific Tx BD bits */
 	TxPad=		SBIT(1),	/* pad short frames */
@@ -45,21 +48,22 @@ enum {
 	TxeCSL=		SBIT(15),
 
 	/* psmr */
-	PRO=		BIT(9),	/* promiscuous mode */
-	LPB=			BIT(3),	/* local protect bit */
-	FDE=		BIT(5),	/* full duplex ethernet */
 	CRCE=		BIT(24),	/* Ethernet CRC */
+	FCE=		BIT(10),	/* flow control */
+	PRO=		BIT(9),		/* promiscuous mode */
+	FDE=		BIT(5),		/* full duplex ethernet */
+	LPB=		BIT(3),		/* local protect bit */
 
 	/* gfmr */
 	ENET=		0xc,		/* ethernet mode */
 	ENT=		BIT(27),
 	ENR=		BIT(26),
-	TCI=			BIT(2),
+	TCI=		BIT(2),
 
 	/* FCC function code register */
 	GBL=		0x20,
-	BO=			0x18,
-	EB=			0x10,	/* Motorola byte order */
+	BO=		0x18,
+	EB=		0x10,		/* Motorola byte order */
 	TC2=		0x04,
 	DTB=		0x02,
 	BDB=		0x01,
@@ -68,13 +72,18 @@ enum {
 	GRA=		SBIT(8),
 	RXC=		SBIT(9),
 	TXC=		SBIT(10),
-	TXE=			SBIT(11),
-	RXF=			SBIT(12),
-	BSY=			SBIT(13),
+	TXE=		SBIT(11),
+	RXF=		SBIT(12),
+	BSY=		SBIT(13),
 	TXB=		SBIT(14),
 	RXB=		SBIT(15),
 };
 
+enum {		/* Mcr */
+	MDIread	=	0x60020000,	/* read opcode */
+	MDIwrite =	0x50020000,	/* write opcode */
+};
+
 typedef struct Etherparam Etherparam;
 struct Etherparam {
 /*0x00*/	FCCparam;
@@ -130,19 +139,24 @@ struct Etherparam {
 /*0x100*/
 };
 
-typedef struct {
+typedef struct Ctlr Ctlr;
+struct Ctlr {
 	Lock;
-	int		fccid;
-	int		port;
+	int	fccid;
+	int	port;
 	ulong	pmdio;
 	ulong	pmdck;
-	int		init;
-	int		active;
-	FCC*		fcc;
+	int	init;
+	int	active;
+	int	duplex;		/* 1 == full */
+	FCC*	fcc;
 
 	Ring;
+	Block*	rcvbufs[Nrdre];
+	Mii*	mii;
+	Timer;
 
-	ulong	interrupts;			/* statistics */
+	ulong	interrupts;	/* statistics */
 	ulong	deferred;
 	ulong	heartbeat;
 	ulong	latecoll;
@@ -151,12 +165,22 @@ typedef struct {
 	ulong	overrun;
 	ulong	carrierlost;
 	ulong	retrycount;
-} Ctlr;
+};
 
 static	int	fccirq[] = {0x20, 0x21, 0x22};
 static	int	fccid[] = {FCC1ID, FCC2ID, FCC3ID};
 
-int	ioringinit(Ring* r, int nrdre, int ntdre, int bufsize);
+#ifdef DBG
+ulong fccrhisto[16];
+ulong fccthisto[16];
+ulong fccrthisto[16];
+ulong fcctrhisto[16];
+ulong ehisto[0x80];
+#endif
+
+static int fccmiimir(Mii*, int, int);
+static int fccmiimiw(Mii*, int, int, int);
+static void fccltimer(Ureg*, Timer*);
 
 static void
 attach(Ether *ether)
@@ -164,9 +188,15 @@ attach(Ether *ether)
 	Ctlr *ctlr;
 
 	ctlr = ether->ctlr;
+	ilock(ctlr);
 	ctlr->active = 1;
 	ctlr->fcc->gfmr |= ENR|ENT;
-	eieio();
+	iunlock(ctlr);
+	ctlr->tmode = Tperiodic;
+	ctlr->tf = fccltimer;
+	ctlr->ta = ether;
+	ctlr->tns = 5000000000LL;	/* 5 seconds */
+	timeradd(ctlr);
 }
 
 static void
@@ -255,7 +285,7 @@ txstart(Ether *ether)
 		dcflush(dre, sizeof(BD));
 		dre->status = (dre->status & BDWrap) | BDReady|TxPad|BDInt|BDLast|TxTC;
 		dcflush(dre, sizeof(BD));
-		ctlr->fcc->ftodr = 1<<15;	/* transmit now */
+/*		ctlr->fcc->ftodr = 1<<15;	/* transmit now; Don't do this according to errata */
 		ctlr->ntq++;
 		ctlr->tdrh = NEXT(ctlr->tdrh, Ntdre);
 	}
@@ -275,11 +305,11 @@ transmit(Ether* ether)
 static void
 interrupt(Ureg*, void *arg)
 {
-	int len, status;
+	int len, status, rcvd, xmtd, restart;
 	ushort events;
 	Ctlr *ctlr;
 	BD *dre;
-	Block *b;
+	Block *b, *nb;
 	Ether *ether = arg;
 
 	ctlr = ether->ctlr;
@@ -291,25 +321,32 @@ interrupt(Ureg*, void *arg)
 	 * happen.
 	 */
 	events = ctlr->fcc->fcce;
-	eieio();
 	ctlr->fcc->fcce = events;		/* clear events */
-	eieio();
+
+#ifdef DBG
+	ehisto[events & 0x7f]++;
+#endif
+
 	ctlr->interrupts++;
 
-	if(events & RXB)
+	if(events & BSY)
 		ctlr->overrun++;
 	if(events & TXE)
 		ether->oerrs++;
 
+#ifdef DBG
+	rcvd = xmtd = 0;
+#endif
 	/*
 	 * Receiver interrupt: run round the descriptor ring logging
 	 * errors and passing valid receive data up to the higher levels
 	 * until we encounter a descriptor still owned by the chip.
 	 */
-	if(events & (RXF|RXB)){
+	if(events & RXF){
 		dre = &ctlr->rdr[ctlr->rdrx];
 		dczap(dre, sizeof(BD));
 		while(((status = dre->status) & BDEmpty) == 0){
+			rcvd++;
 			if(status & RxError || (status & (BDFirst|BDLast)) != (BDFirst|BDLast)){
 				if(status & (RxeLG|RxeSH))
 					ether->buffs++;
@@ -320,17 +357,22 @@ interrupt(Ureg*, void *arg)
 				if(status & RxeOV)
 					ether->overflows++;
 				print("eth rx: %ux\n", status);
-			}
-			else{
+			}else{
 				/*
 				 * We have a packet. Read it in.
 				 */
 				len = dre->length-4;
-				dczap(KADDR(dre->addr), len);
-				if((b = iallocb(len)) != 0){
-					memmove(b->wp, KADDR(dre->addr), len);
+				b = ctlr->rcvbufs[ctlr->rdrx];
+				assert(dre->addr == PADDR(b->rp));
+				dczap(b->rp, len);
+				if(nb = iallocb(Bufsize)){
 					b->wp += len;
 					etheriq(ether, b, 1);
+					b = nb;
+					b->rp = (uchar*)(((ulong)b->rp + CACHELINESZ-1) & ~(CACHELINESZ-1));
+					b->wp = b->rp;
+					ctlr->rcvbufs[ctlr->rdrx] = b;
+					ctlr->rdr[ctlr->rdrx].addr = PADDR(b->wp);
 				}else
 					ether->soverflows++;
 			}
@@ -353,7 +395,8 @@ interrupt(Ureg*, void *arg)
 	 * Transmitter interrupt: handle anything queued for a free descriptor.
 	 */
 	if(events & (TXB|TXE)){
-		lock(ctlr);
+		ilock(ctlr);
+		restart = 0;
 		while(ctlr->ntq){
 			dre = &ctlr->tdr[ctlr->tdri];
 			dczap(dre, sizeof(BD));
@@ -372,6 +415,8 @@ interrupt(Ureg*, void *arg)
 				ctlr->underrun++;
 			if(status & TxeCSL)
 				ctlr->carrierlost++;
+			if(status & (TxeLC|TxeRL|TxeUN))
+				restart = 1;
 			ctlr->retrycount += (status>>2)&0xF;
 			b = ctlr->txb[ctlr->tdri];
 			if(b == nil)
@@ -380,38 +425,76 @@ interrupt(Ureg*, void *arg)
 			freeb(b);
 			ctlr->ntq--;
 			ctlr->tdri = NEXT(ctlr->tdri, Ntdre);
+			xmtd++;
 		}
 
-		if(events & TXE)
+		if(restart){
+			ctlr->fcc->gfmr &= ~ENT;
+			delay(10);
+			ctlr->fcc->gfmr |= ENT;
 			cpmop(RestartTx, ctlr->fccid, 0xc);
-
+		}
 		txstart(ether);
-		unlock(ctlr);
+		iunlock(ctlr);
 	}
+#ifdef DBG
+	if(rcvd >= nelem(fccrhisto))
+		rcvd = nelem(fccrhisto) - 1;
+	if(xmtd >= nelem(fccthisto))
+		xmtd = nelem(fccthisto) - 1;
+	if(rcvd)
+		fcctrhisto[xmtd]++;
+	else
+		fccthisto[xmtd]++;
+	if(xmtd)
+		fccrthisto[rcvd]++;
+	else
+		fccrhisto[rcvd]++;
+#endif
 }
 
 static long
 ifstat(Ether* ether, void* a, long n, ulong offset)
 {
 	char *p;
-	int len;
+	int len, i, r;
 	Ctlr *ctlr;
+	MiiPhy *phy;
 
 	if(n == 0)
 		return 0;
 
 	ctlr = ether->ctlr;
 
-	p = malloc(READSTR);
-	len = snprint(p, READSTR, "interrupts: %lud\n", ctlr->interrupts);
-	len += snprint(p+len, READSTR-len, "carrierlost: %lud\n", ctlr->carrierlost);
-	len += snprint(p+len, READSTR-len, "heartbeat: %lud\n", ctlr->heartbeat);
-	len += snprint(p+len, READSTR-len, "retrylimit: %lud\n", ctlr->retrylim);
-	len += snprint(p+len, READSTR-len, "retrycount: %lud\n", ctlr->retrycount);
-	len += snprint(p+len, READSTR-len, "latecollisions: %lud\n", ctlr->latecoll);
-	len += snprint(p+len, READSTR-len, "rxoverruns: %lud\n", ctlr->overrun);
-	len += snprint(p+len, READSTR-len, "txunderruns: %lud\n", ctlr->underrun);
-	snprint(p+len, READSTR-len, "framesdeferred: %lud\n", ctlr->deferred);
+	p = malloc(2*READSTR);
+	len = snprint(p, 2*READSTR, "interrupts: %lud\n", ctlr->interrupts);
+	len += snprint(p+len, 2*READSTR-len, "carrierlost: %lud\n", ctlr->carrierlost);
+	len += snprint(p+len, 2*READSTR-len, "heartbeat: %lud\n", ctlr->heartbeat);
+	len += snprint(p+len, 2*READSTR-len, "retrylimit: %lud\n", ctlr->retrylim);
+	len += snprint(p+len, 2*READSTR-len, "retrycount: %lud\n", ctlr->retrycount);
+	len += snprint(p+len, 2*READSTR-len, "latecollisions: %lud\n", ctlr->latecoll);
+	len += snprint(p+len, 2*READSTR-len, "rxoverruns: %lud\n", ctlr->overrun);
+	len += snprint(p+len, 2*READSTR-len, "txunderruns: %lud\n", ctlr->underrun);
+	len += snprint(p+len, 2*READSTR-len, "framesdeferred: %lud\n", ctlr->deferred);
+	miistatus(ctlr->mii);
+	phy = ctlr->mii->curphy;
+	len += snprint(p+len, 2*READSTR-len, "phy: link=%d, tfc=%d, rfc=%d, speed=%d, fd=%d\n",
+		phy->link, phy->tfc, phy->rfc, phy->speed, phy->fd);
+
+#ifdef DBG
+	if(ctlr->mii != nil && ctlr->mii->curphy != nil){
+		len += snprint(p+len, 2*READSTR, "phy:   ");
+		for(i = 0; i < NMiiPhyr; i++){
+			if(i && ((i & 0x07) == 0))
+				len += snprint(p+len, 2*READSTR-len, "\n       ");
+			r = miimir(ctlr->mii, i);
+			len += snprint(p+len, 2*READSTR-len, " %4.4uX", r);
+		}
+		snprint(p+len, 2*READSTR-len, "\n");
+	}
+#endif
+	snprint(p+len, 2*READSTR-len, "\n");
+
 	n = readstr(offset, a, n, p);
 	free(p);
 
@@ -421,11 +504,12 @@ ifstat(Ether* ether, void* a, long n, ulong offset)
 /*
  * This follows the MPC8260 user guide: section28.9's initialisation sequence.
  */
-static void
+static int
 fccsetup(Ctlr *ctlr, FCC *fcc, uchar *ea)
 {
 	int i;
 	Etherparam *p;
+	MiiPhy *phy;
 
 	/* Turn Ethernet off */
 	fcc->gfmr &= ~(ENR | ENT);
@@ -434,7 +518,7 @@ fccsetup(Ctlr *ctlr, FCC *fcc, uchar *ea)
 	switch(ctlr->port) {
 	default:
 		iopunlock();
-		return;
+		return -1;
 	case 0:
 		/* Step 1 (Section 28.9), write the parallel ports */
 		ctlr->pmdio = 0x01000000;
@@ -509,12 +593,11 @@ fccsetup(Ctlr *ctlr, FCC *fcc, uchar *ea)
 	memset(p, 0, sizeof(Etherparam));
 
 	/* Step 4 */
-//	fcc->gfmr |= (TCI | ENET);
 	fcc->gfmr |= ENET;
 
 	/* Step 5 */
-	fcc->fpsmr = CRCE | FDE | LPB;		/* full duplex operation */
-//	fcc->fpsmr = CRCE;		/* half duplex operation */
+	fcc->fpsmr = CRCE | FDE | LPB;	/* full duplex operation */
+	ctlr->duplex = ~0;
 
 	/* Step 6 */
 	fcc->fdsr = 0xd555;
@@ -530,11 +613,11 @@ fccsetup(Ctlr *ctlr, FCC *fcc, uchar *ea)
 
 	p->retlim = 15;	/* retry limit */
 
-	p->mrblr = Bufsize;
+	p->mrblr = (Rbsize+0x1f)&~0x1f;		/* multiple of 32 */
 	p->mflr = Rbsize;
-	p->minflr = ETHERMINTU + 4;
-	p->maxd1 = (Rbsize+3) & ~3;
-	p->maxd2 = (Rbsize+3) & ~3;
+	p->minflr = ETHERMINTU;
+	p->maxd1 = (Rbsize+7) & ~7;
+	p->maxd2 = (Rbsize+7) & ~7;
 
 	for(i=0; i<Eaddrlen; i+=2)
 		p->paddr[2-i/2] = (ea[i+1]<<8)|ea[i];
@@ -558,7 +641,33 @@ fccsetup(Ctlr *ctlr, FCC *fcc, uchar *ea)
 	/* Step 13, Issue the Init Tx and Rx command, specifying 0xc for ethernet*/
 	cpmop(InitRxTx, fccid[ctlr->port], 0xc);
 
-	// Step 14, Enable ethernet: done at attach time
+	/* Step 14, Link management */
+	if((ctlr->mii = malloc(sizeof(Mii))) == nil)
+		return -1;
+	ctlr->mii->mir = fccmiimir;
+	ctlr->mii->miw = fccmiimiw;
+	ctlr->mii->ctlr = ctlr;
+
+	if(mii(ctlr->mii, ~0) == 0 || (phy = ctlr->mii->curphy) == nil){
+		free(ctlr->mii);
+		ctlr->mii = nil;
+		return -1;
+	}
+	miiane(ctlr->mii, ~0, ~0, ~0);
+#ifdef DBG
+	print("oui=%X, phyno=%d, ", phy->oui, phy->phyno);
+	print("anar=%ux, ", phy->anar);
+	print("fc=%ux, ", phy->fc);
+	print("mscr=%ux, ", phy->mscr);
+
+	print("link=%ux, ", phy->link);
+	print("speed=%ux, ", phy->speed);
+	print("fd=%ux, ", phy->fd);
+	print("rfc=%ux, ", phy->rfc);
+	print("tfc=%ux\n", phy->tfc);
+#endif
+	/* Step 15, Enable ethernet: done at attach time */
+	return 0;
 }
 
 static int
@@ -567,6 +676,8 @@ reset(Ether* ether)
 	uchar ea[Eaddrlen];
 	Ctlr *ctlr;
 	FCC *fcc;
+	Block *b;
+	int i;
 
 	if(m->cpuhz < 24000000){
 		print("%s ether: system speed must be >= 24MHz for ether use\n", ether->type);
@@ -593,8 +704,15 @@ reset(Ether* ether)
 	 * PowerQUICC II manual (Section 28.6).  When they are allocated
 	 * in DPram and the Dcache is enabled, the processor will hang
 	 */
-	if(ioringinit(ctlr, Nrdre, Ntdre, Bufsize) < 0)
+	if(ioringinit(ctlr, Nrdre, Ntdre, 0) < 0)
 		panic("etherfcc init");
+	for(i = 0; i < Nrdre; i++){
+		b = iallocb(Bufsize);
+		b->rp = (uchar*)(((ulong)b->rp + CACHELINESZ-1) & ~(CACHELINESZ-1));
+		b->wp = b->rp;
+		ctlr->rcvbufs[i] = b;
+		ctlr->rdr[i].addr = PADDR(b->wp);
+	}
 
 	fccsetup(ctlr, fcc, ether->ea);
 
@@ -626,3 +744,148 @@ etherfcclink(void)
 {
 	addethercard("fcc", reset);
 }
+
+static void
+nanodelay(void)
+{
+	static int count;
+	int i;
+
+	for(i = 0; i < 500; i++)
+		count++;
+	return;
+}
+
+static
+void miiwriteloop(Ctlr *ctlr, Port *port, int cnt, ulong cmd)
+{
+	int i;
+
+	for(i = 0; i < cnt; i++){
+		port->pdat &= ~ctlr->pmdck;
+		if(cmd & BIT(i))
+			port->pdat |= ctlr->pmdio;
+		else
+			port->pdat &= ~ctlr->pmdio;
+		nanodelay();
+		port->pdat |= ctlr->pmdck;
+		nanodelay();
+	}
+}
+
+static int
+fccmiimiw(Mii *mii, int pa, int ra, int data)
+{
+	int x;
+	Port *port;
+	ulong cmd;
+	Ctlr *ctlr;
+
+	/*
+	 * MII Management Interface Write.
+	 */
+
+	ctlr = mii->ctlr;
+	port = iomem->port + 3;
+	cmd = MDIwrite | (pa<<(5+2+16))| (ra<<(2+16)) | (data & 0xffff);
+
+	x = splhi();
+
+	port->pdir |= (ctlr->pmdio|ctlr->pmdck);
+	nanodelay();
+
+	miiwriteloop(ctlr, port, 32, ~0);
+	miiwriteloop(ctlr, port, 32, cmd);
+
+	port->pdir |= (ctlr->pmdio|ctlr->pmdck);
+	nanodelay();
+
+	miiwriteloop(ctlr, port, 32, ~0);
+
+	splx(x);
+	return 1;
+}
+
+static int
+fccmiimir(Mii *mii, int pa, int ra)
+{
+	int data, i, x;
+	Port *port;
+	ulong cmd;
+	Ctlr *ctlr;
+
+	ctlr = mii->ctlr;
+	port = iomem->port + 3;
+
+	cmd = MDIread | pa<<(5+2+16) | ra<<(2+16);
+
+	x = splhi();
+	port->pdir |= (ctlr->pmdio|ctlr->pmdck);
+	nanodelay();
+
+	miiwriteloop(ctlr, port, 32, ~0);
+
+	/* Clock out the first 14 MS bits of the command */
+	miiwriteloop(ctlr, port, 14, cmd);
+
+	/* Turn-around */
+	port->pdat &= ~ctlr->pmdck;
+	port->pdir &= ~ctlr->pmdio;
+	nanodelay();
+
+	/* For read, clock in 18 bits, use 16 */
+	data = 0;
+	for(i=0; i<18; i++){
+		data <<= 1;
+		if(port->pdat & ctlr->pmdio)
+			data |= 1;
+		port->pdat |= ctlr->pmdck;
+		nanodelay();
+		port->pdat &= ~ctlr->pmdck;
+		nanodelay();
+	}
+	port->pdir |= (ctlr->pmdio|ctlr->pmdck);
+	nanodelay();
+	miiwriteloop(ctlr, port, 32, ~0);
+	splx(x);
+	return data & 0xffff;
+}
+
+static void
+fccltimer(Ureg*, Timer *t)
+{
+	Ether *ether;
+	Ctlr *ctlr;
+	MiiPhy *phy;
+	ulong gfmr;
+
+	ether = t->ta;
+	ctlr = ether->ctlr;
+	if(ctlr->mii == nil || ctlr->mii->curphy == nil)
+		return;
+	phy = ctlr->mii->curphy;
+	if(miistatus(ctlr->mii) < 0){
+		print("miistatus failed\n");
+		return;
+	}
+	if(phy->link == 0){
+		print("link lost\n");
+		return;
+	}
+	ether->mbps = phy->speed;
+
+	if(phy->fd != ctlr->duplex)
+		print("set duplex\n");
+	ilock(ctlr);
+	gfmr = ctlr->fcc->gfmr;
+	if(phy->fd != ctlr->duplex){
+		ctlr->fcc->gfmr &= ~(ENR|ENT);
+		if(phy->fd)
+			ctlr->fcc->fpsmr |= FDE | LPB;		/* full duplex operation */
+		else
+			ctlr->fcc->fpsmr &= ~(FDE | LPB);	/* half duplex operation */
+		ctlr->duplex = phy->fd;
+	}
+	ctlr->fcc->gfmr = gfmr;
+	iunlock(ctlr);
+}

+ 58 - 55
sys/src/9/ppc/m8260.c

@@ -26,26 +26,26 @@ struct {
 	ulong	hi;
 	ulong	lo;
 } vec2mask[64]	= {
-[0]	= {0,			0	},	/* Error,			No interrupt */
-[1]	= {0,			BIT(16)},	/* I2C */
-[2]	= {0,			BIT(17)},	/* SPI */
-[3]	= {0,			BIT(18)},	/* Risc Timers */
-[4]	= {0,			BIT(19)},	/* SMC1 */
-[5]	= {0,			BIT(20)},	/* SMC2 */
-[6]	= {0,			BIT(21)},	/* IDMA1 */
-[7]	= {0,			BIT(22)},	/* IDMA2 */
-[8]	= {0,			BIT(23)},	/* IDMA3 */
-[9]	= {0,			BIT(24)},	/* IDMA4 */
-[10]	= {0,			BIT(25)},	/* SDMA */
-[11]	= {0,			0	},	/* Reserved */
-[12]	= {0,			BIT(27)},	/* Timer1 */
-[13]	= {0,			BIT(28)},	/* Timer2 */
-[14]	= {0,			BIT(29)},	/* Timer3 */
-[15]	= {0,			BIT(30)},	/* Timer4 */
+[0]	= {0,		0	},	/* Error, No interrupt */
+[1]	= {0,		BIT(16)	},	/* I2C */
+[2]	= {0,		BIT(17)	},	/* SPI */
+[3]	= {0,		BIT(18)	},	/* Risc Timers */
+[4]	= {0,		BIT(19)	},	/* SMC1 */
+[5]	= {0,		BIT(20)	},	/* SMC2 */
+[6]	= {0,		BIT(21)	},	/* IDMA1 */
+[7]	= {0,		BIT(22)	},	/* IDMA2 */
+[8]	= {0,		BIT(23)	},	/* IDMA3 */
+[9]	= {0,		BIT(24)	},	/* IDMA4 */
+[10]	= {0,		BIT(25)	},	/* SDMA */
+[11]	= {0,		0	},	/* Reserved */
+[12]	= {0,		BIT(27)	},	/* Timer1 */
+[13]	= {0,		BIT(28)	},	/* Timer2 */
+[14]	= {0,		BIT(29)	},	/* Timer3 */
+[15]	= {0,		BIT(30)	},	/* Timer4 */
 
 [16]	= {BIT(29),	0	},	/* TMCNT */
 [17]	= {BIT(30),	0	},	/* PIT */
-[18]	= {0,			0	},	/* Reserved */
+[18]	= {0,		0	},	/* Reserved */
 [19]	= {BIT(17),	0	},	/* IRQ1 */
 [20]	= {BIT(18),	0	},	/* IRQ2 */
 [21]	= {BIT(19),	0	},	/* IRQ3 */
@@ -53,29 +53,29 @@ struct {
 [23]	= {BIT(21),	0	},	/* IRQ5 */
 [24]	= {BIT(22),	0	},	/* IRQ6 */
 [25]	= {BIT(23),	0	},	/* IRQ7 */
-[26]	= {0,			0	},	/* Reserved */
-[27]	= {0,			0	},	/* Reserved */
-[28]	= {0,			0	},	/* Reserved */
-[29]	= {0,			0	},	/* Reserved */
-[30]	= {0,			0	},	/* Reserved */
-[31]	= {0,			0	},	/* Reserved */
-
-[32]	= {0,			BIT(0)},	/* FCC1 */
-[33]	= {0,			BIT(1)},	/* FCC2 */
-[34]	= {0,			BIT(2)},	/* FCC3 */
-[35]	= {0,			0	},	/* Reserved */
-[36]	= {0,			BIT(4)},	/* MCC1 */
-[37]	= {0,			BIT(5)},	/* MCC2 */
-[38]	= {0,			0	},	/* Reserved */
-[39]	= {0,			0	},	/* Reserved */
-[40]	= {0,			BIT(8)},	/* SCC1 */
-[41]	= {0,			BIT(9)},	/* SCC2 */
-[42]	= {0,			BIT(10)},	/* SCC3 */
-[43]	= {0,			BIT(11)},	/* SCC4 */
-[44]	= {0,			0	},	/* Reserved */
-[45]	= {0,			0	},	/* Reserved */
-[46]	= {0,			0	},	/* Reserved */
-[47]	= {0,			0	},	/* Reserved */
+[26]	= {0,		0	},	/* Reserved */
+[27]	= {0,		0	},	/* Reserved */
+[28]	= {0,		0	},	/* Reserved */
+[29]	= {0,		0	},	/* Reserved */
+[30]	= {0,		0	},	/* Reserved */
+[31]	= {0,		0	},	/* Reserved */
+
+[32]	= {0,		BIT(0)	},	/* FCC1 */
+[33]	= {0,		BIT(1)	},	/* FCC2 */
+[34]	= {0,		BIT(2)	},	/* FCC3 */
+[35]	= {0,		0	},	/* Reserved */
+[36]	= {0,		BIT(4)	},	/* MCC1 */
+[37]	= {0,		BIT(5)	},	/* MCC2 */
+[38]	= {0,		0	},	/* Reserved */
+[39]	= {0,		0	},	/* Reserved */
+[40]	= {0,		BIT(8)	},	/* SCC1 */
+[41]	= {0,		BIT(9)	},	/* SCC2 */
+[42]	= {0,		BIT(10)	},	/* SCC3 */
+[43]	= {0,		BIT(11)	},	/* SCC4 */
+[44]	= {0,		0	},	/* Reserved */
+[45]	= {0,		0	},	/* Reserved */
+[46]	= {0,		0	},	/* Reserved */
+[47]	= {0,		0	},	/* Reserved */
 
 [48]	= {BIT(15),	0	},	/* PC15 */
 [49]	= {BIT(14),	0	},	/* PC14 */
@@ -83,16 +83,16 @@ struct {
 [51]	= {BIT(12),	0	},	/* PC12 */
 [52]	= {BIT(11),	0	},	/* PC11 */
 [53]	= {BIT(10),	0	},	/* PC10 */
-[54]	= {BIT(9),		0	},	/* PC9 */
-[55]	= {BIT(8),		0	},	/* PC8 */
-[56]	= {BIT(7),		0	},	/* PC7 */
-[57]	= {BIT(6),		0	},	/* PC6 */
-[58]	= {BIT(5),		0	},	/* PC5 */
-[59]	= {BIT(4),		0	},	/* PC4 */
-[60]	= {BIT(3),		0	},	/* PC3 */
-[61]	= {BIT(2),		0	},	/* PC2 */
-[62]	= {BIT(1),		0	},	/* PC1 */
-[63]	= {BIT(0),		0	},	/* PC0 */
+[54]	= {BIT(9),	0	},	/* PC9 */
+[55]	= {BIT(8),	0	},	/* PC8 */
+[56]	= {BIT(7),	0	},	/* PC7 */
+[57]	= {BIT(6),	0	},	/* PC6 */
+[58]	= {BIT(5),	0	},	/* PC5 */
+[59]	= {BIT(4),	0	},	/* PC4 */
+[60]	= {BIT(3),	0	},	/* PC3 */
+[61]	= {BIT(2),	0	},	/* PC2 */
+[62]	= {BIT(1),	0	},	/* PC1 */
+[63]	= {BIT(0),	0	},	/* PC0 */
 };
 
 /* Blast memory layout:
@@ -556,7 +556,7 @@ bdalloc(int n)
 
 /*
  * Initialise receive and transmit buffer rings.  Only used for FCC
- * EThernet now.
+ * Ethernet now.
  *
  * Ioringinit will allocate the buffer descriptors in normal memory
  * and NOT in Dual-Ported Ram, as prescribed by the MPC8260
@@ -582,11 +582,14 @@ ioringinit(Ring* r, int nrdre, int ntdre, int bufsize)
 	r->nrdre = nrdre;
 	if(r->rdr == nil)
 		r->rdr = xspanalloc(nrdre*sizeof(BD), 0, 8);
-	if(r->rrb == nil)
-		r->rrb = xspanalloc(nrdre*bufsize, 0, CACHELINESZ);
-	if(r->rdr == nil || r->rrb == nil)
+	if(r->rdr == nil)
 		return -1;
-	x = PADDR(r->rrb);
+	if(r->rrb == nil && bufsize){
+		r->rrb = xspanalloc(nrdre*bufsize, 0, CACHELINESZ);
+		if(r->rrb == nil)
+			return -1;
+	}
+	x = bufsize ? PADDR(r->rrb) : 0;
 	for(i = 0; i < nrdre; i++){
 		r->rdr[i].length = 0;
 		r->rdr[i].addr = x;

+ 17 - 17
sys/src/9/ppc/m8260.h

@@ -8,27 +8,27 @@ struct BD {
 
 enum{
 	BDEmpty=	SBIT(0),
-	BDReady=		SBIT(0),
+	BDReady=	SBIT(0),
 	BDWrap=		SBIT(2),
 	BDInt=		SBIT(3),
 	BDLast=		SBIT(4),
-	BDFirst=		SBIT(5),
+	BDFirst=	SBIT(5),
 };
 
 typedef struct Ring Ring;
 
 struct Ring {
-	BD*		rdr;			/* receive descriptor ring */
-	void*	rrb;			/* receive ring buffers */
-	int		rdrx;			/* index into rdr */
-	int		nrdre;		/* length of rdr */
-
-	BD*		tdr;			/* transmit descriptor ring */
-	void**	txb;			/* corresponding transmit ring buffers */
-	int		tdrh;			/* host index into tdr */
-	int		tdri;			/* interface index into tdr */
-	int		ntdre;		/* length of tdr */
-	int		ntq;			/* pending transmit requests */
+	BD*	rdr;		/* receive descriptor ring */
+	void*	rrb;		/* receive ring buffers */
+	int	rdrx;		/* index into rdr */
+	int	nrdre;		/* length of rdr */
+
+	BD*	tdr;		/* transmit descriptor ring */
+	void**	txb;		/* corresponding transmit ring buffers */
+	int	tdrh;		/* host index into tdr */
+	int	tdri;		/* interface index into tdr */
+	int	ntdre;		/* length of tdr */
+	int	ntq;		/* pending transmit requests */
 };
 
 int	ioringinit(Ring*, int, int, int);
@@ -136,15 +136,15 @@ struct SCC {
 
 typedef struct FCC FCC;
 struct FCC {
-/*0x00*/	ulong	gfmr;	/*  general mode register 28.2/28-3 */
-/*0x04*/	ulong	fpsmr;	/*  protocol-specific mode reg. 29.13.2(ATM) 30.18.1(Ether) */
-/*0x08*/	ushort	ftodr;	/*  transmit on demand register 28.5/28-7 */
+/*0x00*/	ulong	gfmr;		/*  general mode register 28.2/28-3 */
+/*0x04*/	ulong	fpsmr;		/*  protocol-specific mode reg. 29.13.2(ATM) 30.18.1(Ether) */
+/*0x08*/	ushort	ftodr;		/*  transmit on demand register 28.5/28-7 */
 /*0x0A*/	ushort	Rsvd0A;
 /*0x0C*/	ushort	fdsr;		/*  data synchronization register 28.4/28-7 */
 /*0x0E*/	ushort	Rsvd0E;
 /*0x10*/	ushort	fcce;		/* event register 29.13.3 (ATM), 30.18.2 (Ethernet) */
 /*0x12*/	ushort	Rsvd12;
-/*0x14*/	ushort	fccm;	/* mask register */
+/*0x14*/	ushort	fccm;		/* mask register */
 /*0x16*/	ushort	Rsvd16;
 /*0x18*/	uchar	fccs;		/* status register 8 bits 31.10 (HDLC) */
 /*0x19*/	uchar	Rsvd19[3];

+ 80 - 33
sys/src/9/ppc/trap.c

@@ -112,27 +112,27 @@ char *regname[]={
 	"CAUSE",	"SRR1",
 	"PC",		"GOK",
 	"LR",		"CR",
-	"XER",	"CTR",
+	"XER",		"CTR",
 	"R0",		"R1",
 	"R2",		"R3",
 	"R4",		"R5",
 	"R6",		"R7",
 	"R8",		"R9",
-	"R10",	"R11",
-	"R12",	"R13",
-	"R14",	"R15",
-	"R16",	"R17",
-	"R18",	"R19",
-	"R20",	"R21",
-	"R22",	"R23",
-	"R24",	"R25",
-	"R26",	"R27",
-	"R28",	"R29",
-	"R30",	"R31",
-	"DCMP",	"ICMP",
+	"R10",		"R11",
+	"R12",		"R13",
+	"R14",		"R15",
+	"R16",		"R17",
+	"R18",		"R19",
+	"R20",		"R21",
+	"R22",		"R23",
+	"R24",		"R25",
+	"R26",		"R27",
+	"R28",		"R29",
+	"R30",		"R31",
+	"DCMP",		"ICMP",
 	"DMISS",	"IMISS",
 	"HASH1",	"HASH2",
-	"DAR",	"DSISR",
+	"DAR",		"DSISR",
 };
 
 void
@@ -385,37 +385,84 @@ int intrstack[5];
 uvlong intrtime[5];
 vlong lastoffset;
 int inintr;
+int nintr[10];
+int nintro;
+int dblintr[64];
+ulong thisto[32];
+ulong thistoo;
+vlong vnot[64];
+ulong vnon[64];
+
+void
+dumpvno(void)
+{
+	int i;
+
+	for(i = 0; i < nelem(vnon); i++){
+		if(vnon[i])
+			print("%d	%lld	%lud\n", i, vnot[i], vnon[i]);
+		vnot[i] = 0;
+		vnon[i] = 0;
+	}
+	for(i = 0; i < nelem(thisto); i++){
+		if(thisto[i]) print("%d	%lud\n", i, thisto[i]);
+		thisto[i] = 0;
+	}
+	if(thistoo) print("ovl	%lud\n", thistoo);
+	thistoo = 0;
+}
 
 void
 intr(Ureg *ureg)
 {
-	int vno;
+	int vno, pvno, i;
 	Vctl *ctl, *v;
 	void (*pt)(Proc*, int, vlong);
+	uvlong tt, x;
 
-	vno = intvec();
+	cycles(&tt);
 	pt = proctrace;
-	if(up && up->trace && pt)
-		pt(up, (vno << 16) | SInts, 0);
+	pvno = -1;
+	for(i = 0; i < 64; i++){
+		vno = intvec();
+		if(vno == 0)
+			break;
+		cycles(&x);
+		vnot[vno] -= x;
+		if(vno == pvno)
+			dblintr[vno]++;
+		pvno = vno;
+		if(pt && up && up->trace)
+			pt(up, (vno << 16) | SInts, 0);
+	
+		if(vno > nelem(vctl) || (ctl = vctl[vno]) == 0) {
+			iprint("spurious intr %d\n", vno);
+			return;
+		}
 
-//	intrstack[inintr - 1] = vno;
+		for(v = ctl; v != nil; v = v->next)
+			if(v->f)
+				v->f(ureg, v->a);
 
-	if(vno > nelem(vctl) || (ctl = vctl[vno]) == 0) {
-		iprint("spurious intr %d\n", vno);
-//		inintr--;
-		return;
-	}
+		intend(vno);	/* reenable the interrupt */
 
-	for(v = ctl; v != nil; v = v->next){
-		if(v->f)
-			v->f(ureg, v->a);
+		if(pt && up && up->trace)
+			pt(up, (vno << 16) | SInte, 0);
+		cycles(&x);
+		vnot[vno] += x;
+		vnon[vno]++;
 	}
-
-	intend(vno);	/* reenable the interrupt */
-	pt = proctrace;
-	if(up && up->trace && pt)
-		pt(up, (vno << 16) | SInte, 0);
-//	inintr--;
+	if(i < nelem(nintr))
+		nintr[i]++;
+	else
+		nintro++;
+	cycles(&x);
+	tt = x - tt;
+	i = tt / 3600;	 /* 100 microseconds units */
+	if(i < nelem(thisto))
+		thisto[i]++;
+	else
+		thistoo++;
 	preempted();
 }
 

+ 7 - 3
sys/src/libc/power/cycles.s

@@ -1,13 +1,17 @@
 #define TBRL	268
 #define TBRU	269		/* Time base Upper/Lower (Reading) */
 
-TEXT cycles(SB),1,$0	/* time stamp counter; _cycles since power up */
+/*
+ * time stamp counter; _cycles since power up
+ * Runs at fasthz/4 cycles per second (m->clkin>>3)
+ */
+TEXT cycles(SB),1,$0
 loop:
 	MOVW	SPR(TBRU),R7
 	MOVW	SPR(TBRL),R8
 	MOVW	SPR(TBRU),R5
-	CMP		R5,R7
-	BNE		loop
+	CMP	R5,R7
+	BNE	loop
 	MOVW	R7,0(R3)
 	MOVW	R8,4(R3)
 	RETURN