patch-2.4.0-test3 linux/drivers/net/sk_g16.c

Next file: linux/drivers/net/sk_mca.c
Previous file: linux/drivers/net/sk98lin/skvpd.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.0-test2/linux/drivers/net/sk_g16.c linux/drivers/net/sk_g16.c
@@ -19,6 +19,8 @@
  *                  Paul Gortmaker, 03/97: Fix for v2.1.x to use read{b,w}
  *                  write{b,w} and memcpy -> memcpy_{to,from}io
  *
+ *		    Jeff Garzik, 06/2000, Modularize
+ *
 -*/
 
 static const char *rcsid = "$Id: sk_g16.c,v 1.1 1994/06/30 16:25:15 root Exp $";
@@ -53,8 +55,10 @@
  *        - Try to find out if the board is in 8 Bit or 16 Bit slot.
  *          If in 8 Bit mode don't use IRQ 11.
  *        - (Try to make it slightly faster.) 
+ *	  - Power management support
  */
 
+#include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/ptrace.h>
@@ -455,7 +459,8 @@
 /* static variables */
 
 static SK_RAM *board;  /* pointer to our memory mapped board components */
-
+static struct net_device *SK_dev;
+unsigned long SK_ioaddr;
 static spinlock_t SK_lock = SPIN_LOCK_UNLOCKED;
 
 /* Macros */
@@ -537,7 +542,7 @@
 
 int __init SK_init(struct net_device *dev)
 {
-	int ioaddr         = 0;            /* I/O port address used for POS regs */
+	int ioaddr;			   /* I/O port address used for POS regs */
 	int *port, ports[] = SK_IO_PORTS;  /* SK_G16 supported ports */
 
 	/* get preconfigured base_addr from dev which is done in Space.c */
@@ -548,15 +553,23 @@
 
 	if (base_addr > 0x0ff)        /* Check a single specified address */
 	{
+	    int rc = -ENODEV;
+
+	    ioaddr = base_addr;
+
 	    /* Check if on specified address is a SK_G16 */
+	    if (!request_region(ioaddr, ETHERCARD_TOTAL_SIZE, "sk_g16"))
+	    	return -EBUSY;
 
 	    if ( (inb(SK_POS0) == SK_IDLOW) ||
 		 (inb(SK_POS1) == SK_IDHIGH) )  
 	    {
-		return SK_probe(dev, base_addr);  
+		rc = SK_probe(dev, ioaddr);
 	    }
 
-	    return -ENODEV;            /* Sorry, but on specified address NO SK_G16 */
+	    if (rc)
+	        release_region(ioaddr, ETHERCARD_TOTAL_SIZE);
+	    return rc;
 	}
 	else if (base_addr > 0)       /* Don't probe at all */
 	{
@@ -571,7 +584,7 @@
 
 	    /* Check if I/O Port region is used by another board */
 
-	    if (check_region(ioaddr, ETHERCARD_TOTAL_SIZE))
+	    if (!request_region(ioaddr, ETHERCARD_TOTAL_SIZE, "sk_g16"))
 	    {
 		continue;             /* Try next Port address */
 	    }
@@ -581,6 +594,7 @@
 	    if ( !(inb(SK_POS0) == SK_IDLOW) ||
 		 !(inb(SK_POS1) == SK_IDHIGH) )
 	    {
+	        release_region(ioaddr, ETHERCARD_TOTAL_SIZE);
 		continue;             /* Try next Port address */
 	    }
 
@@ -590,6 +604,8 @@
 	    {
 		return 0; /* Card found and initialized */
 	    }
+
+	    release_region(ioaddr, ETHERCARD_TOTAL_SIZE);
 	}
 
 	dev->base_addr = base_addr;   /* Write back original base_addr */
@@ -598,6 +614,61 @@
 
 } /* End of SK_init */
 
+
+MODULE_AUTHOR("Patrick J.D. Weichmann");
+MODULE_DESCRIPTION("Schneider & Koch G16 Ethernet Device Driver");
+MODULE_PARM(io, "i");
+MODULE_PARM_DESC(io, "0 to probe common ports (unsafe), or the I/O base of the board");
+
+
+#ifdef MODULE
+static int io = 0; /* 0 == probe */
+
+static int __init SK_init_module (void)
+{
+	int rc;
+	
+	SK_dev = init_etherdev (NULL, 0);
+	if (!SK_dev)
+		return -ENOMEM;
+	
+	rc = SK_init (SK_dev);
+	if (rc) {
+		unregister_netdev (SK_dev);
+		kfree (SK_dev);
+		SK_dev = NULL;
+	}
+	
+	return rc;
+}
+#endif /* MODULE */
+
+
+static void __exit SK_cleanup_module (void)
+{
+	if (SK_dev) {
+		if (SK_dev->priv) {
+			kfree(SK_dev->priv);
+			SK_dev->priv = NULL;
+		}
+		unregister_netdev(SK_dev);
+		kfree(SK_dev);
+		SK_dev = NULL;
+	}
+	if (SK_ioaddr) {
+		release_region(SK_ioaddr, ETHERCARD_TOTAL_SIZE);
+		SK_ioaddr = 0;
+	}
+		
+}
+
+
+#ifdef MODULE
+module_init(SK_init_module);
+#endif
+module_exit(SK_cleanup_module);
+
+
 
 /*-
  * Function       : SK_probe
@@ -774,9 +845,6 @@
     }
     memset((char *) dev->priv, 0, sizeof(struct priv)); /* clear memory */
 
-    /* Grab the I/O Port region */
-    request_region(ioaddr, ETHERCARD_TOTAL_SIZE,"sk_g16");
-
     /* Assign our Device Driver functions */
 
     dev->open                   = SK_open;
@@ -817,6 +885,9 @@
     SK_print_ram(dev);
 #endif 
 
+    SK_dev = dev;
+    SK_ioaddr = ioaddr;
+
     return 0;                            /* Initialization done */
 
 } /* End of SK_probe() */
@@ -1078,8 +1149,7 @@
 
     /* Prepare LANCE Control and Status Registers */
 
-    save_flags(flags);
-    cli();
+    spin_lock_irqsave(&SK_lock, flags);
 
     SK_write_reg(CSR3, CSR3_ACON);   /* Ale Control !!!THIS MUST BE SET!!!! */
  
@@ -1114,7 +1184,7 @@
 
     SK_write_reg(CSR0, CSR0_INIT); 
 
-    restore_flags(flags);
+    spin_unlock_irqrestore(&SK_lock, flags);
 
     /* Wait until LANCE finished initialization */
     

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)