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

📄 au1000_eth.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * * Alchemy Semi Au1000 ethernet driver * * Copyright 2001 MontaVista Software Inc. * Author: MontaVista Software, Inc. *         	ppopov@mvista.com or source@mvista.com * * ######################################################################## * *  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. * * ######################################################################## * *  */#ifndef __mips__#error This driver only works with MIPS architectures!#endif#include <linux/module.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/string.h>#include <linux/timer.h>#include <linux/errno.h>#include <linux/in.h>#include <linux/ioport.h>#include <linux/slab.h>#include <linux/interrupt.h>#include <linux/pci.h>#include <linux/init.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/skbuff.h>#include <linux/delay.h>#include <asm/irq.h>#include <asm/bitops.h>#include <asm/io.h>#include <asm/au1000.h>#include "au1000_eth.h"#ifdef AU1000_ETH_DEBUGstatic int au1000_debug = 10;#elsestatic int au1000_debug = 3;#endif// prototypesstatic void *dma_alloc(size_t, dma_addr_t *);static void dma_free(void *, size_t);static void hard_stop(struct net_device *);static int __init au1000_probe1(struct net_device *, long, int, int);static int au1000_init(struct net_device *);static int au1000_open(struct net_device *);static int au1000_close(struct net_device *);static int au1000_tx(struct sk_buff *, struct net_device *);static int au1000_rx(struct net_device *);static void au1000_interrupt(int, void *, struct pt_regs *);static void au1000_tx_timeout(struct net_device *);static int au1000_set_config(struct net_device *dev, struct ifmap *map);static void set_rx_mode(struct net_device *);static struct net_device_stats *au1000_get_stats(struct net_device *);static inline void update_tx_stats(struct net_device *, u32, u32);static inline void update_rx_stats(struct net_device *, u32);static void au1000_timer(unsigned long);static void cleanup_buffers(struct net_device *);static int au1000_ioctl(struct net_device *, struct ifreq *, int);static int mdio_read(struct net_device *, int, int);static void mdio_write(struct net_device *, int, int, u16);static inline void sync(void);extern  void ack_rise_edge_irq(unsigned int);static int next_dev;/* * Theory of operation * * The Au1000 MACs use a simple rx and tx descriptor ring scheme.  * There are four receive and four transmit descriptors.  These  * descriptors are not in memory; rather, they are just a set of  * hardware registers. * * Since the Au1000 has a coherent data cache, the receive and * transmit buffers are allocated from the KSEG0 segment. The  * hardware registers, however, are still mapped at KSEG1 to * make sure there's no out-of-order writes, and that all writes * complete immediately. *//* * Base address and interupt of the Au1000 ethernet macs */static struct {	unsigned int port;	int irq;} au1000_iflist[NUM_INTERFACES] = {	{AU1000_ETH0_BASE, AU1000_ETH0_IRQ}, 	{AU1000_ETH1_BASE, AU1000_ETH1_IRQ}};static char version[] __devinitdata =    "au1000eth.c:0.1 ppopov@mvista.com\n";// FIX! Need real Ethernet addressesstatic unsigned char au1000_mac_addr[2][6] __devinitdata = { 	{0x00, 0x50, 0xc2, 0x0c, 0x30, 0x00},	{0x00, 0x50, 0xc2, 0x0c, 0x40, 0x00}};#define nibswap(x) ((((x) >> 4) & 0x0f) | (((x) << 4) & 0xf0))#define RUN_AT(x) (jiffies + (x))// For reading/writing 32-bit words from/to DMA memory#define cpu_to_dma32 cpu_to_be32#define dma32_to_cpu be32_to_cpu/* CPU pipeline flush */static inline void sync(void){	asm volatile ("sync");}/* FIXME  * All of the PHY code really should be detached from the MAC  * code. */static char *phy_link[] = 	{"unknown", 	"10Base2", "10BaseT", 	"AUI",	"100BaseT", "100BaseTX", "100BaseFX"};int bcm_5201_init(struct net_device *dev, int phy_addr){	s16 data;		/* Stop auto-negotiation */	//printk("bcm_5201_init\n");	data = mdio_read(dev, phy_addr, MII_CONTROL);	mdio_write(dev, phy_addr, MII_CONTROL, data & ~MII_CNTL_AUTO);	/* Set advertisement to 10/100 and Half/Full duplex	 * (full capabilities) */	data = mdio_read(dev, phy_addr, MII_ANADV);	data |= MII_NWAY_TX | MII_NWAY_TX_FDX | MII_NWAY_T_FDX | MII_NWAY_T;	mdio_write(dev, phy_addr, MII_ANADV, data);		/* Restart auto-negotiation */	data = mdio_read(dev, phy_addr, MII_CONTROL);	data |= MII_CNTL_RST_AUTO | MII_CNTL_AUTO;	mdio_write(dev, phy_addr, MII_CONTROL, data);	//dump_mii(dev, phy_addr);	return 0;}int bcm_5201_reset(struct net_device *dev, int phy_addr){	s16 mii_control, timeout;		//printk("bcm_5201_reset\n");	mii_control = mdio_read(dev, phy_addr, MII_CONTROL);	mdio_write(dev, phy_addr, MII_CONTROL, mii_control | MII_CNTL_RESET);	mdelay(1);	for (timeout = 100; timeout > 0; --timeout) {		mii_control = mdio_read(dev, phy_addr, MII_CONTROL);		if ((mii_control & MII_CNTL_RESET) == 0)			break;		mdelay(1);	}	if (mii_control & MII_CNTL_RESET) {		printk(KERN_ERR "%s PHY reset timeout !\n", dev->name);		return -1;	}	return 0;}int bcm_5201_status(struct net_device *dev, int phy_addr, u16 *link, u16 *speed){	u16 mii_data;	struct au1000_private *aup;	if (!dev) {		printk(KERN_ERR "bcm_5201_status error: NULL dev\n");		return -1;	}	aup = (struct au1000_private *) dev->priv;	mii_data = mdio_read(dev, aup->phy_addr, MII_STATUS);	if (mii_data & MII_STAT_LINK) {		*link = 1;		mii_data = mdio_read(dev, aup->phy_addr, MII_AUX_CNTRL);		if (mii_data & MII_AUX_100) {			if (mii_data & MII_AUX_FDX) {				*speed = IF_PORT_100BASEFX;				dev->if_port = IF_PORT_100BASEFX;			}			else {				*speed = IF_PORT_100BASETX;				dev->if_port = IF_PORT_100BASETX;			}		}		else  {			*speed = IF_PORT_10BASET;			dev->if_port = IF_PORT_10BASET;		}	}	else {		*link = 0;		*speed = 0;	}	return 0;}int am79c901_init(struct net_device *dev, int phy_addr){	printk("am79c901_init\n");	return 0;}int am79c901_reset(struct net_device *dev, int phy_addr){	printk("am79c901_reset\n");	return 0;}int am79c901_status(struct net_device *dev, int phy_addr, u16 *link, u16 *speed){	return 0;}struct phy_ops bcm_5201_ops = {	bcm_5201_init,	bcm_5201_reset,	bcm_5201_status,};struct phy_ops am79c901_ops = {	am79c901_init,	am79c901_reset,	am79c901_status,};static struct mii_chip_info {	const char * name;	u16 phy_id0;	u16 phy_id1;	struct phy_ops *phy_ops;	} mii_chip_table[] = {	{"Broadcom BCM5201 10/100 BaseT PHY",  0x0040, 0x6212, &bcm_5201_ops },	{"AMD 79C901 HomePNA PHY",  0x0000, 0x35c8, &am79c901_ops },	{0,},};static int mdio_read(struct net_device *dev, int phy_id, int reg){	struct au1000_private *aup = (struct au1000_private *) dev->priv;	u32 timedout = 20;	u32 mii_control;	while (aup->mac->mii_control & MAC_MII_BUSY) {		mdelay(1);		if (--timedout == 0) {			printk(KERN_ERR "%s: read_MII busy timeout!!\n", dev->name);			return -1;		}	}	mii_control = MAC_SET_MII_SELECT_REG(reg) | 		MAC_SET_MII_SELECT_PHY(phy_id) | MAC_MII_READ;	aup->mac->mii_control = mii_control;	timedout = 20;	while (aup->mac->mii_control & MAC_MII_BUSY) {		mdelay(1);		if (--timedout == 0) {			printk(KERN_ERR "%s: mdio_read busy timeout!!\n", dev->name);			return -1;		}	}	return (int)aup->mac->mii_data;}static void mdio_write(struct net_device *dev, int phy_id, int reg, u16 value){	struct au1000_private *aup = (struct au1000_private *) dev->priv;	u32 timedout = 20;	u32 mii_control;	while (aup->mac->mii_control & MAC_MII_BUSY) {		mdelay(1);		if (--timedout == 0) {			printk(KERN_ERR "%s: mdio_write busy timeout!!\n", dev->name);			return;		}	}	mii_control = MAC_SET_MII_SELECT_REG(reg) | 		MAC_SET_MII_SELECT_PHY(phy_id) | MAC_MII_WRITE;	aup->mac->mii_data = value;	aup->mac->mii_control = mii_control;}static void dump_mii(struct net_device *dev, int phy_id){	int i, val;	for (i = 0; i < 7; i++) {		if ((val = mdio_read(dev, phy_id, i)) >= 0)			printk("%s: MII Reg %d=%x\n", dev->name, i, val);	}	for (i = 16; i < 25; i++) {		if ((val = mdio_read(dev, phy_id, i)) >= 0)			printk("%s: MII Reg %d=%x\n", dev->name, i, val);	}}static int __init mii_probe (struct net_device * dev){	struct au1000_private *aup = (struct au1000_private *) dev->priv;	int phy_addr;	aup->mii = NULL;	/* search for total of 32 possible mii phy addresses */	for (phy_addr = 0; phy_addr < 32; phy_addr++) {		u16 mii_status;		u16 phy_id0, phy_id1;		int i;		mii_status = mdio_read(dev, phy_addr, MII_STATUS);		if (mii_status == 0xffff || mii_status == 0x0000)			/* the mii is not accessable, try next one */			continue;		phy_id0 = mdio_read(dev, phy_addr, MII_PHY_ID0);		phy_id1 = mdio_read(dev, phy_addr, MII_PHY_ID1);		/* search our mii table for the current mii */ 		for (i = 0; mii_chip_table[i].phy_id1; i++)			if (phy_id0 == mii_chip_table[i].phy_id0 &&			    phy_id1 == mii_chip_table[i].phy_id1) {				struct mii_phy * mii_phy;				printk(KERN_INFO "%s: %s found at phy address %d\n",				       dev->name, mii_chip_table[i].name, phy_addr);				if ((mii_phy = kmalloc(sizeof(struct mii_phy), GFP_KERNEL)) != NULL) {					mii_phy->chip_info = mii_chip_table+i;					mii_phy->phy_addr = phy_addr;					//mii_phy->status = mdio_read(dev, phy_addr, MII_STATUS);					mii_phy->next = aup->mii;					aup->phy_ops = mii_chip_table[i].phy_ops;					aup->mii = mii_phy;				}				/* the current mii is on our mii_info_table,				   try next address */				break;			}	}	if (aup->mii == NULL) {		printk(KERN_ERR "%s: No MII transceivers found!\n", dev->name);		return -1;	}	/* use last PHY */	aup->phy_addr = aup->mii->phy_addr;	printk(KERN_INFO "%s: Using %s as default\n", dev->name, aup->mii->chip_info->name);	return 0;}/* * Buffer allocation/deallocation routines. The buffer descriptor returned * has the virtual and dma address of a buffer suitable for  * both, receive and transmit operations. */static db_dest_t *GetFreeDB(struct au1000_private *aup){	db_dest_t *pDB;	pDB = aup->pDBfree;	if (pDB) {		aup->pDBfree = pDB->pnext;	}	//printk("GetFreeDB: %x\n", pDB);	return pDB;}void ReleaseDB(struct au1000_private *aup, db_dest_t *pDB){	db_dest_t *pDBfree = aup->pDBfree;	if (pDBfree)		pDBfree->pnext = pDB;	aup->pDBfree = pDB;}/*

⌨️ 快捷键说明

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