nusb/ether: add aue driver for admtek pegasus usb ethernet adapter

This commit is contained in:
ppatience0 2013-08-24 19:18:15 -04:00
parent 808480f76b
commit 334054e0e7
4 changed files with 259 additions and 2 deletions

View file

@ -16,6 +16,8 @@ if(! nusb/usbd)
nusb/ether -t a88772 $etherargs $1 & nusb/ether -t a88772 $etherargs $1 &
case 0b951780 14eaab11 17370039 0411006e 050d5055 case 0b951780 14eaab11 17370039 0411006e 050d5055
nusb/ether -t a88178 $etherargs $1 & nusb/ether -t a88178 $etherargs $1 &
case 2001abc1
nusb/ether -t aue $etherargs $1 &
case * case *
switch($4){ switch($4){
case *03 case *03

View file

@ -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;
}

View file

@ -753,7 +753,7 @@ usage(void)
exits("usage"); exits("usage");
} }
extern int aueinit(Dev *);
extern int a88178init(Dev *); extern int a88178init(Dev *);
extern int a88772init(Dev *); extern int a88772init(Dev *);
extern int smscinit(Dev *); extern int smscinit(Dev *);
@ -767,6 +767,7 @@ static struct {
"smsc", smscinit, "smsc", smscinit,
"a88178", a88178init, "a88178", a88178init,
"a88772", a88772init, "a88772", a88772init,
"aue", aueinit,
}; };
void void

View file

@ -5,7 +5,7 @@ LIB=../lib/usb.a$O
TARG=ether TARG=ether
HFILES= 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 </sys/src/cmd/mkone