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

📄 at_ethtool.c

📁 Linux* Base Driver for the Attansic(R) L1 Gigabit Ethernet Adapter
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "at.h"
#include "at_hw.h"

#ifdef SIOCETHTOOL
#include <asm/uaccess.h>

extern char at_driver_name[];
extern char at_driver_version[];
#ifdef SIOCGMIIPHY
extern int at_set_spd_dplx(struct at_adapter* adapter,uint16_t spddplx);
#endif 
extern int32_t at_up(struct at_adapter* adapter);
extern void at_down(struct at_adapter* adapter);
extern void at_reset(struct at_adapter* adapter);
extern int32_t at_setup_ring_resources(struct at_adapter* adapter);
extern void at_free_ring_resources(struct at_adapter* adapter);

#ifdef	ETHTOOL_GSTATS
struct at_stats {
	char stat_string[ETH_GSTRING_LEN];
	int sizeof_stat;
	int stat_offset;
};

#define AT_STAT(m) sizeof(((struct at_adapter *)0)->m), \
		      offsetof(struct at_adapter, m)
static struct at_stats at_gstrings_stats[] = {
	{ "rx_packets",             AT_STAT(soft_stats.rx_packets)          },
	{ "tx_packets",             AT_STAT(soft_stats.tx_packets)          },
	{ "rx_bytes",               AT_STAT(soft_stats.rx_bytes)            },
	{ "tx_bytes",               AT_STAT(soft_stats.tx_bytes)            },
	{ "rx_errors",              AT_STAT(soft_stats.rx_errors)           },
	{ "tx_errors",              AT_STAT(soft_stats.tx_errors)           },
	{ "rx_dropped",             AT_STAT(net_stats.rx_dropped)           },
	{ "tx_dropped",             AT_STAT(net_stats.tx_dropped)           },
	{ "multicast",              AT_STAT(soft_stats.multicast)           },
	{ "collisions",             AT_STAT(soft_stats.collisions)          },
	{ "rx_length_errors",       AT_STAT(soft_stats.rx_length_errors)    },
	{ "rx_over_errors",         AT_STAT(soft_stats.rx_missed_errors)    },
	{ "rx_crc_errors",          AT_STAT(soft_stats.rx_crc_errors)       },
	{ "rx_frame_errors",        AT_STAT(soft_stats.rx_frame_errors)     },
	{ "rx_fifo_errors",         AT_STAT(soft_stats.rx_fifo_errors)      },
	{ "rx_missed_errors",       AT_STAT(soft_stats.rx_missed_errors)    },
	{ "tx_aborted_errors",      AT_STAT(soft_stats.tx_aborted_errors)   },
	{ "tx_carrier_errors",      AT_STAT(soft_stats.tx_carrier_errors)   },
	{ "tx_fifo_errors",         AT_STAT(soft_stats.tx_fifo_errors)      },
	{ "tx_window_errors",       AT_STAT(soft_stats.tx_window_errors)    },
	{ "tx_abort_exce_coll",     AT_STAT(soft_stats.excecol)             },
	{ "tx_abort_late_coll",     AT_STAT(soft_stats.latecol)             },
	{ "tx_deferred_ok",         AT_STAT(soft_stats.deffer)              },
	{ "tx_single_coll_ok",      AT_STAT(soft_stats.scc)                 },
	{ "tx_multi_coll_ok",       AT_STAT(soft_stats.mcc)                 },
	{ "tx_underun",             AT_STAT(soft_stats.tx_underun)          },
	{ "tx_trunc",               AT_STAT(soft_stats.tx_trunc)            },
	{ "tx_pause",               AT_STAT(soft_stats.tx_pause)            },
	{ "rx_pause",               AT_STAT(soft_stats.rx_pause)            },
	{ "rx_rrd_ov",              AT_STAT(soft_stats.rx_rrd_ov)           },
	{ "rx_trunc",               AT_STAT(soft_stats.rx_trunc)            }
};
#define AT_STATS_LEN	\
	sizeof(at_gstrings_stats) / sizeof(struct at_stats)
#endif	/* ETHTOOL_GSTATS */

#ifdef	ETHTOOL_GWOL
static void
at_ethtool_gwol(struct at_adapter *adapter, struct ethtool_wolinfo *wol)
{
	wol->supported = 
	        WAKE_UCAST | WAKE_MCAST |
			 WAKE_BCAST | WAKE_MAGIC;

	wol->wolopts = 0;
	if(adapter->wol & AT_WUFC_EX)
		wol->wolopts |= WAKE_UCAST;
	if(adapter->wol & AT_WUFC_MC)
		wol->wolopts |= WAKE_MCAST;
	if(adapter->wol & AT_WUFC_BC)
		wol->wolopts |= WAKE_BCAST;
	if(adapter->wol & AT_WUFC_MAG)
		wol->wolopts |= WAKE_MAGIC;
	return;
	
}
#endif	/* ETHTOOL_GWOL */

#ifdef	ETHTOOL_SWOL
static int
at_ethtool_swol(struct at_adapter *adapter, struct ethtool_wolinfo *wol)
{
	if(wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE))
		return -EOPNOTSUPP;

	adapter->wol = 0;

	if(wol->wolopts & WAKE_UCAST)
		adapter->wol |= AT_WUFC_EX;
	if(wol->wolopts & WAKE_MCAST)
		adapter->wol |= AT_WUFC_MC;
	if(wol->wolopts & WAKE_BCAST)
		adapter->wol |= AT_WUFC_BC;
	if(wol->wolopts & WAKE_MAGIC)
		adapter->wol |= AT_WUFC_MAG;
	

	return 0;
}
#endif	/* ETHTOOL_SWOL */

static int
at_ethtool_sset(struct at_adapter *adapter, struct ethtool_cmd *ecmd)
{
	struct at_hw *hw = &adapter->hw;
	uint16_t phy_data;
	int ret_val = 0;
        uint16_t old_media_type = hw->MediaType;
	
	if(netif_running(adapter->netdev)) {
	    at_down(adapter);
	}
	//michael add 2005-11-17
	DEBUGOUT("enter at_ethtool_sset---michael debug\n");
	if(ecmd->autoneg == AUTONEG_ENABLE) {
	    hw->MediaType = MEDIA_TYPE_AUTO_SENSOR;
	} else {
	    if (ecmd->speed == SPEED_1000) {
		if (ecmd->duplex != DUPLEX_FULL) {
	            printk(KERN_WARNING"can't force to 1000MHalf !\n");
		    ret_val = -EINVAL;
		    goto exit_sset;				
		}
		hw->MediaType = MEDIA_TYPE_1000M_FULL;
	    } else if (ecmd->speed == SPEED_100) {
		if (ecmd->duplex == DUPLEX_FULL) {
		    hw->MediaType = MEDIA_TYPE_100M_FULL;
		} else {
		    hw->MediaType = MEDIA_TYPE_100M_HALF;
		}
	    } else {
		if (ecmd->duplex == DUPLEX_FULL) {
	            hw->MediaType = MEDIA_TYPE_10M_FULL;
		} else {
		    hw->MediaType = MEDIA_TYPE_10M_HALF;
		}
	    }
	}
	switch (hw->MediaType)
	{
	case MEDIA_TYPE_AUTO_SENSOR:
		ecmd->advertising = 
					  ADVERTISED_10baseT_Half |
					  ADVERTISED_10baseT_Full |
					  ADVERTISED_100baseT_Half |
					  ADVERTISED_100baseT_Full |
					  ADVERTISED_1000baseT_Full|
					  ADVERTISED_Autoneg |
					  ADVERTISED_TP;
		break;
	case MEDIA_TYPE_1000M_FULL:
		ecmd->advertising = 
						  ADVERTISED_1000baseT_Full|
						  ADVERTISED_Autoneg |
						  ADVERTISED_TP;
		break;
	default:
		ecmd->advertising = 0;
		break;
	} 

	if(at_phy_setup_autoneg_adv(hw)) {
		ret_val = -EINVAL;
		goto exit_sset;
	}

    if (hw->MediaType == MEDIA_TYPE_AUTO_SENSOR ||
    	hw->MediaType == MEDIA_TYPE_1000M_FULL) {
    	phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN;
    } else {
        switch (hw->MediaType)
    	{
    	case MEDIA_TYPE_100M_FULL:
    		phy_data = MII_CR_FULL_DUPLEX|MII_CR_SPEED_100|MII_CR_RESET;
    		break;
    	case MEDIA_TYPE_100M_HALF:
    		phy_data = MII_CR_SPEED_100|MII_CR_RESET;
    		break;
    	case MEDIA_TYPE_10M_FULL:
    		phy_data = MII_CR_FULL_DUPLEX|MII_CR_SPEED_10|MII_CR_RESET;
    		break;
    	default: // MEDIA_TYPE_10M_HALF:
    		phy_data = MII_CR_SPEED_10|MII_CR_RESET;
    		break;
    	}
    }
    
    at_write_phy_reg(hw, MII_BMCR, phy_data);

exit_sset: 
    if (ret_val) {
        hw->MediaType = old_media_type;
    }
    
    if(netif_running(adapter->netdev)) {
	at_up(adapter);
    } else if (!ret_val) {
	at_reset(adapter);
    }

    return ret_val;
}

static void
at_ethtool_gset(struct at_adapter *adapter, struct ethtool_cmd *ecmd)
{
	struct at_hw *hw = &adapter->hw;


	ecmd->supported = (SUPPORTED_10baseT_Half |
	                   SUPPORTED_10baseT_Full |
	                   SUPPORTED_100baseT_Half |
	                   SUPPORTED_100baseT_Full |
	                   SUPPORTED_1000baseT_Full|
	                   SUPPORTED_Autoneg |
	                   SUPPORTED_TP);

	ecmd->advertising = ADVERTISED_TP;

	if (hw->MediaType == MEDIA_TYPE_AUTO_SENSOR ||
	    hw->MediaType == MEDIA_TYPE_1000M_FULL) {
		ecmd->advertising |= ADVERTISED_Autoneg;
		if (hw->MediaType == MEDIA_TYPE_AUTO_SENSOR) {
			ecmd->advertising |= ADVERTISED_Autoneg;
			
			ecmd->advertising |= 
						(ADVERTISED_10baseT_Half 	|
						 ADVERTISED_10baseT_Full 	|
						 ADVERTISED_100baseT_Half	|
						 ADVERTISED_100baseT_Full	|
						 ADVERTISED_1000baseT_Full  );
		} else {
			ecmd->advertising |= 
						(ADVERTISED_1000baseT_Full);
		}
	}
	ecmd->port = PORT_TP;
	ecmd->phy_address = 0;
	ecmd->transceiver = XCVR_INTERNAL;

	if(netif_carrier_ok(adapter->netdev)) 
	{
        uint16_t link_speed, link_duplex;
        
		at_get_speed_and_duplex(hw, &link_speed, &link_duplex);
		ecmd->speed = link_speed;
		if(link_duplex == FULL_DUPLEX)
			ecmd->duplex = DUPLEX_FULL;
		else
			ecmd->duplex = DUPLEX_HALF;
	} else {
		ecmd->speed = -1;
		ecmd->duplex = -1;
	}

	if (hw->MediaType == MEDIA_TYPE_AUTO_SENSOR ||
	    hw->MediaType == MEDIA_TYPE_1000M_FULL) {
		ecmd->autoneg = AUTONEG_ENABLE;
	} else {
		ecmd->autoneg = AUTONEG_DISABLE;
	}
}


#ifdef	ETHTOOL_GDRVINFO
static void
at_ethtool_gdrvinfo(struct at_adapter *adapter,
                       struct ethtool_drvinfo *drvinfo)
{
	strncpy(drvinfo->driver,  at_driver_name, 32);
	strncpy(drvinfo->version, at_driver_version, 32);
	strncpy(drvinfo->fw_version, "N/A", 32);
	strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
#ifdef  ETHTOOL_GEEPROM
	drvinfo->eedump_len = 48;
#endif//ETHTOOL_GEEPROM	
}
#endif	/* ETHTOOL_GDRVINFO */

#ifdef	ETHTOOL_GRINGPARAM
static int
at_ethtool_gring(struct at_adapter *adapter,
                    struct ethtool_ringparam *ring)
{
	struct at_tpd_ring *txdr = &adapter->tpd_ring;
	struct at_rfd_ring *rxdr = &adapter->rfd_ring;

	ring->rx_max_pending = 2048;
	ring->tx_max_pending = 1024;
	ring->rx_mini_max_pending = 0;
	ring->rx_jumbo_max_pending = 0;
	ring->rx_pending = rxdr->count;
	ring->tx_pending = txdr->count;
	ring->rx_mini_pending = 0;
	ring->rx_jumbo_pending = 0;

	return 0;
}
#endif /* ETHTOOL_GRINGPARAM */
#ifdef	ETHTOOL_SRINGPARAM
static int 
at_ethtool_sring(struct at_adapter *adapter,
                 struct ethtool_ringparam *ring)
{
	int err;
	struct at_tpd_ring *tpdr = &adapter->tpd_ring;
	struct at_rrd_ring *rrdr = &adapter->rrd_ring;
	struct at_rfd_ring *rfdr = &adapter->rfd_ring;
	
	struct at_tpd_ring tpd_old, tpd_new;
	struct at_rfd_ring rfd_old, rfd_new;
	struct at_rrd_ring rrd_old , rrd_new;


	tpd_old = adapter->tpd_ring;
	rfd_old = adapter->rfd_ring;
	rrd_old = adapter->rrd_ring;
	
	if(netif_running(adapter->netdev))
		at_down(adapter);

	rfdr->count = (uint16_t)max(ring->rx_pending, (uint32_t)32);
	rfdr->count = rfdr->count>2048 ? 2048 : rfdr->count;
	rfdr->count = (rfdr->count+3)&~3;
	rrdr->count = rfdr->count;
	
	tpdr->count = (uint16_t)max(ring->tx_pending, (uint32_t)16);
	tpdr->count = tpdr->count>1024 ? 1024 : tpdr->count;
	tpdr->count = (tpdr->count+3)&~3;

	if(netif_running(adapter->netdev)) {
		/* try to get new resources before deleting old */
	    if ((err = at_setup_ring_resources(adapter)))
	        goto err_setup_ring;	
	
		
		/* save the new, restore the old in order to free it,
		 * then restore the new back again */	
	
		rfd_new = adapter->rfd_ring;
		rrd_new = adapter->rrd_ring;
		tpd_new = adapter->tpd_ring;

⌨️ 快捷键说明

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