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

📄 via-rhine.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 4 页
字号:
	int boguscnt = np->dirty_rx + RX_RING_SIZE - np->cur_rx;	if (debug > 4) {		printk(KERN_DEBUG " In via_rhine_rx(), entry %d status %8.8x.\n",			   entry, le32_to_cpu(np->rx_head_desc->rx_status));	}	/* If EOP is set on the next entry, it's a new packet. Send it up. */	while ( ! (np->rx_head_desc->rx_status & cpu_to_le32(DescOwn))) {		struct rx_desc *desc = np->rx_head_desc;		u32 desc_status = le32_to_cpu(desc->rx_status);		int data_size = desc_status >> 16;		if (debug > 4)			printk(KERN_DEBUG "  via_rhine_rx() status is %8.8x.\n",				   desc_status);		if (--boguscnt < 0)			break;		if ( (desc_status & (RxWholePkt | RxErr)) !=  RxWholePkt) {			if ((desc_status & RxWholePkt) !=  RxWholePkt) {				printk(KERN_WARNING "%s: Oversized Ethernet frame spanned "					   "multiple buffers, entry %#x length %d status %8.8x!\n",					   dev->name, entry, data_size, desc_status);				printk(KERN_WARNING "%s: Oversized Ethernet frame %p vs %p.\n",					   dev->name, np->rx_head_desc, &np->rx_ring[entry]);				np->stats.rx_length_errors++;			} else if (desc_status & RxErr) {				/* There was a error. */				if (debug > 2)					printk(KERN_DEBUG "  via_rhine_rx() Rx error was %8.8x.\n",						   desc_status);				np->stats.rx_errors++;				if (desc_status & 0x0030) np->stats.rx_length_errors++;				if (desc_status & 0x0048) np->stats.rx_fifo_errors++;				if (desc_status & 0x0004) np->stats.rx_frame_errors++;				if (desc_status & 0x0002) {					/* this can also be updated outside the interrupt handler */					spin_lock (&np->lock);					np->stats.rx_crc_errors++;					spin_unlock (&np->lock);				}			}		} else {			struct sk_buff *skb;			/* Length should omit the CRC */			int pkt_len = data_size - 4;			/* Check if the packet is long enough to accept without copying			   to a minimally-sized skbuff. */			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 */				pci_dma_sync_single(np->pdev, np->rx_skbuff_dma[entry],						    np->rx_buf_sz, PCI_DMA_FROMDEVICE);				/* *_IP_COPYSUM isn't defined anywhere and eth_copy_and_sum				   is memcpy for all archs so this is kind of pointless right				   now ... or? */#if HAS_IP_COPYSUM                     /* Call copy + cksum if available. */				eth_copy_and_sum(skb, np->rx_skbuff[entry]->tail, pkt_len, 0);				skb_put(skb, pkt_len);#else				memcpy(skb_put(skb, pkt_len), np->rx_skbuff[entry]->tail,					   pkt_len);#endif			} else {				skb = np->rx_skbuff[entry];				if (skb == NULL) {					printk(KERN_ERR "%s: Inconsistent Rx descriptor chain.\n",						   dev->name);					break;				}				np->rx_skbuff[entry] = NULL;				skb_put(skb, pkt_len);				pci_unmap_single(np->pdev, np->rx_skbuff_dma[entry],								 np->rx_buf_sz, PCI_DMA_FROMDEVICE);			}			skb->protocol = eth_type_trans(skb, dev);			netif_rx(skb);			dev->last_rx = jiffies;			np->stats.rx_bytes += pkt_len;			np->stats.rx_packets++;		}		entry = (++np->cur_rx) % RX_RING_SIZE;		np->rx_head_desc = &np->rx_ring[entry];	}	/* Refill the Rx ring buffers. */	for (; np->cur_rx - np->dirty_rx > 0; np->dirty_rx++) {		struct sk_buff *skb;		entry = np->dirty_rx % RX_RING_SIZE;		if (np->rx_skbuff[entry] == NULL) {			skb = dev_alloc_skb(np->rx_buf_sz);			np->rx_skbuff[entry] = skb;			if (skb == NULL)				break;			/* Better luck next round. */			skb->dev = dev;			/* Mark as being used by this device. */			np->rx_skbuff_dma[entry] =				pci_map_single(np->pdev, skb->tail, np->rx_buf_sz, 							   PCI_DMA_FROMDEVICE);			np->rx_ring[entry].addr = cpu_to_le32(np->rx_skbuff_dma[entry]);		}		np->rx_ring[entry].rx_status = cpu_to_le32(DescOwn);	}	/* Pre-emptively restart Rx engine. */	writew(CmdRxDemand | np->chip_cmd, dev->base_addr + ChipCmd);}static void via_rhine_error(struct net_device *dev, int intr_status){	struct netdev_private *np = dev->priv;	long ioaddr = dev->base_addr;	spin_lock (&np->lock);	if (intr_status & (IntrMIIChange | IntrLinkChange)) {		if (readb(ioaddr + MIIStatus) & 0x02) {			/* Link failed, restart autonegotiation. */			if (np->drv_flags & HasDavicomPhy)				mdio_write(dev, np->phys[0], MII_BMCR, 0x3300);		} else			via_rhine_check_duplex(dev);		if (debug)			printk(KERN_ERR "%s: MII status changed: Autonegotiation "				   "advertising %4.4x  partner %4.4x.\n", dev->name,			   mdio_read(dev, np->phys[0], MII_ADVERTISE),			   mdio_read(dev, np->phys[0], MII_LPA));	}	if (intr_status & IntrStatsMax) {		np->stats.rx_crc_errors	+= readw(ioaddr + RxCRCErrs);		np->stats.rx_missed_errors	+= readw(ioaddr + RxMissed);		clear_tally_counters(ioaddr);	}	if (intr_status & IntrTxAbort) {		/* Stats counted in Tx-done handler, just restart Tx. */		writew(CmdTxDemand | np->chip_cmd, dev->base_addr + ChipCmd);	}	if (intr_status & IntrTxUnderrun) {		if (np->tx_thresh < 0xE0)			writeb(np->tx_thresh += 0x20, ioaddr + TxConfig);		if (debug > 1)			printk(KERN_INFO "%s: Transmitter underrun, increasing Tx "				   "threshold setting to %2.2x.\n", dev->name, np->tx_thresh);	}	if ((intr_status & ~( IntrLinkChange | IntrStatsMax |						  IntrTxAbort | IntrTxAborted))) {		if (debug > 1)			printk(KERN_ERR "%s: Something Wicked happened! %4.4x.\n",			   dev->name, intr_status);		/* Recovery for other fault sources not known. */		writew(CmdTxDemand | np->chip_cmd, dev->base_addr + ChipCmd);	}	spin_unlock (&np->lock);}static struct net_device_stats *via_rhine_get_stats(struct net_device *dev){	struct netdev_private *np = dev->priv;	long ioaddr = dev->base_addr;	unsigned long flags;	spin_lock_irqsave(&np->lock, flags);	np->stats.rx_crc_errors	+= readw(ioaddr + RxCRCErrs);	np->stats.rx_missed_errors	+= readw(ioaddr + RxMissed);	clear_tally_counters(ioaddr);	spin_unlock_irqrestore(&np->lock, flags);	return &np->stats;}/* Clears the "tally counters" for CRC errors and missed frames(?).   It has been reported that some chips need a write of 0 to clear   these, for others the counters are set to 1 when written to and   instead cleared when read. So we clear them both ways ... */static inline void clear_tally_counters(const long ioaddr){	writel(0, ioaddr + RxMissed);	readw(ioaddr + RxCRCErrs);	readw(ioaddr + RxMissed);}/* The big-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 = 0x04c11db7U;static inline u32 ether_crc(int length, unsigned char *data){    int crc = -1;    while(--length >= 0) {		unsigned char current_octet = *data++;		int bit;		for (bit = 0; bit < 8; bit++, current_octet >>= 1) {			crc = (crc << 1) ^				((crc < 0) ^ (current_octet & 1) ? ethernet_polynomial : 0);		}    }    return crc;}static void via_rhine_set_rx_mode(struct net_device *dev){	struct netdev_private *np = dev->priv;	long ioaddr = dev->base_addr;	u32 mc_filter[2];			/* Multicast hash filter */	u8 rx_mode;					/* Note: 0x02=accept runt, 0x01=accept errs */	if (dev->flags & IFF_PROMISC) {			/* Set promiscuous. */		/* Unconditionally log net taps. */		printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", dev->name);		rx_mode = 0x1C;	} else if ((dev->mc_count > multicast_filter_limit)			   ||  (dev->flags & IFF_ALLMULTI)) {		/* Too many to match, or accept all multicasts. */		writel(0xffffffff, ioaddr + MulticastFilter0);		writel(0xffffffff, ioaddr + MulticastFilter1);		rx_mode = 0x0C;	} else {		struct dev_mc_list *mclist;		int i;		memset(mc_filter, 0, sizeof(mc_filter));		for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;			 i++, mclist = mclist->next) {			int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26;			mc_filter[bit_nr >> 5] |= cpu_to_le32(1 << (bit_nr & 31));		}		writel(mc_filter[0], ioaddr + MulticastFilter0);		writel(mc_filter[1], ioaddr + MulticastFilter1);		rx_mode = 0x0C;	}	writeb(np->rx_thresh | rx_mode, ioaddr + RxConfig);}static int via_rhine_ethtool_ioctl (struct net_device *dev, void *useraddr){	struct netdev_private *np = dev->priv;	u32 ethcmd;	if (get_user(ethcmd, (u32 *)useraddr))		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->pdev->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 };		if (!(np->drv_flags & CanHaveMII))			break;		spin_lock_irq(&np->lock);		mii_ethtool_gset(&np->mii_if, &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 (!(np->drv_flags & CanHaveMII))			break;		if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))			return -EFAULT;		spin_lock_irq(&np->lock);		r = mii_ethtool_sset(&np->mii_if, &ecmd);		spin_unlock_irq(&np->lock);		return r;	}	/* restart autonegotiation */	case ETHTOOL_NWAY_RST: {		if (!(np->drv_flags & CanHaveMII))			break;		return mii_nway_restart(&np->mii_if);	}	/* get link status */	case ETHTOOL_GLINK: {		struct ethtool_value edata = {ETHTOOL_GLINK};		if (!(np->drv_flags & CanHaveMII))			break;		edata.data = mii_link_ok(&np->mii_if);		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 via_rhine_ioctl(struct net_device *dev, struct ifreq *rq, int cmd){	struct netdev_private *np = dev->priv;	struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data;	unsigned long flags;	int retval;	if (cmd == SIOCETHTOOL)		return via_rhine_ethtool_ioctl(dev, (void *) rq->ifr_data);	spin_lock_irqsave(&np->lock, flags);	retval = 0;	switch(cmd) {	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */	case SIOCDEVPRIVATE:		/* for binary compat, remove in 2.5 */		data->phy_id = np->phys[0] & 0x1f;		/* Fall Through */	case SIOCGMIIREG:		/* Read MII PHY register. */	case SIOCDEVPRIVATE+1:		/* for binary compat, remove in 2.5 */		data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f);		break;	case SIOCSMIIREG:		/* Write MII PHY register. */	case SIOCDEVPRIVATE+2:		/* for binary compat, remove in 2.5 */		if (!capable(CAP_NET_ADMIN)) {			retval = -EPERM;			break;		}		mdio_write(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);		break;	default:		retval = -EOPNOTSUPP;	}	spin_unlock_irqrestore(&np->lock, flags);	return retval;}static int via_rhine_close(struct net_device *dev){	long ioaddr = dev->base_addr;	struct netdev_private *np = dev->priv;	del_timer_sync(&np->timer);	spin_lock_irq(&np->lock);	netif_stop_queue(dev);	if (debug > 1)		printk(KERN_DEBUG "%s: Shutting down ethercard, status was %4.4x.\n",			   dev->name, readw(ioaddr + ChipCmd));	/* Switch to loopback mode to avoid hardware races. */	writeb(np->tx_thresh | 0x02, ioaddr + TxConfig);	/* Disable interrupts by clearing the interrupt mask. */	writew(0x0000, ioaddr + IntrEnable);	/* Stop the chip's Tx and Rx processes. */	writew(CmdStop, ioaddr + ChipCmd);	spin_unlock_irq(&np->lock);	free_irq(np->pdev->irq, dev);	free_rbufs(dev);	free_tbufs(dev);	free_ring(dev);	return 0;}static void __devexit via_rhine_remove_one (struct pci_dev *pdev){	struct net_device *dev = pci_get_drvdata(pdev);		unregister_netdev(dev);	pci_release_regions(pdev);#ifdef USE_MEM	iounmap((char *)(dev->base_addr));#endif	kfree(dev);	pci_disable_device(pdev);	pci_set_drvdata(pdev, NULL);}static struct pci_driver via_rhine_driver = {	name:		"via-rhine",	id_table:	via_rhine_pci_tbl,	probe:		via_rhine_init_one,	remove:		__devexit_p(via_rhine_remove_one),};static int __init via_rhine_init (void){/* when a module, this is printed whether or not devices are found in probe */#ifdef MODULE	printk(version);#endif	return pci_module_init (&via_rhine_driver);}static void __exit via_rhine_cleanup (void){	pci_unregister_driver (&via_rhine_driver);}module_init(via_rhine_init);module_exit(via_rhine_cleanup);/* * Local variables: *  compile-command: "gcc -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -c via-rhine.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`" *  c-indent-level: 4 *  c-basic-offset: 4 *  tab-width: 4 * End: */

⌨️ 快捷键说明

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