netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] (19/42) 3c515-T10
@ 2003-11-13  0:43 Stephen Hemminger
  2003-11-13 19:32 ` Stephen Hemminger
  0 siblings, 1 reply; 3+ messages in thread
From: Stephen Hemminger @ 2003-11-13  0:43 UTC (permalink / raw)
  To: jgarzik; +Cc: netdev

NE43-3c515
	* convert to dynamic allocation
	* fixed up device list handling

diff -Nru a/drivers/net/3c515.c b/drivers/net/3c515.c
--- a/drivers/net/3c515.c	Wed Nov 12 13:20:13 2003
+++ b/drivers/net/3c515.c	Wed Nov 12 13:20:13 2003
@@ -307,7 +307,8 @@
 
 struct corkscrew_private {
 	const char *product_name;
-	struct net_device *next_module;
+	struct list_head list;
+	struct net_device *our_dev;
 	/* The Rx and Tx rings are here to keep them quad-word-aligned. */
 	struct boom_rx_desc rx_ring[RX_RING_SIZE];
 	struct boom_tx_desc tx_ring[TX_RING_SIZE];
@@ -329,6 +330,7 @@
 		full_bus_master_tx:1, full_bus_master_rx:1,	/* Boomerang  */
 		tx_full:1;
 	spinlock_t lock;
+	struct device *dev;
 };
 
 /* The action to take with a media selection timer tick.
@@ -367,17 +369,12 @@
 
 MODULE_DEVICE_TABLE(isapnp, corkscrew_isapnp_adapters);
 
-static int corkscrew_isapnp_phys_addr[3];
-
 static int nopnp;
 #endif /* __ISAPNP__ */
 
-static int corkscrew_scan(struct net_device *dev);
-static struct net_device *corkscrew_found_device(struct net_device *dev,
-						 int ioaddr, int irq,
-						 int product_index,
-						 int options);
-static int corkscrew_probe1(struct net_device *dev);
+static struct net_device *corkscrew_scan(int unit);
+static void corkscrew_setup(struct net_device *dev, int ioaddr,
+			    struct pnp_dev *idev, int card_number);
 static int corkscrew_open(struct net_device *dev);
 static void corkscrew_timer(unsigned long arg);
 static int corkscrew_start_xmit(struct sk_buff *skb,
@@ -413,47 +410,99 @@
 #ifdef MODULE
 static int debug = -1;
 /* A list of all installed Vortex devices, for removing the driver module. */
-static struct net_device *root_corkscrew_dev;
+/* we will need locking (and refcounting) if we ever use it for more */
+static LIST_HEAD(root_corkscrew_dev);
 
 int init_module(void)
 {
-	int cards_found;
-
+	int found = 0;
 	if (debug >= 0)
 		corkscrew_debug = debug;
 	if (corkscrew_debug)
 		printk(version);
-
-	root_corkscrew_dev = NULL;
-	cards_found = corkscrew_scan(NULL);
-	return cards_found ? 0 : -ENODEV;
+	while (corkscrew_scan(-1))
+		found++;
+	return found ? 0 : -ENODEV;
 }
 
 #else
-int tc515_probe(struct net_device *dev)
+struct net_device *tc515_probe(int unit)
 {
-	int cards_found = 0;
+	struct net_device *dev = corkscrew_scan(unit);
+	static int printed;
 
-	SET_MODULE_OWNER(dev);
-
-	cards_found = corkscrew_scan(dev);
+	if (!dev)
+		return ERR_PTR(-ENODEV);
 
-	if (corkscrew_debug > 0 && cards_found)
+	if (corkscrew_debug > 0 && !printed) {
+		printed = 1;
 		printk(version);
+	}
 
-	return cards_found ? 0 : -ENODEV;
+	return dev;
 }
 #endif				/* not MODULE */
 
-static int corkscrew_scan(struct net_device *dev)
+static int check_device(unsigned ioaddr)
+{
+	int timer;
+
+	if (!request_region(ioaddr, CORKSCREW_TOTAL_SIZE, "3c515"))
+		return 0;
+	/* Check the resource configuration for a matching ioaddr. */
+	if ((inw(ioaddr + 0x2002) & 0x1f0) != (ioaddr & 0x1f0)) {
+		release_region(ioaddr, CORKSCREW_TOTAL_SIZE);
+		return 0;
+	}
+	/* Verify by reading the device ID from the EEPROM. */
+	outw(EEPROM_Read + 7, ioaddr + Wn0EepromCmd);
+	/* Pause for at least 162 us. for the read to take place. */
+	for (timer = 4; timer >= 0; timer--) {
+		udelay(162);
+		if ((inw(ioaddr + Wn0EepromCmd) & 0x0200) == 0)
+			break;
+	}
+	if (inw(ioaddr + Wn0EepromData) != 0x6d50) {
+		release_region(ioaddr, CORKSCREW_TOTAL_SIZE);
+		return 0;
+	}
+	return 1;
+}
+
+static void cleanup_card(struct net_device *dev)
+{
+	struct corkscrew_private *vp = (struct corkscrew_private *) dev->priv;
+	list_del_init(&vp->list);
+	if (dev->dma)
+		free_dma(dev->dma);
+	outw(TotalReset, dev->base_addr + EL3_CMD);
+	release_region(dev->base_addr, CORKSCREW_TOTAL_SIZE);
+	if (vp->dev)
+		pnp_device_detach(to_pnp_dev(vp->dev));
+}
+
+static struct net_device *corkscrew_scan(int unit)
 {
-	int cards_found = 0;
+	struct net_device *dev;
+	static int cards_found = 0;
 	static int ioaddr;
+	int err;
 #ifdef __ISAPNP__
 	short i;
 	static int pnp_cards;
 #endif
 
+	dev = alloc_etherdev(sizeof(struct corkscrew_private));
+	if (!dev)
+		return ERR_PTR(-ENOMEM);
+
+	if (unit >= 0) {
+		sprintf(dev->name, "eth%d", unit);
+		netdev_boot_setup_check(dev);
+	}
+
+	SET_MODULE_OWNER(dev);
+
 #ifdef __ISAPNP__
 	if(nopnp == 1)
 		goto no_pnp;
@@ -470,7 +519,7 @@
 			if (pnp_activate_dev(idev) < 0) {
 				printk("pnp activate failed (out of resources?)\n");
 				pnp_device_detach(idev);
-				return -ENOMEM;
+				continue;
 			}
 			if (!pnp_port_valid(idev, 0) || !pnp_irq_valid(idev, 0)) {
 				pnp_device_detach(idev);
@@ -478,40 +527,22 @@
 			}
 			ioaddr = pnp_port_start(idev, 0);
 			irq = pnp_irq(idev, 0);
-			if(corkscrew_debug)
-				printk ("ISAPNP reports %s at i/o 0x%x, irq %d\n",
-					(char*) corkscrew_isapnp_adapters[i].driver_data, ioaddr, irq);
-					
-			if ((inw(ioaddr + 0x2002) & 0x1f0) != (ioaddr & 0x1f0)) {
+			if (!check_device(ioaddr)) {
 				pnp_device_detach(idev);
 				continue;
 			}
-			/* Verify by reading the device ID from the EEPROM. */
-			{
-				int timer;
-				outw(EEPROM_Read + 7, ioaddr + Wn0EepromCmd);
-				/* Pause for at least 162 us. for the read to take place. */
-				for (timer = 4; timer >= 0; timer--) {
-					udelay(162);
-					if ((inw(ioaddr + Wn0EepromCmd) & 0x0200)
-				    		== 0)
-							break;
-				}
-				if (inw(ioaddr + Wn0EepromData) != 0x6d50) {
-					pnp_device_detach(idev);
-					continue;
-				}
-			}
+			if(corkscrew_debug)
+				printk ("ISAPNP reports %s at i/o 0x%x, irq %d\n",
+					(char*) corkscrew_isapnp_adapters[i].driver_data, ioaddr, irq);
 			printk(KERN_INFO "3c515 Resource configuration register %#4.4x, DCR %4.4x.\n",
 		     		inl(ioaddr + 0x2002), inw(ioaddr + 0x2000));
 			/* irq = inw(ioaddr + 0x2002) & 15; */ /* Use the irq from isapnp */
-			corkscrew_isapnp_phys_addr[pnp_cards] = ioaddr;
-			corkscrew_found_device(dev, ioaddr, irq, CORKSCREW_ID, dev
-				       	&& dev->mem_start ? dev->
-				       	mem_start : options[cards_found]);
-			dev = 0;
+			corkscrew_setup(dev, ioaddr, idev, cards_found++);
 			pnp_cards++;
-			cards_found++;
+			err = register_netdev(dev);
+			if (!err)
+				return dev;
+			cleanup_card(dev);
 		}
 	}
 no_pnp:
@@ -519,123 +550,62 @@
 
 	/* Check all locations on the ISA bus -- evil! */
 	for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x20) {
-		int irq;
-#ifdef __ISAPNP__
-		/* Make sure this was not already picked up by isapnp */
-		if(ioaddr == corkscrew_isapnp_phys_addr[0]) continue;
-		if(ioaddr == corkscrew_isapnp_phys_addr[1]) continue;
-		if(ioaddr == corkscrew_isapnp_phys_addr[2]) continue;
-#endif /* __ISAPNP__ */
-		if (check_region(ioaddr, CORKSCREW_TOTAL_SIZE))
-			continue;
-		/* Check the resource configuration for a matching ioaddr. */
-		if ((inw(ioaddr + 0x2002) & 0x1f0) != (ioaddr & 0x1f0))
+		if (!check_device(ioaddr))
 			continue;
-		/* Verify by reading the device ID from the EEPROM. */
-		{
-			int timer;
-			outw(EEPROM_Read + 7, ioaddr + Wn0EepromCmd);
-			/* Pause for at least 162 us. for the read to take place. */
-			for (timer = 4; timer >= 0; timer--) {
-				udelay(162);
-				if ((inw(ioaddr + Wn0EepromCmd) & 0x0200)
-				    == 0)
-					break;
-			}
-			if (inw(ioaddr + Wn0EepromData) != 0x6d50)
-				continue;
-		}
+
 		printk(KERN_INFO "3c515 Resource configuration register %#4.4x, DCR %4.4x.\n",
 		     inl(ioaddr + 0x2002), inw(ioaddr + 0x2000));
-		irq = inw(ioaddr + 0x2002) & 15;
-		corkscrew_found_device(dev, ioaddr, irq, CORKSCREW_ID,
-				       dev && dev->mem_start ?  dev->mem_start :
-				         (cards_found >= MAX_UNITS ? -1 :
-						options[cards_found]));
-		dev = 0;
-		cards_found++;
+		corkscrew_setup(dev, ioaddr, NULL, cards_found++);
+		err = register_netdev(dev);
+		if (!err)
+			return dev;
+		cleanup_card(dev);
 	}
-	if (corkscrew_debug)
-		printk(KERN_INFO "%d 3c515 cards found.\n", cards_found);
-	return cards_found;
+	free_netdev(dev);
+	return NULL;
 }
 
-static struct net_device *corkscrew_found_device(struct net_device *dev,
-						 int ioaddr, int irq,
-						 int product_index,
-						 int options)
+static void corkscrew_setup(struct net_device *dev, int ioaddr,
+			    struct pnp_dev *idev, int card_number)
 {
-	struct corkscrew_private *vp;
-
-#ifdef MODULE
-	/* Allocate and fill new device structure. */
-	int dev_size = sizeof(struct corkscrew_private);
-
-	dev = alloc_etherdev(dev_size);
-	if (!dev)
-		goto err_out;
-	memset(dev, 0, dev_size);
+	struct corkscrew_private *vp = (struct corkscrew_private *) dev->priv;
+	unsigned int eeprom[0x40], checksum = 0;	/* EEPROM contents */
+	int i;
+	int irq;
 
-	vp = (struct corkscrew_private *) dev->priv;
-	dev->base_addr = ioaddr;
-	dev->irq = irq;
-	dev->dma = (product_index == CORKSCREW_ID ? inw(ioaddr + 0x2000) & 7 : 0);
-	dev->init = corkscrew_probe1;
-	vp->product_name = "3c515";
-	vp->options = options;
-	if (options >= 0) {
-		vp->media_override = ((options & 7) == 2) ? 0 : options & 7;
-		vp->full_duplex = (options & 8) ? 1 : 0;
-		vp->bus_master = (options & 16) ? 1 : 0;
+	if (idev) {
+		irq = pnp_irq(idev, 0);
+		vp->dev = &idev->dev;
 	} else {
-		vp->media_override = 7;
-		vp->full_duplex = 0;
-		vp->bus_master = 0;
+		irq = inw(ioaddr + 0x2002) & 15;
 	}
-	vp->next_module = root_corkscrew_dev;
-	root_corkscrew_dev = dev;
-	SET_MODULE_OWNER(dev);
-	if (register_netdev(dev) < 0)
-		goto err_free_dev;
-#else				/* not a MODULE */
-	/* Caution: quad-word alignment required for rings! */
-	dev->priv = kmalloc(sizeof(struct corkscrew_private), GFP_KERNEL);
-	if (!dev->priv)
-		goto err_out;
-	memset(dev->priv, 0, sizeof(struct corkscrew_private));
-	dev = init_etherdev(dev, sizeof(struct corkscrew_private));
+
 	dev->base_addr = ioaddr;
 	dev->irq = irq;
-	dev->dma = (product_index == CORKSCREW_ID ? inw(ioaddr + 0x2000) & 7 : 0);
-	vp = (struct corkscrew_private *) dev->priv;
+	dev->dma = inw(ioaddr + 0x2000) & 7;
 	vp->product_name = "3c515";
-	vp->options = options;
-	if (options >= 0) {
-		vp->media_override = ((options & 7) == 2) ? 0 : options & 7;
-		vp->full_duplex = (options & 8) ? 1 : 0;
-		vp->bus_master = (options & 16) ? 1 : 0;
+	vp->options = dev->mem_start;
+	vp->our_dev = dev;
+
+	if (!vp->options) {
+		 if (card_number >= MAX_UNITS)
+			vp->options = -1;
+		else
+			vp->options = options[card_number];
+	}
+
+	if (vp->options >= 0) {
+		vp->media_override = vp->options & 7;
+		if (vp->media_override == 2)
+			vp->media_override = 0;
+		vp->full_duplex = (vp->options & 8) ? 1 : 0;
+		vp->bus_master = (vp->options & 16) ? 1 : 0;
 	} else {
 		vp->media_override = 7;
 		vp->full_duplex = 0;
 		vp->bus_master = 0;
 	}
-
-	corkscrew_probe1(dev);
-#endif				/* MODULE */
-	return dev;
-
-err_free_dev:
-	free_netdev(dev);
-err_out:
-	return NULL;
-}
-
-static int corkscrew_probe1(struct net_device *dev)
-{
-	int ioaddr = dev->base_addr;
-	struct corkscrew_private *vp = (struct corkscrew_private *) dev->priv;
-	unsigned int eeprom[0x40], checksum = 0;	/* EEPROM contents */
-	int i;
+	list_add(&vp->list, &root_corkscrew_dev);
 
 	printk(KERN_INFO "%s: 3Com %s at %#3x,", dev->name, vp->product_name, ioaddr);
 
@@ -707,9 +677,6 @@
 	/* vp->full_bus_master_rx = 0; */
 	vp->full_bus_master_rx = (vp->capabilities & 0x20) ? 1 : 0;
 
-	/* We do a request_region() to register /proc/ioports info. */
-	request_region(ioaddr, CORKSCREW_TOTAL_SIZE, vp->product_name);
-
 	/* The 3c51x-specific entries in the device structure. */
 	dev->open = &corkscrew_open;
 	dev->hard_start_xmit = &corkscrew_start_xmit;
@@ -719,8 +686,6 @@
 	dev->get_stats = &corkscrew_get_stats;
 	dev->set_multicast_list = &set_rx_mode;
 	dev->ethtool_ops = &netdev_ethtool_ops;
-
-	return 0;
 }
 \f
 
@@ -1608,20 +1573,16 @@
 #ifdef MODULE
 void cleanup_module(void)
 {
-	struct net_device *next_dev;
-
-	while (root_corkscrew_dev) {
-		next_dev =
-		    ((struct corkscrew_private *) root_corkscrew_dev->
-		     priv)->next_module;
-		if (root_corkscrew_dev->dma)
-			free_dma(root_corkscrew_dev->dma);
-		unregister_netdev(root_corkscrew_dev);
-		outw(TotalReset, root_corkscrew_dev->base_addr + EL3_CMD);
-		release_region(root_corkscrew_dev->base_addr,
-			       CORKSCREW_TOTAL_SIZE);
-		free_netdev(root_corkscrew_dev);
-		root_corkscrew_dev = next_dev;
+	while (!list_empty(&root_corkscrew_dev)) {
+		struct net_device *dev;
+		struct corkscrew_private *vp;
+
+		vp = list_entry(root_corkscrew_dev.next,
+				struct corkscrew_private, list);
+		dev = vp->our_dev;
+		unregister_netdev(dev);
+		cleanup_card(dev);
+		free_netdev(dev);
 	}
 }
 #endif				/* MODULE */
diff -Nru a/drivers/net/Space.c b/drivers/net/Space.c
--- a/drivers/net/Space.c	Wed Nov 12 13:20:13 2003
+++ b/drivers/net/Space.c	Wed Nov 12 13:20:13 2003
@@ -84,7 +84,7 @@
 extern int hplance_probe(struct net_device *dev);
 extern int bagetlance_probe(struct net_device *);
 extern int mvme147lance_probe(struct net_device *dev);
-extern int tc515_probe(struct net_device *dev);
+extern struct net_device *tc515_probe(int unit);
 extern struct net_device *lance_probe(int unit);
 extern int mace_probe(struct net_device *dev);
 extern int macsonic_probe(struct net_device *dev);
@@ -201,13 +201,13 @@
 #ifdef CONFIG_HP100 		/* ISA, EISA & PCI */
 	{hp100_probe, 0},
 #endif	
-#ifdef CONFIG_3C515
-	{tc515_probe, 0},
-#endif
 	{NULL, 0},
 };
 
 static struct devprobe2 isa_probes2[] __initdata = {
+#ifdef CONFIG_3C515
+	{tc515_probe, 0},
+#endif
 #ifdef CONFIG_ULTRA 
 	{ultra_probe, 0},
 #endif

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2003-11-13 19:36 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-11-13  0:43 [PATCH] (19/42) 3c515-T10 Stephen Hemminger
2003-11-13 19:32 ` Stephen Hemminger
2003-11-13 19:36   ` Jeff Garzik

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).