2 * Microchip (ex SMSC) LAN78XX
3 * Also used as ethernet core in LAN7515 usb hub + ethernet
19 Rxfifosize = (12*1024),
20 Txfifosize = (12*1024),
27 /* USB vendor requests */
31 /* device registers */
108 Adall = Ad10h|Ad10f|Ad100h|Ad100f,
123 static int burstcap = Hsburst, bulkdelay = Defbulkdly;
126 wr(Dev *d, int reg, int val)
130 ret = usbcmd(d, Rh2d|Rvendor|Rdev, Writereg, 0, reg,
131 (uchar*)&val, sizeof(val));
133 fprint(2, "%s: wr(%x, %x): %r", argv0, reg, val);
142 ret = usbcmd(d, Rd2h|Rvendor|Rdev, Readreg, 0, reg,
143 (uchar*)&rval, sizeof(rval));
145 fprint(2, "%s: rr(%x): %r", argv0, reg);
152 miird(Dev *d, int idx)
154 while(rr(d, MIIaddr) & MIIbusy)
156 wr(d, MIIaddr, PHYinternal<<11 | idx<<6 | MIIread | MIIbusy);
157 while(rr(d, MIIaddr) & MIIbusy)
159 return rr(d, MIIdata);
163 miiwr(Dev *d, int idx, int val)
165 while(rr(d, MIIaddr) & MIIbusy)
168 wr(d, MIIaddr, PHYinternal<<11 | idx<<6 | MIIwrite | MIIbusy);
169 while(rr(d, MIIaddr) & MIIbusy)
174 eepromr(Dev *d, int off, uchar *buf, int len)
178 for(i = 0; i < E2pbusytime; i++)
179 if((rr(d, E2pcmd) & Busy) == 0)
183 for(i = 0; i < len; i++){
184 wr(d, E2pcmd, Busy|Read|(i+off));
185 while((v = rr(d, E2pcmd) & (Busy|Timeout)) == Busy)
189 buf[i] = rr(d, E2pdata);
199 miiwr(d, Bmcr, Bmcrreset|Anenable);
200 for(i = 0; i < Resettime/10; i++){
201 if((miird(d, Bmcr) & Bmcrreset) == 0)
205 miiwr(d, Advertise, Adcsma|Adall|Adpause|Adpauseasym);
206 miiwr(d, Ctrl1000, Ad1000f);
207 miiwr(d, Phyintmask, 0);
208 miiwr(d, Ledmodes, (Linkact<<Led1shift) | (Link1000<<Led0shift));
209 miiwr(d, Bmcr, miird(d, Bmcr)|Anenable|Anrestart);
214 doreset(Dev *d, int reg, int bit)
218 if(wr(d, reg, bit) < 0)
220 for(i = 0; i < Resettime/10; i++){
221 if((rr(d, reg) & bit) == 0)
229 lan78xxreceive(Dev *ep)
235 n = Doburst? burstcap*512: Maxpkt;
237 if((n = read(ep->dfd, b->wp, n)) < 10){
242 while(BLEN(b) >= 10){
248 if((hd & Rxerror) == 0){
253 etheriq(copyblock(b, n));
255 b->rp = (uchar*)(((uintptr)b->rp + n + 3)&~3);
262 lan78xxtransmit(Dev *ep, Block *b)
264 int n = BLEN(b) & 0xFFFFF;
266 PUT4(b->rp, n | Txfcs);
268 write(ep->dfd, b->rp, BLEN(b));
273 lan78xxpromiscuous(Dev *d, int on)
277 rxctl = rr(d, Rfectl);
285 return wr(d, Rfectl, rxctl);
289 lan78xxmulticast(Dev *d, uchar *, int)
293 rxctl = rr(d, Rfectl);
298 return wr(d, Rfectl, rxctl);
307 if(!doreset(d, Hwcfg, Lrst) || !doreset(d, Pmctrl, Phyrst))
309 for(i = 0; i < Resettime/10; i++){
310 if(rr(d, Pmctrl) & Ready)
314 if((rr(d, Pmctrl) & Ready) == 0){
315 fprint(2, "%s: device not ready after reset\n", argv0);
320 if(eepromr(d, MACoffset, macaddr, Eaddrlen) < 0)
321 fprint(2, "%s: can't read etheraddr from EEPROM\n", argv0);
328 wr(d, Addrfilth, a|Afvalid);
330 wr(d, Usbcfg0, rr(d, Usbcfg0) | Bir);
332 wr(d, Hwcfg, rr(d, Hwcfg)|Mef);
333 wr(d, Usbcfg0, rr(d, Usbcfg0)|Bce);
334 wr(d, Burstcap, burstcap);
335 wr(d, Bulkdelay, bulkdelay);
337 wr(d, Hwcfg, rr(d, Hwcfg)&~Mef);
338 wr(d, Usbcfg0, rr(d, Usbcfg0)&~Bce);
342 wr(d, Rxfifo, (Rxfifosize-512)/512);
343 wr(d, Txfifo, (Txfifosize-512)/512);
345 wr(d, Hwcfg, rr(d, Hwcfg) | Led0en|Led1en);
348 wr(d, Rfectl, (rr(d, Rfectl) & ~Rxcoe) | Ab|Dpf); /* TODO could offload checksums? */
352 wr(d, Maccr, rr(d,Maccr)|Add|Asd);
354 wr(d, Intepctl, rr(d, Intepctl)|Phyint);
355 wr(d, Mactx, Mactxen);
356 wr(d, Macrx, rr(d, Macrx) | Macfcs|Macrxen);
357 wr(d, Txfifoctl, Txen);
358 wr(d, Rxfifoctl, Rxen);
360 eptransmit = lan78xxtransmit;
361 epreceive = lan78xxreceive;
362 eppromiscuous = lan78xxpromiscuous;
363 epmulticast = lan78xxmulticast;