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

📄 r8169.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 4 页
字号:
		tp->cp_cmd |= PCIDAC;	else {		rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);		if (rc < 0) {			printk(KERN_ERR PFX "DMA configuration failed.\n");			goto err_out_free_res;		}	}	// enable PCI bus-mastering	pci_set_master(pdev);	// ioremap MMIO region 	ioaddr = ioremap(mmio_start, mmio_len);	if (ioaddr == NULL) {		printk(KERN_ERR PFX "cannot remap MMIO, aborting\n");		rc = -EIO;		goto err_out_free_res;	}	// Soft reset the chip. 	RTL_W8(ChipCmd, CmdReset);	// Check that the chip has finished the reset.	for (i = 1000; i > 0; i--) {		if ((RTL_R8(ChipCmd) & CmdReset) == 0)			break;		udelay(10);	}	// Identify chip attached to board	rtl8169_get_mac_version(tp, ioaddr);	rtl8169_get_phy_version(tp, ioaddr);	rtl8169_print_mac_version(tp);	rtl8169_print_phy_version(tp);	for (i = ARRAY_SIZE(rtl_chip_info) - 1; i >= 0; i--) {		if (tp->mac_version == rtl_chip_info[i].mac_version)			break;	}	if (i < 0) {		/* Unknown chip: assume array element #0, original RTL-8169 */		printk(KERN_DEBUG PFX		       "PCI device %s: unknown chip version, assuming %s\n",		       pci_name(pdev), rtl_chip_info[0].name);		i++;	}	tp->chipset = i;	*ioaddr_out = ioaddr;	*dev_out = dev;	return 0;err_out_free_res:	pci_release_regions(pdev);err_out_disable:	pci_disable_device(pdev);err_out:	free_netdev(dev);	return rc;}static int __devinitrtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent){	struct net_device *dev = NULL;	struct rtl8169_private *tp = NULL;	void *ioaddr = NULL;	static int board_idx = -1;	static int printed_version = 0;	u8 autoneg, duplex;	u16 speed;	int i, rc;	assert(pdev != NULL);	assert(ent != NULL);	board_idx++;	if (!printed_version) {		printk(KERN_INFO RTL8169_DRIVER_NAME " loaded\n");		printed_version = 1;	}	rc = rtl8169_init_board(pdev, &dev, &ioaddr);	if (rc)		return rc;	tp = dev->priv;	assert(ioaddr != NULL);	assert(dev != NULL);	assert(tp != NULL);	if (RTL_R8(PHYstatus) & TBI_Enable) {		tp->set_speed = rtl8169_set_speed_tbi;		tp->get_settings = rtl8169_gset_tbi;		tp->phy_reset_enable = rtl8169_tbi_reset_enable;		tp->phy_reset_pending = rtl8169_tbi_reset_pending;		tp->link_ok = rtl8169_tbi_link_ok;		tp->phy_1000_ctrl_reg = PHY_Cap_1000_Full; /* Implied by TBI */	} else {		tp->set_speed = rtl8169_set_speed_xmii;		tp->get_settings = rtl8169_gset_xmii;		tp->phy_reset_enable = rtl8169_xmii_reset_enable;		tp->phy_reset_pending = rtl8169_xmii_reset_pending;		tp->link_ok = rtl8169_xmii_link_ok;	}	// Get MAC address.  FIXME: read EEPROM	for (i = 0; i < MAC_ADDR_LEN; i++)		dev->dev_addr[i] = RTL_R8(MAC0 + i);	dev->open = rtl8169_open;	dev->hard_start_xmit = rtl8169_start_xmit;	dev->get_stats = rtl8169_get_stats;	dev->ethtool_ops = &rtl8169_ethtool_ops;	dev->stop = rtl8169_close;	dev->tx_timeout = rtl8169_tx_timeout;	dev->set_multicast_list = rtl8169_set_rx_mode;	dev->watchdog_timeo = RTL8169_TX_TIMEOUT;	dev->irq = pdev->irq;	dev->base_addr = (unsigned long) ioaddr;#ifdef CONFIG_R8169_NAPI	dev->poll = rtl8169_poll;	dev->weight = R8169_NAPI_WEIGHT;	printk(KERN_INFO PFX "NAPI enabled\n");#endif	tp->intr_mask = 0xffff;	tp->pci_dev = pdev;	tp->mmio_addr = ioaddr;	spin_lock_init(&tp->lock);	rc = register_netdev(dev);	if (rc) {		iounmap(ioaddr);		pci_release_regions(pdev);		pci_disable_device(pdev);		free_netdev(dev);		return rc;	}	printk(KERN_DEBUG "%s: Identified chip type is '%s'.\n", dev->name,	       rtl_chip_info[tp->chipset].name);	pci_set_drvdata(pdev, dev);	printk(KERN_INFO "%s: %s at 0x%lx, "	       "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "	       "IRQ %d\n",	       dev->name,	       rtl_chip_info[ent->driver_data].name,	       dev->base_addr,	       dev->dev_addr[0], dev->dev_addr[1],	       dev->dev_addr[2], dev->dev_addr[3],	       dev->dev_addr[4], dev->dev_addr[5], dev->irq);	rtl8169_hw_phy_config(dev);	dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");	RTL_W8(0x82, 0x01);	if (tp->mac_version < RTL_GIGA_MAC_VER_E) {		dprintk("Set PCI Latency=0x40\n");		pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x40);	}	if (tp->mac_version == RTL_GIGA_MAC_VER_D) {		dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");		RTL_W8(0x82, 0x01);		dprintk("Set PHY Reg 0x0bh = 0x00h\n");		mdio_write(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0	}	rtl8169_link_option(board_idx, &autoneg, &speed, &duplex);	rtl8169_set_speed(dev, autoneg, speed, duplex);		if (RTL_R8(PHYstatus) & TBI_Enable)		printk(KERN_INFO PFX "%s: TBI auto-negotiating\n", dev->name);	return 0;}static void __devexitrtl8169_remove_one(struct pci_dev *pdev){	struct net_device *dev = pci_get_drvdata(pdev);	struct rtl8169_private *tp = netdev_priv(dev);	assert(dev != NULL);	assert(tp != NULL);	unregister_netdev(dev);	iounmap(tp->mmio_addr);	pci_release_regions(pdev);	pci_disable_device(pdev);	free_netdev(dev);	pci_set_drvdata(pdev, NULL);}#ifdef CONFIG_PMstatic int rtl8169_suspend(struct pci_dev *pdev, u32 state){	struct net_device *dev = pci_get_drvdata(pdev);	struct rtl8169_private *tp = netdev_priv(dev);	void *ioaddr = tp->mmio_addr;	unsigned long flags;	if (!netif_running(dev))		return 0;		netif_device_detach(dev);	netif_stop_queue(dev);	spin_lock_irqsave(&tp->lock, flags);	/* Disable interrupts, stop Rx and Tx */	RTL_W16(IntrMask, 0);	RTL_W8(ChipCmd, 0);			/* Update the error counts. */	tp->stats.rx_missed_errors += RTL_R32(RxMissed);	RTL_W32(RxMissed, 0);	spin_unlock_irqrestore(&tp->lock, flags);		return 0;}static int rtl8169_resume(struct pci_dev *pdev){	struct net_device *dev = pci_get_drvdata(pdev);	if (!netif_running(dev))	    return 0;	netif_device_attach(dev);	rtl8169_hw_start(dev);	return 0;}                                                                                #endif /* CONFIG_PM */static intrtl8169_open(struct net_device *dev){	struct rtl8169_private *tp = netdev_priv(dev);	struct pci_dev *pdev = tp->pci_dev;	int retval;	retval =	    request_irq(dev->irq, rtl8169_interrupt, SA_SHIRQ, dev->name, dev);	if (retval < 0)		goto out;	retval = -ENOMEM;	/*	 * Rx and Tx desscriptors needs 256 bytes alignment.	 * pci_alloc_consistent provides more.	 */	tp->TxDescArray = pci_alloc_consistent(pdev, R8169_TX_RING_BYTES,					       &tp->TxPhyAddr);	if (!tp->TxDescArray)		goto err_free_irq;	tp->RxDescArray = pci_alloc_consistent(pdev, R8169_RX_RING_BYTES,					       &tp->RxPhyAddr);	if (!tp->RxDescArray)		goto err_free_tx;	retval = rtl8169_init_ring(dev);	if (retval < 0)		goto err_free_rx;	rtl8169_hw_start(dev);	rtl8169_request_timer(dev);	rtl8169_check_link_status(dev, tp, tp->mmio_addr);out:	return retval;err_free_rx:	pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray,			    tp->RxPhyAddr);err_free_tx:	pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray,			    tp->TxPhyAddr);err_free_irq:	free_irq(dev->irq, dev);	goto out;}static voidrtl8169_hw_start(struct net_device *dev){	struct rtl8169_private *tp = netdev_priv(dev);	void *ioaddr = tp->mmio_addr;	u32 i;	/* Soft reset the chip. */	RTL_W8(ChipCmd, CmdReset);	/* Check that the chip has finished the reset. */	for (i = 1000; i > 0; i--) {		if ((RTL_R8(ChipCmd) & CmdReset) == 0)			break;		udelay(10);	}	RTL_W8(Cfg9346, Cfg9346_Unlock);	RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);	RTL_W8(EarlyTxThres, EarlyTxThld);	// For gigabit rtl8169	RTL_W16(RxMaxSize, RxPacketMaxSize);	// Set Rx Config register	i = rtl8169_rx_config |		(RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask);	RTL_W32(RxConfig, i);	/* Set DMA burst size and Interframe Gap Time */	RTL_W32(TxConfig,		(TX_DMA_BURST << TxDMAShift) | (InterFrameGap <<						TxInterFrameGapShift));	tp->cp_cmd |= RTL_R16(CPlusCmd);	RTL_W16(CPlusCmd, tp->cp_cmd);	if (tp->mac_version == RTL_GIGA_MAC_VER_D) {		dprintk(KERN_INFO PFX "Set MAC Reg C+CR Offset 0xE0. "			"Bit-3 and bit-14 MUST be 1\n");		tp->cp_cmd |= (1 << 14) | PCIMulRW;		RTL_W16(CPlusCmd, tp->cp_cmd);	}	tp->cur_rx = 0;	RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr & DMA_32BIT_MASK));	RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr >> 32));	RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr & DMA_32BIT_MASK));	RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr >> 32));	RTL_W8(Cfg9346, Cfg9346_Lock);	udelay(10);	RTL_W32(RxMissed, 0);	rtl8169_set_rx_mode(dev);	/* no early-rx interrupts */	RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000);	/* Enable all known interrupts by setting the interrupt mask. */	RTL_W16(IntrMask, rtl8169_intr_mask);	netif_start_queue(dev);}static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc){	desc->addr = 0x0badbadbadbadbadull;	desc->status &= ~cpu_to_le32(OWNbit | RsvdMask);}static void rtl8169_free_rx_skb(struct pci_dev *pdev, struct sk_buff **sk_buff,				struct RxDesc *desc){	pci_unmap_single(pdev, le64_to_cpu(desc->addr), RX_BUF_SIZE,			 PCI_DMA_FROMDEVICE);	dev_kfree_skb(*sk_buff);	*sk_buff = NULL;	rtl8169_make_unusable_by_asic(desc);}static inline void rtl8169_return_to_asic(struct RxDesc *desc){	desc->status |= cpu_to_le32(OWNbit + RX_BUF_SIZE);}static inline void rtl8169_give_to_asic(struct RxDesc *desc, dma_addr_t mapping){	desc->addr = cpu_to_le64(mapping);	desc->status |= cpu_to_le32(OWNbit + RX_BUF_SIZE);}static int rtl8169_alloc_rx_skb(struct pci_dev *pdev, struct net_device *dev,				struct sk_buff **sk_buff, struct RxDesc *desc){	struct sk_buff *skb;	dma_addr_t mapping;	int ret = 0;	skb = dev_alloc_skb(RX_BUF_SIZE);	if (!skb)		goto err_out;	skb->dev = dev;	skb_reserve(skb, 2);	*sk_buff = skb;	mapping = pci_map_single(pdev, skb->tail, RX_BUF_SIZE,				 PCI_DMA_FROMDEVICE);	rtl8169_give_to_asic(desc, mapping);out:	return ret;err_out:	ret = -ENOMEM;	rtl8169_make_unusable_by_asic(desc);	goto out;}static void rtl8169_rx_clear(struct rtl8169_private *tp){	int i;	for (i = 0; i < NUM_RX_DESC; i++) {		if (tp->Rx_skbuff[i]) {			rtl8169_free_rx_skb(tp->pci_dev, tp->Rx_skbuff + i,					    tp->RxDescArray + i);		}	}}static u32 rtl8169_rx_fill(struct rtl8169_private *tp, struct net_device *dev,			   u32 start, u32 end){	u32 cur;		for (cur = start; end - cur > 0; cur++) {		int ret, i = cur % NUM_RX_DESC;		if (tp->Rx_skbuff[i])			continue;					ret = rtl8169_alloc_rx_skb(tp->pci_dev, dev, tp->Rx_skbuff + i,					   tp->RxDescArray + i);		if (ret < 0)			break;	}	return cur - start;}static inline void rtl8169_mark_as_last_descriptor(struct RxDesc *desc){	desc->status |= cpu_to_le32(EORbit);}static int rtl8169_init_ring(struct net_device *dev){	struct rtl8169_private *tp = netdev_priv(dev);	tp->cur_rx = tp->dirty_rx = 0;	tp->cur_tx = tp->dirty_tx = 0;	memset(tp->TxDescArray, 0x0, NUM_TX_DESC * sizeof (struct TxDesc));	memset(tp->RxDescArray, 0x0, NUM_RX_DESC * sizeof (struct RxDesc));	memset(tp->Tx_skbuff, 0x0, NUM_TX_DESC * sizeof(struct sk_buff *));	memset(tp->Rx_skbuff, 0x0, NUM_RX_DESC * sizeof(struct sk_buff *));	if (rtl8169_rx_fill(tp, dev, 0, NUM_RX_DESC) != NUM_RX_DESC)		goto err_out;	rtl8169_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1);	return 0;err_out:	rtl8169_rx_clear(tp);	return -ENOMEM;}static void rtl8169_unmap_tx_skb(struct pci_dev *pdev, struct sk_buff **sk_buff,				 struct TxDesc *desc){	u32 len = sk_buff[0]->len;	pci_unmap_single(pdev, le64_to_cpu(desc->addr),			 len < ETH_ZLEN ? ETH_ZLEN : len, PCI_DMA_TODEVICE);	desc->addr = 0x00;	*sk_buff = NULL;}static voidrtl8169_tx_clear(struct rtl8169_private *tp)

⌨️ 快捷键说明

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