shithub: riscv

Download patch

ref: 08a080e8c2c775eda149d3e830bd4fad2c35f249
parent: b883050361d478ba29b6b3c07c200493994fb3be
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Jan 29 17:21:56 EST 2023

nusb/ether: support for asix ax88179 (thanks Aidan K. Wiggins)

Tested with tp-link UE305, works well.

From all other sources it seems this should also work for the
88178a, but I didn't have one on hand.

--- a/sys/src/9/boot/nusbrc
+++ b/sys/src/9/boot/nusbrc
@@ -19,6 +19,8 @@
 			nusb/ether -t a88772 $etherargs $id
 		case 0b951780 14eaab11 17370039 0411006e 050d5055
 			nusb/ether -t a88178 $etherargs $id
+		case 0b951790
+			nusb/ether -t a88179 $etherargs $id
 		case 2001abc1
 			nusb/ether -t aue $etherargs $id
 		case 0bda8150
--- a/sys/src/cmd/nusb/ether/asix.c
+++ b/sys/src/cmd/nusb/ether/asix.c
@@ -12,60 +12,33 @@
 #include "usb.h"
 #include "dat.h"
 
+/*
+ * Asix common
+ */
 enum
 {
-
-	/* Asix commands */
-	Cswmii		= 0x06,		/* set sw mii */
-	Crmii		= 0x07,		/* read mii reg */
-	Cwmii		= 0x08,		/* write mii reg */
-	Chwmii		= 0x0a,		/* set hw mii */
-	Creeprom	= 0x0b,		/* read eeprom */
-	Cwdis		= 0x0e,		/* write disable */
-	Cwena		= 0x0d,		/* write enable */
-	Crrxctl		= 0x0f,		/* read rx ctl */
-	Cwrxctl		= 0x10,		/* write rx ctl */
-	Cwipg		= 0x12,		/* write ipg */
-	Crmac		= 0x13,		/* read mac addr */
-	Crphy		= 0x19,		/* read phy id */
-	Cwmedium		= 0x1b,		/* write medium mode */
-	Crgpio		= 0x1e,		/* read gpio */
-	Cwgpio		= 0x1f,		/* write gpios */
-	Creset		= 0x20,		/* reset */
-	Cwphy		= 0x22,		/* select phy */
-
-	/* reset codes */
-	Rclear		= 0x00,
-	Rprte		= 0x04,
-	Rprl		= 0x08,
-	Riprl		= 0x20,
-	Rippd		= 0x40,
-
-	Gpiogpo1en	= 0x04,	/* gpio1 enable */,
-	Gpiogpo1		= 0x08,	/* gpio1 value */
-	Gpiogpo2en	= 0x10,	/* gpio2 enable */
-	Gpiogpo2		= 0x20,	/* gpio2 value */
-	Gpiorse		= 0x80,	/* gpio reload serial eeprom */
-
-	Pmask		= 0x1F,
-	Pembed		= 0x10,			/* embedded phy */
-
-	Mfd		= 0x002,		/* media */
-	Mac		= 0x004,
-	Mrfc		= 0x010,
-	Mtfc		= 0x020,
-	Mjfe		= 0x040,
-	Mre		= 0x100,
-	Mps		= 0x200,
+	Mgm		= 0x0001,		/* media */
+	Mfd		= 0x0002,
+	Mac		= 0x0004,
+	Mmhz		= 0x0008,
+	Mrfc		= 0x0010,
+	Mtfc		= 0x0020,
+	Mjfe		= 0x0040,
+	Mre		= 0x0100,
+	Mps		= 0x0200,
+	Munk		= 0x8000,
 	Mall772		= Mfd|Mrfc|Mtfc|Mps|Mac|Mre,
 	Mall178		= Mps|Mfd|Mac|Mrfc|Mtfc|Mjfe|Mre,
+	Mall179		= Mgm|Mfd|Mmhz|Mrfc|Mtfc|Mjfe|Munk|Mre,
 
-	Ipgdflt		= 0x15|0x0c|0x12,	/* default ipg0, 1, 2 */
-	Rxctlso		= 0x80,
+	Rxctldce	= 0x0100,		/* drop crcerr */
+	Rxctlso		= 0x80,			/* start operation */
+	Rxctlam		= 0x10,
 	Rxctlab		= 0x08,
 	Rxctlsep	= 0x04,
 	Rxctlamall	= 0x02,			/* all multicast */
 	Rxctlprom	= 0x01,			/* promiscuous */
+	Rxall179	= Rxctldce|Rxctlso|Rxctlab|Rxctlamall,
 
 	/* MII */
 	Miibmcr			= 0x00,		/* basic mode ctrl reg. */
@@ -90,7 +63,49 @@
 		Mtxrxdly	= 0x82,
 
 	Miic1000			= 0x09,
+};
 
+/*
+ *	a88178 & a88772
+ */
+enum
+{
+	/* Asix commands */
+	Cswmii		= 0x06,		/* set sw mii */
+	Crmii		= 0x07,		/* read mii reg */
+	Cwmii		= 0x08,		/* write mii reg */
+	Chwmii		= 0x0a,		/* set hw mii */
+	Creeprom	= 0x0b,		/* read eeprom */
+	Cwdis		= 0x0e,		/* write disable */
+	Cwena		= 0x0d,		/* write enable */
+	Crrxctl		= 0x0f,		/* read rx ctl */
+	Cwrxctl		= 0x10,		/* write rx ctl */
+	Cwipg		= 0x12,		/* write ipg */
+	Crmac		= 0x13,		/* read mac addr */
+	Crphy		= 0x19,		/* read phy id */
+	Cwmedium	= 0x1b,		/* write medium mode */
+	Crgpio		= 0x1e,		/* read gpio */
+	Cwgpio		= 0x1f,		/* write gpios */
+	Creset		= 0x20,		/* reset */
+	Cwphy		= 0x22,		/* select phy */
+
+	/* reset codes */
+	Rclear		= 0x00,
+	Rprte		= 0x04,
+	Rprl		= 0x08,
+	Riprl		= 0x20,
+	Rippd		= 0x40,
+
+	Ipgdflt		= 0x15|0x0c|0x12,	/* default ipg0, 1, 2 */
+
+	Gpiogpo1en	= 0x04,		/* gpio1 enable */,
+	Gpiogpo1		= 0x08,		/* gpio1 value */
+	Gpiogpo2en	= 0x10,		/* gpio2 enable */
+	Gpiogpo2		= 0x20,		/* gpio2 value */
+	Gpiorse		= 0x80,		/* gpio reload serial eeprom */
+
+	Pmask		= 0x1F,
+	Pembed		= 0x10,			/* embedded phy */	
 };
 
 static uint asixphy;
@@ -160,7 +175,7 @@
 
 	r = Rd2h|Rvendor|Rdev;
 	if(usbcmd(d, r, Crmii, phy, reg, v, 2) < 0){
-		fprint(2, "%s: miiwrite: %r\n", argv0);
+		fprint(2, "%s: miiread: %r\n", argv0);
 		return -1;
 	}
 	r = GET2(v);
@@ -169,7 +184,6 @@
 	return r;
 }
 
-
 static int
 miiwrite(Dev *d, int phy, int reg, int val)
 {
@@ -391,6 +405,258 @@
 	eptransmit = asixtransmit;
 	eppromiscuous = asixpromiscuous;
 	epmulticast = asixmulticast;
+
+	return 0;
+}
+
+/*
+ *	a88179 & a88178a
+ */
+enum
+{
+	/* Access */
+	Amac			= 0x01,
+		Nid		= 0x10,
+
+	Aphy			= 0x02,
+		Physts		= 0x02,
+		Phyid		= 0x03,
+
+	/* Control */
+	Crxctl			= 0x0b,
+	Cmed			= 0x22,		/* medium status register */
+
+	Cmmsr			= 0x24,		/* control monitor */	
+		Mrwmp		= 0x04,
+		Mpmepol		= 0x20,
+		Mpmetyp		= 0x40,
+
+	Cphy			= 0x26,		/* control phy */
+		Cphybz		= 0x0010,
+		Cphyiprl	= 0x0020,
+
+	Cblkinq			= 0x2e,
+
+	Csclk			= 0x33,		/* select clock */
+		Sclkbcs		= 0x01,
+		Sclkacs		= 0x02,
+
+	Cpwtrl			= 0x54,
+	Cpwtrh			= 0x55,
+
+	Usbss 		= 0x04,
+	Usbhs		= 0x02,
+	Usbfs		= 0x01,
+};
+
+static int
+a179set(Dev *d, int c, int v, int i, uchar *b, int l)
+{
+	int r, ec;
+
+	r = Rh2d|Rvendor|Rdev;
+	ec = usbcmd(d, r, c, v, i, b, l);
+	if(ec < 0)
+		fprint(2, "%s: a179set %x %x: %r\n", argv0, c, v);
+	return ec;
+}
+
+static int
+a179set1(Dev *d, int v, uchar b)
+{
+	return a179set(d, Amac, v, 1, &b, 1);
+}
+
+static int
+a179set2(Dev *d, int v, ushort b)
+{
+	uchar buf[2];
+
+	memcpy(buf, &b, 2);
+	return a179set(d, Amac, v, 2, buf, 2);
+}
+
+static int
+a179get(Dev *d, int c, int v, int i, uchar *buf, int l)
+{
+	int r, ec;
+
+	r = Rd2h|Rvendor|Rdev;
+	ec = usbcmd(d, r, c, v, i, buf, l);
+	if(ec < 0)
+		fprint(2, "%s: a179get %x %x: %r\n", argv0, c, v);
+	return ec;
+}
+
+static int
+a179miiread(Dev *d, int reg)
+{
+	int r;
+	uchar v[2];
+
+	r = Rd2h|Rvendor|Rdev;
+	if(usbcmd(d, r, Aphy, Phyid, reg, v, 2) < 0){
+		fprint(2, "%s: a179miiread: %r\n", argv0);
+		return -1;
+	}
+	r = GET2(v);
+	if(r == 0xFFFF)
+		return -1;
+	return r;
+}
+
+
+static int
+a179miiwrite(Dev *d, int reg, uint val)
+{
+	int r;
+	uchar v[2];
+
+	PUT2(v, val);
+	r = Rh2d|Rvendor|Rdev;
+	if(usbcmd(d, r, Aphy, Phyid, reg, v, 2) < 0){
+		fprint(2, "%s: a179miiwrite: %#x %#x %r\n", argv0, reg, val);
+		return -1;
+	}
+	return 0;
+}
+
+static int a179bufsz;
+
+static int
+a179receive(Dev *ep)
+{
+	Block *b;
+	uchar *hdr;
+	uint pktlen, npkt;
+	int n;
+
+	b = allocb(a179bufsz);
+	if((n = read(ep->dfd, b->wp, b->lim - b->base)) < 0){
+		freeb(b);
+		return -1;
+	}
+	b->wp += n;
+	npkt = GET2(b->wp-4);
+	hdr = b->base + GET2(b->wp-2);
+	b->wp -= 4;
+	while(npkt-- > 0){
+		pktlen = GET2(hdr+2) & 0x1FFF;
+		if(pktlen < ETHERHDRSIZE || pktlen > BLEN(b))
+			break;
+		etheriq(copyblock(b, pktlen-4));
+		b->rp += (pktlen+7) & 0xFFF8;
+		hdr += 4;
+	}
+	freeb(b);
+	return 0;
+}
+
+static void
+a179transmit(Dev *ep, Block *b)
+{
+	uint hd[2];
+
+	hd[0] = BLEN(b);
+	hd[1] = 0;
+	b->rp -= 8;
+	if((BLEN(b) % ep->maxpkt) == 0)
+		hd[1] |= 0x80008000;
+	PUT4(b->rp, hd[0]);
+	PUT4(b->rp+4, hd[1]);
+	write(ep->dfd, b->rp, BLEN(b));
+	freeb(b);
+}
+
+static int
+a179getrxctl(Dev *d)
+{
+	uchar buf[2];
+
+	memset(buf, 0, sizeof(buf));
+	if(a179get(d, Amac, Crxctl, 2, buf, 2) < 0)
+		return -1;
+	return GET2(buf);
+}
+
+static int
+a179promiscuous(Dev *d, int on)
+{
+	ushort rxctl;
+
+	rxctl = a179getrxctl(d);
+	if(on)
+		rxctl |= Rxctlprom;
+	else
+		rxctl &= ~Rxctlprom;
+	return a179set2(d, Crxctl, rxctl);
+}
+
+static int
+a179multicast(Dev *d, uchar*, int)
+{
+	int rxctl;
+
+	rxctl = a179getrxctl(d);
+	if(nmulti != 0)
+		rxctl |= Rxctlamall;
+	else
+		rxctl &= ~Rxctlamall;
+	return a179set2(d, Crxctl, rxctl);
+}
+
+int
+a88179init(Dev *d)
+{
+	uchar qctrl[4][5] = {
+		{0x07, 0x4f, 0x00, 0x02, 0xff},
+		{0x07, 0x20, 0x03, 0x03, 0xff},
+		{0x07, 0xae, 0x07, 0x04, 0xff},
+		{0x07, 0xcc, 0x4c, 0x04, 0x08}
+	};
+	uchar link;
+	int bmcr, spd;
+
+	a179set2(d, Cphy, 0);
+	a179set2(d, Cphy, Cphyiprl);
+	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){
+		if(a179set(d, Amac, Nid, Eaddrlen, macaddr, Eaddrlen) < 0)
+			return -1;
+	}else if(a179get(d, Amac, Nid, Eaddrlen, macaddr, Eaddrlen) < 0)
+		return -1;
+	if(a179set2(d, Crxctl, Rxall179) < 0)
+		return -1;
+	if(a179set1(d, Cmmsr, Mpmetyp|Mpmepol|Mrwmp) < 0)
+		return -1;
+	if(a179set2(d, Cmed, Mall179) < 0)
+		return -1;
+
+	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;
+	}
+	a179set(d, Amac, Cblkinq, 5, qctrl[spd], 5);
+	a179bufsz = 1024*(qctrl[spd][3]+2);
+
+	bmcr = a179miiread(d, Miibmcr);
+	if((bmcr & Bmcranena) != 0){
+		bmcr |= Bmcrar;
+		a179miiwrite(d, Miibmcr, bmcr);
+	}	
+
+	epreceive = a179receive;
+	eptransmit = a179transmit;
+	eppromiscuous = a179promiscuous;
+	epmulticast = a179multicast;
 
 	return 0;
 }
--- a/sys/src/cmd/nusb/ether/ether.c
+++ b/sys/src/cmd/nusb/ether/ether.c
@@ -845,7 +845,7 @@
 
 	nerr = 0;
 	for(;;){
-		/* receive allocates buffer and calls etheriq(b, 1); */
+		/* receive allocates buffer and calls etheriq */
 		if((*epreceive)(epin) < 0){
 			rerrstr(err, sizeof(err));
 			if(strstr(err, "interrupted") || strstr(err, "timed out"))
@@ -881,6 +881,7 @@
 extern int aueinit(Dev *);
 extern int a88178init(Dev *);
 extern int a88772init(Dev *);
+extern int a88179init(Dev *);
 extern int smscinit(Dev *);
 extern int lan78xxinit(Dev *);
 extern int cdcinit(Dev *);
@@ -896,6 +897,7 @@
 	"lan78xx",	lan78xxinit,
 	"a88178",	a88178init,
 	"a88772",	a88772init,
+	"a88179",	a88179init,
 	"aue",		aueinit,
 	"url",		urlinit,
 	"rndis",	rndisinit,