/* * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ /* * Intel Gigabit Ethernet PCI-Express Controllers. * 8256[36], 8257[1-79] * Pretty basic, does not use many of the chip smarts. * The interrupt mitigation tuning for each chip variant * is probably different. The reset/initialisation * sequence needs straightened out. Doubt the PHY code * for the 82575eb is right. */#include "u.h"#include "../port/lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "io.h"#include "../port/error.h"#include "../port/netif.h" #include "etherif.h" /* * these are in the order they appear in the manual, not numeric order. * It was too hard to find them in the book. Ref 21489, rev 2.6 */ enum { /* General */ Ctrl = 0x0000, /* Device Control */ Status = 0x0008, /* Device Status */ Eec = 0x0010, /* EEPROM/Flash Control/Data */ Eerd = 0x0014, /* EEPROM Read */ Ctrlext = 0x0018, /* Extended Device Control */ Fla = 0x001c, /* Flash Access */ Mdic = 0x0020, /* MDI Control */ Seresctl = 0x0024, /* Serdes ana */ Fcal = 0x0028, /* Flow Control Address Low */ Fcah = 0x002C, /* Flow Control Address High */ Fct = 0x0030, /* Flow Control Type */ Kumctrlsta = 0x0034, /* MAC-PHY Interface */ Vet = 0x0038, /* VLAN EtherType */ Fcttv = 0x0170, /* Flow Control Transmit Timer Value */ Txcw = 0x0178, /* Transmit Configuration Word */ Rxcw = 0x0180, /* Receive Configuration Word */ Ledctl = 0x0E00, /* LED control */ Pba = 0x1000, /* Packet Buffer Allocation */ Pbs = 0x1008, /* Packet Buffer Size */ /* Interrupt */ Icr = 0x00C0, /* Interrupt Cause Read */ Itr = 0x00c4, /* Interrupt Throttling Rate */ Ics = 0x00C8, /* Interrupt Cause Set */ Ims = 0x00D0, /* Interrupt Mask Set/Read */ Imc = 0x00D8, /* Interrupt mask Clear */ Iam = 0x00E0, /* Interrupt acknowledge Auto Mask */ /* Receive */ Rctl = 0x0100, /* Control */ Ert = 0x2008, /* Early Receive Threshold (573[EVL], 579 only) */ Fcrtl = 0x2160, /* Flow Control RX Threshold Low */ Fcrth = 0x2168, /* Flow Control Rx Threshold High */ Psrctl = 0x2170, /* Packet Split Receive Control */ Rdbal = 0x2800, /* Rdesc Base Address Low Queue 0 */ Rdbah = 0x2804, /* Rdesc Base Address High Queue 0 */ Rdlen = 0x2808, /* Descriptor Length Queue 0 */ Rdh = 0x2810, /* Descriptor Head Queue 0 */ Rdt = 0x2818, /* Descriptor Tail Queue 0 */ Rdtr = 0x2820, /* Descriptor Timer Ring */ Rxdctl = 0x2828, /* Descriptor Control */ Radv = 0x282C, /* Interrupt Absolute Delay Timer */ Rdbal1 = 0x2900, /* Rdesc Base Address Low Queue 1 */ Rdbah1 = 0x2804, /* Rdesc Base Address High Queue 1 */ Rdlen1 = 0x2908, /* Descriptor Length Queue 1 */ Rdh1 = 0x2910, /* Descriptor Head Queue 1 */ Rdt1 = 0x2918, /* Descriptor Tail Queue 1 */ Rxdctl1 = 0x2928, /* Descriptor Control Queue 1 */ Rsrpd = 0x2c00, /* Small Packet Detect */ Raid = 0x2c08, /* ACK interrupt delay */ Cpuvec = 0x2c10, /* CPU Vector */ Rxcsum = 0x5000, /* Checksum Control */ Rfctl = 0x5008, /* Filter Control */ Mta = 0x5200, /* Multicast Table Array */ Ral = 0x5400, /* Receive Address Low */ Rah = 0x5404, /* Receive Address High */ Vfta = 0x5600, /* VLAN Filter Table Array */ Mrqc = 0x5818, /* Multiple Receive Queues Command */ Rssim = 0x5864, /* RSS Interrupt Mask */ Rssir = 0x5868, /* RSS Interrupt Request */ Reta = 0x5c00, /* Redirection Table */ Rssrk = 0x5c80, /* RSS Random Key */ /* Transmit */ Tctl = 0x0400, /* Transmit Control */ Tipg = 0x0410, /* Transmit IPG */ Tkabgtxd = 0x3004, /* glci afe band gap transmit ref data, or something */ Tdbal = 0x3800, /* Tdesc Base Address Low */ Tdbah = 0x3804, /* Tdesc Base Address High */ Tdlen = 0x3808, /* Descriptor Length */ Tdh = 0x3810, /* Descriptor Head */ Tdt = 0x3818, /* Descriptor Tail */ Tidv = 0x3820, /* Interrupt Delay Value */ Txdctl = 0x3828, /* Descriptor Control */ Tadv = 0x382C, /* Interrupt Absolute Delay Timer */ Tarc0 = 0x3840, /* Arbitration Counter Queue 0 */ Tdbal1 = 0x3900, /* Descriptor Base Low Queue 1 */ Tdbah1 = 0x3904, /* Descriptor Base High Queue 1 */ Tdlen1 = 0x3908, /* Descriptor Length Queue 1 */ Tdh1 = 0x3910, /* Descriptor Head Queue 1 */ Tdt1 = 0x3918, /* Descriptor Tail Queue 1 */ Txdctl1 = 0x3928, /* Descriptor Control 1 */ Tarc1 = 0x3940, /* Arbitration Counter Queue 1 */ /* Statistics */ Statistics = 0x4000, /* Start of Statistics Area */ Gorcl = 0x88/4, /* Good Octets Received Count */ Gotcl = 0x90/4, /* Good Octets Transmitted Count */ Torl = 0xC0/4, /* Total Octets Received */ Totl = 0xC8/4, /* Total Octets Transmitted */ Nstatistics = 0x124/4,}; enum { /* Ctrl */ GIOmd = 1<<2, /* BIO master disable */ Lrst = 1<<3, /* link reset */ Slu = 1<<6, /* Set Link Up */ SspeedMASK = 3<<8, /* Speed Selection */ SspeedSHIFT = 8, Sspeed10 = 0x00000000, /* 10Mb/s */ Sspeed100 = 0x00000100, /* 100Mb/s */ Sspeed1000 = 0x00000200, /* 1000Mb/s */ Frcspd = 1<<11, /* Force Speed */ Frcdplx = 1<<12, /* Force Duplex */ SwdpinsloMASK = 0x003C0000, /* Software Defined Pins - lo nibble */ SwdpinsloSHIFT = 18, SwdpioloMASK = 0x03C00000, /* Software Defined Pins - I or O */ SwdpioloSHIFT = 22, Devrst = 1<<26, /* Device Reset */ Rfce = 1<<27, /* Receive Flow Control Enable */ Tfce = 1<<28, /* Transmit Flow Control Enable */ Vme = 1<<30, /* VLAN Mode Enable */ Phyrst = 1<<31, /* Phy Reset */}; enum { /* Status */ Lu = 1<<1, /* Link Up */ Lanid = 3<<2, /* mask for Lan ID. */ Txoff = 1<<4, /* Transmission Paused */ Tbimode = 1<<5, /* TBI Mode Indication */ Phyra = 1<<10, /* PHY Reset Asserted */ GIOme = 1<<19, /* GIO Master Enable Status */}; enum { /* Eerd */ EEstart = 1<<0, /* Start Read */ EEdone = 1<<1, /* Read done */}; enum { /* Ctrlext */ Asdchk = 1<<12, /* ASD Check */ Eerst = 1<<13, /* EEPROM Reset */ Spdbyps = 1<<15, /* Speed Select Bypass */}; enum { /* EEPROM content offsets */ Ea = 0x00, /* Ethernet Address */ Cf = 0x03, /* Compatibility Field */ Icw1 = 0x0A, /* Initialization Control Word 1 */ Sid = 0x0B, /* Subsystem ID */ Svid = 0x0C, /* Subsystem Vendor ID */ Did = 0x0D, /* Device ID */ Vid = 0x0E, /* Vendor ID */ Icw2 = 0x0F, /* Initialization Control Word 2 */}; enum { /* Mdic */ MDIdMASK = 0x0000FFFF, /* Data */ MDIdSHIFT = 0, MDIrMASK = 0x001F0000, /* PHY Register Address */ MDIrSHIFT = 16, MDIpMASK = 0x03E00000, /* PHY Address */ MDIpSHIFT = 21, MDIwop = 0x04000000, /* Write Operation */ MDIrop = 0x08000000, /* Read Operation */ MDIready = 0x10000000, /* End of Transaction */ MDIie = 0x20000000, /* Interrupt Enable */ MDIe = 0x40000000, /* Error */}; enum { /* phy interface registers */ Phyctl = 0, /* phy ctl */ Physsr = 17, /* phy secondary status */ Phyier = 18, /* 82573 phy interrupt enable */ Phyisr = 19, /* 82563 phy interrupt status */ Phylhr = 19, /* 8257[12] link health */ Rtlink = 1<<10, /* realtime link status */ Phyan = 1<<11, /* phy has auto-negotiated */ /* Phyctl bits */ Ran = 1<<9, /* restart auto-negotiation */ Ean = 1<<12, /* enable auto-negotiation */ /* 82573 Phyier bits */ Lscie = 1<<10, /* link status changed ie */ Ancie = 1<<11, /* auto-negotiation complete ie */ Spdie = 1<<14, /* speed changed ie */ Panie = 1<<15, /* phy auto-negotiation error ie */ /* Phylhr/Phyisr bits */ Anf = 1<<6, /* lhr: auto-negotiation fault */ Ane = 1<<15, /* isr: auto-negotiation error */}; enum { /* Icr, Ics, Ims, Imc */ Txdw = 0x00000001, /* Transmit Descriptor Written Back */ Txqe = 0x00000002, /* Transmit Queue Empty */ Lsc = 0x00000004, /* Link Status Change */ Rxseq = 0x00000008, /* Receive Sequence Error */ Rxdmt0 = 0x00000010, /* Rdesc Minimum Threshold Reached */ Rxo = 0x00000040, /* Receiver Overrun */ Rxt0 = 0x00000080, /* Receiver Timer Interrupt */ Mdac = 0x00000200, /* MDIO Access Completed */ Rxcfg = 0x00000400, /* Receiving /C/ ordered sets */ Gpi0 = 0x00000800, /* General Purpose Interrupts */ Gpi1 = 0x00001000, Gpi2 = 0x00002000, Gpi3 = 0x00004000, Ack = 0x00020000, /* Receive ACK frame */}; enum { /* Txcw */ TxcwFd = 0x00000020, /* Full Duplex */ TxcwHd = 0x00000040, /* Half Duplex */ TxcwPauseMASK = 0x00000180, /* Pause */ TxcwPauseSHIFT = 7, TxcwPs = 1<<TxcwPauseSHIFT, /* Pause Supported */ TxcwAs = 2<<TxcwPauseSHIFT, /* Asymmetric FC desired */ TxcwRfiMASK = 0x00003000, /* Remote Fault Indication */ TxcwRfiSHIFT = 12, TxcwNpr = 0x00008000, /* Next Page Request */ TxcwConfig = 0x40000000, /* Transmit Config Control */ TxcwAne = 0x80000000, /* Auto-Negotiation Enable */}; enum { /* Rctl */ Rrst = 0x00000001, /* Receiver Software Reset */ Ren = 0x00000002, /* Receiver Enable */ Sbp = 0x00000004, /* Store Bad Packets */ Upe = 0x00000008, /* Unicast Promiscuous Enable */ Mpe = 0x00000010, /* Multicast Promiscuous Enable */ Lpe = 0x00000020, /* Long Packet Reception Enable */ LbmMASK = 0x000000C0, /* Loopback Mode */ LbmOFF = 0x00000000, /* No Loopback */ LbmTBI = 0x00000040, /* TBI Loopback */ LbmMII = 0x00000080, /* GMII/MII Loopback */ LbmXCVR = 0x000000C0, /* Transceiver Loopback */ RdtmsMASK = 0x00000300, /* Rdesc Minimum Threshold Size */ RdtmsHALF = 0x00000000, /* Threshold is 1/2 Rdlen */ RdtmsQUARTER = 0x00000100, /* Threshold is 1/4 Rdlen */ RdtmsEIGHTH = 0x00000200, /* Threshold is 1/8 Rdlen */ MoMASK = 0x00003000, /* Multicast Offset */ Bam = 0x00008000, /* Broadcast Accept Mode */ BsizeMASK = 0x00030000, /* Receive Buffer Size */ Bsize16384 = 0x00010000, /* Bsex = 1 */ Bsize8192 = 0x00020000, /* Bsex = 1 */ Bsize2048 = 0x00000000, Bsize1024 = 0x00010000, Bsize512 = 0x00020000, Bsize256 = 0x00030000, BsizeFlex = 0x08000000, /* Flexible Bsize in 1KB increments */ Vfe = 0x00040000, /* VLAN Filter Enable */ Cfien = 0x00080000, /* Canonical Form Indicator Enable */ Cfi = 0x00100000, /* Canonical Form Indicator value */ Dpf = 0x00400000, /* Discard Pause Frames */ Pmcf = 0x00800000, /* Pass MAC Control Frames */ Bsex = 0x02000000, /* Buffer Size Extension */ Secrc = 0x04000000, /* Strip CRC from incoming packet */}; enum { /* Tctl */ Trst = 0x00000001, /* Transmitter Software Reset */ Ten = 0x00000002, /* Transmit Enable */ Psp = 0x00000008, /* Pad Short Packets */ Mulr = 0x10000000, /* Allow multiple concurrent requests */ CtMASK = 0x00000FF0, /* Collision Threshold */ CtSHIFT = 4, ColdMASK = 0x003FF000, /* Collision Distance */ ColdSHIFT = 12, Swxoff = 0x00400000, /* Sofware XOFF Transmission */ Pbe = 0x00800000, /* Packet Burst Enable */ Rtlc = 0x01000000, /* Re-transmit on Late Collision */ Nrtu = 0x02000000, /* No Re-transmit on Underrrun */}; enum { /* [RT]xdctl */ PthreshMASK = 0x0000003F, /* Prefetch Threshold */ PthreshSHIFT = 0, HthreshMASK = 0x00003F00, /* Host Threshold */ HthreshSHIFT = 8, WthreshMASK = 0x003F0000, /* Writeback Threshold */ WthreshSHIFT = 16, Gran = 0x01000000, /* Granularity */ Qenable = 0x02000000, /* Queue Enable (82575) */}; enum { /* Rxcsum */ PcssMASK = 0x00FF, /* Packet Checksum Start */ PcssSHIFT = 0, Ipofl = 0x0100, /* IP Checksum Off-load Enable */ Tuofl = 0x0200, /* TCP/UDP Checksum Off-load Enable */}; enum { /* Receive Delay Timer Ring */ DelayMASK = 0xFFFF, /* delay timer in 1.024nS increments */ DelaySHIFT = 0, Fpd = 0x80000000, /* Flush partial Descriptor Block */}; typedef struct Ctlr Ctlr;typedef struct Rd Rd;typedef struct Td Td; struct Rd { /* Receive Descriptor */ u32int addr[2]; u16int length; u16int checksum; u8int status; u8int errors; u16int special;}; enum { /* Rd status */ Rdd = 0x01, /* Descriptor Done */ Reop = 0x02, /* End of Packet */ Ixsm = 0x04, /* Ignore Checksum Indication */ Vp = 0x08, /* Packet is 802.1Q (matched VET) */ Tcpcs = 0x20, /* TCP Checksum Calculated on Packet */ Ipcs = 0x40, /* IP Checksum Calculated on Packet */ Pif = 0x80, /* Passed in-exact filter */}; enum { /* Rd errors */ Ce = 0x01, /* CRC Error or Alignment Error */ Se = 0x02, /* Symbol Error */ Seq = 0x04, /* Sequence Error */ Cxe = 0x10, /* Carrier Extension Error */ Tcpe = 0x20, /* TCP/UDP Checksum Error */ Ipe = 0x40, /* IP Checksum Error */ Rxe = 0x80, /* RX Data Error */}; struct Td { /* Transmit Descriptor */ u32int addr[2]; /* Data */ u32int control; u32int status;}; enum { /* Tdesc control */ LenMASK = 0x000FFFFF, /* Data/Packet Length Field */ LenSHIFT = 0, DtypeCD = 0x00000000, /* Data Type 'Context Descriptor' */ DtypeDD = 0x00100000, /* Data Type 'Data Descriptor' */ PtypeTCP = 0x01000000, /* TCP/UDP Packet Type (CD) */ Teop = 0x01000000, /* End of Packet (DD) */ PtypeIP = 0x02000000, /* IP Packet Type (CD) */ Ifcs = 0x02000000, /* Insert FCS (DD) */ Tse = 0x04000000, /* TCP Segmentation Enable */ Rs = 0x08000000, /* Report Status */ Rps = 0x10000000, /* Report Status Sent */ Dext = 0x20000000, /* Descriptor Extension */ Vle = 0x40000000, /* VLAN Packet Enable */ Ide = 0x80000000, /* Interrupt Delay Enable */}; enum { /* Tdesc status */ Tdd = 0x0001, /* Descriptor Done */ Ec = 0x0002, /* Excess Collisions */ Lc = 0x0004, /* Late Collision */ Tu = 0x0008, /* Transmit Underrun */ CssMASK = 0xFF00, /* Checksum Start Field */ CssSHIFT = 8,}; typedef struct { u16int *reg; u32int *reg32; u16int base; u16int lim;} Flash; enum { /* 16 and 32-bit flash registers for ich flash parts */ Bfpr = 0x00/4, /* flash base 0:12; lim 16:28 */ Fsts = 0x04/2, /* flash status; Hsfsts */ Fctl = 0x06/2, /* flash control; Hsfctl */ Faddr = 0x08/4, /* flash address to r/w */ Fdata = 0x10/4, /* data @ address */ /* status register */ Fdone = 1<<0, /* flash cycle done */ Fcerr = 1<<1, /* cycle error; write 1 to clear */ Ael = 1<<2, /* direct access error log; 1 to clear */ Scip = 1<<5, /* spi cycle in progress */ Fvalid = 1<<14, /* flash descriptor valid */ /* control register */ Fgo = 1<<0, /* start cycle */ Flcycle = 1<<1, /* two bits: r=0; w=2 */ Fdbc = 1<<8, /* bytes to read; 5 bits */}; enum { Nrd = 512, /* power of two */ Ntd = 64, /* power of two */ /* 1024 buffers can be filled in 12 ms. at full line rate */ Nrb = 1024, /* private receive buffers per Ctlr */}; enum { Iany, i82563, i82566, i82567, i82571, i82572, i82573, i82574, i82575, i82576, i82577, i82579,}; static int rbtab[] = { 0, 9014, ETHERMAXTU, ETHERMAXTU, 9234, 9234, 8192, /* terrible performance above 8k */ ETHERMAXTU, ETHERMAXTU, ETHERMAXTU, ETHERMAXTU, 9018,}; static char *tname[] = { "any", "i82563", "i82566", "i82567", "i82571", "i82572", "i82573", "i82574", "i82575", "i82576", "i82577", "i82579",}; struct Ctlr { int port; Pcidev *pcidev; Ctlr *next; Ether *edev; int active; int type; ushort eeprom[0x40]; QLock alock; /* attach */ int attached; int nrd; int ntd; int nrb; /* # rcv bufs this Ctlr has in the pool */ unsigned rbsz; /* unsigned for % and / by 1024 */ int *nic; Lock imlock; int im; /* interrupt mask */ Rendez lrendez; int lim; QLock slock;Lines 1–500 of 1858. Load more
/* * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ /* * Intel Gigabit Ethernet PCI-Express Controllers. * 8256[36], 8257[1-79] * Pretty basic, does not use many of the chip smarts. * The interrupt mitigation tuning for each chip variant * is probably different. The reset/initialisation * sequence needs straightened out. Doubt the PHY code * for the 82575eb is right. */ #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" #include "../port/error.h" #include "../port/netif.h" #include "etherif.h" /* * these are in the order they appear in the manual, not numeric order. * It was too hard to find them in the book. Ref 21489, rev 2.6 */ enum { /* General */ Ctrl = 0x0000, /* Device Control */ Status = 0x0008, /* Device Status */ Eec = 0x0010, /* EEPROM/Flash Control/Data */ Eerd = 0x0014, /* EEPROM Read */ Ctrlext = 0x0018, /* Extended Device Control */ Fla = 0x001c, /* Flash Access */ Mdic = 0x0020, /* MDI Control */ Seresctl = 0x0024, /* Serdes ana */ Fcal = 0x0028, /* Flow Control Address Low */ Fcah = 0x002C, /* Flow Control Address High */ Fct = 0x0030, /* Flow Control Type */ Kumctrlsta = 0x0034, /* MAC-PHY Interface */ Vet = 0x0038, /* VLAN EtherType */ Fcttv = 0x0170, /* Flow Control Transmit Timer Value */ Txcw = 0x0178, /* Transmit Configuration Word */ Rxcw = 0x0180, /* Receive Configuration Word */ Ledctl = 0x0E00, /* LED control */ Pba = 0x1000, /* Packet Buffer Allocation */ Pbs = 0x1008, /* Packet Buffer Size */ /* Interrupt */ Icr = 0x00C0, /* Interrupt Cause Read */ Itr = 0x00c4, /* Interrupt Throttling Rate */ Ics = 0x00C8, /* Interrupt Cause Set */ Ims = 0x00D0, /* Interrupt Mask Set/Read */ Imc = 0x00D8, /* Interrupt mask Clear */ Iam = 0x00E0, /* Interrupt acknowledge Auto Mask */ /* Receive */ Rctl = 0x0100, /* Control */ Ert = 0x2008, /* Early Receive Threshold (573[EVL], 579 only) */ Fcrtl = 0x2160, /* Flow Control RX Threshold Low */ Fcrth = 0x2168, /* Flow Control Rx Threshold High */ Psrctl = 0x2170, /* Packet Split Receive Control */ Rdbal = 0x2800, /* Rdesc Base Address Low Queue 0 */ Rdbah = 0x2804, /* Rdesc Base Address High Queue 0 */ Rdlen = 0x2808, /* Descriptor Length Queue 0 */ Rdh = 0x2810, /* Descriptor Head Queue 0 */ Rdt = 0x2818, /* Descriptor Tail Queue 0 */ Rdtr = 0x2820, /* Descriptor Timer Ring */ Rxdctl = 0x2828, /* Descriptor Control */ Radv = 0x282C, /* Interrupt Absolute Delay Timer */ Rdbal1 = 0x2900, /* Rdesc Base Address Low Queue 1 */ Rdbah1 = 0x2804, /* Rdesc Base Address High Queue 1 */ Rdlen1 = 0x2908, /* Descriptor Length Queue 1 */ Rdh1 = 0x2910, /* Descriptor Head Queue 1 */ Rdt1 = 0x2918, /* Descriptor Tail Queue 1 */ Rxdctl1 = 0x2928, /* Descriptor Control Queue 1 */ Rsrpd = 0x2c00, /* Small Packet Detect */ Raid = 0x2c08, /* ACK interrupt delay */ Cpuvec = 0x2c10, /* CPU Vector */ Rxcsum = 0x5000, /* Checksum Control */ Rfctl = 0x5008, /* Filter Control */ Mta = 0x5200, /* Multicast Table Array */ Ral = 0x5400, /* Receive Address Low */ Rah = 0x5404, /* Receive Address High */ Vfta = 0x5600, /* VLAN Filter Table Array */ Mrqc = 0x5818, /* Multiple Receive Queues Command */ Rssim = 0x5864, /* RSS Interrupt Mask */ Rssir = 0x5868, /* RSS Interrupt Request */ Reta = 0x5c00, /* Redirection Table */ Rssrk = 0x5c80, /* RSS Random Key */ /* Transmit */ Tctl = 0x0400, /* Transmit Control */ Tipg = 0x0410, /* Transmit IPG */ Tkabgtxd = 0x3004, /* glci afe band gap transmit ref data, or something */ Tdbal = 0x3800, /* Tdesc Base Address Low */ Tdbah = 0x3804, /* Tdesc Base Address High */ Tdlen = 0x3808, /* Descriptor Length */ Tdh = 0x3810, /* Descriptor Head */ Tdt = 0x3818, /* Descriptor Tail */ Tidv = 0x3820, /* Interrupt Delay Value */ Txdctl = 0x3828, /* Descriptor Control */ Tadv = 0x382C, /* Interrupt Absolute Delay Timer */ Tarc0 = 0x3840, /* Arbitration Counter Queue 0 */ Tdbal1 = 0x3900, /* Descriptor Base Low Queue 1 */ Tdbah1 = 0x3904, /* Descriptor Base High Queue 1 */ Tdlen1 = 0x3908, /* Descriptor Length Queue 1 */ Tdh1 = 0x3910, /* Descriptor Head Queue 1 */ Tdt1 = 0x3918, /* Descriptor Tail Queue 1 */ Txdctl1 = 0x3928, /* Descriptor Control 1 */ Tarc1 = 0x3940, /* Arbitration Counter Queue 1 */ /* Statistics */ Statistics = 0x4000, /* Start of Statistics Area */ Gorcl = 0x88/4, /* Good Octets Received Count */ Gotcl = 0x90/4, /* Good Octets Transmitted Count */ Torl = 0xC0/4, /* Total Octets Received */ Totl = 0xC8/4, /* Total Octets Transmitted */ Nstatistics = 0x124/4, }; enum { /* Ctrl */ GIOmd = 1<<2, /* BIO master disable */ Lrst = 1<<3, /* link reset */ Slu = 1<<6, /* Set Link Up */ SspeedMASK = 3<<8, /* Speed Selection */ SspeedSHIFT = 8, Sspeed10 = 0x00000000, /* 10Mb/s */ Sspeed100 = 0x00000100, /* 100Mb/s */ Sspeed1000 = 0x00000200, /* 1000Mb/s */ Frcspd = 1<<11, /* Force Speed */ Frcdplx = 1<<12, /* Force Duplex */ SwdpinsloMASK = 0x003C0000, /* Software Defined Pins - lo nibble */ SwdpinsloSHIFT = 18, SwdpioloMASK = 0x03C00000, /* Software Defined Pins - I or O */ SwdpioloSHIFT = 22, Devrst = 1<<26, /* Device Reset */ Rfce = 1<<27, /* Receive Flow Control Enable */ Tfce = 1<<28, /* Transmit Flow Control Enable */ Vme = 1<<30, /* VLAN Mode Enable */ Phyrst = 1<<31, /* Phy Reset */ }; enum { /* Status */ Lu = 1<<1, /* Link Up */ Lanid = 3<<2, /* mask for Lan ID. */ Txoff = 1<<4, /* Transmission Paused */ Tbimode = 1<<5, /* TBI Mode Indication */ Phyra = 1<<10, /* PHY Reset Asserted */ GIOme = 1<<19, /* GIO Master Enable Status */ }; enum { /* Eerd */ EEstart = 1<<0, /* Start Read */ EEdone = 1<<1, /* Read done */ }; enum { /* Ctrlext */ Asdchk = 1<<12, /* ASD Check */ Eerst = 1<<13, /* EEPROM Reset */ Spdbyps = 1<<15, /* Speed Select Bypass */ }; enum { /* EEPROM content offsets */ Ea = 0x00, /* Ethernet Address */ Cf = 0x03, /* Compatibility Field */ Icw1 = 0x0A, /* Initialization Control Word 1 */ Sid = 0x0B, /* Subsystem ID */ Svid = 0x0C, /* Subsystem Vendor ID */ Did = 0x0D, /* Device ID */ Vid = 0x0E, /* Vendor ID */ Icw2 = 0x0F, /* Initialization Control Word 2 */ }; enum { /* Mdic */ MDIdMASK = 0x0000FFFF, /* Data */ MDIdSHIFT = 0, MDIrMASK = 0x001F0000, /* PHY Register Address */ MDIrSHIFT = 16, MDIpMASK = 0x03E00000, /* PHY Address */ MDIpSHIFT = 21, MDIwop = 0x04000000, /* Write Operation */ MDIrop = 0x08000000, /* Read Operation */ MDIready = 0x10000000, /* End of Transaction */ MDIie = 0x20000000, /* Interrupt Enable */ MDIe = 0x40000000, /* Error */ }; enum { /* phy interface registers */ Phyctl = 0, /* phy ctl */ Physsr = 17, /* phy secondary status */ Phyier = 18, /* 82573 phy interrupt enable */ Phyisr = 19, /* 82563 phy interrupt status */ Phylhr = 19, /* 8257[12] link health */ Rtlink = 1<<10, /* realtime link status */ Phyan = 1<<11, /* phy has auto-negotiated */ /* Phyctl bits */ Ran = 1<<9, /* restart auto-negotiation */ Ean = 1<<12, /* enable auto-negotiation */ /* 82573 Phyier bits */ Lscie = 1<<10, /* link status changed ie */ Ancie = 1<<11, /* auto-negotiation complete ie */ Spdie = 1<<14, /* speed changed ie */ Panie = 1<<15, /* phy auto-negotiation error ie */ /* Phylhr/Phyisr bits */ Anf = 1<<6, /* lhr: auto-negotiation fault */ Ane = 1<<15, /* isr: auto-negotiation error */ }; enum { /* Icr, Ics, Ims, Imc */ Txdw = 0x00000001, /* Transmit Descriptor Written Back */ Txqe = 0x00000002, /* Transmit Queue Empty */ Lsc = 0x00000004, /* Link Status Change */ Rxseq = 0x00000008, /* Receive Sequence Error */ Rxdmt0 = 0x00000010, /* Rdesc Minimum Threshold Reached */ Rxo = 0x00000040, /* Receiver Overrun */ Rxt0 = 0x00000080, /* Receiver Timer Interrupt */ Mdac = 0x00000200, /* MDIO Access Completed */ Rxcfg = 0x00000400, /* Receiving /C/ ordered sets */ Gpi0 = 0x00000800, /* General Purpose Interrupts */ Gpi1 = 0x00001000, Gpi2 = 0x00002000, Gpi3 = 0x00004000, Ack = 0x00020000, /* Receive ACK frame */ }; enum { /* Txcw */ TxcwFd = 0x00000020, /* Full Duplex */ TxcwHd = 0x00000040, /* Half Duplex */ TxcwPauseMASK = 0x00000180, /* Pause */ TxcwPauseSHIFT = 7, TxcwPs = 1<<TxcwPauseSHIFT, /* Pause Supported */ TxcwAs = 2<<TxcwPauseSHIFT, /* Asymmetric FC desired */ TxcwRfiMASK = 0x00003000, /* Remote Fault Indication */ TxcwRfiSHIFT = 12, TxcwNpr = 0x00008000, /* Next Page Request */ TxcwConfig = 0x40000000, /* Transmit Config Control */ TxcwAne = 0x80000000, /* Auto-Negotiation Enable */ }; enum { /* Rctl */ Rrst = 0x00000001, /* Receiver Software Reset */ Ren = 0x00000002, /* Receiver Enable */ Sbp = 0x00000004, /* Store Bad Packets */ Upe = 0x00000008, /* Unicast Promiscuous Enable */ Mpe = 0x00000010, /* Multicast Promiscuous Enable */ Lpe = 0x00000020, /* Long Packet Reception Enable */ LbmMASK = 0x000000C0, /* Loopback Mode */ LbmOFF = 0x00000000, /* No Loopback */ LbmTBI = 0x00000040, /* TBI Loopback */ LbmMII = 0x00000080, /* GMII/MII Loopback */ LbmXCVR = 0x000000C0, /* Transceiver Loopback */ RdtmsMASK = 0x00000300, /* Rdesc Minimum Threshold Size */ RdtmsHALF = 0x00000000, /* Threshold is 1/2 Rdlen */ RdtmsQUARTER = 0x00000100, /* Threshold is 1/4 Rdlen */ RdtmsEIGHTH = 0x00000200, /* Threshold is 1/8 Rdlen */ MoMASK = 0x00003000, /* Multicast Offset */ Bam = 0x00008000, /* Broadcast Accept Mode */ BsizeMASK = 0x00030000, /* Receive Buffer Size */ Bsize16384 = 0x00010000, /* Bsex = 1 */ Bsize8192 = 0x00020000, /* Bsex = 1 */ Bsize2048 = 0x00000000, Bsize1024 = 0x00010000, Bsize512 = 0x00020000, Bsize256 = 0x00030000, BsizeFlex = 0x08000000, /* Flexible Bsize in 1KB increments */ Vfe = 0x00040000, /* VLAN Filter Enable */ Cfien = 0x00080000, /* Canonical Form Indicator Enable */ Cfi = 0x00100000, /* Canonical Form Indicator value */ Dpf = 0x00400000, /* Discard Pause Frames */ Pmcf = 0x00800000, /* Pass MAC Control Frames */ Bsex = 0x02000000, /* Buffer Size Extension */ Secrc = 0x04000000, /* Strip CRC from incoming packet */ }; enum { /* Tctl */ Trst = 0x00000001, /* Transmitter Software Reset */ Ten = 0x00000002, /* Transmit Enable */ Psp = 0x00000008, /* Pad Short Packets */ Mulr = 0x10000000, /* Allow multiple concurrent requests */ CtMASK = 0x00000FF0, /* Collision Threshold */ CtSHIFT = 4, ColdMASK = 0x003FF000, /* Collision Distance */ ColdSHIFT = 12, Swxoff = 0x00400000, /* Sofware XOFF Transmission */ Pbe = 0x00800000, /* Packet Burst Enable */ Rtlc = 0x01000000, /* Re-transmit on Late Collision */ Nrtu = 0x02000000, /* No Re-transmit on Underrrun */ }; enum { /* [RT]xdctl */ PthreshMASK = 0x0000003F, /* Prefetch Threshold */ PthreshSHIFT = 0, HthreshMASK = 0x00003F00, /* Host Threshold */ HthreshSHIFT = 8, WthreshMASK = 0x003F0000, /* Writeback Threshold */ WthreshSHIFT = 16, Gran = 0x01000000, /* Granularity */ Qenable = 0x02000000, /* Queue Enable (82575) */ }; enum { /* Rxcsum */ PcssMASK = 0x00FF, /* Packet Checksum Start */ PcssSHIFT = 0, Ipofl = 0x0100, /* IP Checksum Off-load Enable */ Tuofl = 0x0200, /* TCP/UDP Checksum Off-load Enable */ }; enum { /* Receive Delay Timer Ring */ DelayMASK = 0xFFFF, /* delay timer in 1.024nS increments */ DelaySHIFT = 0, Fpd = 0x80000000, /* Flush partial Descriptor Block */ }; typedef struct Ctlr Ctlr; typedef struct Rd Rd; typedef struct Td Td; struct Rd { /* Receive Descriptor */ u32int addr[2]; u16int length; u16int checksum; u8int status; u8int errors; u16int special; }; enum { /* Rd status */ Rdd = 0x01, /* Descriptor Done */ Reop = 0x02, /* End of Packet */ Ixsm = 0x04, /* Ignore Checksum Indication */ Vp = 0x08, /* Packet is 802.1Q (matched VET) */ Tcpcs = 0x20, /* TCP Checksum Calculated on Packet */ Ipcs = 0x40, /* IP Checksum Calculated on Packet */ Pif = 0x80, /* Passed in-exact filter */ }; enum { /* Rd errors */ Ce = 0x01, /* CRC Error or Alignment Error */ Se = 0x02, /* Symbol Error */ Seq = 0x04, /* Sequence Error */ Cxe = 0x10, /* Carrier Extension Error */ Tcpe = 0x20, /* TCP/UDP Checksum Error */ Ipe = 0x40, /* IP Checksum Error */ Rxe = 0x80, /* RX Data Error */ }; struct Td { /* Transmit Descriptor */ u32int addr[2]; /* Data */ u32int control; u32int status; }; enum { /* Tdesc control */ LenMASK = 0x000FFFFF, /* Data/Packet Length Field */ LenSHIFT = 0, DtypeCD = 0x00000000, /* Data Type 'Context Descriptor' */ DtypeDD = 0x00100000, /* Data Type 'Data Descriptor' */ PtypeTCP = 0x01000000, /* TCP/UDP Packet Type (CD) */ Teop = 0x01000000, /* End of Packet (DD) */ PtypeIP = 0x02000000, /* IP Packet Type (CD) */ Ifcs = 0x02000000, /* Insert FCS (DD) */ Tse = 0x04000000, /* TCP Segmentation Enable */ Rs = 0x08000000, /* Report Status */ Rps = 0x10000000, /* Report Status Sent */ Dext = 0x20000000, /* Descriptor Extension */ Vle = 0x40000000, /* VLAN Packet Enable */ Ide = 0x80000000, /* Interrupt Delay Enable */ }; enum { /* Tdesc status */ Tdd = 0x0001, /* Descriptor Done */ Ec = 0x0002, /* Excess Collisions */ Lc = 0x0004, /* Late Collision */ Tu = 0x0008, /* Transmit Underrun */ CssMASK = 0xFF00, /* Checksum Start Field */ CssSHIFT = 8, }; typedef struct { u16int *reg; u32int *reg32; u16int base; u16int lim; } Flash; enum { /* 16 and 32-bit flash registers for ich flash parts */ Bfpr = 0x00/4, /* flash base 0:12; lim 16:28 */ Fsts = 0x04/2, /* flash status; Hsfsts */ Fctl = 0x06/2, /* flash control; Hsfctl */ Faddr = 0x08/4, /* flash address to r/w */ Fdata = 0x10/4, /* data @ address */ /* status register */ Fdone = 1<<0, /* flash cycle done */ Fcerr = 1<<1, /* cycle error; write 1 to clear */ Ael = 1<<2, /* direct access error log; 1 to clear */ Scip = 1<<5, /* spi cycle in progress */ Fvalid = 1<<14, /* flash descriptor valid */ /* control register */ Fgo = 1<<0, /* start cycle */ Flcycle = 1<<1, /* two bits: r=0; w=2 */ Fdbc = 1<<8, /* bytes to read; 5 bits */ }; enum { Nrd = 512, /* power of two */ Ntd = 64, /* power of two */ /* 1024 buffers can be filled in 12 ms. at full line rate */ Nrb = 1024, /* private receive buffers per Ctlr */ }; enum { Iany, i82563, i82566, i82567, i82571, i82572, i82573, i82574, i82575, i82576, i82577, i82579, }; static int rbtab[] = { 0, 9014, ETHERMAXTU, ETHERMAXTU, 9234, 9234, 8192, /* terrible performance above 8k */ ETHERMAXTU, ETHERMAXTU, ETHERMAXTU, ETHERMAXTU, 9018, }; static char *tname[] = { "any", "i82563", "i82566", "i82567", "i82571", "i82572", "i82573", "i82574", "i82575", "i82576", "i82577", "i82579", }; struct Ctlr { int port; Pcidev *pcidev; Ctlr *next; Ether *edev; int active; int type; ushort eeprom[0x40]; QLock alock; /* attach */ int attached; int nrd; int ntd; int nrb; /* # rcv bufs this Ctlr has in the pool */ unsigned rbsz; /* unsigned for % and / by 1024 */ int *nic; Lock imlock; int im; /* interrupt mask */ Rendez lrendez; int lim; QLock slock;