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

📄 r8169.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	RTL_W8(ChipCmd, 0x00);	rtl8169_irq_mask_and_ack(ioaddr);	RTL_R16(CPlusCmd);}static unsigned int rtl8169_tbi_reset_pending(void __iomem *ioaddr){	return RTL_R32(TBICSR) & TBIReset;}static unsigned int rtl8169_xmii_reset_pending(void __iomem *ioaddr){	return mdio_read(ioaddr, MII_BMCR) & BMCR_RESET;}static unsigned int rtl8169_tbi_link_ok(void __iomem *ioaddr){	return RTL_R32(TBICSR) & TBILinkOk;}static unsigned int rtl8169_xmii_link_ok(void __iomem *ioaddr){	return RTL_R8(PHYstatus) & LinkStatus;}static void rtl8169_tbi_reset_enable(void __iomem *ioaddr){	RTL_W32(TBICSR, RTL_R32(TBICSR) | TBIReset);}static void rtl8169_xmii_reset_enable(void __iomem *ioaddr){	unsigned int val;	val = mdio_read(ioaddr, MII_BMCR) | BMCR_RESET;	mdio_write(ioaddr, MII_BMCR, val & 0xffff);}static void rtl8169_check_link_status(struct net_device *dev,				      struct rtl8169_private *tp,				      void __iomem *ioaddr){	unsigned long flags;	spin_lock_irqsave(&tp->lock, flags);	if (tp->link_ok(ioaddr)) {		netif_carrier_on(dev);		if (netif_msg_ifup(tp))			printk(KERN_INFO PFX "%s: link up\n", dev->name);	} else {		if (netif_msg_ifdown(tp))			printk(KERN_INFO PFX "%s: link down\n", dev->name);		netif_carrier_off(dev);	}	spin_unlock_irqrestore(&tp->lock, flags);}static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol){	struct rtl8169_private *tp = netdev_priv(dev);	void __iomem *ioaddr = tp->mmio_addr;	u8 options;	wol->wolopts = 0;#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST)	wol->supported = WAKE_ANY;	spin_lock_irq(&tp->lock);	options = RTL_R8(Config1);	if (!(options & PMEnable))		goto out_unlock;	options = RTL_R8(Config3);	if (options & LinkUp)		wol->wolopts |= WAKE_PHY;	if (options & MagicPacket)		wol->wolopts |= WAKE_MAGIC;	options = RTL_R8(Config5);	if (options & UWF)		wol->wolopts |= WAKE_UCAST;	if (options & BWF)		wol->wolopts |= WAKE_BCAST;	if (options & MWF)		wol->wolopts |= WAKE_MCAST;out_unlock:	spin_unlock_irq(&tp->lock);}static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol){	struct rtl8169_private *tp = netdev_priv(dev);	void __iomem *ioaddr = tp->mmio_addr;	unsigned int i;	static struct {		u32 opt;		u16 reg;		u8  mask;	} cfg[] = {		{ WAKE_ANY,   Config1, PMEnable },		{ WAKE_PHY,   Config3, LinkUp },		{ WAKE_MAGIC, Config3, MagicPacket },		{ WAKE_UCAST, Config5, UWF },		{ WAKE_BCAST, Config5, BWF },		{ WAKE_MCAST, Config5, MWF },		{ WAKE_ANY,   Config5, LanWake }	};	spin_lock_irq(&tp->lock);	RTL_W8(Cfg9346, Cfg9346_Unlock);	for (i = 0; i < ARRAY_SIZE(cfg); i++) {		u8 options = RTL_R8(cfg[i].reg) & ~cfg[i].mask;		if (wol->wolopts & cfg[i].opt)			options |= cfg[i].mask;		RTL_W8(cfg[i].reg, options);	}	RTL_W8(Cfg9346, Cfg9346_Lock);	if (wol->wolopts)		tp->features |= RTL_FEATURE_WOL;	else		tp->features &= ~RTL_FEATURE_WOL;	spin_unlock_irq(&tp->lock);	return 0;}static void rtl8169_get_drvinfo(struct net_device *dev,				struct ethtool_drvinfo *info){	struct rtl8169_private *tp = netdev_priv(dev);	strcpy(info->driver, MODULENAME);	strcpy(info->version, RTL8169_VERSION);	strcpy(info->bus_info, pci_name(tp->pci_dev));}static int rtl8169_get_regs_len(struct net_device *dev){	return R8169_REGS_SIZE;}static int rtl8169_set_speed_tbi(struct net_device *dev,				 u8 autoneg, u16 speed, u8 duplex){	struct rtl8169_private *tp = netdev_priv(dev);	void __iomem *ioaddr = tp->mmio_addr;	int ret = 0;	u32 reg;	reg = RTL_R32(TBICSR);	if ((autoneg == AUTONEG_DISABLE) && (speed == SPEED_1000) &&	    (duplex == DUPLEX_FULL)) {		RTL_W32(TBICSR, reg & ~(TBINwEnable | TBINwRestart));	} else if (autoneg == AUTONEG_ENABLE)		RTL_W32(TBICSR, reg | TBINwEnable | TBINwRestart);	else {		if (netif_msg_link(tp)) {			printk(KERN_WARNING "%s: "			       "incorrect speed setting refused in TBI mode\n",			       dev->name);		}		ret = -EOPNOTSUPP;	}	return ret;}static int rtl8169_set_speed_xmii(struct net_device *dev,				  u8 autoneg, u16 speed, u8 duplex){	struct rtl8169_private *tp = netdev_priv(dev);	void __iomem *ioaddr = tp->mmio_addr;	int auto_nego, giga_ctrl;	auto_nego = mdio_read(ioaddr, MII_ADVERTISE);	auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL |		       ADVERTISE_100HALF | ADVERTISE_100FULL);	giga_ctrl = mdio_read(ioaddr, MII_CTRL1000);	giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);	if (autoneg == AUTONEG_ENABLE) {		auto_nego |= (ADVERTISE_10HALF | ADVERTISE_10FULL |			      ADVERTISE_100HALF | ADVERTISE_100FULL);		giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF;	} else {		if (speed == SPEED_10)			auto_nego |= ADVERTISE_10HALF | ADVERTISE_10FULL;		else if (speed == SPEED_100)			auto_nego |= ADVERTISE_100HALF | ADVERTISE_100FULL;		else if (speed == SPEED_1000)			giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF;		if (duplex == DUPLEX_HALF)			auto_nego &= ~(ADVERTISE_10FULL | ADVERTISE_100FULL);		if (duplex == DUPLEX_FULL)			auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_100HALF);		/* This tweak comes straight from Realtek's driver. */		if ((speed == SPEED_100) && (duplex == DUPLEX_HALF) &&		    ((tp->mac_version == RTL_GIGA_MAC_VER_13) ||		     (tp->mac_version == RTL_GIGA_MAC_VER_16))) {			auto_nego = ADVERTISE_100HALF | ADVERTISE_CSMA;		}	}	/* The 8100e/8101e do Fast Ethernet only. */	if ((tp->mac_version == RTL_GIGA_MAC_VER_13) ||	    (tp->mac_version == RTL_GIGA_MAC_VER_14) ||	    (tp->mac_version == RTL_GIGA_MAC_VER_15) ||	    (tp->mac_version == RTL_GIGA_MAC_VER_16)) {		if ((giga_ctrl & (ADVERTISE_1000FULL | ADVERTISE_1000HALF)) &&		    netif_msg_link(tp)) {			printk(KERN_INFO "%s: PHY does not support 1000Mbps.\n",			       dev->name);		}		giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);	}	auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;	if ((tp->mac_version == RTL_GIGA_MAC_VER_12) ||	    (tp->mac_version == RTL_GIGA_MAC_VER_17)) {		/* Vendor specific (0x1f) and reserved (0x0e) MII registers. */		mdio_write(ioaddr, 0x1f, 0x0000);		mdio_write(ioaddr, 0x0e, 0x0000);	}	tp->phy_auto_nego_reg = auto_nego;	tp->phy_1000_ctrl_reg = giga_ctrl;	mdio_write(ioaddr, MII_ADVERTISE, auto_nego);	mdio_write(ioaddr, MII_CTRL1000, giga_ctrl);	mdio_write(ioaddr, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART);	return 0;}static int rtl8169_set_speed(struct net_device *dev,			     u8 autoneg, u16 speed, u8 duplex){	struct rtl8169_private *tp = netdev_priv(dev);	int ret;	ret = tp->set_speed(dev, autoneg, speed, duplex);	if (netif_running(dev) && (tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL))		mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT);	return ret;}static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd){	struct rtl8169_private *tp = netdev_priv(dev);	unsigned long flags;	int ret;	spin_lock_irqsave(&tp->lock, flags);	ret = rtl8169_set_speed(dev, cmd->autoneg, cmd->speed, cmd->duplex);	spin_unlock_irqrestore(&tp->lock, flags);	return ret;}static u32 rtl8169_get_rx_csum(struct net_device *dev){	struct rtl8169_private *tp = netdev_priv(dev);	return tp->cp_cmd & RxChkSum;}static int rtl8169_set_rx_csum(struct net_device *dev, u32 data){	struct rtl8169_private *tp = netdev_priv(dev);	void __iomem *ioaddr = tp->mmio_addr;	unsigned long flags;	spin_lock_irqsave(&tp->lock, flags);	if (data)		tp->cp_cmd |= RxChkSum;	else		tp->cp_cmd &= ~RxChkSum;	RTL_W16(CPlusCmd, tp->cp_cmd);	RTL_R16(CPlusCmd);	spin_unlock_irqrestore(&tp->lock, flags);	return 0;}#ifdef CONFIG_R8169_VLANstatic inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp,				      struct sk_buff *skb){	return (tp->vlgrp && vlan_tx_tag_present(skb)) ?		TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00;}static void rtl8169_vlan_rx_register(struct net_device *dev,				     struct vlan_group *grp){	struct rtl8169_private *tp = netdev_priv(dev);	void __iomem *ioaddr = tp->mmio_addr;	unsigned long flags;	spin_lock_irqsave(&tp->lock, flags);	tp->vlgrp = grp;	if (tp->vlgrp)		tp->cp_cmd |= RxVlan;	else		tp->cp_cmd &= ~RxVlan;	RTL_W16(CPlusCmd, tp->cp_cmd);	RTL_R16(CPlusCmd);	spin_unlock_irqrestore(&tp->lock, flags);}static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc,			       struct sk_buff *skb){	u32 opts2 = le32_to_cpu(desc->opts2);	int ret;	if (tp->vlgrp && (opts2 & RxVlanTag)) {		rtl8169_rx_hwaccel_skb(skb, tp->vlgrp, swab16(opts2 & 0xffff));		ret = 0;	} else		ret = -1;	desc->opts2 = 0;	return ret;}#else /* !CONFIG_R8169_VLAN */static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp,				      struct sk_buff *skb){	return 0;}static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc,			       struct sk_buff *skb){	return -1;}#endifstatic void rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd){	struct rtl8169_private *tp = netdev_priv(dev);	void __iomem *ioaddr = tp->mmio_addr;	u32 status;	cmd->supported =		SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_FIBRE;	cmd->port = PORT_FIBRE;	cmd->transceiver = XCVR_INTERNAL;	status = RTL_R32(TBICSR);	cmd->advertising = (status & TBINwEnable) ?  ADVERTISED_Autoneg : 0;	cmd->autoneg = !!(status & TBINwEnable);	cmd->speed = SPEED_1000;	cmd->duplex = DUPLEX_FULL; /* Always set */}static void rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd){	struct rtl8169_private *tp = netdev_priv(dev);	void __iomem *ioaddr = tp->mmio_addr;	u8 status;	cmd->supported = SUPPORTED_10baseT_Half |			 SUPPORTED_10baseT_Full |			 SUPPORTED_100baseT_Half |			 SUPPORTED_100baseT_Full |			 SUPPORTED_1000baseT_Full |			 SUPPORTED_Autoneg |			 SUPPORTED_TP;	cmd->autoneg = 1;	cmd->advertising = ADVERTISED_TP | ADVERTISED_Autoneg;	if (tp->phy_auto_nego_reg & ADVERTISE_10HALF)		cmd->advertising |= ADVERTISED_10baseT_Half;	if (tp->phy_auto_nego_reg & ADVERTISE_10FULL)		cmd->advertising |= ADVERTISED_10baseT_Full;	if (tp->phy_auto_nego_reg & ADVERTISE_100HALF)		cmd->advertising |= ADVERTISED_100baseT_Half;	if (tp->phy_auto_nego_reg & ADVERTISE_100FULL)		cmd->advertising |= ADVERTISED_100baseT_Full;	if (tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)		cmd->advertising |= ADVERTISED_1000baseT_Full;	status = RTL_R8(PHYstatus);	if (status & _1000bpsF)		cmd->speed = SPEED_1000;	else if (status & _100bps)		cmd->speed = SPEED_100;	else if (status & _10bps)		cmd->speed = SPEED_10;	if (status & TxFlowCtrl)		cmd->advertising |= ADVERTISED_Asym_Pause;	if (status & RxFlowCtrl)		cmd->advertising |= ADVERTISED_Pause;	cmd->duplex = ((status & _1000bpsF) || (status & FullDup)) ?		      DUPLEX_FULL : DUPLEX_HALF;}static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd){	struct rtl8169_private *tp = netdev_priv(dev);	unsigned long flags;	spin_lock_irqsave(&tp->lock, flags);	tp->get_settings(dev, cmd);	spin_unlock_irqrestore(&tp->lock, flags);	return 0;}static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs,			     void *p){	struct rtl8169_private *tp = netdev_priv(dev);	unsigned long flags;	if (regs->len > R8169_REGS_SIZE)		regs->len = R8169_REGS_SIZE;	spin_lock_irqsave(&tp->lock, flags);	memcpy_fromio(p, tp->mmio_addr, regs->len);	spin_unlock_irqrestore(&tp->lock, flags);}static u32 rtl8169_get_msglevel(struct net_device *dev){	struct rtl8169_private *tp = netdev_priv(dev);	return tp->msg_enable;}static void rtl8169_set_msglevel(struct net_device *dev, u32 value){	struct rtl8169_private *tp = netdev_priv(dev);	tp->msg_enable = value;}static const char rtl8169_gstrings[][ETH_GSTRING_LEN] = {	"tx_packets",	"rx_packets",	"tx_errors",	"rx_errors",	"rx_missed",	"align_errors",	"tx_single_collisions",	"tx_multi_collisions",	"unicast",	"broadcast",	"multicast",	"tx_aborted",	"tx_underrun",};struct rtl8169_counters {	__le64	tx_packets;	__le64	rx_packets;	__le64	tx_errors;	__le32	rx_errors;	__le16	rx_missed;	__le16	align_errors;	__le32	tx_one_collision;	__le32	tx_multi_collision;	__le64	rx_unicast;	__le64	rx_broadcast;	__le32	rx_multicast;	__le16	tx_aborted;	__le16	tx_underun;};static int rtl8169_get_sset_count(struct net_device *dev, int sset){	switch (sset) {	case ETH_SS_STATS:		return ARRAY_SIZE(rtl8169_gstrings);	default:		return -EOPNOTSUPP;	}}static void rtl8169_get_ethtool_stats(struct net_device *dev,				      struct ethtool_stats *stats, u64 *data){	struct rtl8169_private *tp = netdev_priv(dev);	void __iomem *ioaddr = tp->mmio_addr;	struct rtl8169_counters *counters;	dma_addr_t paddr;	u32 cmd;

⌨️ 快捷键说明

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