[PARPORT] 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, 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:18:45 EST