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

From: Dave Strauss (
Date: Fri Sep 14 2001 - 18:12:48 EDT

  • Next message: ASA: "[PARPORT] External keyboard..."

    On Mon, 10 Sep 2001 22:37:32 +0100, Philip Blundell <> wrote:
    > >I think at least for now I think I'm just going to turn DMA off. I'm
    > >still open to trying other experiments, though, if anybody wants to
    > >suggest something.
    > I guess it would be instructive to know how the corruptions
    > correspond to invocations of parport_pc_fifo_write_block_dma. If
    > you feel like hacking that function around a bit, how about adding
    > a flag that gets set when the "DMA write timed out" condition
    > happens; if the flag is set on entry to the function, dump out the
    > first few bytes in `buf' to the console and clear the flag again.
    > I'm slightly suspicious that there might be a hardware flaw in
    > either your DMA controller or your parallel port. If you have
    > another computer with a different chipset available, it would be
    > interesting to know whether you can make the same thing happen.
    > p.

    For those of you just joining us, here's a recap:

    I've been trying to get ECP mode writes working on my machine running
    a 2.4.2 kernel. To do this, parport_pc must be built with
    CONFIG_PARPORT_PC_FIFO, some changes must be made to lp.o to tell
    parport to use ECP mode, and the irq option for parport_pc must be set
    to "auto" in /etc/modules.conf. If the dma option is set to "auto",
    DMA will be used for loading up the FIFO; otherwise if the dma option
    is set tup "none" PIO will be used for loading the FIFO.

    In the course of doing these changes and testing them out, I
    discovered problems when the FIFO/DMA combination is used to send data
    to a printer in compatibility mode if there is a long pause in the
    data stream; i.e. if the transfer to the printer looks like:

          swallow lots of bytes
          pause 30 seconds or so
          swallow lots more bytes

    In this case the printer receives garbage data. I spent a of time
    trying to pinpoint where the problem was, and could only conclude that
    it happened when the code timed out in parport_pc_fifo_write_block_dma().
    There didn't seem to be any problem, though, if I set things up to
    use PIO instead of DMA, so ultimately I decided to do that.

    Since then I've done some further testing and have discovered that, at
    least with the hardware I have, there are problems in ECP mode as well
    -- except that for ECP mode the problems exist whether I use DMA or
    whether I use PIO to send data to the FIFO. The problems appear to be
    related to the process used to recover from the timeouts -- putting
    the port into test mode and trying to determine how many bytes are
    left in the FIFO. I'm beginning to think, in fact, that the hardware
    is broken in such a way that whenever the FIFO is used, you'd better
    not mess with the port's mode until that byte has been received by
    the peripheral.

    So here's what I've got:

           Mode PIO/DMA status
           ----- -------- ------
           compat. PIO OK
           compat. DMA broken after timeout
           ECP PIO broken after timeout
           ECP DMA broken after timeout

    I've got a workaround (listed below) , but I don't really like it,
    because the effect is to change parport_pc_fifo_write_block_pio() and
    parport_pc_fifo_write_block_dma() from non-blocking to blocking calls.
    Suggestions for better solutions would be appreciated. For example,
    could/should we add an option for parport_pc to do non-blocking
    vs. blocking writes for dealing with such apparently broken hardware?
    I see this as analogous to the the DOS mode command for setting

    As an aside, I've changed from using a specialized test program in
    the printer to using a Postscript program which causes a pause
    in the download. See below.

    -- Dave Strauss

    Changes to parport_pc.c:

    RCS file: RCS/parport_pc.c,v
    retrieving revision 1.3
    diff -up -r1.3 parport_pc.c
    --- parport_pc.c 2001/09/13 21:34:52 1.3
    +++ parport_pc.c 2001/09/14 21:28:57
    @@ -531,7 +531,7 @@ static size_t parport_pc_fifo_write_bloc
                             if (!time_before (jiffies, expire)) {
                                     /* Timed out. */
                                     printk (KERN_DEBUG "FIFO write timed out\n");
    - break;
    + expire = jiffies + port->cad->timeout;
                             ecrval = inb (ECONTROL (port));
                             if (!(ecrval & (1<<2))) {
    @@ -652,7 +652,7 @@ static size_t parport_pc_fifo_write_bloc
                     if (!time_before (jiffies, expire)) {
                             /* Timed out. */
                             printk (KERN_DEBUG "DMA write timed out\n");
    - break;
    + expire = jiffies + port->cad->timeout;
                     /* Is serviceIntr set? */
                     if (!(inb (ECONTROL (port)) & (1<<2))) {

    Postscript test file, fill in the blanks:
    ----------------------- CUT HERE -------------------------
    1 2 add 3 add 4 add 5 add 6 add 7 add 8 add 9 add 10 add pop
    [ repeat for 7000 lines or so ]

    (waiting\n) print flush
    /start realtime def
    { realtime start sub 40000 gt { exit } if} loop
    (continuing\n) print flush

    1 2 add 3 add 4 add 5 add 6 add 7 add 8 add 9 add 10 add pop
    [ repeat for another 7000 lines or so ]
    ----------------------- CUT HERE -------------------------

    To see problems with the download, you will have to download an error
    handler that will print out errors when they happen. Some Postscript
    printers have a front panel setting to do this.

    -- To unsubscribe, send mail to: --
    -- with the single word "unsubscribe" in the body of the message. --

    This archive was generated by hypermail 2b29 : Sat Sep 15 2001 - 04:14:50 EDT