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,