[1087] in linux-net channel archive
PLIP [patch]
daemon@ATHENA.MIT.EDU (Philip Blundell)
Sun Sep 10 10:04:35 1995
Date: Sat, 9 Sep 1995 20:33:13 +0100 (BST)
From: Philip Blundell <pjb27@cam.ac.uk>
To: gniibe@mri.co.jp
cc: linux-net@vger.rutgers.edu
The attached diff fixes a couple of problems with the current PLIP driver.
Somehow, the check for the return value from register_netdev() seemed to be
backwards. This was causing all sorts of disaster when the driver was loaded
as a module, as it would register itself and then promptly flag 'failure to
initialise', leaving bad pointers all over the place.
There was also a small problem with claiming workspace in plip_init. Although
the return value was being correctly checked, the code didn't free up the
claimed I/O ports when it returned the error status.
The port at 3BC was being treated as 4 bytes, whereas it is actually only 3.
This causes trouble with the mda console driver (which claims port 3bf for
itself).
I've also added a couple of new features. Firstly and trivially, a message
is printk()d if the driver is loaded but it doesn't find any ports. Secondly,
a variable 'portmap' is added. This is treated as a bitmap of which ports the
driver is allowed to use. The idea is that when you load the driver with
insmod, you can tell it to only grab one or two particular ports, so as to
leave some for the lp driver.
--- linux/drivers/net/plip.c Mon Aug 14 10:57:49 1995
+++ linux/drivers/net/plip.c Sat Sep 9 19:01:18 1995
@@ -12,6 +12,15 @@
* Modularization and ifreq/ifmap support by Alan Cox.
* Rewritten by Niibe Yutaka.
*
+ * 9-Sep-95 Philip Blundell <pjb27@cam.ac.uk>
+ * - portmask added
+ * - only claim 3 bytes of I/O space for port at 0x3bc
+ * - treat NULL return from register_netdev() as success in
+ * init_module()
+ * - added message if driver loaded as a module but no
+ * interfaces present.
+ * - release claimed I/O ports if malloc() fails during init
+ *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
@@ -106,6 +115,9 @@
#endif
static unsigned int net_debug = NET_DEBUG;
+/* Bit-mask of ports to support */
+int portmask = 0xff;
+
/* In micro second */
#define PLIP_DELAY_UNIT 1
@@ -206,8 +218,10 @@
{
struct net_local *nl;
+ int iosize = (PAR_DATA(dev) == 0x3bc) ? 3 : 8;
+
/* Check region before the probe */
- if (check_region(PAR_DATA(dev), (PAR_DATA(dev) == 0x3bc)? 4 : 8) < 0)
+ if (check_region(PAR_DATA(dev), iosize) < 0)
return -ENODEV;
/* Check that there is something at base_addr. */
@@ -244,7 +258,7 @@
" Please set IRQ by ifconfig.\n", irq);
}
- request_region(PAR_DATA(dev), (PAR_DATA(dev) == 0x3bc)? 4 : 8, dev->name);
+ request_region(PAR_DATA(dev), iosize, dev->name);
/* Fill in the generic fields of the device structure. */
ether_setup(dev);
@@ -260,8 +274,11 @@
/* Set the private structure */
dev->priv = kmalloc(sizeof (struct net_local), GFP_KERNEL);
- if (dev->priv == NULL)
- return EAGAIN;
+ if (dev->priv == NULL) {
+ printk(KERN_ERR "%s: out of memory\n", dev->name);
+ release_region(PAR_DATA(dev), iosize);
+ return -EAGAIN;
+ }
memset(dev->priv, 0, sizeof(struct net_local));
nl = (struct net_local *) dev->priv;
@@ -1066,14 +1083,22 @@
{
int devices=0;
- if (register_netdev(&dev_plip0) != 0)
- devices++;
- if (register_netdev(&dev_plip1) != 0)
- devices++;
- if (register_netdev(&dev_plip2) != 0)
- devices++;
- if (devices == 0)
+ if (portmask & 1) {
+ if (register_netdev(&dev_plip0) == 0)
+ devices++;
+ }
+ if (portmask & 2) {
+ if (register_netdev(&dev_plip1) == 0)
+ devices++;
+ }
+ if (portmask & 4) {
+ if (register_netdev(&dev_plip2) == 0)
+ devices++;
+ }
+ if (devices == 0) {
+ printk(KERN_INFO "plip: no interfaces found\n");
return -EIO;
+ }
return 0;
}
@@ -1082,19 +1107,19 @@
{
if (dev_plip0.priv) {
unregister_netdev(&dev_plip0);
- release_region(PAR_DATA(&dev_plip0), (PAR_DATA(&dev_plip0) == 0x3bc)? 4 : 8);
+ release_region(PAR_DATA(&dev_plip0), (PAR_DATA(&dev_plip0) == 0x3bc) ? 3 : 8);
kfree_s(dev_plip0.priv, sizeof(struct net_local));
dev_plip0.priv = NULL;
}
if (dev_plip1.priv) {
unregister_netdev(&dev_plip1);
- release_region(PAR_DATA(&dev_plip1), (PAR_DATA(&dev_plip1) == 0x3bc)? 4 : 8);
+ release_region(PAR_DATA(&dev_plip1), (PAR_DATA(&dev_plip1) == 0x3bc) ? 3 : 8);
kfree_s(dev_plip1.priv, sizeof(struct net_local));
dev_plip1.priv = NULL;
}
if (dev_plip2.priv) {
unregister_netdev(&dev_plip2);
- release_region(PAR_DATA(&dev_plip2), (PAR_DATA(&dev_plip2) == 0x3bc)? 4 : 8);
+ release_region(PAR_DATA(&dev_plip2), (PAR_DATA(&dev_plip2) == 0x3bc) ? 3 : 8);
kfree_s(dev_plip2.priv, sizeof(struct net_local));
dev_plip2.priv = NULL;
}
--
pjb