]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc/ether82563.c
merge
[plan9front.git] / sys / src / 9 / pc / ether82563.c
1 /*
2  * Intel 8256[367], 8257[1-9], 8258[03], i350
3  *      Gigabit Ethernet PCI-Express Controllers
4  * Coraid EtherDrive® hba
5  */
6 #include "u.h"
7 #include "../port/lib.h"
8 #include "mem.h"
9 #include "dat.h"
10 #include "fns.h"
11 #include "io.h"
12 #include "../port/error.h"
13 #include "../port/netif.h"
14
15 #include "etherif.h"
16
17 /*
18  * note: the 82575, 82576 and 82580 are operated using registers aliased
19  * to the 82563-style architecture.  many features seen in the 82598
20  * are also seen in the 82575 part.
21  */
22
23 enum {
24         /* General */
25
26         Ctrl            = 0x0000,       /* Device Control */
27         Status          = 0x0008,       /* Device Status */
28         Eec             = 0x0010,       /* EEPROM/Flash Control/Data */
29         Eerd            = 0x0014,       /* EEPROM Read */
30         Ctrlext         = 0x0018,       /* Extended Device Control */
31         Fla             = 0x001c,       /* Flash Access */
32         Mdic            = 0x0020,       /* MDI Control */
33         Fcal            = 0x0028,       /* Flow Control Address Low */
34         Fcah            = 0x002C,       /* Flow Control Address High */
35         Fct             = 0x0030,       /* Flow Control Type */
36         Kumctrlsta      = 0x0034,       /* Kumeran Control and Status Register */
37         Connsw          = 0x0034,       /* copper / fiber switch control; 82575/82576 */
38         Vet             = 0x0038,       /* VLAN EtherType */
39         Fcttv           = 0x0170,       /* Flow Control Transmit Timer Value */
40         Txcw            = 0x0178,       /* Transmit Configuration Word */
41         Rxcw            = 0x0180,       /* Receive Configuration Word */
42         Ledctl          = 0x0E00,       /* LED control */
43         Pba             = 0x1000,       /* Packet Buffer Allocation */
44         Pbs             = 0x1008,       /* Packet Buffer Size */
45
46         /* Interrupt */
47
48         Icr             = 0x00C0,       /* Interrupt Cause Read */
49         Itr             = 0x00c4,       /* Interrupt Throttling Rate */
50         Ics             = 0x00C8,       /* Interrupt Cause Set */
51         Ims             = 0x00D0,       /* Interrupt Mask Set/Read */
52         Imc             = 0x00D8,       /* Interrupt mask Clear */
53         Iam             = 0x00E0,       /* Interrupt acknowledge Auto Mask */
54         Eitr            = 0x1680,       /* Extended itr; 82575/6 80 only */
55
56         /* Receive */
57
58         Rctl            = 0x0100,       /* Control */
59         Ert             = 0x2008,       /* Early Receive Threshold (573[EVL], 82578 only) */
60         Fcrtl           = 0x2160,       /* Flow Control RX Threshold Low */
61         Fcrth           = 0x2168,       /* Flow Control Rx Threshold High */
62         Psrctl          = 0x2170,       /* Packet Split Receive Control */
63         Drxmxod         = 0x2540,       /* dma max outstanding bytes (82575) */
64         Rdbal           = 0x2800,       /* Rdesc Base Address Low Queue 0 */
65         Rdbah           = 0x2804,       /* Rdesc Base Address High Queue 0 */
66         Rdlen           = 0x2808,       /* Descriptor Length Queue 0 */
67         Srrctl          = 0x280c,       /* split and replication rx control (82575) */
68         Rdh             = 0x2810,       /* Descriptor Head Queue 0 */
69         Rdt             = 0x2818,       /* Descriptor Tail Queue 0 */
70         Rdtr            = 0x2820,       /* Descriptor Timer Ring */
71         Rxdctl          = 0x2828,       /* Descriptor Control */
72         Radv            = 0x282C,       /* Interrupt Absolute Delay Timer */
73         Rsrpd           = 0x2c00,       /* Small Packet Detect */
74         Raid            = 0x2c08,       /* ACK interrupt delay */
75         Cpuvec          = 0x2c10,       /* CPU Vector */
76         Rxcsum          = 0x5000,       /* Checksum Control */
77         Rmpl            = 0x5004,       /* rx maximum packet length (82575) */
78         Rfctl           = 0x5008,       /* Filter Control */
79         Mta             = 0x5200,       /* Multicast Table Array */
80         Ral             = 0x5400,       /* Receive Address Low */
81         Rah             = 0x5404,       /* Receive Address High */
82         Vfta            = 0x5600,       /* VLAN Filter Table Array */
83         Mrqc            = 0x5818,       /* Multiple Receive Queues Command */
84
85         /* Transmit */
86
87         Tctl            = 0x0400,       /* Transmit Control */
88         Tipg            = 0x0410,       /* Transmit IPG */
89         Tkabgtxd        = 0x3004,       /* glci afe band gap transmit ref data, or something */
90         Tdbal           = 0x3800,       /* Tdesc Base Address Low */
91         Tdbah           = 0x3804,       /* Tdesc Base Address High */
92         Tdlen           = 0x3808,       /* Descriptor Length */
93         Tdh             = 0x3810,       /* Descriptor Head */
94         Tdt             = 0x3818,       /* Descriptor Tail */
95         Tidv            = 0x3820,       /* Interrupt Delay Value */
96         Txdctl          = 0x3828,       /* Descriptor Control */
97         Tadv            = 0x382C,       /* Interrupt Absolute Delay Timer */
98         Tarc0           = 0x3840,       /* Arbitration Counter Queue 0 */
99
100         /* Statistics */
101
102         Statistics      = 0x4000,       /* Start of Statistics Area */
103         Gorcl           = 0x88/4,       /* Good Octets Received Count */
104         Gotcl           = 0x90/4,       /* Good Octets Transmitted Count */
105         Torl            = 0xC0/4,       /* Total Octets Received */
106         Totl            = 0xC8/4,       /* Total Octets Transmitted */
107         Nstatistics     = 0x124/4,
108 };
109
110 enum {                                  /* Ctrl */
111         Lrst            = 1<<3,         /* link reset */
112         Slu             = 1<<6,         /* Set Link Up */
113         Devrst          = 1<<26,        /* Device Reset */
114         Rfce            = 1<<27,        /* Receive Flow Control Enable */
115         Tfce            = 1<<28,        /* Transmit Flow Control Enable */
116         Phyrst          = 1<<31,        /* Phy Reset */
117 };
118
119 enum {                                  /* Status */
120         Lu              = 1<<1,         /* Link Up */
121         Lanid           = 3<<2,         /* mask for Lan ID. */
122         Txoff           = 1<<4,         /* Transmission Paused */
123         Tbimode         = 1<<5,         /* TBI Mode Indication */
124         Phyra           = 1<<10,        /* PHY Reset Asserted */
125         GIOme           = 1<<19,        /* GIO Master Enable Status */
126 };
127
128 enum {                                  /* Eec */
129         Nvpres          = 1<<8,
130         Autord          = 1<<9,
131         Sec1val         = 1<<22,
132 };
133
134 enum {                                  /* Eerd */
135         EEstart         = 1<<0,         /* Start Read */
136         EEdone          = 1<<1,         /* Read done */
137 };
138
139 enum {                                  /* Ctrlext */
140         Eerst           = 1<<13,        /* EEPROM Reset */
141         Linkmode        = 3<<22,        /* linkmode */
142         Internalphy     = 0<<22,        /* " internal phy (copper) */
143         Sgmii           = 2<<22,        /* " sgmii */
144         Serdes          = 3<<22,        /* " serdes */
145 };
146
147 enum {
148         /* Connsw */
149         Enrgirq         = 1<<2, /* interrupt on power detect (enrgsrc) */
150 };
151
152 enum {                                  /* EEPROM content offsets */
153         Ea              = 0x00,         /* Ethernet Address */
154 };
155
156 enum {                                  /* Mdic */
157         MDIdMASK        = 0x0000FFFF,   /* Data */
158         MDIdSHIFT       = 0,
159         MDIrMASK        = 0x001F0000,   /* PHY Register Address */
160         MDIrSHIFT       = 16,
161         MDIpMASK        = 0x03E00000,   /* PHY Address */
162         MDIpSHIFT       = 21,
163         MDIwop          = 0x04000000,   /* Write Operation */
164         MDIrop          = 0x08000000,   /* Read Operation */
165         MDIready        = 0x10000000,   /* End of Transaction */
166         MDIie           = 0x20000000,   /* Interrupt Enable */
167         MDIe            = 0x40000000,   /* Error */
168 };
169
170 enum {                                  /* phy interface */
171         Phyctl          = 0,            /* phy ctl register */
172         Physr           = 1,            /* phy status register */
173         Phyid1          = 2,            /* phy id1 */
174         Phyid2          = 3,            /* phy id2 */
175         Phyisr          = 19,           /* 82563 phy interrupt status register */
176         Phylhr          = 19,           /* 8257[12] link health register */
177         Physsr          = 17,           /* phy secondary status register */
178         Phyprst         = 193<<8 | 17,  /* 8256[34] phy port reset */
179         Phyier          = 18,           /* 82573 phy interrupt enable register */
180         Phypage         = 22,           /* 8256[34] page register */
181         Phystat         = 26,           /* 82580 phy status */
182         Phyapage        = 29,
183         Rtlink          = 1<<10,        /* realtime link status */
184         Phyan           = 1<<11,        /* phy has autonegotiated */
185
186         /* Phyctl bits */
187         Ran             = 1<<9, /* restart auto negotiation */
188         Ean             = 1<<12,        /* enable auto negotiation */
189
190         /* Phyprst bits */
191         Prst            = 1<<0, /* reset the port */
192
193         /* 82573 Phyier bits */
194         Lscie           = 1<<10,        /* link status changed ie */
195         Ancie           = 1<<11,        /* auto negotiation complete ie */
196         Spdie           = 1<<14,        /* speed changed ie */
197         Panie           = 1<<15,        /* phy auto negotiation error ie */
198
199         /* Phylhr/Phyisr bits */
200         Anf             = 1<<6, /* lhr: auto negotiation fault */
201         Ane             = 1<<15,        /* isr: auto negotiation error */
202
203         /* 82580 Phystat bits */
204         Ans     = 1<<14 | 1<<15,        /* 82580 autoneg. status */
205         Link    = 1<<6,         /* 82580 Link */
206
207         /* Rxcw builtin serdes */
208         Anc             = 1<<31,
209         Rxsynch         = 1<<30,
210         Rxcfg           = 1<<29,
211         Rxcfgch         = 1<<28,
212         Rxcfgbad        = 1<<27,
213         Rxnc            = 1<<26,
214
215         /* Txcw */
216         Txane           = 1<<31,
217         Txcfg           = 1<<30,
218 };
219
220 enum {                                  /* fiber (pcs) interface */
221         Pcsctl  = 0x4208,               /* pcs control */
222         Pcsstat = 0x420c,               /* pcs status */
223
224         /* Pcsctl bits */
225         Pan     = 1<<16,                /* autoegotiate */
226         Prestart        = 1<<17,                /* restart an (self clearing) */
227
228         /* Pcsstat bits */
229         Linkok  = 1<<0,         /* link is okay */
230         Andone  = 1<<16,                /* an phase is done see below for success */
231         Anbad   = 1<<19 | 1<<20,        /* Anerror | Anremfault */
232 };
233
234 enum {                                  /* Icr, Ics, Ims, Imc */
235         Txdw            = 0x00000001,   /* Transmit Descriptor Written Back */
236         Txqe            = 0x00000002,   /* Transmit Queue Empty */
237         Lsc             = 0x00000004,   /* Link Status Change */
238         Rxseq           = 0x00000008,   /* Receive Sequence Error */
239         Rxdmt0          = 0x00000010,   /* Rdesc Minimum Threshold Reached */
240         Rxo             = 0x00000040,   /* Receiver Overrun */
241         Rxt0            = 0x00000080,   /* Receiver Timer Interrupt; !82575/6/80 only */
242         Rxdw            = 0x00000080,   /* Rdesc write back; 82575/6/80 only */
243         Mdac            = 0x00000200,   /* MDIO Access Completed */
244         Rxcfgset                = 0x00000400,   /* Receiving /C/ ordered sets */
245         Ack             = 0x00020000,   /* Receive ACK frame */
246         Omed            = 1<<20,        /* media change; pcs interface */
247 };
248
249 enum {                                  /* Txcw */
250         TxcwFd          = 0x00000020,   /* Full Duplex */
251         TxcwHd          = 0x00000040,   /* Half Duplex */
252         TxcwPauseMASK   = 0x00000180,   /* Pause */
253         TxcwPauseSHIFT  = 7,
254         TxcwPs          = 1<<TxcwPauseSHIFT,    /* Pause Supported */
255         TxcwAs          = 2<<TxcwPauseSHIFT,    /* Asymmetric FC desired */
256         TxcwRfiMASK     = 0x00003000,   /* Remote Fault Indication */
257         TxcwRfiSHIFT    = 12,
258         TxcwNpr         = 0x00008000,   /* Next Page Request */
259         TxcwConfig      = 0x40000000,   /* Transmit COnfig Control */
260         TxcwAne         = 0x80000000,   /* Auto-Negotiation Enable */
261 };
262
263 enum {                                  /* Rctl */
264         Rrst            = 0x00000001,   /* Receiver Software Reset */
265         Ren             = 0x00000002,   /* Receiver Enable */
266         Sbp             = 0x00000004,   /* Store Bad Packets */
267         Upe             = 0x00000008,   /* Unicast Promiscuous Enable */
268         Mpe             = 0x00000010,   /* Multicast Promiscuous Enable */
269         Lpe             = 0x00000020,   /* Long Packet Reception Enable */
270         RdtmsMASK       = 0x00000300,   /* Rdesc Minimum Threshold Size */
271         RdtmsHALF       = 0x00000000,   /* Threshold is 1/2 Rdlen */
272         RdtmsQUARTER    = 0x00000100,   /* Threshold is 1/4 Rdlen */
273         RdtmsEIGHTH     = 0x00000200,   /* Threshold is 1/8 Rdlen */
274         MoMASK          = 0x00003000,   /* Multicast Offset */
275         Bam             = 0x00008000,   /* Broadcast Accept Mode */
276         BsizeMASK       = 0x00030000,   /* Receive Buffer Size */
277         Bsize16384      = 0x00010000,   /* Bsex = 1 */
278         Bsize8192       = 0x00020000,   /* Bsex = 1 */
279         Bsize2048       = 0x00000000,
280         Bsize1024       = 0x00010000,
281         Bsize512        = 0x00020000,
282         Bsize256        = 0x00030000,
283         BsizeFlex       = 0x08000000,   /* Flexable Bsize in 1kb increments */
284         Vfe             = 0x00040000,   /* VLAN Filter Enable */
285         Cfien           = 0x00080000,   /* Canonical Form Indicator Enable */
286         Cfi             = 0x00100000,   /* Canonical Form Indicator value */
287         Dpf             = 0x00400000,   /* Discard Pause Frames */
288         Pmcf            = 0x00800000,   /* Pass MAC Control Frames */
289         Bsex            = 0x02000000,   /* Buffer Size Extension */
290         Secrc           = 0x04000000,   /* Strip CRC from incoming packet */
291 };
292
293 enum {                                  /* Srrctl */
294         Dropen          = 1<<31,
295 };
296
297 enum {                                  /* Tctl */
298         Trst            = 0x00000001,   /* Transmitter Software Reset */
299         Ten             = 0x00000002,   /* Transmit Enable */
300         Psp             = 0x00000008,   /* Pad Short Packets */
301         Mulr            = 0x10000000,   /* Allow multiple concurrent requests */
302         CtMASK          = 0x00000FF0,   /* Collision Threshold */
303         CtSHIFT         = 4,
304         ColdMASK        = 0x003FF000,   /* Collision Distance */
305         ColdSHIFT       = 12,
306         Swxoff          = 0x00400000,   /* Sofware XOFF Transmission */
307         Pbe             = 0x00800000,   /* Packet Burst Enable */
308         Rtlc            = 0x01000000,   /* Re-transmit on Late Collision */
309         Nrtu            = 0x02000000,   /* No Re-transmit on Underrrun */
310 };
311
312 enum {                                  /* [RT]xdctl */
313         PthreshMASK     = 0x0000003F,   /* Prefetch Threshold */
314         PthreshSHIFT    = 0,
315         HthreshMASK     = 0x00003F00,   /* Host Threshold */
316         HthreshSHIFT    = 8,
317         WthreshMASK     = 0x003F0000,   /* Writeback Threshold */
318         WthreshSHIFT    = 16,
319         Gran            = 0x01000000,   /* Granularity; not 82575 */
320         Enable          = 0x02000000,
321 };
322
323 enum {                                  /* Rxcsum */
324         Ipofl           = 0x0100,       /* IP Checksum Off-load Enable */
325         Tuofl           = 0x0200,       /* TCP/UDP Checksum Off-load Enable */
326 };
327
328 typedef struct Rd {                     /* Receive Descriptor */
329         u32int  addr[2];
330         u16int  length;
331         u16int  checksum;
332         uchar   status;
333         uchar   errors;
334         u16int  special;
335 } Rd;
336
337 enum {                                  /* Rd status */
338         Rdd             = 0x01,         /* Descriptor Done */
339         Reop            = 0x02,         /* End of Packet */
340         Ixsm            = 0x04,         /* Ignore Checksum Indication */
341         Vp              = 0x08,         /* Packet is 802.1Q (matched VET) */
342         Tcpcs           = 0x20,         /* TCP Checksum Calculated on Packet */
343         Ipcs            = 0x40,         /* IP Checksum Calculated on Packet */
344         Pif             = 0x80,         /* Passed in-exact filter */
345 };
346
347 enum {                                  /* Rd errors */
348         Ce              = 0x01,         /* CRC Error or Alignment Error */
349         Se              = 0x02,         /* Symbol Error */
350         Seq             = 0x04,         /* Sequence Error */
351         Cxe             = 0x10,         /* Carrier Extension Error */
352         Tcpe            = 0x20,         /* TCP/UDP Checksum Error */
353         Ipe             = 0x40,         /* IP Checksum Error */
354         Rxe             = 0x80,         /* RX Data Error */
355 };
356
357 typedef struct {                        /* Transmit Descriptor */
358         u32int  addr[2];                /* Data */
359         u32int  control;
360         u32int  status;
361 } Td;
362
363 enum {                                  /* Tdesc control */
364         LenMASK         = 0x000FFFFF,   /* Data/Packet Length Field */
365         LenSHIFT        = 0,
366         DtypeCD         = 0x00000000,   /* Data Type 'Context Descriptor' */
367         DtypeDD         = 0x00100000,   /* Data Type 'Data Descriptor' */
368         PtypeTCP        = 0x01000000,   /* TCP/UDP Packet Type (CD) */
369         Teop            = 0x01000000,   /* End of Packet (DD) */
370         PtypeIP         = 0x02000000,   /* IP Packet Type (CD) */
371         Ifcs            = 0x02000000,   /* Insert FCS (DD) */
372         Tse             = 0x04000000,   /* TCP Segmentation Enable */
373         Rs              = 0x08000000,   /* Report Status */
374         Rps             = 0x10000000,   /* Report Status Sent */
375         Dext            = 0x20000000,   /* Descriptor Extension */
376         Vle             = 0x40000000,   /* VLAN Packet Enable */
377         Ide             = 0x80000000,   /* Interrupt Delay Enable */
378 };
379
380 enum {                                  /* Tdesc status */
381         Tdd             = 0x0001,       /* Descriptor Done */
382         Ec              = 0x0002,       /* Excess Collisions */
383         Lc              = 0x0004,       /* Late Collision */
384         Tu              = 0x0008,       /* Transmit Underrun */
385         CssMASK         = 0xFF00,       /* Checksum Start Field */
386         CssSHIFT        = 8,
387 };
388
389 typedef struct {
390         u16int  *reg;
391         u32int  *reg32;
392         uint    base;
393         uint    lim;
394 } Flash;
395
396 enum {
397         /* 16 and 32-bit flash registers for ich flash parts */
398         Bfpr    = 0x00/4,               /* flash base 0:12; lim 16:28 */
399         Fsts    = 0x04/2,               /* flash status; Hsfsts */
400         Fctl    = 0x06/2,               /* flash control; Hsfctl */
401         Faddr   = 0x08/4,               /* flash address to r/w */
402         Fdata   = 0x10/4,               /* data @ address */
403
404         /* status register */
405         Fdone   = 1<<0,                 /* flash cycle done */
406         Fcerr   = 1<<1,                 /* cycle error; write 1 to clear */
407         Ael     = 1<<2,                 /* direct access error log; 1 to clear */
408         Scip    = 1<<5,                 /* spi cycle in progress */
409         Fvalid  = 1<<14,                /* flash descriptor valid */
410
411         /* control register */
412         Fgo     = 1<<0,                 /* start cycle */
413         Flcycle = 1<<1,                 /* two bits: r=0; w=2 */
414         Fdbc    = 1<<8,                 /* bytes to read; 5 bits */
415 };
416
417 enum {
418         Nrd             = 256,          /* power of two */
419         Ntd             = 128,          /* power of two */
420         Nrb             = 512+512,      /* private receive buffers per Ctlr */
421         Rbalign         = BY2PG,        /* rx buffer alignment */
422 };
423
424 /*
425  * cavet emptor: 82577/78 have been entered speculatitively.
426  * awating datasheet from intel.
427  */
428 enum {
429         i82563,
430         i82566,
431         i82567,
432         i82567m,
433         i82571,
434         i82572,
435         i82573,
436         i82574,
437         i82575,
438         i82576,
439         i82577,
440         i82577m,        
441         i82578,
442         i82578m,
443         i82579,
444         i82580,
445         i82583,
446         i210,
447         i217,
448         i218,
449         i219,
450         i350,
451         Nctlrtype,
452 };
453
454 enum {
455         Fload   = 1<<0,
456         Fert    = 1<<1,
457         F75     = 1<<2,
458         Fpba    = 1<<3,
459         Fflashea= 1<<4,
460         F79phy  = 1<<5,
461         Fnofct  = 1<<6,
462         Fbadcsum= 1<<7,
463 };
464
465 typedef struct Ctlrtype Ctlrtype;
466 struct Ctlrtype {
467         char    *name;
468         int     mtu;
469         int     flag;
470 };
471
472 static Ctlrtype cttab[Nctlrtype] = {
473 [i82563]        "i82563",       9014,   Fpba,
474 [i82566]        "i82566",       1514,   Fload,
475 [i82567]        "i82567",       9234,   Fload,
476 [i82567m]       "i82567m",      1514,   Fload,
477 [i82571]        "i82571",       9234,   Fpba,
478 [i82572]        "i82572",       9234,   Fpba,
479 [i82573]        "i82573",       8192,   Fert,           /* terrible perf above 8k */
480 [i82574]        "i82574",       9018,   0,
481 [i82575]        "i82575",       9728,   F75|Fflashea,
482 [i82576]        "i82576",       9728,   F75,
483 [i82577]        "i82577",       4096,   Fload|Fert,
484 [i82577m]       "i82577",       1514,   Fload|Fert,
485 [i82578]        "i82578",       4096,   Fload|Fert,
486 [i82578m]       "i82578",       1514,   Fload|Fert,
487 [i82579]        "i82579",       9018,   Fload|Fert|F79phy|Fnofct,
488 [i82580]        "i82580",       9728,   F75|F79phy,
489 [i82583]        "i82583",       1514,   0,
490 [i210]          "i210",         9728,   F75|Fnofct|Fert,
491 [i217]          "i217",         9728,   Fload|Fnofct|Fert|Fbadcsum,
492 [i218]          "i218",         9728,   Fload|Fert|F79phy|Fnofct|Fbadcsum,
493 [i219]          "i219",         9728,   Fload|Fert|F79phy|Fnofct,
494 [i350]          "i350",         9728,   F75|F79phy|Fnofct,
495 };
496
497 typedef void (*Freefn)(Block*);
498
499 typedef struct Ctlr Ctlr;
500 struct Ctlr {
501         ulong   port;
502         Pcidev  *pcidev;
503         Ctlr    *next;
504         int     active;
505         int     type;
506         u16int  eeprom[0x40];
507
508         QLock   alock;                  /* attach */
509         void    *alloc;                 /* receive/transmit descriptors */
510         int     nrd;
511         int     ntd;
512         uint    rbsz;
513
514         u32int  *nic;
515         Lock    imlock;
516         int     im;                     /* interrupt mask */
517
518         Rendez  lrendez;
519         int     lim;
520
521         QLock   slock;
522         u32int  statistics[Nstatistics];
523         uint    lsleep;
524         uint    lintr;
525         uint    rsleep;
526         uint    rintr;
527         uint    txdw;
528         uint    tintr;
529         uint    ixsm;
530         uint    ipcs;
531         uint    tcpcs;
532         uint    speeds[4];
533         uint    phyerrata;
534
535         uchar   ra[Eaddrlen];           /* receive address */
536         u32int  mta[128];               /* multicast table array */
537
538         Rendez  rrendez;
539         int     rim;
540         int     rdfree;
541         Rd      *rdba;                  /* receive descriptor base address */
542         Block   **rb;                   /* receive buffers */
543         uint    rdh;                    /* receive descriptor head */
544         uint    rdt;                    /* receive descriptor tail */
545         int     rdtr;                   /* receive delay timer ring value */
546         int     radv;                   /* receive interrupt absolute delay timer */
547
548         Rendez  trendez;
549         QLock   tlock;
550         int     tbusy;
551         Td      *tdba;                  /* transmit descriptor base address */
552         Block   **tb;                   /* transmit buffers */
553         int     tdh;                    /* transmit descriptor head */
554         int     tdt;                    /* transmit descriptor tail */
555
556         int     fcrtl;
557         int     fcrth;
558
559         u32int  pba;                    /* packet buffer allocation */
560 };
561
562 #define csr32r(c, r)    (*((c)->nic+((r)/4)))
563 #define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v))
564
565 static  Ctlr    *i82563ctlrhead;
566 static  Ctlr    *i82563ctlrtail;
567
568 static char *statistics[Nstatistics] = {
569         "CRC Error",
570         "Alignment Error",
571         "Symbol Error",
572         "RX Error",
573         "Missed Packets",
574         "Single Collision",
575         "Excessive Collisions",
576         "Multiple Collision",
577         "Late Collisions",
578         nil,
579         "Collision",
580         "Transmit Underrun",
581         "Defer",
582         "Transmit - No CRS",
583         "Sequence Error",
584         "Carrier Extension Error",
585         "Receive Error Length",
586         nil,
587         "XON Received",
588         "XON Transmitted",
589         "XOFF Received",
590         "XOFF Transmitted",
591         "FC Received Unsupported",
592         "Packets Received (64 Bytes)",
593         "Packets Received (65-127 Bytes)",
594         "Packets Received (128-255 Bytes)",
595         "Packets Received (256-511 Bytes)",
596         "Packets Received (512-1023 Bytes)",
597         "Packets Received (1024-mtu Bytes)",
598         "Good Packets Received",
599         "Broadcast Packets Received",
600         "Multicast Packets Received",
601         "Good Packets Transmitted",
602         nil,
603         "Good Octets Received",
604         nil,
605         "Good Octets Transmitted",
606         nil,
607         nil,
608         nil,
609         "Receive No Buffers",
610         "Receive Undersize",
611         "Receive Fragment",
612         "Receive Oversize",
613         "Receive Jabber",
614         "Management Packets Rx",
615         "Management Packets Drop",
616         "Management Packets Tx",
617         "Total Octets Received",
618         nil,
619         "Total Octets Transmitted",
620         nil,
621         "Total Packets Received",
622         "Total Packets Transmitted",
623         "Packets Transmitted (64 Bytes)",
624         "Packets Transmitted (65-127 Bytes)",
625         "Packets Transmitted (128-255 Bytes)",
626         "Packets Transmitted (256-511 Bytes)",
627         "Packets Transmitted (512-1023 Bytes)",
628         "Packets Transmitted (1024-mtu Bytes)",
629         "Multicast Packets Transmitted",
630         "Broadcast Packets Transmitted",
631         "TCP Segmentation Context Transmitted",
632         "TCP Segmentation Context Fail",
633         "Interrupt Assertion",
634         "Interrupt Rx Pkt Timer",
635         "Interrupt Rx Abs Timer",
636         "Interrupt Tx Pkt Timer",
637         "Interrupt Tx Abs Timer",
638         "Interrupt Tx Queue Empty",
639         "Interrupt Tx Desc Low",
640         "Interrupt Rx Min",
641         "Interrupt Rx Overrun",
642 };
643
644 static char*
645 cname(Ctlr *c)
646 {
647         return cttab[c->type].name;
648 }
649
650 static long
651 i82563ifstat(Ether *edev, void *a, long n, ulong offset)
652 {
653         char *s, *p, *e, *stat;
654         int i, r;
655         uvlong tuvl, ruvl;
656         Ctlr *ctlr;
657
658         p = s = smalloc(READSTR);
659         e = p + READSTR;
660
661         ctlr = edev->ctlr;
662         qlock(&ctlr->slock);
663
664         for(i = 0; i < Nstatistics; i++){
665                 r = csr32r(ctlr, Statistics + i*4);
666                 if((stat = statistics[i]) == nil)
667                         continue;
668                 switch(i){
669                 case Gorcl:
670                 case Gotcl:
671                 case Torl:
672                 case Totl:
673                         ruvl = r;
674                         ruvl += (uvlong)csr32r(ctlr, Statistics+(i+1)*4) << 32;
675                         tuvl = ruvl;
676                         tuvl += ctlr->statistics[i];
677                         tuvl += (uvlong)ctlr->statistics[i+1] << 32;
678                         if(tuvl == 0)
679                                 continue;
680                         ctlr->statistics[i] = tuvl;
681                         ctlr->statistics[i+1] = tuvl >> 32;
682                         p = seprint(p, e, "%s: %llud %llud\n", stat, tuvl, ruvl);
683                         i++;
684                         break;
685
686                 default:
687                         ctlr->statistics[i] += r;
688                         if(ctlr->statistics[i] == 0)
689                                 continue;
690                         p = seprint(p, e, "%s: %ud %ud\n", stat,
691                                 ctlr->statistics[i], r);
692                         break;
693                 }
694         }
695
696         p = seprint(p, e, "lintr: %ud %ud\n", ctlr->lintr, ctlr->lsleep);
697         p = seprint(p, e, "rintr: %ud %ud\n", ctlr->rintr, ctlr->rsleep);
698         p = seprint(p, e, "tintr: %ud %ud\n", ctlr->tintr, ctlr->txdw);
699         p = seprint(p, e, "ixcs: %ud %ud %ud\n", ctlr->ixsm, ctlr->ipcs, ctlr->tcpcs);
700         p = seprint(p, e, "rdtr: %ud\n", ctlr->rdtr);
701         p = seprint(p, e, "radv: %ud\n", ctlr->radv);
702         p = seprint(p, e, "ctrl: %.8ux\n", csr32r(ctlr, Ctrl));
703         p = seprint(p, e, "ctrlext: %.8ux\n", csr32r(ctlr, Ctrlext));
704         p = seprint(p, e, "status: %.8ux\n", csr32r(ctlr, Status));
705         p = seprint(p, e, "txcw: %.8ux\n", csr32r(ctlr, Txcw));
706         p = seprint(p, e, "txdctl: %.8ux\n", csr32r(ctlr, Txdctl));
707         p = seprint(p, e, "pba: %.8ux\n", ctlr->pba);
708
709         p = seprint(p, e, "speeds: 10:%ud 100:%ud 1000:%ud ?:%ud\n",
710                 ctlr->speeds[0], ctlr->speeds[1], ctlr->speeds[2], ctlr->speeds[3]);
711         p = seprint(p, e, "type: %s\n", cname(ctlr));
712
713         p = seprint(p, e, "eeprom:");
714         for(i = 0; i < 0x40; i++){
715                 if(i && ((i & 7) == 0))
716                         p = seprint(p, e, "\n       ");
717                 p = seprint(p, e, " %4.4ux", ctlr->eeprom[i]);
718         }
719         p = seprint(p, e, "\n");
720
721         USED(p);
722         n = readstr(offset, a, n, s);
723         free(s);
724         qunlock(&ctlr->slock);
725
726         return n;
727 }
728
729 static void
730 i82563promiscuous(void *arg, int on)
731 {
732         int rctl;
733         Ctlr *ctlr;
734         Ether *edev;
735
736         edev = arg;
737         ctlr = edev->ctlr;
738
739         rctl = csr32r(ctlr, Rctl);
740         rctl &= ~MoMASK;
741         if(on)
742                 rctl |= Upe|Mpe;
743         else
744                 rctl &= ~(Upe|Mpe);
745         csr32w(ctlr, Rctl, rctl);
746 }
747
748 static void
749 i82563multicast(void *arg, uchar *addr, int on)
750 {
751         int bit, x;
752         Ctlr *ctlr;
753         Ether *edev;
754
755         edev = arg;
756         ctlr = edev->ctlr;
757
758         switch(ctlr->type){
759         case i82566:
760         case i82567:
761         case i82567m:
762         case i82577:
763         case i82577m:
764         case i82579:
765         case i210:
766         case i217:
767         case i218:
768         case i219:
769                 bit = (addr[5]<<2)|(addr[4]>>6);
770                 x = (bit>>5) & 31;
771                 break;
772         default:
773                 bit = (addr[5]<<4)|(addr[4]>>4);
774                 x = (bit>>5) & 127;
775                 break;
776         }
777         bit &= 31;
778
779         /*
780          * multiple ether addresses can hash to the same filter bit,
781          * so it's never safe to clear a filter bit.
782          * if we want to clear filter bits, we need to keep track of
783          * all the multicast addresses in use, clear all the filter bits,
784          * then set the ones corresponding to in-use addresses.
785          */
786         if(on)
787                 ctlr->mta[x] |= 1<<bit;
788
789         csr32w(ctlr, Mta+x*4, ctlr->mta[x]);
790 }
791
792 static void
793 i82563im(Ctlr *ctlr, int im)
794 {
795         ilock(&ctlr->imlock);
796         ctlr->im |= im;
797         csr32w(ctlr, Ims, ctlr->im);
798         iunlock(&ctlr->imlock);
799 }
800
801 static void
802 i82563txinit(Ctlr *ctlr)
803 {
804         u32int r;
805         Block *b;
806         int i;
807
808         if(cttab[ctlr->type].flag & F75)
809                 csr32w(ctlr, Tctl, 0x0F<<CtSHIFT | Psp);
810         else
811                 csr32w(ctlr, Tctl, 0x0F<<CtSHIFT | Psp | 66<<ColdSHIFT | Mulr);
812         csr32w(ctlr, Tipg, 6<<20 | 8<<10 | 8);          /* yb sez: 0x702008 */
813         for(i = 0; i < ctlr->ntd; i++){
814                 if((b = ctlr->tb[i]) != nil){
815                         ctlr->tb[i] = nil;
816                         freeb(b);
817                 }
818                 memset(&ctlr->tdba[i], 0, sizeof(Td));
819         }
820         csr32w(ctlr, Tdbal, PCIWADDR(ctlr->tdba));
821         csr32w(ctlr, Tdbah, 0);
822         csr32w(ctlr, Tdlen, ctlr->ntd * sizeof(Td));
823         ctlr->tdh = PREV(0, ctlr->ntd);
824         csr32w(ctlr, Tdh, 0);
825         ctlr->tdt = 0;
826         csr32w(ctlr, Tdt, 0);
827         csr32w(ctlr, Tidv, 128);
828         csr32w(ctlr, Tadv, 64);
829         csr32w(ctlr, Tctl, csr32r(ctlr, Tctl) | Ten);
830         r = csr32r(ctlr, Txdctl) & ~WthreshMASK;
831         r |= 4<<WthreshSHIFT | 4<<PthreshSHIFT;
832         if(cttab[ctlr->type].flag & F75)
833                 r |= Enable;
834         csr32w(ctlr, Txdctl, r);
835 }
836
837 static uint
838 i82563cleanup(Ctlr *c)
839 {
840         Block *b;
841         uint tdh, n;
842
843         tdh = c->tdh;
844         while(c->tdba[n = NEXT(tdh, c->ntd)].status & Tdd){
845                 tdh = n;
846                 if((b = c->tb[tdh]) != nil){
847                         c->tb[tdh] = nil;
848                         freeb(b);
849                 }else
850                         iprint("82563 tx underrun!\n");
851                 c->tdba[tdh].status = 0;
852         }
853
854         return c->tdh = tdh;
855 }
856
857 static int
858 notrim(void *v)
859 {
860         Ctlr *c;
861
862         c = v;
863         return (c->im & Txdw) == 0;
864 }
865
866 static void
867 i82563tproc(void *v)
868 {
869         Td *td;
870         Block *bp;
871         Ether *edev;
872         Ctlr *ctlr;
873         uint tdt, n;
874
875         edev = v;
876         ctlr = edev->ctlr;
877         i82563txinit(ctlr);
878
879         tdt = ctlr->tdt;
880         while(waserror())
881                 ;
882         for(;;){
883                 n = NEXT(tdt, ctlr->ntd);
884                 if(n == i82563cleanup(ctlr)){
885                         ctlr->txdw++;
886                         i82563im(ctlr, Txdw);
887                         sleep(&ctlr->trendez, notrim, ctlr);
888                         continue;
889                 }
890                 bp = qbread(edev->oq, 100000);
891                 td = &ctlr->tdba[tdt];
892                 td->addr[0] = PCIWADDR(bp->rp);
893                 td->addr[1] = 0;
894                 td->control = Ide|Rs|Ifcs|Teop|BLEN(bp);
895                 coherence();
896                 ctlr->tb[tdt] = bp;
897                 ctlr->tdt = tdt = n;
898                 csr32w(ctlr, Tdt, tdt);
899         }
900 }
901
902 static void
903 i82563replenish(Ctlr *ctlr)
904 {
905         uint rdt, i;
906         Block *bp;
907         Rd *rd;
908
909         i = 0;
910         for(rdt = ctlr->rdt; NEXT(rdt, ctlr->nrd) != ctlr->rdh; rdt = NEXT(rdt, ctlr->nrd)){
911                 rd = &ctlr->rdba[rdt];
912                 if(ctlr->rb[rdt] != nil){
913                         iprint("82563: tx overrun\n");
914                         break;
915                 }
916                 i++;
917                 bp = allocb(ctlr->rbsz + Rbalign);
918                 bp->rp = bp->wp = (uchar*)ROUND((uintptr)bp->base, Rbalign);
919                 ctlr->rb[rdt] = bp;
920                 rd->addr[0] = PCIWADDR(bp->rp);
921                 rd->addr[1] = 0;
922                 rd->status = 0;
923                 ctlr->rdfree++;
924         }
925         if(i != 0){
926                 coherence();
927                 ctlr->rdt = rdt;
928                 csr32w(ctlr, Rdt, rdt);
929         }
930 }
931
932 static void
933 i82563rxinit(Ctlr *ctlr)
934 {
935         int i;
936         Block *bp;
937
938         if(ctlr->rbsz <= 2048)
939                 csr32w(ctlr, Rctl, Dpf|Bsize2048|Bam|RdtmsHALF);
940         else{
941                 i = ctlr->rbsz / 1024;
942                 if(ctlr->rbsz % 1024)
943                         i++;
944                 if(cttab[ctlr->type].flag & F75){
945                         csr32w(ctlr, Rctl, Lpe|Dpf|Bsize2048|Bam|RdtmsHALF|Secrc);
946                         if(ctlr->type != i82575)
947                                 i |= (ctlr->nrd/2>>4)<<20;              /* RdmsHalf */
948                         csr32w(ctlr, Srrctl, i | Dropen);
949                         csr32w(ctlr, Rmpl, ctlr->rbsz);
950 //                      csr32w(ctlr, Drxmxod, 0x7ff);
951                 }else
952                         csr32w(ctlr, Rctl, Lpe|Dpf|BsizeFlex*i|Bam|RdtmsHALF|Secrc);
953         }
954
955         if(cttab[ctlr->type].flag & Fert)
956                 csr32w(ctlr, Ert, 1024/8);
957
958         if(ctlr->type == i82566)
959                 csr32w(ctlr, Pbs, 16);
960
961         csr32w(ctlr, Rdbal, PCIWADDR(ctlr->rdba));
962         csr32w(ctlr, Rdbah, 0);
963         csr32w(ctlr, Rdlen, ctlr->nrd * sizeof(Rd));
964         ctlr->rdh = 0;
965         csr32w(ctlr, Rdh, 0);
966         ctlr->rdt = 0;
967         csr32w(ctlr, Rdt, 0);
968         ctlr->rdtr = 25;
969         ctlr->radv = 500;
970         csr32w(ctlr, Rdtr, ctlr->rdtr);
971         csr32w(ctlr, Radv, ctlr->radv);
972
973         for(i = 0; i < ctlr->nrd; i++)
974                 if((bp = ctlr->rb[i]) != nil){
975                         ctlr->rb[i] = nil;
976                         freeb(bp);
977                 }
978         if(cttab[ctlr->type].flag & F75)
979                 csr32w(ctlr, Rxdctl, 1<<WthreshSHIFT | 8<<PthreshSHIFT | 1<<HthreshSHIFT | Enable);
980         else
981                 csr32w(ctlr, Rxdctl, 2<<WthreshSHIFT | 2<<PthreshSHIFT);
982
983         /*
984          * Enable checksum offload.
985          */
986         csr32w(ctlr, Rxcsum, Tuofl | Ipofl | ETHERHDRSIZE);
987 }
988
989 static int
990 i82563rim(void *v)
991 {
992         return ((Ctlr*)v)->rim != 0;
993 }
994
995 static void
996 i82563rproc(void *arg)
997 {
998         uint rdh, rim, im;
999         Block *bp;
1000         Ctlr *ctlr;
1001         Ether *edev;
1002         Rd *rd;
1003
1004         edev = arg;
1005         ctlr = edev->ctlr;
1006
1007         i82563rxinit(ctlr);
1008         csr32w(ctlr, Rctl, csr32r(ctlr, Rctl) | Ren);
1009         if(cttab[ctlr->type].flag & F75){
1010                 csr32w(ctlr, Rxdctl, csr32r(ctlr, Rxdctl) | Enable);
1011                 im = Rxt0|Rxo|Rxdmt0|Rxseq|Ack;
1012         }else
1013                 im = Rxt0|Rxo|Rxdmt0|Rxseq|Ack;
1014
1015         while(waserror())
1016                 ;
1017         for(;;){
1018                 i82563im(ctlr, im);
1019                 ctlr->rsleep++;
1020                 i82563replenish(ctlr);
1021                 sleep(&ctlr->rrendez, i82563rim, ctlr);
1022
1023                 rdh = ctlr->rdh;
1024                 for(;;){
1025                         rim = ctlr->rim;
1026                         ctlr->rim = 0;
1027                         rd = &ctlr->rdba[rdh];
1028                         if(!(rd->status & Rdd))
1029                                 break;
1030
1031                         /*
1032                          * Accept eop packets with no errors.
1033                          * With no errors and the Ixsm bit set,
1034                          * the descriptor status Tpcs and Ipcs bits give
1035                          * an indication of whether the checksums were
1036                          * calculated and valid.
1037                          */
1038                         bp = ctlr->rb[rdh];
1039                         if((rd->status & Reop) && rd->errors == 0){
1040                                 bp->wp += rd->length;
1041                                 if(!(rd->status & Ixsm)){
1042                                         ctlr->ixsm++;
1043                                         if(rd->status & Ipcs){
1044                                                 /*
1045                                                  * IP checksum calculated
1046                                                  * (and valid as errors == 0).
1047                                                  */
1048                                                 ctlr->ipcs++;
1049                                                 bp->flag |= Bipck;
1050                                         }
1051                                         if(rd->status & Tcpcs){
1052                                                 /*
1053                                                  * TCP/UDP checksum calculated
1054                                                  * (and valid as errors == 0).
1055                                                  */
1056                                                 ctlr->tcpcs++;
1057                                                 bp->flag |= Btcpck|Budpck;
1058                                         }
1059                                         bp->checksum = rd->checksum;
1060                                         bp->flag |= Bpktck;
1061                                 }
1062                                 etheriq(edev, bp, 1);
1063                         } else
1064                                 freeb(bp);
1065                         ctlr->rb[rdh] = nil;
1066                         ctlr->rdfree--;
1067                         ctlr->rdh = rdh = NEXT(rdh, ctlr->nrd);
1068                         if(ctlr->nrd-ctlr->rdfree >= 32 || (rim & Rxdmt0))
1069                                 i82563replenish(ctlr);
1070                 }
1071         }
1072 }
1073
1074 static int
1075 i82563lim(void *v)
1076 {
1077         return ((Ctlr*)v)->lim != 0;
1078 }
1079
1080 static int speedtab[] = {
1081         10, 100, 1000, 0
1082 };
1083
1084 static uint
1085 phyread(Ctlr *c, int phyno, int reg)
1086 {
1087         uint phy, i;
1088
1089         csr32w(c, Mdic, MDIrop | phyno<<MDIpSHIFT | reg<<MDIrSHIFT);
1090         phy = 0;
1091         for(i = 0; i < 64; i++){
1092                 phy = csr32r(c, Mdic);
1093                 if(phy & (MDIe|MDIready))
1094                         break;
1095                 microdelay(1);
1096         }
1097         if((phy & (MDIe|MDIready)) != MDIready){
1098                 print("%s: phy %d wedged %.8ux\n", cttab[c->type].name, phyno, phy);
1099                 return ~0;
1100         }
1101         return phy & 0xffff;
1102 }
1103
1104 static uint
1105 phywrite0(Ctlr *c, int phyno, int reg, ushort val)
1106 {
1107         uint phy, i;
1108
1109         csr32w(c, Mdic, MDIwop | phyno<<MDIpSHIFT | reg<<MDIrSHIFT | val);
1110         phy = 0;
1111         for(i = 0; i < 64; i++){
1112                 phy = csr32r(c, Mdic);
1113                 if(phy & (MDIe|MDIready))
1114                         break;
1115                 microdelay(1);
1116         }
1117         if((phy & (MDIe|MDIready)) != MDIready)
1118                 return ~0;
1119         return 0;
1120 }
1121
1122 static uint
1123 setpage(Ctlr *c, uint phyno, uint p, uint r)
1124 {
1125         uint pr;
1126
1127         if(c->type == i82563){
1128                 if(r >= 16 && r <= 28 && r != 22)
1129                         pr = Phypage;
1130                 else if(r == 30 || r == 31)
1131                         pr = Phyapage;
1132                 else
1133                         return 0;
1134                 return phywrite0(c, phyno, pr, p);
1135         }else if(p == 0)
1136                 return 0;
1137         return ~0;
1138 }
1139
1140 static uint
1141 phywrite(Ctlr *c, uint phyno, uint reg, ushort v)
1142 {
1143         if(setpage(c, phyno, reg>>8, reg & 0xff) == ~0)
1144                 panic("%s: bad phy reg %.4ux", cname(c), reg);
1145         return phywrite0(c, phyno, reg & 0xff, v);
1146 }
1147
1148 static void
1149 phyerrata(Ether *e, Ctlr *c, uint phyno)
1150 {
1151         if(e->mbps == 0){
1152                 if(c->phyerrata == 0){
1153                         c->phyerrata++;
1154                         phywrite(c, phyno, Phyprst, Prst);      /* try a port reset */
1155                         print("%s: phy port reset\n", cname(c));
1156                 }
1157         }else
1158                 c->phyerrata = 0;
1159 }
1160
1161 static uint
1162 phyprobe(Ctlr *c, uint mask)
1163 {
1164         uint phy, phyno;
1165
1166         for(phyno=0; mask != 0; phyno++, mask>>=1){
1167                 if((mask & 1) == 0)
1168                         continue;
1169                 if(phyread(c, phyno, Physr) == ~0)
1170                         continue;
1171                 phy = (phyread(c, phyno, Phyid1) & 0x3FFF)<<6;
1172                 phy |= phyread(c, phyno, Phyid2) >> 10;
1173                 if(phy == 0xFFFFF || phy == 0)
1174                         continue;
1175                 print("%s: phy%d oui %#ux\n", cname(c), phyno, phy);
1176                 return phyno;
1177         }
1178         print("%s: no phy\n", cname(c));
1179         return ~0;
1180 }
1181
1182 static void
1183 phyl79proc(void *v)
1184 {
1185         uint a, i, r, phy, phyno;
1186         Ctlr *c;
1187         Ether *e;
1188
1189         e = v;
1190         c = e->ctlr;
1191
1192         phyno = phyprobe(c, 3<<1);
1193         if(phyno == ~0){
1194                 print("%s: no phy, exiting\n", up->text);
1195                 pexit("no phy", 1);
1196         }
1197
1198         while(waserror())
1199                 ;
1200         for(;;){
1201                 phy = phyread(c, phyno, Phystat);
1202                 if(phy == ~0){
1203                         phy = 0;
1204                         i = 3;
1205                         goto next;
1206                 }
1207                 i = (phy>>8) & 3;
1208                 a = phy & Ans;
1209                 if(a){
1210                         r = phyread(c, phyno, Phyctl);
1211                         phywrite(c, phyno, Phyctl, r | Ran | Ean);
1212                 }
1213 next:
1214                 e->link = i != 3 && (phy & Link) != 0;
1215                 if(e->link == 0)
1216                         i = 3;
1217                 c->speeds[i]++;
1218                 e->mbps = speedtab[i];
1219                 c->lim = 0;
1220                 i82563im(c, Lsc);
1221                 c->lsleep++;
1222                 sleep(&c->lrendez, i82563lim, c);
1223         }
1224 }
1225
1226 static void
1227 phylproc(void *v)
1228 {
1229         uint a, i, phy, phyno;
1230         Ctlr *c;
1231         Ether *e;
1232
1233         e = v;
1234         c = e->ctlr;
1235
1236         phyno = phyprobe(c, 3<<1);
1237         if(phyno == ~0){
1238                 print("%s: no phy, exiting\n", up->text);
1239                 pexit("no phy", 1);
1240         }
1241
1242         if(c->type == i82573 && (phy = phyread(c, phyno, Phyier)) != ~0)
1243                 phywrite(c, phyno, Phyier, phy | Lscie | Ancie | Spdie | Panie);
1244
1245         while(waserror())
1246                 ;
1247         for(;;){
1248                 phy = phyread(c, phyno, Physsr);
1249                 if(phy == ~0){
1250                         phy = 0;
1251                         i = 3;
1252                         goto next;
1253                 }
1254                 i = (phy>>14) & 3;
1255                 switch(c->type){
1256                 default:
1257                         a = 0;
1258                         break;
1259                 case i82563:
1260                 case i82578:
1261                 case i82578m:
1262                 case i82583:
1263                         a = phyread(c, phyno, Phyisr) & Ane;
1264                         break;
1265                 case i82571:
1266                 case i82572:
1267                 case i82575:
1268                 case i82576:
1269                         a = phyread(c, phyno, Phylhr) & Anf;
1270                         i = (i-1) & 3;
1271                         break;
1272                 }
1273                 if(a)
1274                         phywrite(c, phyno, Phyctl, phyread(c, phyno, Phyctl) | Ran | Ean);
1275 next:
1276                 e->link = (phy & Rtlink) != 0;
1277                 if(e->link == 0)
1278                         i = 3;
1279                 c->speeds[i]++;
1280                 e->mbps = speedtab[i];
1281                 if(c->type == i82563)
1282                         phyerrata(e, c, phyno);
1283                 c->lim = 0;
1284                 i82563im(c, Lsc);
1285                 c->lsleep++;
1286                 sleep(&c->lrendez, i82563lim, c);
1287         }
1288 }
1289
1290 static void
1291 pcslproc(void *v)
1292 {
1293         uint i, phy;
1294         Ctlr *c;
1295         Ether *e;
1296
1297         e = v;
1298         c = e->ctlr;
1299
1300         if(c->type == i82575 || c->type == i82576)
1301                 csr32w(c, Connsw, Enrgirq);
1302         while(waserror())
1303                 ;
1304         for(;;){
1305                 phy = csr32r(c, Pcsstat);
1306                 e->link = phy & Linkok;
1307                 i = 3;
1308                 if(e->link)
1309                         i = (phy & 6) >> 1;
1310                 else if(phy & Anbad)
1311                         csr32w(c, Pcsctl, csr32r(c, Pcsctl) | Pan | Prestart);
1312                 c->speeds[i]++;
1313                 e->mbps = speedtab[i];
1314                 c->lim = 0;
1315                 i82563im(c, Lsc | Omed);
1316                 c->lsleep++;
1317                 sleep(&c->lrendez, i82563lim, c);
1318         }
1319 }
1320
1321 static void
1322 serdeslproc(void *v)
1323 {
1324         uint i, tx, rx;
1325         Ctlr *c;
1326         Ether *e;
1327
1328         e = v;
1329         c = e->ctlr;
1330
1331         while(waserror())
1332                 ;
1333         for(;;){
1334                 rx = csr32r(c, Rxcw);
1335                 tx = csr32r(c, Txcw);
1336                 USED(tx);
1337                 e->link = (rx & 1<<31) != 0;
1338 //              e->link = (csr32r(c, Status) & Lu) != 0;
1339                 i = 3;
1340                 if(e->link)
1341                         i = 2;
1342                 c->speeds[i]++;
1343                 e->mbps = speedtab[i];
1344                 c->lim = 0;
1345                 i82563im(c, Lsc);
1346                 c->lsleep++;
1347                 sleep(&c->lrendez, i82563lim, c);
1348         }
1349 }
1350
1351 static void
1352 i82563attach(Ether *edev)
1353 {
1354         char name[KNAMELEN];
1355         Ctlr *ctlr;
1356
1357         ctlr = edev->ctlr;
1358         qlock(&ctlr->alock);
1359         if(ctlr->alloc != nil){
1360                 qunlock(&ctlr->alock);
1361                 return;
1362         }
1363
1364         ctlr->nrd = Nrd;
1365         ctlr->ntd = Ntd;
1366         ctlr->alloc = malloc(ctlr->nrd*sizeof(Rd)+ctlr->ntd*sizeof(Td) + 255);
1367         ctlr->rb = malloc(ctlr->nrd * sizeof(Block*));
1368         ctlr->tb = malloc(ctlr->ntd * sizeof(Block*));
1369         if(ctlr->alloc == nil || ctlr->rb == nil || ctlr->tb == nil){
1370                 free(ctlr->rb);
1371                 ctlr->rb = nil;
1372                 free(ctlr->tb);
1373                 ctlr->tb = nil;
1374                 free(ctlr->alloc);
1375                 ctlr->alloc = nil;
1376                 qunlock(&ctlr->alock);
1377                 error(Enomem);
1378         }
1379         ctlr->rdba = (Rd*)ROUNDUP((uintptr)ctlr->alloc, 256);
1380         ctlr->tdba = (Td*)(ctlr->rdba + ctlr->nrd);
1381
1382         if(waserror()){
1383                 free(ctlr->tb);
1384                 ctlr->tb = nil;
1385                 free(ctlr->rb);
1386                 ctlr->rb = nil;
1387                 free(ctlr->alloc);
1388                 ctlr->alloc = nil;
1389                 qunlock(&ctlr->alock);
1390                 nexterror();
1391         }
1392
1393         snprint(name, sizeof name, "#l%dl", edev->ctlrno);
1394         if(csr32r(ctlr, Status) & Tbimode)
1395                 kproc(name, serdeslproc, edev);         /* mac based serdes */
1396         else if((csr32r(ctlr, Ctrlext) & Linkmode) == Serdes)
1397                 kproc(name, pcslproc, edev);            /* phy based serdes */
1398         else if(cttab[ctlr->type].flag & F79phy)
1399                 kproc(name, phyl79proc, edev);
1400         else
1401                 kproc(name, phylproc, edev);
1402
1403         snprint(name, sizeof name, "#l%dr", edev->ctlrno);
1404         kproc(name, i82563rproc, edev);
1405
1406         snprint(name, sizeof name, "#l%dt", edev->ctlrno);
1407         kproc(name, i82563tproc, edev);
1408
1409         qunlock(&ctlr->alock);
1410         poperror();
1411 }
1412
1413 static void
1414 i82563interrupt(Ureg*, void *arg)
1415 {
1416         Ctlr *ctlr;
1417         Ether *edev;
1418         int icr, im;
1419
1420         edev = arg;
1421         ctlr = edev->ctlr;
1422
1423         ilock(&ctlr->imlock);
1424         csr32w(ctlr, Imc, ~0);
1425         im = ctlr->im;
1426
1427         while(icr = csr32r(ctlr, Icr) & ctlr->im){
1428                 if(icr & (Lsc | Omed)){
1429                         im &= ~(Lsc | Omed);
1430                         ctlr->lim = icr & (Lsc | Omed);
1431                         wakeup(&ctlr->lrendez);
1432                         ctlr->lintr++;
1433                 }
1434                 if(icr & (Rxt0|Rxo|Rxdmt0|Rxseq|Ack)){
1435                         ctlr->rim = icr & (Rxt0|Rxo|Rxdmt0|Rxseq|Ack);
1436                         im &= ~(Rxt0|Rxo|Rxdmt0|Rxseq|Ack);
1437                         wakeup(&ctlr->rrendez);
1438                         ctlr->rintr++;
1439                 }
1440                 if(icr & Txdw){
1441                         im &= ~Txdw;
1442                         ctlr->tintr++;
1443                         wakeup(&ctlr->trendez);
1444                 }
1445         }
1446
1447         ctlr->im = im;
1448         csr32w(ctlr, Ims, im);
1449         iunlock(&ctlr->imlock);
1450 }
1451
1452 static int
1453 i82563detach(Ctlr *ctlr)
1454 {
1455         int r, timeo;
1456
1457         /* balance rx/tx packet buffer; survives reset */
1458         if(ctlr->rbsz > 8192 && cttab[ctlr->type].flag & Fpba){
1459                 ctlr->pba = csr32r(ctlr, Pba);
1460                 r = ctlr->pba >> 16;
1461                 r += ctlr->pba & 0xffff;
1462                 r >>= 1;
1463                 csr32w(ctlr, Pba, r);
1464         }else if(ctlr->type == i82573 && ctlr->rbsz > 1514)
1465                 csr32w(ctlr, Pba, 14);
1466         ctlr->pba = csr32r(ctlr, Pba);
1467
1468         /*
1469          * Perform a device reset to get the chip back to the
1470          * power-on state, followed by an EEPROM reset to read
1471          * the defaults for some internal registers.
1472          */
1473         csr32w(ctlr, Imc, ~0);
1474         csr32w(ctlr, Rctl, 0);
1475         csr32w(ctlr, Tctl, csr32r(ctlr, Tctl) & ~Ten);
1476
1477         delay(10);
1478
1479         r = csr32r(ctlr, Ctrl);
1480         if(ctlr->type == i82566 || ctlr->type == i82579)
1481                 r |= Phyrst;
1482         /*
1483          * hack: 82579LM on lenovo X230 is stuck at 10mbps after
1484          * reseting the phy, but works fine if we dont reset.
1485          */
1486         if(ctlr->pcidev->did == 0x1502)
1487                 r &= ~Phyrst;
1488         csr32w(ctlr, Ctrl, Devrst | r);
1489         delay(1);
1490         for(timeo = 0;; timeo++){
1491                 if((csr32r(ctlr, Ctrl) & (Devrst|Phyrst)) == 0)
1492                         break;
1493                 if(timeo >= 1000)
1494                         return -1;
1495                 delay(1);
1496         }
1497
1498         r = csr32r(ctlr, Ctrl);
1499         csr32w(ctlr, Ctrl, Slu|r);
1500
1501         r = csr32r(ctlr, Ctrlext);
1502         csr32w(ctlr, Ctrlext, r|Eerst);
1503         delay(1);
1504         for(timeo = 0; timeo < 1000; timeo++){
1505                 if(!(csr32r(ctlr, Ctrlext) & Eerst))
1506                         break;
1507                 delay(1);
1508         }
1509         if(csr32r(ctlr, Ctrlext) & Eerst)
1510                 return -1;
1511
1512         csr32w(ctlr, Imc, ~0);
1513         delay(1);
1514         for(timeo = 0; timeo < 1000; timeo++){
1515                 if((csr32r(ctlr, Icr) & ~Rxcfg) == 0)
1516                         break;
1517                 delay(1);
1518         }
1519         if(csr32r(ctlr, Icr) & ~Rxcfg)
1520                 return -1;
1521
1522         return 0;
1523 }
1524
1525 static void
1526 i82563shutdown(Ether *edev)
1527 {
1528         i82563detach(edev->ctlr);
1529 }
1530
1531 static int
1532 eeread(Ctlr *ctlr, int adr)
1533 {
1534         int timeout;
1535
1536         csr32w(ctlr, Eerd, EEstart | adr << 2);
1537         timeout = 1000;
1538         while ((csr32r(ctlr, Eerd) & EEdone) == 0 && timeout--)
1539                 microdelay(5);
1540         if (timeout < 0) {
1541                 print("%s: eeread timeout\n", cname(ctlr));
1542                 return -1;
1543         }
1544         return (csr32r(ctlr, Eerd) >> 16) & 0xffff;
1545 }
1546
1547 static int
1548 eeload(Ctlr *ctlr)
1549 {
1550         u16int sum;
1551         int data, adr;
1552
1553         sum = 0;
1554         for (adr = 0; adr < 0x40; adr++) {
1555                 data = eeread(ctlr, adr);
1556                 if(data == -1) return -1;
1557                 ctlr->eeprom[adr] = data;
1558                 sum += data;
1559         }
1560         return sum;
1561 }
1562
1563 static int
1564 fread16(Ctlr *c, Flash *f, int ladr)
1565 {
1566         u16int s;
1567         int timeout;
1568
1569         delay(1);
1570         s = f->reg[Fsts];
1571         if((s&Fvalid) == 0)
1572                 return -1;
1573         f->reg[Fsts] |= Fcerr | Ael;
1574         for(timeout = 0; timeout < 10; timeout++){
1575                 if((s&Scip) == 0)
1576                         goto done;
1577                 delay(1);
1578                 s = f->reg[Fsts];
1579         }
1580         return -1;
1581 done:
1582         f->reg[Fsts] |= Fdone;
1583         f->reg32[Faddr] = ladr;
1584
1585         /* setup flash control register */
1586         s = f->reg[Fctl] & ~0x3ff;
1587         f->reg[Fctl] = s | 1<<8 | Fgo;  /* 2 byte read */
1588         timeout = 1000;
1589         while((f->reg[Fsts] & Fdone) == 0 && timeout--)
1590                 microdelay(5);
1591         if(timeout < 0){
1592                 print("%s: fread timeout\n", cname(c));
1593                 return -1;
1594         }
1595         if(f->reg[Fsts] & (Fcerr|Ael))
1596                 return -1;
1597         return f->reg32[Fdata] & 0xffff;
1598 }
1599
1600 static int
1601 fread32(Ctlr *c, Flash *f, int ladr, u32int *data)
1602 {
1603         u32int s;
1604         int timeout;
1605
1606         delay(1);
1607         s = f->reg32[Fsts/2];
1608         if((s&Fvalid) == 0)
1609                 return -1;
1610         f->reg32[Fsts/2] |= Fcerr | Ael;
1611         for(timeout = 0; timeout < 10; timeout++){
1612                 if((s&Scip) == 0)
1613                         goto done;
1614                 delay(1);
1615                 s = f->reg32[Fsts/2];
1616         }
1617         return -1;
1618 done:
1619         f->reg32[Fsts/2] |= Fdone;
1620         f->reg32[Faddr] = ladr;
1621
1622         /* setup flash control register */
1623         s = (f->reg32[Fctl/2] >> 16) & ~0x3ff;
1624         f->reg32[Fctl/2] = (s | 3<<8 | Fgo) << 16;      /* 4 byte read */
1625         timeout = 1000;
1626         while((f->reg32[Fsts/2] & Fdone) == 0 && timeout--)
1627                 microdelay(5);
1628         if(timeout < 0){
1629                 print("%s: fread timeout\n", cname(c));
1630                 return -1;
1631         }
1632         if(f->reg32[Fsts/2] & (Fcerr|Ael))
1633                 return -1;
1634         *data = f->reg32[Fdata];
1635         return 0;
1636 }
1637
1638 static int
1639 fload32(Ctlr *c)
1640 {
1641         int r, adr;
1642         u16int sum;
1643         u32int w;
1644         Flash f;
1645
1646         f.reg32 = &c->nic[0xe000/4];
1647         f.reg = nil;
1648         f.base = 0;
1649         f.lim = (((csr32r(c, 0xC) >> 1) & 0x1F) + 1) << 12;
1650         r = f.lim >> 1;
1651         if(fread32(c, &f, r + 0x24, &w) == -1  || (w & 0xC000) != 0x8000)
1652                 r = 0;
1653         sum = 0;
1654         for(adr = 0; adr < 0x20; adr++) {
1655                 if(fread32(c, &f, r + adr*4, &w) == -1)
1656                         return -1;
1657                 c->eeprom[adr*2+0] = w;
1658                 c->eeprom[adr*2+1] = w>>16;
1659                 sum += w & 0xFFFF;
1660                 sum += w >> 16;
1661         }
1662         return sum;
1663 }
1664
1665 static int
1666 fload(Ctlr *c)
1667 {
1668         int data, r, adr;
1669         u16int sum;
1670         void *va;
1671         Flash f;
1672
1673         memset(c->eeprom, 0xFF, sizeof(c->eeprom));
1674         if(c->pcidev->mem[1].bar == 0)
1675                 return fload32(c);      /* i219 */
1676
1677         va = vmap(c->pcidev->mem[1].bar & ~0x0f, c->pcidev->mem[1].size);
1678         if(va == nil)
1679                 return -1;
1680         f.reg = va;
1681         f.reg32 = va;
1682         f.base = f.reg32[Bfpr] & 0x1fff;
1683         f.lim = f.reg32[Bfpr]>>16 & 0x1fff;
1684         if(csr32r(c, Eec) & Sec1val)
1685                 f.base += f.lim+1 - f.base >> 1;
1686         r = f.base << 12;
1687         sum = 0;
1688         for(adr = 0; adr < 0x40; adr++) {
1689                 data = fread16(c, &f, r + adr*2);
1690                 if(data == -1)
1691                         goto out;
1692                 c->eeprom[adr] = data;
1693                 sum += data;
1694         }
1695 out:
1696         vunmap(va, c->pcidev->mem[1].size);
1697         return sum;
1698 }
1699
1700 static void
1701 defaultea(Ctlr *ctlr, uchar *ra)
1702 {
1703         uint i, r;
1704         uvlong u;
1705         static uchar nilea[Eaddrlen];
1706
1707         if(memcmp(ra, nilea, Eaddrlen) != 0)
1708                 return;
1709         if(cttab[ctlr->type].flag & Fflashea){
1710                 /* intel mb bug */
1711                 u = (uvlong)csr32r(ctlr, Rah)<<32u | (ulong)csr32r(ctlr, Ral);
1712                 for(i = 0; i < Eaddrlen; i++)
1713                         ra[i] = u >> 8*i;
1714         }
1715         if(memcmp(ra, nilea, Eaddrlen) != 0)
1716                 return;
1717         for(i = 0; i < Eaddrlen/2; i++){
1718                 ra[2*i] = ctlr->eeprom[Ea+i];
1719                 ra[2*i+1] = ctlr->eeprom[Ea+i] >> 8;
1720         }
1721         r = (csr32r(ctlr, Status) & Lanid) >> 2;
1722         ra[5] += r;                             /* ea ctlr[n] = ea ctlr[0]+n */
1723 }
1724
1725 static int
1726 i82563reset(Ctlr *ctlr)
1727 {
1728         uchar *ra;
1729         int i, r;
1730
1731         if(i82563detach(ctlr))
1732                 return -1;
1733         if(cttab[ctlr->type].flag & Fload)
1734                 r = fload(ctlr);
1735         else
1736                 r = eeload(ctlr);
1737         if(r != 0 && r != 0xbaba){
1738                 print("%s: bad eeprom checksum - %#.4ux", cname(ctlr), r);
1739                 if(cttab[ctlr->type].flag & Fbadcsum)
1740                         print("; ignored\n");
1741                 else {
1742                         print("\n");
1743                         return -1;
1744                 }
1745         }
1746
1747         ra = ctlr->ra;
1748         defaultea(ctlr, ra);
1749         csr32w(ctlr, Ral, ra[3]<<24 | ra[2]<<16 | ra[1]<<8 | ra[0]);
1750         csr32w(ctlr, Rah, 1<<31 | ra[5]<<8 | ra[4]);
1751         for(i = 1; i < 16; i++){
1752                 csr32w(ctlr, Ral+i*8, 0);
1753                 csr32w(ctlr, Rah+i*8, 0);
1754         }
1755         memset(ctlr->mta, 0, sizeof(ctlr->mta));
1756         for(i = 0; i < 128; i++)
1757                 csr32w(ctlr, Mta + i*4, 0);
1758         csr32w(ctlr, Fcal, 0x00C28001);
1759         csr32w(ctlr, Fcah, 0x0100);
1760         if((cttab[ctlr->type].flag & Fnofct) == 0)
1761                 csr32w(ctlr, Fct, 0x8808);
1762         csr32w(ctlr, Fcttv, 0x0100);
1763         csr32w(ctlr, Fcrtl, ctlr->fcrtl);
1764         csr32w(ctlr, Fcrth, ctlr->fcrth);
1765         if(cttab[ctlr->type].flag & F75)
1766                 csr32w(ctlr, Eitr, 128<<2);             /* 128 ¼ microsecond intervals */
1767         return 0;
1768 }
1769
1770 enum {
1771         CMrdtr,
1772         CMradv,
1773         CMpause,
1774         CMan,
1775 };
1776
1777 static Cmdtab i82563ctlmsg[] = {
1778         CMrdtr, "rdtr", 2,
1779         CMradv, "radv", 2,
1780         CMpause, "pause", 1,
1781         CMan,   "an",   1,
1782 };
1783
1784 static long
1785 i82563ctl(Ether *edev, void *buf, long n)
1786 {
1787         char *p;
1788         ulong v;
1789         Ctlr *ctlr;
1790         Cmdbuf *cb;
1791         Cmdtab *ct;
1792
1793         if((ctlr = edev->ctlr) == nil)
1794                 error(Enonexist);
1795
1796         cb = parsecmd(buf, n);
1797         if(waserror()){
1798                 free(cb);
1799                 nexterror();
1800         }
1801
1802         ct = lookupcmd(cb, i82563ctlmsg, nelem(i82563ctlmsg));
1803         switch(ct->index){
1804         case CMrdtr:
1805                 v = strtoul(cb->f[1], &p, 0);
1806                 if(*p || v > 0xffff)
1807                         error(Ebadarg);
1808                 ctlr->rdtr = v;
1809                 csr32w(ctlr, Rdtr, v);
1810                 break;
1811         case CMradv:
1812                 v = strtoul(cb->f[1], &p, 0);
1813                 if(*p || v > 0xffff)
1814                         error(Ebadarg);
1815                 ctlr->radv = v;
1816                 csr32w(ctlr, Radv, v);
1817                 break;
1818         case CMpause:
1819                 csr32w(ctlr, Ctrl, csr32r(ctlr, Ctrl) ^ (Rfce | Tfce));
1820                 break;
1821         case CMan:
1822                 csr32w(ctlr, Ctrl, csr32r(ctlr, Ctrl) | Lrst | Phyrst);
1823                 break;
1824         }
1825         free(cb);
1826         poperror();
1827
1828         return n;
1829 }
1830
1831 static int
1832 didtype(int d)
1833 {
1834         /*
1835          * Some names and did values are from
1836          * OpenBSD's em(4) Intel driver.
1837          */
1838         switch(d){
1839         case 0x1096:            /* copper */
1840         case 0x10ba:            /* copper “gilgal” */
1841         case 0x1098:            /* serdes; not seen */
1842         case 0x10bb:            /* serdes */
1843                 return i82563;
1844         case 0x1049:            /* ich8; mm */
1845         case 0x104a:            /* ich8; dm */
1846         case 0x104b:            /* ich8; dc */
1847         case 0x104d:            /* ich8; v “ninevah” */
1848         case 0x10bd:            /* ich9; dm-2 */
1849         case 0x294c:            /* ich9 */
1850         case 0x104c:            /* ich8; untested */
1851         case 0x10c4:            /* ich8; untested */
1852         case 0x10c5:            /* ich8; untested */
1853                 return i82566;
1854         case 0x10de:            /* lm ich10d */
1855         case 0x10df:            /* lf ich10 */
1856         case 0x10e5:            /* lm ich9 */
1857         case 0x10f5:            /* lm ich9m; “boazman” */
1858         case 0x10ce:            /* v ich10 */
1859         case 0x10c0:            /* ich9 */
1860         case 0x10c2:            /* ich9; untested */
1861         case 0x10c3:            /* ich9; untested */
1862         case 0x1501:            /* ich8; untested */
1863                 return i82567;
1864         case 0x10bf:            /* lf ich9m */
1865         case 0x10cb:            /* v ich9m */
1866         case 0x10cd:            /* lf ich10 */
1867         case 0x10cc:            /* lm ich10 */
1868                 return i82567m;
1869         case 0x105e:            /* eb copper */
1870         case 0x105f:            /* eb fiber */
1871         case 0x1060:            /* eb serdes */
1872         case 0x10a4:            /* eb copper */
1873         case 0x10a5:            /* eb fiber */
1874         case 0x10bc:            /* eb copper */
1875         case 0x10d9:            /* eb serdes */
1876         case 0x10da:            /* eb serdes “ophir” */
1877         case 0x10a0:            /* eb; untested */
1878         case 0x10a1:            /* eb; untested */
1879         case 0x10d5:            /* copper; untested */
1880                 return i82571;
1881         case 0x107d:            /* ei copper */
1882         case 0x107e:            /* ei fiber */
1883         case 0x107f:            /* ei serdes */
1884         case 0x10b9:            /* ei “rimon” */
1885                 return i82572;
1886         case 0x108b:            /* e “vidalia” */
1887         case 0x108c:            /* e (iamt) */
1888         case 0x109a:            /* l “tekoa” */
1889         case 0x10b0:            /* l; untested */
1890         case 0x10b2:            /* v; untested */
1891         case 0x10b3:            /* e; untested */
1892         case 0x10b4:            /* l; untested */
1893                 return i82573;
1894         case 0x10d3:            /* l or it; “hartwell” */
1895         case 0x10f6:            /* la; untested */
1896                 return i82574;
1897         case 0x10a7:            /* eb */
1898         case 0x10a9:            /* eb fiber/serdes */
1899         case 0x10d6:            /* untested */
1900         case 0x10e2:            /* untested */
1901                 return i82575;
1902         case 0x10c9:            /* copper */
1903         case 0x10e6:            /* fiber */
1904         case 0x10e7:            /* serdes; “kawela” */
1905         case 0x10e8:            /* copper; untested */
1906         case 0x150a:            /* untested */
1907         case 0x150d:            /* serdes backplane */
1908         case 0x1518:            /* serdes; untested */
1909         case 0x1526:            /* untested */
1910                 return i82576;
1911         case 0x10ea:            /* lc “calpella”; aka pch lan */
1912                 return i82577;
1913         case 0x10eb:            /* lm “calpella” */
1914                 return i82577m;
1915         case 0x10ef:            /* dc “piketon” */
1916                 return i82578;
1917         case 0x1502:            /* lm */
1918         case 0x1503:            /* v “lewisville” */
1919                 return i82579;
1920         case 0x10f0:            /* dm “king's creek” */
1921                 return i82578m;
1922         case 0x150e:            /* copper “barton hills” */
1923         case 0x150f:            /* fiber */
1924         case 0x1510:            /* serdes backplane */
1925         case 0x1511:            /* sgmii sfp */
1926         case 0x1516:            /* copper */
1927                 return i82580;
1928         case 0x1506:            /* v */
1929         case 0x150c:            /* untested */
1930                 return i82583;
1931         case 0x1533:            /* copper */
1932                 return i210;
1933         case 0x153a:            /* i217-lm */
1934         case 0x153b:            /* i217-v */
1935                 return i217;
1936         case 0x1559:            /* i218-v */
1937         case 0x155a:            /* i218-lm */
1938         case 0x15a0:            /* i218-lm */
1939         case 0x15a1:            /* i218-v */
1940         case 0x15a2:            /* i218-lm */
1941         case 0x15a3:            /* i218-v */
1942                 return i218;
1943         case 0x156f:            /* i219-lm */
1944         case 0x15b7:            /* i219-lm */
1945         case 0x1570:            /* i219-v */
1946         case 0x15b8:            /* i219-v */
1947         case 0x15b9:            /* i219-lm */
1948         case 0x15d6:            /* i219-v */
1949         case 0x15d7:            /* i219-lm */
1950         case 0x15d8:            /* i219-v */
1951         case 0x15e3:            /* i219-lm */
1952                 return i219;
1953         case 0x151f:            /* “powerville” eeprom-less */
1954         case 0x1521:            /* copper */
1955         case 0x1522:            /* fiber */
1956         case 0x1523:            /* serdes */
1957         case 0x1524:            /* sgmii */
1958         case 0x1546:            /* untested */
1959                 return i350;
1960         }
1961         return -1;
1962 }
1963
1964 static void
1965 hbafixup(Pcidev *p)
1966 {
1967         uint i;
1968
1969         i = pcicfgr32(p, PciSVID);
1970         if((i & 0xffff) == 0x1b52 && p->did == 1)
1971                 p->did = i>>16;
1972 }
1973
1974 static void
1975 i82563pci(void)
1976 {
1977         int type;
1978         Ctlr *ctlr;
1979         Pcidev *p;
1980
1981         for(p = nil; p = pcimatch(p, 0x8086, 0);){
1982                 hbafixup(p);
1983                 if((type = didtype(p->did)) == -1)
1984                         continue;
1985                 ctlr = malloc(sizeof(Ctlr));
1986                 if(ctlr == nil){
1987                         print("%s: can't allocate memory\n", cttab[type].name);
1988                         continue;
1989                 }
1990                 ctlr->type = type;
1991                 ctlr->pcidev = p;
1992                 ctlr->rbsz = cttab[type].mtu;
1993                 ctlr->port = p->mem[0].bar & ~0x0F;
1994                 if(i82563ctlrhead != nil)
1995                         i82563ctlrtail->next = ctlr;
1996                 else
1997                         i82563ctlrhead = ctlr;
1998                 i82563ctlrtail = ctlr;
1999         }
2000 }
2001
2002 static int
2003 setup(Ctlr *ctlr)
2004 {
2005         Pcidev *p;
2006
2007         p = ctlr->pcidev;
2008         ctlr->nic = vmap(ctlr->port, p->mem[0].size);
2009         if(ctlr->nic == nil){
2010                 print("%s: can't map 0x%lux\n", cname(ctlr), ctlr->port);
2011                 return -1;
2012         }
2013         if(i82563reset(ctlr)){
2014                 vunmap(ctlr->nic, p->mem[0].size);
2015                 return -1;
2016         }
2017         pcisetbme(ctlr->pcidev);
2018         return 0;
2019 }
2020
2021 static int
2022 pnp(Ether *edev, int type)
2023 {
2024         Ctlr *ctlr;
2025         static int done;
2026
2027         if(!done) {
2028                 i82563pci();
2029                 done = 1;
2030         }
2031
2032         /*
2033          * Any adapter matches if no edev->port is supplied,
2034          * otherwise the ports must match.
2035          */
2036         for(ctlr = i82563ctlrhead; ; ctlr = ctlr->next){
2037                 if(ctlr == nil)
2038                         return -1;
2039                 if(ctlr->active)
2040                         continue;
2041                 if(type != -1 && ctlr->type != type)
2042                         continue;
2043                 if(edev->port == 0 || edev->port == ctlr->port){
2044                         ctlr->active = 1;
2045                         memmove(ctlr->ra, edev->ea, Eaddrlen);
2046                         if(setup(ctlr) == 0)
2047                                 break;
2048                 }
2049         }
2050
2051         edev->ctlr = ctlr;
2052         edev->port = ctlr->port;
2053         edev->irq = ctlr->pcidev->intl;
2054         edev->tbdf = ctlr->pcidev->tbdf;
2055         edev->mbps = 1000;
2056         edev->maxmtu = ctlr->rbsz;
2057         memmove(edev->ea, ctlr->ra, Eaddrlen);
2058
2059         /*
2060          * Linkage to the generic ethernet driver.
2061          */
2062         edev->attach = i82563attach;
2063 //      edev->transmit = i82563transmit;
2064         edev->interrupt = i82563interrupt;
2065         edev->ifstat = i82563ifstat;
2066         edev->ctl = i82563ctl;
2067
2068         edev->arg = edev;
2069         edev->promiscuous = i82563promiscuous;
2070         edev->shutdown = i82563shutdown;
2071         edev->multicast = i82563multicast;
2072
2073         return 0;
2074 }
2075
2076 static int
2077 anypnp(Ether *e)
2078 {
2079         return pnp(e, -1);
2080 }
2081
2082 static int
2083 i82563pnp(Ether *e)
2084 {
2085         return pnp(e, i82563);
2086 }
2087
2088 static int
2089 i82566pnp(Ether *e)
2090 {
2091         return pnp(e, i82566);
2092 }
2093
2094 static int
2095 i82567pnp(Ether *e)
2096 {
2097         return pnp(e, i82567m) & pnp(e, i82567);
2098 }
2099
2100 static int
2101 i82571pnp(Ether *e)
2102 {
2103         return pnp(e, i82571);
2104 }
2105
2106 static int
2107 i82572pnp(Ether *e)
2108 {
2109         return pnp(e, i82572);
2110 }
2111
2112 static int
2113 i82573pnp(Ether *e)
2114 {
2115         return pnp(e, i82573);
2116 }
2117
2118 static int
2119 i82574pnp(Ether *e)
2120 {
2121         return pnp(e, i82574);
2122 }
2123
2124 static int
2125 i82575pnp(Ether *e)
2126 {
2127         return pnp(e, i82575);
2128 }
2129
2130 static int
2131 i82576pnp(Ether *e)
2132 {
2133         return pnp(e, i82576);
2134 }
2135
2136 static int
2137 i82577pnp(Ether *e)
2138 {
2139         return pnp(e, i82577m) & pnp(e, i82577);
2140 }
2141
2142 static int
2143 i82578pnp(Ether *e)
2144 {
2145         return pnp(e, i82578m) & pnp(e, i82578);
2146 }
2147
2148 static int
2149 i82579pnp(Ether *e)
2150 {
2151         return pnp(e, i82579);
2152 }
2153
2154 static int
2155 i82580pnp(Ether *e)
2156 {
2157         return pnp(e, i82580);
2158 }
2159
2160 static int
2161 i82583pnp(Ether *e)
2162 {
2163         return pnp(e, i82583);
2164 }
2165
2166 static int
2167 i210pnp(Ether *e)
2168 {
2169         return pnp(e, i210);
2170 }
2171
2172 static int
2173 i217pnp(Ether *e)
2174 {
2175         return pnp(e, i217);
2176 }
2177
2178 static int
2179 i218pnp(Ether *e)
2180 {
2181         return pnp(e, i218);
2182 }
2183
2184 static int
2185 i219pnp(Ether *e)
2186 {
2187         return pnp(e, i219);
2188 }
2189
2190 static int
2191 i350pnp(Ether *e)
2192 {
2193         return pnp(e, i350);
2194 }
2195
2196 void
2197 ether82563link(void)
2198 {
2199         /*
2200          * recognise lots of model numbers for debugging
2201          * also good for forcing onboard nic(s) as ether0
2202          * try to make that unnecessary by listing lom first.
2203          */
2204         addethercard("i82563", i82563pnp);
2205         addethercard("i82566", i82566pnp);
2206         addethercard("i82574", i82574pnp);
2207         addethercard("i82576", i82576pnp);
2208         addethercard("i82567", i82567pnp);
2209         addethercard("i82573", i82573pnp);
2210
2211         addethercard("i82571", i82571pnp);
2212         addethercard("i82572", i82572pnp);
2213         addethercard("i82575", i82575pnp);
2214         addethercard("i82577", i82577pnp);
2215         addethercard("i82578", i82578pnp);
2216         addethercard("i82579", i82579pnp);
2217         addethercard("i82580", i82580pnp);
2218         addethercard("i82583", i82583pnp);
2219         addethercard("i210", i210pnp);
2220         addethercard("i217", i217pnp);
2221         addethercard("i218", i218pnp);
2222         addethercard("i219", i219pnp);
2223         addethercard("i350", i350pnp);
2224         addethercard("igbepcie", anypnp);
2225 }