]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc/ether82563.c
6fea78ce8c532bf377060e8e2c83b1c35d405a83
[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 };
420
421 /*
422  * cavet emptor: 82577/78 have been entered speculatitively.
423  * awating datasheet from intel.
424  */
425 enum {
426         i82563,
427         i82566,
428         i82567,
429         i82567m,
430         i82571,
431         i82572,
432         i82573,
433         i82574,
434         i82575,
435         i82576,
436         i82577,
437         i82577m,        
438         i82578,
439         i82578m,
440         i82579,
441         i82580,
442         i82583,
443         i350,
444         Nctlrtype,
445 };
446
447 enum {
448         Fload   = 1<<0,
449         Fert    = 1<<1,
450         F75     = 1<<2,
451         Fpba    = 1<<3,
452         Fflashea= 1<<4,
453         F79phy  = 1<<5,
454 };
455
456 typedef struct Ctlrtype Ctlrtype;
457 struct Ctlrtype {
458         int     type;
459         int     mtu;
460         int     flag;
461         char    *name;
462 };
463
464 static Ctlrtype cttab[Nctlrtype] = {
465         i82563,         9014,   Fpba,           "i82563",
466         i82566,         1514,   Fload,          "i82566",
467         i82567,         9234,   Fload,          "i82567",
468         i82567m,        1514,   Fload,          "i82567m",
469         i82571,         9234,   Fpba,           "i82571",
470         i82572,         9234,   Fpba,           "i82572",
471         i82573,         8192,   Fert,           "i82573",               /* terrible perf above 8k */
472         i82574,         9018,   0,              "i82574",
473         i82575,         9728,   F75|Fflashea,   "i82575",
474         i82576,         9728,   F75,            "i82576",
475         i82577,         4096,   Fload|Fert,     "i82577",
476         i82577m,        1514,   Fload|Fert,     "i82577",
477         i82578,         4096,   Fload|Fert,     "i82578",
478         i82578m,        1514,   Fload|Fert,     "i82578",
479         i82579,         9018,   Fload|Fert|F79phy,      "i82579",
480         i82580,         9728,   F75|F79phy,     "i82580",
481         i82583,         1514,   0,              "i82583",
482         i350,           9728,   F75|F79phy,     "i350",
483 };
484
485 typedef void (*Freefn)(Block*);
486
487 typedef struct Ctlr Ctlr;
488 struct Ctlr {
489         ulong   port;
490         Pcidev  *pcidev;
491         Ctlr    *next;
492         int     active;
493         int     type;
494         u16int  eeprom[0x40];
495
496         QLock   alock;                  /* attach */
497         void    *alloc;                 /* receive/transmit descriptors */
498         int     nrd;
499         int     ntd;
500         uint    rbsz;
501
502         u32int  *nic;
503         Lock    imlock;
504         int     im;                     /* interrupt mask */
505
506         Rendez  lrendez;
507         int     lim;
508
509         QLock   slock;
510         u32int  statistics[Nstatistics];
511         uint    lsleep;
512         uint    lintr;
513         uint    rsleep;
514         uint    rintr;
515         uint    txdw;
516         uint    tintr;
517         uint    ixsm;
518         uint    ipcs;
519         uint    tcpcs;
520         uint    speeds[4];
521         uint    phyerrata;
522
523         uchar   ra[Eaddrlen];           /* receive address */
524         u32int  mta[128];               /* multicast table array */
525
526         Rendez  rrendez;
527         int     rim;
528         int     rdfree;
529         Rd      *rdba;                  /* receive descriptor base address */
530         Block   **rb;                   /* receive buffers */
531         uint    rdh;                    /* receive descriptor head */
532         uint    rdt;                    /* receive descriptor tail */
533         int     rdtr;                   /* receive delay timer ring value */
534         int     radv;                   /* receive interrupt absolute delay timer */
535
536         Rendez  trendez;
537         QLock   tlock;
538         int     tbusy;
539         Td      *tdba;                  /* transmit descriptor base address */
540         Block   **tb;                   /* transmit buffers */
541         int     tdh;                    /* transmit descriptor head */
542         int     tdt;                    /* transmit descriptor tail */
543
544         int     fcrtl;
545         int     fcrth;
546
547         u32int  pba;                    /* packet buffer allocation */
548 };
549
550 #define csr32r(c, r)    (*((c)->nic+((r)/4)))
551 #define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v))
552
553 static  Ctlr    *i82563ctlrhead;
554 static  Ctlr    *i82563ctlrtail;
555
556 static char *statistics[Nstatistics] = {
557         "CRC Error",
558         "Alignment Error",
559         "Symbol Error",
560         "RX Error",
561         "Missed Packets",
562         "Single Collision",
563         "Excessive Collisions",
564         "Multiple Collision",
565         "Late Collisions",
566         nil,
567         "Collision",
568         "Transmit Underrun",
569         "Defer",
570         "Transmit - No CRS",
571         "Sequence Error",
572         "Carrier Extension Error",
573         "Receive Error Length",
574         nil,
575         "XON Received",
576         "XON Transmitted",
577         "XOFF Received",
578         "XOFF Transmitted",
579         "FC Received Unsupported",
580         "Packets Received (64 Bytes)",
581         "Packets Received (65-127 Bytes)",
582         "Packets Received (128-255 Bytes)",
583         "Packets Received (256-511 Bytes)",
584         "Packets Received (512-1023 Bytes)",
585         "Packets Received (1024-mtu Bytes)",
586         "Good Packets Received",
587         "Broadcast Packets Received",
588         "Multicast Packets Received",
589         "Good Packets Transmitted",
590         nil,
591         "Good Octets Received",
592         nil,
593         "Good Octets Transmitted",
594         nil,
595         nil,
596         nil,
597         "Receive No Buffers",
598         "Receive Undersize",
599         "Receive Fragment",
600         "Receive Oversize",
601         "Receive Jabber",
602         "Management Packets Rx",
603         "Management Packets Drop",
604         "Management Packets Tx",
605         "Total Octets Received",
606         nil,
607         "Total Octets Transmitted",
608         nil,
609         "Total Packets Received",
610         "Total Packets Transmitted",
611         "Packets Transmitted (64 Bytes)",
612         "Packets Transmitted (65-127 Bytes)",
613         "Packets Transmitted (128-255 Bytes)",
614         "Packets Transmitted (256-511 Bytes)",
615         "Packets Transmitted (512-1023 Bytes)",
616         "Packets Transmitted (1024-mtu Bytes)",
617         "Multicast Packets Transmitted",
618         "Broadcast Packets Transmitted",
619         "TCP Segmentation Context Transmitted",
620         "TCP Segmentation Context Fail",
621         "Interrupt Assertion",
622         "Interrupt Rx Pkt Timer",
623         "Interrupt Rx Abs Timer",
624         "Interrupt Tx Pkt Timer",
625         "Interrupt Tx Abs Timer",
626         "Interrupt Tx Queue Empty",
627         "Interrupt Tx Desc Low",
628         "Interrupt Rx Min",
629         "Interrupt Rx Overrun",
630 };
631
632 static char*
633 cname(Ctlr *c)
634 {
635         return cttab[c->type].name;
636 }
637
638 static long
639 i82563ifstat(Ether *edev, void *a, long n, ulong offset)
640 {
641         char *s, *p, *e, *stat;
642         int i, r;
643         uvlong tuvl, ruvl;
644         Ctlr *ctlr;
645
646         p = s = smalloc(READSTR);
647         e = p + READSTR;
648
649         ctlr = edev->ctlr;
650         qlock(&ctlr->slock);
651
652         for(i = 0; i < Nstatistics; i++){
653                 r = csr32r(ctlr, Statistics + i*4);
654                 if((stat = statistics[i]) == nil)
655                         continue;
656                 switch(i){
657                 case Gorcl:
658                 case Gotcl:
659                 case Torl:
660                 case Totl:
661                         ruvl = r;
662                         ruvl += (uvlong)csr32r(ctlr, Statistics+(i+1)*4) << 32;
663                         tuvl = ruvl;
664                         tuvl += ctlr->statistics[i];
665                         tuvl += (uvlong)ctlr->statistics[i+1] << 32;
666                         if(tuvl == 0)
667                                 continue;
668                         ctlr->statistics[i] = tuvl;
669                         ctlr->statistics[i+1] = tuvl >> 32;
670                         p = seprint(p, e, "%s: %llud %llud\n", stat, tuvl, ruvl);
671                         i++;
672                         break;
673
674                 default:
675                         ctlr->statistics[i] += r;
676                         if(ctlr->statistics[i] == 0)
677                                 continue;
678                         p = seprint(p, e, "%s: %ud %ud\n", stat,
679                                 ctlr->statistics[i], r);
680                         break;
681                 }
682         }
683
684         p = seprint(p, e, "lintr: %ud %ud\n", ctlr->lintr, ctlr->lsleep);
685         p = seprint(p, e, "rintr: %ud %ud\n", ctlr->rintr, ctlr->rsleep);
686         p = seprint(p, e, "tintr: %ud %ud\n", ctlr->tintr, ctlr->txdw);
687         p = seprint(p, e, "ixcs: %ud %ud %ud\n", ctlr->ixsm, ctlr->ipcs, ctlr->tcpcs);
688         p = seprint(p, e, "rdtr: %ud\n", ctlr->rdtr);
689         p = seprint(p, e, "radv: %ud\n", ctlr->radv);
690         p = seprint(p, e, "ctrl: %.8ux\n", csr32r(ctlr, Ctrl));
691         p = seprint(p, e, "ctrlext: %.8ux\n", csr32r(ctlr, Ctrlext));
692         p = seprint(p, e, "status: %.8ux\n", csr32r(ctlr, Status));
693         p = seprint(p, e, "txcw: %.8ux\n", csr32r(ctlr, Txcw));
694         p = seprint(p, e, "txdctl: %.8ux\n", csr32r(ctlr, Txdctl));
695         p = seprint(p, e, "pba: %.8ux\n", ctlr->pba);
696
697         p = seprint(p, e, "speeds: 10:%ud 100:%ud 1000:%ud ?:%ud\n",
698                 ctlr->speeds[0], ctlr->speeds[1], ctlr->speeds[2], ctlr->speeds[3]);
699         p = seprint(p, e, "type: %s\n", cname(ctlr));
700
701 //      p = seprint(p, e, "eeprom:");
702 //      for(i = 0; i < 0x40; i++){
703 //              if(i && ((i & 7) == 0))
704 //                      p = seprint(p, e, "\n       ");
705 //              p = seprint(p, e, " %4.4ux", ctlr->eeprom[i]);
706 //      }
707 //      p = seprint(p, e, "\n");
708
709         USED(p);
710         n = readstr(offset, a, n, s);
711         free(s);
712         qunlock(&ctlr->slock);
713
714         return n;
715 }
716
717 static void
718 i82563promiscuous(void *arg, int on)
719 {
720         int rctl;
721         Ctlr *ctlr;
722         Ether *edev;
723
724         edev = arg;
725         ctlr = edev->ctlr;
726
727         rctl = csr32r(ctlr, Rctl);
728         rctl &= ~MoMASK;
729         if(on)
730                 rctl |= Upe|Mpe;
731         else
732                 rctl &= ~(Upe|Mpe);
733         csr32w(ctlr, Rctl, rctl);
734 }
735
736 static void
737 i82563multicast(void *arg, uchar *addr, int on)
738 {
739         int bit, x;
740         Ctlr *ctlr;
741         Ether *edev;
742
743         edev = arg;
744         ctlr = edev->ctlr;
745
746         x = addr[5]>>1;
747         if(ctlr->type == i82566)
748                 x &= 31;
749         bit = ((addr[5] & 1)<<4)|(addr[4]>>4);
750         /*
751          * multiple ether addresses can hash to the same filter bit,
752          * so it's never safe to clear a filter bit.
753          * if we want to clear filter bits, we need to keep track of
754          * all the multicast addresses in use, clear all the filter bits,
755          * then set the ones corresponding to in-use addresses.
756          */
757         if(on)
758                 ctlr->mta[x] |= 1<<bit;
759 //      else
760 //              ctlr->mta[x] &= ~(1<<bit);
761
762         csr32w(ctlr, Mta+x*4, ctlr->mta[x]);
763 }
764
765 static void
766 i82563im(Ctlr *ctlr, int im)
767 {
768         ilock(&ctlr->imlock);
769         ctlr->im |= im;
770         csr32w(ctlr, Ims, ctlr->im);
771         iunlock(&ctlr->imlock);
772 }
773
774 static void
775 i82563txinit(Ctlr *ctlr)
776 {
777         u32int r;
778         Block *b;
779         int i;
780
781         if(cttab[ctlr->type].flag & F75)
782                 csr32w(ctlr, Tctl, 0x0F<<CtSHIFT | Psp);
783         else
784                 csr32w(ctlr, Tctl, 0x0F<<CtSHIFT | Psp | 66<<ColdSHIFT | Mulr);
785         csr32w(ctlr, Tipg, 6<<20 | 8<<10 | 8);          /* yb sez: 0x702008 */
786         for(i = 0; i < ctlr->ntd; i++){
787                 if((b = ctlr->tb[i]) != nil){
788                         ctlr->tb[i] = nil;
789                         freeb(b);
790                 }
791                 memset(&ctlr->tdba[i], 0, sizeof(Td));
792         }
793         csr32w(ctlr, Tdbal, PCIWADDR(ctlr->tdba));
794         csr32w(ctlr, Tdbah, 0);
795         csr32w(ctlr, Tdlen, ctlr->ntd * sizeof(Td));
796         ctlr->tdh = PREV(0, ctlr->ntd);
797         csr32w(ctlr, Tdh, 0);
798         ctlr->tdt = 0;
799         csr32w(ctlr, Tdt, 0);
800         csr32w(ctlr, Tidv, 128);
801         csr32w(ctlr, Tadv, 64);
802         csr32w(ctlr, Tctl, csr32r(ctlr, Tctl) | Ten);
803         r = csr32r(ctlr, Txdctl) & ~WthreshMASK;
804         r |= 4<<WthreshSHIFT | 4<<PthreshSHIFT;
805         if(cttab[ctlr->type].flag & F75)
806                 r |= Enable;
807         csr32w(ctlr, Txdctl, r);
808 }
809
810 static uint
811 i82563cleanup(Ctlr *c)
812 {
813         Block *b;
814         uint tdh, n;
815
816         tdh = c->tdh;
817         while(c->tdba[n = NEXT(tdh, c->ntd)].status & Tdd){
818                 tdh = n;
819                 if((b = c->tb[tdh]) != nil){
820                         c->tb[tdh] = nil;
821                         freeb(b);
822                 }else
823                         iprint("82563 tx underrun!\n");
824                 c->tdba[tdh].status = 0;
825         }
826
827         return c->tdh = tdh;
828 }
829
830 static int
831 notrim(void *v)
832 {
833         Ctlr *c;
834
835         c = v;
836         return (c->im & Txdw) == 0;
837 }
838
839 static void
840 i82563tproc(void *v)
841 {
842         Td *td;
843         Block *bp;
844         Ether *edev;
845         Ctlr *ctlr;
846         uint tdt, n;
847
848         edev = v;
849         ctlr = edev->ctlr;
850         i82563txinit(ctlr);
851
852         tdt = ctlr->tdt;
853         for(;;){
854                 n = NEXT(tdt, ctlr->ntd);
855                 if(n == i82563cleanup(ctlr)){
856                         ctlr->txdw++;
857                         i82563im(ctlr, Txdw);
858                         sleep(&ctlr->trendez, notrim, ctlr);
859                         continue;
860                 }
861                 bp = qbread(edev->oq, 100000);
862                 td = &ctlr->tdba[tdt];
863                 td->addr[0] = PCIWADDR(bp->rp);
864                 td->addr[1] = 0;
865                 td->control = Ide|Rs|Ifcs|Teop|BLEN(bp);
866                 coherence();
867                 ctlr->tb[tdt] = bp;
868                 ctlr->tdt = tdt = n;
869                 csr32w(ctlr, Tdt, tdt);
870         }
871 }
872
873 static void
874 i82563replenish(Ctlr *ctlr)
875 {
876         uint rdt, i;
877         Block *bp;
878         Rd *rd;
879
880         i = 0;
881         for(rdt = ctlr->rdt; NEXT(rdt, ctlr->nrd) != ctlr->rdh; rdt = NEXT(rdt, ctlr->nrd)){
882                 rd = &ctlr->rdba[rdt];
883                 if(ctlr->rb[rdt] != nil){
884                         iprint("82563: tx overrun\n");
885                         break;
886                 }
887                 i++;
888                 bp = allocb(ctlr->rbsz + Rbalign);
889                 bp->rp = bp->wp = (uchar*)ROUND((uintptr)bp->base, Rbalign);
890                 ctlr->rb[rdt] = bp;
891                 rd->addr[0] = PCIWADDR(bp->rp);
892                 rd->addr[1] = 0;
893                 rd->status = 0;
894                 ctlr->rdfree++;
895         }
896         if(i != 0){
897                 coherence();
898                 ctlr->rdt = rdt;
899                 csr32w(ctlr, Rdt, rdt);
900         }
901 }
902
903 static void
904 i82563rxinit(Ctlr *ctlr)
905 {
906         int i;
907         Block *bp;
908
909         if(ctlr->rbsz <= 2048)
910                 csr32w(ctlr, Rctl, Dpf|Bsize2048|Bam|RdtmsHALF);
911         else{
912                 i = ctlr->rbsz / 1024;
913                 if(ctlr->rbsz % 1024)
914                         i++;
915                 if(cttab[ctlr->type].flag & F75){
916                         csr32w(ctlr, Rctl, Lpe|Dpf|Bsize2048|Bam|RdtmsHALF|Secrc);
917                         if(ctlr->type != i82575)
918                                 i |= (ctlr->nrd/2>>4)<<20;              /* RdmsHalf */
919                         csr32w(ctlr, Srrctl, i | Dropen);
920                         csr32w(ctlr, Rmpl, ctlr->rbsz);
921 //                      csr32w(ctlr, Drxmxod, 0x7ff);
922                 }else
923                         csr32w(ctlr, Rctl, Lpe|Dpf|BsizeFlex*i|Bam|RdtmsHALF|Secrc);
924         }
925
926         if(cttab[ctlr->type].flag & Fert)
927                 csr32w(ctlr, Ert, 1024/8);
928
929         if(ctlr->type == i82566)
930                 csr32w(ctlr, Pbs, 16);
931
932         csr32w(ctlr, Rdbal, PCIWADDR(ctlr->rdba));
933         csr32w(ctlr, Rdbah, 0);
934         csr32w(ctlr, Rdlen, ctlr->nrd * sizeof(Rd));
935         ctlr->rdh = 0;
936         csr32w(ctlr, Rdh, 0);
937         ctlr->rdt = 0;
938         csr32w(ctlr, Rdt, 0);
939         ctlr->rdtr = 25;
940         ctlr->radv = 500;
941         csr32w(ctlr, Rdtr, ctlr->rdtr);
942         csr32w(ctlr, Radv, ctlr->radv);
943
944         for(i = 0; i < ctlr->nrd; i++)
945                 if((bp = ctlr->rb[i]) != nil){
946                         ctlr->rb[i] = nil;
947                         freeb(bp);
948                 }
949         if(cttab[ctlr->type].flag & F75)
950                 csr32w(ctlr, Rxdctl, 1<<WthreshSHIFT | 8<<PthreshSHIFT | 1<<HthreshSHIFT | Enable);
951         else
952                 csr32w(ctlr, Rxdctl, 2<<WthreshSHIFT | 2<<PthreshSHIFT);
953
954         /*
955          * Enable checksum offload.
956          */
957         csr32w(ctlr, Rxcsum, Tuofl | Ipofl | ETHERHDRSIZE);
958 }
959
960 static int
961 i82563rim(void *v)
962 {
963         return ((Ctlr*)v)->rim != 0;
964 }
965
966 static void
967 i82563rproc(void *arg)
968 {
969         uint rdh, rim, im;
970         Block *bp;
971         Ctlr *ctlr;
972         Ether *edev;
973         Rd *rd;
974
975         edev = arg;
976         ctlr = edev->ctlr;
977
978         i82563rxinit(ctlr);
979         csr32w(ctlr, Rctl, csr32r(ctlr, Rctl) | Ren);
980         if(cttab[ctlr->type].flag & F75){
981                 csr32w(ctlr, Rxdctl, csr32r(ctlr, Rxdctl) | Enable);
982                 im = Rxt0|Rxo|Rxdmt0|Rxseq|Ack;
983         }else
984                 im = Rxt0|Rxo|Rxdmt0|Rxseq|Ack;
985
986         for(;;){
987                 i82563im(ctlr, im);
988                 ctlr->rsleep++;
989                 i82563replenish(ctlr);
990                 sleep(&ctlr->rrendez, i82563rim, ctlr);
991
992                 rdh = ctlr->rdh;
993                 for(;;){
994                         rim = ctlr->rim;
995                         ctlr->rim = 0;
996                         rd = &ctlr->rdba[rdh];
997                         if(!(rd->status & Rdd))
998                                 break;
999
1000                         /*
1001                          * Accept eop packets with no errors.
1002                          * With no errors and the Ixsm bit set,
1003                          * the descriptor status Tpcs and Ipcs bits give
1004                          * an indication of whether the checksums were
1005                          * calculated and valid.
1006                          */
1007                         bp = ctlr->rb[rdh];
1008                         if((rd->status & Reop) && rd->errors == 0){
1009                                 bp->wp += rd->length;
1010                                 bp->lim = bp->wp;       /* lie like a dog.  avoid packblock. */
1011                                 if(!(rd->status & Ixsm)){
1012                                         ctlr->ixsm++;
1013                                         if(rd->status & Ipcs){
1014                                                 /*
1015                                                  * IP checksum calculated
1016                                                  * (and valid as errors == 0).
1017                                                  */
1018                                                 ctlr->ipcs++;
1019                                                 bp->flag |= Bipck;
1020                                         }
1021                                         if(rd->status & Tcpcs){
1022                                                 /*
1023                                                  * TCP/UDP checksum calculated
1024                                                  * (and valid as errors == 0).
1025                                                  */
1026                                                 ctlr->tcpcs++;
1027                                                 bp->flag |= Btcpck|Budpck;
1028                                         }
1029                                         bp->checksum = rd->checksum;
1030                                         bp->flag |= Bpktck;
1031                                 }
1032                                 etheriq(edev, bp, 1);
1033                         } else
1034                                 freeb(bp);
1035                         ctlr->rb[rdh] = nil;
1036                         ctlr->rdfree--;
1037                         ctlr->rdh = rdh = NEXT(rdh, ctlr->nrd);
1038                         if(ctlr->nrd-ctlr->rdfree >= 32 || (rim & Rxdmt0))
1039                                 i82563replenish(ctlr);
1040                 }
1041         }
1042 }
1043
1044 static int
1045 i82563lim(void *v)
1046 {
1047         return ((Ctlr*)v)->lim != 0;
1048 }
1049
1050 static int speedtab[] = {
1051         10, 100, 1000, 0
1052 };
1053
1054 static uint
1055 phyread(Ctlr *c, int phyno, int reg)
1056 {
1057         uint phy, i;
1058
1059         csr32w(c, Mdic, MDIrop | phyno<<MDIpSHIFT | reg<<MDIrSHIFT);
1060         phy = 0;
1061         for(i = 0; i < 64; i++){
1062                 phy = csr32r(c, Mdic);
1063                 if(phy & (MDIe|MDIready))
1064                         break;
1065                 microdelay(1);
1066         }
1067         if((phy & (MDIe|MDIready)) != MDIready){
1068                 print("%s: phy %d wedged %.8ux\n", cttab[c->type].name, phyno, phy);
1069                 return ~0;
1070         }
1071         return phy & 0xffff;
1072 }
1073
1074 static uint
1075 phywrite0(Ctlr *c, int phyno, int reg, ushort val)
1076 {
1077         uint phy, i;
1078
1079         csr32w(c, Mdic, MDIwop | phyno<<MDIpSHIFT | reg<<MDIrSHIFT | val);
1080         phy = 0;
1081         for(i = 0; i < 64; i++){
1082                 phy = csr32r(c, Mdic);
1083                 if(phy & (MDIe|MDIready))
1084                         break;
1085                 microdelay(1);
1086         }
1087         if((phy & (MDIe|MDIready)) != MDIready)
1088                 return ~0;
1089         return 0;
1090 }
1091
1092 static uint
1093 setpage(Ctlr *c, uint phyno, uint p, uint r)
1094 {
1095         uint pr;
1096
1097         if(c->type == i82563){
1098                 if(r >= 16 && r <= 28 && r != 22)
1099                         pr = Phypage;
1100                 else if(r == 30 || r == 31)
1101                         pr = Phyapage;
1102                 else
1103                         return 0;
1104                 return phywrite0(c, phyno, pr, p);
1105         }else if(p == 0)
1106                 return 0;
1107         return ~0;
1108 }
1109
1110 static uint
1111 phywrite(Ctlr *c, uint phyno, uint reg, ushort v)
1112 {
1113         if(setpage(c, phyno, reg>>8, reg & 0xff) == ~0)
1114                 panic("%s: bad phy reg %.4ux", cname(c), reg);
1115         return phywrite0(c, phyno, reg & 0xff, v);
1116 }
1117
1118 static void
1119 phyerrata(Ether *e, Ctlr *c)
1120 {
1121         if(e->mbps == 0){
1122                 if(c->phyerrata == 0){
1123                         c->phyerrata++;
1124                         phywrite(c, 1, Phyprst, Prst);  /* try a port reset */
1125                         print("%s: phy port reset\n", cname(c));
1126                 }
1127         }else
1128                 c->phyerrata = 0;
1129 }
1130
1131 static void
1132 phyl79proc(void *v)
1133 {
1134         uint a, i, r, phy, phyno;
1135         Ctlr *c;
1136         Ether *e;
1137
1138         e = v;
1139         c = e->ctlr;
1140
1141         phyno = 1;
1142         if(c->type == i82579)
1143                 phyno = 2;
1144
1145         for(;;){
1146                 phy = phyread(c, phyno, Phystat);
1147                 if(phy == ~0){
1148                         phy = 0;
1149                         i = 3;
1150                         goto next;
1151                 }
1152                 i = (phy>>8) & 3;
1153                 a = phy & Ans;
1154                 if(a){
1155                         r = phyread(c, phyno, Phyctl);
1156                         phywrite(c, phyno, Phyctl, r | Ran | Ean);
1157                 }
1158 next:
1159                 e->link = i != 3 && (phy & Link) != 0;
1160                 if(e->link == 0)
1161                         i = 3;
1162                 c->speeds[i]++;
1163                 e->mbps = speedtab[i];
1164                 c->lim = 0;
1165                 i82563im(c, Lsc);
1166                 c->lsleep++;
1167                 sleep(&c->lrendez, i82563lim, c);
1168         }
1169 }
1170
1171 static void
1172 phylproc(void *v)
1173 {
1174         uint a, i, phy;
1175         Ctlr *c;
1176         Ether *e;
1177
1178         e = v;
1179         c = e->ctlr;
1180
1181         if(c->type == i82573 && (phy = phyread(c, 1, Phyier)) != ~0)
1182                 phywrite(c, 1, Phyier, phy | Lscie | Ancie | Spdie | Panie);
1183         for(;;){
1184                 phy = phyread(c, 1, Physsr);
1185                 if(phy == ~0){
1186                         phy = 0;
1187                         i = 3;
1188                         goto next;
1189                 }
1190                 i = (phy>>14) & 3;
1191                 switch(c->type){
1192                 default:
1193                         a = 0;
1194                         break;
1195                 case i82563:
1196                 case i82578:
1197                 case i82578m:
1198                 case i82583:
1199                         a = phyread(c, 1, Phyisr) & Ane;
1200                         break;
1201                 case i82571:
1202                 case i82572:
1203                 case i82575:
1204                 case i82576:
1205                         a = phyread(c, 1, Phylhr) & Anf;
1206                         i = (i-1) & 3;
1207                         break;
1208                 }
1209                 if(a)
1210                         phywrite(c, 1, Phyctl, phyread(c, 1, Phyctl) | Ran | Ean);
1211 next:
1212                 e->link = (phy & Rtlink) != 0;
1213                 if(e->link == 0)
1214                         i = 3;
1215                 c->speeds[i]++;
1216                 e->mbps = speedtab[i];
1217                 if(c->type == i82563)
1218                         phyerrata(e, c);
1219                 c->lim = 0;
1220                 i82563im(c, Lsc);
1221                 c->lsleep++;
1222                 sleep(&c->lrendez, i82563lim, c);
1223         }
1224 }
1225
1226 static void
1227 pcslproc(void *v)
1228 {
1229         uint i, phy;
1230         Ctlr *c;
1231         Ether *e;
1232
1233         e = v;
1234         c = e->ctlr;
1235
1236         if(c->type == i82575 || c->type == i82576)
1237                 csr32w(c, Connsw, Enrgirq);
1238         for(;;){
1239                 phy = csr32r(c, Pcsstat);
1240                 e->link = phy & Linkok;
1241                 i = 3;
1242                 if(e->link)
1243                         i = (phy & 6) >> 1;
1244                 else if(phy & Anbad)
1245                         csr32w(c, Pcsctl, csr32r(c, Pcsctl) | Pan | Prestart);
1246                 c->speeds[i]++;
1247                 e->mbps = speedtab[i];
1248                 c->lim = 0;
1249                 i82563im(c, Lsc | Omed);
1250                 c->lsleep++;
1251                 sleep(&c->lrendez, i82563lim, c);
1252         }
1253 }
1254
1255 static void
1256 serdeslproc(void *v)
1257 {
1258         uint i, tx, rx;
1259         Ctlr *c;
1260         Ether *e;
1261
1262         e = v;
1263         c = e->ctlr;
1264
1265         for(;;){
1266                 rx = csr32r(c, Rxcw);
1267                 tx = csr32r(c, Txcw);
1268                 USED(tx);
1269                 e->link = (rx & 1<<31) != 0;
1270 //              e->link = (csr32r(c, Status) & Lu) != 0;
1271                 i = 3;
1272                 if(e->link)
1273                         i = 2;
1274                 c->speeds[i]++;
1275                 e->mbps = speedtab[i];
1276                 c->lim = 0;
1277                 i82563im(c, Lsc);
1278                 c->lsleep++;
1279                 sleep(&c->lrendez, i82563lim, c);
1280         }
1281 }
1282
1283 static void
1284 maclproc(void *v)
1285 {
1286         uint i;
1287         Ctlr *c;
1288         Ether *e;
1289
1290         e = v;
1291         c = e->ctlr;
1292
1293         for(;;){
1294                 i = csr32r(c, Status);
1295                 e->link = (i & Lu) != 0;
1296                 i = (i >> 6) & 3;       /* link speed 6:7 */
1297                 if(e->link == 0)
1298                         i = 3;
1299                 c->speeds[i]++;
1300                 e->mbps = speedtab[i];
1301                 c->lim = 0;
1302                 i82563im(c, Lsc);
1303                 c->lsleep++;
1304                 sleep(&c->lrendez, i82563lim, c);
1305         }
1306 }
1307
1308 static void
1309 i82563attach(Ether *edev)
1310 {
1311         char name[KNAMELEN];
1312         Ctlr *ctlr;
1313
1314         ctlr = edev->ctlr;
1315         qlock(&ctlr->alock);
1316         if(ctlr->alloc != nil){
1317                 qunlock(&ctlr->alock);
1318                 return;
1319         }
1320
1321         ctlr->nrd = Nrd;
1322         ctlr->ntd = Ntd;
1323         ctlr->alloc = malloc(ctlr->nrd*sizeof(Rd)+ctlr->ntd*sizeof(Td) + 255);
1324         ctlr->rb = malloc(ctlr->nrd * sizeof(Block*));
1325         ctlr->tb = malloc(ctlr->ntd * sizeof(Block*));
1326         if(ctlr->alloc == nil || ctlr->rb == nil || ctlr->tb == nil){
1327                 free(ctlr->rb);
1328                 ctlr->rb = nil;
1329                 free(ctlr->tb);
1330                 ctlr->tb = nil;
1331                 free(ctlr->alloc);
1332                 ctlr->alloc = nil;
1333                 qunlock(&ctlr->alock);
1334                 error(Enomem);
1335         }
1336         ctlr->rdba = (Rd*)ROUNDUP((uintptr)ctlr->alloc, 256);
1337         ctlr->tdba = (Td*)(ctlr->rdba + ctlr->nrd);
1338
1339         if(waserror()){
1340                 free(ctlr->tb);
1341                 ctlr->tb = nil;
1342                 free(ctlr->rb);
1343                 ctlr->rb = nil;
1344                 free(ctlr->alloc);
1345                 ctlr->alloc = nil;
1346                 qunlock(&ctlr->alock);
1347                 nexterror();
1348         }
1349
1350         snprint(name, sizeof name, "#l%dl", edev->ctlrno);
1351         if(csr32r(ctlr, Status) & Tbimode)
1352                 kproc(name, serdeslproc, edev);         /* mac based serdes */
1353         else if((csr32r(ctlr, Ctrlext) & Linkmode) == Serdes)
1354                 kproc(name, pcslproc, edev);            /* phy based serdes */
1355         else if(cttab[ctlr->type].flag & F79phy)
1356                 kproc(name, phyl79proc, edev);
1357         else if(ctlr->type == i82567)
1358                 kproc(name, maclproc, edev);            /* use mac link status */
1359         else
1360                 kproc(name, phylproc, edev);
1361
1362         snprint(name, sizeof name, "#l%dr", edev->ctlrno);
1363         kproc(name, i82563rproc, edev);
1364
1365         snprint(name, sizeof name, "#l%dt", edev->ctlrno);
1366         kproc(name, i82563tproc, edev);
1367
1368         qunlock(&ctlr->alock);
1369         poperror();
1370 }
1371
1372 static void
1373 i82563interrupt(Ureg*, void *arg)
1374 {
1375         Ctlr *ctlr;
1376         Ether *edev;
1377         int icr, im;
1378
1379         edev = arg;
1380         ctlr = edev->ctlr;
1381
1382         ilock(&ctlr->imlock);
1383         csr32w(ctlr, Imc, ~0);
1384         im = ctlr->im;
1385
1386         while(icr = csr32r(ctlr, Icr) & ctlr->im){
1387                 if(icr & (Lsc | Omed)){
1388                         im &= ~(Lsc | Omed);
1389                         ctlr->lim = icr & (Lsc | Omed);
1390                         wakeup(&ctlr->lrendez);
1391                         ctlr->lintr++;
1392                 }
1393                 if(icr & (Rxt0|Rxo|Rxdmt0|Rxseq|Ack)){
1394                         ctlr->rim = icr & (Rxt0|Rxo|Rxdmt0|Rxseq|Ack);
1395                         im &= ~(Rxt0|Rxo|Rxdmt0|Rxseq|Ack);
1396                         wakeup(&ctlr->rrendez);
1397                         ctlr->rintr++;
1398                 }
1399                 if(icr & Txdw){
1400                         im &= ~Txdw;
1401                         ctlr->tintr++;
1402                         wakeup(&ctlr->trendez);
1403                 }
1404         }
1405
1406         ctlr->im = im;
1407         csr32w(ctlr, Ims, im);
1408         iunlock(&ctlr->imlock);
1409 }
1410
1411 static int
1412 i82563detach(Ctlr *ctlr)
1413 {
1414         int r, timeo;
1415
1416         /* balance rx/tx packet buffer; survives reset */
1417         if(ctlr->rbsz > 8192 && cttab[ctlr->type].flag & Fpba){
1418                 ctlr->pba = csr32r(ctlr, Pba);
1419                 r = ctlr->pba >> 16;
1420                 r += ctlr->pba & 0xffff;
1421                 r >>= 1;
1422                 csr32w(ctlr, Pba, r);
1423         }else if(ctlr->type == i82573 && ctlr->rbsz > 1514)
1424                 csr32w(ctlr, Pba, 14);
1425         ctlr->pba = csr32r(ctlr, Pba);
1426
1427         /*
1428          * Perform a device reset to get the chip back to the
1429          * power-on state, followed by an EEPROM reset to read
1430          * the defaults for some internal registers.
1431          */
1432         csr32w(ctlr, Imc, ~0);
1433         csr32w(ctlr, Rctl, 0);
1434         csr32w(ctlr, Tctl, csr32r(ctlr, Tctl) & ~Ten);
1435
1436         delay(10);
1437
1438         r = csr32r(ctlr, Ctrl);
1439         if(ctlr->type == i82566 || ctlr->type == i82579)
1440                 r |= Phyrst;
1441         /*
1442          * hack: 82579LM on lenovo X230 is stuck at 10mbps after
1443          * reseting the phy, but works fine if we dont reset.
1444          */
1445         if(ctlr->pcidev->did == 0x1502)
1446                 r &= ~Phyrst;
1447         csr32w(ctlr, Ctrl, Devrst | r);
1448         delay(1);
1449         for(timeo = 0;; timeo++){
1450                 if((csr32r(ctlr, Ctrl) & (Devrst|Phyrst)) == 0)
1451                         break;
1452                 if(timeo >= 1000)
1453                         return -1;
1454                 delay(1);
1455         }
1456
1457         r = csr32r(ctlr, Ctrl);
1458         csr32w(ctlr, Ctrl, Slu|r);
1459
1460         r = csr32r(ctlr, Ctrlext);
1461         csr32w(ctlr, Ctrlext, r|Eerst);
1462         delay(1);
1463         for(timeo = 0; timeo < 1000; timeo++){
1464                 if(!(csr32r(ctlr, Ctrlext) & Eerst))
1465                         break;
1466                 delay(1);
1467         }
1468         if(csr32r(ctlr, Ctrlext) & Eerst)
1469                 return -1;
1470
1471         csr32w(ctlr, Imc, ~0);
1472         delay(1);
1473         for(timeo = 0; timeo < 1000; timeo++){
1474                 if((csr32r(ctlr, Icr) & ~Rxcfg) == 0)
1475                         break;
1476                 delay(1);
1477         }
1478         if(csr32r(ctlr, Icr) & ~Rxcfg)
1479                 return -1;
1480
1481         return 0;
1482 }
1483
1484 static void
1485 i82563shutdown(Ether *edev)
1486 {
1487         i82563detach(edev->ctlr);
1488 }
1489
1490 static int
1491 eeread(Ctlr *ctlr, int adr)
1492 {
1493         int timeout;
1494
1495         csr32w(ctlr, Eerd, EEstart | adr << 2);
1496         timeout = 1000;
1497         while ((csr32r(ctlr, Eerd) & EEdone) == 0 && timeout--)
1498                 microdelay(5);
1499         if (timeout < 0) {
1500                 print("%s: eeread timeout\n", cname(ctlr));
1501                 return -1;
1502         }
1503         return (csr32r(ctlr, Eerd) >> 16) & 0xffff;
1504 }
1505
1506 static int
1507 eeload(Ctlr *ctlr)
1508 {
1509         u16int sum;
1510         int data, adr;
1511
1512         sum = 0;
1513         for (adr = 0; adr < 0x40; adr++) {
1514                 data = eeread(ctlr, adr);
1515                 if(data == -1) return -1;
1516                 ctlr->eeprom[adr] = data;
1517                 sum += data;
1518         }
1519         return sum;
1520 }
1521
1522 static int
1523 fcycle(Ctlr *, Flash *f)
1524 {
1525         u16int s;
1526         int i;
1527
1528         s = f->reg[Fsts];
1529         if((s&Fvalid) == 0)
1530                 return -1;
1531         f->reg[Fsts] |= Fcerr | Ael;
1532         for(i = 0; i < 10; i++){
1533                 if((s&Scip) == 0)
1534                         return 0;
1535                 delay(1);
1536                 s = f->reg[Fsts];
1537         }
1538         return -1;
1539 }
1540
1541 static int
1542 fread(Ctlr *c, Flash *f, int ladr)
1543 {
1544         u16int s;
1545         int timeout;
1546
1547         delay(1);
1548         if(fcycle(c, f) == -1)
1549                 return -1;
1550         f->reg[Fsts] |= Fdone;
1551         f->reg32[Faddr] = ladr;
1552
1553         /* setup flash control register */
1554         s = f->reg[Fctl] & ~0x3ff;
1555         f->reg[Fctl] = s | 1<<8 | Fgo;  /* 2 byte read */
1556         timeout = 1000;
1557         while((f->reg[Fsts] & Fdone) == 0 && timeout--)
1558                 microdelay(5);
1559         if(timeout < 0){
1560                 print("%s: fread timeout\n", cname(c));
1561                 return -1;
1562         }
1563         if(f->reg[Fsts] & (Fcerr|Ael))
1564                 return -1;
1565         return f->reg32[Fdata] & 0xffff;
1566 }
1567
1568 static int
1569 fload(Ctlr *c)
1570 {
1571         int data, r, adr;
1572         u16int sum;
1573         void *va;
1574         Flash f;
1575
1576         va = vmap(c->pcidev->mem[1].bar & ~0x0f, c->pcidev->mem[1].size);
1577         if(va == nil)
1578                 return -1;
1579         f.reg = va;
1580         f.reg32 = va;
1581         f.base = f.reg32[Bfpr] & 0x1fff;
1582         f.lim = f.reg32[Bfpr]>>16 & 0x1fff;
1583         if(csr32r(c, Eec) & Sec1val)
1584                 f.base += f.lim+1 - f.base >> 1;
1585         r = f.base << 12;
1586         sum = 0;
1587         for(adr = 0; adr < 0x40; adr++) {
1588                 data = fread(c, &f, r + adr*2);
1589                 if(data == -1)
1590                         return -1;
1591                 c->eeprom[adr] = data;
1592                 sum += data;
1593         }
1594         vunmap(va, c->pcidev->mem[1].size);
1595         return sum;
1596 }
1597
1598 static void
1599 defaultea(Ctlr *ctlr, uchar *ra)
1600 {
1601         uint i, r;
1602         uvlong u;
1603         static uchar nilea[Eaddrlen];
1604
1605         if(memcmp(ra, nilea, Eaddrlen) != 0)
1606                 return;
1607         if(cttab[ctlr->type].flag & Fflashea){
1608                 /* intel mb bug */
1609                 u = (uvlong)csr32r(ctlr, Rah)<<32u | (ulong)csr32r(ctlr, Ral);
1610                 for(i = 0; i < Eaddrlen; i++)
1611                         ra[i] = u >> 8*i;
1612         }
1613         if(memcmp(ra, nilea, Eaddrlen) != 0)
1614                 return;
1615         for(i = 0; i < Eaddrlen/2; i++){
1616                 ra[2*i] = ctlr->eeprom[Ea+i];
1617                 ra[2*i+1] = ctlr->eeprom[Ea+i] >> 8;
1618         }
1619         r = (csr32r(ctlr, Status) & Lanid) >> 2;
1620         ra[5] += r;                             /* ea ctlr[n] = ea ctlr[0]+n */
1621 }
1622
1623 static int
1624 i82563reset(Ctlr *ctlr)
1625 {
1626         uchar *ra;
1627         int i, r;
1628
1629         if(i82563detach(ctlr))
1630                 return -1;
1631         if(cttab[ctlr->type].flag & Fload)
1632                 r = fload(ctlr);
1633         else
1634                 r = eeload(ctlr);
1635         if(r != 0 && r != 0xbaba){
1636                 print("%s: bad eeprom checksum - %#.4ux\n",
1637                         cname(ctlr), r);
1638                 return -1;
1639         }
1640
1641         ra = ctlr->ra;
1642         defaultea(ctlr, ra);
1643         csr32w(ctlr, Ral, ra[3]<<24 | ra[2]<<16 | ra[1]<<8 | ra[0]);
1644         csr32w(ctlr, Rah, 1<<31 | ra[5]<<8 | ra[4]);
1645         for(i = 1; i < 16; i++){
1646                 csr32w(ctlr, Ral+i*8, 0);
1647                 csr32w(ctlr, Rah+i*8, 0);
1648         }
1649         memset(ctlr->mta, 0, sizeof(ctlr->mta));
1650         for(i = 0; i < 128; i++)
1651                 csr32w(ctlr, Mta + i*4, 0);
1652         csr32w(ctlr, Fcal, 0x00C28001);
1653         csr32w(ctlr, Fcah, 0x0100);
1654         if(ctlr->type != i82579)
1655                 csr32w(ctlr, Fct, 0x8808);
1656         csr32w(ctlr, Fcttv, 0x0100);
1657         csr32w(ctlr, Fcrtl, ctlr->fcrtl);
1658         csr32w(ctlr, Fcrth, ctlr->fcrth);
1659         if(cttab[ctlr->type].flag & F75)
1660                 csr32w(ctlr, Eitr, 128<<2);             /* 128 ¼ microsecond intervals */
1661         return 0;
1662 }
1663
1664 enum {
1665         CMrdtr,
1666         CMradv,
1667         CMpause,
1668         CMan,
1669 };
1670
1671 static Cmdtab i82563ctlmsg[] = {
1672         CMrdtr, "rdtr", 2,
1673         CMradv, "radv", 2,
1674         CMpause, "pause", 1,
1675         CMan,   "an",   1,
1676 };
1677
1678 static long
1679 i82563ctl(Ether *edev, void *buf, long n)
1680 {
1681         char *p;
1682         ulong v;
1683         Ctlr *ctlr;
1684         Cmdbuf *cb;
1685         Cmdtab *ct;
1686
1687         if((ctlr = edev->ctlr) == nil)
1688                 error(Enonexist);
1689
1690         cb = parsecmd(buf, n);
1691         if(waserror()){
1692                 free(cb);
1693                 nexterror();
1694         }
1695
1696         ct = lookupcmd(cb, i82563ctlmsg, nelem(i82563ctlmsg));
1697         switch(ct->index){
1698         case CMrdtr:
1699                 v = strtoul(cb->f[1], &p, 0);
1700                 if(*p || v > 0xffff)
1701                         error(Ebadarg);
1702                 ctlr->rdtr = v;
1703                 csr32w(ctlr, Rdtr, v);
1704                 break;
1705         case CMradv:
1706                 v = strtoul(cb->f[1], &p, 0);
1707                 if(*p || v > 0xffff)
1708                         error(Ebadarg);
1709                 ctlr->radv = v;
1710                 csr32w(ctlr, Radv, v);
1711                 break;
1712         case CMpause:
1713                 csr32w(ctlr, Ctrl, csr32r(ctlr, Ctrl) ^ (Rfce | Tfce));
1714                 break;
1715         case CMan:
1716                 csr32w(ctlr, Ctrl, csr32r(ctlr, Ctrl) | Lrst | Phyrst);
1717                 break;
1718         }
1719         free(cb);
1720         poperror();
1721
1722         return n;
1723 }
1724
1725 static int
1726 didtype(int d)
1727 {
1728         /*
1729          * Some names and did values are from
1730          * OpenBSD's em(4) Intel driver.
1731          */
1732         switch(d){
1733         case 0x1096:            /* copper */
1734         case 0x10ba:            /* copper “gilgal” */
1735         case 0x1098:            /* serdes; not seen */
1736         case 0x10bb:            /* serdes */
1737                 return i82563;
1738         case 0x1049:            /* ich8; mm */
1739         case 0x104a:            /* ich8; dm */
1740         case 0x104b:            /* ich8; dc */
1741         case 0x104d:            /* ich8; v “ninevah” */
1742         case 0x10bd:            /* ich9; dm-2 */
1743         case 0x294c:            /* ich9 */
1744         case 0x104c:            /* ich8; untested */
1745         case 0x10c4:            /* ich8; untested */
1746         case 0x10c5:            /* ich8; untested */
1747                 return i82566;
1748         case 0x10de:            /* lm ich10d */
1749         case 0x10df:            /* lf ich10 */
1750         case 0x10e5:            /* lm ich9 */
1751         case 0x10f5:            /* lm ich9m; “boazman” */
1752         case 0x10ce:            /* v ich10 */
1753         case 0x10c0:            /* ich9 */
1754         case 0x10c2:            /* ich9; untested */
1755         case 0x10c3:            /* ich9; untested */
1756         case 0x1501:            /* ich8; untested */
1757                 return i82567;
1758         case 0x10bf:            /* lf ich9m */
1759         case 0x10cb:            /* v ich9m */
1760         case 0x10cd:            /* lf ich10 */
1761         case 0x10cc:            /* lm ich10 */
1762                 return i82567m;
1763         case 0x105e:            /* eb copper */
1764         case 0x105f:            /* eb fiber */
1765         case 0x1060:            /* eb serdes */
1766         case 0x10a4:            /* eb copper */
1767         case 0x10a5:            /* eb fiber */
1768         case 0x10bc:            /* eb copper */
1769         case 0x10d9:            /* eb serdes */
1770         case 0x10da:            /* eb serdes “ophir” */
1771         case 0x10a0:            /* eb; untested */
1772         case 0x10a1:            /* eb; untested */
1773         case 0x10d5:            /* copper; untested */
1774                 return i82571;
1775         case 0x107d:            /* ei copper */
1776         case 0x107e:            /* ei fiber */
1777         case 0x107f:            /* ei serdes */
1778         case 0x10b9:            /* ei “rimon” */
1779                 return i82572;
1780         case 0x108b:            /* e “vidalia” */
1781         case 0x108c:            /* e (iamt) */
1782         case 0x109a:            /* l “tekoa” */
1783         case 0x10b0:            /* l; untested */
1784         case 0x10b2:            /* v; untested */
1785         case 0x10b3:            /* e; untested */
1786         case 0x10b4:            /* l; untested */
1787                 return i82573;
1788         case 0x10d3:            /* l or it; “hartwell” */
1789         case 0x10f6:            /* la; untested */
1790                 return i82574;
1791         case 0x10a7:            /* eb */
1792         case 0x10a9:            /* eb fiber/serdes */
1793         case 0x10d6:            /* untested */
1794         case 0x10e2:            /* untested */
1795                 return i82575;
1796         case 0x10c9:            /* copper */
1797         case 0x10e6:            /* fiber */
1798         case 0x10e7:            /* serdes; “kawela” */
1799         case 0x10e8:            /* copper; untested */
1800         case 0x150a:            /* untested */
1801         case 0x150d:            /* serdes backplane */
1802         case 0x1518:            /* serdes; untested */
1803         case 0x1526:            /* untested */
1804                 return i82576;
1805         case 0x10ea:            /* lc “calpella”; aka pch lan */
1806                 return i82577;
1807         case 0x10eb:            /* lm “calpella” */
1808                 return i82577m;
1809         case 0x10ef:            /* dc “piketon” */
1810                 return i82578;
1811         case 0x1502:            /* lm */
1812         case 0x1503:            /* v “lewisville” */
1813                 return i82579;
1814         case 0x10f0:            /* dm “king's creek” */
1815                 return i82578m;
1816         case 0x150e:            /* copper “barton hills” */
1817         case 0x150f:            /* fiber */
1818         case 0x1510:            /* serdes backplane */
1819         case 0x1511:            /* sgmii sfp */
1820         case 0x1516:            /* copper */
1821                 return i82580;
1822         case 0x1506:            /* v */
1823         case 0x150c:            /* untested */
1824                 return i82583;
1825         case 0x151f:            /* “powerville” eeprom-less */
1826         case 0x1521:            /* copper */
1827         case 0x1522:            /* fiber */
1828         case 0x1523:            /* serdes */
1829         case 0x1524:            /* sgmii */
1830         case 0x1546:            /* untested */
1831                 return i350;
1832         }
1833         return -1;
1834 }
1835
1836 static void
1837 hbafixup(Pcidev *p)
1838 {
1839         uint i;
1840
1841         i = pcicfgr32(p, PciSVID);
1842         if((i & 0xffff) == 0x1b52 && p->did == 1)
1843                 p->did = i>>16;
1844 }
1845
1846 static void
1847 i82563pci(void)
1848 {
1849         int type;
1850         Ctlr *ctlr;
1851         Pcidev *p;
1852
1853         for(p = nil; p = pcimatch(p, 0x8086, 0);){
1854                 hbafixup(p);
1855                 if((type = didtype(p->did)) == -1)
1856                         continue;
1857                 ctlr = malloc(sizeof(Ctlr));
1858                 if(ctlr == nil){
1859                         print("%s: can't allocate memory\n", cttab[type].name);
1860                         continue;
1861                 }
1862                 ctlr->type = type;
1863                 ctlr->pcidev = p;
1864                 ctlr->rbsz = cttab[type].mtu;
1865                 ctlr->port = p->mem[0].bar & ~0x0F;
1866                 if(i82563ctlrhead != nil)
1867                         i82563ctlrtail->next = ctlr;
1868                 else
1869                         i82563ctlrhead = ctlr;
1870                 i82563ctlrtail = ctlr;
1871         }
1872 }
1873
1874 static int
1875 setup(Ctlr *ctlr)
1876 {
1877         Pcidev *p;
1878
1879         p = ctlr->pcidev;
1880         ctlr->nic = vmap(ctlr->port, p->mem[0].size);
1881         if(ctlr->nic == nil){
1882                 print("%s: can't map %#p\n", cname(ctlr), ctlr->port);
1883                 return -1;
1884         }
1885         if(i82563reset(ctlr)){
1886                 vunmap(ctlr->nic, p->mem[0].size);
1887                 return -1;
1888         }
1889         pcisetbme(ctlr->pcidev);
1890         return 0;
1891 }
1892
1893 static int
1894 pnp(Ether *edev, int type)
1895 {
1896         Ctlr *ctlr;
1897         static int done;
1898
1899         if(!done) {
1900                 i82563pci();
1901                 done = 1;
1902         }
1903
1904         /*
1905          * Any adapter matches if no edev->port is supplied,
1906          * otherwise the ports must match.
1907          */
1908         for(ctlr = i82563ctlrhead; ; ctlr = ctlr->next){
1909                 if(ctlr == nil)
1910                         return -1;
1911                 if(ctlr->active)
1912                         continue;
1913                 if(type != -1 && ctlr->type != type)
1914                         continue;
1915                 if(edev->port == 0 || edev->port == ctlr->port){
1916                         ctlr->active = 1;
1917                         memmove(ctlr->ra, edev->ea, Eaddrlen);
1918                         if(setup(ctlr) == 0)
1919                                 break;
1920                 }
1921         }
1922
1923         edev->ctlr = ctlr;
1924         edev->port = ctlr->port;
1925         edev->irq = ctlr->pcidev->intl;
1926         edev->tbdf = ctlr->pcidev->tbdf;
1927         edev->mbps = 1000;
1928         edev->maxmtu = ctlr->rbsz;
1929         memmove(edev->ea, ctlr->ra, Eaddrlen);
1930
1931         /*
1932          * Linkage to the generic ethernet driver.
1933          */
1934         edev->attach = i82563attach;
1935 //      edev->transmit = i82563transmit;
1936         edev->interrupt = i82563interrupt;
1937         edev->ifstat = i82563ifstat;
1938         edev->ctl = i82563ctl;
1939
1940         edev->arg = edev;
1941         edev->promiscuous = i82563promiscuous;
1942         edev->shutdown = i82563shutdown;
1943         edev->multicast = i82563multicast;
1944
1945         return 0;
1946 }
1947
1948 static int
1949 anypnp(Ether *e)
1950 {
1951         return pnp(e, -1);
1952 }
1953
1954 static int
1955 i82563pnp(Ether *e)
1956 {
1957         return pnp(e, i82563);
1958 }
1959
1960 static int
1961 i82566pnp(Ether *e)
1962 {
1963         return pnp(e, i82566);
1964 }
1965
1966 static int
1967 i82567pnp(Ether *e)
1968 {
1969         return pnp(e, i82567m) & pnp(e, i82567);
1970 }
1971
1972 static int
1973 i82571pnp(Ether *e)
1974 {
1975         return pnp(e, i82571);
1976 }
1977
1978 static int
1979 i82572pnp(Ether *e)
1980 {
1981         return pnp(e, i82572);
1982 }
1983
1984 static int
1985 i82573pnp(Ether *e)
1986 {
1987         return pnp(e, i82573);
1988 }
1989
1990 static int
1991 i82574pnp(Ether *e)
1992 {
1993         return pnp(e, i82574);
1994 }
1995
1996 static int
1997 i82575pnp(Ether *e)
1998 {
1999         return pnp(e, i82575);
2000 }
2001
2002 static int
2003 i82576pnp(Ether *e)
2004 {
2005         return pnp(e, i82576);
2006 }
2007
2008 static int
2009 i82577pnp(Ether *e)
2010 {
2011         return pnp(e, i82577m) & pnp(e, i82577);
2012 }
2013
2014 static int
2015 i82578pnp(Ether *e)
2016 {
2017         return pnp(e, i82578m) & pnp(e, i82578);
2018 }
2019
2020 static int
2021 i82579pnp(Ether *e)
2022 {
2023         return pnp(e, i82579);
2024 }
2025
2026 static int
2027 i82580pnp(Ether *e)
2028 {
2029         return pnp(e, i82580);
2030 }
2031
2032 static int
2033 i82583pnp(Ether *e)
2034 {
2035         return pnp(e, i82583);
2036 }
2037
2038 static int
2039 i350pnp(Ether *e)
2040 {
2041         return pnp(e, i350);
2042 }
2043
2044 void
2045 ether82563link(void)
2046 {
2047         /*
2048          * recognise lots of model numbers for debugging
2049          * also good for forcing onboard nic(s) as ether0
2050          * try to make that unnecessary by listing lom first.
2051          */
2052         addethercard("i82563", i82563pnp);
2053         addethercard("i82566", i82566pnp);
2054         addethercard("i82574", i82574pnp);
2055         addethercard("i82576", i82576pnp);
2056         addethercard("i82567", i82567pnp);
2057         addethercard("i82573", i82573pnp);
2058
2059         addethercard("i82571", i82571pnp);
2060         addethercard("i82572", i82572pnp);
2061         addethercard("i82575", i82575pnp);
2062         addethercard("i82577", i82577pnp);
2063         addethercard("i82578", i82578pnp);
2064         addethercard("i82579", i82579pnp);
2065         addethercard("i82580", i82580pnp);
2066         addethercard("i82583", i82583pnp);
2067         addethercard("i350", i350pnp);
2068         addethercard("igbepcie", anypnp);
2069 }