On Fri, 10 Mar 2000, Richard Stover wrote:
> Since I've been working on a device driver to handle a high speed
> camera that will produce data at very high rates I've been looking at
> issues like this. If you have a peripheral that does follow the ECP
> standards you shouldn't have to loose any data. The way to stop data
> is to negotiate from reverse to forward phase (from input to output).
> When the host sets nReverseRequest (also called nInit high, the
> pheripheral must tri-state its data bus. If the peripheral was in the
> middle of a data transmission it must assume the data byte will be
> discarded by the host and it stops all furthter transfers. You can
> then read whatever is left in the fifo. nReverseRequest is bit 2 of
> the device control register.
Here's a patch to test out (I can't test it myself). Let me know if it's
okay. It applies to 2.3.52pre3.
Tim.
*/
Index: drivers/parport/parport_pc.c
===================================================================
RCS file: /usr/local/src/cvsroot/linux/drivers/parport/parport_pc.c,v
retrieving revision 1.40
diff -d -u -r1.40 parport_pc.c
--- drivers/parport/parport_pc.c 2000/03/14 13:55:01 1.40
+++ drivers/parport/parport_pc.c 2000/03/14 16:45:56
@@ -178,9 +178,6 @@
int cnfga;
const struct parport_pc_private *priv = p->physport->private_data;
- /* Prevent further data transfer. */
- frob_econtrol (p, 0xe0, ECR_TST << 5);
-
/* Adjust for the contents of the FIFO. */
for (residue = priv->fifo_depth; ; residue--) {
if (inb (ECONTROL (p)) & 0x2)
@@ -862,7 +859,8 @@
length, flags);
/* Switch to reverse mode if necessary. */
- if (port->ieee1284.phase != IEEE1284_PH_REV_IDLE) {
+ if ((port->ieee1284.phase != IEEE1284_PH_REV_IDLE) &&
+ (port->ieee1284.phase != IEEE1284_PH_REV_DATA)) {
/* Event 38: Set nAutoFd low */
parport_frob_control (port,
PARPORT_CONTROL_AUTOFD,
@@ -879,7 +877,7 @@
parport_wait_peripheral (port, PARPORT_STATUS_PAPEROUT, 0);
}
- /* Set up ECP parallel port mode.*/
+ /* Set up ECP FIFO mode.*/
parport_pc_data_reverse (port); /* Must be in PS2 mode */
parport_pc_frob_control (port,
PARPORT_CONTROL_STROBE |
@@ -951,14 +949,23 @@
left--;
}
+ port->ieee1284.phase = IEEE1284_PH_REV_IDLE;
+
+ /* Go to forward idle mode to shut the peripheral up. */
+ parport_frob_control (port, PARPORT_CONTROL_INIT, 0);
+ parport_wait_peripheral (port,
+ PARPORT_STATUS_PAPEROUT,
+ PARPORT_STATUS_PAPEROUT);
+ port->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
+
/* Finish up. */
- if (change_mode (port, ECR_PS2) == -EBUSY) {
+ {
int lost = get_fifo_residue (port);
- printk (KERN_DEBUG "%s: DATA LOSS (%d bytes)!\n", port->name,
- lost);
+ if (lost)
+ /* Shouldn't happen with compliant peripherals. */
+ printk (KERN_DEBUG "%s: DATA LOSS (%d bytes)!\n",
+ port->name, lost);
}
-
- port->ieee1284.phase = IEEE1284_PH_REV_IDLE;
return length - left;
}
-- 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 2b29 : Tue Mar 14 2000 - 11:55:04 EST