📄 parportbook.tmpl
字号:
<!-- -*- sgml -*- --><!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V4.1//EN"[]><book id="ParportGuide"> <bookinfo> <title>The Linux 2.4 Parallel Port Subsystem</title> <authorgroup> <author> <firstname>Tim</firstname> <surname>Waugh</surname> <affiliation> <address> <email>twaugh@redhat.com</email> </address> </affiliation> </author> </authorgroup> <copyright> <year>1999-2000</year> <holder>Tim Waugh</holder> </copyright> <legalnotice> <para> Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License". </para> </legalnotice> </bookinfo> <toc></toc> <chapter id="design"> <title>Design goals</title> <sect1> <title>The problems</title> <para> The first parallel port support for Linux came with the line printer driver, <literal>lp</literal>. The printer driver is a character special device, and (in Linux 2.0) had support for writing, via <function>write</function>, and configuration and statistics reporting via <function>ioctl</function>. </para> <para> The printer driver could be used on any computer that had an IBM PC-compatible parallel port. Because some architectures have parallel ports that aren't really the same as PC-style ports, other variants of the printer driver were written in order to support Amiga and Atari parallel ports. </para> <para> When the Iomega Zip drive was released, and a driver written for it, a problem became apparent. The Zip drive is a parallel port device that provides a parallel port of its own---it is designed to sit between a computer and an attached printer, with the printer plugged into the Zip drive, and the Zip drive plugged into the computer. </para> <para> The problem was that, although printers and Zip drives were both supported, for any given port only one could be used at a time. Only one of the two drivers could be present in the kernel at once. This was because of the fact that both drivers wanted to drive the same hardware---the parallel port. When the printer driver initialised, it would call the <function>check_region</function> function to make sure that the IO region associated with the parallel port was free, and then it would call <function>request_region</function> to allocate it. The Zip drive used the same mechanism. Whichever driver initialised first would gain exclusive control of the parallel port. </para> <para> The only way around this problem at the time was to make sure that both drivers were available as loadable kernel modules. To use the printer, load the printer driver module; then for the Zip drive, unload the printer driver module and load the Zip driver module. </para> <para> The net effect was that printing a document that was stored on a Zip drive was a bit of an ordeal, at least if the Zip drive and printer shared a parallel port. A better solution was needed. </para> <para> Zip drives are not the only devices that presented problems for Linux. There are other devices with pass-through ports, for example parallel port CD-ROM drives. There are also printers that report their status textually rather than using simple error pins: sending a command to the printer can cause it to report the number of pages that it has ever printed, or how much free memory it has, or whether it is running out of toner, and so on. The printer driver didn't originally offer any facility for reading back this information (although Carsten Gross added nibble mode readback support for kernel 2.2). </para> <para> The IEEE has issued a standards document called IEEE 1284, which documents existing practice for parallel port communications in a variety of modes. Those modes are: <quote>compatibility</quote>, reverse nibble, reverse byte, ECP and EPP. Newer devices often use the more advanced modes of transfer (ECP and EPP). In Linux 2.0, the printer driver only supported <quote>compatibility mode</quote> (i.e. normal printer protocol) and reverse nibble mode. </para> </sect1> <sect1> <title>The solutions</title><!-- How they are addressed - sharing model - overview of structure (i.e. port drivers) in 2.2 and 2.3. - IEEE 1284 stuff - whether or not 'platform independence' goal was met --> <para> The <literal>parport</literal> code in Linux 2.2 was designed to meet these problems of architectural differences in parallel ports, of port-sharing between devices with pass-through ports, and of lack of support for IEEE 1284 transfer modes. </para> <!-- platform differences --> <para> There are two layers to the <literal>parport</literal> subsystem, only one of which deals directly with the hardware. The other layer deals with sharing and IEEE 1284 transfer modes. In this way, parallel support for a particular architecture comes in the form of a module which registers itself with the generic sharing layer. </para> <!-- sharing model --> <para> The sharing model provided by the <literal>parport</literal> subsystem is one of exclusive access. A device driver, such as the printer driver, must ask the <literal>parport</literal> layer for access to the port, and can only use the port once access has been granted. When it has finished a <quote>transaction</quote>, it can tell the <literal>parport</literal> layer that it may release the port for other device drivers to use. </para> <!-- talk a bit about how drivers can share devices on the same port --> <para> Devices with pass-through ports all manage to share a parallel port with other devices in generally the same way. The device has a latch for each of the pins on its pass-through port. The normal state of affairs is pass-through mode, with the device copying the signal lines between its host port and its pass-through port. When the device sees a special signal from the host port, it latches the pass-through port so that devices further downstream don't get confused by the pass-through device's conversation with the host parallel port: the device connected to the pass-through port (and any devices connected in turn to it) are effectively cut off from the computer. When the pass-through device has completed its transaction with the computer, it enables the pass-through port again. </para> <mediaobject> <imageobject> <imagedata fileref="parport-share" format="eps"> </imageobject> <imageobject> <imagedata fileref="parport-share.png" format="png"> </imageobject> </mediaobject> <para> This technique relies on certain <quote>special signals</quote> being invisible to devices that aren't watching for them. This tends to mean only changing the data signals and leaving the control signals alone. IEEE 1284.3 documents a standard protocol for daisy-chaining devices together with parallel ports. </para> <!-- transfer modes --> <para> Support for standard transfer modes are provided as operations that can be performed on a port, along with operations for setting the data lines, or the control lines, or reading the status lines. These operations appear to the device driver as function pointers; more later. </para> </sect1> </chapter> <chapter id="transfermodes"> <title>Standard transfer modes</title> <!-- Defined by IEEE, but in common use (even though there are widely --> <!-- varying implementations). --> <para> The <quote>standard</quote> transfer modes in use over the parallel port are <quote>defined</quote> by a document called IEEE 1284. It really just codifies existing practice and documents protocols (and variations on protocols) that have been in common use for quite some time. </para> <para> The original definitions of which pin did what were set out by Centronics Data Computer Corporation, but only the printer-side interface signals were specified. </para> <para> By the early 1980s, IBM's host-side implementation had become the most widely used. New printers emerged that claimed Centronics compatibility, but although compatible with Centronics they differed from one another in a number of ways. </para> <para> As a result of this, when IEEE 1284 was published in 1994, all that it could really do was document the various protocols that are used for printers (there are about six variations on a theme). </para> <para> In addition to the protocol used to talk to Centronics-compatible printers, IEEE 1284 defined other protocols that are used for unidirectional peripheral-to-host transfers (reverse nibble and reverse byte) and for fast bidirectional transfers (ECP and EPP). </para> </chapter> <chapter id="structure"> <title>Structure</title><!-- Main structure - sharing core - parports and their IEEE 1284 overrides - IEEE 1284 transfer modes for generic ports - maybe mention muxes here - pardevices - IEEE 1284.3 API --> <mediaobject> <imageobject> <imagedata fileref="parport-structure" format="eps"> </imageobject> <imageobject> <imagedata fileref="parport-structure.png" format="png"> </imageobject> </mediaobject> <sect1> <title>Sharing core</title> <para> At the core of the <literal>parport</literal> subsystem is the sharing mechanism (see <filename>drivers/parport/share.c</filename>). This module, <literal>parport</literal>, is responsible for keeping track of which ports there are in the system, which device drivers might be interested in new ports, and whether or not each port is available for use (or if not, which driver is currently using it). </para> </sect1> <sect1> <title>Parports and their overrides</title> <para> The generic <literal>parport</literal> sharing code doesn't directly handle the parallel port hardware. That is done instead by <quote>low-level</quote> <literal>parport</literal> drivers. The function of a low-level <literal>parport</literal> driver is to detect parallel ports, register them with the sharing code, and provide a list of access functions for each port. </para> <para> The most basic access functions that must be provided are ones for examining the status lines, for setting the control lines, and for setting the data lines. There are also access functions for setting the direction of the data lines; normally they are in the <quote>forward</quote> direction (that is, the computer drives them), but some ports allow switching to <quote>reverse</quote> mode (driven by the peripheral). There is an access function for examining the data lines once in reverse mode. </para> </sect1> <sect1> <title>IEEE 1284 transfer modes</title> <para> Stacked on top of the sharing mechanism, but still in the <literal>parport</literal> module, are functions for transferring data. They are provided for the device drivers to use, and are very much like library routines. Since these transfer functions are provided by the generic <literal>parport</literal> core they must use the <quote>lowest common denominator</quote> set of access functions: they can set the control lines, examine the status lines, and use the data lines. With some parallel ports the data lines can only be set and not examined, and with other ports accessing the data register causes control line activity; with these types of situations, the IEEE 1284 transfer functions make a best effort attempt to do the right thing. In some cases, it is not physically possible to use particular IEEE 1284 transfer modes. </para> <para> The low-level <literal>parport</literal> drivers also provide IEEE 1284 transfer functions, as names in the access function list. The low-level driver can just name the generic IEEE 1284 transfer functions for this. Some parallel ports can do IEEE 1284 transfers in hardware; for those ports, the low-level driver can provide functions to utilise that feature. </para> </sect1> <!-- muxes? --> <sect1> <title>Pardevices and parport_drivers</title> <para> When a parallel port device driver (such as <literal>lp</literal>) initialises it tells the sharing layer about itself using <function>parport_register_driver</function>. The information is put into a <structname>struct parport_driver</structname>, which is put into a linked list. The information in a <structname>struct parport_driver</structname> really just amounts to some function pointers to callbacks in the parallel port device driver. </para> <para> During its initialisation, a low-level port driver tells the sharing layer about all the ports that it has found (using <function>parport_register_port</function>), and the sharing layer creates a <structname>struct parport</structname> for each of them. Each <structname>struct parport</structname> contains (among other things) a pointer to a <structname>struct
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -