/* * Intel 8254[340]NN Gigabit Ethernet Controller * as found on the Intel PRO/1000 series of adapters: * 82543GC Intel PRO/1000 T * 82544EI Intel PRO/1000 XT * 82540EM Intel PRO/1000 MT * 82541[GP]I * 82547GI * 82546GB * 82546EB * To Do: * finish autonegotiation code; * integrate fiber stuff back in (this ONLY handles * the CAT5 cards at the moment); * add checksum-offload; * add tuning control via ctl file; * this driver is little-endian specific. */#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"#include "ethermii.h" enum { i82542 = (0x1000<<16)|0x8086, i82543gc = (0x1004<<16)|0x8086, i82544ei = (0x1008<<16)|0x8086, i82547ei = (0x1019<<16)|0x8086, i82540em = (0x100E<<16)|0x8086, i82540eplp = (0x101E<<16)|0x8086, i82545gmc = (0x1026<<16)|0x8086, i82547gi = (0x1075<<16)|0x8086, i82541gi = (0x1076<<16)|0x8086, i82541gi2 = (0x1077<<16)|0x8086, i82546gb = (0x1079<<16)|0x8086, i82541pi = (0x107c<<16)|0x8086, i82546eb = (0x1010<<16)|0x8086,}; enum { Ctrl = 0x00000000, /* Device Control */ Ctrldup = 0x00000004, /* Device Control Duplicate */ Status = 0x00000008, /* Device Status */ Eecd = 0x00000010, /* EEPROM/Flash Control/Data */ Ctrlext = 0x00000018, /* Extended Device Control */ Mdic = 0x00000020, /* MDI Control */ Fcal = 0x00000028, /* Flow Control Address Low */ Fcah = 0x0000002C, /* Flow Control Address High */ Fct = 0x00000030, /* Flow Control Type */ Icr = 0x000000C0, /* Interrupt Cause Read */ Ics = 0x000000C8, /* Interrupt Cause Set */ Ims = 0x000000D0, /* Interrupt Mask Set/Read */ Imc = 0x000000D8, /* Interrupt mask Clear */ Rctl = 0x00000100, /* Receive Control */ Fcttv = 0x00000170, /* Flow Control Transmit Timer Value */ Txcw = 0x00000178, /* Transmit Configuration Word */ Rxcw = 0x00000180, /* Receive Configuration Word */ Tctl = 0x00000400, /* Transmit Control */ Tipg = 0x00000410, /* Transmit IPG */ Tbt = 0x00000448, /* Transmit Burst Timer */ Ait = 0x00000458, /* Adaptive IFS Throttle */ Fcrtl = 0x00002160, /* Flow Control RX Threshold Low */ Fcrth = 0x00002168, /* Flow Control Rx Threshold High */ Rdfh = 0x00002410, /* Receive data fifo head */ Rdft = 0x00002418, /* Receive data fifo tail */ Rdfhs = 0x00002420, /* Receive data fifo head saved */ Rdfts = 0x00002428, /* Receive data fifo tail saved */ Rdfpc = 0x00002430, /* Receive data fifo packet count */ Rdbal = 0x00002800, /* Rd Base Address Low */ Rdbah = 0x00002804, /* Rd Base Address High */ Rdlen = 0x00002808, /* Receive Descriptor Length */ Rdh = 0x00002810, /* Receive Descriptor Head */ Rdt = 0x00002818, /* Receive Descriptor Tail */ Rdtr = 0x00002820, /* Receive Descriptor Timer Ring */ Rxdctl = 0x00002828, /* Receive Descriptor Control */ Radv = 0x0000282C, /* Receive Interrupt Absolute Delay Timer */ Txdmac = 0x00003000, /* Transfer DMA Control */ Ett = 0x00003008, /* Early Transmit Control */ Tdfh = 0x00003410, /* Transmit data fifo head */ Tdft = 0x00003418, /* Transmit data fifo tail */ Tdfhs = 0x00003420, /* Transmit data Fifo Head saved */ Tdfts = 0x00003428, /* Transmit data fifo tail saved */ Tdfpc = 0x00003430, /* Trasnmit data Fifo packet count */ Tdbal = 0x00003800, /* Td Base Address Low */ Tdbah = 0x00003804, /* Td 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 */ 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, Rxcsum = 0x00005000, /* Receive Checksum Control */ Mta = 0x00005200, /* Multicast Table Array */ Ral = 0x00005400, /* Receive Address Low */ Rah = 0x00005404, /* Receive Address High */ Manc = 0x00005820, /* Management Control */}; enum { /* Ctrl */ Bem = 0x00000002, /* Big Endian Mode */ Prior = 0x00000004, /* Priority on the PCI bus */ Lrst = 0x00000008, /* Link Reset */ Asde = 0x00000020, /* Auto-Speed Detection Enable */ Slu = 0x00000040, /* Set Link Up */ Ilos = 0x00000080, /* Invert Loss of Signal (LOS) */ SspeedMASK = 0x00000300, /* Speed Selection */ SspeedSHIFT = 8, Sspeed10 = 0x00000000, /* 10Mb/s */ Sspeed100 = 0x00000100, /* 100Mb/s */ Sspeed1000 = 0x00000200, /* 1000Mb/s */ Frcspd = 0x00000800, /* Force Speed */ Frcdplx = 0x00001000, /* Force Duplex */ SwdpinsloMASK = 0x003C0000, /* Software Defined Pins - lo nibble */ SwdpinsloSHIFT = 18, SwdpioloMASK = 0x03C00000, /* Software Defined Pins - I or O */ SwdpioloSHIFT = 22, Devrst = 0x04000000, /* Device Reset */ Rfce = 0x08000000, /* Receive Flow Control Enable */ Tfce = 0x10000000, /* Transmit Flow Control Enable */ Vme = 0x40000000, /* VLAN Mode Enable */}; enum { /* Status */ Lu = 0x00000002, /* Link Up */ Tckok = 0x00000004, /* Transmit clock is running */ Rbcok = 0x00000008, /* Receive clock is running */ Txoff = 0x00000010, /* Transmission Paused */ Tbimode = 0x00000020, /* TBI Mode Indication */ LspeedMASK = 0x000000C0, /* Link Speed Setting */ LspeedSHIFT = 6, Lspeed10 = 0x00000000, /* 10Mb/s */ Lspeed100 = 0x00000040, /* 100Mb/s */ Lspeed1000 = 0x00000080, /* 1000Mb/s */ Mtxckok = 0x00000400, /* MTX clock is running */ Pci66 = 0x00000800, /* PCI Bus speed indication */ Bus64 = 0x00001000, /* PCI Bus width indication */ Pcixmode = 0x00002000, /* PCI-X mode */ PcixspeedMASK = 0x0000C000, /* PCI-X bus speed */ PcixspeedSHIFT = 14, Pcix66 = 0x00000000, /* 50-66MHz */ Pcix100 = 0x00004000, /* 66-100MHz */ Pcix133 = 0x00008000, /* 100-133MHz */}; enum { /* Ctrl and Status */ Fd = 0x00000001, /* Full-Duplex */ AsdvMASK = 0x00000300, AsdvSHIFT = 8, Asdv10 = 0x00000000, /* 10Mb/s */ Asdv100 = 0x00000100, /* 100Mb/s */ Asdv1000 = 0x00000200, /* 1000Mb/s */}; enum { /* Eecd */ Sk = 0x00000001, /* Clock input to the EEPROM */ Cs = 0x00000002, /* Chip Select */ Di = 0x00000004, /* Data Input to the EEPROM */ Do = 0x00000008, /* Data Output from the EEPROM */ Areq = 0x00000040, /* EEPROM Access Request */ Agnt = 0x00000080, /* EEPROM Access Grant */ Eepresent = 0x00000100, /* EEPROM Present */ Eesz256 = 0x00000200, /* EEPROM is 256 words not 64 */ Eeszaddr = 0x00000400, /* EEPROM size for 8254[17] */ Spi = 0x00002000, /* EEPROM is SPI not Microwire */}; enum { /* Ctrlext */ Gpien = 0x0000000F, /* General Purpose Interrupt Enables */ SwdpinshiMASK = 0x000000F0, /* Software Defined Pins - hi nibble */ SwdpinshiSHIFT = 4, SwdpiohiMASK = 0x00000F00, /* Software Defined Pins - I or O */ SwdpiohiSHIFT = 8, Asdchk = 0x00001000, /* ASD Check */ Eerst = 0x00002000, /* EEPROM Reset */ Ips = 0x00004000, /* Invert Power State */ Spdbyps = 0x00008000, /* Speed Select Bypass */}; enum { /* EEPROM content offsets */ Ea = 0x00, /* Ethernet Address */ Cf = 0x03, /* Compatibility Field */ Pba = 0x08, /* Printed Board Assembly number */ 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, /* Rd 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,}; /* * The Mdic register isn't implemented on the 82543GC, * the software defined pins are used instead. * These definitions work for the Intel PRO/1000 T Server Adapter. * The direction pin bits are read from the EEPROM. */enum { Mdd = ((1<<2)<<SwdpinsloSHIFT), /* data */ Mddo = ((1<<2)<<SwdpioloSHIFT), /* pin direction */ Mdc = ((1<<3)<<SwdpinsloSHIFT), /* clock */ Mdco = ((1<<3)<<SwdpioloSHIFT), /* pin direction */ Mdr = ((1<<0)<<SwdpinshiSHIFT), /* reset */ Mdro = ((1<<0)<<SwdpiohiSHIFT), /* pin direction */}; 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 { /* Rxcw */ Rxword = 0x0000FFFF, /* Data from auto-negotiation process */ Rxnocarrier = 0x04000000, /* Carrier Sense indication */ Rxinvalid = 0x08000000, /* Invalid Symbol during configuration */ Rxchange = 0x10000000, /* Change to the Rxword indication */ Rxconfig = 0x20000000, /* /C/ order set reception indication */ Rxsync = 0x40000000, /* Lost bit synchronization indication */ Anc = 0x80000000, /* Auto Negotiation Complete */}; 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, /* Rd 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 */ Mo47b36 = 0x00000000, /* bits [47:36] of received address */ Mo46b35 = 0x00001000, /* bits [46:35] of received address */ Mo45b34 = 0x00002000, /* bits [45:34] of received address */ Mo43b32 = 0x00003000, /* bits [43:32] of received address */ Bam = 0x00008000, /* Broadcast Accept Mode */ BsizeMASK = 0x00030000, /* Receive Buffer Size */ Bsize2048 = 0x00000000, /* Bsex = 0 */ Bsize1024 = 0x00010000, /* Bsex = 0 */ Bsize512 = 0x00020000, /* Bsex = 0 */ Bsize256 = 0x00030000, /* Bsex = 0 */ Bsize16384 = 0x00010000, /* Bsex = 1 */ 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 */ 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 */ LthreshMASK = 0xFE000000, /* Low Threshold */ LthreshSHIFT = 25,}; enum { /* Rxcsum */ PcssMASK = 0x000000FF, /* Packet Checksum Start */ PcssSHIFT = 0, Ipofl = 0x00000100, /* IP Checksum Off-load Enable */ Tuofl = 0x00000200, /* TCP/UDP Checksum Off-load Enable */}; enum { /* Manc */ Arpen = 0x00002000, /* Enable ARP Request Filtering */}; enum { /* Receive Delay Timer Ring */ DelayMASK = 0x0000FFFF, /* delay timer in 1.024nS increments */ DelaySHIFT = 0, Fpd = 0x80000000, /* Flush partial Descriptor Block */}; typedef struct Rd { /* Receive Descriptor */ uint addr[2]; ushort length; ushort checksum; uchar status; uchar errors; ushort 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 Td Td;struct Td { /* Transmit Descriptor */ union { uint addr[2]; /* Data */ struct { /* Context */ uchar ipcss; uchar ipcso; ushort ipcse; uchar tucss; uchar tucso; ushort tucse; }; }; uint control; uint status;}; enum { /* Td 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 { /* Td status */ Tdd = 0x00000001, /* Descriptor Done */ Ec = 0x00000002, /* Excess Collisions */ Lc = 0x00000004, /* Late Collision */ Tu = 0x00000008, /* Transmit Underrun */ Iixsm = 0x00000100, /* Insert IP Checksum */ Itxsm = 0x00000200, /* Insert TCP/UDP Checksum */ HdrlenMASK = 0x0000FF00, /* Header Length (Tse) */ HdrlenSHIFT = 8, VlanMASK = 0x0FFF0000, /* VLAN Identifier */ VlanSHIFT = 16, Tcfi = 0x10000000, /* Canonical Form Indicator */ PriMASK = 0xE0000000, /* User Priority */ PriSHIFT = 29, MssMASK = 0xFFFF0000, /* Maximum Segment Size (Tse) */ MssSHIFT = 16,}; enum { Nrd = 256, /* multiple of 8 */ Ntd = 64, /* multiple of 8 */ Nrb = 1024, /* private receive buffers per Ctlr */ Rbsz = 2048,}; typedef struct Ctlr Ctlr;typedef struct Ctlr { int port; Pcidev* pcidev; Ctlr* next; Ether* edev; int active; int started; int id; int cls; ushort eeprom[0x40]; QLock alock; /* attach */ void* alloc; /* receive/transmit descriptors */ int nrd; int ntd; int nrb; /* how many this Ctlr has in the pool */ int* nic; Lock imlock; int im; /* interrupt mask */ Mii* mii; Rendez lrendez; int lim; int link; QLock slock; uint statistics[Nstatistics]; uint lsleep; uint lintr; uint rsleep; uint rintr; uint txdw; uint tintr; uint ixsm; uint ipcs; uint tcpcs; uchar ra[Eaddrlen]; /* receive address */ ulong mta[128]; /* multicast table array */ Rendez rrendez; int rim; int rdfree; Rd* rdba; /* receive descriptor base address */ Block** rb; /* receive buffers */ int rdh; /* receive descriptor head */ int rdt; /* receive descriptor tail */ int rdtr; /* receive delay timer ring value */ Lock tlock; int tbusy; int tdfree; Td* tdba; /* transmit descriptor base address */ Block** tb; /* transmit buffers */ int tdh; /* transmit descriptor head */Lines 1–500 of 1989. Load more
/* * Intel 8254[340]NN Gigabit Ethernet Controller * as found on the Intel PRO/1000 series of adapters: * 82543GC Intel PRO/1000 T * 82544EI Intel PRO/1000 XT * 82540EM Intel PRO/1000 MT * 82541[GP]I * 82547GI * 82546GB * 82546EB * To Do: * finish autonegotiation code; * integrate fiber stuff back in (this ONLY handles * the CAT5 cards at the moment); * add checksum-offload; * add tuning control via ctl file; * this driver is little-endian specific. */ #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" #include "ethermii.h" enum { i82542 = (0x1000<<16)|0x8086, i82543gc = (0x1004<<16)|0x8086, i82544ei = (0x1008<<16)|0x8086, i82547ei = (0x1019<<16)|0x8086, i82540em = (0x100E<<16)|0x8086, i82540eplp = (0x101E<<16)|0x8086, i82545gmc = (0x1026<<16)|0x8086, i82547gi = (0x1075<<16)|0x8086, i82541gi = (0x1076<<16)|0x8086, i82541gi2 = (0x1077<<16)|0x8086, i82546gb = (0x1079<<16)|0x8086, i82541pi = (0x107c<<16)|0x8086, i82546eb = (0x1010<<16)|0x8086, }; enum { Ctrl = 0x00000000, /* Device Control */ Ctrldup = 0x00000004, /* Device Control Duplicate */ Status = 0x00000008, /* Device Status */ Eecd = 0x00000010, /* EEPROM/Flash Control/Data */ Ctrlext = 0x00000018, /* Extended Device Control */ Mdic = 0x00000020, /* MDI Control */ Fcal = 0x00000028, /* Flow Control Address Low */ Fcah = 0x0000002C, /* Flow Control Address High */ Fct = 0x00000030, /* Flow Control Type */ Icr = 0x000000C0, /* Interrupt Cause Read */ Ics = 0x000000C8, /* Interrupt Cause Set */ Ims = 0x000000D0, /* Interrupt Mask Set/Read */ Imc = 0x000000D8, /* Interrupt mask Clear */ Rctl = 0x00000100, /* Receive Control */ Fcttv = 0x00000170, /* Flow Control Transmit Timer Value */ Txcw = 0x00000178, /* Transmit Configuration Word */ Rxcw = 0x00000180, /* Receive Configuration Word */ Tctl = 0x00000400, /* Transmit Control */ Tipg = 0x00000410, /* Transmit IPG */ Tbt = 0x00000448, /* Transmit Burst Timer */ Ait = 0x00000458, /* Adaptive IFS Throttle */ Fcrtl = 0x00002160, /* Flow Control RX Threshold Low */ Fcrth = 0x00002168, /* Flow Control Rx Threshold High */ Rdfh = 0x00002410, /* Receive data fifo head */ Rdft = 0x00002418, /* Receive data fifo tail */ Rdfhs = 0x00002420, /* Receive data fifo head saved */ Rdfts = 0x00002428, /* Receive data fifo tail saved */ Rdfpc = 0x00002430, /* Receive data fifo packet count */ Rdbal = 0x00002800, /* Rd Base Address Low */ Rdbah = 0x00002804, /* Rd Base Address High */ Rdlen = 0x00002808, /* Receive Descriptor Length */ Rdh = 0x00002810, /* Receive Descriptor Head */ Rdt = 0x00002818, /* Receive Descriptor Tail */ Rdtr = 0x00002820, /* Receive Descriptor Timer Ring */ Rxdctl = 0x00002828, /* Receive Descriptor Control */ Radv = 0x0000282C, /* Receive Interrupt Absolute Delay Timer */ Txdmac = 0x00003000, /* Transfer DMA Control */ Ett = 0x00003008, /* Early Transmit Control */ Tdfh = 0x00003410, /* Transmit data fifo head */ Tdft = 0x00003418, /* Transmit data fifo tail */ Tdfhs = 0x00003420, /* Transmit data Fifo Head saved */ Tdfts = 0x00003428, /* Transmit data fifo tail saved */ Tdfpc = 0x00003430, /* Trasnmit data Fifo packet count */ Tdbal = 0x00003800, /* Td Base Address Low */ Tdbah = 0x00003804, /* Td 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 */ 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, Rxcsum = 0x00005000, /* Receive Checksum Control */ Mta = 0x00005200, /* Multicast Table Array */ Ral = 0x00005400, /* Receive Address Low */ Rah = 0x00005404, /* Receive Address High */ Manc = 0x00005820, /* Management Control */ }; enum { /* Ctrl */ Bem = 0x00000002, /* Big Endian Mode */ Prior = 0x00000004, /* Priority on the PCI bus */ Lrst = 0x00000008, /* Link Reset */ Asde = 0x00000020, /* Auto-Speed Detection Enable */ Slu = 0x00000040, /* Set Link Up */ Ilos = 0x00000080, /* Invert Loss of Signal (LOS) */ SspeedMASK = 0x00000300, /* Speed Selection */ SspeedSHIFT = 8, Sspeed10 = 0x00000000, /* 10Mb/s */ Sspeed100 = 0x00000100, /* 100Mb/s */ Sspeed1000 = 0x00000200, /* 1000Mb/s */ Frcspd = 0x00000800, /* Force Speed */ Frcdplx = 0x00001000, /* Force Duplex */ SwdpinsloMASK = 0x003C0000, /* Software Defined Pins - lo nibble */ SwdpinsloSHIFT = 18, SwdpioloMASK = 0x03C00000, /* Software Defined Pins - I or O */ SwdpioloSHIFT = 22, Devrst = 0x04000000, /* Device Reset */ Rfce = 0x08000000, /* Receive Flow Control Enable */ Tfce = 0x10000000, /* Transmit Flow Control Enable */ Vme = 0x40000000, /* VLAN Mode Enable */ }; enum { /* Status */ Lu = 0x00000002, /* Link Up */ Tckok = 0x00000004, /* Transmit clock is running */ Rbcok = 0x00000008, /* Receive clock is running */ Txoff = 0x00000010, /* Transmission Paused */ Tbimode = 0x00000020, /* TBI Mode Indication */ LspeedMASK = 0x000000C0, /* Link Speed Setting */ LspeedSHIFT = 6, Lspeed10 = 0x00000000, /* 10Mb/s */ Lspeed100 = 0x00000040, /* 100Mb/s */ Lspeed1000 = 0x00000080, /* 1000Mb/s */ Mtxckok = 0x00000400, /* MTX clock is running */ Pci66 = 0x00000800, /* PCI Bus speed indication */ Bus64 = 0x00001000, /* PCI Bus width indication */ Pcixmode = 0x00002000, /* PCI-X mode */ PcixspeedMASK = 0x0000C000, /* PCI-X bus speed */ PcixspeedSHIFT = 14, Pcix66 = 0x00000000, /* 50-66MHz */ Pcix100 = 0x00004000, /* 66-100MHz */ Pcix133 = 0x00008000, /* 100-133MHz */ }; enum { /* Ctrl and Status */ Fd = 0x00000001, /* Full-Duplex */ AsdvMASK = 0x00000300, AsdvSHIFT = 8, Asdv10 = 0x00000000, /* 10Mb/s */ Asdv100 = 0x00000100, /* 100Mb/s */ Asdv1000 = 0x00000200, /* 1000Mb/s */ }; enum { /* Eecd */ Sk = 0x00000001, /* Clock input to the EEPROM */ Cs = 0x00000002, /* Chip Select */ Di = 0x00000004, /* Data Input to the EEPROM */ Do = 0x00000008, /* Data Output from the EEPROM */ Areq = 0x00000040, /* EEPROM Access Request */ Agnt = 0x00000080, /* EEPROM Access Grant */ Eepresent = 0x00000100, /* EEPROM Present */ Eesz256 = 0x00000200, /* EEPROM is 256 words not 64 */ Eeszaddr = 0x00000400, /* EEPROM size for 8254[17] */ Spi = 0x00002000, /* EEPROM is SPI not Microwire */ }; enum { /* Ctrlext */ Gpien = 0x0000000F, /* General Purpose Interrupt Enables */ SwdpinshiMASK = 0x000000F0, /* Software Defined Pins - hi nibble */ SwdpinshiSHIFT = 4, SwdpiohiMASK = 0x00000F00, /* Software Defined Pins - I or O */ SwdpiohiSHIFT = 8, Asdchk = 0x00001000, /* ASD Check */ Eerst = 0x00002000, /* EEPROM Reset */ Ips = 0x00004000, /* Invert Power State */ Spdbyps = 0x00008000, /* Speed Select Bypass */ }; enum { /* EEPROM content offsets */ Ea = 0x00, /* Ethernet Address */ Cf = 0x03, /* Compatibility Field */ Pba = 0x08, /* Printed Board Assembly number */ 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, /* Rd 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, }; /* * The Mdic register isn't implemented on the 82543GC, * the software defined pins are used instead. * These definitions work for the Intel PRO/1000 T Server Adapter. * The direction pin bits are read from the EEPROM. */ enum { Mdd = ((1<<2)<<SwdpinsloSHIFT), /* data */ Mddo = ((1<<2)<<SwdpioloSHIFT), /* pin direction */ Mdc = ((1<<3)<<SwdpinsloSHIFT), /* clock */ Mdco = ((1<<3)<<SwdpioloSHIFT), /* pin direction */ Mdr = ((1<<0)<<SwdpinshiSHIFT), /* reset */ Mdro = ((1<<0)<<SwdpiohiSHIFT), /* pin direction */ }; 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 { /* Rxcw */ Rxword = 0x0000FFFF, /* Data from auto-negotiation process */ Rxnocarrier = 0x04000000, /* Carrier Sense indication */ Rxinvalid = 0x08000000, /* Invalid Symbol during configuration */ Rxchange = 0x10000000, /* Change to the Rxword indication */ Rxconfig = 0x20000000, /* /C/ order set reception indication */ Rxsync = 0x40000000, /* Lost bit synchronization indication */ Anc = 0x80000000, /* Auto Negotiation Complete */ }; 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, /* Rd 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 */ Mo47b36 = 0x00000000, /* bits [47:36] of received address */ Mo46b35 = 0x00001000, /* bits [46:35] of received address */ Mo45b34 = 0x00002000, /* bits [45:34] of received address */ Mo43b32 = 0x00003000, /* bits [43:32] of received address */ Bam = 0x00008000, /* Broadcast Accept Mode */ BsizeMASK = 0x00030000, /* Receive Buffer Size */ Bsize2048 = 0x00000000, /* Bsex = 0 */ Bsize1024 = 0x00010000, /* Bsex = 0 */ Bsize512 = 0x00020000, /* Bsex = 0 */ Bsize256 = 0x00030000, /* Bsex = 0 */ Bsize16384 = 0x00010000, /* Bsex = 1 */ 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 */ 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 */ LthreshMASK = 0xFE000000, /* Low Threshold */ LthreshSHIFT = 25, }; enum { /* Rxcsum */ PcssMASK = 0x000000FF, /* Packet Checksum Start */ PcssSHIFT = 0, Ipofl = 0x00000100, /* IP Checksum Off-load Enable */ Tuofl = 0x00000200, /* TCP/UDP Checksum Off-load Enable */ }; enum { /* Manc */ Arpen = 0x00002000, /* Enable ARP Request Filtering */ }; enum { /* Receive Delay Timer Ring */ DelayMASK = 0x0000FFFF, /* delay timer in 1.024nS increments */ DelaySHIFT = 0, Fpd = 0x80000000, /* Flush partial Descriptor Block */ }; typedef struct Rd { /* Receive Descriptor */ uint addr[2]; ushort length; ushort checksum; uchar status; uchar errors; ushort 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 Td Td; struct Td { /* Transmit Descriptor */ union { uint addr[2]; /* Data */ struct { /* Context */ uchar ipcss; uchar ipcso; ushort ipcse; uchar tucss; uchar tucso; ushort tucse; }; }; uint control; uint status; }; enum { /* Td 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 { /* Td status */ Tdd = 0x00000001, /* Descriptor Done */ Ec = 0x00000002, /* Excess Collisions */ Lc = 0x00000004, /* Late Collision */ Tu = 0x00000008, /* Transmit Underrun */ Iixsm = 0x00000100, /* Insert IP Checksum */ Itxsm = 0x00000200, /* Insert TCP/UDP Checksum */ HdrlenMASK = 0x0000FF00, /* Header Length (Tse) */ HdrlenSHIFT = 8, VlanMASK = 0x0FFF0000, /* VLAN Identifier */ VlanSHIFT = 16, Tcfi = 0x10000000, /* Canonical Form Indicator */ PriMASK = 0xE0000000, /* User Priority */ PriSHIFT = 29, MssMASK = 0xFFFF0000, /* Maximum Segment Size (Tse) */ MssSHIFT = 16, }; enum { Nrd = 256, /* multiple of 8 */ Ntd = 64, /* multiple of 8 */ Nrb = 1024, /* private receive buffers per Ctlr */ Rbsz = 2048, }; typedef struct Ctlr Ctlr; typedef struct Ctlr { int port; Pcidev* pcidev; Ctlr* next; Ether* edev; int active; int started; int id; int cls; ushort eeprom[0x40]; QLock alock; /* attach */ void* alloc; /* receive/transmit descriptors */ int nrd; int ntd; int nrb; /* how many this Ctlr has in the pool */ int* nic; Lock imlock; int im; /* interrupt mask */ Mii* mii; Rendez lrendez; int lim; int link; QLock slock; uint statistics[Nstatistics]; uint lsleep; uint lintr; uint rsleep; uint rintr; uint txdw; uint tintr; uint ixsm; uint ipcs; uint tcpcs; uchar ra[Eaddrlen]; /* receive address */ ulong mta[128]; /* multicast table array */ Rendez rrendez; int rim; int rdfree; Rd* rdba; /* receive descriptor base address */ Block** rb; /* receive buffers */ int rdh; /* receive descriptor head */ int rdt; /* receive descriptor tail */ int rdtr; /* receive delay timer ring value */ Lock tlock; int tbusy; int tdfree; Td* tdba; /* transmit descriptor base address */ Block** tb; /* transmit buffers */ int tdh; /* transmit descriptor head */