]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc/etheryuk.c
audiohda: fix syntax error
[plan9front.git] / sys / src / 9 / pc / etheryuk.c
1 /*
2  * marvell 88e8057 yukon2
3  * copyright © 2009-10 erik quanstrom
4  */
5 #include "u.h"
6 #include "../port/lib.h"
7 #include "mem.h"
8 #include "dat.h"
9 #include "fns.h"
10 #include "io.h"
11 #include "../port/pci.h"
12 #include "../port/error.h"
13 #include "../port/netif.h"
14 #include "../port/etherif.h"
15
16 #define Pciwaddrh(x)    0
17 #define Pciwaddrl(x)    PCIWADDR(x)
18 #define is64()          (sizeof(uintptr) == 8)
19 #define dprint(...)     if(debug) print(__VA_ARGS__); else {}
20
21 extern  void    sfence(void);
22
23 enum {
24         Nctlr   = 4,
25         Nrb     = 1024,
26         Rbalign = 64,
27         Fprobe  = 1<<0,
28         Sringcnt        = 2048,
29         Tringcnt        = 512,
30         Rringcnt        = 512,
31         Rringl  = Rringcnt - 8,
32 };
33
34 enum {
35         /* pci registers */
36         Pciphy  = 0x40,
37         Pciclk  = 0x80,
38         Pciasp  = 0x84,
39         Pcistate        = 0x88,
40         Pcicf0  = 0x90,
41         Pcicf1  = 0x94,
42
43         /* “csr” registers */
44         Ctst    = 0x0004/2,             /* control and status */
45         Pwrctl  = 0x0007,               /* power control */
46         Isr     = 0x0008/4,             /* interrupt src */
47         Ism     = 0x000c/4,             /* interrupt mask */
48         Hwe     = 0x0010/4,             /* hw error */
49         Hwem    = 0x0014/4,             /* hw error mask*/
50         Isrc2   = 0x001c/4,
51         Eisr    = 0x0024/4,
52         Lisr    = 0x0028/4,             /* leave isr */
53         Icr     = 0x002c/4,
54         Macadr  = 0x0100,               /* mac address 2ports*3 */
55         Pmd     = 0x0119,
56         Maccfg  = 0x011a,
57         Chip    = 0x011b,
58         Ramcnt  = 0x011c,               /* # of 4k blocks */
59         Hres    = 0x011e,
60         Clkgate = 0x011d,
61         Clkctl  = 0x0120/4,
62         Tstctl1 = 0x0158,
63         Tstctl2 = 0x0159,
64         Gpio    = 0x015c/4,
65
66         Rictl   = 0x01a0,               /* ri ram buffer ctl */
67         Rib     = 0x0190,               /* ri buffer0 */
68
69         /* other unoffset registers */
70         Asfcs   = 0x0e68,               /* asf command and status */
71         Asfhost = 0x0e6c/4,
72
73         Statctl = 0x0e80/4,             /* status */
74         Stattl  = 0x0e84/2,             /* tail (previous) status addr */
75         Stataddr        = 0x0e88/4,             /* status address low */
76         Statth  = 0x0e98/2,
77         Stathd  = 0x0e9c/2,
78         Statwm  = 0x0eac,               /* stat watermark */
79         Statiwm = 0x0ead,               /* isr stat watermark */
80
81         Dpolltm = 0x0e08/4,             /* descriptor pool timer */
82
83         /* timers */
84         Tgv     = 0x0e14/4,             /* gmac timer current value */
85         Tgc     = 0x0e18,               /* gmac timer ctl */
86         Tgt     = 0x0e1a,               /* gmac timer test */
87
88         Tsti    = 0x0ec0/4,             /* stat tx timer ini */
89         Tlti    = 0x0eb0/4,             /* level */
90         Titi    = 0x0ed0/4,             /* isr */
91
92         Tstc    = 0x0ec8,               /* stat tx timer ctl */
93         Tltc    = 0x0eb8,               /* level timer ctl */
94         Titc    = 0x0ed8,               /* isr timer ctl */
95
96         /* “gmac” registers */
97         Stat    = 0x000/2,
98         Ctl     = 0x004/2,
99         Txctl   = 0x008/2,
100         Rxctl   = 0x00c/2,
101         Txflow  = 0x010/2,
102         Txparm  = 0x014/2,
103         Serctl  = 0x018/2,              /* serial mode */
104         Mchash  = 0x034/2,              /* 4 registers; 4 bytes apart */
105
106         /* interrupt sources and masks */
107         Txirq   = 0x044/2,
108         Rxirq   = 0x048/2,
109         Trirq   = 0x04c/2,              /* tx/rx overflow irq source */
110         Txmask  = 0x050/2,
111         Rxmask  = 0x054/2,
112         Trmask  = 0x058/2,
113
114         Smictl  = 0x080/2,              /* serial mode control */
115         Smidata = 0x084/2,
116         Phyaddr = 0x088/2,
117
118         Ea0     = 0x01c/2,              /* 3 16 bit gmac registers */
119         Ea1     = 0x028/2,
120
121         Stats   = 0x0100/4,
122
123         /* mac registers */
124         Txactl  = 0x210,                        /* transmit arbiter ctl */
125
126         Grxea   = 0x0c40/4,             /* rx fifo end address */
127         Gfrxctl = 0x0c48/4,             /* gmac rxfifo ctl */
128         Grxfm   = 0x0c4c/4,             /* fifo flush mask */
129         Grxft   = 0x0c50/4,             /* fifo flush threshold */
130         Grxtt   = 0x0c54/4,             /* rx truncation threshold */
131         Gmfea   = 0x0d40/4,             /* end address */
132         Gmfae   = 0x0d44/4,             /* almost empty thresh */
133         Gmfctl  = 0x0d48/4,             /* tx gmac fifo ctl */
134
135         Rxphi   = 0x0c58,               /* pause high watermark */
136         Rxplo   = 0x0c5c,               /* pause low watermark */
137
138         Rxwp    = 0x0c60/4,
139         Rxwlev  = 0x0c68/4,
140         Rxrp    = 0x0c70/4,
141         Rxrlev  = 0x0c78/4,
142
143         Mac     = 0x0f00/4,             /* global mac control */
144         Phy     = 0x0f04/4,             /* phy control register */
145
146         Irq     = 0x0f08,               /* irq source */
147         Irqm    = 0x0f0c,               /* irq mask */
148         Linkctl = 0x0f10,
149
150         /* queue registers; all offsets from Qbase*/
151         Qbase   = 0x0400,
152         Qportsz = 0x0080,               /* BOTCH; tx diff is 2x rx diff */
153
154         Qr      = 0x000,
155         Qtxs    = 0x200,
156         Qtx     = 0x280,
157
158         /* queue offsets */
159         Qd      = 0x00,
160         Qvlan   = 0x20,
161         Qdone   = 0x24,
162         Qaddrl  = 0x28,
163         Qaddrh  = 0x2c,
164         Qbc     = 0x30,
165         Qcsr    = 0x34,                 /* 32bit */
166         Qtest   = 0x38,
167         Qwm     = 0x40,
168
169         /* buffer registers; all offsets from Rbase */
170         Rbase   = 0x0800,
171
172         Rstart  = 0x00,
173         Rend    = 0x04,
174         Rwp     = 0x08,
175         Rrp     = 0x0c,
176         Rpon    = 0x10,                 /* pause frames on */
177         Rpoff   = 0x14,                 /* pause frames off */
178         Rhon    = 0x18,                 /* high-priority frames on */
179         Rhoff   = 0x1c,                 /* high-priority  frames off */
180         Rctl    = 0x28,
181
182         /* prefetch */
183         Pbase   = 0x450,
184         Pctl    = 0x00,
185         Plidx   = 0x04,                 /* last addr; 16 bit */
186         Paddrl  = 0x08,
187         Paddrh  = 0x0c,
188         Pgetidx = 0x10,                 /* 16 bit */
189         Pputidx = 0x14,                 /* 16 bit */
190         Pfifow  = 0x20,                 /* 8 bit */
191         Pfifor  = 0x24,                 /* 8 bit */
192         Pfifowm = 0x20,                 /* 8 bit */
193
194         /* indirect phy registers */
195         Phyctl  = 0x000,
196         Phystat = 0x001,
197         Phyid0  = 0x002,
198         Phyid1  = 0x003,
199         Phyana  = 0x004,                        /* auto neg advertisement */
200         Phylpa  = 0x005,                        /* link partner ability */
201         Phyanee = 0x006,                        /* auto neg adv expansion */
202         Phynp   = 0x007,                        /* next page */
203         Phylnp  = 0x008,                        /* link partner next page */
204         Gbectl  = 0x009,
205         Gbestat = 0x00a,
206         Phyphy  = 0x010,                        /* phy specific ctl */
207         Phylstat        = 0x011,
208         Phyintm = 0x012,                        /* phy interrupt mask */
209         Phyint  = 0x013,
210         Phyextctl       = 0x014,
211         Phyrxe  = 0x015,                        /* rx error counter */
212         Phypage = 0x016,                        /* external address */
213         Phypadr = 0x01d,                        /* phy page address */
214 };
215
216 enum {
217         /* Pciasp */
218         Aspforce                = 1<<15,
219         Aspglinkdn      = 1<<14,        /* gphy link down */
220         Aspfempty       = 1<<13,
221         Aspclkrun       = 1<<12,
222         Aspmsk          = Aspforce | Aspglinkdn | Aspfempty | Aspclkrun,
223
224         /* Pcistate */
225         Vmain           = 3<<27,
226
227         /* Stat */
228         Sfast           = 1<<15,        /* 100mbit */
229         Duplex          = 1<<14,
230         Txnofc          = 1<<13,        /* tx flow control disabled */
231         Link            = 1<<12,        /* link up */
232         Pausest         = 1<<11,        /* pause state */
233         Txactive                = 1<<10,
234         Excesscol       = 1<<9,
235         Latecol         = 1<<8,
236         Physc           = 1<<5, /* phy status change */
237         Sgbe            = 1<<4, /* gbe speed */
238         Rxnofc          = 1<<2, /* rx flow control disabled */
239         Promisc         = 1<<1, /* promiscuous mode enabled */
240
241         /* Ctl */
242         Promiscen       = 1<<14,
243         Txfcdis         = 1<<13,
244         Txen            = 1<<12,
245         Rxen            = 1<<11,
246         Bursten         = 1<<10,
247         Loopen          = 1<<9,
248         Gbeen           = 1<<7,
249         Fpass           = 1<<6, /* "force link pass" ? */
250         Duplexen        = 1<<5,
251         Rxfcdis         = 1<<4,
252         Fasten          = 1<<3, /* enable 100mbit */
253         Adudis          = 1<<2, /* disable auto upd duplex */
254         Afcdis          = 1<<1, /* disable auto upd flow ctl */
255         Aspddis         = 1<<0, /* disable auto upd speed */
256
257         /* Rxctl */
258         Ufilter         = 1<<15,        /* unicast filter */
259         Mfilter         = 1<<14,        /* multicast filter */
260         Rmcrc           = 1<<13,        /* remove frame crc */
261
262         /* Serctl */
263         Vlanen          = 1<<9,
264         Jumboen         = 1<<8,
265
266         /* Txactl */
267         Txaclr          = 1<<1,
268         Txarst          = 1<<0,
269
270         /* Asfcs: yukex only */
271         Asfbrrst                = 1<<9, /* bridge reset */
272         Asfcpurst       = 1<<8, /* cpu reset */
273         Asfucrst                = 3<<0, /* µctlr reset */
274
275         /* Asfcs */
276         Asfhvos         = 1<<4, /* os present */
277         Asfrst          = 1<<3,
278         Asfrun          = 1<<2,
279         Asfcirq         = 1<<1,
280         Afsirq          = 1<<0,
281
282         /* Statctl */
283         Statirqclr      = 1<<4,
284         Staton          = 1<<3,
285         Statoff         = 1<<2,
286         Statclr         = 1<<1,
287         Statrst         = 1<<0,
288
289         /* Mac */
290         Nomacsec        = 1<<13 | 1<<11,
291         Nortx           = 1<<9,
292         Macpause        = 1<<3,
293         Macpauseoff     = 1<<2,
294         Macrstclr       = 1<<1,
295         Macrst          = 1<<0,
296
297         /* Phy */
298         Gphyrstclr      = 1<<1,
299         Gphyrst         = 1<<0,
300
301         /* Irqm */
302         Txovfl          = 1<<5, /* tx counter overflow */
303         Rxovfl          = 1<<4, /* rx counter overflow */
304         Txurun          = 1<<3, /* transmit fifo underrun */
305         Txdone          = 1<<2, /* frame tx done */
306         Rxorun          = 1<<1, /* rx fifo overrun */
307         Rxdone          = 1<<0, /* frame rx done */
308
309         /* Linkctl */
310         Linkclr         = 1<<1,
311         Linkrst         = 1<<0,
312
313         /* Smictl */
314         Smiread         = 1<<5,
315         Smiwrite                = 0<<5,
316         Smirdone        = 1<<4,
317         Smibusy         = 1<<3,
318
319         /* Phyaddr */
320         Mibclear                = 1<<5,
321
322         /* Ctst */
323         Asfdis          = 1<<12,        /* asf disable */
324         Clken           = 1<<11,        /* enable clock */
325
326         Swirq           = 1<<7,
327         Swirqclr                = 1<<6,
328         Mstopped        = 1<<5, /* master is stopped */
329         Mstop           = 1<<4, /* stop master */
330         Mstrclr         = 1<<3, /* master reset clear */
331         Mstrrset                = 1<<2, /* master reset */
332         Swclr           = 1<<1,
333         Swrst           = 1<<0,
334
335         /* Pwrctl */
336         Vauxen          = 1<<7,
337         Vauxdis         = 1<<6,
338         Vccen           = 1<<5,
339         Vccdis          = 1<<4,
340         Vauxon          = 1<<3,
341         Vauxoff         = 1<<2,
342         Vccon           = 1<<1,
343         Vccoff          = 1<<0,
344
345         /* timers */
346         Tstart          = 1<<2,
347         Tstop           = 1<<1,
348         Tclrirq         = 1<<0,
349
350         /* Dpolltm */
351         Pollstart               = 1<<1,
352         Pollstop                = 1<<0,
353
354         /* csr interrupts: Isrc2, Eisr, etc. */
355         Ihwerr          = 1<<31,
356         Ibmu            = 1<<30,        /* sring irq */
357         Isoftware       = 1<<25,
358
359         Iphy            = 1<<4,
360         Imac            = 1<<3,
361         Irx             = 1<<2,
362         Itxs            = 1<<1, /* descriptor error */
363         Itx             = 1<<0, /* descriptor error */
364
365         Iport           = 0x1f,
366         Iphy2base       = 8,
367         Ierror          = (Imac | Itx | Irx)*(1 | 1<<Iphy2base),
368
369         /* hwe interrupts: Hwe Hwem */
370         Htsof           = 1<<29,        /* timer stamp overflow */
371         Hsensor         = 1<<28,
372         Hmerr           = 1<<27,        /* master error */
373         Hstatus         = 1<<26,        /* status exception */
374         Hpcie           = 1<<25,        /* pcie error */
375         Hpcie2          = 1<<24,        /* " */
376
377         Hrparity                = 1<<5, /* ram read parity error */
378         Hwparity                = 1<<4, /* ram write parity error */
379         Hmfault         = 1<<3, /* mac fault */
380         Hrxparity       = 1<<2, /* rx parity */
381         Htcptxs         = 1<<1, /* tcp length mismatch */
382         Htcptxa         = 1<<0, /* tcp length mismatch */
383
384         H1base          = 1<<0,
385         H2base          = 1<<8,
386         Hmask           = 0x3f,
387         Hdflt           = Htsof | Hmerr | Hstatus | Hmask*(H1base | H2base),
388
389         /* Clkctl */
390         Clkdiven                = 1<<1,
391         Clkdivdis       = 1<<0,
392
393         /* Clkgate */
394         Link2inactive   = 1<<7,
395
396         /* Phyctl */
397         Phyrst  = 1<<15,
398         Phy100  = 1<<14,                /* manual enable 100mbit */
399         Aneen   = 1<<12,                /* auto negotiation enable */
400         Phyoff  = 1<<11,                /* turn phy off */
401         Anerst  = 1<<9,         /* auto neg reset */
402         Phydpx  = 1<<8,
403         Phy1000 = 1<<5,         /* manual enable gbe */
404
405         /* Phyana */
406         Annp    = 1<<15,                /* request next page */
407         Anack   = 1<<14,                /* ack rx (read only) */
408         Anrf    = 1<<13,                /* remote fault */
409         Anpa    = 1<<11,                /* try asymmetric pause */
410         Anp     = 1<<10,                /* try pause */
411         An100f  = 1<<8,
412         An100h  = 1<<7,
413         An10f   = 1<<6,
414         An10h   = 1<<5,
415         Anonly  = 1<<0,
416         Anall   = An100f | An100h | An10f | An10h | Anonly,
417
418         /* Gbectl */
419         Gbef    = 1<<9,         /* auto neg gbe full */
420         Gbeh    = 1<<8,         /* auto neg gbe half */
421         Gbexf   = 1<<6,         /* auto neg gbe full fiber */
422         Gbexh   = 1<<5,         /* auto neg gbe full fiber */
423
424         /* Phyphy */
425         Pptf    = 3<<14,                /* tx fifo depth */
426         Pprf    = 3<<12,                /* rx fifo depth */
427         Pped    = 3<<8,         /* energy detect */
428         Ppmdix  = 3<<5,         /* mdix conf */
429         Ppmdixa = 3<<5,         /* automdix */
430
431         Ppengy  = 1<<14,                /* fe+ enable energy detect */
432         Ppscrdis        = 1<<9,         /* fe+ scrambler disable */
433         Ppnpe   = 1<<12,                /* fe+ enable next page */
434
435         /* Phylstat */
436         Physpd  = 3<<14,
437         Phydupx = 1<<13,
438         Phypr   = 1<<12,                /* page rx */
439         Phydone = 1<<11,                /* speed and duplex neg. done */
440         Plink   = 1<<10,
441         Pwirelen        = 7<<7,
442         Pmdi    = 1<<6,
443         Pdwnsh  = 1<<5,         /* downshift */
444         Penergy = 1<<4,         /* energy detect */
445         Ptxpause = 1<<3,                /* tx pause enabled */
446         Prxpause        = 1<<2,         /* rx pause enabled */
447         Ppol    = 1<<2,         /* polarity */
448         Pjarjar = 1<<1,         /* mesa no understasa */
449
450         /* Phyintm */
451         Anerr   = 1<<15,                /* an error */
452         Lsp     = 1<<14,                /* link speed change */
453         Andc    = 1<<13,                /* an duplex change */
454         Anok    = 1<<11,
455         Lsc     = 1<<10,                /* link status change */
456         Symerr  = 1<<9,         /* symbol error */
457         Fcarr   = 1<<8,         /* false carrier */
458         Fifoerr = 1<<7,
459         Mdich   = 1<<6,
460         Downsh  = 1<<5,
461         Engych  = 1<<4,         /* energy change */
462         Dtech   = 1<<2,         /* dte power det status */
463         Polch   = 1<<1,         /* polarity change */
464         Jabber  = 1<<0,
465
466         /* Phyextctl */
467         Dnmstr  = 1<<9,         /* master downshift; 0: 1x; 1: 2x; 2: 3x */
468         Dnslv   = 1<<8,
469
470         /* Tgc */
471         Tgstart = 1<<2,
472         Tgstop  = 1<<1,
473         Tgclr   = 1<<0,         /* clear irq */
474
475         /* Tstctl1 */
476         Tstwen  = 1<<1,         /* enable config reg r/w */
477         Tstwdis = 1<<0,         /* disable config reg r/w */
478
479         /* Gpio */
480         Norace  = 1<<13,
481
482         /* Rictl */
483         Rirpclr = 1<<9,
484         Riwpclr = 1<<8,
485         Riclr   = 1<<1,
486         Rirst   = 1<<0,
487
488         /* Rbase opcodes */
489         Rsfon   = 1<<5,         /* enable store/fwd */
490         Rsfoff  = 1<<4,
491         Renable = 1<<3,
492         Rdisable        = 1<<2,
493         Rrstclr = 1<<1,
494         Rrst    = 1<<0,
495
496         /* Qbase opcodes */
497         Qidle   = 1<<31,
498         Qtcprx  = 1<<30,
499         Qiprx   = 1<<29,
500         Qrssen  = 1<<15,
501         Qrssdis = 1<<14,
502         Qsumen  = 1<<13,                /* tcp/ip cksum */
503         Qsumdis = 1<<12,
504         Qcirqpar        = 1<<11,                /* clear irq on parity errors */
505         Qcirqck = 1<<10,
506         Qstop   = 1<<9,
507         Qstart  = 1<<8,
508         Qfifoon = 1<<7,
509         Qfifooff        = 1<<6,
510         Qfifoen = 1<<5,
511         Qfiforst        = 1<<4,
512         Qenable = 1<<3,
513         Qdisable        = 1<<2,
514         Qrstclr = 1<<1,
515         Qrst    = 1<<0,
516
517         Qallclr = Qfiforst | Qfifooff | Qrstclr,
518         Qgo     = Qcirqpar | Qcirqck | Qstart | Qfifoen | Qenable,
519
520         /* Qtest bits */
521         Qckoff  = 1<<31,                /* tx: auto checksum off */
522         Qckon   = 1<<30,
523         Qramdis = 1<<24,                /* rx: ram disable */
524
525         /* Pbase opcodes */
526         Prefon  = 1<<3,         /* prefetch on */
527         Prefoff = 1<<2,
528         Prefrstclr      = 1<<1,
529         Prefrst = 1<<0,
530
531         /* ring opcodes */
532         Hw      = 0x80,                 /* bitmask */
533         Ock     = 0x12,                 /* tcp checksum start */
534         Oaddr64 = 0x21,
535         Obuf    = 0x40,
536         Opkt    = 0x41,
537         Orxstat = 0x60,
538         Orxts   = 0x61,                 /* rx timestamp */
539         Orxvlan = 0x62,
540         Orxchks = 0x64,
541         Otxidx  = 0x68,
542         Omacs   = 0x6c,                 /* macsec */
543         Oputidx = 0x70,
544
545         /* ring status */
546         Eop     = 0x80,
547
548         /* Gfrxctl */
549         Gftrunc = 1<<27,
550         Gftroff = 1<<26,
551
552         Gfroon  = 1<<19,        /* flush on rx overrun */
553         Gfrooff = 1<<18,
554         Gffon   = 1<<7, /* rx fifo flush mode on */
555         Gffoff  = 1<<6,
556         Gfon    = 1<<3,
557         Gfoff   = 1<<2,
558         Gfrstclr        = 1<<1,
559         Gfrst   = 1<<0,
560
561         /* Gmfctl */
562         Gmfsfoff        = 1<<31,        /* disable store-forward (ec ultra) */
563         Gmfsfon = 1<<30,        /* able store-forward (ec ultra) */
564         Gmfvon  = 1<<25,        /* vlan tag on */
565         Gmfvoff = 1<<24,        /* vlan off */
566         Gmfjon  = 1<<23,        /* jumbo on (ec ultra) */
567         Gmfjoff = 1<<22,        /* jumbo off */
568         Gmfcfu  = 1<<6, /* clear fifio underrun irq */
569         Gmfcfc  = 1<<5, /* clear frame complete irq */
570         Gmfcpe  = 1<<4, /* clear parity error irq */
571         Gmfon   = 1<<3,
572         Gmfoff  = 1<<2,
573         Gmfclr  = 1<<1,
574         Gmfrst  = 1<<0,
575
576         /* rx frame */
577         Flen    = 0x7fff<<17,
578         Fvlan   = 1<<13,
579         Fjabbr  = 1<<12,
580         Ftoosm  = 1<<11,
581         Fmc     = 1<<10,        /* multicast */
582         Fbc     = 1<<9,
583         Fok     = 1<<8, /* good frame */
584         Fokfc   = 1<<7,
585         Fbadfc  = 1<<6,
586         Fmiierr = 1<<5,
587         Ftoobg  = 1<<4, /* oversized */
588         Ffrag   = 1<<3, /* fragment */
589         Fcrcerr = 1<<1,
590         Ffifoof = 1<<0, /* fifo overflow */
591         Ferror  = Ffifoof | Fcrcerr | Ffrag | Ftoobg
592                 | Fmiierr | Fbadfc | Ftoosm | Fjabbr,
593
594         /* rx checksum bits in Status.ctl */
595         Badck   = 5,            /* arbitrary bad checksum */
596
597         Ctcpok  = 1<<7, /* tcp or udp cksum ok */
598         Cisip6  = 1<<3,
599         Cisip4  = 1<<1,
600
601         /* more status ring rx bits */
602         Rxvlan  = 1<<13,
603         Rxjab   = 1<<12,        /* jabber */
604         Rxsmall = 1<<11,        /* too small */
605         Rxmc    = 1<<10,        /* multicast */
606         Rxbc    = 1<<9, /* bcast */
607         Rxok    = 1<<8,
608         Rxfcok  = 1<<7, /* flow control pkt */
609         Rxfcbad = 1<<6,
610         Rxmiierr        = 1<<5,
611         Rxbig   = 1<<4, /* too big */
612         Rxfrag  = 1<<3,
613         Rxcrcerr        = 1<<1,
614         Rxfov   = 1<<0, /* fifo overflow */
615         Rxerror = Rxfov | Rxcrcerr | Rxfrag | Rxbig | Rxmiierr
616                 | Rxfcbad | Rxsmall | Rxjab,
617 };
618
619 enum {
620         Ffiber  = 1<<0,
621         Fgbe    = 1<<1,
622         Fnewphy = 1<<2,
623         Fapwr   = 1<<3,
624         Fnewle  = 1<<4,
625         Fram    = 1<<5,
626         Fancy   =Fgbe | Fnewphy | Fapwr,
627
628         Yukxl   = 0,
629         Yukecu,
630         Yukex,
631         Yukec,
632         Yukfe,
633         Yukfep,
634         Yuksup,
635         Yukul2,
636         Yukba,          /* doesn't exist */
637         Yukopt,
638         Nyuk,
639 };
640
641 typedef struct Chipid Chipid;
642 typedef struct Ctlr Ctlr;
643 typedef void (*Freefn)(Block*);
644 typedef struct Kproc Kproc;
645 typedef struct Mc Mc;
646 typedef struct Stattab Stattab;
647 typedef struct Status Status;
648 typedef struct Sring Sring;
649 typedef struct Vtab Vtab;
650
651 struct Chipid {
652         uchar   feat;
653         uchar   okrev;
654         uchar   mhz;
655         char    *name;
656 };
657
658 struct Kproc {
659         Rendez;
660         uint    event;
661 };
662
663 struct Sring {
664         uint    wp;
665         uint    rp;
666         uint    cnt;
667         uint    m;
668         Status  *r;
669 };
670
671 struct Ctlr {
672         Pcidev  *p;
673         Ctlr    *oport;         /* port 2 */
674         uchar   qno;
675         uchar   attach;
676         uchar   rxinit;
677         uchar   txinit;
678         uchar   flag;
679         uchar   feat;
680         uchar   type;
681         uchar   rev;
682         uchar   nports;
683         uchar   portno;
684         uvlong  io;
685         uchar   *reg8;
686         ushort  *reg16;
687         uint    *reg;
688         uint    rbsz;
689         uchar   ra[Eaddrlen];
690         uint    mca;
691         uint    nmc;
692         Mc      *mc;
693         void    *alloc;
694         Sring   status;
695         Sring   tx;
696         Block   *tbring[Tringcnt];
697         Sring   rx;
698         Block   *rbring[Rringcnt];
699         Kproc   txmit;
700         Kproc   rxmit;
701         Kproc   iproc;
702 };
703
704 struct Mc {
705         Mc      *next;
706         uchar   ea[Eaddrlen];
707 };
708
709 struct Stattab {
710         uint    offset;
711         char    *name;
712 };
713
714 struct Status {
715         uchar   status[4];
716         uchar   l[2];
717         uchar   ctl;
718         uchar   op;
719 };
720
721 struct Vtab {
722         int     vid;
723         int     did;
724         int     mtu;
725         char    *name;
726 };
727
728 static Chipid idtab[] = {
729 [Yukxl]         Fgbe | Fnewphy,         0xff,   156,    "yukon-2 xl",
730 [Yukecu]        Fancy,                  0xff,   125,    "yukon-2 ec ultra",
731 [Yukex]         Fancy | Fnewle,         0xff,   125,    "yukon-2 extreme",
732 [Yukec]         Fgbe,                   2,      125,    "yukon-2 ec",
733 [Yukfe]         0,                      0xff,   100,    "yukon-2 fe",
734 [Yukfep]        Fnewphy|Fapwr | Fnewle, 0xff,   50,     "yukon-2 fe+",
735 [Yuksup]        Fgbe | Fnewphy | Fnewle,        0xff,   125,    "yukon-2 supreme",
736 [Yukul2]                Fgbe |Fapwr,            0xff,   125,    "yukon-2 ultra2",
737 [Yukba]         0,                      0,      0,      "??",
738 [Yukopt]        Fancy,                  0xff,   125,    "yukon-2 optima",
739 };
740
741 static Vtab vtab[] = {
742         0x11ab, 0x4354, 1514,   "88e8040",      /* unsure on mtu */
743         0x11ab, 0x4362, 1514,   "88e8053",
744         0x11ab, 0x4363, 1514,   "88e8055",
745         0x11ab, 0x4364, 1514,   "88e8056",
746         0x11ab, 0x4380, 1514,   "88e8057",
747         0x11ab, 0x436b, 1514,   "88e8071",      /* unsure on mtu */
748         0x1186, 0x4b00, 9000,   "dge-560t",
749         0x1186, 0x4b02, 1514,   "dge-550sx",
750         0x1186, 0x4b03, 1514,   "dge-550t",
751 };
752
753 static Stattab stattab[] = {
754         0,      "rx ucast",
755         8,      "rx bcast",
756         16,     "rx pause",
757         24,     "rx mcast",
758         32,     "rx chk seq",
759
760         48,     "rx ok low",
761         56,     "rx ok high",
762         64,     "rx bad low",
763         72,     "rx bad high",
764
765         80,     "rx frames < 64",
766         88,     "rx frames < 64 fcs",
767         96,     "rx frames 64",
768         104,    "rx frames 65-127",
769         112,    "rx frames 128-255",
770         120,    "rx frames 256-511",
771         128,    "rx frames 512-1023",
772         136,    "rx frames 1024-1518",
773         144,    "rx frames 1519-mtu",
774         152,    "rx frames too long",
775         160,    "rx jabber",
776         176,    "rx fifo oflow",
777
778         192,    "tx ucast",
779         200,    "tx bcast",
780         208,    "tx pause",
781         216,    "tx mcast",
782
783         224,    "tx ok low",
784         232,    "tx ok hi",
785
786         240,    "tx frames 64",
787         248,    "tx frames 65-127",
788         256,    "tx frames 128-255",
789         264,    "tx frames 256-511",
790         272,    "tx frames 512-1023",
791         280,    "tx frames 1024-1518",
792         288,    "tx frames 1519-mtu",
793
794         304,    "tx coll",
795         312,    "tx late coll",
796         320,    "tx excess coll",
797         328,    "tx mul col",
798         336,    "tx single col",
799         344,    "tx underrun",
800 };
801
802 static  uint    phypwr[] = {1<<26, 1<<27};
803 static  uint    coma[] = {1<<28, 1<<29};
804 static  uchar   nilea[Eaddrlen];
805 static  int     debug;
806 static  Ctlr    *ctlrtab[Nctlr];
807 static  int     nctlr;
808
809 static int
810 icansleep(void *v)
811 {
812         Kproc *k;
813
814         k = v;
815         return k->event != 0;
816 }
817
818 static void
819 unstarve(Kproc *k)
820 {
821         k->event = 1;
822         wakeup(k);
823 }
824
825 static void
826 starve(Kproc *k)
827 {
828         sleep(k, icansleep, k);
829         k->event = 0;
830 }
831
832 static int
833 getnslot(Sring *r, uint *wp, Status **t, uint n)
834 {
835         int i;
836
837         if(r->m - (int)(wp[0] - r->rp) < n)
838                 return -1;
839         for(i = 0; i < n; i++)
840                 t[i] = r->r + (wp[0]++ & r->m);
841         return 0;
842 }
843
844 static uint
845 macread32(Ctlr *c, uint r)
846 {
847         return c->reg[c->portno*0x20 + r];
848 }
849
850 static void
851 macwrite32(Ctlr *c, uint r, uint v)
852 {
853         c->reg[c->portno*0x20 + r] = v;
854 }
855
856 static uint
857 macread16(Ctlr *c, uint r)
858 {
859         return c->reg16[c->portno*0x40 + r];
860 }
861
862 static void
863 macwrite16(Ctlr *c, uint r, uint v)
864 {
865         c->reg16[c->portno*0x40 + r] = v;
866 }
867
868 static uint
869 macread8(Ctlr *c, uint r)
870 {
871         return c->reg8[c->portno*0x80 + r];
872 }
873
874 static void
875 macwrite8(Ctlr *c, uint r, uint v)
876 {
877         c->reg8[c->portno*0x80 + r] = v;
878 }
879
880 static uint gmac32[2] = {
881         0x2800/4,
882         0x3800/4,
883 };
884
885 static ushort
886 gmacread32(Ctlr *c, uint r)
887 {
888         return c->reg[gmac32[c->portno] + r];
889 }
890
891 static void
892 gmacwrite32(Ctlr *c, uint r, uint v)
893 {
894         c->reg[gmac32[c->portno] + r] = v;
895 }
896
897 static uint gmac[2] = {
898         0x2800/2,
899         0x3800/2,
900 };
901
902 static ushort
903 gmacread(Ctlr *c, uint r)
904 {
905         return c->reg16[gmac[c->portno] + r];
906 }
907
908 static void
909 gmacwrite(Ctlr *c, uint r, ushort v)
910 {
911         c->reg16[gmac[c->portno] + r] = v;
912 }
913
914 static uint
915 qrread(Ctlr *c, uint r)
916 {
917         return c->reg[Qbase + c->portno*Qportsz + r>>2];
918 }
919
920 static void
921 qrwrite(Ctlr *c, uint r, uint v)
922 {
923         c->reg[Qbase + c->portno*Qportsz + r>>2] = v;
924 }
925
926 static uint
927 qrread16(Ctlr *c, uint r)
928 {
929         return c->reg16[Qbase + c->portno*Qportsz + r>>1];
930 }
931
932 static void
933 qrwrite16(Ctlr *c, uint r, uint v)
934 {
935         c->reg16[Qbase + c->portno*Qportsz + r>>1] = v;
936 }
937
938 static uint
939 qrread8(Ctlr *c, uint r)
940 {
941         return c->reg8[Qbase + c->portno*Qportsz + r>>0];
942 }
943
944 static void
945 qrwrite8(Ctlr *c, uint r, uint v)
946 {
947         c->reg8[Qbase + c->portno*Qportsz + r>>0] = v;
948 }
949
950 static uint
951 rrread32(Ctlr *c, uint r)
952 {
953         return c->reg[Rbase + c->portno*Qportsz + r>>2];
954 }
955
956 static void
957 rrwrite32(Ctlr *c, uint r, uint v)
958 {
959         c->reg[Rbase + c->portno*Qportsz + r>>2] = v;
960 }
961
962 static void
963 rrwrite8(Ctlr *c, uint r, uint v)
964 {
965         c->reg8[Rbase + c->portno*Qportsz + r] = v;
966 }
967
968 static uint
969 rrread8(Ctlr *c, uint r)
970 {
971         return c->reg8[Rbase + c->portno*Qportsz + r];
972 }
973
974 static uint
975 prread32(Ctlr *c, uint r)
976 {
977         return c->reg[Pbase + c->portno*Qportsz + r>>2];
978 }
979
980 static void
981 prwrite32(Ctlr *c, uint r, uint v)
982 {
983         c->reg[Pbase + c->portno*Qportsz + r>>2] = v;
984 }
985
986 static uint
987 prread16(Ctlr *c, uint r)
988 {
989         return c->reg16[Pbase + c->portno*Qportsz + r>>1];
990 }
991
992 static void
993 prwrite16(Ctlr *c, uint r, uint v)
994 {
995         c->reg16[Pbase + c->portno*Qportsz + r>>1] = v;
996 }
997
998 static ushort
999 phyread(Ctlr *c, uint r)
1000 {
1001         ushort v;
1002
1003         gmacwrite(c, Smictl, Smiread | r<<6);
1004         for(;;){
1005                 v = gmacread(c, Smictl);
1006                 if(v == 0xffff)
1007                         error("phy read");
1008                 if(v & Smirdone)
1009                         return gmacread(c, Smidata);
1010                 microdelay(10);
1011         }
1012 }
1013
1014 static ushort
1015 phywrite(Ctlr *c, uint r, ushort v)
1016 {
1017         gmacwrite(c, Smidata, v);
1018         gmacwrite(c, Smictl, Smiwrite | r<<6);
1019         for(;;){
1020                 v = gmacread(c, Smictl);
1021                 if(v == 0xffff)
1022                         error("phy write");
1023                 if((v & Smibusy) == 0)
1024                         return gmacread(c, Smidata);
1025                 microdelay(10);
1026         }
1027 }
1028
1029 static uvlong lorder = 0x0706050403020100ull;
1030
1031 static uvlong
1032 getle(uchar *t, int w)
1033 {
1034         uint i;
1035         uvlong r;
1036
1037         r = 0;
1038         for(i = w; i != 0; )
1039                 r = r<<8 | t[--i];
1040         return r;
1041 }
1042
1043 static void
1044 putle(uchar *t, uvlong r, int w)
1045 {
1046         uchar *o, *f;
1047         uint i;
1048
1049         f = (uchar*)&r;
1050         o = (uchar*)&lorder;
1051         for(i = 0; i < w; i++)
1052                 t[o[i]] = f[i];
1053 }
1054
1055 static void
1056 bufinit(Ctlr *c, uint q, uint start, uint end)
1057 {
1058         uint t;
1059
1060         rrwrite8(c, q + Rctl, Rrstclr);
1061         rrwrite32(c, q + Rstart, start);
1062         rrwrite32(c, q + Rend, end-1);
1063         rrwrite32(c, q + Rwp, start);
1064         rrwrite32(c, q + Rrp, start);
1065
1066         if(q == Qr || q == Qr + Qportsz){
1067                 t = start-end;
1068                 rrwrite32(c, q + Rpon, t - 8192/8);
1069                 rrwrite32(c, q + Rpoff, t - 16384/8);
1070         } else
1071                 rrwrite8(c, q + Rctl, Rsfon);
1072         rrwrite8(c, q + Rctl, Renable);
1073         rrread8(c, q + Rctl);
1074 }
1075
1076 static void
1077 qinit(Ctlr *c, uint queue)
1078 {
1079         qrwrite(c, queue + Qcsr, Qallclr);
1080         qrwrite(c, queue + Qcsr, Qgo);
1081         qrwrite(c, queue + Qcsr, Qfifoon);
1082         qrwrite16(c, queue + Qwm,  0x600);              /* magic */
1083 //      qrwrite16(c, queue + Qwm,  0x80);               /* pcie magic; assume pcie; no help */
1084 }
1085
1086 /* initialized prefetching */
1087 static void
1088 pinit(Ctlr *c, uint queue, Sring *r)
1089 {
1090         union {
1091                 uchar   u[4];
1092                 uint    l;
1093         } u;
1094
1095         prwrite32(c, queue + Pctl, Prefrst);
1096         prwrite32(c, queue + Pctl, Prefrstclr);
1097         putle(u.u, Pciwaddrh(r->r), 4);
1098         prwrite32(c, queue + Paddrh, u.l);
1099         putle(u.u, Pciwaddrl(r->r), 4);
1100         prwrite32(c, queue + Paddrl, u.l);
1101         prwrite16(c, queue + Plidx, r->m);
1102         prwrite32(c, queue + Pctl, Prefon);
1103         prread32(c, queue + Pctl);
1104 }
1105
1106 static void
1107 txinit(Ether *e)
1108 {
1109         Ctlr *c;
1110         Sring *r;
1111
1112         c = e->ctlr;
1113         r = &c->tx;
1114         if(c->txinit == 1)
1115                 return;
1116         c->txinit = 1;
1117         r->wp = 0;
1118         r->rp = 0;
1119         qinit(c, Qtx);
1120         pinit(c,  Qtx, &c->tx);
1121 }
1122
1123 static void
1124 linkup(Ctlr *c, uint w)
1125 {
1126         static Lock l;
1127
1128         lock(&l);
1129         gmacwrite(c, Ctl, w|gmacread(c, Ctl));
1130         unlock(&l);
1131 }
1132
1133 static void
1134 tproc(void *v)
1135 {
1136         Block *b;
1137         Ctlr *c;
1138         Ether *e;
1139         Sring *r;
1140         Status *tab[2], *t;
1141
1142         e = v;
1143         c = e->ctlr;
1144         r = &c->tx;
1145
1146         txinit(e);
1147         linkup(c, Txen);
1148         while(waserror())
1149                 ;
1150         for(;;){
1151                 if((b = qbread(e->oq, 100000)) == nil)
1152                         break;
1153                 while(getnslot(r, &r->wp, tab, 1 + is64()) == -1)
1154                         starve(&c->txmit);
1155                 t = tab[is64()];
1156                 c->tbring[t - r->r] = b;
1157                 if(is64()){
1158                         Status *t = tab[0];
1159                         t->ctl = 0;
1160                         t->op = Oaddr64 | Hw;
1161                         putle(t->status, Pciwaddrh(b->rp), 4);
1162                 }
1163                 putle(t->status, Pciwaddrl(b->rp), 4);
1164                 putle(t->l, BLEN(b), 2);
1165                 t->op = Opkt | Hw;
1166                 t->ctl = Eop;
1167                 sfence();
1168                 prwrite16(c, Qtx + Pputidx, r->wp & r->m);
1169         }
1170         print("#l%d: tproc: queue closed\n", e->ctlrno);
1171         pexit("queue closed", 1);
1172 }
1173
1174 static void
1175 rxinit(Ether *e)
1176 {
1177         Ctlr *c;
1178         Sring *r;
1179         Status *t;
1180
1181         c = e->ctlr;
1182         r = &c->rx;
1183         if(c->rxinit == 1)
1184                 return;
1185         c->rxinit = 1;
1186         qinit(c, Qr);
1187         if(c->type == Yukecu && (c->rev == 2 || c->rev == 3))
1188                 qrwrite(c, Qr + Qtest, Qramdis);
1189         pinit(c,  Qr, &c->rx);
1190
1191         if((c->flag & Fnewle) == 0){
1192                 while(getnslot(r, &r->wp, &t, 1) == -1)
1193                         starve(&c->rxmit);
1194                 putle(t->status, 14<<16 | 14, 4);
1195                 t->ctl = 0;
1196                 t->op = Ock | Hw;
1197                 qrwrite(c, Qr + Qcsr, Qsumen);
1198         }
1199         macwrite32(c, Gfrxctl, Gftroff);
1200 }
1201
1202 /* debug; remove */
1203 #include "yukdump.h"
1204 static int
1205 rxscrew(Ether *e, Sring *r, Status *t, uint wp)
1206 {
1207         Ctlr *c;
1208
1209         c = e->ctlr;
1210         if((int)(wp - r->rp) >= r->cnt){
1211                 print("rxscrew1 wp %ud(%ud) rp %ud %zd\n", wp, r->wp, r->rp, t-r->r);
1212                 return -1;
1213         }
1214         if(c->rbring[t - r->r]){
1215                 print("rxscrew2 wp %ud rp %ud %zd\n", wp, r->rp, t-r->r);
1216                 descriptorfu(e, Qr);
1217                 return -1;
1218         }
1219         return 0;
1220 }
1221
1222 static int
1223 replenish(Ether *e, Ctlr *c)
1224 {
1225         int n, lim;
1226         uint wp;
1227         Block *b;
1228         Sring *r;
1229         Status *tab[2], *t;
1230
1231         r = &c->rx;
1232         wp = r->wp;
1233
1234         lim = r->cnt/2;
1235         if(lim > 128)
1236                 lim = 128;              /* hw limit? */
1237         for(n = 0; n < lim; n++){
1238                 b = iallocb(c->rbsz + Rbalign);
1239                 if(b == nil || getnslot(r, &wp, tab, 1 + is64()) == -1){
1240                         freeb(b);
1241                         break;
1242                 }
1243                 b->rp = b->wp = (uchar*)ROUND((uintptr)b->base, Rbalign);
1244
1245                 t = tab[is64()];
1246                 if(rxscrew(e, r, t, wp) == -1){
1247                         freeb(b);
1248                         break;
1249                 }
1250                 c->rbring[t - r->r] = b;
1251
1252                 if(is64()){
1253                         Status *t = tab[0];
1254                         putle(t->status, Pciwaddrh(b->wp), 4);
1255                         t->ctl = 0;
1256                         t->op = Oaddr64 | Hw;
1257                 }
1258                 putle(t->status, Pciwaddrl(b->wp), 4);
1259                 putle(t->l, c->rbsz, 2);
1260                 t->ctl = 0;
1261                 t->op = Opkt | Hw;
1262         }
1263         if(n>0){
1264                 r->wp = wp;
1265                 sfence();
1266                 prwrite16(c, Qr + Pputidx, wp & r->m);
1267                 dprint("yuk: replenish %d %ud-%ud [%d-%d]\n", n, r->rp, wp, r->rp&r->m, wp&r->m);
1268         }
1269         return n == lim;
1270 }
1271
1272 static void
1273 rproc(void *v)
1274 {
1275         Ctlr *c;
1276         Ether *e;
1277
1278         e = v;
1279         c = e->ctlr;
1280
1281         rxinit(e);
1282         linkup(c, Rxen);
1283         while(waserror())
1284                 ;
1285         for(;;){
1286                 if(replenish(e, c) == 0)
1287                         starve(&c->rxmit);
1288         }
1289 }
1290
1291 static void
1292 promiscuous(void *a, int on)
1293 {
1294         uint r;
1295         Ether *e;
1296         Ctlr *c;
1297
1298         e = a;
1299         c = e->ctlr;
1300         r = gmacread(c, Rxctl);
1301         if(on)
1302                 r &= ~(Ufilter|Mfilter);
1303         else
1304                 r |= Ufilter|Mfilter;
1305         gmacwrite(c, Rxctl, r);
1306 }
1307
1308 static uchar pauseea[] = {1, 0x80, 0xc2, 0, 0, 1};
1309
1310 static void
1311 multicast(void *a, uchar *ea, int on)
1312 {
1313         uchar f[8];
1314         uint i, r, b;
1315         Ctlr *c;
1316         Ether *e;
1317         Mc **ll, *l, *p;
1318
1319         e = a;
1320         c = e->ctlr;
1321         r = gmacread(c, Rxctl);
1322         if(on){
1323                 for(ll = &c->mc; *ll != nil; ll = &(*ll)->next)
1324                         if(memcmp((*ll)->ea, ea, Eaddrlen) == 0)
1325                                 return;
1326                 *ll = malloc(sizeof **ll);
1327                 memmove((*ll)->ea, ea, Eaddrlen);
1328         }else{
1329                 for(p = nil, l = c->mc; l != nil; p = l, l = l->next)
1330                         if(memcmp(l->ea, ea, Eaddrlen) == 0)
1331                                 break;
1332                 if(l == nil)
1333                         return;
1334                 if(p != nil)
1335                         p->next = l->next;
1336                 else
1337                         c->mc = l->next;
1338                 free(l);
1339         }
1340         memset(f, 0, sizeof f);
1341         if(0 /* flow control */){
1342                 b = ethercrc(pauseea, Eaddrlen) & 0x3f;
1343                 f[b>>3] |= 1 << (b & 7);
1344         }
1345         for(l = c->mc; l != nil; l = l->next){
1346                 b = ethercrc(l->ea, Eaddrlen) & 0x3f;
1347                 f[b>>3] |= 1 << (b & 7);
1348         }
1349         for(i = 0; i < sizeof f / 2; i++)
1350                 gmacwrite(c, Mchash + 2*i, f[i] | f[i+1]<<8);
1351         gmacwrite(c, Rxctl, r | Mfilter);
1352 }
1353
1354 static int spdtab[4] = {
1355         10, 100, 1000, 0,
1356 };
1357
1358 static void
1359 link(Ether *e)
1360 {
1361         uint i, s, spd;
1362         Ctlr *c;
1363
1364         c = e->ctlr;
1365         i = phyread(c, Phyint);
1366         s = phyread(c, Phylstat);
1367         dprint("#l%d: yuk: link %.8ux %.8ux\n", e->ctlrno, i, s);
1368         spd = 0;
1369         e->link = (s & Plink) != 0;
1370         if(e->link && c->feat&Ffiber)
1371                 spd = 1000;
1372         else if(e->link){
1373                 spd = s & Physpd;
1374                 spd >>= 14;
1375                 spd = spdtab[spd];
1376         }
1377         e->mbps = spd;
1378         dprint("#l%d: yuk: link %d spd %d\n", e->ctlrno, e->link, e->mbps);
1379 }
1380
1381 static void
1382 txcleanup(Ctlr *c, uint end)
1383 {
1384         uint rp;
1385         Block *b;
1386         Sring *r;
1387         Status *t;
1388
1389         r = &c->tx;
1390         end &= r->m;
1391         for(rp = r->rp & r->m; rp != end; rp = r->rp & r->m){
1392                 t = r->r + rp;
1393                 r->rp++;
1394                 if((t->ctl & Eop) == 0)
1395                         continue;
1396                 b = c->tbring[rp];
1397                 c->tbring[rp] = nil;
1398                 if(b != nil)
1399                         freeb(b);
1400         }
1401         unstarve(&c->txmit);
1402 }
1403
1404 static void
1405 rx(Ether *e, uint l, uint x, uint flag)
1406 {
1407         uint cnt, i, rp;
1408         Block *b;
1409         Ctlr *c;
1410         Sring *r;
1411
1412         c = e->ctlr;
1413         r = &c->rx;
1414         for(rp = r->rp;;){
1415                 if(rp == r->wp){
1416                         print("#l%d: yuk rx empty\n", e->ctlrno);
1417                         return;
1418                 }
1419                 i = rp++&r->m;
1420                 b = c->rbring[i];
1421                 c->rbring[i] = nil;
1422                 if(b != nil)
1423                         break;
1424         }
1425         r->rp = rp;
1426         cnt = x>>16 & 0x7fff;
1427         if((cnt != l || x&Rxerror) &&
1428         !(c->type == Yukfep && c->rev == 0)){
1429                 print("#l%d: yuk rx error %.4ux\n", e->ctlrno, x&0xffff);
1430                 freeb(b);
1431         }else{
1432                 b->wp += l;
1433                 b->flag |= flag;
1434                 etheriq(e, b);
1435         }
1436         unstarve(&c->rxmit);
1437 }
1438
1439 static uint
1440 cksum(Ctlr *c, uint ck, uint css)
1441 {
1442         if(c->flag & Fnewle && css&(Cisip4|Cisip6) && css&Ctcpok)
1443                 return Bipck | Btcpck | Budpck;
1444         else if(ck == 0xffff || ck == 0)
1445                 return Bipck;
1446         return 0;
1447 }
1448
1449 static void
1450 sring(Ether *e)
1451 {
1452         uint i, lim, op, l, x;
1453         Ctlr *c;
1454         Sring *r;
1455         Status *s;
1456         static uint ck = Badck;
1457
1458         c = e->ctlr;
1459         r = &c->status;
1460         lim = c->reg16[Stathd] & r->m;
1461         for(;;){
1462                 i = r->rp & r->m;
1463                 if(i == lim){
1464                         lim = c->reg16[Stathd] & r->m;
1465                         if(i == lim)
1466                                 break;
1467                 }
1468                 s = r->r + i;
1469                 op = s->op;
1470                 if((op & Hw) == 0)
1471                         break;
1472                 op &= ~Hw;
1473                 switch(op){
1474                 case Orxchks:
1475                         ck = getle(s->status, 4) & 0xffff;
1476                         break;
1477                 case Orxstat:
1478                         l = getle(s->l, 2);
1479                         x = getle(s->status, 4);
1480                         rx(e, l, x, cksum(c, ck, s->ctl));
1481                         ck = Badck;
1482                         break;
1483                 case Otxidx:
1484                         l = getle(s->l, 2);
1485                         x = getle(s->status, 4);
1486                         txcleanup(c, x & 0xfff);
1487
1488                         x = l>>24 & 0xff | l<< 8;
1489                         x &= 0xfff;
1490                         if(x != 0 && c->oport)
1491                                 txcleanup(c->oport, x);
1492                         break;
1493                 default:
1494                         print("#l%d: yuk: funny opcode %.2ux\n", e->ctlrno, op);
1495                         break;
1496                 }
1497                 s->op = 0;
1498                 r->rp++;
1499         }
1500         c->reg[Statctl] = Statirqclr;
1501 }
1502
1503 enum {
1504         Pciaer  = 0x1d00,
1505         Pciunc  = 0x0004,
1506 };
1507
1508 static void
1509 hwerror(Ether *e, uint cause)
1510 {
1511         uint u;
1512         Ctlr *c;
1513
1514         c = e->ctlr;
1515         cause = c->reg[Hwe];
1516         if(cause == 0)
1517                 print("hwe: no cause\n");
1518         if(cause & Htsof){
1519                 c->reg8[Tgc] = Tgclr;
1520                 cause &= ~Htsof;
1521         }
1522         if(cause & (Hmerr | Hstatus)){
1523                 c->reg8[Tstctl1] = Tstwen;
1524                 u = pcicfgr16(c->p, PciPSR) | 0x7800;
1525                 pcicfgw16(c->p, PciPSR, u);
1526                 c->reg8[Tstctl1] = Tstwdis;
1527                 cause &= ~(Hmerr | Hstatus);
1528         }
1529         if(cause & Hpcie){
1530                 c->reg8[Tstctl1] = Tstwen;
1531                 c->reg[Pciaer + Pciunc>>2] = ~0;
1532                 u =  c->reg[Pciaer + Pciunc>>2];
1533                 USED(u);
1534                 print("#l%d: pcierror %.8ux\n", e->ctlrno, u);
1535                 c->reg8[Tstctl1] = Tstwdis;
1536                 cause &= ~Hpcie;
1537         }
1538         if(cause & Hrxparity){
1539                 print("#l%d: ram parity read error.  bug? ca %.8ux\n", e->ctlrno, cause);
1540                 qrwrite(c, Qtx + Qcsr, Qcirqpar);
1541                 cause &= ~Hrxparity;
1542         }
1543         if(cause & Hrparity){
1544                 print("#l%d: ram parity read error.  bug? ca %.8ux\n", e->ctlrno, cause);
1545                 descriptorfu(e, Qr);
1546                 descriptorfu(e, Qtx);
1547                 c->reg16[Rictl + c->portno*0x40>>1] = Rirpclr;
1548                 cause &= ~Hrparity;
1549         }
1550         if(cause & Hwparity){
1551                 print("#l%d: ram parity write error.  bug? ca %.8ux\n", e->ctlrno, cause);
1552                 descriptorfu(e, Qr);
1553                 descriptorfu(e, Qtx);
1554                 c->reg16[Rictl + c->portno*0x40>>1] = Riwpclr;
1555                 cause &= ~Hwparity;
1556         }
1557         if(cause & Hmfault){
1558                 print("#l%d: mac parity error\n", e->ctlrno);
1559                 macwrite32(c, Gmfctl, Gmfcpe);
1560                 cause &= ~Hmfault;
1561         }
1562         if(cause)
1563                 print("#l%d: leftover hwe %.8ux\n", e->ctlrno, cause);
1564 }
1565
1566 static void
1567 macintr(Ether *e)
1568 {
1569         uint cause;
1570         Ctlr *c;
1571
1572         c = e->ctlr;
1573         cause = macread8(c, Irq);
1574         cause  &= ~(Rxdone | Txdone);
1575         if(cause == 0)
1576                 return;
1577         print("#l%d: mac error %.8ux\n", e->ctlrno, cause);
1578         if(cause & Txovfl){
1579                 gmacread32(c, Txirq);
1580                 cause &= ~Txovfl;
1581         }
1582         if(cause & Rxovfl){
1583                 gmacread32(c, Rxirq);
1584                 cause &= ~Rxovfl;
1585         }
1586         if(cause & Rxorun){
1587                 macwrite32(c, Gfrxctl, Gmfcfu);
1588                 cause &= ~Rxorun;
1589         }
1590         if(cause & Txurun){
1591                 macwrite32(c, Gmfctl, Gmfcfu);
1592                 cause &= ~Txurun;
1593         }
1594         if(cause)
1595                 print("#l%d: leftover mac error %.8ux\n", e->ctlrno, cause);
1596 }
1597
1598 static struct {
1599         uint    i;
1600         uint    q;
1601         char    *s;
1602 } emap[] = {
1603         Irx,            Qr,             "qr",
1604         Itxs,           Qtxs,           "qtxs",
1605         Itx,            Qtx,            "qtx",
1606         Irx<<Iphy2base, Qr + 0x80,      "qr1",
1607         Itxs<<Iphy2base,        Qtxs + 0x100,   "qtxs1",
1608         Itx<<Iphy2base, Qtx + 0x100,    "qtx1",
1609 };
1610
1611 static void
1612 eerror(Ether *e, uint cause)
1613 {
1614         uint i, o, q;
1615         Ctlr *c;
1616
1617         c = e->ctlr;
1618
1619         if(cause & Imac){
1620                 macintr(e);
1621                 cause &= ~Imac;
1622         }
1623         if(cause & (Irx | Itxs | Itx)*(1 | 1<<Iphy2base))
1624                 for(i = 0; i < nelem(emap); i++){
1625                         if((cause & emap[i].i) == 0)
1626                                 continue;
1627                         q = emap[i].q;
1628                         o = prread16(c, q + Pgetidx);
1629                         print("#l%d: yuk: bug: %s: @%d ca=%.8ux\n", 
1630                                 e->ctlrno, emap[i].s, o, cause);
1631                         descriptorfu(e, q);
1632                         qrwrite(c, emap[i].q + Qcsr, Qcirqck);
1633                         cause &= ~emap[i].i;
1634                 }
1635         if(cause)
1636                 print("#l%d: leftover error %.8ux\n", e->ctlrno, cause);
1637 }
1638
1639 static void
1640 iproc(void *v)
1641 {
1642         uint cause, d;
1643         Ether *e;
1644         Ctlr *c;
1645
1646         e = v;
1647         c = e->ctlr;
1648         while(waserror())
1649                 ;
1650         for(;;){
1651                 starve(&c->iproc);
1652                 cause = c->reg[Eisr];
1653                 if(cause & Iphy)
1654                         link(e);
1655                 if(cause & Ihwerr)
1656                         hwerror(e, cause);
1657                 if(cause & Ierror)
1658                         eerror(e, cause & Ierror);
1659                 if(cause & Ibmu)
1660                         sring(e);
1661                 d = c->reg[Lisr];
1662                 USED(d);
1663         }
1664 }
1665
1666 static void
1667 interrupt(Ureg*, void *v)
1668 {
1669         uint cause;
1670         Ctlr *c;
1671         Ether *e;
1672
1673         e = v;
1674         c = e->ctlr;
1675
1676         /* reading Isrc2 masks interrupts */
1677         cause = c->reg[Isrc2];
1678         if(cause == 0 || cause == ~0){
1679                 /* reenable interrupts */
1680                 c->reg[Icr] = 2;
1681                 return;
1682         }
1683         unstarve(&c->iproc);
1684 }
1685
1686 static void
1687 storefw(Ctlr *c)
1688 {
1689         if(c->type == Yukex && c->rev != 1
1690         || c->type == Yukfep
1691         || c->type == Yuksup)
1692                 macwrite32(c, Gmfctl, Gmfjon | Gmfsfon);
1693         else{
1694                 macwrite32(c, Gmfae, 0x8000 | 0x70);    /* tx gmac fifo */
1695                 macwrite32(c, Gmfctl, Gmfsfoff);
1696         }
1697 }
1698
1699 static void
1700 raminit(Ctlr *c)
1701 {
1702         uint ram, rx;
1703
1704         if(ram = c->reg8[Ramcnt] * 4096/8){     /* in qwords */
1705                 c->flag |= Fram;
1706                 rx = ROUNDUP((2*ram)/3, 1024/8);
1707                 bufinit(c, Qr, 0, rx);
1708                 bufinit(c, Qtx, rx, ram);
1709                 rrwrite8(c, Qtxs + Rctl, Rrst); /* sync tx off */
1710         }else{
1711                 macwrite8(c, Rxplo, 768/8);
1712                 macwrite8(c, Rxphi, 1024/8);
1713                 storefw(c);
1714         }
1715 }
1716
1717 static void
1718 attach(Ether *e)
1719 {
1720         char buf[KNAMELEN];
1721         Ctlr *c;
1722         static Lock l;
1723
1724         c = e->ctlr;
1725         if(c->attach == 1)
1726                 return;
1727         lock(&l);
1728         if(c->attach == 1){
1729                 unlock(&l);
1730                 return;
1731         }
1732         c->attach = 1;
1733         unlock(&l);
1734
1735         snprint(buf, sizeof buf, "#l%dtproc", e->ctlrno);
1736         kproc(buf, tproc, e);
1737         snprint(buf, sizeof buf, "#l%drproc", e->ctlrno);
1738         kproc(buf, rproc, e);
1739         snprint(buf, sizeof buf, "#l%diproc", e->ctlrno);
1740         kproc(buf, iproc, e);
1741
1742         c->reg[Ism] |= Ibmu | Iport<<Iphy2base*c->portno;
1743 }
1744
1745 static long
1746 ifstat(Ether *e0, void *a, long n, ulong offset)
1747 {
1748         char *s, *e, *p;
1749         int i;
1750         uint u;
1751         Ctlr *c;
1752
1753         c = e0->ctlr;
1754         p = s = malloc(READSTR);
1755         e = p + READSTR;
1756         for(i = 0; i < nelem(stattab); i++){
1757                 u = gmacread32(c, Stats + stattab[i].offset/4);
1758                 if(u > 0)
1759                         p = seprint(p, e, "%s\t%ud\n", stattab[i].name, u);
1760         }
1761         p = seprint(p, e, "stat %.4ux ctl %.3ux\n", gmacread(c, Stat), gmacread(c, Ctl));
1762         p = seprint(p, e, "pref %.8ux %.4ux\n", prread32(c, Qr + Pctl), prread16(c, Qr + Pgetidx));
1763         if(debug){
1764                 p = dumppci(c, p, e);
1765                 p = dumpgmac(c, p, e);
1766                 p = dumpmac(c, p, e);
1767                 p = dumpreg(c, p, e);
1768         }
1769         seprint(p, e, "%s rev %d phy %s\n", idtab[c->type].name,
1770                 c->rev, c->feat&Ffiber? "fiber": "copper");
1771         n = readstr(offset, a, n, s);
1772         free(s);
1773         return n;
1774 }
1775
1776 static Cmdtab ctltab[] = {
1777         1,      "debug",                1,
1778         2,      "descriptorfu", 1,
1779 };
1780
1781 static long
1782 ctl(Ether *e, void *buf, long n)
1783 {
1784         Cmdbuf *cb;
1785         Cmdtab *t;
1786
1787         cb = parsecmd(buf, n);
1788         if(waserror()){
1789                 free(cb);
1790                 nexterror();
1791         }
1792         t = lookupcmd(cb, ctltab, nelem(ctltab));
1793         switch(t->index){
1794         case 0:
1795                 debug ^= 1;
1796                 break;
1797         case 1:
1798                 descriptorfu(e, Qr);
1799                 break;
1800         }
1801         free(cb);
1802         poperror();
1803         return n;
1804 }
1805
1806 static uint
1807 yukpcicfgr32(Ctlr *c, uint r)
1808 {
1809         return c->reg[r + 0x1c00>>2];
1810 }
1811
1812 static void
1813 yukpcicfgw32(Ctlr *c, uint r, uint v)
1814 {
1815         c->reg[r + 0x1c00>>2] = v;
1816 }
1817
1818 static void
1819 phypower(Ctlr *c)
1820 {
1821         uint u, u0;
1822
1823         u = u0 = yukpcicfgr32(c, Pciphy);
1824         u &= ~phypwr[c->portno];
1825         if(c->type == Yukxl && c->rev > 1)
1826                 u |= coma[c->portno];
1827         if(u != u0 || 1){
1828                 c->reg8[Tstctl1] = Tstwen;
1829                 yukpcicfgw32(c, Pciphy, u);
1830                 c->reg8[Tstctl1] = Tstwdis;
1831         }
1832         if(c->type == Yukfe)
1833                 c->reg8[Phyctl] = Aneen;
1834         else if(c->flag & Fapwr)
1835                 macwrite32(c, Phy, Gphyrstclr);
1836 }
1837
1838 static void
1839 phyinit(Ctlr *c)
1840 {
1841         uint u;
1842
1843         if((c->feat & Fnewphy) == 0){
1844                 u = phyread(c, Phyextctl);
1845                 u &= ~0xf70;                    /* clear downshift counters */
1846                 u |= 0x7<<4;                    /* mac tx clock = 25mhz */
1847                 if(c->type == Yukec)
1848                         u |= 2*Dnmstr | Dnslv;
1849                 else
1850                         u |= Dnslv;
1851                 phywrite(c, Phyextctl, u);
1852         }
1853         u = phyread(c, Phyphy);
1854
1855         /* questionable value */
1856         if(c->feat & Ffiber)
1857                 u &= ~Ppmdix;
1858         else if(c->feat & Fgbe){
1859                 u &= ~Pped;
1860                 u |= Ppmdixa;
1861                 if(c->flag & Fnewphy){
1862                 //      u &= ~(7<<12);
1863                 //      u |= 2*(1<<12) | 1<<11; /* like 2*Dnmstr | Dnslv */
1864                         u |= 2*(1<<9) | 1<<11;
1865                 }
1866         }else{
1867                 u |= Ppmdixa >> 1;              /* why the shift? */
1868                 if(c->type == Yukfep && c->rev == 0){
1869                 }
1870         }
1871
1872         phywrite(c, Phyphy, u);
1873         /* copper/fiber specific stuff gmacwrite(c, Ctl, 0); */
1874         gmacwrite(c, Ctl, 0);
1875         if(c->feat & Fgbe)
1876                 if(c->feat & Ffiber)
1877                         phywrite(c, Gbectl, Gbexf | Gbexh);
1878                 else
1879                         phywrite(c, Gbectl, Gbef | Gbeh);
1880         phywrite(c, Phyana, Anall);
1881         phywrite(c, Phyctl, Phyrst | Anerst | Aneen);
1882         /* chip specific stuff? */
1883         if (c->type == Yukfep){
1884                 u = phyread(c, Phyphy) | Ppnpe;
1885                 u &= ~(Ppengy | Ppscrdis);
1886                 phywrite(c, Phyphy, u);
1887 //              phywrite(c, 0x16, 0x0b54);              /* write to fe_led_par */
1888
1889                 /* yukfep and rev 0: apply workaround for integrated resistor calibration */
1890                 phywrite(c, Phypadr, 17);
1891                 phywrite(c, 0x1e, 0x3f60);
1892         }
1893         phywrite(c, Phyintm, Anok | Anerr | Lsc);
1894         dprint("phyid %.4ux step %.4ux\n", phyread(c, 2), phyread(c, 3));
1895 }
1896
1897 static int
1898 identify(Ctlr *c)
1899 {
1900         char t;
1901
1902         pcicfgw32(c->p, Pciclk, 0);
1903         c->reg16[Ctst] = Swclr;
1904
1905         c->type = c->reg8[Chip] - 0xb3;
1906         c->rev = c->reg8[Maccfg]>>4 & 0xf;
1907         if(c->type >= Nyuk)
1908                 return -1;
1909         if(idtab[c->type].okrev != 0xff)
1910         if(c->rev != idtab[c->type].okrev)
1911                 return -1;
1912         c->feat |= idtab[c->type].feat;
1913
1914         t = c->reg8[Pmd];
1915         if(t == 'L' || t == 'S' || t == 'P')
1916                 c->feat |= Ffiber;
1917         c->portno = 0;
1918         /* check second port ... whatever */
1919         return 0;
1920 }
1921
1922 static uint
1923 µ2clk(Ctlr *c, int µs)
1924 {
1925         return idtab[c->type].mhz * µs;
1926 }
1927
1928 static void
1929 gmacsetea(Ctlr *c, uint r)
1930 {
1931         uchar *ra;
1932         int i;
1933
1934         ra = c->ra;
1935         for(i = 0; i < Eaddrlen; i += 2)
1936                 gmacwrite(c, r + i, ra[i + 0] | ra[i + 1]<<8);
1937 }
1938
1939 static int
1940 reset(Ctlr *c)
1941 {
1942         uint i, j;
1943         Block *b;
1944
1945         identify(c);
1946
1947         if(c->type == Yukex)
1948                 c->reg16[Asfcs/2] &= ~(Asfbrrst | Asfcpurst | Asfucrst);
1949         else
1950                 c->reg8[Asfcs] = Asfrst;
1951         c->reg16[Ctst] = Asfdis;
1952
1953         c->reg16[Ctst] = Swrst;
1954         c->reg16[Ctst] = Swclr;
1955
1956         c->reg8[Tstctl1] = Tstwen;
1957         pcicfgw16(c->p, PciPSR, pcicfgr16(c->p, PciPSR) | 0xf100);
1958         c->reg16[Ctst] = Mstrclr;
1959         /* fixup pcie extended error goes here */
1960
1961         c->reg8[Pwrctl] = Vauxen | Vccen | Vauxoff | Vccon;
1962         c->reg[Clkctl] = Clkdivdis;
1963         if(c->type == Yukxl && c->rev > 1)
1964                 c->reg8[Clkgate] = ~Link2inactive;
1965         else
1966                 c->reg8[Clkgate] = 0;
1967         if(c->flag & Fapwr){
1968                 pcicfgw32(c->p, Pciclk, 0);
1969                 pcicfgw32(c->p, Pciasp, pcicfgr32(c->p, Pciasp) & Aspmsk);
1970                 pcicfgw32(c->p, Pcistate, pcicfgr32(c->p, Pcistate) & Vmain);
1971                 pcicfgw32(c->p, Pcicf1, 0);
1972                 c->reg[Gpio] |= Norace;
1973                 print("yuk2: advanced power %.8ux\n", c->reg[Gpio]);
1974         }
1975         c->reg8[Tstctl1] = Tstwdis;
1976
1977         for(i = 0; i < c->nports; i++){
1978                 macwrite8(c, Linkctl, Linkrst);
1979                 macwrite8(c, Linkctl, Linkclr);
1980                 if(c->type == Yukex || c->type == Yuksup)
1981                         macwrite16(c, Mac, Nomacsec | Nortx);
1982         }
1983
1984         c->reg[Dpolltm] = Pollstop;
1985
1986         for(i = 0; i < c->nports; i++)
1987                 macwrite8(c, Txactl, Txaclr);
1988         for(i = 0; i < c->nports; i++){
1989                 c->reg8[i*64 + Rictl] = Riclr;
1990                 for(j = 0; j < 12; j++)
1991                         c->reg8[i*64 + Rib + j] = 36;   /* qword times */
1992         }
1993
1994         c->reg[Hwem] = Hdflt;
1995         macwrite8(c, Irqm, 0);
1996         for(i = 0; i < 4; i++)
1997                 gmacwrite(c, Mchash + 2*i, 0);
1998         gmacwrite(c, Rxctl, Ufilter | Mfilter | Rmcrc);
1999
2000         for(i = 0; i < nelem(c->tbring); i++)
2001                 if(b = c->tbring[i]){
2002                         c->tbring[i] = nil;
2003                         freeb(b);
2004                 }
2005         for(i = 0; i < nelem(c->rbring); i++)
2006                 if(b = c->rbring[i]){
2007                         c->rbring[i] = nil;
2008                         freeb(b);
2009                 }
2010
2011         memset(c->tbring, 0, sizeof c->tbring[0] * nelem(c->tbring));
2012         memset(c->rbring, 0, sizeof c->rbring[0] * nelem(c->rbring));
2013         memset(c->tx.r, 0, sizeof c->tx.r[0] * c->tx.cnt);
2014         memset(c->rx.r, 0, sizeof c->rx.r[0] * c->rx.cnt);
2015         memset(c->status.r, 0, sizeof c->status.r[0] * c->status.cnt);
2016         c->reg[Statctl] = Statrst;
2017         c->reg[Statctl] = Statclr;
2018         c->reg[Stataddr + 0] = Pciwaddrl(c->status.r);
2019         c->reg[Stataddr + 4] = Pciwaddrh(c->status.r);
2020         c->reg16[Stattl] = c->status.m;
2021         c->reg16[Statth] = 10;
2022         c->reg8[Statwm] = 16;
2023         if(c->type == Yukxl && c->rev == 0)
2024                 c->reg8[Statiwm] = 4;
2025         else
2026                 c->reg8[Statiwm] = 4; //16;
2027
2028         /* set transmit, isr,  level timers */
2029         c->reg[Tsti] = µ2clk(c, 1000);
2030         c->reg[Titi] = µ2clk(c, 20);
2031         c->reg[Tlti] = µ2clk(c, 100);
2032
2033         c->reg[Statctl] = Staton;
2034
2035         c->reg8[Tstc] = Tstart;
2036         c->reg8[Tltc] = Tstart;
2037         c->reg8[Titc] = Tstart;
2038
2039         return 0;
2040 }
2041
2042 static void
2043 macinit(Ctlr *c)
2044 {
2045         uint r, i;
2046
2047         r = macread32(c, Phy) & ~(Gphyrst | Gphyrstclr);
2048         macwrite32(c, Phy, r | Gphyrst);
2049         macwrite32(c, Phy, r | Gphyrstclr);
2050         /* macwrite32(c, Mac, Macrst); ? */
2051         macwrite32(c, Mac, Macrstclr);
2052
2053         if(c->type == Yukxl && c->rev == 0 && c->portno == 1){
2054         }
2055
2056         macread8(c, Irq);
2057         macwrite8(c, Irqm, Txurun);
2058
2059         phypower(c);
2060         phyinit(c);
2061
2062         gmacwrite(c, Phyaddr, (r = gmacread(c, Phyaddr)) | Mibclear);
2063         for(i = 0; i < nelem(stattab); i++)
2064                 gmacread32(c, Stats + stattab[i].offset/4);
2065         gmacwrite(c, Phyaddr, r);
2066
2067         gmacwrite(c, Txctl, 4<<10);     /* collision distance */
2068         gmacwrite(c, Txflow, 0xffff);   /* flow control */
2069         gmacwrite(c, Txparm, 3<<14 | 0xb<<9 | 0x1c<<4 | 4);
2070         gmacwrite(c, Rxctl, Ufilter | Mfilter | Rmcrc);
2071         gmacwrite(c, Serctl, 0x04<<11 /* blind */ | Jumboen | 0x1e /* ipig */);
2072
2073         gmacsetea(c, Ea0);
2074         gmacsetea(c, Ea1);
2075
2076         gmacwrite(c, Txmask, 0);
2077         gmacwrite(c, Rxmask, 0);
2078         gmacwrite(c, Trmask, 0);
2079
2080         macwrite32(c, Gfrxctl, Gfrstclr);
2081         r = Gfon | Gffon;
2082         if(c->type == Yukex || c->type == Yukfep)
2083                 r |= Gfroon;
2084         macwrite32(c, Gfrxctl, r);
2085         if(c->type == Yukxl)
2086                 macwrite32(c, Grxfm, 0);
2087         else
2088                 macwrite32(c, Grxfm, Ferror);
2089         if(c->type == Yukfep && c->rev == 0)
2090                 macwrite32(c, Grxft, 0x178);
2091         else
2092                 macwrite32(c, Grxft, 0xb);
2093
2094         macwrite32(c, Gmfctl, Gmfclr);  /* clear reset */
2095         macwrite32(c, Gmfctl, Gmfon);   /* on */
2096
2097         raminit(c);
2098         if(c->type == Yukfep && c->rev == 0)
2099                 c->reg[Gmfea] = c->reg[Gmfea] & ~3;
2100
2101         c->rxinit = 0;
2102         c->txinit = 0;
2103 }
2104
2105 static void*
2106 slice(void **v, uint r, uint sz)
2107 {
2108         uintptr a;
2109
2110         a = (uintptr)*v;
2111         a = ROUNDUP(a, r);
2112         *v = (void*)(a + sz);
2113         return (void*)a;
2114 }
2115
2116 static void
2117 setupr(Sring *r, uint cnt)
2118 {
2119         r->rp = 0;
2120         r->wp = 0;
2121         r->cnt = cnt;
2122         r->m = cnt - 1;
2123 }
2124
2125 static int
2126 setup(Ctlr *c)
2127 {
2128         uint n;
2129         void *v, *mem;
2130         Pcidev *p;
2131
2132         p = c->p;
2133         if(p->mem[0].bar & 1)
2134                 return -1;
2135         c->io = p->mem[0].bar&~0xf;
2136         mem = vmap(c->io, p->mem[0].size);
2137         if(mem == nil){
2138                 print("yuk: cant map %llux\n", c->io);
2139                 return -1;
2140         }
2141         pcienable(p);
2142         c->p = p;
2143         c->reg = (uint*)mem;
2144         c->reg8 = (uchar*)mem;
2145         c->reg16 = (ushort*)mem;
2146         if(memcmp(c->ra, nilea, sizeof c->ra) == 0)
2147                 memmove(c->ra, c->reg8 + Macadr + 8*c->portno, Eaddrlen);
2148
2149         setupr(&c->status, Sringcnt);
2150         setupr(&c->tx, Tringcnt);
2151         setupr(&c->rx, Rringcnt);
2152
2153         n = sizeof c->status.r[0] * (c->status.cnt + c->tx.cnt + c->rx.cnt);
2154         n += 16*4096*2;                         /* rounding slop */
2155         c->alloc = xspanalloc(n, 16*4096, 0);   /* unknown alignment constraints */
2156         memset(c->alloc, 0, n);
2157
2158         v = c->alloc;
2159         c->status.r = slice(&v, 16*4096, sizeof c->status.r[0] * c->status.cnt);
2160         c->tx.r = slice(&v, 16*4096, sizeof c->tx.r[0] * c->tx.cnt);
2161         c->rx.r = slice(&v, 16*4096, sizeof c->rx.r[0] * c->rx.cnt);
2162
2163         c->nports = 1;                          /* BOTCH */
2164         if(reset(c)){
2165                 print("yuk: cant reset\n");
2166                 free(c->alloc);
2167                 vunmap(mem, p->mem[0].size);
2168                 pcidisable(p);
2169                 return -1;
2170         }
2171         macinit(c);
2172         pcisetbme(p);
2173         return 0;
2174 }
2175
2176 static void
2177 shutdown(Ether *e)
2178 {
2179         Ctlr *c;
2180         Pcidev *p;
2181
2182         c = e->ctlr;
2183
2184         reset(c);
2185         if(0){
2186                 p = c->p;
2187                 vunmap(c->reg, p->mem[0].size);
2188                 free(c->alloc);
2189         }
2190 }
2191
2192 static void
2193 scan(void)
2194 {
2195         int i;
2196         Pcidev *p;
2197         Ctlr *c;
2198
2199         for(p = nil; p = pcimatch(p, 0, 0); ){
2200                 for(i = 0; i < nelem(vtab); i++)
2201                         if(vtab[i].vid == p->vid)
2202                         if(vtab[i].did == p->did)
2203                                 break;
2204                 if(i == nelem(vtab))
2205                         continue;
2206                 if(nctlr == nelem(ctlrtab)){
2207                         print("yuk: too many controllers\n");
2208                         return;
2209                 }
2210                 c = malloc(sizeof *c);
2211                 if(c == nil){
2212                         print("yuk: no memory for Ctlr\n");
2213                         return;
2214                 }
2215                 c->p = p;
2216                 c->qno = nctlr;
2217                 c->rbsz = vtab[i].mtu;
2218                 ctlrtab[nctlr++] = c;
2219         }
2220 }
2221
2222 static int
2223 pnp(Ether *e)
2224 {
2225         int i;
2226         Ctlr *c;
2227
2228         if(nctlr == 0)
2229                 scan();
2230         for(i = 0;; i++){
2231                 if(i == nctlr)
2232                         return -1;
2233                 c = ctlrtab[i];
2234                 if(c == nil || c->flag&Fprobe)
2235                         continue;
2236                 if(e->port != 0 && e->port != (ulong)(uintptr)c->reg)
2237                         continue;
2238                 c->flag |= Fprobe;
2239                 if(setup(c) != 0)
2240                         continue;
2241                 break;
2242         }
2243         e->ctlr = c;
2244         e->port = c->io;
2245         e->irq = c->p->intl;
2246         e->tbdf = c->p->tbdf;
2247         e->mbps = 1000;
2248         e->maxmtu = c->rbsz;
2249         memmove(e->ea, c->ra, Eaddrlen);
2250         e->arg = e;
2251         e->attach = attach;
2252         e->ctl = ctl;
2253         e->ifstat = ifstat;
2254         e->multicast = multicast;
2255         e->promiscuous = promiscuous;
2256         e->shutdown = shutdown;
2257         e->transmit = nil;
2258
2259         intrenable(e->irq, interrupt, e, e->tbdf, e->name);
2260
2261         return 0;
2262 }
2263
2264 void
2265 etheryuklink(void)
2266 {
2267         addethercard("yuk", pnp);
2268 }