#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
struct ewrk3_private {
char adapter_name[80]; /* Name exported to /proc/ioports */
u_long shmem_base; /* Shared memory start address */
+ void __iomem *shmem;
u_long shmem_length; /* Shared memory window length */
struct net_device_stats stats; /* Public stats */
struct ewrk3_stats pktStats; /* Private stats counters */
u_char lemac; /* Chip rev. level */
u_char hard_strapped; /* Don't allow a full open */
u_char txc; /* Transmit cut through */
- u_char *mctbl; /* Pointer to the multicast table */
+ void __iomem *mctbl; /* Pointer to the multicast table */
u_char led_mask; /* Used to reserve LED access for ethtool */
spinlock_t hw_lock;
};
*/
static int ewrk3_open(struct net_device *dev);
static int ewrk3_queue_pkt(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t ewrk3_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t ewrk3_interrupt(int irq, void *dev_id);
static int ewrk3_close(struct net_device *dev);
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 const struct ethtool_ops ethtool_ops_203;
+static const struct ethtool_ops ethtool_ops;
/*
** Private functions
mdelay(1);\
}
+#ifndef MODULE
struct net_device * __init ewrk3_probe(int unit)
{
struct net_device *dev = alloc_etherdev(sizeof(struct ewrk3_private));
SET_MODULE_OWNER(dev);
err = ewrk3_probe1(dev, dev->base_addr, dev->irq);
- if (err)
+ if (err)
goto out;
return dev;
out:
free_netdev(dev);
return ERR_PTR(err);
-
+
}
+#endif
static int __init ewrk3_probe1(struct net_device *dev, u_long iobase, int irq)
{
/* Address PROM pattern */
err = isa_probe(dev, iobase);
- if (err != 0)
+ if (err != 0)
err = eisa_probe(dev, iobase);
if (err)
return err;
}
-static int __init
+static int __init
ewrk3_hw_init(struct net_device *dev, u_long iobase)
{
struct ewrk3_private *lp;
printk("%s: Device has a bad on-board EEPROM.\n", dev->name);
return -ENXIO;
}
-
+
EthwrkSignature(name, eeprom_image);
- if (*name == '\0')
+ if (*name == '\0')
return -ENXIO;
dev->base_addr = iobase;
-
+
if (iobase > 0x400) {
outb(eisa_cr, EISA_CR); /* Rewrite the EISA CR */
}
lemac = eeprom_image[EEPROM_CHIPVER];
cmr = inb(EWRK3_CMR);
-
+
if (((lemac == LeMAC) && ((cmr & CMR_NO_EEPROM) != CMR_NO_EEPROM)) ||
((lemac == LeMAC2) && !(cmr & CMR_HS))) {
printk("%s: %s at %#4lx", dev->name, name, iobase);
printk("%2.2x:", dev->dev_addr[i]);
}
printk("%2.2x,\n", dev->dev_addr[i]);
-
+
if (status) {
printk(" which has an EEPROM CRC error.\n");
return -ENXIO;
if (eeprom_image[EEPROM_SETUP] & SETUP_DRAM)
cmr |= CMR_DRAM;
outb(cmr, EWRK3_CMR);
-
+
cr = inb(EWRK3_CR); /* Set up the Control Register */
cr |= eeprom_image[EEPROM_SETUP] & SETUP_APD;
if (cr & SETUP_APD)
** uncommenting this line.
*/
/* FORCE_2K_MODE; */
-
+
if (hard_strapped) {
printk(" is hard strapped.\n");
} else if (mem_start) {
printk(" is in I/O only mode");
}
- lp = (struct ewrk3_private *) dev->priv;
+ lp = netdev_priv(dev);
lp->shmem_base = mem_start;
+ lp->shmem = ioremap(mem_start, shmem_length);
+ if (!lp->shmem)
+ return -ENOMEM;
lp->shmem_length = shmem_length;
lp->lemac = lemac;
lp->hard_strapped = hard_strapped;
lp->led_mask = CR_LED;
spin_lock_init(&lp->hw_lock);
-
+
lp->mPage = 64;
if (cmr & CMR_DRAM)
lp->mPage <<= 1; /* 2 DRAMS on module */
-
+
sprintf(lp->adapter_name, "%s (%s)", name, dev->name);
-
+
lp->irq_mask = ICR_TNEM | ICR_TXDM | ICR_RNEM | ICR_RXDM;
-
+
if (!hard_strapped) {
/*
** Enable EWRK3 board interrupts for autoprobing
*/
icr |= ICR_IE; /* Enable interrupts */
outb(icr, EWRK3_ICR);
-
+
/* The DMA channel may be passed in on this parameter. */
dev->dma = 0;
-
+
/* To auto-IRQ we enable the initialization-done and DMA err,
interrupts. For now we will always get a DMA error. */
if (dev->irq < 2) {
#ifndef MODULE
u_char irqnum;
unsigned long irq_mask;
-
+
irq_mask = probe_irq_on();
-
+
/*
** Trigger a TNE interrupt.
*/
icr |= ICR_TNEM;
outb(1, EWRK3_TDQ); /* Write to the TX done queue */
outb(icr, EWRK3_ICR); /* Unmask the TXD interrupt */
-
+
irqnum = irq[((icr & IRQ_SEL) >> 4)];
-
+
mdelay(20);
dev->irq = probe_irq_off(irq_mask);
if ((dev->irq) && (irqnum == dev->irq)) {
} else {
printk(", but incorrect IRQ line detected.\n");
}
+ iounmap(lp->shmem);
return -ENXIO;
}
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;
-
+
dev->mem_start = 0;
return 0;
}
-\f
+
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;
/*
* Transmit timeout
*/
-
+
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;
-
- if (!lp->hard_strapped)
+
+ if (!lp->hard_strapped)
{
printk(KERN_WARNING"%s: transmit timed/locked out, status %04x, resetting.\n",
dev->name, inb(EWRK3_CSR));
*/
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;
+ void __iomem *buf = NULL;
u_char icr;
u_char page;
if (lp->shmem_length == IO_ONLY) {
outb (page, EWRK3_IOPR);
} else if (lp->shmem_length == SHMEM_2K) {
- buf = lp->shmem_base;
+ buf = lp->shmem;
outb (page, EWRK3_MPR);
} else if (lp->shmem_length == SHMEM_32K) {
- buf = ((((short) page << 11) & 0x7800) + lp->shmem_base);
+ buf = (((short) page << 11) & 0x7800) + lp->shmem;
outb ((page >> 4), EWRK3_MPR);
} else if (lp->shmem_length == SHMEM_64K) {
- buf = ((((short) page << 11) & 0xf800) + lp->shmem_base);
+ buf = (((short) page << 11) & 0xf800) + lp->shmem;
outb ((page >> 5), EWRK3_MPR);
} else {
printk (KERN_ERR "%s: Oops - your private data area is hosed!\n",
}
outb (page, EWRK3_TQ); /* Start sending pkt */
} else {
- isa_writeb ((char) (TCR_QMODE | TCR_PAD | TCR_IFC), buf); /* ctrl byte */
+ writeb ((char) (TCR_QMODE | TCR_PAD | TCR_IFC), buf); /* ctrl byte */
buf += 1;
- isa_writeb ((char) (skb->len & 0xff), buf); /* length (16 bit xfer) */
+ writeb ((char) (skb->len & 0xff), buf); /* length (16 bit xfer) */
buf += 1;
if (lp->txc) {
- isa_writeb ((char)
- (((skb->len >> 8) & 0xff) | XCT), buf);
+ writeb(((skb->len >> 8) & 0xff) | XCT, buf);
buf += 1;
- isa_writeb (0x04, buf); /* index byte */
+ writeb (0x04, buf); /* index byte */
buf += 1;
- isa_writeb (0x00, (buf + skb->len)); /* Write the XCT flag */
- isa_memcpy_toio (buf, skb->data, PRELOAD); /* Write PRELOAD bytes */
+ writeb (0x00, (buf + skb->len)); /* Write the XCT flag */
+ memcpy_toio (buf, skb->data, PRELOAD); /* Write PRELOAD bytes */
outb (page, EWRK3_TQ); /* Start sending pkt */
- isa_memcpy_toio (buf + PRELOAD,
+ memcpy_toio (buf + PRELOAD,
skb->data + PRELOAD,
skb->len - PRELOAD);
- isa_writeb (0xff, (buf + skb->len)); /* Write the XCT flag */
+ writeb (0xff, (buf + skb->len)); /* Write the XCT flag */
} else {
- isa_writeb ((char)
- ((skb->len >> 8) & 0xff), buf);
+ writeb ((skb->len >> 8) & 0xff, buf);
buf += 1;
- isa_writeb (0x04, buf); /* index byte */
+ writeb (0x04, buf); /* index byte */
buf += 1;
- isa_memcpy_toio (buf, skb->data, skb->len); /* Write data bytes */
+ memcpy_toio (buf, skb->data, skb->len); /* Write data bytes */
outb (page, EWRK3_TQ); /* Start sending pkt */
}
}
/*
** The EWRK3 interrupt handler.
*/
-static irqreturn_t ewrk3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t ewrk3_interrupt(int irq, void *dev_id)
{
struct net_device *dev = dev_id;
struct ewrk3_private *lp;
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;
- u_long buf = 0;
+ void __iomem *buf = NULL;
while (inb(EWRK3_RQC) && !status) { /* Whilst there's incoming data */
if ((page = inb(EWRK3_RQ)) < lp->mPage) { /* Get next entry's buffer page */
if (lp->shmem_length == IO_ONLY) {
outb(page, EWRK3_IOPR);
} else if (lp->shmem_length == SHMEM_2K) {
- buf = lp->shmem_base;
+ buf = lp->shmem;
outb(page, EWRK3_MPR);
} else if (lp->shmem_length == SHMEM_32K) {
- buf = ((((short) page << 11) & 0x7800) + lp->shmem_base);
+ buf = (((short) page << 11) & 0x7800) + lp->shmem;
outb((page >> 4), EWRK3_MPR);
} else if (lp->shmem_length == SHMEM_64K) {
- buf = ((((short) page << 11) & 0xf800) + lp->shmem_base);
+ buf = (((short) page << 11) & 0xf800) + lp->shmem;
outb((page >> 5), EWRK3_MPR);
} else {
status = -1;
pkt_len = inb(EWRK3_DATA);
pkt_len |= ((u_short) inb(EWRK3_DATA) << 8);
} else {
- rx_status = isa_readb(buf);
+ rx_status = readb(buf);
buf += 1;
- pkt_len = isa_readw(buf);
+ pkt_len = readw(buf);
buf += 3;
}
*p++ = inb(EWRK3_DATA);
}
} else {
- isa_memcpy_fromio(p, buf, pkt_len);
+ memcpy_fromio(p, buf, pkt_len);
}
for (i = 1; i < EWRK3_PKT_STAT_SZ - 1; i++) {
*/
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;
netif_stop_queue(dev);
-
+
if (ewrk3_debug > 1) {
printk("%s: Shutting down ethercard, status was %2.2x.\n",
dev->name, inb(EWRK3_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;
csr = inb(EWRK3_CSR);
if (lp->shmem_length == IO_ONLY) {
- lp->mctbl = (char *) PAGE0_HTE;
+ lp->mctbl = NULL;
} else {
- lp->mctbl = (char *) (lp->shmem_base + PAGE0_HTE);
+ lp->mctbl = lp->shmem + PAGE0_HTE;
}
csr &= ~(CSR_PME | CSR_MCE);
*/
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;
char *addrs, bit, byte;
- short *p = (short *) lp->mctbl;
+ short __iomem *p = lp->mctbl;
u16 hashcode;
u32 crc;
if (lp->shmem_length == IO_ONLY) {
outb(0, EWRK3_IOPR);
- outw(EEPROM_OFFSET(lp->mctbl), EWRK3_PIR1);
+ outw(PAGE0_HTE, EWRK3_PIR1);
} else {
outb(0, EWRK3_MPR);
}
if (lp->shmem_length == IO_ONLY) {
outb(0xff, EWRK3_DATA);
} else { /* memset didn't work here */
- isa_writew(0xffff, (int) p);
+ writew(0xffff, p);
p++;
i++;
}
outb(0x00, EWRK3_DATA);
}
} else {
- isa_memset_io((int) lp->mctbl, 0, (HASH_TABLE_LEN >> 3));
- isa_writeb(0x80, (int) (lp->mctbl + (HASH_TABLE_LEN >> 4) - 1));
+ memset_io(lp->mctbl, 0, HASH_TABLE_LEN >> 3);
+ writeb(0x80, lp->mctbl + (HASH_TABLE_LEN >> 4) - 1);
}
/* Update table */
if (lp->shmem_length == IO_ONLY) {
u_char tmp;
- outw((short) ((long) lp->mctbl) + byte, EWRK3_PIR1);
+ outw(PAGE0_HTE + byte, EWRK3_PIR1);
tmp = inb(EWRK3_DATA);
tmp |= bit;
- outw((short) ((long) lp->mctbl) + byte, EWRK3_PIR1);
+ outw(PAGE0_HTE + byte, EWRK3_PIR1);
outb(tmp, EWRK3_DATA);
} else {
- isa_writeb(isa_readb((int)(lp->mctbl + byte)) | bit, (int)(lp->mctbl + byte));
+ writeb(readb(lp->mctbl + byte) | bit, lp->mctbl + byte);
}
}
}
for (; (i < maxSlots) && (dev != NULL);
iobase += EWRK3_IOP_INC, i++)
{
- if (request_region(iobase, EWRK3_TOTAL_SIZE, dev->name)) {
+ if (request_region(iobase, EWRK3_TOTAL_SIZE, DRV_NAME)) {
if (DevicePresent(iobase) == 0) {
int irq = dev->irq;
ret = ewrk3_hw_init(dev, iobase);
if (ioaddr < 0x1000)
goto out;
- if (ioaddr == 0) { /* Autoprobing */
- iobase = EISA_SLOT_INC; /* Get the first slot address */
- i = 1;
- maxSlots = MAX_EISA_SLOTS;
- } else { /* Probe a specific location */
- iobase = ioaddr;
- i = (ioaddr >> 12);
- maxSlots = i + 1;
- }
+ iobase = ioaddr;
+ i = (ioaddr >> 12);
+ maxSlots = i + 1;
for (i = 1; (i < maxSlots) && (dev != NULL); i++, iobase += EISA_SLOT_INC) {
if (EISA_signature(name, EISA_ID) == 0) {
- if (request_region(iobase, EWRK3_TOTAL_SIZE, dev->name) &&
+ if (request_region(iobase, EWRK3_TOTAL_SIZE, DRV_NAME) &&
DevicePresent(iobase) == 0) {
int irq = dev->irq;
ret = ewrk3_hw_init(dev, iobase);
return status; /* return the device name string */
}
-static int ewrk3_ethtool_ioctl(struct net_device *dev, void *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 *)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;
- }
+ int fwrev = Read_EEPROM(dev->base_addr, EEPROM_REVLVL);
- /* 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;
-
- 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;
- }
+ msleep(250);
+ 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 const 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 const 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_ioctl *ioc = (struct ewrk3_ioctl *) &rq->ifr_data;
+ 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;
u_char csr;
u_char addr[HASH_TABLE_LEN * ETH_ALEN];
u_short val[(HASH_TABLE_LEN * ETH_ALEN) >> 1];
};
-
- union ewrk3_addr *tmp;
- /* ethtool IOCTLs are handled elsewhere */
- if (cmd == SIOCETHTOOL)
- return ewrk3_ethtool_ioctl(dev, (void *)rq->ifr_data);
+ union ewrk3_addr *tmp;
- /* Other than ethtool, all we handle are private IOCTLs */
+ /* All we handle are private IOCTLs */
if (cmd != EWRK3IOCTL)
return -EOPNOTSUPP;
if (copy_to_user(ioc->data, tmp->addr, ioc->len))
status = -EFAULT;
break;
-
+
case EWRK3_SET_HWADDR: /* Set the hardware address */
if (capable(CAP_NET_ADMIN)) {
spin_lock_irqsave(&lp->hw_lock, flags);
}
} else {
outb(0, EWRK3_MPR);
- isa_memcpy_fromio(tmp->addr, lp->shmem_base + PAGE0_HTE, (HASH_TABLE_LEN >> 3));
+ memcpy_fromio(tmp->addr, lp->shmem + PAGE0_HTE, (HASH_TABLE_LEN >> 3));
}
spin_unlock_irqrestore(&lp->hw_lock, flags);
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)");
int i;
for( i=0; i<ndevs; i++ ) {
- unregister_netdev(ewrk3_devs[i]);
- release_region(ewrk3_devs[i]->base_addr, EWRK3_TOTAL_SIZE);
- free_netdev(ewrk3_devs[i]);
+ struct net_device *dev = ewrk3_devs[i];
+ struct ewrk3_private *lp = netdev_priv(dev);
ewrk3_devs[i] = NULL;
+ unregister_netdev(dev);
+ release_region(dev->base_addr, EWRK3_TOTAL_SIZE);
+ iounmap(lp->shmem);
+ free_netdev(dev);
}
}
#endif /* MODULE */
MODULE_LICENSE("GPL");
-\f
+
/*
* Local variables: