natsemi.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 2,270 行 · 第 1/5 页

C
2,270
字号
	RxOff			= 0x08,	RxOn			= 0x04,	TxOff			= 0x02,	TxOn			= 0x01,};enum ChipConfig_bits {	CfgPhyDis		= 0x200,	CfgPhyRst		= 0x400,	CfgExtPhy		= 0x1000,	CfgAnegEnable		= 0x2000,	CfgAneg100		= 0x4000,	CfgAnegFull		= 0x8000,	CfgAnegDone		= 0x8000000,	CfgFullDuplex		= 0x20000000,	CfgSpeed100		= 0x40000000,	CfgLink			= 0x80000000,};enum EECtrl_bits {	EE_ShiftClk		= 0x04,	EE_DataIn		= 0x01,	EE_ChipSelect		= 0x08,	EE_DataOut		= 0x02,	MII_Data 		= 0x10,	MII_Write		= 0x20,	MII_ShiftClk		= 0x40,};enum PCIBusCfg_bits {	EepromReload		= 0x4,};/* Bits in the interrupt status/mask registers. */enum IntrStatus_bits {	IntrRxDone		= 0x0001,	IntrRxIntr		= 0x0002,	IntrRxErr		= 0x0004,	IntrRxEarly		= 0x0008,	IntrRxIdle		= 0x0010,	IntrRxOverrun		= 0x0020,	IntrTxDone		= 0x0040,	IntrTxIntr		= 0x0080,	IntrTxErr		= 0x0100,	IntrTxIdle		= 0x0200,	IntrTxUnderrun		= 0x0400,	StatsMax		= 0x0800,	SWInt			= 0x1000,	WOLPkt			= 0x2000,	LinkChange		= 0x4000,	IntrHighBits		= 0x8000,	RxStatusFIFOOver	= 0x10000,	IntrPCIErr		= 0xf00000,	RxResetDone		= 0x1000000,	TxResetDone		= 0x2000000,	IntrAbnormalSummary	= 0xCD20,};/* * Default Interrupts: * Rx OK, Rx Packet Error, Rx Overrun, * Tx OK, Tx Packet Error, Tx Underrun, * MIB Service, Phy Interrupt, High Bits, * Rx Status FIFO overrun, * Received Target Abort, Received Master Abort, * Signalled System Error, Received Parity Error */#define DEFAULT_INTR 0x00f1cd65enum TxConfig_bits {	TxDrthMask		= 0x3f,	TxFlthMask		= 0x3f00,	TxMxdmaMask		= 0x700000,	TxMxdma_512		= 0x0,	TxMxdma_4		= 0x100000,	TxMxdma_8		= 0x200000,	TxMxdma_16		= 0x300000,	TxMxdma_32		= 0x400000,	TxMxdma_64		= 0x500000,	TxMxdma_128		= 0x600000,	TxMxdma_256		= 0x700000,	TxCollRetry		= 0x800000,	TxAutoPad		= 0x10000000,	TxMacLoop		= 0x20000000,	TxHeartIgn		= 0x40000000,	TxCarrierIgn		= 0x80000000};/*  * Tx Configuration: * - 256 byte DMA burst length * - fill threshold 512 bytes (i.e. restart DMA when 512 bytes are free) * - 64 bytes initial drain threshold (i.e. begin actual transmission *   when 64 byte are in the fifo) * - on tx underruns, increase drain threshold by 64. * - at most use a drain threshold of 1472 bytes: The sum of the fill *   threshold and the drain threshold must be less than 2016 bytes. * */#define TX_FLTH_VAL		((512/32) << 8)#define TX_DRTH_VAL_START	(64/32)#define TX_DRTH_VAL_INC		2#define TX_DRTH_VAL_LIMIT	(1472/32)enum RxConfig_bits {	RxDrthMask		= 0x3e,	RxMxdmaMask		= 0x700000,	RxMxdma_512		= 0x0,	RxMxdma_4		= 0x100000,	RxMxdma_8		= 0x200000,	RxMxdma_16		= 0x300000,	RxMxdma_32		= 0x400000,	RxMxdma_64		= 0x500000,	RxMxdma_128		= 0x600000,	RxMxdma_256		= 0x700000,	RxAcceptLong		= 0x8000000,	RxAcceptTx		= 0x10000000,	RxAcceptRunt		= 0x40000000,	RxAcceptErr		= 0x80000000};#define RX_DRTH_VAL		(128/8)enum ClkRun_bits {	PMEEnable		= 0x100,	PMEStatus		= 0x8000,};enum WolCmd_bits {	WakePhy			= 0x1,	WakeUnicast		= 0x2,	WakeMulticast		= 0x4,	WakeBroadcast		= 0x8,	WakeArp			= 0x10,	WakePMatch0		= 0x20,	WakePMatch1		= 0x40,	WakePMatch2		= 0x80,	WakePMatch3		= 0x100,	WakeMagic		= 0x200,	WakeMagicSecure		= 0x400,	SecureHack		= 0x100000,	WokePhy			= 0x400000,	WokeUnicast		= 0x800000,	WokeMulticast		= 0x1000000,	WokeBroadcast		= 0x2000000,	WokeArp			= 0x4000000,	WokePMatch0		= 0x8000000,	WokePMatch1		= 0x10000000,	WokePMatch2		= 0x20000000,	WokePMatch3		= 0x40000000,	WokeMagic		= 0x80000000,	WakeOptsSummary		= 0x7ff};enum RxFilterAddr_bits {	RFCRAddressMask		= 0x3ff,	AcceptMulticast		= 0x00200000,	AcceptMyPhys		= 0x08000000,	AcceptAllPhys		= 0x10000000,	AcceptAllMulticast	= 0x20000000,	AcceptBroadcast		= 0x40000000,	RxFilterEnable		= 0x80000000};enum StatsCtrl_bits {	StatsWarn		= 0x1,	StatsFreeze		= 0x2,	StatsClear		= 0x4,	StatsStrobe		= 0x8,};enum MIntrCtrl_bits {	MICRIntEn		= 0x2,};enum PhyCtrl_bits {	PhyAddrMask		= 0x1f,};#define PHY_ADDR_NONE		32#define PHY_ADDR_INTERNAL	1/* values we might find in the silicon revision register */#define SRR_DP83815_C	0x0302#define SRR_DP83815_D	0x0403#define SRR_DP83816_A4	0x0504#define SRR_DP83816_A5	0x0505/* The Rx and Tx buffer descriptors. *//* Note that using only 32 bit fields simplifies conversion to big-endian   architectures. */struct netdev_desc {	u32 next_desc;	s32 cmd_status;	u32 addr;	u32 software_use;};/* Bits in network_desc.status */enum desc_status_bits {	DescOwn=0x80000000, DescMore=0x40000000, DescIntr=0x20000000,	DescNoCRC=0x10000000, DescPktOK=0x08000000,	DescSizeMask=0xfff,	DescTxAbort=0x04000000, DescTxFIFO=0x02000000,	DescTxCarrier=0x01000000, DescTxDefer=0x00800000,	DescTxExcDefer=0x00400000, DescTxOOWCol=0x00200000,	DescTxExcColl=0x00100000, DescTxCollCount=0x000f0000,	DescRxAbort=0x04000000, DescRxOver=0x02000000,	DescRxDest=0x01800000, DescRxLong=0x00400000,	DescRxRunt=0x00200000, DescRxInvalid=0x00100000,	DescRxCRC=0x00080000, DescRxAlign=0x00040000,	DescRxLoop=0x00020000, DesRxColl=0x00010000,};struct netdev_private {	/* Descriptor rings first for alignment */	dma_addr_t ring_dma;	struct netdev_desc *rx_ring;	struct netdev_desc *tx_ring;	/* The addresses of receive-in-place skbuffs */	struct sk_buff *rx_skbuff[RX_RING_SIZE];	dma_addr_t rx_dma[RX_RING_SIZE];	/* address of a sent-in-place packet/buffer, for later free() */	struct sk_buff *tx_skbuff[TX_RING_SIZE];	dma_addr_t tx_dma[TX_RING_SIZE];	struct net_device_stats stats;	/* Media monitoring timer */	struct timer_list timer;	/* Frequently used values: keep some adjacent for cache effect */	struct pci_dev *pci_dev;	struct netdev_desc *rx_head_desc;	/* Producer/consumer ring indices */	unsigned int cur_rx, dirty_rx;	unsigned int cur_tx, dirty_tx;	/* Based on MTU+slack. */	unsigned int rx_buf_sz;	int oom;	/* Do not touch the nic registers */	int hands_off;	/* external phy that is used: only valid if dev->if_port != PORT_TP */	int mii;	int phy_addr_external;	unsigned int full_duplex;	/* Rx filter */	u32 cur_rx_mode;	u32 rx_filter[16];	/* FIFO and PCI burst thresholds */	u32 tx_config, rx_config;	/* original contents of ClkRun register */	u32 SavedClkRun;	/* silicon revision */	u32 srr;	/* expected DSPCFG value */	u16 dspcfg;	/* parms saved in ethtool format */	u16	speed;		/* The forced speed, 10Mb, 100Mb, gigabit */	u8	duplex;		/* Duplex, half or full */	u8	autoneg;	/* Autonegotiation enabled */	/* MII transceiver section */	u16 advertising;	unsigned int iosize;	spinlock_t lock;	u32 msg_enable;};static void move_int_phy(struct net_device *dev, int addr);static int eeprom_read(void __iomem *ioaddr, int location);static int mdio_read(struct net_device *dev, int reg);static void mdio_write(struct net_device *dev, int reg, u16 data);static void init_phy_fixup(struct net_device *dev);static int miiport_read(struct net_device *dev, int phy_id, int reg);static void miiport_write(struct net_device *dev, int phy_id, int reg, u16 data);static int find_mii(struct net_device *dev);static void natsemi_reset(struct net_device *dev);static void natsemi_reload_eeprom(struct net_device *dev);static void natsemi_stop_rxtx(struct net_device *dev);static int netdev_open(struct net_device *dev);static void do_cable_magic(struct net_device *dev);static void undo_cable_magic(struct net_device *dev);static void check_link(struct net_device *dev);static void netdev_timer(unsigned long data);static void dump_ring(struct net_device *dev);static void tx_timeout(struct net_device *dev);static int alloc_ring(struct net_device *dev);static void refill_rx(struct net_device *dev);static void init_ring(struct net_device *dev);static void drain_tx(struct net_device *dev);static void drain_ring(struct net_device *dev);static void free_ring(struct net_device *dev);static void reinit_ring(struct net_device *dev);static void init_registers(struct net_device *dev);static int start_tx(struct sk_buff *skb, struct net_device *dev);static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *regs);static void netdev_error(struct net_device *dev, int intr_status);static void netdev_rx(struct net_device *dev);static void netdev_tx_done(struct net_device *dev);static int natsemi_change_mtu(struct net_device *dev, int new_mtu);#ifdef CONFIG_NET_POLL_CONTROLLERstatic void natsemi_poll_controller(struct net_device *dev);#endifstatic void __set_rx_mode(struct net_device *dev);static void set_rx_mode(struct net_device *dev);static void __get_stats(struct net_device *dev);static struct net_device_stats *get_stats(struct net_device *dev);static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);static int netdev_set_wol(struct net_device *dev, u32 newval);static int netdev_get_wol(struct net_device *dev, u32 *supported, u32 *cur);static int netdev_set_sopass(struct net_device *dev, u8 *newval);static int netdev_get_sopass(struct net_device *dev, u8 *data);static int netdev_get_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd);static int netdev_set_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd);static void enable_wol_mode(struct net_device *dev, int enable_intr);static int netdev_close(struct net_device *dev);static int netdev_get_regs(struct net_device *dev, u8 *buf);static int netdev_get_eeprom(struct net_device *dev, u8 *buf);static inline void __iomem *ns_ioaddr(struct net_device *dev){	return (void __iomem *) dev->base_addr;}static void move_int_phy(struct net_device *dev, int addr){	struct netdev_private *np = netdev_priv(dev);	void __iomem *ioaddr = ns_ioaddr(dev);	int target = 31;	/* 	 * The internal phy is visible on the external mii bus. Therefore we must	 * move it away before we can send commands to an external phy.	 * There are two addresses we must avoid:	 * - the address on the external phy that is used for transmission.	 * - the address that we want to access. User space can access phys	 *   on the mii bus with SIOCGMIIREG/SIOCSMIIREG, independant from the	 *   phy that is used for transmission.	 */	if (target == addr)		target--;	if (target == np->phy_addr_external)		target--;	writew(target, ioaddr + PhyCtrl);	readw(ioaddr + PhyCtrl);	udelay(1);}static int __devinit natsemi_probe1 (struct pci_dev *pdev,	const struct pci_device_id *ent){	struct net_device *dev;	struct netdev_private *np;	int i, option, irq, chip_idx = ent->driver_data;	static int find_cnt = -1;	unsigned long iostart, iosize;	void __iomem *ioaddr;	const int pcibar = 1; /* PCI base address register */	int prev_eedata;	u32 tmp;/* when built into the kernel, we only print version if device is found */#ifndef MODULE	static int printed_version;	if (!printed_version++)		printk(version);#endif	i = pci_enable_device(pdev);	if (i) return i;	/* natsemi has a non-standard PM control register	 * in PCI config space.  Some boards apparently need	 * to be brought to D0 in this manner.	 */	pci_read_config_dword(pdev, PCIPM, &tmp);	if (tmp & PCI_PM_CTRL_STATE_MASK) {		/* D0 state, disable PME assertion */		u32 newtmp = tmp & ~PCI_PM_CTRL_STATE_MASK;		pci_write_config_dword(pdev, PCIPM, newtmp);	}	find_cnt++;	iostart = pci_resource_start(pdev, pcibar);	iosize = pci_resource_len(pdev, pcibar);	irq = pdev->irq;	if (natsemi_pci_info[chip_idx].flags & PCI_USES_MASTER)		pci_set_master(pdev);	dev = alloc_etherdev(sizeof (struct netdev_private));	if (!dev)		return -ENOMEM;	SET_MODULE_OWNER(dev);	SET_NETDEV_DEV(dev, &pdev->dev);	i = pci_request_regions(pdev, DRV_NAME);	if (i)		goto err_pci_request_regions;	ioaddr = ioremap(iostart, iosize);	if (!ioaddr) {		i = -ENOMEM;		goto err_ioremap;	}	/* Work around the dropped serial bit. */	prev_eedata = eeprom_read(ioaddr, 6);	for (i = 0; i < 3; i++) {		int eedata = eeprom_read(ioaddr, i + 7);		dev->dev_addr[i*2] = (eedata << 1) + (prev_eedata >> 15);		dev->dev_addr[i*2+1] = eedata >> 7;		prev_eedata = eedata;	}	dev->base_addr = (unsigned long __force) ioaddr;	dev->irq = irq;	np = netdev_priv(dev);	np->pci_dev = pdev;	pci_set_drvdata(pdev, dev);	np->iosize = iosize;	spin_lock_init(&np->lock);	np->msg_enable = (debug >= 0) ? (1<<debug)-1 : NATSEMI_DEF_MSG;	np->hands_off = 0;	/* Initial port:	 * - If the nic was configured to use an external phy and if find_mii	 *   finds a phy: use external port, first phy that replies.	 * - Otherwise: internal port.	 * Note that the phy address for the internal phy doesn't matter:	 * The address would be used to access a phy over the mii bus, but	 * the internal phy is accessed through mapped registers.	 */	if (readl(ioaddr + ChipConfig) & CfgExtPhy)		dev->if_port = PORT_MII;	else		dev->if_port = PORT_TP;	/* Reset the chip to erase previous misconfiguration. */	natsemi_reload_eeprom(dev);	natsemi_reset(dev);	if (dev->if_port != PORT_TP) {		np->phy_addr_external = find_mii(dev);		if (np->phy_addr_external == PHY_ADDR_NONE) {			dev->if_port = PORT_TP;			np->phy_addr_external = PHY_ADDR_INTERNAL;		}	} else {		np->phy_addr_external = PHY_ADDR_INTERNAL;	}	option = find_cnt < MAX_UNITS ? options[find_cnt] : 0;	if (dev->mem_start)

⌨️ 快捷键说明

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