Commit a04563a1 authored by Marc Zyngier's avatar Marc Zyngier Committed by Linus Torvalds

[PATCH] depca update (was Re: [Patch] DMA mapping API for Alpha)

this patch has been sleeping
in Alan tree for quite some time. It updates the depca driver to the
EISA/sysfs API, gets rid of check_region, and properly reserve memory
region. Patch is against latest BK.
parent 4a37c106
...@@ -230,6 +230,7 @@ ...@@ -230,6 +230,7 @@
by acme@conectiva.com.br by acme@conectiva.com.br
0.54 08-Nov-01 use library crc32 functions 0.54 08-Nov-01 use library crc32 functions
by Matt_Domsch@dell.com by Matt_Domsch@dell.com
0.55 01-Mar-03 Use EISA/sysfs framework <maz@wild-wind.fr.eu.org>
========================================================================= =========================================================================
*/ */
...@@ -263,6 +264,11 @@ ...@@ -263,6 +264,11 @@
#include <linux/mca.h> #include <linux/mca.h>
#endif #endif
#ifdef CONFIG_EISA
#include <linux/device.h>
#include <linux/eisa.h>
#endif
#include "depca.h" #include "depca.h"
static char version[] __initdata = "depca.c:v0.53 2001/1/12 davies@maniac.ultranet.com\n"; static char version[] __initdata = "depca.c:v0.53 2001/1/12 davies@maniac.ultranet.com\n";
...@@ -328,6 +334,25 @@ static enum { ...@@ -328,6 +334,25 @@ static enum {
DEPCA, de100, de101, de200, de201, de202, de210, de212, de422, unknown DEPCA, de100, de101, de200, de201, de202, de210, de212, de422, unknown
} adapter; } adapter;
#ifdef CONFIG_EISA
struct eisa_device_id depca_eisa_ids[] = {
{ "DEC4220" },
{ "" }
};
static int depca_eisa_probe (struct device *device);
static int depca_eisa_remove (struct device *device);
struct eisa_driver depca_eisa_driver = {
.id_table = depca_eisa_ids,
.driver = {
.name = "depca",
.probe = depca_eisa_probe,
.remove = __devexit_p (depca_eisa_remove)
}
};
#endif
/* /*
** Miscellaneous info... ** Miscellaneous info...
*/ */
...@@ -388,6 +413,8 @@ struct depca_private { ...@@ -388,6 +413,8 @@ struct depca_private {
void *rx_buff[NUM_RX_DESC]; /* CPU virt address of sh'd memory buffs */ void *rx_buff[NUM_RX_DESC]; /* CPU virt address of sh'd memory buffs */
void *tx_buff[NUM_TX_DESC]; /* CPU virt address of sh'd memory buffs */ void *tx_buff[NUM_TX_DESC]; /* CPU virt address of sh'd memory buffs */
void *sh_mem; /* CPU mapped virt address of device RAM */ void *sh_mem; /* CPU mapped virt address of device RAM */
u_long mem_start; /* Bus address of device RAM (before remap) */
u_long mem_len; /* device memory size */
/* Device address space fields */ /* Device address space fields */
u_long device_ram_start; /* Start of RAM in device addr space */ u_long device_ram_start; /* Start of RAM in device addr space */
/* Offsets used in both address spaces */ /* Offsets used in both address spaces */
...@@ -450,10 +477,8 @@ static int InitRestartDepca(struct net_device *dev); ...@@ -450,10 +477,8 @@ static int InitRestartDepca(struct net_device *dev);
static void DepcaSignature(char *name, u_long paddr); static void DepcaSignature(char *name, u_long paddr);
static int DevicePresent(u_long ioaddr); static int DevicePresent(u_long ioaddr);
static int get_hw_addr(struct net_device *dev); static int get_hw_addr(struct net_device *dev);
static int EISA_signature(char *name, s32 eisa_id);
static void SetMulticastFilter(struct net_device *dev); static void SetMulticastFilter(struct net_device *dev);
static void isa_probe(struct net_device *dev, u_long iobase); static void isa_probe(struct net_device *dev, u_long iobase);
static void eisa_probe(struct net_device *dev, u_long iobase);
#ifdef CONFIG_MCA #ifdef CONFIG_MCA
static void mca_probe(struct net_device *dev, u_long iobase); static void mca_probe(struct net_device *dev, u_long iobase);
#endif #endif
...@@ -503,7 +528,9 @@ int __init depca_probe(struct net_device *dev) ...@@ -503,7 +528,9 @@ int __init depca_probe(struct net_device *dev)
mca_probe(dev, iobase); mca_probe(dev, iobase);
#endif #endif
isa_probe(dev, iobase); isa_probe(dev, iobase);
eisa_probe(dev, iobase); #ifdef CONFIG_EISA
eisa_driver_register (&depca_eisa_driver);
#endif
if ((tmp == num_depcas) && (iobase != 0) && loading_module) { if ((tmp == num_depcas) && (iobase != 0) && loading_module) {
printk("%s: depca_probe() cannot find device at 0x%04lx.\n", dev->name, iobase); printk("%s: depca_probe() cannot find device at 0x%04lx.\n", dev->name, iobase);
...@@ -530,6 +557,7 @@ static int __init depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_s ...@@ -530,6 +557,7 @@ static int __init depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_s
int i, j, offset, netRAM, mem_len, status = 0; int i, j, offset, netRAM, mem_len, status = 0;
s16 nicsr; s16 nicsr;
u_long mem_start = 0, mem_base[] = DEPCA_RAM_BASE_ADDRESSES; u_long mem_start = 0, mem_base[] = DEPCA_RAM_BASE_ADDRESSES;
int is_eisa = ((ioaddr & 0x0fff) == DEPCA_EISA_IO_PORTS);
STOP_DEPCA; STOP_DEPCA;
...@@ -555,7 +583,7 @@ static int __init depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_s ...@@ -555,7 +583,7 @@ static int __init depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_s
if (mca_slot != -1) { if (mca_slot != -1) {
printk("%s: %s at 0x%04lx (MCA slot %d)", dev->name, name, ioaddr, mca_slot); printk("%s: %s at 0x%04lx (MCA slot %d)", dev->name, name, ioaddr, mca_slot);
} else if ((ioaddr & 0x0fff) == DEPCA_EISA_IO_PORTS) { /* EISA slot address */ } else if (is_eisa) { /* EISA slot address */
printk("%s: %s at 0x%04lx (EISA slot %d)", dev->name, name, ioaddr, (int) ((ioaddr >> 12) & 0x0f)); printk("%s: %s at 0x%04lx (EISA slot %d)", dev->name, name, ioaddr, (int) ((ioaddr >> 12) & 0x0f));
} else { /* ISA port address */ } else { /* ISA port address */
printk("%s: %s at 0x%04lx", dev->name, name, ioaddr); printk("%s: %s at 0x%04lx", dev->name, name, ioaddr);
...@@ -600,9 +628,11 @@ static int __init depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_s ...@@ -600,9 +628,11 @@ static int __init depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_s
} }
/* Define the device private memory */ /* Define the device private memory */
if (!is_eisa) {
dev->priv = (void *) kmalloc(sizeof(struct depca_private), GFP_KERNEL); dev->priv = (void *) kmalloc(sizeof(struct depca_private), GFP_KERNEL);
if (dev->priv == NULL) if (dev->priv == NULL)
return -ENOMEM; return -ENOMEM;
}
lp = (struct depca_private *) dev->priv; lp = (struct depca_private *) dev->priv;
memset((char *) dev->priv, 0, sizeof(struct depca_private)); memset((char *) dev->priv, 0, sizeof(struct depca_private));
lp->adapter = adapter; lp->adapter = adapter;
...@@ -610,18 +640,23 @@ static int __init depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_s ...@@ -610,18 +640,23 @@ static int __init depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_s
lp->lock = SPIN_LOCK_UNLOCKED; lp->lock = SPIN_LOCK_UNLOCKED;
sprintf(lp->adapter_name, "%s (%s)", name, dev->name); sprintf(lp->adapter_name, "%s (%s)", name, dev->name);
status = -EBUSY; status = -EBUSY;
if (!request_region(ioaddr, DEPCA_TOTAL_SIZE, lp->adapter_name)) {
printk(KERN_ERR "depca: I/O resource 0x%x @ 0x%lx busy\n", DEPCA_TOTAL_SIZE, ioaddr); /* Initialisation Block */
if (!request_mem_region (mem_start, mem_len, lp->adapter_name)) {
printk(KERN_ERR "depca: cannot request ISA memory, aborting\n");
goto out_priv; goto out_priv;
} }
/* Initialisation Block */
lp->sh_mem = ioremap(mem_start, mem_len);
status = -EIO; status = -EIO;
lp->sh_mem = ioremap(mem_start, mem_len);
if (lp->sh_mem == NULL) { if (lp->sh_mem == NULL) {
printk(KERN_ERR "depca: cannot remap ISA memory, aborting\n"); printk(KERN_ERR "depca: cannot remap ISA memory, aborting\n");
goto out_region; release_mem_region (mem_start, mem_len);
goto out_priv;
} }
lp->mem_start = mem_start;
lp->mem_len = mem_len;
lp->device_ram_start = mem_start & LA_MASK; lp->device_ram_start = mem_start & LA_MASK;
offset = 0; offset = 0;
...@@ -703,7 +738,7 @@ static int __init depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_s ...@@ -703,7 +738,7 @@ static int __init depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_s
status = -ENXIO; status = -ENXIO;
if (!irqnum) { if (!irqnum) {
printk(" and failed to detect IRQ line.\n"); printk(" and failed to detect IRQ line.\n");
goto out_region; goto out_priv;
} else { } else {
for (dev->irq = 0, i = 0; (depca_irq[i]) && (!dev->irq); i++) for (dev->irq = 0, i = 0; (depca_irq[i]) && (!dev->irq); i++)
if (irqnum == depca_irq[i]) { if (irqnum == depca_irq[i]) {
...@@ -714,7 +749,7 @@ static int __init depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_s ...@@ -714,7 +749,7 @@ static int __init depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_s
status = -ENXIO; status = -ENXIO;
if (!dev->irq) { if (!dev->irq) {
printk(" but incorrect IRQ line detected.\n"); printk(" but incorrect IRQ line detected.\n");
goto out_region; goto out_priv;
} }
} }
#endif /* MODULE */ #endif /* MODULE */
...@@ -739,13 +774,16 @@ static int __init depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_s ...@@ -739,13 +774,16 @@ static int __init depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_s
dev->mem_start = 0; dev->mem_start = 0;
/* Fill in the generic field of the device structure. */ /* Fill in the generic field of the device structure. */
if (!is_eisa)
ether_setup(dev); ether_setup(dev);
return 0; return 0;
out_region:
release_region(ioaddr, DEPCA_TOTAL_SIZE);
out_priv: out_priv:
if (!is_eisa) {
kfree(dev->priv); kfree(dev->priv);
dev->priv = NULL; dev->priv = NULL;
} else {
unregister_netdev (dev);
}
return status; return status;
} }
...@@ -1351,18 +1389,28 @@ static void __init mca_probe(struct net_device *dev, u_long ioaddr) ...@@ -1351,18 +1389,28 @@ static void __init mca_probe(struct net_device *dev, u_long ioaddr)
** Get everything allocated and initialized... (almost just ** Get everything allocated and initialized... (almost just
** like the ISA and EISA probes) ** like the ISA and EISA probes)
*/ */
if (!request_region (iobase, DEPCA_TOTAL_SIZE, "depca")) {
if (autoprobed)
printk(KERN_WARNING "%s: region already allocated at 0x%04lx.\n", dev->name, iobase);
goto next;
}
if (DevicePresent(iobase) != 0) { if (DevicePresent(iobase) != 0) {
/* /*
** If the MCA configuration says the card should be here, ** If the MCA configuration says the card should be here,
** it really should be here. ** it really should be here.
*/ */
printk(KERN_ERR "%s: MCA reports card at 0x%lx but it is not responding.\n", dev->name, iobase); printk(KERN_ERR "%s: MCA reports card at 0x%lx but it is not responding.\n", dev->name, iobase);
goto release_next;
} }
if (check_region(iobase, DEPCA_TOTAL_SIZE) == 0) { if (!(dev = alloc_device(dev, iobase)))
if ((dev = alloc_device(dev, iobase)) != NULL) { goto release_next;
num_eth++;
dev->irq = irq; dev->irq = irq;
if (depca_hw_init(dev, iobase, slot) == 0) { if (depca_hw_init(dev, iobase, slot))
goto release_next;
/* /*
** Adapter initialized correctly: Name it in ** Adapter initialized correctly: Name it in
** /proc/mca. ** /proc/mca.
...@@ -1370,12 +1418,6 @@ static void __init mca_probe(struct net_device *dev, u_long ioaddr) ...@@ -1370,12 +1418,6 @@ static void __init mca_probe(struct net_device *dev, u_long ioaddr)
mca_set_adapter_name(slot, "DE210/212 Ethernet Adapter"); mca_set_adapter_name(slot, "DE210/212 Ethernet Adapter");
mca_mark_as_used(slot); mca_mark_as_used(slot);
num_depcas++; num_depcas++;
}
num_eth++;
}
} else if (autoprobed) {
printk(KERN_WARNING "%s: region already allocated at 0x%04lx.\n", dev->name, iobase);
}
/* /*
** If this is a probe by a module, return after setting up the ** If this is a probe by a module, return after setting up the
...@@ -1388,6 +1430,12 @@ static void __init mca_probe(struct net_device *dev, u_long ioaddr) ...@@ -1388,6 +1430,12 @@ static void __init mca_probe(struct net_device *dev, u_long ioaddr)
** Set up to check the next slot and loop. ** Set up to check the next slot and loop.
*/ */
slot++; slot++;
continue;
release_next:
release_region (iobase, DEPCA_TOTAL_SIZE);
next:
slot++;
} }
} }
...@@ -1418,70 +1466,101 @@ static void __init isa_probe(struct net_device *dev, u_long ioaddr) ...@@ -1418,70 +1466,101 @@ static void __init isa_probe(struct net_device *dev, u_long ioaddr)
} }
for (; (i < maxSlots) && (dev != NULL) && ports[i]; i++) { for (; (i < maxSlots) && (dev != NULL) && ports[i]; i++) {
if (check_region(ports[i], DEPCA_TOTAL_SIZE) == 0) { if (!request_region (ports[i], DEPCA_TOTAL_SIZE, "depca")) {
if (DevicePresent(ports[i]) == 0) { if (autoprobed)
if ((dev = alloc_device(dev, ports[i])) != NULL) { printk("%s: region already allocated at 0x%04x.\n", dev->name, ports[i]);
if (depca_hw_init(dev, ports[i], -1) == 0) { continue;
num_depcas++;
} }
num_eth++;
if (DevicePresent(ports[i])) {
release_region (ports[i], DEPCA_TOTAL_SIZE);
continue;
} }
if (!(dev = alloc_device(dev, ports[i]))) {
release_region (ports[i], DEPCA_TOTAL_SIZE);
continue;
} }
} else if (autoprobed) {
printk("%s: region already allocated at 0x%04x.\n", dev->name, ports[i]); num_eth++;
if (depca_hw_init(dev, ports[i], -1)) {
release_region (ports[i], DEPCA_TOTAL_SIZE);
continue;
} }
num_depcas++;
} }
return; return;
} }
/* /*
** EISA bus I/O device probe. Probe from slot 1 since slot 0 is usually ** EISA callbacks from sysfs.
** the motherboard. Upto 15 EISA devices are supported.
*/ */
static void __init eisa_probe(struct net_device *dev, u_long ioaddr)
#ifdef CONFIG_EISA
static int __init depca_eisa_probe (struct device *device)
{ {
int i, maxSlots; struct eisa_device *edev;
struct net_device *dev;
u_long iobase; u_long iobase;
char name[DEPCA_STRLEN]; int status = 0;
if (!ioaddr && autoprobed) edev = to_eisa_device (device);
return; /* Been here before ! */ iobase = edev->base_addr + DEPCA_EISA_IO_PORTS;
if ((ioaddr < 0x400) && (ioaddr > 0))
return; /* ISA Address */
if (ioaddr == 0) { /* Autoprobing */ if (!request_region (iobase, DEPCA_TOTAL_SIZE, "depca")) {
iobase = EISA_SLOT_INC; /* Get the first slot address */ status = -EBUSY;
i = 1; goto out;
maxSlots = MAX_EISA_SLOTS;
} else { /* Probe a specific location */
iobase = ioaddr;
i = (ioaddr >> 12);
maxSlots = i + 1;
} }
if ((iobase & 0x0fff) == 0)
iobase += DEPCA_EISA_IO_PORTS;
for (; (i < maxSlots) && (dev != NULL); i++, iobase += EISA_SLOT_INC) { if (DevicePresent(iobase)) {
if (check_region(iobase, DEPCA_TOTAL_SIZE) == 0) { status = -ENODEV;
if (EISA_signature(name, EISA_ID)) { goto out_release;
if (DevicePresent(iobase) == 0) {
if ((dev = alloc_device(dev, iobase)) != NULL) {
if (depca_hw_init(dev, iobase, -1) == 0) {
num_depcas++;
}
num_eth++;
}
}
}
} else if (autoprobed) {
printk("%s: region already allocated at 0x%04lx.\n", dev->name, iobase);
} }
if (!(dev = init_etherdev (NULL, sizeof (struct depca_private)))) {
status = -ENOMEM;
goto out_release;
} }
return; eisa_set_drvdata (edev, dev);
if ((status = depca_hw_init(dev, iobase, -1)))
goto out_free;
num_depcas++;
return 0;
out_free:
kfree (dev);
out_release:
release_region (iobase, DEPCA_TOTAL_SIZE);
out:
return status;
} }
static int __devexit depca_eisa_remove (struct device *device)
{
struct net_device *dev;
struct eisa_device *edev;
struct depca_private *lp;
edev = to_eisa_device (device);
dev = eisa_get_drvdata (edev);
lp = dev->priv;
unregister_netdev (dev);
iounmap (lp->sh_mem);
release_mem_region (lp->mem_start, lp->mem_len);
release_region (dev->base_addr, DEPCA_TOTAL_SIZE);
kfree (dev);
return 0;
}
#endif
/* /*
** Search the entire 'eth' device list for a fixed probe. If a match isn't ** Search the entire 'eth' device list for a fixed probe. If a match isn't
** found then check for an autoprobe or unused device location. If they ** found then check for an autoprobe or unused device location. If they
...@@ -1781,40 +1860,6 @@ static int load_packet(struct net_device *dev, struct sk_buff *skb) ...@@ -1781,40 +1860,6 @@ static int load_packet(struct net_device *dev, struct sk_buff *skb)
return status; return status;
} }
/*
** Look for a particular board name in the EISA configuration space
*/
static int __init EISA_signature(char *name, s32 eisa_id)
{
u_int i;
const char *signatures[] = DEPCA_SIGNATURE;
char ManCode[DEPCA_STRLEN];
union {
s32 ID;
char Id[4];
} Eisa;
int status = 0;
*name = '\0';
Eisa.ID = inl(eisa_id);
ManCode[0] = (((Eisa.Id[0] >> 2) & 0x1f) + 0x40);
ManCode[1] = (((Eisa.Id[1] & 0xe0) >> 5) + ((Eisa.Id[0] & 0x03) << 3) + 0x40);
ManCode[2] = (((Eisa.Id[2] >> 4) & 0x0f) + 0x30);
ManCode[3] = ((Eisa.Id[2] & 0x0f) + 0x30);
ManCode[4] = (((Eisa.Id[3] >> 4) & 0x0f) + 0x30);
ManCode[5] = '\0';
for (i = 0; (*signatures[i] != '\0') && (*name == '\0'); i++) {
if (strstr(ManCode, signatures[i]) != NULL) {
strcpy(name, ManCode);
status = 1;
}
}
return status;
}
static void depca_dbg_open(struct net_device *dev) static void depca_dbg_open(struct net_device *dev)
{ {
struct depca_private *lp = (struct depca_private *) dev->priv; struct depca_private *lp = (struct depca_private *) dev->priv;
...@@ -2067,6 +2112,7 @@ void cleanup_module(void) ...@@ -2067,6 +2112,7 @@ void cleanup_module(void)
unregister_netdev(&thisDepca); unregister_netdev(&thisDepca);
if (lp) { if (lp) {
iounmap(lp->sh_mem); iounmap(lp->sh_mem);
release_mem_region (lp->mem_start, lp->mem_len);
#ifdef CONFIG_MCA #ifdef CONFIG_MCA
if (lp->mca_slot != -1) if (lp->mca_slot != -1)
mca_mark_as_unused(lp->mca_slot); mca_mark_as_unused(lp->mca_slot);
......
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