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

📄 pmcmspeth.c

📁 175dswitch的驱动源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/****************************************************************** * Copyright 2005 PMC-Sierra, Inc * * PMC-SIERRA DISCLAIMS ANY LIABILITY OF ANY KIND * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS * SOFTWARE. *//*********************************************************************** *  mspeth.c :  PMC-Sierra MSP EVM ethernet driver for linux * * Originally based on mspeth.c driver which contains substantially the * same hardware. * Based on skelton.c by Donald Becker. * ported by Andrew Hughes, Andrew_Hughes@pmc-sierra.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  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED * WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN * NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF * USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * 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. */#include <asm/brecis/prom.h>#include <asm/brecis/brecisint.h>#include <asm/bootinfo.h>#include <asm/uaccess.h>/* Include file with the procfs structs and function protos */#include <linux/proc_fs.h>/* driver includes */#include "pmcmspeth.h"#include "bridge.h"unsigned char  seth0mac[6],seth1mac[6];int  nFlag[5];int tempdata[4];MAC smac;unsigned int sxjvalue;#define TIME_IP   50//added by Shi ->struct PORT{	unsigned flag;	unsigned count;};struct IP{	unsigned int ip;	unsigned long t;	int flag;};struct COMP{	int nCount;	struct IP Ip[10];};struct COMP  scomp[65536];	//struct PORT nPubPort[65536];//struct PORT nPubIcmpPort[65536];//MAC smac1[5];VLAN svlan[6];VLAN tmpsvlan[5];//added by Shi <-/*static struct timer_list macTimer;static int macTimer_on;*/struct sdata{	struct sk_buff *skb[64];	int flag[64];	int nFlag[64];}data;int nwCur,nrCur;struct tasklet_struct wan_tasklet;unsigned long stime;//added by Shi ->unsigned short getmol(char *strKey){	int nStrLen=0;	union suffix unTemp;	int nCount=0;	unsigned short nMark=0;	nStrLen=3;	unTemp.cMarker[0]=(strKey[nCount]&0xff);	unTemp.cMarker[1]=(strKey[nCount+1]&0xff);	nMark=unTemp.nMarker;	for(nCount=1;nCount<nStrLen;nCount++)	{		unTemp.cMarker[0]=(strKey[nCount]&0xff);		unTemp.cMarker[1]=(strKey[nCount+1]&0xff);		nMark^=unTemp.nMarker;	}	return nMark;}unsigned short makeword(unsigned char hi,unsigned char lo){	unsigned short n;	n=hi;	n=n<<8;	n|=lo;	return n;}unsigned int makelong(unsigned short hi,unsigned short lo){	unsigned int n;	n=hi;	n=n<<16;	n|=lo;	return n;}//added by Shi <-/************************************************************************** * The name of the card. Is used for messages and in the requests for * io regions, irqs and dma channels.  versions etc.  Also, various other * identifying character constants. */static const char version[] =    "pmcmspeth.c:v0.00 25/05/2005, PMC-Sierra\n";static const char cardname[] = "pmcmspeth";static const char drv_version[] = "$Revision: 1.1.4.2 $";static const char drv_reldate[] =    "$Date: 2007/03/01 09:34:13 $";static const char drv_file[] = __FILE__;/************************************************************************** * Internal mspeth data structures.  Two things to recall *    (1) use the KSEG1 address to access hardware *    (2) make sure of the indice ordering */static const u32 MacBases[MSPETH_MAX_UNITS + 1] =    { MAC0_BASE, MAC1_BASE, MAC2_BASE, 0 };static const u32 MacRSTBases[MSPETH_MAX_UNITS + 1] =    { MAC0_RST, MAC1_RST, MAC2_RST, 0 };static const u8 MacIRQs[MSPETH_MAX_UNITS + 1] =    { BRECISINT_MAC0, BRECISINT_MAC1, BRECISINT_MAC2, 0 };static char *macname[] = { "ethaddr0", "ethaddr1", "ethaddr2", "unknown" };/* array of PHYs.  Notice that the index here isn't for hardware (although we might have as many * PHYs as we have MACs) */static struct mspeth_phy phy_ctrl[MSPETH_MAX_UNITS + 3] =    { {0, MD_UNASSIGNED_PHY, false},{0, MD_UNASSIGNED_PHY, false},{0, MD_UNASSIGNED_PHY, false},{0, MD_UNASSIGNED_PHY, false},{0, MD_UNASSIGNED_PHY, false},{0, MD_UNASSIGNED_PHY, false}};/* debugging flags *//* hammtrev, 2005-11-25: * For some odd reason, setting MSPETH_DEBUG to a non-zero value was setting * this variable to some garbage value when assigned statically here. Moving * assignment of this variable into mspeth_probe(). */static unsigned int mspeth_debug;/* A list of all installed mspeth devices. */static struct net_device *root_mspeth_dev = NULL;/************************************************************************** * Function prototypes *//* all the functions that get called by upper layers */static int mspeth_open(struct net_device *dev);static int mspeth_send_packet(struct sk_buff *skb, struct net_device *dev);static void mspeth_tx_timeout(struct net_device *dev);static void mspeth_interrupt(int irq, void *dev_id, struct pt_regs *regs);static void mspeth_hard_restart_bh(unsigned long devaddr);static void mspeth_rx(unsigned long devaddr);static void mspeth_txdone(unsigned long devaddr);static int mspeth_close(struct net_device *dev);static struct net_device_stats *mspeth_get_stats(struct net_device *dev);static void mspeth_set_multicast_list(struct net_device *dev);static int mspeth_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);/* private utility functions */static void mspeth_soft_restart(struct net_device *dev);static void mspeth_hard_restart(struct net_device *dev);static void mspeth_mac_reset(struct net_device *dev);static void mspeth_mac_init(struct net_device *dev);static void mspeth_phy_init(struct net_device *dev);static void mspeth_phy_reset(struct net_device *dev);static int mspeth_proc_info(char *buffer, char **start, off_t offset,			    int length);static bool mspeth_queue_init(struct net_device *dev);static void mspeth_set_arc_entry(struct mspeth_regs *tr, int index,				 unsigned char *addr);static void mspeth_check_tx_stat(struct net_device *dev, int status);static void mspeth_phyprobe(void);static void mspeth_init_phyaddr(struct net_device *dev);static void mspeth_init_cmdline(struct net_device *devp);static void mspeth_clear_queues(struct net_device *dev);static void mspeth_fatal_error_interrupt(struct net_device *dev,					 int status);/*###############################################################################                                                                            ## Define the utility functions used by the the various other actual          ##     routines here.  These should all be inline or macros                   ##                                                                            ###############################################################################*/#define flush_memqueue() ({__asm__ volatile ("lw $0, %0" : : "m" (*MEM_CNFG1_REG));})#define flush_dmaqueue() ({__asm__ volatile ("lw $0, %0" : : "m" ((u32)&tr->Int_Src));})#define read_mspreg(addr) (*(volatile u32 *)((addr)))#define write_mspreg(val,addr) (*(volatile u32 *)((addr)) = (u32)(val))#define setbit_mspreg(val,addr) write_mspreg(read_mspreg(addr) |  (val),addr)#define clrbit_mspreg(val,addr) write_mspreg(read_mspreg(addr) & ~(val),addr)#define vtonocache(p)   KSEG1ADDR(virt_to_phys(p))#define rd_nocache(addr) (*(volatile u32 *)(KSEG1ADDR((u32)(addr))))#define wr_nocache(val,addr) (*(volatile u32 *)(KSEG1ADDR((u32)(addr))) = (u32)(val))#ifdef CONFIG_CPU_HAS_NONCOHERENT_CACHE/************************************************************************ * writeback_buffer - force the cache to write contents of cached buffer * to memory and invalidate the buffer.  Must start on 16 byte boundary, * must "own" to next higher 15 byte boundary from end of buffer */inline static void writeback_buffer(void *bufaddr, unsigned int length){	unsigned long end = (unsigned long) bufaddr + length;	bufaddr =	    (void *) ((unsigned int) bufaddr & ~(L1_CACHE_BYTES - 1));	while (((unsigned long) bufaddr + 0x200) < end) {		cache16_unroll32(bufaddr, Hit_Writeback_Inv_D);		bufaddr += 0x200;	}	while ((unsigned long) bufaddr < end) {		flush_dcache_line((u32) bufaddr);		bufaddr += L1_CACHE_BYTES;	}}/************************************************************************ * writeback_qdesc - writeback a Q_Desc structure.  Must start on a  *     16 byte boundary */inline static void writeback_qdesc(struct Q_Desc *qdesc){	flush_dcache_line((u32) qdesc);	flush_dcache_line(((u32) qdesc) + 16);}/************************************************************************ * writeback_bdesc - writeback a BDesc structure. */inline static void writeback_bdesc(struct BDesc *bdesc){	flush_dcache_line((u32) bdesc);}#else#define writeback_buffer(a,l) do {} while (0)#define writeback_qdesc(a) do {} while (0)#define writeback_bdesc(a) do {} while (0)#endif				/* CONFIG_CPU_HAS_NONCOHERENT_CACHE *//************************************************************************ * pref - prefetch to data cache *      Prefetch data to help improve performance */#define pref(base, offset)      __asm__ __volatile__(   \                "pref 0, %1(%0)"                \                :                               \                : "r" (base),                   \                  "I" (offset));/************************************************************************ * invalidate_buffer - Invalidate buffer cache *      - must start on 16 byte boundary *      - must "own" to next higher 16 byte boundary from end of buffer */inline static void invalidate_buffer(void *bufaddr, unsigned int length){	unsigned long end = (unsigned long) bufaddr + length;	bufaddr =	    (void *) ((unsigned int) bufaddr & ~(L1_CACHE_BYTES - 1));	while (((unsigned long) bufaddr + 0x200) < end) {		cache16_unroll32(bufaddr, Hit_Invalidate_D);		bufaddr += 0x200;	}	while ((unsigned long) bufaddr < end) {		invalidate_dcache_line((u32) bufaddr);		bufaddr += L1_CACHE_BYTES;	}}/************************************************************************ * invalidate_qdesc - Invalidate a Q_Desc structure.  Must start on a  *     16 byte boundary */inline static void invalidate_qdesc(struct Q_Desc *qdesc){	if (mspeth_debug > 2) 		printk(KERN_INFO "Invalidating Q_Desc at address 0x%08x\n", qdesc);	invalidate_dcache_line((u32) qdesc);	invalidate_dcache_line(((u32) qdesc) + 16);}/************************************************************************ * Read/Write a MDIO register. */inline static u32 read_mspphyreg(int phyindex, int phy_reg){	struct mspeth_regs *tr =//	    (struct mspeth_regs *) MacBases[phy_ctrl[phyindex].hwindex];	    (struct mspeth_regs *) MacBases[phy_ctrl[0].hwindex];	int flags;	u32 data;	/* protect access with spin lock *///	spin_lock_irqsave(&phy_ctrl[phyindex], flags);	spin_lock_irqsave(&phy_ctrl[0], flags);//	write_mspreg(MD_CA_BUSY_BIT | (phy_ctrl[phyindex].phyaddr << 5) |	write_mspreg(MD_CA_BUSY_BIT | (phyindex << 5) |		     phy_reg, &tr->MD_CA);	while (read_mspreg(&tr->MD_CA) & MD_CA_BUSY_BIT) {;	}	data = read_mspreg(&tr->MD_DATA);	/* unlock *///	spin_unlock_irqrestore(&phy_ctrl[phyindex], flags);	spin_unlock_irqrestore(&phy_ctrl[0], flags);	return data;}inline static void write_mspphyreg(u32 d, int phyindex, int phy_reg){	struct mspeth_regs *tr =//	    (struct mspeth_regs *) MacBases[phy_ctrl[phyindex].hwindex];	    (struct mspeth_regs *) MacBases[phy_ctrl[0].hwindex];	int flags;	/* protect access with spin lock *///	spin_lock_irqsave(&phy_ctrl[phyindex], flags);	spin_lock_irqsave(&phy_ctrl[0], flags);	write_mspreg(d, &tr->MD_DATA);	write_mspreg(MD_CA_BUSY_BIT | MD_CA_Wr |//		     (phy_ctrl[phyindex].phyaddr << 5) | phy_reg,		     (phyindex << 5) | phy_reg,		     &tr->MD_CA);	while (read_mspreg(&tr->MD_CA) & MD_CA_BUSY_BIT) {;	}	/* unlock *///	spin_unlock_irqrestore(&phy_ctrl[phyindex], flags);	spin_unlock_irqrestore(&phy_ctrl[0], flags);}/************************************************************************** * allocate and align a max length socket buffer for this device */inline static struct sk_buff *mspeth_alloc_skb(struct net_device *dev){	struct sk_buff *skb;	/* we need a bit more that an ethernet frame for the aligment stuff so	 * preallocate two more*/	skb = dev_alloc_skb(MSP_END_BUFSIZE + 2);		if (skb == NULL) {		printk(KERN_WARNING		       "MSETH (alloc_skb) %s: cannot allocate skb!\n",		       dev->name);		return NULL;	}	/* align and fill out fields specific to our device.  Notice that	 * our device is smart about FCS etc ......	 */	skb_reserve(skb, 2);	skb->dev = dev;	skb->ip_summed = CHECKSUM_HW;	return skb;}/************************************************************************** * error reporting functions -- used for debugging mostly */static void dump_qdesc(struct Q_Desc *fd){	printk("  Q_Desc(%p): %08x %08x %08x %08x\n", fd, fd->fd.FDNext,	       fd->fd.FDSystem, fd->fd.FDStat, fd->fd.FDCtl);	printk("    BD: %08x %08x\n", fd->bd.BuffData, fd->bd.BDCtl);}static void dump_blist(struct BL_Desc *fd){	int i;	printk("  BL_Desc(%p): %08x %08x %08x %08x\n", fd, fd->fd.FDNext,	       fd->fd.FDSystem, fd->fd.FDStat, fd->fd.FDCtl);	for (i = 0; i < RX_BUF_NUM << 1; i++)		printk("    BD #%d: %08x %08x\n", i, fd->bd[i].BuffData,		       fd->bd[i].BDCtl);}static void print_buf(char *add, int length){	int i;	int len = length;	printk("print_buf(%08x)(%x)\n", (unsigned int) add, length);	if (len > 100)		len = 100;	for (i = 0; i < len; i++) {		printk(" %2.2X", (unsigned char) add[i]);		if (!(i % 16))			printk("\n");	}	printk("\n");}static void print_eth(char *add){

⌨️ 快捷键说明

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