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

📄 r6040.c

📁 Linux Home Server 是专门为家庭和SOHO/SMB 设计的高性价比的ISCSI 存储服务器, 具有如下的特色: 强大的iscsi 存储服务器软件; 混合iscsi 和NAS 服务;
💻 C
📖 第 1 页 / 共 3 页
字号:
		else			lp->phy_mode = (PHY_MODE & 0x0100) ? 0x8000:0x0;	}	/* configure duplex mode */	lp->mcr0 |= lp->phy_mode;	/* improve performance (by RDC guys) */	phy_write(ioaddr, 30, 17, (phy_read(ioaddr, 30, 17) | 0x4000));	phy_write(ioaddr, 30, 17, ~((~phy_read(ioaddr, 30, 17)) | 0x2000));	phy_write(ioaddr, 0, 19, 0x0000);	phy_write(ioaddr, 0, 30, 0x01F0);	/* Reset MAC and init all registers */	r6040_init_mac_regs(lp);	return 0;}/*  A periodic timer routine	Polling PHY Chip Link Status*/void r6040_timer(unsigned long data){	struct net_device *dev = (struct net_device *)data;	struct r6040_private *lp = netdev_priv(dev);	void __iomem *ioaddr = lp->base;	u16 phy_mode;	/* Polling PHY Chip Status */	if (PHY_MODE == 0x3100)		phy_mode = phy_mode_chk(dev);	else		phy_mode = (PHY_MODE & 0x0100) ? 0x8000:0x0;	if (phy_mode != lp->phy_mode) {		lp->phy_mode = phy_mode;		lp->mcr0 = (lp->mcr0 & 0x7fff) | phy_mode;		iowrite16(lp->mcr0, ioaddr);		printk(KERN_INFO "Link Change x%x \n", ioread16(ioaddr));	}	/* Timer active again */	mod_timer(&lp->timer, jiffies + round_jiffies(HZ));}int r6040_open(struct net_device *dev){	struct r6040_private *lp = netdev_priv(dev);	int ret;	dbg(DBG_OPEN, "ENTER\n");	/* Request IRQ and Register interrupt handler */	ret = request_irq(dev->irq, &r6040_interrupt,		IRQF_SHARED, dev->name, dev);	if (ret)		return ret;	dbg(DBG_OPEN, "got irq %d\n", dev->irq);	/* Allocate Descriptor memory */	lp->rx_ring =		pci_alloc_consistent(lp->pdev, RX_DESC_SIZE, &lp->rx_ring_dma);	if (!lp->rx_ring)		return -ENOMEM;	dbg(DBG_OPEN, "allocated rx ring\n");	lp->tx_ring =		pci_alloc_consistent(lp->pdev, TX_DESC_SIZE, &lp->tx_ring_dma);	if (!lp->tx_ring) {		pci_free_consistent(lp->pdev, RX_DESC_SIZE, lp->rx_ring,				     lp->rx_ring_dma);		return -ENOMEM;	}	dbg(DBG_OPEN, "allocated tx ring\n");	if ((ret=r6040_up(dev))) {		pci_free_consistent(lp->pdev, TX_DESC_SIZE, lp->tx_ring,				    lp->tx_ring_dma);		pci_free_consistent(lp->pdev, RX_DESC_SIZE, lp->rx_ring,				     lp->rx_ring_dma);		return ret;	}			napi_enable(&lp->napi);	netif_start_queue(dev);	/* set and active a timer process */	setup_timer(&lp->timer, r6040_timer, (unsigned long) dev);	if (lp->switch_sig != ICPLUS_PHY_ID)		mod_timer(&lp->timer, jiffies + HZ);	return 0;}int r6040_start_xmit(struct sk_buff *skb, struct net_device *dev){	struct r6040_private *lp = netdev_priv(dev);	struct r6040_descriptor *descptr;	void __iomem *ioaddr = lp->base;	unsigned long flags;	int ret = NETDEV_TX_OK;	/* Critical Section */	spin_lock_irqsave(&lp->lock, flags);	/* TX resource check */	if (!lp->tx_free_desc) {		spin_unlock_irqrestore(&lp->lock, flags);		netif_stop_queue(dev);		printk(KERN_ERR DRV_NAME ": no tx descriptor\n");		ret = NETDEV_TX_BUSY;		return ret;	}	/* Statistic Counter */	dev->stats.tx_packets++;	dev->stats.tx_bytes += skb->len;	/* Set TX descriptor & Transmit it */	lp->tx_free_desc--;	descptr = lp->tx_insert_ptr;	if (skb->len < MISR)		descptr->len = MISR;	else		descptr->len = skb->len;	descptr->skb_ptr = skb;	descptr->buf = cpu_to_le32(pci_map_single(lp->pdev,		skb->data, skb->len, PCI_DMA_TODEVICE));	dbg(DBG_TX_DESCR, "desc @ %p: len x%x buf %08x skb->data %p skb->len x%x jiffies %lu\n",	    descptr, descptr->len, descptr->buf, skb->data, skb->len, jiffies);	{		char obuf[2*32+1];		dbg(DBG_TX_DATA, "tx len x%x: %s\n",		    descptr->len, hex2str(skb->data, obuf, sizeof(obuf)/2, '\0'));	}	descptr->status = 0x8000;	/* Trigger the MAC to check the TX descriptor */	iowrite16(0x01, ioaddr + MTPR);	lp->tx_insert_ptr = descptr->vndescp;	/* If no tx resource, stop */	if (!lp->tx_free_desc)		netif_stop_queue(dev);	dev->trans_start = jiffies;	spin_unlock_irqrestore(&lp->lock, flags);	return ret;}/*! set MAC addresses and promiscous mode */void r6040_multicast_list(struct net_device *dev){	struct r6040_private *lp = netdev_priv(dev);	void __iomem *ioaddr = lp->base;	u16 *adrp;	u16 reg;	unsigned long flags;	struct dev_mc_list *dmi = dev->mc_list;	int i;	char obuf[3*ETH_ALEN] __attribute__ ((unused));	/* MAC Address */	adrp = (u16 *)dev->dev_addr;	iowrite16(adrp[0], ioaddr + MID_0L);	iowrite16(adrp[1], ioaddr + MID_0M);	iowrite16(adrp[2], ioaddr + MID_0H);	dbg(DBG_MAC_ADDR, "%s: set MAC addr %s\n", 	    dev->name, hex2str(dev->dev_addr, obuf, ETH_ALEN, ':'));	/* Promiscous Mode */	spin_lock_irqsave(&lp->lock, flags);	/* Clear AMCP & PROM bits */	reg = ioread16(ioaddr) & ~0x0120;	if (dev->flags & IFF_PROMISC) {		reg |= 0x0020;		lp->mcr0 |= 0x0020;	}	/* Too many multicast addresses	 * accept all traffic */	else if ((dev->mc_count > MCAST_MAX)		|| (dev->flags & IFF_ALLMULTI))		reg |= 0x0020;	iowrite16(reg, ioaddr);	spin_unlock_irqrestore(&lp->lock, flags);	/* Build the hash table */	if (dev->mc_count > MCAST_MAX) {		u16 hash_table[4];		u32 crc;		for (i = 0; i < 4; i++)			hash_table[i] = 0;		for (i = 0; i < dev->mc_count; i++) {			char *addrs = dmi->dmi_addr;			dmi = dmi->next;			if (!(*addrs & 1))				continue;			crc = ether_crc_le(6, addrs);			crc >>= 26;			hash_table[crc >> 4] |= 1 << (15 - (crc & 0xf));		}		/* Write the index of the hash table */		for (i = 0; i < 4; i++)			iowrite16(hash_table[i] << 14, ioaddr + MCR1);		/* Fill the MAC hash tables with their values */		iowrite16(hash_table[0], ioaddr + MAR0);		iowrite16(hash_table[1], ioaddr + MAR1);		iowrite16(hash_table[2], ioaddr + MAR2);		iowrite16(hash_table[3], ioaddr + MAR3);	}	/* Multicast Address 1~4 case */	for (i = 0, dmi; (i < dev->mc_count) && (i < MCAST_MAX); i++) {		adrp = (u16 *)dmi->dmi_addr;		iowrite16(adrp[0], ioaddr + MID_1L + 8*i);		iowrite16(adrp[1], ioaddr + MID_1M + 8*i);		iowrite16(adrp[2], ioaddr + MID_1H + 8*i);		dmi = dmi->next;	}	for (i = dev->mc_count; i < MCAST_MAX; i++) {		iowrite16(0xffff, ioaddr + MID_0L + 8*i);		iowrite16(0xffff, ioaddr + MID_0M + 8*i);		iowrite16(0xffff, ioaddr + MID_0H + 8*i);	}}STATIC void netdev_get_drvinfo(struct net_device *dev,			struct ethtool_drvinfo *info){	struct r6040_private *rp = netdev_priv(dev);	strcpy(info->driver, DRV_NAME);	strcpy(info->version, DRV_VERSION);	strcpy(info->bus_info, pci_name(rp->pdev));}STATIC int netdev_get_settings(struct net_device *dev, struct ethtool_cmd *cmd){	struct r6040_private *rp = netdev_priv(dev);	int rc;	spin_lock_irq(&rp->lock);	rc = mii_ethtool_gset(&rp->mii_if, cmd);	spin_unlock_irq(&rp->lock);	return rc;}STATIC int netdev_set_settings(struct net_device *dev, struct ethtool_cmd *cmd){	struct r6040_private *rp = netdev_priv(dev);	int rc;	spin_lock_irq(&rp->lock);	rc = mii_ethtool_sset(&rp->mii_if, cmd);	spin_unlock_irq(&rp->lock);	r6040_set_carrier(&rp->mii_if);	return rc;}STATIC u32 netdev_get_link(struct net_device *dev){	struct r6040_private *rp = netdev_priv(dev);	return mii_link_ok(&rp->mii_if);}static struct ethtool_ops netdev_ethtool_ops = {	.get_drvinfo		= netdev_get_drvinfo,	.get_settings		= netdev_get_settings,	.set_settings		= netdev_set_settings,	.get_link		= netdev_get_link,};int __devinit r6040_init_one(struct pci_dev *pdev,					 const struct pci_device_id *ent){	struct net_device *dev;	struct r6040_private *lp;	void __iomem *ioaddr;	int err, io_size = R6040_IO_SIZE;	static int card_idx = -1;	int bar = 0;	long pioaddr;	printk(KERN_INFO "%s\n", version);	printk(KERN_INFO DRV_NAME ": debug %x\n", debug);	err = pci_enable_device(pdev);	if (err)		return err;	/* this should always be supported */	if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {		printk(KERN_ERR DRV_NAME "32-bit PCI DMA addresses"				"not supported by the card\n");		return -ENODEV;	}	if (pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) {		printk(KERN_ERR DRV_NAME "32-bit PCI DMA addresses"				"not supported by the card\n");		return -ENODEV;	}	/* IO Size check */	if (pci_resource_len(pdev, 0) < io_size) {		printk(KERN_ERR "Insufficient PCI resources, aborting\n");		return -EIO;	}	pioaddr = pci_resource_start(pdev, 0);	/* IO map base address */	pci_set_master(pdev);	dev = alloc_etherdev(sizeof(struct r6040_private));	if (!dev) {		printk(KERN_ERR "Failed to allocate etherdev\n");		return -ENOMEM;	}	SET_NETDEV_DEV(dev, &pdev->dev);	lp = netdev_priv(dev);	if (pci_request_regions(pdev, DRV_NAME)) {		printk(KERN_ERR DRV_NAME ": Failed to request PCI regions\n");		err = -ENODEV;		goto err_out_disable;	}	ioaddr = pci_iomap(pdev, bar, io_size);	if (!ioaddr) {		printk(KERN_ERR "ioremap failed for device %s\n",			pci_name(pdev));		return -EIO;	}	/* Init system & device */	lp->base = ioaddr;	dev->irq = pdev->irq;	spin_lock_init(&lp->lock);	pci_set_drvdata(pdev, dev);	card_idx++;	/* Link new device into r6040_root_dev */	lp->pdev = pdev;	lp->dev = dev;	/* Init RDC private data */	lp->mcr0 = 0x1002;	lp->phy_addr = phy_table[card_idx];	lp->switch_sig = 0;	/* The RDC-specific entries in the device structure. */	dev->open = &r6040_open;	dev->hard_start_xmit = &r6040_start_xmit;	dev->stop = &r6040_close;	dev->get_stats = r6040_get_stats;	dev->set_multicast_list = &r6040_multicast_list;	dev->do_ioctl = &r6040_ioctl;	dev->ethtool_ops = &netdev_ethtool_ops;	dev->tx_timeout = &r6040_tx_timeout;	dev->watchdog_timeo = TX_TIMEOUT;	{	/* TODO: fix the setting of the MAC address.	   Right now you must either specify a netdevice with "parent=", whose	   address is copied or the (default) address of the Sitecom WL-153	   bootloader is used */		static const u8 dflt_addr[ETH_ALEN] = {0,0x50,0xfc,2,3,4};		if (parent_dev) {			memcpy(dev->dev_addr, parent_dev->dev_addr, ETH_ALEN);		} else {			printk(KERN_WARNING "%s: no parent - using default mac address\n",			       dev->name);			memcpy(dev->dev_addr, dflt_addr, ETH_ALEN);		}		dev->dev_addr[ETH_ALEN-1] += card_idx; /* + 0 or 1 */	}#ifdef CONFIG_NET_POLL_CONTROLLER	dev->poll_controller = r6040_poll_controller;#endif	netif_napi_add(dev, &lp->napi, r6040_poll, 64);	lp->mii_if.dev = dev;	lp->mii_if.mdio_read = mdio_read;	lp->mii_if.mdio_write = mdio_write;	lp->mii_if.phy_id = lp->phy_addr;	lp->mii_if.phy_id_mask = 0x1f;	lp->mii_if.reg_num_mask = 0x1f;	/* Register net device. After this dev->name assign */	err = register_netdev(dev);	if (err) {		printk(KERN_ERR DRV_NAME ": Failed to register net device\n");		goto err_out_res;	}	dbg(DBG_INIT, "%s successfully registered\n", dev->name);	return 0;err_out_res:	pci_release_regions(pdev);err_out_disable:	pci_disable_device(pdev);	pci_set_drvdata(pdev, NULL);	free_netdev(dev);	return err;}void __devexit r6040_remove_one(struct pci_dev *pdev){	struct net_device *dev = pci_get_drvdata(pdev);	unregister_netdev(dev);	pci_release_regions(pdev);	free_netdev(dev);	pci_disable_device(pdev);	pci_set_drvdata(pdev, NULL);}static struct pci_device_id r6040_pci_tbl[] = {	{ PCI_DEVICE(PCI_VENDOR_ID_RDC, 0x6040) },	{ 0 }};MODULE_DEVICE_TABLE(pci, r6040_pci_tbl);static struct pci_driver r6040_driver = {	.name		= DRV_NAME,	.id_table	= r6040_pci_tbl,	.probe		= r6040_init_one,	.remove		= __devexit_p(r6040_remove_one),};static int __init r6040_init(void){	if (parent)		parent_dev = dev_get_by_name(&init_net, parent);		return pci_register_driver(&r6040_driver);}static void __exit r6040_cleanup(void){	pci_unregister_driver(&r6040_driver);}module_init(r6040_init);module_exit(r6040_cleanup);

⌨️ 快捷键说明

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