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

📄 ns83820.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 4 页
字号:
#define _VERSION "0.20"/* ns83820.c by Benjamin LaHaise with contributions. * * Questions/comments/discussion to linux-ns83820@kvack.org. * * $Revision: 1.34.2.23 $ * * Copyright 2001 Benjamin LaHaise. * Copyright 2001, 2002 Red Hat. * * Mmmm, chocolate vanilla mocha... * * * 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 * ========= *	20010414	0.1 - created *	20010622	0.2 - basic rx and tx. *	20010711	0.3 - added duplex and link state detection support. *	20010713	0.4 - zero copy, no hangs. *			0.5 - 64 bit dma support (davem will hate me for this) *			    - disable jumbo frames to avoid tx hangs *			    - work around tx deadlocks on my 1.02 card via *			      fiddling with TXCFG *	20010810	0.6 - use pci dma api for ringbuffers, work on ia64 *	20010816	0.7 - misc cleanups *	20010826	0.8 - fix critical zero copy bugs *			0.9 - internal experiment *	20010827	0.10 - fix ia64 unaligned access. *	20010906	0.11 - accept all packets with checksum errors as *			       otherwise fragments get lost *			     - fix >> 32 bugs *			0.12 - add statistics counters *			     - add allmulti/promisc support *	20011009	0.13 - hotplug support, other smaller pci api cleanups *	20011204	0.13a - optical transceiver support added *				by Michael Clark <michael@metaparadigm.com> *	20011205	0.13b - call register_netdev earlier in initialization *				suppress duplicate link status messages *	20011117 	0.14 - ethtool GDRVINFO, GLINK support from jgarzik *	20011204 	0.15	get ppc (big endian) working *	20011218	0.16	various cleanups *	20020310	0.17	speedups *	20020610	0.18 -	actually use the pci dma api for highmem *			     -	remove pci latency register fiddling *			0.19 -	better bist support *			     -	add ihr and reset_phy parameters *			     -	gmii bus probing *			     -	fix missed txok introduced during performance *				tuning *			0.20 -	fix stupid RFEN thinko.  i am such a smurf. * * Driver Overview * =============== * * This driver was originally written for the National Semiconductor * 83820 chip, a 10/100/1000 Mbps 64 bit PCI ethernet NIC.  Hopefully * this code will turn out to be a) clean, b) correct, and c) fast. * With that in mind, I'm aiming to split the code up as much as * reasonably possible.  At present there are X major sections that * break down into a) packet receive, b) packet transmit, c) link * management, d) initialization and configuration.  Where possible, * these code paths are designed to run in parallel. * * This driver has been tested and found to work with the following * cards (in no particular order): * *	Cameo		SOHO-GA2000T	SOHO-GA2500T *	D-Link		DGE-500T *	PureData	PDP8023Z-TG *	SMC		SMC9452TX	SMC9462TX *	Netgear		GA621 * * Special thanks to SMC for providing hardware to test this driver on. * * Reports of success or failure would be greatly appreciated. *///#define dprintk		printk#define dprintk(x...)		do { } while (0)#include <linux/module.h>#include <linux/types.h>#include <linux/pci.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/delay.h>#include <linux/smp_lock.h>#include <linux/workqueue.h>#include <linux/init.h>#include <linux/ip.h>	/* for iph */#include <linux/in.h>	/* for IPPROTO_... */#include <linux/eeprom.h>#include <linux/compiler.h>#include <linux/prefetch.h>#include <linux/ethtool.h>#include <linux/timer.h>#include <asm/io.h>#include <asm/uaccess.h>#include <asm/system.h>#define DRV_NAME "ns83820"/* Global parameters.  See MODULE_PARM near the bottom. */static int ihr = 2;static int reset_phy = 0;static int lnksts = 0;		/* CFG_LNKSTS bit polarity *//* Dprintk is used for more interesting debug events */#undef Dprintk#define	Dprintk			dprintk#if defined(CONFIG_HIGHMEM64G) || defined(__ia64__)#define USE_64BIT_ADDR	"+"#endif#if defined(USE_64BIT_ADDR)#define	VERSION	_VERSION USE_64BIT_ADDR#define TRY_DAC	1#else#define	VERSION	_VERSION#define TRY_DAC	0#endif/* tunables */#define RX_BUF_SIZE	1500	/* 8192 *//* Must not exceed ~65000. */#define NR_RX_DESC	64#define NR_TX_DESC	128/* not tunable */#define REAL_RX_BUF_SIZE (RX_BUF_SIZE + 14)	/* rx/tx mac addr + type */#define MIN_TX_DESC_FREE	8/* register defines */#define CFGCS		0x04#define CR_TXE		0x00000001#define CR_TXD		0x00000002/* Ramit : Here's a tip, don't do a RXD immediately followed by an RXE * The Receive engine skips one descriptor and moves * onto the next one!! */#define CR_RXE		0x00000004#define CR_RXD		0x00000008#define CR_TXR		0x00000010#define CR_RXR		0x00000020#define CR_SWI		0x00000080#define CR_RST		0x00000100#define PTSCR_EEBIST_FAIL       0x00000001#define PTSCR_EEBIST_EN         0x00000002#define PTSCR_EELOAD_EN         0x00000004#define PTSCR_RBIST_FAIL        0x000001b8#define PTSCR_RBIST_DONE        0x00000200#define PTSCR_RBIST_EN          0x00000400#define PTSCR_RBIST_RST         0x00002000#define MEAR_EEDI		0x00000001#define MEAR_EEDO		0x00000002#define MEAR_EECLK		0x00000004#define MEAR_EESEL		0x00000008#define MEAR_MDIO		0x00000010#define MEAR_MDDIR		0x00000020#define MEAR_MDC		0x00000040#define ISR_TXDESC3	0x40000000#define ISR_TXDESC2	0x20000000#define ISR_TXDESC1	0x10000000#define ISR_TXDESC0	0x08000000#define ISR_RXDESC3	0x04000000#define ISR_RXDESC2	0x02000000#define ISR_RXDESC1	0x01000000#define ISR_RXDESC0	0x00800000#define ISR_TXRCMP	0x00400000#define ISR_RXRCMP	0x00200000#define ISR_DPERR	0x00100000#define ISR_SSERR	0x00080000#define ISR_RMABT	0x00040000#define ISR_RTABT	0x00020000#define ISR_RXSOVR	0x00010000#define ISR_HIBINT	0x00008000#define ISR_PHY		0x00004000#define ISR_PME		0x00002000#define ISR_SWI		0x00001000#define ISR_MIB		0x00000800#define ISR_TXURN	0x00000400#define ISR_TXIDLE	0x00000200#define ISR_TXERR	0x00000100#define ISR_TXDESC	0x00000080#define ISR_TXOK	0x00000040#define ISR_RXORN	0x00000020#define ISR_RXIDLE	0x00000010#define ISR_RXEARLY	0x00000008#define ISR_RXERR	0x00000004#define ISR_RXDESC	0x00000002#define ISR_RXOK	0x00000001#define TXCFG_CSI	0x80000000#define TXCFG_HBI	0x40000000#define TXCFG_MLB	0x20000000#define TXCFG_ATP	0x10000000#define TXCFG_ECRETRY	0x00800000#define TXCFG_BRST_DIS	0x00080000#define TXCFG_MXDMA1024	0x00000000#define TXCFG_MXDMA512	0x00700000#define TXCFG_MXDMA256	0x00600000#define TXCFG_MXDMA128	0x00500000#define TXCFG_MXDMA64	0x00400000#define TXCFG_MXDMA32	0x00300000#define TXCFG_MXDMA16	0x00200000#define TXCFG_MXDMA8	0x00100000#define CFG_LNKSTS	0x80000000#define CFG_SPDSTS	0x60000000#define CFG_SPDSTS1	0x40000000#define CFG_SPDSTS0	0x20000000#define CFG_DUPSTS	0x10000000#define CFG_TBI_EN	0x01000000#define CFG_MODE_1000	0x00400000/* Ramit : Dont' ever use AUTO_1000, it never works and is buggy. * Read the Phy response and then configure the MAC accordingly */#define CFG_AUTO_1000	0x00200000#define CFG_PINT_CTL	0x001c0000#define CFG_PINT_DUPSTS	0x00100000#define CFG_PINT_LNKSTS	0x00080000#define CFG_PINT_SPDSTS	0x00040000#define CFG_TMRTEST	0x00020000#define CFG_MRM_DIS	0x00010000#define CFG_MWI_DIS	0x00008000#define CFG_T64ADDR	0x00004000#define CFG_PCI64_DET	0x00002000#define CFG_DATA64_EN	0x00001000#define CFG_M64ADDR	0x00000800#define CFG_PHY_RST	0x00000400#define CFG_PHY_DIS	0x00000200#define CFG_EXTSTS_EN	0x00000100#define CFG_REQALG	0x00000080#define CFG_SB		0x00000040#define CFG_POW		0x00000020#define CFG_EXD		0x00000010#define CFG_PESEL	0x00000008#define CFG_BROM_DIS	0x00000004#define CFG_EXT_125	0x00000002#define CFG_BEM		0x00000001#define EXTSTS_UDPPKT	0x00200000#define EXTSTS_TCPPKT	0x00080000#define EXTSTS_IPPKT	0x00020000#define SPDSTS_POLARITY	(CFG_SPDSTS1 | CFG_SPDSTS0 | CFG_DUPSTS | (lnksts ? CFG_LNKSTS : 0))#define MIBC_MIBS	0x00000008#define MIBC_ACLR	0x00000004#define MIBC_FRZ	0x00000002#define MIBC_WRN	0x00000001#define PCR_PSEN	(1 << 31)#define PCR_PS_MCAST	(1 << 30)#define PCR_PS_DA	(1 << 29)#define PCR_STHI_8	(3 << 23)#define PCR_STLO_4	(1 << 23)#define PCR_FFHI_8K	(3 << 21)#define PCR_FFLO_4K	(1 << 21)#define PCR_PAUSE_CNT	0xFFFE#define RXCFG_AEP	0x80000000#define RXCFG_ARP	0x40000000#define RXCFG_STRIPCRC	0x20000000#define RXCFG_RX_FD	0x10000000#define RXCFG_ALP	0x08000000#define RXCFG_AIRL	0x04000000#define RXCFG_MXDMA512	0x00700000#define RXCFG_DRTH	0x0000003e#define RXCFG_DRTH0	0x00000002#define RFCR_RFEN	0x80000000#define RFCR_AAB	0x40000000#define RFCR_AAM	0x20000000#define RFCR_AAU	0x10000000#define RFCR_APM	0x08000000#define RFCR_APAT	0x07800000#define RFCR_APAT3	0x04000000#define RFCR_APAT2	0x02000000#define RFCR_APAT1	0x01000000#define RFCR_APAT0	0x00800000#define RFCR_AARP	0x00400000#define RFCR_MHEN	0x00200000#define RFCR_UHEN	0x00100000#define RFCR_ULM	0x00080000#define VRCR_RUDPE	0x00000080#define VRCR_RTCPE	0x00000040#define VRCR_RIPE	0x00000020#define VRCR_IPEN	0x00000010#define VRCR_DUTF	0x00000008#define VRCR_DVTF	0x00000004#define VRCR_VTREN	0x00000002#define VRCR_VTDEN	0x00000001#define VTCR_PPCHK	0x00000008#define VTCR_GCHK	0x00000004#define VTCR_VPPTI	0x00000002#define VTCR_VGTI	0x00000001#define CR		0x00#define CFG		0x04#define MEAR		0x08#define PTSCR		0x0c#define	ISR		0x10#define	IMR		0x14#define	IER		0x18#define	IHR		0x1c#define TXDP		0x20#define TXDP_HI		0x24#define TXCFG		0x28#define GPIOR		0x2c#define RXDP		0x30#define RXDP_HI		0x34#define RXCFG		0x38#define PQCR		0x3c#define WCSR		0x40#define PCR		0x44#define RFCR		0x48#define RFDR		0x4c#define SRR		0x58#define VRCR		0xbc#define VTCR		0xc0#define VDR		0xc4#define CCSR		0xcc#define TBICR		0xe0#define TBISR		0xe4#define TANAR		0xe8#define TANLPAR		0xec#define TANER		0xf0#define TESR		0xf4#define TBICR_MR_AN_ENABLE	0x00001000#define TBICR_MR_RESTART_AN	0x00000200#define TBISR_MR_LINK_STATUS	0x00000020#define TBISR_MR_AN_COMPLETE	0x00000004#define TANAR_PS2 		0x00000100#define TANAR_PS1 		0x00000080#define TANAR_HALF_DUP 		0x00000040#define TANAR_FULL_DUP 		0x00000020#define GPIOR_GP5_OE		0x00000200#define GPIOR_GP4_OE		0x00000100#define GPIOR_GP3_OE		0x00000080#define GPIOR_GP2_OE		0x00000040#define GPIOR_GP1_OE		0x00000020#define GPIOR_GP3_OUT		0x00000004#define GPIOR_GP1_OUT		0x00000001#define LINK_AUTONEGOTIATE	0x01#define LINK_DOWN		0x02#define LINK_UP			0x04#ifdef USE_64BIT_ADDR#define HW_ADDR_LEN	8#define desc_addr_set(desc, addr)				\	do {							\		u64 __addr = (addr);				\		(desc)[0] = cpu_to_le32(__addr);		\		(desc)[1] = cpu_to_le32(__addr >> 32);		\	} while(0)#define desc_addr_get(desc)					\		(((u64)le32_to_cpu((desc)[1]) << 32)		\		     | le32_to_cpu((desc)[0]))#else#define HW_ADDR_LEN	4#define desc_addr_set(desc, addr)	((desc)[0] = cpu_to_le32(addr))#define desc_addr_get(desc)		(le32_to_cpu((desc)[0]))#endif#define DESC_LINK		0#define DESC_BUFPTR		(DESC_LINK + HW_ADDR_LEN/4)#define DESC_CMDSTS		(DESC_BUFPTR + HW_ADDR_LEN/4)#define DESC_EXTSTS		(DESC_CMDSTS + 4/4)#define CMDSTS_OWN	0x80000000#define CMDSTS_MORE	0x40000000#define CMDSTS_INTR	0x20000000#define CMDSTS_ERR	0x10000000#define CMDSTS_OK	0x08000000#define CMDSTS_LEN_MASK	0x0000ffff#define CMDSTS_DEST_MASK	0x01800000#define CMDSTS_DEST_SELF	0x00800000#define CMDSTS_DEST_MULTI	0x01000000#define DESC_SIZE	8		/* Should be cache line sized */struct rx_info {	spinlock_t	lock;	int		up;	long		idle;	struct sk_buff	*skbs[NR_RX_DESC];	u32		*next_rx_desc;	u16		next_rx, next_empty;	u32		*descs;	dma_addr_t	phy_descs;};struct ns83820 {	struct net_device_stats	stats;	u8			*base;	struct pci_dev		*pci_dev;	struct rx_info		rx_info;	struct tasklet_struct	rx_tasklet;	unsigned		ihr;	struct work_struct	tq_refill;	/* protects everything below.  irqsave when using. */	spinlock_t		misc_lock;	u32			CFG_cache;	u32			MEAR_cache;	u32			IMR_cache;	struct eeprom		ee;	unsigned		linkstate;	spinlock_t	tx_lock;	u16		tx_done_idx;	u16		tx_idx;	volatile u16	tx_free_idx;	/* idx of free desc chain */	u16		tx_intr_idx;	atomic_t	nr_tx_skbs;	struct sk_buff	*tx_skbs[NR_TX_DESC];	char		pad[16] __attribute__((aligned(16)));	u32		*tx_descs;	dma_addr_t	tx_phy_descs;	struct timer_list	tx_watchdog;};static inline struct ns83820 *PRIV(struct net_device *dev){	return netdev_priv(dev);}#define __kick_rx(dev)	writel(CR_RXE, dev->base + CR)static inline void kick_rx(struct net_device *ndev){	struct ns83820 *dev = PRIV(ndev);	dprintk("kick_rx: maybe kicking\n");	if (test_and_clear_bit(0, &dev->rx_info.idle)) {		dprintk("actually kicking\n");		writel(dev->rx_info.phy_descs +			(4 * DESC_SIZE * dev->rx_info.next_rx),		       dev->base + RXDP);		if (dev->rx_info.next_rx == dev->rx_info.next_empty)			printk(KERN_DEBUG "%s: uh-oh: next_rx == next_empty???\n",				ndev->name);		__kick_rx(dev);	}}//free = (tx_done_idx + NR_TX_DESC-2 - free_idx) % NR_TX_DESC#define start_tx_okay(dev)	\	(((NR_TX_DESC-2 + dev->tx_done_idx - dev->tx_free_idx) % NR_TX_DESC) > MIN_TX_DESC_FREE)/* Packet Receiver * * The hardware supports linked lists of receive descriptors for * which ownership is transfered back and forth by means of an * ownership bit.  While the hardware does support the use of a * ring for receive descriptors, we only make use of a chain in * an attempt to reduce bus traffic under heavy load scenarios. * This will also make bugs a bit more obvious.  The current code * only makes use of a single rx chain; I hope to implement * priority based rx for version 1.0.  Goal: even under overload * conditions, still route realtime traffic with as low jitter as * possible. */static inline void build_rx_desc(struct ns83820 *dev, u32 *desc, dma_addr_t link, dma_addr_t buf, u32 cmdsts, u32 extsts){	desc_addr_set(desc + DESC_LINK, link);	desc_addr_set(desc + DESC_BUFPTR, buf);	desc[DESC_EXTSTS] = cpu_to_le32(extsts);	mb();	desc[DESC_CMDSTS] = cpu_to_le32(cmdsts);}#define nr_rx_empty(dev) ((NR_RX_DESC-2 + dev->rx_info.next_rx - dev->rx_info.next_empty) % NR_RX_DESC)static inline int ns83820_add_rx_skb(struct ns83820 *dev, struct sk_buff *skb){	unsigned next_empty;	u32 cmdsts;	u32 *sg;	dma_addr_t buf;	next_empty = dev->rx_info.next_empty;	/* don't overrun last rx marker */	if (unlikely(nr_rx_empty(dev) <= 2)) {		kfree_skb(skb);		return 1;	}#if 0	dprintk("next_empty[%d] nr_used[%d] next_rx[%d]\n",		dev->rx_info.next_empty,		dev->rx_info.nr_used,		dev->rx_info.next_rx

⌨️ 快捷键说明

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