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

📄 tc35815.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	/* Tx control lock.  This protects the transmit buffer ring	 * state along with the "tx full" state of the driver.  This	 * means all netif_queue flow control actions are protected	 * by this lock as well.	 */	spinlock_t lock;	int phy_addr;	int fullduplex;	unsigned short saved_lpa;	struct timer_list timer;	enum tc35815_timer_state timer_state; /* State of auto-neg timer. */	unsigned int timer_ticks;	/* Number of clicks at each state  */	/*	 * Transmitting: Batch Mode.	 *	1 BD in 1 TxFD.	 * Receiving: Packing Mode. (TC35815_USE_PACKEDBUFFER)	 *	1 circular FD for Free Buffer List.	 *	RX_BUF_NUM BD in Free Buffer FD.	 *	One Free Buffer BD has PAGE_SIZE data buffer.	 * Or Non-Packing Mode.	 *	1 circular FD for Free Buffer List.	 *	RX_BUF_NUM BD in Free Buffer FD.	 *	One Free Buffer BD has ETH_FRAME_LEN data buffer.	 */	void * fd_buf;	/* for TxFD, RxFD, FrFD */	dma_addr_t fd_buf_dma;	struct TxFD *tfd_base;	unsigned int tfd_start;	unsigned int tfd_end;	struct RxFD *rfd_base;	struct RxFD *rfd_limit;	struct RxFD *rfd_cur;	struct FrFD *fbl_ptr;#ifdef TC35815_USE_PACKEDBUFFER	unsigned char fbl_curid;	void * data_buf[RX_BUF_NUM];		/* packing */	dma_addr_t data_buf_dma[RX_BUF_NUM];	struct {		struct sk_buff *skb;		dma_addr_t skb_dma;	} tx_skbs[TX_FD_NUM];#else	unsigned int fbl_count;	struct {		struct sk_buff *skb;		dma_addr_t skb_dma;	} tx_skbs[TX_FD_NUM], rx_skbs[RX_BUF_NUM];#endif	struct mii_if_info mii;	unsigned short mii_id[2];	u32 msg_enable;	board_t boardtype;};static inline dma_addr_t fd_virt_to_bus(struct tc35815_local *lp, void *virt){	return lp->fd_buf_dma + ((u8 *)virt - (u8 *)lp->fd_buf);}#ifdef DEBUGstatic inline void *fd_bus_to_virt(struct tc35815_local *lp, dma_addr_t bus){	return (void *)((u8 *)lp->fd_buf + (bus - lp->fd_buf_dma));}#endif#ifdef TC35815_USE_PACKEDBUFFERstatic inline void *rxbuf_bus_to_virt(struct tc35815_local *lp, dma_addr_t bus){	int i;	for (i = 0; i < RX_BUF_NUM; i++) {		if (bus >= lp->data_buf_dma[i] &&		    bus < lp->data_buf_dma[i] + PAGE_SIZE)			return (void *)((u8 *)lp->data_buf[i] +					(bus - lp->data_buf_dma[i]));	}	return NULL;}#define TC35815_DMA_SYNC_ONDEMANDstatic void* alloc_rxbuf_page(struct pci_dev *hwdev, dma_addr_t *dma_handle){#ifdef TC35815_DMA_SYNC_ONDEMAND	void *buf;	/* pci_map + pci_dma_sync will be more effective than	 * pci_alloc_consistent on some archs. */	if ((buf = (void *)__get_free_page(GFP_ATOMIC)) == NULL)		return NULL;	*dma_handle = pci_map_single(hwdev, buf, PAGE_SIZE,				     PCI_DMA_FROMDEVICE);	if (pci_dma_mapping_error(*dma_handle)) {		free_page((unsigned long)buf);		return NULL;	}	return buf;#else	return pci_alloc_consistent(hwdev, PAGE_SIZE, dma_handle);#endif}static void free_rxbuf_page(struct pci_dev *hwdev, void *buf, dma_addr_t dma_handle){#ifdef TC35815_DMA_SYNC_ONDEMAND	pci_unmap_single(hwdev, dma_handle, PAGE_SIZE, PCI_DMA_FROMDEVICE);	free_page((unsigned long)buf);#else	pci_free_consistent(hwdev, PAGE_SIZE, buf, dma_handle);#endif}#else /* TC35815_USE_PACKEDBUFFER */static struct sk_buff *alloc_rxbuf_skb(struct net_device *dev,				       struct pci_dev *hwdev,				       dma_addr_t *dma_handle){	struct sk_buff *skb;	skb = dev_alloc_skb(RX_BUF_SIZE);	if (!skb)		return NULL;	*dma_handle = pci_map_single(hwdev, skb->data, RX_BUF_SIZE,				     PCI_DMA_FROMDEVICE);	if (pci_dma_mapping_error(*dma_handle)) {		dev_kfree_skb_any(skb);		return NULL;	}	skb_reserve(skb, 2);	/* make IP header 4byte aligned */	return skb;}static void free_rxbuf_skb(struct pci_dev *hwdev, struct sk_buff *skb, dma_addr_t dma_handle){	pci_unmap_single(hwdev, dma_handle, RX_BUF_SIZE,			 PCI_DMA_FROMDEVICE);	dev_kfree_skb_any(skb);}#endif /* TC35815_USE_PACKEDBUFFER *//* Index to functions, as function prototypes. */static int	tc35815_open(struct net_device *dev);static int	tc35815_send_packet(struct sk_buff *skb, struct net_device *dev);static irqreturn_t	tc35815_interrupt(int irq, void *dev_id);#ifdef TC35815_NAPIstatic int	tc35815_rx(struct net_device *dev, int limit);static int	tc35815_poll(struct napi_struct *napi, int budget);#elsestatic void	tc35815_rx(struct net_device *dev);#endifstatic void	tc35815_txdone(struct net_device *dev);static int	tc35815_close(struct net_device *dev);static struct	net_device_stats *tc35815_get_stats(struct net_device *dev);static void	tc35815_set_multicast_list(struct net_device *dev);static void     tc35815_tx_timeout(struct net_device *dev);static int	tc35815_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);#ifdef CONFIG_NET_POLL_CONTROLLERstatic void	tc35815_poll_controller(struct net_device *dev);#endifstatic const struct ethtool_ops tc35815_ethtool_ops;/* Example routines you must write ;->. */static void 	tc35815_chip_reset(struct net_device *dev);static void 	tc35815_chip_init(struct net_device *dev);static void	tc35815_find_phy(struct net_device *dev);static void 	tc35815_phy_chip_init(struct net_device *dev);#ifdef DEBUGstatic void	panic_queues(struct net_device *dev);#endifstatic void tc35815_timer(unsigned long data);static void tc35815_start_auto_negotiation(struct net_device *dev,					   struct ethtool_cmd *ep);static int tc_mdio_read(struct net_device *dev, int phy_id, int location);static void tc_mdio_write(struct net_device *dev, int phy_id, int location,			  int val);#ifdef CONFIG_CPU_TX49XX/* * Find a platform_device providing a MAC address.  The platform code * should provide a "tc35815-mac" device with a MAC address in its * platform_data. */static int __devinit tc35815_mac_match(struct device *dev, void *data){	struct platform_device *plat_dev = to_platform_device(dev);	struct pci_dev *pci_dev = data;	unsigned int id = pci_dev->irq;	return !strcmp(plat_dev->name, "tc35815-mac") && plat_dev->id == id;}static int __devinit tc35815_read_plat_dev_addr(struct net_device *dev){	struct tc35815_local *lp = dev->priv;	struct device *pd = bus_find_device(&platform_bus_type, NULL,					    lp->pci_dev, tc35815_mac_match);	if (pd) {		if (pd->platform_data)			memcpy(dev->dev_addr, pd->platform_data, ETH_ALEN);		put_device(pd);		return is_valid_ether_addr(dev->dev_addr) ? 0 : -ENODEV;	}	return -ENODEV;}#elsestatic int __devinit tc35815_read_plat_dev_addr(struct net_device *dev){	return -ENODEV;}#endifstatic int __devinit tc35815_init_dev_addr (struct net_device *dev){	struct tc35815_regs __iomem *tr =		(struct tc35815_regs __iomem *)dev->base_addr;	int i;	while (tc_readl(&tr->PROM_Ctl) & PROM_Busy)		;	for (i = 0; i < 6; i += 2) {		unsigned short data;		tc_writel(PROM_Busy | PROM_Read | (i / 2 + 2), &tr->PROM_Ctl);		while (tc_readl(&tr->PROM_Ctl) & PROM_Busy)			;		data = tc_readl(&tr->PROM_Data);		dev->dev_addr[i] = data & 0xff;		dev->dev_addr[i+1] = data >> 8;	}	if (!is_valid_ether_addr(dev->dev_addr))		return tc35815_read_plat_dev_addr(dev);	return 0;}static int __devinit tc35815_init_one (struct pci_dev *pdev,				       const struct pci_device_id *ent){	void __iomem *ioaddr = NULL;	struct net_device *dev;	struct tc35815_local *lp;	int rc;	unsigned long mmio_start, mmio_end, mmio_flags, mmio_len;	static int printed_version;	if (!printed_version++) {		printk(version);		dev_printk(KERN_DEBUG, &pdev->dev,			   "speed:%d duplex:%d doforce:%d\n",			   options.speed, options.duplex, options.doforce);	}	if (!pdev->irq) {		dev_warn(&pdev->dev, "no IRQ assigned.\n");		return -ENODEV;	}	/* dev zeroed in alloc_etherdev */	dev = alloc_etherdev (sizeof (*lp));	if (dev == NULL) {		dev_err(&pdev->dev, "unable to alloc new ethernet\n");		return -ENOMEM;	}	SET_NETDEV_DEV(dev, &pdev->dev);	lp = dev->priv;	lp->dev = dev;	/* enable device (incl. PCI PM wakeup), and bus-mastering */	rc = pci_enable_device (pdev);	if (rc)		goto err_out;	mmio_start = pci_resource_start (pdev, 1);	mmio_end = pci_resource_end (pdev, 1);	mmio_flags = pci_resource_flags (pdev, 1);	mmio_len = pci_resource_len (pdev, 1);	/* set this immediately, we need to know before	 * we talk to the chip directly */	/* make sure PCI base addr 1 is MMIO */	if (!(mmio_flags & IORESOURCE_MEM)) {		dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n");		rc = -ENODEV;		goto err_out;	}	/* check for weird/broken PCI region reporting */	if ((mmio_len < sizeof(struct tc35815_regs))) {		dev_err(&pdev->dev, "Invalid PCI region size(s), aborting\n");		rc = -ENODEV;		goto err_out;	}	rc = pci_request_regions (pdev, MODNAME);	if (rc)		goto err_out;	pci_set_master (pdev);	/* ioremap MMIO region */	ioaddr = ioremap (mmio_start, mmio_len);	if (ioaddr == NULL) {		dev_err(&pdev->dev, "cannot remap MMIO, aborting\n");		rc = -EIO;		goto err_out_free_res;	}	/* Initialize the device structure. */	dev->open = tc35815_open;	dev->hard_start_xmit = tc35815_send_packet;	dev->stop = tc35815_close;	dev->get_stats = tc35815_get_stats;	dev->set_multicast_list = tc35815_set_multicast_list;	dev->do_ioctl = tc35815_ioctl;	dev->ethtool_ops = &tc35815_ethtool_ops;	dev->tx_timeout = tc35815_tx_timeout;	dev->watchdog_timeo = TC35815_TX_TIMEOUT;#ifdef TC35815_NAPI	netif_napi_add(dev, &lp->napi, tc35815_poll, NAPI_WEIGHT);#endif#ifdef CONFIG_NET_POLL_CONTROLLER	dev->poll_controller = tc35815_poll_controller;#endif	dev->irq = pdev->irq;	dev->base_addr = (unsigned long) ioaddr;	spin_lock_init(&lp->lock);	lp->pci_dev = pdev;	lp->boardtype = ent->driver_data;	lp->msg_enable = NETIF_MSG_TX_ERR | NETIF_MSG_HW | NETIF_MSG_DRV | NETIF_MSG_LINK;	pci_set_drvdata(pdev, dev);	/* Soft reset the chip. */	tc35815_chip_reset(dev);	/* Retrieve the ethernet address. */	if (tc35815_init_dev_addr(dev)) {		dev_warn(&pdev->dev, "not valid ether addr\n");		random_ether_addr(dev->dev_addr);	}	rc = register_netdev (dev);	if (rc)		goto err_out_unmap;	memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);	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,		board_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);	setup_timer(&lp->timer, tc35815_timer, (unsigned long) dev);	lp->mii.dev = dev;	lp->mii.mdio_read = tc_mdio_read;	lp->mii.mdio_write = tc_mdio_write;	lp->mii.phy_id_mask = 0x1f;	lp->mii.reg_num_mask = 0x1f;	tc35815_find_phy(dev);	lp->mii.phy_id = lp->phy_addr;	lp->mii.full_duplex = 0;	lp->mii.force_media = 0;	return 0;err_out_unmap:	iounmap(ioaddr);err_out_free_res:	pci_release_regions (pdev);err_out:	free_netdev (dev);	return rc;}static void __devexit tc35815_remove_one (struct pci_dev *pdev){	struct net_device *dev = pci_get_drvdata (pdev);	unsigned long mmio_addr;	mmio_addr = dev->base_addr;	unregister_netdev (dev);	if (mmio_addr) {		iounmap ((void __iomem *)mmio_addr);		pci_release_regions (pdev);	}	free_netdev (dev);	pci_set_drvdata (pdev, NULL);}static inttc35815_init_queues(struct net_device *dev){	struct tc35815_local *lp = dev->priv;	int i;	unsigned long fd_addr;	if (!lp->fd_buf) {		BUG_ON(sizeof(struct FDesc) +		       sizeof(struct BDesc) * RX_BUF_NUM +		       sizeof(struct FDesc) * RX_FD_NUM +		       sizeof(struct TxFD) * TX_FD_NUM >		       PAGE_SIZE * FD_PAGE_NUM);		if ((lp->fd_buf = pci_alloc_consistent(lp->pci_dev, PAGE_SIZE * FD_PAGE_NUM, &lp->fd_buf_dma)) == 0)			return -ENOMEM;		for (i = 0; i < RX_BUF_NUM; i++) {#ifdef TC35815_USE_PACKEDBUFFER			if ((lp->data_buf[i] = alloc_rxbuf_page(lp->pci_dev, &lp->data_buf_dma[i])) == NULL) {				while (--i >= 0) {					free_rxbuf_page(lp->pci_dev,							lp->data_buf[i],							lp->data_buf_dma[i]);					lp->data_buf[i] = NULL;				}				pci_free_consistent(lp->pci_dev,						    PAGE_SIZE * FD_PAGE_NUM,						    lp->fd_buf,

⌨️ 快捷键说明

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