Messages in this thread Patch in this message | | | Subject | [PATCH] fix 3c509.c for MCA drivers | From | James Bottomley <> | Date | 02 Feb 2003 22:09:24 -0500 |
| |
The attached fixes the MCA version of the 3c509 and updates it to the new MCA API.
Someone who knows PNP-ISA should migrate it to a probing API for that too.
I've put the el3_probe back into Space.c for ISA only otherwise the driver won't work for ISA (could someone with an ISA card test this).
James
# This is a BitKeeper generated patch for the following project: # Project Name: Linux kernel tree # This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas: # ChangeSet 1.956 -> 1.957 # drivers/net/3c509.c 1.29 -> 1.30 # drivers/net/Space.c 1.15 -> 1.16 # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 03/02/02 jejb@mulgrave.(none) 1.957 # 3c509 fixes: correct MCA probing, add back ISA probe to Space.c # -------------------------------------------- # diff -Nru a/drivers/net/3c509.c b/drivers/net/3c509.c --- a/drivers/net/3c509.c Sun Feb 2 22:04:26 2003 +++ b/drivers/net/3c509.c Sun Feb 2 22:04:26 2003 @@ -103,6 +103,10 @@ static int el3_debug = 2; #endif +/* Used to do a global count of all the cards in the system. Must be + * a global variable so that the mca/eisa probe routines can increment + * it */ +static int el3_cards = 0; /* To minimize the size of the driver source I only define operating constants if they are used several times. You'll need the manual @@ -167,16 +171,15 @@ /* skb send-queue */ int head, size; struct sk_buff *queue[SKB_QUEUE_SIZE]; - char mca_slot; #ifdef CONFIG_PM struct pm_dev *pmdev; #endif -#ifdef __ISAPNP__ - struct pnp_dev *pnpdev; -#endif -#ifdef CONFIG_EISA - struct eisa_device *edev; -#endif + enum { + EL3_MCA, + EL3_PNP, + EL3_EISA, + } type; /* type of device */ + struct device *dev; }; static int id_port __initdata = 0x110; /* Start with 0x110 to avoid new sound cards.*/ static struct net_device *el3_root_dev; @@ -200,6 +203,8 @@ static int el3_resume(struct pm_dev *pdev); static int el3_pm_callback(struct pm_dev *pdev, pm_request_t rqst, void *data); #endif +/* generic device remove for all device types */ +static int el3_device_remove (struct device *device); #ifdef CONFIG_EISA struct eisa_device_id el3_eisa_ids[] = { @@ -209,31 +214,46 @@ }; static int el3_eisa_probe (struct device *device); -static int el3_eisa_remove (struct device *device); struct eisa_driver el3_eisa_driver = { .id_table = el3_eisa_ids, .driver = { .name = "3c509", .probe = el3_eisa_probe, - .remove = __devexit_p (el3_eisa_remove) + .remove = __devexit_p (el3_device_remove) } }; #endif #ifdef CONFIG_MCA -struct el3_mca_adapters_struct { - char* name; - int id; +static int el3_mca_probe(struct device *dev); + +static short el3_mca_adapter_ids[] __initdata = { + 0x627c, + 0x627d, + 0x62db, + 0x62f6, + 0x62f7, + 0x0000 +}; + +static char *el3_mca_adapter_names[] __initdata = { + "3Com 3c529 EtherLink III (10base2)", + "3Com 3c529 EtherLink III (10baseT)", + "3Com 3c529 EtherLink III (test mode)", + "3Com 3c529 EtherLink III (TP or coax)", + "3Com 3c529 EtherLink III (TP)", + NULL }; -static struct el3_mca_adapters_struct el3_mca_adapters[] __initdata = { - { "3Com 3c529 EtherLink III (10base2)", 0x627c }, - { "3Com 3c529 EtherLink III (10baseT)", 0x627d }, - { "3Com 3c529 EtherLink III (test mode)", 0x62db }, - { "3Com 3c529 EtherLink III (TP or coax)", 0x62f6 }, - { "3Com 3c529 EtherLink III (TP)", 0x62f7 }, - { NULL, 0 }, +static struct mca_driver el3_mca_driver = { + .id_table = el3_mca_adapter_ids, + .driver = { + .name = "3c529", + .bus = &mca_bus_type, + .probe = el3_mca_probe, + .remove = __devexit_p(el3_device_remove), + }, }; #endif /* CONFIG_MCA */ @@ -264,12 +284,12 @@ }; static u16 el3_isapnp_phys_addr[8][3]; -#endif /* __ISAPNP__ */ static int nopnp; +#endif /* __ISAPNP__ */ /* With the driver model introduction for EISA devices, both init * and cleanup have been split : - * - EISA devices probe/remove starts in el3_eisa_probe/el3_eisa_remove + * - EISA devices probe/remove starts in el3_eisa_probe/el3_device_remove * - MCA/ISA still use el3_probe * * Both call el3_common_init/el3_common_remove. */ @@ -278,10 +298,9 @@ { struct el3_private *lp = dev->priv; short i; - -#ifdef CONFIG_EISA - if (!lp->edev) /* EISA devices are not chained */ -#endif + + el3_cards++; + if (!lp->dev) /* probed devices are not chained */ { lp->next_dev = el3_root_dev; el3_root_dev = dev; @@ -337,17 +356,13 @@ struct el3_private *lp = dev->priv; (void) lp; /* Keep gcc quiet... */ -#ifdef CONFIG_MCA - if(lp->mca_slot!=-1) - mca_mark_as_unused(lp->mca_slot); -#endif #ifdef CONFIG_PM if (lp->pmdev) pm_unregister(lp->pmdev); #endif #ifdef __ISAPNP__ - if (lp->pnpdev) - pnp_device_detach(lp->pnpdev); + if (lp->type == EL3_PNP) + pnp_device_detach(to_pnp_dev(lp->dev)); #endif unregister_netdev (dev); @@ -363,76 +378,11 @@ int ioaddr, irq, if_port; u16 phys_addr[3]; static int current_tag; - int mca_slot = -1; #ifdef __ISAPNP__ static int pnp_cards; struct pnp_dev *idev = NULL; #endif /* __ISAPNP__ */ -#ifdef CONFIG_MCA - /* Based on Erik Nygren's (nygren@mit.edu) 3c529 patch, heavily - * modified by Chris Beauregard (cpbeaure@csclub.uwaterloo.ca) - * to support standard MCA probing. - * - * redone for multi-card detection by ZP Gu (zpg@castle.net) - * now works as a module - */ - - if( MCA_bus ) { - int slot, j; - u_char pos4, pos5; - - for( j = 0; el3_mca_adapters[j].name != NULL; j ++ ) { - slot = 0; - while( slot != MCA_NOTFOUND ) { - slot = mca_find_unused_adapter( - el3_mca_adapters[j].id, slot ); - if( slot == MCA_NOTFOUND ) break; - - /* if we get this far, an adapter has been - * detected and is enabled - */ - - pos4 = mca_read_stored_pos( slot, 4 ); - pos5 = mca_read_stored_pos( slot, 5 ); - - ioaddr = ((short)((pos4&0xfc)|0x02)) << 8; - irq = pos5 & 0x0f; - - /* probing for a card at a particular IO/IRQ */ - if(dev && ((dev->irq >= 1 && dev->irq != irq) || - (dev->base_addr >= 1 && dev->base_addr != ioaddr))) { - slot++; /* probing next slot */ - continue; - } - - printk("3c509: found %s at slot %d\n", - el3_mca_adapters[j].name, slot + 1 ); - - /* claim the slot */ - mca_set_adapter_name(slot, el3_mca_adapters[j].name); - mca_set_adapter_procfn(slot, NULL, NULL); - mca_mark_as_used(slot); - - if_port = pos4 & 0x03; - if (el3_debug > 2) { - printk("3c529: irq %d ioaddr 0x%x ifport %d\n", irq, ioaddr, if_port); - } - EL3WINDOW(0); - for (i = 0; i < 3; i++) { - phys_addr[i] = htons(read_eeprom(ioaddr, i)); - } - - mca_slot = slot; - - goto found; - } - } - /* if we get here, we didn't find an MCA adapter */ - return -ENODEV; - } -#endif /* CONFIG_MCA */ - #ifdef __ISAPNP__ if (nopnp == 1) goto no_pnp; @@ -580,7 +530,7 @@ /* Free the interrupt so that some other card can use it. */ outw(0x0f00, ioaddr + WN0_IRQ); - found: + dev = init_etherdev(NULL, sizeof(struct el3_private)); if (dev == NULL) { release_region(ioaddr, EL3_IO_EXTENT); @@ -594,13 +544,80 @@ dev->if_port = if_port; lp = dev->priv; #ifdef __ISAPNP__ - lp->pnpdev = idev; + lp->dev = &idev->dev; #endif - lp->mca_slot = mca_slot; return el3_common_init (dev); } +#ifdef CONFIG_MCA +static int __init el3_mca_probe(struct device *device) { + /* Based on Erik Nygren's (nygren@mit.edu) 3c529 patch, + * heavily modified by Chris Beauregard + * (cpbeaure@csclub.uwaterloo.ca) to support standard MCA + * probing. + * + * redone for multi-card detection by ZP Gu (zpg@castle.net) + * now works as a module */ + + struct el3_private *lp; + short i; + int ioaddr, irq, if_port; + u16 phys_addr[3]; + struct net_device *dev = NULL; + u_char pos4, pos5; + struct mca_device *mdev = to_mca_device(device); + int slot = mdev->slot; + + pos4 = mca_device_read_stored_pos(mdev, 4); + pos5 = mca_device_read_stored_pos(mdev, 5); + + ioaddr = ((short)((pos4&0xfc)|0x02)) << 8; + irq = pos5 & 0x0f; + + + printk("3c529: found %s at slot %d\n", + el3_mca_adapter_names[mdev->index], slot + 1); + + /* claim the slot */ + strncpy(device->name, el3_mca_adapter_names[mdev->index], + sizeof(device->name)); + mca_device_set_claim(mdev, 1); + + if_port = pos4 & 0x03; + + irq = mca_device_transform_irq(mdev, irq); + ioaddr = mca_device_transform_ioport(mdev, ioaddr); + if (el3_debug > 2) { + printk("3c529: irq %d ioaddr 0x%x ifport %d\n", irq, ioaddr, if_port); + } + EL3WINDOW(0); + for (i = 0; i < 3; i++) { + phys_addr[i] = htons(read_eeprom(ioaddr, i)); + } + + dev = init_etherdev(NULL, sizeof(struct el3_private)); + if (dev == NULL) { + release_region(ioaddr, EL3_IO_EXTENT); + return -ENOMEM; + } + + SET_MODULE_OWNER(dev); + + memcpy(dev->dev_addr, phys_addr, sizeof(phys_addr)); + dev->base_addr = ioaddr; + dev->irq = irq; + dev->if_port = if_port; + lp = dev->priv; + lp->dev = device; + lp->type = EL3_MCA; + device->driver_data = dev; + + return el3_common_init (dev); +} + +#endif /* CONFIG_MCA */ + #ifdef CONFIG_EISA static int __init el3_eisa_probe (struct device *device) { @@ -642,25 +659,26 @@ dev->irq = irq; dev->if_port = if_port; lp = dev->priv; - lp->mca_slot = -1; - lp->edev = edev; + lp->dev = device; + lp->type = EL3_EISA; eisa_set_drvdata (edev, dev); return el3_common_init (dev); } +#endif -static int __devexit el3_eisa_remove (struct device *device) +/* This remove works for all device types. + * + * The net dev must be stored in the driver_data field */ +static int __devexit el3_device_remove (struct device *device) { - struct eisa_device *edev; struct net_device *dev; - edev = to_eisa_device (device); - dev = eisa_get_drvdata (edev); + dev = device->driver_data; el3_common_remove (dev); return 0; } -#endif /* Read a word from the EEPROM using the regular EEPROM access register. Assume that we are in register window zero. @@ -1080,7 +1098,7 @@ free_irq(dev->irq, dev); /* Switching back to window 0 disables the IRQ. */ EL3WINDOW(0); - if (!lp->edev) { + if (lp->type != EL3_EISA) { /* But we explicitly zero the IRQ line select anyway. Don't do * it on EISA cards, it prevents the module from getting an * IRQ after unload+reload... */ @@ -1530,7 +1548,7 @@ static int __init el3_init_module(void) { - int el3_cards = 0; + el3_cards = 0; if (debug >= 0) el3_debug = debug; @@ -1548,8 +1566,9 @@ if (eisa_driver_register (&el3_eisa_driver) < 0) { eisa_driver_unregister (&el3_eisa_driver); } - else - el3_cards++; /* Found an eisa card */ +#endif +#ifdef CONFIG_MCA + mca_register_driver(&el3_mca_driver); #endif return el3_cards ? 0 : -ENODEV; } @@ -1568,6 +1587,9 @@ #ifdef CONFIG_EISA eisa_driver_unregister (&el3_eisa_driver); +#endif +#ifdef CONFIG_MCA + mca_unregister_driver(&el3_mca_driver); #endif } diff -Nru a/drivers/net/Space.c b/drivers/net/Space.c --- a/drivers/net/Space.c Sun Feb 2 22:04:26 2003 +++ b/drivers/net/Space.c Sun Feb 2 22:04:26 2003 @@ -224,6 +224,9 @@ #ifdef CONFIG_EL2 /* 3c503 */ {el2_probe, 0}, #endif +#ifdef CONFIG_EL3 + {el3_probe, 0}, +#endif #ifdef CONFIG_HPLAN {hp_probe, 0}, #endif
| |