From a2b108e09c7a31ee423e32c525e0b3eb926d123c Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Wed, 6 Feb 2002 16:01:35 -0500 Subject: [PATCH] Add support for basic ethtool ioctls to 3com net drivers, 3c501, 3c503, 3c505, 3c507, 3c509, 3c515, 3c523, 3c527. --- drivers/net/3c501.c | 91 +++++++++++++++++++++++++++++++++++++++++- drivers/net/3c503.c | 77 +++++++++++++++++++++++++++++++++++- drivers/net/3c505.c | 95 +++++++++++++++++++++++++++++++++++++++++++- drivers/net/3c507.c | 95 +++++++++++++++++++++++++++++++++++++++++++- drivers/net/3c509.c | 92 ++++++++++++++++++++++++++++++++++++++++++- drivers/net/3c515.c | 96 ++++++++++++++++++++++++++++++++++++++++++++- drivers/net/3c523.c | 75 ++++++++++++++++++++++++++++++++++- drivers/net/3c527.c | 94 ++++++++++++++++++++++++++++++++++++++++++-- 8 files changed, 704 insertions(+), 11 deletions(-) diff --git a/drivers/net/3c501.c b/drivers/net/3c501.c index 13a272d5f7e8..74f82b397b05 100644 --- a/drivers/net/3c501.c +++ b/drivers/net/3c501.c @@ -87,8 +87,12 @@ * */ +#define DRV_NAME "3c501" +#define DRV_VERSION "2001/11/17" + + static const char version[] = - "3c501.c: 2000/02/08 Alan Cox (alan@redhat.com).\n"; + DRV_NAME ".c: " DRV_VERSION " Alan Cox (alan@redhat.com).\n"; /* * Braindamage remaining: @@ -108,7 +112,9 @@ static const char version[] = #include #include /* for CONFIG_IP_MULTICAST */ #include +#include +#include #include #include @@ -139,12 +145,14 @@ static void el_reset(struct net_device *dev); static int el1_close(struct net_device *dev); static struct net_device_stats *el1_get_stats(struct net_device *dev); static void set_multicast_list(struct net_device *dev); +static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); #define EL1_IO_EXTENT 16 #ifndef EL_DEBUG #define EL_DEBUG 0 /* use 0 for production, 1 for devel., >2 for debug */ #endif /* Anything above 5 is wordy death! */ +#define debug el_debug static int el_debug = EL_DEBUG; /* @@ -377,6 +385,7 @@ static int __init el1_probe1(struct net_device *dev, int ioaddr) dev->stop = &el1_close; dev->get_stats = &el1_get_stats; dev->set_multicast_list = &set_multicast_list; + dev->do_ioctl = netdev_ioctl; /* * Setup the generic properties @@ -915,6 +924,86 @@ static void set_multicast_list(struct net_device *dev) } } +/** + * netdev_ethtool_ioctl: Handle network interface SIOCETHTOOL ioctls + * @dev: network interface on which out-of-band action is to be performed + * @useraddr: userspace address to which data is to be read and returned + * + * Process the various commands of the SIOCETHTOOL interface. + */ + +static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr) +{ + u32 ethcmd; + + /* dev_ioctl() in ../../net/core/dev.c has already checked + capable(CAP_NET_ADMIN), so don't bother with that here. */ + + 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); + sprintf(info.bus_info, "ISA 0x%lx", dev->base_addr); + if (copy_to_user (useraddr, &info, sizeof (info))) + 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; +} + +/** + * netdev_ioctl: Handle network interface ioctls + * @dev: network interface on which out-of-band action is to be performed + * @rq: user request data + * @cmd: command issued by user + * + * Process the various out-of-band ioctls passed to this driver. + */ + +static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) +{ + int rc = 0; + + switch (cmd) { + case SIOCETHTOOL: + rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data); + break; + + default: + rc = -EOPNOTSUPP; + break; + } + + return rc; +} + #ifdef MODULE static struct net_device dev_3c501 = { diff --git a/drivers/net/3c503.c b/drivers/net/3c503.c index c1768a1d078a..b0967446175d 100644 --- a/drivers/net/3c503.c +++ b/drivers/net/3c503.c @@ -29,11 +29,17 @@ Paul Gortmaker : add support for the 2nd 8kB of RAM on 16 bit cards. Paul Gortmaker : multiple card support for module users. rjohnson@analogic.com : Fix up PIO interface for efficient operation. + Jeff Garzik : ethtool support */ +#define DRV_NAME "3c503" +#define DRV_VERSION "1.10a" +#define DRV_RELDATE "11/17/2001" + + static const char version[] = - "3c503.c:v1.10 9/23/93 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n"; + DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " Donald Becker (becker@scyld.com)\n"; #include @@ -45,7 +51,9 @@ static const char version[] = #include #include #include +#include +#include #include #include #include @@ -74,6 +82,7 @@ static void el2_block_input(struct net_device *dev, int count, struct sk_buff *s int ring_offset); static void el2_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page); +static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); /* This routine probes for a memory-mapped 3c503 board by looking for @@ -301,6 +310,7 @@ el2_probe1(struct net_device *dev, int ioaddr) dev->open = &el2_open; dev->stop = &el2_close; + dev->do_ioctl = &netdev_ioctl; if (dev->mem_start) printk("%s: %s - %dkB RAM, 8kB shared mem window at %#6lx-%#6lx.\n", @@ -607,6 +617,71 @@ el2_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring outb_p(ei_status.interface_num == 0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL); return; } + +/** + * netdev_ethtool_ioctl: Handle network interface SIOCETHTOOL ioctls + * @dev: network interface on which out-of-band action is to be performed + * @useraddr: userspace address to which data is to be read and returned + * + * Process the various commands of the SIOCETHTOOL interface. + */ + +static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr) +{ + u32 ethcmd; + + /* dev_ioctl() in ../../net/core/dev.c has already checked + capable(CAP_NET_ADMIN), so don't bother with that here. */ + + 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); + sprintf(info.bus_info, "ISA 0x%lx", dev->base_addr); + if (copy_to_user (useraddr, &info, sizeof (info))) + return -EFAULT; + return 0; + } + + default: + break; + } + + return -EOPNOTSUPP; +} + +/** + * netdev_ioctl: Handle network interface ioctls + * @dev: network interface on which out-of-band action is to be performed + * @rq: user request data + * @cmd: command issued by user + * + * Process the various out-of-band ioctls passed to this driver. + */ + +static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) +{ + int rc = 0; + + switch (cmd) { + case SIOCETHTOOL: + rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data); + break; + + default: + rc = -EOPNOTSUPP; + break; + } + + return rc; +} + + #ifdef MODULE #define MAX_EL2_CARDS 4 /* Max number of EL2 cards per module */ diff --git a/drivers/net/3c505.c b/drivers/net/3c505.c index 7f91256e65ab..f4549150cdf7 100644 --- a/drivers/net/3c505.c +++ b/drivers/net/3c505.c @@ -35,8 +35,13 @@ * Philip Blundell * Multicard/soft configurable dma channel/rev 2 hardware support * by Christopher Collins + * Ethtool support (jgarzik), 11/17/2001 */ +#define DRV_NAME "3c505" +#define DRV_VERSION "1.10a" + + /* Theory of operation: * * The 3c505 is quite an intelligent board. All communication with it is done @@ -103,6 +108,9 @@ #include #include #include +#include + +#include #include #include #include @@ -148,10 +156,11 @@ static char couldnot_msg[] __initdata = "%s: 3c505 not found\n"; *********************************************************/ #ifdef ELP_DEBUG -static const int elp_debug = ELP_DEBUG; +static int elp_debug = ELP_DEBUG; #else -static const int elp_debug; +static int elp_debug; #endif +#define debug elp_debug /* * 0 = no messages (well, some) @@ -1260,6 +1269,87 @@ static void elp_set_mc_list(struct net_device *dev) } } +/** + * netdev_ethtool_ioctl: Handle network interface SIOCETHTOOL ioctls + * @dev: network interface on which out-of-band action is to be performed + * @useraddr: userspace address to which data is to be read and returned + * + * Process the various commands of the SIOCETHTOOL interface. + */ + +static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr) +{ + u32 ethcmd; + + /* dev_ioctl() in ../../net/core/dev.c has already checked + capable(CAP_NET_ADMIN), so don't bother with that here. */ + + 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); + sprintf(info.bus_info, "ISA 0x%lx", dev->base_addr); + if (copy_to_user (useraddr, &info, sizeof (info))) + 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; +} + +/** + * netdev_ioctl: Handle network interface ioctls + * @dev: network interface on which out-of-band action is to be performed + * @rq: user request data + * @cmd: command issued by user + * + * Process the various out-of-band ioctls passed to this driver. + */ + +static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) +{ + int rc = 0; + + switch (cmd) { + case SIOCETHTOOL: + rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data); + break; + + default: + rc = -EOPNOTSUPP; + break; + } + + return rc; +} + + /****************************************************** * * initialise Etherlink Plus board @@ -1280,6 +1370,7 @@ static inline void elp_init(struct net_device *dev) dev->tx_timeout = elp_timeout; /* local */ dev->watchdog_timeo = 10*HZ; dev->set_multicast_list = elp_set_mc_list; /* local */ + dev->do_ioctl = netdev_ioctl; /* local */ /* Setup the generic properties */ ether_setup(dev); diff --git a/drivers/net/3c507.c b/drivers/net/3c507.c index df46dbbebfd5..3de089075730 100644 --- a/drivers/net/3c507.c +++ b/drivers/net/3c507.c @@ -25,8 +25,12 @@ The statistics need to be updated correctly. */ +#define DRV_NAME "3c507" +#define DRV_VERSION "1.10a" +#define DRV_RELDATE "11/17/2001" + static const char version[] = - "3c507.c:v1.10 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n"; + DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " Donald Becker (becker@scyld.com)\n"; #include @@ -52,6 +56,9 @@ static const char version[] = #include #include #include +#include + +#include #include #include #include @@ -70,6 +77,8 @@ static const char version[] = #define NET_DEBUG 1 #endif static unsigned int net_debug = NET_DEBUG; +#define debug net_debug + /* A zero-terminated list of common I/O addresses to be probed. */ static unsigned int netcard_portlist[] __initdata = @@ -296,6 +305,7 @@ static void el16_tx_timeout (struct net_device *dev); static void hardware_send_packet(struct net_device *dev, void *buf, short length); static void init_82586_mem(struct net_device *dev); +static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); /* Check for a network adaptor of this type, and return '0' iff one exists. @@ -427,6 +437,7 @@ static int __init el16_probe1(struct net_device *dev, int ioaddr) dev->get_stats = el16_get_stats; dev->tx_timeout = el16_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; + dev->do_ioctl = netdev_ioctl; ether_setup(dev); /* Generic ethernet behaviour */ @@ -864,6 +875,88 @@ static void el16_rx(struct net_device *dev) lp->rx_head = rx_head; lp->rx_tail = rx_tail; } + +/** + * netdev_ethtool_ioctl: Handle network interface SIOCETHTOOL ioctls + * @dev: network interface on which out-of-band action is to be performed + * @useraddr: userspace address to which data is to be read and returned + * + * Process the various commands of the SIOCETHTOOL interface. + */ + +static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr) +{ + u32 ethcmd; + + /* dev_ioctl() in ../../net/core/dev.c has already checked + capable(CAP_NET_ADMIN), so don't bother with that here. */ + + 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); + sprintf(info.bus_info, "ISA 0x%lx", dev->base_addr); + if (copy_to_user (useraddr, &info, sizeof (info))) + 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; +} + +/** + * netdev_ioctl: Handle network interface ioctls + * @dev: network interface on which out-of-band action is to be performed + * @rq: user request data + * @cmd: command issued by user + * + * Process the various out-of-band ioctls passed to this driver. + */ + +static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) +{ + int rc = 0; + + switch (cmd) { + case SIOCETHTOOL: + rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data); + break; + + default: + rc = -EOPNOTSUPP; + break; + } + + return rc; +} + + #ifdef MODULE static struct net_device dev_3c507; static int io = 0x300; diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c index e6eddb3f0459..4f5c959c5f12 100644 --- a/drivers/net/3c509.c +++ b/drivers/net/3c509.c @@ -43,8 +43,14 @@ v1.18 12Mar2001 Andrew Morton - Avoid bogus detect of 3c590's (Andrzej Krzysztofowicz) - Reviewed against 1.18 from scyld.com + v1.18 17Nov2001 Jeff Garzik + - ethtool support */ +#define DRV_NAME "3c509" +#define DRV_VERSION "1.18a" +#define DRV_RELDATE "17Nov2001" + /* A few values that may be tweaked. */ /* Time in jiffies before concluding the transmitter is hung. */ @@ -70,12 +76,14 @@ static int max_interrupt_work = 10; #include #include /* for udelay() */ #include +#include +#include #include #include #include -static char versionA[] __initdata = "3c509.c:1.18 12Mar2001 becker@scyld.com\n"; +static char versionA[] __initdata = DRV_NAME ".c:" DRV_VERSION " " DRV_RELDATE "becker@scyld.com\n"; static char versionB[] __initdata = "http://www.scyld.com/network/3c509.html\n"; #ifdef EL3_DEBUG @@ -84,6 +92,7 @@ static int el3_debug = EL3_DEBUG; static int el3_debug = 2; #endif + /* To minimize the size of the driver source I only define operating constants if they are used several times. You'll need the manual anyway if you want to understand driver details. */ @@ -158,6 +167,7 @@ static int el3_rx(struct net_device *dev); static int el3_close(struct net_device *dev); static void set_multicast_list(struct net_device *dev); static void el3_tx_timeout (struct net_device *dev); +static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); #ifdef CONFIG_MCA struct el3_mca_adapters_struct { @@ -513,6 +523,7 @@ no_pnp: dev->set_multicast_list = &set_multicast_list; dev->tx_timeout = el3_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; + dev->do_ioctl = netdev_ioctl; /* Fill in the generic fields of the device structure. */ ether_setup(dev); @@ -1003,6 +1014,85 @@ el3_close(struct net_device *dev) return 0; } +/** + * netdev_ethtool_ioctl: Handle network interface SIOCETHTOOL ioctls + * @dev: network interface on which out-of-band action is to be performed + * @useraddr: userspace address to which data is to be read and returned + * + * Process the various commands of the SIOCETHTOOL interface. + */ + +static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr) +{ + u32 ethcmd; + + /* dev_ioctl() in ../../net/core/dev.c has already checked + capable(CAP_NET_ADMIN), so don't bother with that here. */ + + 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); + if (copy_to_user (useraddr, &info, sizeof (info))) + return -EFAULT; + return 0; + } + + /* get message-level */ + case ETHTOOL_GMSGLVL: { + struct ethtool_value edata = {ETHTOOL_GMSGLVL}; + edata.data = el3_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; + el3_debug = edata.data; + return 0; + } + + default: + break; + } + + return -EOPNOTSUPP; +} + +/** + * netdev_ioctl: Handle network interface ioctls + * @dev: network interface on which out-of-band action is to be performed + * @rq: user request data + * @cmd: command issued by user + * + * Process the various out-of-band ioctls passed to this driver. + */ + +static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) +{ + int rc = 0; + + switch (cmd) { + case SIOCETHTOOL: + rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data); + break; + + default: + rc = -EOPNOTSUPP; + break; + } + + return rc; +} + #ifdef MODULE /* Parameters that may be passed into the module. */ static int debug = -1; diff --git a/drivers/net/3c515.c b/drivers/net/3c515.c index de2013540e2d..d1f48335d2d7 100644 --- a/drivers/net/3c515.c +++ b/drivers/net/3c515.c @@ -16,9 +16,17 @@ 2/2/00- Added support for kernel-level ISAPnP by Stephen Frost and Alessandro Zummo Cleaned up for 2.3.x/softnet by Jeff Garzik and Alan Cox. + + 11/17/2001 - Added ethtool support (jgarzik) + */ -static char *version = "3c515.c:v0.99-sn 2000/02/12 becker@cesdis.gsfc.nasa.gov and others\n"; +#define DRV_NAME "3c515" +#define DRV_VERSION "0.99t" +#define DRV_RELDATE "17-Nov-2001" + +static char *version = +DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " becker@scyld.com and others\n"; #define CORKSCREW 1 @@ -63,6 +71,9 @@ static int max_interrupt_work = 20; #include #include #include +#include + +#include #include #include #include @@ -393,6 +404,7 @@ static int corkscrew_close(struct net_device *dev); static void update_stats(int addr, struct net_device *dev); static struct net_device_stats *corkscrew_get_stats(struct net_device *dev); static void set_rx_mode(struct net_device *dev); +static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); /* @@ -721,6 +733,7 @@ static int corkscrew_probe1(struct net_device *dev) dev->stop = &corkscrew_close; dev->get_stats = &corkscrew_get_stats; dev->set_multicast_list = &set_rx_mode; + dev->do_ioctl = netdev_ioctl; return 0; } @@ -1591,6 +1604,87 @@ static void set_rx_mode(struct net_device *dev) outw(new_mode, ioaddr + EL3_CMD); } + +/** + * netdev_ethtool_ioctl: Handle network interface SIOCETHTOOL ioctls + * @dev: network interface on which out-of-band action is to be performed + * @useraddr: userspace address to which data is to be read and returned + * + * Process the various commands of the SIOCETHTOOL interface. + */ + +static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr) +{ + u32 ethcmd; + + /* dev_ioctl() in ../../net/core/dev.c has already checked + capable(CAP_NET_ADMIN), so don't bother with that here. */ + + 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); + sprintf(info.bus_info, "ISA 0x%lx", dev->base_addr); + if (copy_to_user (useraddr, &info, sizeof (info))) + return -EFAULT; + return 0; + } + + /* get message-level */ + case ETHTOOL_GMSGLVL: { + struct ethtool_value edata = {ETHTOOL_GMSGLVL}; + edata.data = corkscrew_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; + corkscrew_debug = edata.data; + return 0; + } + + default: + break; + } + + return -EOPNOTSUPP; +} + +/** + * netdev_ioctl: Handle network interface ioctls + * @dev: network interface on which out-of-band action is to be performed + * @rq: user request data + * @cmd: command issued by user + * + * Process the various out-of-band ioctls passed to this driver. + */ + +static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) +{ + int rc = 0; + + switch (cmd) { + case SIOCETHTOOL: + rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data); + break; + + default: + rc = -EOPNOTSUPP; + break; + } + + return rc; +} + #ifdef MODULE void cleanup_module(void) diff --git a/drivers/net/3c523.c b/drivers/net/3c523.c index 64d559cf253e..47f958104c9c 100644 --- a/drivers/net/3c523.c +++ b/drivers/net/3c523.c @@ -81,10 +81,15 @@ added option to disable multicast as is causes problems Ganesh Sittampalam Stuart Adamson + Nov 2001 + added support for ethtool (jgarzik) $Header: /fsys2/home/chrisb/linux-1.3.59-MCA/drivers/net/RCS/3c523.c,v 1.1 1996/02/05 01:53:46 chrisb Exp chrisb $ */ +#define DRV_NAME "3c523" +#define DRV_VERSION "17-Nov-2001" + #include #include #include @@ -95,6 +100,9 @@ #include #include #include +#include + +#include #include #include #include @@ -182,6 +190,7 @@ static void elmc_timeout(struct net_device *dev); #ifdef ELMC_MULTICAST static void set_multicast_list(struct net_device *dev); #endif +static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); /* helper-functions */ static int init586(struct net_device *dev); @@ -563,7 +572,8 @@ int __init elmc_probe(struct net_device *dev) #else dev->set_multicast_list = NULL; #endif - + dev->do_ioctl = netdev_ioctl; + ether_setup(dev); /* note that we haven't actually requested the IRQ from the kernel. @@ -1214,6 +1224,69 @@ static void set_multicast_list(struct net_device *dev) } #endif +/** + * netdev_ethtool_ioctl: Handle network interface SIOCETHTOOL ioctls + * @dev: network interface on which out-of-band action is to be performed + * @useraddr: userspace address to which data is to be read and returned + * + * Process the various commands of the SIOCETHTOOL interface. + */ + +static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr) +{ + u32 ethcmd; + + /* dev_ioctl() in ../../net/core/dev.c has already checked + capable(CAP_NET_ADMIN), so don't bother with that here. */ + + 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); + sprintf(info.bus_info, "MCA 0x%lx", dev->base_addr); + if (copy_to_user (useraddr, &info, sizeof (info))) + return -EFAULT; + return 0; + } + + default: + break; + } + + return -EOPNOTSUPP; +} + +/** + * netdev_ioctl: Handle network interface ioctls + * @dev: network interface on which out-of-band action is to be performed + * @rq: user request data + * @cmd: command issued by user + * + * Process the various out-of-band ioctls passed to this driver. + */ + +static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) +{ + int rc = 0; + + switch (cmd) { + case SIOCETHTOOL: + rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data); + break; + + default: + rc = -EOPNOTSUPP; + break; + } + + return rc; +} + /*************************************************************************/ #ifdef MODULE diff --git a/drivers/net/3c527.c b/drivers/net/3c527.c index 7aa8c837e645..4f64f79e0006 100644 --- a/drivers/net/3c527.c +++ b/drivers/net/3c527.c @@ -16,8 +16,12 @@ * */ +#define DRV_NAME "3c527" +#define DRV_VERSION "0.6a" +#define DRV_RELDATE "2001/11/17" + static const char *version = - "3c527.c:v0.6 2001/03/03 Richard Proctor (rnp@netlink.co.nz)\n"; +DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " Richard Proctor (rnp@netlink.co.nz)\n"; /** * DOC: Traps for the unwary @@ -90,6 +94,9 @@ static const char *version = #include #include #include +#include + +#include #include #include #include @@ -108,7 +115,7 @@ static const char *version = * The name of the card. Is used for messages and in the requests for * io regions, irqs and dma channels */ -static const char* cardname = "3c527"; +static const char* cardname = DRV_NAME; /* use 0 for production, 1 for verification, >2 for debug */ #ifndef NET_DEBUG @@ -213,6 +220,7 @@ static int mc32_close(struct net_device *dev); static struct net_device_stats *mc32_get_stats(struct net_device *dev); static void mc32_set_multicast_list(struct net_device *dev); static void mc32_reset_multicast_list(struct net_device *dev); +static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); /** * mc32_probe - Search for supported boards @@ -502,7 +510,7 @@ static int __init mc32_probe1(struct net_device *dev, int slot) dev->set_multicast_list = mc32_set_multicast_list; dev->tx_timeout = mc32_timeout; dev->watchdog_timeo = HZ*5; /* Board does all the work */ - + dev->do_ioctl = netdev_ioctl; lp->xceiver_state = HALTED; @@ -1644,6 +1652,86 @@ static void mc32_reset_multicast_list(struct net_device *dev) do_mc32_set_multicast_list(dev,1); } +/** + * netdev_ethtool_ioctl: Handle network interface SIOCETHTOOL ioctls + * @dev: network interface on which out-of-band action is to be performed + * @useraddr: userspace address to which data is to be read and returned + * + * Process the various commands of the SIOCETHTOOL interface. + */ + +static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr) +{ + u32 ethcmd; + + /* dev_ioctl() in ../../net/core/dev.c has already checked + capable(CAP_NET_ADMIN), so don't bother with that here. */ + + 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); + sprintf(info.bus_info, "MCA 0x%lx", dev->base_addr); + if (copy_to_user (useraddr, &info, sizeof (info))) + return -EFAULT; + return 0; + } + + /* get message-level */ + case ETHTOOL_GMSGLVL: { + struct ethtool_value edata = {ETHTOOL_GMSGLVL}; + edata.data = mc32_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; + mc32_debug = edata.data; + return 0; + } + + default: + break; + } + + return -EOPNOTSUPP; +} + +/** + * netdev_ioctl: Handle network interface ioctls + * @dev: network interface on which out-of-band action is to be performed + * @rq: user request data + * @cmd: command issued by user + * + * Process the various out-of-band ioctls passed to this driver. + */ + +static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) +{ + int rc = 0; + + switch (cmd) { + case SIOCETHTOOL: + rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data); + break; + + default: + rc = -EOPNOTSUPP; + break; + } + + return rc; +} + #ifdef MODULE static struct net_device this_device; -- 2.39.5