?? drivers_net_arm_ep93xx_eth_c_diff.htm
字號:
<!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 + -