📄 simp911x.c
字号:
//PMT_CTRL Not Used
//GPIO_CFG Only used during initialization, in Lan_Initialize
//GPT_CFG Not Used
//GPT_CNT Not Used
//ENDIAN Not Used
//FREE_RUN Not Used
//RX_DROP Only used in Rx Thread, Rx_ProcessPackets
//MAC_CSR_CMD Protected by MacPhyAccessLock
//MAC_CSR_DATA Protected by MacPhyAccessLock
// Because the two previous MAC_CSR_ registers are protected
// All MAC, and PHY registers are protected as well.
//AFC_CFG Used during initialization, in Lan_Initialize
// During run time, used in timer call back, in Phy_UpdateLinkMode
//E2P_CMD Used during initialization, in Lan_Initialize
//E2P_DATA Not Used
#define LINK_OFF (0x00UL)
#define LINK_SPEED_10HD (0x01UL)
#define LINK_SPEED_10FD (0x02UL)
#define LINK_SPEED_100HD (0x04UL)
#define LINK_SPEED_100FD (0x08UL)
#define LINK_SYMMETRIC_PAUSE (0x10UL)
#define LINK_ASYMMETRIC_PAUSE (0x20UL)
#define LINK_AUTO_NEGOTIATE (0x40UL)
typedef struct _PRIVATE_DATA {
DWORD dwLanBase;
DWORD dwInstanceIndex;
DWORD dwIdRev;
struct net_device *dev;
spinlock_t MacPhyAccessLock;
//The MacPhyAccessLock must be acquired before
// calling any of the following functions
// Mac_GetRegDW
// Mac_SetRegDW
// Phy_GetRegW
// Phy_SetRegW
// but only when multiple threads may be calling these functions
// concurrently. For this Driver this only occurs during runtime
// when the Timer callback calls Phy_UpdateLinkMode(), which
// can run concurrently with Rx_SetMulticastList().
// Acquiring the lock is not necessary during initialization
// and shutdown, since the other threads are not running
// at those times.
BOOLEAN RxCongested;
struct net_device_stats stats;
DWORD dwPhyAddress;
#ifdef USE_LED1_WORK_AROUND
DWORD NotUsingExtPhy;
#endif
DWORD dwLinkSpeed;
DWORD dwLinkSettings;
struct timer_list LinkPollingTimer;
BOOLEAN StopLinkPolling;
BOOLEAN RequestIrqDisable;
BOOLEAN SoftwareInterruptSignal;
#ifdef USE_PHY_WORK_AROUND
#define MIN_PACKET_SIZE (64)
DWORD dwTxStartMargen;
BYTE LoopBackTxPacket[MIN_PACKET_SIZE];
DWORD dwTxEndMargen;
DWORD dwRxStartMargen;
BYTE LoopBackRxPacket[MIN_PACKET_SIZE];
DWORD dwRxEndMargen;
DWORD dwResetCount;
#endif
} PRIVATE_DATA, *PPRIVATE_DATA;
/*
****************************************************************************
****************************************************************************
* MAC Control and Status Register (Indirect Address)
* Offset (through the MAC_CSR CMD and DATA port)
****************************************************************************
****************************************************************************
*
*/
#define MAC_CR (0x01UL) // R/W
/* MAC_CR - MAC Control Register */
#define MAC_CR_RXALL_ (0x80000000UL)
#define MAC_CR_HBDIS_ (0x10000000UL)
#define MAC_CR_RCVOWN_ (0x00800000UL)
#define MAC_CR_LOOPBK_ (0x00200000UL)
#define MAC_CR_FDPX_ (0x00100000UL)
#define MAC_CR_MCPAS_ (0x00080000UL)
#define MAC_CR_PRMS_ (0x00040000UL)
#define MAC_CR_INVFILT_ (0x00020000UL)
#define MAC_CR_PASSBAD_ (0x00010000UL)
#define MAC_CR_HFILT_ (0x00008000UL)
#define MAC_CR_HPFILT_ (0x00002000UL)
#define MAC_CR_LCOLL_ (0x00001000UL)
#define MAC_CR_BCAST_ (0x00000800UL)
#define MAC_CR_DISRTY_ (0x00000400UL)
#define MAC_CR_PADSTR_ (0x00000100UL)
#define MAC_CR_BOLMT_MASK_ (0x000000C0UL)
#define MAC_CR_DFCHK_ (0x00000020UL)
#define MAC_CR_TXEN_ (0x00000008UL)
#define MAC_CR_RXEN_ (0x00000004UL)
#define ADDRH (0x02UL) // R/W mask 0x0000FFFFUL
#define ADDRL (0x03UL) // R/W mask 0xFFFFFFFFUL
#define HASHH (0x04UL) // R/W
#define HASHL (0x05UL) // R/W
#define MII_ACC (0x06UL) // R/W
#define MII_ACC_PHY_ADDR_ (0x0000F800UL)
#define MII_ACC_MIIRINDA_ (0x000007C0UL)
#define MII_ACC_MII_WRITE_ (0x00000002UL)
#define MII_ACC_MII_BUSY_ (0x00000001UL)
#define MII_DATA (0x07UL) // R/W mask 0x0000FFFFUL
#define FLOW (0x08UL) // R/W
#define FLOW_FCPT_ (0xFFFF0000UL)
#define FLOW_FCPASS_ (0x00000004UL)
#define FLOW_FCEN_ (0x00000002UL)
#define FLOW_FCBSY_ (0x00000001UL)
#define VLAN1 (0x09UL) // R/W mask 0x0000FFFFUL
#define VLAN2 (0x0AUL) // R/W mask 0x0000FFFFUL
#define WUFF (0x0BUL) // WO
#define WUCSR (0x0CUL) // R/W
#define WUCSR_GUE_ (0x00000200UL)
#define WUCSR_WUFR_ (0x00000040UL)
#define WUCSR_MPR_ (0x00000020UL)
#define WUCSR_WAKE_EN_ (0x00000004UL)
#define WUCSR_MPEN_ (0x00000002UL)
void Mac_Initialize(PPRIVATE_DATA privateData);
static BOOLEAN MacNotBusy(PPRIVATE_DATA privateData);
DWORD Mac_GetRegDW(PPRIVATE_DATA privateData,DWORD dwRegOffset);
void Mac_SetRegDW(PPRIVATE_DATA privateData,DWORD dwRegOffset,DWORD dwVal);
/*
****************************************************************************
* Chip Specific MII Defines
****************************************************************************
*
* Phy register offsets and bit definitions
*
*/
#define LAN9118_PHY_ID (0x00C0001C)
#define PHY_BCR ((DWORD)0U)
#define PHY_BCR_RESET_ ((WORD)0x8000U)
#define PHY_BCR_SPEED_SELECT_ ((WORD)0x2000U)
#define PHY_BCR_AUTO_NEG_ENABLE_ ((WORD)0x1000U)
#define PHY_BCR_RESTART_AUTO_NEG_ ((WORD)0x0200U)
#define PHY_BCR_DUPLEX_MODE_ ((WORD)0x0100U)
#define PHY_BSR ((DWORD)1U)
#define PHY_BSR_LINK_STATUS_ ((WORD)0x0004U)
#define PHY_BSR_REMOTE_FAULT_ ((WORD)0x0010U)
#define PHY_BSR_AUTO_NEG_COMP_ ((WORD)0x0020U)
#define PHY_ID_1 ((DWORD)2U)
#define PHY_ID_2 ((DWORD)3U)
#define PHY_ANEG_ADV ((DWORD)4U)
#define PHY_ANEG_ADV_PAUSE_ ((WORD)0x0C00)
#define PHY_ANEG_ADV_ASYMP_ ((WORD)0x0800)
#define PHY_ANEG_ADV_SYMP_ ((WORD)0x0400)
#define PHY_ANEG_ADV_10H_ ((WORD)0x020)
#define PHY_ANEG_ADV_10F_ ((WORD)0x040)
#define PHY_ANEG_ADV_100H_ ((WORD)0x080)
#define PHY_ANEG_ADV_100F_ ((WORD)0x100)
#define PHY_ANEG_ADV_SPEED_ ((WORD)0x1E0)
#define PHY_ANEG_LPA ((DWORD)5U)
#define PHY_ANEG_LPA_ASYMP_ ((WORD)0x0800)
#define PHY_ANEG_LPA_SYMP_ ((WORD)0x0400)
#define PHY_ANEG_LPA_100FDX_ ((WORD)0x0100)
#define PHY_ANEG_LPA_100HDX_ ((WORD)0x0080)
#define PHY_ANEG_LPA_10FDX_ ((WORD)0x0040)
#define PHY_ANEG_LPA_10HDX_ ((WORD)0x0020)
#define PHY_MODE_CTRL_STS ((DWORD)17) // Mode Control/Status Register
#define MODE_CTRL_STS_EDPWRDOWN_ ((WORD)0x2000U)
#define MODE_CTRL_STS_ENERGYON_ ((WORD)0x0002U)
#define PHY_INT_SRC ((DWORD)29)
#define PHY_INT_SRC_ENERGY_ON_ ((WORD)0x0080U)
#define PHY_INT_SRC_ANEG_COMP_ ((WORD)0x0040U)
#define PHY_INT_SRC_REMOTE_FAULT_ ((WORD)0x0020U)
#define PHY_INT_SRC_LINK_DOWN_ ((WORD)0x0010U)
#define PHY_INT_MASK ((DWORD)30)
#define PHY_INT_MASK_ENERGY_ON_ ((WORD)0x0080U)
#define PHY_INT_MASK_ANEG_COMP_ ((WORD)0x0040U)
#define PHY_INT_MASK_REMOTE_FAULT_ ((WORD)0x0020U)
#define PHY_INT_MASK_LINK_DOWN_ ((WORD)0x0010U)
#define PHY_SPECIAL ((DWORD)31)
#define PHY_SPECIAL_SPD_ ((WORD)0x001CU)
#define PHY_SPECIAL_SPD_10HALF_ ((WORD)0x0004U)
#define PHY_SPECIAL_SPD_10FULL_ ((WORD)0x0014U)
#define PHY_SPECIAL_SPD_100HALF_ ((WORD)0x0008U)
#define PHY_SPECIAL_SPD_100FULL_ ((WORD)0x0018U)
BOOLEAN Phy_Initialize(
PPRIVATE_DATA privateData,
DWORD dwPhyAddr);
void Phy_SetLink(PPRIVATE_DATA privateData);
WORD Phy_GetRegW(
PPRIVATE_DATA privateData,
DWORD dwRegIndex);
void Phy_SetRegW(
PPRIVATE_DATA privateData,
DWORD dwRegIndex,
WORD wVal);
void Phy_UpdateLinkMode(
PPRIVATE_DATA privateData);
void Phy_GetLinkMode(
PPRIVATE_DATA privateData);
void Phy_CheckLink(unsigned long ptr);
void Tx_Initialize(
PPRIVATE_DATA privateData);
static void Tx_WriteFifo(
DWORD dwLanBase,
DWORD *pdwBuf,
DWORD dwDwordCount);
static DWORD Tx_GetTxStatusCount(
PPRIVATE_DATA privateData);
static DWORD Tx_CompleteTx(
PPRIVATE_DATA privateData);
void Tx_SendSkb(
PPRIVATE_DATA privateData,
struct sk_buff *skb);
BOOLEAN Tx_HandleInterrupt(
PPRIVATE_DATA privateData,DWORD dwIntSts);
void Tx_UpdateTxCounters(
PPRIVATE_DATA privateData);
void Rx_Initialize(
PPRIVATE_DATA privateData);
static void Rx_ReadFifo(
DWORD dwLanBase,
DWORD *pdwBuf,
DWORD dwDwordCount);
static void Rx_HandOffSkb(
PPRIVATE_DATA privateData,
struct sk_buff *skb);
static DWORD Rx_PopRxStatus(
PPRIVATE_DATA privateData);
void Rx_CountErrors(PPRIVATE_DATA privateData,DWORD dwRxStatus);
void Rx_FastForward(PPRIVATE_DATA privateData,DWORD dwDwordCount);
void Rx_ProcessPackets(PPRIVATE_DATA privateData);
void Rx_ProcessPacketsTasklet(unsigned long data);
BOOLEAN Rx_HandleInterrupt(
PPRIVATE_DATA privateData,
DWORD dwIntSts);
static DWORD Hash(BYTE addr[6]);
void Rx_SetMulticastList(
struct net_device *dev);
#ifdef USE_LED1_WORK_AROUND
extern volatile DWORD g_GpioSetting;
volatile DWORD g_GpioSettingOriginal;
#endif
BOOLEAN Lan_Initialize(
PPRIVATE_DATA privateData,DWORD dwIntCfg);
//This driver supports multiple instances
// of the LAN911x
//NOTE: at the time of this driver release
// we do not have a multiple instance platform
// to test with. Therefore the support this
// driver has for multiple instances is largely
// for illustrative purposes only, and has
// not been thoroughly tested.
//To load 2 instances follow this example
// insmod simp911x.o lan_base=ADDR1,ADDR2 irq=IRQ1,IRQ2
//Where ADDR1 and IRQ1 are replaced with the lan_base address
// and irq of the first instance. And ADDR2 and IRQ2 are
// replaced with the lan_base address and irq of the
// second instance.
//To change the supported instances
// change MAX_INSTANCES and the number of
// initializing elements in the following resource arrays
// lan_base,
// irq,
// mac_addr_hi16,
// mac_addr_lo32,
// phy_addr
// also must modify the second parameter of all
// MODULE_PARM macros (except for MODULE_PARM(debug_mode,"i");)
// to "0-Xi" where X is replaced
// with the same value of MAX_INSTANCES
// also must modify the Rx_TaskletParameter,
// And make sure there are enough Rx_Tasklets declared
// And make sure Rx_HandleInterrupt will schedule
// the correct Rx_Tasklet
#define MAX_INSTANCES 8
DWORD lan_base[MAX_INSTANCES]=
{0x00UL,0x00UL,0x00UL,0x00UL,
0x00UL,0x00UL,0x00UL,0x00UL};
MODULE_PARM(lan_base,"0-8i");
MODULE_PARM_DESC(lan_base,"Base Address of LAN911x");
DWORD irq[MAX_INSTANCES]=
{0x00UL,0x00UL,0x00UL,0x00UL,
0x00UL,0x00UL,0x00UL,0x00UL};
MODULE_PARM(irq,"0-8i");
MODULE_PARM_DESC(irq,"Force use of specific IRQ");
DWORD mac_addr_hi16[MAX_INSTANCES]=
{0xFFFFFFFFUL,0xFFFFFFFFUL,0xFFFFFFFFUL,0xFFFFFFFFUL,
0xFFFFFFFFUL,0xFFFFFFFFUL,0xFFFFFFFFUL,0xFFFFFFFFUL};
MODULE_PARM(mac_addr_hi16,"0-8i");
MODULE_PARM_DESC(mac_addr_hi16,"Specifies the high 16 bits of the mac address");
DWORD mac_addr_lo32[MAX_INSTANCES]=
{0xFFFFFFFFUL,0xFFFFFFFFUL,0xFFFFFFFFUL,0xFFFFFFFFUL,
0xFFFFFFFFUL,0xFFFFFFFFUL,0xFFFFFFFFUL,0xFFFFFFFFUL};
MODULE_PARM(mac_addr_lo32,"0-8i");
MODULE_PARM_DESC(mac_addr_lo32,"Specifies the low 32 bits of the mac address");
#ifdef USE_DEBUG
DWORD debug_mode=0x3UL;
#else
DWORD debug_mode=0x0UL;
#endif
MODULE_PARM(debug_mode,"i");
MODULE_PARM_DESC(debug_mode,"bit 0 enables trace points, bit 1 enables warning points");
DWORD phy_addr[MAX_INSTANCES]=
{0xFFFFFFFFUL,0xFFFFFFFFUL,0xFFFFFFFFUL,0xFFFFFFFFUL,
0xFFFFFFFFUL,0xFFFFFFFFUL,0xFFFFFFFFUL,0xFFFFFFFFUL};
MODULE_PARM(phy_addr,"0-8i");
MODULE_PARM_DESC(phy_addr,"phy_Addr,0xFFFFFFFF=use internal phy,0-31=use external phy with specified address, else autodetect external phy addr");
//this array is used to keep track of which
// instances were successfully registered.
// That way they can be unregistered properly.
DWORD registered[MAX_INSTANCES];
unsigned long Rx_TaskletParameter[MAX_INSTANCES]=
{0UL,0UL,0UL,0UL,0UL,0UL,0UL,0UL};
DECLARE_TASKLET(Rx_Tasklet0,Rx_ProcessPacketsTasklet,0);
DECLARE_TASKLET(Rx_Tasklet1,Rx_ProcessPacketsTasklet,1);
DECLARE_TASKLET(Rx_Tasklet2,Rx_ProcessPacketsTasklet,2);
DECLARE_TASKLET(Rx_Tasklet3,Rx_ProcessPacketsTasklet,3);
DECLARE_TASKLET(Rx_Tasklet4,Rx_ProcessPacketsTasklet,4);
DECLARE_TASKLET(Rx_Tasklet5,Rx_ProcessPacketsTasklet,5);
DECLARE_TASKLET(Rx_Tasklet6,Rx_ProcessPacketsTasklet,6);
DECLARE_TASKLET(Rx_Tasklet7,Rx_ProcessPacketsTasklet,7);
MODULE_LICENSE("GPL");
int Simp911x_init(struct net_device *dev);
int Simp911x_open(struct net_device *dev);
int Simp911x_stop(struct net_device *dev);
int Simp911x_hard_start_xmit(struct sk_buff *skb, struct net_device *dev);
struct net_device_stats * Simp911x_get_stats(struct net_device *dev);
void Simp911x_set_multicast_list(struct net_device *dev);
irqreturn_t Simp911x_ISR(int irq,void *dev_id,struct pt_regs *regs);
int Simp911x_init_module(void);
void Simp911x_cleanup_module(void);
DWORD gRegistrationIndex=0;
//gRegistrationIndex is used to pass the current
// instance index from Simp911x_init_module
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -