[PARPORT] Re: patch-2.1.131-ac8-1284


Andrea Arcangeli (andrea@e-mind.com)
Tue, 15 Dec 1998 16:49:34 +0100 (CET)


On Mon, 14 Dec 1998, Tim Waugh wrote:

>My feeling is that the new code shouldn't need it. If it isn't ready
>straight away, we poll quite fast. parport_wait_peripheral could be made
>to start off very fast (every 5us instead of 25us, maybe).

I added debugging code that allow us to know when the irq make sense. I
also changed the compatibilty mode handshake to allow the irq to make
sense. Here the differences between the original ieee compatibility mode
code and the new after my changes:

Dec 15 16:28:12 laser kernel: lp0: using parport0 (interrupt-driven).
Dec 15 16:28:13 laser kernel: Using compatibility mode
Dec 15 16:28:13 laser kernel: Woo hoo! Using interrupts!
Dec 15 16:28:13 laser kernel: Woo hoo! Interrupt make sense!
Dec 15 16:28:13 laser kernel: Using compatibility mode
Dec 15 16:28:14 laser last message repeated 14 times
Dec 15 16:28:17 laser kernel: Woo hoo! Interrupt make sense!
Dec 15 16:28:17 laser kernel: Using compatibility mode
Dec 15 16:28:17 laser last message repeated 6 times
Dec 15 16:28:20 laser kernel: Woo hoo! Interrupt make sense!
Dec 15 16:28:21 laser last message repeated 2 times
Dec 15 16:28:21 laser kernel: Using compatibility mode
Dec 15 16:28:21 laser last message repeated 3 times
Dec 15 16:28:24 laser kernel: Woo hoo! Interrupt make sense!
Dec 15 16:28:24 laser kernel: Using compatibility mode
Dec 15 16:28:24 laser last message repeated 9 times
Dec 15 16:28:27 laser kernel: Woo hoo! Interrupt make sense!
Dec 15 16:28:27 laser kernel: Using compatibility mode
Dec 15 16:28:27 laser last message repeated 4 times

And after the changes:

Dec 15 16:31:00 laser kernel: parport0: PC-style at 0x378, irq 7
[SPP,ECP,ECPEPP
,ECPPS2]
Dec 15 16:31:00 laser kernel: lp0: using parport0 (interrupt-driven).
Dec 15 16:31:01 laser kernel: Using compatibility mode
Dec 15 16:31:01 laser kernel: Woo hoo! Using interrupts!
Dec 15 16:31:01 laser kernel: Woo hoo! Interrupt make sense!
Dec 15 16:31:01 laser last message repeated 11 times
Dec 15 16:31:01 laser kernel: oo hoo! Interrupt make sense!
Dec 15 16:31:01 laser kernel: Woo hoo! Interrupt make sense!
Dec 15 16:31:01 laser last message repeated 480 times
Dec 15 16:31:01 laser kernel: Using compatibility mode
Dec 15 16:31:01 laser kernel: Woo hoo! Interrupt make sense!
Dec 15 16:31:01 laser kernel: oo hoo! Interrupt make sense!
Dec 15 16:31:01 laser kernel: Woo hoo! Interrupt make sense!
Dec 15 16:31:01 laser last message repeated 962 times
Dec 15 16:31:01 laser kernel: Using compatibility mode
Dec 15 16:31:01 laser kernel: Woo hoo! Interrupt make sense!
Dec 15 16:31:01 laser last message repeated 5 times
Dec 15 16:31:01 laser kernel: ooo hoo! Interrupt make sense!
Dec 15 16:31:01 laser kernel: Woo hoo! Interrupt make sense!
Dec 15 16:31:01 laser last message repeated 481 times
Dec 15 16:31:01 laser kernel: ooo hoo! Interrupt make sense!
Dec 15 16:31:01 laser kernel: Woo hoo! Interrupt make sense!
Dec 15 16:31:01 laser last message repeated 481 times
Dec 15 16:31:01 laser kernel: Using compatibility mode
Dec 15 16:31:01 laser kernel: oo hoo! Interrupt make sense!
Dec 15 16:31:01 laser kernel: Woo hoo! Interrupt make sense!
Dec 15 16:31:01 laser last message repeated 359 times
Dec 15 16:31:01 laser kernel: Woo hoo! Interroo hoo! Interrupt make sense!
Dec 15 16:31:01 laser kernel: Woo hoo! Interrupt make sense!
Dec 15 16:31:01 laser last message repeated 480 times
Dec 15 16:31:01 laser kernel: Using compatibility mode
Dec 15 16:31:01 laser kernel: Woo hoo! Interrupt make sense!
Dec 15 16:31:01 laser last message repeated 125 times
Dec 15 16:31:01 laser kernel: Woo hoo! Inteoo hoo! Interrupt make sense!
Dec 15 16:31:01 laser kernel: Woo hoo! Interrupt make sense!
Dec 15 16:31:01 laser last message repeated 480 times
Dec 15 16:31:01 laser kernel: Using compatibility mode
Dec 15 16:31:01 laser kernel: Woo hoo! Interrupt make sense!
Dec 15 16:31:01 laser last message repeated 27 times
Dec 15 16:31:01 laser kernel: Using compatibility mode
Dec 15 16:31:01 laser kernel: oo hoo! Interrupt make sense!
Dec 15 16:31:01 laser kernel: Woo hoo! Interrupt make sense!
Dec 15 16:31:01 laser last message repeated 487 times
Dec 15 16:31:01 laser kernel: oo hoo! Interrupt make sense!
Dec 15 16:31:01 laser kernel: Woo hoo! Interrupt make sense!
Dec 15 16:31:01 laser last message repeated 359 times
Dec 15 16:31:01 laser kernel: Woo hoo! Interroo hoo! Interrupt make sense!
Dec 15 16:31:01 laser kernel: Woo hoo! Interrupt make sense!
Dec 15 16:31:01 laser last message repeated 480 times
Dec 15 16:31:01 laser kernel: Using compatibility mode
Dec 15 16:31:02 laser last message repeated 2 times
Dec 15 16:31:02 laser kernel: Woo hoo! Interrupt make sense!
Dec 15 16:31:02 laser last message repeated 393 times
Dec 15 16:31:02 laser kernel: Using compatibility mode
Dec 15 16:31:02 laser kernel: Woo hoo! Interrupt make sense!
Dec 15 16:31:02 laser last message repeated 6 times
Dec 15 16:31:02 laser kernel: Using compatibility mode
Dec 15 16:31:02 laser kernel: Woo hoo! Interrupt make sense!
Dec 15 16:31:02 laser last message repeated 4 times
Dec 15 16:31:02 laser kernel: oo hoo! Interrupt make sense!
Dec 15 16:31:02 laser kernel: Woo hoo! Interrupt make sense!
Dec 15 16:31:02 laser last message repeated 480 times
Dec 15 16:31:02 laser kernel: oo hoo! Interrupt make sense!

I don' t need to say that the CPU get very lighter efficiently used
and being far to lose printing performance...

For the LP_STATS issue I personally don' t care. I am the guy that
#ifdeffed the stuff btw ;). If somebody will fix it in obvious way it' s
welcome though ;)

Here a new whole patch against patch-2.1.131-ac8-iee1284 on torque.net:

diff -urN linux/drivers/misc/parport_arc.c linux-arca/drivers/misc/parport_arc.c
--- linux/drivers/misc/parport_arc.c Sat Dec 12 13:16:55 1998
+++ linux-arca/drivers/misc/parport_arc.c Tue Dec 15 15:47:27 1998
@@ -116,15 +116,15 @@
         arc_dec_use_count,
         arc_fill_inode,
 
- NULL, /* epp_write_block */
- NULL, /* epp_read_block */
+ parport_ieee1284_write_epp, /* epp_write_block */
+ parport_ieee1284_read_epp, /* epp_read_block */
 
- NULL, /* ecp_write_block */
- NULL, /* epp_write_block */
-
- NULL, /* compat_write_block */
- NULL, /* nibble_read_block */
- NULL /* byte_read_block */
+ parport_ieee1284_write_ecp, /* ecp_write_block */
+ parport_ieee1284_read_ecp, /* ecp_read_block */
+
+ parport_ieee1284_write_compat, /* compat_write_block */
+ parport_ieee1284_read_nibble, /* nibble_read_block */
+ parport_ieee1284_read_byte, /* byte_read_block */
 };
 
 /* --- Initialisation code -------------------------------- */
diff -urN linux/drivers/misc/parport_ax.c linux-arca/drivers/misc/parport_ax.c
--- linux/drivers/misc/parport_ax.c Sat Dec 12 13:16:55 1998
+++ linux-arca/drivers/misc/parport_ax.c Tue Dec 15 15:47:31 1998
@@ -323,17 +323,17 @@
 
         parport_ax_inc_use_count,
         parport_ax_dec_use_count,
- parport_ax_fill_inode
+ parport_ax_fill_inode,
 
- NULL, /* epp_write_block */
- NULL, /* epp_read_block */
+ parport_ieee1284_write_epp, /* epp_write_block */
+ parport_ieee1284_read_epp, /* epp_read_block */
 
- NULL, /* ecp_write_block */
- NULL, /* ecp_read_block */
+ parport_ieee1284_write_ecp, /* ecp_write_block */
+ parport_ieee1284_read_ecp, /* ecp_read_block */
 
- NULL, /* compat_write_block */
- NULL, /* nibble_read_block */
- NULL /* byte_read_block */
+ parport_ieee1284_write_compat, /* compat_write_block */
+ parport_ieee1284_read_nibble, /* nibble_read_block */
+ parport_ieee1284_read_byte, /* byte_read_block */
 };
 
 
diff -urN linux/drivers/misc/parport_ieee1284.c linux-arca/drivers/misc/parport_ieee1284.c
--- linux/drivers/misc/parport_ieee1284.c Tue Dec 15 16:38:47 1998
+++ linux-arca/drivers/misc/parport_ieee1284.c Tue Dec 15 16:31:46 1998
@@ -46,6 +46,7 @@
         struct timer_list timer;
         typedef void (*tm_func) (unsigned long);
 
+#if 0 /* this sucks every kind of irq handshake */
         /* 500usecs of fast polling.
          *
          * This should be adjustable.
@@ -62,6 +63,7 @@
                         break;
                 udelay(25);
         }
+#endif
 
         /* 40ms of slow polling. */
         init_timer (&timer);
@@ -282,11 +284,12 @@
         sema_init (&sem, 0);
         error = fn (port, buffer, len, callback, &info);
 
- if (!error)
- /* Wait for completion. */
- down_interruptible (&sem);
+ if (error)
+ return error;
 
- return error ? error : info.count;
+ /* Wait for completion. */
+ down_interruptible (&sem);
+ return info.count;
 }
 
 static inline
@@ -301,22 +304,30 @@
         sema_init (&sem, 0);
         error = fn (port, buffer, len, callback, &info);
 
- if (!error)
- /* Wait for completion. */
- down_interruptible (&sem);
+ if (error)
+ return error;
 
- return error ? error : info.count;
+ /* Wait for completion. */
+ down_interruptible (&sem);
+ return info.count;
 }
 
 /* Handle an interrupt. */
 void parport_ieee1284_interrupt (int which, void *handle, struct pt_regs *regs)
 {
         struct parport *port = handle;
+#ifdef DEBUG
+ struct semaphore *sem = &port->ieee1284.sem;
+#endif
         if (!(port->cad->flags & PARPORT_DEV_IEEE1284IRQ)) {
                 port->cad->flags |= PARPORT_DEV_IEEE1284IRQ;
                 DPRINTK (KERN_DEBUG "Woo hoo! Using interrupts!\n");
         }
 
+#ifdef DEBUG
+ if (!atomic_read(&sem->count))
+ DPRINTK (KERN_DEBUG "Woo hoo! Interrupt make sense!\n");
+#endif
         parport_ieee1284_wakeup (port);
 
         if (port->ieee1284.phase == IEEE1284_PH_REV_IDLE) {
diff -urN linux/drivers/misc/parport_ieee1284_ops.c linux-arca/drivers/misc/parport_ieee1284_ops.c
--- linux/drivers/misc/parport_ieee1284_ops.c Tue Dec 15 16:38:47 1998
+++ linux-arca/drivers/misc/parport_ieee1284_ops.c Tue Dec 15 16:20:34 1998
@@ -6,7 +6,7 @@
 #include <linux/parport.h>
 #include <linux/delay.h>
 
-#define DEBUG /* undef me for production */
+#undef DEBUG /* undef me for production */
 
 #ifdef DEBUG
 #define DPRINTK(stuff...) printk (stuff)
@@ -118,16 +118,11 @@
                 parport_write_data (port, *byte++);
                 udelay (1);
 
- /* Is the peripheral ready yet? */
- if (!parport_wait_peripheral (port, mask, val))
- /* Skip the loop */
- goto ready;
-
                 /* Wait until the peripheral's ready */
                 do {
- /* Is there a signal pending? */
- if (signal_pending (current))
- goto stop;
+ /* Is the peripheral ready now? */
+ if (!(parport_wait_peripheral (port, mask, val)))
+ goto ready;
 
                         /* Is the peripheral upset? */
                         if ((parport_read_status (port) &
@@ -138,25 +133,29 @@
                                 PARPORT_STATUS_ERROR))
                                 goto stop;
 
+#if 0
                         /* Yield the port for a while. */
                         if (count && polling (dev))
                                 parport_release (dev);
+#endif
                         timer.expires = jiffies + wait;
                         timer.data = (unsigned long) port;
                         timer.function = (tm_func) parport_ieee1284_wakeup;
                         add_timer (&timer);
                         down_interruptible (&port->ieee1284.sem);
                         del_timer (&timer);
+#if 0
                         if (count && polling (dev))
                                 parport_claim_or_block (dev);
+#endif
 
- /* Is the peripheral ready now? */
- if (!(parport_wait_peripheral (port, mask, val)))
- goto ready;
+ /* We unblocked due a signal? */
+ if (signal_pending (current))
+ goto stop;
 
                         /* Wait longer next time. */
- if (wait < (port->ieee1284.timeout / 2))
- wait *= 2;
+ if (wait < (port->ieee1284.timeout >> 1))
+ wait <<= 1;
                 } while (time_before (jiffies, expire));
 
                 DPRINTK (KERN_DEBUG "Timed out\n");
@@ -173,14 +172,15 @@
                 /* Assume it was received. */
                 count++;
 
- /* Let another driver have a go. */
- parport_yield_blocking (dev);
+ /* Let another driver or/and another process have a go. */
+ if (current->need_resched && !parport_yield_blocking (dev))
+ schedule ();
         }
  stop:
         port->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
 
         /* Call the callback function. */
- if (fn) fn (port, handle, count);
+ fn (port, handle, count);
 
         return signal_pending (current) ? -EINTR : 0;
 }
@@ -246,7 +246,7 @@
 
         port->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
 
- if (fn) fn (port, handle, written);
+ fn (port, handle, written);
         return 0;
 }
 
@@ -257,7 +257,7 @@
                                             void *, size_t),
                                 void *handle)
 {
- if (fn) fn (port, handle, 0);
+ fn (port, handle, 0);
         return -ENOSYS; /* FIXME */
 }
 
@@ -348,7 +348,7 @@
         }
 
         /* Call the callback. */
- if (fn) fn (port, handle, count);
+ fn (port, handle, count);
 
         return 0;
 }
@@ -426,7 +426,7 @@
         }
 
         /* Call the callback. */
- if (fn) fn (port, handle, count);
+ fn (port, handle, count);
 
         return 0;
 }
@@ -442,7 +442,7 @@
                 if (ecp_forward_to_reverse (port))
                         return -EIO;
 
- if (fn) fn (port, handle, 0);
+ fn (port, handle, 0);
         return -ENOSYS; /* FIXME */
 }
 
@@ -453,6 +453,6 @@
                                            void *, size_t),
                                void *handle)
 {
- if (fn) fn (port, handle, 0);
+ fn (port, handle, 0);
         return -ENOSYS; /* FIXME */
 }
--- linux/drivers/char/lp.c Tue Dec 15 16:38:47 1998
+++ linux-arca/drivers/char/lp.c Mon Dec 14 18:46:09 1998
@@ -27,6 +27,9 @@
  * Obsoleted the CAREFUL flag since a printer that doesn' t work with
  * CAREFUL will block a bit after in lp_check_status().
  * Andrea Arcangeli, 15 Oct 1998
+ * Obsoleted and removed all the lowlevel stuff implemented in the last
+ * month to use the IEEE1284 functions (that handle the _new_ compatibilty mode
+ * fine).
  */
 
 /* This driver should, in theory, work with any parallel port that has an
@@ -58,74 +61,6 @@
  * # insmod lp.o reset=1
  */
 
-/*
- * LP OPTIMIZATIONS
- *
- * - TRUST_IRQ flag
- *
- * Epson Stylus Color, HP and many other new printers want the TRUST_IRQ flag
- * set when printing with interrupts. This is a long story. Such printers
- * use a broken handshake (see the timing graph below) when printing with
- * interrupts. The lp driver as default is just able to handle such bogus
- * handshake, but setting such flag cause lp to go faster and probably do
- * what such printers want (even if not documented).
- *
- * NOTE that setting the TRUST_IRQ flag in some printer can cause the irq
- * printing to fail completly. You must try, to know if your printer
- * will handle it. I suggest a graphics printing to force a major flow of
- * characters to the printer for do the test. NOTE also that the TRUST_IRQ
- * flag _should_ be fine everywhere but there is a lot of buggy hardware out
- * there, so I am forced to implement it as a not-default thing.
- * WARNING: before to do the test, be sure to have not played with the
- * `-w' parameter of tunelp!
- *
- * Note also that lp automagically warn you (with a KERN_WARNING) if it
- * detects that you could _try_ to set the TRUST_IRQ flag to speed up the
- * printing and decrease the CPU load.
- *
- * To set the TRUST_IRQ flag you can use this command:
- *
- * tunelp /dev/lp? -T on
- *
- * If you have an old tunelp executable you can (hack and) use this simple
- * C lazy proggy to set the flag in the lp driver:
-
--------------------------- cut here -------------------------------------
-#include <fcntl.h>
-#include <sys/ioctl.h>
-
-#define LPTRUSTIRQ 0x060f
-
-int main(int argc, char **argv)
-{
- int fd = open("/dev/lp0", O_RDONLY);
- ioctl(fd, LPTRUSTIRQ, argc - 1);
- if (argc - 1)
- printf("trusting the irq\n");
- else
- printf("untrusting the irq\n");
- return 0;
-}
--------------------------- cut here -------------------------------------
-
- * - LP_WAIT time
- *
- * You can use this setting if your printer is fast enough and/or your
- * machine is slow enough ;-).
- *
- * tunelp /dev/lp? -w 0
- *
- * - LP_CHAR tries
- *
- * If you print with irqs probably you can decrease the CPU load a lot using
- * this setting. This is not the default because the printing is reported to
- * be jerky somewhere...
- *
- * tunelp /dev/lp? -c 1
- *
- * 11 Nov 1998, Andrea Arcangeli
- */
-
 /* COMPATIBILITY WITH OLD KERNELS
  *
  * Under Linux 2.0 and previous versions, lp devices were bound to ports at
@@ -162,6 +97,14 @@
  * this case fine too.
  *
  * 15 Oct 1998, Andrea Arcangeli
+ *
+ * The so called `buggy' handshake is really the well documented compatibility
+ * mode IEEE1284 handshake. They changed the well known Centronics handshake
+ * acking in the middle of busy expecting to not break drivers or legacy
+ * application, while they broken linux lp until I fixed it reverse engeneering
+ * the protocol by hand some month ago...
+ *
+ * 14 Dec 1998, Andrea Arcangeli
  */
 
 #include <linux/module.h>
@@ -194,7 +137,7 @@
 #ifdef LP_STATS
                            0, 0, {0},
 #endif
- NULL, 0, 0, 0}
+ NULL, 0,}
 };
 
 /* Test if printer is ready */
@@ -232,29 +175,6 @@
 #define w_ctr(x,y) do { parport_write_control(lp_table[(x)].dev->port, (y)); } while (0)
 #define w_dtr(x,y) do { parport_write_data(lp_table[(x)].dev->port, (y)); } while (0)
 
-static __inline__ void lp_yield (int minor)
-{
- if (!parport_yield_blocking (lp_table[minor].dev))
- {
- if (current->need_resched)
- schedule ();
- } else
- lp_table[minor].irq_missed = 1;
-}
-
-static __inline__ void lp_schedule(int minor, long timeout)
-{
- struct pardevice *dev = lp_table[minor].dev;
- register unsigned long int timeslip = (jiffies - dev->time);
- if ((timeslip > dev->timeslice) && (dev->port->waithead != NULL)) {
- lp_parport_release(minor);
- lp_table[minor].irq_missed = 1;
- schedule_timeout(timeout);
- lp_parport_claim(minor);
- } else
- schedule_timeout(timeout);
-}
-
 static int lp_reset(int minor)
 {
         int retval;
@@ -267,8 +187,6 @@
         return retval;
 }
 
-#define lp_wait(minor) udelay(LP_WAIT(minor))
-
 static void lp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
         struct lp_struct *lp_dev = (struct lp_struct *) dev_id;
@@ -277,11 +195,16 @@
 
 static void lp_error (int minor)
 {
+ int polling;
+
         if (LP_F(minor) & LP_ABORT)
                 return;
 
+ polling = !(lp_table[minor].dev->flags & PARPORT_DEV_IEEE1284IRQ);
+ if (polling) lp_parport_release(minor);
         current->state = TASK_INTERRUPTIBLE;
         schedule_timeout (LP_TIMEOUT_POLLED);
+ if (polling) lp_parport_claim(minor);
 }
 
 static int lp_check_status(int minor)
--- linux/include/linux/lp.h Sat Dec 5 11:16:38 1998
+++ linux-arca/include/linux/lp.h Mon Dec 14 18:45:38 1998
@@ -125,8 +125,6 @@
 #endif
         struct wait_queue *wait_q;
         unsigned int last_error;
- volatile unsigned int irq_detected:1;
- volatile unsigned int irq_missed:1;
 };
 
 /*
@@ -171,9 +169,6 @@
  * It is used only in the lp_init() and lp_reset() routine.
  */
 #define LP_DELAY 50
-
-#define LP_POLLED(minor) (lp_table[(minor)].dev->port->irq == PARPORT_IRQ_NONE)
-#define LP_PREEMPTED(minor) (lp_table[(minor)].dev->port->waithead != NULL)
 
 /*
  * function prototypes

This new code will be in arca-57 very soon too...

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:55 EST