Commit 1a4457da authored by Russell King's avatar Russell King

Bug fixes for Acorn network drivers.

parent 99675e6e
...@@ -718,7 +718,7 @@ dropping:{ ...@@ -718,7 +718,7 @@ dropping:{
/* /*
* Don't print this message too many times... * Don't print this message too many times...
*/ */
if (jiffies - last_warned > 30 * HZ) { if (time_after(jiffies, last_warned + 10 * HZ)) {
last_warned = jiffies; last_warned = jiffies;
printk("%s: memory squeeze, dropping packet.\n", dev->name); printk("%s: memory squeeze, dropping packet.\n", dev->name);
} }
......
/* /*
* linux/drivers/acorn/net/etherh.c * linux/drivers/acorn/net/etherh.c
* *
* Copyright (C) 2000 Russell King * Copyright (C) 2000-2002 Russell King
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as * it under the terms of the GNU General Public License version 2 as
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
* 12-10-1999 CK/TEW EtherM driver first release * 12-10-1999 CK/TEW EtherM driver first release
* 21-12-2000 TTC EtherH/EtherM integration * 21-12-2000 TTC EtherH/EtherM integration
* 25-12-2000 RMK 1.08 Clean integration of EtherM into this driver. * 25-12-2000 RMK 1.08 Clean integration of EtherM into this driver.
* 03-01-2002 RMK 1.09 Always enable IRQs if we're in the nic slot.
*/ */
#include <linux/module.h> #include <linux/module.h>
...@@ -64,13 +65,18 @@ static const card_ids __init etherh_cids[] = { ...@@ -64,13 +65,18 @@ static const card_ids __init etherh_cids[] = {
{ 0xffff, 0xffff } { 0xffff, 0xffff }
}; };
struct etherh_priv {
unsigned int id;
unsigned int ctrl_port;
unsigned int ctrl;
};
MODULE_AUTHOR("Russell King"); MODULE_AUTHOR("Russell King");
MODULE_DESCRIPTION("EtherH/EtherM driver"); MODULE_DESCRIPTION("EtherH/EtherM driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
static char version[] __initdata = static char version[] __initdata =
"EtherH/EtherM Driver (c) 2000 Russell King v1.08\n"; "EtherH/EtherM Driver (c) 2002 Russell King v1.09\n";
#define ETHERH500_DATAPORT 0x200 /* MEMC */ #define ETHERH500_DATAPORT 0x200 /* MEMC */
#define ETHERH500_NS8390 0x000 /* MEMC */ #define ETHERH500_NS8390 0x000 /* MEMC */
...@@ -97,18 +103,61 @@ static char version[] __initdata = ...@@ -97,18 +103,61 @@ static char version[] __initdata =
#define ETHERM_TX_START_PAGE 64 #define ETHERM_TX_START_PAGE 64
#define ETHERM_STOP_PAGE 127 #define ETHERM_STOP_PAGE 127
/* --------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------ */
static inline void etherh_set_ctrl(struct etherh_priv *eh, unsigned int mask)
{
eh->ctrl |= mask;
outb(eh->ctrl, eh->ctrl_port);
}
static inline void etherh_clr_ctrl(struct etherh_priv *eh, unsigned int mask)
{
eh->ctrl &= ~mask;
outb(eh->ctrl, eh->ctrl_port);
}
static inline unsigned int etherh_get_stat(struct etherh_priv *eh)
{
return inb(eh->ctrl_port);
}
static void etherh_irq_enable(ecard_t *ec, int irqnr)
{
struct etherh_priv *eh = ec->irq_data;
etherh_set_ctrl(eh, ETHERH_CP_IE);
}
static void etherh_irq_disable(ecard_t *ec, int irqnr)
{
struct etherh_priv *eh = ec->irq_data;
etherh_clr_ctrl(eh, ETHERH_CP_IE);
}
static expansioncard_ops_t etherh_ops = {
irqenable: etherh_irq_enable,
irqdisable: etherh_irq_disable,
};
static void static void
etherh_setif(struct net_device *dev) etherh_setif(struct net_device *dev)
{ {
struct ei_device *ei_local = (struct ei_device *) dev->priv; struct ei_device *ei_local = (struct ei_device *) dev->priv;
struct etherh_priv *eh = (struct etherh_priv *)dev->rmem_start;
unsigned long addr, flags; unsigned long addr, flags;
save_flags_cli(flags); local_irq_save(flags);
/* set the interface type */ /* set the interface type */
switch (dev->mem_end) { switch (eh->id) {
case PROD_I3_ETHERLAN600: case PROD_I3_ETHERLAN600:
case PROD_I3_ETHERLAN600A: case PROD_I3_ETHERLAN600A:
addr = dev->base_addr + EN0_RCNTHI; addr = dev->base_addr + EN0_RCNTHI;
...@@ -124,14 +173,13 @@ etherh_setif(struct net_device *dev) ...@@ -124,14 +173,13 @@ etherh_setif(struct net_device *dev)
break; break;
case PROD_I3_ETHERLAN500: case PROD_I3_ETHERLAN500:
addr = dev->rmem_start;
switch (dev->if_port) { switch (dev->if_port) {
case IF_PORT_10BASE2: case IF_PORT_10BASE2:
outb(inb(addr) & ~ETHERH_CP_IF, addr); etherh_clr_ctrl(eh, ETHERH_CP_IF);
break; break;
case IF_PORT_10BASET: case IF_PORT_10BASET:
outb(inb(addr) | ETHERH_CP_IF, addr); etherh_set_ctrl(eh, ETHERH_CP_IF);
break; break;
} }
break; break;
...@@ -140,16 +188,17 @@ etherh_setif(struct net_device *dev) ...@@ -140,16 +188,17 @@ etherh_setif(struct net_device *dev)
break; break;
} }
restore_flags(flags); local_irq_restore(flags);
} }
static int static int
etherh_getifstat(struct net_device *dev) etherh_getifstat(struct net_device *dev)
{ {
struct ei_device *ei_local = (struct ei_device *) dev->priv; struct ei_device *ei_local = (struct ei_device *) dev->priv;
struct etherh_priv *eh = (struct etherh_priv *)dev->rmem_start;
int stat = 0; int stat = 0;
switch (dev->mem_end) { switch (eh->id) {
case PROD_I3_ETHERLAN600: case PROD_I3_ETHERLAN600:
case PROD_I3_ETHERLAN600A: case PROD_I3_ETHERLAN600A:
switch (dev->if_port) { switch (dev->if_port) {
...@@ -168,7 +217,7 @@ etherh_getifstat(struct net_device *dev) ...@@ -168,7 +217,7 @@ etherh_getifstat(struct net_device *dev)
stat = 1; stat = 1;
break; break;
case IF_PORT_10BASET: case IF_PORT_10BASET:
stat = inb(dev->rmem_start) & ETHERH_CP_HEARTBEAT; stat = etherh_get_stat(eh) & ETHERH_CP_HEARTBEAT;
break; break;
} }
break; break;
...@@ -251,7 +300,13 @@ etherh_block_output (struct net_device *dev, int count, const unsigned char *buf ...@@ -251,7 +300,13 @@ etherh_block_output (struct net_device *dev, int count, const unsigned char *buf
return; return;
} }
ei_local->dmaing |= 1; /*
* Make sure we have a round number of bytes if we're in word mode.
*/
if (count & 1 && ei_local->word16)
count++;
ei_local->dmaing = 1;
addr = dev->base_addr; addr = dev->base_addr;
dma_addr = dev->mem_start; dma_addr = dev->mem_start;
...@@ -291,7 +346,7 @@ etherh_block_output (struct net_device *dev, int count, const unsigned char *buf ...@@ -291,7 +346,7 @@ etherh_block_output (struct net_device *dev, int count, const unsigned char *buf
} }
outb (ENISR_RDC, addr + EN0_ISR); outb (ENISR_RDC, addr + EN0_ISR);
ei_local->dmaing &= ~1; ei_local->dmaing = 0;
} }
/* /*
...@@ -311,7 +366,7 @@ etherh_block_input (struct net_device *dev, int count, struct sk_buff *skb, int ...@@ -311,7 +366,7 @@ etherh_block_input (struct net_device *dev, int count, struct sk_buff *skb, int
return; return;
} }
ei_local->dmaing |= 1; ei_local->dmaing = 1;
addr = dev->base_addr; addr = dev->base_addr;
dma_addr = dev->mem_start; dma_addr = dev->mem_start;
...@@ -332,7 +387,7 @@ etherh_block_input (struct net_device *dev, int count, struct sk_buff *skb, int ...@@ -332,7 +387,7 @@ etherh_block_input (struct net_device *dev, int count, struct sk_buff *skb, int
insb (dma_addr, buf, count); insb (dma_addr, buf, count);
outb (ENISR_RDC, addr + EN0_ISR); outb (ENISR_RDC, addr + EN0_ISR);
ei_local->dmaing &= ~1; ei_local->dmaing = 0;
} }
/* /*
...@@ -351,7 +406,7 @@ etherh_get_header (struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_p ...@@ -351,7 +406,7 @@ etherh_get_header (struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_p
return; return;
} }
ei_local->dmaing |= 1; ei_local->dmaing = 1;
addr = dev->base_addr; addr = dev->base_addr;
dma_addr = dev->mem_start; dma_addr = dev->mem_start;
...@@ -369,7 +424,7 @@ etherh_get_header (struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_p ...@@ -369,7 +424,7 @@ etherh_get_header (struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_p
insb (dma_addr, hdr, sizeof (*hdr)); insb (dma_addr, hdr, sizeof (*hdr));
outb (ENISR_RDC, addr + EN0_ISR); outb (ENISR_RDC, addr + EN0_ISR);
ei_local->dmaing &= ~1; ei_local->dmaing = 0;
} }
/* /*
...@@ -427,23 +482,6 @@ etherh_close(struct net_device *dev) ...@@ -427,23 +482,6 @@ etherh_close(struct net_device *dev)
return 0; return 0;
} }
static void etherh_irq_enable(ecard_t *ec, int irqnr)
{
unsigned int ctrl_addr = (unsigned int)ec->irq_data;
outb(inb(ctrl_addr) | ETHERH_CP_IE, ctrl_addr);
}
static void etherh_irq_disable(ecard_t *ec, int irqnr)
{
unsigned int ctrl_addr = (unsigned int)ec->irq_data;
outb(inb(ctrl_addr) & ~ETHERH_CP_IE, ctrl_addr);
}
static expansioncard_ops_t etherh_ops = {
irqenable: etherh_irq_enable,
irqdisable: etherh_irq_disable,
};
/* /*
* Initialisation * Initialisation
*/ */
...@@ -506,6 +544,7 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec) ...@@ -506,6 +544,7 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec)
{ {
struct ei_device *ei_local; struct ei_device *ei_local;
struct net_device *dev; struct net_device *dev;
struct etherh_priv *eh;
const char *dev_type; const char *dev_type;
int i, size; int i, size;
...@@ -517,6 +556,10 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec) ...@@ -517,6 +556,10 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec)
if (!dev) if (!dev)
goto out; goto out;
eh = kmalloc(sizeof(struct etherh_priv), GFP_KERNEL);
if (!eh)
goto out_nopriv;
SET_MODULE_OWNER(dev); SET_MODULE_OWNER(dev);
dev->open = etherh_open; dev->open = etherh_open;
...@@ -524,8 +567,15 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec) ...@@ -524,8 +567,15 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec)
dev->set_config = etherh_set_config; dev->set_config = etherh_set_config;
dev->irq = ec->irq; dev->irq = ec->irq;
dev->base_addr = ecard_address(ec, ECARD_MEMC, 0); dev->base_addr = ecard_address(ec, ECARD_MEMC, 0);
dev->mem_end = ec->cid.product; dev->rmem_start = (unsigned long)eh;
/*
* IRQ and control port handling
*/
ec->ops = &etherh_ops; ec->ops = &etherh_ops;
ec->irq_data = eh;
eh->ctrl = 0;
eh->id = ec->cid.product;
switch (ec->cid.product) { switch (ec->cid.product) {
case PROD_ANT_ETHERM: case PROD_ANT_ETHERM:
...@@ -533,7 +583,7 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec) ...@@ -533,7 +583,7 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec)
goto free; goto free;
dev->base_addr += ETHERM_NS8390; dev->base_addr += ETHERM_NS8390;
dev->mem_start = dev->base_addr + ETHERM_DATAPORT; dev->mem_start = dev->base_addr + ETHERM_DATAPORT;
ec->irq_data = (void *)(dev->base_addr + ETHERM_CTRLPORT); eh->ctrl_port = dev->base_addr + ETHERM_CTRLPORT;
break; break;
case PROD_I3_ETHERLAN500: case PROD_I3_ETHERLAN500:
...@@ -541,8 +591,7 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec) ...@@ -541,8 +591,7 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec)
goto free; goto free;
dev->base_addr += ETHERH500_NS8390; dev->base_addr += ETHERH500_NS8390;
dev->mem_start = dev->base_addr + ETHERH500_DATAPORT; dev->mem_start = dev->base_addr + ETHERH500_DATAPORT;
dev->rmem_start = (unsigned long) eh->ctrl_port = ecard_address (ec, ECARD_IOC, ECARD_FAST)
ec->irq_data = (void *)ecard_address (ec, ECARD_IOC, ECARD_FAST)
+ ETHERH500_CTRLPORT; + ETHERH500_CTRLPORT;
break; break;
...@@ -551,8 +600,8 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec) ...@@ -551,8 +600,8 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec)
if (etherh_addr(dev->dev_addr, ec)) if (etherh_addr(dev->dev_addr, ec))
goto free; goto free;
dev->base_addr += ETHERH600_NS8390; dev->base_addr += ETHERH600_NS8390;
dev->mem_start = dev->base_addr + ETHERH600_DATAPORT; dev->mem_start = dev->base_addr + ETHERH600_DATAPORT;
ec->irq_data = (void *)(dev->base_addr + ETHERH600_CTRLPORT); eh->ctrl_port = dev->base_addr + ETHERH600_CTRLPORT;
break; break;
default: default:
...@@ -571,6 +620,12 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec) ...@@ -571,6 +620,12 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec)
if (ethdev_init(dev)) if (ethdev_init(dev))
goto release; goto release;
/*
* If we're in the NIC slot, make sure the IRQ is enabled
*/
if (dev->irq == 11)
etherh_set_ctrl(eh, ETHERH_CP_IE);
/* /*
* Unfortunately, ethdev_init eventually calls * Unfortunately, ethdev_init eventually calls
* ether_setup, which re-writes dev->flags. * ether_setup, which re-writes dev->flags.
...@@ -636,6 +691,8 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec) ...@@ -636,6 +691,8 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec)
release: release:
release_region(dev->base_addr, 16); release_region(dev->base_addr, 16);
free: free:
kfree(eh);
out_nopriv:
unregister_netdev(dev); unregister_netdev(dev);
kfree(dev); kfree(dev);
out: out:
...@@ -696,6 +753,7 @@ static void __exit etherh_exit(void) ...@@ -696,6 +753,7 @@ static void __exit etherh_exit(void)
} }
if (e_card[i]) { if (e_card[i]) {
e_card[i]->ops = NULL; e_card[i]->ops = NULL;
kfree(e_card[i]->irq_data);
ecard_release(e_card[i]); ecard_release(e_card[i]);
e_card[i] = NULL; e_card[i] = NULL;
} }
......
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