/* * Bootstrap driver for * Intel 82563, 82571, 82573, 82575, 82576, 82577 * GbE PCI-Express Controllers. */#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#ifndef CACHELINESZ#define CACHELINESZ 32 /* pentium & later */#endif /* from pci.c */enum{ /* command register pcidev->pcr */ IOen = 1<<0, MEMen = 1<<1, MASen = 1<<2, MemWrInv = 1<<4, PErrEn = 1<<6, SErrEn = 1<<8,}; /* * 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 = 0x00000000, /* Device Control */ Status = 0x00000008, /* Device Status */ Eec = 0x00000010, /* EEPROM/Flash Control/Data */ Eerd = 0x00000014, /* EEPROM Read */ Ctrlext = 0x00000018, /* Extended Device Control */ Fla = 0x0000001c, /* Flash Access */ Mdic = 0x00000020, /* MDI Control */ Seresctl = 0x00000024, /* Serdes ana */ Fcal = 0x00000028, /* Flow Control Address Low */ Fcah = 0x0000002C, /* Flow Control Address High */ Fct = 0x00000030, /* Flow Control Type */ Kumctrlsta = 0x00000034, /* MAC-PHY Interface */ Vet = 0x00000038, /* VLAN EtherType */ Fcttv = 0x00000170, /* Flow Control Transmit Timer Value */ Txcw = 0x00000178, /* Transmit Configuration Word */ Rxcw = 0x00000180, /* Receive Configuration Word */ Ledctl = 0x00000E00, /* LED control */ Pba = 0x00001000, /* Packet Buffer Allocation */ Pbs = 0x00001008, /* Packet Buffer Size */ /* Interrupt */ Icr = 0x000000C0, /* Interrupt Cause Read */ Ics = 0x000000C8, /* Interrupt Cause Set */ Ims = 0x000000D0, /* Interrupt Mask Set/Read */ Imc = 0x000000D8, /* Interrupt mask Clear */ Iam = 0x000000E0, /* Interrupt acknowledge Auto Mask */ /* Receive */ Rctl = 0x00000100, /* Receive Control */ Ert = 0x00002008, /* Early Receive Threshold (573[EVL] only) */ Fcrtl = 0x00002160, /* Flow Control RX Threshold Low */ Fcrth = 0x00002168, /* Flow Control Rx Threshold High */ Psrctl = 0x00002170, /* Packet Split Receive Control */ Rdbal = 0x00002800, /* Rdesc Base Address Low Queue 0 */ Rdbah = 0x00002804, /* Rdesc Base Address High Queue 0 */ Rdlen = 0x00002808, /* Receive Descriptor Length Queue 0 */ Rdh = 0x00002810, /* Receive Descriptor Head Queue 0 */ Rdt = 0x00002818, /* Receive Descriptor Tail Queue 0 */ Rdtr = 0x00002820, /* Receive Descriptor Timer Ring */ Rxdctl = 0x00002828, /* Receive Descriptor Control */ Radv = 0x0000282C, /* Receive Interrupt Absolute Delay Timer */ Rdbal1 = 0x00002900, /* Rdesc Base Address Low Queue 1 */ Rdbah1 = 0x00002804, /* Rdesc Base Address High Queue 1 */ Rdlen1 = 0x00002908, /* Receive Descriptor Length Queue 1 */ Rdh1 = 0x00002910, /* Receive Descriptor Head Queue 1 */ Rdt1 = 0x00002918, /* Receive Descriptor Tail Queue 1 */ Rxdctl1 = 0x00002928, /* Receive Descriptor Control Queue 1 */ Rsrpd = 0x00002c00, /* Receive Small Packet Detect */ Raid = 0x00002c08, /* Receive ACK interrupt delay */ Cpuvec = 0x00002c10, /* CPU Vector */ Rxcsum = 0x00005000, /* Receive Checksum Control */ Rfctl = 0x00005008, /* Receive Filter Control */ Mta = 0x00005200, /* Multicast Table Array */ Ral = 0x00005400, /* Receive Address Low */ Rah = 0x00005404, /* Receive Address High */ Vfta = 0x00005600, /* VLAN Filter Table Array */ Mrqc = 0x00005818, /* Multiple Receive Queues Command */ Rssim = 0x00005864, /* RSS Interrupt Mask */ Rssir = 0x00005868, /* RSS Interrupt Request */ Reta = 0x00005c00, /* Redirection Table */ Rssrk = 0x00005c80, /* RSS Random Key */ /* Transmit */ Tctl = 0x00000400, /* Transmit Control */ Tipg = 0x00000410, /* Transmit IPG */ Tdbal = 0x00003800, /* Tdesc Base Address Low */ Tdbah = 0x00003804, /* Tdesc Base Address High */ Tdlen = 0x00003808, /* Transmit Descriptor Length */ Tdh = 0x00003810, /* Transmit Descriptor Head */ Tdt = 0x00003818, /* Transmit Descriptor Tail */ Tidv = 0x00003820, /* Transmit Interrupt Delay Value */ Txdctl = 0x00003828, /* Transmit Descriptor Control */ Tadv = 0x0000382C, /* Transmit Interrupt Absolute Delay Timer */ Tarc0 = 0x00003840, /* Transmit Arbitration Counter Queue 0 */ Tdbal1 = 0x00003900, /* Transmit Descriptor Base Low Queue 1 */ Tdbah1 = 0x00003904, /* Transmit Descriptor Base High Queue 1 */ Tdlen1 = 0x00003908, /* Transmit Descriptor Length Queue 1 */ Tdh1 = 0x00003910, /* Transmit Descriptor Head Queue 1 */ Tdt1 = 0x00003918, /* Transmit Descriptor Tail Queue 1 */ Txdctl1 = 0x00003928, /* Transmit Descriptor Control 1 */ Tarc1 = 0x00003940, /* Transmit Arbitration Counter Queue 1 */ /* Statistics */ Statistics = 0x00004000, /* 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 = 64, }; 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 */ Phy_rst = 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 */ SpeedMASK = 0x000000C0, Speed10 = 0x00000000, /* 10Mb/s */ Speed100 = 0x00000040, /* 100Mb/s */ Speed1000 = 0x00000080, /* 1000Mb/s */ Phyra = 1<<10, /* PHY Reset Asserted */ GIOme = 1<<19, /* GIO Master Enable Status */}; enum { /* Ctrl and Status */ Fd = 0x00000001, /* Full-Duplex */ AsdvMASK = 0x00000300, Asdv10 = 0x00000000, /* 10Mb/s */ Asdv100 = 0x00000100, /* 100Mb/s */ Asdv1000 = 0x00000200, /* 1000Mb/s */}; enum { /* Eec */ Sk = 1<<0, /* Clock input to the EEPROM */ Cs = 1<<1, /* Chip Select */ Di = 1<<2, /* Data Input to the EEPROM */ Do = 1<<3, /* Data Output from the EEPROM */ Areq = 1<<6, /* EEPROM Access Request */ Agnt = 1<<7, /* EEPROM Access Grant */}; enum { /* Eerd */ ee_start = 1<<0, /* Start Read */ ee_done = 1<<1, /* Read done */ ee_addr = 0xfff8<<2, /* Read address [15:2] */ ee_data = 0xffff<<16, /* Read Data; Data returned from eeprom/nvm */}; 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 { /* 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 */ Bsize2048 = 0x00000000, Bsize1024 = 0x00010000, Bsize512 = 0x00020000, Bsize256 = 0x00030000, 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 (82575eb) */}; enum { /* Rxcsum */ PcssMASK = 0x000000FF, /* Packet Checksum Start */ PcssSHIFT = 0, Ipofl = 0x00000100, /* IP Checksum Off-load Enable */ Tuofl = 0x00000200, /* TCP/UDP Checksum Off-load Enable */}; typedef struct Rdesc { /* Receive Descriptor */ uint addr[2]; ushort length; ushort checksum; uchar status; uchar errors; ushort special;} Rdesc; enum { /* Rdesc 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 { /* Rdesc 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 Tdesc { /* Legacy+Normal Transmit Descriptor */ uint addr[2]; uint control; /* varies with descriptor type */ uint status; /* varies with descriptor type */} Tdesc; 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 = 0x00000001, /* Descriptor Done */ Ec = 0x00000002, /* Excess Collisions */ Lc = 0x00000004, /* Late Collision */ Tu = 0x00000008, /* Transmit Underrun */ CssMASK = 0x0000FF00, /* Checksum Start Field */ CssSHIFT = 8,}; typedef struct { ushort *reg; ulong *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 { Nrdesc = 32, /* multiple of 8 */ Ntdesc = 8, /* multiple of 8 */}; enum { i82563, i82566, i82567, i82571, i82572, i82573, i82574, i82575, i82576, i82577,}; static char *tname[] = { "i82563", "i82566", "i82567", "i82571", "i82572", "i82573", "i82574", "i82575", "i82576", "i82577",}; typedef struct Ctlr Ctlr;struct Ctlr { int port; Pcidev *pcidev; Ctlr *next; int active; int cls; ushort eeprom[0x40]; uchar ra[Eaddrlen]; /* receive address */ int type; u32int* nic; Lock imlock; int im; /* interrupt mask */ Lock slock; uint statistics[Nstatistics]; Rdesc *rdba; /* receive descriptor base address */ Block **rb; /* receive buffers */ int rdh; /* receive descriptor head */ int rdt; /* receive descriptor tail */ Tdesc *tdba; /* transmit descriptor base address */ Lock tdlock; Block **tb; /* transmit buffers */ int tdh; /* transmit descriptor head */ int tdt; /* transmit descriptor tail */ int txcw; int fcrtl; int fcrth; /* bootstrap goo */ Block *bqhead; /* transmission queue */ Block *bqtail;}; static Ctlr *ctlrhead;static Ctlr *ctlrtail; #define csr32r(c, r) (*((c)->nic+((r)/4)))#define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v)) static voidi82563im(Ctlr* ctlr, int im){ ilock(&ctlr->imlock); ctlr->im |= im; csr32w(ctlr, Ims, ctlr->im); iunlock(&ctlr->imlock);} static voidi82563attach(Ether* edev){ int ctl; Ctlr *ctlr; ctlr = edev->ctlr;Lines 1–500 of 1171. Load more
/* * Bootstrap driver for * Intel 82563, 82571, 82573, 82575, 82576, 82577 * GbE PCI-Express Controllers. */ #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 #ifndef CACHELINESZ #define CACHELINESZ 32 /* pentium & later */ #endif /* from pci.c */ enum { /* command register pcidev->pcr */ IOen = 1<<0, MEMen = 1<<1, MASen = 1<<2, MemWrInv = 1<<4, PErrEn = 1<<6, SErrEn = 1<<8, }; /* * 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 = 0x00000000, /* Device Control */ Status = 0x00000008, /* Device Status */ Eec = 0x00000010, /* EEPROM/Flash Control/Data */ Eerd = 0x00000014, /* EEPROM Read */ Ctrlext = 0x00000018, /* Extended Device Control */ Fla = 0x0000001c, /* Flash Access */ Mdic = 0x00000020, /* MDI Control */ Seresctl = 0x00000024, /* Serdes ana */ Fcal = 0x00000028, /* Flow Control Address Low */ Fcah = 0x0000002C, /* Flow Control Address High */ Fct = 0x00000030, /* Flow Control Type */ Kumctrlsta = 0x00000034, /* MAC-PHY Interface */ Vet = 0x00000038, /* VLAN EtherType */ Fcttv = 0x00000170, /* Flow Control Transmit Timer Value */ Txcw = 0x00000178, /* Transmit Configuration Word */ Rxcw = 0x00000180, /* Receive Configuration Word */ Ledctl = 0x00000E00, /* LED control */ Pba = 0x00001000, /* Packet Buffer Allocation */ Pbs = 0x00001008, /* Packet Buffer Size */ /* Interrupt */ Icr = 0x000000C0, /* Interrupt Cause Read */ Ics = 0x000000C8, /* Interrupt Cause Set */ Ims = 0x000000D0, /* Interrupt Mask Set/Read */ Imc = 0x000000D8, /* Interrupt mask Clear */ Iam = 0x000000E0, /* Interrupt acknowledge Auto Mask */ /* Receive */ Rctl = 0x00000100, /* Receive Control */ Ert = 0x00002008, /* Early Receive Threshold (573[EVL] only) */ Fcrtl = 0x00002160, /* Flow Control RX Threshold Low */ Fcrth = 0x00002168, /* Flow Control Rx Threshold High */ Psrctl = 0x00002170, /* Packet Split Receive Control */ Rdbal = 0x00002800, /* Rdesc Base Address Low Queue 0 */ Rdbah = 0x00002804, /* Rdesc Base Address High Queue 0 */ Rdlen = 0x00002808, /* Receive Descriptor Length Queue 0 */ Rdh = 0x00002810, /* Receive Descriptor Head Queue 0 */ Rdt = 0x00002818, /* Receive Descriptor Tail Queue 0 */ Rdtr = 0x00002820, /* Receive Descriptor Timer Ring */ Rxdctl = 0x00002828, /* Receive Descriptor Control */ Radv = 0x0000282C, /* Receive Interrupt Absolute Delay Timer */ Rdbal1 = 0x00002900, /* Rdesc Base Address Low Queue 1 */ Rdbah1 = 0x00002804, /* Rdesc Base Address High Queue 1 */ Rdlen1 = 0x00002908, /* Receive Descriptor Length Queue 1 */ Rdh1 = 0x00002910, /* Receive Descriptor Head Queue 1 */ Rdt1 = 0x00002918, /* Receive Descriptor Tail Queue 1 */ Rxdctl1 = 0x00002928, /* Receive Descriptor Control Queue 1 */ Rsrpd = 0x00002c00, /* Receive Small Packet Detect */ Raid = 0x00002c08, /* Receive ACK interrupt delay */ Cpuvec = 0x00002c10, /* CPU Vector */ Rxcsum = 0x00005000, /* Receive Checksum Control */ Rfctl = 0x00005008, /* Receive Filter Control */ Mta = 0x00005200, /* Multicast Table Array */ Ral = 0x00005400, /* Receive Address Low */ Rah = 0x00005404, /* Receive Address High */ Vfta = 0x00005600, /* VLAN Filter Table Array */ Mrqc = 0x00005818, /* Multiple Receive Queues Command */ Rssim = 0x00005864, /* RSS Interrupt Mask */ Rssir = 0x00005868, /* RSS Interrupt Request */ Reta = 0x00005c00, /* Redirection Table */ Rssrk = 0x00005c80, /* RSS Random Key */ /* Transmit */ Tctl = 0x00000400, /* Transmit Control */ Tipg = 0x00000410, /* Transmit IPG */ Tdbal = 0x00003800, /* Tdesc Base Address Low */ Tdbah = 0x00003804, /* Tdesc Base Address High */ Tdlen = 0x00003808, /* Transmit Descriptor Length */ Tdh = 0x00003810, /* Transmit Descriptor Head */ Tdt = 0x00003818, /* Transmit Descriptor Tail */ Tidv = 0x00003820, /* Transmit Interrupt Delay Value */ Txdctl = 0x00003828, /* Transmit Descriptor Control */ Tadv = 0x0000382C, /* Transmit Interrupt Absolute Delay Timer */ Tarc0 = 0x00003840, /* Transmit Arbitration Counter Queue 0 */ Tdbal1 = 0x00003900, /* Transmit Descriptor Base Low Queue 1 */ Tdbah1 = 0x00003904, /* Transmit Descriptor Base High Queue 1 */ Tdlen1 = 0x00003908, /* Transmit Descriptor Length Queue 1 */ Tdh1 = 0x00003910, /* Transmit Descriptor Head Queue 1 */ Tdt1 = 0x00003918, /* Transmit Descriptor Tail Queue 1 */ Txdctl1 = 0x00003928, /* Transmit Descriptor Control 1 */ Tarc1 = 0x00003940, /* Transmit Arbitration Counter Queue 1 */ /* Statistics */ Statistics = 0x00004000, /* 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 = 64, }; 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 */ Phy_rst = 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 */ SpeedMASK = 0x000000C0, Speed10 = 0x00000000, /* 10Mb/s */ Speed100 = 0x00000040, /* 100Mb/s */ Speed1000 = 0x00000080, /* 1000Mb/s */ Phyra = 1<<10, /* PHY Reset Asserted */ GIOme = 1<<19, /* GIO Master Enable Status */ }; enum { /* Ctrl and Status */ Fd = 0x00000001, /* Full-Duplex */ AsdvMASK = 0x00000300, Asdv10 = 0x00000000, /* 10Mb/s */ Asdv100 = 0x00000100, /* 100Mb/s */ Asdv1000 = 0x00000200, /* 1000Mb/s */ }; enum { /* Eec */ Sk = 1<<0, /* Clock input to the EEPROM */ Cs = 1<<1, /* Chip Select */ Di = 1<<2, /* Data Input to the EEPROM */ Do = 1<<3, /* Data Output from the EEPROM */ Areq = 1<<6, /* EEPROM Access Request */ Agnt = 1<<7, /* EEPROM Access Grant */ }; enum { /* Eerd */ ee_start = 1<<0, /* Start Read */ ee_done = 1<<1, /* Read done */ ee_addr = 0xfff8<<2, /* Read address [15:2] */ ee_data = 0xffff<<16, /* Read Data; Data returned from eeprom/nvm */ }; 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 { /* 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 */ Bsize2048 = 0x00000000, Bsize1024 = 0x00010000, Bsize512 = 0x00020000, Bsize256 = 0x00030000, 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 (82575eb) */ }; enum { /* Rxcsum */ PcssMASK = 0x000000FF, /* Packet Checksum Start */ PcssSHIFT = 0, Ipofl = 0x00000100, /* IP Checksum Off-load Enable */ Tuofl = 0x00000200, /* TCP/UDP Checksum Off-load Enable */ }; typedef struct Rdesc { /* Receive Descriptor */ uint addr[2]; ushort length; ushort checksum; uchar status; uchar errors; ushort special; } Rdesc; enum { /* Rdesc 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 { /* Rdesc 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 Tdesc { /* Legacy+Normal Transmit Descriptor */ uint addr[2]; uint control; /* varies with descriptor type */ uint status; /* varies with descriptor type */ } Tdesc; 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 = 0x00000001, /* Descriptor Done */ Ec = 0x00000002, /* Excess Collisions */ Lc = 0x00000004, /* Late Collision */ Tu = 0x00000008, /* Transmit Underrun */ CssMASK = 0x0000FF00, /* Checksum Start Field */ CssSHIFT = 8, }; typedef struct { ushort *reg; ulong *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 { Nrdesc = 32, /* multiple of 8 */ Ntdesc = 8, /* multiple of 8 */ }; enum { i82563, i82566, i82567, i82571, i82572, i82573, i82574, i82575, i82576, i82577, }; static char *tname[] = { "i82563", "i82566", "i82567", "i82571", "i82572", "i82573", "i82574", "i82575", "i82576", "i82577", }; typedef struct Ctlr Ctlr; struct Ctlr { int port; Pcidev *pcidev; Ctlr *next; int active; int cls; ushort eeprom[0x40]; uchar ra[Eaddrlen]; /* receive address */ int type; u32int* nic; Lock imlock; int im; /* interrupt mask */ Lock slock; uint statistics[Nstatistics]; Rdesc *rdba; /* receive descriptor base address */ Block **rb; /* receive buffers */ int rdh; /* receive descriptor head */ int rdt; /* receive descriptor tail */ Tdesc *tdba; /* transmit descriptor base address */ Lock tdlock; Block **tb; /* transmit buffers */ int tdh; /* transmit descriptor head */ int tdt; /* transmit descriptor tail */ int txcw; int fcrtl; int fcrth; /* bootstrap goo */ Block *bqhead; /* transmission queue */ Block *bqtail; }; static Ctlr *ctlrhead; static Ctlr *ctlrtail; #define csr32r(c, r) (*((c)->nic+((r)/4))) #define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v)) static void i82563im(Ctlr* ctlr, int im) { ilock(&ctlr->imlock); ctlr->im |= im; csr32w(ctlr, Ims, ctlr->im); iunlock(&ctlr->imlock); } static void i82563attach(Ether* edev) { int ctl; Ctlr *ctlr; ctlr = edev->ctlr;