📄 smsc911x.c
字号:
/***************************************************************************
*
* Copyright (C) 2004-2005 SMSC
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that 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.
*
***************************************************************************
* File: smsc911x.c
* see readme.txt for programmers guide
*/
#ifndef __KERNEL__
# define __KERNEL__
#endif
#ifdef USING_LINT
#include "lint.h"
#else //not USING_LINT
#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/ioport.h>
#include <linux/errno.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/delay.h>
#include <linux/mii.h>
#include <linux/timer.h>
#include <asm/irq.h>
#include <asm/dma.h>
#include <asm/bitops.h>
#include <linux/version.h>
#endif //not USING_LINT
static const char date_code[] = "022805";
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
typedef void irqreturn_t;
#define IRQ_NONE
#define IRQ_HANDLED
#define IRQ_RETVAL(x)
#else
#define LINUX_2_6_OR_NEWER
#endif
//select platform, batch or make file should define one of these
//#define USE_PEAKS
//#define USE_PEAKS_LITE
//#define USE_SH3_SE01
//#define USE_SH3_POLARIS
//#define USE_XSCALE
#ifdef USE_DEBUG
//select debug modes
#define USE_WARNING
#define USE_TRACE
#define USE_ASSERT
#endif //USE_DEBUG
typedef long TIME_SPAN;
#define MAX_TIME_SPAN ((TIME_SPAN)(0x7FFFFFFFUL))
typedef unsigned long DWORD;
typedef unsigned short WORD;
typedef unsigned char BYTE;
typedef unsigned char BOOLEAN;
#define TRUE ((BOOLEAN)1)
#define FALSE ((BOOLEAN)0)
#define HIBYTE(word) ((BYTE)(((WORD)(word))>>8))
#define LOBYTE(word) ((BYTE)(((WORD)(word))&0x00FFU))
#define HIWORD(dWord) ((WORD)(((DWORD)(dWord))>>16))
#define LOWORD(dWord) ((WORD)(((DWORD)(dWord))&0x0000FFFFUL))
#define TRANSFER_PIO (256UL)
#define TRANSFER_REQUEST_DMA (255UL)
//these are values that can be assigned to
//PLATFORM_RX_DMA
//PLATFORM_TX_DMA
// in addition to any specific dma channel
/*******************************************************
* Macro: SMSC_TRACE
* Description:
* This macro is used like printf.
* It can be used anywhere you want to display information
* For any release version it should not be left in
* performance sensitive Tx and Rx code paths.
* To use this macro define USE_TRACE and set bit 0 of debug_mode
*******************************************************/
#ifdef USING_LINT
extern void SMSC_TRACE(const char * a, ...);
#else //not USING_LINT
#ifdef USE_TRACE
extern DWORD debug_mode;
#ifndef USE_WARNING
#define USE_WARNING
#endif
# define SMSC_TRACE(msg,args...) \
if(debug_mode&0x01UL) { \
printk("SMSC: " msg "\n", ## args); \
}
#else
# define SMSC_TRACE(msg,args...)
#endif
#endif //not USING_LINT
/*******************************************************
* Macro: SMSC_WARNING
* Description:
* This macro is used like printf.
* It can be used anywhere you want to display warning information
* For any release version it should not be left in
* performance sensitive Tx and Rx code paths.
* To use this macro define USE_TRACE or
* USE_WARNING and set bit 1 of debug_mode
*******************************************************/
#ifdef USING_LINT
extern void SMSC_WARNING(const char * a, ...);
#else //not USING_LINT
#ifdef USE_WARNING
extern DWORD debug_mode;
#ifndef USE_ASSERT
#define USE_ASSERT
#endif
# define SMSC_WARNING(msg, args...) \
if(debug_mode&0x02UL) { \
printk("SMSC_WARNING: " msg "\n",## args); \
}
#else
# define SMSC_WARNING(msg, args...)
#endif
#endif //not USING_LINT
/*******************************************************
* Macro: SMSC_ASSERT
* Description:
* This macro is used to test assumptions made when coding.
* It can be used anywhere, but is intended only for situations
* where a failure is fatal.
* If code execution where allowed to continue it is assumed that
* only further unrecoverable errors would occur and so this macro
* includes an infinite loop to prevent further corruption.
* Assertions are only intended for use during developement to
* insure consistency of logic through out the driver.
* A driver should not be released if assertion failures are
* still occuring.
* To use this macro define USE_TRACE or USE_WARNING or
* USE_ASSERT
*******************************************************/
#ifdef USING_LINT
extern void SMSC_ASSERT(BOOLEAN condition);
#else //not USING_LINT
#ifdef USE_ASSERT
# define SMSC_ASSERT(condition) \
if(!(condition)) { \
printk("SMSC_ASSERTION_FAILURE: File=" __FILE__ ", Line=%d\n",__LINE__); \
while(1); \
}
#else
# define SMSC_ASSERT(condition)
#endif
#endif //not USING_LINT
#define Lan_GetRegDW(dwOffset) \
((*(volatile DWORD *)(privateData->dwLanBase+dwOffset)))
#define Lan_SetRegDW(dwOffset,dwVal) \
((*(volatile DWORD *)(privateData->dwLanBase+dwOffset))=(dwVal))
#define Lan_ClrBitsDW(dwOffset,dwBits) \
((*(volatile DWORD *)(privateData->dwLanBase+dwOffset))&=(~dwBits))
#define Lan_SetBitsDW(dwOffset,dwBits) \
((*(volatile DWORD *)(privateData->dwLanBase+dwOffset))|=(dwBits))
//Below are the register offsets and bit definitions
// of the Lan911x memory space
#define RX_DATA_FIFO (0x00UL)
#define TX_DATA_FIFO (0x20UL)
#define TX_CMD_A_INT_ON_COMP_ (0x80000000UL)
#define TX_CMD_A_INT_BUF_END_ALGN_ (0x03000000UL)
#define TX_CMD_A_INT_4_BYTE_ALGN_ (0x00000000UL)
#define TX_CMD_A_INT_16_BYTE_ALGN_ (0x01000000UL)
#define TX_CMD_A_INT_32_BYTE_ALGN_ (0x02000000UL)
#define TX_CMD_A_INT_DATA_OFFSET_ (0x001F0000UL)
#define TX_CMD_A_INT_FIRST_SEG_ (0x00002000UL)
#define TX_CMD_A_INT_LAST_SEG_ (0x00001000UL)
#define TX_CMD_A_BUF_SIZE_ (0x000007FFUL)
#define TX_CMD_B_PKT_TAG_ (0xFFFF0000UL)
#define TX_CMD_B_ADD_CRC_DISABLE_ (0x00002000UL)
#define TX_CMD_B_DISABLE_PADDING_ (0x00001000UL)
#define TX_CMD_B_PKT_BYTE_LENGTH_ (0x000007FFUL)
#define RX_STATUS_FIFO (0x40UL)
#define RX_STS_ES_ (0x00008000UL)
#define RX_STS_MCAST_ (0x00000400UL)
#define RX_STATUS_FIFO_PEEK (0x44UL)
#define TX_STATUS_FIFO (0x48UL)
#define TX_STATUS_FIFO_PEEK (0x4CUL)
#define ID_REV (0x50UL)
#define ID_REV_CHIP_ID_ (0xFFFF0000UL) // RO
#define ID_REV_REV_ID_ (0x0000FFFFUL) // RO
#define INT_CFG (0x54UL)
#define INT_CFG_INT_DEAS_ (0xFF000000UL) // R/W
#define INT_CFG_IRQ_INT_ (0x00001000UL) // RO
#define INT_CFG_IRQ_EN_ (0x00000100UL) // R/W
#define INT_CFG_IRQ_POL_ (0x00000010UL) // R/W Not Affected by SW Reset
#define INT_CFG_IRQ_TYPE_ (0x00000001UL) // R/W Not Affected by SW Reset
#define INT_STS (0x58UL)
#define INT_STS_SW_INT_ (0x80000000UL) // R/WC
#define INT_STS_TXSTOP_INT_ (0x02000000UL) // R/WC
#define INT_STS_RXSTOP_INT_ (0x01000000UL) // R/WC
#define INT_STS_RXDFH_INT_ (0x00800000UL) // R/WC
#define INT_STS_RXDF_INT_ (0x00400000UL) // R/WC
#define INT_STS_TX_IOC_ (0x00200000UL) // R/WC
#define INT_STS_RXD_INT_ (0x00100000UL) // R/WC
#define INT_STS_GPT_INT_ (0x00080000UL) // R/WC
#define INT_STS_PHY_INT_ (0x00040000UL) // RO
#define INT_STS_PME_INT_ (0x00020000UL) // R/WC
#define INT_STS_TXSO_ (0x00010000UL) // R/WC
#define INT_STS_RWT_ (0x00008000UL) // R/WC
#define INT_STS_RXE_ (0x00004000UL) // R/WC
#define INT_STS_TXE_ (0x00002000UL) // R/WC
#define INT_STS_ERX_ (0x00001000UL) // R/WC
#define INT_STS_TDFU_ (0x00000800UL) // R/WC
#define INT_STS_TDFO_ (0x00000400UL) // R/WC
#define INT_STS_TDFA_ (0x00000200UL) // R/WC
#define INT_STS_TSFF_ (0x00000100UL) // R/WC
#define INT_STS_TSFL_ (0x00000080UL) // R/WC
#define INT_STS_RDFO_ (0x00000040UL) // R/WC
#define INT_STS_RDFL_ (0x00000020UL) // R/WC
#define INT_STS_RSFF_ (0x00000010UL) // R/WC
#define INT_STS_RSFL_ (0x00000008UL) // R/WC
#define INT_STS_GPIO2_INT_ (0x00000004UL) // R/WC
#define INT_STS_GPIO1_INT_ (0x00000002UL) // R/WC
#define INT_STS_GPIO0_INT_ (0x00000001UL) // R/WC
#define INT_EN (0x5CUL)
#define INT_EN_SW_INT_EN_ (0x80000000UL) // R/W
#define INT_EN_TXSTOP_INT_EN_ (0x02000000UL) // R/W
#define INT_EN_RXSTOP_INT_EN_ (0x01000000UL) // R/W
#define INT_EN_RXDFH_INT_EN_ (0x00800000UL) // R/W
#define INT_EN_RXDF_INT_EN_ (0x00400000UL) // R/W
#define INT_EN_TIOC_INT_EN_ (0x00200000UL) // R/W
#define INT_EN_RXD_INT_EN_ (0x00100000UL) // R/W
#define INT_EN_GPT_INT_EN_ (0x00080000UL) // R/W
#define INT_EN_PHY_INT_EN_ (0x00040000UL) // R/W
#define INT_EN_PME_INT_EN_ (0x00020000UL) // R/W
#define INT_EN_TXSO_EN_ (0x00010000UL) // R/W
#define INT_EN_RWT_EN_ (0x00008000UL) // R/W
#define INT_EN_RXE_EN_ (0x00004000UL) // R/W
#define INT_EN_TXE_EN_ (0x00002000UL) // R/W
#define INT_EN_ERX_EN_ (0x00001000UL) // R/W
#define INT_EN_TDFU_EN_ (0x00000800UL) // R/W
#define INT_EN_TDFO_EN_ (0x00000400UL) // R/W
#define INT_EN_TDFA_EN_ (0x00000200UL) // R/W
#define INT_EN_TSFF_EN_ (0x00000100UL) // R/W
#define INT_EN_TSFL_EN_ (0x00000080UL) // R/W
#define INT_EN_RDFO_EN_ (0x00000040UL) // R/W
#define INT_EN_RDFL_EN_ (0x00000020UL) // R/W
#define INT_EN_RSFF_EN_ (0x00000010UL) // R/W
#define INT_EN_RSFL_EN_ (0x00000008UL) // R/W
#define INT_EN_GPIO2_INT_ (0x00000004UL) // R/W
#define INT_EN_GPIO1_INT_ (0x00000002UL) // R/W
#define INT_EN_GPIO0_INT_ (0x00000001UL) // R/W
#define BYTE_TEST (0x64UL)
#define FIFO_INT (0x68UL)
#define FIFO_INT_TX_AVAIL_LEVEL_ (0xFF000000UL) // R/W
#define FIFO_INT_TX_STS_LEVEL_ (0x00FF0000UL) // R/W
#define FIFO_INT_RX_AVAIL_LEVEL_ (0x0000FF00UL) // R/W
#define FIFO_INT_RX_STS_LEVEL_ (0x000000FFUL) // R/W
#define RX_CFG (0x6CUL)
#define RX_CFG_RX_END_ALGN_ (0xC0000000UL) // R/W
#define RX_CFG_RX_END_ALGN4_ (0x00000000UL) // R/W
#define RX_CFG_RX_END_ALGN16_ (0x40000000UL) // R/W
#define RX_CFG_RX_END_ALGN32_ (0x80000000UL) // R/W
#define RX_CFG_RX_DMA_CNT_ (0x0FFF0000UL) // R/W
#define RX_CFG_RX_DUMP_ (0x00008000UL) // R/W
#define RX_CFG_RXDOFF_ (0x00001F00UL) // R/W
#define RX_CFG_RXBAD_ (0x00000001UL) // R/W
#define TX_CFG (0x70UL)
#define TX_CFG_TX_DMA_LVL_ (0xE0000000UL) // R/W
#define TX_CFG_TX_DMA_CNT_ (0x0FFF0000UL) // R/W Self Clearing
#define TX_CFG_TXS_DUMP_ (0x00008000UL) // Self Clearing
#define TX_CFG_TXD_DUMP_ (0x00004000UL) // Self Clearing
#define TX_CFG_TXSAO_ (0x00000004UL) // R/W
#define TX_CFG_TX_ON_ (0x00000002UL) // R/W
#define TX_CFG_STOP_TX_ (0x00000001UL) // Self Clearing
#define HW_CFG (0x74UL)
#define HW_CFG_TTM_ (0x00200000UL) // R/W
#define HW_CFG_SF_ (0x00100000UL) // R/W
#define HW_CFG_TX_FIF_SZ_ (0x000F0000UL) // R/W
#define HW_CFG_TR_ (0x00003000UL) // R/W
#define HW_CFG_PHY_CLK_SEL_ (0x00000060UL) // R/W
#define HW_CFG_PHY_CLK_SEL_INT_PHY_ (0x00000000UL) // R/W
#define HW_CFG_PHY_CLK_SEL_EXT_PHY_ (0x00000020UL) // R/W
#define HW_CFG_PHY_CLK_SEL_CLK_DIS_ (0x00000040UL) // R/W
#define HW_CFG_SMI_SEL_ (0x00000010UL) // R/W
#define HW_CFG_EXT_PHY_DET_ (0x00000008UL) // RO
#define HW_CFG_EXT_PHY_EN_ (0x00000004UL) // R/W
#define HW_CFG_32_16_BIT_MODE_ (0x00000004UL) // RO
#define HW_CFG_SRST_TO_ (0x00000002UL) // RO
#define HW_CFG_SRST_ (0x00000001UL) // Self Clearing
#define RX_DP_CTRL (0x78UL)
#define RX_DP_CTRL_RX_FFWD_ (0x00000FFFUL) // R/W
#define RX_DP_CTRL_FFWD_BUSY_ (0x80000000UL) // RO
#define RX_FIFO_INF (0x7CUL)
#define RX_FIFO_INF_RXSUSED_ (0x00FF0000UL) // RO
#define RX_FIFO_INF_RXDUSED_ (0x0000FFFFUL) // RO
#define TX_FIFO_INF (0x80UL)
#define TX_FIFO_INF_TSUSED_ (0x00FF0000UL) // RO
#define TX_FIFO_INF_TSFREE_ (0x00FF0000UL) // RO
#define TX_FIFO_INF_TDFREE_ (0x0000FFFFUL) // RO
#define PMT_CTRL (0x84UL)
#define PMT_CTRL_PM_MODE_ (0x00018000UL) // Self Clearing
#define PMT_CTRL_PHY_RST_ (0x00000400UL) // Self Clearing
#define PMT_CTRL_WOL_EN_ (0x00000200UL) // R/W
#define PMT_CTRL_ED_EN_ (0x00000100UL) // R/W
#define PMT_CTRL_PME_TYPE_ (0x00000040UL) // R/W Not Affected by SW Reset
#define PMT_CTRL_WUPS_ (0x00000030UL) // R/WC
#define PMT_CTRL_WUPS_NOWAKE_ (0x00000000UL) // R/WC
#define PMT_CTRL_WUPS_ED_ (0x00000010UL) // R/WC
#define PMT_CTRL_WUPS_WOL_ (0x00000020UL) // R/WC
#define PMT_CTRL_WUPS_MULTI_ (0x00000030UL) // R/WC
#define PMT_CTRL_PME_IND_ (0x00000008UL) // R/W
#define PMT_CTRL_PME_POL_ (0x00000004UL) // R/W
#define PMT_CTRL_PME_EN_ (0x00000002UL) // R/W Not Affected by SW Reset
#define PMT_CTRL_READY_ (0x00000001UL) // RO
#define GPIO_CFG (0x88UL)
#define GPIO_CFG_LED3_EN_ (0x40000000UL) // R/W
#define GPIO_CFG_LED2_EN_ (0x20000000UL) // R/W
#define GPIO_CFG_LED1_EN_ (0x10000000UL) // R/W
#define GPIO_CFG_GPIO2_INT_POL_ (0x04000000UL) // R/W
#define GPIO_CFG_GPIO1_INT_POL_ (0x02000000UL) // R/W
#define GPIO_CFG_GPIO0_INT_POL_ (0x01000000UL) // R/W
#define GPIO_CFG_EEPR_EN_ (0x00E00000UL) // R/W
#define GPIO_CFG_GPIOBUF2_ (0x00040000UL) // R/W
#define GPIO_CFG_GPIOBUF1_ (0x00020000UL) // R/W
#define GPIO_CFG_GPIOBUF0_ (0x00010000UL) // R/W
#define GPIO_CFG_GPIODIR2_ (0x00000400UL) // R/W
#define GPIO_CFG_GPIODIR1_ (0x00000200UL) // R/W
#define GPIO_CFG_GPIODIR0_ (0x00000100UL) // R/W
#define GPIO_CFG_GPIOD4_ (0x00000020UL) // R/W
#define GPIO_CFG_GPIOD3_ (0x00000010UL) // R/W
#define GPIO_CFG_GPIOD2_ (0x00000004UL) // R/W
#define GPIO_CFG_GPIOD1_ (0x00000002UL) // R/W
#define GPIO_CFG_GPIOD0_ (0x00000001UL) // R/W
#define GPT_CFG (0x8CUL)
#define GPT_CFG_TIMER_EN_ (0x20000000UL) // R/W
#define GPT_CFG_GPT_LOAD_ (0x0000FFFFUL) // R/W
#define GPT_CNT (0x90UL)
#define GPT_CNT_GPT_CNT_ (0x0000FFFFUL) // RO
#define FPGA_REV (0x94UL)
#define FPGA_REV_FPGA_REV_ (0x0000FFFFUL) // RO
#define ENDIAN (0x98UL)
#define FREE_RUN (0x9CUL)
#define RX_DROP (0xA0UL)
#define MAC_CSR_CMD (0xA4UL)
#define MAC_CSR_CMD_CSR_BUSY_ (0x80000000UL) // Self Clearing
#define MAC_CSR_CMD_R_NOT_W_ (0x40000000UL) // R/W
#define MAC_CSR_CMD_CSR_ADDR_ (0x000000FFUL) // R/W
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -