📄 forcedeth.c
字号:
if (np->speed_duplex == NV_SPEED_DUPLEX_1000_FULL_DUPLEX && np->autoneg == AUTONEG_DISABLE) printk(KERN_INFO "%s: 1000mpbs full only allowed with autoneg\n", pci_name(np->pci_dev)); 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); if (np->autoneg == AUTONEG_DISABLE){ np->pause_flags &= ~(NV_PAUSEFRAME_RX_ENABLE | NV_PAUSEFRAME_TX_ENABLE); if (np->pause_flags & NV_PAUSEFRAME_RX_REQ) np->pause_flags |= NV_PAUSEFRAME_RX_ENABLE; if (np->pause_flags & NV_PAUSEFRAME_TX_REQ) np->pause_flags |= NV_PAUSEFRAME_TX_ENABLE; mii_control &= ~(BMCR_ANENABLE|BMCR_SPEED100|BMCR_SPEED1000|BMCR_FULLDPLX); if (reg & (ADVERTISE_10FULL|ADVERTISE_100FULL)) mii_control |= BMCR_FULLDPLX; if (reg & (ADVERTISE_100HALF|ADVERTISE_100FULL)) mii_control |= BMCR_SPEED100; } else { mii_control |= BMCR_ANENABLE; } /* reset the phy and setup BMCR * (certain phys need reset at same time new values are set) */ 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)); return PHY_ERROR; } if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT7)) { 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_MSK2; phy_reserved |= PHY_VITESSE_INIT8; 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_INIT9)) { 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_REG1, PHY_VITESSE_INIT10)) { printk(KERN_INFO "%s: phy init 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; } } /* some phys clear out pause advertisment on reset, set it back */ mii_rw(dev, np->phyaddr, MII_ADVERTISE, reg); /* restart auto negotiation */ if (np->autoneg == AUTONEG_ENABLE) { mii_control = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ); mii_control |= (BMCR_ANRESTART | BMCR_ANENABLE); if (mii_rw(dev, np->phyaddr, MII_BMCR, mii_control)) { return PHY_ERROR; } } return 0;}static void nv_start_rx(struct net_device *dev){ struct fe_priv *np = get_nvpriv(dev); u8 __iomem *base = get_hwbase(dev); u32 rx_ctrl = readl(base + NvRegReceiverControl); dprintk(KERN_DEBUG "%s:%s\n",dev->name,__FUNCTION__); /* Already running? Stop it. */ if ((readl(base + NvRegReceiverControl) & NVREG_RCVCTL_START) && !np->mac_in_use) { rx_ctrl &= ~NVREG_RCVCTL_START; writel(rx_ctrl, base + NvRegReceiverControl); pci_push(base); } writel(np->linkspeed, base + NvRegLinkSpeed); pci_push(base); rx_ctrl |= NVREG_RCVCTL_START; if (np->mac_in_use) rx_ctrl &= ~NVREG_RCVCTL_RX_PATH_EN; writel(rx_ctrl, base + NvRegReceiverControl); dprintk(KERN_DEBUG "%s: nv_start_rx to duplex %d, speed 0x%08x.\n", dev->name, np->duplex, np->linkspeed); pci_push(base);}static void nv_stop_rx(struct net_device *dev){ struct fe_priv *np = get_nvpriv(dev); u8 __iomem *base = get_hwbase(dev); u32 rx_ctrl = readl(base + NvRegReceiverControl); dprintk(KERN_DEBUG "%s:%s\n",dev->name,__FUNCTION__); if (!np->mac_in_use) rx_ctrl &= ~NVREG_RCVCTL_START; else rx_ctrl |= NVREG_RCVCTL_RX_PATH_EN; writel(rx_ctrl, base + NvRegReceiverControl); reg_delay(dev, NvRegReceiverStatus, NVREG_RCVSTAT_BUSY, 0, NV_RXSTOP_DELAY1, NV_RXSTOP_DELAY1MAX, KERN_INFO "nv_stop_rx: ReceiverStatus remained busy"); udelay(NV_RXSTOP_DELAY2); if (!np->mac_in_use) writel(0, base + NvRegLinkSpeed);}static void nv_start_tx(struct net_device *dev){ struct fe_priv *np = get_nvpriv(dev); u8 __iomem *base = get_hwbase(dev); u32 tx_ctrl = readl(base + NvRegTransmitterControl); dprintk(KERN_DEBUG "%s:%s\n",dev->name,__FUNCTION__); tx_ctrl |= NVREG_XMITCTL_START; if (np->mac_in_use) tx_ctrl &= ~NVREG_XMITCTL_TX_PATH_EN; writel(tx_ctrl, base + NvRegTransmitterControl); pci_push(base);}static void nv_stop_tx(struct net_device *dev){ struct fe_priv *np = get_nvpriv(dev); u8 __iomem *base = get_hwbase(dev); u32 tx_ctrl = readl(base + NvRegTransmitterControl); dprintk(KERN_DEBUG "%s:%s\n",dev->name,__FUNCTION__); if (!np->mac_in_use) tx_ctrl &= ~NVREG_XMITCTL_START; else tx_ctrl |= NVREG_XMITCTL_TX_PATH_EN; writel(tx_ctrl, base + NvRegTransmitterControl); reg_delay(dev, NvRegTransmitterStatus, NVREG_XMITSTAT_BUSY, 0, NV_TXSTOP_DELAY1, NV_TXSTOP_DELAY1MAX, KERN_INFO "nv_stop_tx: TransmitterStatus remained busy"); udelay(NV_TXSTOP_DELAY2); if (!np->mac_in_use) writel(readl(base + NvRegTransmitPoll) & NVREG_TRANSMITPOLL_MAC_ADDR_REV, base + NvRegTransmitPoll);}static void nv_txrx_reset(struct net_device *dev){ struct fe_priv *np = get_nvpriv(dev); u8 __iomem *base = get_hwbase(dev); unsigned int i; dprintk(KERN_DEBUG "%s:%s\n",dev->name,__FUNCTION__); writel(NVREG_TXRXCTL_BIT2 | np->txrxctl_bits, base + NvRegTxRxControl); for(i=0;i<10000;i++){ udelay(1); if(readl(base+NvRegTxRxControl) & NVREG_TXRXCTL_IDLE) break; } writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->txrxctl_bits, base + NvRegTxRxControl); pci_push(base); udelay(NV_TXRX_RESET_DELAY); pci_push(base);}static void nv_mac_reset(struct net_device *dev){ struct fe_priv *np = get_nvpriv(dev); u8 __iomem *base = get_hwbase(dev); u32 temp1,temp2,temp3; dprintk(KERN_DEBUG "%s:%s\n",dev->name,__FUNCTION__); writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->txrxctl_bits, base + NvRegTxRxControl); /* save registers since they will be cleared on reset */ temp1 = readl(base + NvRegMacAddrA); temp2 = readl(base + NvRegMacAddrB); temp3 = readl(base + NvRegTransmitPoll); pci_push(base); writel(NVREG_MAC_RESET_ASSERT, base + NvRegMacReset); pci_push(base); udelay(NV_MAC_RESET_DELAY); writel(0, base + NvRegMacReset); pci_push(base); udelay(NV_MAC_RESET_DELAY); /* restore saved registers */ writel(temp1, base + NvRegMacAddrA); writel(temp2, base + NvRegMacAddrB); writel(temp3, base + NvRegTransmitPoll); writel(NVREG_TXRXCTL_BIT2 | np->txrxctl_bits, base + NvRegTxRxControl); pci_push(base);}#if NVVER < SLES9static int nv_ethtool_ioctl(struct net_device *dev, void *useraddr){ struct fe_priv *np = get_nvpriv(dev); u8 *base = get_hwbase(dev); u32 ethcmd; if (copy_from_user(ðcmd, useraddr, sizeof (ethcmd))) return -EFAULT; switch (ethcmd) { case ETHTOOL_GDRVINFO: { struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; strcpy(info.driver, "forcedeth"); strcpy(info.version, FORCEDETH_VERSION); strcpy(info.bus_info, pci_name(np->pci_dev)); if (copy_to_user(useraddr, &info, sizeof (info))) return -EFAULT; return 0; } case ETHTOOL_GLINK: { struct ethtool_value edata = { ETHTOOL_GLINK }; edata.data = !!netif_carrier_ok(dev); if (copy_to_user(useraddr, &edata, sizeof(edata))) return -EFAULT; return 0; } case ETHTOOL_GWOL: { struct ethtool_wolinfo wolinfo; memset(&wolinfo, 0, sizeof(wolinfo)); wolinfo.supported = WAKE_MAGIC; spin_lock_irq(&np->lock); if (np->wolenabled) wolinfo.wolopts = WAKE_MAGIC; spin_unlock_irq(&np->lock); if (copy_to_user(useraddr, &wolinfo, sizeof(wolinfo))) return -EFAULT; return 0; } case ETHTOOL_SWOL: { struct ethtool_wolinfo wolinfo; if (copy_from_user(&wolinfo, useraddr, sizeof(wolinfo))) return -EFAULT; spin_lock_irq(&np->lock); if (wolinfo.wolopts == 0) { writel(0, base + NvRegWakeUpFlags); np->wolenabled = NV_WOL_DISABLED; } if (wolinfo.wolopts & WAKE_MAGIC) { writel(NVREG_WAKEUPFLAGS_ENABLE, base + NvRegWakeUpFlags); np->wolenabled = NV_WOL_ENABLED; } spin_unlock_irq(&np->lock); return 0; } default: break; } return -EOPNOTSUPP;}/* * nv_ioctl: dev->do_ioctl function * Called with rtnl_lock held. */static int nv_ioctl(struct net_device *dev, struct ifreq *rq, int cmd){ switch(cmd) { case SIOCETHTOOL: return nv_ethtool_ioctl(dev, rq->ifr_data); default: return -EOPNOTSUPP; }}#endif/* * nv_alloc_rx: fill rx ring entries. * Return 1 if the allocations for the skbs failed and the * rx engine is without Available descriptors */static inline int nv_alloc_rx(struct net_device *dev){ struct fe_priv *np = get_nvpriv(dev); struct ring_desc* less_rx; struct sk_buff *skb; less_rx = np->get_rx.orig; if (less_rx-- == np->first_rx.orig) less_rx = np->last_rx.orig; while (np->put_rx.orig != less_rx) { skb = dev_alloc_skb(np->rx_buf_sz + NV_RX_ALLOC_PAD); if (skb) { skb->dev = dev; np->put_rx_ctx->skb = skb;#if NVVER > FEDORA7 np->put_rx_ctx->dma = pci_map_single(np->pci_dev, skb->data, skb_tailroom(skb), PCI_DMA_FROMDEVICE); np->put_rx_ctx->dma_len = skb_tailroom(skb);#else np->put_rx_ctx->dma = pci_map_single(np->pci_dev, skb->data, skb->end-skb->data, PCI_DMA_FROMDEVICE); np->put_rx_ctx->dma_len = skb->end-skb->data;#endif np->put_rx.orig->PacketBuffer = cpu_to_le32(np->put_rx_ctx->dma); wmb(); np->put_rx.orig->FlagLen = cpu_to_le32(np->rx_buf_sz | NV_RX_AVAIL); if (unlikely(np->put_rx.orig++ == np->last_rx.orig)) np->put_rx.orig = np->first_rx.orig; if (unlikely(np->put_rx_ctx++ == np->last_rx_ctx)) np->put_rx_ctx = np->first_rx_ctx; } else { return 1; } } return 0;}static inline int nv_alloc_rx_optimized(struct net_device *dev){ struct fe_priv *np = get_nvpriv(dev); struct ring_desc_ex* less_rx; struct sk_buff *skb; less_rx = np->get_rx.ex; if (less_rx-- == np->first_rx.ex) less_rx = np->last_rx.ex; while (np->put_rx.ex != less_rx) { skb = dev_alloc_skb(np->rx_buf_sz + NV_RX_ALLOC_PAD); if (skb) { skb->dev = dev; np->put_rx_ctx->skb = skb;#if NVVER > FEDORA7 np->put_rx_ctx->dma = pci_map_single(np->pci_dev, skb->data, skb_tailroom(skb), PCI_DMA_FROMDEVICE); np->put_rx_ctx->dma_len = skb_tailroom(skb);#else np->put_rx_ctx->dma = pci_map_single(np->pci_dev, skb->data, skb->end-skb->data, PCI_DMA_FROMDEVICE); np->put_rx
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -