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