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

📄 fealnx.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 4 页
字号:
				if (tx_status & (CSL | LC | EC | UDF | HF)) {					np->stats.tx_errors++;					if (tx_status & EC)						np->stats.tx_aborted_errors++;					if (tx_status & CSL)						np->stats.tx_carrier_errors++;					if (tx_status & LC)						np->stats.tx_window_errors++;					if (tx_status & UDF)						np->stats.tx_fifo_errors++;					if ((tx_status & HF) && np->mii.full_duplex == 0)						np->stats.tx_heartbeat_errors++;#ifdef ETHER_STATS					if (tx_status & EC)						np->stats.collisions16++;#endif				} else {#ifdef ETHER_STATS					if (tx_status & DFR)						np->stats.tx_deferred++;#endif					np->stats.tx_bytes +=					    ((tx_control & PKTSMask) >> PKTSShift);					np->stats.collisions +=					    ((tx_status & NCRMask) >> NCRShift);					np->stats.tx_packets++;				}			} else {				np->stats.tx_bytes +=				    ((tx_control & PKTSMask) >> PKTSShift);				np->stats.tx_packets++;			}			/* Free the original skb. */			pci_unmap_single(np->pci_dev, np->cur_tx->buffer,				np->cur_tx->skbuff->len, PCI_DMA_TODEVICE);			dev_kfree_skb_irq(np->cur_tx->skbuff);			np->cur_tx->skbuff = NULL;			--np->really_tx_count;			if (np->cur_tx->control & TXLD) {				np->cur_tx = np->cur_tx->next_desc_logical;				++np->free_tx_count;			} else {				np->cur_tx = np->cur_tx->next_desc_logical;				np->cur_tx = np->cur_tx->next_desc_logical;				np->free_tx_count += 2;			}			num_tx++;		}		/* end of for loop */				if (num_tx && np->free_tx_count >= 2)			netif_wake_queue(dev);		/* read transmit status for enhanced mode only */		if (np->crvalue & 0x02000000) {			long data;			data = readl(ioaddr + TSR);			np->stats.tx_errors += (data & 0xff000000) >> 24;			np->stats.tx_aborted_errors += (data & 0xff000000) >> 24;			np->stats.tx_window_errors += (data & 0x00ff0000) >> 16;#ifdef ETHER_STATS			np->stats.collisions16 += (data & 0xff000000) >> 24;#endif			np->stats.collisions += (data & 0x0000ffff);		}		if (--boguscnt < 0) {			printk(KERN_WARNING "%s: Too much work at interrupt, "			       "status=0x%4.4x.\n", dev->name, intr_status);			break;		}	} while (1);	/* read the tally counters */	/* missed pkts */	np->stats.rx_missed_errors += readl(ioaddr + TALLY) & 0x7fff;	/* crc error */	np->stats.rx_crc_errors += (readl(ioaddr + TALLY) & 0x7fff0000) >> 16;	if (debug)		printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n",		       dev->name, readl(ioaddr + ISR));	writel(np->imrvalue, ioaddr + IMR);	return;}/* This routine is logically part of the interrupt handler, but seperated   for clarity and better register allocation. */static int netdev_rx(struct net_device *dev){	struct netdev_private *np = dev->priv;	/* If EOP is set on the next entry, it's a new packet. Send it up. */	while (!(np->cur_rx->status & RXOWN)) {		s32 rx_status = np->cur_rx->status;		if (np->really_rx_count == 0)			break;		if (debug)			printk(KERN_DEBUG "  netdev_rx() status was %8.8x.\n", rx_status);		if ((!((rx_status & RXFSD) && (rx_status & RXLSD)))		    || (rx_status & ErrorSummary)) {			if (rx_status & ErrorSummary) {	/* there was a fatal error */				if (debug)					printk(KERN_DEBUG					       "%s: Receive error, Rx status %8.8x.\n",					       dev->name, rx_status);				np->stats.rx_errors++;	/* end of a packet. */				if (rx_status & (LONG | RUNT))					np->stats.rx_length_errors++;				if (rx_status & RXER)					np->stats.rx_frame_errors++;				if (rx_status & CRC)					np->stats.rx_crc_errors++;			} else {				int need_to_reset = 0;				int desno = 0;				if (rx_status & RXFSD) {	/* this pkt is too long, over one rx buffer */					struct fealnx_desc *cur;					/* check this packet is received completely? */					cur = np->cur_rx;					while (desno <= np->really_rx_count) {						++desno;						if ((!(cur->status & RXOWN))						    && (cur->status & RXLSD))							break;						/* goto next rx descriptor */						cur = cur->next_desc_logical;					}					if (desno > np->really_rx_count)						need_to_reset = 1;				} else	/* RXLSD did not find, something error */					need_to_reset = 1;				if (need_to_reset == 0) {					int i;					np->stats.rx_length_errors++;					/* free all rx descriptors related this long pkt */					for (i = 0; i < desno; ++i)						free_one_rx_descriptor(np);					continue;				} else {	/* something error, need to reset this chip */					reset_rx_descriptors(dev);				}				break;	/* exit the while loop */			}		} else {	/* this received pkt is ok */			struct sk_buff *skb;			/* Omit the four octet CRC from the length. */			short pkt_len = ((rx_status & FLNGMASK) >> FLNGShift) - 4;#ifndef final_version			if (debug)				printk(KERN_DEBUG "  netdev_rx() normal Rx pkt length %d"				       " status %x.\n", pkt_len, rx_status);#endif			pci_dma_sync_single(np->pci_dev, np->cur_rx->buffer,				np->rx_buf_sz, PCI_DMA_FROMDEVICE);			pci_unmap_single(np->pci_dev, np->cur_rx->buffer,				np->rx_buf_sz, PCI_DMA_FROMDEVICE);			/* 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 */				/* Call copy + cksum if available. */#if ! defined(__alpha__)				eth_copy_and_sum(skb, 					np->cur_rx->skbuff->tail, pkt_len, 0);				skb_put(skb, pkt_len);#else				memcpy(skb_put(skb, pkt_len),					np->cur_rx->skbuff->tail, pkt_len);#endif			} else {				skb_put(skb = np->cur_rx->skbuff, pkt_len);				np->cur_rx->skbuff = NULL;				if (np->really_rx_count == RX_RING_SIZE)					np->lack_rxbuf = np->cur_rx;				--np->really_rx_count;			}			skb->protocol = eth_type_trans(skb, dev);			netif_rx(skb);			dev->last_rx = jiffies;			np->stats.rx_packets++;			np->stats.rx_bytes += pkt_len;		}		if (np->cur_rx->skbuff == NULL) {			struct sk_buff *skb;			skb = dev_alloc_skb(np->rx_buf_sz);			if (skb != NULL) {				skb->dev = dev;	/* Mark as being used by this device. */				np->cur_rx->buffer = pci_map_single(np->pci_dev, skb->tail,					np->rx_buf_sz, PCI_DMA_FROMDEVICE);				np->cur_rx->skbuff = skb;				++np->really_rx_count;			}		}		if (np->cur_rx->skbuff != NULL)			free_one_rx_descriptor(np);	}			/* end of while loop */	/*  allocate skb for rx buffers */	allocate_rx_buffers(dev);	return 0;}static struct net_device_stats *get_stats(struct net_device *dev){	long ioaddr = dev->base_addr;	struct netdev_private *np = dev->priv;	/* The chip only need report frame silently dropped. */	if (netif_running(dev)) {		np->stats.rx_missed_errors += readl(ioaddr + TALLY) & 0x7fff;		np->stats.rx_crc_errors += (readl(ioaddr + TALLY) & 0x7fff0000) >> 16;	}	return &np->stats;}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 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 */	u32 rx_mode;	if (dev->flags & IFF_PROMISC) {	/* Set promiscuous. */		/* Unconditionally log net taps. */		printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", dev->name);		memset(mc_filter, 0xff, sizeof(mc_filter));		rx_mode = PROM | AB | AM;	} else if ((dev->mc_count > multicast_filter_limit)		   || (dev->flags & IFF_ALLMULTI)) {		/* Too many to match, or accept all multicasts. */		memset(mc_filter, 0xff, sizeof(mc_filter));		rx_mode = AB | AM;	} 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) {			set_bit((ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26) ^ 0x3F,				mc_filter);		}		rx_mode = AB | AM;	}	stop_nic_tx(ioaddr, np->crvalue);	stop_nic_rx(ioaddr, np->crvalue & (~0x40000));	writel(mc_filter[0], ioaddr + MAR0);	writel(mc_filter[1], ioaddr + MAR1);	np->crvalue &= ~RxModeMask;	np->crvalue |= rx_mode;	writel(np->crvalue, ioaddr + TCRRCR);}static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr){	struct netdev_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 mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd){	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 = ((struct netdev_private *) dev->priv)->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);		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;		mdio_write(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);		return 0;	default:		return -EOPNOTSUPP;	}}static int netdev_close(struct net_device *dev){	long ioaddr = dev->base_addr;	struct netdev_private *np = dev->priv;	int i;	netif_stop_queue(dev);	/* Disable interrupts by clearing the interrupt mask. */	writel(0x0000, ioaddr + IMR);	/* Stop the chip's Tx and Rx processes. */	stop_nic_tx(ioaddr, 0);	stop_nic_rx(ioaddr, 0);	del_timer_sync(&np->timer);	free_irq(dev->irq, dev);	/* Free all the skbuffs in the Rx queue. */	for (i = 0; i < RX_RING_SIZE; i++) {		struct sk_buff *skb = np->rx_ring[i].skbuff;		np->rx_ring[i].status = 0;		if (skb) {			pci_unmap_single(np->pci_dev, np->rx_ring[i].buffer,				np->rx_buf_sz, PCI_DMA_FROMDEVICE);			dev_kfree_skb(skb);			np->rx_ring[i].skbuff = NULL;		}	}	for (i = 0; i < TX_RING_SIZE; i++) {		struct sk_buff *skb = np->tx_ring[i].skbuff;		if (skb) {			pci_unmap_single(np->pci_dev, np->tx_ring[i].buffer,				skb->len, PCI_DMA_TODEVICE);			dev_kfree_skb(skb);			np->tx_ring[i].skbuff = NULL;		}	}	return 0;}static struct pci_device_id fealnx_pci_tbl[] __devinitdata = {	{0x1516, 0x0800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},	{0x1516, 0x0803, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},	{0x1516, 0x0891, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},	{} /* terminate list */};MODULE_DEVICE_TABLE(pci, fealnx_pci_tbl);static struct pci_driver fealnx_driver = {	name:		"fealnx",	id_table:	fealnx_pci_tbl,	probe:		fealnx_init_one,	remove:		__devexit_p(fealnx_remove_one),};static int __init fealnx_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(&fealnx_driver);}static void __exit fealnx_exit(void){	pci_unregister_driver(&fealnx_driver);}module_init(fealnx_init);module_exit(fealnx_exit);

⌨️ 快捷键说明

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