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

📄 em86xx_eth.c

📁 bootloader源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * */#ifdef BOOTLOADER#include "config.h"#include "version.h"#include "util.h"#include "net.h"#include "net_ipv4.h"#include "em86xxapi.h"#include "irqs.h"#include "errno.h"#include "uart.h"#else#include <linux/config.h>#include <linux/kernel.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/spinlock.h>#include <linux/interrupt.h>#include <linux/signal.h>#include <linux/sched.h>#include <linux/module.h>#include <linux/compatmac.h>#include <linux/mm.h>#include <linux/init.h>#include <linux/timer.h>#include <linux/mii.h>#include <asm/virtconvert.h>#include <asm/arch/irqs.h>#endif //BOOTLOADER#include "em86xx_eth.h"/* Uncomment this for different messages *///#define ETH_DEBUG #define ETH_ERRMSG #define ETH_MSG#ifdef BOOTLOADER#define DRIVER "em86xx_eth"/* For static buffer allocation */#define STATIC_BUF_ALLOC#define printk          uart_printf#endif /* BOOTLOADER *//* For software filtering*///#define USE_SW_FILTERING#define USE_HW_FILTERING#ifdef ETH_DEBUG#define DBG_PRINT	printk#elsestatic void inline DBG_PRINT(const char *x, ...) { ; }#endif /* ETH_DEBUG */#ifdef ETH_ERRMSG#define ERR_PRINT	printk#elsestatic void inline ERR_PRINT(const char *x, ...) { ; }#endif /* ETH_ERRMSG */#ifdef ETH_MSG#define MSG_PRINT	printk#elsestatic void inline MSG_PRINT(const char *x, ...) { ; }#endif /* ETH_ERRMSG *//* Hack: this is the mac address by default */#define DEF_MAC_HI	0x00000011#ifdef BOOTLOADER#define DEF_MAC_LO	0xdeadbeef#else#define DEF_MAC_LO	0xaabbccdd#endif/* Default maximum link wait */#define DEF_LINK_LOOP		1000#define DEF_MAX_LINK_LOOP	0x1000000#define ETH_IRQ_FLAGS	(DmaIntNormal	  | DmaIntAbnormal    | DmaIntRxStopped		| \			DmaIntRxNoBuffer  | DmaIntRxCompleted)#define ETH_RXTX_FLAGS	(DmaTxStart       | DmaRxStart)#ifndef USE_HW_FILTERING #define ETH_MAC_FLAGS   (MacTxEnable      |  MacRxEnable       | MacPromiscuousModeOn	| \                        MacPadStripEnable |  MacHashFilterOn   | MacPerfectFilterOff 	| \                        MacRetryDisable   | MacFullDuplex      | MacHeartBeatOff)#else #define ETH_MAC_FLAGS	(MacTxEnable   	  | MacRxEnable        | MacPromiscuousModeOff  | \			MacPadStripEnable | MacHashFilterOn    | MacPerfectFilterOn     | \                        MacRetryDisable   | MacFullDuplex      | MacMulticastFilterOn   | \			MacHeartBeatOff)#define DEFAULT_BROADCAST_ADDRESS { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF }#endif /*USE_HW_FILTERING*/#define MP_FRAME_FLAGS  (DescRxLast        | DescRxFirst)#define TX_DESC1_FLAGS 	(DescTxLast        | DescTxFirst        | DescChain)#define RX_ERROR_FLAGS  (DescFilteringFail | DescError		| DescRxTruncated	| \			DescLengthError    | DescRxDamaged 	| DescRxLongFrame	| \			DescRxLongFrame	   | DescRxCollision	| DescRxMiiError	| \			DescRxCrc)#define TX_ERROR_FLAGS  (DescTxLostCarrier | DescTxNoCarrier	| DescTxLateCollision 	| \			DescTxExcCollisions| DescTxHeartbeatFail| DescTxUnderflow)/* Number of descriptors and buffer size */#define MIN_NUM_RDESC	8#define MIN_NUM_TDESC	8#define NUM_RDESC 	32	#define NUM_TDESC	16	#define R_BUF_SIZE	0x700	/* needs to be < 2KB */#define T_BUF_SIZE	0x700	/* needs to be < 2KB *//* Private data for this ethernet device */typedef struct {	struct net_device_stats stats; /* stats */	unsigned long last_rxidx;      /* last rx idx to descriptor */	unsigned long next_txidx;      /* next tx idx to descriptor */} EM86XX_ETH_PRIV;/* Descriptors and buffers: notice the alignments */#ifdef STATIC_BUF_ALLOC static struct em86xx_desc eth_rxdsc[NUM_RDESC] __attribute__ ((__aligned__(16)));static struct em86xx_desc eth_txdsc[NUM_TDESC] __attribute__ ((__aligned__(16)));static unsigned char eth_rxbuf[NUM_RDESC * R_BUF_SIZE] __attribute__ ((__aligned__(16)));static unsigned char eth_txbuf[NUM_TDESC * T_BUF_SIZE] __attribute__ ((__aligned__(16)));#elsestatic struct em86xx_desc *eth_rxdsc 	= NULL;static struct em86xx_desc *eth_txdsc 	= NULL;static unsigned char *eth_rxbuf 	= NULL;static unsigned char *eth_txbuf		= NULL;static unsigned long desc_page  	= 0L;static unsigned long rxbuf_pages 	= 0L;static unsigned long txbuf_pages 	= 0L;static unsigned long rxbuf_order 	= 0L;static unsigned long txbuf_order 	= 0L;#endif/* Number of descriptors */static unsigned long num_rxdesc = NUM_RDESC;static unsigned long num_txdesc = NUM_TDESC;/* The real data pointer to be accessed in non-cache region */static volatile struct em86xx_desc *rxdsc = NULL;static volatile struct em86xx_desc *txdsc = NULL;static volatile unsigned char *rxbuf	  = NULL;static volatile unsigned char *txbuf	  = NULL;/* Reference count for device */static int dev_count = 0;/* For storing MAC address */static unsigned long def_mac_hi = DEF_MAC_HI;static unsigned long def_mac_lo = DEF_MAC_LO;/* Link status flag */static volatile int link_up 		 = 0;static volatile int link_configured	 = 0;static unsigned long max_link_loop	 = 0;static unsigned long ld_count		 = 0;static int reset_flag			 = 0;static int em86xx_eth_reset_desc(struct net_device *dev, int *reset);#ifdef BOOTLOADERstatic void em86xx_eth_intr_handler(int irq, void *dev_id);#elsestatic struct timer_list eth_timer;static struct net_device em86xx_eth_dev;static void em86xx_eth_intr_handler(int irq, void *dev_id, struct pt_regs *regs);MODULE_AUTHOR("Craig Qu");MODULE_DESCRIPTION("Sigma Designs ethernet driver");MODULE_LICENSE("GPL");MODULE_PARM(def_mac_hi, "i");MODULE_PARM(def_mac_lo, "i");#ifndef STATIC_BUF_ALLOC MODULE_PARM(num_rxdesc, "i");MODULE_PARM(num_txdesc, "i");#endif#endif /* BOOTLOADER *//* Get the device mac address */static int em86xx_get_macaddr(unsigned char *addr){#ifdef BOOTLOADER	if(	mac_read(addr) == -1) {		*addr++ = (def_mac_hi & 0x0000ff00) >> 8;		*addr++ = (def_mac_hi & 0x000000ff);		*addr++ = (def_mac_lo & 0xff000000) >> 24;		*addr++ = (def_mac_lo & 0x00ff0000) >> 16;		*addr++ = (def_mac_lo & 0x0000ff00) >> 8;		*addr   = (def_mac_lo & 0x000000ff);	}#else	*addr++ = (def_mac_hi & 0x0000ff00) >> 8;	*addr++ = (def_mac_hi & 0x000000ff);	*addr++ = (def_mac_lo & 0xff000000) >> 24;	*addr++ = (def_mac_lo & 0x00ff0000) >> 16;	*addr++ = (def_mac_lo & 0x0000ff00) >> 8;	*addr   = (def_mac_lo & 0x000000ff);#endif		return 0;}/* Setting up MAC address of ethernet PHY and device data */static int em86xx_set_mac(struct net_device *dev){	unsigned long hi_mac, low_mac;	/* Set up device mac address */	if (em86xx_get_macaddr(dev->dev_addr))		return(-EIO);	if (!is_valid_ether_addr(dev->dev_addr))		MSG_PRINT("%s: bogus mac address detected.\n", dev->name);	hi_mac =  (dev->dev_addr[5] << 8)  | dev->dev_addr[4];	low_mac = (dev->dev_addr[3] << 24) | (dev->dev_addr[2] << 16) | 		  (dev->dev_addr[1] << 8)  | dev->dev_addr[0];	/* Set up MAC address */	em86xx_write_reg(EM86XX_MACAHR_REG, hi_mac);	em86xx_write_reg(EM86XX_MACALR_REG, low_mac);	return 0;}#ifndef BOOTLOADER/* Setting customized mac address */static int em86xx_eth_set_macaddr(struct net_device *dev, void *addr){	unsigned long hi_mac, low_mac;	/* Check if given address is valid ethernet MAC address */	if (!is_valid_ether_addr(addr))		return(-EIO);	/* Turn off IRQ and stop receive/transmit */	em86xx_write_reg(EM86XX_CR_REG, 0);	em86xx_write_reg(EM86XX_IER_REG, 0);	netif_carrier_off(dev); /* Shutdown interface */	/* Save the customize mac address */	memcpy(dev->dev_addr, addr, 6);	hi_mac  = (dev->dev_addr[5] << 8) | dev->dev_addr[4];	low_mac = (dev->dev_addr[3] << 24)| (dev->dev_addr[2] << 16) | 		  (dev->dev_addr[1] << 8) | dev->dev_addr[0];	def_mac_hi = hi_mac;	def_mac_lo = low_mac;	/* Set up MAC address */	em86xx_write_reg(EM86XX_MACAHR_REG, hi_mac );	em86xx_write_reg(EM86XX_MACALR_REG, low_mac );	/* Restart everything */	link_up = link_configured = 0;	return 0;}#endif /* BOOTLOADER *//*serach for phy address */static int em86xx_phy_probe(void){        int phy_addr 	= 0;	u16 phy_id 	= 0;        u16 phy_status 	= 0;        /* search for total of 32 possible mii phy addresses */        for (phy_addr = 0; phy_addr < 32; phy_addr++) {                register int i;                for(i = 0; i < 2; i++)                        phy_status = em86xx_mii_read(phy_addr,GEN_sts);                if (phy_status != 0xffff && phy_status != 0x0000)			break;	}	phy_id =  em86xx_mii_read(phy_addr,GEN_id_lo);	DBG_PRINT("Found PHY RTL%04x at Addr = %d Status=0x%x\n", phy_id, phy_addr, phy_status); 	return phy_addr;}/* Initialize the ethernet link status, mac, and flow control */static int em86xx_link_config(struct net_device *dev, int timeout){	unsigned long word = 0; 	int i = timeout, fdx = 0, speed = 0, phy_addr= 0;	/* If link is up and configured, don't do anything */	if ((link_up != 0) && (link_configured != 0))		return 0;	else		DBG_PRINT("%s: re-configure link (%ld).\n", dev->name, i);	/* Turn off IRQ and stop receive/transmit */	em86xx_write_reg(EM86XX_CR_REG, 0);	em86xx_write_reg(EM86XX_IER_REG, 0);	/*get PHY addr*/		phy_addr = em86xx_phy_probe();        /* wait for autonegotiation complete */        while( i-- > 0 ) {                if( (em86xx_mii_read(phy_addr, GEN_sts) & AUTOCMPLT) != 0 )			break;        }	if (i == 0)		MSG_PRINT("%s: auto-negotiation failed.\n", dev->name);        if( (em86xx_mii_read(phy_addr, GEN_sts) & LINK) == 0 ) {		printk( "\nem86xx_eth::open(%s) - no link\n", dev->name );		return -ENODEV;        } else  		link_up = 1;        fdx = (em86xx_mii_read(phy_addr, GEN_ctl) & DUPLEX) != 0;        printk(  "\nem86xx_eth::open(%s) - %s-duplex mode\n",                       dev->name, fdx ? "Full" : "Half" );        speed = (em86xx_mii_read(phy_addr, GEN_ctl) & SPEED) != 0;        printk(  "em86xx_eth::open(%s) - 10%s Mbit/s\n",                           dev->name, speed ? "0" : "" );	/* set the descriptor base address */	em86xx_write_reg(EM86XX_RLBAR_REG, (u32)rxdsc);	em86xx_write_reg(EM86XX_TLBAR_REG, (u32)txdsc);		/* configure PHY if, MII with 100Mbps or 10Mbps */	word = MiiIfExtPhyMii | ((speed) ? MiiIfSpeed100M : MiiIfSpeed10M);	em86xx_write_reg(EM86XX_IFR_REG, word); 	/* set bus mode: burst length = 32 | BLE | ~DBO */	word = (32 << 8) /*| (1 << 7) | (1 << 20)*/ ;	em86xx_write_reg(EM86XX_BMR_REG, word); 	/* enable MAC flow ctrl */	word = (1 << 1);	em86xx_write_reg(EM86XX_FCR_REG, word); 	/* configure MAC ctrller */	word = ETH_MAC_FLAGS;	word |= MacLoopbackOff; 	if (fdx)  		word |= MacFullDuplex;    	em86xx_write_reg(EM86XX_MACCR_REG, word);	/* Turn on the IRQ and start receive/transmit */	em86xx_write_reg(EM86XX_IER_REG, ETH_IRQ_FLAGS);	em86xx_write_reg(EM86XX_CR_REG, ETH_RXTX_FLAGS); 	link_configured = 1;	return 0;}#ifdef USE_HW_FILTERINGstatic int em86xx_hash( u8 addr[6] ){        int i;        u32 crc = 0xFFFFFFFF;        u32 poly = 0xEDB88320;        //u32 poly = 0x04C11DB7;        for( i=0; i<6; i++ ){                int bit;                u8 data = addr[i];                for( bit=0; bit<8; bit++ ){                        int p = (crc^data) & 1;                        crc >>= 1;                        if( p != 0 ) crc ^= poly;                        data >>= 1;                }        }        /* return upper 6 bits */        return (crc>>26) & 0x3F;}#endif/* Ethernet hardware initialization */static int em86xx_eth_hw_init(struct net_device *dev){#ifdef USE_HW_FILTERING	int n = 0; 	u8  broadcast_addr[6]  = DEFAULT_BROADCAST_ADDRESS;#endif	/* reset dma engine*/	em86xx_write_reg(EM86XX_BMR_REG, DmaResetOn);	/*em86xx_write_reg(EM86XX_BMR_REG, DmaResetOff);*/

⌨️ 快捷键说明

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