Commit e739c970 authored by James Bottomley's avatar James Bottomley

update smc-mca to new MCA API

This updates to the new API and means that smc-mca is now probed similarly to a PCI device
parent 17445dc8
...@@ -48,7 +48,6 @@ extern int ne2_probe(struct net_device *dev); ...@@ -48,7 +48,6 @@ extern int ne2_probe(struct net_device *dev);
extern int hp100_probe(struct net_device *dev); extern int hp100_probe(struct net_device *dev);
extern int ultra_probe(struct net_device *dev); extern int ultra_probe(struct net_device *dev);
extern int ultra32_probe(struct net_device *dev); extern int ultra32_probe(struct net_device *dev);
extern int ultramca_probe(struct net_device *dev);
extern int wd_probe(struct net_device *dev); extern int wd_probe(struct net_device *dev);
extern int el2_probe(struct net_device *dev); extern int el2_probe(struct net_device *dev);
extern int ne_probe(struct net_device *dev); extern int ne_probe(struct net_device *dev);
...@@ -192,9 +191,6 @@ static struct devprobe eisa_probes[] __initdata = { ...@@ -192,9 +191,6 @@ static struct devprobe eisa_probes[] __initdata = {
static struct devprobe mca_probes[] __initdata = { static struct devprobe mca_probes[] __initdata = {
#ifdef CONFIG_ULTRAMCA
{ultramca_probe, 0},
#endif
#ifdef CONFIG_NE2_MCA #ifdef CONFIG_NE2_MCA
{ne2_probe, 0}, {ne2_probe, 0},
#endif #endif
......
...@@ -53,8 +53,6 @@ ...@@ -53,8 +53,6 @@
#include "smc-mca.h" #include "smc-mca.h"
#include <linux/mca.h> #include <linux/mca.h>
int ultramca_probe(struct net_device *dev);
static int ultramca_open(struct net_device *dev); static int ultramca_open(struct net_device *dev);
static void ultramca_reset_8390(struct net_device *dev); static void ultramca_reset_8390(struct net_device *dev);
static void ultramca_get_8390_hdr(struct net_device *dev, static void ultramca_get_8390_hdr(struct net_device *dev,
...@@ -91,37 +89,57 @@ struct smc_mca_adapters_t { ...@@ -91,37 +89,57 @@ struct smc_mca_adapters_t {
char *name; char *name;
}; };
static struct smc_mca_adapters_t smc_mca_adapters[] __initdata = { #define MAX_ULTRAMCA_CARDS 4 /* Max number of Ultra cards per module */
{ 0x61c8, "SMC Ethercard PLUS Elite/A BNC/AUI (WD8013EP/A)" },
{ 0x61c9, "SMC Ethercard PLUS Elite/A UTP/AUI (WD8013WP/A)" }, static int ultra_io[MAX_ULTRAMCA_CARDS];
{ 0x6fc0, "WD Ethercard PLUS/A (WD8003E/A or WD8003ET/A)" }, static int ultra_irq[MAX_ULTRAMCA_CARDS];
{ 0x6fc1, "WD Starcard PLUS/A (WD8003ST/A)" }, MODULE_LICENSE("GPL");
{ 0x6fc2, "WD Ethercard PLUS 10T/A (WD8003W/A)" },
{ 0xefd4, "IBM PS/2 Adapter/A for Ethernet UTP/AUI (WD8013WP/A)" }, MODULE_PARM(ultra_io, "1-" __MODULE_STRING(MAX_ULTRAMCA_CARDS) "i");
{ 0xefd5, "IBM PS/2 Adapter/A for Ethernet BNC/AUI (WD8013EP/A)" }, MODULE_PARM(ultra_irq, "1-" __MODULE_STRING(MAX_ULTRAMCA_CARDS) "i");
{ 0xefe5, "IBM PS/2 Adapter/A for Ethernet" }, MODULE_PARM_DESC(ultra_io, "SMC Ultra/EtherEZ MCA I/O base address(es)");
{ 0x0000, NULL } MODULE_PARM_DESC(ultra_irq, "SMC Ultra/EtherEZ MCA IRQ number(s)");
static short smc_mca_adapter_ids[] __initdata = {
0x61c8,
0x61c9,
0x6fc0,
0x6fc1,
0x6fc2,
0xefd4,
0xefd5,
0xefe5,
0x0000
};
static char *smc_mca_adapter_names[] __initdata = {
"SMC Ethercard PLUS Elite/A BNC/AUI (WD8013EP/A)",
"SMC Ethercard PLUS Elite/A UTP/AUI (WD8013WP/A)",
"WD Ethercard PLUS/A (WD8003E/A or WD8003ET/A)",
"WD Starcard PLUS/A (WD8003ST/A)",
"WD Ethercard PLUS 10T/A (WD8003W/A)",
"IBM PS/2 Adapter/A for Ethernet UTP/AUI (WD8013WP/A)",
"IBM PS/2 Adapter/A for Ethernet BNC/AUI (WD8013EP/A)",
"IBM PS/2 Adapter/A for Ethernet",
NULL
}; };
int __init ultramca_probe(struct net_device *dev) static int ultra_found = 0;
int __init ultramca_probe(struct device *gen_dev)
{ {
unsigned short ioaddr; unsigned short ioaddr;
struct net_device *dev;
unsigned char reg4, num_pages; unsigned char reg4, num_pages;
char slot = -1; struct mca_device *mca_dev = to_mca_device(gen_dev);
char slot = mca_dev->slot;
unsigned char pos2 = 0xff, pos3 = 0xff, pos4 = 0xff, pos5 = 0xff; unsigned char pos2 = 0xff, pos3 = 0xff, pos4 = 0xff, pos5 = 0xff;
int i, j; int i;
int adapter_found = 0; int adapter = mca_dev->index;
int adapter = 0;
int tbase = 0; int tbase = 0;
int tirq = 0; int tirq = 0;
int base_addr = dev->base_addr; int base_addr = ultra_io[ultra_found];
int irq = dev->irq; int irq = ultra_irq[ultra_found];
if (!MCA_bus) {
return -ENODEV;
}
SET_MODULE_OWNER(dev);
if (base_addr || irq) { if (base_addr || irq) {
printk(KERN_INFO "Probing for SMC MCA adapter"); printk(KERN_INFO "Probing for SMC MCA adapter");
...@@ -134,82 +152,76 @@ int __init ultramca_probe(struct net_device *dev) ...@@ -134,82 +152,76 @@ int __init ultramca_probe(struct net_device *dev)
} }
} }
/* proper multicard detection by ZP Gu (zpg@castle.net) */ tirq = 0;
tbase = 0;
for (j = 0; (smc_mca_adapters[j].name != NULL) && !adapter_found; j++) {
slot = mca_find_unused_adapter(smc_mca_adapters[j].id, 0); /* If we're trying to match a specificied irq or io address,
* we'll reject the adapter found unless it's the one we're
while((slot != MCA_NOTFOUND) && !adapter_found) { * looking for */
tirq = 0;
tbase = 0; pos2 = mca_device_read_stored_pos(mca_dev, 2); /* io_addr */
pos3 = mca_device_read_stored_pos(mca_dev, 3); /* shared mem */
/* If we're trying to match a specificied irq or pos4 = mca_device_read_stored_pos(mca_dev, 4); /* ROM bios addr range */
* io address, we'll reject the adapter pos5 = mca_device_read_stored_pos(mca_dev, 5); /* irq, media and RIPL */
* found unless it's the one we're looking for
*/ /* Test the following conditions:
* - If an irq parameter is supplied, compare it
pos2 = mca_read_stored_pos(slot, 2); /* io_addr */ * with the irq of the adapter we found
pos3 = mca_read_stored_pos(slot, 3); /* shared mem */ * - If a base_addr paramater is given, compare it
pos4 = mca_read_stored_pos(slot, 4); /* ROM bios addr * with the base_addr of the adapter we found
* range */ * - Check that the irq and the base_addr of the
pos5 = mca_read_stored_pos(slot, 5); /* irq, media * adapter we found is not already in use by
* and RIPL */ * this driver
*/
/* Test the following conditions:
* - If an irq parameter is supplied, compare it
* with the irq of the adapter we found
* - If a base_addr paramater is given, compare it
* with the base_addr of the adapter we found
* - Check that the irq and the base_addr of the
* adapter we found is not already in use by
* this driver
*/
switch (j) { /* j = card-idx (card array above) [hs] */
case _61c8_SMC_Ethercard_PLUS_Elite_A_BNC_AUI_WD8013EP_A:
case _61c9_SMC_Ethercard_PLUS_Elite_A_UTP_AUI_WD8013EP_A:
case _efd4_IBM_PS2_Adapter_A_for_Ethernet_UTP_AUI_WD8013WP_A:
case _efd5_IBM_PS2_Adapter_A_for_Ethernet_BNC_AUI_WD8013WP_A:
{
tbase = addr_table[(pos2 & 0xf0) >> 4].base_addr;
tirq = irq_table[(pos5 & 0xc) >> 2].new_irq;
break;
}
case _6fc0_WD_Ethercard_PLUS_A_WD8003E_A_OR_WD8003ET_A:
case _6fc1_WD_Starcard_PLUS_A_WD8003ST_A:
case _6fc2_WD_Ethercard_PLUS_10T_A_WD8003W_A:
case _efe5_IBM_PS2_Adapter_A_for_Ethernet:
{
tbase = ((pos2 & 0x0fe) * 0x10);
tirq = irq_table[(pos5 & 3)].old_irq;
break;
}
}
if(!tirq || !tbase || (irq && irq != tirq) || (base_addr && tbase != base_addr)) { switch (mca_dev->index) {
slot = mca_find_unused_adapter(smc_mca_adapters[j].id, slot + 1); case _61c8_SMC_Ethercard_PLUS_Elite_A_BNC_AUI_WD8013EP_A:
} else { case _61c9_SMC_Ethercard_PLUS_Elite_A_UTP_AUI_WD8013EP_A:
adapter_found = 1; case _efd4_IBM_PS2_Adapter_A_for_Ethernet_UTP_AUI_WD8013WP_A:
adapter = j; case _efd5_IBM_PS2_Adapter_A_for_Ethernet_BNC_AUI_WD8013WP_A:
} {
tbase = addr_table[(pos2 & 0xf0) >> 4].base_addr;
tirq = irq_table[(pos5 & 0xc) >> 2].new_irq;
break;
}
case _6fc0_WD_Ethercard_PLUS_A_WD8003E_A_OR_WD8003ET_A:
case _6fc1_WD_Starcard_PLUS_A_WD8003ST_A:
case _6fc2_WD_Ethercard_PLUS_10T_A_WD8003W_A:
case _efe5_IBM_PS2_Adapter_A_for_Ethernet:
{
tbase = ((pos2 & 0x0fe) * 0x10);
tirq = irq_table[(pos5 & 3)].old_irq;
break;
} }
} }
if(!adapter_found) { if(!tirq || !tbase
return ((base_addr || irq) ? -ENXIO : -ENODEV); || (irq && irq != tirq)
} || (base_addr && tbase != base_addr))
/* FIXME: we're trying to force the ordering of the
* devices here, there should be a way of getting this
* to happen */
return -ENXIO;
/* Adapter found. */ /* Adapter found. */
dev = alloc_etherdev(0);
if(!dev)
return -ENODEV;
SET_MODULE_OWNER(dev);
if((i = register_netdev(dev)) != 0)
return i;
printk(KERN_INFO "%s: %s found in slot %d\n", printk(KERN_INFO "%s: %s found in slot %d\n",
dev->name, smc_mca_adapters[adapter].name, slot + 1); dev->name, smc_mca_adapter_names[adapter], slot + 1);
mca_set_adapter_name(slot, smc_mca_adapters[adapter].name); strncpy(gen_dev->name, smc_mca_adapter_names[adapter], sizeof(gen_dev->name));
mca_mark_as_used(slot); mca_device_set_claim(mca_dev, 1);
dev->base_addr = ioaddr = tbase; dev->base_addr = ioaddr = mca_device_transform_ioport(mca_dev, tbase);
dev->irq = tirq; dev->irq = mca_device_transform_irq(mca_dev, tirq);
dev->mem_start = 0; dev->mem_start = 0;
num_pages = 40; num_pages = 40;
...@@ -220,7 +232,8 @@ int __init ultramca_probe(struct net_device *dev) ...@@ -220,7 +232,8 @@ int __init ultramca_probe(struct net_device *dev)
for (i = 0; i < 16; i++) { /* taking 16 counts for (i = 0; i < 16; i++) { /* taking 16 counts
* up to 15 [hs] */ * up to 15 [hs] */
if (mem_table[i].mem_index == (pos3 & ~MEM_MASK)) { if (mem_table[i].mem_index == (pos3 & ~MEM_MASK)) {
dev->mem_start = mem_table[i].mem_start; dev->mem_start = (unsigned long)
mca_device_transform_memory(mca_dev, (void *)mem_table[i].mem_start);
num_pages = mem_table[i].num_pages; num_pages = mem_table[i].num_pages;
} }
} }
...@@ -231,7 +244,8 @@ int __init ultramca_probe(struct net_device *dev) ...@@ -231,7 +244,8 @@ int __init ultramca_probe(struct net_device *dev)
case _6fc2_WD_Ethercard_PLUS_10T_A_WD8003W_A: case _6fc2_WD_Ethercard_PLUS_10T_A_WD8003W_A:
case _efe5_IBM_PS2_Adapter_A_for_Ethernet: case _efe5_IBM_PS2_Adapter_A_for_Ethernet:
{ {
dev->mem_start = ((pos3 & 0xfc) * 0x1000); dev->mem_start = (unsigned long)
mca_device_transform_memory(mca_dev, (void *)((pos3 & 0xfc) * 0x1000));
num_pages = 0x40; num_pages = 0x40;
break; break;
} }
...@@ -242,7 +256,8 @@ int __init ultramca_probe(struct net_device *dev) ...@@ -242,7 +256,8 @@ int __init ultramca_probe(struct net_device *dev)
* the index of the 0x2000 step. * the index of the 0x2000 step.
* beware different number of pages [hs] * beware different number of pages [hs]
*/ */
dev->mem_start = 0xc0000 + (0x2000 * (pos3 & 0xf)); dev->mem_start = (unsigned long)
mca_device_transform_memory(mca_dev, (void *)(0xc0000 + (0x2000 * (pos3 & 0xf))));
num_pages = 0x20 + (2 * (pos3 & 0x10)); num_pages = 0x20 + (2 * (pos3 & 0x10));
break; break;
} }
...@@ -260,7 +275,7 @@ int __init ultramca_probe(struct net_device *dev) ...@@ -260,7 +275,7 @@ int __init ultramca_probe(struct net_device *dev)
printk(KERN_INFO "%s: Parameters: %#3x,", dev->name, ioaddr); printk(KERN_INFO "%s: Parameters: %#3x,", dev->name, ioaddr);
for (i = 0; i < 6; i++) for (i = 0; i < 6; i++)
printk(KERN_INFO " %2.2X", dev->dev_addr[i] = inb(ioaddr + 8 + i)); printk(" %2.2X", dev->dev_addr[i] = inb(ioaddr + 8 + i));
/* Switch from the station address to the alternate register set /* Switch from the station address to the alternate register set
* and read the useful registers there. * and read the useful registers there.
...@@ -283,10 +298,11 @@ int __init ultramca_probe(struct net_device *dev) ...@@ -283,10 +298,11 @@ int __init ultramca_probe(struct net_device *dev)
*/ */
if (ethdev_init(dev)) { if (ethdev_init(dev)) {
printk (KERN_INFO ", no memory for dev->priv.\n"); printk (", no memory for dev->priv.\n");
release_region(ioaddr, ULTRA_IO_EXTENT); release_region(ioaddr, ULTRA_IO_EXTENT);
return -ENOMEM; return -ENOMEM;
} }
gen_dev->driver_data = dev;
/* The 8390 isn't at the base address, so fake the offset /* The 8390 isn't at the base address, so fake the offset
*/ */
...@@ -303,7 +319,7 @@ int __init ultramca_probe(struct net_device *dev) ...@@ -303,7 +319,7 @@ int __init ultramca_probe(struct net_device *dev)
dev->mem_end = ei_status.rmem_end = dev->mem_end = ei_status.rmem_end =
dev->mem_start + (ei_status.stop_page - START_PG) * 256; dev->mem_start + (ei_status.stop_page - START_PG) * 256;
printk(KERN_INFO ", IRQ %d memory %#lx-%#lx.\n", printk(", IRQ %d memory %#lx-%#lx.\n",
dev->irq, dev->mem_start, dev->mem_end - 1); dev->irq, dev->mem_start, dev->mem_end - 1);
ei_status.reset_8390 = &ultramca_reset_8390; ei_status.reset_8390 = &ultramca_reset_8390;
...@@ -315,6 +331,7 @@ int __init ultramca_probe(struct net_device *dev) ...@@ -315,6 +331,7 @@ int __init ultramca_probe(struct net_device *dev)
dev->open = &ultramca_open; dev->open = &ultramca_open;
dev->stop = &ultramca_close_card; dev->stop = &ultramca_close_card;
NS8390_init(dev, 0); NS8390_init(dev, 0);
return 0; return 0;
...@@ -428,69 +445,48 @@ static int ultramca_close_card(struct net_device *dev) ...@@ -428,69 +445,48 @@ static int ultramca_close_card(struct net_device *dev)
return 0; return 0;
} }
static int ultramca_remove(struct device *gen_dev)
{
struct mca_device *mca_dev = to_mca_device(gen_dev);
struct net_device *dev = (struct net_device *)gen_dev->driver_data;
#ifdef MODULE if(dev && dev->priv) {
#undef MODULE /* don't want to bother now! */ /* NB: ultra_close_card() does free_irq */
int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET;
#define MAX_ULTRAMCA_CARDS 4 /* Max number of Ultra cards per module */ mca_device_set_claim(mca_dev, 0);
release_region(ioaddr, ULTRA_IO_EXTENT);
unregister_netdev(dev);
kfree(dev->priv);
}
return 0;
}
static struct net_device dev_ultra[MAX_ULTRAMCA_CARDS];
static int io[MAX_ULTRAMCA_CARDS];
static int irq[MAX_ULTRAMCA_CARDS];
MODULE_LICENSE("GPL");
MODULE_PARM(io, "1-" __MODULE_STRING(MAX_ULTRAMCA_CARDS) "i"); static struct mca_driver ultra_driver = {
MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_ULTRAMCA_CARDS) "i"); .id_table = smc_mca_adapter_ids,
MODULE_PARM_DESC(io, "SMC Ultra/EtherEZ MCA I/O base address(es)"); .driver = {
MODULE_PARM_DESC(irq, "SMC Ultra/EtherEZ MCA IRQ number(s)"); .name = "smc-mca",
.bus = &mca_bus_type,
.probe = ultramca_probe,
.remove = ultramca_remove,
}
};
int init_module(void) static int __init ultramca_init_module(void)
{ {
int this_dev, found = 0; if(!MCA_bus)
return -ENXIO;
for (this_dev = 0; this_dev < MAX_ULTRAMCA_CARDS; this_dev++) { mca_register_driver(&ultra_driver);
struct net_device *dev = &dev_ultra[this_dev];
dev->irq = irq[this_dev];
dev->base_addr = io[this_dev];
dev->init = ultramca_probe;
if (register_netdev(dev) != 0) { return ultra_found ? 0 : -ENXIO;
if (found != 0) { /* Got at least one. */
return 0;
}
printk(KERN_NOTICE "smc-mca.c: No SMC Ultra card found (i/o = 0x%x).\n", io[this_dev]);
return -ENXIO;
}
found++;
}
return 0;
} }
void cleanup_module(void) static void __exit ultramca_cleanup_module(void)
{ {
int this_dev; mca_unregister_driver(&ultra_driver);
for (this_dev = 0; this_dev < MAX_ULTRAMCA_CARDS; this_dev++) {
struct net_device *dev = &dev_ultra[this_dev];
if (dev->priv != NULL) {
void *priv = dev->priv;
/* NB: ultra_close_card() does free_irq */
int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET;
mca_mark_as_unused(ei_status.priv);
release_region(ioaddr, ULTRA_IO_EXTENT);
unregister_netdev(dev);
kfree(priv);
}
}
} }
#endif /* MODULE */ module_init(ultramca_init_module);
module_exit(ultramca_cleanup_module);
/*
* Local variables:
* compile-command: "gcc -D__KERNEL__ -Wall -O6 -I/usr/src/linux/net/inet -c smc-mca.c"
* version-control: t
* kept-new-versions: 5
* c-indent-level: 8
* tab-width: 8
* End:
*/
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