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

📄 drivers_net_arm_ep93xx_eth_c_diff.htm

📁 linux2.6.11.6drivers_net_arm_ep93xx_eth_c
💻 HTM
📖 第 1 页 / 共 5 页
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- saved from url=(0086)http://members.inode.at/m.burian/ep93xx/patches/acme/drivers_net_arm_ep93xx_eth.c.diff -->
<HTML><HEAD>
<META content="text/html; charset=iso-8859-1" http-equiv=Content-Type>
<META content="MSHTML 5.00.3502.5390" name=GENERATOR></HEAD>
<BODY><XMP>--- linux-2.6.12/drivers/net/arm/ep93xx_eth.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.12-ep93xx-gao5-fix-ethernet-hang/drivers/net/arm/ep93xx_eth.c	2005-07-12 08:55:35.000000000 +0200
@@ -0,0 +1,1868 @@
+/*----------------------------------------------------------------------------
+ * ep93xx_eth.c
+ *  Ethernet Device Driver for Cirrus Logic EP93xx.
+ *
+ * Copyright (C) 2003 by Cirrus Logic www.cirrus.com 
+ * This software may be used and distributed according to the terms
+ * of the GNU Public License.
+ *
+ *   This driver was written based on skeleton.c by Donald Becker and
+ * smc9194.c by Erik Stahlman.  
+ *
+ * Theory of Operation
+ * Driver Configuration
+ *  - Getting MAC address from system
+ *     To setup identical MAC address for each target board, driver need
+ *      to get a MAC address from system.  Normally, system has a Serial 
+ *      EEPROM or other media to store individual MAC address when 
+ *      manufacturing.
+ *      The macro GET_MAC_ADDR is prepared to get the MAC address from 
+ *      system and one should supply a routine for this purpose.
+ * Driver Initialization
+ * DMA Operation
+ * Cache Coherence
+ *
+ * History:
+ * 07/19/01 0.1  Sungwook Kim  initial release
+ * 10/16/01 0.2  Sungwook Kim  add workaround for ignorance of Tx request while sending frame
+ *                             add some error stuations handling
+ *
+ * 03/25/03 Melody Lee Modified for EP93xx
+ *--------------------------------------------------------------------------*/
+
+static const char *version = "ep93xx_eth.c: V1.0 09/04/2003 Cirrus Logic\n";
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/in.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/irq.h>
+#include <asm/arch/hardware.h>
+
+#include "ep93xx_eth.h"
+
+/*----------------------------------------------------------------------------
+ * The name of the card.
+ * It is used for messages and in the requests for io regions, irqs and ...
+ * This device is not in a card but I used same name in skeleton.c file.
+ *--------------------------------------------------------------------------*/
+#define  cardname  "ep93xx_ethernet"
+
+/*----------------------------------------------------------------------------
+ * Macro to get MAC address from system
+ *
+ * Parameters:
+ *  - pD  : a pointer to the net device information, struct net_device.
+ *          one can get base address of device from pD->base_addr,
+ *          device instance ID (0 for 1st and so on) from netdev_priv(pD).
+ *  - pMac: a pointer to a 6 bytes length buffer to return device MAC address.
+ *          this buffer will be initialized with default_mac[] value before
+ *          calling.
+ * Return: none
+ *--------------------------------------------------------------------------*/
+#ifdef CONFIG_SENSORS_EEPROM
+
+#include <linux/i2c.h>
+
+static unsigned char ep93xx_mac_addr[8];
+static int ep93xx_mac_addr_valid = 0;
+
+int ep93xx_set_mac_addr(struct i2c_client *client)
+{
+	int i;
+
+	ep93xx_mac_addr[0] = i2c_smbus_read_byte_data(client, 0x00);
+
+	for (i=1; i<8; i++) {
+		ep93xx_mac_addr[i] = i2c_smbus_read_byte(client);
+	}
+
+	/* We use the "0x55-xx-xx-xx-xx-xx-xx-0xAA" as the signature. */
+	if (ep93xx_mac_addr[0] == 0x55 && ep93xx_mac_addr[7] == 0xaa) {
+		ep93xx_mac_addr_valid = 1;
+		return 1;
+	}
+	else {
+		return 0;
+	}
+}
+
+#define  GET_MAC_ADDR(pD, pMac) (ep93xx_mac_addr_valid && \
+				 memcpy(pMac, &(ep93xx_mac_addr[1]), 6) )
+#else
+#define  GET_MAC_ADDR(pD, pMac)
+#endif
+
+/****  default MAC address if GET_MAC_ADDR does not override  *************/
+/* static const u8  default_mac[6] = {0x00, 0xba, 0xd0, 0x0b, 0xad, 0x00}; */
+static const u8 default_mac[6] = { 0x78, 0x56, 0x34, 0x12, 0x1C, 0x32 };
+
+/*----------------------------------------------------------------------------
+ * A List of default device port configuration for auto probing.
+ * At this time, the CPU has only one Ethernet device,
+ * but better to support multiple device configuration.
+ * Keep in mind that the array must end in zero.
+ *--------------------------------------------------------------------------*/
+
+/* We get the MAC_BASE from include/asm-arm/arch-ep93xx/regmap.h */
+static struct {
+	unsigned int baseAddr;	/*base address, (0:end mark) */
+	int irq;		/*IRQ number, (0:auto detect) */
+} portList[] __initdata = {
+	{
+	MAC_BASE, 39}, {
+	0 /*end mark */ , 0}
+};
+
+/*----------------------------------------------------------------------------
+ * Some definitions belong to the operation of this driver.
+ * You should understand how it affect to driver before any modification.
+ *--------------------------------------------------------------------------*/
+
+/****  Interrupt Sources in Use  *******************************************/
+/*#define  Default_IntSrc  (IntEn_RxMIE|IntEn_RxSQIE|IntEn_TxLEIE|IntEn_TIE|IntEn_TxSQIE|IntEn_RxEOFIE|IntEn_RxEOBIE|IntEn_RxHDRIE)
+*/
+#define  Default_IntSrc  (IntEn_TxSQIE|IntEn_RxEOFIE|IntEn_RxEOBIE|IntEn_RxHDRIE)
+
+/****  Length of Device Queue in number of entries
+       (must be less than or equal to 255)  ********************************/
+#define  LEN_QueRxDesc  64	/*length of Rx Descriptor Queue (4 or bigger) Must be power of 2. */
+#define  LEN_QueRxSts   LEN_QueRxDesc	/*length of Rx Status Queue */
+#define  LEN_QueTxDesc  8	/*length of Tx Descriptor Queue (4 or bigger) Must be power of 2. */
+#define  LEN_QueTxSts   LEN_QueTxDesc	/*length of Tx Status Queue */
+
+/****  Tx Queue fill-up level control  *************************************/
+#define  LVL_TxStop    LEN_QueTxDesc - 2	/*level to ask the stack to stop Tx */
+#define  LVL_TxResume  2	/*level to ask the stack to resume Tx */
+
+/****  Rx Buffer length in bytes  ******************************************/
+#define  LEN_RxBuf  (1518+2+16)	/*length of Rx buffer, must be 4-byte aligned */
+#define  LEN_TxBuf   LEN_RxBuf
+
+/*----------------------------------------------------------------------------
+ * MACRO for ease
+ *--------------------------------------------------------------------------*/
+
+#define  Align32(a)  (((unsigned int)(a)+3)&~0x03)	/*32bit address alignment */
+#define  IdxNext(idxCur,len)  (((idxCur)+1)%(len))	/*calc next array index number */
+
+/****  malloc/free routine for DMA buffer  **********************************/
+ /*use non-cached DMA buffer */
+/* #define  MALLOC_DMA(size, pPhyAddr)  consistent_alloc(GFP_KERNEL|GFP_DMA, (size), (dma_addr_t*)(pPhyAddr), NULL) */
+#define MALLOC_DMA(size, pPhyAddr) dma_alloc_coherent(NULL, size, (dma_addr_t*)(pPhyAddr),  GFP_KERNEL|GFP_DMA)
+#define  FREE_DMA(vaddr)            consistent_free(vaddr)
+extern void cpu_arm920_dcache_clean_range(u32 va_bgn, u32 va_end);
+#define  dma_cache_wback(vaddr,size)  cpu_arm920_dcache_clean_range((u32)(vaddr),(u32)(vaddr)+(size)-1)
+
+/*----------------------------------------------------------------------------
+ * DEBUGGING LEVELS
+ *
+ * 0 for normal operation
+ * 1 for slightly more details
+ * >2 for various levels of increasingly useless information
+ *    2 for interrupt tracking, status flags
+ *    3 for packet dumps, etc.
+ *--------------------------------------------------------------------------*/
+#define  _DBG  0
+
+#if (_DBG > 2 )
+#define PRINTK3(x) printk x
+#else
+#define PRINTK3(x)
+#endif
+
+#if _DBG > 1
+#define PRINTK2(x) printk x
+#else
+#define PRINTK2(x)
+#endif
+
+#if _DBG > 0
+#define PRINTK1(x) printk x
+#else
+#define PRINTK1(x)
+#endif
+
+#ifdef _DBG
+#define PRINTK(x) printk x
+#else
+#define PRINTK(x)
+#endif
+
+#define  _PRTK_ENTRY      PRINTK2	/*to trace function entries */
+#define  _PRTK_SWERR      PRINTK	/*logical S/W error */
+#define  _PRTK_SYSFAIL    PRINTK	/*system service failure */
+#define  _PRTK_HWFAIL     PRINTK	/*H/W operation failure message */
+#define  _PRTK_WARN       PRINTK1	/*warning information */
+#define  _PRTK_INFO       PRINTK2	/*general information */
+#define  _PRTK_ENTRY_ISR  PRINTK3	/*to trace function entries belong to ISR */
+#define  _PRTK_WARN_ISR   PRINTK1	/*warning informations from ISR */
+#define  _PRTK_INFO_ISR   PRINTK3	/*general informations from ISR */
+#define  _PRTK_           PRINTK	/*for temporary print out */
+
+#if 0
+# define  _PRTK_DUMP       PRINTK1	/*to dump large amount of debug info */
+#endif
+
+/*----------------------------------------------------------------------------
+ * Custom Data Structures
+ *--------------------------------------------------------------------------*/
+
+/****  the information about the buffer passed to device.
+       there are matching bufferDescriptor informations 
+       for each Tx/Rx Descriptor Queue entry to trace 
+       the buffer within those queues.  ************************************/
+struct bufferDescriptor {
+	void *vaddr;		/*virtual address representing the buffer passed to device */
+	int (*pFreeRtn) (void *pBuf);	/*free routine */
+};
+
+/****  device privite informations
+       pointed by struct net_device::priv  *********************************/
+struct ep93xxEth_info {
+    /****  static device informations  **********************************/
+	struct {
+		int id;		/*device instance ID (0 for 1st and so on)
+				   must be first element of this structure */
+		union receiveDescriptor *pQueRxDesc;	/*pointer to Rx Descriptor Queue */
+		union receiveStatus *pQueRxSts;	/*pointer to Rx Status Queue */
+		union transmitDescriptor *pQueTxDesc;	/*pointer to Tx Descriptor Queue */
+		union transmitStatus *pQueTxSts;	/*pointer to Tx Status Queue */
+		unsigned char *pRxBuf;	/*base of Rx Buffer pool */
+		unsigned char *pTxBuf;	/*base of Tx Buffer pool */
+		unsigned long phyQueueBase;	/*physical address of device queues */
+		unsigned long phyQueRxDesc,	/*physical address of Rx Descriptor Queue */
+		 phyQueRxSts,	/*physical address of Rx Status Queue */
+		 phyQueTxDesc,	/*physical address of Tx Descriptor Queue */
+		 phyQueTxSts,	/*physical address of Tx Status Queue */
+		 phyRxBuf,	/*physical address of Rx Buffer pool */
+		 phyTxBuf;	/*physical address of Tx Buffer pool */
+		struct bufferDescriptor *pRxBufDesc,	/*info of Rx Buffers */
+		*pTxBufDesc;	/*info of Tx Buffers */
+		int miiIdPhy;	/*MII Bus ID of Ethernet PHY */
+	} s;
+    /****  dynamic information, subject to clear when device open  ******/
+	struct {
+		struct net_device_stats stats;	/*statistic data */
+		int idxQueRxDesc,	/*next processing index of device queues */
+		 idxQueRxSts, idxQueTxDescHead, idxQueTxDescTail, idxQueTxSts;
+		int txStopped;	/*flag for Tx condition */
+	} d;
+};
+
+/*----------------------------------------------------------------------------
+ * Global Variables
+ *--------------------------------------------------------------------------*/
+static int numOfInstance = 0;	/*total number of device instance, 0 means the 1st instance. */
+
+/*static struct sk_buff gTxSkb; */
+/*static char gTxBuff[LEN_TxBuf]; */
+
+static char gTxDataBuff[LEN_QueTxDesc][LEN_TxBuf];
+
+/* To know if PHY auto-negotiation has done? */
+static int gPhyAutoNegoDone = 0;
+
+/*----------------------------------------------------------------------------
+ * Function Proto-types
+ *--------------------------------------------------------------------------*/
+struct net_device *__init ep93xx_probe(int unit);
+static int do_ep93xx_probe(struct net_device *pD);
+static int ep93xxEth_open(struct net_device *pD);
+static int ep93xxEth_close(struct net_device *pD);
+static int ep93xxEth_hardStartXmit(struct sk_buff *pSkb, struct net_device *pD);
+static void ep93xxEth_txTimeout(struct net_device *pD);
+static void ep93xxEth_setMulticastList(struct net_device *pD);
+static struct net_device_stats *ep93xxEth_getStats(struct net_device *pD);
+
+static irqreturn_t ep93xxEth_isr(int irq, void *pDev, struct pt_regs *pRegs);
+
+/*============================================================================
+ *
+ * Internal Routines
+ *
+ *==========================================================================*/
+
+/*****************************************************************************
+* free_skb()
+*****************************************************************************/
+static int free_skb(void *pSkb)
+{
+	dev_kfree_skb_irq((struct sk_buff *)pSkb);
+	return 0;
+}				/*free_skb() */
+
+/*****************************************************************************
+* waitOnReg32()
+*****************************************************************************/
+static int waitOnReg32(struct net_device *pD, int reg,
+		       unsigned long mask, unsigned long expect, int tout)
+{
+	int i;
+	int dt;
+
+/*    _PRTK_ENTRY(("waitOnReg32(pD:0x%x,reg:0x%x,mask:0x%x,expect:0x%x,tout:%d)\n",
+                 pD,reg,mask,expect,tout));
+*/
+
+	for (i = 0; i < 10000;) {
+		dt = RegRd32(reg);
+		dt = (dt ^ expect) & mask;
+		if (0 == dt)
+			break;
+		if (tout)
+			i++;
+	}			/*for */
+	return dt;
+}				/*waitOnReg32() */
+
+#define  phy_wr(reg,dt)  _phy_write(pD, ((struct ep93xxEth_info*)netdev_priv(pD))->s.miiIdPhy, (reg), (dt))
+#define  phy_rd(reg)     _phy_read(pD, ((struct ep93xxEth_info*)netdev_priv(pD))->s.miiIdPhy, (reg))
+#define  phy_waitRdy()  waitOnReg32(pD, REG_MIISts,MIISts_Busy, ~MIISts_Busy, 1)
+
+/*****************************************************************************
+* _phy_write()
+*****************************************************************************/
+static void _phy_write(struct net_device *pD, int idPhy, int reg, u16 dt)
+{
+
+/*    _PRTK_ENTRY(("_phy_write(pD:0x%p,idPhy:%d,reg:0x%x,dt:0x%x)\n",pD,idPhy,reg,dt));*/
+
+	phy_waitRdy();
+	RegWr32(REG_MIIData, dt);
+	RegWr32(REG_MIICmd,
+		MIICmd_OP_WR | ((idPhy & 0x1f) << 5) | ((reg & 0x1f) << 0));

⌨️ 快捷键说明

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