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

📄 starfire.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
			} else				crc >>= 1;		}	}	return crc;}static void set_rx_mode(struct net_device *dev){	long ioaddr = dev->base_addr;	u32 rx_mode;	struct dev_mc_list *mclist;	int i;	if (dev->flags & IFF_PROMISC) {	/* Set promiscuous. */		rx_mode = AcceptBroadcast|AcceptAllMulticast|AcceptAll|AcceptMyPhys;	} else if ((dev->mc_count > multicast_filter_limit)		   || (dev->flags & IFF_ALLMULTI)) {		/* Too many to match, or accept all multicasts. */		rx_mode = AcceptBroadcast|AcceptAllMulticast|AcceptMyPhys;	} else if (dev->mc_count <= 15) {		/* Use the 16 element perfect filter, skip first entry. */		long filter_addr = ioaddr + PerfFilterTable + 1 * 16;		for (i = 1, mclist = dev->mc_list; mclist && i <= dev->mc_count;		     i++, mclist = mclist->next) {			u16 *eaddrs = (u16 *)mclist->dmi_addr;			writew(cpu_to_be16(eaddrs[2]), filter_addr); filter_addr += 4;			writew(cpu_to_be16(eaddrs[1]), filter_addr); filter_addr += 4;			writew(cpu_to_be16(eaddrs[0]), filter_addr); filter_addr += 8;		}		while (i++ < 16) {			writew(0xffff, filter_addr); filter_addr += 4;			writew(0xffff, filter_addr); filter_addr += 4;			writew(0xffff, filter_addr); filter_addr += 8;		}		rx_mode = AcceptBroadcast | AcceptMyPhys;	} else {		/* Must use a multicast hash table. */		long filter_addr;		u16 mc_filter[32] __attribute__ ((aligned(sizeof(long))));	/* Multicast hash filter */		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_le(ETH_ALEN, mclist->dmi_addr) >> 23;			__u32 *fptr = (__u32 *) &mc_filter[(bit_nr >> 4) & ~1];			*fptr |= cpu_to_le32(1 << (bit_nr & 31));		}		/* Clear the perfect filter list, skip first entry. */		filter_addr = ioaddr + PerfFilterTable + 1 * 16;		for (i = 1; i < 16; i++) {			writew(0xffff, filter_addr); filter_addr += 4;			writew(0xffff, filter_addr); filter_addr += 4;			writew(0xffff, filter_addr); filter_addr += 8;		}		for (filter_addr = ioaddr + HashTable, i=0; i < 32; filter_addr+= 16, i++)			writew(mc_filter[i], filter_addr);		rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;	}	writel(rx_mode, ioaddr + RxFilterMode);}static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr){	struct ethtool_cmd ecmd;	struct netdev_private *np = dev->priv;	if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))		return -EFAULT;	switch (ecmd.cmd) {	case ETHTOOL_GSET:		ecmd.supported =			SUPPORTED_10baseT_Half |			SUPPORTED_10baseT_Full |			SUPPORTED_100baseT_Half |			SUPPORTED_100baseT_Full |			SUPPORTED_Autoneg |			SUPPORTED_MII;		ecmd.advertising = ADVERTISED_MII;		if (np->advertising & ADVERTISE_10HALF)			ecmd.advertising |= ADVERTISED_10baseT_Half;		if (np->advertising & ADVERTISE_10FULL)			ecmd.advertising |= ADVERTISED_10baseT_Full;		if (np->advertising & ADVERTISE_100HALF)			ecmd.advertising |= ADVERTISED_100baseT_Half;		if (np->advertising & ADVERTISE_100FULL)			ecmd.advertising |= ADVERTISED_100baseT_Full;		if (np->autoneg) {			ecmd.advertising |= ADVERTISED_Autoneg;			ecmd.autoneg = AUTONEG_ENABLE;		} else			ecmd.autoneg = AUTONEG_DISABLE;		ecmd.port = PORT_MII;		ecmd.transceiver = XCVR_INTERNAL;		ecmd.phy_address = np->phys[0];		ecmd.speed = np->speed100 ? SPEED_100 : SPEED_10;		ecmd.duplex = np->full_duplex ? DUPLEX_FULL : DUPLEX_HALF;		ecmd.maxtxpkt = TX_RING_SIZE;		ecmd.maxrxpkt = np->intr_mitigation; /* not 100% accurate */		if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))			return -EFAULT;		return 0;	case ETHTOOL_SSET: {		u16 autoneg, speed100, full_duplex;		autoneg = (ecmd.autoneg == AUTONEG_ENABLE);		speed100 = (ecmd.speed == SPEED_100);		full_duplex = (ecmd.duplex == DUPLEX_FULL);		np->autoneg = autoneg;		if (speed100 != np->speed100 ||		    full_duplex != np->full_duplex) {			np->speed100 = speed100;			np->full_duplex = full_duplex;			/* change advertising bits */			np->advertising &= ~(ADVERTISE_10HALF |					     ADVERTISE_10FULL |					     ADVERTISE_100HALF |					     ADVERTISE_100FULL |					     ADVERTISE_100BASE4);			if (speed100) {				if (full_duplex)					np->advertising |= ADVERTISE_100FULL;				else					np->advertising |= ADVERTISE_100HALF;			} else {				if (full_duplex)					np->advertising |= ADVERTISE_10FULL;				else					np->advertising |= ADVERTISE_10HALF;			}		}		check_duplex(dev);		return 0;	}	case ETHTOOL_GDRVINFO: {		struct ethtool_drvinfo info;		memset(&info, 0, sizeof(info));		info.cmd = ecmd.cmd;		strcpy(info.driver, DRV_NAME);		strcpy(info.version, DRV_VERSION);		*info.fw_version = 0;		strcpy(info.bus_info, PCI_SLOT_NAME(np->pci_dev));		if (copy_to_user(useraddr, &info, sizeof(info)))		       return -EFAULT;		return 0;	}	/* restart autonegotiation */	case ETHTOOL_NWAY_RST: {		int tmp;		int r = -EINVAL;		/* if autoneg is off, it's an error */		tmp = mdio_read(dev, np->phys[0], MII_BMCR);		if (tmp & BMCR_ANENABLE) {			tmp |= (BMCR_ANRESTART);			mdio_write(dev, np->phys[0], MII_BMCR, tmp);			r = 0;		}		return r;	}	/* get link status */	case ETHTOOL_GLINK: {		struct ethtool_value edata = {ETHTOOL_GLINK};		if (mdio_read(dev, np->phys[0], MII_BMSR) & BMSR_LSTATUS)			edata.data = 1;		else			edata.data = 0;		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:		return -EOPNOTSUPP;	}}static int netdev_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;	switch(cmd) {	case SIOCETHTOOL:		return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);	/* Legacy mii-diag interface */	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);		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 (data->phy_id == np->phys[0]) {			u16 value = data->val_in;			switch (data->reg_num) {			case 0:				if (value & (BMCR_RESET | BMCR_ANENABLE))					/* Autonegotiation. */					np->autoneg = 1;				else {					np->full_duplex = (value & BMCR_FULLDPLX) ? 1 : 0;					np->autoneg = 0;				}				break;			case 4:				np->advertising = value;				break;			}			check_duplex(dev);		}		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);	netif_stop_if(dev);	if (debug > 1) {		printk(KERN_DEBUG "%s: Shutting down ethercard, Intr status %4.4x.\n",			   dev->name, (int)readl(ioaddr + IntrStatus));		printk(KERN_DEBUG "%s: Queue pointers were Tx %d / %d,  Rx %d / %d.\n",			   dev->name, np->cur_tx, np->dirty_tx, np->cur_rx, np->dirty_rx);	}	/* Disable interrupts by clearing the interrupt mask. */	writel(0, ioaddr + IntrEnable);	/* Stop the chip's Tx and Rx processes. */#ifdef __i386__	if (debug > 2) {		printk("\n"KERN_DEBUG"  Tx ring at %8.8x:\n",			   np->tx_ring_dma);		for (i = 0; i < 8 /* TX_RING_SIZE is huge! */; i++)			printk(KERN_DEBUG " #%d desc. %8.8x %8.8x -> %8.8x.\n",			       i, le32_to_cpu(np->tx_ring[i].status),			       le32_to_cpu(np->tx_ring[i].first_addr),			       le32_to_cpu(np->tx_done_q[i].status));		printk(KERN_DEBUG "  Rx ring at %8.8x -> %p:\n",		       np->rx_ring_dma, np->rx_done_q);		if (np->rx_done_q)			for (i = 0; i < 8 /* RX_RING_SIZE */; i++) {				printk(KERN_DEBUG " #%d desc. %8.8x -> %8.8x\n",				       i, le32_to_cpu(np->rx_ring[i].rxaddr), le32_to_cpu(np->rx_done_q[i].status));		}	}#endif /* __i386__ debugging only */	free_irq(dev->irq, dev);	/* Free all the skbuffs in the Rx queue. */	for (i = 0; i < RX_RING_SIZE; i++) {		np->rx_ring[i].rxaddr = cpu_to_le32(0xBADF00D0); /* An invalid address. */		if (np->rx_info[i].skb != NULL) {			pci_unmap_single(np->pci_dev, np->rx_info[i].mapping, np->rx_buf_sz, PCI_DMA_FROMDEVICE);			dev_kfree_skb(np->rx_info[i].skb);		}		np->rx_info[i].skb = NULL;		np->rx_info[i].mapping = 0;	}	for (i = 0; i < TX_RING_SIZE; i++) {		struct sk_buff *skb = np->tx_info[i].skb;#ifdef ZEROCOPY		int j;#endif /* ZEROCOPY */		if (skb == NULL)			continue;		pci_unmap_single(np->pci_dev,				 np->tx_info[i].first_mapping,				 skb_first_frag_len(skb), PCI_DMA_TODEVICE);		np->tx_info[i].first_mapping = 0;		dev_kfree_skb(skb);		np->tx_info[i].skb = NULL;#ifdef ZEROCOPY		for (j = 0; j < MAX_STARFIRE_FRAGS; j++)			if (np->tx_info[i].frag_mapping[j]) {				pci_unmap_single(np->pci_dev,						 np->tx_info[i].frag_mapping[j],						 skb_shinfo(skb)->frags[j].size,						 PCI_DMA_TODEVICE);				np->tx_info[i].frag_mapping[j] = 0;			} else				break;#endif /* ZEROCOPY */	}	COMPAT_MOD_DEC_USE_COUNT;	return 0;}static void __devexit starfire_remove_one (struct pci_dev *pdev){	struct net_device *dev = pci_get_drvdata(pdev);	struct netdev_private *np;	if (!dev)		BUG();	np = dev->priv;	if (np->tx_done_q)		pci_free_consistent(pdev, PAGE_SIZE,				    np->tx_done_q, np->tx_done_q_dma);	if (np->rx_done_q)		pci_free_consistent(pdev,				    sizeof(struct rx_done_desc) * DONE_Q_SIZE,				    np->rx_done_q, np->rx_done_q_dma);	if (np->tx_ring)		pci_free_consistent(pdev, PAGE_SIZE,				    np->tx_ring, np->tx_ring_dma);	if (np->rx_ring)		pci_free_consistent(pdev, PAGE_SIZE,				    np->rx_ring, np->rx_ring_dma);	unregister_netdev(dev);	iounmap((char *)dev->base_addr);	pci_release_regions(pdev);	pci_set_drvdata(pdev, NULL);	kfree(dev);			/* Will also free np!! */}static struct pci_driver starfire_driver = {	name:		DRV_NAME,	probe:		starfire_init_one,	remove:		__devexit_p(starfire_remove_one),	id_table:	starfire_pci_tbl,};static int __init starfire_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 (&starfire_driver);}static void __exit starfire_cleanup (void){	pci_unregister_driver (&starfire_driver);}module_init(starfire_init);module_exit(starfire_cleanup);/* * Local variables: *  compile-command: "gcc -DMODULE -Wall -Wstrict-prototypes -O2 -c starfire.c" *  simple-compile-command: "gcc -DMODULE -O2 -c starfire.c" *  c-basic-offset: 8 *  tab-width: 8 * End: */

⌨️ 快捷键说明

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