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

📄 simp911x.c

📁 SMSC 9118 Driver for linux
💻 C
📖 第 1 页 / 共 5 页
字号:
//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 + -