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);
extern int hp100_probe(struct net_device *dev);
extern int ultra_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 el2_probe(struct net_device *dev);
extern int ne_probe(struct net_device *dev);
......@@ -192,9 +191,6 @@ static struct devprobe eisa_probes[] __initdata = {
static struct devprobe mca_probes[] __initdata = {
#ifdef CONFIG_ULTRAMCA
{ultramca_probe, 0},
#endif
#ifdef CONFIG_NE2_MCA
{ne2_probe, 0},
#endif
......
......@@ -53,8 +53,6 @@
#include "smc-mca.h"
#include <linux/mca.h>
int ultramca_probe(struct net_device *dev);
static int ultramca_open(struct net_device *dev);
static void ultramca_reset_8390(struct net_device *dev);
static void ultramca_get_8390_hdr(struct net_device *dev,
......@@ -91,37 +89,57 @@ struct smc_mca_adapters_t {
char *name;
};
static struct smc_mca_adapters_t smc_mca_adapters[] __initdata = {
{ 0x61c8, "SMC Ethercard PLUS Elite/A BNC/AUI (WD8013EP/A)" },
{ 0x61c9, "SMC Ethercard PLUS Elite/A UTP/AUI (WD8013WP/A)" },
{ 0x6fc0, "WD Ethercard PLUS/A (WD8003E/A or WD8003ET/A)" },
{ 0x6fc1, "WD Starcard PLUS/A (WD8003ST/A)" },
{ 0x6fc2, "WD Ethercard PLUS 10T/A (WD8003W/A)" },
{ 0xefd4, "IBM PS/2 Adapter/A for Ethernet UTP/AUI (WD8013WP/A)" },
{ 0xefd5, "IBM PS/2 Adapter/A for Ethernet BNC/AUI (WD8013EP/A)" },
{ 0xefe5, "IBM PS/2 Adapter/A for Ethernet" },
{ 0x0000, NULL }
#define MAX_ULTRAMCA_CARDS 4 /* Max number of Ultra cards per module */
static int ultra_io[MAX_ULTRAMCA_CARDS];
static int ultra_irq[MAX_ULTRAMCA_CARDS];
MODULE_LICENSE("GPL");
MODULE_PARM(ultra_io, "1-" __MODULE_STRING(MAX_ULTRAMCA_CARDS) "i");
MODULE_PARM(ultra_irq, "1-" __MODULE_STRING(MAX_ULTRAMCA_CARDS) "i");
MODULE_PARM_DESC(ultra_io, "SMC Ultra/EtherEZ MCA I/O base address(es)");
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;
struct net_device *dev;
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;
int i, j;
int adapter_found = 0;
int adapter = 0;
int i;
int adapter = mca_dev->index;
int tbase = 0;
int tirq = 0;
int base_addr = dev->base_addr;
int irq = dev->irq;
if (!MCA_bus) {
return -ENODEV;
}
SET_MODULE_OWNER(dev);
int base_addr = ultra_io[ultra_found];
int irq = ultra_irq[ultra_found];
if (base_addr || irq) {
printk(KERN_INFO "Probing for SMC MCA adapter");
......@@ -134,82 +152,76 @@ int __init ultramca_probe(struct net_device *dev)
}
}
/* proper multicard detection by ZP Gu (zpg@castle.net) */
for (j = 0; (smc_mca_adapters[j].name != NULL) && !adapter_found; j++) {
slot = mca_find_unused_adapter(smc_mca_adapters[j].id, 0);
while((slot != MCA_NOTFOUND) && !adapter_found) {
tirq = 0;
tbase = 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 looking for
*/
pos2 = mca_read_stored_pos(slot, 2); /* io_addr */
pos3 = mca_read_stored_pos(slot, 3); /* shared mem */
pos4 = mca_read_stored_pos(slot, 4); /* ROM bios addr
* range */
pos5 = mca_read_stored_pos(slot, 5); /* irq, media
* and RIPL */
/* 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;
}
}
tirq = 0;
tbase = 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
* looking for */
pos2 = mca_device_read_stored_pos(mca_dev, 2); /* io_addr */
pos3 = mca_device_read_stored_pos(mca_dev, 3); /* shared mem */
pos4 = mca_device_read_stored_pos(mca_dev, 4); /* ROM bios addr range */
pos5 = mca_device_read_stored_pos(mca_dev, 5); /* irq, media and RIPL */
/* 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
*/
if(!tirq || !tbase || (irq && irq != tirq) || (base_addr && tbase != base_addr)) {
slot = mca_find_unused_adapter(smc_mca_adapters[j].id, slot + 1);
} else {
adapter_found = 1;
adapter = j;
}
switch (mca_dev->index) {
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(!adapter_found) {
return ((base_addr || irq) ? -ENXIO : -ENODEV);
}
if(!tirq || !tbase
|| (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. */
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",
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);
mca_mark_as_used(slot);
strncpy(gen_dev->name, smc_mca_adapter_names[adapter], sizeof(gen_dev->name));
mca_device_set_claim(mca_dev, 1);
dev->base_addr = ioaddr = tbase;
dev->irq = tirq;
dev->base_addr = ioaddr = mca_device_transform_ioport(mca_dev, tbase);
dev->irq = mca_device_transform_irq(mca_dev, tirq);
dev->mem_start = 0;
num_pages = 40;
......@@ -220,7 +232,8 @@ int __init ultramca_probe(struct net_device *dev)
for (i = 0; i < 16; i++) { /* taking 16 counts
* up to 15 [hs] */
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;
}
}
......@@ -231,7 +244,8 @@ int __init ultramca_probe(struct net_device *dev)
case _6fc2_WD_Ethercard_PLUS_10T_A_WD8003W_A:
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;
break;
}
......@@ -242,7 +256,8 @@ int __init ultramca_probe(struct net_device *dev)
* the index of the 0x2000 step.
* 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));
break;
}
......@@ -260,7 +275,7 @@ int __init ultramca_probe(struct net_device *dev)
printk(KERN_INFO "%s: Parameters: %#3x,", dev->name, ioaddr);
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
* and read the useful registers there.
......@@ -283,10 +298,11 @@ int __init ultramca_probe(struct net_device *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);
return -ENOMEM;
}
gen_dev->driver_data = dev;
/* The 8390 isn't at the base address, so fake the offset
*/
......@@ -303,7 +319,7 @@ int __init ultramca_probe(struct net_device *dev)
dev->mem_end = ei_status.rmem_end =
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);
ei_status.reset_8390 = &ultramca_reset_8390;
......@@ -315,6 +331,7 @@ int __init ultramca_probe(struct net_device *dev)
dev->open = &ultramca_open;
dev->stop = &ultramca_close_card;
NS8390_init(dev, 0);
return 0;
......@@ -428,69 +445,48 @@ static int ultramca_close_card(struct net_device *dev)
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
#undef MODULE /* don't want to bother now! */
if(dev && dev->priv) {
/* 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");
MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_ULTRAMCA_CARDS) "i");
MODULE_PARM_DESC(io, "SMC Ultra/EtherEZ MCA I/O base address(es)");
MODULE_PARM_DESC(irq, "SMC Ultra/EtherEZ MCA IRQ number(s)");
static struct mca_driver ultra_driver = {
.id_table = smc_mca_adapter_ids,
.driver = {
.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++) {
struct net_device *dev = &dev_ultra[this_dev];
dev->irq = irq[this_dev];
dev->base_addr = io[this_dev];
dev->init = ultramca_probe;
mca_register_driver(&ultra_driver);
if (register_netdev(dev) != 0) {
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;
return ultra_found ? 0 : -ENXIO;
}
void cleanup_module(void)
static void __exit ultramca_cleanup_module(void)
{
int this_dev;
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);
}
}
mca_unregister_driver(&ultra_driver);
}
#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