Re: [PARPORT] ECP mode transfers in 2.4.x kernels

From: Dave Strauss (D.Strauss@motorola.com)
Date: Thu Aug 16 2001 - 12:52:16 EDT

  • Next message: Tim Waugh: "Re: [PARPORT] ECP mode transfers in 2.4.x kernels"

    On Wed, 15 Aug 2001 22:59:37 +0100, Philip Blundell <philb@gnu.org> wrote:
    >
    >
    > >What do I have to do to get a Linux box to do ECP mode transfers?
    >
    > I had a play with this a few months ago with inconclusive results. I think
    > this was the patch, if you want to try it. It would certainly be interesting
    > to hear what happens for you.
    >
    > p.
    >
    > [ ... ]
    >

    Philip,

    Thanks for the patch!

    So I guess it wasn't such a stupid question after all. Also I guess
    there's no easy answer (at least for the unsophisticated user).

    Regarding the patch, I've applied it and there is good news and bad
    news. The good news is that data transfers do indeed happen in ECP
    mode now. The bad news is that are a few problems. I've addressed at
    least one of them but there are still others -- see my patch (which
    includes yours) below (sorry but I don't know the version number of
    the file I started with, and I don't have CVS access from where I'm
    sitting now).

    First problem: once the port is in ECP mode, any call to
    lp_wait_ready() will fail because the call to lp_check_status() will
    be wrong because the status lines mean different things in ECP mode.
    I've gotten around it by getting out of lp_wait_ready() immediately
    if the device is not in compatibility mode, but I'm not convinced this
    is the correct thing to do. Perhaps lp_check_status() should be
    changed instead.

    Second problem: the original patch leaves the parallel port in ECP
    mode permanently. My experience with working on printers of various
    sorts is that this is in general a Bad Thing; the 1284 protocol is
    easily broken if either side gets out of sync with the other, and the
    longer the port is left in ECP mode the easier it is for this to
    happen. Also, if other drivers want to use the port in other modes
    (or in other ways) this could cause problems. I've gotten around this
    in the patch below by always reverting to compatibility mode when the
    write is completed, but again I'm not sure this is the correct thing.
    Ideally we would like to leave the port in ECP mode if more data is
    going to be sent, but of course we can't tell from the lp driver if
    this is going to happen. Also there's the issue of error recovery.
    One possibility I'm thinking of trying would be to force the port to
    compatibility mode at the beginning, then into ECP mode (if the port
    can handle it), then back to compatibility mode when the write is
    completed; this doesn't address the meta-data issue but that probably
    can't be helped.

    Third problem: the data transfer rate is still very slow. I'm
    expecting upwards or 400 Kbytes/sec but and getting only about 50
    Kbytes/sec. I'm not why this is so.

    Fourth problem: I'm getting garbage in the data stream. At this point
    I haven't been able to characterize it very well beyong the fact that
    the data reaching the printer is incorrect. I'm not sure if I'm
    getting extra characters, dropped characters, garbled characters, or
    all three.

    -- Dave Strauss

    ===================================================================
    diff -u -p lp.c.orig lp.c.new
    --- lp.c.orig Thu Aug 16 12:06:15 2001
    +++ lp.c.new Thu Aug 16 12:01:29 2001
    @@ -224,7 +224,15 @@ static int lp_check_status(int minor)
     
     static int lp_wait_ready(int minor)
     {
    +
    +
             int error = 0;
    +
    + /* If we're not in compatibility mode, we're ready now! */
    + if (lp_table[minor].mode != IEEE1284_MODE_COMPAT) {
    + return (0);
    + }
    +
             do {
                     error = lp_check_status (minor);
                     if (error && (LP_F(minor) & LP_ABORT))
    @@ -246,6 +254,7 @@ static ssize_t lp_write(struct file * fi
             ssize_t retv = 0;
             ssize_t written;
             size_t copy_size = count;
    + int ret;
     
     #ifdef LP_STATS
             if (jiffies-lp_table[minor].lastcall > LP_TIME(minor))
    @@ -269,7 +278,11 @@ static ssize_t lp_write(struct file * fi
              parport_claim_or_block (lp_table[minor].dev);
     
             /* Go to compatibility mode. */
    - parport_negotiate (port, IEEE1284_MODE_COMPAT);
    + if ((ret = parport_negotiate (port, lp_table[minor].mode)) != 0) {
    + printk(KERN_DEBUG "lp%d: selecting compatibility mode (%d).\n",
    + minor, ret);
    + lp_table[minor].mode = IEEE1284_MODE_COMPAT;
    + }
     
             parport_set_timeout (lp_table[minor].dev,
                                  lp_table[minor].timeout);
    @@ -319,6 +332,9 @@ static ssize_t lp_write(struct file * fi
                     }
             } while (count > 0);
     
    + /* Always return to compatibility mode when we're done. */
    + parport_negotiate (port, IEEE1284_MODE_COMPAT);
    +
              parport_release (lp_table[minor].dev);
     
             up (&lp_table[minor].port_mutex);
    @@ -662,6 +678,12 @@ static int lp_register(int nr, struct pa
             if (lp_table[nr].dev == NULL)
                     return 1;
             lp_table[nr].flags |= LP_EXIST;
    +
    + if (port->probe_info[0].class != PARPORT_CLASS_LEGACY
    + && (port->modes & PARPORT_MODE_ECP))
    + lp_table[nr].mode = IEEE1284_MODE_ECP;
    + else
    + lp_table[nr].mode = IEEE1284_MODE_COMPAT;
     
             if (reset)
                     lp_reset(nr);

    -- 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 : Thu Aug 16 2001 - 12:56:51 EDT