]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/nusb/ether/aue.c
nusb/ether: tune buffer size parameters for SMSC ethernet (raspi) (thanks richard...
[plan9front.git] / sys / src / cmd / nusb / ether / aue.c
1 /*
2 * admtek pegasus driver copy-pasted from bill paul's
3 * openbsd/freebsd aue(4) driver, with help
4 * from the datasheet and petko manolov's linux
5 * drivers/net/usb/pegasus.c driver
6 */
7 #include <u.h>
8 #include <libc.h>
9 #include <thread.h>
10
11 #include "usb.h"
12 #include "dat.h"
13
14 enum {
15         Readreg = 0xf0,
16         Writereg = 0xf1,
17
18         Ctl0 = 0x00,
19         C0incrxcrc = 1 << 0,
20         C0allmulti = 1 << 1,
21         C0stopbackoff = 1 << 2,
22         C0rxstatappend = 1 << 3,
23         C0wakeonen = 1 << 4,
24         C0rxpauseen = 1 << 5,
25         C0rxen = 1 << 6,
26         C0txen = 1 << 7,
27
28         Ctl1 = 0x01,
29         C1homelan = 1 << 2,
30         C1resetmac = 1 << 3,
31         C1speedsel = 1 << 4,
32         C1duplex = 1 << 5,
33         C1delayhome = 1 << 6,
34
35         Ctl2 = 0x02,
36         C2ep3clr = 1 << 0,
37         C2rxbadpkt = 1 << 1,
38         C2prom = 1 << 2,
39         C2loopback = 1 << 3,
40         C2eepromwren = 1 << 4,
41         C2eepromload = 1 << 5,
42
43         Par = 0x10,
44
45         Eereg = 0x20,
46         Eedata = 0x21,
47
48         Eectl = 0x23,
49         Eectlwr = 1 << 0,
50         Eectlrd = 1 << 1,
51         Eectldn = 1 << 2,
52
53         Phyaddr = 0x25,
54         Phydata = 0x26,
55
56         Phyctl = 0x28,
57         Phyctlphyreg = 0x1f,
58         Phyctlwr = 1 << 5,
59         Phyctlrd = 1 << 6,
60         Phyctldn = 1 << 7,
61
62         Gpio0 = 0x7e,
63         Gpio1 = 0x7f,
64         Gpioin0 = 1 << 0,
65         Gpioout0 = 1 << 1,
66         Gpiosel0 = 1 << 2,
67         Gpioin1 = 1 << 3,
68         Gpioout1 = 1 << 4,
69         Gpiosel1 = 1 << 5,
70
71         Rxerror = 0x1e << 16,
72
73         Timeout = 1000
74 };
75
76 static int csr8r(Dev *, int);
77 static int csr16r(Dev *, int);
78 static int csr8w(Dev *, int, int);
79 static int eeprom16r(Dev *, int);
80 static void reset(Dev *);
81
82 static int
83 csr8r(Dev *d, int reg)
84 {
85         int rc;
86         uchar v;
87
88         rc = usbcmd(d, Rd2h|Rvendor|Rdev, Readreg,
89                 0, reg, &v, sizeof v);
90         if(rc < 0) {
91                 fprint(2, "%s: csr8r(%#x): %r\n",
92                         argv0, reg);
93                 return 0;
94         }
95         return v;
96 }
97
98 static int
99 csr16r(Dev *d, int reg)
100 {
101         int rc;
102         uchar v[2];
103
104         rc = usbcmd(d, Rd2h|Rvendor|Rdev, Readreg,
105                 0, reg, v, sizeof v);
106         if(rc < 0) {
107                 fprint(2, "%s: csr16r(%#x): %r\n",
108                         argv0, reg);
109                 return 0;
110         }
111         return GET2(v);
112 }
113
114 static int
115 csr8w(Dev *d, int reg, int val)
116 {
117         int rc;
118         uchar v;
119         
120         v = val;
121         rc = usbcmd(d, Rh2d|Rvendor|Rdev, Writereg,
122                 val&0xff, reg, &v, sizeof v);
123         if(rc < 0) {
124                 fprint(2, "%s: csr8w(%#x, %#x): %r\n",
125                         argv0, reg, val);
126         }
127         return rc;
128 }
129
130 static int
131 eeprom16r(Dev *d, int off)
132 {
133         int i;
134
135         csr8w(d, Eereg, off);
136         csr8w(d, Eectl, Eectlrd);
137         for(i = 0; i < Timeout; i++) {
138                 if(csr8r(d, Eectl) & Eectldn)
139                         break;
140         }
141         if(i >= Timeout) {
142                 fprint(2, "%s: EEPROM read timed out\n",
143                         argv0);
144         }
145         return csr16r(d, Eedata);
146 }
147
148 static void
149 reset(Dev *d)
150 {
151         int i;
152
153         csr8w(d, Ctl1, csr8r(d, Ctl1)|C1resetmac);
154         for(i = 0; i < Timeout; i++) {
155                 if(!(csr8r(d, Ctl1) & C1resetmac))
156                         break;
157         }
158         if(i >= Timeout)
159                 fprint(2, "%s: reset failed\n", argv0);
160         csr8w(d, Gpio0, Gpiosel0|Gpiosel1);
161         csr8w(d, Gpio0, Gpiosel0|Gpiosel1|Gpioout0);
162         sleep(10);
163 }
164
165 static int
166 auereceive(Dev *ep)
167 {
168         Block *b;
169         uint hd;
170         int n;
171
172         b = allocb(Maxpkt+4);
173         if((n = read(ep->dfd, b->wp, b->lim - b->base)) < 0){
174                 freeb(b);
175                 return -1;
176         }
177         if(n < 4){
178                 freeb(b);
179                 return 0;
180         }
181         b->wp += n-4;
182         hd = GET4(b->wp);
183         n = hd & 0xfff;
184         if((hd & Rxerror) != 0 || n > BLEN(b)){
185                 freeb(b);
186                 return 0;
187         }
188         b->wp = b->rp + n;
189         etheriq(b);
190         return 0;
191 }
192
193 static void
194 auetransmit(Dev *ep, Block *b)
195 {
196         int n;
197
198         n = BLEN(b);
199         b->rp -= 2;
200         PUT2(b->rp, n);
201         write(ep->dfd, b->rp, BLEN(b));
202         freeb(b);
203 }
204
205 static int
206 auepromiscuous(Dev *d, int on)
207 {
208         int r;
209
210         r = csr8r(d, Ctl2);
211         if(on)
212                 r |= C2prom;
213         else
214                 r &= ~C2prom;
215         return csr8w(d, Ctl2, r);
216 }
217
218 static int
219 auemulticast(Dev *d, uchar*, int)
220 {
221         int r;
222
223         r = csr8r(d, Ctl0);
224         if(nmulti)
225                 r |= C0allmulti;
226         else
227                 r &= ~C0allmulti;
228         return csr8w(d, Ctl0, r);
229 }
230
231 int
232 aueinit(Dev *d)
233 {
234         int i, v;
235         uchar *p;
236
237         reset(d);
238         for(i = 0, p = macaddr; i < 3; i++, p += 2) {
239                 v = eeprom16r(d, i);
240                 PUT2(p, v);
241         }
242         for(i = 0; i < sizeof macaddr; i++)
243                 csr8w(d, Par+i, macaddr[i]);
244         csr8w(d, Ctl2, csr8r(d, Ctl2)&~C2prom);
245         csr8w(d, Ctl0, C0rxstatappend|C0rxen);
246         csr8w(d, Ctl0, csr8r(d, Ctl0)|C0txen);
247         csr8w(d, Ctl2, csr8r(d, Ctl2)|C2ep3clr);
248
249         epreceive = auereceive;
250         eptransmit = auetransmit;
251         eppromiscuous = auepromiscuous;
252         epmulticast = auemulticast;
253
254         return 0;
255 }