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

📄 epic100.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 4 页
字号:
			if (pkt_len < rx_copybreak				&& (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {				skb->dev = dev;				skb_reserve(skb, 2);	/* 16 byte align the IP header */#if 1 /* HAS_IP_COPYSUM */				eth_copy_and_sum(skb, ep->rx_skbuff[entry]->tail, pkt_len, 0);				skb_put(skb, pkt_len);#else				memcpy(skb_put(skb, pkt_len), ep->rx_skbuff[entry]->tail,					   pkt_len);#endif			} else {				pci_unmap_single(ep->pci_dev, 					ep->rx_ring[entry].bufaddr, 					ep->rx_buf_sz, PCI_DMA_FROMDEVICE);				skb_put(skb = ep->rx_skbuff[entry], pkt_len);				ep->rx_skbuff[entry] = NULL;			}			skb->protocol = eth_type_trans(skb, dev);			netif_rx(skb);			dev->last_rx = jiffies;			ep->stats.rx_packets++;			ep->stats.rx_bytes += pkt_len;		}		work_done++;		entry = (++ep->cur_rx) % RX_RING_SIZE;	}	/* Refill the Rx ring buffers. */	for (; ep->cur_rx - ep->dirty_rx > 0; ep->dirty_rx++) {		entry = ep->dirty_rx % RX_RING_SIZE;		if (ep->rx_skbuff[entry] == NULL) {			struct sk_buff *skb;			skb = ep->rx_skbuff[entry] = dev_alloc_skb(ep->rx_buf_sz);			if (skb == NULL)				break;			skb->dev = dev;			/* Mark as being used by this device. */			skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */			ep->rx_ring[entry].bufaddr = pci_map_single(ep->pci_dev, 				skb->tail, ep->rx_buf_sz, PCI_DMA_FROMDEVICE);			work_done++;		}		ep->rx_ring[entry].rxstatus = cpu_to_le32(DescOwn);	}	return work_done;}static int epic_close(struct net_device *dev){	long ioaddr = dev->base_addr;	struct epic_private *ep = dev->priv;	struct sk_buff *skb;	int i;	netif_stop_queue(dev);	if (debug > 1)		printk(KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n",			   dev->name, (int)inl(ioaddr + INTSTAT));	del_timer_sync(&ep->timer);	epic_pause(dev);	free_irq(dev->irq, dev);	/* Free all the skbuffs in the Rx queue. */	for (i = 0; i < RX_RING_SIZE; i++) {		skb = ep->rx_skbuff[i];		ep->rx_skbuff[i] = 0;		ep->rx_ring[i].rxstatus = 0;		/* Not owned by Epic chip. */		ep->rx_ring[i].buflength = 0;		if (skb) {			pci_unmap_single(ep->pci_dev, ep->rx_ring[i].bufaddr, 				 	 ep->rx_buf_sz, PCI_DMA_FROMDEVICE);			dev_kfree_skb(skb);		}		ep->rx_ring[i].bufaddr = 0xBADF00D0; /* An invalid address. */	}	for (i = 0; i < TX_RING_SIZE; i++) {		skb = ep->tx_skbuff[i];		ep->tx_skbuff[i] = 0;		if (!skb)			continue;		pci_unmap_single(ep->pci_dev, ep->tx_ring[i].bufaddr, 				 skb->len, PCI_DMA_TODEVICE);		dev_kfree_skb(skb);	}	/* Green! Leave the chip in low-power mode. */	outl(0x0008, ioaddr + GENCTL);	return 0;}static struct net_device_stats *epic_get_stats(struct net_device *dev){	struct epic_private *ep = dev->priv;	long ioaddr = dev->base_addr;	if (netif_running(dev)) {		/* Update the error counts. */		ep->stats.rx_missed_errors += inb(ioaddr + MPCNT);		ep->stats.rx_frame_errors += inb(ioaddr + ALICNT);		ep->stats.rx_crc_errors += inb(ioaddr + CRCCNT);	}	return &ep->stats;}/* Set or clear the multicast filter for this adaptor.   Note that we only use exclusion around actually queueing the   new frame, not around filling ep->setup_frame.  This is non-deterministic   when re-entered but still correct. *//* The little-endian AUTODIN II ethernet CRC calculation.   N.B. Do not use for bulk data, use a table-based routine instead.   This is common code and should be moved to net/core/crc.c */static unsigned const ethernet_polynomial_le = 0xedb88320U;static inline unsigned ether_crc_le(int length, unsigned char *data){	unsigned int crc = 0xffffffff;	/* Initial value. */	while(--length >= 0) {		unsigned char current_octet = *data++;		int bit;		for (bit = 8; --bit >= 0; current_octet >>= 1) {			if ((crc ^ current_octet) & 1) {				crc >>= 1;				crc ^= ethernet_polynomial_le;			} else				crc >>= 1;		}	}	return crc;}static void set_rx_mode(struct net_device *dev){	long ioaddr = dev->base_addr;	struct epic_private *ep = dev->priv;	unsigned char mc_filter[8];		 /* Multicast hash filter */	int i;	if (dev->flags & IFF_PROMISC) {			/* Set promiscuous. */		outl(0x002C, ioaddr + RxCtrl);		/* Unconditionally log net taps. */		printk(KERN_INFO "%s: Promiscuous mode enabled.\n", dev->name);		memset(mc_filter, 0xff, sizeof(mc_filter));	} else if ((dev->mc_count > 0)  ||  (dev->flags & IFF_ALLMULTI)) {		/* There is apparently a chip bug, so the multicast filter		   is never enabled. */		/* Too many to filter perfectly -- accept all multicasts. */		memset(mc_filter, 0xff, sizeof(mc_filter));		outl(0x000C, ioaddr + RxCtrl);	} else if (dev->mc_count == 0) {		outl(0x0004, ioaddr + RxCtrl);		return;	} else {					/* Never executed, for now. */		struct dev_mc_list *mclist;		memset(mc_filter, 0, sizeof(mc_filter));		for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;			 i++, mclist = mclist->next)			set_bit(ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x3f,					mc_filter);	}	/* ToDo: perhaps we need to stop the Tx and Rx process here? */	if (memcmp(mc_filter, ep->mc_filter, sizeof(mc_filter))) {		for (i = 0; i < 4; i++)			outw(((u16 *)mc_filter)[i], ioaddr + MC0 + i*4);		memcpy(ep->mc_filter, mc_filter, sizeof(mc_filter));	}	return;}static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr){	struct epic_private *np = dev->priv;	u32 ethcmd;	if (copy_from_user (&ethcmd, useraddr, sizeof (ethcmd)))		return -EFAULT;	switch (ethcmd) {	case ETHTOOL_GDRVINFO: {		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };		strcpy (info.driver, DRV_NAME);		strcpy (info.version, DRV_VERSION);		strcpy (info.bus_info, np->pci_dev->slot_name);		if (copy_to_user (useraddr, &info, sizeof (info)))			return -EFAULT;		return 0;	}	/* get settings */	case ETHTOOL_GSET: {		struct ethtool_cmd ecmd = { ETHTOOL_GSET };		spin_lock_irq(&np->lock);		mii_ethtool_gset(&np->mii, &ecmd);		spin_unlock_irq(&np->lock);		if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))			return -EFAULT;		return 0;	}	/* set settings */	case ETHTOOL_SSET: {		int r;		struct ethtool_cmd ecmd;		if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))			return -EFAULT;		spin_lock_irq(&np->lock);		r = mii_ethtool_sset(&np->mii, &ecmd);		spin_unlock_irq(&np->lock);		return r;	}	/* restart autonegotiation */	case ETHTOOL_NWAY_RST: {		return mii_nway_restart(&np->mii);	}	/* get link status */	case ETHTOOL_GLINK: {		struct ethtool_value edata = {ETHTOOL_GLINK};		edata.data = mii_link_ok(&np->mii);		if (copy_to_user(useraddr, &edata, sizeof(edata)))			return -EFAULT;		return 0;	}	/* get message-level */	case ETHTOOL_GMSGLVL: {		struct ethtool_value edata = {ETHTOOL_GMSGLVL};		edata.data = debug;		if (copy_to_user(useraddr, &edata, sizeof(edata)))			return -EFAULT;		return 0;	}	/* set message-level */	case ETHTOOL_SMSGLVL: {		struct ethtool_value edata;		if (copy_from_user(&edata, useraddr, sizeof(edata)))			return -EFAULT;		debug = edata.data;		return 0;	}	default:		break;	}	return -EOPNOTSUPP;}static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd){	struct epic_private *ep = dev->priv;	long ioaddr = dev->base_addr;	struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data;	switch(cmd) {	case SIOCETHTOOL:		return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */	case SIOCDEVPRIVATE:		/* for binary compat, remove in 2.5 */		data->phy_id = ep->phys[0] & 0x1f;		/* Fall Through */	case SIOCGMIIREG:		/* Read MII PHY register. */	case SIOCDEVPRIVATE+1:		/* for binary compat, remove in 2.5 */		if (! netif_running(dev)) {			outl(0x0200, ioaddr + GENCTL);			outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);		}		data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f);#if 0					/* Just leave on if the ioctl() is ever used. */		if (! netif_running(dev)) {			outl(0x0008, ioaddr + GENCTL);			outl((inl(ioaddr + NVCTL) & ~0x483C) | 0x0000, ioaddr + NVCTL);		}#endif		return 0;	case SIOCSMIIREG:		/* Write MII PHY register. */	case SIOCDEVPRIVATE+2:		/* for binary compat, remove in 2.5 */		if (!capable(CAP_NET_ADMIN))			return -EPERM;		if (! netif_running(dev)) {			outl(0x0200, ioaddr + GENCTL);			outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);		}		if (data->phy_id == ep->phys[0]) {			u16 value = data->val_in;			switch (data->reg_num) {			case 0:				/* Check for autonegotiation on or reset. */				ep->mii.duplex_lock = (value & 0x9000) ? 0 : 1;				if (ep->mii.duplex_lock)					ep->mii.full_duplex = (value & 0x0100) ? 1 : 0;				break;			case 4: ep->mii.advertising = value; break;			}			/* Perhaps check_duplex(dev), depending on chip semantics. */		}		mdio_write(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);#if 0					/* Leave on if the ioctl() is used. */		if (! netif_running(dev)) {			outl(0x0008, ioaddr + GENCTL);			outl((inl(ioaddr + NVCTL) & ~0x483C) | 0x0000, ioaddr + NVCTL);		}#endif		return 0;	default:		return -EOPNOTSUPP;	}}static void __devexit epic_remove_one (struct pci_dev *pdev){	struct net_device *dev = pci_get_drvdata(pdev);	struct epic_private *ep = dev->priv;		pci_free_consistent(pdev, TX_TOTAL_SIZE, ep->tx_ring, ep->tx_ring_dma);	pci_free_consistent(pdev, RX_TOTAL_SIZE, ep->rx_ring, ep->rx_ring_dma);	unregister_netdev(dev);#ifndef USE_IO_OPS	iounmap((void*) dev->base_addr);#endif	pci_release_regions(pdev);	kfree(dev);	pci_set_drvdata(pdev, NULL);	/* pci_power_off(pdev, -1); */}#ifdef CONFIG_PMstatic int epic_suspend (struct pci_dev *pdev, u32 state){	struct net_device *dev = pci_get_drvdata(pdev);	long ioaddr = dev->base_addr;	if (!netif_running(dev))		return 0;	epic_pause(dev);	/* Put the chip into low-power mode. */	outl(0x0008, ioaddr + GENCTL);	/* pci_power_off(pdev, -1); */	return 0;}static int epic_resume (struct pci_dev *pdev){	struct net_device *dev = pci_get_drvdata(pdev);	if (!netif_running(dev))		return 0;	epic_restart(dev);	/* pci_power_on(pdev); */	return 0;}#endif /* CONFIG_PM */static struct pci_driver epic_driver = {	name:		DRV_NAME,	id_table:	epic_pci_tbl,	probe:		epic_init_one,	remove:		__devexit_p(epic_remove_one),#ifdef CONFIG_PM	suspend:	epic_suspend,	resume:		epic_resume,#endif /* CONFIG_PM */};static int __init epic_init (void){/* when a module, this is printed whether or not devices are found in probe */#ifdef MODULE	printk (KERN_INFO "%s" KERN_INFO "%s" KERN_INFO "%s",		version, version2, version3);#endif	return pci_module_init (&epic_driver);}static void __exit epic_cleanup (void){	pci_unregister_driver (&epic_driver);}module_init(epic_init);module_exit(epic_cleanup);

⌨️ 快捷键说明

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