Commit a2b108e0 authored by Jeff Garzik's avatar Jeff Garzik

Add support for basic ethtool ioctls to 3com net drivers,

3c501, 3c503, 3c505, 3c507, 3c509, 3c515, 3c523, 3c527.
parent a97c3b80
...@@ -87,8 +87,12 @@ ...@@ -87,8 +87,12 @@
* *
*/ */
#define DRV_NAME "3c501"
#define DRV_VERSION "2001/11/17"
static const char version[] = 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: * Braindamage remaining:
...@@ -108,7 +112,9 @@ static const char version[] = ...@@ -108,7 +112,9 @@ static const char version[] =
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/config.h> /* for CONFIG_IP_MULTICAST */ #include <linux/config.h> /* for CONFIG_IP_MULTICAST */
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/ethtool.h>
#include <asm/uaccess.h>
#include <asm/bitops.h> #include <asm/bitops.h>
#include <asm/io.h> #include <asm/io.h>
...@@ -139,12 +145,14 @@ static void el_reset(struct net_device *dev); ...@@ -139,12 +145,14 @@ static void el_reset(struct net_device *dev);
static int el1_close(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 struct net_device_stats *el1_get_stats(struct net_device *dev);
static void set_multicast_list(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 #define EL1_IO_EXTENT 16
#ifndef EL_DEBUG #ifndef EL_DEBUG
#define EL_DEBUG 0 /* use 0 for production, 1 for devel., >2 for debug */ #define EL_DEBUG 0 /* use 0 for production, 1 for devel., >2 for debug */
#endif /* Anything above 5 is wordy death! */ #endif /* Anything above 5 is wordy death! */
#define debug el_debug
static int el_debug = EL_DEBUG; static int el_debug = EL_DEBUG;
/* /*
...@@ -377,6 +385,7 @@ static int __init el1_probe1(struct net_device *dev, int ioaddr) ...@@ -377,6 +385,7 @@ static int __init el1_probe1(struct net_device *dev, int ioaddr)
dev->stop = &el1_close; dev->stop = &el1_close;
dev->get_stats = &el1_get_stats; dev->get_stats = &el1_get_stats;
dev->set_multicast_list = &set_multicast_list; dev->set_multicast_list = &set_multicast_list;
dev->do_ioctl = netdev_ioctl;
/* /*
* Setup the generic properties * Setup the generic properties
...@@ -915,6 +924,86 @@ static void set_multicast_list(struct net_device *dev) ...@@ -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 #ifdef MODULE
static struct net_device dev_3c501 = { static struct net_device dev_3c501 = {
......
...@@ -29,11 +29,17 @@ ...@@ -29,11 +29,17 @@
Paul Gortmaker : add support for the 2nd 8kB of RAM on 16 bit cards. Paul Gortmaker : add support for the 2nd 8kB of RAM on 16 bit cards.
Paul Gortmaker : multiple card support for module users. Paul Gortmaker : multiple card support for module users.
rjohnson@analogic.com : Fix up PIO interface for efficient operation. 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[] = 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 <linux/module.h> #include <linux/module.h>
...@@ -45,7 +51,9 @@ static const char version[] = ...@@ -45,7 +51,9 @@ static const char version[] =
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/ethtool.h>
#include <asm/uaccess.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
...@@ -74,6 +82,7 @@ static void el2_block_input(struct net_device *dev, int count, struct sk_buff *s ...@@ -74,6 +82,7 @@ static void el2_block_input(struct net_device *dev, int count, struct sk_buff *s
int ring_offset); int ring_offset);
static void el2_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, static void el2_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
int ring_page); 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 /* This routine probes for a memory-mapped 3c503 board by looking for
...@@ -301,6 +310,7 @@ el2_probe1(struct net_device *dev, int ioaddr) ...@@ -301,6 +310,7 @@ el2_probe1(struct net_device *dev, int ioaddr)
dev->open = &el2_open; dev->open = &el2_open;
dev->stop = &el2_close; dev->stop = &el2_close;
dev->do_ioctl = &netdev_ioctl;
if (dev->mem_start) if (dev->mem_start)
printk("%s: %s - %dkB RAM, 8kB shared mem window at %#6lx-%#6lx.\n", 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 ...@@ -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); outb_p(ei_status.interface_num == 0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL);
return; 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 #ifdef MODULE
#define MAX_EL2_CARDS 4 /* Max number of EL2 cards per module */ #define MAX_EL2_CARDS 4 /* Max number of EL2 cards per module */
......
...@@ -35,8 +35,13 @@ ...@@ -35,8 +35,13 @@
* Philip Blundell <Philip.Blundell@pobox.com> * Philip Blundell <Philip.Blundell@pobox.com>
* Multicard/soft configurable dma channel/rev 2 hardware support * Multicard/soft configurable dma channel/rev 2 hardware support
* by Christopher Collins <ccollins@pcug.org.au> * by Christopher Collins <ccollins@pcug.org.au>
* Ethtool support (jgarzik), 11/17/2001
*/ */
#define DRV_NAME "3c505"
#define DRV_VERSION "1.10a"
/* Theory of operation: /* Theory of operation:
* *
* The 3c505 is quite an intelligent board. All communication with it is done * The 3c505 is quite an intelligent board. All communication with it is done
...@@ -103,6 +108,9 @@ ...@@ -103,6 +108,9 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/ethtool.h>
#include <asm/uaccess.h>
#include <asm/bitops.h> #include <asm/bitops.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/dma.h> #include <asm/dma.h>
...@@ -148,10 +156,11 @@ static char couldnot_msg[] __initdata = "%s: 3c505 not found\n"; ...@@ -148,10 +156,11 @@ static char couldnot_msg[] __initdata = "%s: 3c505 not found\n";
*********************************************************/ *********************************************************/
#ifdef ELP_DEBUG #ifdef ELP_DEBUG
static const int elp_debug = ELP_DEBUG; static int elp_debug = ELP_DEBUG;
#else #else
static const int elp_debug; static int elp_debug;
#endif #endif
#define debug elp_debug
/* /*
* 0 = no messages (well, some) * 0 = no messages (well, some)
...@@ -1260,6 +1269,87 @@ static void elp_set_mc_list(struct net_device *dev) ...@@ -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 * initialise Etherlink Plus board
...@@ -1280,6 +1370,7 @@ static inline void elp_init(struct net_device *dev) ...@@ -1280,6 +1370,7 @@ static inline void elp_init(struct net_device *dev)
dev->tx_timeout = elp_timeout; /* local */ dev->tx_timeout = elp_timeout; /* local */
dev->watchdog_timeo = 10*HZ; dev->watchdog_timeo = 10*HZ;
dev->set_multicast_list = elp_set_mc_list; /* local */ dev->set_multicast_list = elp_set_mc_list; /* local */
dev->do_ioctl = netdev_ioctl; /* local */
/* Setup the generic properties */ /* Setup the generic properties */
ether_setup(dev); ether_setup(dev);
......
...@@ -25,8 +25,12 @@ ...@@ -25,8 +25,12 @@
The statistics need to be updated correctly. 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[] = 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 <linux/module.h> #include <linux/module.h>
...@@ -52,6 +56,9 @@ static const char version[] = ...@@ -52,6 +56,9 @@ static const char version[] =
#include <linux/in.h> #include <linux/in.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/ethtool.h>
#include <asm/uaccess.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/bitops.h> #include <asm/bitops.h>
#include <asm/io.h> #include <asm/io.h>
...@@ -70,6 +77,8 @@ static const char version[] = ...@@ -70,6 +77,8 @@ static const char version[] =
#define NET_DEBUG 1 #define NET_DEBUG 1
#endif #endif
static unsigned int net_debug = NET_DEBUG; static unsigned int net_debug = NET_DEBUG;
#define debug net_debug
/* A zero-terminated list of common I/O addresses to be probed. */ /* A zero-terminated list of common I/O addresses to be probed. */
static unsigned int netcard_portlist[] __initdata = static unsigned int netcard_portlist[] __initdata =
...@@ -296,6 +305,7 @@ static void el16_tx_timeout (struct net_device *dev); ...@@ -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 hardware_send_packet(struct net_device *dev, void *buf, short length);
static void init_82586_mem(struct net_device *dev); 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. /* 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) ...@@ -427,6 +437,7 @@ static int __init el16_probe1(struct net_device *dev, int ioaddr)
dev->get_stats = el16_get_stats; dev->get_stats = el16_get_stats;
dev->tx_timeout = el16_tx_timeout; dev->tx_timeout = el16_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT; dev->watchdog_timeo = TX_TIMEOUT;
dev->do_ioctl = netdev_ioctl;
ether_setup(dev); /* Generic ethernet behaviour */ ether_setup(dev); /* Generic ethernet behaviour */
...@@ -864,6 +875,88 @@ static void el16_rx(struct net_device *dev) ...@@ -864,6 +875,88 @@ static void el16_rx(struct net_device *dev)
lp->rx_head = rx_head; lp->rx_head = rx_head;
lp->rx_tail = rx_tail; 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 #ifdef MODULE
static struct net_device dev_3c507; static struct net_device dev_3c507;
static int io = 0x300; static int io = 0x300;
......
...@@ -43,8 +43,14 @@ ...@@ -43,8 +43,14 @@
v1.18 12Mar2001 Andrew Morton <andrewm@uow.edu.au> v1.18 12Mar2001 Andrew Morton <andrewm@uow.edu.au>
- Avoid bogus detect of 3c590's (Andrzej Krzysztofowicz) - Avoid bogus detect of 3c590's (Andrzej Krzysztofowicz)
- Reviewed against 1.18 from scyld.com - Reviewed against 1.18 from scyld.com
v1.18 17Nov2001 Jeff Garzik <jgarzik@mandrakesoft.com>
- ethtool support
*/ */
#define DRV_NAME "3c509"
#define DRV_VERSION "1.18a"
#define DRV_RELDATE "17Nov2001"
/* A few values that may be tweaked. */ /* A few values that may be tweaked. */
/* Time in jiffies before concluding the transmitter is hung. */ /* Time in jiffies before concluding the transmitter is hung. */
...@@ -70,12 +76,14 @@ static int max_interrupt_work = 10; ...@@ -70,12 +76,14 @@ static int max_interrupt_work = 10;
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/delay.h> /* for udelay() */ #include <linux/delay.h> /* for udelay() */
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/ethtool.h>
#include <asm/uaccess.h>
#include <asm/bitops.h> #include <asm/bitops.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/irq.h> #include <asm/irq.h>
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"; static char versionB[] __initdata = "http://www.scyld.com/network/3c509.html\n";
#ifdef EL3_DEBUG #ifdef EL3_DEBUG
...@@ -84,6 +92,7 @@ static int el3_debug = EL3_DEBUG; ...@@ -84,6 +92,7 @@ static int el3_debug = EL3_DEBUG;
static int el3_debug = 2; static int el3_debug = 2;
#endif #endif
/* To minimize the size of the driver source I only define operating /* To minimize the size of the driver source I only define operating
constants if they are used several times. You'll need the manual constants if they are used several times. You'll need the manual
anyway if you want to understand driver details. */ anyway if you want to understand driver details. */
...@@ -158,6 +167,7 @@ static int el3_rx(struct net_device *dev); ...@@ -158,6 +167,7 @@ static int el3_rx(struct net_device *dev);
static int el3_close(struct net_device *dev); static int el3_close(struct net_device *dev);
static void set_multicast_list(struct net_device *dev); static void set_multicast_list(struct net_device *dev);
static void el3_tx_timeout (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 #ifdef CONFIG_MCA
struct el3_mca_adapters_struct { struct el3_mca_adapters_struct {
...@@ -513,6 +523,7 @@ int __init el3_probe(struct net_device *dev) ...@@ -513,6 +523,7 @@ int __init el3_probe(struct net_device *dev)
dev->set_multicast_list = &set_multicast_list; dev->set_multicast_list = &set_multicast_list;
dev->tx_timeout = el3_tx_timeout; dev->tx_timeout = el3_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT; dev->watchdog_timeo = TX_TIMEOUT;
dev->do_ioctl = netdev_ioctl;
/* Fill in the generic fields of the device structure. */ /* Fill in the generic fields of the device structure. */
ether_setup(dev); ether_setup(dev);
...@@ -1003,6 +1014,85 @@ el3_close(struct net_device *dev) ...@@ -1003,6 +1014,85 @@ el3_close(struct net_device *dev)
return 0; 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 #ifdef MODULE
/* Parameters that may be passed into the module. */ /* Parameters that may be passed into the module. */
static int debug = -1; static int debug = -1;
......
...@@ -16,9 +16,17 @@ ...@@ -16,9 +16,17 @@
2/2/00- Added support for kernel-level ISAPnP 2/2/00- Added support for kernel-level ISAPnP
by Stephen Frost <sfrost@snowman.net> and Alessandro Zummo by Stephen Frost <sfrost@snowman.net> and Alessandro Zummo
Cleaned up for 2.3.x/softnet by Jeff Garzik and Alan Cox. 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 #define CORKSCREW 1
...@@ -63,6 +71,9 @@ static int max_interrupt_work = 20; ...@@ -63,6 +71,9 @@ static int max_interrupt_work = 20;
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/ethtool.h>
#include <asm/uaccess.h>
#include <asm/bitops.h> #include <asm/bitops.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/dma.h> #include <asm/dma.h>
...@@ -393,6 +404,7 @@ static int corkscrew_close(struct net_device *dev); ...@@ -393,6 +404,7 @@ static int corkscrew_close(struct net_device *dev);
static void update_stats(int addr, 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 struct net_device_stats *corkscrew_get_stats(struct net_device *dev);
static void set_rx_mode(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) ...@@ -721,6 +733,7 @@ static int corkscrew_probe1(struct net_device *dev)
dev->stop = &corkscrew_close; dev->stop = &corkscrew_close;
dev->get_stats = &corkscrew_get_stats; dev->get_stats = &corkscrew_get_stats;
dev->set_multicast_list = &set_rx_mode; dev->set_multicast_list = &set_rx_mode;
dev->do_ioctl = netdev_ioctl;
return 0; return 0;
} }
...@@ -1591,6 +1604,87 @@ static void set_rx_mode(struct net_device *dev) ...@@ -1591,6 +1604,87 @@ static void set_rx_mode(struct net_device *dev)
outw(new_mode, ioaddr + EL3_CMD); 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 #ifdef MODULE
void cleanup_module(void) void cleanup_module(void)
......
...@@ -81,10 +81,15 @@ ...@@ -81,10 +81,15 @@
added option to disable multicast as is causes problems added option to disable multicast as is causes problems
Ganesh Sittampalam <ganesh.sittampalam@magdalen.oxford.ac.uk> Ganesh Sittampalam <ganesh.sittampalam@magdalen.oxford.ac.uk>
Stuart Adamson <stuart.adamson@compsoc.net> Stuart Adamson <stuart.adamson@compsoc.net>
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 $ $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 <linux/module.h> #include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/sched.h> #include <linux/sched.h>
...@@ -95,6 +100,9 @@ ...@@ -95,6 +100,9 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/mca.h> #include <linux/mca.h>
#include <linux/ethtool.h>
#include <asm/uaccess.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/bitops.h> #include <asm/bitops.h>
#include <asm/io.h> #include <asm/io.h>
...@@ -182,6 +190,7 @@ static void elmc_timeout(struct net_device *dev); ...@@ -182,6 +190,7 @@ static void elmc_timeout(struct net_device *dev);
#ifdef ELMC_MULTICAST #ifdef ELMC_MULTICAST
static void set_multicast_list(struct net_device *dev); static void set_multicast_list(struct net_device *dev);
#endif #endif
static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
/* helper-functions */ /* helper-functions */
static int init586(struct net_device *dev); static int init586(struct net_device *dev);
...@@ -563,7 +572,8 @@ int __init elmc_probe(struct net_device *dev) ...@@ -563,7 +572,8 @@ int __init elmc_probe(struct net_device *dev)
#else #else
dev->set_multicast_list = NULL; dev->set_multicast_list = NULL;
#endif #endif
dev->do_ioctl = netdev_ioctl;
ether_setup(dev); ether_setup(dev);
/* note that we haven't actually requested the IRQ from the kernel. /* 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) ...@@ -1214,6 +1224,69 @@ static void set_multicast_list(struct net_device *dev)
} }
#endif #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 #ifdef MODULE
......
...@@ -16,8 +16,12 @@ ...@@ -16,8 +16,12 @@
* *
*/ */
#define DRV_NAME "3c527"
#define DRV_VERSION "0.6a"
#define DRV_RELDATE "2001/11/17"
static const char *version = 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 * DOC: Traps for the unwary
...@@ -90,6 +94,9 @@ static const char *version = ...@@ -90,6 +94,9 @@ static const char *version =
#include <linux/in.h> #include <linux/in.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/ethtool.h>
#include <asm/uaccess.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/bitops.h> #include <asm/bitops.h>
#include <asm/io.h> #include <asm/io.h>
...@@ -108,7 +115,7 @@ static const char *version = ...@@ -108,7 +115,7 @@ static const char *version =
* The name of the card. Is used for messages and in the requests for * The name of the card. Is used for messages and in the requests for
* io regions, irqs and dma channels * 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 */ /* use 0 for production, 1 for verification, >2 for debug */
#ifndef NET_DEBUG #ifndef NET_DEBUG
...@@ -213,6 +220,7 @@ static int mc32_close(struct net_device *dev); ...@@ -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 struct net_device_stats *mc32_get_stats(struct net_device *dev);
static void mc32_set_multicast_list(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 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 * mc32_probe - Search for supported boards
...@@ -502,7 +510,7 @@ static int __init mc32_probe1(struct net_device *dev, int slot) ...@@ -502,7 +510,7 @@ static int __init mc32_probe1(struct net_device *dev, int slot)
dev->set_multicast_list = mc32_set_multicast_list; dev->set_multicast_list = mc32_set_multicast_list;
dev->tx_timeout = mc32_timeout; dev->tx_timeout = mc32_timeout;
dev->watchdog_timeo = HZ*5; /* Board does all the work */ dev->watchdog_timeo = HZ*5; /* Board does all the work */
dev->do_ioctl = netdev_ioctl;
lp->xceiver_state = HALTED; lp->xceiver_state = HALTED;
...@@ -1644,6 +1652,86 @@ static void mc32_reset_multicast_list(struct net_device *dev) ...@@ -1644,6 +1652,86 @@ static void mc32_reset_multicast_list(struct net_device *dev)
do_mc32_set_multicast_list(dev,1); 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 #ifdef MODULE
static struct net_device this_device; static struct net_device this_device;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment