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

📄 forcedeth.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * forcedeth: Ethernet driver for NVIDIA nForce media access controllers. * * Note: This driver is a cleanroom reimplementation based on reverse *      engineered documentation written by Carl-Daniel Hailfinger *      and Andrew de Quincey. It's neither supported nor endorsed *      by NVIDIA Corp. Use at your own risk. * * NVIDIA, nForce and other NVIDIA marks are trademarks or registered * trademarks of NVIDIA Corporation in the United States and other * countries. * * Copyright (C) 2003,4 Manfred Spraul * Copyright (C) 2004 Andrew de Quincey (wol support) * Copyright (C) 2004 Carl-Daniel Hailfinger (invalid MAC handling, insane *		IRQ rate fixes, bigendian fixes, cleanups, verification) * Copyright (c) 2004 NVIDIA Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * * Changelog: * 	0.01: 05 Oct 2003: First release that compiles without warnings. * 	0.02: 05 Oct 2003: Fix bug for nv_drain_tx: do not try to free NULL skbs. * 			   Check all PCI BARs for the register window. * 			   udelay added to mii_rw. * 	0.03: 06 Oct 2003: Initialize dev->irq. * 	0.04: 07 Oct 2003: Initialize np->lock, reduce handled irqs, add printks. * 	0.05: 09 Oct 2003: printk removed again, irq status print tx_timeout. * 	0.06: 10 Oct 2003: MAC Address read updated, pff flag generation updated, * 			   irq mask updated * 	0.07: 14 Oct 2003: Further irq mask updates. * 	0.08: 20 Oct 2003: rx_desc.Length initialization added, nv_alloc_rx refill * 			   added into irq handler, NULL check for drain_ring. * 	0.09: 20 Oct 2003: Basic link speed irq implementation. Only handle the * 			   requested interrupt sources. * 	0.10: 20 Oct 2003: First cleanup for release. * 	0.11: 21 Oct 2003: hexdump for tx added, rx buffer sizes increased. * 			   MAC Address init fix, set_multicast cleanup. * 	0.12: 23 Oct 2003: Cleanups for release. * 	0.13: 25 Oct 2003: Limit for concurrent tx packets increased to 10. * 			   Set link speed correctly. start rx before starting * 			   tx (nv_start_rx sets the link speed). * 	0.14: 25 Oct 2003: Nic dependant irq mask. * 	0.15: 08 Nov 2003: fix smp deadlock with set_multicast_list during * 			   open. * 	0.16: 15 Nov 2003: include file cleanup for ppc64, rx buffer size * 			   increased to 1628 bytes. * 	0.17: 16 Nov 2003: undo rx buffer size increase. Substract 1 from * 			   the tx length. * 	0.18: 17 Nov 2003: fix oops due to late initialization of dev_stats * 	0.19: 29 Nov 2003: Handle RxNoBuf, detect & handle invalid mac * 			   addresses, really stop rx if already running * 			   in nv_start_rx, clean up a bit. * 	0.20: 07 Dec 2003: alloc fixes * 	0.21: 12 Jan 2004: additional alloc fix, nic polling fix. *	0.22: 19 Jan 2004: reprogram timer to a sane rate, avoid lockup *			   on close. *	0.23: 26 Jan 2004: various small cleanups *	0.24: 27 Feb 2004: make driver even less anonymous in backtraces *	0.25: 09 Mar 2004: wol support *	0.26: 03 Jun 2004: netdriver specific annotation, sparse-related fixes *	0.27: 19 Jun 2004: Gigabit support, new descriptor rings, *			   added CK804/MCP04 device IDs, code fixes *			   for registers, link status and other minor fixes. *	0.28: 21 Jun 2004: Big cleanup, making driver mostly endian safe *	0.29: 31 Aug 2004: Add backup timer for link change notification. * * Known bugs: * We suspect that on some hardware no TX done interrupts are generated. * This means recovery from netif_stop_queue only happens if the hw timer * interrupt fires (100 times/second, configurable with NVREG_POLL_DEFAULT) * and the timer is active in the IRQMask, or if a rx packet arrives by chance. * If your hardware reliably generates tx done interrupts, then you can remove * DEV_NEED_TIMERIRQ from the driver_data flags. * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few * superfluous timer interrupts from the nic. */#define FORCEDETH_VERSION		"0.29"#define DRV_NAME			"forcedeth"#include <linux/module.h>#include <linux/types.h>#include <linux/pci.h>#include <linux/interrupt.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/delay.h>#include <linux/spinlock.h>#include <linux/ethtool.h>#include <linux/timer.h>#include <linux/skbuff.h>#include <linux/mii.h>#include <linux/random.h>#include <linux/init.h>#include <asm/irq.h>#include <asm/io.h>#include <asm/uaccess.h>#include <asm/system.h>#if 0#define dprintk			printk#else#define dprintk(x...)		do { } while (0)#endif/* * Hardware access: */#define DEV_NEED_LASTPACKET1	0x0001	/* set LASTPACKET1 in tx flags */#define DEV_IRQMASK_1		0x0002  /* use NVREG_IRQMASK_WANTED_1 for irq mask */#define DEV_IRQMASK_2		0x0004  /* use NVREG_IRQMASK_WANTED_2 for irq mask */#define DEV_NEED_TIMERIRQ	0x0008  /* set the timer irq flag in the irq mask */#define DEV_NEED_LINKTIMER	0x0010	/* poll link settings. Relies on the timer irq */enum {	NvRegIrqStatus = 0x000,#define NVREG_IRQSTAT_MIIEVENT	0x040#define NVREG_IRQSTAT_MASK		0x1ff	NvRegIrqMask = 0x004,#define NVREG_IRQ_RX_ERROR		0x0001#define NVREG_IRQ_RX			0x0002#define NVREG_IRQ_RX_NOBUF		0x0004#define NVREG_IRQ_TX_ERR		0x0008#define NVREG_IRQ_TX2			0x0010#define NVREG_IRQ_TIMER			0x0020#define NVREG_IRQ_LINK			0x0040#define NVREG_IRQ_TX1			0x0100#define NVREG_IRQMASK_WANTED_1		0x005f#define NVREG_IRQMASK_WANTED_2		0x0147#define NVREG_IRQ_UNKNOWN		(~(NVREG_IRQ_RX_ERROR|NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF|NVREG_IRQ_TX_ERR|NVREG_IRQ_TX2|NVREG_IRQ_TIMER|NVREG_IRQ_LINK|NVREG_IRQ_TX1))	NvRegUnknownSetupReg6 = 0x008,#define NVREG_UNKSETUP6_VAL		3/* * NVREG_POLL_DEFAULT is the interval length of the timer source on the nic * NVREG_POLL_DEFAULT=97 would result in an interval length of 1 ms */	NvRegPollingInterval = 0x00c,#define NVREG_POLL_DEFAULT	970	NvRegMisc1 = 0x080,#define NVREG_MISC1_HD		0x02#define NVREG_MISC1_FORCE	0x3b0f3c	NvRegTransmitterControl = 0x084,#define NVREG_XMITCTL_START	0x01	NvRegTransmitterStatus = 0x088,#define NVREG_XMITSTAT_BUSY	0x01	NvRegPacketFilterFlags = 0x8c,#define NVREG_PFF_ALWAYS	0x7F0008#define NVREG_PFF_PROMISC	0x80#define NVREG_PFF_MYADDR	0x20	NvRegOffloadConfig = 0x90,#define NVREG_OFFLOAD_HOMEPHY	0x601#define NVREG_OFFLOAD_NORMAL	RX_NIC_BUFSIZE	NvRegReceiverControl = 0x094,#define NVREG_RCVCTL_START	0x01	NvRegReceiverStatus = 0x98,#define NVREG_RCVSTAT_BUSY	0x01	NvRegRandomSeed = 0x9c,#define NVREG_RNDSEED_MASK	0x00ff#define NVREG_RNDSEED_FORCE	0x7f00#define NVREG_RNDSEED_FORCE2	0x2d00#define NVREG_RNDSEED_FORCE3	0x7400	NvRegUnknownSetupReg1 = 0xA0,#define NVREG_UNKSETUP1_VAL	0x16070f	NvRegUnknownSetupReg2 = 0xA4,#define NVREG_UNKSETUP2_VAL	0x16	NvRegMacAddrA = 0xA8,	NvRegMacAddrB = 0xAC,	NvRegMulticastAddrA = 0xB0,#define NVREG_MCASTADDRA_FORCE	0x01	NvRegMulticastAddrB = 0xB4,	NvRegMulticastMaskA = 0xB8,	NvRegMulticastMaskB = 0xBC,	NvRegPhyInterface = 0xC0,#define PHY_RGMII		0x10000000	NvRegTxRingPhysAddr = 0x100,	NvRegRxRingPhysAddr = 0x104,	NvRegRingSizes = 0x108,#define NVREG_RINGSZ_TXSHIFT 0#define NVREG_RINGSZ_RXSHIFT 16	NvRegUnknownTransmitterReg = 0x10c,	NvRegLinkSpeed = 0x110,#define NVREG_LINKSPEED_FORCE 0x10000#define NVREG_LINKSPEED_10	1000#define NVREG_LINKSPEED_100	100#define NVREG_LINKSPEED_1000	50	NvRegUnknownSetupReg5 = 0x130,#define NVREG_UNKSETUP5_BIT31	(1<<31)	NvRegUnknownSetupReg3 = 0x13c,#define NVREG_UNKSETUP3_VAL1	0x200010	NvRegTxRxControl = 0x144,#define NVREG_TXRXCTL_KICK	0x0001#define NVREG_TXRXCTL_BIT1	0x0002#define NVREG_TXRXCTL_BIT2	0x0004#define NVREG_TXRXCTL_IDLE	0x0008#define NVREG_TXRXCTL_RESET	0x0010	NvRegMIIStatus = 0x180,#define NVREG_MIISTAT_ERROR		0x0001#define NVREG_MIISTAT_LINKCHANGE	0x0008#define NVREG_MIISTAT_MASK		0x000f#define NVREG_MIISTAT_MASK2		0x000f	NvRegUnknownSetupReg4 = 0x184,#define NVREG_UNKSETUP4_VAL	8	NvRegAdapterControl = 0x188,#define NVREG_ADAPTCTL_START	0x02#define NVREG_ADAPTCTL_LINKUP	0x04#define NVREG_ADAPTCTL_PHYVALID	0x40000#define NVREG_ADAPTCTL_RUNNING	0x100000#define NVREG_ADAPTCTL_PHYSHIFT	24	NvRegMIISpeed = 0x18c,#define NVREG_MIISPEED_BIT8	(1<<8)#define NVREG_MIIDELAY	5	NvRegMIIControl = 0x190,#define NVREG_MIICTL_INUSE	0x08000#define NVREG_MIICTL_WRITE	0x00400#define NVREG_MIICTL_ADDRSHIFT	5	NvRegMIIData = 0x194,	NvRegWakeUpFlags = 0x200,#define NVREG_WAKEUPFLAGS_VAL		0x7770#define NVREG_WAKEUPFLAGS_BUSYSHIFT	24#define NVREG_WAKEUPFLAGS_ENABLESHIFT	16#define NVREG_WAKEUPFLAGS_D3SHIFT	12#define NVREG_WAKEUPFLAGS_D2SHIFT	8#define NVREG_WAKEUPFLAGS_D1SHIFT	4#define NVREG_WAKEUPFLAGS_D0SHIFT	0#define NVREG_WAKEUPFLAGS_ACCEPT_MAGPAT		0x01#define NVREG_WAKEUPFLAGS_ACCEPT_WAKEUPPAT	0x02#define NVREG_WAKEUPFLAGS_ACCEPT_LINKCHANGE	0x04#define NVREG_WAKEUPFLAGS_ENABLE	0x1111	NvRegPatternCRC = 0x204,	NvRegPatternMask = 0x208,	NvRegPowerCap = 0x268,#define NVREG_POWERCAP_D3SUPP	(1<<30)#define NVREG_POWERCAP_D2SUPP	(1<<26)#define NVREG_POWERCAP_D1SUPP	(1<<25)	NvRegPowerState = 0x26c,#define NVREG_POWERSTATE_POWEREDUP	0x8000#define NVREG_POWERSTATE_VALID		0x0100#define NVREG_POWERSTATE_MASK		0x0003#define NVREG_POWERSTATE_D0		0x0000#define NVREG_POWERSTATE_D1		0x0001#define NVREG_POWERSTATE_D2		0x0002#define NVREG_POWERSTATE_D3		0x0003};/* Big endian: should work, but is untested */struct ring_desc {	u32 PacketBuffer;	u32 FlagLen;};#define FLAG_MASK_V1 0xffff0000#define FLAG_MASK_V2 0xffffc000#define LEN_MASK_V1 (0xffffffff ^ FLAG_MASK_V1)#define LEN_MASK_V2 (0xffffffff ^ FLAG_MASK_V2)#define NV_TX_LASTPACKET	(1<<16)#define NV_TX_RETRYERROR	(1<<19)#define NV_TX_LASTPACKET1	(1<<24)#define NV_TX_DEFERRED		(1<<26)#define NV_TX_CARRIERLOST	(1<<27)#define NV_TX_LATECOLLISION	(1<<28)#define NV_TX_UNDERFLOW		(1<<29)#define NV_TX_ERROR		(1<<30)#define NV_TX_VALID		(1<<31)#define NV_TX2_LASTPACKET	(1<<29)#define NV_TX2_RETRYERROR	(1<<18)#define NV_TX2_LASTPACKET1	(1<<23)#define NV_TX2_DEFERRED		(1<<25)#define NV_TX2_CARRIERLOST	(1<<26)#define NV_TX2_LATECOLLISION	(1<<27)#define NV_TX2_UNDERFLOW	(1<<28)/* error and valid are the same for both */#define NV_TX2_ERROR		(1<<30)#define NV_TX2_VALID		(1<<31)#define NV_RX_DESCRIPTORVALID	(1<<16)#define NV_RX_MISSEDFRAME	(1<<17)#define NV_RX_SUBSTRACT1	(1<<18)#define NV_RX_ERROR1		(1<<23)#define NV_RX_ERROR2		(1<<24)#define NV_RX_ERROR3		(1<<25)#define NV_RX_ERROR4		(1<<26)#define NV_RX_CRCERR		(1<<27)#define NV_RX_OVERFLOW		(1<<28)#define NV_RX_FRAMINGERR	(1<<29)#define NV_RX_ERROR		(1<<30)#define NV_RX_AVAIL		(1<<31)#define NV_RX2_DESCRIPTORVALID	(1<<29)#define NV_RX2_SUBSTRACT1	(1<<25)#define NV_RX2_ERROR1		(1<<18)#define NV_RX2_ERROR2		(1<<19)#define NV_RX2_ERROR3		(1<<20)#define NV_RX2_ERROR4		(1<<21)#define NV_RX2_CRCERR		(1<<22)#define NV_RX2_OVERFLOW		(1<<23)#define NV_RX2_FRAMINGERR	(1<<24)/* error and avail are the same for both */#define NV_RX2_ERROR		(1<<30)#define NV_RX2_AVAIL		(1<<31)/* Miscelaneous hardware related defines: */#define NV_PCI_REGSZ		0x270/* various timeout delays: all in usec */#define NV_TXRX_RESET_DELAY	4#define NV_TXSTOP_DELAY1	10#define NV_TXSTOP_DELAY1MAX	500000#define NV_TXSTOP_DELAY2	100#define NV_RXSTOP_DELAY1	10#define NV_RXSTOP_DELAY1MAX	500000#define NV_RXSTOP_DELAY2	100#define NV_SETUP5_DELAY		5#define NV_SETUP5_DELAYMAX	50000#define NV_POWERUP_DELAY	5#define NV_POWERUP_DELAYMAX	5000#define NV_MIIBUSY_DELAY	50#define NV_MIIPHY_DELAY	10#define NV_MIIPHY_DELAYMAX	10000#define NV_WAKEUPPATTERNS	5#define NV_WAKEUPMASKENTRIES	4/* General driver defaults */#define NV_WATCHDOG_TIMEO	(5*HZ)#define RX_RING		128#define TX_RING		64/*  * If your nic mysteriously hangs then try to reduce the limits * to 1/0: It might be required to set NV_TX_LASTPACKET in the * last valid ring entry. But this would be impossible to * implement - probably a disassembly error. */#define TX_LIMIT_STOP	63#define TX_LIMIT_START	62/* rx/tx mac addr + type + vlan + align + slack*/#define RX_NIC_BUFSIZE		(ETH_DATA_LEN + 64)/* even more slack */#define RX_ALLOC_BUFSIZE	(ETH_DATA_LEN + 128)#define OOM_REFILL	(1+HZ/20)#define POLL_WAIT	(1+HZ/100)#define LINK_TIMEOUT	(3*HZ)#define DESC_VER_1	0x0#define DESC_VER_2	0x02100/* PHY defines */#define PHY_OUI_MARVELL	0x5043#define PHY_OUI_CICADA	0x03f1#define PHYID1_OUI_MASK	0x03ff#define PHYID1_OUI_SHFT	6#define PHYID2_OUI_MASK	0xfc00#define PHYID2_OUI_SHFT	10#define PHY_INIT1	0x0f000#define PHY_INIT2	0x0e00#define PHY_INIT3	0x01000#define PHY_INIT4	0x0200#define PHY_INIT5	0x0004#define PHY_INIT6	0x02000#define PHY_GIGABIT	0x0100#define PHY_TIMEOUT	0x1#define PHY_ERROR	0x2#define PHY_100	0x1#define PHY_1000	0x2#define PHY_HALF	0x100/* FIXME: MII defines that should be added to <linux/mii.h> */#define MII_1000BT_CR	0x09#define MII_1000BT_SR	0x0a#define ADVERTISE_1000FULL	0x0200#define ADVERTISE_1000HALF	0x0100#define LPA_1000FULL	0x0800#define LPA_1000HALF	0x0400/* * SMP locking: * All hardware access under dev->priv->lock, except the performance * critical parts: * - rx is (pseudo-) lockless: it relies on the single-threading provided *	by the arch code for interrupts. * - tx setup is lockless: it relies on dev->xmit_lock. Actual submission *	needs dev->priv->lock :-( * - set_multicast_list: preparation lockless, relies on dev->xmit_lock. *//* in dev: base, irq */struct fe_priv {	spinlock_t lock;	/* General data:	 * Locking: spin_lock(&np->lock); */	struct net_device_stats stats;	int in_shutdown;	u32 linkspeed;	int duplex;	int phyaddr;	int wolenabled;	unsigned int phy_oui;	u16 gigabit;	/* General data: RO fields */	dma_addr_t ring_addr;	struct pci_dev *pci_dev;	u32 orig_mac[2];	u32 irqmask;	u32 desc_ver;	/* rx specific fields.	 * Locking: Within irq hander or disable_irq+spin_lock(&np->lock);	 */	struct ring_desc *rx_ring;	unsigned int cur_rx, refill_rx;	struct sk_buff *rx_skbuff[RX_RING];	dma_addr_t rx_dma[RX_RING];	unsigned int rx_buf_sz;	struct timer_list oom_kick;	struct timer_list nic_poll;	/* media detection workaround.	 * Locking: Within irq hander or disable_irq+spin_lock(&np->lock);	 */	int need_linktimer;	unsigned long link_timeout;	/*	 * tx specific fields.	 */	struct ring_desc *tx_ring;	unsigned int next_tx, nic_tx;	struct sk_buff *tx_skbuff[TX_RING];	dma_addr_t tx_dma[TX_RING];	u32 tx_flags;};/* * Maximum number of loops until we assume that a bit in the irq mask * is stuck. Overridable with module param. */static int max_interrupt_work = 5;static inline struct fe_priv *get_nvpriv(struct net_device *dev){	return (struct fe_priv *) dev->priv;}static inline u8 *get_hwbase(struct net_device *dev){	return (u8 *) dev->base_addr;}static inline void pci_push(u8 * base){	/* force out pending posted writes */	readl(base);}static inline u32 nv_descr_getlength(struct ring_desc *prd, u32 v){	return le32_to_cpu(prd->FlagLen)		& ((v == DESC_VER_1) ? LEN_MASK_V1 : LEN_MASK_V2);}static int reg_delay(struct net_device *dev, int offset, u32 mask, u32 target,				int delay, int delaymax, const char *msg){	u8 *base = get_hwbase(dev);	pci_push(base);	do {		udelay(delay);		delaymax -= delay;		if (delaymax < 0) {			if (msg)				printk(msg);			return 1;		}	} while ((readl(base + offset) & mask) != target);	return 0;}

⌨️ 快捷键说明

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