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

📄 r8169.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 4 页
字号:
		if (p->media == option)			break;	}	*autoneg = p->autoneg;	*speed = p->speed;	*duplex = p->duplex;}static void rtl8169_get_drvinfo(struct net_device *dev,				struct ethtool_drvinfo *info){	struct rtl8169_private *tp = netdev_priv(dev);	strcpy(info->driver, RTL8169_DRIVER_NAME);	strcpy(info->version, RTL8169_VERSION );	strcpy(info->bus_info, pci_name(tp->pci_dev));}static int rtl8169_set_speed_tbi(struct net_device *dev,				 u8 autoneg, u16 speed, u8 duplex){	struct rtl8169_private *tp = netdev_priv(dev);	void *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 {		printk(KERN_WARNING PFX		       "%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 *ioaddr = tp->mmio_addr;	int auto_nego, giga_ctrl;	auto_nego = mdio_read(ioaddr, PHY_AUTO_NEGO_REG);	auto_nego &= ~(PHY_Cap_10_Half | PHY_Cap_10_Full |		       PHY_Cap_100_Half | PHY_Cap_100_Full);	giga_ctrl = mdio_read(ioaddr, PHY_1000_CTRL_REG);	giga_ctrl &= ~(PHY_Cap_1000_Full | PHY_Cap_Null);	if (autoneg == AUTONEG_ENABLE) {		auto_nego |= (PHY_Cap_10_Half | PHY_Cap_10_Full |			      PHY_Cap_100_Half | PHY_Cap_100_Full);		giga_ctrl |= PHY_Cap_1000_Full;	} else {		if (speed == SPEED_10)			auto_nego |= PHY_Cap_10_Half | PHY_Cap_10_Full;		else if (speed == SPEED_100)			auto_nego |= PHY_Cap_100_Half | PHY_Cap_100_Full;		else if (speed == SPEED_1000)			giga_ctrl |= PHY_Cap_1000_Full;		if (duplex == DUPLEX_HALF)			auto_nego &= ~(PHY_Cap_10_Full | PHY_Cap_100_Full);	}	tp->phy_auto_nego_reg = auto_nego;	tp->phy_1000_ctrl_reg = giga_ctrl;	mdio_write(ioaddr, PHY_AUTO_NEGO_REG, auto_nego);	mdio_write(ioaddr, PHY_1000_CTRL_REG, giga_ctrl);	mdio_write(ioaddr, PHY_CTRL_REG, PHY_Enable_Auto_Nego |					 PHY_Restart_Auto_Nego);	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 & PHY_Cap_1000_Full))		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 void rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd){	struct rtl8169_private *tp = netdev_priv(dev);	void *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 *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 & PHY_Cap_10_Half)		cmd->advertising |= ADVERTISED_10baseT_Half;	if (tp->phy_auto_nego_reg & PHY_Cap_10_Full)		cmd->advertising |= ADVERTISED_10baseT_Full;	if (tp->phy_auto_nego_reg & PHY_Cap_100_Half)		cmd->advertising |= ADVERTISED_100baseT_Half;	if (tp->phy_auto_nego_reg & PHY_Cap_100_Full)		cmd->advertising |= ADVERTISED_100baseT_Full;	if (tp->phy_1000_ctrl_reg & PHY_Cap_1000_Full)		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;	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 struct ethtool_ops rtl8169_ethtool_ops = {	.get_drvinfo		= rtl8169_get_drvinfo,	.get_link		= ethtool_op_get_link,	.get_settings		= rtl8169_get_settings,	.set_settings		= rtl8169_set_settings,};static void rtl8169_write_gmii_reg_bit(void *ioaddr, int reg, int bitnum,				       int bitval){	int val;	val = mdio_read(ioaddr, reg);	val = (bitval == 1) ?		val | (bitval << bitnum) :  val & ~(0x0001 << bitnum);	mdio_write(ioaddr, reg, val & 0xffff); }static void rtl8169_get_mac_version(struct rtl8169_private *tp, void *ioaddr){	const struct {		u32 mask;		int mac_version;	} mac_info[] = {		{ 0x1 << 26,	RTL_GIGA_MAC_VER_E },		{ 0x1 << 23,	RTL_GIGA_MAC_VER_D }, 		{ 0x00000000,	RTL_GIGA_MAC_VER_B } /* Catch-all */	}, *p = mac_info;	u32 reg;	reg = RTL_R32(TxConfig) & 0x7c800000;	while ((reg & p->mask) != p->mask)		p++;	tp->mac_version = p->mac_version;}static void rtl8169_print_mac_version(struct rtl8169_private *tp){	struct {		int version;		char *msg;	} mac_print[] = {		{ RTL_GIGA_MAC_VER_E, "RTL_GIGA_MAC_VER_E" },		{ RTL_GIGA_MAC_VER_D, "RTL_GIGA_MAC_VER_D" },		{ RTL_GIGA_MAC_VER_B, "RTL_GIGA_MAC_VER_B" },		{ 0, NULL }	}, *p;	for (p = mac_print; p->msg; p++) {		if (tp->mac_version == p->version) {			dprintk("mac_version == %s (%04d)\n", p->msg,				  p->version);			return;		}	}	dprintk("mac_version == Unknown\n");}static void rtl8169_get_phy_version(struct rtl8169_private *tp, void *ioaddr){	const struct {		u16 mask;		u16 set;		int phy_version;	} phy_info[] = {		{ 0x000f, 0x0002, RTL_GIGA_PHY_VER_G },		{ 0x000f, 0x0001, RTL_GIGA_PHY_VER_F },		{ 0x000f, 0x0000, RTL_GIGA_PHY_VER_E },		{ 0x0000, 0x0000, RTL_GIGA_PHY_VER_D } /* Catch-all */	}, *p = phy_info;	u16 reg;	reg = mdio_read(ioaddr, 3) & 0xffff;	while ((reg & p->mask) != p->set)		p++;	tp->phy_version = p->phy_version;}static void rtl8169_print_phy_version(struct rtl8169_private *tp){	struct {		int version;		char *msg;		u32 reg;	} phy_print[] = {		{ RTL_GIGA_PHY_VER_G, "RTL_GIGA_PHY_VER_G", 0x0002 },		{ RTL_GIGA_PHY_VER_F, "RTL_GIGA_PHY_VER_F", 0x0001 },		{ RTL_GIGA_PHY_VER_E, "RTL_GIGA_PHY_VER_E", 0x0000 },		{ RTL_GIGA_PHY_VER_D, "RTL_GIGA_PHY_VER_D", 0x0000 },		{ 0, NULL, 0x0000 }	}, *p;	for (p = phy_print; p->msg; p++) {		if (tp->phy_version == p->version) {			dprintk("phy_version == %s (%04x)\n", p->msg, p->reg);			return;		}	}	dprintk("phy_version == Unknown\n");}static void rtl8169_hw_phy_config(struct net_device *dev){	struct rtl8169_private *tp = netdev_priv(dev);	void *ioaddr = tp->mmio_addr;	struct {		u16 regs[5]; /* Beware of bit-sign propagation */	} phy_magic[5] = { {		{ 0x0000,	//w 4 15 12 0		  0x00a1,	//w 3 15 0 00a1		  0x0008,	//w 2 15 0 0008		  0x1020,	//w 1 15 0 1020		  0x1000 } },{	//w 0 15 0 1000		{ 0x7000,	//w 4 15 12 7		  0xff41,	//w 3 15 0 ff41		  0xde60,	//w 2 15 0 de60		  0x0140,	//w 1 15 0 0140		  0x0077 } },{	//w 0 15 0 0077		{ 0xa000,	//w 4 15 12 a		  0xdf01,	//w 3 15 0 df01		  0xdf20,	//w 2 15 0 df20		  0xff95,	//w 1 15 0 ff95		  0xfa00 } },{	//w 0 15 0 fa00		{ 0xb000,	//w 4 15 12 b		  0xff41,	//w 3 15 0 ff41		  0xde20,	//w 2 15 0 de20		  0x0140,	//w 1 15 0 0140		  0x00bb } },{	//w 0 15 0 00bb		{ 0xf000,	//w 4 15 12 f		  0xdf01,	//w 3 15 0 df01		  0xdf20,	//w 2 15 0 df20		  0xff95,	//w 1 15 0 ff95		  0xbf00 }	//w 0 15 0 bf00		}	}, *p = phy_magic;	int i;	rtl8169_print_mac_version(tp);	rtl8169_print_phy_version(tp);	if (tp->mac_version <= RTL_GIGA_MAC_VER_B)		return;	if (tp->phy_version >= RTL_GIGA_PHY_VER_F) 		return;	dprintk("MAC version != 0 && PHY version == 0 or 1\n");	dprintk("Do final_reg2.cfg\n");	/* Shazam ! */	// phy config for RTL8169s mac_version C chip	mdio_write(ioaddr, 31, 0x0001);			//w 31 2 0 1	mdio_write(ioaddr, 21, 0x1000);			//w 21 15 0 1000	mdio_write(ioaddr, 24, 0x65c7);			//w 24 15 0 65c7	rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 0);	//w 4 11 11 0	for (i = 0; i < ARRAY_SIZE(phy_magic); i++, p++) {		int val, pos = 4;		val = (mdio_read(ioaddr, pos) & 0x0fff) | (p->regs[0] & 0xffff);		mdio_write(ioaddr, pos, val);		while (--pos >= 0)			mdio_write(ioaddr, pos, p->regs[4 - pos] & 0xffff);		rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 1); //w 4 11 11 1		rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 0); //w 4 11 11 0	}	mdio_write(ioaddr, 31, 0x0000); //w 31 2 0 0}static void rtl8169_phy_timer(unsigned long __opaque){	struct net_device *dev = (struct net_device *)__opaque;	struct rtl8169_private *tp = netdev_priv(dev);	struct timer_list *timer = &tp->timer;	void *ioaddr = tp->mmio_addr;	unsigned long timeout = RTL8169_PHY_TIMEOUT;	assert(tp->mac_version > RTL_GIGA_MAC_VER_B);	assert(tp->phy_version < RTL_GIGA_PHY_VER_G);	if (!(tp->phy_1000_ctrl_reg & PHY_Cap_1000_Full))		return;	spin_lock_irq(&tp->lock);	if (tp->phy_reset_pending(ioaddr)) {		/* 		 * A busy loop could burn quite a few cycles on nowadays CPU.		 * Let's delay the execution of the timer for a few ticks.		 */		timeout = HZ/10;		goto out_mod_timer;	}	if (tp->link_ok(ioaddr))		goto out_unlock;	printk(KERN_WARNING PFX "%s: PHY reset until link up\n", dev->name);	tp->phy_reset_enable(ioaddr);out_mod_timer:	mod_timer(timer, jiffies + timeout);out_unlock:	spin_unlock_irq(&tp->lock);}static inline void rtl8169_delete_timer(struct net_device *dev){	struct rtl8169_private *tp = netdev_priv(dev);	struct timer_list *timer = &tp->timer;	if ((tp->mac_version <= RTL_GIGA_MAC_VER_B) ||	    (tp->phy_version >= RTL_GIGA_PHY_VER_G))		return;	del_timer_sync(timer);}static inline void rtl8169_request_timer(struct net_device *dev){	struct rtl8169_private *tp = netdev_priv(dev);	struct timer_list *timer = &tp->timer;	if ((tp->mac_version <= RTL_GIGA_MAC_VER_B) ||	    (tp->phy_version >= RTL_GIGA_PHY_VER_G))		return;	init_timer(timer);	timer->expires = jiffies + RTL8169_PHY_TIMEOUT;	timer->data = (unsigned long)(dev);	timer->function = rtl8169_phy_timer;	add_timer(timer);}static int __devinitrtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,		   void **ioaddr_out){	void *ioaddr = NULL;	struct net_device *dev;	struct rtl8169_private *tp;	unsigned long mmio_start, mmio_end, mmio_flags, mmio_len;	int rc, i, acpi_idle_state = 0, pm_cap;	assert(pdev != NULL);	assert(ioaddr_out != NULL);	*ioaddr_out = NULL;	*dev_out = NULL;	// dev zeroed in alloc_etherdev 	dev = alloc_etherdev(sizeof (*tp));	if (dev == NULL) {		printk(KERN_ERR PFX "unable to alloc new ethernet\n");		return -ENOMEM;	}	SET_MODULE_OWNER(dev);	SET_NETDEV_DEV(dev, &pdev->dev);	tp = dev->priv;	// enable device (incl. PCI PM wakeup and hotplug setup)	rc = pci_enable_device(pdev);	if (rc) {		printk(KERN_ERR PFX "%s: enable failure\n", pdev->slot_name);		goto err_out;	}	/* save power state before pci_enable_device overwrites it */	pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM);	if (pm_cap) {		u16 pwr_command;		pci_read_config_word(pdev, pm_cap + PCI_PM_CTRL, &pwr_command);		acpi_idle_state = pwr_command & PCI_PM_CTRL_STATE_MASK;	} else {		printk(KERN_ERR PFX		       "Cannot find PowerManagement capability, aborting.\n");		goto err_out_free_res;	}	mmio_start = pci_resource_start(pdev, 1);	mmio_end = pci_resource_end(pdev, 1);	mmio_flags = pci_resource_flags(pdev, 1);	mmio_len = pci_resource_len(pdev, 1);	// make sure PCI base addr 1 is MMIO	if (!(mmio_flags & IORESOURCE_MEM)) {		printk(KERN_ERR PFX		       "region #1 not an MMIO resource, aborting\n");		rc = -ENODEV;		goto err_out_disable;	}	// check for weird/broken PCI region reporting	if (mmio_len < RTL_MIN_IO_SIZE) {		printk(KERN_ERR PFX "Invalid PCI region size(s), aborting\n");		rc = -ENODEV;		goto err_out_disable;	}	rc = pci_request_regions(pdev, MODULENAME);	if (rc) {		printk(KERN_ERR PFX "%s: could not request regions.\n",		       pdev->slot_name);		goto err_out_disable;	}	tp->cp_cmd = PCIMulRW | RxChkSum;	if ((sizeof(dma_addr_t) > 4) &&	    !pci_set_dma_mask(pdev, DMA_64BIT_MASK) && use_dac)

⌨️ 快捷键说明

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