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

📄 fs_enet-main.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
	curidx = bdp - fep->tx_bd_base;	/*	 * Clear all of the status flags. 	 */	CBDC_SC(bdp, BD_ENET_TX_STATS);	/*	 * Save skb pointer. 	 */	fep->tx_skbuff[curidx] = skb;	fep->stats.tx_bytes += skb->len;	/*	 * Push the data cache so the CPM does not get stale memory data. 	 */	CBDW_BUFADDR(bdp, dma_map_single(fep->dev,				skb->data, skb->len, DMA_TO_DEVICE));	CBDW_DATLEN(bdp, skb->len);	dev->trans_start = jiffies;	/*	 * If this was the last BD in the ring, start at the beginning again. 	 */	if ((CBDR_SC(bdp) & BD_ENET_TX_WRAP) == 0)		fep->cur_tx++;	else		fep->cur_tx = fep->tx_bd_base;	if (!--fep->tx_free)		netif_stop_queue(dev);	/* Trigger transmission start */	sc = BD_ENET_TX_READY | BD_ENET_TX_INTR |	     BD_ENET_TX_LAST | BD_ENET_TX_TC;	/* note that while FEC does not have this bit	 * it marks it as available for software use	 * yay for hw reuse :) */	if (skb->len <= 60)		sc |= BD_ENET_TX_PAD;	CBDS_SC(bdp, sc);	(*fep->ops->tx_kickstart)(dev);	spin_unlock_irqrestore(&fep->tx_lock, flags);	return NETDEV_TX_OK;}static int fs_request_irq(struct net_device *dev, int irq, const char *name,		irqreturn_t (*irqf)(int irq, void *dev_id, struct pt_regs *regs)){	struct fs_enet_private *fep = netdev_priv(dev);	(*fep->ops->pre_request_irq)(dev, irq);	return request_irq(irq, irqf, SA_SHIRQ, name, dev);}static void fs_free_irq(struct net_device *dev, int irq){	struct fs_enet_private *fep = netdev_priv(dev);	free_irq(irq, dev);	(*fep->ops->post_free_irq)(dev, irq);}/**********************************************************************************//* This interrupt occurs when the PHY detects a link change. */static irqreturn_tfs_mii_link_interrupt(int irq, void *dev_id, struct pt_regs *regs){	struct net_device *dev = dev_id;	struct fs_enet_private *fep;	const struct fs_platform_info *fpi;	fep = netdev_priv(dev);	fpi = fep->fpi;	/*	 * Acknowledge the interrupt if possible. If we have not	 * found the PHY yet we can't process or acknowledge the	 * interrupt now. Instead we ignore this interrupt for now,	 * which we can do since it is edge triggered. It will be	 * acknowledged later by fs_enet_open().	 */	if (!fep->phy)		return IRQ_NONE;	fs_mii_ack_int(dev);	fs_mii_link_status_change_check(dev, 0);	return IRQ_HANDLED;}static void fs_timeout(struct net_device *dev){	struct fs_enet_private *fep = netdev_priv(dev);	unsigned long flags;	int wake = 0;	fep->stats.tx_errors++;	spin_lock_irqsave(&fep->lock, flags);	if (dev->flags & IFF_UP) {		(*fep->ops->stop)(dev);		(*fep->ops->restart)(dev);	}	wake = fep->tx_free && !(CBDR_SC(fep->cur_tx) & BD_ENET_TX_READY);	spin_unlock_irqrestore(&fep->lock, flags);	if (wake)		netif_wake_queue(dev);}static int fs_enet_open(struct net_device *dev){	struct fs_enet_private *fep = netdev_priv(dev);	const struct fs_platform_info *fpi = fep->fpi;	int r;	/* Install our interrupt handler. */	r = fs_request_irq(dev, fep->interrupt, "fs_enet-mac", fs_enet_interrupt);	if (r != 0) {		printk(KERN_ERR DRV_MODULE_NAME		       ": %s Could not allocate FEC IRQ!", dev->name);		return -EINVAL;	}	/* Install our phy interrupt handler */	if (fpi->phy_irq != -1) {		r = fs_request_irq(dev, fpi->phy_irq, "fs_enet-phy", fs_mii_link_interrupt);		if (r != 0) {			printk(KERN_ERR DRV_MODULE_NAME			       ": %s Could not allocate PHY IRQ!", dev->name);			fs_free_irq(dev, fep->interrupt);			return -EINVAL;		}	}	fs_mii_startup(dev);	netif_carrier_off(dev);	fs_mii_link_status_change_check(dev, 1);	return 0;}static int fs_enet_close(struct net_device *dev){	struct fs_enet_private *fep = netdev_priv(dev);	const struct fs_platform_info *fpi = fep->fpi;	unsigned long flags;	netif_stop_queue(dev);	netif_carrier_off(dev);	fs_mii_shutdown(dev);	spin_lock_irqsave(&fep->lock, flags);	(*fep->ops->stop)(dev);	spin_unlock_irqrestore(&fep->lock, flags);	/* release any irqs */	if (fpi->phy_irq != -1)		fs_free_irq(dev, fpi->phy_irq);	fs_free_irq(dev, fep->interrupt);	return 0;}static struct net_device_stats *fs_enet_get_stats(struct net_device *dev){	struct fs_enet_private *fep = netdev_priv(dev);	return &fep->stats;}/*************************************************************************/static void fs_get_drvinfo(struct net_device *dev,			    struct ethtool_drvinfo *info){	strcpy(info->driver, DRV_MODULE_NAME);	strcpy(info->version, DRV_MODULE_VERSION);}static int fs_get_regs_len(struct net_device *dev){	struct fs_enet_private *fep = netdev_priv(dev);	return (*fep->ops->get_regs_len)(dev);}static void fs_get_regs(struct net_device *dev, struct ethtool_regs *regs,			 void *p){	struct fs_enet_private *fep = netdev_priv(dev);	unsigned long flags;	int r, len;	len = regs->len;	spin_lock_irqsave(&fep->lock, flags);	r = (*fep->ops->get_regs)(dev, p, &len);	spin_unlock_irqrestore(&fep->lock, flags);	if (r == 0)		regs->version = 0;}static int fs_get_settings(struct net_device *dev, struct ethtool_cmd *cmd){	struct fs_enet_private *fep = netdev_priv(dev);	unsigned long flags;	int rc;	spin_lock_irqsave(&fep->lock, flags);	rc = mii_ethtool_gset(&fep->mii_if, cmd);	spin_unlock_irqrestore(&fep->lock, flags);	return rc;}static int fs_set_settings(struct net_device *dev, struct ethtool_cmd *cmd){	struct fs_enet_private *fep = netdev_priv(dev);	unsigned long flags;	int rc;	spin_lock_irqsave(&fep->lock, flags);	rc = mii_ethtool_sset(&fep->mii_if, cmd);	spin_unlock_irqrestore(&fep->lock, flags);	return rc;}static int fs_nway_reset(struct net_device *dev){	struct fs_enet_private *fep = netdev_priv(dev);	return mii_nway_restart(&fep->mii_if);}static u32 fs_get_msglevel(struct net_device *dev){	struct fs_enet_private *fep = netdev_priv(dev);	return fep->msg_enable;}static void fs_set_msglevel(struct net_device *dev, u32 value){	struct fs_enet_private *fep = netdev_priv(dev);	fep->msg_enable = value;}static struct ethtool_ops fs_ethtool_ops = {	.get_drvinfo = fs_get_drvinfo,	.get_regs_len = fs_get_regs_len,	.get_settings = fs_get_settings,	.set_settings = fs_set_settings,	.nway_reset = fs_nway_reset,	.get_link = ethtool_op_get_link,	.get_msglevel = fs_get_msglevel,	.set_msglevel = fs_set_msglevel,	.get_tx_csum = ethtool_op_get_tx_csum,	.set_tx_csum = ethtool_op_set_tx_csum,	/* local! */	.get_sg = ethtool_op_get_sg,	.set_sg = ethtool_op_set_sg,	.get_regs = fs_get_regs,};static int fs_ioctl(struct net_device *dev, struct ifreq *rq, int cmd){	struct fs_enet_private *fep = netdev_priv(dev);	struct mii_ioctl_data *mii = (struct mii_ioctl_data *)&rq->ifr_data;	unsigned long flags;	int rc;	if (!netif_running(dev))		return -EINVAL;	spin_lock_irqsave(&fep->lock, flags);	rc = generic_mii_ioctl(&fep->mii_if, mii, cmd, NULL);	spin_unlock_irqrestore(&fep->lock, flags);	return rc;}extern int fs_mii_connect(struct net_device *dev);extern void fs_mii_disconnect(struct net_device *dev);static struct net_device *fs_init_instance(struct device *dev,		const struct fs_platform_info *fpi){	struct net_device *ndev = NULL;	struct fs_enet_private *fep = NULL;	int privsize, i, r, err = 0, registered = 0;	/* guard */	if ((unsigned int)fpi->fs_no >= FS_MAX_INDEX)		return ERR_PTR(-EINVAL);	privsize = sizeof(*fep) + (sizeof(struct sk_buff **) *			    (fpi->rx_ring + fpi->tx_ring));	ndev = alloc_etherdev(privsize);	if (!ndev) {		err = -ENOMEM;		goto err;	}	SET_MODULE_OWNER(ndev);	fep = netdev_priv(ndev);	memset(fep, 0, privsize);	/* clear everything */	fep->dev = dev;	dev_set_drvdata(dev, ndev);	fep->fpi = fpi;	if (fpi->init_ioports)		fpi->init_ioports();#ifdef CONFIG_FS_ENET_HAS_FEC	if (fs_get_fec_index(fpi->fs_no) >= 0)		fep->ops = &fs_fec_ops;#endif#ifdef CONFIG_FS_ENET_HAS_SCC	if (fs_get_scc_index(fpi->fs_no) >=0 )		fep->ops = &fs_scc_ops;#endif#ifdef CONFIG_FS_ENET_HAS_FCC	if (fs_get_fcc_index(fpi->fs_no) >= 0)		fep->ops = &fs_fcc_ops;#endif	if (fep->ops == NULL) {		printk(KERN_ERR DRV_MODULE_NAME		       ": %s No matching ops found (%d).\n",		       ndev->name, fpi->fs_no);		err = -EINVAL;		goto err;	}	r = (*fep->ops->setup_data)(ndev);	if (r != 0) {		printk(KERN_ERR DRV_MODULE_NAME		       ": %s setup_data failed\n",			ndev->name);		err = r;		goto err;	}	/* point rx_skbuff, tx_skbuff */	fep->rx_skbuff = (struct sk_buff **)&fep[1];	fep->tx_skbuff = fep->rx_skbuff + fpi->rx_ring;	/* init locks */	spin_lock_init(&fep->lock);	spin_lock_init(&fep->tx_lock);	/*	 * Set the Ethernet address. 	 */	for (i = 0; i < 6; i++)		ndev->dev_addr[i] = fpi->macaddr[i];		r = (*fep->ops->allocate_bd)(ndev);		if (fep->ring_base == NULL) {		printk(KERN_ERR DRV_MODULE_NAME		       ": %s buffer descriptor alloc failed (%d).\n", ndev->name, r);		err = r;		goto err;	}	/*	 * Set receive and transmit descriptor base.	 */	fep->rx_bd_base = fep->ring_base;	fep->tx_bd_base = fep->rx_bd_base + fpi->rx_ring;	/* initialize ring size variables */	fep->tx_ring = fpi->tx_ring;	fep->rx_ring = fpi->rx_ring;	/*	 * The FEC Ethernet specific entries in the device structure. 	 */	ndev->open = fs_enet_open;	ndev->hard_start_xmit = fs_enet_start_xmit;	ndev->tx_timeout = fs_timeout;	ndev->watchdog_timeo = 2 * HZ;	ndev->stop = fs_enet_close;	ndev->get_stats = fs_enet_get_stats;	ndev->set_multicast_list = fs_set_multicast_list;	if (fpi->use_napi) {		ndev->poll = fs_enet_rx_napi;		ndev->weight = fpi->napi_weight;	}	ndev->ethtool_ops = &fs_ethtool_ops;	ndev->do_ioctl = fs_ioctl;	init_timer(&fep->phy_timer_list);	netif_carrier_off(ndev);	err = register_netdev(ndev);	if (err != 0) {		printk(KERN_ERR DRV_MODULE_NAME		       ": %s register_netdev failed.\n", ndev->name);		goto err;	}	registered = 1;	err = fs_mii_connect(ndev);	if (err != 0) {		printk(KERN_ERR DRV_MODULE_NAME		       ": %s fs_mii_connect failed.\n", ndev->name);		goto err;	}	return ndev;      err:	if (ndev != NULL) {		if (registered)			unregister_netdev(ndev);		if (fep != NULL) {			(*fep->ops->free_bd)(ndev);			(*fep->ops->cleanup_data)(ndev);		}		free_netdev(ndev);	}	dev_set_drvdata(dev, NULL);	return ERR_PTR(err);}static int fs_cleanup_instance(struct net_device *ndev){	struct fs_enet_private *fep;	const struct fs_platform_info *fpi;	struct device *dev;	if (ndev == NULL)		return -EINVAL;	fep = netdev_priv(ndev);	if (fep == NULL)		return -EINVAL;	fpi = fep->fpi;	fs_mii_disconnect(ndev);	unregister_netdev(ndev);	dma_free_coherent(fep->dev, (fpi->tx_ring + fpi->rx_ring) * sizeof(cbd_t),			  fep->ring_base, fep->ring_mem_addr);	/* reset it */	(*fep->ops->cleanup_data)(ndev);	dev = fep->dev;	if (dev != NULL) {		dev_set_drvdata(dev, NULL);		fep->dev = NULL;	}	free_netdev(ndev);	return 0;}/**************************************************************************************//* handy pointer to the immap */void *fs_enet_immap = NULL;static int setup_immap(void){	phys_addr_t paddr = 0;	unsigned long size = 0;#ifdef CONFIG_CPM1	paddr = IMAP_ADDR;	size = 0x10000;	/* map 64K */#endif#ifdef CONFIG_CPM2	paddr = CPM_MAP_ADDR;	size = 0x40000;	/* map 256 K */#endif	fs_enet_immap = ioremap(paddr, size);	if (fs_enet_immap == NULL)		return -EBADF;	/* XXX ahem; maybe just BUG_ON? */	return 0;}static void cleanup_immap(void){	if (fs_enet_immap != NULL) {		iounmap(fs_enet_immap);		fs_enet_immap = NULL;	}}/**************************************************************************************/static int __devinit fs_enet_probe(struct device *dev){	struct net_device *ndev;	/* no fixup - no device */	if (dev->platform_data == NULL) {		printk(KERN_INFO "fs_enet: "				"probe called with no platform data; "				"remove unused devices\n");		return -ENODEV;	}	ndev = fs_init_instance(dev, dev->platform_data);	if (IS_ERR(ndev))		return PTR_ERR(ndev);	return 0;}static int fs_enet_remove(struct device *dev){	return fs_cleanup_instance(dev_get_drvdata(dev));}static struct device_driver fs_enet_fec_driver = {	.name	  	= "fsl-cpm-fec",	.bus		= &platform_bus_type,	.probe		= fs_enet_probe,	.remove		= fs_enet_remove,#ifdef CONFIG_PM/*	.suspend	= fs_enet_suspend,	TODO *//*	.resume		= fs_enet_resume,	TODO */#endif};static struct device_driver fs_enet_scc_driver = {	.name	  	= "fsl-cpm-scc",	.bus		= &platform_bus_type,	.probe		= fs_enet_probe,	.remove		= fs_enet_remove,#ifdef CONFIG_PM/*	.suspend	= fs_enet_suspend,	TODO *//*	.resume		= fs_enet_resume,	TODO */#endif};static struct device_driver fs_enet_fcc_driver = {	.name	  	= "fsl-cpm-fcc",	.bus		= &platform_bus_type,	.probe		= fs_enet_probe,	.remove		= fs_enet_remove,#ifdef CONFIG_PM/*	.suspend	= fs_enet_suspend,	TODO *//*	.resume		= fs_enet_resume,	TODO */#endif};static int __init fs_init(void){	int r;	printk(KERN_INFO			"%s", version);	r = setup_immap();	if (r != 0)		return r;	r = driver_register(&fs_enet_fec_driver);	if (r != 0)		goto err;	r = driver_register(&fs_enet_fcc_driver);	if (r != 0)		goto err;	r = driver_register(&fs_enet_scc_driver);	if (r != 0)		goto err;	return 0;err:	cleanup_immap();	return r;	}static void __exit fs_cleanup(void){	driver_unregister(&fs_enet_fec_driver);	driver_unregister(&fs_enet_fcc_driver);	driver_unregister(&fs_enet_scc_driver);	cleanup_immap();}/**************************************************************************************/module_init(fs_init);module_exit(fs_cleanup);

⌨️ 快捷键说明

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