From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on inbox.vuxu.org X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham autolearn_force=no version=3.4.4 Received: (qmail 20487 invoked from network); 29 Jan 2023 01:18:37 -0000 Received: from 9front.inri.net (168.235.81.73) by inbox.vuxu.org with ESMTPUTF8; 29 Jan 2023 01:18:37 -0000 Received: from oneiri.one ([170.39.227.229]) by 9front; Sat Jan 28 20:16:14 -0500 2023 Message-ID: From: Aidan K. Wiggins Date: Sat, 28 Jan 2023 17:15:49 -0800 To: 9front@9front.org MIME-Version: 1.0 Content-Type: text/plain; charset="US-ASCII" Content-Transfer-Encoding: 7bit List-ID: <9front.9front.org> List-Help: X-Glyph: ➈ X-Bullshit: lossless transactional element layer Subject: [9front] [PATCH] nusb/ether: support for asix ax88179 Reply-To: 9front@9front.org Precedence: bulk Pretty self explanatory :) 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. diff bd3c854f6022c48418ecd918fe921a9140d28f30 uncommitted --- 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,