[PATCH] fix 3c509.c for MCA drivers

From: James Bottomley (James.Bottomley@steeleye.com)
Date: Sun Feb 02 2003 - 22:09:24 EST


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

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Fri Feb 07 2003 - 22:00:10 EST