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

📄 forcedeth.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
 */enum {	NV_OPTIMIZATION_MODE_THROUGHPUT,	NV_OPTIMIZATION_MODE_CPU};static int optimization_mode = NV_OPTIMIZATION_MODE_THROUGHPUT;/* * Poll interval for timer irq * * This interval determines how frequent an interrupt is generated. * The is value is determined by [(time_in_micro_secs * 100) / (2^10)] * Min = 0, and Max = 65535 */static int poll_interval = -1;/* * MSI interrupts */enum {	NV_MSI_INT_DISABLED,	NV_MSI_INT_ENABLED};static int msi = NV_MSI_INT_ENABLED;/* * MSIX interrupts */enum {	NV_MSIX_INT_DISABLED,	NV_MSIX_INT_ENABLED};static int msix = NV_MSIX_INT_DISABLED;/* * DMA 64bit */enum {	NV_DMA_64BIT_DISABLED,	NV_DMA_64BIT_ENABLED};static int dma_64bit = NV_DMA_64BIT_ENABLED;static inline struct fe_priv *get_nvpriv(struct net_device *dev){	return netdev_priv(dev);}static inline u8 __iomem *get_hwbase(struct net_device *dev){	return ((struct fe_priv *)netdev_priv(dev))->base;}static inline void pci_push(u8 __iomem *base){	/* force out pending posted writes */	readl(base);}static inline u32 nv_descr_getlength(struct ring_desc *prd, u32 v){	return le32_to_cpu(prd->flaglen)		& ((v == DESC_VER_1) ? LEN_MASK_V1 : LEN_MASK_V2);}static inline u32 nv_descr_getlength_ex(struct ring_desc_ex *prd, u32 v){	return le32_to_cpu(prd->flaglen) & LEN_MASK_V2;}static int reg_delay(struct net_device *dev, int offset, u32 mask, u32 target,				int delay, int delaymax, const char *msg){	u8 __iomem *base = get_hwbase(dev);	pci_push(base);	do {		udelay(delay);		delaymax -= delay;		if (delaymax < 0) {			if (msg)				printk(msg);			return 1;		}	} while ((readl(base + offset) & mask) != target);	return 0;}#define NV_SETUP_RX_RING 0x01#define NV_SETUP_TX_RING 0x02static void setup_hw_rings(struct net_device *dev, int rxtx_flags){	struct fe_priv *np = get_nvpriv(dev);	u8 __iomem *base = get_hwbase(dev);	if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {		if (rxtx_flags & NV_SETUP_RX_RING) {			writel((u32) cpu_to_le64(np->ring_addr), base + NvRegRxRingPhysAddr);		}		if (rxtx_flags & NV_SETUP_TX_RING) {			writel((u32) cpu_to_le64(np->ring_addr + np->rx_ring_size*sizeof(struct ring_desc)), base + NvRegTxRingPhysAddr);		}	} else {		if (rxtx_flags & NV_SETUP_RX_RING) {			writel((u32) cpu_to_le64(np->ring_addr), base + NvRegRxRingPhysAddr);			writel((u32) (cpu_to_le64(np->ring_addr) >> 32), base + NvRegRxRingPhysAddrHigh);		}		if (rxtx_flags & NV_SETUP_TX_RING) {			writel((u32) cpu_to_le64(np->ring_addr + np->rx_ring_size*sizeof(struct ring_desc_ex)), base + NvRegTxRingPhysAddr);			writel((u32) (cpu_to_le64(np->ring_addr + np->rx_ring_size*sizeof(struct ring_desc_ex)) >> 32), base + NvRegTxRingPhysAddrHigh);		}	}}static void free_rings(struct net_device *dev){	struct fe_priv *np = get_nvpriv(dev);	if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {		if (np->rx_ring.orig)			pci_free_consistent(np->pci_dev, sizeof(struct ring_desc) * (np->rx_ring_size + np->tx_ring_size),					    np->rx_ring.orig, np->ring_addr);	} else {		if (np->rx_ring.ex)			pci_free_consistent(np->pci_dev, sizeof(struct ring_desc_ex) * (np->rx_ring_size + np->tx_ring_size),					    np->rx_ring.ex, np->ring_addr);	}	if (np->rx_skb)		kfree(np->rx_skb);	if (np->tx_skb)		kfree(np->tx_skb);}static int using_multi_irqs(struct net_device *dev){	struct fe_priv *np = get_nvpriv(dev);	if (!(np->msi_flags & NV_MSI_X_ENABLED) ||	    ((np->msi_flags & NV_MSI_X_ENABLED) &&	     ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1)))		return 0;	else		return 1;}static void nv_enable_irq(struct net_device *dev){	struct fe_priv *np = get_nvpriv(dev);	if (!using_multi_irqs(dev)) {		if (np->msi_flags & NV_MSI_X_ENABLED)			enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector);		else			enable_irq(np->pci_dev->irq);	} else {		enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);		enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector);		enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector);	}}static void nv_disable_irq(struct net_device *dev){	struct fe_priv *np = get_nvpriv(dev);	if (!using_multi_irqs(dev)) {		if (np->msi_flags & NV_MSI_X_ENABLED)			disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector);		else			disable_irq(np->pci_dev->irq);	} else {		disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);		disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector);		disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector);	}}/* In MSIX mode, a write to irqmask behaves as XOR */static void nv_enable_hw_interrupts(struct net_device *dev, u32 mask){	u8 __iomem *base = get_hwbase(dev);	writel(mask, base + NvRegIrqMask);}static void nv_disable_hw_interrupts(struct net_device *dev, u32 mask){	struct fe_priv *np = get_nvpriv(dev);	u8 __iomem *base = get_hwbase(dev);	if (np->msi_flags & NV_MSI_X_ENABLED) {		writel(mask, base + NvRegIrqMask);	} else {		if (np->msi_flags & NV_MSI_ENABLED)			writel(0, base + NvRegMSIIrqMask);		writel(0, base + NvRegIrqMask);	}}#define MII_READ	(-1)/* mii_rw: read/write a register on the PHY. * * Caller must guarantee serialization */static int mii_rw(struct net_device *dev, int addr, int miireg, int value){	u8 __iomem *base = get_hwbase(dev);	u32 reg;	int retval;	writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus);	reg = readl(base + NvRegMIIControl);	if (reg & NVREG_MIICTL_INUSE) {		writel(NVREG_MIICTL_INUSE, base + NvRegMIIControl);		udelay(NV_MIIBUSY_DELAY);	}	reg = (addr << NVREG_MIICTL_ADDRSHIFT) | miireg;	if (value != MII_READ) {		writel(value, base + NvRegMIIData);		reg |= NVREG_MIICTL_WRITE;	}	writel(reg, base + NvRegMIIControl);	if (reg_delay(dev, NvRegMIIControl, NVREG_MIICTL_INUSE, 0,			NV_MIIPHY_DELAY, NV_MIIPHY_DELAYMAX, NULL)) {		dprintk(KERN_DEBUG "%s: mii_rw of reg %d at PHY %d timed out.\n",				dev->name, miireg, addr);		retval = -1;	} else if (value != MII_READ) {		/* it was a write operation - fewer failures are detectable */		dprintk(KERN_DEBUG "%s: mii_rw wrote 0x%x to reg %d at PHY %d\n",				dev->name, value, miireg, addr);		retval = 0;	} else if (readl(base + NvRegMIIStatus) & NVREG_MIISTAT_ERROR) {		dprintk(KERN_DEBUG "%s: mii_rw of reg %d at PHY %d failed.\n",				dev->name, miireg, addr);		retval = -1;	} else {		retval = readl(base + NvRegMIIData);		dprintk(KERN_DEBUG "%s: mii_rw read from reg %d at PHY %d: 0x%x.\n",				dev->name, miireg, addr, retval);	}	return retval;}static int phy_reset(struct net_device *dev, u32 bmcr_setup){	struct fe_priv *np = netdev_priv(dev);	u32 miicontrol;	unsigned int tries = 0;	miicontrol = BMCR_RESET | bmcr_setup;	if (mii_rw(dev, np->phyaddr, MII_BMCR, miicontrol)) {		return -1;	}	/* wait for 500ms */	msleep(500);	/* must wait till reset is deasserted */	while (miicontrol & BMCR_RESET) {		msleep(10);		miicontrol = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);		/* FIXME: 100 tries seem excessive */		if (tries++ > 100)			return -1;	}	return 0;}static int phy_init(struct net_device *dev){	struct fe_priv *np = get_nvpriv(dev);	u8 __iomem *base = get_hwbase(dev);	u32 phyinterface, phy_reserved, mii_status, mii_control, mii_control_1000,reg;	/* phy errata for E3016 phy */	if (np->phy_model == PHY_MODEL_MARVELL_E3016) {		reg = mii_rw(dev, np->phyaddr, MII_NCONFIG, MII_READ);		reg &= ~PHY_MARVELL_E3016_INITMASK;		if (mii_rw(dev, np->phyaddr, MII_NCONFIG, reg)) {			printk(KERN_INFO "%s: phy write to errata reg failed.\n", pci_name(np->pci_dev));			return PHY_ERROR;		}	}	if (np->phy_oui == PHY_OUI_REALTEK) {		if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));			return PHY_ERROR;		}		if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, PHY_REALTEK_INIT2)) {			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));			return PHY_ERROR;		}		if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3)) {			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));			return PHY_ERROR;		}		if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG3, PHY_REALTEK_INIT4)) {			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));			return PHY_ERROR;		}		if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));			return PHY_ERROR;		}	}	/* set advertise register */	reg = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ);	reg |= (ADVERTISE_10HALF|ADVERTISE_10FULL|ADVERTISE_100HALF|ADVERTISE_100FULL|ADVERTISE_PAUSE_ASYM|ADVERTISE_PAUSE_CAP);	if (mii_rw(dev, np->phyaddr, MII_ADVERTISE, reg)) {		printk(KERN_INFO "%s: phy write to advertise failed.\n", pci_name(np->pci_dev));		return PHY_ERROR;	}	/* get phy interface type */	phyinterface = readl(base + NvRegPhyInterface);	/* see if gigabit phy */	mii_status = mii_rw(dev, np->phyaddr, MII_BMSR, MII_READ);	if (mii_status & PHY_GIGABIT) {		np->gigabit = PHY_GIGABIT;		mii_control_1000 = mii_rw(dev, np->phyaddr, MII_CTRL1000, MII_READ);		mii_control_1000 &= ~ADVERTISE_1000HALF;		if (phyinterface & PHY_RGMII)			mii_control_1000 |= ADVERTISE_1000FULL;		else			mii_control_1000 &= ~ADVERTISE_1000FULL;		if (mii_rw(dev, np->phyaddr, MII_CTRL1000, mii_control_1000)) {			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));			return PHY_ERROR;		}	}	else		np->gigabit = 0;	mii_control = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);	mii_control |= BMCR_ANENABLE;	/* reset the phy	 * (certain phys need bmcr to be setup with reset)	 */	if (phy_reset(dev, mii_control)) {		printk(KERN_INFO "%s: phy reset failed\n", pci_name(np->pci_dev));		return PHY_ERROR;	}	/* phy vendor specific configuration */	if ((np->phy_oui == PHY_OUI_CICADA) && (phyinterface & PHY_RGMII) ) {		phy_reserved = mii_rw(dev, np->phyaddr, MII_RESV1, MII_READ);		phy_reserved &= ~(PHY_CICADA_INIT1 | PHY_CICADA_INIT2);		phy_reserved |= (PHY_CICADA_INIT3 | PHY_CICADA_INIT4);		if (mii_rw(dev, np->phyaddr, MII_RESV1, phy_reserved)) {			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));			return PHY_ERROR;		}		phy_reserved = mii_rw(dev, np->phyaddr, MII_NCONFIG, MII_READ);		phy_reserved |= PHY_CICADA_INIT5;		if (mii_rw(dev, np->phyaddr, MII_NCONFIG, phy_reserved)) {			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));			return PHY_ERROR;		}	}	if (np->phy_oui == PHY_OUI_CICADA) {		phy_reserved = mii_rw(dev, np->phyaddr, MII_SREVISION, MII_READ);		phy_reserved |= PHY_CICADA_INIT6;		if (mii_rw(dev, np->phyaddr, MII_SREVISION, phy_reserved)) {			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));			return PHY_ERROR;		}	}	if (np->phy_oui == PHY_OUI_VITESSE) {		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG1, PHY_VITESSE_INIT1)) {			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));			return PHY_ERROR;		}		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT2)) {			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));			return PHY_ERROR;		}		phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, MII_READ);		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, phy_reserved)) {			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));			return PHY_ERROR;		}		phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, MII_READ);		phy_reserved &= ~PHY_VITESSE_INIT_MSK1;		phy_reserved |= PHY_VITESSE_INIT3;		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, phy_reserved)) {			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));			return PHY_ERROR;		}		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT4)) {			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));			return PHY_ERROR;		}		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT5)) {			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));			return PHY_ERROR;		}		phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, MII_READ);		phy_reserved &= ~PHY_VITESSE_INIT_MSK1;		phy_reserved |= PHY_VITESSE_INIT3;		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, phy_reserved)) {			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));			return PHY_ERROR;		}		phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, MII_READ);		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, phy_reserved)) {			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));			return PHY_ERROR;		}		if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT6)) {			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));

⌨️ 快捷键说明

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