Inaky Perez Gonzalez (inaky@peloncho.fis.ucm.es)
Sat, 09 May 1998 02:59:31 +0200
Hi all
I recently discovered a weird [though not very dangerours]
parport behaviour while using 2.1.99:
$ modprobe parport
$ modprobe parport_pc
Gave me:
parport0: PC-style at 0x378 [SPP,EPP,ECP,ECPEPP,ECPPS2]
parport1: PC-style at 0x278, irq 11 [SPP,PS2,EPP,ECPEPP,ECPPS2]
Now, doing:
$ rmmod parport_pc
$ modprobe parport_pc
Resulted in:
parport2: PC-style at 0x378 [SPP,EPP,ECP,ECPEPP,ECPPS2]
parport3: PC-style at 0x278, irq 11 [SPP,PS2,EPP,ECPEPP,ECPPS2]
If you repeated, it would go up each time ...
So, the problem is caused by the parport_register_port() and
parport_unregister_port() functions. These where incrementating the
ports count on registering but not on unregistration. The most
confusing effect of this was having the parport dancing around each
time you loaded/unloaded the module and lpd trying to find it.
Also, the registration function was using just the ports
number as number for the port. This is, IMHO, inherently dangerous, as
if we had, say three ports, addressed as 0, 1 and 2, removed the one
in the middle [ok, imagine you *can* do it], and then re-registered
it, it'd get address number 2, and thus a collision against third port
would happen.
So well, it took some time of simple hacking to do it instead
of studying f.... differential equations, so here it is :)
Have a nice time!
cd linux/drivers/misc/
diff -uN linux/drivers/misc/parport_share.c\~ linux/drivers/misc/parport_share.c
--- linux/drivers/misc/parport_share.c~ Sat May 2 02:25:34 1998
+++ linux/drivers/misc/parport_share.c Sat May 9 02:41:07 1998
@@ -66,7 +66,8 @@
struct parport *parport_register_port(unsigned long base, int irq, int dma,
struct parport_operations *ops)
{
- struct parport *tmp;
+ int counter;
+ struct parport *tmp, *itr;
/* Check for a previously registered port.
NOTE: we will ignore irq and dma if we find a previously
@@ -92,7 +93,25 @@
tmp->devices = tmp->cad = NULL;
tmp->flags = 0;
tmp->ops = ops;
- tmp->number = portcount;
+ /* search a free address number <inaky@peloncho.fis.ucm.es> */
+ for (counter = 0, itr = portlist;
+ counter < portcount && itr != NULL;
+ counter++)
+ {
+ itr = portlist;
+ /* we walk the list now, and if the number 'counter' is
+ * used, we skip to the next one; if it isn't, 'itr' will end
+ * the loop being NULL, what should make the for loop finish.
+ */
+ while (itr != NULL)
+ if (itr->number == counter) /* used? ... */
+ break; /* ... skip to next */
+ else
+ itr = itr->next;
+ if (itr == NULL) /* if unused, we get it */
+ break;
+ }
+ tmp->number = counter;
spin_lock_init (&tmp->lock);
tmp->name = kmalloc(15, GFP_KERNEL);
@@ -101,7 +120,7 @@
kfree(tmp);
return NULL;
}
- sprintf(tmp->name, "parport%d", portcount);
+ sprintf(tmp->name, "parport%d", tmp->number);
/* Chain the entry to our list. */
if (portlist_tail)
@@ -133,6 +152,7 @@
portlist_tail = p;
}
}
+ portcount--;
kfree(port);
}
Diff finished at Sat May 9 02:42:33
--Linux-USB! http://peloncho.fis.ucm.es/~inaky/USB.html - - Inaky Perez Gonzalez -- PGP pubkey fingerprint - inaky@peloncho.fis.ucm.es -- 8E 34 3A 62 64 99 E2 44 - http://peloncho.fis.ucm.es/~inaky -- AD 7B 30 D9 DD FF 3E 4C - --------------------------------- -- ----------------------- - The loneliness of the long distance runner .....
-- To unsubscribe, send mail to: linux-parport-request@torque.net -- -- with the single word "unsubscribe" in the body of the message. --
This archive was generated by hypermail 2.0b3 on Wed 30 Dec 1998 - 10:17:43 EST