diff options
author | ppatience0 <ppatience0@gmail.com> | 2013-08-24 19:18:15 -0400 |
---|---|---|
committer | ppatience0 <ppatience0@gmail.com> | 2013-08-24 19:18:15 -0400 |
commit | 334054e0e7c80a8b6b817089214e5282174fc7c9 (patch) | |
tree | 4a5d5456b18bfaa4659fa1faba5b5e9b2b4262d7 /sys/src/cmd/nusb | |
parent | 808480f76bedbbe4215da11de31f7403de668b2a (diff) |
nusb/ether: add aue driver for admtek pegasus usb ethernet adapter
Diffstat (limited to 'sys/src/cmd/nusb')
-rw-r--r-- | sys/src/cmd/nusb/ether/aue.c | 254 | ||||
-rw-r--r-- | sys/src/cmd/nusb/ether/ether.c | 3 | ||||
-rw-r--r-- | sys/src/cmd/nusb/ether/mkfile | 2 |
3 files changed, 257 insertions, 2 deletions
diff --git a/sys/src/cmd/nusb/ether/aue.c b/sys/src/cmd/nusb/ether/aue.c new file mode 100644 index 000000000..44719222f --- /dev/null +++ b/sys/src/cmd/nusb/ether/aue.c @@ -0,0 +1,254 @@ +/* +* admtek pegasus driver copy-pasted from bill paul's +* openbsd/freebsd aue(4) driver, with help +* from the datasheet and petko manolov's linux +* drivers/net/usb/pegasus.c driver +*/ +#include <u.h> +#include <libc.h> +#include <thread.h> +#include <bio.h> +#include <auth.h> +#include <fcall.h> +#include <9p.h> + +#include "usb.h" +#include "dat.h" + +enum { + Readreg = 0xf0, + Writereg = 0xf1, + + Ctl0 = 0x00, + C0incrxcrc = 1 << 0, + C0allmulti = 1 << 1, + C0stopbackoff = 1 << 2, + C0rxstatappend = 1 << 3, + C0wakeonen = 1 << 4, + C0rxpauseen = 1 << 5, + C0rxen = 1 << 6, + C0txen = 1 << 7, + + Ctl1 = 0x01, + C1homelan = 1 << 2, + C1resetmac = 1 << 3, + C1speedsel = 1 << 4, + C1duplex = 1 << 5, + C1delayhome = 1 << 6, + + Ctl2 = 0x02, + C2ep3clr = 1 << 0, + C2rxbadpkt = 1 << 1, + C2prom = 1 << 2, + C2loopback = 1 << 3, + C2eepromwren = 1 << 4, + C2eepromload = 1 << 5, + + Par = 0x10, + + Eereg = 0x20, + Eedata = 0x21, + + Eectl = 0x23, + Eectlwr = 1 << 0, + Eectlrd = 1 << 1, + Eectldn = 1 << 2, + + Phyaddr = 0x25, + Phydata = 0x26, + + Phyctl = 0x28, + Phyctlphyreg = 0x1f, + Phyctlwr = 1 << 5, + Phyctlrd = 1 << 6, + Phyctldn = 1 << 7, + + Gpio0 = 0x7e, + Gpio1 = 0x7f, + Gpioin0 = 1 << 0, + Gpioout0 = 1 << 1, + Gpiosel0 = 1 << 2, + Gpioin1 = 1 << 3, + Gpioout1 = 1 << 4, + Gpiosel1 = 1 << 5, + + Rxerror = 0x1e << 16, + + Timeout = 1000 +}; + +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); +static void auewrite(Dev *, uchar *, int); + +static int +csr8r(Dev *d, int reg) +{ + int rc; + uchar v; + + rc = usbcmd(d, Rd2h|Rvendor|Rdev, Readreg, + 0, reg, &v, sizeof v); + if(rc < 0) { + fprint(2, "%s: csr8r(%#x): %r\n", + argv0, reg); + return 0; + } + return v; +} + +static int +csr16r(Dev *d, int reg) +{ + int rc; + uchar v[2]; + + rc = usbcmd(d, Rd2h|Rvendor|Rdev, Readreg, + 0, reg, v, sizeof v); + if(rc < 0) { + fprint(2, "%s: csr16r(%#x): %r\n", + argv0, reg); + return 0; + } + return GET2(v); +} + +static int +csr8w(Dev *d, int reg, int val) +{ + int rc; + uchar v; + + v = val; + rc = usbcmd(d, Rh2d|Rvendor|Rdev, Writereg, + val&0xff, reg, &v, sizeof v); + if(rc < 0) { + fprint(2, "%s: csr8w(%#x, %#x): %r\n", + argv0, reg, 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) +{ + int i; + + csr8w(d, Eereg, off); + csr8w(d, Eectl, Eectlrd); + for(i = 0; i < Timeout; i++) { + if(csr8r(d, Eectl) & Eectldn) + break; + } + if(i >= Timeout) { + fprint(2, "%s: EEPROM read timed out\n", + argv0); + } + return csr16r(d, Eedata); +} + +static void +reset(Dev *d) +{ + int i; + + csr8w(d, Ctl1, csr8r(d, Ctl1)|C1resetmac); + for(i = 0; i < Timeout; i++) { + if(!(csr8r(d, Ctl1) & C1resetmac)) + break; + } + if(i >= Timeout) + fprint(2, "%s: reset failed\n", argv0); + csr8w(d, Gpio0, Gpiosel0|Gpiosel1); + csr8w(d, Gpio0, Gpiosel0|Gpiosel1|Gpioout0); + sleep(10); +} + +static int +aueread(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; + q = bin + nbin - 4; + hd = GET4(q); + n = hd & 0xfff; + if(n < 6 || n > nbin) { + nbin = 0; + return 0; + } + if(hd & Rxerror) { + fprint(2, "%s: rx error %#ux\n", + argv0, hd); + n = 0; + } else { + if(n > plen) + n = plen; + if(n > 0) + memmove(p, bin, n); + } + if(n < nbin) + memmove(bin, bin+n, nbin-n); + nbin -= n; + return n; +} + +static void +auewrite(Dev *ep, uchar *p, int n) +{ + if(n > sizeof bout-2) + n = sizeof bout - 2; + PUT2(bout, n); + memmove(bout+2, p, n); + write(ep->dfd, bout, n+2); +} + +int +aueinit(Dev *d) +{ + int i, v; + uchar *p; + + reset(d); + for(i = 0, p = macaddr; i < 3; i++, p += 2) { + v = eeprom16r(d, i); + PUT2(p, v); + } + for(i = 0; i < sizeof macaddr; i++) + csr8w(d, Par+i, macaddr[i]); + csr8w(d, Ctl2, csr8r(d, Ctl2)&~C2prom); + csr8w(d, Ctl0, C0rxstatappend|C0rxen); + csr8w(d, Ctl0, csr8r(d, Ctl0)|C0txen); + csr8w(d, Ctl2, csr8r(d, Ctl2)|C2ep3clr); + epread = aueread; + epwrite = auewrite; + return 0; +} diff --git a/sys/src/cmd/nusb/ether/ether.c b/sys/src/cmd/nusb/ether/ether.c index 143c4a9de..076b5af6c 100644 --- a/sys/src/cmd/nusb/ether/ether.c +++ b/sys/src/cmd/nusb/ether/ether.c @@ -753,7 +753,7 @@ usage(void) exits("usage"); } - +extern int aueinit(Dev *); extern int a88178init(Dev *); extern int a88772init(Dev *); extern int smscinit(Dev *); @@ -767,6 +767,7 @@ static struct { "smsc", smscinit, "a88178", a88178init, "a88772", a88772init, + "aue", aueinit, }; void diff --git a/sys/src/cmd/nusb/ether/mkfile b/sys/src/cmd/nusb/ether/mkfile index 369c3aabf..22c297d7e 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 +OFILES=ether.$O cdc.$O smsc.$O asix.$O aue.$O </sys/src/cmd/mkone |