2 * Intel 8256[367], 8257[1-9], 8258[03], i350
3 * Gigabit Ethernet PCI-Express Controllers
4 * Coraid EtherDrive® hba
7 #include "../port/lib.h"
12 #include "../port/error.h"
13 #include "../port/netif.h"
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.
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 */
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 */
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 */
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 */
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,
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 */
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 */
135 EEstart = 1<<0, /* Start Read */
136 EEdone = 1<<1, /* Read done */
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 */
149 Enrgirq = 1<<2, /* interrupt on power detect (enrgsrc) */
152 enum { /* EEPROM content offsets */
153 Ea = 0x00, /* Ethernet Address */
157 MDIdMASK = 0x0000FFFF, /* Data */
159 MDIrMASK = 0x001F0000, /* PHY Register Address */
161 MDIpMASK = 0x03E00000, /* PHY Address */
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 */
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 */
180 Rtlink = 1<<10, /* realtime link status */
181 Phyan = 1<<11, /* phy has autonegotiated */
184 Ran = 1<<9, /* restart auto negotiation */
185 Ean = 1<<12, /* enable auto negotiation */
188 Prst = 1<<0, /* reset the port */
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 */
196 /* Phylhr/Phyisr bits */
197 Anf = 1<<6, /* lhr: auto negotiation fault */
198 Ane = 1<<15, /* isr: auto negotiation error */
200 /* 82580 Phystat bits */
201 Ans = 1<<14 | 1<<15, /* 82580 autoneg. status */
202 Link = 1<<6, /* 82580 Link */
204 /* Rxcw builtin serdes */
217 enum { /* fiber (pcs) interface */
218 Pcsctl = 0x4208, /* pcs control */
219 Pcsstat = 0x420c, /* pcs status */
222 Pan = 1<<16, /* autoegotiate */
223 Prestart = 1<<17, /* restart an (self clearing) */
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 */
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 */
247 TxcwFd = 0x00000020, /* Full Duplex */
248 TxcwHd = 0x00000040, /* Half Duplex */
249 TxcwPauseMASK = 0x00000180, /* Pause */
251 TxcwPs = 1<<TxcwPauseSHIFT, /* Pause Supported */
252 TxcwAs = 2<<TxcwPauseSHIFT, /* Asymmetric FC desired */
253 TxcwRfiMASK = 0x00003000, /* Remote Fault Indication */
255 TxcwNpr = 0x00008000, /* Next Page Request */
256 TxcwConfig = 0x40000000, /* Transmit COnfig Control */
257 TxcwAne = 0x80000000, /* Auto-Negotiation Enable */
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 */
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 */
301 ColdMASK = 0x003FF000, /* Collision Distance */
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 */
309 enum { /* [RT]xdctl */
310 PthreshMASK = 0x0000003F, /* Prefetch Threshold */
312 HthreshMASK = 0x00003F00, /* Host Threshold */
314 WthreshMASK = 0x003F0000, /* Writeback Threshold */
316 Gran = 0x01000000, /* Granularity; not 82575 */
321 Ipofl = 0x0100, /* IP Checksum Off-load Enable */
322 Tuofl = 0x0200, /* TCP/UDP Checksum Off-load Enable */
325 typedef struct Rd { /* Receive Descriptor */
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 */
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 */
354 typedef struct { /* Transmit Descriptor */
355 u32int addr[2]; /* Data */
360 enum { /* Tdesc control */
361 LenMASK = 0x000FFFFF, /* Data/Packet Length Field */
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 */
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 */
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 */
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 */
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 */
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 */
422 * cavet emptor: 82577/78 have been entered speculatitively.
423 * awating datasheet from intel.
456 typedef struct Ctlrtype Ctlrtype;
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",
485 typedef void (*Freefn)(Block*);
487 typedef struct Ctlr Ctlr;
496 QLock alock; /* attach */
497 void *alloc; /* receive/transmit descriptors */
504 int im; /* interrupt mask */
510 u32int statistics[Nstatistics];
523 uchar ra[Eaddrlen]; /* receive address */
524 u32int mta[128]; /* multicast table array */
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 */
539 Td *tdba; /* transmit descriptor base address */
540 Block **tb; /* transmit buffers */
541 int tdh; /* transmit descriptor head */
542 int tdt; /* transmit descriptor tail */
547 u32int pba; /* packet buffer allocation */
550 #define csr32r(c, r) (*((c)->nic+((r)/4)))
551 #define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v))
553 static Ctlr *i82563ctlrhead;
554 static Ctlr *i82563ctlrtail;
556 static char *statistics[Nstatistics] = {
563 "Excessive Collisions",
564 "Multiple Collision",
572 "Carrier Extension Error",
573 "Receive Error Length",
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",
591 "Good Octets Received",
593 "Good Octets Transmitted",
597 "Receive No Buffers",
602 "Management Packets Rx",
603 "Management Packets Drop",
604 "Management Packets Tx",
605 "Total Octets Received",
607 "Total Octets Transmitted",
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",
629 "Interrupt Rx Overrun",
635 return cttab[c->type].name;
639 i82563ifstat(Ether *edev, void *a, long n, ulong offset)
641 char *s, *p, *e, *stat;
646 p = s = smalloc(READSTR);
652 for(i = 0; i < Nstatistics; i++){
653 r = csr32r(ctlr, Statistics + i*4);
654 if((stat = statistics[i]) == nil)
662 ruvl += (uvlong)csr32r(ctlr, Statistics+(i+1)*4) << 32;
664 tuvl += ctlr->statistics[i];
665 tuvl += (uvlong)ctlr->statistics[i+1] << 32;
668 ctlr->statistics[i] = tuvl;
669 ctlr->statistics[i+1] = tuvl >> 32;
670 p = seprint(p, e, "%s: %llud %llud\n", stat, tuvl, ruvl);
675 ctlr->statistics[i] += r;
676 if(ctlr->statistics[i] == 0)
678 p = seprint(p, e, "%s: %ud %ud\n", stat,
679 ctlr->statistics[i], r);
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);
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));
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]);
707 // p = seprint(p, e, "\n");
710 n = readstr(offset, a, n, s);
712 qunlock(&ctlr->slock);
718 i82563promiscuous(void *arg, int on)
727 rctl = csr32r(ctlr, Rctl);
733 csr32w(ctlr, Rctl, rctl);
737 i82563multicast(void *arg, uchar *addr, int on)
747 if(ctlr->type == i82566)
749 bit = ((addr[5] & 1)<<4)|(addr[4]>>4);
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.
758 ctlr->mta[x] |= 1<<bit;
760 // ctlr->mta[x] &= ~(1<<bit);
762 csr32w(ctlr, Mta+x*4, ctlr->mta[x]);
766 i82563im(Ctlr *ctlr, int im)
768 ilock(&ctlr->imlock);
770 csr32w(ctlr, Ims, ctlr->im);
771 iunlock(&ctlr->imlock);
775 i82563txinit(Ctlr *ctlr)
781 if(cttab[ctlr->type].flag & F75)
782 csr32w(ctlr, Tctl, 0x0F<<CtSHIFT | Psp);
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){
791 memset(&ctlr->tdba[i], 0, sizeof(Td));
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);
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)
807 csr32w(ctlr, Txdctl, r);
811 i82563cleanup(Ctlr *c)
817 while(c->tdba[n = NEXT(tdh, c->ntd)].status & Tdd){
819 if((b = c->tb[tdh]) != nil){
823 iprint("82563 tx underrun!\n");
824 c->tdba[tdh].status = 0;
836 return (c->im & Txdw) == 0;
854 n = NEXT(tdt, ctlr->ntd);
855 if(n == i82563cleanup(ctlr)){
857 i82563im(ctlr, Txdw);
858 sleep(&ctlr->trendez, notrim, ctlr);
861 bp = qbread(edev->oq, 100000);
862 td = &ctlr->tdba[tdt];
863 td->addr[0] = PCIWADDR(bp->rp);
865 td->control = Ide|Rs|Ifcs|Teop|BLEN(bp);
869 csr32w(ctlr, Tdt, tdt);
874 i82563replenish(Ctlr *ctlr)
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");
888 bp = allocb(ctlr->rbsz + Rbalign);
889 bp->rp = bp->wp = (uchar*)ROUND((uintptr)bp->base, Rbalign);
891 rd->addr[0] = PCIWADDR(bp->rp);
899 csr32w(ctlr, Rdt, rdt);
904 i82563rxinit(Ctlr *ctlr)
909 if(ctlr->rbsz <= 2048)
910 csr32w(ctlr, Rctl, Dpf|Bsize2048|Bam|RdtmsHALF);
912 i = ctlr->rbsz / 1024;
913 if(ctlr->rbsz % 1024)
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);
923 csr32w(ctlr, Rctl, Lpe|Dpf|BsizeFlex*i|Bam|RdtmsHALF|Secrc);
926 if(cttab[ctlr->type].flag & Fert)
927 csr32w(ctlr, Ert, 1024/8);
929 if(ctlr->type == i82566)
930 csr32w(ctlr, Pbs, 16);
932 csr32w(ctlr, Rdbal, PCIWADDR(ctlr->rdba));
933 csr32w(ctlr, Rdbah, 0);
934 csr32w(ctlr, Rdlen, ctlr->nrd * sizeof(Rd));
936 csr32w(ctlr, Rdh, 0);
938 csr32w(ctlr, Rdt, 0);
941 csr32w(ctlr, Rdtr, ctlr->rdtr);
942 csr32w(ctlr, Radv, ctlr->radv);
944 for(i = 0; i < ctlr->nrd; i++)
945 if((bp = ctlr->rb[i]) != nil){
949 if(cttab[ctlr->type].flag & F75)
950 csr32w(ctlr, Rxdctl, 1<<WthreshSHIFT | 8<<PthreshSHIFT | 1<<HthreshSHIFT | Enable);
952 csr32w(ctlr, Rxdctl, 2<<WthreshSHIFT | 2<<PthreshSHIFT);
955 * Enable checksum offload.
957 csr32w(ctlr, Rxcsum, Tuofl | Ipofl | ETHERHDRSIZE);
963 return ((Ctlr*)v)->rim != 0;
967 i82563rproc(void *arg)
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;
984 im = Rxt0|Rxo|Rxdmt0|Rxseq|Ack;
989 i82563replenish(ctlr);
990 sleep(&ctlr->rrendez, i82563rim, ctlr);
996 rd = &ctlr->rdba[rdh];
997 if(!(rd->status & Rdd))
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.
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)){
1013 if(rd->status & Ipcs){
1015 * IP checksum calculated
1016 * (and valid as errors == 0).
1021 if(rd->status & Tcpcs){
1023 * TCP/UDP checksum calculated
1024 * (and valid as errors == 0).
1027 bp->flag |= Btcpck|Budpck;
1029 bp->checksum = rd->checksum;
1032 etheriq(edev, bp, 1);
1035 ctlr->rb[rdh] = nil;
1037 ctlr->rdh = rdh = NEXT(rdh, ctlr->nrd);
1038 if(ctlr->nrd-ctlr->rdfree >= 32 || (rim & Rxdmt0))
1039 i82563replenish(ctlr);
1047 return ((Ctlr*)v)->lim != 0;
1050 static int speedtab[] = {
1055 phyread(Ctlr *c, int phyno, int reg)
1059 csr32w(c, Mdic, MDIrop | phyno<<MDIpSHIFT | reg<<MDIrSHIFT);
1061 for(i = 0; i < 64; i++){
1062 phy = csr32r(c, Mdic);
1063 if(phy & (MDIe|MDIready))
1067 if((phy & (MDIe|MDIready)) != MDIready){
1068 print("%s: phy %d wedged %.8ux\n", cttab[c->type].name, phyno, phy);
1071 return phy & 0xffff;
1075 phywrite0(Ctlr *c, int phyno, int reg, ushort val)
1079 csr32w(c, Mdic, MDIwop | phyno<<MDIpSHIFT | reg<<MDIrSHIFT | val);
1081 for(i = 0; i < 64; i++){
1082 phy = csr32r(c, Mdic);
1083 if(phy & (MDIe|MDIready))
1087 if((phy & (MDIe|MDIready)) != MDIready)
1093 setpage(Ctlr *c, uint phyno, uint p, uint r)
1097 if(c->type == i82563){
1098 if(r >= 16 && r <= 28 && r != 22)
1100 else if(r == 30 || r == 31)
1104 return phywrite0(c, phyno, pr, p);
1111 phywrite(Ctlr *c, uint phyno, uint reg, ushort v)
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);
1119 phyerrata(Ether *e, Ctlr *c)
1122 if(c->phyerrata == 0){
1124 phywrite(c, 1, Phyprst, Prst); /* try a port reset */
1125 print("%s: phy port reset\n", cname(c));
1134 uint a, i, r, phy, phyno;
1142 if(c->type == i82579)
1146 phy = phyread(c, phyno, Phystat);
1155 r = phyread(c, phyno, Phyctl);
1156 phywrite(c, phyno, Phyctl, r | Ran | Ean);
1159 e->link = i != 3 && (phy & Link) != 0;
1163 e->mbps = speedtab[i];
1167 sleep(&c->lrendez, i82563lim, c);
1181 if(c->type == i82573 && (phy = phyread(c, 1, Phyier)) != ~0)
1182 phywrite(c, 1, Phyier, phy | Lscie | Ancie | Spdie | Panie);
1184 phy = phyread(c, 1, Physsr);
1199 a = phyread(c, 1, Phyisr) & Ane;
1205 a = phyread(c, 1, Phylhr) & Anf;
1210 phywrite(c, 1, Phyctl, phyread(c, 1, Phyctl) | Ran | Ean);
1212 e->link = (phy & Rtlink) != 0;
1216 e->mbps = speedtab[i];
1217 if(c->type == i82563)
1222 sleep(&c->lrendez, i82563lim, c);
1236 if(c->type == i82575 || c->type == i82576)
1237 csr32w(c, Connsw, Enrgirq);
1239 phy = csr32r(c, Pcsstat);
1240 e->link = phy & Linkok;
1244 else if(phy & Anbad)
1245 csr32w(c, Pcsctl, csr32r(c, Pcsctl) | Pan | Prestart);
1247 e->mbps = speedtab[i];
1249 i82563im(c, Lsc | Omed);
1251 sleep(&c->lrendez, i82563lim, c);
1256 serdeslproc(void *v)
1266 rx = csr32r(c, Rxcw);
1267 tx = csr32r(c, Txcw);
1269 e->link = (rx & 1<<31) != 0;
1270 // e->link = (csr32r(c, Status) & Lu) != 0;
1275 e->mbps = speedtab[i];
1279 sleep(&c->lrendez, i82563lim, c);
1294 i = csr32r(c, Status);
1295 e->link = (i & Lu) != 0;
1296 i = (i >> 6) & 3; /* link speed 6:7 */
1300 e->mbps = speedtab[i];
1304 sleep(&c->lrendez, i82563lim, c);
1309 i82563attach(Ether *edev)
1311 char name[KNAMELEN];
1315 qlock(&ctlr->alock);
1316 if(ctlr->alloc != nil){
1317 qunlock(&ctlr->alock);
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){
1333 qunlock(&ctlr->alock);
1336 ctlr->rdba = (Rd*)ROUNDUP((uintptr)ctlr->alloc, 256);
1337 ctlr->tdba = (Td*)(ctlr->rdba + ctlr->nrd);
1346 qunlock(&ctlr->alock);
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 */
1360 kproc(name, phylproc, edev);
1362 snprint(name, sizeof name, "#l%dr", edev->ctlrno);
1363 kproc(name, i82563rproc, edev);
1365 snprint(name, sizeof name, "#l%dt", edev->ctlrno);
1366 kproc(name, i82563tproc, edev);
1368 qunlock(&ctlr->alock);
1373 i82563interrupt(Ureg*, void *arg)
1382 ilock(&ctlr->imlock);
1383 csr32w(ctlr, Imc, ~0);
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);
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);
1402 wakeup(&ctlr->trendez);
1407 csr32w(ctlr, Ims, im);
1408 iunlock(&ctlr->imlock);
1412 i82563detach(Ctlr *ctlr)
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;
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);
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.
1432 csr32w(ctlr, Imc, ~0);
1433 csr32w(ctlr, Rctl, 0);
1434 csr32w(ctlr, Tctl, csr32r(ctlr, Tctl) & ~Ten);
1438 r = csr32r(ctlr, Ctrl);
1439 if(ctlr->type == i82566 || ctlr->type == i82579)
1442 * hack: 82579LM on lenovo X230 is stuck at 10mbps after
1443 * reseting the phy, but works fine if we dont reset.
1445 if(ctlr->pcidev->did == 0x1502)
1447 csr32w(ctlr, Ctrl, Devrst | r);
1449 for(timeo = 0;; timeo++){
1450 if((csr32r(ctlr, Ctrl) & (Devrst|Phyrst)) == 0)
1457 r = csr32r(ctlr, Ctrl);
1458 csr32w(ctlr, Ctrl, Slu|r);
1460 r = csr32r(ctlr, Ctrlext);
1461 csr32w(ctlr, Ctrlext, r|Eerst);
1463 for(timeo = 0; timeo < 1000; timeo++){
1464 if(!(csr32r(ctlr, Ctrlext) & Eerst))
1468 if(csr32r(ctlr, Ctrlext) & Eerst)
1471 csr32w(ctlr, Imc, ~0);
1473 for(timeo = 0; timeo < 1000; timeo++){
1474 if((csr32r(ctlr, Icr) & ~Rxcfg) == 0)
1478 if(csr32r(ctlr, Icr) & ~Rxcfg)
1485 i82563shutdown(Ether *edev)
1487 i82563detach(edev->ctlr);
1491 eeread(Ctlr *ctlr, int adr)
1495 csr32w(ctlr, Eerd, EEstart | adr << 2);
1497 while ((csr32r(ctlr, Eerd) & EEdone) == 0 && timeout--)
1500 print("%s: eeread timeout\n", cname(ctlr));
1503 return (csr32r(ctlr, Eerd) >> 16) & 0xffff;
1513 for (adr = 0; adr < 0x40; adr++) {
1514 data = eeread(ctlr, adr);
1515 if(data == -1) return -1;
1516 ctlr->eeprom[adr] = data;
1523 fcycle(Ctlr *, Flash *f)
1531 f->reg[Fsts] |= Fcerr | Ael;
1532 for(i = 0; i < 10; i++){
1542 fread(Ctlr *c, Flash *f, int ladr)
1548 if(fcycle(c, f) == -1)
1550 f->reg[Fsts] |= Fdone;
1551 f->reg32[Faddr] = ladr;
1553 /* setup flash control register */
1554 s = f->reg[Fctl] & ~0x3ff;
1555 f->reg[Fctl] = s | 1<<8 | Fgo; /* 2 byte read */
1557 while((f->reg[Fsts] & Fdone) == 0 && timeout--)
1560 print("%s: fread timeout\n", cname(c));
1563 if(f->reg[Fsts] & (Fcerr|Ael))
1565 return f->reg32[Fdata] & 0xffff;
1576 va = vmap(c->pcidev->mem[1].bar & ~0x0f, c->pcidev->mem[1].size);
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;
1587 for(adr = 0; adr < 0x40; adr++) {
1588 data = fread(c, &f, r + adr*2);
1591 c->eeprom[adr] = data;
1594 vunmap(va, c->pcidev->mem[1].size);
1599 defaultea(Ctlr *ctlr, uchar *ra)
1603 static uchar nilea[Eaddrlen];
1605 if(memcmp(ra, nilea, Eaddrlen) != 0)
1607 if(cttab[ctlr->type].flag & Fflashea){
1609 u = (uvlong)csr32r(ctlr, Rah)<<32u | (ulong)csr32r(ctlr, Ral);
1610 for(i = 0; i < Eaddrlen; i++)
1613 if(memcmp(ra, nilea, Eaddrlen) != 0)
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;
1619 r = (csr32r(ctlr, Status) & Lanid) >> 2;
1620 ra[5] += r; /* ea ctlr[n] = ea ctlr[0]+n */
1624 i82563reset(Ctlr *ctlr)
1629 if(i82563detach(ctlr))
1631 if(cttab[ctlr->type].flag & Fload)
1635 if(r != 0 && r != 0xbaba){
1636 print("%s: bad eeprom checksum - %#.4ux\n",
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);
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 */
1671 static Cmdtab i82563ctlmsg[] = {
1674 CMpause, "pause", 1,
1679 i82563ctl(Ether *edev, void *buf, long n)
1687 if((ctlr = edev->ctlr) == nil)
1690 cb = parsecmd(buf, n);
1696 ct = lookupcmd(cb, i82563ctlmsg, nelem(i82563ctlmsg));
1699 v = strtoul(cb->f[1], &p, 0);
1700 if(*p || v > 0xffff)
1703 csr32w(ctlr, Rdtr, v);
1706 v = strtoul(cb->f[1], &p, 0);
1707 if(*p || v > 0xffff)
1710 csr32w(ctlr, Radv, v);
1713 csr32w(ctlr, Ctrl, csr32r(ctlr, Ctrl) ^ (Rfce | Tfce));
1716 csr32w(ctlr, Ctrl, csr32r(ctlr, Ctrl) | Lrst | Phyrst);
1729 * Some names and did values are from
1730 * OpenBSD's em(4) Intel driver.
1733 case 0x1096: /* copper */
1734 case 0x10ba: /* copper “gilgal” */
1735 case 0x1098: /* serdes; not seen */
1736 case 0x10bb: /* serdes */
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 */
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 */
1758 case 0x10bf: /* lf ich9m */
1759 case 0x10cb: /* v ich9m */
1760 case 0x10cd: /* lf ich10 */
1761 case 0x10cc: /* lm ich10 */
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 */
1775 case 0x107d: /* ei copper */
1776 case 0x107e: /* ei fiber */
1777 case 0x107f: /* ei serdes */
1778 case 0x10b9: /* ei “rimon” */
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 */
1788 case 0x10d3: /* l or it; “hartwell” */
1789 case 0x10f6: /* la; untested */
1791 case 0x10a7: /* eb */
1792 case 0x10a9: /* eb fiber/serdes */
1793 case 0x10d6: /* untested */
1794 case 0x10e2: /* untested */
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 */
1805 case 0x10ea: /* lc “calpella”; aka pch lan */
1807 case 0x10eb: /* lm “calpella” */
1809 case 0x10ef: /* dc “piketon” */
1811 case 0x1502: /* lm */
1812 case 0x1503: /* v “lewisville” */
1814 case 0x10f0: /* dm “king's creek” */
1816 case 0x150e: /* copper “barton hills” */
1817 case 0x150f: /* fiber */
1818 case 0x1510: /* serdes backplane */
1819 case 0x1511: /* sgmii sfp */
1820 case 0x1516: /* copper */
1822 case 0x1506: /* v */
1823 case 0x150c: /* untested */
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 */
1841 i = pcicfgr32(p, PciSVID);
1842 if((i & 0xffff) == 0x1b52 && p->did == 1)
1853 for(p = nil; p = pcimatch(p, 0x8086, 0);){
1855 if((type = didtype(p->did)) == -1)
1857 ctlr = malloc(sizeof(Ctlr));
1859 print("%s: can't allocate memory\n", cttab[type].name);
1864 ctlr->rbsz = cttab[type].mtu;
1865 ctlr->port = p->mem[0].bar & ~0x0F;
1866 if(i82563ctlrhead != nil)
1867 i82563ctlrtail->next = ctlr;
1869 i82563ctlrhead = ctlr;
1870 i82563ctlrtail = ctlr;
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);
1885 if(i82563reset(ctlr)){
1886 vunmap(ctlr->nic, p->mem[0].size);
1889 pcisetbme(ctlr->pcidev);
1894 pnp(Ether *edev, int type)
1905 * Any adapter matches if no edev->port is supplied,
1906 * otherwise the ports must match.
1908 for(ctlr = i82563ctlrhead; ; ctlr = ctlr->next){
1913 if(type != -1 && ctlr->type != type)
1915 if(edev->port == 0 || edev->port == ctlr->port){
1917 memmove(ctlr->ra, edev->ea, Eaddrlen);
1918 if(setup(ctlr) == 0)
1924 edev->port = ctlr->port;
1925 edev->irq = ctlr->pcidev->intl;
1926 edev->tbdf = ctlr->pcidev->tbdf;
1928 edev->maxmtu = ctlr->rbsz;
1929 memmove(edev->ea, ctlr->ra, Eaddrlen);
1932 * Linkage to the generic ethernet driver.
1934 edev->attach = i82563attach;
1935 // edev->transmit = i82563transmit;
1936 edev->interrupt = i82563interrupt;
1937 edev->ifstat = i82563ifstat;
1938 edev->ctl = i82563ctl;
1941 edev->promiscuous = i82563promiscuous;
1942 edev->shutdown = i82563shutdown;
1943 edev->multicast = i82563multicast;
1957 return pnp(e, i82563);
1963 return pnp(e, i82566);
1969 return pnp(e, i82567m) & pnp(e, i82567);
1975 return pnp(e, i82571);
1981 return pnp(e, i82572);
1987 return pnp(e, i82573);
1993 return pnp(e, i82574);
1999 return pnp(e, i82575);
2005 return pnp(e, i82576);
2011 return pnp(e, i82577m) & pnp(e, i82577);
2017 return pnp(e, i82578m) & pnp(e, i82578);
2023 return pnp(e, i82579);
2029 return pnp(e, i82580);
2035 return pnp(e, i82583);
2041 return pnp(e, i350);
2045 ether82563link(void)
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.
2052 addethercard("i82563", i82563pnp);
2053 addethercard("i82566", i82566pnp);
2054 addethercard("i82574", i82574pnp);
2055 addethercard("i82576", i82576pnp);
2056 addethercard("i82567", i82567pnp);
2057 addethercard("i82573", i82573pnp);
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);