⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 r8169.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 4 页
字号:
/*========================================================================= r8169.c: A RealTek RTL-8169 Gigabit Ethernet driver for Linux kernel 2.4.x. -------------------------------------------------------------------- History: Feb  4 2002	- created initially by ShuChen <shuchen@realtek.com.tw>. May 20 2002	- Add link status force-mode and TBI mode support.=========================================================================  1. [DEPRECATED: use ethtool instead] The media can be forced in 5 modes.	 Command: 'insmod r8169 media = SET_MEDIA'	 Ex:	  'insmod r8169 media = 0x04' will force PHY to operate in 100Mpbs Half-duplex.		 SET_MEDIA can be: 		_10_Half	= 0x01 		_10_Full	= 0x02 		_100_Half	= 0x04 		_100_Full	= 0x08 		_1000_Full	= 0x10    2. Support TBI mode.=========================================================================VERSION 1.1	<2002/10/4>	The bit4:0 of MII register 4 is called "selector field", and have to be	00001b to indicate support of IEEE std 802.3 during NWay process of	exchanging Link Code Word (FLP). VERSION 1.2	<2002/11/30>	- Large style cleanup	- Use ether_crc in stock kernel (linux/crc32.h)	- Copy mc_filter setup code from 8139cp	  (includes an optimization, and avoids set_bit use)*/#include <linux/module.h>#include <linux/pci.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/delay.h>#include <linux/ethtool.h>#include <linux/mii.h>#include <linux/crc32.h>#include <linux/init.h>#include <linux/dma-mapping.h>#include <asm/io.h>#define RTL8169_VERSION "1.2"#define MODULENAME "r8169"#define RTL8169_DRIVER_NAME   MODULENAME " Gigabit Ethernet driver " RTL8169_VERSION#define PFX MODULENAME ": "#ifdef RTL8169_DEBUG#define assert(expr) \        if(!(expr)) {					\	        printk( "Assertion failed! %s,%s,%s,line=%d\n",	\        	#expr,__FILE__,__FUNCTION__,__LINE__);		\        }#define dprintk(fmt, args...)	do { printk(PFX fmt, ## args) } while (0)#else#define assert(expr) do {} while (0)#define dprintk(fmt, args...)	do {} while (0)#endif /* RTL8169_DEBUG */#ifdef CONFIG_R8169_NAPI#define rtl8169_rx_skb			netif_receive_skb#define rtl8169_rx_quota(count, quota)	min(count, quota)#else#define rtl8169_rx_skb			netif_rx#define rtl8169_rx_quota(count, quota)	count#endif/* media options */#define MAX_UNITS 8static int media[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 };/* Maximum events (Rx packets, etc.) to handle at each interrupt. */static int max_interrupt_work = 20;/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).   The RTL chips use a 64 element hash table based on the Ethernet CRC.  */static int multicast_filter_limit = 32;/* MAC address length*/#define MAC_ADDR_LEN	6/* max supported gigabit ethernet frame size -- must be at least (dev->mtu+14+4).*/#define MAX_ETH_FRAME_SIZE	1536#define TX_FIFO_THRESH 256	/* In bytes */#define RX_FIFO_THRESH	7	/* 7 means NO threshold, Rx buffer level before first PCI xfer.  */#define RX_DMA_BURST	6	/* Maximum PCI burst, '6' is 1024 */#define TX_DMA_BURST	6	/* Maximum PCI burst, '6' is 1024 */#define EarlyTxThld 	0x3F	/* 0x3F means NO early transmit */#define RxPacketMaxSize	0x0800	/* Maximum size supported is 16K-1 */#define InterFrameGap	0x03	/* 3 means InterFrameGap = the shortest one */#define R8169_NAPI_WEIGHT	64#define NUM_TX_DESC	64	/* Number of Tx descriptor registers */#define NUM_RX_DESC	256	/* Number of Rx descriptor registers */#define RX_BUF_SIZE	1536	/* Rx Buffer size */#define R8169_TX_RING_BYTES	(NUM_TX_DESC * sizeof(struct TxDesc))#define R8169_RX_RING_BYTES	(NUM_RX_DESC * sizeof(struct RxDesc))#define RTL_MIN_IO_SIZE 0x80#define RTL8169_TX_TIMEOUT	(6*HZ)#define RTL8169_PHY_TIMEOUT	(10*HZ)/* write/read MMIO register */#define RTL_W8(reg, val8)	writeb ((val8), ioaddr + (reg))#define RTL_W16(reg, val16)	writew ((val16), ioaddr + (reg))#define RTL_W32(reg, val32)	writel ((val32), ioaddr + (reg))#define RTL_R8(reg)		readb (ioaddr + (reg))#define RTL_R16(reg)		readw (ioaddr + (reg))#define RTL_R32(reg)		((unsigned long) readl (ioaddr + (reg)))enum mac_version {	RTL_GIGA_MAC_VER_B = 0x00,	/* RTL_GIGA_MAC_VER_C = 0x03, */	RTL_GIGA_MAC_VER_D = 0x01,	RTL_GIGA_MAC_VER_E = 0x02};enum phy_version {	RTL_GIGA_PHY_VER_C = 0x03, /* PHY Reg 0x03 bit0-3 == 0x0000 */	RTL_GIGA_PHY_VER_D = 0x04, /* PHY Reg 0x03 bit0-3 == 0x0000 */	RTL_GIGA_PHY_VER_E = 0x05, /* PHY Reg 0x03 bit0-3 == 0x0000 */	RTL_GIGA_PHY_VER_F = 0x06, /* PHY Reg 0x03 bit0-3 == 0x0001 */	RTL_GIGA_PHY_VER_G = 0x07, /* PHY Reg 0x03 bit0-3 == 0x0002 */};#define _R(NAME,MAC,MASK) \	{ .name = NAME, .mac_version = MAC, .RxConfigMask = MASK }const static struct {	const char *name;	u8 mac_version;	u32 RxConfigMask;	/* Clears the bits supported by this chip */} rtl_chip_info[] = {	_R("RTL8169",		RTL_GIGA_MAC_VER_B, 0xff7e1880),	_R("RTL8169s/8110s",	RTL_GIGA_MAC_VER_D, 0xff7e1880),	_R("RTL8169s/8110s",	RTL_GIGA_MAC_VER_E, 0xff7e1880)};#undef _Rstatic struct pci_device_id rtl8169_pci_tbl[] = {	{0x10ec, 0x8169, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},	{0,},};MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl);static int rx_copybreak = 200;static int use_dac;enum RTL8169_registers {	MAC0 = 0,		/* Ethernet hardware address. */	MAR0 = 8,		/* Multicast filter. */	TxDescStartAddrLow = 0x20,	TxDescStartAddrHigh = 0x24,	TxHDescStartAddrLow = 0x28,	TxHDescStartAddrHigh = 0x2c,	FLASH = 0x30,	ERSR = 0x36,	ChipCmd = 0x37,	TxPoll = 0x38,	IntrMask = 0x3C,	IntrStatus = 0x3E,	TxConfig = 0x40,	RxConfig = 0x44,	RxMissed = 0x4C,	Cfg9346 = 0x50,	Config0 = 0x51,	Config1 = 0x52,	Config2 = 0x53,	Config3 = 0x54,	Config4 = 0x55,	Config5 = 0x56,	MultiIntr = 0x5C,	PHYAR = 0x60,	TBICSR = 0x64,	TBI_ANAR = 0x68,	TBI_LPAR = 0x6A,	PHYstatus = 0x6C,	RxMaxSize = 0xDA,	CPlusCmd = 0xE0,	RxDescAddrLow = 0xE4,	RxDescAddrHigh = 0xE8,	EarlyTxThres = 0xEC,	FuncEvent = 0xF0,	FuncEventMask = 0xF4,	FuncPresetState = 0xF8,	FuncForceEvent = 0xFC,};enum RTL8169_register_content {	/*InterruptStatusBits */	SYSErr = 0x8000,	PCSTimeout = 0x4000,	SWInt = 0x0100,	TxDescUnavail = 0x80,	RxFIFOOver = 0x40,	LinkChg = 0x20,	RxOverflow = 0x10,	TxErr = 0x08,	TxOK = 0x04,	RxErr = 0x02,	RxOK = 0x01,	/*RxStatusDesc */	RxRES = 0x00200000,	RxCRC = 0x00080000,	RxRUNT = 0x00100000,	RxRWT = 0x00400000,	/*ChipCmdBits */	CmdReset = 0x10,	CmdRxEnb = 0x08,	CmdTxEnb = 0x04,	RxBufEmpty = 0x01,	/*Cfg9346Bits */	Cfg9346_Lock = 0x00,	Cfg9346_Unlock = 0xC0,	/*rx_mode_bits */	AcceptErr = 0x20,	AcceptRunt = 0x10,	AcceptBroadcast = 0x08,	AcceptMulticast = 0x04,	AcceptMyPhys = 0x02,	AcceptAllPhys = 0x01,	/*RxConfigBits */	RxCfgFIFOShift = 13,	RxCfgDMAShift = 8,	/*TxConfigBits */	TxInterFrameGapShift = 24,	TxDMAShift = 8,	/* DMA burst value (0-7) is shift this many bits */	/* TBICSR p.28 */	TBIReset	= 0x80000000,	TBILoopback	= 0x40000000,	TBINwEnable	= 0x20000000,	TBINwRestart	= 0x10000000,	TBILinkOk	= 0x02000000,	TBINwComplete	= 0x01000000,	/* CPlusCmd p.31 */	RxVlan		= (1 << 6),	RxChkSum	= (1 << 5),	PCIDAC		= (1 << 4),	PCIMulRW	= (1 << 3),	/*rtl8169_PHYstatus */	TBI_Enable = 0x80,	TxFlowCtrl = 0x40,	RxFlowCtrl = 0x20,	_1000bpsF = 0x10,	_100bps = 0x08,	_10bps = 0x04,	LinkStatus = 0x02,	FullDup = 0x01,	/*GIGABIT_PHY_registers */	PHY_CTRL_REG = 0,	PHY_STAT_REG = 1,	PHY_AUTO_NEGO_REG = 4,	PHY_1000_CTRL_REG = 9,	/*GIGABIT_PHY_REG_BIT */	PHY_Restart_Auto_Nego = 0x0200,	PHY_Enable_Auto_Nego = 0x1000,	//PHY_STAT_REG = 1;	PHY_Auto_Neco_Comp = 0x0020,	//PHY_AUTO_NEGO_REG = 4;	PHY_Cap_10_Half = 0x0020,	PHY_Cap_10_Full = 0x0040,	PHY_Cap_100_Half = 0x0080,	PHY_Cap_100_Full = 0x0100,	//PHY_1000_CTRL_REG = 9;	PHY_Cap_1000_Full = 0x0200,	PHY_Cap_Null = 0x0,	/*_MediaType*/	_10_Half = 0x01,	_10_Full = 0x02,	_100_Half = 0x04,	_100_Full = 0x08,	_1000_Full = 0x10,	/*_TBICSRBit*/	TBILinkOK = 0x02000000,};enum _DescStatusBit {	OWNbit = 0x80000000,	EORbit = 0x40000000,	FSbit = 0x20000000,	LSbit = 0x10000000,};#define RsvdMask	0x3fffc000struct TxDesc {	u32 status;	u32 vlan_tag;	u64 addr;};struct RxDesc {	u32 status;	u32 vlan_tag;	u64 addr;};struct rtl8169_private {	void *mmio_addr;		/* memory map physical address */	struct pci_dev *pci_dev;	/* Index of PCI device  */	struct net_device_stats stats;	/* statistics of net device */	spinlock_t lock;		/* spin lock flag */	int chipset;	int mac_version;	int phy_version;	u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */	u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */	u32 dirty_rx;	u32 dirty_tx;	struct TxDesc *TxDescArray;	/* 256-aligned Tx descriptor ring */	struct RxDesc *RxDescArray;	/* 256-aligned Rx descriptor ring */	dma_addr_t TxPhyAddr;	dma_addr_t RxPhyAddr;	struct sk_buff *Rx_skbuff[NUM_RX_DESC];	/* Rx data buffers */	struct sk_buff *Tx_skbuff[NUM_TX_DESC];	/* Tx data buffers */	struct timer_list timer;	u16 cp_cmd;	u16 intr_mask;	int phy_auto_nego_reg;	int phy_1000_ctrl_reg;	int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex);	void (*get_settings)(struct net_device *, struct ethtool_cmd *);	void (*phy_reset_enable)(void *);	unsigned int (*phy_reset_pending)(void *);	unsigned int (*link_ok)(void *);};MODULE_AUTHOR("Realtek");MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver");MODULE_PARM(media, "1-" __MODULE_STRING(MAX_UNITS) "i");MODULE_PARM(rx_copybreak, "i");MODULE_PARM(use_dac, "i");MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot.");MODULE_LICENSE("GPL");static int rtl8169_open(struct net_device *dev);static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev);static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance,			      struct pt_regs *regs);static int rtl8169_init_ring(struct net_device *dev);static void rtl8169_hw_start(struct net_device *dev);static int rtl8169_close(struct net_device *dev);static void rtl8169_set_rx_mode(struct net_device *dev);static void rtl8169_tx_timeout(struct net_device *dev);static struct net_device_stats *rtl8169_get_stats(struct net_device *netdev);#ifdef CONFIG_R8169_NAPIstatic int rtl8169_poll(struct net_device *dev, int *budget);#endifstatic const u16 rtl8169_intr_mask =	SYSErr | LinkChg | RxOverflow | RxFIFOOver | TxErr | TxOK | RxErr | RxOK;static const u16 rtl8169_napi_event =	RxOK | RxOverflow | RxFIFOOver | TxOK | TxErr;static const unsigned int rtl8169_rx_config =    (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift);#define PHY_Cap_10_Half_Or_Less PHY_Cap_10_Half#define PHY_Cap_10_Full_Or_Less PHY_Cap_10_Full | PHY_Cap_10_Half_Or_Less#define PHY_Cap_100_Half_Or_Less PHY_Cap_100_Half | PHY_Cap_10_Full_Or_Less#define PHY_Cap_100_Full_Or_Less PHY_Cap_100_Full | PHY_Cap_100_Half_Or_Lessstatic void mdio_write(void *ioaddr, int RegAddr, int value){	int i;	RTL_W32(PHYAR, 0x80000000 | (RegAddr & 0xFF) << 16 | value);	udelay(1000);	for (i = 2000; i > 0; i--) {		// Check if the RTL8169 has completed writing to the specified MII register		if (!(RTL_R32(PHYAR) & 0x80000000)) 			break;		udelay(100);	}}static int mdio_read(void *ioaddr, int RegAddr){	int i, value = -1;	RTL_W32(PHYAR, 0x0 | (RegAddr & 0xFF) << 16);	udelay(1000);	for (i = 2000; i > 0; i--) {		// Check if the RTL8169 has completed retrieving data from the specified MII register		if (RTL_R32(PHYAR) & 0x80000000) {			value = (int) (RTL_R32(PHYAR) & 0xFFFF);			break;		}		udelay(100);	}	return value;}static unsigned int rtl8169_tbi_reset_pending(void *ioaddr){	return RTL_R32(TBICSR) & TBIReset;}static unsigned int rtl8169_xmii_reset_pending(void *ioaddr){	return mdio_read(ioaddr, 0) & 0x8000;}static unsigned int rtl8169_tbi_link_ok(void *ioaddr){	return RTL_R32(TBICSR) & TBILinkOk;}static unsigned int rtl8169_xmii_link_ok(void *ioaddr){	return RTL_R8(PHYstatus) & LinkStatus;}static void rtl8169_tbi_reset_enable(void *ioaddr){	RTL_W32(TBICSR, RTL_R32(TBICSR) | TBIReset);}static void rtl8169_xmii_reset_enable(void *ioaddr){	unsigned int val;	val = (mdio_read(ioaddr, PHY_CTRL_REG) | 0x8000) & 0xffff;	mdio_write(ioaddr, PHY_CTRL_REG, val);}static void rtl8169_check_link_status(struct net_device *dev,				      struct rtl8169_private *tp, void *ioaddr){	unsigned long flags;	spin_lock_irqsave(&tp->lock, flags);	if (tp->link_ok(ioaddr)) {		netif_carrier_on(dev);		printk(KERN_INFO PFX "%s: link up\n", dev->name);	} else		netif_carrier_off(dev);	spin_unlock_irqrestore(&tp->lock, flags);}static void rtl8169_link_option(int idx, u8 *autoneg, u16 *speed, u8 *duplex){	struct {		u16 speed;		u8 duplex;		u8 autoneg;		u8 media;	} link_settings[] = {		{ SPEED_10,	DUPLEX_HALF, AUTONEG_DISABLE,	_10_Half },		{ SPEED_10,	DUPLEX_FULL, AUTONEG_DISABLE,	_10_Full },		{ SPEED_100,	DUPLEX_HALF, AUTONEG_DISABLE,	_100_Half },		{ SPEED_100,	DUPLEX_FULL, AUTONEG_DISABLE,	_100_Full },		{ SPEED_1000,	DUPLEX_FULL, AUTONEG_DISABLE,	_1000_Full },		/* Make TBI happy */		{ SPEED_1000,	DUPLEX_FULL, AUTONEG_ENABLE,	0xff }	}, *p;	unsigned char option;		option = ((idx < MAX_UNITS) && (idx >= 0)) ? media[idx] : 0xff;	if ((option != 0xff) && !idx)		printk(KERN_WARNING PFX "media option is deprecated.\n");	for (p = link_settings; p->media != 0xff; p++) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -