931-935.html

来自「linux-unix130.linux.and.unix.ebooks130 l」· HTML 代码 · 共 179 行

HTML
179
字号
<HTML>

<HEAD>

<TITLE>Linux Unleashed, Third Edition:Writing Device Drivers</TITLE>

<SCRIPT>
<!--
function displayWindow(url, width, height) {
        var Win = window.open(url,"displayWindow",'width=' + width +
',height=' + height + ',resizable=1,scrollbars=yes');
}
//-->
</SCRIPT>
</HEAD>

 -->




<!--ISBN=0672313723//-->

<!--TITLE=Linux Unleashed, Third Edition//-->

<!--AUTHOR=Tim Parker//-->

<!--PUBLISHER=Macmillan Computer Publishing//-->

<!--IMPRINT=Sams//-->

<!--CHAPTER=58//-->

<!--PAGES=931-935//-->

<!--UNASSIGNED1//-->

<!--UNASSIGNED2//-->



<CENTER>

<TABLE BORDER>

<TR>

<TD><A HREF="929-931.html">Previous</A></TD>

<TD><A HREF="../ewtoc.html">Table of Contents</A></TD>

<TD><A HREF="935-938.html">Next</A></TD>

</TR>

</TABLE>

</CENTER>

<P><BR></P>

<P>An example of device register&#146;s initialization is shown in the device driver for a standard screen terminal (UART) device:

</P>

<!-- CODE //-->

<PRE>

/* define the registers */

#define RRDATA    0x01   /* receive */

#define RTDATA    0x02   /* transmit */

#define RSTATUS   0x03   /* status */

#define RCONTRL   0x04   /* control */

&#133;etc

/* define the status registers */

#define SRRDY    0x01   /* received data ready */

#define STRDY    0x02   /* transmitter ready */

#define SPERR    0x08   /* parity error */

#define SCTS     0x40   /* clear to send status */

&#133;etc

</PRE>

<!-- END CODE //-->

<P>The functions the device driver must perform are dependent on the nature of the device. All devices have an <TT>open()</TT> and <TT>close()</TT> routine that allows the device to perform I/O.</P>

<H4 ALIGN="LEFT"><A NAME="Heading6"></A><FONT COLOR="#000077">Opening the Device</FONT></H4>

<P>The <TT>open()</TT> routine must check to ensure a valid device is specified, validate the device request (permission to access the device or device not ready), then initialize the device. The <TT>open()</TT> routine is run every time a process uses the device.</P>

<P>The <TT>open()</TT> routine presented here is for a generic terminal device, <TT>td</TT>.</P>

<!-- CODE //-->

<PRE>

tdopen(device,flag)

int device,flag;

&#123;

          /* definitions for local variables ignored */

          /* details and definitions ignored in code */



          /* check device number */

          if (UNMODEM(device) &gt;= NTDEVS)

          &#123;

             seterror(ENXIO);

             return;

          &#125;



          /* check if device in use */

          /* if so, see if superuser (suser) for override */

          tp = &td_tty[UNMODEM(device)];

          address = td_address[UNMODEM(device)];

          if((tp-&gt;t_lflag & XCLUDE) && !suser())

          &#123;

             seterror(EBBUSY);

             return;

          &#125;



          /* if not open, initialize by calling ttinit() */

          if((tp-&gt;t_state & (ISOPEN|WOPEN)) == 0)

          &#123;

             ttinit(tp);

             /* initialize flags, and call tdparam() to set line */

             tdparam(device);

          &#125;



          /* if a modem is used, check carrier status */

          /* if direct, set carrier detect flags */

          /* set interrupt priority to avoid overwrite */

          /* wait for carrier detect signal */

          /* code eliminated from example */

</PRE>

<!-- END CODE //-->

<H4 ALIGN="LEFT"><A NAME="Heading7"></A><FONT COLOR="#000077">Closing the Device</FONT></H4>

<P>The <TT>close()</TT> routine is used only after the process is finished with the device. The routine disables interrupts from the device and issues any shut-down commands. All internal references to the device are reset. <TT>close()</TT> routines are not usually required in many device drivers because the device is treated as being available throughout. Exceptions are removable media and exclusive-use devices. Some modems require closing (<TT>close()</TT>) to allow the line to be hung up.</P>

<P>Again, the terminal device example is used for the <TT>close()</TT> routine sample:</P>

<!-- CODE //-->

<PRE>

          tdclose(device)

          &#123;

               register struct tty *tp;

               tp = &td_tty[UNMODEM(device)];

               (*linesw[tp-&gt;t_line].l_close)(tp);

               if(tp-&gt;t_cflag & HUPCL)

                    tdmodem(device,TURNOFF);

               /* turn off exclusive flag bit */

               ip-&gt;t_lflag & =~XCLUDE

          &#125;

</PRE>

<!-- END CODE //-->

<H4 ALIGN="LEFT"><A NAME="Heading8"></A><FONT COLOR="#000077">strategy Functions</FONT></H4>

<P><TT>strategy</TT> functions (block mode devices only) are issued with a parameter to the kernel buffer header. The buffer header contains the instructions for a read or write along with a memory location for the operation to occur to or from. The size of the buffer is usually fixed at installation and varies from 512 to 1024 bytes. It can be examined in the file <TT>param.h</TT> as the <TT>BSIZE</TT> variable. A device&#146;s block size may be smaller than the buffer block size, in which case the driver executes multiple reads or writes.</P>

<P>The <TT>strategy</TT> function can be illustrated in a sample device driver for a hard disk. No code is supplied, but the skeleton explains the functions of the device driver in order:</P>

<!-- CODE //-->

<PRE>

     int hdstrategy(bp)

     register struct buf *bp;

     &#123;

          /* initialize drive and partition numbers */

          /* set local variables */

          /* check for valid drive & partition */

          /* compute target cylinder */

          /* disable interrupts */

          /* push request into the queue */

          /* check controller: if not active, start it */

          /* reset interrupt level */

        &#125;

</PRE>

<!-- END CODE //-->

<H4 ALIGN="LEFT"><A NAME="Heading9"></A><FONT COLOR="#000077">write() Functions</FONT></H4>

<P>Character mode devices employ a <TT>write()</TT> instruction which checks the arguments of the instruction for validity and then copies the data from the process memory to the device driver buffer. When all data is copied, or the buffer is full, I/O is initiated to the device until the buffer is empty, at which point the process is repeated. Data is read from the process memory using a simple function (<TT>cpass</TT>) that returns a <TT>-1</TT> when end of memory is reached. The data is written to process memory using a complementary function (<TT>passc</TT>). The <TT>write()</TT> routine is illustrated for the terminal device:</P>

<!-- CODE SNIP //-->

<PRE>

tdwrite(device)

         &#123;

              register struct tty *tp;

              tp=&td_tty[UNMODEM(device)];

              (*linesw[tp-&gt;t_line].l_write)(tp);

         &#125;

</PRE>

<!-- END CODE SNIP //-->

<P>Large amounts of data are handled by a process called <TT>copyio</TT>, which takes the addresses of source and destination, a byte count, and a status flag as arguments.</P>

<H4 ALIGN="LEFT"><A NAME="Heading10"></A><FONT COLOR="#000077">read() Functions</FONT></H4>

<P>The <TT>read()</TT> operation for character mode devices transfers data from the device to the process memory. The operation is analogous to that of the <TT>write()</TT> procedure. For the terminal device, the <TT>read()</TT> code becomes:</P>

<!-- CODE SNIP //-->

<PRE>

          tdread(device)

          &#123;

                 register struct tty *tp;

                 tp=&td_tty[UNMODEM(device)];

                 (*linesw[tp-&gt;t_line].l_read)(tp);

          &#125;

</PRE>

<!-- END CODE SNIP //-->

<P>A small buffer is used when several characters are to be copied at once by <TT>read()</TT> or <TT>write()</TT>, rather than continually copying single characters. <TT>clist</TT> implements a small buffer used by character mode devices as a series of linked lists that use <TT>getc</TT> and <TT>putc</TT> to move characters on and off the buffer, respectively. A header for <TT>clist</TT> maintains a count of the contents.</P><P><BR></P>

<CENTER>

<TABLE BORDER>

<TR>

<TD><A HREF="929-931.html">Previous</A></TD>

<TD><A HREF="../ewtoc.html">Table of Contents</A></TD>

<TD><A HREF="935-938.html">Next</A></TD>

</TR>

</TABLE>

</CENTER>





</td>
</tr>
</table>

<!-- begin footer information -->





</body></html>

⌨️ 快捷键说明

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