Re: .98 lp.o not working, .97 OK

Tom Grigg (st588@bayou.uh.edu)
Tue, 7 May 1996 04:56:01 -0500 (CDT)


On Mon, 6 May 1996, Eyal Lebedinsky wrote:

> lp.o just says "kernel: lp1 off-line" repeatedly.

Ok, I've figured out what's wrong with the code.

The test to see if the printer is off-line in the new code looks like this:

status = LP_S(minor);
if ((status & LP_OFFL) || !(status & LP_PSELECD)) {

However, there's a problem with the above. Peeking into
linux/include/linux/lp.h, we find LP_OFFL:

* These are the lp_table[minor].flags flags...
*/
#define LP_EXIST 0x0001
#define LP_SELEC 0x0002
#define LP_BUSY 0x0004
#define LP_OFFL 0x0008

going further, we find LP_PSELECD:

/*
* bit defines for 8255 status port
* base + 1
* accessed with LP_S(minor), which gets the byte...
*/
#define LP_PBUSY 0x80 /* inverted input, active high */
#define LP_PACK 0x40 /* unchanged input, active low */
#define LP_POUTPA 0x20 /* unchanged input, active high */
#define LP_PSELECD 0x10 /* unchanged input, active high */
#define LP_PERRORP 0x08 /* unchanged input, active low */

The important things to note are the comments above the lists of values.
Note that LP_OFFL is supposed to be used to test a bit in
lp_table[minor].flags, whereas LP_PSELECD is used to test a bit in
the value returned by LP_S(minor).

Now check the code at the top again and notice that the value returned by
LP_S(minor) is tested against both LP_OFFL and LP_PSELECD. LP_OFFL is
not supposed to be used to test a value returned by LP_S(minor), and in
this context is equivalent to LP_PERRORP (see above), which is not what
we want.

Oops, we get a continuous stream of 'lp off-line' error messages, perhaps
because LP_PERRORP is active low?

Anyway, here's a patch:

Index: linux/drivers/char/lp.c
===================================================================
RCS file: /usr/local/cvsroot/linux/drivers/char/lp.c,v
retrieving revision 1.1.1.2
diff -u -r1.1.1.2 lp.c
--- lp.c 1996/05/04 23:17:08 1.1.1.2
+++ lp.c 1996/05/07 09:28:04
@@ -183,7 +183,7 @@
if (lp_table[minor].runchars > LP_STAT(minor).maxrun)
LP_STAT(minor).maxrun = lp_table[minor].runchars;
status = LP_S(minor);
- if ((status & LP_OFFL) || !(status & LP_PSELECD)) {
+ if (!(status & LP_PSELECD)) {
printk(KERN_INFO "lp%d off-line\n", minor);
if (LP_F(minor) & LP_ABORT)
return rc?rc:-EIO;
@@ -248,7 +248,7 @@
LP_STAT(minor).maxrun = lp_table[minor].runchars;
status = LP_S(minor);

- if ((status & LP_OFFL) || !(status & LP_PSELECD)) {
+ if (!(status & LP_PSELECD)) {
printk(KERN_INFO "lp%d off-line\n", minor);
if(LP_F(minor) & LP_ABORT)
return temp-buf?temp-buf:-EIO;