Path: utzoo!utgpu!jarvis.csri.toronto.edu!cs.utexas.edu!tut.cis.ohio-state.edu!pt.cs.cmu.edu!fas.ri.cmu.edu!dstewart From: dstewart@fas.ri.cmu.edu (David B Stewart) Newsgroups: comp.unix.wizards Subject: Parallel Port Drivers Message-ID: <7905@pt.cs.cmu.edu> Date: 9 Feb 90 05:42:01 GMT Organization: Carnegie-Mellon University, CS/RI Lines: 104 Here is a question about Parallel Ports: Suppose I have (well, don't suppose, I do have it) a Parallel I/O (pio) device which offers 64 bits of data, which can be subdivided into 8 groups of 8 bits each. Each group can be defined as either input XOR output. Also available are 8 input lines and 8 output lines for handshaking (They have the ability to create interrupts and to be masked). There is no hardware limitation specifying 1 input and one output handshake line per group of 8 bits; they can be used completely independently of the 64 data bits. My question, what is the best way to define read() and write() drivers for this port? An overview of various options I have considered follow: Should I treat each 8 bit port as a separate device, and thus have /dev/pio0 to /dev/pio7? Group then into 16 bit ports to have /dev/pio0 to /dev/pio3? Keep all 64 bits as a single /dev/pio0? Arbitrary; e.g. one 32bit device, one 16bit device, and two 8bit devices? How should the handshaking lines be used? Some handshaking modes require only one input and one output line, but other modes require two input and/or two output lines. If I group 16 or mode bits into a single device, what do I do to read/write modes? Allow all 16 bits to be input XOR output? Maybe it is better 8 bits input AND 8 bits output? These configurations obviously depend on the hardware to be connected to the parallel ports (most hardware is anywhere from 8 bits to 32 bits), Suppose I wish to use the 64 bits as follows, and I want all devices to be able to perform only open(), read(), write(), close() and ioctl() operations on the device. What can I do? Device A: 16 bits input, 2 output handshake lines, 1 input handshake. Device B: 8 bits input, 0 output handshake, 1 input handshake. Device C: 16 bits input, 8 bits output, 2 output hdsk, 2 input hdsk Device D: 8 bits output, no handshaking. 8 bits unused. The above description is not arbitrary. It represents various devices within our robot system. However, I must also have the ability to define the ports in a different way (i.e. remove some devices listed above, and put in different ones) without having to rebuild the kernel. The best solution I can think of is the following, but there are still problems with it: - Group ports into 4 devices of 16 bits each. - Each device has the ability to be opened as O_RDONLY, in which case all 16 bits are input; O_WRONLY in which case all bits are output; or O_RDWR, in which case 8 bits are input, and the other 8 output. - Use an ioctl() to select one of several predefined handshaking modes. - If more than 16 bits required, than 2 devices must be opened. The problems I still have with the above: - Suppose we need 32 bits input, and we open /dev/pio0 and /dev/pio1; and we want to write 10 32-bit numbers to the port (assuming the device driver takes care of appropriate handshaking.) Ideally, we would say: write(fd,intbuffer, 10*sizeof(int)). But that does not work, since we now have 2 fds, and the following: write(fd1,intbuffer,10*sizeof(short)) write(fd2,intbuffer,10*sizeof(short)) will not work, since the handshaking mode requires all 32 bits at once. It is possible to use an ioctl() to say 'link fd1 with fd2' in which case doing a write to fd1 will work as though it is a 32-bit port; but that would require lots of special exceptions within the device driver. - Given a device which has 8 input ports and 8 output ports and the following handshake mode: - Write 8 bits of data to output port - Raise Data Ready (one of the output handshake lines) - Wait for Data Ack (one of the input handshake lines) - Read 8 bits of data from input port Assume the speed is in the range of 100-500 Hz; it is not feasable to do: loop n times { write(fd,outbuf,1) read(fd,inbuf,1) } What should be done is: writeread(fd,outbuf,inbuf,n); What can I do if I don't have the ability to create my own writeread() system call? What if I do have the ability, is this the best way? I would appreciate any experiences you may have had with writing drivers for parallel ports, any any suggestions and/or ideas you may have regarding some of the problems outlined above. Thanks ~dave -- David B. Stewart, Dept. of Elec. & Comp. Engr., and The Robotics Institute, Carnegie Mellon University, email: stewart@faraday.ece.cmu.edu The following software is now available; ask me for details CHIMERA II, A Real-time OS for Sensor-Based Control Applications