]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc/ether8169.c
ether8169: support rtl8402 variant
[plan9front.git] / sys / src / 9 / pc / ether8169.c
1 /*
2  * Realtek RTL8110S/8169S Gigabit Ethernet Controllers.
3  * Mostly there. There are some magic register values used
4  * which are not described in any datasheet or driver but seem
5  * to be necessary.
6  * No tuning has been done. Only tested on an RTL8110S, there
7  * are slight differences between the chips in the series so some
8  * tweaks may be needed.
9  */
10 #include "u.h"
11 #include "../port/lib.h"
12 #include "mem.h"
13 #include "dat.h"
14 #include "fns.h"
15 #include "io.h"
16 #include "../port/pci.h"
17 #include "../port/error.h"
18 #include "../port/netif.h"
19 #include "../port/etherif.h"
20 #include "../port/ethermii.h"
21
22 enum {                                  /* registers */
23         Idr0            = 0x00,         /* MAC address */
24         Mar0            = 0x08,         /* Multicast address */
25         Dtccr           = 0x10,         /* Dump Tally Counter Command */
26         Tnpds           = 0x20,         /* Transmit Normal Priority Descriptors */
27         Thpds           = 0x28,         /* Transmit High Priority Descriptors */
28         Flash           = 0x30,         /* Flash Memory Read/Write */
29         Erbcr           = 0x34,         /* Early Receive Byte Count */
30         Ersr            = 0x36,         /* Early Receive Status */
31         Cr              = 0x37,         /* Command Register */
32         Tppoll          = 0x38,         /* Transmit Priority Polling */
33         Imr             = 0x3C,         /* Interrupt Mask */
34         Isr             = 0x3E,         /* Interrupt Status */
35         Tcr             = 0x40,         /* Transmit Configuration */
36         Rcr             = 0x44,         /* Receive Configuration */
37         Tctr            = 0x48,         /* Timer Count */
38         Mpc             = 0x4C,         /* Missed Packet Counter */
39         Cr9346          = 0x50,         /* 9346 Command Register */
40         Config0         = 0x51,         /* Configuration Register 0 */
41         Config1         = 0x52,         /* Configuration Register 1 */
42         Config2         = 0x53,         /* Configuration Register 2 */
43         Config3         = 0x54,         /* Configuration Register 3 */
44         Config4         = 0x55,         /* Configuration Register 4 */
45         Config5         = 0x56,         /* Configuration Register 5 */
46         Timerint        = 0x58,         /* Timer Interrupt */
47         Mulint          = 0x5C,         /* Multiple Interrupt Select */
48         Phyar           = 0x60,         /* PHY Access */
49         Tbicsr0         = 0x64,         /* TBI Control and Status */
50         Tbianar         = 0x68,         /* TBI Auto-Negotiation Advertisment */
51         Tbilpar         = 0x6A,         /* TBI Auto-Negotiation Link Partner */
52         Phystatus       = 0x6C,         /* PHY Status */
53         Pmch            = 0x6F,         /* power management */
54         Ldps            = 0x82,         /* link down power saving */
55
56         Rms             = 0xDA,         /* Receive Packet Maximum Size */
57         Cplusc          = 0xE0,         /* C+ Command */
58         Coal            = 0xE2,         /* Interrupt Mitigation (Coalesce) */
59         Rdsar           = 0xE4,         /* Receive Descriptor Start Address */
60         Etx             = 0xEC,         /* Early Transmit Threshold */
61 };
62
63 enum {                                  /* Dtccr */
64         Cmd             = 0x00000008,   /* Command */
65 };
66
67 enum {                                  /* Cr */
68         Te              = 0x04,         /* Transmitter Enable */
69         Re              = 0x08,         /* Receiver Enable */
70         Rst             = 0x10,         /* Software Reset */
71 };
72
73 enum {                                  /* Tppoll */
74         Fswint          = 0x01,         /* Forced Software Interrupt */
75         Npq             = 0x40,         /* Normal Priority Queue polling */
76         Hpq             = 0x80,         /* High Priority Queue polling */
77 };
78
79 enum {                                  /* Imr/Isr */
80         Rok             = 0x0001,       /* Receive OK */
81         Rer             = 0x0002,       /* Receive Error */
82         Tok             = 0x0004,       /* Transmit OK */
83         Ter             = 0x0008,       /* Transmit Error */
84         Rdu             = 0x0010,       /* Receive Descriptor Unavailable */
85         Punlc           = 0x0020,       /* Packet Underrun or Link Change */
86         Fovw            = 0x0040,       /* Receive FIFO Overflow */
87         Tdu             = 0x0080,       /* Transmit Descriptor Unavailable */
88         Swint           = 0x0100,       /* Software Interrupt */
89         Timeout         = 0x4000,       /* Timer */
90         Serr            = 0x8000,       /* System Error */
91 };
92
93 enum {                                  /* Tcr */
94         MtxdmaSHIFT     = 8,            /* Max. DMA Burst Size */
95         MtxdmaMASK      = 0x00000700,
96         Mtxdmaunlimited = 0x00000700,
97         Acrc            = 0x00010000,   /* Append CRC (not) */
98         Lbk0            = 0x00020000,   /* Loopback Test 0 */
99         Lbk1            = 0x00040000,   /* Loopback Test 1 */
100         Ifg2            = 0x00080000,   /* Interframe Gap 2 */
101         HwveridSHIFT    = 23,           /* Hardware Version ID */
102         HwveridMASK     = 0x7C800000,
103         Macv01          = 0x00000000,   /* RTL8169 */
104         Macv02          = 0x00800000,   /* RTL8169S/8110S */
105         Macv03          = 0x04000000,   /* RTL8169S/8110S */
106         Macv04          = 0x10000000,   /* RTL8169SB/8110SB */
107         Macv05          = 0x18000000,   /* RTL8169SC/8110SC */
108         Macv07          = 0x24800000,   /* RTL8102e */
109         Macv07a         = 0x34800000,   /* RTL8102e */
110         Macv11          = 0x30000000,   /* RTL8168B/8111B */
111         Macv12          = 0x38000000,   /* RTL8169B/8111B */
112         Macv12a         = 0x3c000000,   /* RTL8169C/8111C */
113         Macv13          = 0x34000000,   /* RTL8101E */
114         Macv14          = 0x30800000,   /* RTL8100E */
115         Macv15          = 0x38800000,   /* RTL8100E */
116 //      Macv19          = 0x3c000000,   /* dup Macv12a: RTL8111c-gr */
117         Macv25          = 0x28000000,   /* RTL8168D */
118         Macv26          = 0x48000000,   /* RTL8111/8168B */
119         Macv27          = 0x2c800000,   /* RTL8111e */
120         Macv28          = 0x2c000000,   /* RTL8111/8168B */
121         Macv29          = 0x40800000,   /* RTL8101/8102E */
122         Macv30          = 0x24000000,   /* RTL8101E? (untested) */
123         Macv38          = 0x44000000,   /* RTL8402 */
124         Macv39          = 0x44800000,   /* RTL8106E */
125         Macv40          = 0x4c000000,   /* RTL8168G */
126         Macv42          = 0x50800000,   /* RTL8168GU */
127         Macv44          = 0x5c800000,   /* RTL8411B */
128         Macv45          = 0x54000000,   /* RTL8111HN */
129
130         Ifg0            = 0x01000000,   /* Interframe Gap 0 */
131         Ifg1            = 0x02000000,   /* Interframe Gap 1 */
132 };
133
134 enum {                                  /* Rcr */
135         Aap             = 0x00000001,   /* Accept All Packets */
136         Apm             = 0x00000002,   /* Accept Physical Match */
137         Am              = 0x00000004,   /* Accept Multicast */
138         Ab              = 0x00000008,   /* Accept Broadcast */
139         Ar              = 0x00000010,   /* Accept Runt */
140         Aer             = 0x00000020,   /* Accept Error */
141         Sel9356         = 0x00000040,   /* 9356 EEPROM used */
142         MrxdmaSHIFT     = 8,            /* Max. DMA Burst Size */
143         MrxdmaMASK      = 0x00000700,
144         Mrxdmaunlimited = 0x00000700,
145         RxfthSHIFT      = 13,           /* Receive Buffer Length */
146         RxfthMASK       = 0x0000E000,
147         Rxfth256        = 0x00008000,
148         Rxfthnone       = 0x0000E000,
149         Rer8            = 0x00010000,   /* Accept Error Packets > 8 bytes */
150         MulERINT        = 0x01000000,   /* Multiple Early Interrupt Select */
151 };
152
153 enum {                                  /* Cr9346 */
154         Eedo            = 0x01,         /* */
155         Eedi            = 0x02,         /* */
156         Eesk            = 0x04,         /* */
157         Eecs            = 0x08,         /* */
158         Eem0            = 0x40,         /* Operating Mode */
159         Eem1            = 0x80,
160 };
161
162 enum {                                  /* Phyar */
163         DataMASK        = 0x0000FFFF,   /* 16-bit GMII/MII Register Data */
164         DataSHIFT       = 0,
165         RegaddrMASK     = 0x001F0000,   /* 5-bit GMII/MII Register Address */
166         RegaddrSHIFT    = 16,
167         Flag            = 0x80000000,   /* */
168 };
169
170 enum {                                  /* Phystatus */
171         Fd              = 0x01,         /* Full Duplex */
172         Linksts         = 0x02,         /* Link Status */
173         Speed10         = 0x04,         /* */
174         Speed100        = 0x08,         /* */
175         Speed1000       = 0x10,         /* */
176         Rxflow          = 0x20,         /* */
177         Txflow          = 0x40,         /* */
178         Entbi           = 0x80,         /* */
179 };
180
181 enum {                                  /* Cplusc */
182         Txenb           = 0x0001,       /* enable C+ transmit mode */
183         Rxenb           = 0x0002,       /* enable C+ receive mode */
184         Mulrw           = 0x0008,       /* PCI Multiple R/W Enable */
185         Dac             = 0x0010,       /* PCI Dual Address Cycle Enable */
186         Rxchksum        = 0x0020,       /* Receive Checksum Offload Enable */
187         Rxvlan          = 0x0040,       /* Receive VLAN De-tagging Enable */
188         Macstatdis      = 0x0080,       /* Disable Mac Statistics */
189         Endian          = 0x0200,       /* Endian Mode */
190 };
191
192 typedef struct D D;                     /* Transmit/Receive Descriptor */
193 struct D {
194         u32int  control;
195         u32int  vlan;
196         u32int  addrlo;
197         u32int  addrhi;
198 };
199
200 enum {                                  /* Transmit Descriptor control */
201         TxflMASK        = 0x0000FFFF,   /* Transmit Frame Length */
202         TxflSHIFT       = 0,
203         Tcps            = 0x00010000,   /* TCP Checksum Offload */
204         Udpcs           = 0x00020000,   /* UDP Checksum Offload */
205         Ipcs            = 0x00040000,   /* IP Checksum Offload */
206         Lgsen           = 0x08000000,   /* TSO; WARNING: contains lark's vomit */
207 };
208
209 enum {                                  /* Receive Descriptor control */
210         RxflMASK        = 0x00001FFF,   /* Receive Frame Length */
211         Tcpf            = 0x00004000,   /* TCP Checksum Failure */
212         Udpf            = 0x00008000,   /* UDP Checksum Failure */
213         Ipf             = 0x00010000,   /* IP Checksum Failure */
214         Pid0            = 0x00020000,   /* Protocol ID0 */
215         Pid1            = 0x00040000,   /* Protocol ID1 */
216         Crce            = 0x00080000,   /* CRC Error */
217         Runt            = 0x00100000,   /* Runt Packet */
218         Res             = 0x00200000,   /* Receive Error Summary */
219         Rwt             = 0x00400000,   /* Receive Watchdog Timer Expired */
220         Fovf            = 0x00800000,   /* FIFO Overflow */
221         Bovf            = 0x01000000,   /* Buffer Overflow */
222         Bar             = 0x02000000,   /* Broadcast Address Received */
223         Pam             = 0x04000000,   /* Physical Address Matched */
224         Mar             = 0x08000000,   /* Multicast Address Received */
225 };
226
227 enum {                                  /* General Descriptor control */
228         Ls              = 0x10000000,   /* Last Segment Descriptor */
229         Fs              = 0x20000000,   /* First Segment Descriptor */
230         Eor             = 0x40000000,   /* End of Descriptor Ring */
231         Own             = 0x80000000,   /* Ownership */
232 };
233
234 /*
235  */
236 enum {                                  /* Ring sizes  (<= 1024) */
237         Ntd             = 64,           /* Transmit Ring */
238         Nrd             = 256,          /* Receive Ring */
239
240         Mtu             = ETHERMAXTU,
241         Mps             = ROUNDUP(ETHERMAXTU+4, 128),
242 };
243
244 typedef struct Dtcc Dtcc;
245 struct Dtcc {
246         u64int  txok;
247         u64int  rxok;
248         u64int  txer;
249         u32int  rxer;
250         u16int  misspkt;
251         u16int  fae;
252         u32int  tx1col;
253         u32int  txmcol;
254         u64int  rxokph;
255         u64int  rxokbrd;
256         u32int  rxokmu;
257         u16int  txabt;
258         u16int  txundrn;
259 };
260
261 enum {                                          /* Variants */
262         Rtl8100e        = (0x8136<<16)|0x10EC,  /* RTL810[01]E: pci -e */
263         Rtl8169c        = (0x0116<<16)|0x16EC,  /* RTL8169C+ (USR997902) */
264         Rtl8169sc       = (0x8167<<16)|0x10EC,  /* RTL8169SC */
265         Rtl8168b        = (0x8168<<16)|0x10EC,  /* RTL8168B: pci-e */
266         Rtl8169         = (0x8169<<16)|0x10EC,  /* RTL8169 */
267 };
268
269 typedef struct Ctlr Ctlr;
270 typedef struct Ctlr {
271         Lock;
272
273         int     port;
274         Pcidev* pcidev;
275         Ctlr*   next;
276         int     active;
277
278         QLock   alock;                  /* attach */
279         int     init;                   /*  */
280         Rendez  reset;
281
282         int     pciv;                   /*  */
283         int     macv;                   /* MAC version */
284         int     phyv;                   /* PHY version */
285         int     pcie;                   /* flag: pci-express device? */
286
287         uvlong  mchash;                 /* multicast hash */
288
289         Mii*    mii;
290
291         D*      td;                     /* descriptor ring */
292         Block** tb;                     /* transmit buffers */
293         int     ntd;
294
295         int     tdh;                    /* head - producer index (host) */
296         int     tdt;                    /* tail - consumer index (NIC) */
297         int     ntq;
298
299         D*      rd;                     /* descriptor ring */
300         Block** rb;                     /* receive buffers */
301         int     nrd;
302
303         int     rdh;                    /* head - producer index (NIC) */
304         int     rdt;                    /* tail - consumer index (host) */
305         int     nrq;
306
307         int     tcr;                    /* transmit configuration register */
308         int     rcr;                    /* receive configuration register */
309         int     imr;
310
311         QLock   slock;                  /* statistics */
312         Dtcc*   dtcc;
313         uint    txdu;
314         uint    tcpf;
315         uint    udpf;
316         uint    ipf;
317         uint    fovf;
318         uint    rer;
319         uint    rdu;
320         uint    punlc;
321         uint    serr;
322         uint    fovw;
323         uint    mcast;
324         uint    frag;                   /* partial packets; rb was too small */
325 } Ctlr;
326
327 static Ctlr* rtl8169ctlrhead;
328 static Ctlr* rtl8169ctlrtail;
329
330 #define csr8r(c, r)     (inb((c)->port+(r)))
331 #define csr16r(c, r)    (ins((c)->port+(r)))
332 #define csr32r(c, r)    (inl((c)->port+(r)))
333 #define csr8w(c, r, b)  (outb((c)->port+(r), (u8int)(b)))
334 #define csr16w(c, r, w) (outs((c)->port+(r), (u16int)(w)))
335 #define csr32w(c, r, l) (outl((c)->port+(r), (u32int)(l)))
336
337 static int
338 rtl8169miimir(Mii* mii, int pa, int ra)
339 {
340         uint r;
341         int timeo;
342         Ctlr *ctlr;
343
344         if(pa != 1)
345                 return -1;
346         ctlr = mii->ctlr;
347
348         r = (ra<<16) & RegaddrMASK;
349         csr32w(ctlr, Phyar, r);
350         delay(1);
351         for(timeo = 0; timeo < 2000; timeo++){
352                 if((r = csr32r(ctlr, Phyar)) & Flag)
353                         break;
354                 microdelay(100);
355         }
356         if(!(r & Flag))
357                 return -1;
358
359         return (r & DataMASK)>>DataSHIFT;
360 }
361
362 static int
363 rtl8169miimiw(Mii* mii, int pa, int ra, int data)
364 {
365         uint r;
366         int timeo;
367         Ctlr *ctlr;
368
369         if(pa != 1)
370                 return -1;
371         ctlr = mii->ctlr;
372
373         r = Flag|((ra<<16) & RegaddrMASK)|((data<<DataSHIFT) & DataMASK);
374         csr32w(ctlr, Phyar, r);
375         delay(1);
376         for(timeo = 0; timeo < 2000; timeo++){
377                 if(!((r = csr32r(ctlr, Phyar)) & Flag))
378                         break;
379                 microdelay(100);
380         }
381         if(r & Flag)
382                 return -1;
383
384         return 0;
385 }
386
387 static void
388 rtl8169mii(Ether *edev)
389 {
390         Ctlr *ctlr = edev->ctlr;
391         MiiPhy *phy;
392
393         /*
394          * Link management.
395          */
396         ctlr->mii = smalloc(sizeof(Mii));
397         ctlr->mii->mir = rtl8169miimir;
398         ctlr->mii->miw = rtl8169miimiw;
399         ctlr->mii->ctlr = ctlr;
400
401         /*
402          * PHY wakeup
403          */
404         switch(ctlr->macv){
405         case Macv25:
406         case Macv28:
407         case Macv29:
408         case Macv30:
409                 csr8w(ctlr, Pmch, csr8r(ctlr, Pmch) | 0x80);
410                 break;
411         }
412         rtl8169miimiw(ctlr->mii, 1, 0x1f, 0);
413         rtl8169miimiw(ctlr->mii, 1, 0x0e, 0);
414
415         /*
416          * Get rev number out of Phyidr2 so can config properly.
417          * There's probably more special stuff for Macv0[234] needed here.
418          */
419         ctlr->phyv = rtl8169miimir(ctlr->mii, 1, Phyidr2) & 0x0F;
420         if(ctlr->macv == Macv02){
421                 csr8w(ctlr, Ldps, 1);                           /* magic */
422                 rtl8169miimiw(ctlr->mii, 1, 0x0B, 0x0000);      /* magic */
423         }
424         
425         if(mii(ctlr->mii, (1<<1)) == 0 || (phy = ctlr->mii->curphy) == nil){
426                 error("no phy");
427                 return;
428         }
429
430         print("#l%d: rtl8169: oui %#ux phyno %d, macv = %#8.8ux phyv = %#4.4ux\n",
431                 edev->ctlrno, phy->oui, phy->phyno, ctlr->macv, ctlr->phyv);
432
433         miireset(ctlr->mii);
434
435         microdelay(100);
436
437         miiane(ctlr->mii, ~0, ~0, ~0);
438 }
439
440 static void
441 rtl8169promiscuous(void* arg, int on)
442 {
443         Ether *edev;
444         Ctlr * ctlr;
445
446         edev = arg;
447         ctlr = edev->ctlr;
448         ilock(ctlr);
449         if(on)
450                 ctlr->rcr |= Aap;
451         else
452                 ctlr->rcr &= ~Aap;
453         csr32w(ctlr, Rcr, ctlr->rcr);
454         iunlock(ctlr);
455 }
456
457 enum {
458         /* everyone else uses 0x04c11db7, but they both produce the same crc */
459         Etherpolybe = 0x04c11db6,
460         Bytemask = (1<<8) - 1,
461 };
462
463 static ulong
464 ethercrcbe(uchar *addr, long len)
465 {
466         int i, j;
467         ulong c, crc, carry;
468
469         crc = ~0UL;
470         for (i = 0; i < len; i++) {
471                 c = addr[i];
472                 for (j = 0; j < 8; j++) {
473                         carry = ((crc & (1UL << 31))? 1: 0) ^ (c & 1);
474                         crc <<= 1;
475                         c >>= 1;
476                         if (carry)
477                                 crc = (crc ^ Etherpolybe) | carry;
478                 }
479         }
480         return crc;
481 }
482
483 static ulong
484 swabl(ulong l)
485 {
486         return l>>24 | (l>>8) & (Bytemask<<8) |
487                 (l<<8) & (Bytemask<<16) | l<<24;
488 }
489
490 static void
491 rtl8169multicast(void* ether, uchar *eaddr, int add)
492 {
493         Ether *edev;
494         Ctlr *ctlr;
495
496         if (!add)
497                 return; /* ok to keep receiving on old mcast addrs */
498
499         edev = ether;
500         ctlr = edev->ctlr;
501         ilock(ctlr);
502
503         ctlr->mchash |= 1ULL << (ethercrcbe(eaddr, Eaddrlen) >> 26);
504
505         ctlr->rcr |= Am;
506         csr32w(ctlr, Rcr, ctlr->rcr);
507
508         /* pci-e variants reverse the order of the hash byte registers */
509         if (ctlr->pcie) {
510                 csr32w(ctlr, Mar0,   swabl(ctlr->mchash>>32));
511                 csr32w(ctlr, Mar0+4, swabl(ctlr->mchash));
512         } else {
513                 csr32w(ctlr, Mar0,   ctlr->mchash);
514                 csr32w(ctlr, Mar0+4, ctlr->mchash>>32);
515         }
516
517         iunlock(ctlr);
518 }
519
520 static long
521 rtl8169ifstat(Ether* edev, void* a, long n, ulong offset)
522 {
523         char *p;
524         Ctlr *ctlr;
525         Dtcc *dtcc;
526         int i, l, r, timeo;
527
528         p = smalloc(READSTR);
529
530         ctlr = edev->ctlr;
531         qlock(&ctlr->slock);
532
533         if(waserror()){
534                 qunlock(&ctlr->slock);
535                 free(p);
536                 nexterror();
537         }
538
539         csr32w(ctlr, Dtccr+4, 0);
540         csr32w(ctlr, Dtccr, PCIWADDR(ctlr->dtcc)|Cmd);
541         for(timeo = 0; timeo < 1000; timeo++){
542                 if(!(csr32r(ctlr, Dtccr) & Cmd))
543                         break;
544                 delay(1);
545         }
546         if(csr32r(ctlr, Dtccr) & Cmd)
547                 error(Eio);
548         dtcc = ctlr->dtcc;
549
550         edev->oerrs = dtcc->txer;
551         edev->crcs = dtcc->rxer;
552         edev->frames = dtcc->fae;
553         edev->buffs = dtcc->misspkt;
554         edev->overflows = ctlr->txdu+ctlr->rdu;
555
556         if(n == 0){
557                 qunlock(&ctlr->slock);
558                 poperror();
559                 free(p);
560                 return 0;
561         }
562
563         l = snprint(p, READSTR, "TxOk: %llud\n", dtcc->txok);
564         l += snprint(p+l, READSTR-l, "RxOk: %llud\n", dtcc->rxok);
565         l += snprint(p+l, READSTR-l, "TxEr: %llud\n", dtcc->txer);
566         l += snprint(p+l, READSTR-l, "RxEr: %ud\n", dtcc->rxer);
567         l += snprint(p+l, READSTR-l, "MissPkt: %ud\n", dtcc->misspkt);
568         l += snprint(p+l, READSTR-l, "FAE: %ud\n", dtcc->fae);
569         l += snprint(p+l, READSTR-l, "Tx1Col: %ud\n", dtcc->tx1col);
570         l += snprint(p+l, READSTR-l, "TxMCol: %ud\n", dtcc->txmcol);
571         l += snprint(p+l, READSTR-l, "RxOkPh: %llud\n", dtcc->rxokph);
572         l += snprint(p+l, READSTR-l, "RxOkBrd: %llud\n", dtcc->rxokbrd);
573         l += snprint(p+l, READSTR-l, "RxOkMu: %ud\n", dtcc->rxokmu);
574         l += snprint(p+l, READSTR-l, "TxAbt: %ud\n", dtcc->txabt);
575         l += snprint(p+l, READSTR-l, "TxUndrn: %ud\n", dtcc->txundrn);
576
577         l += snprint(p+l, READSTR-l, "serr: %ud\n", ctlr->serr);
578         l += snprint(p+l, READSTR-l, "fovw: %ud\n", ctlr->fovw);
579
580         l += snprint(p+l, READSTR-l, "txdu: %ud\n", ctlr->txdu);
581         l += snprint(p+l, READSTR-l, "tcpf: %ud\n", ctlr->tcpf);
582         l += snprint(p+l, READSTR-l, "udpf: %ud\n", ctlr->udpf);
583         l += snprint(p+l, READSTR-l, "ipf: %ud\n", ctlr->ipf);
584         l += snprint(p+l, READSTR-l, "fovf: %ud\n", ctlr->fovf);
585         l += snprint(p+l, READSTR-l, "rer: %ud\n", ctlr->rer);
586         l += snprint(p+l, READSTR-l, "rdu: %ud\n", ctlr->rdu);
587         l += snprint(p+l, READSTR-l, "punlc: %ud\n", ctlr->punlc);
588
589         l += snprint(p+l, READSTR-l, "tcr: %#8.8ux\n", ctlr->tcr);
590         l += snprint(p+l, READSTR-l, "rcr: %#8.8ux\n", ctlr->rcr);
591         l += snprint(p+l, READSTR-l, "multicast: %ud\n", ctlr->mcast);
592
593         if(ctlr->mii != nil && ctlr->mii->curphy != nil){
594                 l += snprint(p+l, READSTR-l, "phy:   ");
595                 for(i = 0; i < NMiiPhyr; i++){
596                         if(i && ((i & 0x07) == 0))
597                                 l += snprint(p+l, READSTR-l, "\n       ");
598                         r = miimir(ctlr->mii, i);
599                         l += snprint(p+l, READSTR-l, " %4.4ux", r);
600                 }
601                 snprint(p+l, READSTR-l, "\n");
602         }
603
604         n = readstr(offset, a, n, p);
605
606         qunlock(&ctlr->slock);
607         poperror();
608         free(p);
609
610         return n;
611 }
612
613 static void
614 rtl8169halt(Ctlr* ctlr)
615 {
616         csr8w(ctlr, Cr, 0);
617
618         ctlr->imr = 0;
619         csr16w(ctlr, Imr, 0);
620         csr16w(ctlr, Isr, ~0);
621 }
622
623 static int
624 rtl8169reset(Ctlr* ctlr)
625 {
626         u32int r;
627         int timeo;
628
629         /*
630          * Soft reset the controller.
631          */
632         csr8w(ctlr, Cr, Rst);
633         for(r = timeo = 0; timeo < 1000; timeo++){
634                 r = csr8r(ctlr, Cr);
635                 if(!(r & Rst))
636                         break;
637                 delay(1);
638         }
639         rtl8169halt(ctlr);
640
641         if(r & Rst)
642                 return -1;
643         return 0;
644 }
645
646 static void
647 rtl8169replenish(Ctlr* ctlr)
648 {
649         D *d;
650         int x;
651         Block *bp;
652         u64int pa;
653
654         x = ctlr->rdt;
655         while(NEXT(x, ctlr->nrd) != ctlr->rdh){
656                 bp = iallocb(Mps);
657                 if(bp == nil){
658                         iprint("rtl8169: no available buffers\n");
659                         break;
660                 }
661                 ctlr->rb[x] = bp;
662                 ctlr->nrq++;
663                 pa = PCIWADDR(bp->rp);
664                 d = &ctlr->rd[x];
665                 d->addrlo = pa;
666                 d->addrhi = pa >> 32;
667                 coherence();
668                 d->control = (d->control & Eor) | Own | BALLOC(bp);
669                 x = NEXT(x, ctlr->nrd);
670                 ctlr->rdt = x;
671         }
672 }
673
674 static void
675 rtl8169init(Ether* edev)
676 {
677         int i;
678         u32int r;
679         Block *bp;
680         Ctlr *ctlr;
681         u64int pa;
682         u16int cplusc;
683
684         ctlr = edev->ctlr;
685         ilock(ctlr);
686         if(rtl8169reset(ctlr) < 0){
687                 iunlock(ctlr);
688                 error("reset failed");
689         }
690
691         memset(ctlr->td, 0, sizeof(D)*ctlr->ntd);
692         ctlr->tdh = ctlr->tdt = ctlr->ntq = 0;
693         ctlr->td[ctlr->ntd-1].control = Eor;
694         for(i = 0; i < ctlr->ntd; i++)
695                 if(bp = ctlr->tb[i]){
696                         ctlr->tb[i] = nil;
697                         freeb(bp);
698                 }
699
700         memset(ctlr->rd, 0, sizeof(D)*ctlr->nrd);
701         ctlr->rdh = ctlr->rdt = ctlr->nrq = 0;
702         ctlr->rd[ctlr->nrd-1].control = Eor;
703         for(i = 0; i < ctlr->nrd; i++)
704                 if(bp = ctlr->rb[i]){
705                         ctlr->rb[i] = nil;
706                         freeb(bp);
707                 }
708
709         rtl8169replenish(ctlr);
710
711         cplusc = csr16r(ctlr, Cplusc);
712         cplusc &= ~(Endian|Rxchksum);
713         cplusc |= Txenb|Mulrw;
714         switch(ctlr->macv){
715         case Macv40:
716         case Macv44:
717                 cplusc |= Macstatdis;
718                 break;
719         default:
720                 cplusc |= Rxenb;
721                 break;
722         }
723         csr16w(ctlr, Cplusc, cplusc);
724
725         pa = PCIWADDR(ctlr->td);
726         csr32w(ctlr, Tnpds+4, pa>>32);
727         csr32w(ctlr, Tnpds, pa);
728
729         pa = PCIWADDR(ctlr->rd);
730         csr32w(ctlr, Rdsar+4, pa>>32);
731         csr32w(ctlr, Rdsar, pa);
732
733         csr8w(ctlr, Cr, Te|Re);
734
735         csr32w(ctlr, Tcr, Ifg1|Ifg0|Mtxdmaunlimited);
736         ctlr->tcr = csr32r(ctlr, Tcr);
737         switch(ctlr->macv){
738         case Macv42:
739         case Macv45:
740                 ctlr->rcr = Rxfth256|Mrxdmaunlimited|Ab|Am|Apm;
741                 break;
742         default:
743                 ctlr->rcr = Rxfthnone|Mrxdmaunlimited|Ab|Am|Apm;
744                 break;
745         }
746         ctlr->mchash = 0;
747         csr32w(ctlr, Mar0,   0);
748         csr32w(ctlr, Mar0+4, 0);
749         csr32w(ctlr, Rcr, ctlr->rcr);
750
751         /* maximum packet sizes, unlimited */
752         csr8w(ctlr, Etx, 0x3f);
753         csr16w(ctlr, Rms, 0x3fff);
754
755         csr16w(ctlr, Coal, 0);
756
757         /* no early rx interrupts */
758         r = csr16r(ctlr, Mulint) & 0xF000;
759         csr16w(ctlr, Mulint, r);
760
761         ctlr->imr = Serr|Fovw|Punlc|Rdu|Ter|Rer|Rok|Tdu;
762         csr16w(ctlr, Imr, ctlr->imr);
763
764         csr32w(ctlr, Mpc, 0);
765
766         iunlock(ctlr);
767 }
768
769 static void
770 rtl8169reseter(void *arg)
771 {
772         Ether *edev;
773         Ctlr *ctlr;
774
775         edev = arg;
776         while(waserror())
777                 ;
778         for(;;){
779                 ctlr = edev->ctlr;
780                 sleep(&ctlr->reset, return0, nil);
781                 rtl8169init(edev);
782         }
783 }
784
785 static void rtl8169interrupt(Ureg*, void* arg);
786
787 static void
788 rtl8169attach(Ether* edev)
789 {
790         Ctlr *ctlr;
791
792         ctlr = edev->ctlr;
793         qlock(&ctlr->alock);
794         if(ctlr->init){
795                 qunlock(&ctlr->alock);
796                 return;
797         }
798         if(waserror()){
799                 print("#l%d: rtl8169: %s\n", edev->ctlrno, up->errstr);
800                 qunlock(&ctlr->alock);
801                 nexterror();
802         }
803         ctlr->ntd = Ntd;
804         ctlr->nrd = Nrd;
805
806         ctlr->tb = malloc(ctlr->ntd*sizeof(Block*));
807         ctlr->rb = malloc(ctlr->nrd*sizeof(Block*));
808         ctlr->td = mallocalign(sizeof(D)*ctlr->ntd, 256, 0, 0);
809         ctlr->rd = mallocalign(sizeof(D)*ctlr->nrd, 256, 0, 0);
810         ctlr->dtcc = mallocalign(sizeof(Dtcc), 64, 0, 0);
811         if(waserror()){
812                 free(ctlr->tb);
813                 ctlr->tb = nil;
814                 free(ctlr->rb);
815                 ctlr->rb = nil;
816                 free(ctlr->td);
817                 ctlr->td = nil;
818                 free(ctlr->rd);
819                 ctlr->rd = nil;
820                 free(ctlr->dtcc);
821                 ctlr->dtcc = nil;
822                 nexterror();
823         }
824
825         if(ctlr->tb == nil || ctlr->rb == nil 
826         || ctlr->td == nil || ctlr->rd == nil
827         || ctlr->dtcc == nil)
828                 error(Enomem);
829
830         pcisetbme(ctlr->pcidev);
831         intrenable(edev->irq, rtl8169interrupt, edev, edev->tbdf, edev->name);
832         if(waserror()){
833                 rtl8169halt(ctlr);
834                 pciclrbme(ctlr->pcidev);
835                 intrdisable(edev->irq, rtl8169interrupt, edev, edev->tbdf, edev->name);
836                 nexterror();
837         }
838
839         rtl8169init(edev);
840         rtl8169mii(edev);
841         ctlr->init = 1;
842
843         poperror();
844         poperror();
845
846         kproc("rtl8169", rtl8169reseter, edev);
847
848         qunlock(&ctlr->alock);
849         poperror();
850 }
851
852 static void
853 rtl8169link(Ether* edev)
854 {
855         uint r;
856         int limit;
857         Ctlr *ctlr;
858
859         ctlr = edev->ctlr;
860
861         r = csr8r(ctlr, Phystatus);
862         /*
863          * Maybe the link changed - do we care very much?
864          * Could stall transmits if no link, maybe?
865          */
866         edev->link = (r & Linksts) != 0;
867
868         limit = 256*1024;
869         if(r & Speed10){
870                 edev->mbps = 10;
871                 limit = 65*1024;
872         } else if(r & Speed100)
873                 edev->mbps = 100;
874         else if(r & Speed1000)
875                 edev->mbps = 1000;
876
877         if(edev->oq != nil)
878                 qsetlimit(edev->oq, limit);
879 }
880
881 static void
882 rtl8169transmit(Ether* edev)
883 {
884         D *d;
885         Block *bp;
886         Ctlr *ctlr;
887         u64int pa;
888         int x;
889
890         ctlr = edev->ctlr;
891
892         if(!canlock(ctlr))
893                 return;
894         for(x = ctlr->tdh; ctlr->ntq > 0; x = NEXT(x, ctlr->ntd)){
895                 d = &ctlr->td[x];
896                 if(d->control & Own)
897                         break;
898
899                 /*
900                  * Free it up.
901                  * Need to clean the descriptor here? Not really.
902                  * Simple freeb for now (no chain and freeblist).
903                  * Use ntq count for now.
904                  */
905                 freeb(ctlr->tb[x]);
906                 ctlr->tb[x] = nil;
907                 ctlr->ntq--;
908         }
909         ctlr->tdh = x;
910
911         x = ctlr->tdt;
912         while(ctlr->ntq < (ctlr->ntd-1)){
913                 if((bp = qget(edev->oq)) == nil)
914                         break;
915
916                 pa = PCIWADDR(bp->rp);
917                 d = &ctlr->td[x];
918                 d->addrlo = pa;
919                 d->addrhi = pa >> 32;
920                 coherence();
921                 d->control = (d->control & Eor) | Own | Fs | Ls | BLEN(bp);
922
923                 ctlr->tb[x] = bp;
924                 ctlr->ntq++;
925
926                 x = NEXT(x, ctlr->ntd);
927         }
928         if(x != ctlr->tdt)
929                 ctlr->tdt = x;
930         else if(ctlr->ntq >= (ctlr->ntd-1))
931                 ctlr->txdu++;
932
933         if(ctlr->ntq > 0){
934                 coherence();
935                 csr8w(ctlr, Tppoll, Npq);
936         }
937         unlock(ctlr);
938 }
939
940 static void
941 rtl8169receive(Ether* edev)
942 {
943         D *d;
944         Block *bp;
945         Ctlr *ctlr;
946         u32int control;
947         int x;
948
949         ctlr = edev->ctlr;
950         if(ctlr->nrq < ctlr->nrd/2)
951                 rtl8169replenish(ctlr);
952
953         for(x = ctlr->rdh; x != ctlr->rdt;){
954                 d = &ctlr->rd[x];
955                 if((control = d->control) & Own)
956                         break;
957
958                 bp = ctlr->rb[x];
959                 ctlr->rb[x] = nil;
960                 ctlr->nrq--;
961
962                 x = NEXT(x, ctlr->nrd);
963                 ctlr->rdh = x;
964
965                 if(ctlr->nrq < ctlr->nrd/2)
966                         rtl8169replenish(ctlr);
967
968                 if((control & (Fs|Ls|Res)) == (Fs|Ls)){
969                         bp->wp = bp->rp + (control & RxflMASK) - 4;
970
971                         if(control & Fovf)
972                                 ctlr->fovf++;
973                         if(control & Mar)
974                                 ctlr->mcast++;
975
976                         switch(control & (Pid1|Pid0)){
977                         default:
978                                 break;
979                         case Pid0:
980                                 if(control & Tcpf){
981                                         ctlr->tcpf++;
982                                         break;
983                                 }
984                                 bp->flag |= Btcpck;
985                                 break;
986                         case Pid1:
987                                 if(control & Udpf){
988                                         ctlr->udpf++;
989                                         break;
990                                 }
991                                 bp->flag |= Budpck;
992                                 break;
993                         case Pid1|Pid0:
994                                 if(control & Ipf){
995                                         ctlr->ipf++;
996                                         break;
997                                 }
998                                 bp->flag |= Bipck;
999                                 break;
1000                         }
1001                         etheriq(edev, bp);
1002                 }else{
1003                         if(!(control & Res))
1004                                 ctlr->frag++;
1005                         freeb(bp);
1006                 }
1007         }
1008 }
1009
1010 static void
1011 rtl8169restart(Ctlr *ctlr)
1012 {
1013         rtl8169halt(ctlr);
1014         wakeup(&ctlr->reset);
1015 }
1016
1017 static void
1018 rtl8169interrupt(Ureg*, void* arg)
1019 {
1020         Ctlr *ctlr;
1021         Ether *edev;
1022         u32int isr;
1023
1024         edev = arg;
1025         ctlr = edev->ctlr;
1026
1027         while((isr = csr16r(ctlr, Isr)) != 0 && isr != 0xFFFF){
1028                 csr16w(ctlr, Isr, isr);
1029                 if((isr & ctlr->imr) == 0)
1030                         break;
1031
1032                 if(isr & Serr)
1033                         ctlr->serr++;
1034                 if(isr & Fovw)
1035                         ctlr->fovw++;
1036                 if(isr & Rer)
1037                         ctlr->rer++;
1038                 if(isr & Rdu)
1039                         ctlr->rdu++;
1040                 if(isr & Punlc)
1041                         ctlr->punlc++;
1042
1043                 if(isr & (Serr|Fovw)){
1044                         rtl8169restart(ctlr);
1045                         break;
1046                 }
1047
1048                 if(isr & (Punlc|Rdu|Rer|Rok))
1049                         rtl8169receive(edev);
1050
1051                 if(isr & (Tdu|Ter|Tok))
1052                         rtl8169transmit(edev);
1053
1054                 if(isr & Punlc)
1055                         rtl8169link(edev);
1056         }
1057 }
1058
1059 static void
1060 rtl8169shutdown(Ether *edev)
1061 {
1062         Ctlr *ctlr = edev->ctlr;
1063
1064         rtl8169halt(ctlr);
1065 }
1066
1067 int
1068 vetmacv(Ctlr *ctlr, uint *macv)
1069 {
1070         *macv = csr32r(ctlr, Tcr) & HwveridMASK;
1071         switch(*macv){
1072         default:
1073                 return -1;
1074         case Macv01:
1075         case Macv02:
1076         case Macv03:
1077         case Macv04:
1078         case Macv05:
1079         case Macv07:
1080         case Macv07a:
1081         case Macv11:
1082         case Macv12:
1083         case Macv12a:
1084         case Macv13:
1085         case Macv14:
1086         case Macv15:
1087         case Macv25:
1088         case Macv26:
1089         case Macv27:
1090         case Macv28:
1091         case Macv29:
1092         case Macv30:
1093         case Macv38:
1094         case Macv39:
1095         case Macv40:
1096         case Macv42:
1097         case Macv44:
1098         case Macv45:
1099                 break;
1100         }
1101         return 0;
1102 }
1103
1104 static void
1105 rtl8169pci(void)
1106 {
1107         Pcidev *p;
1108         Ctlr *ctlr;
1109         int i, port, pcie;
1110         uint macv;
1111
1112         p = nil;
1113         while(p = pcimatch(p, 0, 0)){
1114                 if(p->ccrb != 0x02 || p->ccru != 0)
1115                         continue;
1116
1117                 pcie = 0;
1118                 switch(i = ((p->did<<16)|p->vid)){
1119                 default:
1120                         continue;
1121                 case Rtl8100e:                  /* RTL810[01]E ? */
1122                 case Rtl8168b:                  /* RTL8168B */
1123                         pcie = 1;
1124                         break;
1125                 case Rtl8169c:                  /* RTL8169C */
1126                 case Rtl8169sc:                 /* RTL8169SC */
1127                 case Rtl8169:                   /* RTL8169 */
1128                         break;
1129                 case (0xC107<<16)|0x1259:       /* Corega CG-LAPCIGT */
1130                         i = Rtl8169;
1131                         break;
1132                 }
1133
1134                 if(p->mem[0].size == 0 || (p->mem[0].bar & 1) == 0)
1135                         continue;
1136                 port = p->mem[0].bar & ~3;
1137                 if(ioalloc(port, p->mem[0].size, 0, "rtl8169") < 0){
1138                         print("rtl8169: port %#ux in use\n", port);
1139                         continue;
1140                 }
1141
1142                 ctlr = malloc(sizeof(Ctlr));
1143                 if(ctlr == nil){
1144                         print("rtl8169: can't allocate memory\n");
1145                         iofree(port);
1146                         continue;
1147                 }
1148                 ctlr->port = port;
1149                 ctlr->pcidev = p;
1150                 ctlr->pciv = i;
1151                 ctlr->pcie = pcie;
1152
1153                 pcienable(p);
1154                 if(vetmacv(ctlr, &macv) == -1){
1155                         print("rtl8169: %T: unknown mac %.4ux %.8ux\n", p->tbdf, p->did, macv);
1156                         pcidisable(p);
1157                         iofree(port);
1158                         free(ctlr);
1159                         continue;
1160                 }
1161                 rtl8169halt(ctlr);
1162
1163                 /*
1164                  * Extract the chip hardware version,
1165                  * needed to configure each properly.
1166                  */
1167                 ctlr->macv = macv;
1168                 if(rtl8169ctlrhead != nil)
1169                         rtl8169ctlrtail->next = ctlr;
1170                 else
1171                         rtl8169ctlrhead = ctlr;
1172                 rtl8169ctlrtail = ctlr;
1173         }
1174 }
1175
1176 static int
1177 rtl8169pnp(Ether* edev)
1178 {
1179         u32int r;
1180         Ctlr *ctlr;
1181         uchar ea[Eaddrlen];
1182         static int once;
1183
1184         if(once == 0){
1185                 once = 1;
1186                 rtl8169pci();
1187         }
1188
1189         /*
1190          * Any adapter matches if no edev->port is supplied,
1191          * otherwise the ports must match.
1192          */
1193         for(ctlr = rtl8169ctlrhead; ctlr != nil; ctlr = ctlr->next){
1194                 if(ctlr->active)
1195                         continue;
1196                 if(edev->port == 0 || edev->port == ctlr->port){
1197                         ctlr->active = 1;
1198                         break;
1199                 }
1200         }
1201         if(ctlr == nil)
1202                 return -1;
1203
1204         edev->ctlr = ctlr;
1205         edev->port = ctlr->port;
1206         edev->irq = ctlr->pcidev->intl;
1207         edev->tbdf = ctlr->pcidev->tbdf;
1208         edev->mbps = 100;
1209         edev->maxmtu = Mtu;
1210
1211         /*
1212          * Check if the adapter's station address is to be overridden.
1213          * If not, read it from the device and set in edev->ea.
1214          */
1215         memset(ea, 0, Eaddrlen);
1216         if(memcmp(ea, edev->ea, Eaddrlen) == 0){
1217                 r = csr32r(ctlr, Idr0);
1218                 edev->ea[0] = r;
1219                 edev->ea[1] = r>>8;
1220                 edev->ea[2] = r>>16;
1221                 edev->ea[3] = r>>24;
1222                 r = csr32r(ctlr, Idr0+4);
1223                 edev->ea[4] = r;
1224                 edev->ea[5] = r>>8;
1225         }
1226
1227         edev->attach = rtl8169attach;
1228         edev->transmit = rtl8169transmit;
1229         edev->ifstat = rtl8169ifstat;
1230         edev->shutdown = rtl8169shutdown;
1231
1232         edev->arg = edev;
1233         edev->promiscuous = rtl8169promiscuous;
1234         edev->multicast = rtl8169multicast;
1235
1236         rtl8169link(edev);
1237
1238         return 0;
1239 }
1240
1241 void
1242 ether8169link(void)
1243 {
1244         addethercard("rtl8169", rtl8169pnp);
1245 }