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

📄 ns83820.c

📁 linux下从网卡远程启动
💻 C
📖 第 1 页 / 共 2 页
字号:
/***************************************************************************    ns83820.c: Etherboot device driver for the National Semiconductor 83820*    Written 2004 by Timothy Legge <tlegge@rogers.com>**    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., 675 Mass Ave, Cambridge, MA 02139, USA.**    Portions of this code based on:*	ns83820.c by Benjamin LaHaise with contributions* 		for Linux kernel 2.4.x.*	*    Linux Driver Version 0.20, 20020610* *  *    	*    REVISION HISTORY:*    ================**    v1.0	02-16-2004	timlegge	Initial port of Linux driver*    v1.1	02-19-2004	timlegge	More rohbust transmit and poll*    *    Indent Options: indent -kr -i8***************************************************************************//* to get some global routines like printf */#include "etherboot.h"/* to get the interface to the body of the program */#include "nic.h"/* to get the PCI support functions, if this is a PCI NIC */#include "pci.h"#if ARCH == ia64		/* Support 64-bit addressing */#define USE_64BIT_ADDR#endif//#define DDEBUG#ifdef DDEBUG#define dprintf(x) printf x#else#define dprintf(x)#endiftypedef unsigned char u8;typedef signed char s8;typedef unsigned short u16;typedef signed short s16;typedef unsigned int u32;typedef signed int s32;#define HZ 100/* Condensed operations for readability. */#define virt_to_le32desc(addr)  cpu_to_le32(virt_to_bus(addr))#define le32desc_to_virt(addr)  bus_to_virt(le32_to_cpu(addr))/* NIC specific static variables go here *//* 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 */#if defined(CONFIG_HIGHMEM64G) || defined(__ia64__)#define USE_64BIT_ADDR	"+"#endif#if defined(USE_64BIT_ADDR)#define TRY_DAC	1#else#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	1		   /* not tunable *//* Extra 6 bytes for 64 bit alignment (divisable by 8) */#define REAL_RX_BUF_SIZE (RX_BUF_SIZE + 14 + 6)	/* 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#define __kick_rx()	writel(CR_RXE, ns->base + CR)#define kick_rx() do { \	dprintf(("kick_rx: maybe kicking\n")); \		writel(virt_to_le32desc(&rx_ring[ns->cur_rx]), ns->base + RXDP); \		if (ns->next_rx == ns->next_empty) \			dprintf(("uh-oh: next_rx == next_empty???\n"));\		__kick_rx(); \} while(0)#ifdef USE_64BIT_ADDR#define HW_ADDR_LEN	8#else#define HW_ADDR_LEN	4#endif#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 */#ifdef USE_64BIT_ADDRstruct ring_desc {	uint64_t link;	uint64_t bufptr;	u32 cmdsts;	u32 extsts;		/* Extended status field */};#elsestruct ring_desc {	u32 link;	u32 bufptr;	u32 cmdsts;	u32 extsts;		/* Extended status field */};#endif/* Define the TX Descriptor */static struct ring_desc tx_ring[NR_TX_DESC]    __attribute__ ((aligned(8)));/* Create a static buffer of size REAL_RX_BUF_SIZE for eachTX Descriptor.  All descriptors point to apart of this buffer */static unsigned char txb[NR_TX_DESC * REAL_RX_BUF_SIZE];/* Define the TX Descriptor */static struct ring_desc rx_ring[NR_RX_DESC]    __attribute__ ((aligned(8)));/* Create a static buffer of size REAL_RX_BUF_SIZE for eachRX Descriptor   All descriptors point to apart of this buffer */static unsigned char rxb[NR_RX_DESC * REAL_RX_BUF_SIZE]    __attribute__ ((aligned(8)));/* Private Storage for the NIC */struct ns83820_private {	u8 *base;	int up;	long idle;	u32 *next_rx_desc;	u16 next_rx, next_empty;	u32 cur_rx;	u32 *descs;	unsigned ihr;	u32 CFG_cache;	u32 MEAR_cache;	u32 IMR_cache;	int linkstate;	u16 tx_done_idx;	u16 tx_idx;	u16 tx_intr_idx;	u32 phy_descs;	u32 *tx_descs;} nsx;static struct ns83820_private *ns;static void phy_intr(struct nic *nic __unused){	static char *speeds[] =	    { "10", "100", "1000", "1000(?)", "1000F" };	u32 cfg, new_cfg;	u32 tbisr, tanar, tanlpar;	int speed, fullduplex, newlinkstate;	cfg = readl(ns->base + CFG) ^ SPDSTS_POLARITY;	if (ns->CFG_cache & CFG_TBI_EN) {		/* we have an optical transceiver */		tbisr = readl(ns->base + TBISR);		tanar = readl(ns->base + TANAR);		tanlpar = readl(ns->base + TANLPAR);		dprintf(("phy_intr: tbisr=%hX, tanar=%hX, tanlpar=%hX\n",			 tbisr, tanar, tanlpar));		if ((fullduplex = (tanlpar & TANAR_FULL_DUP)		     && (tanar & TANAR_FULL_DUP))) {			/* both of us are full duplex */			writel(readl(ns->base + TXCFG)			       | TXCFG_CSI | TXCFG_HBI | TXCFG_ATP,			       ns->base + TXCFG);			writel(readl(ns->base + RXCFG) | RXCFG_RX_FD,			       ns->base + RXCFG);			/* Light up full duplex LED */			writel(readl(ns->base + GPIOR) | GPIOR_GP1_OUT,			       ns->base + GPIOR);		} else if (((tanlpar & TANAR_HALF_DUP)			    && (tanar & TANAR_HALF_DUP))			   || ((tanlpar & TANAR_FULL_DUP)			       && (tanar & TANAR_HALF_DUP))			   || ((tanlpar & TANAR_HALF_DUP)			       && (tanar & TANAR_FULL_DUP))) {			/* one or both of us are half duplex */			writel((readl(ns->base + TXCFG)				& ~(TXCFG_CSI | TXCFG_HBI)) | TXCFG_ATP,			       ns->base + TXCFG);			writel(readl(ns->base + RXCFG) & ~RXCFG_RX_FD,			       ns->base + RXCFG);			/* Turn off full duplex LED */			writel(readl(ns->base + GPIOR) & ~GPIOR_GP1_OUT,			       ns->base + GPIOR);		}		speed = 4;	/* 1000F */	} else {		/* we have a copper transceiver */		new_cfg =		    ns->CFG_cache & ~(CFG_SB | CFG_MODE_1000 | CFG_SPDSTS);		if (cfg & CFG_SPDSTS1)			new_cfg |= CFG_MODE_1000;		else			new_cfg &= ~CFG_MODE_1000;		speed = ((cfg / CFG_SPDSTS0) & 3);		fullduplex = (cfg & CFG_DUPSTS);		if (fullduplex)			new_cfg |= CFG_SB;		if ((cfg & CFG_LNKSTS) &&		    ((new_cfg ^ ns->CFG_cache) & CFG_MODE_1000)) {			writel(new_cfg, ns->base + CFG);			ns->CFG_cache = new_cfg;		}		ns->CFG_cache &= ~CFG_SPDSTS;		ns->CFG_cache |= cfg & CFG_SPDSTS;	}	newlinkstate = (cfg & CFG_LNKSTS) ? LINK_UP : LINK_DOWN;	if (newlinkstate & LINK_UP && ns->linkstate != newlinkstate) {		printf("link now %s mbps, %s duplex and up.\n",		       speeds[speed], fullduplex ? "full" : "half");	} else if (newlinkstate & LINK_DOWN		   && ns->linkstate != newlinkstate) {		printf("link now down.\n");	}	ns->linkstate = newlinkstate;}

⌨️ 快捷键说明

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