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

Bug fixes for Acorn network drivers.

parent 99675e6e
......@@ -718,7 +718,7 @@ dropping:{
/*
* 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;
printk("%s: memory squeeze, dropping packet.\n", dev->name);
}
......
/*
* 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
* it under the terms of the GNU General Public License version 2 as
......@@ -23,6 +23,7 @@
* 12-10-1999 CK/TEW EtherM driver first release
* 21-12-2000 TTC EtherH/EtherM integration
* 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>
......@@ -64,13 +65,18 @@ static const card_ids __init etherh_cids[] = {
{ 0xffff, 0xffff }
};
struct etherh_priv {
unsigned int id;
unsigned int ctrl_port;
unsigned int ctrl;
};
MODULE_AUTHOR("Russell King");
MODULE_DESCRIPTION("EtherH/EtherM driver");
MODULE_LICENSE("GPL");
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_NS8390 0x000 /* MEMC */
......@@ -97,18 +103,61 @@ static char version[] __initdata =
#define ETHERM_TX_START_PAGE 64
#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
etherh_setif(struct net_device *dev)
{
struct ei_device *ei_local = (struct ei_device *) dev->priv;
struct etherh_priv *eh = (struct etherh_priv *)dev->rmem_start;
unsigned long addr, flags;
save_flags_cli(flags);
local_irq_save(flags);
/* set the interface type */
switch (dev->mem_end) {
switch (eh->id) {
case PROD_I3_ETHERLAN600:
case PROD_I3_ETHERLAN600A:
addr = dev->base_addr + EN0_RCNTHI;
......@@ -124,14 +173,13 @@ etherh_setif(struct net_device *dev)
break;
case PROD_I3_ETHERLAN500:
addr = dev->rmem_start;
switch (dev->if_port) {
case IF_PORT_10BASE2:
outb(inb(addr) & ~ETHERH_CP_IF, addr);
etherh_clr_ctrl(eh, ETHERH_CP_IF);
break;
case IF_PORT_10BASET:
outb(inb(addr) | ETHERH_CP_IF, addr);
etherh_set_ctrl(eh, ETHERH_CP_IF);
break;
}
break;
......@@ -140,16 +188,17 @@ etherh_setif(struct net_device *dev)
break;
}
restore_flags(flags);
local_irq_restore(flags);
}
static int
etherh_getifstat(struct net_device *dev)
{
struct ei_device *ei_local = (struct ei_device *) dev->priv;
struct etherh_priv *eh = (struct etherh_priv *)dev->rmem_start;
int stat = 0;
switch (dev->mem_end) {
switch (eh->id) {
case PROD_I3_ETHERLAN600:
case PROD_I3_ETHERLAN600A:
switch (dev->if_port) {
......@@ -168,7 +217,7 @@ etherh_getifstat(struct net_device *dev)
stat = 1;
break;
case IF_PORT_10BASET:
stat = inb(dev->rmem_start) & ETHERH_CP_HEARTBEAT;
stat = etherh_get_stat(eh) & ETHERH_CP_HEARTBEAT;
break;
}
break;
......@@ -251,7 +300,13 @@ etherh_block_output (struct net_device *dev, int count, const unsigned char *buf
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;
dma_addr = dev->mem_start;
......@@ -291,7 +346,7 @@ etherh_block_output (struct net_device *dev, int count, const unsigned char *buf
}
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
return;
}
ei_local->dmaing |= 1;
ei_local->dmaing = 1;
addr = dev->base_addr;
dma_addr = dev->mem_start;
......@@ -332,7 +387,7 @@ etherh_block_input (struct net_device *dev, int count, struct sk_buff *skb, int
insb (dma_addr, buf, count);
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
return;
}
ei_local->dmaing |= 1;
ei_local->dmaing = 1;
addr = dev->base_addr;
dma_addr = dev->mem_start;
......@@ -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));
outb (ENISR_RDC, addr + EN0_ISR);
ei_local->dmaing &= ~1;
ei_local->dmaing = 0;
}
/*
......@@ -427,23 +482,6 @@ etherh_close(struct net_device *dev)
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
*/
......@@ -506,6 +544,7 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec)
{
struct ei_device *ei_local;
struct net_device *dev;
struct etherh_priv *eh;
const char *dev_type;
int i, size;
......@@ -517,6 +556,10 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec)
if (!dev)
goto out;
eh = kmalloc(sizeof(struct etherh_priv), GFP_KERNEL);
if (!eh)
goto out_nopriv;
SET_MODULE_OWNER(dev);
dev->open = etherh_open;
......@@ -524,8 +567,15 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec)
dev->set_config = etherh_set_config;
dev->irq = ec->irq;
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->irq_data = eh;
eh->ctrl = 0;
eh->id = ec->cid.product;
switch (ec->cid.product) {
case PROD_ANT_ETHERM:
......@@ -533,7 +583,7 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec)
goto free;
dev->base_addr += ETHERM_NS8390;
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;
case PROD_I3_ETHERLAN500:
......@@ -541,8 +591,7 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec)
goto free;
dev->base_addr += ETHERH500_NS8390;
dev->mem_start = dev->base_addr + ETHERH500_DATAPORT;
dev->rmem_start = (unsigned long)
ec->irq_data = (void *)ecard_address (ec, ECARD_IOC, ECARD_FAST)
eh->ctrl_port = ecard_address (ec, ECARD_IOC, ECARD_FAST)
+ ETHERH500_CTRLPORT;
break;
......@@ -552,7 +601,7 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec)
goto free;
dev->base_addr += ETHERH600_NS8390;
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;
default:
......@@ -571,6 +620,12 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec)
if (ethdev_init(dev))
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
* ether_setup, which re-writes dev->flags.
......@@ -636,6 +691,8 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec)
release:
release_region(dev->base_addr, 16);
free:
kfree(eh);
out_nopriv:
unregister_netdev(dev);
kfree(dev);
out:
......@@ -696,6 +753,7 @@ static void __exit etherh_exit(void)
}
if (e_card[i]) {
e_card[i]->ops = NULL;
kfree(e_card[i]->irq_data);
ecard_release(e_card[i]);
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