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