diff --git a/sys/src/9/boot/nusbrc b/sys/src/9/boot/nusbrc index ff2a12ed9..88be1c85f 100755 --- a/sys/src/9/boot/nusbrc +++ b/sys/src/9/boot/nusbrc @@ -18,6 +18,8 @@ if(! nusb/usbd) nusb/ether -t a88178 $etherargs $1 & case 2001abc1 nusb/ether -t aue $etherargs $1 & + case 0bda8150 + nusb/ether -t url $etherargs $1 & case * switch($4){ case *03 diff --git a/sys/src/cmd/nusb/ether/asix.c b/sys/src/cmd/nusb/ether/asix.c index dc0158f42..4b725f57c 100644 --- a/sys/src/cmd/nusb/ether/asix.c +++ b/sys/src/cmd/nusb/ether/asix.c @@ -8,10 +8,6 @@ #include #include #include -#include -#include -#include -#include <9p.h> #include "usb.h" #include "dat.h" diff --git a/sys/src/cmd/nusb/ether/aue.c b/sys/src/cmd/nusb/ether/aue.c index 44719222f..1ee77a3cd 100644 --- a/sys/src/cmd/nusb/ether/aue.c +++ b/sys/src/cmd/nusb/ether/aue.c @@ -7,10 +7,6 @@ #include #include #include -#include -#include -#include -#include <9p.h> #include "usb.h" #include "dat.h" @@ -80,7 +76,6 @@ enum { static int csr8r(Dev *, int); static int csr16r(Dev *, int); static int csr8w(Dev *, int, int); -static int csr16w(Dev *, int, int); static int eeprom16r(Dev *, int); static void reset(Dev *); static int aueread(Dev *, uchar *, int); @@ -134,22 +129,6 @@ csr8w(Dev *d, int reg, int val) return rc; } -static int -csr16w(Dev *d, int reg, int val) -{ - int rc; - uchar v[2]; - - PUT2(v, val); - rc = usbcmd(d, Rh2d|Rvendor|Rdev, Writereg, - val&0xffff, reg, v, sizeof v); - if(rc < 0) { - fprint(2, "%s: csr16w(%#x, %#x): %r\n", - argv0, reg, val); - } - return rc; -} - static int eeprom16r(Dev *d, int off) { diff --git a/sys/src/cmd/nusb/ether/cdc.c b/sys/src/cmd/nusb/ether/cdc.c index 057599dec..28f56c0ae 100644 --- a/sys/src/cmd/nusb/ether/cdc.c +++ b/sys/src/cmd/nusb/ether/cdc.c @@ -5,10 +5,6 @@ #include #include #include -#include -#include -#include -#include <9p.h> #include #include "usb.h" diff --git a/sys/src/cmd/nusb/ether/ether.c b/sys/src/cmd/nusb/ether/ether.c index 076b5af6c..042edcdcd 100644 --- a/sys/src/cmd/nusb/ether/ether.c +++ b/sys/src/cmd/nusb/ether/ether.c @@ -1,8 +1,6 @@ #include #include #include -#include -#include #include #include <9p.h> #include @@ -758,6 +756,7 @@ extern int a88178init(Dev *); extern int a88772init(Dev *); extern int smscinit(Dev *); extern int cdcinit(Dev *); +extern int urlinit(Dev *); static struct { char *name; @@ -768,6 +767,7 @@ static struct { "a88178", a88178init, "a88772", a88772init, "aue", aueinit, + "url", urlinit, }; void diff --git a/sys/src/cmd/nusb/ether/mkfile b/sys/src/cmd/nusb/ether/mkfile index 22c297d7e..e7b887757 100644 --- a/sys/src/cmd/nusb/ether/mkfile +++ b/sys/src/cmd/nusb/ether/mkfile @@ -5,7 +5,7 @@ LIB=../lib/usb.a$O TARG=ether HFILES= -OFILES=ether.$O cdc.$O smsc.$O asix.$O aue.$O +OFILES=ether.$O cdc.$O smsc.$O asix.$O aue.$O url.$O #include #include -#include -#include -#include -#include <9p.h> -#include #include "usb.h" #include "dat.h" diff --git a/sys/src/cmd/nusb/ether/url.c b/sys/src/cmd/nusb/ether/url.c new file mode 100644 index 000000000..af3cfe7c2 --- /dev/null +++ b/sys/src/cmd/nusb/ether/url.c @@ -0,0 +1,337 @@ +/* +* realtek rtl8150 10/100 usb ethernet device driver +* +* copy-pasted from shingo watanabe's openbsd url(4) driver +* and bill paul's and shunsuke akiyama's freebsd rue(4) driver +*/ +#include +#include +#include + +#include "usb.h" +#include "dat.h" + +enum { + Timeout = 50, + Mfl = 60, /* min frame len */ +}; + +enum { /* requests */ + Rqm = 0x05, /* request mem */ + Crm = 1, /* command read mem */ + Cwm = 2, /* command write mem */ +}; + +enum { /* registers */ + Idr0 = 0x120, /* ether addr, load from 93c46 */ + Idr1 = 0x121, + Idr2 = 0x122, + Idr3 = 0x123, + Idr4 = 0x124, + Idr5 = 0x125, + + Mar0 = 0x126, /* multicast addr */ + Mar1 = 0x127, + Mar2 = 0x128, + Mar3 = 0x129, + Mar4 = 0x12a, + Mar5 = 0x12b, + Mar6 = 0x12c, + Mar7 = 0x12d, + + Cr = 0x12e, /* command */ + Tcr = 0x12f, /* transmit control */ + Rcr = 0x130, /* receive configuration */ + Tsr = 0x132, + Rsr = 0x133, + Con0 = 0x135, + Con1 = 0x136, + Msr = 0x137, /* media status */ + Phyar = 0x138, /* mii phy addr select */ + Phydr = 0x139, /* mii phy data */ + Phycr = 0x13b, /* mii phy control */ + Gppc = 0x13d, + Wcr = 0x13e, /* wake count */ + Bmcr = 0x140, /* basic mode control */ + Bmsr = 0x142, /* basic mode status */ + Anar = 0x144, /* an advertisement */ + Anlp = 0x146, /* an link partner ability */ + Aner = 0x148, + Nwtr = 0x14a, /* nway test */ + Cscr = 0x14c, + + Crc0 = 0x14e, + Crc1 = 0x150, + Crc2 = 0x152, + Crc3 = 0x154, + Crc4 = 0x156, + + Bm0 = 0x158, /* byte mask */ + Bm1 = 0x160, + Bm2 = 0x168, + Bm3 = 0x170, + Bm4 = 0x178, + + Phy1 = 0x180, + Phy2 = 0x184, + Tw1 = 0x186 +}; + +enum { /* Cr */ + We = 1 << 5, /* eeprom write enable */ + Sr = 1 << 4, /* software reset */ + Re = 1 << 3, /* ethernet receive enable */ + Te = 1 << 2, /* ethernet transmit enable */ + Ep3ce = 1 << 1, /* enable clr of perf counter */ + Al = 1 << 0 /* auto-load contents of 93c46 */ +}; + +enum { /* Tcr */ + Tr1 = 1 << 7, /* tx retry count */ + Tr0 = 1 << 6, + Ifg1 = 1 << 4, /* interframe gap time */ + Ifg0 = 1 << 3, + Nocrc = 1 << 0 /* no crc appended */ +}; + +enum { /* Rcr */ + Tail = 1 << 7, + Aer = 1 << 6, + Ar = 1 << 5, + Am = 1 << 4, + Ab = 1 << 3, + Ad = 1 << 2, + Aam = 1 << 1, + Aap = 1 << 0 +}; + +enum { /* Msr */ + Tfce = 1 << 7, + Rfce = 1 << 6, + Mdx = 1 << 4, /* duplex */ + S100 = 1 << 3, /* speed 100 */ + Lnk = 1 << 2, + Tpf = 1 << 1, + Rpf = 1 << 0 +}; + +enum { /* Phyar */ + Phyamsk = 0x1f +}; + +enum { /* Phycr */ + Phyown = 1 << 6, /* own bit */ + Rwcr = 1 << 5, /* mii mgmt data r/w control */ + Phyoffmsk = 0x1f /* phy register offset */ +}; + +enum { /* Bmcr */ + Spd = 0x2000, /* speed set */ + Bdx = 0x0100 /* duplex */ +}; + +enum { /* Anar */ + Ap = 0x0400 /* pause */ +}; + +enum { /* Anlp */ + Lpp = 0x0400 /* pause */ +}; + +enum { /* eeprom address declarations */ + Ebase = 0x1200, + Eidr0 = Ebase + 0x02, + Eidr1 = Ebase + 0x03, + Eidr2 = Ebase + 0x03, + Eidr3 = Ebase + 0x03, + Eidr4 = Ebase + 0x03, + Eidr5 = Ebase + 0x03, + Eint = Ebase + 0x17 /* interval */ +}; + +enum { /* receive header */ + Bcm = 0x0fff, /* rx bytes count mask */ + Vpm = 0x1000, /* valid packet mask */ + Rpm = 0x2000, /* runt packet mask */ + Ppm = 0x4000, /* physical match packet mask */ + Mpm = 0x8000 /* multicast packet mask */ +}; + +static int mem(Dev *, int, int, uchar *, int); +static int csr8r(Dev *, int); +static int csr16r(Dev *, int); +static int csr8w(Dev *, int, int); +static int csr16w(Dev *, int, int); +static int csr32w(Dev *, int, int); +static void reset(Dev *); +static int urlread(Dev *, uchar *, int); +static void urlwrite(Dev *, uchar *, int); +int urlinit(Dev *); + +static int +mem(Dev *d, int cmd, int off, uchar *buf, int len) +{ + int r, rc; + + if(d == nil) + return 0; + r = Rvendor | Rdev; + if(cmd == Crm) + r |= Rd2h; + else + r |= Rh2d; + rc = usbcmd(d, r, Rqm, off, 0, buf, len); + if(rc < 0) { + fprint(2, "%s: mem(%d, %#.4x) failed\n", + argv0, cmd, off); + } + return rc; +} + +static int +csr8r(Dev *d, int reg) +{ + uchar v; + + v = 0; + if(mem(d, Crm, reg, &v, sizeof v) < 0) + return 0; + return v; +} + +static int +csr16r(Dev *d, int reg) +{ + uchar v[2]; + + PUT2(v, 0); + if(mem(d, Crm, reg, v, sizeof v) < 0) + return 0; + return GET2(v); +} + +static int +csr8w(Dev *d, int reg, int val) +{ + uchar v; + + v = val; + if(mem(d, Cwm, reg, &v, sizeof v) < 0) + return -1; + return 0; +} + +static int +csr16w(Dev *d, int reg, int val) +{ + uchar v[2]; + + PUT2(v, val); + if(mem(d, Cwm, reg, v, sizeof v) < 0) + return -1; + return 0; +} + +static int +csr32w(Dev *d, int reg, int val) +{ + uchar v[4]; + + PUT4(v, val); + if(mem(d, Cwm, reg, v, sizeof v) < 0) + return -1; + return 0; +} + +static void +reset(Dev *d) +{ + int i, r; + + r = csr8r(d, Cr) | Sr; + csr8w(d, Cr, r); + + for(i = 0; i < Timeout; i++) { + if((csr8r(d, Cr) & Sr) == 0) + break; + sleep(10); + } + if(i >= Timeout) + fprint(2, "%s: reset failed\n", argv0); + + sleep(100); +} + +static int +urlread(Dev *ep, uchar *p, int plen) +{ + int n; + uint hd; + uchar *q; + + if(nbin < 4) + nbin = read(ep->dfd, bin, sizeof bin); + if(nbin < 0) + return -1; + if(nbin < 4) + return 0; + n = nbin - 4; + if(n < 6) { + nbin = 0; + return 0; + } + q = bin + n; + hd = GET2(q); + if((hd & Vpm) == 0) { + fprint(2, "url: rx error: %#.4ux\n", hd); + n = 0; + } else { + if(n > plen) + n = plen; + if(n > 0) + memmove(p, bin, n); + } + nbin = 0; + return n; +} + +static void +urlwrite(Dev *ep, uchar *p, int n) +{ + if(n > sizeof bout) + n = sizeof bout; + memmove(bout, p, n); + if(n < Mfl) { + memset(bout+n, 0, Mfl-n); + n = Mfl; + } + write(ep->dfd, bout, n); +} + +int +urlinit(Dev *d) +{ + int i, r; + + reset(d); + if(mem(d, Crm, Idr0, macaddr, sizeof macaddr) < 0) + return -1; + + reset(d); + for(i = 0; i < sizeof macaddr; i++) + csr8w(d, Idr0+i, macaddr[i]); + + csr8w(d, Tcr, Tr1|Tr0|Ifg1|Ifg0); + csr16w(d, Rcr, Tail|Ad|Ab); + + r = csr16r(d, Rcr) & ~(Am | Aam | Aap); + csr16w(d, Rcr, r); + csr32w(d, Mar0, 0); + csr32w(d, Mar4, 0); + + csr8w(d, Cr, Te|Re); + + epwrite = urlwrite; + epread = urlread; + return 0; +}