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

📄 dl2k.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
		}		np->rx_ring[entry].fraginfo |=		    cpu_to_le64((u64)np->rx_buf_sz << 48);		np->rx_ring[entry].status = 0;		entry = (entry + 1) % RX_RING_SIZE;	}	np->old_rx = entry;	spin_unlock(&np->rx_lock);	return 0;}static voidrio_error (struct net_device *dev, int int_status){	long ioaddr = dev->base_addr;	struct netdev_private *np = netdev_priv(dev);	u16 macctrl;	/* Link change event */	if (int_status & LinkEvent) {		if (mii_wait_link (dev, 10) == 0) {			printk (KERN_INFO "%s: Link up\n", dev->name);			if (np->phy_media)				mii_get_media_pcs (dev);			else				mii_get_media (dev);			if (np->speed == 1000)				np->tx_coalesce = tx_coalesce;			else				np->tx_coalesce = 1;			macctrl = 0;			macctrl |= (np->vlan) ? AutoVLANuntagging : 0;			macctrl |= (np->full_duplex) ? DuplexSelect : 0;			macctrl |= (np->tx_flow) ?				TxFlowControlEnable : 0;			macctrl |= (np->rx_flow) ?				RxFlowControlEnable : 0;			writew(macctrl,	ioaddr + MACCtrl);			np->link_status = 1;			netif_carrier_on(dev);		} else {			printk (KERN_INFO "%s: Link off\n", dev->name);			np->link_status = 0;			netif_carrier_off(dev);		}	}	/* UpdateStats statistics registers */	if (int_status & UpdateStats) {		get_stats (dev);	}	/* PCI Error, a catastronphic error related to the bus interface	   occurs, set GlobalReset and HostReset to reset. */	if (int_status & HostError) {		printk (KERN_ERR "%s: HostError! IntStatus %4.4x.\n",			dev->name, int_status);		writew (GlobalReset | HostReset, ioaddr + ASICCtrl + 2);		mdelay (500);	}}static struct net_device_stats *get_stats (struct net_device *dev){	long ioaddr = dev->base_addr;	struct netdev_private *np = netdev_priv(dev);#ifdef MEM_MAPPING	int i;#endif	unsigned int stat_reg;	/* All statistics registers need to be acknowledged,	   else statistic overflow could cause problems */	np->stats.rx_packets += readl (ioaddr + FramesRcvOk);	np->stats.tx_packets += readl (ioaddr + FramesXmtOk);	np->stats.rx_bytes += readl (ioaddr + OctetRcvOk);	np->stats.tx_bytes += readl (ioaddr + OctetXmtOk);	np->stats.multicast = readl (ioaddr + McstFramesRcvdOk);	np->stats.collisions += readl (ioaddr + SingleColFrames)			     +  readl (ioaddr + MultiColFrames);	/* detailed tx errors */	stat_reg = readw (ioaddr + FramesAbortXSColls);	np->stats.tx_aborted_errors += stat_reg;	np->stats.tx_errors += stat_reg;	stat_reg = readw (ioaddr + CarrierSenseErrors);	np->stats.tx_carrier_errors += stat_reg;	np->stats.tx_errors += stat_reg;	/* Clear all other statistic register. */	readl (ioaddr + McstOctetXmtOk);	readw (ioaddr + BcstFramesXmtdOk);	readl (ioaddr + McstFramesXmtdOk);	readw (ioaddr + BcstFramesRcvdOk);	readw (ioaddr + MacControlFramesRcvd);	readw (ioaddr + FrameTooLongErrors);	readw (ioaddr + InRangeLengthErrors);	readw (ioaddr + FramesCheckSeqErrors);	readw (ioaddr + FramesLostRxErrors);	readl (ioaddr + McstOctetXmtOk);	readl (ioaddr + BcstOctetXmtOk);	readl (ioaddr + McstFramesXmtdOk);	readl (ioaddr + FramesWDeferredXmt);	readl (ioaddr + LateCollisions);	readw (ioaddr + BcstFramesXmtdOk);	readw (ioaddr + MacControlFramesXmtd);	readw (ioaddr + FramesWEXDeferal);#ifdef MEM_MAPPING	for (i = 0x100; i <= 0x150; i += 4)		readl (ioaddr + i);#endif	readw (ioaddr + TxJumboFrames);	readw (ioaddr + RxJumboFrames);	readw (ioaddr + TCPCheckSumErrors);	readw (ioaddr + UDPCheckSumErrors);	readw (ioaddr + IPCheckSumErrors);	return &np->stats;}static intclear_stats (struct net_device *dev){	long ioaddr = dev->base_addr;#ifdef MEM_MAPPING	int i;#endif	/* All statistics registers need to be acknowledged,	   else statistic overflow could cause problems */	readl (ioaddr + FramesRcvOk);	readl (ioaddr + FramesXmtOk);	readl (ioaddr + OctetRcvOk);	readl (ioaddr + OctetXmtOk);	readl (ioaddr + McstFramesRcvdOk);	readl (ioaddr + SingleColFrames);	readl (ioaddr + MultiColFrames);	readl (ioaddr + LateCollisions);	/* detailed rx errors */	readw (ioaddr + FrameTooLongErrors);	readw (ioaddr + InRangeLengthErrors);	readw (ioaddr + FramesCheckSeqErrors);	readw (ioaddr + FramesLostRxErrors);	/* detailed tx errors */	readw (ioaddr + FramesAbortXSColls);	readw (ioaddr + CarrierSenseErrors);	/* Clear all other statistic register. */	readl (ioaddr + McstOctetXmtOk);	readw (ioaddr + BcstFramesXmtdOk);	readl (ioaddr + McstFramesXmtdOk);	readw (ioaddr + BcstFramesRcvdOk);	readw (ioaddr + MacControlFramesRcvd);	readl (ioaddr + McstOctetXmtOk);	readl (ioaddr + BcstOctetXmtOk);	readl (ioaddr + McstFramesXmtdOk);	readl (ioaddr + FramesWDeferredXmt);	readw (ioaddr + BcstFramesXmtdOk);	readw (ioaddr + MacControlFramesXmtd);	readw (ioaddr + FramesWEXDeferal);#ifdef MEM_MAPPING	for (i = 0x100; i <= 0x150; i += 4)		readl (ioaddr + i);#endif	readw (ioaddr + TxJumboFrames);	readw (ioaddr + RxJumboFrames);	readw (ioaddr + TCPCheckSumErrors);	readw (ioaddr + UDPCheckSumErrors);	readw (ioaddr + IPCheckSumErrors);	return 0;}static intchange_mtu (struct net_device *dev, int new_mtu){	struct netdev_private *np = netdev_priv(dev);	int max = (np->jumbo) ? MAX_JUMBO : 1536;	if ((new_mtu < 68) || (new_mtu > max)) {		return -EINVAL;	}	dev->mtu = new_mtu;	return 0;}static voidset_multicast (struct net_device *dev){	long ioaddr = dev->base_addr;	u32 hash_table[2];	u16 rx_mode = 0;	struct netdev_private *np = netdev_priv(dev);	hash_table[0] = hash_table[1] = 0;	/* RxFlowcontrol DA: 01-80-C2-00-00-01. Hash index=0x39 */	hash_table[1] |= 0x02000000;	if (dev->flags & IFF_PROMISC) {		/* Receive all frames promiscuously. */		rx_mode = ReceiveAllFrames;	} else if ((dev->flags & IFF_ALLMULTI) ||			(dev->mc_count > multicast_filter_limit)) {		/* Receive broadcast and multicast frames */		rx_mode = ReceiveBroadcast | ReceiveMulticast | ReceiveUnicast;	} else if (dev->mc_count > 0) {		int i;		struct dev_mc_list *mclist;		/* Receive broadcast frames and multicast frames filtering		   by Hashtable */		rx_mode =		    ReceiveBroadcast | ReceiveMulticastHash | ReceiveUnicast;		for (i=0, mclist = dev->mc_list; mclist && i < dev->mc_count;				i++, mclist=mclist->next)		{			int bit, index = 0;			int crc = ether_crc_le (ETH_ALEN, mclist->dmi_addr);			/* The inverted high significant 6 bits of CRC are			   used as an index to hashtable */			for (bit = 0; bit < 6; bit++)				if (crc & (1 << (31 - bit)))					index |= (1 << bit);			hash_table[index / 32] |= (1 << (index % 32));		}	} else {		rx_mode = ReceiveBroadcast | ReceiveUnicast;	}	if (np->vlan) {		/* ReceiveVLANMatch field in ReceiveMode */		rx_mode |= ReceiveVLANMatch;	}	writel (hash_table[0], ioaddr + HashTable0);	writel (hash_table[1], ioaddr + HashTable1);	writew (rx_mode, ioaddr + ReceiveMode);}static void rio_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info){	struct netdev_private *np = netdev_priv(dev);	strcpy(info->driver, "dl2k");	strcpy(info->version, DRV_VERSION);	strcpy(info->bus_info, pci_name(np->pdev));}static int rio_get_settings(struct net_device *dev, struct ethtool_cmd *cmd){	struct netdev_private *np = netdev_priv(dev);	if (np->phy_media) {		/* fiber device */		cmd->supported = SUPPORTED_Autoneg | SUPPORTED_FIBRE;		cmd->advertising= ADVERTISED_Autoneg | ADVERTISED_FIBRE;		cmd->port = PORT_FIBRE;		cmd->transceiver = XCVR_INTERNAL;	} else {		/* copper device */		cmd->supported = SUPPORTED_10baseT_Half |			SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half			| SUPPORTED_100baseT_Full | SUPPORTED_1000baseT_Full |			SUPPORTED_Autoneg | SUPPORTED_MII;		cmd->advertising = ADVERTISED_10baseT_Half |			ADVERTISED_10baseT_Full | ADVERTISED_100baseT_Half |			ADVERTISED_100baseT_Full | ADVERTISED_1000baseT_Full|			ADVERTISED_Autoneg | ADVERTISED_MII;		cmd->port = PORT_MII;		cmd->transceiver = XCVR_INTERNAL;	}	if ( np->link_status ) {		cmd->speed = np->speed;		cmd->duplex = np->full_duplex ? DUPLEX_FULL : DUPLEX_HALF;	} else {		cmd->speed = -1;		cmd->duplex = -1;	}	if ( np->an_enable)		cmd->autoneg = AUTONEG_ENABLE;	else		cmd->autoneg = AUTONEG_DISABLE;	cmd->phy_address = np->phy_addr;	return 0;}static int rio_set_settings(struct net_device *dev, struct ethtool_cmd *cmd){	struct netdev_private *np = netdev_priv(dev);	netif_carrier_off(dev);	if (cmd->autoneg == AUTONEG_ENABLE) {		if (np->an_enable)			return 0;		else {			np->an_enable = 1;			mii_set_media(dev);			return 0;		}	} else {		np->an_enable = 0;		if (np->speed == 1000) {			cmd->speed = SPEED_100;			cmd->duplex = DUPLEX_FULL;			printk("Warning!! Can't disable Auto negotiation in 1000Mbps, change to Manual 100Mbps, Full duplex.\n");		}		switch(cmd->speed + cmd->duplex) {		case SPEED_10 + DUPLEX_HALF:			np->speed = 10;			np->full_duplex = 0;			break;		case SPEED_10 + DUPLEX_FULL:			np->speed = 10;			np->full_duplex = 1;			break;		case SPEED_100 + DUPLEX_HALF:			np->speed = 100;			np->full_duplex = 0;			break;		case SPEED_100 + DUPLEX_FULL:			np->speed = 100;			np->full_duplex = 1;			break;		case SPEED_1000 + DUPLEX_HALF:/* not supported */		case SPEED_1000 + DUPLEX_FULL:/* not supported */		default:			return -EINVAL;		}		mii_set_media(dev);	}	return 0;}static u32 rio_get_link(struct net_device *dev){	struct netdev_private *np = netdev_priv(dev);	return np->link_status;}static const struct ethtool_ops ethtool_ops = {	.get_drvinfo = rio_get_drvinfo,	.get_settings = rio_get_settings,	.set_settings = rio_set_settings,	.get_link = rio_get_link,};static intrio_ioctl (struct net_device *dev, struct ifreq *rq, int cmd){	int phy_addr;	struct netdev_private *np = netdev_priv(dev);	struct mii_data *miidata = (struct mii_data *) &rq->ifr_ifru;	struct netdev_desc *desc;	int i;	phy_addr = np->phy_addr;	switch (cmd) {	case SIOCDEVPRIVATE:		break;	case SIOCDEVPRIVATE + 1:		miidata->out_value = mii_read (dev, phy_addr, miidata->reg_num);		break;	case SIOCDEVPRIVATE + 2:		mii_write (dev, phy_addr, miidata->reg_num, miidata->in_value);		break;	case SIOCDEVPRIVATE + 3:		break;	case SIOCDEVPRIVATE + 4:		break;	case SIOCDEVPRIVATE + 5:		netif_stop_queue (dev);		break;	case SIOCDEVPRIVATE + 6:		netif_wake_queue (dev);		break;	case SIOCDEVPRIVATE + 7:		printk		    ("tx_full=%x cur_tx=%lx old_tx=%lx cur_rx=%lx old_rx=%lx\n",		     netif_queue_stopped(dev), np->cur_tx, np->old_tx, np->cur_rx,		     np->old_rx);		break;	case SIOCDEVPRIVATE + 8:		printk("TX ring:\n");		for (i = 0; i < TX_RING_SIZE; i++) {			desc = &np->tx_ring[i];			printk			    ("%02x:cur:%08x next:%08x status:%08x frag1:%08x frag0:%08x",			     i,			     (u32) (np->tx_ring_dma + i * sizeof (*desc)),			     (u32)le64_to_cpu(desc->next_desc),			     (u32)le64_to_cpu(desc->status),			     (u32)(le64_to_cpu(desc->fraginfo) >> 32),			     (u32)le64_to_cpu(desc->fraginfo));			printk ("\n");		}		printk ("\n");		break;	default:		return -EOPNOTSUPP;	}	return 0;}#define EEP_READ 0x0200#define EEP_BUSY 0x8000/* Read the EEPROM word *//* We use I/O instruction to read/write eeprom to avoid fail on some machines */static intread_eeprom (long ioaddr, int eep_addr){	int i = 1000;	outw (EEP_READ | (eep_addr & 0xff), ioaddr + EepromCtrl);	while (i-- > 0) {		if (!(inw (ioaddr + EepromCtrl) & EEP_BUSY)) {			return inw (ioaddr + EepromData);		}	}	return 0;}enum phy_ctrl_bits {	MII_READ = 0x00, MII_CLK = 0x01, MII_DATA1 = 0x02, MII_WRITE = 0x04,	MII_DUPLEX = 0x08,};#define mii_delay() readb(ioaddr)static voidmii_sendbit (struct net_device *dev, u32 data){	long ioaddr = dev->base_addr + PhyCtrl;	data = (data) ? MII_DATA1 : 0;	data |= MII_WRITE;	data |= (readb (ioaddr) & 0xf8) | MII_WRITE;	writeb (data, ioaddr);	mii_delay ();	writeb (data | MII_CLK, ioaddr);	mii_delay ();}static intmii_getbit (struct net_device *dev){	long ioaddr = dev->base_addr + PhyCtrl;	u8 data;	data = (readb (ioaddr) & 0xf8) | MII_READ;	writeb (data, ioaddr);	mii_delay ();	writeb (data | MII_CLK, ioaddr);	mii_delay ();	return ((readb (ioaddr) >> 1) & 1);}

⌨️ 快捷键说明

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