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

📄 ax88796.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	ax->running = 0;	wmb();	del_timer_sync(&ax->mii_timer);	ax_ei_close(dev);	free_irq(dev->irq, dev);	return 0;}static int ax_ioctl(struct net_device *dev, struct ifreq *req, int cmd){	struct ax_device *ax = to_ax_dev(dev);	unsigned long flags;	int rc;	if (!netif_running(dev))		return -EINVAL;	spin_lock_irqsave(&ax->mii_lock, flags);	rc = generic_mii_ioctl(&ax->mii, if_mii(req), cmd, NULL);	spin_unlock_irqrestore(&ax->mii_lock, flags);	return rc;}/* ethtool ops */static void ax_get_drvinfo(struct net_device *dev,			   struct ethtool_drvinfo *info){	struct ax_device *ax = to_ax_dev(dev);	strcpy(info->driver, DRV_NAME);	strcpy(info->version, DRV_VERSION);	strcpy(info->bus_info, ax->dev->name);}static int ax_get_settings(struct net_device *dev, struct ethtool_cmd *cmd){	struct ax_device *ax = to_ax_dev(dev);	unsigned long flags;	spin_lock_irqsave(&ax->mii_lock, flags);	mii_ethtool_gset(&ax->mii, cmd);	spin_lock_irqsave(&ax->mii_lock, flags);	return 0;}static int ax_set_settings(struct net_device *dev, struct ethtool_cmd *cmd){	struct ax_device *ax = to_ax_dev(dev);	unsigned long flags;	int rc;	spin_lock_irqsave(&ax->mii_lock, flags);	rc = mii_ethtool_sset(&ax->mii, cmd);	spin_lock_irqsave(&ax->mii_lock, flags);	return rc;}static int ax_nway_reset(struct net_device *dev){	struct ax_device *ax = to_ax_dev(dev);	return mii_nway_restart(&ax->mii);}static u32 ax_get_link(struct net_device *dev){	struct ax_device *ax = to_ax_dev(dev);	return mii_link_ok(&ax->mii);}static const struct ethtool_ops ax_ethtool_ops = {	.get_drvinfo		= ax_get_drvinfo,	.get_settings		= ax_get_settings,	.set_settings		= ax_set_settings,	.nway_reset		= ax_nway_reset,	.get_link		= ax_get_link,};#ifdef CONFIG_AX88796_93CX6static void ax_eeprom_register_read(struct eeprom_93cx6 *eeprom){	struct ei_device *ei_local = eeprom->data;	u8 reg = ei_inb(ei_local->mem + AX_MEMR);	eeprom->reg_data_in = reg & AX_MEMR_EEI;	eeprom->reg_data_out = reg & AX_MEMR_EEO; /* Input pin */	eeprom->reg_data_clock = reg & AX_MEMR_EECLK;	eeprom->reg_chip_select = reg & AX_MEMR_EECS;}static void ax_eeprom_register_write(struct eeprom_93cx6 *eeprom){	struct ei_device *ei_local = eeprom->data;	u8 reg = ei_inb(ei_local->mem + AX_MEMR);	reg &= ~(AX_MEMR_EEI | AX_MEMR_EECLK | AX_MEMR_EECS);	if (eeprom->reg_data_in)		reg |= AX_MEMR_EEI;	if (eeprom->reg_data_clock)		reg |= AX_MEMR_EECLK;	if (eeprom->reg_chip_select)		reg |= AX_MEMR_EECS;	ei_outb(reg, ei_local->mem + AX_MEMR);	udelay(10);}#endif/* setup code */static void ax_initial_setup(struct net_device *dev, struct ei_device *ei_local){	void __iomem *ioaddr = ei_local->mem;	struct ax_device *ax = to_ax_dev(dev);	/* Select page 0*/	ei_outb(E8390_NODMA+E8390_PAGE0+E8390_STOP, ioaddr + E8390_CMD);	/* set to byte access */	ei_outb(ax->plat->dcr_val & ~1, ioaddr + EN0_DCFG);	ei_outb(ax->plat->gpoc_val, ioaddr + EI_SHIFT(0x17));}/* ax_init_dev * * initialise the specified device, taking care to note the MAC * address it may already have (if configured), ensure * the device is ready to be used by lib8390.c and registerd with * the network layer. */static int ax_init_dev(struct net_device *dev, int first_init){	struct ei_device *ei_local = netdev_priv(dev);	struct ax_device *ax = to_ax_dev(dev);	void __iomem *ioaddr = ei_local->mem;	unsigned int start_page;	unsigned int stop_page;	int ret;	int i;	ret = ax_initial_check(dev);	if (ret)		goto err_out;	/* setup goes here */	ax_initial_setup(dev, ei_local);	/* read the mac from the card prom if we need it */	if (first_init && ax->plat->flags & AXFLG_HAS_EEPROM) {		unsigned char SA_prom[32];		for(i = 0; i < sizeof(SA_prom); i+=2) {			SA_prom[i] = ei_inb(ioaddr + NE_DATAPORT);			SA_prom[i+1] = ei_inb(ioaddr + NE_DATAPORT);		}		if (ax->plat->wordlength == 2)			for (i = 0; i < 16; i++)				SA_prom[i] = SA_prom[i+i];		memcpy(dev->dev_addr,  SA_prom, 6);	}#ifdef CONFIG_AX88796_93CX6	if (first_init && ax->plat->flags & AXFLG_HAS_93CX6) {		unsigned char mac_addr[6];		struct eeprom_93cx6 eeprom;		eeprom.data = ei_local;		eeprom.register_read = ax_eeprom_register_read;		eeprom.register_write = ax_eeprom_register_write;		eeprom.width = PCI_EEPROM_WIDTH_93C56;		eeprom_93cx6_multiread(&eeprom, 0,				       (__le16 __force *)mac_addr,				       sizeof(mac_addr) >> 1);		memcpy(dev->dev_addr,  mac_addr, 6);	}#endif	if (ax->plat->wordlength == 2) {		/* We must set the 8390 for word mode. */		ei_outb(ax->plat->dcr_val, ei_local->mem + EN0_DCFG);		start_page = NESM_START_PG;		stop_page = NESM_STOP_PG;	} else {		start_page = NE1SM_START_PG;		stop_page = NE1SM_STOP_PG;	}	/* load the mac-address from the device if this is the	 * first time we've initialised */	if (first_init && ax->plat->flags & AXFLG_MAC_FROMDEV) {		ei_outb(E8390_NODMA + E8390_PAGE1 + E8390_STOP,			ei_local->mem + E8390_CMD); /* 0x61 */		for (i = 0 ; i < ETHER_ADDR_LEN ; i++)			dev->dev_addr[i] = ei_inb(ioaddr + EN1_PHYS_SHIFT(i));	}	ax_reset_8390(dev);	ei_status.name = "AX88796";	ei_status.tx_start_page = start_page;	ei_status.stop_page = stop_page;	ei_status.word16 = (ax->plat->wordlength == 2);	ei_status.rx_start_page = start_page + TX_PAGES;#ifdef PACKETBUF_MEMSIZE	 /* Allow the packet buffer size to be overridden by know-it-alls. */	ei_status.stop_page = ei_status.tx_start_page + PACKETBUF_MEMSIZE;#endif	ei_status.reset_8390	= &ax_reset_8390;	ei_status.block_input	= &ax_block_input;	ei_status.block_output	= &ax_block_output;	ei_status.get_8390_hdr	= &ax_get_8390_hdr;	ei_status.priv = 0;	dev->open		= ax_open;	dev->stop		= ax_close;	dev->do_ioctl		= ax_ioctl;	dev->ethtool_ops	= &ax_ethtool_ops;	ax->msg_enable		= NETIF_MSG_LINK;	ax->mii.phy_id_mask	= 0x1f;	ax->mii.reg_num_mask	= 0x1f;	ax->mii.phy_id		= 0x10;		/* onboard phy */	ax->mii.force_media	= 0;	ax->mii.full_duplex	= 0;	ax->mii.mdio_read	= ax_phy_read;	ax->mii.mdio_write	= ax_phy_write;	ax->mii.dev		= dev;#ifdef CONFIG_NET_POLL_CONTROLLER	dev->poll_controller = ax_ei_poll;#endif	ax_NS8390_init(dev, 0);	if (first_init) {		printk("AX88796: %dbit, irq %d, %lx, MAC: ",		       ei_status.word16 ? 16:8, dev->irq, dev->base_addr);		for (i = 0; i < ETHER_ADDR_LEN; i++)			printk("%2.2x%c", dev->dev_addr[i],			       (i < (ETHER_ADDR_LEN-1) ? ':' : ' '));		printk("\n");	}	ret = register_netdev(dev);	if (ret)		goto out_irq;	return 0; out_irq:	/* cleanup irq */	free_irq(dev->irq, dev); err_out:	return ret;}static int ax_remove(struct platform_device *_dev){	struct net_device *dev = platform_get_drvdata(_dev);	struct ax_device  *ax;	ax = to_ax_dev(dev);	unregister_netdev(dev);	free_irq(dev->irq, dev);	iounmap(ei_status.mem);	release_resource(ax->mem);	kfree(ax->mem);	if (ax->map2) {		iounmap(ax->map2);		release_resource(ax->mem2);		kfree(ax->mem2);	}	free_netdev(dev);	return 0;}/* ax_probe * * This is the entry point when the platform device system uses to * notify us of a new device to attach to. Allocate memory, find * the resources and information passed, and map the necessary registers.*/static int ax_probe(struct platform_device *pdev){	struct net_device *dev;	struct ax_device  *ax;	struct resource   *res;	size_t size;	int ret;	dev = ax__alloc_ei_netdev(sizeof(struct ax_device));	if (dev == NULL)		return -ENOMEM;	/* ok, let's setup our device */	ax = to_ax_dev(dev);	memset(ax, 0, sizeof(struct ax_device));	spin_lock_init(&ax->mii_lock);	ax->dev = pdev;	ax->plat = pdev->dev.platform_data;	platform_set_drvdata(pdev, dev);	ei_status.rxcr_base  = ax->plat->rcr_val;	/* find the platform resources */	dev->irq  = platform_get_irq(pdev, 0);	if (dev->irq < 0) {		dev_err(&pdev->dev, "no IRQ specified\n");		ret = -ENXIO;		goto exit_mem;	}	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);	if (res == NULL) {		dev_err(&pdev->dev, "no MEM specified\n");		ret = -ENXIO;		goto exit_mem;	}	size = (res->end - res->start) + 1;	/* setup the register offsets from either the platform data	 * or by using the size of the resource provided */	if (ax->plat->reg_offsets)		ei_status.reg_offset = ax->plat->reg_offsets;	else {		ei_status.reg_offset = ax->reg_offsets;		for (ret = 0; ret < 0x18; ret++)			ax->reg_offsets[ret] = (size / 0x18) * ret;	}	ax->mem = request_mem_region(res->start, size, pdev->name);	if (ax->mem == NULL) {		dev_err(&pdev->dev, "cannot reserve registers\n"); 		ret = -ENXIO;		goto exit_mem;	}	ei_status.mem = ioremap(res->start, size);	dev->base_addr = (unsigned long)ei_status.mem;	if (ei_status.mem == NULL) {		dev_err(&pdev->dev, "Cannot ioremap area (%08llx,%08llx)\n",			(unsigned long long)res->start,			(unsigned long long)res->end); 		ret = -ENXIO;		goto exit_req;	}	/* look for reset area */	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);	if (res == NULL) {		if (!ax->plat->reg_offsets) {			for (ret = 0; ret < 0x20; ret++)				ax->reg_offsets[ret] = (size / 0x20) * ret;		}		ax->map2 = NULL;	} else { 		size = (res->end - res->start) + 1;		ax->mem2 = request_mem_region(res->start, size, pdev->name);		if (ax->mem == NULL) {			dev_err(&pdev->dev, "cannot reserve registers\n");			ret = -ENXIO;			goto exit_mem1;		}		ax->map2 = ioremap(res->start, size);		if (ax->map2 == NULL) {			dev_err(&pdev->dev, "cannot map reset register\n");			ret = -ENXIO;			goto exit_mem2;		}		ei_status.reg_offset[0x1f] = ax->map2 - ei_status.mem;	}	/* got resources, now initialise and register device */	ret = ax_init_dev(dev, 1);	if (!ret)		return 0;	if (ax->map2 == NULL)		goto exit_mem1;	iounmap(ax->map2); exit_mem2:	release_resource(ax->mem2);	kfree(ax->mem2); exit_mem1:	iounmap(ei_status.mem); exit_req:	release_resource(ax->mem);	kfree(ax->mem); exit_mem:	free_netdev(dev);	return ret;}/* suspend and resume */#ifdef CONFIG_PMstatic int ax_suspend(struct platform_device *dev, pm_message_t state){	struct net_device *ndev = platform_get_drvdata(dev);	struct ax_device  *ax = to_ax_dev(ndev);	ax->resume_open = ax->running;	netif_device_detach(ndev);	ax_close(ndev);	return 0;}static int ax_resume(struct platform_device *pdev){	struct net_device *ndev = platform_get_drvdata(pdev);	struct ax_device  *ax = to_ax_dev(ndev);	ax_initial_setup(ndev, netdev_priv(ndev));	ax_NS8390_init(ndev, ax->resume_open);	netif_device_attach(ndev);	if (ax->resume_open)		ax_open(ndev);	return 0;}#else#define ax_suspend NULL#define ax_resume  NULL#endifstatic struct platform_driver axdrv = {	.driver	= {		.name		= "ax88796",		.owner		= THIS_MODULE,	},	.probe		= ax_probe,	.remove		= ax_remove,	.suspend	= ax_suspend,	.resume		= ax_resume,};static int __init axdrv_init(void){	return platform_driver_register(&axdrv);}static void __exit axdrv_exit(void){	platform_driver_unregister(&axdrv);}module_init(axdrv_init);module_exit(axdrv_exit);MODULE_DESCRIPTION("AX88796 10/100 Ethernet platform driver");MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");MODULE_LICENSE("GPL v2");

⌨️ 快捷键说明

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