lp fix against pre-2.1.127-7

Andrea Arcangeli (andrea@e-mind.com)
Fri, 6 Nov 1998 20:15:43 +0100 (CET)


Hpa, the stall you reported it' s due a missing schedule_timeout() ;->. I
didn' t noticed that in the last days because I was under pressure...

Here a preliminary patch that _only_ fix bugs (compared to 2.1.126), this
is not intended to go into 2.1.127 (even if safe) because I would like to
be sure that the trustirq thing really broke the printing somewhere before
to cut it out. In the weekend I'll try to submit to Linus a patch that fix
lp without cutting out the trustirq thing.

Trusting the irq is the only way to give a sense to the irq printing
here (and probably in many other places...).

Index: linux/drivers/char/lp.c
diff -u linux/drivers/char/lp.c:1.1.1.4 linux/drivers/char/lp.c:1.1.1.1.12.14
--- linux/drivers/char/lp.c:1.1.1.4 Wed Nov 4 13:06:06 1998
+++ linux/drivers/char/lp.c Fri Nov 6 20:07:10 1998
@@ -18,11 +18,7 @@
* by Riccardo Facchetti <fizban@tin.it>
* Redesigned interrupt handling for handle printers with buggy handshake
* by Andrea Arcangeli, 11 May 1998
- * Full efficient handling of printer with buggy irq handshake (now I have
- * understood the meaning of the strange handshake). This is done sending new
- * characters if the interrupt is just happened, even if the printer say to
- * be still BUSY. This is needed at least with Epson Stylus Color.
- * I also fixed the irq on the rising edge of the strobe problem.
+ * Fixed the irq on the rising edge of the strobe problem.
* Andrea Arcangeli, 15 Oct 1998
*/

@@ -84,13 +80,12 @@
*
* ftp://e-mind.com/pub/linux/pscan/
*
+ * 11 May 98, Andrea Arcangeli
+ *
* My printer scanner run on an Epson Stylus Color show that such printer
* generates the irq on the _rising_ edge of the STROBE. Now lp handle
* this case fine too.
*
- * I also understood that on such printer we are just allowed to send
- * new characters after the interrupt even if the BUSY line is still active.
- *
* 15 Oct 1998, Andrea Arcangeli
*/

@@ -124,25 +119,16 @@
#ifdef LP_STATS
0, 0, {0},
#endif
- NULL, 0, 0, 0}
+ NULL, 0, 0, 0, 0}
};

-/*
- * Test if printer is ready.
- */
-#define LP_READY(status) \
+/* Test if printer is ready (and optionally has no error conditions) */
+#define LP_READY(minor, status) \
+ ((LP_F(minor) & LP_CAREFUL) ? _LP_CAREFUL_READY(status) : ((status) & LP_PBUSY))
+#define _LP_CAREFUL_READY(status) \
((status) & (LP_PBUSY|LP_POUTPA|LP_PSELECD|LP_PERRORP)) == \
(LP_PBUSY|LP_PSELECD|LP_PERRORP)

-/*
- * Test if the printer has error conditions.
- */
-#define LP_NO_ERROR(status) \
- ((status) & (LP_POUTPA|LP_PSELECD|LP_PERRORP)) == \
- (LP_PSELECD|LP_PERRORP)
-
-#define LP_NO_ACKING(status) ((status) & LP_PACK)
-
#undef LP_DEBUG
#undef LP_READ_DEBUG

@@ -189,7 +175,7 @@
schedule_timeout(timeout);
lp_parport_claim(minor);
} else
- schedule();
+ schedule_timeout(timeout);
}

static int lp_reset(int minor)
@@ -221,27 +207,9 @@

for (;;)
{
- unsigned char status;
lp_yield(minor);
-
- status = r_str(minor);
- /*
- * On Epson Stylus Color we must continue even if LP_READY()
- * is false to be efficient. This way is backwards
- * compatible with old not-buggy printers. -arca
- */
- if (LP_NO_ERROR(status) &&
- ((lp_table[minor].irq_detected && LP_NO_ACKING(status)) ||
- LP_READY(status)))
+ if (LP_READY(minor, r_str(minor)))
break;
- /*
- * To have a chance to sleep on the interrupt we should break
- * the polling loop ASAP. Unfortunately there seems to be
- * some hardware that underperform so we leave this
- * configurable at runtime. So when printing with irqs
- * `tunelp /dev/lp0 -c 1' is a must to take the full
- * advantage of the irq. -arca
- */
if (++count == LP_CHAR(minor))
return 0;
}
@@ -253,19 +221,6 @@
stats->chars++;
#endif

- /*
- * Epson Stylus Color generate the IRQ on the rising edge of
- * strobe so clean the irq's information before playing with
- * the strobe. -arca
- */
- lp_table[minor].irq_detected = 0;
- lp_table[minor].irq_missed = 0;
- /*
- * Be sure that the CPU doesn' t reorder instruction. I am not sure
- * if it' s needed also before an outb(). If not tell me ;-). -arca
- */
- mb();
-
/* must wait before taking strobe high, and after taking strobe
low, according spec. Some printers need it, others don't. */
lp_wait(minor);
@@ -277,11 +232,29 @@
lp_wait(minor);
w_ctr(minor, LP_PSELECP | LP_PINITP);
} else {
+ /*
+ * Epson Stylus Color generate the IRQ on the rising edge of
+ * strobe so clean the irq's information before playing with
+ * the strobe. -arca
+ */
+ lp_table[minor].irq_detected = 0;
+ lp_table[minor].irq_missed = 0;
+ /*
+ * Be sure that the CPU doesn' t reorder instructions.
+ * I am not sure if it' s needed also before an outb().
+ * If not tell me ;-). -arca
+ */
+ mb();
w_ctr(minor, LP_PSELECP | LP_PINITP | LP_PSTROBE | LP_PINTEN);
lp_wait(minor);
w_ctr(minor, LP_PSELECP | LP_PINITP | LP_PINTEN);
}

+ /*
+ * Give to the printer a chance to put BUSY low.
+ */
+ lp_wait(minor);
+
#ifdef LP_STATS
/* update waittime statistics */
if (count > stats->maxwait) {
@@ -371,7 +344,6 @@
lp_table[minor].last_error = 0;
lp_table[minor].irq_detected = 0;
lp_table[minor].irq_missed = 1;
- LP_POLLED(minor) = lp_table[minor].dev->port->irq == PARPORT_IRQ_NONE;

if (LP_POLLED(minor))
w_ctr(minor, LP_PSELECP | LP_PINITP);
@@ -480,6 +452,12 @@
*/
lp_parport_claim (minor);

+ /*
+ * We can set the polled flag here since once we have parport claimed
+ * the parport irq remains locked. -arca
+ */
+ LP_POLLED(minor) = lp_table[minor].dev->port->irq == PARPORT_IRQ_NONE;
+
retv = lp_write_buf(minor, buf, count);

lp_parport_release (minor);
@@ -694,6 +672,12 @@
else
LP_F(minor) &= ~LP_ABORTOPEN;
break;
+ case LPCAREFUL:
+ if (arg)
+ LP_F(minor) |= LP_CAREFUL;
+ else
+ LP_F(minor) &= ~LP_CAREFUL;
+ break;
case LPWAIT:
LP_WAIT(minor) = arg;
break;
@@ -736,7 +720,6 @@
}
return retval;
}
-

static struct file_operations lp_fops = {
lp_lseek,
Index: linux/include/linux/lp.h
diff -u linux/include/linux/lp.h:1.1.1.4 linux/include/linux/lp.h:1.1.1.1.12.6
--- linux/include/linux/lp.h:1.1.1.4 Wed Nov 4 13:09:24 1998
+++ linux/include/linux/lp.h Fri Nov 6 02:02:54 1998
@@ -25,9 +25,7 @@
#define LP_NOPA 0x0010
#define LP_ERR 0x0020
#define LP_ABORT 0x0040
-#if 0
#define LP_CAREFUL 0x0080
-#endif
#define LP_ABORTOPEN 0x0100

/* timeout for each character. This is relative to bus cycles -- it
@@ -67,11 +65,9 @@
or 0 for polling (no IRQ) */
#define LPGETIRQ 0x0606 /* get the current IRQ number */
#define LPWAIT 0x0608 /* corresponds to LP_INIT_WAIT */
-#ifdef LP_NEED_CAREFUL
#define LPCAREFUL 0x0609 /* call with TRUE arg to require out-of-paper, off-
line, and error indicators good on all writes,
FALSE to ignore them. Default is ignore. */
-#endif
#define LPABORTOPEN 0x060a /* call with TRUE arg to abort open() on error,
FALSE to ignore error. Default is ignore. */
#define LPGETSTATUS 0x060b /* return LP_S(minor) */

Andrea Arcangeli

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/