]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc/etheryuk.c
pc kernel: kproc error and exit
[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 "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        = Nrb,
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         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, 0x4364, 1514,   "88e8056",
744         0x11ab, 0x4380, 1514,   "88e8057",
745         0x11ab, 0x436b, 1514,   "88e8071",      /* unsure on mtu */
746         0x1186, 0x4b00, 9000,   "dge-560t",
747         0x1186, 0x4b02, 1514,   "dge-550sx",
748         0x1186, 0x4b03, 1514,   "dge-550t",
749 };
750
751 static Stattab stattab[] = {
752         0,      "rx ucast",
753         8,      "rx bcast",
754         16,     "rx pause",
755         24,     "rx mcast",
756         32,     "rx chk seq",
757
758         48,     "rx ok low",
759         56,     "rx ok high",
760         64,     "rx bad low",
761         72,     "rx bad high",
762
763         80,     "rx frames < 64",
764         88,     "rx frames < 64 fcs",
765         96,     "rx frames 64",
766         104,    "rx frames 65-127",
767         112,    "rx frames 128-255",
768         120,    "rx frames 256-511",
769         128,    "rx frames 512-1023",
770         136,    "rx frames 1024-1518",
771         144,    "rx frames 1519-mtu",
772         152,    "rx frames too long",
773         160,    "rx jabber",
774         176,    "rx fifo oflow",
775
776         192,    "tx ucast",
777         200,    "tx bcast",
778         208,    "tx pause",
779         216,    "tx mcast",
780
781         224,    "tx ok low",
782         232,    "tx ok hi",
783
784         240,    "tx frames 64",
785         248,    "tx frames 65-127",
786         256,    "tx frames 128-255",
787         264,    "tx frames 256-511",
788         272,    "tx frames 512-1023",
789         280,    "tx frames 1024-1518",
790         288,    "tx frames 1519-mtu",
791
792         304,    "tx coll",
793         312,    "tx late coll",
794         320,    "tx excess coll",
795         328,    "tx mul col",
796         336,    "tx single col",
797         344,    "tx underrun",
798 };
799
800 static  uint    phypwr[] = {1<<26, 1<<27};
801 static  uint    coma[] = {1<<28, 1<<29};
802 static  uchar   nilea[Eaddrlen];
803 static  int     debug;
804 static  Ctlr    *ctlrtab[Nctlr];
805 static  int     nctlr;
806 static  struct {
807         union {
808                 struct {
809                         Lock;
810                         Block   *b;
811                         uint    starve;
812                 };
813                 uchar pad[128];         /* cacheline */
814         };
815         Kproc   *k;
816         Block   *x;
817         uint    nfast;
818         uint    nslow;
819 } rbtab[Nctlr];
820
821 static int
822 icansleep(void *v)
823 {
824         Kproc *k;
825
826         k = v;
827         return k->event != 0;
828 }
829
830 static void
831 unstarve(Kproc *k)
832 {
833         k->event = 1;
834         wakeup(k);
835 }
836
837 static void
838 starve(Kproc *k)
839 {
840         sleep(k, icansleep, k);
841         k->event = 0;
842 }
843
844 static Status*
845 getslot(Sring *r, Kproc *k)
846 {
847         if(r->rp + r->m - r->wp & ~r->m)
848                 starve(k);
849         return r->r + (r->wp++ & r->m);
850 }
851
852 static int
853 getnslot(Sring *r, uint *wp, Status **t, uint n)
854 {
855         int i;
856
857         if(r->rp + r->m - (n - 1) - wp[0] & ~r->m)
858                 return -1;
859         for(i = 0; i < n; i++)
860                 t[i] = r->r + (wp[0]++ & r->m);
861         return 0;
862 }
863
864 /* assume allocs come from a single thread; 30*0.999x speedup */
865 static Block*
866 rballoc(int t)
867 {
868         Block *b;
869
870         if((b = rbtab[t].x) != nil){
871                 rbtab[t].nfast++;
872                 rbtab[t].x = b->next;
873                 b->next = nil;
874 b->ref = 1;
875                 return b;
876         }
877
878         ilock(&rbtab[t]);
879         b = rbtab[t].x = rbtab[t].b;
880         rbtab[t].b = nil;
881         if(b == nil)
882                 rbtab[t].starve = 1;
883         iunlock(&rbtab[t]);
884         
885         rbtab[t].nslow++;
886         if(b != nil){
887                 rbtab[t].x = b->next;
888                 b->next = nil;
889 b->ref = 1;
890         }
891         return b;
892 }
893
894 static void
895 rbfree(Block *b, int t)
896 {
897         b->rp = b->wp = (uchar*)ROUND((uintptr)b->base, Rbalign);
898         b->flag &= ~(Bipck | Budpck | Btcpck | Bpktck);
899         ilock(&rbtab[t]);
900         b->next = rbtab[t].b;
901         if(b->next == nil && rbtab[t].starve){
902                 rbtab[t].starve = 0;
903                 unstarve(rbtab[t].k);
904         }
905         rbtab[t].b = b;
906         iunlock(&rbtab[t]);
907 }
908
909 static void
910 rbfree0(Block *b)
911 {
912         rbfree(b, 0);
913 }
914
915 static void
916 rbfree1(Block *b)
917 {
918         rbfree(b, 1);
919 }
920
921 static void
922 rbfree2(Block *b)
923 {
924         rbfree(b, 2);
925 }
926
927 static void
928 rbfree3(Block *b)
929 {
930         rbfree(b, 3);
931 }
932
933 static Freefn freetab[Nctlr] = {
934         rbfree0,
935         rbfree1,
936         rbfree2,
937         rbfree3,
938 };
939
940 static uint
941 macread32(Ctlr *c, uint r)
942 {
943         return c->reg[c->portno*0x20 + r];
944 }
945
946 static void
947 macwrite32(Ctlr *c, uint r, uint v)
948 {
949         c->reg[c->portno*0x20 + r] = v;
950 }
951
952 static uint
953 macread16(Ctlr *c, uint r)
954 {
955         return c->reg16[c->portno*0x40 + r];
956 }
957
958 static void
959 macwrite16(Ctlr *c, uint r, uint v)
960 {
961         c->reg16[c->portno*0x40 + r] = v;
962 }
963
964 static uint
965 macread8(Ctlr *c, uint r)
966 {
967         return c->reg8[c->portno*0x80 + r];
968 }
969
970 static void
971 macwrite8(Ctlr *c, uint r, uint v)
972 {
973         c->reg8[c->portno*0x80 + r] = v;
974 }
975
976 static uint gmac32[2] = {
977         0x2800/4,
978         0x3800/4,
979 };
980
981 static ushort
982 gmacread32(Ctlr *c, uint r)
983 {
984         return c->reg[gmac32[c->portno] + r];
985 }
986
987 static void
988 gmacwrite32(Ctlr *c, uint r, uint v)
989 {
990         c->reg[gmac32[c->portno] + r] = v;
991 }
992
993 static uint gmac[2] = {
994         0x2800/2,
995         0x3800/2,
996 };
997
998 static ushort
999 gmacread(Ctlr *c, uint r)
1000 {
1001         return c->reg16[gmac[c->portno] + r];
1002 }
1003
1004 static void
1005 gmacwrite(Ctlr *c, uint r, ushort v)
1006 {
1007         c->reg16[gmac[c->portno] + r] = v;
1008 }
1009
1010 static uint
1011 qrread(Ctlr *c, uint r)
1012 {
1013         return c->reg[Qbase + c->portno*Qportsz + r>>2];
1014 }
1015
1016 static void
1017 qrwrite(Ctlr *c, uint r, uint v)
1018 {
1019         c->reg[Qbase + c->portno*Qportsz + r>>2] = v;
1020 }
1021
1022 static uint
1023 qrread16(Ctlr *c, uint r)
1024 {
1025         return c->reg16[Qbase + c->portno*Qportsz + r>>1];
1026 }
1027
1028 static void
1029 qrwrite16(Ctlr *c, uint r, uint v)
1030 {
1031         c->reg16[Qbase + c->portno*Qportsz + r>>1] = v;
1032 }
1033
1034 static uint
1035 qrread8(Ctlr *c, uint r)
1036 {
1037         return c->reg8[Qbase + c->portno*Qportsz + r>>0];
1038 }
1039
1040 static void
1041 qrwrite8(Ctlr *c, uint r, uint v)
1042 {
1043         c->reg8[Qbase + c->portno*Qportsz + r>>0] = v;
1044 }
1045
1046 static uint
1047 rrread32(Ctlr *c, uint r)
1048 {
1049         return c->reg[Rbase + c->portno*Qportsz + r>>2];
1050 }
1051
1052 static void
1053 rrwrite32(Ctlr *c, uint r, uint v)
1054 {
1055         c->reg[Rbase + c->portno*Qportsz + r>>2] = v;
1056 }
1057
1058 static void
1059 rrwrite8(Ctlr *c, uint r, uint v)
1060 {
1061         c->reg8[Rbase + c->portno*Qportsz + r] = v;
1062 }
1063
1064 static uint
1065 rrread8(Ctlr *c, uint r)
1066 {
1067         return c->reg8[Rbase + c->portno*Qportsz + r];
1068 }
1069
1070 static uint
1071 prread32(Ctlr *c, uint r)
1072 {
1073         return c->reg[Pbase + c->portno*Qportsz + r>>2];
1074 }
1075
1076 static void
1077 prwrite32(Ctlr *c, uint r, uint v)
1078 {
1079         c->reg[Pbase + c->portno*Qportsz + r>>2] = v;
1080 }
1081
1082 static uint
1083 prread16(Ctlr *c, uint r)
1084 {
1085         return c->reg16[Pbase + c->portno*Qportsz + r>>1];
1086 }
1087
1088 static void
1089 prwrite16(Ctlr *c, uint r, uint v)
1090 {
1091         c->reg16[Pbase + c->portno*Qportsz + r>>1] = v;
1092 }
1093
1094 static ushort
1095 phyread(Ctlr *c, uint r)
1096 {
1097         ushort v;
1098
1099         gmacwrite(c, Smictl, Smiread | r<<6);
1100         for(;;){
1101                 v = gmacread(c, Smictl);
1102                 if(v == 0xffff)
1103                         error("phy read");
1104                 if(v & Smirdone)
1105                         return gmacread(c, Smidata);
1106                 microdelay(10);
1107         }
1108 }
1109
1110 static ushort
1111 phywrite(Ctlr *c, uint r, ushort v)
1112 {
1113         gmacwrite(c, Smidata, v);
1114         gmacwrite(c, Smictl, Smiwrite | r<<6);
1115         for(;;){
1116                 v = gmacread(c, Smictl);
1117                 if(v == 0xffff)
1118                         error("phy write");
1119                 if((v & Smibusy) == 0)
1120                         return gmacread(c, Smidata);
1121                 microdelay(10);
1122         }
1123 }
1124
1125 static uvlong lorder = 0x0706050403020100ull;
1126
1127 static uvlong
1128 getle(uchar *t, int w)
1129 {
1130         uint i;
1131         uvlong r;
1132
1133         r = 0;
1134         for(i = w; i != 0; )
1135                 r = r<<8 | t[--i];
1136         return r;
1137 }
1138
1139 static void
1140 putle(uchar *t, uvlong r, int w)
1141 {
1142         uchar *o, *f;
1143         uint i;
1144
1145         f = (uchar*)&r;
1146         o = (uchar*)&lorder;
1147         for(i = 0; i < w; i++)
1148                 t[o[i]] = f[i];
1149 }
1150
1151 static void
1152 bufinit(Ctlr *c, uint q, uint start, uint end)
1153 {
1154         uint t;
1155
1156         rrwrite8(c, q + Rctl, Rrstclr);
1157         rrwrite32(c, q + Rstart, start);
1158         rrwrite32(c, q + Rend, end-1);
1159         rrwrite32(c, q + Rwp, start);
1160         rrwrite32(c, q + Rrp, start);
1161
1162         if(q == Qr || q == Qr + Qportsz){
1163                 t = start-end;
1164                 rrwrite32(c, q + Rpon, t - 8192/8);
1165                 rrwrite32(c, q + Rpoff, t - 16384/8);
1166         } else
1167                 rrwrite8(c, q + Rctl, Rsfon);
1168         rrwrite8(c, q + Rctl, Renable);
1169         rrread8(c, q + Rctl);
1170 }
1171
1172 static void
1173 qinit(Ctlr *c, uint queue)
1174 {
1175         qrwrite(c, queue + Qcsr, Qallclr);
1176         qrwrite(c, queue + Qcsr, Qgo);
1177         qrwrite(c, queue + Qcsr, Qfifoon);
1178         qrwrite16(c, queue + Qwm,  0x600);              /* magic */
1179 //      qrwrite16(c, queue + Qwm,  0x80);               /* pcie magic; assume pcie; no help */
1180 }
1181
1182 /* initialized prefetching */
1183 static void
1184 pinit(Ctlr *c, uint queue, Sring *r)
1185 {
1186         union {
1187                 uchar   u[4];
1188                 uint    l;
1189         } u;
1190
1191         prwrite32(c, queue + Pctl, Prefrst);
1192         prwrite32(c, queue + Pctl, Prefrstclr);
1193         putle(u.u, Pciwaddrh(r->r), 4);
1194         prwrite32(c, queue + Paddrh, u.l);
1195         putle(u.u, Pciwaddrl(r->r), 4);
1196         prwrite32(c, queue + Paddrl, u.l);
1197         prwrite16(c, queue + Plidx, r->m);
1198         prwrite32(c, queue + Pctl, Prefon);
1199         prread32(c, queue + Pctl);
1200 }
1201
1202 static void
1203 txinit(Ether *e)
1204 {
1205         Ctlr *c;
1206         Sring *r;
1207
1208         c = e->ctlr;
1209         r = &c->tx;
1210         if(c->txinit == 1)
1211                 return;
1212         c->txinit = 1;
1213         r->wp = 0;
1214         r->rp = 0;
1215         qinit(c, Qtx);
1216         pinit(c,  Qtx, &c->tx);
1217 }
1218
1219 static void
1220 linkup(Ctlr *c, uint w)
1221 {
1222         static Lock l;
1223
1224         lock(&l);
1225         gmacwrite(c, Ctl, w|gmacread(c, Ctl));
1226         unlock(&l);
1227 }
1228
1229 static void
1230 tproc(void *v)
1231 {
1232         Block *b;
1233         Ctlr *c;
1234         Ether *e;
1235         Kproc *k;
1236         Sring *r;
1237         Status *t;
1238
1239         e = v;
1240         c = e->ctlr;
1241         k = &c->txmit;
1242         r = &c->tx;
1243
1244         txinit(e);
1245         linkup(c, Txen);
1246         while(waserror())
1247                 ;
1248         for(;;){
1249                 if((b = qbread(e->oq, 100000)) == nil)
1250                         break;
1251                 if(Pciwaddrh(b->rp) != 0){
1252                         t = getslot(r, k);
1253                         t->ctl = 0;
1254                         t->op = Oaddr64 | Hw;
1255                         putle(t->status, Pciwaddrh(b->rp), 4);
1256                 }
1257                 t = getslot(r, k);
1258                 c->tbring[t - r->r] = b;
1259                 putle(t->status, Pciwaddrl(b->rp), 4);
1260                 putle(t->l, BLEN(b), 2);
1261                 t->op = Opkt | Hw;
1262                 t->ctl = Eop;
1263                 sfence();
1264                 prwrite16(c, Qtx + Pputidx, r->wp & r->m);
1265         }
1266         print("#l%d: tproc: queue closed\n", e->ctlrno);
1267         pexit("queue closed", 1);
1268 }
1269
1270 static void
1271 rxinit(Ether *e)
1272 {
1273         int i;
1274         Ctlr *c;
1275         Block *b;
1276         Sring *r;
1277         Status *t;
1278
1279         c = e->ctlr;
1280         r = &c->rx;
1281         if(c->rxinit == 1)
1282                 return;
1283         c->rxinit = 1;
1284         for(i = 0; i < Nrb; i++){
1285                 b = allocb(c->rbsz + Rbalign);
1286                 b->free = freetab[c->qno];
1287                 freeb(b);
1288         }
1289
1290         qinit(c, Qr);
1291         if(c->type == Yukecu && (c->rev == 2 || c->rev == 3))
1292                 qrwrite(c, Qr + Qtest, Qramdis);
1293         pinit(c,  Qr, &c->rx);
1294
1295         if((c->flag & Fnewle) == 0){
1296                 t = getslot(r, &c->rxmit);
1297                 putle(t->status, 14<<16 | 14, 4);
1298                 t->ctl = 0;
1299                 t->op = Ock | Hw;
1300                 qrwrite(c, Qr + Qcsr, Qsumen);
1301         }
1302         macwrite32(c, Gfrxctl, Gftroff);
1303 }
1304
1305 /* debug; remove */
1306 #include "yukdump.h"
1307 static int
1308 rxscrew(Ether *e, Sring *r, Status *t, uint wp)
1309 {
1310         Ctlr *c;
1311
1312         c = e->ctlr;
1313         if(wp - r->rp > r->cnt){
1314                 print("rxscrew1 wp %ud(%ud) rp %ud %lud\n", wp, r->wp, r->rp, t-r->r);
1315                 return -1;
1316         }
1317         if(c->rbring[t - r->r]){
1318                 print("rxscrew2 wp %ud rp %ud %lud\n", wp, r->rp, t-r->r);
1319                 descriptorfu(e, Qr);
1320                 return -1;
1321         }
1322         return 0;
1323 }
1324
1325 static int
1326 replenish(Ether *e, Ctlr *c)
1327 {
1328         int req, n, lim;
1329         uint wp;
1330         Block *b;
1331         Sring *r;
1332         Status *tab[2], *t;
1333
1334         r = &c->rx;
1335         wp = r->wp;
1336         req = 1 + is64();
1337
1338         lim = r->cnt/2;
1339         if(lim > 128)
1340                 lim = 128;              /* hw limit? */
1341         for(n = 0; n < lim; n++){
1342                 b = rballoc(c->qno);
1343                 if(b == nil || getnslot(r, &wp, tab, req) == -1){
1344                         freeb(b);
1345                         break;
1346                 }
1347                 t = tab[0];
1348                 if(is64()){
1349                         putle(t->status, Pciwaddrh(b->wp), 4);
1350                         t->ctl = 0;
1351                         t->op = Oaddr64 | Hw;
1352                         t = tab[1];
1353                 }
1354                 if(rxscrew(e, r, t, wp) == -1)
1355                         break;
1356                 assert(c->rbring[t - r->r] == nil);
1357                 c->rbring[t - r->r] = b;
1358
1359                 putle(t->status, Pciwaddrl(b->wp), 4);
1360                 putle(t->l, c->rbsz, 2);
1361                 t->ctl = 0;
1362                 t->op = Opkt | Hw;
1363         }
1364         if(n>0){
1365                 sfence();
1366                 prwrite16(c, Qr + Pputidx, wp & r->m);
1367                 r->wp = wp;
1368                 dprint("yuk: replenish %d %ud-%ud [%d-%d]\n", n, r->rp, wp, r->rp&r->m, wp&r->m);
1369         }
1370         return lim - n == 0;
1371 }
1372
1373 static void
1374 rproc(void *v)
1375 {
1376         Ctlr *c;
1377         Ether *e;
1378         Kproc *k;
1379
1380         e = v;
1381         c = e->ctlr;
1382         k = &c->rxmit;
1383
1384         rxinit(e);
1385         linkup(c, Rxen);
1386         while(waserror())
1387                 ;
1388         for(;;)
1389                 if(replenish(e, c) == 0){
1390                         starve(k);
1391                         print("yuk: rx unstarve?\n");
1392                 }
1393 }
1394
1395 static void
1396 promiscuous(void *a, int on)
1397 {
1398         uint r;
1399         Ether *e;
1400         Ctlr *c;
1401
1402         e = a;
1403         c = e->ctlr;
1404         r = gmacread(c, Rxctl);
1405         if(on)
1406                 r &= ~(Ufilter|Mfilter);
1407         else
1408                 r |= Ufilter|Mfilter;
1409         gmacwrite(c, Rxctl, r);
1410 }
1411
1412 static uchar pauseea[] = {1, 0x80, 0xc2, 0, 0, 1};
1413
1414 static void
1415 multicast(void *a, uchar *ea, int on)
1416 {
1417         uchar f[8];
1418         uint i, r, b;
1419         Ctlr *c;
1420         Ether *e;
1421         Mc **ll, *l, *p;
1422
1423         e = a;
1424         c = e->ctlr;
1425         r = gmacread(c, Rxctl);
1426         if(on){
1427                 for(ll = &c->mc; *ll != nil; ll = &(*ll)->next)
1428                         if(memcmp((*ll)->ea, ea, Eaddrlen) == 0)
1429                                 return;
1430                 *ll = malloc(sizeof **ll);
1431                 memmove((*ll)->ea, ea, Eaddrlen);
1432         }else{
1433                 for(p = nil, l = c->mc; l != nil; p = l, l = l->next)
1434                         if(memcmp(l->ea, ea, Eaddrlen) == 0)
1435                                 break;
1436                 if(l == nil)
1437                         return;
1438                 if(p != nil)
1439                         p->next = l->next;
1440                 else
1441                         c->mc = l->next;
1442                 free(l);
1443         }
1444         memset(f, 0, sizeof f);
1445         if(0 /* flow control */){
1446                 b = ethercrc(pauseea, Eaddrlen) & 0x3f;
1447                 f[b>>3] |= 1 << (b & 7);
1448         }
1449         for(l = c->mc; l != nil; l = l->next){
1450                 b = ethercrc(l->ea, Eaddrlen) & 0x3f;
1451                 f[b>>3] |= 1 << (b & 7);
1452         }
1453         for(i = 0; i < sizeof f / 2; i++)
1454                 gmacwrite(c, Mchash + 2*i, f[i] | f[i+1]<<8);
1455         gmacwrite(c, Rxctl, r | Mfilter);
1456 }
1457
1458 static int spdtab[4] = {
1459         10, 100, 1000, 0,
1460 };
1461
1462 static void
1463 link(Ether *e)
1464 {
1465         uint i, s, spd;
1466         Ctlr *c;
1467
1468         c = e->ctlr;
1469         i = phyread(c, Phyint);
1470         s = phyread(c, Phylstat);
1471         dprint("#l%d: yuk: link %.8ux %.8ux\n", e->ctlrno, i, s);
1472         spd = 0;
1473         e->link = (s & Plink) != 0;
1474         if(e->link && c->feat&Ffiber)
1475                 spd = 1000;
1476         else if(e->link){
1477                 spd = s & Physpd;
1478                 spd >>= 14;
1479                 spd = spdtab[spd];
1480         }
1481         e->mbps = spd;
1482         dprint("#l%d: yuk: link %d spd %d\n", e->ctlrno, e->link, e->mbps);
1483 }
1484
1485 static void
1486 txcleanup(Ctlr *c, uint end)
1487 {
1488         uint rp0, rp;
1489         Block *b;
1490         Sring *r;
1491         Status *t;
1492
1493         r = &c->tx;
1494         rp0 = r->rp & r->m;
1495         for(rp = rp0; rp != end; rp = r->rp & r->m){
1496                 t = r->r + rp;
1497                 r->rp++;
1498                 if((t->ctl & Eop) == 0)
1499                         continue;
1500                 b = c->tbring[rp];
1501                 c->tbring[rp] = nil;
1502                 if(b != nil)
1503                         freeb(b);
1504         }
1505         if(r->wp - r->rp > 16){         /* BOTCH */
1506                 print("TX unstarve %ud - %ud \n", r->wp, r->rp);
1507                 unstarve(&c->txmit);
1508         }
1509 }
1510
1511 static void
1512 rx(Ether *e, uint l, uint x, uint flag)
1513 {
1514         uint cnt, i, rp;
1515         Block *b;
1516         Ctlr *c;
1517         Sring *r;
1518
1519         c = e->ctlr;
1520         r = &c->rx;
1521         for(rp = r->rp;;){
1522                 i = rp++&r->m;
1523                 b = c->rbring[i];
1524                 c->rbring[i] = nil;
1525                 if(b != nil)
1526                         break;
1527         }
1528         cnt = x>>16 & 0x7fff;
1529         if(cnt != l || x&Rxerror &&
1530         !(c->type == Yukfep && c->rev == 0)){
1531                 print("#l%d: yuk rx error %.4ux\n", e->ctlrno, x&0xffff);
1532                 freeb(b);
1533         }else{
1534                 b->wp += l;
1535                 b->lim = b->wp;         /* lie like a dog */
1536                 b->flag |= flag;
1537                 etheriq(e, b, 1);
1538         }
1539         r->rp = rp;
1540 }
1541
1542 static uint
1543 cksum(Ctlr *c, uint ck, uint css)
1544 {
1545         if(c->flag & Fnewle && css&(Cisip4|Cisip6) && css&Ctcpok)
1546                 return Bipck | Btcpck | Budpck;
1547         else if(ck == 0xffff || ck == 0)
1548                 return Bipck;
1549         return 0;
1550 }
1551
1552 static void
1553 sring(Ether *e)
1554 {
1555         uint i, p, lim, op, l, x;
1556         Ctlr *c;
1557         Sring *r;
1558         Status *s;
1559         static uint ck = Badck;
1560
1561         c = e->ctlr;
1562         r = &c->status;
1563         lim = r->rp & r->m;
1564         p = 0;
1565         for(;;){
1566                 if((r->rp & r->m) == lim){
1567                         lim = c->reg16[Stathd];
1568                         if((r->rp & r->m) == lim)
1569                                 break;
1570                 }
1571                 i = r->rp & r->m;
1572                 s = r->r + i;
1573                 op = s->op;
1574                 if((op & Hw) == 0)
1575                         break;
1576                 op &= ~Hw;
1577                 switch(op){
1578                 case Orxchks:
1579                         ck = getle(s->status, 4) & 0xffff;
1580                         break;
1581                 case Orxstat:
1582                         l = getle(s->l, 2);
1583                         x = getle(s->status, 4);
1584                         rx(e, l, x, cksum(c, ck, s->ctl));
1585                         ck = Badck;
1586                         p++;
1587                         break;
1588                 case Otxidx:
1589                         l = getle(s->l, 2);
1590                         x = getle(s->status, 4);
1591                         txcleanup(c, x & 0xfff);
1592
1593                         x = l>>24 & 0xff | l<< 8;
1594                         x &= 0xfff;
1595                         if(x != 0 && c->oport)
1596                                 txcleanup(c->oport, x);
1597                         break;
1598                 default:
1599                         print("#l%d: yuk: funny opcode %.2ux\n", e->ctlrno, op);
1600                         break;
1601                 }
1602                 s->op = 0;
1603                 r->rp++;
1604         }
1605         while(p && replenish(e, c) != 0)
1606                 ;
1607         c->reg[Statctl] = Statirqclr;
1608 }
1609
1610 enum {
1611         Pciaer  = 0x1d00,
1612         Pciunc  = 0x0004,
1613 };
1614
1615 static void
1616 hwerror(Ether *e, uint cause)
1617 {
1618         uint u;
1619         Ctlr *c;
1620
1621         c = e->ctlr;
1622         cause = c->reg[Hwe];
1623         if(cause == 0)
1624                 print("hwe: no cause\n");
1625         if(cause & Htsof){
1626                 c->reg8[Tgc] = Tgclr;
1627                 cause &= ~Htsof;
1628         }
1629         if(cause & (Hmerr | Hstatus)){
1630                 c->reg8[Tstctl1] = Tstwen;
1631                 u = pcicfgr16(c->p, PciPSR) | 0x7800;
1632                 pcicfgw16(c->p, PciPSR, u);
1633                 c->reg8[Tstctl1] = Tstwdis;
1634                 cause &= ~(Hmerr | Hstatus);
1635         }
1636         if(cause & Hpcie){
1637                 c->reg8[Tstctl1] = Tstwen;
1638                 c->reg[Pciaer + Pciunc>>2] = ~0;
1639                 u =  c->reg[Pciaer + Pciunc>>2];
1640                 USED(u);
1641                 print("#l%d: pcierror %.8ux\n", e->ctlrno, u);
1642                 c->reg8[Tstctl1] = Tstwdis;
1643                 cause &= ~Hpcie;
1644         }
1645         if(cause & Hrxparity){
1646                 print("#l%d: ram parity read error.  bug? ca %.8ux\n", e->ctlrno, cause);
1647                 qrwrite(c, Qtx + Qcsr, Qcirqpar);
1648                 cause &= ~Hrxparity;
1649         }
1650         if(cause & Hrparity){
1651                 print("#l%d: ram parity read error.  bug? ca %.8ux\n", e->ctlrno, cause);
1652                 descriptorfu(e, Qr);
1653                 descriptorfu(e, Qtx);
1654                 c->reg16[Rictl + c->portno*0x40>>1] = Rirpclr;
1655                 cause &= ~Hrparity;
1656         }
1657         if(cause & Hwparity){
1658                 print("#l%d: ram parity write error.  bug? ca %.8ux\n", e->ctlrno, cause);
1659                 descriptorfu(e, Qr);
1660                 descriptorfu(e, Qtx);
1661                 c->reg16[Rictl + c->portno*0x40>>1] = Riwpclr;
1662                 cause &= ~Hwparity;
1663         }
1664         if(cause & Hmfault){
1665                 print("#l%d: mac parity error\n", e->ctlrno);
1666                 macwrite32(c, Gmfctl, Gmfcpe);
1667                 cause &= ~Hmfault;
1668         }
1669         if(cause)
1670                 print("#l%d: leftover hwe %.8ux\n", e->ctlrno, cause);
1671 }
1672
1673 static void
1674 macintr(Ether *e)
1675 {
1676         uint cause;
1677         Ctlr *c;
1678
1679         c = e->ctlr;
1680         cause = macread8(c, Irq);
1681         cause  &= ~(Rxdone | Txdone);
1682         if(cause == 0)
1683                 return;
1684         print("#l%d: mac error %.8ux\n", e->ctlrno, cause);
1685         if(cause & Txovfl){
1686                 gmacread32(c, Txirq);
1687                 cause &= ~Txovfl;
1688         }
1689         if(cause & Rxovfl){
1690                 gmacread32(c, Rxirq);
1691                 cause &= ~Rxovfl;
1692         }
1693         if(cause & Rxorun){
1694                 macwrite32(c, Gfrxctl, Gmfcfu);
1695                 cause &= ~Rxorun;
1696         }
1697         if(cause & Txurun){
1698                 macwrite32(c, Gmfctl, Gmfcfu);
1699                 cause &= ~Txurun;
1700         }
1701         if(cause)
1702                 print("#l%d: leftover mac error %.8ux\n", e->ctlrno, cause);
1703 }
1704
1705 static struct {
1706         uint    i;
1707         uint    q;
1708         char    *s;
1709 } emap[] = {
1710         Irx,            Qr,             "qr",
1711         Itxs,           Qtxs,           "qtxs",
1712         Itx,            Qtx,            "qtx",
1713         Irx<<Iphy2base, Qr + 0x80,      "qr1",
1714         Itxs<<Iphy2base,        Qtxs + 0x100,   "qtxs1",
1715         Itx<<Iphy2base, Qtx + 0x100,    "qtx1",
1716 };
1717
1718 static void
1719 eerror(Ether *e, uint cause)
1720 {
1721         uint i, o, q;
1722         Ctlr *c;
1723
1724         c = e->ctlr;
1725
1726         if(cause & Imac){
1727                 macintr(e);
1728                 cause &= ~Imac;
1729         }
1730         if(cause & (Irx | Itxs | Itx)*(1 | 1<<Iphy2base))
1731                 for(i = 0; i < nelem(emap); i++){
1732                         if((cause & emap[i].i) == 0)
1733                                 continue;
1734                         q = emap[i].q;
1735                         o = prread16(c, q + Pgetidx);
1736                         print("#l%d: yuk: bug: %s: @%d ca=%.8ux\n", 
1737                                 e->ctlrno, emap[i].s, o, cause);
1738                         descriptorfu(e, q);
1739                         qrwrite(c, emap[i].q + Qcsr, Qcirqck);
1740                         cause &= ~emap[i].i;
1741                 }
1742         if(cause)
1743                 print("#l%d: leftover error %.8ux\n", e->ctlrno, cause);
1744 }
1745
1746 static void
1747 iproc(void *v)
1748 {
1749         uint cause, d;
1750         Ether *e;
1751         Ctlr *c;
1752         Kproc *k;
1753
1754         e = v;
1755         c = e->ctlr;
1756         k = &c->iproc;
1757         while(waserror())
1758                 ;
1759         for(;;){
1760                 starve(k);
1761                 cause = c->reg[Eisr];
1762                 if(cause & Iphy)
1763                         link(e);
1764                 if(cause & Ihwerr)
1765                         hwerror(e, cause);
1766                 if(cause & Ierror)
1767                         eerror(e, cause & Ierror);
1768                 if(cause & Ibmu)
1769                         sring(e);
1770                 d = c->reg[Lisr];
1771                 USED(d);
1772         }
1773 }
1774
1775 static void
1776 interrupt(Ureg*, void *v)
1777 {
1778         uint cause;
1779         Ctlr *c;
1780         Ether *e;
1781
1782         e = v;
1783         c = e->ctlr;
1784
1785         cause = c->reg[Isrc2];
1786         if(cause != 0 && cause != ~0)
1787                 unstarve(&c->iproc);
1788 }
1789
1790 static void
1791 storefw(Ctlr *c)
1792 {
1793         if(c->type == Yukex && c->rev != 1
1794         || c->type == Yukfep
1795         || c->type == Yuksup)
1796                 macwrite32(c, Gmfctl, Gmfjon | Gmfsfon);
1797         else{
1798                 macwrite32(c, Gmfae, 0x8000 | 0x70);    /* tx gmac fifo */
1799                 macwrite32(c, Gmfctl, Gmfsfoff);
1800         }
1801 }
1802
1803 static void
1804 raminit(Ctlr *c)
1805 {
1806         uint ram, rx;
1807
1808         if(ram = c->reg8[Ramcnt] * 4096/8){     /* in qwords */
1809                 c->flag |= Fram;
1810                 rx = ROUNDUP((2*ram)/3, 1024/8);
1811                 bufinit(c, Qr, 0, rx);
1812                 bufinit(c, Qtx, rx, ram);
1813                 rrwrite8(c, Qtxs + Rctl, Rrst); /* sync tx off */
1814         }else{
1815                 macwrite8(c, Rxplo, 768/8);
1816                 macwrite8(c, Rxphi, 1024/8);
1817                 storefw(c);
1818         }
1819 }
1820
1821 static void
1822 attach(Ether *e)
1823 {
1824         char buf[KNAMELEN];
1825         Ctlr *c;
1826         static Lock l;
1827
1828         c = e->ctlr;
1829         if(c->attach == 1)
1830                 return;
1831         lock(&l);
1832         if(c->attach == 1){
1833                 unlock(&l);
1834                 return;
1835         }
1836         c->attach = 1;
1837         unlock(&l);
1838
1839         snprint(buf, sizeof buf, "#l%dtproc", e->ctlrno);
1840         kproc(buf, tproc, e);
1841         snprint(buf, sizeof buf, "#l%drproc", e->ctlrno);
1842         kproc(buf, rproc, e);
1843         snprint(buf, sizeof buf, "#l%diproc", e->ctlrno);
1844         kproc(buf, iproc, e);
1845
1846         c->reg[Ism] |= Ibmu | Iport<<Iphy2base*c->portno;
1847 }
1848
1849 static long
1850 ifstat(Ether *e0, void *a, long n, ulong offset)
1851 {
1852         char *s, *e, *p;
1853         int i;
1854         uint u;
1855         Ctlr *c;
1856
1857         c = e0->ctlr;
1858         p = s = malloc(READSTR);
1859         e = p + READSTR;
1860         for(i = 0; i < nelem(stattab); i++){
1861                 u = gmacread32(c, Stats + stattab[i].offset/4);
1862                 if(u > 0)
1863                         p = seprint(p, e, "%s\t%ud\n", stattab[i].name, u);
1864         }
1865         p = seprint(p, e, "stat %.4ux ctl %.3ux\n", gmacread(c, Stat), gmacread(c, Ctl));
1866         p = seprint(p, e, "irq %.8ux\n", c->reg[Isrc2]);
1867         p = seprint(p, e, "pref %.8ux %.4ux\n", prread32(c, Qr + Pctl), prread16(c, Qr + Pgetidx));
1868         p = seprint(p, e, "nfast %ud nslow %ud\n", rbtab[c->qno].nfast, rbtab[c->qno].nslow);
1869         if(debug){
1870                 p = dumppci(c, p, e);
1871                 p = dumpgmac(c, p, e);
1872                 p = dumpmac(c, p, e);
1873                 p = dumpreg(c, p, e);
1874         }
1875         seprint(p, e, "%s rev %d phy %s\n", idtab[c->type].name,
1876                 c->rev, c->feat&Ffiber? "fiber": "copper");
1877         n = readstr(offset, a, n, s);
1878         free(s);
1879         return n;
1880 }
1881
1882 static Cmdtab ctltab[] = {
1883         1,      "debug",                1,
1884         2,      "descriptorfu", 1,
1885 };
1886
1887 static long
1888 ctl(Ether *e, void *buf, long n)
1889 {
1890         Cmdbuf *cb;
1891         Cmdtab *t;
1892
1893         cb = parsecmd(buf, n);
1894         if(waserror()){
1895                 free(cb);
1896                 nexterror();
1897         }
1898         t = lookupcmd(cb, ctltab, nelem(ctltab));
1899         switch(t->index){
1900         case 0:
1901                 debug ^= 1;
1902                 break;
1903         case 1:
1904                 descriptorfu(e, Qr);
1905                 break;
1906         }
1907         free(cb);
1908         poperror();
1909         return n;
1910 }
1911
1912 static uint
1913 yukpcicfgr32(Ctlr *c, uint r)
1914 {
1915         return c->reg[r + 0x1c00>>2];
1916 }
1917
1918 static void
1919 yukpcicfgw32(Ctlr *c, uint r, uint v)
1920 {
1921         c->reg[r + 0x1c00>>2] = v;
1922 }
1923
1924 static void
1925 phypower(Ctlr *c)
1926 {
1927         uint u, u0;
1928
1929         u = u0 = yukpcicfgr32(c, Pciphy);
1930         u &= ~phypwr[c->portno];
1931         if(c->type == Yukxl && c->rev > 1)
1932                 u |= coma[c->portno];
1933         if(u != u0 || 1){
1934                 c->reg8[Tstctl1] = Tstwen;
1935                 yukpcicfgw32(c, Pciphy, u);
1936                 c->reg8[Tstctl1] = Tstwdis;
1937         }
1938         if(c->type == Yukfe)
1939                 c->reg8[Phyctl] = Aneen;
1940         else if(c->flag & Fapwr)
1941                 macwrite32(c, Phy, Gphyrstclr);
1942 }
1943
1944 static void
1945 phyinit(Ctlr *c)
1946 {
1947         uint u;
1948
1949         if((c->feat & Fnewphy) == 0){
1950                 u = phyread(c, Phyextctl);
1951                 u &= ~0xf70;                    /* clear downshift counters */
1952                 u |= 0x7<<4;                    /* mac tx clock = 25mhz */
1953                 if(c->type == Yukec)
1954                         u |= 2*Dnmstr | Dnslv;
1955                 else
1956                         u |= Dnslv;
1957                 phywrite(c, Phyextctl, u);
1958         }
1959         u = phyread(c, Phyphy);
1960
1961         /* questionable value */
1962         if(c->feat & Ffiber)
1963                 u &= ~Ppmdix;
1964         else if(c->feat & Fgbe){
1965                 u &= ~Pped;
1966                 u |= Ppmdixa;
1967                 if(c->flag & Fnewphy){
1968                 //      u &= ~(7<<12);
1969                 //      u |= 2*(1<<12) | 1<<11; /* like 2*Dnmstr | Dnslv */
1970                         u |= 2*(1<<9) | 1<<11;
1971                 }
1972         }else{
1973                 u |= Ppmdixa >> 1;              /* why the shift? */
1974                 if(c->type == Yukfep && c->rev == 0){
1975                 }
1976         }
1977
1978         phywrite(c, Phyphy, u);
1979         /* copper/fiber specific stuff gmacwrite(c, Ctl, 0); */
1980         gmacwrite(c, Ctl, 0);
1981         if(c->feat & Fgbe)
1982                 if(c->feat & Ffiber)
1983                         phywrite(c, Gbectl, Gbexf | Gbexh);
1984                 else
1985                         phywrite(c, Gbectl, Gbef | Gbeh);
1986         phywrite(c, Phyana, Anall);
1987         phywrite(c, Phyctl, Phyrst | Anerst | Aneen);
1988         /* chip specific stuff? */
1989         if (c->type == Yukfep){
1990                 u = phyread(c, Phyphy) | Ppnpe;
1991                 u &= ~(Ppengy | Ppscrdis);
1992                 phywrite(c, Phyphy, u);
1993 //              phywrite(c, 0x16, 0x0b54);              /* write to fe_led_par */
1994
1995                 /* yukfep and rev 0: apply workaround for integrated resistor calibration */
1996                 phywrite(c, Phypadr, 17);
1997                 phywrite(c, 0x1e, 0x3f60);
1998         }
1999         phywrite(c, Phyintm, Anok | Anerr | Lsc);
2000         dprint("phyid %.4ux step %.4ux\n", phyread(c, 2), phyread(c, 3));
2001 }
2002
2003 static int
2004 identify(Ctlr *c)
2005 {
2006         char t;
2007
2008         pcicfgw32(c->p, Pciclk, 0);
2009         c->reg16[Ctst] = Swclr;
2010
2011         c->type = c->reg8[Chip] - 0xb3;
2012         c->rev = c->reg8[Maccfg]>>4 & 0xf;
2013         if(c->type >= Nyuk)
2014                 return -1;
2015         if(idtab[c->type].okrev != 0xff)
2016         if(c->rev != idtab[c->type].okrev)
2017                 return -1;
2018         c->feat |= idtab[c->type].feat;
2019
2020         t = c->reg8[Pmd];
2021         if(t == 'L' || t == 'S' || t == 'P')
2022                 c->feat |= Ffiber;
2023         c->portno = 0;
2024         /* check second port ... whatever */
2025         return 0;
2026 }
2027
2028 static uint
2029 µ2clk(Ctlr *c, int µs)
2030 {
2031         return idtab[c->type].mhz * µs;
2032 }
2033
2034 static void
2035 gmacsetea(Ctlr *c, uint r)
2036 {
2037         uchar *ra;
2038         int i;
2039
2040         ra = c->ra;
2041         for(i = 0; i < Eaddrlen; i += 2)
2042                 gmacwrite(c, r + i, ra[i + 0] | ra[i + 1]<<8);
2043 }
2044
2045 static int
2046 reset(Ctlr *c)
2047 {
2048         uint i, j;
2049         Block *b;
2050
2051         identify(c);
2052
2053         if(c->type == Yukex)
2054                 c->reg16[Asfcs/2] &= ~(Asfbrrst | Asfcpurst | Asfucrst);
2055         else
2056                 c->reg8[Asfcs] = Asfrst;
2057         c->reg16[Ctst] = Asfdis;
2058
2059         c->reg16[Ctst] = Swrst;
2060         c->reg16[Ctst] = Swclr;
2061
2062         c->reg8[Tstctl1] = Tstwen;
2063         pcicfgw16(c->p, PciPSR, pcicfgr16(c->p, PciPSR) | 0xf100);
2064         c->reg16[Ctst] = Mstrclr;
2065         /* fixup pcie extended error goes here */
2066
2067         c->reg8[Pwrctl] = Vauxen | Vccen | Vauxoff | Vccon;
2068         c->reg[Clkctl] = Clkdivdis;
2069         if(c->type == Yukxl && c->rev > 1)
2070                 c->reg8[Clkgate] = ~Link2inactive;
2071         else
2072                 c->reg8[Clkgate] = 0;
2073         if(c->flag & Fapwr){
2074                 pcicfgw32(c->p, Pciclk, 0);
2075                 pcicfgw32(c->p, Pciasp, pcicfgr32(c->p, Pciasp) & Aspmsk);
2076                 pcicfgw32(c->p, Pcistate, pcicfgr32(c->p, Pcistate) & Vmain);
2077                 pcicfgw32(c->p, Pcicf1, 0);
2078                 c->reg[Gpio] |= Norace;
2079                 print("yuk2: advanced power %.8ux\n", c->reg[Gpio]);
2080         }
2081         c->reg8[Tstctl1] = Tstwdis;
2082
2083         for(i = 0; i < c->nports; i++){
2084                 macwrite8(c, Linkctl, Linkrst);
2085                 macwrite8(c, Linkctl, Linkclr);
2086                 if(c->type == Yukex || c->type == Yuksup)
2087                         macwrite16(c, Mac, Nomacsec | Nortx);
2088         }
2089
2090         c->reg[Dpolltm] = Pollstop;
2091
2092         for(i = 0; i < c->nports; i++)
2093                 macwrite8(c, Txactl, Txaclr);
2094         for(i = 0; i < c->nports; i++){
2095                 c->reg8[i*64 + Rictl] = Riclr;
2096                 for(j = 0; j < 12; j++)
2097                         c->reg8[i*64 + Rib + j] = 36;   /* qword times */
2098         }
2099
2100         c->reg[Hwem] = Hdflt;
2101         macwrite8(c, Irqm, 0);
2102         for(i = 0; i < 4; i++)
2103                 gmacwrite(c, Mchash + 2*i, 0);
2104         gmacwrite(c, Rxctl, Ufilter | Mfilter | Rmcrc);
2105
2106         for(i = 0; i < nelem(c->tbring); i++)
2107                 if(b = c->tbring[i]){
2108                         c->tbring[i] = nil;
2109                         freeb(b);
2110                 }
2111         for(i = 0; i < nelem(c->rbring); i++)
2112                 if(b = c->rbring[i]){
2113                         c->rbring[i] = nil;
2114                         freeb(b);
2115                 }
2116
2117         memset(c->tbring, 0, sizeof c->tbring[0] * nelem(c->tbring));
2118         memset(c->rbring, 0, sizeof c->rbring[0] * nelem(c->rbring));
2119         memset(c->tx.r, 0, sizeof c->tx.r[0] * c->tx.cnt);
2120         memset(c->rx.r, 0, sizeof c->rx.r[0] * c->rx.cnt);
2121         memset(c->status.r, 0, sizeof c->status.r[0] * c->status.cnt);
2122         c->reg[Statctl] = Statrst;
2123         c->reg[Statctl] = Statclr;
2124         c->reg[Stataddr + 0] = Pciwaddrl(c->status.r);
2125         c->reg[Stataddr + 4] = Pciwaddrh(c->status.r);
2126         c->reg16[Stattl] = c->status.m;
2127         c->reg16[Statth] = 10;
2128         c->reg8[Statwm] = 16;
2129         if(c->type == Yukxl && c->rev == 0)
2130                 c->reg8[Statiwm] = 4;
2131         else
2132                 c->reg8[Statiwm] = 4; //16;
2133
2134         /* set transmit, isr,  level timers */
2135         c->reg[Tsti] = µ2clk(c, 1000);
2136         c->reg[Titi] = µ2clk(c, 20);
2137         c->reg[Tlti] = µ2clk(c, 100);
2138
2139         c->reg[Statctl] = Staton;
2140
2141         c->reg8[Tstc] = Tstart;
2142         c->reg8[Tltc] = Tstart;
2143         c->reg8[Titc] = Tstart;
2144
2145         return 0;
2146 }
2147
2148 static void
2149 macinit(Ctlr *c)
2150 {
2151         uint r, i;
2152
2153         r = macread32(c, Phy) & ~(Gphyrst | Gphyrstclr);
2154         macwrite32(c, Phy, r | Gphyrst);
2155         macwrite32(c, Phy, r | Gphyrstclr);
2156         /* macwrite32(c, Mac, Macrst); ? */
2157         macwrite32(c, Mac, Macrstclr);
2158
2159         if(c->type == Yukxl && c->rev == 0 && c->portno == 1){
2160         }
2161
2162         macread8(c, Irq);
2163         macwrite8(c, Irqm, Txurun);
2164
2165         phypower(c);
2166         phyinit(c);
2167
2168         gmacwrite(c, Phyaddr, (r = gmacread(c, Phyaddr)) | Mibclear);
2169         for(i = 0; i < nelem(stattab); i++)
2170                 gmacread32(c, Stats + stattab[i].offset/4);
2171         gmacwrite(c, Phyaddr, r);
2172
2173         gmacwrite(c, Txctl, 4<<10);     /* collision distance */
2174         gmacwrite(c, Txflow, 0xffff);   /* flow control */
2175         gmacwrite(c, Txparm, 3<<14 | 0xb<<9 | 0x1c<<4 | 4);
2176         gmacwrite(c, Rxctl, Ufilter | Mfilter | Rmcrc);
2177         gmacwrite(c, Serctl, 0x04<<11 /* blind */ | Jumboen | 0x1e /* ipig */);
2178
2179         gmacsetea(c, Ea0);
2180         gmacsetea(c, Ea1);
2181
2182         gmacwrite(c, Txmask, 0);
2183         gmacwrite(c, Rxmask, 0);
2184         gmacwrite(c, Trmask, 0);
2185
2186         macwrite32(c, Gfrxctl, Gfrstclr);
2187         r = Gfon | Gffon;
2188         if(c->type == Yukex || c->type == Yukfep)
2189                 r |= Gfroon;
2190         macwrite32(c, Gfrxctl, r);
2191         if(c->type == Yukxl)
2192                 macwrite32(c, Grxfm, 0);
2193         else
2194                 macwrite32(c, Grxfm, Ferror);
2195         if(c->type == Yukfep && c->rev == 0)
2196                 macwrite32(c, Grxft, 0x178);
2197         else
2198                 macwrite32(c, Grxft, 0xb);
2199
2200         macwrite32(c, Gmfctl, Gmfclr);  /* clear reset */
2201         macwrite32(c, Gmfctl, Gmfon);   /* on */
2202
2203         raminit(c);
2204         if(c->type == Yukfep && c->rev == 0)
2205                 c->reg[Gmfea] = c->reg[Gmfea] & ~3;
2206
2207         c->rxinit = 0;
2208         c->txinit = 0;
2209 }
2210
2211 static void*
2212 slice(void **v, uint r, uint sz)
2213 {
2214         uintptr a;
2215
2216         a = (uintptr)*v;
2217         a = ROUNDUP(a, r);
2218         *v = (void*)(a + sz);
2219         return (void*)a;
2220 }
2221
2222 static void
2223 setupr(Sring *r, uint cnt)
2224 {
2225         r->rp = 0;
2226         r->wp = 0;
2227         r->cnt = cnt;
2228         r->m = cnt - 1;
2229 }
2230
2231 static int
2232 setup(Ctlr *c)
2233 {
2234         uint n;
2235         void *v, *mem;
2236         Pcidev *p;
2237
2238         p = c->p;
2239         c->io = p->mem[0].bar&~0xf;
2240         mem = vmap(c->io, p->mem[0].size);
2241         if(mem == nil){
2242                 print("yuk: cant map %#p\n", c->io);
2243                 return -1;
2244         }
2245         c->p = p;
2246         c->reg = (uint*)mem;
2247         c->reg8 = (uchar*)mem;
2248         c->reg16 = (ushort*)mem;
2249         if(memcmp(c->ra, nilea, sizeof c->ra) == 0)
2250                 memmove(c->ra, c->reg8 + Macadr + 8*c->portno, Eaddrlen);
2251
2252         setupr(&c->status, Sringcnt);
2253         setupr(&c->tx, Tringcnt);
2254         setupr(&c->rx, Rringcnt);
2255
2256         n = sizeof c->status.r[0] * (c->status.cnt + c->tx.cnt + c->rx.cnt);
2257         n += 16*4096*2;                         /* rounding slop */
2258         c->alloc = xspanalloc(n, 16*4096, 0);   /* unknown alignment constraints */
2259         memset(c->alloc, 0, n);
2260
2261         v = c->alloc;
2262         c->status.r = slice(&v, 16*4096, sizeof c->status.r[0] * c->status.cnt);
2263         c->tx.r = slice(&v, 16*4096, sizeof c->tx.r[0] * c->tx.cnt);
2264         c->rx.r = slice(&v, 16*4096, sizeof c->rx.r[0] * c->rx.cnt);
2265
2266         c->nports = 1;                          /* BOTCH */
2267         pcisetbme(p);
2268         if(reset(c)){
2269                 print("yuk: cant reset\n");
2270                 pciclrbme(p);
2271                 free(c->alloc);
2272                 vunmap(mem, p->mem[0].size);
2273                 return -1;
2274         }
2275         macinit(c);
2276         return 0;
2277 }
2278
2279 static void
2280 shutdown(Ether *e)
2281 {
2282         Ctlr *c;
2283         Pcidev *p;
2284
2285         c = e->ctlr;
2286
2287         reset(c);
2288         if(0){
2289                 p = c->p;
2290                 vunmap(c->reg, p->mem[0].size);
2291                 free(c->alloc);
2292         }
2293 }
2294
2295 static void
2296 scan(void)
2297 {
2298         int i;
2299         Pcidev *p;
2300         Ctlr *c;
2301
2302         for(p = nil; p = pcimatch(p, 0, 0); ){
2303                 for(i = 0; i < nelem(vtab); i++)
2304                         if(vtab[i].vid == p->vid)
2305                         if(vtab[i].did == p->did)
2306                                 break;
2307                 if(i == nelem(vtab))
2308                         continue;
2309                 if(nctlr == nelem(ctlrtab)){
2310                         print("yuk: too many controllers\n");
2311                         return;
2312                 }
2313                 c = malloc(sizeof *c);
2314                 c->p = p;
2315                 c->qno = nctlr;
2316                 rbtab[c->qno].k = &c->rxmit;
2317                 c->rbsz = vtab[i].mtu;
2318                 ctlrtab[nctlr++] = c;
2319         }
2320 }
2321
2322 static int
2323 pnp(Ether *e)
2324 {
2325         int i;
2326         Ctlr *c;
2327
2328         if(nctlr == 0)
2329                 scan();
2330         for(i = 0;; i++){
2331                 if(i == nctlr)
2332                         return -1;
2333                 c = ctlrtab[i];
2334                 if(c == nil || c->flag&Fprobe)
2335                         continue;
2336                 if(e->port != 0 && e->port != (ulong)c->reg)
2337                         continue;
2338                 c->flag |= Fprobe;
2339                 if(setup(c) != 0)
2340                         continue;
2341                 break;
2342         }
2343         e->ctlr = c;
2344         e->port = c->io;
2345         e->irq = c->p->intl;
2346         e->tbdf = c->p->tbdf;
2347         e->mbps = 1000;
2348         e->maxmtu = c->rbsz;
2349         memmove(e->ea, c->ra, Eaddrlen);
2350         e->arg = e;
2351         e->attach = attach;
2352         e->ctl = ctl;
2353         e->ifstat = ifstat;
2354         e->interrupt = interrupt;
2355         e->multicast = multicast;
2356         e->promiscuous = promiscuous;
2357         e->shutdown = shutdown;
2358         e->transmit = nil;
2359
2360         return 0;
2361 }
2362
2363 void
2364 etheryuklink(void)
2365 {
2366         addethercard("yuk", pnp);
2367 }