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