netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH][2.6] depca update
@ 2003-09-16 19:12 Marc Zyngier
  2003-09-20 17:57 ` Jeff Garzik
  0 siblings, 1 reply; 2+ messages in thread
From: Marc Zyngier @ 2003-09-16 19:12 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: Andrew Morton, netdev

[-- Attachment #1: Type: text/plain, Size: 624 bytes --]

Jeff, Andrew,

I finally found some time to hack the depca driver, in basically the
same way I did with the de4x5 driver. The patch is quite big (shuffles
a lot of code around, removes lots of global variables), mainly in
order to use the driver model on every bus supported by this driver.

I also removed the probing from Space.c, so the usual warning about
device renumbering applies.

Tested on alpha (DE422, EISA) and i386 (two DE201, ISA), built-in and
modular. The MCA part is completly untested, since I lack the hardware
(no, I do not own every single piece of junk hardware out
there... ;-).

Thanks,

        M.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: depca.patch --]
[-- Type: text/x-patch, Size: 34010 bytes --]

--- ../vanilla/linux-2.5/drivers/net/depca.c	2003-05-12 06:53:34.000000000 +0200
+++ linux-2.5/drivers/net/depca.c	2003-09-16 20:40:18.000000000 +0200
@@ -1,4 +1,4 @@
-/*  depca.c: A DIGITAL DEPCA  & EtherWORKS ethernet driver for linux.
+/*  depca.c: A DIGITAL DEPCA & EtherWORKS ethernet driver for linux.
 
     Written 1994, 1995 by David C. Davies.
 
@@ -253,7 +253,8 @@
 #include <linux/types.h>
 #include <linux/unistd.h>
 #include <linux/ctype.h>
-#include <linux/mca-legacy.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
 
 #include <asm/uaccess.h>
 #include <asm/bitops.h>
@@ -265,7 +266,6 @@
 #endif
 
 #ifdef CONFIG_EISA
-#include <linux/device.h>
 #include <linux/eisa.h>
 #endif
 
@@ -305,21 +305,21 @@
 ** EISA bus defines
 */
 #define DEPCA_EISA_IO_PORTS 0x0c00	/* I/O port base address, slot 0 */
-#define MAX_EISA_SLOTS 16
-#define EISA_SLOT_INC 0x1000
 
 /*
 ** ISA Bus defines
 */
 #define DEPCA_RAM_BASE_ADDRESSES {0xc0000,0xd0000,0xe0000,0x00000}
-#define DEPCA_IO_PORTS {0x300, 0x200, 0}
 #define DEPCA_TOTAL_SIZE 0x10
-static short mem_chkd;
 
-/*
-** Adapter ID for the MCA EtherWORKS DE210/212 adapter
-*/
-#define DE212_ID 0x6def
+static struct {
+	u_long iobase;
+	struct platform_device *device;
+} depca_io_ports[] = {
+	{ 0x300, NULL },
+	{ 0x200, NULL },
+	{ 0    , NULL },
+};
 
 /*
 ** Name <-> Adapter mapping
@@ -330,34 +330,86 @@
 			 "DE210","DE212",\
                          "DE422",\
                          ""}
-static enum {
+
+static char* __initdata depca_signature[] = DEPCA_SIGNATURE;
+
+enum depca_type {
 	DEPCA, de100, de101, de200, de201, de202, de210, de212, de422, unknown
-} adapter;
+};
+
+static char depca_string[] = "depca";
+
+static int depca_device_remove (struct device *device);
 
 #ifdef CONFIG_EISA
 struct eisa_device_id depca_eisa_ids[] = {
-	{ "DEC4220" },
+	{ "DEC4220", de422 },
 	{ "" }
 };
 
 static int depca_eisa_probe  (struct device *device);
-static int depca_eisa_remove (struct device *device);
 
 struct eisa_driver depca_eisa_driver = {
 	.id_table = depca_eisa_ids,
 	.driver   = {
-		.name    = "depca",
+		.name    = depca_string,
 		.probe   = depca_eisa_probe,
-		.remove  = __devexit_p (depca_eisa_remove)
+		.remove  = __devexit_p (depca_device_remove)
 	}
 };
 #endif
 
+#ifdef CONFIG_MCA
+/*
+** Adapter ID for the MCA EtherWORKS DE210/212 adapter
+*/
+#define DE210_ID 0x628d
+#define DE212_ID 0x6def
+
+static short depca_mca_adapter_ids[] = {
+	DE210_ID,
+	DE212_ID,
+	0x0000
+};
+
+static char *depca_mca_adapter_name[] = {
+	"DEC EtherWORKS MC Adapter (DE210)",
+	"DEC EtherWORKS MC Adapter (DE212)",
+	NULL
+};
+
+static enum depca_type depca_mca_adapter_type[] = {
+	de210,
+	de212,
+	0
+};
+
+static int depca_mca_probe (struct device *);
+
+static struct mca_driver depca_mca_driver = {
+	.id_table = depca_mca_adapter_ids,
+	.driver   = {
+		.name   = depca_string,
+		.bus    = &mca_bus_type,
+		.probe  = depca_mca_probe,
+		.remove = __devexit_p(depca_device_remove),
+	},
+};
+#endif
+
+static int depca_isa_probe (struct device *);
+
+static struct device_driver depca_isa_driver = {
+	.name   = depca_string,
+	.bus    = &platform_bus_type,
+	.probe  = depca_isa_probe,
+	.remove = __devexit_p(depca_device_remove),
+};
+	
 /*
 ** Miscellaneous info...
 */
 #define DEPCA_STRLEN 16
-#define MAX_NUM_DEPCAS 2
 
 /*
 ** Memory Alignment. Each descriptor is 4 longwords long. To force a
@@ -402,10 +454,13 @@
 #define DEPCA_PKT_BIN_SZ  128	/* Should be >=100 unless you
 				   increase DEPCA_PKT_STAT_SZ */
 struct depca_private {
-	char devname[DEPCA_STRLEN];	/* Device Product String                  */
 	char adapter_name[DEPCA_STRLEN];	/* /proc/ioports string                  */
-	char adapter;		/* Adapter type                           */
-	char mca_slot;		/* MCA slot, if MCA else -1               */
+	enum depca_type adapter;		/* Adapter type */
+	enum {
+                DEPCA_BUS_MCA = 1,
+                DEPCA_BUS_ISA,
+                DEPCA_BUS_EISA,
+        } depca_bus;	        /* type of bus */
 	struct depca_init init_block;	/* Shadow Initialization block            */
 /* CPU address space fields */
 	struct depca_rx_desc *rx_ring;	/* Pointer to start of RX descriptor ring */
@@ -467,45 +522,39 @@
 /*
 ** Private functions
 */
-static int depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_slot);
 static void depca_init_ring(struct net_device *dev);
 static int depca_rx(struct net_device *dev);
 static int depca_tx(struct net_device *dev);
 
 static void LoadCSRs(struct net_device *dev);
 static int InitRestartDepca(struct net_device *dev);
-static void DepcaSignature(char *name, u_long paddr);
+static int DepcaSignature(char *name, u_long paddr);
 static int DevicePresent(u_long ioaddr);
 static int get_hw_addr(struct net_device *dev);
 static void SetMulticastFilter(struct net_device *dev);
-static void isa_probe(struct net_device *dev, u_long iobase);
-#ifdef CONFIG_MCA
-static void mca_probe(struct net_device *dev, u_long iobase);
-#endif
-static struct net_device *alloc_device(struct net_device *dev, u_long iobase);
-static int depca_dev_index(char *s);
-static struct net_device *insert_device(struct net_device *dev, u_long iobase, int (*init) (struct net_device *));
 static int load_packet(struct net_device *dev, struct sk_buff *skb);
 static void depca_dbg_open(struct net_device *dev);
 
-#ifdef MODULE
-static int autoprobed = 1, loading_module = 1;
-# else
 static u_char de1xx_irq[] __initdata = { 2, 3, 4, 5, 7, 9, 0 };
 static u_char de2xx_irq[] __initdata = { 5, 9, 10, 11, 15, 0 };
 static u_char de422_irq[] __initdata = { 5, 9, 10, 11, 0 };
 static u_char *depca_irq;
-static int autoprobed, loading_module;
-#endif				/* MODULE */
 
-static char name[DEPCA_STRLEN];
-static int num_depcas, num_eth;
+static int irq;
+static int io;
+static char *adapter_name;
 static int mem;			/* For loadable module assignment
 				   use insmod mem=0x????? .... */
-static char *adapter_name;	/* = '\0';     If no PROM when loadable module
-				   use insmod adapter_name=DE??? ...
-				   bss initializes this to zero
-				 */
+module_param (irq, int, 0);
+module_param (io, int, 0);
+module_param (adapter_name, charp, 0);
+module_param (mem, int, 0);
+MODULE_PARM_DESC(irq, "DEPCA IRQ number");
+MODULE_PARM_DESC(io, "DEPCA I/O base address");
+MODULE_PARM_DESC(adapter_name, "DEPCA adapter name");
+MODULE_PARM_DESC(mem, "DEPCA shared memory address");
+MODULE_LICENSE("GPL");
+
 /*
 ** Miscellaneous defines...
 */
@@ -513,52 +562,30 @@
     outw(CSR0, DEPCA_ADDR);\
     outw(STOP, DEPCA_DATA)
 
-int __init depca_probe(struct net_device *dev)
-{
-	int tmp = num_depcas, status = -ENODEV;
-	u_long iobase = dev->base_addr;
-
-	SET_MODULE_OWNER(dev);
-
-	if ((iobase == 0) && loading_module) {
-		printk("Autoprobing is not supported when loading a module based driver.\n");
-		status = -EIO;
-	} else {
-#ifdef CONFIG_MCA
-		mca_probe(dev, iobase);
-#endif
-		isa_probe(dev, iobase);
-#ifdef CONFIG_EISA
-		eisa_driver_register (&depca_eisa_driver);
-#endif
-
-		if ((tmp == num_depcas) && (iobase != 0) && loading_module) {
-			printk("%s: depca_probe() cannot find device at 0x%04lx.\n", dev->name, iobase);
-		}
-
-		/*
-		   ** Walk the device list to check that at least one device
-		   ** initialised OK
-		 */
-		for (; (dev->priv == NULL) && (dev->next != NULL); dev = dev->next);
-
-		if (dev->priv)
-			status = 0;
-		if (iobase == 0)
-			autoprobed = 1;
-	}
-
-	return status;
-}
-
-static int __init depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_slot)
+static int __init depca_hw_init (struct net_device *dev, struct device *device)
 {
 	struct depca_private *lp;
 	int i, j, offset, netRAM, mem_len, status = 0;
 	s16 nicsr;
-	u_long mem_start = 0, mem_base[] = DEPCA_RAM_BASE_ADDRESSES;
-	int is_eisa = ((ioaddr & 0x0fff) == DEPCA_EISA_IO_PORTS);
+	u_long ioaddr;
+	u_long mem_start;
+
+	/*
+	 * We are now supposed to enter this function with the
+	 * following fields filled with proper values :
+	 *
+	 * dev->base_addr
+	 * lp->mem_start
+	 * lp->depca_bus
+	 * lp->adapter
+	 *
+	 * dev->irq can be set if known from device configuration (on
+	 * MCA or EISA) or module option. Otherwise, it will be auto
+	 * detected.
+	 */
 
+	ioaddr = dev->base_addr;
+	
 	STOP_DEPCA;
 
 	nicsr = inb(DEPCA_NICSR);
@@ -569,24 +596,34 @@
 		return -ENXIO;
 	}
 
-	do {
-		strcpy(name, (adapter_name ? adapter_name : ""));
-		mem_start = (mem ? mem & 0xf0000 : mem_base[mem_chkd++]);
-		DepcaSignature(name, mem_start);
-	} while (!mem && mem_base[mem_chkd] && (adapter == unknown));
+	lp = (struct depca_private *) dev->priv;
+	mem_start = lp->mem_start;
 
-	if ((adapter == unknown) || !mem_start) {	/* DEPCA device not found */
+	if (!mem_start || lp->adapter < DEPCA || lp->adapter >=unknown)
 		return -ENXIO;
-	}
 
-	dev->base_addr = ioaddr;
+	printk ("%s: %s at 0x%04lx",
+	        device->bus_id, depca_signature[lp->adapter], ioaddr);
+	
+	switch (lp->depca_bus) {
+#ifdef CONFIG_MCA
+	case DEPCA_BUS_MCA:
+		printk(" (MCA slot %d)", to_mca_device(device)->slot + 1);
+		break;
+#endif
+
+#ifdef CONFIG_EISA
+	case DEPCA_BUS_EISA:
+		printk(" (EISA slot %d)", to_eisa_device(device)->slot);
+		break;
+#endif
 
-	if (mca_slot != -1) {
-		printk("%s: %s at 0x%04lx (MCA slot %d)", dev->name, name, ioaddr, mca_slot);
-	} else if (is_eisa) {	/* EISA slot address */
-		printk("%s: %s at 0x%04lx (EISA slot %d)", dev->name, name, ioaddr, (int) ((ioaddr >> 12) & 0x0f));
-	} else {		/* ISA port address */
-		printk("%s: %s at 0x%04lx", dev->name, name, ioaddr);
+	case DEPCA_BUS_ISA:
+		break;
+
+	default:
+		printk("Unknown DEPCA bus %d\n", lp->depca_bus);
+		return -ENXIO;
 	}
 
 	printk(", h/w address ");
@@ -601,18 +638,20 @@
 	printk("%2.2x", dev->dev_addr[i]);
 
 	/* Set up the maximum amount of network RAM(kB) */
-	netRAM = ((adapter != DEPCA) ? 64 : 48);
-	if ((nicsr & _128KB) && (adapter == de422))
+	netRAM = ((lp->adapter != DEPCA) ? 64 : 48);
+	if ((nicsr & _128KB) && (lp->adapter == de422))
 		netRAM = 128;
-	offset = 0x0000;
 
 	/* Shared Memory Base Address */
 	if (nicsr & BUF) {
-		offset = 0x8000;	/* 32kbyte RAM offset */
 		nicsr &= ~BS;	/* DEPCA RAM in top 32k */
 		netRAM -= 32;
+
+		/* Only EISA/ISA needs start address to be re-computed */
+		if (lp->depca_bus != DEPCA_BUS_MCA)
+			mem_start += 0x8000;
 	}
-	mem_start += offset;	/* (E)ISA start address */
+	
 	if ((mem_len = (NUM_RX_DESC * (sizeof(struct depca_rx_desc) + RX_BUFF_SZ) + NUM_TX_DESC * (sizeof(struct depca_tx_desc) + TX_BUFF_SZ) + sizeof(struct depca_init)))
 	    > (netRAM << 10)) {
 		printk(",\n       requests %dkB RAM: only %dkB is available!\n", (mem_len >> 10), netRAM);
@@ -622,23 +661,14 @@
 	printk(",\n      has %dkB RAM at 0x%.5lx", netRAM, mem_start);
 
 	/* Enable the shadow RAM. */
-	if (adapter != DEPCA) {
+	if (lp->adapter != DEPCA) {
 		nicsr |= SHE;
 		outb(nicsr, DEPCA_NICSR);
 	}
 
-	/* Define the device private memory */
-	if (!is_eisa) {
-		dev->priv = (void *) kmalloc(sizeof(struct depca_private), GFP_KERNEL);
-		if (dev->priv == NULL)
-			return -ENOMEM;
-	}
-	lp = (struct depca_private *) dev->priv;
-	memset((char *) dev->priv, 0, sizeof(struct depca_private));
-	lp->adapter = adapter;
-	lp->mca_slot = mca_slot;
 	lp->lock = SPIN_LOCK_UNLOCKED;
-	sprintf(lp->adapter_name, "%s (%s)", name, dev->name);
+	sprintf(lp->adapter_name, "%s (%s)",
+		depca_signature[lp->adapter], device->bus_id);
 	status = -EBUSY;
 
 	/* Initialisation Block */
@@ -702,7 +732,6 @@
 	/* To auto-IRQ we enable the initialization-done and DMA err,
 	   interrupts. For now we will always get a DMA error. */
 	if (dev->irq < 2) {
-#ifndef MODULE
 		unsigned char irqnum;
 		unsigned long irq_mask, delay;
 
@@ -725,6 +754,9 @@
 		case de422:
 			depca_irq = de422_irq;
 			break;
+
+		default:
+			break;	/* Not reached */
 		}
 
 		/* Trigger an initialization just for the interrupt. */
@@ -733,6 +765,7 @@
 		delay = jiffies + HZ/50;
 		while (time_before(jiffies, delay))
 			yield();
+
 		irqnum = probe_irq_off(irq_mask);
 
 		status = -ENXIO;
@@ -746,13 +779,11 @@
 					printk(" and uses IRQ%d.\n", dev->irq);
 				}
 
-			status = -ENXIO;
 			if (!dev->irq) {
 				printk(" but incorrect IRQ line detected.\n");
-				goto out_priv;
+				return -ENXIO;
 			}
 		}
-#endif				/* MODULE */
 	} else {
 		printk(" and assigned IRQ%d.\n", dev->irq);
 	}
@@ -773,17 +804,14 @@
 
 	dev->mem_start = 0;
 
-	/* Fill in the generic field of the device structure. */
-	if (!is_eisa)
-		ether_setup(dev);
+	device->driver_data = dev;
+	SET_NETDEV_DEV (dev, device);
+	
+	register_netdev (dev);
 	return 0;
-      out_priv:
-	if (!is_eisa) {
-		kfree(dev->priv);
-		dev->priv = NULL;
-	} else {
-		unregister_netdev (dev);
-	}
+
+ out_priv:
+	
 	return status;
 }
 \f
@@ -1284,215 +1312,265 @@
 	return;
 }
 
+static int __init depca_common_init (u_long ioaddr, struct net_device **devp)
+{
+	int status = 0;
+	
+	if (!request_region (ioaddr, DEPCA_TOTAL_SIZE, depca_string)) {
+		status = -EBUSY;
+		goto out;
+	}
+	
+	if (DevicePresent(ioaddr)) {
+		status = -ENODEV;
+		goto out_release;
+	}
+
+	if (!(*devp = alloc_etherdev (sizeof (struct depca_private)))) {
+		status = -ENOMEM;
+		goto out_release;
+	}
+
+	return 0;
+	
+ out_release:
+	release_region (ioaddr, DEPCA_TOTAL_SIZE);
+ out:
+	return status;
+}
+
 #ifdef CONFIG_MCA
 /*
 ** Microchannel bus I/O device probe
 */
-static void __init mca_probe(struct net_device *dev, u_long ioaddr)
+static int __init depca_mca_probe(struct device *device)
 {
 	unsigned char pos[2];
 	unsigned char where;
-	unsigned long iobase;
-	int irq;
-	int slot = 0;
+	unsigned long iobase, mem_start;
+	int irq, err;
+	struct mca_device *mdev = to_mca_device (device);
+	struct net_device *dev;
+	struct depca_private *lp;
 
 	/*
-	   ** See if we've been here before.
-	 */
-	if ((!ioaddr && autoprobed) || (ioaddr && !loading_module))
-		return;
-
-	if (MCA_bus) {
-		/*
-		   ** Search for the adapter.  If an address has been given, search 
-		   ** specifically for the card at that address.  Otherwise find the
-		   ** first card in the system.
-		 */
-		while ((dev != NULL) && ((slot = mca_find_adapter(DE212_ID, slot)) != MCA_NOTFOUND)) {
-			pos[0] = mca_read_stored_pos(slot, 2);
-			pos[1] = mca_read_stored_pos(slot, 3);
-
-			/*
-			   ** IO of card is handled by bits 1 and 2 of pos0.    
-			   **
-			   **    bit2 bit1    IO
-			   **       0    0    0x2c00
-			   **       0    1    0x2c10
-			   **       1    0    0x2c20
-			   **       1    1    0x2c30
-			 */
-			where = (pos[0] & 6) >> 1;
-			iobase = 0x2c00 + (0x10 * where);
-
-			if ((ioaddr) && (ioaddr != iobase)) {
-				/*
-				   ** Card was found, but not at the right IO location. Continue 
-				   ** scanning from the next MCA slot up for another card.
-				 */
-				slot++;
-				continue;
-			}
-
-			/*
-			   ** Found the adapter we were looking for. Now start setting it up.
-			   ** 
-			   ** First work on decoding the IRQ.  It's stored in the lower 4 bits
-			   ** of pos1.  Bits are as follows (from the ADF file):
-			   **
-			   **      Bits           
-			   **   3   2   1   0    IRQ 
-			   **   --------------------
-			   **   0   0   1   0     5
-			   **   0   0   0   1     9
-			   **   0   1   0   0    10
-			   **   1   0   0   0    11
-			   * */
-			where = pos[1] & 0x0f;
-			switch (where) {
-			case 1:
-				irq = 9;
-				break;
-			case 2:
-				irq = 5;
-				break;
-			case 4:
-				irq = 10;
-				break;
-			case 8:
-				irq = 11;
-				break;
-			default:
-				printk("%s: mca_probe IRQ error.  You should never get here (%d).\n", dev->name, where);
-				return;
-			}
-
-			/*
-			   ** Shared memory address of adapter is stored in bits 3-5 of pos0.
-			   ** They are mapped as follows:
-			   **
-			   **    Bit
-			   **   5  4  3       Memory Addresses
-			   **   0  0  0       C0000-CFFFF (64K)
-			   **   1  0  0       C8000-CFFFF (32K)
-			   **   0  0  1       D0000-DFFFF (64K)
-			   **   1  0  1       D8000-DFFFF (32K)
-			   **   0  1  0       E0000-EFFFF (64K)
-			   **   1  1  0       E8000-EFFFF (32K)
-			 */
-			where = (pos[0] & 0x18) >> 3;
-			mem = 0xc0000 + (where * 0x10000);
-			if (pos[0] & 0x20) {
-				mem += 0x8000;
-			}
+	** Search for the adapter.  If an address has been given, search 
+	** specifically for the card at that address.  Otherwise find the
+	** first card in the system.
+	*/
+	
+	pos[0] = mca_device_read_stored_pos(mdev, 2);
+	pos[1] = mca_device_read_stored_pos(mdev, 3);
 
-			/*
-			   ** Get everything allocated and initialized...  (almost just
-			   ** like the ISA and EISA probes)
-			 */
-			if (!request_region (iobase, DEPCA_TOTAL_SIZE, "depca")) {
-				if (autoprobed)
-					printk(KERN_WARNING "%s: region already allocated at 0x%04lx.\n", dev->name, iobase);
-				goto next;
-			}
-			if (DevicePresent(iobase) != 0) {
-				/*
-				   ** If the MCA configuration says the card should be here,
-				   ** it really should be here.
-				 */
-				printk(KERN_ERR "%s: MCA reports card at 0x%lx but it is not responding.\n", dev->name, iobase);
-				goto release_next;
-			}
+	/*
+	** IO of card is handled by bits 1 and 2 of pos0.    
+	**
+	**    bit2 bit1    IO
+	**       0    0    0x2c00
+	**       0    1    0x2c10
+	**       1    0    0x2c20
+	**       1    1    0x2c30
+	*/
+	where = (pos[0] & 6) >> 1;
+	iobase = 0x2c00 + (0x10 * where);
 
-			if (!(dev = alloc_device(dev, iobase)))
-				goto release_next;
+	/*
+	** Found the adapter we were looking for. Now start setting it up.
+	** 
+	** First work on decoding the IRQ.  It's stored in the lower 4 bits
+	** of pos1.  Bits are as follows (from the ADF file):
+	**
+	**      Bits           
+	**   3   2   1   0    IRQ 
+	**   --------------------
+	**   0   0   1   0     5
+	**   0   0   0   1     9
+	**   0   1   0   0    10
+	**   1   0   0   0    11
+	*/
+	where = pos[1] & 0x0f;
+	switch (where) {
+	case 1:
+		irq = 9;
+		break;
+	case 2:
+		irq = 5;
+		break;
+	case 4:
+		irq = 10;
+		break;
+	case 8:
+		irq = 11;
+		break;
+	default:
+		printk("%s: mca_probe IRQ error.  You should never get here (%d).\n", dev->name, where);
+		return -EINVAL;
+	}
 
-			num_eth++;
-			dev->irq = irq;
-			if (depca_hw_init(dev, iobase, slot))
-				goto release_next;
+	/*
+	** Shared memory address of adapter is stored in bits 3-5 of pos0.
+	** They are mapped as follows:
+	**
+	**    Bit
+	**   5  4  3       Memory Addresses
+	**   0  0  0       C0000-CFFFF (64K)
+	**   1  0  0       C8000-CFFFF (32K)
+	**   0  0  1       D0000-DFFFF (64K)
+	**   1  0  1       D8000-DFFFF (32K)
+	**   0  1  0       E0000-EFFFF (64K)
+	**   1  1  0       E8000-EFFFF (32K)
+	*/
+	where = (pos[0] & 0x18) >> 3;
+	mem_start = 0xc0000 + (where * 0x10000);
+	if (pos[0] & 0x20) {
+		mem_start += 0x8000;
+	}
+
+	/* claim the slot */
+	strncpy(mdev->name, depca_mca_adapter_name[mdev->index],
+		sizeof(mdev->name));
+	mca_device_set_claim(mdev, 1);
+	
+        /*
+	** Get everything allocated and initialized...  (almost just
+	** like the ISA and EISA probes)
+	*/
+	irq = mca_device_transform_irq(mdev, irq);
+	iobase = mca_device_transform_ioport(mdev, iobase);
+
+	if ((err = depca_common_init (iobase, &dev)))
+		goto out_unclaim;
+
+	dev->irq = irq;
+	dev->base_addr = iobase;
+	lp = dev->priv;
+	lp->depca_bus = DEPCA_BUS_MCA;
+	lp->adapter = depca_mca_adapter_type[mdev->index];
+	lp->mem_start = mem_start;
+	
+	if ((err = depca_hw_init(dev, device)))
+		goto out_free;
 			
-			/*
-			** Adapter initialized correctly:  Name it in
-			** /proc/mca.
-			*/
-			mca_set_adapter_name(slot, "DE210/212 Ethernet Adapter");
-			mca_mark_as_used(slot);
-			num_depcas++;
-
-			/*
-			   ** If this is a probe by a module, return after setting up the
-			   ** given card.
-			 */
-			if (ioaddr)
-				return;
-
-			/*
-			** Set up to check the next slot and loop.
-			 */
-			slot++;
-			continue;
+	return 0;
 
-	release_next:
-			release_region (iobase, DEPCA_TOTAL_SIZE);
-	next:
-			slot++;
-		}
-	}
+ out_free:
+	free_netdev (dev);
+	release_region (iobase, DEPCA_TOTAL_SIZE);
+ out_unclaim:
+	mca_device_set_claim(mdev, 0);
 
-	return;
+	return err;;
 }
 #endif
 
 /*
 ** ISA bus I/O device probe
 */
-static void __init isa_probe(struct net_device *dev, u_long ioaddr)
+
+static void depca_platform_release (struct device *device)
 {
-	int i = num_depcas, maxSlots;
-	s32 ports[] = DEPCA_IO_PORTS;
+	struct platform_device *pldev;
 
-	if (!ioaddr && autoprobed)
-		return;		/* Been here before ! */
-	if (ioaddr > 0x400)
-		return;		/* EISA Address */
-	if (i >= MAX_NUM_DEPCAS)
-		return;		/* Too many ISA adapters */
-
-	if (ioaddr == 0) {	/* Autoprobing */
-		maxSlots = MAX_NUM_DEPCAS;
-	} else {		/* Probe a specific location */
-		ports[i] = ioaddr;
-		maxSlots = i + 1;
-	}
-
-	for (; (i < maxSlots) && (dev != NULL) && ports[i]; i++) {
-		if (!request_region (ports[i], DEPCA_TOTAL_SIZE, "depca")) {
-			if (autoprobed)
-				printk("%s: region already allocated at 0x%04x.\n", dev->name, ports[i]);
+	/* free device */
+	pldev = to_platform_device (device);
+	kfree (pldev);
+}
+
+static void __init depca_platform_probe (void)
+{
+	int i;
+	struct platform_device *pldev;
+
+	for (i = 0; depca_io_ports[i].iobase; i++) {
+		depca_io_ports[i].device = NULL;
+		
+		/* if an address has been specified on the command
+		 * line, use it (if valid) */
+		if (io && io != depca_io_ports[i].iobase)
+			continue;
+		
+		if (!(pldev = kmalloc (sizeof (*pldev), GFP_KERNEL)))
 			continue;
-		}
 
-		if (DevicePresent(ports[i])) {
-			release_region (ports[i], DEPCA_TOTAL_SIZE);
+		memset (pldev, 0, sizeof (*pldev));
+		pldev->name = depca_string;
+		pldev->id   = i;
+		pldev->dev.platform_data = (void *) depca_io_ports[i].iobase;
+		pldev->dev.release       = depca_platform_release;
+		depca_io_ports[i].device = pldev;
+
+		if (platform_device_register (pldev)) {
+			kfree (pldev);
+			depca_io_ports[i].device = NULL;
 			continue;
 		}
 
-		if (!(dev = alloc_device(dev, ports[i]))) {
-			release_region (ports[i], DEPCA_TOTAL_SIZE);
-			continue;
+		if (!pldev->dev.driver) {
+		/* The driver was not bound to this device, there was
+		 * no hardware at this address. Unregister it, as the
+		 * release fuction will take care of freeing the
+		 * allocated structure */
+			
+			depca_io_ports[i].device = NULL;
+			platform_device_unregister (pldev);
 		}
+	}
+}
 
-		num_eth++;
+static enum depca_type __init depca_shmem_probe (ulong *mem_start)
+{
+	u_long mem_base[] = DEPCA_RAM_BASE_ADDRESSES;
+	enum depca_type adapter = unknown;
+	int i;
 
-		if (depca_hw_init(dev, ports[i], -1)) {
-			release_region (ports[i], DEPCA_TOTAL_SIZE);
-			continue;
-		}
+	for (i = 0; mem_base[i]; i++) {
+		*mem_start = mem ? mem : mem_base[i];
+		adapter = DepcaSignature (adapter_name, *mem_start);
+		if (adapter != unknown)
+			break;
+	}
+
+	return adapter;
+}
 
-		num_depcas++;
+static int __init depca_isa_probe (struct device *device)
+{
+	struct net_device *dev;
+	struct depca_private *lp;
+	u_long ioaddr, mem_start = 0;
+	enum depca_type adapter = unknown;
+	int status = 0;
+
+	ioaddr = (u_long) device->platform_data;
+
+	if ((status = depca_common_init (ioaddr, &dev)))
+		goto out;
+
+	adapter = depca_shmem_probe (&mem_start);
+	
+	if (adapter == unknown) {
+		status = -ENODEV;
+		goto out_free;
 	}
 
-	return;
+	dev->base_addr = ioaddr;
+	dev->irq = irq;		/* Use whatever value the user gave
+				 * us, and 0 if he didn't. */
+	lp = dev->priv;
+	lp->depca_bus = DEPCA_BUS_ISA;
+	lp->adapter = adapter;
+	lp->mem_start = mem_start;
+	
+	if ((status = depca_hw_init(dev, device)))
+		goto out_free;
+	
+	return 0;
+
+ out_free:
+	free_netdev (dev);
+	release_region (ioaddr, DEPCA_TOTAL_SIZE);
+ out:
+	return status;
 }
 
 /*
@@ -1504,202 +1582,120 @@
 {
 	struct eisa_device *edev;
 	struct net_device *dev;
-	u_long iobase;
+	struct depca_private *lp;
+	u_long ioaddr, mem_start;
 	int status = 0;
 
 	edev = to_eisa_device (device);
-	iobase = edev->base_addr + DEPCA_EISA_IO_PORTS;
+	ioaddr = edev->base_addr + DEPCA_EISA_IO_PORTS;
 
-	if (!request_region (iobase, DEPCA_TOTAL_SIZE, "depca")) {
-		status = -EBUSY;
+	if ((status = depca_common_init (ioaddr, &dev)))
 		goto out;
-	}
-	
-	if (DevicePresent(iobase)) {
-		status = -ENODEV;
-		goto out_release;
-	}
 
-	if (!(dev = init_etherdev (NULL, sizeof (struct depca_private)))) {
-		status = -ENOMEM;
-		goto out_release;
-	}
-		
-	eisa_set_drvdata (edev, dev);
+	/* It would have been nice to get card configuration from the
+	 * card. Unfortunately, this register is write-only (shares
+	 * it's address with the ethernet prom)... As we don't parse
+	 * the EISA configuration structures (yet... :-), just rely on
+	 * the ISA probing to sort it out... */
+	
+	depca_shmem_probe (&mem_start);
 
-	if ((status = depca_hw_init(dev, iobase, -1)))
+	dev->base_addr = ioaddr;
+	dev->irq = irq;
+	lp = dev->priv;
+	lp->depca_bus = DEPCA_BUS_EISA;
+	lp->adapter = edev->id.driver_data;
+	lp->mem_start = mem_start;
+	
+	if ((status = depca_hw_init(dev, device)))
 		goto out_free;
-
-	num_depcas++;
+	
 	return 0;
 
  out_free:
-	kfree (dev);
- out_release:
-	release_region (iobase, DEPCA_TOTAL_SIZE);
+	free_netdev (dev);
+	release_region (ioaddr, DEPCA_TOTAL_SIZE);
  out:
 	return status;
 }
+#endif
 
-static int __devexit depca_eisa_remove (struct device *device)
+static int __devexit depca_device_remove (struct device *device)
 {
 	struct net_device *dev;
-	struct eisa_device *edev;
 	struct depca_private *lp;
+	int bus;
 
-	edev = to_eisa_device (device);
-	dev  = eisa_get_drvdata (edev);
+	dev  = device->driver_data;
 	lp   = dev->priv;
 
 	unregister_netdev (dev);
 	iounmap (lp->sh_mem);
 	release_mem_region (lp->mem_start, lp->mem_len);
 	release_region (dev->base_addr, DEPCA_TOTAL_SIZE);
-	kfree (dev);
+	bus = lp->depca_bus;
+	free_netdev (dev);
 
 	return 0;
 }
-#endif
-
-/*
-** Search the entire 'eth' device list for a fixed probe. If a match isn't
-** found then check for an autoprobe or unused device location. If they
-** are not available then insert a new device structure at the end of
-** the current list.
-*/
-static struct net_device *__init alloc_device(struct net_device *dev, u_long iobase)
-{
-	struct net_device *adev = NULL;
-	int fixed = 0, new_dev = 0;
-
-	num_eth = depca_dev_index(dev->name);
-	if (loading_module)
-		return dev;
-
-	while (1) {
-		if (((dev->base_addr == DEPCA_NDA) || (dev->base_addr == 0)) && !adev) {
-			adev = dev;
-		} else if ((dev->priv == NULL) && (dev->base_addr == iobase)) {
-			fixed = 1;
-		} else {
-			if (dev->next == NULL) {
-				new_dev = 1;
-			} else if (strncmp(dev->next->name, "eth", 3) != 0) {
-				new_dev = 1;
-			}
-		}
-		if ((dev->next == NULL) || new_dev || fixed)
-			break;
-		dev = dev->next;
-		num_eth++;
-	}
-	if (adev && !fixed) {
-		dev = adev;
-		num_eth = depca_dev_index(dev->name);
-		new_dev = 0;
-	}
-
-	if (((dev->next == NULL) && ((dev->base_addr != DEPCA_NDA) && (dev->base_addr != 0)) && !fixed) || new_dev) {
-		num_eth++;	/* New device */
-		dev = insert_device(dev, iobase, depca_probe);
-	}
-
-	return dev;
-}
-
-/*
-** If at end of eth device list and can't use current entry, malloc
-** one up. If memory could not be allocated, print an error message.
-*/
-static struct net_device *__init insert_device(struct net_device *dev, u_long iobase, int (*init) (struct net_device *))
-{
-	struct net_device *new;
-
-	new = (struct net_device *) kmalloc(sizeof(struct net_device), GFP_KERNEL);
-	if (new == NULL) {
-		printk("eth%d: Device not initialised, insufficient memory\n", num_eth);
-		return NULL;
-	} else {
-		new->next = dev->next;
-		dev->next = new;
-		dev = dev->next;	/* point to the new device */
-		if (num_eth > 9999) {
-			sprintf(dev->name, "eth????");	/* New device name */
-		} else {
-			sprintf(dev->name, "eth%d", num_eth);	/* New device name */
-		}
-		dev->base_addr = iobase;	/* assign the io address */
-		dev->init = init;	/* initialisation routine */
-	}
-
-	return dev;
-}
-
-static int __init depca_dev_index(char *s)
-{
-	int i = 0, j = 0;
-
-	for (; *s; s++) {
-		if (isdigit(*s)) {
-			j = 1;
-			i = (i * 10) + (*s - '0');
-		} else if (j)
-			break;
-	}
-
-	return i;
-}
 
 /*
 ** Look for a particular board name in the on-board Remote Diagnostics
 ** and Boot (readb) ROM. This will also give us a clue to the network RAM
 ** base address.
 */
-static void __init DepcaSignature(char *name, u_long paddr)
+static int __init DepcaSignature(char *name, u_long base_addr)
 {
 	u_int i, j, k;
-	const char *signatures[] = DEPCA_SIGNATURE;
 	void *ptr;
 	char tmpstr[16];
+	u_long prom_addr = base_addr + 0xc000;
+	u_long mem_addr = base_addr + 0x8000; /* 32KB */
+
+	/* Can't reserve the prom region, it is already marked as
+	 * used, at least on x86. Instead, reserve a memory region a
+	 * board would certainly use. If it works, go ahead. If not,
+	 * run like hell... */
+	
+	if (!request_mem_region (mem_addr, 16, depca_string))
+		return unknown;
 
 	/* Copy the first 16 bytes of ROM */
-	ptr = ioremap(paddr + 0xc000, 16);
+
+	ptr = ioremap(prom_addr, 16);
 	if (ptr == NULL) {
-		printk(KERN_ERR "depca: I/O remap failed at %lx\n", paddr + 0xc000);
-		adapter = unknown;
-		return;
+		printk(KERN_ERR "depca: I/O remap failed at %lx\n", prom_addr);
+		return unknown;
 	}
 	for (i = 0; i < 16; i++) {
 		tmpstr[i] = readb(ptr + i);
 	}
 	iounmap(ptr);
 
+	release_mem_region (mem_addr, 16);
+
 	/* Check if PROM contains a valid string */
-	for (i = 0; *signatures[i] != '\0'; i++) {
-		for (j = 0, k = 0; j < 16 && k < strlen(signatures[i]); j++) {
-			if (signatures[i][k] == tmpstr[j]) {	/* track signature */
+	for (i = 0; *depca_signature[i] != '\0'; i++) {
+		for (j = 0, k = 0; j < 16 && k < strlen(depca_signature[i]); j++) {
+			if (depca_signature[i][k] == tmpstr[j]) {	/* track signature */
 				k++;
 			} else {	/* lost signature; begin search again */
 				k = 0;
 			}
 		}
-		if (k == strlen(signatures[i]))
+		if (k == strlen(depca_signature[i]))
 			break;
 	}
 
 	/* Check if name string is valid, provided there's no PROM */
-	if (*name && (i == unknown)) {
-		for (i = 0; *signatures[i] != '\0'; i++) {
-			if (strcmp(name, signatures[i]) == 0)
+	if (name && *name && (i == unknown)) {
+		for (i = 0; *depca_signature[i] != '\0'; i++) {
+			if (strcmp(name, depca_signature[i]) == 0)
 				break;
 		}
 	}
 
-	/* Update search results */
-	strcpy(name, signatures[i]);
-	adapter = i;
-
-	return;
+	return i;
 }
 
 /*
@@ -1773,10 +1769,11 @@
 static int __init get_hw_addr(struct net_device *dev)
 {
 	u_long ioaddr = dev->base_addr;
+	struct depca_private *lp = dev->priv;
 	int i, k, tmp, status = 0;
 	u_short j, x, chksum;
 
-	x = (((adapter == de100) || (adapter == de101)) ? 1 : 0);
+	x = (((lp->adapter == de100) || (lp->adapter == de101)) ? 1 : 0);
 
 	for (i = 0, k = 0, j = 0; j < 3; j++) {
 		k <<= 1;
@@ -2083,55 +2080,40 @@
 	return status;
 }
 
-#ifdef MODULE
-static struct net_device thisDepca;
-static int irq = 7;		/* EDIT THESE LINE FOR YOUR CONFIGURATION */
-static int io = 0x200;		/* Or use the irq= io= options to insmod */
-MODULE_PARM(irq, "i");
-MODULE_PARM(io, "i");
-MODULE_PARM_DESC(irq, "DEPCA IRQ number");
-MODULE_PARM_DESC(io, "DEPCA I/O base address");
-
-/* See depca_probe() for autoprobe messages when a module */
-int init_module(void)
+static int __init depca_module_init (void)
 {
-	thisDepca.irq = irq;
-	thisDepca.base_addr = io;
-	thisDepca.init = depca_probe;
+        int err = 0;
 
-	if (register_netdev(&thisDepca) != 0)
-		return -EIO;
-
-	return 0;
+#if CONFIG_MCA
+        err = mca_register_driver (&depca_mca_driver);
+#endif
+#ifdef CONFIG_EISA
+        err |= eisa_driver_register (&depca_eisa_driver);
+#endif
+	err |= driver_register (&depca_isa_driver);
+	depca_platform_probe ();
+	
+        return err;
 }
 
-void cleanup_module(void)
+static void __exit depca_module_exit (void)
 {
-	struct depca_private *lp = thisDepca.priv;
-
-	unregister_netdev(&thisDepca);
-	if (lp) {
-		iounmap(lp->sh_mem);
-		release_mem_region (lp->mem_start, lp->mem_len);
-#ifdef CONFIG_MCA
-		if (lp->mca_slot != -1)
-			mca_mark_as_unused(lp->mca_slot);
+	int i;
+#if CONFIG_MCA
+        mca_unregister_driver (&depca_mca_driver);
 #endif
-		kfree(lp);
-		thisDepca.priv = NULL;
-	}
-	thisDepca.irq = 0;
+#ifdef CONFIG_EISA
+        eisa_driver_unregister (&depca_eisa_driver);
+#endif
+	driver_unregister (&depca_isa_driver);
 
-	release_region(thisDepca.base_addr, DEPCA_TOTAL_SIZE);
+	for (i = 0; depca_io_ports[i].iobase; i++) {
+		if (depca_io_ports[i].device) {
+			platform_device_unregister (depca_io_ports[i].device);
+			depca_io_ports[i].device = NULL;
+		}
+	}
 }
-#endif				/* MODULE */
-MODULE_LICENSE("GPL");
-\f
 
-/*
- * Local variables:
- *  compile-command: "gcc -D__KERNEL__ -I/linux/include -Wall -Wstrict-prototypes -fomit-frame-pointer -fno-strength-reduce -malign-loops=2 -malign-jumps=2 -malign-functions=2 -O2 -m486 -c depca.c"
- *
- *  compile-command: "gcc -D__KERNEL__ -DMODULE -I/linux/include -Wall -Wstrict-prototypes -fomit-frame-pointer -fno-strength-reduce -malign-loops=2 -malign-jumps=2 -malign-functions=2 -O2 -m486 -c depca.c"
- * End:
- */
+module_init (depca_module_init);
+module_exit (depca_module_exit);
--- ../vanilla/linux-2.5/drivers/net/Space.c	2003-09-16 21:01:02.000000000 +0200
+++ linux-2.5/drivers/net/Space.c	2003-09-12 19:40:26.000000000 +0200
@@ -58,7 +58,6 @@
 extern int at1700_probe(struct net_device *);
 extern int fmv18x_probe(struct net_device *);
 extern int eth16i_probe(struct net_device *);
-extern int depca_probe(struct net_device *);
 extern int i82596_probe(struct net_device *);
 extern int ewrk3_probe(struct net_device *);
 extern int el1_probe(struct net_device *);
@@ -252,9 +247,6 @@
 #ifdef CONFIG_EEXPRESS_PRO	/* Intel EtherExpress Pro/10 */
 	{eepro_probe, 0},
 #endif
-#ifdef CONFIG_DEPCA		/* DEC DEPCA */
-	{depca_probe, 0},
-#endif
 #ifdef CONFIG_EWRK3             /* DEC EtherWORKS 3 */
     	{ewrk3_probe, 0},
 #endif

[-- Attachment #3: Type: text/plain, Size: 59 bytes --]


-- 
Places change, faces change. Life is so very strange.

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

* Re: [PATCH][2.6] depca update
  2003-09-16 19:12 [PATCH][2.6] depca update Marc Zyngier
@ 2003-09-20 17:57 ` Jeff Garzik
  0 siblings, 0 replies; 2+ messages in thread
From: Jeff Garzik @ 2003-09-20 17:57 UTC (permalink / raw)
  To: mzyngier; +Cc: Andrew Morton, netdev

applied

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

end of thread, other threads:[~2003-09-20 17:57 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-09-16 19:12 [PATCH][2.6] depca update Marc Zyngier
2003-09-20 17:57 ` 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).