⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 parportbook.tmpl

📁 嵌入式系统设计与实例开发实验教材二源码 多线程应用程序设计 串行端口程序设计 AD接口实验 CAN总线通信实验 GPS通信实验 Linux内核移植与编译实验 IC卡读写实验 SD驱动使
💻 TMPL
📖 第 1 页 / 共 5 页
字号:
   port sharing, and so should only be used when sharing the port with   other device drivers is impossible and would lead to incorrect   behaviour.  Use it sparingly!  </para>  <para>   Devices can also be registered by device drivers based on their   device numbers (the same device numbers as in the previous   section).  </para>  <para>   The <function>parport_open</function> function is similar to   <function>parport_register_device</function>, and   <function>parport_close</function> is the equivalent of   <function>parport_unregister_device</function>.  The difference is   that <function>parport_open</function> takes a device number rather   than a pointer to a <structname>struct parport</structname>.  </para>  <funcsynopsis>   <funcsynopsisinfo>#include &lt;parport.h&gt;   </funcsynopsisinfo>   <funcprototype>    <funcdef>struct pardevice *<function>parport_open</function></funcdef>    <paramdef>int <parameter>devnum</parameter></paramdef>    <paramdef>const char *<parameter>name</parameter></paramdef>    <paramdef>int <parameter>(*pf)</parameter>     <funcparams>void *</funcparams></paramdef>    <paramdef>int <parameter>(*kf)</parameter>     <funcparams>void *</funcparams></paramdef>    <paramdef>int <parameter>(*irqf)</parameter>     <funcparams>int, void *, struct pt_regs *</funcparams></paramdef>    <paramdef>int <parameter>flags</parameter></paramdef>    <paramdef>void *<parameter>handle</parameter></paramdef>   </funcprototype>  </funcsynopsis>  <funcsynopsis>   <funcprototype>    <funcdef>void <function>parport_close</function></funcdef>    <paramdef>struct pardevice *<parameter>dev</parameter></paramdef>   </funcprototype>  </funcsynopsis>  <funcsynopsis>   <funcprototype>    <funcdef>struct pardevice *<function>parport_register_device</function></funcdef>    <paramdef>struct parport *<parameter>port</parameter></paramdef>    <paramdef>const char *<parameter>name</parameter></paramdef>    <paramdef>int <parameter>(*pf)</parameter>     <funcparams>void *</funcparams></paramdef>    <paramdef>int <parameter>(*kf)</parameter>     <funcparams>void *</funcparams></paramdef>    <paramdef>int <parameter>(*irqf)</parameter>     <funcparams>int, void *, struct pt_regs *</funcparams></paramdef>    <paramdef>int <parameter>flags</parameter></paramdef>    <paramdef>void *<parameter>handle</parameter></paramdef>   </funcprototype>  </funcsynopsis>  <funcsynopsis>   <funcprototype>    <funcdef>void <function>parport_unregister_device</function></funcdef>    <paramdef>struct pardevice *<parameter>dev</parameter></paramdef>   </funcprototype>  </funcsynopsis>  <para>   The intended use of these functions is during driver initialisation   while the driver looks for devices that it supports, as   demonstrated by the following code fragment:  </para>  <programlisting>   <![CDATA[int devnum = -1;while ((devnum = parport_find_class (PARPORT_CLASS_DIGCAM,                                     devnum)) != -1) {    struct pardevice *dev = parport_open (devnum, ...);    ...}   ]]></programlisting>  <para>   Once your device driver has registered its device and been handed a   pointer to a <structname>struct pardevice</structname>, the next   thing you are likely to want to do is communicate with the device   you think is there.  To do that you'll need to claim access to the   port.  </para>  <funcsynopsis>   <funcsynopsisinfo>#include &lt;parport.h&gt;   </funcsynopsisinfo>   <funcprototype>    <funcdef>int <function>parport_claim</function></funcdef>    <paramdef>struct pardevice *<parameter>dev</parameter></paramdef>   </funcprototype>  </funcsynopsis>  <funcsynopsis>   <funcprototype>    <funcdef>int <function>parport_claim_or_block</function></funcdef>    <paramdef>struct pardevice *<parameter>dev</parameter></paramdef>   </funcprototype>  </funcsynopsis>  <funcsynopsis>   <funcprototype>    <funcdef>void <function>parport_release</function></funcdef>    <paramdef>struct pardevice *<parameter>dev</parameter></paramdef>   </funcprototype>  </funcsynopsis>  <para>   To claim access to the port, use <function>parport_claim</function>   or <function>parport_claim_or_block</function>.  The first of these   will not block, and so can be used from interrupt context.  If   <function>parport_claim</function> succeeds it will return zero and   the port is available to use.  It may fail (returning non-zero) if   the port is in use by another driver and that driver is not willing   to relinquish control of the port.  </para>  <para>   The other function, <function>parport_claim_or_block</function>,   will block if necessary to wait for the port to be free.  If it   slept, it returns <constant>1</constant>; if it succeeded without   needing to sleep it returns <constant>0</constant>.  If it fails it   will return a negative error code.  </para>  <para>   When you have finished communicating with the device, you can give   up access to the port so that other drivers can communicate with   their devices.  The <function>parport_release</function> function   cannot fail, but it should not be called without the port claimed.   Similarly, you should not try to claim the port if you already have   it claimed.  </para>  <para>   You may find that although there are convenient points for your   driver to relinquish the parallel port and allow other drivers to   talk to their devices, it would be preferable to keep hold of the   port.  The printer driver only needs the port when there is data to   print, for example, but a network driver (such as PLIP) could be   sent a remote packet at any time.  With PLIP, it is no huge   catastrophe if a network packet is dropped, since it will likely be   sent again, so it is possible for that kind of driver to share the   port with other (pass-through) devices.  </para>  <para>   The <function>parport_yield</function> and   <function>parport_yield_blocking</function> functions are for   marking points in the driver at which other drivers may claim the   port and use their devices.  Yielding the port is similar to   releasing it and reclaiming it, but is more efficient because   nothing is done if there are no other devices needing the port.  In   fact, nothing is done even if there are other devices waiting but   the current device is still within its <quote>timeslice</quote>.   The default timeslice is half a second, but it can be adjusted via   a <filename>/proc</filename> entry.  </para>  <funcsynopsis>   <funcsynopsisinfo>#include &lt;parport.h&gt;   </funcsynopsisinfo>   <funcprototype>    <funcdef>int <function>parport_yield</function></funcdef>    <paramdef>struct pardevice *<parameter>dev</parameter></paramdef>   </funcprototype>  </funcsynopsis>  <funcsynopsis>   <funcprototype>    <funcdef>int <function>parport_yield_blocking</function></funcdef>    <paramdef>struct pardevice *<parameter>dev</parameter></paramdef>   </funcprototype>  </funcsynopsis>  <para>   The first of these, <function>parport_yield</function>, will not   block but as a result may fail.  The return value for   <function>parport_yield</function> is the same as for   <function>parport_claim</function>.  The blocking version,   <function>parport_yield_blocking</function>, has the same return   code as <function>parport_claim_or_block</function>.  </para>  <para>   Once the port has been claimed, the device driver can use the   functions in the <structname>struct parport_operations</structname>   pointer in the <structname>struct parport</structname> it has a   pointer to.  For example:  </para>  <programlisting>   <![CDATA[port->ops->write_data (port, d);   ]]></programlisting>  <para>   Some of these operations have <quote>shortcuts</quote>.  For   instance, <function>parport_write_data</function> is equivalent to   the above, but may be a little bit faster (it's a macro that in   some cases can avoid needing to indirect through   <varname>port</varname> and <varname>ops</varname>).  </para> </chapter> <chapter id="portdrivers">  <title>Port drivers</title>  <!-- What port drivers are for (i.e. implementing parport objects). -->  <para>   To recap, then:</para>  <itemizedlist spacing=compact>   <listitem>    <para>     The device driver registers itself with <literal>parport</literal>.    </para>   </listitem>   <listitem>    <para>     A low-level driver finds a parallel port and registers it with     <literal>parport</literal> (these first two things can happen     in either order).  This registration creates a <structname>struct     parport</structname> which is linked onto a list of known ports.    </para>   </listitem>   <listitem>    <para>     <literal>parport</literal> calls the     <function>attach</function> function of each registered device     driver, passing it the pointer to the new <structname>struct     parport</structname>.    </para>   </listitem>   <listitem>    <para>     The device driver gets a handle from     <literal>parport</literal>, for use with     <function>parport_claim</function>/<function>release</function>.     This handle takes the form of a pointer to a <structname>struct     pardevice</structname>, representing a particular device on the     parallel port, and is acquired using     <function>parport_register_device</function>.    </para>   </listitem>   <listitem>    <para>     The device driver claims the port using     <function>parport_claim</function> (or     <function>function_claim_or_block</function>).    </para>   </listitem>   <listitem>    <para>     Then it goes ahead and uses the port.  When finished it releases     the port.    </para>   </listitem>  </itemizedlist>  <para>   The purpose of the low-level drivers, then, is to detect parallel   ports and provide methods of accessing them (i.e. implementing the   operations in <structname>struct   parport_operations</structname>).  </para>  <!-- Should DocBookise this -->  <para>   A more complete description of which operation is supposed to do   what is available in   <filename>Documentation/parport-lowlevel.txt</filename>.  </para> </chapter> <chapter id="lp">  <title>The printer driver</title>  <!-- Talk the reader through the printer driver. -->  <!-- Could even talk about parallel port console here. -->  <para>   The printer driver, <literal>lp</literal> is a character special   device driver and a <literal>parport</literal> client.  As a   character special device driver it registers a <structname>struct   file_operations</structname> using   <function>register_chrdev</function>, with pointers filled in for   <structfield>write</structfield>, <structfield>ioctl</structfield>,   <structfield>open</structfield> and   <structfield>release</structfield>.  As a client of   <literal>parport</literal>, it registers a <structname>struct   parport_driver</structname> using   <function>parport_register_driver</function>, so that   <literal>parport</literal> knows to call   <function>lp_attach</function> when a new parallel port is   discovered (and <function>lp_detach</function> when it goes   away).  </para>  <para>   The parallel port console functionality is also implemented in   <filename>drivers/char/lp.c</filename>, but that won't be covered   here (it's quite simple though).  </para>  <para>   The initialisation of the driver is quite easy to understand (see   <function>lp_init</function>).  The <varname>lp_table</varname> is   an array of structures that contain information about a specific   device (the <structname>struct pardevice</structname> associated   with it, for example).  That array is initialised to sensible   values first of all.  </para>  <para>   Next, the printer driver calls <function>register_chrdev</function>   passing it a pointer to <varname>lp_fops</varname>, which contains   function pointers for the printer driver's implementation of   <function>open</function>, <function>write</function>, and so on.   This part is the same as for any character special device   driver.  </para>  <para>   After successfully registering itself as a character special device   driver, the printer driver registers itself as a   <literal>parport</literal> client using   <function>parport_register_driver</function>.  It passes a pointer   to this structure:  </para>  <programlisting>   <![CDATA[static struct parport_driver lp_driver = {        "lp",        lp_attach,        lp_detach,        NULL};   ]]></programlisting>  <para>   The <function>lp_detach</function> function is not very interesting   (it does nothing); the interesting bit is   <function>lp_attach</function>.  What goes on here depends on   whether the user supplied any parameters.  The possibilities are:   no parameters supplied, in which case the printer driver uses every   port that is detected; the user supplied the parameter   <quote>auto</quote>, in which case only ports on which the device   ID string indicates a printer is present are used; or the user   supplied a list of parallel port numbers to try, in which case only   those are used.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -