📄 em86xx_eth.c
字号:
/* * */#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 + -