1 /*
2 * Microchip (ex SMSC) LAN78XX
3 * Also used as ethernet core in LAN7515 usb hub + ethernet
4 */
5
6 #include <u.h>
7 #include <libc.h>
8 #include <fcall.h>
9 #include <thread.h>
10 #include "usb.h"
11 #include "usbfs.h"
12 #include "ether.h"
13
14 enum {
15 Doburst = 1,
16 Resettime = 1000,
17 E2pbusytime = 1000,
18 Hsburst = 32,
19 Defbulkdly = 1000,
20 Rxfifosize = (12*1024),
21 Txfifosize = (12*1024),
22
23 MACoffset = 1,
24 PHYinternal = 1,
25 Rxerror = 0x00400000,
26 Txfcs = 1<<22,
27
28 /* USB vendor requests */
29 Writereg = 0xA0,
30 Readreg = 0xA1,
31
32 /* device registers */
33 Idrev = 0x00,
34 Intsts = 0x0C,
35 Hwcfg = 0x10,
36 Led0en = 1<<20,
37 Led1en = 1<<21,
38 Mef = 1<<4,
39 Lrst = 1<<1,
40 Pmctrl = 0x14,
41 Ready = 1<<7,
42 Phyrst = 1<<4,
43 Gpiocfg0 = 0x18,
44 Gpiocfg1 = 0x1C,
45 E2pcmd = 0x40,
46 Busy = 1<<31,
47 Timeout = 1<<10,
48 Loaded = 1<<9,
49 Read = 0,
50 E2pdata = 0x44,
51 Burstcap = 0x90,
52 Intepctl = 0x98,
53 Phyint = 1<<17,
54 Bulkdelay = 0x94,
55 Rfectl = 0xB0,
56 Rxcoe = 0xF<<11,
57 Ab = 1<<10,
58 Am = 1<<9,
59 Au = 1<<8,
60 Dpf = 1<<1,
61 Usbcfg0 = 0x80,
62 Bir = 1<<6,
63 Bce = 1<<5,
64 Usbcfg1 = 0x84,
65 Rxfifoctl = 0xC0,
66 Rxen = 1<<31,
67 Txfifoctl = 0xC4,
68 Txen = 1<<31,
69 Rxfifo = 0xC8,
70 Txfifo = 0xCc,
71 Fctflow = 0xD0,
72 Maccr = 0x100,
73 Add = 1<<12,
74 Asd = 1<<11,
75 Macrx = 0x104,
76 Macfcs = 1<<4,
77 Macrxen = 1<<0,
78 Mactx = 0x108,
79 Mactxen = 1<<0,
80 Addrh = 0x118,
81 Addrl = 0x11C,
82 MIIaddr = 0x120,
83 MIIwrite= 1<<1,
84 MIIread = 0<<1,
85 MIIbusy = 1<<0,
86 MIIdata = 0x124,
87 Flow = 0x10C,
88 Addrfilth = 0x400,
89 Afvalid = 1<<31,
90 Addrfiltl = 0x404,
91
92 /* MII registers */
93 Bmcr = 0,
94 Bmcrreset= 1<<15,
95 Speed100= 1<<13,
96 Anenable= 1<<12,
97 Anrestart= 1<<9,
98 Fulldpx = 1<<8,
99 Speed1000= 1<<6,
100 Bmsr = 1,
101 Advertise = 4,
102 Adcsma = 0x0001,
103 Ad10h = 0x0020,
104 Ad10f = 0x0040,
105 Ad100h = 0x0080,
106 Ad100f = 0x0100,
107 Adpause = 0x0400,
108 Adpauseasym= 0x0800,
109 Adall = Ad10h|Ad10f|Ad100h|Ad100f,
110 Lpa = 5,
111 Ctrl1000 = 9,
112 Ad1000h = 0x0400,
113 Ad1000f = 0x0200,
114 Ledmodes = 29,
115 Led0shift = 0,
116 Led1shift = 4,
117 Linkact = 0x0,
118 Link1000 = 0x1,
119 Phyintmask = 25,
120 Anegcomp= 1<<10,
121 Linkchg = 1<<13,
122 };
123
124 static int burstcap = Hsburst, bulkdelay = Defbulkdly;
125
126 static int
wr(Dev * d,int reg,int val)127 wr(Dev *d, int reg, int val)
128 {
129 int ret;
130
131 ret = usbcmd(d, Rh2d|Rvendor|Rdev, Writereg, 0, reg,
132 (uchar*)&val, sizeof(val));
133 if(ret < 0)
134 deprint(2, "%s: wr(%x, %x): %r", argv0, reg, val);
135 return ret;
136 }
137
138 static int
rr(Dev * d,int reg)139 rr(Dev *d, int reg)
140 {
141 int ret, rval;
142
143 ret = usbcmd(d, Rd2h|Rvendor|Rdev, Readreg, 0, reg,
144 (uchar*)&rval, sizeof(rval));
145 if(ret < 0){
146 fprint(2, "%s: rr(%x): %r", argv0, reg);
147 return 0;
148 }
149 return rval;
150 }
151
152 static int
miird(Dev * d,int idx)153 miird(Dev *d, int idx)
154 {
155 while(rr(d, MIIaddr) & MIIbusy)
156 ;
157 wr(d, MIIaddr, PHYinternal<<11 | idx<<6 | MIIread | MIIbusy);
158 while(rr(d, MIIaddr) & MIIbusy)
159 ;
160 return rr(d, MIIdata);
161 }
162
163 static void
miiwr(Dev * d,int idx,int val)164 miiwr(Dev *d, int idx, int val)
165 {
166 while(rr(d, MIIaddr) & MIIbusy)
167 ;
168 wr(d, MIIdata, val);
169 wr(d, MIIaddr, PHYinternal<<11 | idx<<6 | MIIwrite | MIIbusy);
170 while(rr(d, MIIaddr) & MIIbusy)
171 ;
172 }
173
174 static int
eepromr(Dev * d,int off,uchar * buf,int len)175 eepromr(Dev *d, int off, uchar *buf, int len)
176 {
177 int i, v;
178
179 for(i = 0; i < E2pbusytime; i++)
180 if((rr(d, E2pcmd) & Busy) == 0)
181 break;
182 if(i == E2pbusytime)
183 return -1;
184 for(i = 0; i < len; i++){
185 wr(d, E2pcmd, Busy|Read|(i+off));
186 while((v = rr(d, E2pcmd) & (Busy|Timeout)) == Busy)
187 ;
188 if(v & Timeout)
189 return -1;
190 buf[i] = rr(d, E2pdata);
191 }
192 return 0;
193 }
194
195 static void
phyinit(Dev * d)196 phyinit(Dev *d)
197 {
198 int i;
199
200 miiwr(d, Bmcr, Bmcrreset|Anenable);
201 for(i = 0; i < Resettime/10; i++){
202 if((miird(d, Bmcr) & Bmcrreset) == 0)
203 break;
204 sleep(10);
205 }
206 miiwr(d, Advertise, Adcsma|Adall|Adpause|Adpauseasym);
207 miiwr(d, Ctrl1000, Ad1000f);
208 miiwr(d, Phyintmask, 0);
209 miiwr(d, Ledmodes, (Linkact<<Led1shift) | (Link1000<<Led0shift));
210 miiwr(d, Bmcr, miird(d, Bmcr)|Anenable|Anrestart);
211 }
212
213
214 static int
doreset(Dev * d,int reg,int bit)215 doreset(Dev *d, int reg, int bit)
216 {
217 int i;
218
219 if(wr(d, reg, bit) < 0)
220 return -1;
221 for(i = 0; i < Resettime/10; i++){
222 if((rr(d, reg) & bit) == 0)
223 return 1;
224 sleep(10);
225 }
226 return 0;
227 }
228
229 static int
getmac(Dev * d,uchar buf[])230 getmac(Dev *d, uchar buf[])
231 {
232 int i;
233 uchar ea[Eaddrlen];
234
235 if(eepromr(d, MACoffset, ea, Eaddrlen) < 0)
236 return -1;
237 for(i = 0; i < Eaddrlen; i++)
238 if(ea[i] != 0 && ea[i] != 0xFF){
239 memmove(buf, ea, Eaddrlen);
240 break;
241 }
242 return Eaddrlen;
243 }
244
245 static int
lan78xxinit(Ether * ether)246 lan78xxinit(Ether *ether)
247 {
248 Dev *d;
249 u32int a;
250 int i;
251
252 if(ether->cid != S78xx)
253 return -1;
254 d = ether->dev;
255 deprint(2, "%s: setting up LAN78XX\n", argv0);
256 deprint(2, "chip id/rev = %8.8ux\n", rr(d, Idrev));
257 if(!doreset(d, Hwcfg, Lrst) || !doreset(d, Pmctrl, Phyrst))
258 return -1;
259 for(i = 0; i < Resettime/10; i++){
260 if(rr(d, Pmctrl) & Ready)
261 break;
262 sleep(10);
263 }
264 if((rr(d, Pmctrl) & Ready) == 0){
265 deprint(2, "%s: device not ready after reset\n", argv0);
266 return -1;
267 }
268 if(getmac(d, ether->addr) < 0)
269 deprint(2, "%s: can't read etheraddr from EEPROM\n", argv0);
270 a = GET4(ether->addr);
271 wr(d, Addrl, a);
272 wr(d, Addrfiltl, a);
273 a = GET2(ether->addr+4);
274 wr(d, Addrh, a);
275 wr(d, Addrfilth, a|Afvalid);
276 deprint(2, "Address filter %8.8ux %8.8ux\n", rr(d, Addrfilth), rr(d, Addrfiltl));
277
278 wr(d, Usbcfg0, rr(d, Usbcfg0) | Bir);
279 if(Doburst){
280 wr(d, Hwcfg, rr(d, Hwcfg)|Mef);
281 wr(d, Usbcfg0, rr(d, Usbcfg0)|Bce);
282 wr(d, Burstcap, burstcap);
283 wr(d, Bulkdelay, bulkdelay);
284 }else{
285 wr(d, Hwcfg, rr(d, Hwcfg)&~Mef);
286 wr(d, Usbcfg0, rr(d, Usbcfg0)&~Bce);
287 wr(d, Burstcap, 0);
288 wr(d, Bulkdelay, 0);
289 }
290 wr(d, Rxfifo, (Rxfifosize-512)/512);
291 wr(d, Txfifo, (Txfifosize-512)/512);
292 wr(d, Intsts, ~0);
293 wr(d, Hwcfg, rr(d, Hwcfg) | Led0en|Led1en);
294 wr(d, Flow, 0);
295 wr(d, Fctflow, 0);
296 wr(d, Rfectl, (rr(d, Rfectl) & ~Rxcoe) | Ab|Dpf); /* TODO could offload checksums? */
297
298 phyinit(d);
299
300 wr(d, Maccr, rr(d,Maccr)|Add|Asd);
301
302 wr(d, Intepctl, rr(d, Intepctl)|Phyint);
303 wr(d, Mactx, Mactxen);
304 wr(d, Macrx, rr(d, Macrx) | Macfcs|Macrxen);
305 wr(d, Txfifoctl, Txen);
306 wr(d, Rxfifoctl, Rxen);
307
308 return 0;
309 }
310
311 static long
lan78xxbread(Ether * e,Buf * bp)312 lan78xxbread(Ether *e, Buf *bp)
313 {
314 uint hd;
315 int n, m;
316 Buf *rbp;
317
318 rbp = e->aux;
319 if(rbp->ndata < 10){
320 rbp->rp = rbp->data;
321 rbp->ndata = read(e->epin->dfd, rbp->rp, Doburst? burstcap*512:
322 Maxpkt);
323 if(rbp->ndata < 0)
324 return -1;
325 }
326 if(rbp->ndata < 10){
327 werrstr("short frame");
328 fprint(2, "lan78xx short frame %d bytes\n", rbp->ndata);
329 sleep(1000);
330 return 0;
331 }
332 hd = GET4(rbp->rp);
333 n = hd & 0x3FFF;
334 rbp->rp += 10;
335 rbp->ndata -= 10;
336 if(n < 6 || n > rbp->ndata){
337 werrstr("frame length");
338 fprint(2, "lan78xx length error packet %d buf %d\n", n, rbp->ndata);
339 rbp->ndata = 0;
340 return 0;
341 }
342 if(hd & Rxerror){
343 fprint(2, "lan78xx rx error %8.8ux\n", hd);
344 n = 0;
345 }else{
346 bp->rp = bp->data + Hdrsize;
347 memmove(bp->rp, rbp->rp, n);
348 }
349 bp->ndata = n;
350 rbp->rp += n;
351 rbp->ndata -= n;
352 if(rbp->ndata > 0){
353 m = rbp->rp - rbp->data;
354 if(m&3){
355 m = 4 - (m&3);
356 rbp->rp += m;
357 rbp->ndata -= m;
358 }
359 }
360 return n;
361 }
362
363 static long
lan78xxbwrite(Ether * e,Buf * bp)364 lan78xxbwrite(Ether *e, Buf *bp)
365 {
366 int n;
367
368 n = bp->ndata & 0xFFFFF;
369 bp->rp -= 8;
370 bp->ndata += 8;
371 PUT4(bp->rp, n | Txfcs);
372 PUT4(bp->rp+4, 0);
373 n = write(e->epout->dfd, bp->rp, bp->ndata);
374 if(n != bp->ndata)
375 deprint(2, "bwrite %d: %r\n", n);
376 return n;
377 }
378
379 static int
lan78xxpromiscuous(Ether * e,int on)380 lan78xxpromiscuous(Ether *e, int on)
381 {
382 Dev *d;
383 int rxctl;
384
385 d = e->dev;
386 rxctl = rr(d, Rfectl);
387 if(on)
388 rxctl |= Am|Au;
389 else
390 rxctl &= ~(Am|Au);
391 return wr(d, Rfectl, rxctl);
392 }
393
394 static int
lan78xxmulticast(Ether * e,uchar * addr,int on)395 lan78xxmulticast(Ether *e, uchar *addr, int on)
396 {
397 int rxctl;
398 Dev *d;
399
400 USED(addr, on);
401 /* BUG: should write multicast filter */
402 d = e->dev;
403 rxctl = rr(d, Rfectl);
404 if(e->nmcasts != 0)
405 rxctl |= Am;
406 else
407 rxctl &= ~Am;
408 deprint(2, "%s: lan78xxmulticast %d\n", argv0, e->nmcasts);
409 return wr(d, Rfectl, rxctl);
410 }
411
412 static void
lan78xxfree(Ether * ether)413 lan78xxfree(Ether *ether)
414 {
415 free(ether->aux);
416 ether->aux = nil;
417 }
418
419 int
lan78xxreset(Ether * ether)420 lan78xxreset(Ether *ether)
421 {
422 Cinfo *ip;
423 Dev *dev;
424
425 dev = ether->dev;
426 for(ip = cinfo; ip->vid != 0; ip++)
427 if(ip->vid == dev->usb->vid && ip->did == dev->usb->did){
428 ether->cid = ip->cid;
429 if(lan78xxinit(ether) < 0){
430 deprint(2, "%s: lan78xx init failed: %r\n", argv0);
431 return -1;
432 }
433 deprint(2, "%s: lan78xx reset done\n", argv0);
434 ether->name = "lan78xx";
435 if(Doburst){
436 ether->bufsize = burstcap*512;
437 ether->aux = emallocz(sizeof(Buf) +
438 ether->bufsize - Maxpkt, 1);
439 }else{
440 ether->bufsize = Maxpkt;
441 ether->aux = emallocz(sizeof(Buf), 1);
442 }
443 ether->free = lan78xxfree;
444 ether->bread = lan78xxbread;
445 ether->bwrite = lan78xxbwrite;
446 ether->promiscuous = lan78xxpromiscuous;
447 ether->multicast = lan78xxmulticast;
448 ether->mbps = 100; /* BUG */
449 return 0;
450 }
451 return -1;
452 }
453