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"
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, 0x4364, 1514, "88e8056",
744 0x11ab, 0x4380, 1514, "88e8057",
745 0x11ab, 0x436b, 1514, "88e8071", /* unsure on mtu */
746 0x1186, 0x4b00, 9000, "dge-560t",
747 0x1186, 0x4b02, 1514, "dge-550sx",
748 0x1186, 0x4b03, 1514, "dge-550t",
751 static Stattab stattab[] = {
763 80, "rx frames < 64",
764 88, "rx frames < 64 fcs",
766 104, "rx frames 65-127",
767 112, "rx frames 128-255",
768 120, "rx frames 256-511",
769 128, "rx frames 512-1023",
770 136, "rx frames 1024-1518",
771 144, "rx frames 1519-mtu",
772 152, "rx frames too long",
774 176, "rx fifo oflow",
785 248, "tx frames 65-127",
786 256, "tx frames 128-255",
787 264, "tx frames 256-511",
788 272, "tx frames 512-1023",
789 280, "tx frames 1024-1518",
790 288, "tx frames 1519-mtu",
794 320, "tx excess coll",
796 336, "tx single col",
800 static uint phypwr[] = {1<<26, 1<<27};
801 static uint coma[] = {1<<28, 1<<29};
802 static uchar nilea[Eaddrlen];
804 static Ctlr *ctlrtab[Nctlr];
813 return k->event != 0;
826 sleep(k, icansleep, k);
831 getnslot(Sring *r, uint *wp, Status **t, uint n)
835 if(r->m - (int)(wp[0] - r->rp) < n)
837 for(i = 0; i < n; i++)
838 t[i] = r->r + (wp[0]++ & r->m);
843 macread32(Ctlr *c, uint r)
845 return c->reg[c->portno*0x20 + r];
849 macwrite32(Ctlr *c, uint r, uint v)
851 c->reg[c->portno*0x20 + r] = v;
855 macread16(Ctlr *c, uint r)
857 return c->reg16[c->portno*0x40 + r];
861 macwrite16(Ctlr *c, uint r, uint v)
863 c->reg16[c->portno*0x40 + r] = v;
867 macread8(Ctlr *c, uint r)
869 return c->reg8[c->portno*0x80 + r];
873 macwrite8(Ctlr *c, uint r, uint v)
875 c->reg8[c->portno*0x80 + r] = v;
878 static uint gmac32[2] = {
884 gmacread32(Ctlr *c, uint r)
886 return c->reg[gmac32[c->portno] + r];
890 gmacwrite32(Ctlr *c, uint r, uint v)
892 c->reg[gmac32[c->portno] + r] = v;
895 static uint gmac[2] = {
901 gmacread(Ctlr *c, uint r)
903 return c->reg16[gmac[c->portno] + r];
907 gmacwrite(Ctlr *c, uint r, ushort v)
909 c->reg16[gmac[c->portno] + r] = v;
913 qrread(Ctlr *c, uint r)
915 return c->reg[Qbase + c->portno*Qportsz + r>>2];
919 qrwrite(Ctlr *c, uint r, uint v)
921 c->reg[Qbase + c->portno*Qportsz + r>>2] = v;
925 qrread16(Ctlr *c, uint r)
927 return c->reg16[Qbase + c->portno*Qportsz + r>>1];
931 qrwrite16(Ctlr *c, uint r, uint v)
933 c->reg16[Qbase + c->portno*Qportsz + r>>1] = v;
937 qrread8(Ctlr *c, uint r)
939 return c->reg8[Qbase + c->portno*Qportsz + r>>0];
943 qrwrite8(Ctlr *c, uint r, uint v)
945 c->reg8[Qbase + c->portno*Qportsz + r>>0] = v;
949 rrread32(Ctlr *c, uint r)
951 return c->reg[Rbase + c->portno*Qportsz + r>>2];
955 rrwrite32(Ctlr *c, uint r, uint v)
957 c->reg[Rbase + c->portno*Qportsz + r>>2] = v;
961 rrwrite8(Ctlr *c, uint r, uint v)
963 c->reg8[Rbase + c->portno*Qportsz + r] = v;
967 rrread8(Ctlr *c, uint r)
969 return c->reg8[Rbase + c->portno*Qportsz + r];
973 prread32(Ctlr *c, uint r)
975 return c->reg[Pbase + c->portno*Qportsz + r>>2];
979 prwrite32(Ctlr *c, uint r, uint v)
981 c->reg[Pbase + c->portno*Qportsz + r>>2] = v;
985 prread16(Ctlr *c, uint r)
987 return c->reg16[Pbase + c->portno*Qportsz + r>>1];
991 prwrite16(Ctlr *c, uint r, uint v)
993 c->reg16[Pbase + c->portno*Qportsz + r>>1] = v;
997 phyread(Ctlr *c, uint r)
1001 gmacwrite(c, Smictl, Smiread | r<<6);
1003 v = gmacread(c, Smictl);
1007 return gmacread(c, Smidata);
1013 phywrite(Ctlr *c, uint r, ushort v)
1015 gmacwrite(c, Smidata, v);
1016 gmacwrite(c, Smictl, Smiwrite | r<<6);
1018 v = gmacread(c, Smictl);
1021 if((v & Smibusy) == 0)
1022 return gmacread(c, Smidata);
1027 static uvlong lorder = 0x0706050403020100ull;
1030 getle(uchar *t, int w)
1036 for(i = w; i != 0; )
1042 putle(uchar *t, uvlong r, int w)
1048 o = (uchar*)&lorder;
1049 for(i = 0; i < w; i++)
1054 bufinit(Ctlr *c, uint q, uint start, uint end)
1058 rrwrite8(c, q + Rctl, Rrstclr);
1059 rrwrite32(c, q + Rstart, start);
1060 rrwrite32(c, q + Rend, end-1);
1061 rrwrite32(c, q + Rwp, start);
1062 rrwrite32(c, q + Rrp, start);
1064 if(q == Qr || q == Qr + Qportsz){
1066 rrwrite32(c, q + Rpon, t - 8192/8);
1067 rrwrite32(c, q + Rpoff, t - 16384/8);
1069 rrwrite8(c, q + Rctl, Rsfon);
1070 rrwrite8(c, q + Rctl, Renable);
1071 rrread8(c, q + Rctl);
1075 qinit(Ctlr *c, uint queue)
1077 qrwrite(c, queue + Qcsr, Qallclr);
1078 qrwrite(c, queue + Qcsr, Qgo);
1079 qrwrite(c, queue + Qcsr, Qfifoon);
1080 qrwrite16(c, queue + Qwm, 0x600); /* magic */
1081 // qrwrite16(c, queue + Qwm, 0x80); /* pcie magic; assume pcie; no help */
1084 /* initialized prefetching */
1086 pinit(Ctlr *c, uint queue, Sring *r)
1093 prwrite32(c, queue + Pctl, Prefrst);
1094 prwrite32(c, queue + Pctl, Prefrstclr);
1095 putle(u.u, Pciwaddrh(r->r), 4);
1096 prwrite32(c, queue + Paddrh, u.l);
1097 putle(u.u, Pciwaddrl(r->r), 4);
1098 prwrite32(c, queue + Paddrl, u.l);
1099 prwrite16(c, queue + Plidx, r->m);
1100 prwrite32(c, queue + Pctl, Prefon);
1101 prread32(c, queue + Pctl);
1118 pinit(c, Qtx, &c->tx);
1122 linkup(Ctlr *c, uint w)
1127 gmacwrite(c, Ctl, w|gmacread(c, Ctl));
1149 if((b = qbread(e->oq, 100000)) == nil)
1151 while(getnslot(r, &r->wp, tab, 1 + is64()) == -1)
1154 c->tbring[t - r->r] = b;
1158 t->op = Oaddr64 | Hw;
1159 putle(t->status, Pciwaddrh(b->rp), 4);
1161 putle(t->status, Pciwaddrl(b->rp), 4);
1162 putle(t->l, BLEN(b), 2);
1166 prwrite16(c, Qtx + Pputidx, r->wp & r->m);
1168 print("#l%d: tproc: queue closed\n", e->ctlrno);
1169 pexit("queue closed", 1);
1185 if(c->type == Yukecu && (c->rev == 2 || c->rev == 3))
1186 qrwrite(c, Qr + Qtest, Qramdis);
1187 pinit(c, Qr, &c->rx);
1189 if((c->flag & Fnewle) == 0){
1190 while(getnslot(r, &r->wp, &t, 1) == -1)
1192 putle(t->status, 14<<16 | 14, 4);
1195 qrwrite(c, Qr + Qcsr, Qsumen);
1197 macwrite32(c, Gfrxctl, Gftroff);
1201 #include "yukdump.h"
1203 rxscrew(Ether *e, Sring *r, Status *t, uint wp)
1208 if((int)(wp - r->rp) >= r->cnt){
1209 print("rxscrew1 wp %ud(%ud) rp %ud %lud\n", wp, r->wp, r->rp, t-r->r);
1212 if(c->rbring[t - r->r]){
1213 print("rxscrew2 wp %ud rp %ud %lud\n", wp, r->rp, t-r->r);
1214 descriptorfu(e, Qr);
1221 replenish(Ether *e, Ctlr *c)
1234 lim = 128; /* hw limit? */
1235 for(n = 0; n < lim; n++){
1236 b = iallocb(c->rbsz + Rbalign);
1237 if(b == nil || getnslot(r, &wp, tab, 1 + is64()) == -1){
1241 b->rp = b->wp = (uchar*)ROUND((uintptr)b->base, Rbalign);
1244 if(rxscrew(e, r, t, wp) == -1){
1248 c->rbring[t - r->r] = b;
1252 putle(t->status, Pciwaddrh(b->wp), 4);
1254 t->op = Oaddr64 | Hw;
1256 putle(t->status, Pciwaddrl(b->wp), 4);
1257 putle(t->l, c->rbsz, 2);
1264 prwrite16(c, Qr + Pputidx, wp & r->m);
1265 dprint("yuk: replenish %d %ud-%ud [%d-%d]\n", n, r->rp, wp, r->rp&r->m, wp&r->m);
1284 if(replenish(e, c) == 0)
1290 promiscuous(void *a, int on)
1298 r = gmacread(c, Rxctl);
1300 r &= ~(Ufilter|Mfilter);
1302 r |= Ufilter|Mfilter;
1303 gmacwrite(c, Rxctl, r);
1306 static uchar pauseea[] = {1, 0x80, 0xc2, 0, 0, 1};
1309 multicast(void *a, uchar *ea, int on)
1319 r = gmacread(c, Rxctl);
1321 for(ll = &c->mc; *ll != nil; ll = &(*ll)->next)
1322 if(memcmp((*ll)->ea, ea, Eaddrlen) == 0)
1324 *ll = malloc(sizeof **ll);
1325 memmove((*ll)->ea, ea, Eaddrlen);
1327 for(p = nil, l = c->mc; l != nil; p = l, l = l->next)
1328 if(memcmp(l->ea, ea, Eaddrlen) == 0)
1338 memset(f, 0, sizeof f);
1339 if(0 /* flow control */){
1340 b = ethercrc(pauseea, Eaddrlen) & 0x3f;
1341 f[b>>3] |= 1 << (b & 7);
1343 for(l = c->mc; l != nil; l = l->next){
1344 b = ethercrc(l->ea, Eaddrlen) & 0x3f;
1345 f[b>>3] |= 1 << (b & 7);
1347 for(i = 0; i < sizeof f / 2; i++)
1348 gmacwrite(c, Mchash + 2*i, f[i] | f[i+1]<<8);
1349 gmacwrite(c, Rxctl, r | Mfilter);
1352 static int spdtab[4] = {
1363 i = phyread(c, Phyint);
1364 s = phyread(c, Phylstat);
1365 dprint("#l%d: yuk: link %.8ux %.8ux\n", e->ctlrno, i, s);
1367 e->link = (s & Plink) != 0;
1368 if(e->link && c->feat&Ffiber)
1376 dprint("#l%d: yuk: link %d spd %d\n", e->ctlrno, e->link, e->mbps);
1380 txcleanup(Ctlr *c, uint end)
1389 for(rp = r->rp & r->m; rp != end; rp = r->rp & r->m){
1392 if((t->ctl & Eop) == 0)
1395 c->tbring[rp] = nil;
1399 unstarve(&c->txmit);
1403 rx(Ether *e, uint l, uint x, uint flag)
1414 print("#l%d: yuk rx empty\n", e->ctlrno);
1424 cnt = x>>16 & 0x7fff;
1425 if((cnt != l || x&Rxerror) &&
1426 !(c->type == Yukfep && c->rev == 0)){
1427 print("#l%d: yuk rx error %.4ux\n", e->ctlrno, x&0xffff);
1434 unstarve(&c->rxmit);
1438 cksum(Ctlr *c, uint ck, uint css)
1440 if(c->flag & Fnewle && css&(Cisip4|Cisip6) && css&Ctcpok)
1441 return Bipck | Btcpck | Budpck;
1442 else if(ck == 0xffff || ck == 0)
1450 uint i, lim, op, l, x;
1454 static uint ck = Badck;
1458 lim = c->reg16[Stathd] & r->m;
1462 lim = c->reg16[Stathd] & r->m;
1473 ck = getle(s->status, 4) & 0xffff;
1477 x = getle(s->status, 4);
1478 rx(e, l, x, cksum(c, ck, s->ctl));
1483 x = getle(s->status, 4);
1484 txcleanup(c, x & 0xfff);
1486 x = l>>24 & 0xff | l<< 8;
1488 if(x != 0 && c->oport)
1489 txcleanup(c->oport, x);
1492 print("#l%d: yuk: funny opcode %.2ux\n", e->ctlrno, op);
1498 c->reg[Statctl] = Statirqclr;
1507 hwerror(Ether *e, uint cause)
1513 cause = c->reg[Hwe];
1515 print("hwe: no cause\n");
1517 c->reg8[Tgc] = Tgclr;
1520 if(cause & (Hmerr | Hstatus)){
1521 c->reg8[Tstctl1] = Tstwen;
1522 u = pcicfgr16(c->p, PciPSR) | 0x7800;
1523 pcicfgw16(c->p, PciPSR, u);
1524 c->reg8[Tstctl1] = Tstwdis;
1525 cause &= ~(Hmerr | Hstatus);
1528 c->reg8[Tstctl1] = Tstwen;
1529 c->reg[Pciaer + Pciunc>>2] = ~0;
1530 u = c->reg[Pciaer + Pciunc>>2];
1532 print("#l%d: pcierror %.8ux\n", e->ctlrno, u);
1533 c->reg8[Tstctl1] = Tstwdis;
1536 if(cause & Hrxparity){
1537 print("#l%d: ram parity read error. bug? ca %.8ux\n", e->ctlrno, cause);
1538 qrwrite(c, Qtx + Qcsr, Qcirqpar);
1539 cause &= ~Hrxparity;
1541 if(cause & Hrparity){
1542 print("#l%d: ram parity read error. bug? ca %.8ux\n", e->ctlrno, cause);
1543 descriptorfu(e, Qr);
1544 descriptorfu(e, Qtx);
1545 c->reg16[Rictl + c->portno*0x40>>1] = Rirpclr;
1548 if(cause & Hwparity){
1549 print("#l%d: ram parity write error. bug? ca %.8ux\n", e->ctlrno, cause);
1550 descriptorfu(e, Qr);
1551 descriptorfu(e, Qtx);
1552 c->reg16[Rictl + c->portno*0x40>>1] = Riwpclr;
1555 if(cause & Hmfault){
1556 print("#l%d: mac parity error\n", e->ctlrno);
1557 macwrite32(c, Gmfctl, Gmfcpe);
1561 print("#l%d: leftover hwe %.8ux\n", e->ctlrno, cause);
1571 cause = macread8(c, Irq);
1572 cause &= ~(Rxdone | Txdone);
1575 print("#l%d: mac error %.8ux\n", e->ctlrno, cause);
1577 gmacread32(c, Txirq);
1581 gmacread32(c, Rxirq);
1585 macwrite32(c, Gfrxctl, Gmfcfu);
1589 macwrite32(c, Gmfctl, Gmfcfu);
1593 print("#l%d: leftover mac error %.8ux\n", e->ctlrno, cause);
1604 Irx<<Iphy2base, Qr + 0x80, "qr1",
1605 Itxs<<Iphy2base, Qtxs + 0x100, "qtxs1",
1606 Itx<<Iphy2base, Qtx + 0x100, "qtx1",
1610 eerror(Ether *e, uint cause)
1621 if(cause & (Irx | Itxs | Itx)*(1 | 1<<Iphy2base))
1622 for(i = 0; i < nelem(emap); i++){
1623 if((cause & emap[i].i) == 0)
1626 o = prread16(c, q + Pgetidx);
1627 print("#l%d: yuk: bug: %s: @%d ca=%.8ux\n",
1628 e->ctlrno, emap[i].s, o, cause);
1630 qrwrite(c, emap[i].q + Qcsr, Qcirqck);
1631 cause &= ~emap[i].i;
1634 print("#l%d: leftover error %.8ux\n", e->ctlrno, cause);
1650 cause = c->reg[Eisr];
1656 eerror(e, cause & Ierror);
1665 interrupt(Ureg*, void *v)
1674 /* reading Isrc2 masks interrupts */
1675 cause = c->reg[Isrc2];
1676 if(cause == 0 || cause == ~0){
1677 /* reenable interrupts */
1681 unstarve(&c->iproc);
1687 if(c->type == Yukex && c->rev != 1
1688 || c->type == Yukfep
1689 || c->type == Yuksup)
1690 macwrite32(c, Gmfctl, Gmfjon | Gmfsfon);
1692 macwrite32(c, Gmfae, 0x8000 | 0x70); /* tx gmac fifo */
1693 macwrite32(c, Gmfctl, Gmfsfoff);
1702 if(ram = c->reg8[Ramcnt] * 4096/8){ /* in qwords */
1704 rx = ROUNDUP((2*ram)/3, 1024/8);
1705 bufinit(c, Qr, 0, rx);
1706 bufinit(c, Qtx, rx, ram);
1707 rrwrite8(c, Qtxs + Rctl, Rrst); /* sync tx off */
1709 macwrite8(c, Rxplo, 768/8);
1710 macwrite8(c, Rxphi, 1024/8);
1733 snprint(buf, sizeof buf, "#l%dtproc", e->ctlrno);
1734 kproc(buf, tproc, e);
1735 snprint(buf, sizeof buf, "#l%drproc", e->ctlrno);
1736 kproc(buf, rproc, e);
1737 snprint(buf, sizeof buf, "#l%diproc", e->ctlrno);
1738 kproc(buf, iproc, e);
1740 c->reg[Ism] |= Ibmu | Iport<<Iphy2base*c->portno;
1744 ifstat(Ether *e0, void *a, long n, ulong offset)
1752 p = s = malloc(READSTR);
1754 for(i = 0; i < nelem(stattab); i++){
1755 u = gmacread32(c, Stats + stattab[i].offset/4);
1757 p = seprint(p, e, "%s\t%ud\n", stattab[i].name, u);
1759 p = seprint(p, e, "stat %.4ux ctl %.3ux\n", gmacread(c, Stat), gmacread(c, Ctl));
1760 p = seprint(p, e, "pref %.8ux %.4ux\n", prread32(c, Qr + Pctl), prread16(c, Qr + Pgetidx));
1762 p = dumppci(c, p, e);
1763 p = dumpgmac(c, p, e);
1764 p = dumpmac(c, p, e);
1765 p = dumpreg(c, p, e);
1767 seprint(p, e, "%s rev %d phy %s\n", idtab[c->type].name,
1768 c->rev, c->feat&Ffiber? "fiber": "copper");
1769 n = readstr(offset, a, n, s);
1774 static Cmdtab ctltab[] = {
1776 2, "descriptorfu", 1,
1780 ctl(Ether *e, void *buf, long n)
1785 cb = parsecmd(buf, n);
1790 t = lookupcmd(cb, ctltab, nelem(ctltab));
1796 descriptorfu(e, Qr);
1805 yukpcicfgr32(Ctlr *c, uint r)
1807 return c->reg[r + 0x1c00>>2];
1811 yukpcicfgw32(Ctlr *c, uint r, uint v)
1813 c->reg[r + 0x1c00>>2] = v;
1821 u = u0 = yukpcicfgr32(c, Pciphy);
1822 u &= ~phypwr[c->portno];
1823 if(c->type == Yukxl && c->rev > 1)
1824 u |= coma[c->portno];
1826 c->reg8[Tstctl1] = Tstwen;
1827 yukpcicfgw32(c, Pciphy, u);
1828 c->reg8[Tstctl1] = Tstwdis;
1830 if(c->type == Yukfe)
1831 c->reg8[Phyctl] = Aneen;
1832 else if(c->flag & Fapwr)
1833 macwrite32(c, Phy, Gphyrstclr);
1841 if((c->feat & Fnewphy) == 0){
1842 u = phyread(c, Phyextctl);
1843 u &= ~0xf70; /* clear downshift counters */
1844 u |= 0x7<<4; /* mac tx clock = 25mhz */
1845 if(c->type == Yukec)
1846 u |= 2*Dnmstr | Dnslv;
1849 phywrite(c, Phyextctl, u);
1851 u = phyread(c, Phyphy);
1853 /* questionable value */
1854 if(c->feat & Ffiber)
1856 else if(c->feat & Fgbe){
1859 if(c->flag & Fnewphy){
1861 // u |= 2*(1<<12) | 1<<11; /* like 2*Dnmstr | Dnslv */
1862 u |= 2*(1<<9) | 1<<11;
1865 u |= Ppmdixa >> 1; /* why the shift? */
1866 if(c->type == Yukfep && c->rev == 0){
1870 phywrite(c, Phyphy, u);
1871 /* copper/fiber specific stuff gmacwrite(c, Ctl, 0); */
1872 gmacwrite(c, Ctl, 0);
1874 if(c->feat & Ffiber)
1875 phywrite(c, Gbectl, Gbexf | Gbexh);
1877 phywrite(c, Gbectl, Gbef | Gbeh);
1878 phywrite(c, Phyana, Anall);
1879 phywrite(c, Phyctl, Phyrst | Anerst | Aneen);
1880 /* chip specific stuff? */
1881 if (c->type == Yukfep){
1882 u = phyread(c, Phyphy) | Ppnpe;
1883 u &= ~(Ppengy | Ppscrdis);
1884 phywrite(c, Phyphy, u);
1885 // phywrite(c, 0x16, 0x0b54); /* write to fe_led_par */
1887 /* yukfep and rev 0: apply workaround for integrated resistor calibration */
1888 phywrite(c, Phypadr, 17);
1889 phywrite(c, 0x1e, 0x3f60);
1891 phywrite(c, Phyintm, Anok | Anerr | Lsc);
1892 dprint("phyid %.4ux step %.4ux\n", phyread(c, 2), phyread(c, 3));
1900 pcicfgw32(c->p, Pciclk, 0);
1901 c->reg16[Ctst] = Swclr;
1903 c->type = c->reg8[Chip] - 0xb3;
1904 c->rev = c->reg8[Maccfg]>>4 & 0xf;
1907 if(idtab[c->type].okrev != 0xff)
1908 if(c->rev != idtab[c->type].okrev)
1910 c->feat |= idtab[c->type].feat;
1913 if(t == 'L' || t == 'S' || t == 'P')
1916 /* check second port ... whatever */
1921 µ2clk(Ctlr *c, int µs)
1923 return idtab[c->type].mhz * µs;
1927 gmacsetea(Ctlr *c, uint r)
1933 for(i = 0; i < Eaddrlen; i += 2)
1934 gmacwrite(c, r + i, ra[i + 0] | ra[i + 1]<<8);
1945 if(c->type == Yukex)
1946 c->reg16[Asfcs/2] &= ~(Asfbrrst | Asfcpurst | Asfucrst);
1948 c->reg8[Asfcs] = Asfrst;
1949 c->reg16[Ctst] = Asfdis;
1951 c->reg16[Ctst] = Swrst;
1952 c->reg16[Ctst] = Swclr;
1954 c->reg8[Tstctl1] = Tstwen;
1955 pcicfgw16(c->p, PciPSR, pcicfgr16(c->p, PciPSR) | 0xf100);
1956 c->reg16[Ctst] = Mstrclr;
1957 /* fixup pcie extended error goes here */
1959 c->reg8[Pwrctl] = Vauxen | Vccen | Vauxoff | Vccon;
1960 c->reg[Clkctl] = Clkdivdis;
1961 if(c->type == Yukxl && c->rev > 1)
1962 c->reg8[Clkgate] = ~Link2inactive;
1964 c->reg8[Clkgate] = 0;
1965 if(c->flag & Fapwr){
1966 pcicfgw32(c->p, Pciclk, 0);
1967 pcicfgw32(c->p, Pciasp, pcicfgr32(c->p, Pciasp) & Aspmsk);
1968 pcicfgw32(c->p, Pcistate, pcicfgr32(c->p, Pcistate) & Vmain);
1969 pcicfgw32(c->p, Pcicf1, 0);
1970 c->reg[Gpio] |= Norace;
1971 print("yuk2: advanced power %.8ux\n", c->reg[Gpio]);
1973 c->reg8[Tstctl1] = Tstwdis;
1975 for(i = 0; i < c->nports; i++){
1976 macwrite8(c, Linkctl, Linkrst);
1977 macwrite8(c, Linkctl, Linkclr);
1978 if(c->type == Yukex || c->type == Yuksup)
1979 macwrite16(c, Mac, Nomacsec | Nortx);
1982 c->reg[Dpolltm] = Pollstop;
1984 for(i = 0; i < c->nports; i++)
1985 macwrite8(c, Txactl, Txaclr);
1986 for(i = 0; i < c->nports; i++){
1987 c->reg8[i*64 + Rictl] = Riclr;
1988 for(j = 0; j < 12; j++)
1989 c->reg8[i*64 + Rib + j] = 36; /* qword times */
1992 c->reg[Hwem] = Hdflt;
1993 macwrite8(c, Irqm, 0);
1994 for(i = 0; i < 4; i++)
1995 gmacwrite(c, Mchash + 2*i, 0);
1996 gmacwrite(c, Rxctl, Ufilter | Mfilter | Rmcrc);
1998 for(i = 0; i < nelem(c->tbring); i++)
1999 if(b = c->tbring[i]){
2003 for(i = 0; i < nelem(c->rbring); i++)
2004 if(b = c->rbring[i]){
2009 memset(c->tbring, 0, sizeof c->tbring[0] * nelem(c->tbring));
2010 memset(c->rbring, 0, sizeof c->rbring[0] * nelem(c->rbring));
2011 memset(c->tx.r, 0, sizeof c->tx.r[0] * c->tx.cnt);
2012 memset(c->rx.r, 0, sizeof c->rx.r[0] * c->rx.cnt);
2013 memset(c->status.r, 0, sizeof c->status.r[0] * c->status.cnt);
2014 c->reg[Statctl] = Statrst;
2015 c->reg[Statctl] = Statclr;
2016 c->reg[Stataddr + 0] = Pciwaddrl(c->status.r);
2017 c->reg[Stataddr + 4] = Pciwaddrh(c->status.r);
2018 c->reg16[Stattl] = c->status.m;
2019 c->reg16[Statth] = 10;
2020 c->reg8[Statwm] = 16;
2021 if(c->type == Yukxl && c->rev == 0)
2022 c->reg8[Statiwm] = 4;
2024 c->reg8[Statiwm] = 4; //16;
2026 /* set transmit, isr, level timers */
2027 c->reg[Tsti] = µ2clk(c, 1000);
2028 c->reg[Titi] = µ2clk(c, 20);
2029 c->reg[Tlti] = µ2clk(c, 100);
2031 c->reg[Statctl] = Staton;
2033 c->reg8[Tstc] = Tstart;
2034 c->reg8[Tltc] = Tstart;
2035 c->reg8[Titc] = Tstart;
2045 r = macread32(c, Phy) & ~(Gphyrst | Gphyrstclr);
2046 macwrite32(c, Phy, r | Gphyrst);
2047 macwrite32(c, Phy, r | Gphyrstclr);
2048 /* macwrite32(c, Mac, Macrst); ? */
2049 macwrite32(c, Mac, Macrstclr);
2051 if(c->type == Yukxl && c->rev == 0 && c->portno == 1){
2055 macwrite8(c, Irqm, Txurun);
2060 gmacwrite(c, Phyaddr, (r = gmacread(c, Phyaddr)) | Mibclear);
2061 for(i = 0; i < nelem(stattab); i++)
2062 gmacread32(c, Stats + stattab[i].offset/4);
2063 gmacwrite(c, Phyaddr, r);
2065 gmacwrite(c, Txctl, 4<<10); /* collision distance */
2066 gmacwrite(c, Txflow, 0xffff); /* flow control */
2067 gmacwrite(c, Txparm, 3<<14 | 0xb<<9 | 0x1c<<4 | 4);
2068 gmacwrite(c, Rxctl, Ufilter | Mfilter | Rmcrc);
2069 gmacwrite(c, Serctl, 0x04<<11 /* blind */ | Jumboen | 0x1e /* ipig */);
2074 gmacwrite(c, Txmask, 0);
2075 gmacwrite(c, Rxmask, 0);
2076 gmacwrite(c, Trmask, 0);
2078 macwrite32(c, Gfrxctl, Gfrstclr);
2080 if(c->type == Yukex || c->type == Yukfep)
2082 macwrite32(c, Gfrxctl, r);
2083 if(c->type == Yukxl)
2084 macwrite32(c, Grxfm, 0);
2086 macwrite32(c, Grxfm, Ferror);
2087 if(c->type == Yukfep && c->rev == 0)
2088 macwrite32(c, Grxft, 0x178);
2090 macwrite32(c, Grxft, 0xb);
2092 macwrite32(c, Gmfctl, Gmfclr); /* clear reset */
2093 macwrite32(c, Gmfctl, Gmfon); /* on */
2096 if(c->type == Yukfep && c->rev == 0)
2097 c->reg[Gmfea] = c->reg[Gmfea] & ~3;
2104 slice(void **v, uint r, uint sz)
2110 *v = (void*)(a + sz);
2115 setupr(Sring *r, uint cnt)
2131 c->io = p->mem[0].bar&~0xf;
2132 mem = vmap(c->io, p->mem[0].size);
2134 print("yuk: cant map %#p\n", c->io);
2138 c->reg = (uint*)mem;
2139 c->reg8 = (uchar*)mem;
2140 c->reg16 = (ushort*)mem;
2141 if(memcmp(c->ra, nilea, sizeof c->ra) == 0)
2142 memmove(c->ra, c->reg8 + Macadr + 8*c->portno, Eaddrlen);
2144 setupr(&c->status, Sringcnt);
2145 setupr(&c->tx, Tringcnt);
2146 setupr(&c->rx, Rringcnt);
2148 n = sizeof c->status.r[0] * (c->status.cnt + c->tx.cnt + c->rx.cnt);
2149 n += 16*4096*2; /* rounding slop */
2150 c->alloc = xspanalloc(n, 16*4096, 0); /* unknown alignment constraints */
2151 memset(c->alloc, 0, n);
2154 c->status.r = slice(&v, 16*4096, sizeof c->status.r[0] * c->status.cnt);
2155 c->tx.r = slice(&v, 16*4096, sizeof c->tx.r[0] * c->tx.cnt);
2156 c->rx.r = slice(&v, 16*4096, sizeof c->rx.r[0] * c->rx.cnt);
2158 c->nports = 1; /* BOTCH */
2161 print("yuk: cant reset\n");
2164 vunmap(mem, p->mem[0].size);
2182 vunmap(c->reg, p->mem[0].size);
2194 for(p = nil; p = pcimatch(p, 0, 0); ){
2195 for(i = 0; i < nelem(vtab); i++)
2196 if(vtab[i].vid == p->vid)
2197 if(vtab[i].did == p->did)
2199 if(i == nelem(vtab))
2201 if(nctlr == nelem(ctlrtab)){
2202 print("yuk: too many controllers\n");
2205 c = malloc(sizeof *c);
2207 print("yuk: no memory for Ctlr\n");
2212 c->rbsz = vtab[i].mtu;
2213 ctlrtab[nctlr++] = c;
2229 if(c == nil || c->flag&Fprobe)
2231 if(e->port != 0 && e->port != (ulong)c->reg)
2240 e->irq = c->p->intl;
2241 e->tbdf = c->p->tbdf;
2243 e->maxmtu = c->rbsz;
2244 memmove(e->ea, c->ra, Eaddrlen);
2249 e->interrupt = interrupt;
2250 e->multicast = multicast;
2251 e->promiscuous = promiscuous;
2252 e->shutdown = shutdown;
2261 addethercard("yuk", pnp);