#include <linux/types.h>
#include <linux/unistd.h>
#include <linux/ctype.h>
+#include <linux/bitops.h>
-#include <asm/bitops.h>
#include <asm/io.h>
#include <asm/dma.h>
#include <asm/uaccess.h>
#define EWRK3_IOP_INC 0x20 /* I/O address increment */
#define EWRK3_TOTAL_SIZE 0x20 /* required I/O address length */
-/* If you change this, remember to also change MODULE_PARM array limits */
#ifndef MAX_NUM_EWRK3S
#define MAX_NUM_EWRK3S 21
#endif
static struct net_device_stats *ewrk3_get_stats(struct net_device *dev);
static void set_multicast_list(struct net_device *dev);
static int ewrk3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static struct ethtool_ops ethtool_ops_203;
+static struct ethtool_ops ethtool_ops;
/*
** Private functions
printk(" is in I/O only mode");
}
- lp = (struct ewrk3_private *) dev->priv;
+ lp = netdev_priv(dev);
lp->shmem_base = mem_start;
lp->shmem_length = shmem_length;
lp->lemac = lemac;
dev->get_stats = ewrk3_get_stats;
dev->set_multicast_list = set_multicast_list;
dev->do_ioctl = ewrk3_ioctl;
+ if (lp->adapter_name[4] == '3')
+ SET_ETHTOOL_OPS(dev, ðtool_ops_203);
+ else
+ SET_ETHTOOL_OPS(dev, ðtool_ops);
dev->tx_timeout = ewrk3_timeout;
dev->watchdog_timeo = QUEUE_PKT_TIMEOUT;
static int ewrk3_open(struct net_device *dev)
{
- struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
+ struct ewrk3_private *lp = netdev_priv(dev);
u_long iobase = dev->base_addr;
int i, status = 0;
u_char icr, csr;
*/
static void ewrk3_init(struct net_device *dev)
{
- struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
+ struct ewrk3_private *lp = netdev_priv(dev);
u_char csr, page;
u_long iobase = dev->base_addr;
int i;
static void ewrk3_timeout(struct net_device *dev)
{
- struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
+ struct ewrk3_private *lp = netdev_priv(dev);
u_char icr, csr;
u_long iobase = dev->base_addr;
*/
static int ewrk3_queue_pkt (struct sk_buff *skb, struct net_device *dev)
{
- struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
+ struct ewrk3_private *lp = netdev_priv(dev);
u_long iobase = dev->base_addr;
u_long buf = 0;
u_char icr;
u_long iobase;
u_char icr, cr, csr;
- lp = (struct ewrk3_private *) dev->priv;
+ lp = netdev_priv(dev);
iobase = dev->base_addr;
/* get the interrupt information */
/* Called with lp->hw_lock held */
static int ewrk3_rx(struct net_device *dev)
{
- struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
+ struct ewrk3_private *lp = netdev_priv(dev);
u_long iobase = dev->base_addr;
int i, status = 0;
u_char page;
*/
static int ewrk3_tx(struct net_device *dev)
{
- struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
+ struct ewrk3_private *lp = netdev_priv(dev);
u_long iobase = dev->base_addr;
u_char tx_status;
static int ewrk3_close(struct net_device *dev)
{
- struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
+ struct ewrk3_private *lp = netdev_priv(dev);
u_long iobase = dev->base_addr;
u_char icr, csr;
static struct net_device_stats *ewrk3_get_stats(struct net_device *dev)
{
- struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
+ struct ewrk3_private *lp = netdev_priv(dev);
/* Null body since there is no framing error counter */
return &lp->stats;
*/
static void set_multicast_list(struct net_device *dev)
{
- struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
+ struct ewrk3_private *lp = netdev_priv(dev);
u_long iobase = dev->base_addr;
u_char csr;
*/
static void SetMulticastFilter(struct net_device *dev)
{
- struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
+ struct ewrk3_private *lp = netdev_priv(dev);
struct dev_mc_list *dmi = dev->mc_list;
u_long iobase = dev->base_addr;
int i;
return status; /* return the device name string */
}
-static int ewrk3_ethtool_ioctl(struct net_device *dev, void __user *useraddr)
+static void ewrk3_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
{
- struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
- u_long iobase = dev->base_addr;
- u32 ethcmd;
-
- if (get_user(ethcmd, (u32 __user *)useraddr))
- return -EFAULT;
-
- switch (ethcmd) {
-
- /* Get driver info */
- case ETHTOOL_GDRVINFO: {
- struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
- int fwrev = Read_EEPROM(dev->base_addr, EEPROM_REVLVL);
-
- strcpy(info.driver, DRV_NAME);
- strcpy(info.version, DRV_VERSION);
- sprintf(info.fw_version, "%d", fwrev);
- strcpy(info.bus_info, "N/A");
- info.eedump_len = EEPROM_MAX;
- if (copy_to_user(useraddr, &info, sizeof(info)))
- return -EFAULT;
- return 0;
- }
-
- /* Get settings */
- case ETHTOOL_GSET: {
- struct ethtool_cmd ecmd = { ETHTOOL_GSET };
- u_char cr = inb(EWRK3_CR);
-
- switch (lp->adapter_name[4]) {
- case '3': /* DE203 */
- ecmd.supported = SUPPORTED_BNC;
- ecmd.port = PORT_BNC;
- break;
+ int fwrev = Read_EEPROM(dev->base_addr, EEPROM_REVLVL);
- case '4': /* DE204 */
- ecmd.supported = SUPPORTED_TP;
- ecmd.port = PORT_TP;
- break;
+ strcpy(info->driver, DRV_NAME);
+ strcpy(info->version, DRV_VERSION);
+ sprintf(info->fw_version, "%d", fwrev);
+ strcpy(info->bus_info, "N/A");
+ info->eedump_len = EEPROM_MAX;
+}
- case '5': /* DE205 */
- ecmd.supported = SUPPORTED_TP | SUPPORTED_BNC | SUPPORTED_AUI;
- ecmd.autoneg = !(cr & CR_APD);
- /*
- ** Port is only valid if autoneg is disabled
- ** and even then we don't know if AUI is jumpered.
- */
- if (!ecmd.autoneg)
- ecmd.port = (cr & CR_PSEL) ? PORT_BNC : PORT_TP;
- break;
- }
+static int ewrk3_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+ struct ewrk3_private *lp = netdev_priv(dev);
+ unsigned long iobase = dev->base_addr;
+ u8 cr = inb(EWRK3_CR);
+
+ switch (lp->adapter_name[4]) {
+ case '3': /* DE203 */
+ ecmd->supported = SUPPORTED_BNC;
+ ecmd->port = PORT_BNC;
+ break;
- ecmd.supported |= SUPPORTED_10baseT_Half;
- ecmd.speed = SPEED_10;
- ecmd.duplex = DUPLEX_HALF;
+ case '4': /* DE204 */
+ ecmd->supported = SUPPORTED_TP;
+ ecmd->port = PORT_TP;
+ break;
- if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
- return -EFAULT;
- return 0;
+ case '5': /* DE205 */
+ ecmd->supported = SUPPORTED_TP | SUPPORTED_BNC | SUPPORTED_AUI;
+ ecmd->autoneg = !(cr & CR_APD);
+ /*
+ ** Port is only valid if autoneg is disabled
+ ** and even then we don't know if AUI is jumpered.
+ */
+ if (!ecmd->autoneg)
+ ecmd->port = (cr & CR_PSEL) ? PORT_BNC : PORT_TP;
+ break;
}
- /* Set settings */
- case ETHTOOL_SSET: {
- struct ethtool_cmd ecmd;
- u_char cr;
- u_long flags;
-
- /* DE205 is the only card with anything to set */
- if (lp->adapter_name[4] != '5')
- return -EOPNOTSUPP;
-
- if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
- return -EFAULT;
-
- /* Sanity-check parameters */
- if (ecmd.speed != SPEED_10)
- return -EINVAL;
- if (ecmd.port != PORT_TP && ecmd.port != PORT_BNC)
- return -EINVAL; /* AUI is not software-selectable */
- if (ecmd.transceiver != XCVR_INTERNAL)
- return -EINVAL;
- if (ecmd.duplex != DUPLEX_HALF)
- return -EINVAL;
- if (ecmd.phy_address != 0)
- return -EINVAL;
-
- spin_lock_irqsave(&lp->hw_lock, flags);
- cr = inb(EWRK3_CR);
-
- /* If Autoneg is set, change to Auto Port mode */
- /* Otherwise, disable Auto Port and set port explicitly */
- if (ecmd.autoneg) {
- cr &= ~CR_APD;
- } else {
- cr |= CR_APD;
- if (ecmd.port == PORT_TP)
- cr &= ~CR_PSEL; /* Force TP */
- else
- cr |= CR_PSEL; /* Force BNC */
- }
-
- /* Commit the changes */
- outb(cr, EWRK3_CR);
+ ecmd->supported |= SUPPORTED_10baseT_Half;
+ ecmd->speed = SPEED_10;
+ ecmd->duplex = DUPLEX_HALF;
+ return 0;
+}
- spin_unlock_irqrestore(&lp->hw_lock, flags);
- if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
- return -EFAULT;
- return 0;
- }
+static int ewrk3_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+ struct ewrk3_private *lp = netdev_priv(dev);
+ unsigned long iobase = dev->base_addr;
+ unsigned long flags;
+ u8 cr;
- /* Get link status */
- case ETHTOOL_GLINK: {
- struct ethtool_value edata = { ETHTOOL_GLINK };
- u_char cmr = inb(EWRK3_CMR);
+ /* DE205 is the only card with anything to set */
+ if (lp->adapter_name[4] != '5')
+ return -EOPNOTSUPP;
- /* DE203 has BNC only and link status does not apply */
- if (lp->adapter_name[4] == '3')
- return -EOPNOTSUPP;
+ /* Sanity-check parameters */
+ if (ecmd->speed != SPEED_10)
+ return -EINVAL;
+ if (ecmd->port != PORT_TP && ecmd->port != PORT_BNC)
+ return -EINVAL; /* AUI is not software-selectable */
+ if (ecmd->transceiver != XCVR_INTERNAL)
+ return -EINVAL;
+ if (ecmd->duplex != DUPLEX_HALF)
+ return -EINVAL;
+ if (ecmd->phy_address != 0)
+ return -EINVAL;
- /* On DE204 this is always valid since TP is the only port. */
- /* On DE205 this reflects TP status even if BNC or AUI is selected. */
- edata.data = !(cmr & CMR_LINK);
+ spin_lock_irqsave(&lp->hw_lock, flags);
+ cr = inb(EWRK3_CR);
- if (copy_to_user(useraddr, &edata, sizeof(edata)))
- return -EFAULT;
- return 0;
+ /* If Autoneg is set, change to Auto Port mode */
+ /* Otherwise, disable Auto Port and set port explicitly */
+ if (ecmd->autoneg) {
+ cr &= ~CR_APD;
+ } else {
+ cr |= CR_APD;
+ if (ecmd->port == PORT_TP)
+ cr &= ~CR_PSEL; /* Force TP */
+ else
+ cr |= CR_PSEL; /* Force BNC */
}
- /* Blink LED for identification */
- case ETHTOOL_PHYS_ID: {
- struct ethtool_value edata;
- u_long flags;
- u_char cr;
- int count;
-
- if (copy_from_user(&edata, useraddr, sizeof(edata)))
- return -EFAULT;
-
- /* Toggle LED 4x per second */
- count = edata.data << 2;
+ /* Commit the changes */
+ outb(cr, EWRK3_CR);
+ spin_unlock_irqrestore(&lp->hw_lock, flags);
+ return 0;
+}
- spin_lock_irqsave(&lp->hw_lock, flags);
+static u32 ewrk3_get_link(struct net_device *dev)
+{
+ unsigned long iobase = dev->base_addr;
+ u8 cmr = inb(EWRK3_CMR);
+ /* DE203 has BNC only and link status does not apply */
+ /* On DE204 this is always valid since TP is the only port. */
+ /* On DE205 this reflects TP status even if BNC or AUI is selected. */
+ return !(cmr & CMR_LINK);
+}
- /* Bail if a PHYS_ID is already in progress */
- if (lp->led_mask == 0) {
- spin_unlock_irqrestore(&lp->hw_lock, flags);
- return -EBUSY;
- }
+static int ewrk3_phys_id(struct net_device *dev, u32 data)
+{
+ struct ewrk3_private *lp = netdev_priv(dev);
+ unsigned long iobase = dev->base_addr;
+ unsigned long flags;
+ u8 cr;
+ int count;
- /* Prevent ISR from twiddling the LED */
- lp->led_mask = 0;
+ /* Toggle LED 4x per second */
+ count = data << 2;
- while (count--) {
- /* Toggle the LED */
- cr = inb(EWRK3_CR);
- outb(cr ^ CR_LED, EWRK3_CR);
+ spin_lock_irqsave(&lp->hw_lock, flags);
- /* Wait a little while */
- spin_unlock_irqrestore(&lp->hw_lock, flags);
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ>>2);
- spin_lock_irqsave(&lp->hw_lock, flags);
+ /* Bail if a PHYS_ID is already in progress */
+ if (lp->led_mask == 0) {
+ spin_unlock_irqrestore(&lp->hw_lock, flags);
+ return -EBUSY;
+ }
- /* Exit if we got a signal */
- if (signal_pending(current))
- break;
- }
+ /* Prevent ISR from twiddling the LED */
+ lp->led_mask = 0;
- lp->led_mask = CR_LED;
+ while (count--) {
+ /* Toggle the LED */
cr = inb(EWRK3_CR);
- outb(cr & ~CR_LED, EWRK3_CR);
+ outb(cr ^ CR_LED, EWRK3_CR);
+
+ /* Wait a little while */
spin_unlock_irqrestore(&lp->hw_lock, flags);
- return signal_pending(current) ? -ERESTARTSYS : 0;
- }
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(HZ>>2);
+ spin_lock_irqsave(&lp->hw_lock, flags);
+ /* Exit if we got a signal */
+ if (signal_pending(current))
+ break;
}
- return -EOPNOTSUPP;
+ lp->led_mask = CR_LED;
+ cr = inb(EWRK3_CR);
+ outb(cr & ~CR_LED, EWRK3_CR);
+ spin_unlock_irqrestore(&lp->hw_lock, flags);
+ return signal_pending(current) ? -ERESTARTSYS : 0;
}
+static struct ethtool_ops ethtool_ops_203 = {
+ .get_drvinfo = ewrk3_get_drvinfo,
+ .get_settings = ewrk3_get_settings,
+ .set_settings = ewrk3_set_settings,
+ .phys_id = ewrk3_phys_id,
+};
+
+static struct ethtool_ops ethtool_ops = {
+ .get_drvinfo = ewrk3_get_drvinfo,
+ .get_settings = ewrk3_get_settings,
+ .set_settings = ewrk3_set_settings,
+ .get_link = ewrk3_get_link,
+ .phys_id = ewrk3_phys_id,
+};
+
/*
** Perform IOCTL call functions here. Some are privileged operations and the
** effective uid is checked in those cases.
*/
static int ewrk3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
- struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
+ struct ewrk3_private *lp = netdev_priv(dev);
struct ewrk3_ioctl *ioc = (struct ewrk3_ioctl *) &rq->ifr_ifru;
u_long iobase = dev->base_addr;
int i, j, status = 0;
union ewrk3_addr *tmp;
- /* ethtool IOCTLs are handled elsewhere */
- if (cmd == SIOCETHTOOL)
- return ewrk3_ethtool_ioctl(dev, rq->ifr_data);
-
- /* Other than ethtool, all we handle are private IOCTLs */
+ /* All we handle are private IOCTLs */
if (cmd != EWRK3IOCTL)
return -EOPNOTSUPP;
static int io[MAX_NUM_EWRK3S+1] = { 0x300, 0, };
/* '21' below should really be 'MAX_NUM_EWRK3S' */
-MODULE_PARM(io, "0-21i");
-MODULE_PARM(irq, "0-21i");
+module_param_array(io, int, NULL, 0);
+module_param_array(irq, int, NULL, 0);
MODULE_PARM_DESC(io, "EtherWORKS 3 I/O base address(es)");
MODULE_PARM_DESC(irq, "EtherWORKS 3 IRQ number(s)");