shithub: riscv

Download patch

ref: 6ecb921719c6cb64711de9a3f4c1e2334fd352b8
parent: 1633e20b32f9311c8ac7cf43aca194c355aff985
author: Aidan K. Wiggins <akw@oneiri.one>
date: Mon Nov 6 03:55:54 EST 2023

nusb/ether: implement link status for a88179

In addition to a179linkstatus(), there is now proper link detection on
start, and the phy no longer auto powers off when not talked to.

--- a/sys/src/cmd/nusb/ether/asix.c
+++ b/sys/src/cmd/nusb/ether/asix.c
@@ -46,6 +46,9 @@
 		Bmcranena	= 0x1000,	/* auto neg. enable */
 		Bmcrar		= 0x0200,	/* announce restart */
 
+	Miibmsr			= 0x01,
+		Bmsrlink	= 0x0004,
+
 	Miiad			= 0x04,		/* advertise reg. */
 		Adcsma		= 0x0001,
 		Ad1000f		= 0x0200,
@@ -421,11 +424,11 @@
 	Aphy			= 0x02,
 		Physts		= 0x02,
 		Phyid		= 0x03,
+		Phyfd		= 0x11,
 
 	/* Control */
 	Crxctl			= 0x0b,
 	Cmed			= 0x22,		/* medium status register */
-
 	Cmmsr			= 0x24,		/* control monitor */	
 		Mrwmp		= 0x04,
 		Mpmepol		= 0x20,
@@ -436,7 +439,6 @@
 		Cphyiprl	= 0x0020,
 
 	Cblkinq			= 0x2e,
-
 	Csclk			= 0x33,		/* select clock */
 		Sclkbcs		= 0x01,
 		Sclkacs		= 0x02,
@@ -443,10 +445,17 @@
 
 	Cpwtrl			= 0x54,
 	Cpwtrh			= 0x55,
+	Capo			= 0x91,		/* auto-power off phy */
 
-	Usbss 		= 0x04,
-	Usbhs		= 0x02,
+	/* USB/Link conn. */
 	Usbfs		= 0x01,
+	Usbhs		= 0x02,
+	Usbss 		= 0x04,
+	Link10		= 0x10,
+	Link100		= 0x20,
+	Link1000	= 0x40,
+
+	Linkfd		= 0x2000,
 };
 
 static int
@@ -580,6 +589,24 @@
 }
 
 static int
+a179linkup(Dev *d)
+{
+	int timeout;
+	ushort link;
+
+	timeout = 5000;
+	do{
+		link = a179miiread(d, Miibmsr);
+		if(link & Bmsrlink)
+			return 0;
+		sleep(50);
+	}while(timeout -= 50);
+
+	fprint(2, "%s: a179linkup: no link\n", argv0);
+	return -1;
+}
+
+static int
 a179promiscuous(Dev *d, int on)
 {
 	ushort rxctl;
@@ -605,6 +632,21 @@
 	return a179set2(d, Crxctl, rxctl);
 }
 
+static int
+a179linkspeed(Dev *d)
+{
+	uchar link;
+
+	a179get(d, Amac, Physts, 1, &link, 1);
+	if(link & Link1000)
+		return 1000;
+	if(link & Link100)
+		return 100;
+	if(link & Link10)
+		return 10;
+	return 0;
+}
+
 int
 a88179init(Dev *d)
 {
@@ -614,8 +656,9 @@
 		{0x07, 0xae, 0x07, 0x04, 0xff},
 		{0x07, 0xcc, 0x4c, 0x04, 0x08}
 	};
+	ushort mode, fd;
 	uchar link;
-	int bmcr, spd;
+	int spd;
 
 	a179set2(d, Cphy, 0);
 	a179set2(d, Cphy, Cphyiprl);
@@ -622,7 +665,6 @@
 	sleep(200);
 	a179set1(d, Csclk, Sclkacs|Sclkbcs);
 	sleep(100);
-	a179set(d, Amac, Cblkinq, 5, qctrl[0], 5);
 	a179set1(d, Cpwtrl, 0x34);
 	a179set1(d, Cpwtrh, 0x52);
 	if(setmac){
@@ -634,29 +676,40 @@
 		return -1;
 	if(a179set1(d, Cmmsr, Mpmetyp|Mpmepol|Mrwmp) < 0)
 		return -1;
-	if(a179set2(d, Cmed, Mall179) < 0)
+	if(a179set(d, Capo, 0, 0, nil, 0) < 0)
 		return -1;
 
+	if(a179linkup(d) < 0)
+		return -1;
+
+	spd = 3;	/* default bulkinq */
+	mode = Mtfc | Mrfc | Mre;
 	a179get(d, Amac, Physts, 1, &link, 1);
-	switch(link){
-		case Usbss: 		spd = 0; break;
-		case Usbhs: 		spd = 1; break;
-		case Usbss|Usbhs:	spd = 2; break;
-		default:		spd = 3;
-	}
+	if(link & Link1000){
+		mode |= Mgm|Mmhz|Mjfe|Munk;
+		if(link & Usbss)
+			spd = 0;
+		else if(link & Usbhs)
+			spd = 1;
+	}else if(link & Link100){
+		mode |= Mps;
+		if(link & (Usbss|Usbhs))
+			spd = 2;
+	} /* Link10 */
 	a179set(d, Amac, Cblkinq, 5, qctrl[spd], 5);
 	a179bufsz = 1024*(qctrl[spd][3]+2);
+	fd = a179miiread(d, Phyfd);
+	if(fd & Linkfd)
+		mode |= Mfd;
 
-	bmcr = a179miiread(d, Miibmcr);
-	if((bmcr & Bmcranena) != 0){
-		bmcr |= Bmcrar;
-		a179miiwrite(d, Miibmcr, bmcr);
-	}	
+	if(a179set2(d, Cmed, mode) < 0)
+		return -1;
 
 	epreceive = a179receive;
 	eptransmit = a179transmit;
 	eppromiscuous = a179promiscuous;
 	epmulticast = a179multicast;
+	eplinkspeed = a179linkspeed;
 
 	return 0;
 }