1858 lines · 42.2 KB · C
RawDownload
/*  * 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.