patch-2.0.14 linux/drivers/net/depca.c

Next file: linux/drivers/net/ewrk3.c
Previous file: linux/drivers/net/de4x5.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.0.13/linux/drivers/net/depca.c linux/drivers/net/depca.c
@@ -202,11 +202,13 @@
 			  Add new multicasting code.
       0.421   22-Apr-96	  Fix alloc_device() bug <jari@markkus2.fimr.fi>
       0.422   29-Apr-96	  Fix depca_hw_init() bug <jari@markkus2.fimr.fi>
+      0.423    7-Jun-96   Fix module load bug <kmg@barco.be>
+      0.43    16-Aug-96   Update alloc_device() to conform to de4x5.c
 
     =========================================================================
 */
 
-static const char *version = "depca.c:v0.422 96/4/29 davies@wanton.lkg.dec.com\n";
+static const char *version = "depca.c:v0.43 96/8/16 davies@wanton.lkg.dec.com\n";
 
 #include <linux/module.h>
 
@@ -231,6 +233,7 @@
 #include <linux/time.h>
 #include <linux/types.h>
 #include <linux/unistd.h>
+#include <linux/ctype.h>
 
 #include "depca.h"
 
@@ -407,6 +410,8 @@
 static void   isa_probe(struct device *dev, u_long iobase);
 static void   eisa_probe(struct device *dev, u_long iobase);
 static struct device *alloc_device(struct device *dev, u_long iobase);
+static int    depca_dev_index(char *s);
+static struct device *insert_device(struct device *dev, u_long iobase, int (*init)(struct device *));
 static int    load_packet(struct device *dev, struct sk_buff *skb);
 static void   depca_dbg_open(struct device *dev);
 
@@ -483,22 +488,13 @@
   outb(nicsr, DEPCA_NICSR);
 
   if (inw(DEPCA_DATA) == STOP) {
-    if (mem == 0) {
-      while (mem_base[mem_chkd]) {
-	mem_start = mem_base[mem_chkd++];
-	DepcaSignature(name, mem_start);
-	if (*name != '\0') break;
-      }
-    } else {
-      mem_start = mem;
-      if (adapter_name) {
-	strcpy(name, adapter_name);
-      } else{
-	DepcaSignature(name, mem_start);
-      }
-    }
+    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));
 
-    if ((*name != '\0') && mem_start) {           /* found a DEPCA device */
+    if ((adapter != unknown) && mem_start) {        /* found a DEPCA device */
       dev->base_addr = ioaddr;
 
       if ((ioaddr&0x0fff)==DEPCA_EISA_IO_PORTS) {/* EISA slot address */
@@ -650,6 +646,8 @@
 	printk("      which has an Ethernet PROM CRC error.\n");
 	status = -ENXIO;
       }
+    } else {
+      status = -ENXIO;
     }
     if (!status) {
       if (depca_debug > 0) {
@@ -1290,113 +1288,95 @@
 }
 
 /*
-** Allocate the device by pointing to the next available space in the
-** device structure. Should one not be available, it is created.
+** 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 device *alloc_device(struct device *dev, u_long iobase)
+static struct device *
+alloc_device(struct device *dev, u_long iobase)
 {
-  int addAutoProbe = 0;
-  struct device *tmp = NULL, *ret;
-  int (*init)(struct device *) = NULL;
+    struct device *adev = NULL;
+    int fixed = 0, new_dev = 0;
 
-  /*
-  ** Check the device structures for an end of list or unused device
-  */
-  if (!loading_module) {
-    while (dev->next != NULL) {
-      if ((dev->base_addr == DEPCA_NDA) || (dev->base_addr == 0)) break;
-      dev = dev->next;                     /* walk through eth device list */
-      num_eth++;                           /* increment eth device number */
+    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 an autoprobe is requested for another device, we must re-insert
-    ** the request later in the list. Remember the current information.
-    */
-    if ((dev->base_addr == 0) && (num_depcas > 0)) {
-      addAutoProbe++;
-      tmp = dev->next;                     /* point to the next device */
-      init = dev->init;                    /* remember the probe function */
+    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 list and can't use current entry, malloc one up. 
-    ** If memory could not be allocated, print an error message.
-    */
-    if ((dev->next == NULL) &&  
-	!((dev->base_addr == DEPCA_NDA) || (dev->base_addr == 0))){
-      dev->next = (struct device *)kmalloc(sizeof(struct device) + 8,
-					   GFP_KERNEL);
-
-      dev = dev->next;                     /* point to the new device */
-      if (dev == NULL) {
-	printk("eth%d: Device not initialised, insufficient memory\n",
-	       num_eth);
-      } else {
-	/*
-	** If the memory was allocated, point to the new memory area
-	** and initialize it (name, I/O address, next device (NULL) and
-	** initialisation probe routine).
-	*/
+/*
+** 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 device *
+insert_device(struct device *dev, u_long iobase, int (*init)(struct device *))
+{
+    struct device *new;
+
+    new = (struct device *)kmalloc(sizeof(struct device)+8, 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 */
 	dev->name = (char *)(dev + 1);
 	if (num_eth > 9999) {
-	  sprintf(dev->name,"eth????");    /* New device name */
+	    sprintf(dev->name,"eth????");/* New device name */
 	} else {
-	  sprintf(dev->name,"eth%d", num_eth);/* New device name */
+	    sprintf(dev->name,"eth%d", num_eth);/* New device name */
 	}
-	dev->base_addr = iobase;           /* assign the io address */
-	dev->next = NULL;                  /* mark the end of list */
-	dev->init = &depca_probe;          /* initialisation routine */
-	num_depcas++;
-      }
+	dev->base_addr = iobase;       /* assign the io address */
+	dev->init = init;              /* initialisation routine */
     }
-    ret = dev;                             /* return current struct, or NULL */
-  
-    /*
-    ** Now figure out what to do with the autoprobe that has to be inserted.
-    ** Firstly, search the (possibly altered) list for an empty space.
-    */
-    if (ret != NULL) {
-      if (addAutoProbe) {
-	for (;(tmp->next!=NULL) && (tmp->base_addr!=DEPCA_NDA); tmp=tmp->next);
-
-	/*
-	** If no more device structures and can't use the current one, malloc
-	** one up. If memory could not be allocated, print an error message.
-	*/
-	if ((tmp->next == NULL) && !(tmp->base_addr == DEPCA_NDA)) {
-	  tmp->next = (struct device *)kmalloc(sizeof(struct device) + 8,
-					       GFP_KERNEL);
-	  tmp = tmp->next;                     /* point to the new device */
-	  if (tmp == NULL) {
-	    printk("%s: Insufficient memory to extend the device list.\n", 
-		   dev->name);
-	  } else {
-	    /*
-	    ** If the memory was allocated, point to the new memory area
-	    ** and initialize it (name, I/O address, next device (NULL) and
-	    ** initialisation probe routine).
-	    */
-	    tmp->name = (char *)(tmp + 1);
-	    if (num_eth > 9999) {
-	      sprintf(tmp->name,"eth????");       /* New device name */
-	    } else {
-	      sprintf(tmp->name,"eth%d", num_eth);/* New device name */
-	    }
-	    tmp->base_addr = 0;                /* re-insert the io address */
-	    tmp->next = NULL;                  /* mark the end of list */
-	    tmp->init = init;                  /* initialisation routine */
-	  }
-	} else {                               /* structure already exists */
-	  tmp->base_addr = 0;                  /* re-insert the io address */
-	}
-      }
+
+    return dev;
+}
+
+static int
+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;
     }
-  } else {
-    ret = dev;
-  }
 
-  return ret;
+    return i;
 }
 
 /*
@@ -1410,12 +1390,13 @@
   const char *signatures[] = DEPCA_SIGNATURE;
   char tmpstr[16];
 
-  for (i=0;i<16;i++) {                  /* copy the first 16 bytes of ROM to */
-    tmpstr[i] = readb(paddr+0xc000+i);  /* a temporary string */
+  /* Copy the first 16 bytes of ROM */
+  for (i=0;i<16;i++) {
+    tmpstr[i] = readb(paddr+0xc000+i);
   }
 
-  strcpy(name,"");
-  for (i=0;*signatures[i]!='\0' && *name=='\0';i++) {
+  /* 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 */
 	k++;
@@ -1423,12 +1404,19 @@
 	k=0;
       }
     }
-    if (k == strlen(signatures[i])) {
-      strcpy(name,signatures[i]);
+    if (k == strlen(signatures[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) break;
     }
   }
 
-  adapter = i - 1;
+  /* Update search results */
+  strcpy(name,signatures[i]);
+  adapter = i;
 
   return;
 }
@@ -1896,8 +1884,8 @@
 
 /*
  * Local variables:
- *  kernel-compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O2 -m486 -c depca.c"
+ *  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"
  *
- *  module-compile-command: "gcc -D__KERNEL__ -DMODULE -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -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:
  */

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov