2 * marvell 88e8057 yukon2
3 * copyright © 2009-10 erik quanstrom
6 #include "../port/lib.h"
11 #include "../port/error.h"
12 #include "../port/netif.h"
13 #include "../port/etherif.h"
15 #define Pciwaddrh(x) 0
16 #define Pciwaddrl(x) PCIWADDR(x)
17 #define is64() (sizeof(uintptr) == 8)
18 #define dprint(...) if(debug) print(__VA_ARGS__); else {}
20 extern void sfence(void);
30 Rringl = Rringcnt - 8,
43 Ctst = 0x0004/2, /* control and status */
44 Pwrctl = 0x0007, /* power control */
45 Isr = 0x0008/4, /* interrupt src */
46 Ism = 0x000c/4, /* interrupt mask */
47 Hwe = 0x0010/4, /* hw error */
48 Hwem = 0x0014/4, /* hw error mask*/
51 Lisr = 0x0028/4, /* leave isr */
53 Macadr = 0x0100, /* mac address 2ports*3 */
57 Ramcnt = 0x011c, /* # of 4k blocks */
65 Rictl = 0x01a0, /* ri ram buffer ctl */
66 Rib = 0x0190, /* ri buffer0 */
68 /* other unoffset registers */
69 Asfcs = 0x0e68, /* asf command and status */
72 Statctl = 0x0e80/4, /* status */
73 Stattl = 0x0e84/2, /* tail (previous) status addr */
74 Stataddr = 0x0e88/4, /* status address low */
77 Statwm = 0x0eac, /* stat watermark */
78 Statiwm = 0x0ead, /* isr stat watermark */
80 Dpolltm = 0x0e08/4, /* descriptor pool timer */
83 Tgv = 0x0e14/4, /* gmac timer current value */
84 Tgc = 0x0e18, /* gmac timer ctl */
85 Tgt = 0x0e1a, /* gmac timer test */
87 Tsti = 0x0ec0/4, /* stat tx timer ini */
88 Tlti = 0x0eb0/4, /* level */
89 Titi = 0x0ed0/4, /* isr */
91 Tstc = 0x0ec8, /* stat tx timer ctl */
92 Tltc = 0x0eb8, /* level timer ctl */
93 Titc = 0x0ed8, /* isr timer ctl */
95 /* “gmac” registers */
102 Serctl = 0x018/2, /* serial mode */
103 Mchash = 0x034/2, /* 4 registers; 4 bytes apart */
105 /* interrupt sources and masks */
108 Trirq = 0x04c/2, /* tx/rx overflow irq source */
113 Smictl = 0x080/2, /* serial mode control */
117 Ea0 = 0x01c/2, /* 3 16 bit gmac registers */
123 Txactl = 0x210, /* transmit arbiter ctl */
125 Grxea = 0x0c40/4, /* rx fifo end address */
126 Gfrxctl = 0x0c48/4, /* gmac rxfifo ctl */
127 Grxfm = 0x0c4c/4, /* fifo flush mask */
128 Grxft = 0x0c50/4, /* fifo flush threshold */
129 Grxtt = 0x0c54/4, /* rx truncation threshold */
130 Gmfea = 0x0d40/4, /* end address */
131 Gmfae = 0x0d44/4, /* almost empty thresh */
132 Gmfctl = 0x0d48/4, /* tx gmac fifo ctl */
134 Rxphi = 0x0c58, /* pause high watermark */
135 Rxplo = 0x0c5c, /* pause low watermark */
142 Mac = 0x0f00/4, /* global mac control */
143 Phy = 0x0f04/4, /* phy control register */
145 Irq = 0x0f08, /* irq source */
146 Irqm = 0x0f0c, /* irq mask */
149 /* queue registers; all offsets from Qbase*/
151 Qportsz = 0x0080, /* BOTCH; tx diff is 2x rx diff */
164 Qcsr = 0x34, /* 32bit */
168 /* buffer registers; all offsets from Rbase */
175 Rpon = 0x10, /* pause frames on */
176 Rpoff = 0x14, /* pause frames off */
177 Rhon = 0x18, /* high-priority frames on */
178 Rhoff = 0x1c, /* high-priority frames off */
184 Plidx = 0x04, /* last addr; 16 bit */
187 Pgetidx = 0x10, /* 16 bit */
188 Pputidx = 0x14, /* 16 bit */
189 Pfifow = 0x20, /* 8 bit */
190 Pfifor = 0x24, /* 8 bit */
191 Pfifowm = 0x20, /* 8 bit */
193 /* indirect phy registers */
198 Phyana = 0x004, /* auto neg advertisement */
199 Phylpa = 0x005, /* link partner ability */
200 Phyanee = 0x006, /* auto neg adv expansion */
201 Phynp = 0x007, /* next page */
202 Phylnp = 0x008, /* link partner next page */
205 Phyphy = 0x010, /* phy specific ctl */
207 Phyintm = 0x012, /* phy interrupt mask */
210 Phyrxe = 0x015, /* rx error counter */
211 Phypage = 0x016, /* external address */
212 Phypadr = 0x01d, /* phy page address */
218 Aspglinkdn = 1<<14, /* gphy link down */
221 Aspmsk = Aspforce | Aspglinkdn | Aspfempty | Aspclkrun,
227 Sfast = 1<<15, /* 100mbit */
229 Txnofc = 1<<13, /* tx flow control disabled */
230 Link = 1<<12, /* link up */
231 Pausest = 1<<11, /* pause state */
235 Physc = 1<<5, /* phy status change */
236 Sgbe = 1<<4, /* gbe speed */
237 Rxnofc = 1<<2, /* rx flow control disabled */
238 Promisc = 1<<1, /* promiscuous mode enabled */
248 Fpass = 1<<6, /* "force link pass" ? */
251 Fasten = 1<<3, /* enable 100mbit */
252 Adudis = 1<<2, /* disable auto upd duplex */
253 Afcdis = 1<<1, /* disable auto upd flow ctl */
254 Aspddis = 1<<0, /* disable auto upd speed */
257 Ufilter = 1<<15, /* unicast filter */
258 Mfilter = 1<<14, /* multicast filter */
259 Rmcrc = 1<<13, /* remove frame crc */
269 /* Asfcs: yukex only */
270 Asfbrrst = 1<<9, /* bridge reset */
271 Asfcpurst = 1<<8, /* cpu reset */
272 Asfucrst = 3<<0, /* µctlr reset */
275 Asfhvos = 1<<4, /* os present */
289 Nomacsec = 1<<13 | 1<<11,
301 Txovfl = 1<<5, /* tx counter overflow */
302 Rxovfl = 1<<4, /* rx counter overflow */
303 Txurun = 1<<3, /* transmit fifo underrun */
304 Txdone = 1<<2, /* frame tx done */
305 Rxorun = 1<<1, /* rx fifo overrun */
306 Rxdone = 1<<0, /* frame rx done */
322 Asfdis = 1<<12, /* asf disable */
323 Clken = 1<<11, /* enable clock */
327 Mstopped = 1<<5, /* master is stopped */
328 Mstop = 1<<4, /* stop master */
329 Mstrclr = 1<<3, /* master reset clear */
330 Mstrrset = 1<<2, /* master reset */
353 /* csr interrupts: Isrc2, Eisr, etc. */
355 Ibmu = 1<<30, /* sring irq */
361 Itxs = 1<<1, /* descriptor error */
362 Itx = 1<<0, /* descriptor error */
366 Ierror = (Imac | Itx | Irx)*(1 | 1<<Iphy2base),
368 /* hwe interrupts: Hwe Hwem */
369 Htsof = 1<<29, /* timer stamp overflow */
371 Hmerr = 1<<27, /* master error */
372 Hstatus = 1<<26, /* status exception */
373 Hpcie = 1<<25, /* pcie error */
374 Hpcie2 = 1<<24, /* " */
376 Hrparity = 1<<5, /* ram read parity error */
377 Hwparity = 1<<4, /* ram write parity error */
378 Hmfault = 1<<3, /* mac fault */
379 Hrxparity = 1<<2, /* rx parity */
380 Htcptxs = 1<<1, /* tcp length mismatch */
381 Htcptxa = 1<<0, /* tcp length mismatch */
386 Hdflt = Htsof | Hmerr | Hstatus | Hmask*(H1base | H2base),
393 Link2inactive = 1<<7,
397 Phy100 = 1<<14, /* manual enable 100mbit */
398 Aneen = 1<<12, /* auto negotiation enable */
399 Phyoff = 1<<11, /* turn phy off */
400 Anerst = 1<<9, /* auto neg reset */
402 Phy1000 = 1<<5, /* manual enable gbe */
405 Annp = 1<<15, /* request next page */
406 Anack = 1<<14, /* ack rx (read only) */
407 Anrf = 1<<13, /* remote fault */
408 Anpa = 1<<11, /* try asymmetric pause */
409 Anp = 1<<10, /* try pause */
415 Anall = An100f | An100h | An10f | An10h | Anonly,
418 Gbef = 1<<9, /* auto neg gbe full */
419 Gbeh = 1<<8, /* auto neg gbe half */
420 Gbexf = 1<<6, /* auto neg gbe full fiber */
421 Gbexh = 1<<5, /* auto neg gbe full fiber */
424 Pptf = 3<<14, /* tx fifo depth */
425 Pprf = 3<<12, /* rx fifo depth */
426 Pped = 3<<8, /* energy detect */
427 Ppmdix = 3<<5, /* mdix conf */
428 Ppmdixa = 3<<5, /* automdix */
430 Ppengy = 1<<14, /* fe+ enable energy detect */
431 Ppscrdis = 1<<9, /* fe+ scrambler disable */
432 Ppnpe = 1<<12, /* fe+ enable next page */
437 Phypr = 1<<12, /* page rx */
438 Phydone = 1<<11, /* speed and duplex neg. done */
442 Pdwnsh = 1<<5, /* downshift */
443 Penergy = 1<<4, /* energy detect */
444 Ptxpause = 1<<3, /* tx pause enabled */
445 Prxpause = 1<<2, /* rx pause enabled */
446 Ppol = 1<<2, /* polarity */
447 Pjarjar = 1<<1, /* mesa no understasa */
450 Anerr = 1<<15, /* an error */
451 Lsp = 1<<14, /* link speed change */
452 Andc = 1<<13, /* an duplex change */
454 Lsc = 1<<10, /* link status change */
455 Symerr = 1<<9, /* symbol error */
456 Fcarr = 1<<8, /* false carrier */
460 Engych = 1<<4, /* energy change */
461 Dtech = 1<<2, /* dte power det status */
462 Polch = 1<<1, /* polarity change */
466 Dnmstr = 1<<9, /* master downshift; 0: 1x; 1: 2x; 2: 3x */
472 Tgclr = 1<<0, /* clear irq */
475 Tstwen = 1<<1, /* enable config reg r/w */
476 Tstwdis = 1<<0, /* disable config reg r/w */
488 Rsfon = 1<<5, /* enable store/fwd */
501 Qsumen = 1<<13, /* tcp/ip cksum */
503 Qcirqpar = 1<<11, /* clear irq on parity errors */
516 Qallclr = Qfiforst | Qfifooff | Qrstclr,
517 Qgo = Qcirqpar | Qcirqck | Qstart | Qfifoen | Qenable,
520 Qckoff = 1<<31, /* tx: auto checksum off */
522 Qramdis = 1<<24, /* rx: ram disable */
525 Prefon = 1<<3, /* prefetch on */
531 Hw = 0x80, /* bitmask */
532 Ock = 0x12, /* tcp checksum start */
537 Orxts = 0x61, /* rx timestamp */
541 Omacs = 0x6c, /* macsec */
551 Gfroon = 1<<19, /* flush on rx overrun */
553 Gffon = 1<<7, /* rx fifo flush mode on */
561 Gmfsfoff = 1<<31, /* disable store-forward (ec ultra) */
562 Gmfsfon = 1<<30, /* able store-forward (ec ultra) */
563 Gmfvon = 1<<25, /* vlan tag on */
564 Gmfvoff = 1<<24, /* vlan off */
565 Gmfjon = 1<<23, /* jumbo on (ec ultra) */
566 Gmfjoff = 1<<22, /* jumbo off */
567 Gmfcfu = 1<<6, /* clear fifio underrun irq */
568 Gmfcfc = 1<<5, /* clear frame complete irq */
569 Gmfcpe = 1<<4, /* clear parity error irq */
580 Fmc = 1<<10, /* multicast */
582 Fok = 1<<8, /* good frame */
586 Ftoobg = 1<<4, /* oversized */
587 Ffrag = 1<<3, /* fragment */
589 Ffifoof = 1<<0, /* fifo overflow */
590 Ferror = Ffifoof | Fcrcerr | Ffrag | Ftoobg
591 | Fmiierr | Fbadfc | Ftoosm | Fjabbr,
593 /* rx checksum bits in Status.ctl */
594 Badck = 5, /* arbitrary bad checksum */
596 Ctcpok = 1<<7, /* tcp or udp cksum ok */
600 /* more status ring rx bits */
602 Rxjab = 1<<12, /* jabber */
603 Rxsmall = 1<<11, /* too small */
604 Rxmc = 1<<10, /* multicast */
605 Rxbc = 1<<9, /* bcast */
607 Rxfcok = 1<<7, /* flow control pkt */
610 Rxbig = 1<<4, /* too big */
613 Rxfov = 1<<0, /* fifo overflow */
614 Rxerror = Rxfov | Rxcrcerr | Rxfrag | Rxbig | Rxmiierr
615 | Rxfcbad | Rxsmall | Rxjab,
625 Fancy =Fgbe | Fnewphy | Fapwr,
635 Yukba, /* doesn't exist */
640 typedef struct Chipid Chipid;
641 typedef struct Ctlr Ctlr;
642 typedef void (*Freefn)(Block*);
643 typedef struct Kproc Kproc;
644 typedef struct Mc Mc;
645 typedef struct Stattab Stattab;
646 typedef struct Status Status;
647 typedef struct Sring Sring;
648 typedef struct Vtab Vtab;
672 Ctlr *oport; /* port 2 */
695 Block *tbring[Tringcnt];
697 Block *rbring[Rringcnt];
727 static Chipid idtab[] = {
728 [Yukxl] Fgbe | Fnewphy, 0xff, 156, "yukon-2 xl",
729 [Yukecu] Fancy, 0xff, 125, "yukon-2 ec ultra",
730 [Yukex] Fancy | Fnewle, 0xff, 125, "yukon-2 extreme",
731 [Yukec] Fgbe, 2, 125, "yukon-2 ec",
732 [Yukfe] 0, 0xff, 100, "yukon-2 fe",
733 [Yukfep] Fnewphy|Fapwr | Fnewle, 0xff, 50, "yukon-2 fe+",
734 [Yuksup] Fgbe | Fnewphy | Fnewle, 0xff, 125, "yukon-2 supreme",
735 [Yukul2] Fgbe |Fapwr, 0xff, 125, "yukon-2 ultra2",
736 [Yukba] 0, 0, 0, "??",
737 [Yukopt] Fancy, 0xff, 125, "yukon-2 optima",
740 static Vtab vtab[] = {
741 0x11ab, 0x4354, 1514, "88e8040", /* unsure on mtu */
742 0x11ab, 0x4362, 1514, "88e8053",
743 0x11ab, 0x4363, 1514, "88e8055",
744 0x11ab, 0x4364, 1514, "88e8056",
745 0x11ab, 0x4380, 1514, "88e8057",
746 0x11ab, 0x436b, 1514, "88e8071", /* unsure on mtu */
747 0x1186, 0x4b00, 9000, "dge-560t",
748 0x1186, 0x4b02, 1514, "dge-550sx",
749 0x1186, 0x4b03, 1514, "dge-550t",
752 static Stattab stattab[] = {
764 80, "rx frames < 64",
765 88, "rx frames < 64 fcs",
767 104, "rx frames 65-127",
768 112, "rx frames 128-255",
769 120, "rx frames 256-511",
770 128, "rx frames 512-1023",
771 136, "rx frames 1024-1518",
772 144, "rx frames 1519-mtu",
773 152, "rx frames too long",
775 176, "rx fifo oflow",
786 248, "tx frames 65-127",
787 256, "tx frames 128-255",
788 264, "tx frames 256-511",
789 272, "tx frames 512-1023",
790 280, "tx frames 1024-1518",
791 288, "tx frames 1519-mtu",
795 320, "tx excess coll",
797 336, "tx single col",
801 static uint phypwr[] = {1<<26, 1<<27};
802 static uint coma[] = {1<<28, 1<<29};
803 static uchar nilea[Eaddrlen];
805 static Ctlr *ctlrtab[Nctlr];
814 return k->event != 0;
827 sleep(k, icansleep, k);
832 getnslot(Sring *r, uint *wp, Status **t, uint n)
836 if(r->m - (int)(wp[0] - r->rp) < n)
838 for(i = 0; i < n; i++)
839 t[i] = r->r + (wp[0]++ & r->m);
844 macread32(Ctlr *c, uint r)
846 return c->reg[c->portno*0x20 + r];
850 macwrite32(Ctlr *c, uint r, uint v)
852 c->reg[c->portno*0x20 + r] = v;
856 macread16(Ctlr *c, uint r)
858 return c->reg16[c->portno*0x40 + r];
862 macwrite16(Ctlr *c, uint r, uint v)
864 c->reg16[c->portno*0x40 + r] = v;
868 macread8(Ctlr *c, uint r)
870 return c->reg8[c->portno*0x80 + r];
874 macwrite8(Ctlr *c, uint r, uint v)
876 c->reg8[c->portno*0x80 + r] = v;
879 static uint gmac32[2] = {
885 gmacread32(Ctlr *c, uint r)
887 return c->reg[gmac32[c->portno] + r];
891 gmacwrite32(Ctlr *c, uint r, uint v)
893 c->reg[gmac32[c->portno] + r] = v;
896 static uint gmac[2] = {
902 gmacread(Ctlr *c, uint r)
904 return c->reg16[gmac[c->portno] + r];
908 gmacwrite(Ctlr *c, uint r, ushort v)
910 c->reg16[gmac[c->portno] + r] = v;
914 qrread(Ctlr *c, uint r)
916 return c->reg[Qbase + c->portno*Qportsz + r>>2];
920 qrwrite(Ctlr *c, uint r, uint v)
922 c->reg[Qbase + c->portno*Qportsz + r>>2] = v;
926 qrread16(Ctlr *c, uint r)
928 return c->reg16[Qbase + c->portno*Qportsz + r>>1];
932 qrwrite16(Ctlr *c, uint r, uint v)
934 c->reg16[Qbase + c->portno*Qportsz + r>>1] = v;
938 qrread8(Ctlr *c, uint r)
940 return c->reg8[Qbase + c->portno*Qportsz + r>>0];
944 qrwrite8(Ctlr *c, uint r, uint v)
946 c->reg8[Qbase + c->portno*Qportsz + r>>0] = v;
950 rrread32(Ctlr *c, uint r)
952 return c->reg[Rbase + c->portno*Qportsz + r>>2];
956 rrwrite32(Ctlr *c, uint r, uint v)
958 c->reg[Rbase + c->portno*Qportsz + r>>2] = v;
962 rrwrite8(Ctlr *c, uint r, uint v)
964 c->reg8[Rbase + c->portno*Qportsz + r] = v;
968 rrread8(Ctlr *c, uint r)
970 return c->reg8[Rbase + c->portno*Qportsz + r];
974 prread32(Ctlr *c, uint r)
976 return c->reg[Pbase + c->portno*Qportsz + r>>2];
980 prwrite32(Ctlr *c, uint r, uint v)
982 c->reg[Pbase + c->portno*Qportsz + r>>2] = v;
986 prread16(Ctlr *c, uint r)
988 return c->reg16[Pbase + c->portno*Qportsz + r>>1];
992 prwrite16(Ctlr *c, uint r, uint v)
994 c->reg16[Pbase + c->portno*Qportsz + r>>1] = v;
998 phyread(Ctlr *c, uint r)
1002 gmacwrite(c, Smictl, Smiread | r<<6);
1004 v = gmacread(c, Smictl);
1008 return gmacread(c, Smidata);
1014 phywrite(Ctlr *c, uint r, ushort v)
1016 gmacwrite(c, Smidata, v);
1017 gmacwrite(c, Smictl, Smiwrite | r<<6);
1019 v = gmacread(c, Smictl);
1022 if((v & Smibusy) == 0)
1023 return gmacread(c, Smidata);
1028 static uvlong lorder = 0x0706050403020100ull;
1031 getle(uchar *t, int w)
1037 for(i = w; i != 0; )
1043 putle(uchar *t, uvlong r, int w)
1049 o = (uchar*)&lorder;
1050 for(i = 0; i < w; i++)
1055 bufinit(Ctlr *c, uint q, uint start, uint end)
1059 rrwrite8(c, q + Rctl, Rrstclr);
1060 rrwrite32(c, q + Rstart, start);
1061 rrwrite32(c, q + Rend, end-1);
1062 rrwrite32(c, q + Rwp, start);
1063 rrwrite32(c, q + Rrp, start);
1065 if(q == Qr || q == Qr + Qportsz){
1067 rrwrite32(c, q + Rpon, t - 8192/8);
1068 rrwrite32(c, q + Rpoff, t - 16384/8);
1070 rrwrite8(c, q + Rctl, Rsfon);
1071 rrwrite8(c, q + Rctl, Renable);
1072 rrread8(c, q + Rctl);
1076 qinit(Ctlr *c, uint queue)
1078 qrwrite(c, queue + Qcsr, Qallclr);
1079 qrwrite(c, queue + Qcsr, Qgo);
1080 qrwrite(c, queue + Qcsr, Qfifoon);
1081 qrwrite16(c, queue + Qwm, 0x600); /* magic */
1082 // qrwrite16(c, queue + Qwm, 0x80); /* pcie magic; assume pcie; no help */
1085 /* initialized prefetching */
1087 pinit(Ctlr *c, uint queue, Sring *r)
1094 prwrite32(c, queue + Pctl, Prefrst);
1095 prwrite32(c, queue + Pctl, Prefrstclr);
1096 putle(u.u, Pciwaddrh(r->r), 4);
1097 prwrite32(c, queue + Paddrh, u.l);
1098 putle(u.u, Pciwaddrl(r->r), 4);
1099 prwrite32(c, queue + Paddrl, u.l);
1100 prwrite16(c, queue + Plidx, r->m);
1101 prwrite32(c, queue + Pctl, Prefon);
1102 prread32(c, queue + Pctl);
1119 pinit(c, Qtx, &c->tx);
1123 linkup(Ctlr *c, uint w)
1128 gmacwrite(c, Ctl, w|gmacread(c, Ctl));
1150 if((b = qbread(e->oq, 100000)) == nil)
1152 while(getnslot(r, &r->wp, tab, 1 + is64()) == -1)
1155 c->tbring[t - r->r] = b;
1159 t->op = Oaddr64 | Hw;
1160 putle(t->status, Pciwaddrh(b->rp), 4);
1162 putle(t->status, Pciwaddrl(b->rp), 4);
1163 putle(t->l, BLEN(b), 2);
1167 prwrite16(c, Qtx + Pputidx, r->wp & r->m);
1169 print("#l%d: tproc: queue closed\n", e->ctlrno);
1170 pexit("queue closed", 1);
1186 if(c->type == Yukecu && (c->rev == 2 || c->rev == 3))
1187 qrwrite(c, Qr + Qtest, Qramdis);
1188 pinit(c, Qr, &c->rx);
1190 if((c->flag & Fnewle) == 0){
1191 while(getnslot(r, &r->wp, &t, 1) == -1)
1193 putle(t->status, 14<<16 | 14, 4);
1196 qrwrite(c, Qr + Qcsr, Qsumen);
1198 macwrite32(c, Gfrxctl, Gftroff);
1202 #include "yukdump.h"
1204 rxscrew(Ether *e, Sring *r, Status *t, uint wp)
1209 if((int)(wp - r->rp) >= r->cnt){
1210 print("rxscrew1 wp %ud(%ud) rp %ud %zd\n", wp, r->wp, r->rp, t-r->r);
1213 if(c->rbring[t - r->r]){
1214 print("rxscrew2 wp %ud rp %ud %zd\n", wp, r->rp, t-r->r);
1215 descriptorfu(e, Qr);
1222 replenish(Ether *e, Ctlr *c)
1235 lim = 128; /* hw limit? */
1236 for(n = 0; n < lim; n++){
1237 b = iallocb(c->rbsz + Rbalign);
1238 if(b == nil || getnslot(r, &wp, tab, 1 + is64()) == -1){
1242 b->rp = b->wp = (uchar*)ROUND((uintptr)b->base, Rbalign);
1245 if(rxscrew(e, r, t, wp) == -1){
1249 c->rbring[t - r->r] = b;
1253 putle(t->status, Pciwaddrh(b->wp), 4);
1255 t->op = Oaddr64 | Hw;
1257 putle(t->status, Pciwaddrl(b->wp), 4);
1258 putle(t->l, c->rbsz, 2);
1265 prwrite16(c, Qr + Pputidx, wp & r->m);
1266 dprint("yuk: replenish %d %ud-%ud [%d-%d]\n", n, r->rp, wp, r->rp&r->m, wp&r->m);
1285 if(replenish(e, c) == 0)
1291 promiscuous(void *a, int on)
1299 r = gmacread(c, Rxctl);
1301 r &= ~(Ufilter|Mfilter);
1303 r |= Ufilter|Mfilter;
1304 gmacwrite(c, Rxctl, r);
1307 static uchar pauseea[] = {1, 0x80, 0xc2, 0, 0, 1};
1310 multicast(void *a, uchar *ea, int on)
1320 r = gmacread(c, Rxctl);
1322 for(ll = &c->mc; *ll != nil; ll = &(*ll)->next)
1323 if(memcmp((*ll)->ea, ea, Eaddrlen) == 0)
1325 *ll = malloc(sizeof **ll);
1326 memmove((*ll)->ea, ea, Eaddrlen);
1328 for(p = nil, l = c->mc; l != nil; p = l, l = l->next)
1329 if(memcmp(l->ea, ea, Eaddrlen) == 0)
1339 memset(f, 0, sizeof f);
1340 if(0 /* flow control */){
1341 b = ethercrc(pauseea, Eaddrlen) & 0x3f;
1342 f[b>>3] |= 1 << (b & 7);
1344 for(l = c->mc; l != nil; l = l->next){
1345 b = ethercrc(l->ea, Eaddrlen) & 0x3f;
1346 f[b>>3] |= 1 << (b & 7);
1348 for(i = 0; i < sizeof f / 2; i++)
1349 gmacwrite(c, Mchash + 2*i, f[i] | f[i+1]<<8);
1350 gmacwrite(c, Rxctl, r | Mfilter);
1353 static int spdtab[4] = {
1364 i = phyread(c, Phyint);
1365 s = phyread(c, Phylstat);
1366 dprint("#l%d: yuk: link %.8ux %.8ux\n", e->ctlrno, i, s);
1368 e->link = (s & Plink) != 0;
1369 if(e->link && c->feat&Ffiber)
1377 dprint("#l%d: yuk: link %d spd %d\n", e->ctlrno, e->link, e->mbps);
1381 txcleanup(Ctlr *c, uint end)
1390 for(rp = r->rp & r->m; rp != end; rp = r->rp & r->m){
1393 if((t->ctl & Eop) == 0)
1396 c->tbring[rp] = nil;
1400 unstarve(&c->txmit);
1404 rx(Ether *e, uint l, uint x, uint flag)
1415 print("#l%d: yuk rx empty\n", e->ctlrno);
1425 cnt = x>>16 & 0x7fff;
1426 if((cnt != l || x&Rxerror) &&
1427 !(c->type == Yukfep && c->rev == 0)){
1428 print("#l%d: yuk rx error %.4ux\n", e->ctlrno, x&0xffff);
1435 unstarve(&c->rxmit);
1439 cksum(Ctlr *c, uint ck, uint css)
1441 if(c->flag & Fnewle && css&(Cisip4|Cisip6) && css&Ctcpok)
1442 return Bipck | Btcpck | Budpck;
1443 else if(ck == 0xffff || ck == 0)
1451 uint i, lim, op, l, x;
1455 static uint ck = Badck;
1459 lim = c->reg16[Stathd] & r->m;
1463 lim = c->reg16[Stathd] & r->m;
1474 ck = getle(s->status, 4) & 0xffff;
1478 x = getle(s->status, 4);
1479 rx(e, l, x, cksum(c, ck, s->ctl));
1484 x = getle(s->status, 4);
1485 txcleanup(c, x & 0xfff);
1487 x = l>>24 & 0xff | l<< 8;
1489 if(x != 0 && c->oport)
1490 txcleanup(c->oport, x);
1493 print("#l%d: yuk: funny opcode %.2ux\n", e->ctlrno, op);
1499 c->reg[Statctl] = Statirqclr;
1508 hwerror(Ether *e, uint cause)
1514 cause = c->reg[Hwe];
1516 print("hwe: no cause\n");
1518 c->reg8[Tgc] = Tgclr;
1521 if(cause & (Hmerr | Hstatus)){
1522 c->reg8[Tstctl1] = Tstwen;
1523 u = pcicfgr16(c->p, PciPSR) | 0x7800;
1524 pcicfgw16(c->p, PciPSR, u);
1525 c->reg8[Tstctl1] = Tstwdis;
1526 cause &= ~(Hmerr | Hstatus);
1529 c->reg8[Tstctl1] = Tstwen;
1530 c->reg[Pciaer + Pciunc>>2] = ~0;
1531 u = c->reg[Pciaer + Pciunc>>2];
1533 print("#l%d: pcierror %.8ux\n", e->ctlrno, u);
1534 c->reg8[Tstctl1] = Tstwdis;
1537 if(cause & Hrxparity){
1538 print("#l%d: ram parity read error. bug? ca %.8ux\n", e->ctlrno, cause);
1539 qrwrite(c, Qtx + Qcsr, Qcirqpar);
1540 cause &= ~Hrxparity;
1542 if(cause & Hrparity){
1543 print("#l%d: ram parity read error. bug? ca %.8ux\n", e->ctlrno, cause);
1544 descriptorfu(e, Qr);
1545 descriptorfu(e, Qtx);
1546 c->reg16[Rictl + c->portno*0x40>>1] = Rirpclr;
1549 if(cause & Hwparity){
1550 print("#l%d: ram parity write error. bug? ca %.8ux\n", e->ctlrno, cause);
1551 descriptorfu(e, Qr);
1552 descriptorfu(e, Qtx);
1553 c->reg16[Rictl + c->portno*0x40>>1] = Riwpclr;
1556 if(cause & Hmfault){
1557 print("#l%d: mac parity error\n", e->ctlrno);
1558 macwrite32(c, Gmfctl, Gmfcpe);
1562 print("#l%d: leftover hwe %.8ux\n", e->ctlrno, cause);
1572 cause = macread8(c, Irq);
1573 cause &= ~(Rxdone | Txdone);
1576 print("#l%d: mac error %.8ux\n", e->ctlrno, cause);
1578 gmacread32(c, Txirq);
1582 gmacread32(c, Rxirq);
1586 macwrite32(c, Gfrxctl, Gmfcfu);
1590 macwrite32(c, Gmfctl, Gmfcfu);
1594 print("#l%d: leftover mac error %.8ux\n", e->ctlrno, cause);
1605 Irx<<Iphy2base, Qr + 0x80, "qr1",
1606 Itxs<<Iphy2base, Qtxs + 0x100, "qtxs1",
1607 Itx<<Iphy2base, Qtx + 0x100, "qtx1",
1611 eerror(Ether *e, uint cause)
1622 if(cause & (Irx | Itxs | Itx)*(1 | 1<<Iphy2base))
1623 for(i = 0; i < nelem(emap); i++){
1624 if((cause & emap[i].i) == 0)
1627 o = prread16(c, q + Pgetidx);
1628 print("#l%d: yuk: bug: %s: @%d ca=%.8ux\n",
1629 e->ctlrno, emap[i].s, o, cause);
1631 qrwrite(c, emap[i].q + Qcsr, Qcirqck);
1632 cause &= ~emap[i].i;
1635 print("#l%d: leftover error %.8ux\n", e->ctlrno, cause);
1651 cause = c->reg[Eisr];
1657 eerror(e, cause & Ierror);
1666 interrupt(Ureg*, void *v)
1675 /* reading Isrc2 masks interrupts */
1676 cause = c->reg[Isrc2];
1677 if(cause == 0 || cause == ~0){
1678 /* reenable interrupts */
1682 unstarve(&c->iproc);
1688 if(c->type == Yukex && c->rev != 1
1689 || c->type == Yukfep
1690 || c->type == Yuksup)
1691 macwrite32(c, Gmfctl, Gmfjon | Gmfsfon);
1693 macwrite32(c, Gmfae, 0x8000 | 0x70); /* tx gmac fifo */
1694 macwrite32(c, Gmfctl, Gmfsfoff);
1703 if(ram = c->reg8[Ramcnt] * 4096/8){ /* in qwords */
1705 rx = ROUNDUP((2*ram)/3, 1024/8);
1706 bufinit(c, Qr, 0, rx);
1707 bufinit(c, Qtx, rx, ram);
1708 rrwrite8(c, Qtxs + Rctl, Rrst); /* sync tx off */
1710 macwrite8(c, Rxplo, 768/8);
1711 macwrite8(c, Rxphi, 1024/8);
1734 snprint(buf, sizeof buf, "#l%dtproc", e->ctlrno);
1735 kproc(buf, tproc, e);
1736 snprint(buf, sizeof buf, "#l%drproc", e->ctlrno);
1737 kproc(buf, rproc, e);
1738 snprint(buf, sizeof buf, "#l%diproc", e->ctlrno);
1739 kproc(buf, iproc, e);
1741 c->reg[Ism] |= Ibmu | Iport<<Iphy2base*c->portno;
1745 ifstat(Ether *e0, void *a, long n, ulong offset)
1753 p = s = malloc(READSTR);
1755 for(i = 0; i < nelem(stattab); i++){
1756 u = gmacread32(c, Stats + stattab[i].offset/4);
1758 p = seprint(p, e, "%s\t%ud\n", stattab[i].name, u);
1760 p = seprint(p, e, "stat %.4ux ctl %.3ux\n", gmacread(c, Stat), gmacread(c, Ctl));
1761 p = seprint(p, e, "pref %.8ux %.4ux\n", prread32(c, Qr + Pctl), prread16(c, Qr + Pgetidx));
1763 p = dumppci(c, p, e);
1764 p = dumpgmac(c, p, e);
1765 p = dumpmac(c, p, e);
1766 p = dumpreg(c, p, e);
1768 seprint(p, e, "%s rev %d phy %s\n", idtab[c->type].name,
1769 c->rev, c->feat&Ffiber? "fiber": "copper");
1770 n = readstr(offset, a, n, s);
1775 static Cmdtab ctltab[] = {
1777 2, "descriptorfu", 1,
1781 ctl(Ether *e, void *buf, long n)
1786 cb = parsecmd(buf, n);
1791 t = lookupcmd(cb, ctltab, nelem(ctltab));
1797 descriptorfu(e, Qr);
1806 yukpcicfgr32(Ctlr *c, uint r)
1808 return c->reg[r + 0x1c00>>2];
1812 yukpcicfgw32(Ctlr *c, uint r, uint v)
1814 c->reg[r + 0x1c00>>2] = v;
1822 u = u0 = yukpcicfgr32(c, Pciphy);
1823 u &= ~phypwr[c->portno];
1824 if(c->type == Yukxl && c->rev > 1)
1825 u |= coma[c->portno];
1827 c->reg8[Tstctl1] = Tstwen;
1828 yukpcicfgw32(c, Pciphy, u);
1829 c->reg8[Tstctl1] = Tstwdis;
1831 if(c->type == Yukfe)
1832 c->reg8[Phyctl] = Aneen;
1833 else if(c->flag & Fapwr)
1834 macwrite32(c, Phy, Gphyrstclr);
1842 if((c->feat & Fnewphy) == 0){
1843 u = phyread(c, Phyextctl);
1844 u &= ~0xf70; /* clear downshift counters */
1845 u |= 0x7<<4; /* mac tx clock = 25mhz */
1846 if(c->type == Yukec)
1847 u |= 2*Dnmstr | Dnslv;
1850 phywrite(c, Phyextctl, u);
1852 u = phyread(c, Phyphy);
1854 /* questionable value */
1855 if(c->feat & Ffiber)
1857 else if(c->feat & Fgbe){
1860 if(c->flag & Fnewphy){
1862 // u |= 2*(1<<12) | 1<<11; /* like 2*Dnmstr | Dnslv */
1863 u |= 2*(1<<9) | 1<<11;
1866 u |= Ppmdixa >> 1; /* why the shift? */
1867 if(c->type == Yukfep && c->rev == 0){
1871 phywrite(c, Phyphy, u);
1872 /* copper/fiber specific stuff gmacwrite(c, Ctl, 0); */
1873 gmacwrite(c, Ctl, 0);
1875 if(c->feat & Ffiber)
1876 phywrite(c, Gbectl, Gbexf | Gbexh);
1878 phywrite(c, Gbectl, Gbef | Gbeh);
1879 phywrite(c, Phyana, Anall);
1880 phywrite(c, Phyctl, Phyrst | Anerst | Aneen);
1881 /* chip specific stuff? */
1882 if (c->type == Yukfep){
1883 u = phyread(c, Phyphy) | Ppnpe;
1884 u &= ~(Ppengy | Ppscrdis);
1885 phywrite(c, Phyphy, u);
1886 // phywrite(c, 0x16, 0x0b54); /* write to fe_led_par */
1888 /* yukfep and rev 0: apply workaround for integrated resistor calibration */
1889 phywrite(c, Phypadr, 17);
1890 phywrite(c, 0x1e, 0x3f60);
1892 phywrite(c, Phyintm, Anok | Anerr | Lsc);
1893 dprint("phyid %.4ux step %.4ux\n", phyread(c, 2), phyread(c, 3));
1901 pcicfgw32(c->p, Pciclk, 0);
1902 c->reg16[Ctst] = Swclr;
1904 c->type = c->reg8[Chip] - 0xb3;
1905 c->rev = c->reg8[Maccfg]>>4 & 0xf;
1908 if(idtab[c->type].okrev != 0xff)
1909 if(c->rev != idtab[c->type].okrev)
1911 c->feat |= idtab[c->type].feat;
1914 if(t == 'L' || t == 'S' || t == 'P')
1917 /* check second port ... whatever */
1922 µ2clk(Ctlr *c, int µs)
1924 return idtab[c->type].mhz * µs;
1928 gmacsetea(Ctlr *c, uint r)
1934 for(i = 0; i < Eaddrlen; i += 2)
1935 gmacwrite(c, r + i, ra[i + 0] | ra[i + 1]<<8);
1946 if(c->type == Yukex)
1947 c->reg16[Asfcs/2] &= ~(Asfbrrst | Asfcpurst | Asfucrst);
1949 c->reg8[Asfcs] = Asfrst;
1950 c->reg16[Ctst] = Asfdis;
1952 c->reg16[Ctst] = Swrst;
1953 c->reg16[Ctst] = Swclr;
1955 c->reg8[Tstctl1] = Tstwen;
1956 pcicfgw16(c->p, PciPSR, pcicfgr16(c->p, PciPSR) | 0xf100);
1957 c->reg16[Ctst] = Mstrclr;
1958 /* fixup pcie extended error goes here */
1960 c->reg8[Pwrctl] = Vauxen | Vccen | Vauxoff | Vccon;
1961 c->reg[Clkctl] = Clkdivdis;
1962 if(c->type == Yukxl && c->rev > 1)
1963 c->reg8[Clkgate] = ~Link2inactive;
1965 c->reg8[Clkgate] = 0;
1966 if(c->flag & Fapwr){
1967 pcicfgw32(c->p, Pciclk, 0);
1968 pcicfgw32(c->p, Pciasp, pcicfgr32(c->p, Pciasp) & Aspmsk);
1969 pcicfgw32(c->p, Pcistate, pcicfgr32(c->p, Pcistate) & Vmain);
1970 pcicfgw32(c->p, Pcicf1, 0);
1971 c->reg[Gpio] |= Norace;
1972 print("yuk2: advanced power %.8ux\n", c->reg[Gpio]);
1974 c->reg8[Tstctl1] = Tstwdis;
1976 for(i = 0; i < c->nports; i++){
1977 macwrite8(c, Linkctl, Linkrst);
1978 macwrite8(c, Linkctl, Linkclr);
1979 if(c->type == Yukex || c->type == Yuksup)
1980 macwrite16(c, Mac, Nomacsec | Nortx);
1983 c->reg[Dpolltm] = Pollstop;
1985 for(i = 0; i < c->nports; i++)
1986 macwrite8(c, Txactl, Txaclr);
1987 for(i = 0; i < c->nports; i++){
1988 c->reg8[i*64 + Rictl] = Riclr;
1989 for(j = 0; j < 12; j++)
1990 c->reg8[i*64 + Rib + j] = 36; /* qword times */
1993 c->reg[Hwem] = Hdflt;
1994 macwrite8(c, Irqm, 0);
1995 for(i = 0; i < 4; i++)
1996 gmacwrite(c, Mchash + 2*i, 0);
1997 gmacwrite(c, Rxctl, Ufilter | Mfilter | Rmcrc);
1999 for(i = 0; i < nelem(c->tbring); i++)
2000 if(b = c->tbring[i]){
2004 for(i = 0; i < nelem(c->rbring); i++)
2005 if(b = c->rbring[i]){
2010 memset(c->tbring, 0, sizeof c->tbring[0] * nelem(c->tbring));
2011 memset(c->rbring, 0, sizeof c->rbring[0] * nelem(c->rbring));
2012 memset(c->tx.r, 0, sizeof c->tx.r[0] * c->tx.cnt);
2013 memset(c->rx.r, 0, sizeof c->rx.r[0] * c->rx.cnt);
2014 memset(c->status.r, 0, sizeof c->status.r[0] * c->status.cnt);
2015 c->reg[Statctl] = Statrst;
2016 c->reg[Statctl] = Statclr;
2017 c->reg[Stataddr + 0] = Pciwaddrl(c->status.r);
2018 c->reg[Stataddr + 4] = Pciwaddrh(c->status.r);
2019 c->reg16[Stattl] = c->status.m;
2020 c->reg16[Statth] = 10;
2021 c->reg8[Statwm] = 16;
2022 if(c->type == Yukxl && c->rev == 0)
2023 c->reg8[Statiwm] = 4;
2025 c->reg8[Statiwm] = 4; //16;
2027 /* set transmit, isr, level timers */
2028 c->reg[Tsti] = µ2clk(c, 1000);
2029 c->reg[Titi] = µ2clk(c, 20);
2030 c->reg[Tlti] = µ2clk(c, 100);
2032 c->reg[Statctl] = Staton;
2034 c->reg8[Tstc] = Tstart;
2035 c->reg8[Tltc] = Tstart;
2036 c->reg8[Titc] = Tstart;
2046 r = macread32(c, Phy) & ~(Gphyrst | Gphyrstclr);
2047 macwrite32(c, Phy, r | Gphyrst);
2048 macwrite32(c, Phy, r | Gphyrstclr);
2049 /* macwrite32(c, Mac, Macrst); ? */
2050 macwrite32(c, Mac, Macrstclr);
2052 if(c->type == Yukxl && c->rev == 0 && c->portno == 1){
2056 macwrite8(c, Irqm, Txurun);
2061 gmacwrite(c, Phyaddr, (r = gmacread(c, Phyaddr)) | Mibclear);
2062 for(i = 0; i < nelem(stattab); i++)
2063 gmacread32(c, Stats + stattab[i].offset/4);
2064 gmacwrite(c, Phyaddr, r);
2066 gmacwrite(c, Txctl, 4<<10); /* collision distance */
2067 gmacwrite(c, Txflow, 0xffff); /* flow control */
2068 gmacwrite(c, Txparm, 3<<14 | 0xb<<9 | 0x1c<<4 | 4);
2069 gmacwrite(c, Rxctl, Ufilter | Mfilter | Rmcrc);
2070 gmacwrite(c, Serctl, 0x04<<11 /* blind */ | Jumboen | 0x1e /* ipig */);
2075 gmacwrite(c, Txmask, 0);
2076 gmacwrite(c, Rxmask, 0);
2077 gmacwrite(c, Trmask, 0);
2079 macwrite32(c, Gfrxctl, Gfrstclr);
2081 if(c->type == Yukex || c->type == Yukfep)
2083 macwrite32(c, Gfrxctl, r);
2084 if(c->type == Yukxl)
2085 macwrite32(c, Grxfm, 0);
2087 macwrite32(c, Grxfm, Ferror);
2088 if(c->type == Yukfep && c->rev == 0)
2089 macwrite32(c, Grxft, 0x178);
2091 macwrite32(c, Grxft, 0xb);
2093 macwrite32(c, Gmfctl, Gmfclr); /* clear reset */
2094 macwrite32(c, Gmfctl, Gmfon); /* on */
2097 if(c->type == Yukfep && c->rev == 0)
2098 c->reg[Gmfea] = c->reg[Gmfea] & ~3;
2105 slice(void **v, uint r, uint sz)
2111 *v = (void*)(a + sz);
2116 setupr(Sring *r, uint cnt)
2132 c->io = p->mem[0].bar&~0xf;
2133 mem = vmap(c->io, p->mem[0].size);
2135 print("yuk: cant map %#p\n", c->io);
2140 c->reg = (uint*)mem;
2141 c->reg8 = (uchar*)mem;
2142 c->reg16 = (ushort*)mem;
2143 if(memcmp(c->ra, nilea, sizeof c->ra) == 0)
2144 memmove(c->ra, c->reg8 + Macadr + 8*c->portno, Eaddrlen);
2146 setupr(&c->status, Sringcnt);
2147 setupr(&c->tx, Tringcnt);
2148 setupr(&c->rx, Rringcnt);
2150 n = sizeof c->status.r[0] * (c->status.cnt + c->tx.cnt + c->rx.cnt);
2151 n += 16*4096*2; /* rounding slop */
2152 c->alloc = xspanalloc(n, 16*4096, 0); /* unknown alignment constraints */
2153 memset(c->alloc, 0, n);
2156 c->status.r = slice(&v, 16*4096, sizeof c->status.r[0] * c->status.cnt);
2157 c->tx.r = slice(&v, 16*4096, sizeof c->tx.r[0] * c->tx.cnt);
2158 c->rx.r = slice(&v, 16*4096, sizeof c->rx.r[0] * c->rx.cnt);
2160 c->nports = 1; /* BOTCH */
2162 print("yuk: cant reset\n");
2164 vunmap(mem, p->mem[0].size);
2184 vunmap(c->reg, p->mem[0].size);
2196 for(p = nil; p = pcimatch(p, 0, 0); ){
2197 for(i = 0; i < nelem(vtab); i++)
2198 if(vtab[i].vid == p->vid)
2199 if(vtab[i].did == p->did)
2201 if(i == nelem(vtab))
2203 if(nctlr == nelem(ctlrtab)){
2204 print("yuk: too many controllers\n");
2207 c = malloc(sizeof *c);
2209 print("yuk: no memory for Ctlr\n");
2214 c->rbsz = vtab[i].mtu;
2215 ctlrtab[nctlr++] = c;
2231 if(c == nil || c->flag&Fprobe)
2233 if(e->port != 0 && e->port != (ulong)(uintptr)c->reg)
2242 e->irq = c->p->intl;
2243 e->tbdf = c->p->tbdf;
2245 e->maxmtu = c->rbsz;
2246 memmove(e->ea, c->ra, Eaddrlen);
2251 e->multicast = multicast;
2252 e->promiscuous = promiscuous;
2253 e->shutdown = shutdown;
2256 intrenable(e->irq, interrupt, e, e->tbdf, e->name);
2264 addethercard("yuk", pnp);