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

📄 acenic.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (dev == NULL) {		printk(KERN_ERR "acenic: Unable to allocate "		       "net_device structure!\n");		return -ENOMEM;	}	SET_NETDEV_DEV(dev, &pdev->dev);	ap = dev->priv;	ap->pdev = pdev;	ap->name = pci_name(pdev);	dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;#if ACENIC_DO_VLAN	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;	dev->vlan_rx_register = ace_vlan_rx_register;#endif	dev->tx_timeout = &ace_watchdog;	dev->watchdog_timeo = 5*HZ;	dev->open = &ace_open;	dev->stop = &ace_close;	dev->hard_start_xmit = &ace_start_xmit;	dev->get_stats = &ace_get_stats;	dev->set_multicast_list = &ace_set_multicast_list;	SET_ETHTOOL_OPS(dev, &ace_ethtool_ops);	dev->set_mac_address = &ace_set_mac_addr;	dev->change_mtu = &ace_change_mtu;	/* we only display this string ONCE */	if (!boards_found)		printk(version);	if (pci_enable_device(pdev))		goto fail_free_netdev;	/*	 * Enable master mode before we start playing with the	 * pci_command word since pci_set_master() will modify	 * it.	 */	pci_set_master(pdev);	pci_read_config_word(pdev, PCI_COMMAND, &ap->pci_command);	/* OpenFirmware on Mac's does not set this - DOH.. */	if (!(ap->pci_command & PCI_COMMAND_MEMORY)) {		printk(KERN_INFO "%s: Enabling PCI Memory Mapped "		       "access - was not enabled by BIOS/Firmware\n",		       ap->name);		ap->pci_command = ap->pci_command | PCI_COMMAND_MEMORY;		pci_write_config_word(ap->pdev, PCI_COMMAND,				      ap->pci_command);		wmb();	}	pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &ap->pci_latency);	if (ap->pci_latency <= 0x40) {		ap->pci_latency = 0x40;		pci_write_config_byte(pdev, PCI_LATENCY_TIMER, ap->pci_latency);	}	/*	 * Remap the regs into kernel space - this is abuse of	 * dev->base_addr since it was means for I/O port	 * addresses but who gives a damn.	 */	dev->base_addr = pci_resource_start(pdev, 0);	ap->regs = ioremap(dev->base_addr, 0x4000);	if (!ap->regs) {		printk(KERN_ERR "%s:  Unable to map I/O register, "		       "AceNIC %i will be disabled.\n",		       ap->name, boards_found);		goto fail_free_netdev;	}	switch(pdev->vendor) {	case PCI_VENDOR_ID_ALTEON:		if (pdev->device == PCI_DEVICE_ID_FARALLON_PN9100T) {			printk(KERN_INFO "%s: Farallon PN9100-T ",			       ap->name);		} else {			printk(KERN_INFO "%s: Alteon AceNIC ",			       ap->name);		}		break;	case PCI_VENDOR_ID_3COM:		printk(KERN_INFO "%s: 3Com 3C985 ", ap->name);		break;	case PCI_VENDOR_ID_NETGEAR:		printk(KERN_INFO "%s: NetGear GA620 ", ap->name);		break;	case PCI_VENDOR_ID_DEC:		if (pdev->device == PCI_DEVICE_ID_FARALLON_PN9000SX) {			printk(KERN_INFO "%s: Farallon PN9000-SX ",			       ap->name);			break;		}	case PCI_VENDOR_ID_SGI:		printk(KERN_INFO "%s: SGI AceNIC ", ap->name);		break;	default:		printk(KERN_INFO "%s: Unknown AceNIC ", ap->name);		break;	}	printk("Gigabit Ethernet at 0x%08lx, ", dev->base_addr);	printk("irq %d\n", pdev->irq);#ifdef CONFIG_ACENIC_OMIT_TIGON_I	if ((readl(&ap->regs->HostCtrl) >> 28) == 4) {		printk(KERN_ERR "%s: Driver compiled without Tigon I"		       " support - NIC disabled\n", dev->name);		goto fail_uninit;	}#endif	if (ace_allocate_descriptors(dev))		goto fail_free_netdev;#ifdef MODULE	if (boards_found >= ACE_MAX_MOD_PARMS)		ap->board_idx = BOARD_IDX_OVERFLOW;	else		ap->board_idx = boards_found;#else	ap->board_idx = BOARD_IDX_STATIC;#endif	if (ace_init(dev))		goto fail_free_netdev;	if (register_netdev(dev)) {		printk(KERN_ERR "acenic: device registration failed\n");		goto fail_uninit;	}	ap->name = dev->name;	if (ap->pci_using_dac)		dev->features |= NETIF_F_HIGHDMA;	pci_set_drvdata(pdev, dev);	boards_found++;	return 0; fail_uninit:	ace_init_cleanup(dev); fail_free_netdev:	free_netdev(dev);	return -ENODEV;}static void __devexit acenic_remove_one(struct pci_dev *pdev){	struct net_device *dev = pci_get_drvdata(pdev);	struct ace_private *ap = netdev_priv(dev);	struct ace_regs __iomem *regs = ap->regs;	short i;	unregister_netdev(dev);	writel(readl(&regs->CpuCtrl) | CPU_HALT, &regs->CpuCtrl);	if (ap->version >= 2)		writel(readl(&regs->CpuBCtrl) | CPU_HALT, &regs->CpuBCtrl);	/*	 * This clears any pending interrupts	 */	writel(1, &regs->Mb0Lo);	readl(&regs->CpuCtrl);	/* flush */	/*	 * Make sure no other CPUs are processing interrupts	 * on the card before the buffers are being released.	 * Otherwise one might experience some `interesting'	 * effects.	 *	 * Then release the RX buffers - jumbo buffers were	 * already released in ace_close().	 */	ace_sync_irq(dev->irq);	for (i = 0; i < RX_STD_RING_ENTRIES; i++) {		struct sk_buff *skb = ap->skb->rx_std_skbuff[i].skb;		if (skb) {			struct ring_info *ringp;			dma_addr_t mapping;			ringp = &ap->skb->rx_std_skbuff[i];			mapping = pci_unmap_addr(ringp, mapping);			pci_unmap_page(ap->pdev, mapping,				       ACE_STD_BUFSIZE,				       PCI_DMA_FROMDEVICE);			ap->rx_std_ring[i].size = 0;			ap->skb->rx_std_skbuff[i].skb = NULL;			dev_kfree_skb(skb);		}	}	if (ap->version >= 2) {		for (i = 0; i < RX_MINI_RING_ENTRIES; i++) {			struct sk_buff *skb = ap->skb->rx_mini_skbuff[i].skb;			if (skb) {				struct ring_info *ringp;				dma_addr_t mapping;				ringp = &ap->skb->rx_mini_skbuff[i];				mapping = pci_unmap_addr(ringp,mapping);				pci_unmap_page(ap->pdev, mapping,					       ACE_MINI_BUFSIZE,					       PCI_DMA_FROMDEVICE);				ap->rx_mini_ring[i].size = 0;				ap->skb->rx_mini_skbuff[i].skb = NULL;				dev_kfree_skb(skb);			}		}	}	for (i = 0; i < RX_JUMBO_RING_ENTRIES; i++) {		struct sk_buff *skb = ap->skb->rx_jumbo_skbuff[i].skb;		if (skb) {			struct ring_info *ringp;			dma_addr_t mapping;			ringp = &ap->skb->rx_jumbo_skbuff[i];			mapping = pci_unmap_addr(ringp, mapping);			pci_unmap_page(ap->pdev, mapping,				       ACE_JUMBO_BUFSIZE,				       PCI_DMA_FROMDEVICE);			ap->rx_jumbo_ring[i].size = 0;			ap->skb->rx_jumbo_skbuff[i].skb = NULL;			dev_kfree_skb(skb);		}	}	ace_init_cleanup(dev);	free_netdev(dev);}static struct pci_driver acenic_pci_driver = {	.name		= "acenic",	.id_table	= acenic_pci_tbl,	.probe		= acenic_probe_one,	.remove		= __devexit_p(acenic_remove_one),};static int __init acenic_init(void){	return pci_register_driver(&acenic_pci_driver);}static void __exit acenic_exit(void){	pci_unregister_driver(&acenic_pci_driver);}module_init(acenic_init);module_exit(acenic_exit);static void ace_free_descriptors(struct net_device *dev){	struct ace_private *ap = netdev_priv(dev);	int size;	if (ap->rx_std_ring != NULL) {		size = (sizeof(struct rx_desc) *			(RX_STD_RING_ENTRIES +			 RX_JUMBO_RING_ENTRIES +			 RX_MINI_RING_ENTRIES +			 RX_RETURN_RING_ENTRIES));		pci_free_consistent(ap->pdev, size, ap->rx_std_ring,				    ap->rx_ring_base_dma);		ap->rx_std_ring = NULL;		ap->rx_jumbo_ring = NULL;		ap->rx_mini_ring = NULL;		ap->rx_return_ring = NULL;	}	if (ap->evt_ring != NULL) {		size = (sizeof(struct event) * EVT_RING_ENTRIES);		pci_free_consistent(ap->pdev, size, ap->evt_ring,				    ap->evt_ring_dma);		ap->evt_ring = NULL;	}	if (ap->tx_ring != NULL && !ACE_IS_TIGON_I(ap)) {		size = (sizeof(struct tx_desc) * MAX_TX_RING_ENTRIES);		pci_free_consistent(ap->pdev, size, ap->tx_ring,				    ap->tx_ring_dma);	}	ap->tx_ring = NULL;	if (ap->evt_prd != NULL) {		pci_free_consistent(ap->pdev, sizeof(u32),				    (void *)ap->evt_prd, ap->evt_prd_dma);		ap->evt_prd = NULL;	}	if (ap->rx_ret_prd != NULL) {		pci_free_consistent(ap->pdev, sizeof(u32),				    (void *)ap->rx_ret_prd,				    ap->rx_ret_prd_dma);		ap->rx_ret_prd = NULL;	}	if (ap->tx_csm != NULL) {		pci_free_consistent(ap->pdev, sizeof(u32),				    (void *)ap->tx_csm, ap->tx_csm_dma);		ap->tx_csm = NULL;	}}static int ace_allocate_descriptors(struct net_device *dev){	struct ace_private *ap = netdev_priv(dev);	int size;	size = (sizeof(struct rx_desc) *		(RX_STD_RING_ENTRIES +		 RX_JUMBO_RING_ENTRIES +		 RX_MINI_RING_ENTRIES +		 RX_RETURN_RING_ENTRIES));	ap->rx_std_ring = pci_alloc_consistent(ap->pdev, size,					       &ap->rx_ring_base_dma);	if (ap->rx_std_ring == NULL)		goto fail;	ap->rx_jumbo_ring = ap->rx_std_ring + RX_STD_RING_ENTRIES;	ap->rx_mini_ring = ap->rx_jumbo_ring + RX_JUMBO_RING_ENTRIES;	ap->rx_return_ring = ap->rx_mini_ring + RX_MINI_RING_ENTRIES;	size = (sizeof(struct event) * EVT_RING_ENTRIES);	ap->evt_ring = pci_alloc_consistent(ap->pdev, size, &ap->evt_ring_dma);	if (ap->evt_ring == NULL)		goto fail;	/*	 * Only allocate a host TX ring for the Tigon II, the Tigon I	 * has to use PCI registers for this ;-(	 */	if (!ACE_IS_TIGON_I(ap)) {		size = (sizeof(struct tx_desc) * MAX_TX_RING_ENTRIES);		ap->tx_ring = pci_alloc_consistent(ap->pdev, size,						   &ap->tx_ring_dma);		if (ap->tx_ring == NULL)			goto fail;	}	ap->evt_prd = pci_alloc_consistent(ap->pdev, sizeof(u32),					   &ap->evt_prd_dma);	if (ap->evt_prd == NULL)		goto fail;	ap->rx_ret_prd = pci_alloc_consistent(ap->pdev, sizeof(u32),					      &ap->rx_ret_prd_dma);	if (ap->rx_ret_prd == NULL)		goto fail;	ap->tx_csm = pci_alloc_consistent(ap->pdev, sizeof(u32),					  &ap->tx_csm_dma);	if (ap->tx_csm == NULL)		goto fail;	return 0;fail:	/* Clean up. */	ace_init_cleanup(dev);	return 1;}/* * Generic cleanup handling data allocated during init. Used when the * module is unloaded or if an error occurs during initialization */static void ace_init_cleanup(struct net_device *dev){	struct ace_private *ap;	ap = netdev_priv(dev);	ace_free_descriptors(dev);	if (ap->info)		pci_free_consistent(ap->pdev, sizeof(struct ace_info),				    ap->info, ap->info_dma);	kfree(ap->skb);	kfree(ap->trace_buf);	if (dev->irq)		free_irq(dev->irq, dev);	iounmap(ap->regs);}/* * Commands are considered to be slow. */static inline void ace_issue_cmd(struct ace_regs __iomem *regs, struct cmd *cmd){	u32 idx;	idx = readl(&regs->CmdPrd);	writel(*(u32 *)(cmd), &regs->CmdRng[idx]);	idx = (idx + 1) % CMD_RING_ENTRIES;	writel(idx, &regs->CmdPrd);}static int __devinit ace_init(struct net_device *dev){	struct ace_private *ap;	struct ace_regs __iomem *regs;	struct ace_info *info = NULL;	struct pci_dev *pdev;	unsigned long myjif;	u64 tmp_ptr;	u32 tig_ver, mac1, mac2, tmp, pci_state;	int board_idx, ecode = 0;	short i;	unsigned char cache_size;	DECLARE_MAC_BUF(mac);	ap = netdev_priv(dev);	regs = ap->regs;	board_idx = ap->board_idx;	/*	 * aman@sgi.com - its useful to do a NIC reset here to	 * address the `Firmware not running' problem subsequent	 * to any crashes involving the NIC	 */	writel(HW_RESET | (HW_RESET << 24), &regs->HostCtrl);	readl(&regs->HostCtrl);		/* PCI write posting */	udelay(5);	/*	 * Don't access any other registers before this point!	 */#ifdef __BIG_ENDIAN	/*	 * This will most likely need BYTE_SWAP once we switch	 * to using __raw_writel()	 */	writel((WORD_SWAP | CLR_INT | ((WORD_SWAP | CLR_INT) << 24)),	       &regs->HostCtrl);#else

⌨️ 快捷键说明

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