/* * bootstrap driver for * Intel 8256[367], 8257[1-9], 8258[03], i350 * Gigabit Ethernet PCI-Express Controllers * Coraid EtherDrive® hba */#include "u.h"#include "lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "io.h" #include "etherif.h" /* compatibility with cpu kernels */#define iallocb allocb /* * note: the 82575, 82576 and 82580 are operated using registers aliased * to the 82563-style architecture. many features seen in the 82598 * are also seen in the 82575 part. */ 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 */ Fcal = 0x0028, /* Flow Control Address Low */ Fcah = 0x002C, /* Flow Control Address High */ Fct = 0x0030, /* Flow Control Type */ Kumctrlsta = 0x0034, /* Kumeran Control and Status Register */ Connsw = 0x0034, /* copper / fiber switch control; 82575/82576 */ 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 */ Eitr = 0x1680, /* Extended itr; 82575/6 80 only */ /* Receive */ Rctl = 0x0100, /* Control */ Ert = 0x2008, /* Early Receive Threshold (573[EVL], 82578 only) */ Fcrtl = 0x2160, /* Flow Control RX Threshold Low */ Fcrth = 0x2168, /* Flow Control Rx Threshold High */ Psrctl = 0x2170, /* Packet Split Receive Control */ Drxmxod = 0x2540, /* dma max outstanding bytes (82575) */ Rdbal = 0x2800, /* Rdesc Base Address Low Queue 0 */ Rdbah = 0x2804, /* Rdesc Base Address High Queue 0 */ Rdlen = 0x2808, /* Descriptor Length Queue 0 */ Srrctl = 0x280c, /* split and replication rx control (82575) */ 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 */ Rsrpd = 0x2c00, /* Small Packet Detect */ Raid = 0x2c08, /* ACK interrupt delay */ Cpuvec = 0x2c10, /* CPU Vector */ Rxcsum = 0x5000, /* Checksum Control */ Rmpl = 0x5004, /* rx maximum packet length (82575) */ 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 */ /* 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 */ /* 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 */}; enum { /* Ctrl */ Lrst = 1<<3, /* link reset */ Slu = 1<<6, /* Set Link Up */ Devrst = 1<<26, /* Device Reset */ Rfce = 1<<27, /* Receive Flow Control Enable */ Tfce = 1<<28, /* Transmit Flow Control 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 */ Eerst = 1<<13, /* EEPROM Reset */ Linkmode = 3<<22, /* linkmode */ Internalphy = 0<<22, /* " internal phy (copper) */ Sgmii = 2<<22, /* " sgmii */ Serdes = 3<<22, /* " serdes */}; enum { /* Connsw */ Enrgirq = 1<<2, /* interrupt on power detect (enrgsrc) */}; enum { /* EEPROM content offsets */ Ea = 0x00, /* Ethernet Address */}; enum { /* phy interface */ Phyctl = 0, /* phy ctl register */ Phyisr = 19, /* 82563 phy interrupt status register */ Phylhr = 19, /* 8257[12] link health register */ Physsr = 17, /* phy secondary status register */ Phyprst = 193<<8 | 17, /* 8256[34] phy port reset */ Phyier = 18, /* 82573 phy interrupt enable register */ Phypage = 22, /* 8256[34] page register */ Phystat = 26, /* 82580 phy status */ Phyapage = 29, Rtlink = 1<<10, /* realtime link status */ Phyan = 1<<11, /* phy has autonegotiated */ /* Phyctl bits */ Ran = 1<<9, /* restart auto negotiation */ Ean = 1<<12, /* enable auto negotiation */ /* Phyprst bits */ Prst = 1<<0, /* reset the port */ /* 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 */ /* 82580 Phystat bits */ Ans = 1<<14 | 1<<15, /* 82580 autoneg. status */ Link = 1<<6, /* 82580 Link */ /* Rxcw builtin serdes */ Anc = 1<<31, Rxsynch = 1<<30, Rxcfg = 1<<29, Rxcfgch = 1<<28, Rxcfgbad = 1<<27, Rxnc = 1<<26, /* Txcw */ Txane = 1<<31, Txcfg = 1<<30,}; enum { /* fiber (pcs) interface */ Pcsctl = 0x4208, /* pcs control */ Pcsstat = 0x420c, /* pcs status */ /* Pcsctl bits */ Pan = 1<<16, /* autoegotiate */ Prestart = 1<<17, /* restart an (self clearing) */ /* Pcsstat bits */ Linkok = 1<<0, /* link is okay */ Andone = 1<<16, /* an phase is done see below for success */ Anbad = 1<<19 | 1<<20, /* Anerror | Anremfault */}; 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; !82575/6/80 only */ Rxdw = 0x00000080, /* Rdesc write back; 82575/6/80 only */ Mdac = 0x00000200, /* MDIO Access Completed */ Rxcfgset = 0x00000400, /* Receiving /C/ ordered sets */ Ack = 0x00020000, /* Receive ACK frame */ Omed = 1<<20, /* media change; pcs interface */}; 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 */ 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, /* Flexable 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 { /* Srrctl */ Dropen = 1<<31,}; 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; not 82575 */ Enable = 0x02000000,}; enum { /* Rxcsum */ Ipofl = 0x0100, /* IP Checksum Off-load Enable */ Tuofl = 0x0200, /* TCP/UDP Checksum Off-load Enable */}; typedef struct Rd { /* Receive Descriptor */ u32int addr[2]; u16int length; u16int checksum; uchar status; uchar errors; u16int special;} Rd; 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 */}; typedef struct { /* Transmit Descriptor */ u32int addr[2]; /* Data */ u32int control; u32int status;} Td; 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; int sz;} 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 = 64, /* multiple of 8 */ Ntd = 64, /* multiple of 8 */}; /* * cavet emptor: 82577/78 have been entered speculatitively. * awating datasheet from intel. */enum { i82563, i82566, i82567, i82567m, i82571, i82572, i82573, i82574, i82575, i82576, i82577, i82577m, i82578, i82578m, i82579, i82580, i82583, i350, Nctlrtype,}; enum { Fload = 1<<0, Fert = 1<<1, F75 = 1<<2, Fpba = 1<<3, Fflashea = 1<<4, F79phy = 1<<5,}; typedef struct Ctlrtype Ctlrtype;struct Ctlrtype { int type; int mtu; int flag; char *name;}; static Ctlrtype cttab[Nctlrtype] = { i82563, 9014, Fpba, "i82563", i82566, 1514, Fload, "i82566", i82567, 9234, Fload, "i82567", i82567m, 1514, 0, "i82567m", i82571, 9234, Fpba, "i82571", i82572, 9234, Fpba, "i82572", i82573, 8192, Fert, "i82573", /* terrible perf above 8k */ i82574, 9018, 0, "i82574", i82575, 9728, F75|Fflashea, "i82575", i82576, 9728, F75, "i82576", i82577, 4096, Fload|Fert, "i82577", i82577m, 1514, Fload|Fert, "i82577", i82578, 4096, Fload|Fert, "i82578", i82578m, 1514, Fload|Fert, "i82578", i82579, 9018, Fload|Fert|F79phy, "i82579", i82580, 9728, F75|F79phy, "i82580", i82583, 1514, 0, "i82583", i350, 9728, F75|F79phy, "i350",}; typedef struct Ctlr Ctlr;struct Ctlr { ulong port; Pcidev *pcidev; Ctlr *next; int active; int type; u16int eeprom[0x40]; uchar ra[Eaddrlen]; u32int *nic; Lock imlock; int im; /* interrupt mask */ Lock slock; Rd *rdba; /* receive descriptor base address */ Block **rb; /* receive buffers */ int rdh; /* receive descriptor head */ int rdt; /* receive descriptor tail */ Td *tdba; /* transmit descriptor base address */ Lock tdlock; Block **tb; /* transmit buffers */ int tdh; /* transmit descriptor head */ int tdt; /* transmit descriptor tail */ int fcrtl; int fcrth; /* bootstrap goo */ Block *bqhead; /* transmission queue */ Block *bqtail;}; static Ctlr *ctlrhead;static Ctlr *ctlrtail; Lines 1–500 of 1217. Load more
/* * bootstrap driver for * Intel 8256[367], 8257[1-9], 8258[03], i350 * Gigabit Ethernet PCI-Express Controllers * Coraid EtherDrive® hba */ #include "u.h" #include "lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" #include "etherif.h" /* compatibility with cpu kernels */ #define iallocb allocb /* * note: the 82575, 82576 and 82580 are operated using registers aliased * to the 82563-style architecture. many features seen in the 82598 * are also seen in the 82575 part. */ 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 */ Fcal = 0x0028, /* Flow Control Address Low */ Fcah = 0x002C, /* Flow Control Address High */ Fct = 0x0030, /* Flow Control Type */ Kumctrlsta = 0x0034, /* Kumeran Control and Status Register */ Connsw = 0x0034, /* copper / fiber switch control; 82575/82576 */ 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 */ Eitr = 0x1680, /* Extended itr; 82575/6 80 only */ /* Receive */ Rctl = 0x0100, /* Control */ Ert = 0x2008, /* Early Receive Threshold (573[EVL], 82578 only) */ Fcrtl = 0x2160, /* Flow Control RX Threshold Low */ Fcrth = 0x2168, /* Flow Control Rx Threshold High */ Psrctl = 0x2170, /* Packet Split Receive Control */ Drxmxod = 0x2540, /* dma max outstanding bytes (82575) */ Rdbal = 0x2800, /* Rdesc Base Address Low Queue 0 */ Rdbah = 0x2804, /* Rdesc Base Address High Queue 0 */ Rdlen = 0x2808, /* Descriptor Length Queue 0 */ Srrctl = 0x280c, /* split and replication rx control (82575) */ 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 */ Rsrpd = 0x2c00, /* Small Packet Detect */ Raid = 0x2c08, /* ACK interrupt delay */ Cpuvec = 0x2c10, /* CPU Vector */ Rxcsum = 0x5000, /* Checksum Control */ Rmpl = 0x5004, /* rx maximum packet length (82575) */ 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 */ /* 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 */ /* 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 */ }; enum { /* Ctrl */ Lrst = 1<<3, /* link reset */ Slu = 1<<6, /* Set Link Up */ Devrst = 1<<26, /* Device Reset */ Rfce = 1<<27, /* Receive Flow Control Enable */ Tfce = 1<<28, /* Transmit Flow Control 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 */ Eerst = 1<<13, /* EEPROM Reset */ Linkmode = 3<<22, /* linkmode */ Internalphy = 0<<22, /* " internal phy (copper) */ Sgmii = 2<<22, /* " sgmii */ Serdes = 3<<22, /* " serdes */ }; enum { /* Connsw */ Enrgirq = 1<<2, /* interrupt on power detect (enrgsrc) */ }; enum { /* EEPROM content offsets */ Ea = 0x00, /* Ethernet Address */ }; enum { /* phy interface */ Phyctl = 0, /* phy ctl register */ Phyisr = 19, /* 82563 phy interrupt status register */ Phylhr = 19, /* 8257[12] link health register */ Physsr = 17, /* phy secondary status register */ Phyprst = 193<<8 | 17, /* 8256[34] phy port reset */ Phyier = 18, /* 82573 phy interrupt enable register */ Phypage = 22, /* 8256[34] page register */ Phystat = 26, /* 82580 phy status */ Phyapage = 29, Rtlink = 1<<10, /* realtime link status */ Phyan = 1<<11, /* phy has autonegotiated */ /* Phyctl bits */ Ran = 1<<9, /* restart auto negotiation */ Ean = 1<<12, /* enable auto negotiation */ /* Phyprst bits */ Prst = 1<<0, /* reset the port */ /* 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 */ /* 82580 Phystat bits */ Ans = 1<<14 | 1<<15, /* 82580 autoneg. status */ Link = 1<<6, /* 82580 Link */ /* Rxcw builtin serdes */ Anc = 1<<31, Rxsynch = 1<<30, Rxcfg = 1<<29, Rxcfgch = 1<<28, Rxcfgbad = 1<<27, Rxnc = 1<<26, /* Txcw */ Txane = 1<<31, Txcfg = 1<<30, }; enum { /* fiber (pcs) interface */ Pcsctl = 0x4208, /* pcs control */ Pcsstat = 0x420c, /* pcs status */ /* Pcsctl bits */ Pan = 1<<16, /* autoegotiate */ Prestart = 1<<17, /* restart an (self clearing) */ /* Pcsstat bits */ Linkok = 1<<0, /* link is okay */ Andone = 1<<16, /* an phase is done see below for success */ Anbad = 1<<19 | 1<<20, /* Anerror | Anremfault */ }; 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; !82575/6/80 only */ Rxdw = 0x00000080, /* Rdesc write back; 82575/6/80 only */ Mdac = 0x00000200, /* MDIO Access Completed */ Rxcfgset = 0x00000400, /* Receiving /C/ ordered sets */ Ack = 0x00020000, /* Receive ACK frame */ Omed = 1<<20, /* media change; pcs interface */ }; 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 */ 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, /* Flexable 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 { /* Srrctl */ Dropen = 1<<31, }; 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; not 82575 */ Enable = 0x02000000, }; enum { /* Rxcsum */ Ipofl = 0x0100, /* IP Checksum Off-load Enable */ Tuofl = 0x0200, /* TCP/UDP Checksum Off-load Enable */ }; typedef struct Rd { /* Receive Descriptor */ u32int addr[2]; u16int length; u16int checksum; uchar status; uchar errors; u16int special; } Rd; 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 */ }; typedef struct { /* Transmit Descriptor */ u32int addr[2]; /* Data */ u32int control; u32int status; } Td; 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; int sz; } 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 = 64, /* multiple of 8 */ Ntd = 64, /* multiple of 8 */ }; /* * cavet emptor: 82577/78 have been entered speculatitively. * awating datasheet from intel. */ enum { i82563, i82566, i82567, i82567m, i82571, i82572, i82573, i82574, i82575, i82576, i82577, i82577m, i82578, i82578m, i82579, i82580, i82583, i350, Nctlrtype, }; enum { Fload = 1<<0, Fert = 1<<1, F75 = 1<<2, Fpba = 1<<3, Fflashea = 1<<4, F79phy = 1<<5, }; typedef struct Ctlrtype Ctlrtype; struct Ctlrtype { int type; int mtu; int flag; char *name; }; static Ctlrtype cttab[Nctlrtype] = { i82563, 9014, Fpba, "i82563", i82566, 1514, Fload, "i82566", i82567, 9234, Fload, "i82567", i82567m, 1514, 0, "i82567m", i82571, 9234, Fpba, "i82571", i82572, 9234, Fpba, "i82572", i82573, 8192, Fert, "i82573", /* terrible perf above 8k */ i82574, 9018, 0, "i82574", i82575, 9728, F75|Fflashea, "i82575", i82576, 9728, F75, "i82576", i82577, 4096, Fload|Fert, "i82577", i82577m, 1514, Fload|Fert, "i82577", i82578, 4096, Fload|Fert, "i82578", i82578m, 1514, Fload|Fert, "i82578", i82579, 9018, Fload|Fert|F79phy, "i82579", i82580, 9728, F75|F79phy, "i82580", i82583, 1514, 0, "i82583", i350, 9728, F75|F79phy, "i350", }; typedef struct Ctlr Ctlr; struct Ctlr { ulong port; Pcidev *pcidev; Ctlr *next; int active; int type; u16int eeprom[0x40]; uchar ra[Eaddrlen]; u32int *nic; Lock imlock; int im; /* interrupt mask */ Lock slock; Rd *rdba; /* receive descriptor base address */ Block **rb; /* receive buffers */ int rdh; /* receive descriptor head */ int rdt; /* receive descriptor tail */ Td *tdba; /* transmit descriptor base address */ Lock tdlock; Block **tb; /* transmit buffers */ int tdh; /* transmit descriptor head */ int tdt; /* transmit descriptor tail */ int fcrtl; int fcrth; /* bootstrap goo */ Block *bqhead; /* transmission queue */ Block *bqtail; }; static Ctlr *ctlrhead; static Ctlr *ctlrtail;