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

📄 ax88180.c

📁 网络ax88180linux下的驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
/* ax88180: ASIX AX88180 Non-PCI Gigabit Ethernet Linux driver *//*  * Copyright (c) 2005 ASIX Electronics Corporation * Written by Allan Chou <allan@asix.com.tw> * *  This program is free software; you can distribute it and/or modify it *  under the terms of the GNU General Public License (Version 2) as *  published by the Free Software Foundation. * *  This program is distributed in the hope 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. * *//* * ======================================================================== * ASIX AX88180 Non-PCI 16/32-bit Gigabit Ethernet Linux Driver * * The AX88180 Ethernet controller is high performance and highly  * integrated local CPU bus Ethernet controllers with embedded 40K bytes  * SRAM and supports both 16-bit and 32-bit SRAM-Like interfaces  * for any embedded systems.  * The AX88180 is a single chip 10/100/1000Mbps Gigabit Ethernet controller  * that supports both MII and RGMII interfaces and is compliant to  * IEEE 802.3, IEEE 802.3u and IEEE 802.3z standards.   * * Please visit ASIX's web site (http://www.asix.com.tw) for more details. * * Module Name : ax88180.c * Purpose     : This file is the main file. * Author      : Allan Chou <allan@asix.com.tw> * Date        : 2005-12-07 * Notes       : * History     : * $Log:$ * 1.0.0	2005-12-07 * New release for AX88180 US1 chip. * * 1.0.1	2006-06-14 * 1.Modify to support AX88180 US2 chip.  * 2.Modify to support AX88180 US2 burst data access function. * * * * * * * * * * ======================================================================== */#include <linux/config.h>#include <linux/module.h>#include <linux/version.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/types.h>#include <linux/interrupt.h>#include <linux/ioport.h>#include <linux/string.h>#include <linux/init.h>#include <linux/errno.h>#include <linux/spinlock.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/skbuff.h>#include <linux/timer.h>#include <linux/delay.h>#include <linux/crc32.h>#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)#include <linux/ethtool.h>#endif#include <linux/mii.h>#include <linux/if_ether.h>#include <asm/io.h>#include <asm/uaccess.h>		/* User space memory access functions */#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)#	ifdef CONFIG_BOARD_S3C2440_SMDK#		include <asm/irq.h>#		include <asm/arch/S3C2440.h>#	endif#else#	ifdef CONFIG_ARCH_S3C2410#		include <asm/arch/regs-mem.h>#		include <asm/arch/regs-irq.h>#	endif#endif#include "ax88180.h"/* * =========================================================================== * <<<<<<                   Declare Global Variables                    >>>>>> * =========================================================================== */#define	DRV_NAME	"ax88180"#define	DRV_VERSION	"v1.1.0"static char version[] __initdata = KERN_INFO "ax88180: ASIX AX88180 Non-PCI 32-bit Gigabit Ethernet Driver " DRV_VERSION "\n" KERN_INFO "ax88180: Please visit http://www.asix.com.tw for the latest driver.\n";/* * =========================================================================== * <<<<<<             Declare Macro/Structure Definition                >>>>>> * =========================================================================== *///allan1/* Information that need to be kept for each board. */struct _AX88180_PRIVATE {	struct net_device_stats	stats;	unsigned long Phy_MemBase;	unsigned long PhyAddr;	unsigned long PhyID0;	unsigned int MediaMode;	unsigned int RealMediaMode;	unsigned int ForceMedia;	unsigned int LineSpeed;	unsigned int DuplexMode;	unsigned int JumboFlag;	unsigned long RxFilterMode;	unsigned long FirstTxDesc;	unsigned long NextTxDesc;	unsigned long rxbuf_overflow_count;	unsigned char *rx_buf;	spinlock_t lock;	struct mii_if_info mii_if;} AX88180_PRIVATE, *PAX88180_PRIVATE;static unsigned long Log_MemBase = 0;unsigned long mem = PLATFORM_MEMBASE; unsigned long irq = PLATFORM_IRQ;unsigned int jumbo = DISABLE_JUMBO; unsigned int media = 0;#define	PRINTK(flag, args...) if (flag & DEBUG_FLAGS) printk(args)	//Access RXBUFFER_START/TXBUFFER_START to read RX buffer/write TX buffer#define READ_RXBUF(data) data = *(const volatile unsigned long * const)(Log_MemBase + RXBUFFER_START)#define WRITE_TXBUF(data) *(volatile unsigned long *)(Log_MemBase + TXBUFFER_START) = data#define READ_MACREG(regaddr, regdata) regdata = *(volatile unsigned long *)(Log_MemBase + regaddr)#define WRITE_MACREG(regaddr, regdata) { \	*(volatile unsigned long *)(Log_MemBase + regaddr) = regdata; \	}#define READ_PHYREG(phyaddr, regaddr, regdata) { \	unsigned long tmpval1, k1; \	WRITE_MACREG(MDIOCTRL, READ_PHY | (regaddr << 8) | phyaddr); \	for (k1 = 0; k1 < 10000; k1++) { \		READ_MACREG(MDIOCTRL, tmpval1); \		if ((tmpval1 & READ_PHY) == 0) { \			break; \		} \		udelay(1); \	} \	READ_MACREG(MDIODP, regdata); \}#define WRITE_PHYREG(phyaddr, regaddr, regdata) { \	unsigned long tmpval2, k2; \	WRITE_MACREG(MDIODP, regdata); \	WRITE_MACREG(MDIOCTRL, WRITE_PHY | (regaddr << 8) | phyaddr); \	for (k2 = 0; k2 < 10000; k2++) { \		READ_MACREG(MDIOCTRL, tmpval2); \		if ((tmpval2 & WRITE_PHY) == 0) { \			break; \		} \		udelay(1); \	} \}#define RESET_MAC { \	unsigned long tmpval3; \	WRITE_MACREG(MISC, MISC_RESET_MAC); \	READ_MACREG(MISC, tmpval3); \	WRITE_MACREG(MISC, MISC_NORMAL); \	WRITE_MACREG(RXINDICATOR, DEFAULT_RXINDICATOR); \	WRITE_MACREG(TXCMD, DEFAULT_TXCMD); \	WRITE_MACREG(TXBS, DEFAULT_TXBS); \	WRITE_MACREG(TXDES0, DEFAULT_TXDES0); \	WRITE_MACREG(TXDES1, DEFAULT_TXDES1); \	WRITE_MACREG(TXDES2, DEFAULT_TXDES2); \	WRITE_MACREG(TXDES3, DEFAULT_TXDES3); \	WRITE_MACREG(TXCFG, DEFAULT_TXCFG); \	WRITE_MACREG(MACCFG2, DEFAULT_MACCFG2); \	WRITE_MACREG(MACCFG3, DEFAULT_MACCFG3); \	WRITE_MACREG(TXLEN, DEFAULT_TXLEN); \	WRITE_MACREG(TXPAUT, DEFAULT_TXPAUT); \	WRITE_MACREG(RXBTHD0, DEFAULT_RXBTHD0); \	WRITE_MACREG(RXBTHD1, DEFAULT_RXBTHD1); \	WRITE_MACREG(RXFULTHD, DEFAULT_RXFULTHD); \	WRITE_MACREG(DOGTHD0, DEFAULT_DOGTHD0); \	WRITE_MACREG(DOGTHD1, DEFAULT_DOGTHD1); \}#define RESET_PHY { \	unsigned long tmpval3a, k3a; \	WRITE_PHYREG(pax88180_local->PhyAddr, BMCR, PHY_RESET); \	for (k3a = 0; k3a < 500; k3a++) { \		READ_PHYREG(pax88180_local->PhyAddr, BMCR, tmpval3a); \		if (!(tmpval3a & PHY_RESET)) \			break; \		mdelay(1); \	} \}#define	INIT_TXRX_VARIABLES { \	pax88180_local->FirstTxDesc = TXDP0; \	pax88180_local->NextTxDesc = TXDP0; \	pax88180_local->rxbuf_overflow_count = 0; \}#define	ENABLE_INTERRUPT	WRITE_MACREG(IMR, DEFAULT_IMR)#define	DISABLE_INTERRUPT	WRITE_MACREG(IMR, CLEAR_IMR)#define	START_READ_RXBUFF 	WRITE_MACREG(RXINDICATOR, RX_START_READ)#define	STOP_READ_RXBUFF 	WRITE_MACREG(RXINDICATOR, RX_STOP_READ)/* Display all AX88180 MAC registers onto console screen */#define	DISPLAY_ALLMACREG { \	unsigned long tmpval4; \	int k4; \	PRINTK(DEBUG_MSG, "ax88180: AX88180 MAC Registers:\n"); \	for (k4 = 0xFC00; k4 <= 0xFCFF; k4+=4) { \		READ_MACREG(k4, tmpval4); \		PRINTK(DEBUG_MSG, "0x%04x=0x%08lx ", k4, tmpval4); \		if ((k4 & 0xF) == 0xC) \			PRINTK(DEBUG_MSG, "\n"); \	} \	PRINTK(DEBUG_MSG, "\n"); \}//allan3/* Display all AX88180 PHY registers onto console screen */#define	DISPLAY_ALLPHYREG { \	unsigned long tmpval5; \	PRINTK(DEBUG_MSG, "ax88180: AX88180 PHY Registers: (media=%d)\n", media); \	READ_PHYREG(pax88180_local->PhyAddr, BMCR, tmpval5); \	PRINTK(DEBUG_MSG, "BMCR=0x%04x ", (unsigned int)tmpval5); \	READ_PHYREG(pax88180_local->PhyAddr, BMSR, tmpval5); \	PRINTK(DEBUG_MSG, "BMSR=0x%04x ", (unsigned int)tmpval5); \	READ_PHYREG(pax88180_local->PhyAddr, PHYIDR0, tmpval5); \	PRINTK(DEBUG_MSG, "PHYIDR0=0x%04x ", (unsigned int)tmpval5); \	READ_PHYREG(pax88180_local->PhyAddr, PHYIDR1, tmpval5); \	PRINTK(DEBUG_MSG, "PHYIDR1=0x%04x ", (unsigned int)tmpval5); \	READ_PHYREG(pax88180_local->PhyAddr, ANAR, tmpval5); \	PRINTK(DEBUG_MSG, "ANAR=0x%04x ", (unsigned int)tmpval5); \	READ_PHYREG(pax88180_local->PhyAddr, ANLPAR, tmpval5); \	PRINTK(DEBUG_MSG, "ANLPAR=0x%04x \n", (unsigned int)tmpval5); \	READ_PHYREG(pax88180_local->PhyAddr, ANER, tmpval5); \	PRINTK(DEBUG_MSG, "ANER=0x%04x ", (unsigned int)tmpval5); \	READ_PHYREG(pax88180_local->PhyAddr, AUX_1000_CTRL, tmpval5); \	PRINTK(DEBUG_MSG, "1G_CTRL=0x%04x ", (unsigned int)tmpval5); \	READ_PHYREG(pax88180_local->PhyAddr, AUX_1000_STATUS, tmpval5); \	PRINTK(DEBUG_MSG, "1G_STATUS=0x%04x \n", (unsigned int)tmpval5); \	if (pax88180_local->PhyID0 == MARVELL_88E1111_PHYIDR0) { \		READ_PHYREG(pax88180_local->PhyAddr, M88_SSR, tmpval5); \		PRINTK(DEBUG_MSG, "M88_SSR=0x%04x ", (unsigned int)tmpval5); \		READ_PHYREG(pax88180_local->PhyAddr, M88_IER, tmpval5); \		PRINTK(DEBUG_MSG, "M88_IER=0x%04x ", (unsigned int)tmpval5); \		READ_PHYREG(pax88180_local->PhyAddr, M88_ISR, tmpval5); \		PRINTK(DEBUG_MSG, "M88_ISR=0x%04x ", (unsigned int)tmpval5); \		READ_PHYREG(pax88180_local->PhyAddr, M88_EXT_SCR, tmpval5); \		PRINTK(DEBUG_MSG, "M88_EXT_SCR=0x%04x ", (unsigned int)tmpval5); \		READ_PHYREG(pax88180_local->PhyAddr, M88_EXT_SSR, tmpval5); \		PRINTK(DEBUG_MSG, "M88_EXT_SSR=0x%04x \n", (unsigned int)tmpval5); \	} else if (pax88180_local->PhyID0 == CICADA_CIS8201_PHYIDR0) { \		READ_PHYREG(pax88180_local->PhyAddr, CIS_IMR, tmpval5); \		PRINTK(DEBUG_MSG, "CIS_IMR=0x%04x ", (unsigned int)tmpval5); \		READ_PHYREG(pax88180_local->PhyAddr, CIS_ISR, tmpval5); \		PRINTK(DEBUG_MSG, "CIS_ISR=0x%04x ", (unsigned int)tmpval5); \		READ_PHYREG(pax88180_local->PhyAddr, CIS_AUX_CTRL_STATUS, tmpval5); \		PRINTK(DEBUG_MSG, "CIS_AUX=0x%04x \n", (unsigned int)tmpval5); \	} \	READ_MACREG(RXCFG, tmpval5); \	PRINTK(DEBUG_MSG, "RXCFG=0x%08lx ", tmpval5); \	READ_MACREG(MACCFG0, tmpval5); \	PRINTK(DEBUG_MSG, "MACCFG0=0x%08lx ", tmpval5); \	READ_MACREG(MACCFG1, tmpval5); \	PRINTK(DEBUG_MSG, "MACCFG1=0x%08lx ", tmpval5); \	READ_MACREG(MACCFG2, tmpval5); \	PRINTK(DEBUG_MSG, "MACCFG2=0x%08lx \n\n", tmpval5); \} /* Index to functions, as function prototypes. */extern int __init ax88180_probe(struct net_device *global_dev);static int ax88180_open(struct net_device *global_dev);static int ax88180_stop(struct net_device *global_dev);static int ax88180_start_xmit(struct sk_buff *skb, struct net_device *global_dev);static void ax88180_tx_timeout(struct net_device *global_dev);static struct net_device_stats * ax88180_get_stats(struct net_device *global_dev);static void ax88180_set_multicast_list(struct net_device *global_dev);#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)#ifdef CONFIG_BOARD_S3C2440_SMDKint set_external_irq(int irq, int edge, int pullup);#endifstatic void ax88180_interrupt(int irq, void *global_dev_id, struct pt_regs * regs);#elsestatic irqreturn_t ax88180_interrupt(int irq, void *global_dev_id, struct pt_regs * regs);#endifstatic int ax88180_initialization(struct net_device *global_dev);static void ax88180_PHY_initial(struct net_device *global_dev);static void ax88180_meida_config(struct net_device *global_dev);static void get_MarvellPHY_meida_mode(struct net_device *global_dev);static void get_CicadaPHY_meida_mode(struct net_device *global_dev);static void ax88180_rx_handler(struct net_device *global_dev);static void ax88180_tx_handler(struct net_device *global_dev);#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)static int ax88180_ioctl(struct net_device *global_dev, struct ifreq *rq, int cmd);static int ax88180_ethtool_ioctl(struct net_device *global_dev, void *useraddr);static int mdio_read(struct net_device *global_dev, int phy_id, int regaddr);static void mdio_write(struct net_device *global_dev, int phy_id, int regaddr, int regval);#endifint set_external_irq(int irq, int edge, int pullup);/* * =========================================================================== * <<<<<<                        MODULE-ROUTINES                        >>>>>> * =========================================================================== */#ifdef MODULEMODULE_AUTHOR("Allan Chou <allan@asix.com.tw>");MODULE_DESCRIPTION("ASIX AX88180 Non-PCI 32-bit Gigabit Ethernet Driver");MODULE_LICENSE("GPL");/* ***************************************************************************** * AX88180 module mode driver optional parameters: * Syntax: insmod ax88180.o mem=0xXXXXXXXX irq=0xXX media=<media_type> jumbo=x  *   mem	Set memory base address (default is 0x08000000) *   irq	Set IRQ number (default is 0x27) *   media	Set media mode (0:auto, 1:100full, 2:100half, 3:10full 4:10half) *   jumbo	Enable/disable Jumbo frame (1=enable, 0=disable)(default is 0) *  * example: insmod ax88180.o mem=0x08000000 irq=0x27 media=auto jumbo=0  * ***************************************************************************** */#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)MODULE_PARM(media, "i");MODULE_PARM(mem, "i");MODULE_PARM(irq, "i");MODULE_PARM(jumbo, "i");#elsemodule_param(media, int, 0);module_param(jumbo, int, 0);module_param(mem, long, 0);module_param(irq, long, 0);#endifMODULE_PARM_DESC(media, "Media Mode(auto, 100full, 100half, 10full or 10half)");MODULE_PARM_DESC(mem, "Memory Base Address");MODULE_PARM_DESC(irq, "Interrupt Number");MODULE_PARM_DESC(jumbo, "Jumbo Frame(1=enable, 0=disable");static struct net_device dev_ax;static int __init ax88180_init_module(void);static void __exit ax88180_cleanup_module(void);module_init(ax88180_init_module);module_exit(ax88180_cleanup_module);/* ***************************************************************************** * ax88180_init_module() * * Check for a network adaptor of this type, and return '0' if one exists. * * Return 0 on success. ***************************************************************************** */static int __init ax88180_init_module(void){	static struct net_device *global_dev;	PRINTK(INIT_MSG, "ax88180: ax88180_init_module beginning ..........\n");	global_dev = &dev_ax;	global_dev->irq = irq;	global_dev->base_addr = mem;	global_dev->init = ax88180_probe;	if(register_netdev(global_dev) == 0) {		PRINTK(INIT_MSG, "ax88180: ax88180_init_module end ..........\n");		return 0;	}	if (mem != 0) {		PRINTK(WARNING_MSG, "AX88180: No AX88180 card found at memory = %#lx\n", mem);	}	else {		PRINTK(WARNING_MSG, "AX88180: You must supply \"mem=0xNNNNNNN\" value(s) for AX88180.\n");	}	return -ENXIO;}/* ***************************************************************************** * ax88180_cleanup_module() ***************************************************************************** */static void __exit ax88180_cleanup_module(void){	struct _AX88180_PRIVATE *pax88180_local;	static struct net_device *global_dev = &dev_ax; 	PRINTK(INIT_MSG, "ax88180: ax88180_cleanup_module beginning ..........\n");	pax88180_local = (struct _AX88180_PRIVATE *) global_dev->priv;	if (global_dev != NULL) {		unregister_netdev(global_dev);		free_irq(global_dev->irq, global_dev);	}	if (Log_MemBase != 0) {		iounmap((void *)Log_MemBase);	}	if (pax88180_local != NULL) {		if (pax88180_local->Phy_MemBase != 0) {			release_mem_region(pax88180_local->Phy_MemBase, AX88180_MEMORY_SIZE);		}		kfree(global_dev->priv);		global_dev->priv = NULL;				}        PRINTK(INIT_MSG, "ax88180: ax88180_cleanup_module end ..........\n");	return;}#endif/* * =========================================================================== * <<<<<<                        MAIN-ROUTINES                          >>>>>> * =========================================================================== *//* ***************************************************************************** * ax88180_probe() * * This is the entry routine for kernel mode driver. This routine will probe * the AX88180 device and allocate a (64K bytes + private data structure size)  * memory space for AX88180 operation. *  * AX88180 32-bit memory mapping: * ============================== * 0x0000~0x3FFF	RX buffer area * 0x4000~0xFBFF	TX buffer area

⌨️ 快捷键说明

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