[PARPORT] Help using PPDEV with EPP

From: David Hawkins (dwh@ovro.caltech.edu)
Date: Thu Aug 10 2000 - 14:15:03 EDT

  • Next message: Rod Moten @ Home: "[PARPORT] external HP Travan 14GB tape drive"

    This didn't appear on the archives sight, so I am
    sending it again.

    http://www.torque.net/parport/archive/current/

    My apologies to those who have already received this.

    I received one reply to the email, giving the location of an old
    draft of the 1284 standard, for those interested, check out:

    > 1) The IEEE 1284 spec itself. I found it at
    > ftp://ftp.lexmark.com/pub/ieee
    > There are several parts for different aspects.
    >

    I believe the document was in the 1284r subdirectory.

    It looks like 1284 devices have an internal device ID, and
    the negotiation phase requires some response from the device.
    This answers my PPNEGOT question below.

    Dave Hawkins.

    ----- Original Message -----
    From: "David Hawkins" <dwh@ovro.caltech.edu>
    To: <linux-parport@torque.net>; <twaugh@redhat.com>
    Sent: Monday, August 07, 2000 7:28 PM
    Subject: Help using PPDEV with EPP

    > Hi,
    >
    > I have designed several boards that I communicate with
    > via the EPP port on my computer. Each of the boards
    > implements a hardware EPP handshake using an FPGA.
    > In the past I have controlled these devices using
    > _outb / _inb instructions under Win95. I am now porting
    > most of my hardware control to Linux.
    >
    > I have an interface to my boards working using
    > /dev/port. I open the device, lseek to 0x378+3 for
    > EPP address reads/writes and 0x378+4 for EPP data
    > reads/writes. (I have a Tcl/Tk GUI built on top of the /dev/port calls
    > that displays the 5 ports spp/status/control/epp address/epp data,
    > along with appropriate read/write buttons - once I get this
    > new interface working, I'll give directions on where to get
    > it and the Tcl/Tk extension that encapsulates the PPDEV
    > functionality).
    >
    > I was planning on writing an EPP driver, however, looking
    > at the kernel sources it appeared that it had almost been
    > done in parport ... searching on the web showed up the
    > site (www.torque.net) and the user-space PPDEV driver
    > on Tim Waugh's site (people.redhat.com/twaugh/parport).
    >
    > I am running Red Hat 6.2 (2.2.14) and performed the
    > steps mentioned below. I am having some trouble getting
    > the user mode interface to work. I am hoping someone
    > (perhaps Tim) could guide me onto the correct path.
    > If there are limitations to the current PPDEV interface,
    > then I would like to offer myself as a 'test subject' to
    > help iron out issues.
    >
    > Here's what I have done ....
    >
    > 1. downloaded the patch from the link ftp.torque.net/pub/parport
    > located on Tim's page (mentioned above).
    >
    > 2. installed the patch in the source tree
    >
    > 3. ran 'make config' and setup the parallel ports as loadable
    > modules - same for ppdev. Note: I also ran make xconfig to
    > do this, however, although ppdev showed up in the selection
    > menu, attempts to alter the check-box gave an error (visible
    > back in the xterm it was executed from). I recompiled the
    > kernel, updated the slocate database and ran 'slocate ppdev'.
    > Although there were some new ppdev directories generated
    > during the make process, I didn't get a ppdev.o file
    > generated. Any comments on this?
    >
    > 4. I manually generated ppdev.o via
    > gcc -DMODULE -D__KERNEL__ -O2 -Wall -c ppdev.c
    >
    > 5. Since the parallel port stuff was compiled as loadable modules
    > I manually loaded them via in the following order: parport.o,
    > parport_pc.o, and ppdev.o
    > (as per the Documentation/parport.txt instructions)
    >
    > 6. I then ran variations on the code below and have the
    > following observations/suggestions:
    >
    > - the call to PPNEGOT fails. I didn't delve too far into the
    > source code for this call, but does this call require a response
    from
    > the 1284 device? If it does, what are the address/data cycles -
    > I can easily implement the appropriate response in my device.
    >
    > - the calls to write hang. If I use my /dev/port interface to manually
    > deassert the control lines prior to executing ppdev_tst, then the
    > data is written to the device (my board has a dual 7 segment display
    > that I have configured to show the last 4 bits of the last address
    > and data write), however the code still hangs.
    >
    > - both writes appear to go to the address port, (using PPSETMODE to
    > select the data port didn't seem to work).
    > I looked at the source code to see what the function calling
    > sequence looks like and get:
    >
    > User space read/write are implemented via pp_read / pp_write,
    > which are implemented via parport_read / parport_write
    > in which a switch statement selects from the four functions
    > ieee1284_epp_[read/write]_[addr/data].
    >
    > Those four functions are implemented using parport_frob_control,
    > poll_peripheral, parport_read_data, and parport_write_data.
    >
    > It is not clear to me why these functions are written this way when
    > parport.h contains the four functions:
    > parport_epp_[read/write]_[addr/data]
    >
    > which are #defines for parport_pc_[read/write]_epp (data) and
    > parport_pc_[read/write]_app_addr from parport_pc.h/c
    >
    > and these guys are implemented in terms of outb/inb (much the
    > same as the Win95 functions I have been using).
    >
    > parport_[read/write]_data are #defines for
    > parport_pc_[read/write]_data,
    > and these two functions are implemented as reads/writes to the
    > parallel port base address - i.e., SPP reads/writes.
    >
    > So why the added complexity in the implementations of the
    > ieee1284_epp_[read/write]_[addr/data] functions and why does it
    > look like the calls resolve to SPP reads/writes instead of EPP
    address
    > or data reads/writes?
    >
    > There is a note at the top of these functions mentioning they are
    > untested.
    > If someone can give me the rational behind their implementation,
    > I will happily provide 'testing' of these functions in my
    environment.
    >
    > In the ParPort docs, it is not clear what the difference between
    > read()
    > write() calls and ioctls with PPRDATA and PPWDATA. Looking at
    > the source code, I see that the ioctls resolve to parport_write_data
    > and parport_read_data, which as mentioned above resolve to SPP
    > read/writes in parport_pc.h. Would it be more appropriate for these
    > calls to mimic pp_read and pp_write?
    >
    > Thanks for the help!
    >
    > Dave Hawkins
    > Caltech's Owens Valley Radio Observatory
    > dwh@ovro.caltech.edu
    >
    >
    > /*--------------------------------------------------------------------
    > * Filename: ppdev_tst.c
    > * Author: D. W. Hawkins
    > * Date: 8-7-00
    > * Platform: Linux
    > * Used by: Nothing - standalone
    > *--------------------------------------------------------------------
    > * Summary
    > * -------
    > *
    > * This file tests the PPDEV user mode driver to see if it will
    > * meet my requirements of an EPP interface under Linux.
    > *
    > * Machine Setup:
    > * Winbook XL - 233MHz with Red Hat 6.2 (2.2.14 kernel)
    > * PPDEV patch from [Waugh] (ftp://ftp.torque.net/pub/parport)
    > *
    > *--------------------------------------------------------------------
    > * References/Resources
    > * --------------------
    > *
    > * [Waugh]
    > * Tim Waugh's parport website: people.redhat.com/twaugh/parport
    > *
    > * [ParportDoc]
    > * "The Linux 2.4 Parallel Port Subsystem", T. Waugh.
    > * (available via a link from [Waugh])
    > *
    > * [ParportTxt]
    > * Documentation/Parport.txt and Parport-lowlevel.txt
    > * (from the 2.4 kernel source, available via a link from
    > * www.linuxhq.com)
    > *
    > * [Torque]
    > * www.torque.net/parport - News archives and mailing list.
    > *
    > * [Source]
    > * ppdev.h and ppdev.c (provided by the patch)
    > *
    > *--------------------------------------------------------------------
    > */
    >
    > #include <sys/types.h> /* file open() */
    > #include <sys/stat.h>
    > #include <fcntl.h>
    > #include <sys/ioctl.h> /* ioctl() */
    > #include <unistd.h> /* read() / write() */
    > #include <stdio.h> /* printf() */
    >
    > #include <linux/parport.h> /* basic parport interface */
    > #include <linux/ppdev.h> /* user-mode driver */
    >
    >
    > int main()
    > {
    > int fd;
    > int mode, a_mode, d_mode;
    > unsigned char data;
    >
    > /* Following the notes on pp17 - 24 [ParportDoc]
    > */
    > printf("Opening the parallel port.\n");
    > if((fd = open("/dev/parport0",O_RDWR)) < 0) {
    > perror("/dev/parport0");
    > printf("Note: you must be superuser to run this program.\n");
    > exit(1);
    > }
    >
    > /* Try out some of the EPP IOCTL codes
    > *
    > * Claim the device
    > */
    > printf("Claiming the parallel port.\n");
    > if(ioctl(fd, PPCLAIM) < 0) {
    > perror("PPCLAIM");
    > close(fd);
    > exit(1);
    > }
    >
    > /* Negotiate for EPP mode
    > * (from ppdev.h, it looks like user-space read/write calls
    > * will apply to the EPP data register)
    > */
    > /* mode = IEEE1284_MODE_EPP;
    > printf("Negotiating for EPP mode.\n");
    > if(ioctl(fd, PPNEGOT, &mode) < 0) {
    > perror("PPNEGOT");
    > close(fd);
    > exit(1);
    > }
    > */
    > /* Deassert the control lines
    > */
    > printf("Deasserting the control lines.\n");
    > data = 0x04;
    > if(ioctl(fd, PPWCONTROL, &data) < 0) {
    > perror("PPWCONTROL");
    > close(fd);
    > exit(1);
    > }
    >
    > /* Set the read/write mode to the EPP address port
    > */
    > printf("Changing to EPP address mode.\n");
    > a_mode = IEEE1284_MODE_EPP | IEEE1284_ADDR;
    > if(ioctl(fd, PPSETMODE, &a_mode) < 0) {
    > perror("PPSETMODE");
    > close(fd);
    > exit(1);
    > }
    >
    > /* Write an address
    > */
    > printf("Writing an EPP address.\n");
    > data = 0xAB;
    > write(fd,&data,1);
    > /* ioctl(fd,PPWDATA,&data); */
    >
    > /* Set the read/write mode to the EPP data port
    > */
    > printf("Changing to EPP data mode.\n");
    > d_mode = IEEE1284_MODE_EPP | IEEE1284_DATA;
    > if(ioctl(fd, PPSETMODE, &d_mode) < 0) {
    > perror("PPSETMODE");
    > close(fd);
    > exit(1);
    > }
    >
    > /* Write data
    > */
    > printf("Writing EPP data.\n");
    > data = 0xCD;
    > write(fd,&data,1);
    > /* ioctl(fd,PPWDATA,&data); */
    >
    > /* All done!
    > */
    > printf("Releasing the parallel port.\n");
    > if(ioctl(fd, PPRELEASE) < 0) {
    > perror("PPRELEASE");
    > close(fd);
    > exit(1);
    > }
    > close(fd);
    >
    > return 0;
    > }
    >
    >
    >
    >

    -- 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 : Sat Aug 12 2000 - 05:07:43 EDT