<?Pub UDT _bookmark _target?><?Pub EntList amp nbsp gt lt ndash hyphen?><?Pub CX solbook(book(title()bookinfo()part()part(title()partintro()?><chapter id="character-21002"><title>Drivers for Character Devices</title><highlights><para>A <emphasis>character device</emphasis> does not have physically addressable
storage media, such as tape drives or serial ports, where I/O is normally
performed in a byte stream. This chapter describes the structure of a character
device driver, focusing in particular on entry points for character drivers.
In addition, this chapter describes the use of <olink targetdoc="group-refman" targetptr="physio-9f" remap="external"><citerefentry><refentrytitle>physio</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink>  and <olink targetdoc="group-refman" targetptr="aphysio-9f" remap="external"><citerefentry><refentrytitle>aphysio</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> in the context
of synchronous and asynchronous I/O transfers.</para><para>This chapter provides information on the following subjects:</para><itemizedlist><listitem><para><olink targetptr="character-1" remap="internal">Overview of the Character Driver
Structure</olink></para>
</listitem><listitem><para><olink targetptr="character-51" remap="internal">Character Device Autoconfiguration</olink></para>
</listitem><listitem><para><olink targetptr="character-6" remap="internal">Device Access (Character Drivers)</olink></para>
</listitem><listitem><para><olink targetptr="character-25379" remap="internal">I/O Request Handling</olink></para>
</listitem><listitem><para><olink targetptr="character-16543" remap="internal">Mapping Device Memory</olink></para>
</listitem><listitem><para><olink targetptr="character-11313" remap="internal">Multiplexing I/O on File
Descriptors</olink></para>
</listitem><listitem><para><olink targetptr="character-23939" remap="internal">Miscellaneous I/O Control</olink></para>
</listitem><listitem><para><olink targetptr="character-17" remap="internal">32-bit and 64-bit Data Structure
Macros</olink></para>
</listitem>
</itemizedlist>
</highlights><sect1 id="character-1"><title>Overview of the Character Driver Structure</title><para><olink targetptr="character-fig-3" remap="internal">Figure&nbsp;15&ndash;1</olink> shows
data structures and routines that define the structure of a character device
driver. Device drivers typically include the following elements:</para><itemizedlist><listitem><para>Device-loadable driver section</para>
</listitem><listitem><para>Device configuration section</para>
</listitem><listitem><para>Character driver entry points</para>
</listitem>
</itemizedlist><para>The shaded device access section in the following figure illustrates
character driver entry points.</para><figure id="character-fig-3"><title id="character-39247">Character Driver
Roadmap</title><mediaobject><imageobject><imagedata entityref="character.view.epsi"/>
</imageobject><textobject><simpara>Diagram shows structures and entry points for character
device drivers.</simpara>
</textobject>
</mediaobject>
</figure><para>Associated with each device driver is a <olink targetdoc="group-refman" targetptr="dev-ops-9s" remap="external"><citerefentry><refentrytitle>dev_ops</refentrytitle><manvolnum>9S</manvolnum></citerefentry></olink> structure, which in turn
refers to a <olink targetdoc="group-refman" targetptr="cb-ops-9s" remap="external"><citerefentry><refentrytitle>cb_ops</refentrytitle><manvolnum>9S</manvolnum></citerefentry></olink> structure.
These structures contain pointers to the driver entry points:</para><itemizedlist><listitem><para><olink targetdoc="group-refman" targetptr="open-9e" remap="external"><citerefentry><refentrytitle>open</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink></para>
</listitem><listitem><para><olink targetdoc="group-refman" targetptr="close-9e" remap="external"><citerefentry><refentrytitle>close</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink></para>
</listitem><listitem><para><olink targetdoc="group-refman" targetptr="read-9e" remap="external"><citerefentry><refentrytitle>read</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink></para>
</listitem><listitem><para><olink targetdoc="group-refman" targetptr="write-9e" remap="external"><citerefentry><refentrytitle>write</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink></para>
</listitem><listitem><para><olink targetdoc="group-refman" targetptr="ioctl-9e" remap="external"><citerefentry><refentrytitle>ioctl</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink></para>
</listitem><listitem><para><olink targetdoc="group-refman" targetptr="chpoll-9e" remap="external"><citerefentry><refentrytitle>chpoll</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink></para>
</listitem><listitem><para><olink targetdoc="group-refman" targetptr="aread-9e" remap="external"><citerefentry><refentrytitle>aread</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink></para>
</listitem><listitem><para><olink targetdoc="group-refman" targetptr="awrite-9e" remap="external"><citerefentry><refentrytitle>awrite</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink></para>
</listitem><listitem><para><olink targetdoc="group-refman" targetptr="mmap-9e" remap="external"><citerefentry><refentrytitle>mmap</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink></para>
</listitem><listitem><para><olink targetdoc="group-refman" targetptr="devmap-9e" remap="external"><citerefentry><refentrytitle>devmap</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink></para>
</listitem><listitem><para><olink targetdoc="group-refman" targetptr="segmap-9e" remap="external"><citerefentry><refentrytitle>segmap</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink></para>
</listitem><listitem><para><olink targetdoc="group-refman" targetptr="prop-op-9e" remap="external"><citerefentry><refentrytitle>prop_op</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink></para>
</listitem>
</itemizedlist><note><para><indexterm id="character-ix365"><primary>entry points</primary><secondary sortas="character">for character drivers</secondary></indexterm><indexterm id="character-ix366"><primary>character device driver</primary><secondary>entry points for</secondary></indexterm><indexterm id="character-ix367"><primary>entry points</primary><secondary sortas="character">for character drivers</secondary></indexterm>Some of these entry points can be replaced with <olink targetdoc="group-refman" targetptr="nodev-9f" remap="external"><citerefentry><refentrytitle>nodev</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> or <olink targetdoc="group-refman" targetptr="nulldev-9f" remap="external"><citerefentry><refentrytitle>nulldev</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> as appropriate.</para>
</note>
</sect1><sect1 id="character-51"><title>Character Device Autoconfiguration</title><para><indexterm id="character-ix368"><primary>character device driver</primary><secondary>autoconfiguration</secondary></indexterm><indexterm id="character-ix369"><primary>autoconfiguration</primary><secondary sortas="character">of character devices</secondary></indexterm>The  <olink targetdoc="group-refman" targetptr="attach-9e" remap="external"><citerefentry><refentrytitle>attach</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> routine should
perform the common initialization tasks that all devices require, such as:</para><itemizedlist><listitem><para>Allocating per-instance state structures</para>
</listitem><listitem><para>Registering device interrupts</para>
</listitem><listitem><para>Mapping the device's registers</para>
</listitem><listitem><para>Initializing mutex variables and condition variables</para>
</listitem><listitem><para>Creating power-manageable components</para>
</listitem><listitem><para>Creating minor nodes</para>
</listitem>
</itemizedlist><para>See <olink targetptr="autoconf-41111" remap="internal">attach() Entry Point</olink> for
code examples of these tasks.</para><para><indexterm><primary><literal>size</literal> property</primary></indexterm><indexterm><primary>properties</primary><secondary><literal>size</literal> property</secondary></indexterm>Character device drivers create minor nodes of type <literal>S_IFCHR</literal>.
A minor node of <literal>S_IFCHR</literal> causes a character special file
that represents the node to eventually appear in the <filename>/devices</filename> hierarchy.</para><para>The following example shows a typical <olink targetdoc="group-refman" targetptr="attach-9e" remap="external"><citerefentry><refentrytitle>attach</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> routine for character drivers.
Properties that are associated with the device are commonly declared in an <function>attach</function> routine. This example uses a predefined <literal>Size</literal> property. <literal>Size</literal> is the equivalent of the <literal>Nblocks</literal> property
 for getting the size of partition in a block device. If, for example, you
are doing character I/O on a disk device, you might use <literal>Size</literal> to
get the size of a partition. Since <literal>Size</literal> is a 64-bit property,
you must use a 64-bit property interface. In this case, you use  <olink targetdoc="group-refman" targetptr="ddi-prop-update-int64-9f" remap="external"><citerefentry><refentrytitle>ddi_prop_update_int64</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink>. See <olink targetptr="properties-8" remap="internal">Device Properties</olink> for
more information about properties.</para><example id="character-40982"><title>Character Driver <function>attach</function> Routine</title><programlisting>static int
xxattach(dev_info_t *dip, ddi_attach_cmd_t cmd)
{
  int instance = ddi_get_instance(dip);
  switch (cmd) {
  case DDI_ATTACH:
      /*
       * Allocate a state structure and initialize it.
       * Map the device's registers.
       * Add the device driver's interrupt handler(s).
       * Initialize any mutexes and condition variables.
       * Create power manageable components.
       *
       * Create the device's minor node. Note that the node_type
       * argument is set to DDI_NT_TAPE.
       */
       if (ddi_create_minor_node(dip, <replaceable>minor_name</replaceable>, S_IFCHR,
           <replaceable>instance</replaceable>, DDI_NT_TAPE, 0) == DDI_FAILURE)
{
           /* Free resources allocated so far. */
           /* Remove any previously allocated minor nodes. */
           ddi_remove_minor_node(dip, NULL);
           return (DDI_FAILURE);
       }
      /*
       * Create driver properties like "Size." Use "Size"
       * instead of "size" to ensure the property works
       * for large bytecounts.
       */
       xsp-&gt;Size = <replaceable>size_of_device_in_bytes</replaceable>;
       maj_number = ddi_driver_major(dip);
       if (ddi_prop_update_int64(makedevice(maj_number, instance),
           dip, "Size", xsp-&gt;Size) != DDI_PROP_SUCCESS) {
           cmn_err(CE_CONT, "%s: cannot create Size property\n",
               ddi_get_name(dip));
               /* Free resources allocated so far. */
           return (DDI_FAILURE);
       }
      /* ... */
      return (DDI_SUCCESS);
case DDI_RESUME:
      /* See the "Power Management" chapter in this book. */
default:
      return (DDI_FAILURE);
  }
}</programlisting>
</example>
</sect1><sect1 id="character-6"><title>Device Access (Character Drivers)</title><para><indexterm id="character-ix370"><primary><function>open</function> entry point</primary><secondary>character drivers</secondary></indexterm>Access
to a device by one or more application programs is controlled through the <olink targetdoc="group-refman" targetptr="open-9e" remap="external"><citerefentry><refentrytitle>open</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> and <olink targetdoc="group-refman" targetptr="close-9e" remap="external"><citerefentry><refentrytitle>close</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> entry points. An <olink targetdoc="group-refman" targetptr="open-2" remap="external"><citerefentry><refentrytitle>open</refentrytitle><manvolnum>2</manvolnum></citerefentry></olink> system call to a special file
representing a character device always causes a call to the <olink targetdoc="group-refman" targetptr="open-9e" remap="external"><citerefentry><refentrytitle>open</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> routine for the driver. For
a particular minor device, <olink targetdoc="group-refman" targetptr="open-9e" remap="external"><citerefentry><refentrytitle>open</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> can
be called many times. The <olink targetdoc="group-refman" targetptr="close-9e" remap="external"><citerefentry><refentrytitle>close</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> routine
is called only when the final reference to a device is removed. If the device
is accessed through file descriptors, the final call to <olink targetdoc="group-refman" targetptr="close-9e" remap="external"><citerefentry><refentrytitle>close</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> can occur as a result of
a <olink targetdoc="group-refman" targetptr="close-2" remap="external"><citerefentry><refentrytitle>close</refentrytitle><manvolnum>2</manvolnum></citerefentry></olink> or <olink targetdoc="group-refman" targetptr="exit-2" remap="external"><citerefentry><refentrytitle>exit</refentrytitle><manvolnum>2</manvolnum></citerefentry></olink> system call. If the device
is accessed through memory mapping, the final call to <olink targetdoc="group-refman" targetptr="close-9e" remap="external"><citerefentry><refentrytitle>close</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> can occur as a result of
a <olink targetdoc="group-refman" targetptr="munmap-2" remap="external"><citerefentry><refentrytitle>munmap</refentrytitle><manvolnum>2</manvolnum></citerefentry></olink> system
call.</para><sect2 id="character-7"><title><function>open</function> Entry Point (Character
Drivers)</title><indexterm id="character-ix371"><primary>device access functions</primary><secondary>character drivers</secondary>
</indexterm><indexterm id="character-ix372"><primary>character device driver</primary><secondary><function>open</function> entry point</secondary>
</indexterm><para>The primary function of <function>open</function> is to verify that
the open request is allowed. The syntax for <olink targetdoc="group-refman" targetptr="open-9e" remap="external"><citerefentry><refentrytitle>open</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> is as follows:</para><programlisting>int xxopen(dev_t *<replaceable>devp</replaceable>, int <replaceable>flag</replaceable>, int <replaceable>otyp</replaceable>, cred_t *<replaceable>credp</replaceable>);</programlisting><para>where:</para><variablelist><varlistentry><term><replaceable>devp</replaceable></term><listitem><para>Pointer to a device number. The <function>open</function> routine
is passed a pointer so that the driver can change the minor number. With this
pointer, drivers can dynamically create minor instances of the device. An
example would be a pseudo terminal driver that creates a new pseudo-terminal
whenever the driver is opened. A driver that dynamically chooses the minor
number normally creates only one minor device node in <olink targetdoc="group-refman" targetptr="attach-9e" remap="external"><citerefentry><refentrytitle>attach</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> with <olink targetdoc="group-refman" targetptr="ddi-create-minor-node-9f" remap="external"><citerefentry><refentrytitle>ddi_create_minor_node</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink>, then changes the minor number component of <literal>*devp</literal> using <olink targetdoc="group-refman" targetptr="makedevice-9f" remap="external"><citerefentry><refentrytitle>makedevice</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> and <olink targetdoc="group-refman" targetptr="getmajor-9f" remap="external"><citerefentry><refentrytitle>getmajor</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink>:</para><programlisting>*devp = makedevice(getmajor(*<replaceable>devp</replaceable>), <replaceable>new_minor</replaceable>);</programlisting><para>You do not have to call <olink targetdoc="group-refman" targetptr="ddi-create-minor-node-9f" remap="external"><citerefentry><refentrytitle>ddi_create_minor_node</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> for the new
minor. A driver must not change the major number of <literal>*devp</literal>.
The driver must keep track of available minor numbers internally.</para>
</listitem>
</varlistentry><varlistentry><term><replaceable>flag</replaceable></term><listitem><para>Flag with bits to indicate whether the device is opened for
reading (<literal>FREAD</literal>), writing (<literal>FWRITE</literal>), or
both. User threads issuing the <olink targetdoc="group-refman" targetptr="open-2" remap="external"><citerefentry><refentrytitle>open</refentrytitle><manvolnum>2</manvolnum></citerefentry></olink> system
call can also request exclusive access to the device (<literal>FEXCL</literal>)
or specify that the open should not block for any reason (<literal>FNDELAY</literal>),
but the driver must enforce both cases. A driver for a write-only device such
as a printer might consider an <olink targetdoc="group-refman" targetptr="open-9e" remap="external"><citerefentry><refentrytitle>open</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> for reading invalid.</para>
</listitem>
</varlistentry><varlistentry><term><replaceable>otyp</replaceable></term><listitem><para>Integer that indicates how <function>open</function> was called.
The driver must check that the value of <replaceable>otyp</replaceable> is
appropriate for the device. For character drivers, <replaceable>otyp</replaceable> should
be <literal>OTYP_CHR</literal> (see the <olink targetdoc="group-refman" targetptr="open-9e" remap="external"><citerefentry><refentrytitle>open</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> man page).</para>
</listitem>
</varlistentry><varlistentry><term><replaceable>credp</replaceable></term><listitem><para>Pointer to a credential structure containing information about
the caller, such as the user ID and group IDs. Drivers should not examine
the structure directly, but should instead use <olink targetdoc="group-refman" targetptr="drv-priv-9f" remap="external"><citerefentry><refentrytitle>drv_priv</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> to check for the common case
of root privileges. In this example, only <literal>root</literal> or a user
with the PRIV_SYS_DEVICES privilege is allowed to open the device for writing.</para>
</listitem>
</varlistentry>
</variablelist><para>The following example shows a character driver  <olink targetdoc="group-refman" targetptr="open-9e" remap="external"><citerefentry><refentrytitle>open</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> routine.</para><example id="character-27851"><title>Character Driver <citerefentry><refentrytitle>open</refentrytitle><manvolnum>9E</manvolnum></citerefentry> Routine</title><programlisting>static int
xxopen(dev_t *devp, int flag, int otyp, cred_t *credp)
{
    minor_t        instance;

    if (getminor(*devp)         /* if device pointer is invalid */
        return (EINVAL);
    instance = getminor(*devp); /* one-to-one example mapping */
    /* Is the instance attached? */
    if (ddi_get_soft_state(statep, instance) == NULL)
        return (ENXIO);
    /* verify that otyp is appropriate */
    if (otyp != OTYP_CHR)
        return (EINVAL);
    if ((flag &amp; FWRITE) &amp;&amp; drv_priv(credp) == EPERM)
        return (EPERM);
    return (0);
}</programlisting>
</example>
</sect2><sect2 id="character-8"><title><function>close</function> Entry Point (Character
Drivers)</title><para>The syntax for <olink targetdoc="group-refman" targetptr="close-9e" remap="external"><citerefentry><refentrytitle>close</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> is
as follows:</para><programlisting>int xxclose(dev_t <replaceable>dev</replaceable>, int <replaceable>flag</replaceable>, int <replaceable>otyp</replaceable>, cred_t *<replaceable>credp</replaceable>);</programlisting><para><indexterm id="character-ix373"><primary>character device driver</primary><secondary><function>close</function> entry point</secondary></indexterm><indexterm id="character-ix374"><primary><function>close</function> entry point</primary><secondary>description of</secondary></indexterm><function>close</function> should
perform any cleanup necessary to finish using the minor device, and prepare
the device (and driver) to be opened again. For example, the open routine
might have been invoked with the exclusive access (<literal>FEXCL</literal>)
flag. A call to <olink targetdoc="group-refman" targetptr="close-9e" remap="external"><citerefentry><refentrytitle>close</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> would
allow additional open routines to continue. Other functions that <olink targetdoc="group-refman" targetptr="close-9e" remap="external"><citerefentry><refentrytitle>close</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> might perform are:</para><itemizedlist><listitem><para>Waiting for I/O to drain from output buffers before returning</para>
</listitem><listitem><para>Rewinding a tape (tape device)</para>
</listitem><listitem><para>Hanging up the phone line (modem device)</para>
</listitem>
</itemizedlist><para>A driver that waits for I/O to drain could wait forever if draining
stalls due to external conditions such as flow control.  See <olink targetptr="mt-23" remap="internal">Threads Unable to Receive Signals</olink> for information
about how to avoid this problem.</para>
</sect2>
</sect1><sect1 id="character-25379"><title>I/O Request Handling</title><para><indexterm id="character-ix375"><primary>character device driver</primary><secondary>data transfers</secondary></indexterm><indexterm id="character-ix376"><primary>data transfers</primary><secondary>character drivers</secondary></indexterm>This section discusses I/O request processing in detail. </para><sect2 id="character-9"><title>User Addresses</title><para><indexterm id="character-ix377"><primary><function>write</function> function</primary><secondary>user address example</secondary></indexterm>When a user
thread issues a <olink targetdoc="group-refman" targetptr="write-2" remap="external"><citerefentry><refentrytitle>write</refentrytitle><manvolnum>2</manvolnum></citerefentry></olink> system
call, the thread passes the address of a buffer in user space:</para><programlisting>char buffer[] = "python";
count = write(fd, buffer, strlen(buffer) + 1);</programlisting><para>The system builds a <olink targetdoc="group-refman" targetptr="uio-9s" remap="external"><citerefentry><refentrytitle>uio</refentrytitle><manvolnum>9S</manvolnum></citerefentry></olink> structure
to describe this transfer by allocating an <olink targetdoc="group-refman" targetptr="iovec-9s" remap="external"><citerefentry><refentrytitle>iovec</refentrytitle><manvolnum>9S</manvolnum></citerefentry></olink> structure and setting the <literal>iov_base</literal> field to the address passed to <olink targetdoc="group-refman" targetptr="write-2" remap="external"><citerefentry><refentrytitle>write</refentrytitle><manvolnum>2</manvolnum></citerefentry></olink>, in this case, <literal>buffer</literal>.
The <olink targetdoc="group-refman" targetptr="uio-9s" remap="external"><citerefentry><refentrytitle>uio</refentrytitle><manvolnum>9S</manvolnum></citerefentry></olink> structure
is passed to the driver  <olink targetdoc="group-refman" targetptr="write-9e" remap="external"><citerefentry><refentrytitle>write</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> routine.
See <olink targetptr="character-15613" remap="internal">Vectored I/O</olink> for more information
about the <olink targetdoc="group-refman" targetptr="uio-9s" remap="external"><citerefentry><refentrytitle>uio</refentrytitle><manvolnum>9S</manvolnum></citerefentry></olink> structure.</para><para>The address in the <olink targetdoc="group-refman" targetptr="iovec-9s" remap="external"><citerefentry><refentrytitle>iovec</refentrytitle><manvolnum>9S</manvolnum></citerefentry></olink> is
in user space, not kernel space. Thus, the address is neither guaranteed to
be currently in memory nor  to be a valid address. In either case, accessing
a user address directly from the device driver or from the kernel could crash
the system. Thus, device drivers should never access user addresses directly.
Instead, a data transfer routine in the Solaris DDI/DKI should be used to
transfer data into or out of the kernel. These routines can handle page faults.
The DDI/DKI routines can bring in the proper user page to continue the copy
transparently. Alternatively, the routines can return an error on an invalid
access.</para><para><indexterm id="character-ix378"><primary>copying data</primary><secondary><function>copyin</function> function</secondary></indexterm><indexterm id="character-ix379"><primary>copying data</primary><secondary><function>copyout</function> function</secondary></indexterm><olink targetdoc="group-refman" targetptr="copyout-9f" remap="external"><citerefentry><refentrytitle>copyout</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> can
be used to copy data from kernel space to user space. <olink targetdoc="group-refman" targetptr="copyin-9f" remap="external"><citerefentry><refentrytitle>copyin</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> can copy
data from user space to kernel space. <olink targetdoc="group-refman" targetptr="ddi-copyout-9f" remap="external"><citerefentry><refentrytitle>ddi_copyout</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> and <olink targetdoc="group-refman" targetptr="ddi-copyin-9f" remap="external"><citerefentry><refentrytitle>ddi_copyin</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> operate similarly
but are to be used in the <olink targetdoc="group-refman" targetptr="ioctl-9e" remap="external"><citerefentry><refentrytitle>ioctl</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> routine. <olink targetdoc="group-refman" targetptr="copyin-9f" remap="external"><citerefentry><refentrytitle>copyin</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> and <olink targetdoc="group-refman" targetptr="copyout-9f" remap="external"><citerefentry><refentrytitle>copyout</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> can be used
on the buffer described by each <olink targetdoc="group-refman" targetptr="iovec-9s" remap="external"><citerefentry><refentrytitle>iovec</refentrytitle><manvolnum>9S</manvolnum></citerefentry></olink> structure, or <olink targetdoc="group-refman" targetptr="uiomove-9f" remap="external"><citerefentry><refentrytitle>uiomove</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> can perform
the entire transfer to or from a contiguous area of driver or device memory.</para>
</sect2><sect2 id="character-15613"><title>Vectored I/O</title><para>In character drivers, transfers are described by a <olink targetdoc="group-refman" targetptr="uio-9s" remap="external"><citerefentry><refentrytitle>uio</refentrytitle><manvolnum>9S</manvolnum></citerefentry></olink> structure. The <olink targetdoc="group-refman" targetptr="uio-9s" remap="external"><citerefentry><refentrytitle>uio</refentrytitle><manvolnum>9S</manvolnum></citerefentry></olink> structure contains information
about the direction and size of the transfer, plus an array of buffers for
one end of the transfer. The other end is the device.</para><para>The <olink targetdoc="group-refman" targetptr="uio-9s" remap="external"><citerefentry><refentrytitle>uio</refentrytitle><manvolnum>9S</manvolnum></citerefentry></olink> structure
contains the following members:</para><programlisting>iovec_t       *uio_iov;       /* base address of the iovec */
                              /* buffer description array */
int           uio_iovcnt;     /* the number of iovec structures */
off_t         uio_offset;     /* 32-bit offset into file where */
                              /* data is transferred from or to */
offset_t      uio_loffset;    /* 64-bit offset into file where */
                              /* data is transferred from or to */
uio_seg_t     uio_segflg;     /* identifies the type of I/O transfer */
                              /* UIO_SYSSPACE:  kernel &lt;-&gt; kernel */
                              /* UIO_USERSPACE: kernel &lt;-&gt; user */
short         uio_fmode;      /* file mode flags (not driver setTable) */
daddr_t       uio_limit;      /* 32-bit ulimit for file (maximum */
                              /* block offset). not driver settable. */
diskaddr_t    uio_llimit;     /* 64-bit ulimit for file (maximum block */
                              /* block offset). not driver settable. */
int           uio_resid;      /* amount (in bytes) not */
                              /* transferred on completion */</programlisting><para><indexterm id="character-ix382"><primary>scatter-gather</primary><secondary>I/O</secondary></indexterm><indexterm id="character-ix383"><primary>I/O</primary><secondary>scatter/gather structures</secondary></indexterm>A <olink targetdoc="group-refman" targetptr="uio-9s" remap="external"><citerefentry><refentrytitle>uio</refentrytitle><manvolnum>9S</manvolnum></citerefentry></olink> structure is passed to the
driver <olink targetdoc="group-refman" targetptr="read-9e" remap="external"><citerefentry><refentrytitle>read</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> and <olink targetdoc="group-refman" targetptr="write-9e" remap="external"><citerefentry><refentrytitle>write</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> entry points. This structure
is generalized to support what is called <emphasis>gather-write</emphasis> and <emphasis>scatter-read</emphasis>. When writing to a device, the data buffers to be
written do not have to be contiguous in application memory. Similarly, data
that is transferred from a device into memory comes off in a contiguous stream
but can go into noncontiguous areas of application memory. See the <olink targetdoc="group-refman" targetptr="readv-2" remap="external"><citerefentry><refentrytitle>readv</refentrytitle><manvolnum>2</manvolnum></citerefentry></olink>, <olink targetdoc="group-refman" targetptr="writev-2" remap="external"><citerefentry><refentrytitle>writev</refentrytitle><manvolnum>2</manvolnum></citerefentry></olink>, <olink targetdoc="group-refman" targetptr="pread-2" remap="external"><citerefentry><refentrytitle>pread</refentrytitle><manvolnum>2</manvolnum></citerefentry></olink>, and <olink targetdoc="group-refman" targetptr="pwrite-2" remap="external"><citerefentry><refentrytitle>pwrite</refentrytitle><manvolnum>2</manvolnum></citerefentry></olink> man pages
for more information on scatter-gather I/O.</para><para><indexterm id="character-ix384"><primary><structname>iovec</structname> structure</primary></indexterm>Each buffer is described by an <olink targetdoc="group-refman" targetptr="iovec-9s" remap="external"><citerefentry><refentrytitle>iovec</refentrytitle><manvolnum>9S</manvolnum></citerefentry></olink> structure. This structure
contains a pointer to the data area and the number of bytes to be transferred.</para><programlisting>caddr_t    iov_base;    /* address of buffer */
int        iov_len;     /* amount to transfer */</programlisting><para>The <structname>uio</structname> structure contains a pointer to an
array of <olink targetdoc="group-refman" targetptr="iovec-9s" remap="external"><citerefentry><refentrytitle>iovec</refentrytitle><manvolnum>9S</manvolnum></citerefentry></olink> structures.
The base address of this array is held in <literal>uio_iov</literal>, and
the number of elements is stored in <structfield>uio_iovcnt</structfield>.</para><para>The <structfield>uio_offset</structfield> field contains the 32-bit
offset into the device at which the application needs to begin the transfer. <structfield>uio_loffset</structfield> is used for 64-bit file offsets. If the device does
not support the notion of an offset, these fields can be safely ignored. The
driver should interpret either <structfield>uio_offset</structfield> or <structfield>uio_loffset</structfield>, but not both. If the driver has set the <literal>D_64BIT</literal> flag in the <olink targetdoc="group-refman" targetptr="cb-ops-9s" remap="external"><citerefentry><refentrytitle>cb_ops</refentrytitle><manvolnum>9S</manvolnum></citerefentry></olink> structure,
that driver should use <structfield>uio_loffset</structfield>.</para><para>The <structfield>uio_resid</structfield> field starts out as the number
of bytes to be transferred, that is, the sum of all the <structfield>iov_len</structfield> fields
in <structfield>uio_iov</structfield>. This field <emphasis>must</emphasis> be
set by the driver to the number of bytes that were <emphasis>not</emphasis> transferred
before returning. The <olink targetdoc="group-refman" targetptr="read-2" remap="external"><citerefentry><refentrytitle>read</refentrytitle><manvolnum>2</manvolnum></citerefentry></olink> and <olink targetdoc="group-refman" targetptr="write-2" remap="external"><citerefentry><refentrytitle>write</refentrytitle><manvolnum>2</manvolnum></citerefentry></olink> system calls use the return
value from the <olink targetdoc="group-refman" targetptr="read-9e" remap="external"><citerefentry><refentrytitle>read</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> and <olink targetdoc="group-refman" targetptr="write-9e" remap="external"><citerefentry><refentrytitle>write</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> entry points to determine
failed transfers. If a failure occurs, these routines return -1. If the return
value indicates success, the system calls return the number of bytes requested
minus <structfield>uio_resid</structfield>. If <structfield>uio_resid</structfield> is
not changed by the driver, the <olink targetdoc="group-refman" targetptr="read-2" remap="external"><citerefentry><refentrytitle>read</refentrytitle><manvolnum>2</manvolnum></citerefentry></olink> and <olink targetdoc="group-refman" targetptr="write-2" remap="external"><citerefentry><refentrytitle>write</refentrytitle><manvolnum>2</manvolnum></citerefentry></olink> calls return 0. A return value
of 0 indicates end-of-file, even though all the data has been transferred.</para><para>The support routines <olink targetdoc="group-refman" targetptr="uiomove-9f" remap="external"><citerefentry><refentrytitle>uiomove</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink>, <olink targetdoc="group-refman" targetptr="physio-9f" remap="external"><citerefentry><refentrytitle>physio</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink>, and  <olink targetdoc="group-refman" targetptr="aphysio-9f" remap="external"><citerefentry><refentrytitle>aphysio</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> update the <olink targetdoc="group-refman" targetptr="uio-9s" remap="external"><citerefentry><refentrytitle>uio</refentrytitle><manvolnum>9S</manvolnum></citerefentry></olink> structure directly. These
support routines update the device offset to account for the data transfer.
Neither the <structfield>uio_offset</structfield> or <structfield>uio_loffset</structfield> fields
need to be adjusted when the driver is used with a seekable device that uses
the concept of position. I/O performed to a device in this manner is constrained
by the maximum possible value of <structfield>uio_offset</structfield> or <structfield>uio_loffset</structfield>. An example of such a usage is raw I/O on a disk.</para><para>If the device has no concept of position, the driver can take the following
steps:</para><orderedlist><listitem><para>Save <structfield>uio_offset</structfield> or <structfield>uio_loffset</structfield>.</para>
</listitem><listitem><para>Perform the I/O operation.</para>
</listitem><listitem><para>Restore <structfield>uio_offset</structfield> or <structfield>uio_loffset</structfield> to the field's initial value.</para>
</listitem>
</orderedlist><para>I/O that is performed to a device in this manner is not constrained
by the maximum possible value of <structfield>uio_offset</structfield> or <structfield>uio_loffset</structfield>. An example of this type of usage is I/O on a serial
line.</para><para>The following example shows one way to preserve <structfield>uio_loffset</structfield> in
the  <olink targetdoc="group-refman" targetptr="read-9e" remap="external"><citerefentry><refentrytitle>read</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> function.</para><programlisting>static int
xxread(dev_t dev, struct uio *uio_p, cred_t *cred_p)
{
    offset_t off;
    /* ... */
    off = uio_p-&gt;uio_loffset;  /* save the offset */
    /* do the transfer */
    uio_p-&gt;uio_loffset = off;  /* restore it */
}</programlisting>
</sect2><sect2 id="character-11"><title>Differences Between Synchronous and Asynchronous
I/O</title><para><indexterm><primary>synchronous data transfers</primary><secondary>character drivers</secondary></indexterm><indexterm><primary>asynchronous data transfers</primary><secondary>character drivers</secondary></indexterm>Data transfers can be <emphasis>synchronous</emphasis> or <emphasis>asynchronous</emphasis>. The determining
factor is whether the entry point that schedules the transfer returns immediately
or waits until the I/O has been completed.</para><para><indexterm id="character-ix385a"><primary><function>read</function> entry point</primary><secondary>synchronous data transfers</secondary></indexterm><indexterm id="character-ix385b"><primary><function>write</function> function</primary><secondary>synchronous data transfers</secondary></indexterm><indexterm id="character-ix387"><primary>I/O</primary><secondary>synchronous data transfers</secondary></indexterm>The <olink targetdoc="group-refman" targetptr="read-9e" remap="external"><citerefentry><refentrytitle>read</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> and
 <olink targetdoc="group-refman" targetptr="write-9e" remap="external"><citerefentry><refentrytitle>write</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> entry
points are synchronous entry points. The transfer must not return until the
I/O is complete. Upon return from the routines, the process knows whether
the transfer has succeeded.</para><para><indexterm id="character-ix385c"><primary><function>aread</function> entry point</primary><secondary>asynchronous data transfers</secondary></indexterm><indexterm id="character-ix385"><primary><function>awrite</function> entry point</primary><secondary>asynchronous data transfers</secondary></indexterm>The  <olink targetdoc="group-refman" targetptr="aread-9e" remap="external"><citerefentry><refentrytitle>aread</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> and <olink targetdoc="group-refman" targetptr="awrite-9e" remap="external"><citerefentry><refentrytitle>awrite</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> entry points
are asynchronous entry points. Asynchronous entry points schedule the I/O
and return immediately. Upon return, the process that issues the request knows
that the I/O is scheduled and that the status of the I/O must be determined
later. In the meantime, the process can perform other operations. </para><para><indexterm id="character-ix390"><primary>I/O</primary><secondary>asynchronous data transfers</secondary></indexterm>With an asynchronous I/O request to
the kernel, the process is not required to wait while the I/O is in process.
A process can perform multiple I/O requests and allow the kernel to handle
the data transfer details. Asynchronous I/O requests enable applications such
as transaction processing to use concurrent programming methods to increase
performance or response time. Any performance boost for applications that
use asynchronous I/O, however, comes at the expense of greater programming
complexity.</para>
</sect2><sect2 id="character-22917"><title>Data Transfer Methods</title><para>Data can be transferred using either programmed I/O or DMA. These data
transfer methods can be used either by synchronous or by asynchronous entry
points, depending on the capabilities of the device.</para><sect3 id="character-12"><title>Programmed I/O Transfers</title><para><indexterm id="character-ix391"><primary>programmed I/O</primary></indexterm><indexterm id="character-ix392"><primary>I/O</primary><secondary>programmed transfers</secondary></indexterm>Programmed I/O devices rely on the CPU to
perform the data transfer. Programmed I/O data transfers are identical to
other read and write operations for device registers. Various data access
routines are used to read or store values to device memory.</para><para><indexterm id="character-ix393"><primary><function>uiomove</function> function</primary><secondary>example of</secondary></indexterm><indexterm><primary><function>uiomove</function> example</primary></indexterm><olink targetdoc="group-refman" targetptr="uiomove-9f" remap="external"><citerefentry><refentrytitle>uiomove</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> can be used to transfer data
to some programmed I/O devices.  <olink targetdoc="group-refman" targetptr="uiomove-9f" remap="external"><citerefentry><refentrytitle>uiomove</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> transfers data between the
user space, as defined by the <literal>uio(9S)</literal> structure, and the
kernel.  <function>uiomove</function>  can handle page faults, so the memory
to which data is transferred need not be locked down. <function>uiomove</function> also
updates the <literal>uio_resid</literal> field in the <olink targetdoc="group-refman" targetptr="uio-9s" remap="external"><citerefentry><refentrytitle>uio</refentrytitle><manvolnum>9S</manvolnum></citerefentry></olink> structure. The following
example shows one way to write a ramdisk <olink targetdoc="group-refman" targetptr="read-9e" remap="external"><citerefentry><refentrytitle>read</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> routine. It uses synchronous I/O and relies
on the presence of the following fields in the ramdisk state structure:</para><programlisting>caddr_t    ram;        /* base address of ramdisk */
int        ramsize;    /* size of the ramdisk */</programlisting><example id="character-31915"><title>Ramdisk <citerefentry><refentrytitle>read</refentrytitle><manvolnum>9E</manvolnum></citerefentry> Routine Using <citerefentry><refentrytitle>uiomove</refentrytitle><manvolnum>9F</manvolnum></citerefentry></title><programlisting>static int
rd_read(dev_t dev, struct uio *uiop, cred_t *credp)
{
     rd_devstate_t     *rsp;

     rsp = ddi_get_soft_state(rd_statep, getminor(dev));
     if (rsp == NULL)
       return (ENXIO);
     if (uiop-&gt;uio_offset &gt;= rsp-&gt;ramsize)
       return (EINVAL);
     /*
      * uiomove takes the offset into the kernel buffer,
      * the data transfer count (minimum of the requested and
      * the remaining data), the UIO_READ flag, and a pointer
      * to the uio structure.
      */
     return (uiomove(rsp-&gt;ram + uiop-&gt;uio_offset,
         min(uiop-&gt;uio_resid, rsp-&gt;ramsize - uiop-&gt;uio_offset),
         UIO_READ, uiop));
}</programlisting>
</example><para>Another example of programmed I/O would be a driver that writes data
one byte at a time directly to the device's memory. Each byte is retrieved
from the <olink targetdoc="group-refman" targetptr="uio-9s" remap="external"><citerefentry><refentrytitle>uio</refentrytitle><manvolnum>9S</manvolnum></citerefentry></olink> structure
by using <olink targetdoc="group-refman" targetptr="uwritec-9f" remap="external"><citerefentry><refentrytitle>uwritec</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink>.
The byte is then sent to the device. <olink targetdoc="group-refman" targetptr="read-9e" remap="external"><citerefentry><refentrytitle>read</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> can use <olink targetdoc="group-refman" targetptr="ureadc-9f" remap="external"><citerefentry><refentrytitle>ureadc</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> to transfer a byte from the
device to the area described by the <olink targetdoc="group-refman" targetptr="uio-9s" remap="external"><citerefentry><refentrytitle>uio</refentrytitle><manvolnum>9S</manvolnum></citerefentry></olink> structure.</para><example id="character-ex-15"><title>Programmed I/O <citerefentry><refentrytitle>write</refentrytitle><manvolnum>9E</manvolnum></citerefentry> Routine
Using <citerefentry><refentrytitle>uwritec</refentrytitle><manvolnum>9F</manvolnum></citerefentry></title><programlisting>static int
xxwrite(dev_t dev, struct uio *uiop, cred_t *credp)
{
    int    value;
    struct xxstate     *xsp;

    xsp = ddi_get_soft_state(statep, getminor(dev));
    if (xsp == NULL)
        return (ENXIO);
    /* if the device implements a power manageable component, do this: */
    pm_busy_component(xsp-&gt;dip, 0);
    if (xsp-&gt;pm_suspended)
        pm_raise_power(xsp-&gt;dip, normal power);

    while (uiop-&gt;uio_resid &gt; 0) {
        /*
         * do the programmed I/O access
         */
        value = uwritec(uiop);
        if (value == -1)
               return (EFAULT);
        ddi_put8(xsp-&gt;data_access_handle, &amp;xsp-&gt;regp-&gt;data,
            (uint8_t)value);
        ddi_put8(xsp-&gt;data_access_handle, &amp;xsp-&gt;regp-&gt;csr,
            START_TRANSFER);
        /*
         * this device requires a ten microsecond delay
         * between writes
         */
        drv_usecwait(10);
    }
    pm_idle_component(xsp-&gt;dip, 0);
    return (0);
}</programlisting>
</example>
</sect3><sect3 id="character-35745"><title>DMA Transfers (Synchronous)</title><indexterm id="character-ix394"><primary>DMA</primary><secondary>transfers</secondary>
</indexterm><para><indexterm id="character-ix395a"><primary>character device driver</primary><secondary><function>physio</function> function</secondary></indexterm><indexterm id="character-ix396"><primary>I/O</primary><secondary>DMA transfers</secondary></indexterm><indexterm id="character-ix397a"><primary><function>physio</function> function</primary><secondary>description of</secondary></indexterm>Character drivers
generally use  <olink targetdoc="group-refman" targetptr="physio-9f" remap="external"><citerefentry><refentrytitle>physio</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> to
do the setup work for DMA transfers in  <olink targetdoc="group-refman" targetptr="read-9e" remap="external"><citerefentry><refentrytitle>read</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> and <olink targetdoc="group-refman" targetptr="write-9e" remap="external"><citerefentry><refentrytitle>write</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink>, as is shown in <olink targetptr="character-36010" remap="internal">Example&nbsp;15&ndash;5</olink>.</para><programlisting>int physio(int (*<replaceable>strat</replaceable>)(struct <replaceable>buf</replaceable> *), struct buf *<replaceable>bp</replaceable>,
     dev_t <replaceable>dev</replaceable>, int <replaceable>rw</replaceable>, void (*<replaceable>mincnt</replaceable>)(struct <replaceable>buf</replaceable> *),
     struct uio *<replaceable>uio</replaceable>);</programlisting><para><olink targetdoc="group-refman" targetptr="physio-9f" remap="external"><citerefentry><refentrytitle>physio</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> requires
the driver to provide the address of a <olink targetdoc="group-refman" targetptr="strategy-9e" remap="external"><citerefentry><refentrytitle>strategy</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> routine.  <olink targetdoc="group-refman" targetptr="physio-9f" remap="external"><citerefentry><refentrytitle>physio</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> ensures that
memory space is locked down, that is, memory cannot be paged out, for the
duration of the data transfer. This lock-down is necessary for DMA transfers
because DMA transfers cannot handle page faults.  <olink targetdoc="group-refman" targetptr="physio-9f" remap="external"><citerefentry><refentrytitle>physio</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> also provides an automated
way of breaking a larger transfer into a series of smaller, more manageable
ones. See <olink targetptr="character-42867" remap="internal">minphys() Entry Point</olink> for
more information.</para><example id="character-36010"><title><citerefentry><refentrytitle>read</refentrytitle><manvolnum>9E</manvolnum></citerefentry> and <citerefentry><refentrytitle>write</refentrytitle><manvolnum>9E</manvolnum></citerefentry> Routines Using <citerefentry><refentrytitle>physio</refentrytitle><manvolnum>9F</manvolnum></citerefentry></title><programlisting>static int
xxread(dev_t dev, struct uio *uiop, cred_t *credp)
{
     struct xxstate *xsp;
     int ret;

     xsp = ddi_get_soft_state(statep, getminor(dev));
     if (xsp == NULL)
        return (ENXIO);
     ret = physio(xxstrategy, NULL, dev, B_READ, xxminphys, uiop);
     return (ret);
}    

static int
xxwrite(dev_t dev, struct uio *uiop, cred_t *credp)
{     
     struct xxstate *xsp;
     int ret;

     xsp = ddi_get_soft_state(statep, getminor(dev));
     if (xsp == NULL)
        return (ENXIO);
     ret = physio(xxstrategy, NULL, dev, B_WRITE, xxminphys, uiop);
     return (ret);
}</programlisting>
</example><para>In the call to <olink targetdoc="group-refman" targetptr="physio-9f" remap="external"><citerefentry><refentrytitle>physio</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink>, <literal>xxstrategy</literal> is a pointer to the driver <function>strategy</function> routine.
Passing <literal>NULL</literal> as the <olink targetdoc="group-refman" targetptr="buf-9s" remap="external"><citerefentry><refentrytitle>buf</refentrytitle><manvolnum>9S</manvolnum></citerefentry></olink> structure pointer tells <olink targetdoc="group-refman" targetptr="physio-9f" remap="external"><citerefentry><refentrytitle>physio</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> to allocate a <olink targetdoc="group-refman" targetptr="buf-9s" remap="external"><citerefentry><refentrytitle>buf</refentrytitle><manvolnum>9S</manvolnum></citerefentry></olink> structure. If the driver
must provide <olink targetdoc="group-refman" targetptr="physio-9f" remap="external"><citerefentry><refentrytitle>physio</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> with
a <olink targetdoc="group-refman" targetptr="buf-9s" remap="external"><citerefentry><refentrytitle>buf</refentrytitle><manvolnum>9S</manvolnum></citerefentry></olink> structure, <olink targetdoc="group-refman" targetptr="getrbuf-9f" remap="external"><citerefentry><refentrytitle>getrbuf</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> should be
used to allocate the structure. <olink targetdoc="group-refman" targetptr="physio-9f" remap="external"><citerefentry><refentrytitle>physio</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> returns zero if the transfer
completes successfully, or an error number on failure. After calling <olink targetdoc="group-refman" targetptr="strategy-9e" remap="external"><citerefentry><refentrytitle>strategy</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink>, <olink targetdoc="group-refman" targetptr="physio-9f" remap="external"><citerefentry><refentrytitle>physio</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> calls  <olink targetdoc="group-refman" targetptr="biowait-9f" remap="external"><citerefentry><refentrytitle>biowait</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> to block
until the transfer either completes or fails. The return value of <olink targetdoc="group-refman" targetptr="physio-9f" remap="external"><citerefentry><refentrytitle>physio</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> is determined
by the error field in the <olink targetdoc="group-refman" targetptr="buf-9s" remap="external"><citerefentry><refentrytitle>buf</refentrytitle><manvolnum>9S</manvolnum></citerefentry></olink> structure
set by  <olink targetdoc="group-refman" targetptr="bioerror-9f" remap="external"><citerefentry><refentrytitle>bioerror</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink>.</para>
</sect3><sect3 id="character-16"><title>DMA Transfers (Asynchronous)</title><para><indexterm id="character-ix395"><primary>character device driver</primary><secondary><function>aphysio</function> function</secondary></indexterm><indexterm id="character-ix397b"><primary><function>aphysio</function> function</primary></indexterm>Character drivers that support  <olink targetdoc="group-refman" targetptr="aread-9e" remap="external"><citerefentry><refentrytitle>aread</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> and <olink targetdoc="group-refman" targetptr="awrite-9e" remap="external"><citerefentry><refentrytitle>awrite</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> use <olink targetdoc="group-refman" targetptr="aphysio-9f" remap="external"><citerefentry><refentrytitle>aphysio</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> instead of <olink targetdoc="group-refman" targetptr="physio-9f" remap="external"><citerefentry><refentrytitle>physio</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink>.</para><programlisting>int aphysio(int (*<replaceable>strat</replaceable>)(struct <replaceable>buf</replaceable> *), int (*<replaceable>cancel</replaceable>)(struct <replaceable>buf</replaceable> *),
     dev_t <replaceable>dev</replaceable>, int <replaceable>rw</replaceable>, void (*<replaceable>mincnt</replaceable>)(struct <replaceable>buf</replaceable> *),
     struct aio_req *<replaceable>aio_reqp</replaceable>);</programlisting><note><para>The address of  <olink targetdoc="group-refman" targetptr="anocancel-9f" remap="external"><citerefentry><refentrytitle>anocancel</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> is the only value that can
currently be passed as the second argument to  <olink targetdoc="group-refman" targetptr="aphysio-9f" remap="external"><citerefentry><refentrytitle>aphysio</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink>.</para>
</note><para><olink targetdoc="group-refman" targetptr="aphysio-9f" remap="external"><citerefentry><refentrytitle>aphysio</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> requires
the driver to pass the address of a <olink targetdoc="group-refman" targetptr="strategy-9e" remap="external"><citerefentry><refentrytitle>strategy</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> routine.  <olink targetdoc="group-refman" targetptr="aphysio-9f" remap="external"><citerefentry><refentrytitle>aphysio</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> ensures that
memory space is locked down, that is, cannot be paged out, for the duration
of the data transfer. This lock-down is necessary for DMA transfers because
DMA transfers cannot handle page faults.  <olink targetdoc="group-refman" targetptr="aphysio-9f" remap="external"><citerefentry><refentrytitle>aphysio</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> also provides an automated
way of breaking a larger transfer into a series of smaller, more manageable
ones. See <olink targetptr="character-42867" remap="internal">minphys() Entry Point</olink> for
more information.</para><para><olink targetptr="character-36010" remap="internal">Example&nbsp;15&ndash;5</olink> and <olink targetptr="character-29697" remap="internal">Example&nbsp;15&ndash;6</olink> demonstrate that
the  <olink targetdoc="group-refman" targetptr="aread-9e" remap="external"><citerefentry><refentrytitle>aread</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> and <olink targetdoc="group-refman" targetptr="awrite-9e" remap="external"><citerefentry><refentrytitle>awrite</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> entry points
differ only slightly from the  <olink targetdoc="group-refman" targetptr="read-9e" remap="external"><citerefentry><refentrytitle>read</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> and <olink targetdoc="group-refman" targetptr="write-9e" remap="external"><citerefentry><refentrytitle>write</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> entry points. The difference
is primarily in their use of <olink targetdoc="group-refman" targetptr="aphysio-9f" remap="external"><citerefentry><refentrytitle>aphysio</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> instead of <olink targetdoc="group-refman" targetptr="physio-9f" remap="external"><citerefentry><refentrytitle>physio</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink>.</para><example id="character-29697"><title><citerefentry><refentrytitle>aread</refentrytitle><manvolnum>9E</manvolnum></citerefentry> and <citerefentry><refentrytitle>awrite</refentrytitle><manvolnum>9E</manvolnum></citerefentry> Routines Using <citerefentry><refentrytitle>aphysio</refentrytitle><manvolnum>9F</manvolnum></citerefentry></title><programlisting>static int
xxaread(dev_t dev, struct aio_req *aiop, cred_t *cred_p)
{
     struct xxstate *xsp;

     xsp = ddi_get_soft_state(statep, getminor(dev));
     if (xsp == NULL)
         return (ENXIO);
     return (aphysio(xxstrategy, anocancel, dev, B_READ,
     xxminphys, aiop));
}

static int
xxawrite(dev_t dev, struct aio_req *aiop, cred_t *cred_p)
{
     struct xxstate *xsp;

     xsp = ddi_get_soft_state(statep, getminor(dev));
     if (xsp == NULL)
        return (ENXIO);
     return (aphysio(xxstrategy, anocancel, dev, B_WRITE,
     xxminphys,aiop));  
}</programlisting>
</example><para>In the call to  <olink targetdoc="group-refman" targetptr="aphysio-9f" remap="external"><citerefentry><refentrytitle>aphysio</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink>, <function>xxstrategy</function> is a pointer to the driver strategy routine. <replaceable>aiop</replaceable> is a pointer to the <olink targetdoc="group-refman" targetptr="aio-req-9s" remap="external"><citerefentry><refentrytitle>aio_req</refentrytitle><manvolnum>9S</manvolnum></citerefentry></olink> structure. <replaceable>aiop</replaceable> is
passed to  <olink targetdoc="group-refman" targetptr="aread-9e" remap="external"><citerefentry><refentrytitle>aread</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> and <olink targetdoc="group-refman" targetptr="awrite-9e" remap="external"><citerefentry><refentrytitle>awrite</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink>.   <olink targetdoc="group-refman" targetptr="aio-req-9s" remap="external"><citerefentry><refentrytitle>aio_req</refentrytitle><manvolnum>9S</manvolnum></citerefentry></olink> describes
where the data is to be stored in user space.  <olink targetdoc="group-refman" targetptr="aphysio-9f" remap="external"><citerefentry><refentrytitle>aphysio</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> returns zero if the I/O request
is scheduled successfully or an error number on failure. After calling <olink targetdoc="group-refman" targetptr="strategy-9e" remap="external"><citerefentry><refentrytitle>strategy</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink>,  <olink targetdoc="group-refman" targetptr="aphysio-9f" remap="external"><citerefentry><refentrytitle>aphysio</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> returns without
waiting for the I/O to complete or fail.</para>
</sect3><sect3 id="character-42867"><title><function>minphys</function> Entry Point</title><para><indexterm id="character-ix395e"><primary>character device driver</primary><secondary><function>minphys</function> function</secondary></indexterm><indexterm id="character-ix397c"><primary><function>minphys</function> function</primary></indexterm>The <function>minphys</function> entry point is a pointer to a
function to be called by  <olink targetdoc="group-refman" targetptr="physio-9f" remap="external"><citerefentry><refentrytitle>physio</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> or <olink targetdoc="group-refman" targetptr="aphysio-9f" remap="external"><citerefentry><refentrytitle>aphysio</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink>. The purpose
of <replaceable>xxminphys</replaceable> is to ensure that the size of the
requested transfer does not exceed a driver-imposed limit. If the user requests
a larger transfer,  <olink targetdoc="group-refman" targetptr="strategy-9e" remap="external"><citerefentry><refentrytitle>strategy</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> is
called repeatedly, requesting no more than the imposed limit at a time. This
approach is important because DMA resources are limited. Drivers for slow
devices, such as printers, should be careful not to tie up resources for a
long time.</para><para>Usually, a driver passes the address of the kernel function  <olink targetdoc="group-refman" targetptr="minphys-9f" remap="external"><citerefentry><refentrytitle>minphys</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink>, but the
driver can define its own <function>xxminphys</function> routine instead.
The job of <function>xxminphys</function> is to keep the <structfield>b_bcount</structfield> field
of the <olink targetdoc="group-refman" targetptr="buf-9s" remap="external"><citerefentry><refentrytitle>buf</refentrytitle><manvolnum>9S</manvolnum></citerefentry></olink> structure
under a driver's limit. The driver should adhere to other system limits as
well. For example, the driver's <function>xxminphys</function> routine should
call the system <olink targetdoc="group-refman" targetptr="minphys-9f" remap="external"><citerefentry><refentrytitle>minphys</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> routine
after setting the <structfield>b_bcount</structfield> field and before returning.</para><example id="character-ex-17"><title><citerefentry><refentrytitle>minphys</refentrytitle><manvolnum>9F</manvolnum></citerefentry> Routine</title><programlisting>#define XXMINVAL (512 &lt;&lt; 10)    /* 512 KB */
static void
xxminphys(struct buf *bp)
{
    if (bp-&gt;b_bcount &gt; XXMINVAL)
        bp-&gt;b_bcount = XXMINVAL
    minphys(bp);
}</programlisting>
</example>
</sect3><sect3 id="character-64481"><title><function>strategy</function> Entry Point</title><para><indexterm id="character-ix395f"><primary>character device driver</primary><secondary><function>strategy</function> entry point</secondary></indexterm><indexterm id="character-ix397d"><primary><function>strategy</function> entry point</primary><secondary>character drivers</secondary></indexterm>The  <olink targetdoc="group-refman" targetptr="strategy-9e" remap="external"><citerefentry><refentrytitle>strategy</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> routine originated
in block drivers. The strategy function got its name from implementing a strategy
for efficient queuing of I/O requests to a block device. A driver for a character-oriented
device can also use a <literal>strategy(9E)</literal> routine. In the character
I/O model presented here,  <olink targetdoc="group-refman" targetptr="strategy-9e" remap="external"><citerefentry><refentrytitle>strategy</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> does not maintain a queue
of requests, but rather services one request at a time.</para><para>In the following example, the <olink targetdoc="group-refman" targetptr="strategy-9e" remap="external"><citerefentry><refentrytitle>strategy</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> routine for a character-oriented
DMA device allocates DMA resources for synchronous data transfer. <function>strategy</function> starts the command by programming the device register. See <olink targetptr="dma-29901" remap="internal">Chapter&nbsp;9, Direct Memory Access (DMA)</olink> for
a detailed description.</para><note><para><olink targetdoc="group-refman" targetptr="strategy-9e" remap="external"><citerefentry><refentrytitle>strategy</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> does
not receive a device number (<literal>dev_t</literal>) as a parameter. Instead,
the device number is retrieved from the <structfield>b_edev</structfield> field
of the <olink targetdoc="group-refman" targetptr="buf-9s" remap="external"><citerefentry><refentrytitle>buf</refentrytitle><manvolnum>9S</manvolnum></citerefentry></olink> structure
passed to <olink targetdoc="group-refman" targetptr="strategy-9e" remap="external"><citerefentry><refentrytitle>strategy</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink>.</para>
</note><example id="character-35679"><title><citerefentry><refentrytitle>strategy</refentrytitle><manvolnum>9E</manvolnum></citerefentry> Routine</title><programlisting>static int
xxstrategy(struct buf *bp)
{
     minor_t            instance;
     struct xxstate     *xsp;
     ddi_dma_cookie_t   cookie;

     instance = getminor(bp-&gt;b_edev);
     xsp = ddi_get_soft_state(statep, instance);
     /* ... */
      * If the device has power manageable components,
      * mark the device busy with pm_busy_components(9F),
      * and then ensure that the device is
      * powered up by calling pm_raise_power(9F).
      */
     /* Set up DMA resources with ddi_dma_alloc_handle(9F) and
      * ddi_dma_buf_bind_handle(9F).
      */
     xsp-&gt;bp = bp; /* remember bp */
     /* Program DMA engine and start command */
     return (0);
}</programlisting>
</example><note><para>Although <function>strategy</function> is declared to return an <literal>int</literal>, <function>strategy</function> must always return zero.</para>
</note><para>On completion of the DMA transfer, the device generates an interrupt,
causing the interrupt routine to be called. In the following example, <function>xxintr</function> receives a pointer to the state structure for the device that
might have generated the interrupt.</para><example id="character-28538"><title>Interrupt Routine</title><programlisting>static u_int
xxintr(caddr_t arg)
{
     struct xxstate *xsp = (struct xxstate *)arg;
     if ( /* device did not interrupt */ ) {
        return (DDI_INTR_UNCLAIMED);
     }
     if ( /* error */ ) {
        /* error handling */
     }
     /* Release any resources used in the transfer, such as DMA resources.
      * ddi_dma_unbind_handle(9F) and ddi_dma_free_handle(9F)
      * Notify threads that the transfer is complete.
      */
     biodone(xsp-&gt;bp);
     return (DDI_INTR_CLAIMED);
}</programlisting>
</example><para>The driver indicates an error by calling <olink targetdoc="group-refman" targetptr="bioerror-9f" remap="external"><citerefentry><refentrytitle>bioerror</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink>. The driver must call  <olink targetdoc="group-refman" targetptr="biodone-9f" remap="external"><citerefentry><refentrytitle>biodone</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> when the
transfer is complete or after indicating an error with  <olink targetdoc="group-refman" targetptr="bioerror-9f" remap="external"><citerefentry><refentrytitle>bioerror</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink>.</para>
</sect3>
</sect2>
</sect1><sect1 id="character-16543"><title>Mapping Device Memory</title><para><indexterm id="gedul"><primary>character device driver</primary><secondary>memory mapping</secondary></indexterm><indexterm id="gedth"><primary>memory mapping</primary><secondary>device memory management</secondary></indexterm>Some
devices, such as frame buffers, have memory that is directly accessible to
user threads by way of memory mapping. Drivers for these devices typically
do not support the <olink targetdoc="group-refman" targetptr="read-9e" remap="external"><citerefentry><refentrytitle>read</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> and <olink targetdoc="group-refman" targetptr="write-9e" remap="external"><citerefentry><refentrytitle>write</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> interfaces. Instead, these
drivers support memory mapping with the <olink targetdoc="group-refman" targetptr="devmap-9e" remap="external"><citerefentry><refentrytitle>devmap</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> entry point. For example,
a frame buffer driver might implement the <citerefentry><refentrytitle>devmap</refentrytitle><manvolnum>9E</manvolnum></citerefentry> entry point to enable the frame buffer
to be mapped in a user thread.</para><para>The <citerefentry><refentrytitle>devmap</refentrytitle><manvolnum>9E</manvolnum></citerefentry> entry point is called to export device memory or kernel memory
to user applications. The <function>devmap</function> function is called from <olink targetdoc="group-refman" targetptr="devmap-setup-9f" remap="external"><citerefentry><refentrytitle>devmap_setup</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> inside <citerefentry><refentrytitle>segmap</refentrytitle><manvolnum>9E</manvolnum></citerefentry> or on behalf of <olink targetdoc="group-refman" targetptr="ddi-devmap-segmap-9f" remap="external"><citerefentry><refentrytitle>ddi_devmap_segmap</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink>.</para><para><indexterm id="character-ix406"><primary><function>segmap</function> entry point</primary><secondary>description of</secondary></indexterm>The <olink targetdoc="group-refman" targetptr="segmap-9e" remap="external"><citerefentry><refentrytitle>segmap</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> entry point
is responsible for setting up a memory mapping requested by an <olink targetdoc="group-refman" targetptr="mmap-2" remap="external"><citerefentry><refentrytitle>mmap</refentrytitle><manvolnum>2</manvolnum></citerefentry></olink> system call. Drivers for many
memory-mapped devices use <olink targetdoc="group-refman" targetptr="ddi-devmap-segmap-9f" remap="external"><citerefentry><refentrytitle>ddi_devmap_segmap</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> as the entry point rather
than defining their own <citerefentry><refentrytitle>segmap</refentrytitle><manvolnum>9E</manvolnum></citerefentry> routine.</para><para>See <olink targetptr="devmap-24338" remap="internal">Chapter&nbsp;10, Mapping Device
and Kernel Memory</olink> and <olink targetptr="devcnmgt-19679" remap="internal">Chapter&nbsp;11,
Device Context Management</olink> for details.</para>
</sect1><sect1 id="character-11313"><title>Multiplexing I/O on File Descriptors</title><para><indexterm id="character-ix407"><primary>I/O</primary><secondary>multiplexing</secondary></indexterm><indexterm><primary>multiplexing I/O</primary></indexterm>A thread sometimes needs to handle I/O on more than one file descriptor.
One example is an application program that needs to read the temperature from
a temperature-sensing device and then report the temperature to an interactive
display.  A program that makes a read request with no data available should
not block while waiting for the temperature before interacting with the user
again.</para><para><indexterm id="character-ix408"><primary>device polling</primary><secondary><function>poll</function> function</secondary></indexterm>The <olink targetdoc="group-refman" targetptr="poll-2" remap="external"><citerefentry><refentrytitle>poll</refentrytitle><manvolnum>2</manvolnum></citerefentry></olink> system call provides users
with a mechanism for multiplexing I/O over a set of file descriptors that
reference open files.  <olink targetdoc="group-refman" targetptr="poll-2" remap="external"><citerefentry><refentrytitle>poll</refentrytitle><manvolnum>2</manvolnum></citerefentry></olink> identifies
those file descriptors on which a program can send or receive data without
blocking, or on which certain events have occurred.</para><para><indexterm id="character-ix409"><primary>character device driver</primary><secondary>device polling</secondary></indexterm><indexterm id="character-ix410"><primary>device polling</primary><secondary><function>chpoll</function> function</secondary></indexterm><indexterm id="character-ix411"><primary>device polling</primary><secondary sortas="character">in character drivers</secondary></indexterm>To
enable a program to poll a character driver, the driver must implement the <olink targetdoc="group-refman" targetptr="chpoll-9e" remap="external"><citerefentry><refentrytitle>chpoll</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> entry point.
The system calls <citerefentry><refentrytitle>chpoll</refentrytitle><manvolnum>9E</manvolnum></citerefentry> when a user process issues a <olink targetdoc="group-refman" targetptr="poll-2" remap="external"><citerefentry><refentrytitle>poll</refentrytitle><manvolnum>2</manvolnum></citerefentry></olink> system call on a file descriptor
associated with the device. The <citerefentry><refentrytitle>chpoll</refentrytitle><manvolnum>9E</manvolnum></citerefentry> entry point routine is used by non-STREAMS
character device drivers that need to support polling.</para><para>The <olink targetdoc="group-refman" targetptr="chpoll-9e" remap="external"><citerefentry><refentrytitle>chpoll</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> function
uses the following syntax:</para><programlisting>int xxchpoll(dev_t <replaceable>dev</replaceable>, short <replaceable>events</replaceable>, int <replaceable>anyyet</replaceable>, short *<replaceable>reventsp</replaceable>,
     struct <replaceable>pollhead</replaceable> **<replaceable>phpp</replaceable>);</programlisting><para>In the <citerefentry><refentrytitle>chpoll</refentrytitle><manvolnum>9E</manvolnum></citerefentry> entry point, the driver must follow these rules:</para><itemizedlist><listitem><para>Implement the following algorithm when the <citerefentry><refentrytitle>chpoll</refentrytitle><manvolnum>9E</manvolnum></citerefentry> entry
point is called:</para><programlisting>if ( /* events are satisfied now */ ) {
    *reventsp = <replaceable>mask_of_satisfied_events</replaceable>
} else {
    *reventsp = 0;
    if (!anyyet)
        *phpp = &amp;<replaceable>local_pollhead_structure</replaceable>;
}
return (0);</programlisting><para>See the <olink targetdoc="group-refman" targetptr="chpoll-9e" remap="external"><citerefentry><refentrytitle>chpoll</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> man
page for a discussion of events to check. The <citerefentry><refentrytitle>chpoll</refentrytitle><manvolnum>9E</manvolnum></citerefentry> entry point should
then return the mask of satisfied events by setting the return events in <replaceable>*reventsp</replaceable>.</para><para>If no events have occurred, the return field for the events is cleared.
If the <replaceable>anyyet</replaceable> field is not set, the driver must
return an instance of the <structname>pollhead</structname> structure. The <structname>pollhead</structname> structure is usually allocated in a state structure.
The <structname>pollhead</structname> structure should be treated as opaque
by the driver. None of the <structname>pollhead</structname> fields should
be referenced.</para>
</listitem><listitem><para>Call <olink targetdoc="group-refman" targetptr="pollwakeup-9f" remap="external"><citerefentry><refentrytitle>pollwakeup</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> whenever a device condition of type <structfield>events</structfield>,
listed in <olink targetptr="character-25342" remap="internal">Example&nbsp;15&ndash;10</olink>,
occurs. This function should be called only with one event at a time. You
can call <citerefentry><refentrytitle>pollwakeup</refentrytitle><manvolnum>9F</manvolnum></citerefentry> in the interrupt routine when the condition has occurred.</para>
</listitem>
</itemizedlist><para><olink targetptr="character-25342" remap="internal">Example&nbsp;15&ndash;10</olink> and <olink targetptr="character-38661" remap="internal">Example&nbsp;15&ndash;11</olink> show how to implement
the polling discipline and how to use <citerefentry><refentrytitle>pollwakeup</refentrytitle><manvolnum>9F</manvolnum></citerefentry>.</para><para>The following example shows how to handle the <literal>POLLIN</literal> and <literal>POLLERR</literal> events. The driver first reads the status register to determine
the current state of the device. The parameter <structfield>events</structfield> specifies
which conditions the driver should check. If an appropriate condition has
occurred, the driver sets that bit in <replaceable>*reventsp</replaceable>.
If none of the conditions has occurred and if <replaceable>anyyet</replaceable> is
not set, the address of the <structname>pollhead</structname> structure is
returned in <replaceable>*phpp</replaceable>.</para><example id="character-25342"><title><citerefentry><refentrytitle>chpoll</refentrytitle><manvolnum>9E</manvolnum></citerefentry> Routine</title><programlisting>static int
xxchpoll(dev_t dev, short events, int anyyet,
    short *reventsp, struct pollhead **phpp)
{
     uint8_t status;
     short revent;
     struct xxstate *xsp;

     xsp = ddi_get_soft_state(statep, getminor(dev));
     if (xsp == NULL)
         return (ENXIO);
     revent = 0;
     /*
      * Valid events are:
      * POLLIN | POLLOUT | POLLPRI | POLLHUP | POLLERR
      * This example checks only for POLLIN and POLLERR.
      */
     status = ddi_get8(xsp-&gt;data_access_handle, &amp;xsp-&gt;regp-&gt;csr);
     if ((events &amp; POLLIN) &amp;&amp; <replaceable>data available to read</replaceable>) {
        revent |= POLLIN;
     }
     if (status &amp; DEVICE_ERROR) {
        revent |= POLLERR;
     }
     /* if nothing has occurred */
     if (revent == 0) {
        if (!anyyet) {
        *phpp = &amp;xsp-&gt;pollhead;
        }
     }
       *reventsp = revent;
     return (0);
}</programlisting>
</example><para>The following example shows how to use the <olink targetdoc="group-refman" targetptr="pollwakeup-9f" remap="external"><citerefentry><refentrytitle>pollwakeup</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> function. The <citerefentry><refentrytitle>pollwakeup</refentrytitle><manvolnum>9F</manvolnum></citerefentry> function usually is called in the interrupt routine when a
supported condition has occurred. The interrupt routine reads the status from
the status register and checks for the conditions. The routine then calls <citerefentry><refentrytitle>pollwakeup</refentrytitle><manvolnum>9F</manvolnum></citerefentry> for each event to possibly notify polling threads that they
should check again. Note that <citerefentry><refentrytitle>pollwakeup</refentrytitle><manvolnum>9F</manvolnum></citerefentry> should not be called with any locks
held, since deadlock could result if another routine tried to enter <olink targetdoc="group-refman" targetptr="chpoll-9e" remap="external"><citerefentry><refentrytitle>chpoll</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> and grab
the same lock.</para><example id="character-38661"><title>Interrupt Routine Supporting <citerefentry><refentrytitle>chpoll</refentrytitle><manvolnum>9E</manvolnum></citerefentry></title><programlisting>static u_int
xxintr(caddr_t arg)
{
     struct xxstate *xsp = (struct xxstate *)arg;
     uint8_t    status;
     /* normal interrupt processing */
     /* ... */
     status = ddi_get8(xsp-&gt;data_access_handle, &amp;xsp-&gt;regp-&gt;csr);
     if (status &amp; DEVICE_ERROR) {
        pollwakeup(&amp;xsp-&gt;pollhead, POLLERR);
     }
     if ( /* just completed a read */ ) {
        pollwakeup(&amp;xsp-&gt;pollhead, POLLIN);
     }
     /* ... */
     return (DDI_INTR_CLAIMED);
}</programlisting>
</example>
</sect1><sect1 id="character-23939"><title>Miscellaneous I/O Control</title><indexterm id="character-ix412"><primary>I/O</primary><secondary>miscellaneous control of</secondary>
</indexterm><para><indexterm id="character-ix413"><primary>character device driver</primary><secondary>I/O control mechanism</secondary></indexterm><indexterm id="character-ix414"><primary>entry points</primary><secondary><function>ioctl</function> function</secondary></indexterm>The <olink targetdoc="group-refman" targetptr="ioctl-9e" remap="external"><citerefentry><refentrytitle>ioctl</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> routine
is called when a user thread issues an <olink targetdoc="group-refman" targetptr="ioctl-2" remap="external"><citerefentry><refentrytitle>ioctl</refentrytitle><manvolnum>2</manvolnum></citerefentry></olink> system call on a file descriptor
associated with the device. The I/O control mechanism is a catchall for getting
and setting device-specific parameters. This mechanism is frequently used
to set a device-specific mode, either by setting internal driver software
flags or by writing commands to the device. The control mechanism can also
be used to return information to the user about the current device state.
In short, the control mechanism can do whatever the application and driver
need to have done.</para><sect2 id="character-22"><title><function>ioctl</function> Entry Point (Character
Drivers)</title><indexterm id="character-ix415"><primary><function>ioctl</function> function</primary><secondary>character drivers</secondary>
</indexterm><programlisting>int xxioctl(dev_t <replaceable>dev</replaceable>, int <replaceable>cmd</replaceable>, intptr_t <replaceable>arg</replaceable>, int <replaceable>mode</replaceable>,
     cred_t *<replaceable>credp</replaceable>, int *<replaceable>rvalp</replaceable>);</programlisting><para>The <replaceable>cmd</replaceable> parameter indicates which command <olink targetdoc="group-refman" targetptr="ioctl-9e" remap="external"><citerefentry><refentrytitle>ioctl</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> should perform. By convention,
the driver with which an I/O control command is associated is indicated in
bits 8-15 of the command. Typically, the  ASCII code of a character represents
the driver. The driver-specific command in bits 0-7. The creation of some
I/O commands is illustrated in the following example:</para><programlisting>#define XXIOC            (`x' &lt;&lt; 8)   /* `x' is a character that represents device xx */
#define XX_GET_STATUS    (XXIOC | 1)  /* get status register */
#define XX_SET_CMD       (XXIOC | 2)  /* send command */</programlisting><para>The interpretation of <replaceable>arg</replaceable> depends on the
command. I/O control commands should be documented in the driver documentation
or a man page. The command should also be defined in a public header file,
so that applications can determine the name of the command, what the command
does, and what the command accepts or returns as <replaceable>arg</replaceable>.
Any data transfer of <replaceable>arg</replaceable> into or out of the driver
must be performed by the driver.</para><para>Certain classes of devices such as frame buffers or disks must support
standard sets of I/O control requests. These standard I/O control interfaces
are documented in the <citetitle>Solaris 8 Reference Manual Collection</citetitle>.
For example, <olink targetdoc="group-refman" targetptr="fbio-7i" remap="external"><citerefentry><refentrytitle>fbio</refentrytitle><manvolnum>7I</manvolnum></citerefentry></olink> documents
the I/O controls that frame buffers must support, and <olink targetdoc="group-refman" targetptr="dkio-7i" remap="external"><citerefentry><refentrytitle>dkio</refentrytitle><manvolnum>7I</manvolnum></citerefentry></olink> documents standard disk I/O
controls. See <olink targetptr="character-23939" remap="internal">Miscellaneous I/O Control</olink> for
more information on I/O controls.</para><para>Drivers must use <olink targetdoc="group-refman" targetptr="ddi-copyin-9f" remap="external"><citerefentry><refentrytitle>ddi_copyin</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> to transfer <replaceable>arg</replaceable> data from
the user-level application to the kernel level. Drivers must use  <olink targetdoc="group-refman" targetptr="ddi-copyout-9f" remap="external"><citerefentry><refentrytitle>ddi_copyout</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> to transfer data from the kernel to the user level.
 Failure to use <olink targetdoc="group-refman" targetptr="ddi-copyin-9f" remap="external"><citerefentry><refentrytitle>ddi_copyin</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> or <olink targetdoc="group-refman" targetptr="ddi-copyout-9f" remap="external"><citerefentry><refentrytitle>ddi_copyout</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> can result in panics under
two conditions. A panic occurs if the architecture separates the kernel and
user address spaces, or if the user address has been swapped out.</para><para><olink targetdoc="group-refman" targetptr="ioctl-9e" remap="external"><citerefentry><refentrytitle>ioctl</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> is
usually a switch statement with a case for each supported  <olink targetdoc="group-refman" targetptr="ioctl-9e" remap="external"><citerefentry><refentrytitle>ioctl</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> request.</para><example id="character-15130"><title><citerefentry><refentrytitle>ioctl</refentrytitle><manvolnum>9E</manvolnum></citerefentry> Routine</title><programlisting>static int
xxioctl(dev_t dev, int cmd, intptr_t arg, int mode,
    cred_t *credp, int *rvalp)
{
    uint8_t        csr;
    struct xxstate     *xsp;

    xsp = ddi_get_soft_state(statep, getminor(dev));
    if (xsp == NULL) {
        return (ENXIO);
    }
    switch (cmd) {
    case XX_GET_STATUS:
        csr = ddi_get8(xsp-&gt;data_access_handle, &amp;xsp-&gt;regp-&gt;csr);
        if (ddi_copyout(&amp;csr, (void *)arg, sizeof (uint8_t), mode) != 0) {
            return (EFAULT);
        }
        break;
    case XX_SET_CMD:
        if (ddi_copyin((void *)arg, &amp;csr, sizeof (uint8_t), mode) != 0) {
            return (EFAULT);
        }
        ddi_put8(xsp-&gt;data_access_handle, &amp;xsp-&gt;regp-&gt;csr, csr);
        break;
    default:
        /* generic "ioctl unknown" error */
        return (ENOTTY);
    }
    return (0);
}</programlisting>
</example><para>The <replaceable>cmd</replaceable> variable identifies a specific device
control operation. A problem can occur if <replaceable>arg</replaceable> contains
a user virtual address. <olink targetdoc="group-refman" targetptr="ioctl-9e" remap="external"><citerefentry><refentrytitle>ioctl</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> must
call <olink targetdoc="group-refman" targetptr="ddi-copyin-9f" remap="external"><citerefentry><refentrytitle>ddi_copyin</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> or <olink targetdoc="group-refman" targetptr="ddi-copyout-9f" remap="external"><citerefentry><refentrytitle>ddi_copyout</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> to transfer data between
the data structure in the application program pointed to by <replaceable>arg</replaceable> and
the driver. In <olink targetptr="character-15130" remap="internal">Example&nbsp;15&ndash;12</olink>,
for the case of an <literal>XX_GET_STATUS</literal> request, the contents
of <replaceable>xsp-&gt;regp-&gt;csr</replaceable> are copied to the address in <replaceable>arg</replaceable>.  <olink targetdoc="group-refman" targetptr="ioctl-9e" remap="external"><citerefentry><refentrytitle>ioctl</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> can
store in <replaceable>*rvalp</replaceable> any integer value as the return
value to the <olink targetdoc="group-refman" targetptr="ioctl-2" remap="external"><citerefentry><refentrytitle>ioctl</refentrytitle><manvolnum>2</manvolnum></citerefentry></olink> system
call that makes a successful request. Negative return values, such as -1,
should be avoided. Many application programs assume that negative values indicate
failure.</para><para>The following example demonstrates an application that uses the I/O
controls discussed in the previous paragraph.</para><example id="character-20506"><title>Using <citerefentry><refentrytitle>ioctl</refentrytitle><manvolnum>9E</manvolnum></citerefentry></title><programlisting>#include &lt;sys/types.h&gt;
#include "xxio.h"     /* contains device's ioctl cmds and args */
int
main(void)
{
     uint8_t    status;
     /* ... */
     /*
      * read the device status
      */
     if (ioctl(fd, XX_GET_STATUS, &amp;status) == -1) {
         /* error handling */
     }
     printf("device status %x\n", status);
     exit(0);
}</programlisting>
</example>
</sect2><sect2 id="character-24565"><title>I/O Control Support for 64-Bit Capable
Device Drivers</title><para><indexterm id="character-ix416"><primary>device drivers</primary><secondary>64-bit drivers</secondary></indexterm><indexterm><primary>64-bit device drivers</primary></indexterm>The Solaris kernel runs in 64-bit mode
on suitable hardware, supporting both 32-bit applications and 64-bit applications.
A 64-bit device driver is required to support I/O control commands from programs
of both sizes. The difference between a 32-bit program and a 64-bit program
is the C language type model. A 32-bit program is ILP32, and a 64-bit program
is LP64. See <olink targetptr="lp64-35004" remap="internal">Appendix&nbsp;C, Making a Device
Driver 64-Bit Ready</olink> for information on C data type models.</para><para>If data that flows between programs and the kernel is not identical
in format, the driver must be able to handle the model mismatch. Handling
a model mismatch requires making appropriate adjustments to the data.</para><para>To determine whether a model mismatch exists, the  <olink targetdoc="group-refman" targetptr="ioctl-9e" remap="external"><citerefentry><refentrytitle>ioctl</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> mode parameter passes the
data model bits to the driver. As <olink targetptr="character-38299" remap="internal">Example&nbsp;15&ndash;14</olink> shows, the mode parameter is then passed to <olink targetdoc="group-refman" targetptr="ddi-model-convert-from-9f" remap="external"><citerefentry><refentrytitle>ddi_model_convert_from</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> to determine whether any model conversion is necessary. </para><para>A flag subfield of the mode argument is used to pass the data model
to the <olink targetdoc="group-refman" targetptr="ioctl-9e" remap="external"><citerefentry><refentrytitle>ioctl</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink> routine.
The flag is set to one of the following:</para><itemizedlist><listitem><para><literal>DATAMODEL_ILP32</literal></para>
</listitem><listitem><para><literal>DATAMODEL_LP64</literal></para>
</listitem>
</itemizedlist><para><literal>FNATIVE</literal> is conditionally defined to match the data
model of the kernel implementation. The <literal>FMODELS</literal> mask should
be used to extract the flag from the <parameter>mode</parameter> argument.
The driver can then examine the data model explicitly to determine how to
copy the application data structure.</para><para>The DDI function <olink targetdoc="group-refman" targetptr="ddi-model-convert-from-9f" remap="external"><citerefentry><refentrytitle>ddi_model_convert_from</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> is a convenience
routine that can assist some drivers with their <function>ioctl</function> calls.
The function takes the data type model of the user application as an argument
and returns one of the following values:</para><itemizedlist><listitem><para><literal>DDI_MODEL_ILP32</literal> &ndash; Convert from ILP32
application</para>
</listitem><listitem><para><literal>DDI_MODEL_NONE</literal> &ndash; No conversion needed</para>
</listitem>
</itemizedlist><para><literal>DDI_MODEL_NONE</literal> is returned if no data conversion
is necessary, as occurs when the application and driver have the same data
model. <literal>DDI_MODEL_ILP32</literal> is returned to a driver that is
compiled to the LP64 model and that communicates with a 32-bit application.</para><para>In the following example, the driver copies a data structure that contains
a user address. The data structure changes size from ILP32 to LP64. Accordingly,
the 64-bit driver uses a 32-bit version of the structure when communicating
with a 32-bit application.</para><example id="character-38299"><title><citerefentry><refentrytitle>ioctl</refentrytitle><manvolnum>9E</manvolnum></citerefentry> Routine to Support 32-bit Applications
and 64-bit Applications</title><programlisting>struct args32 {
    uint32_t    addr;    /* 32-bit address in LP64 */
    int     len;
}
struct args {
    caddr_t     addr;    /* 64-bit address in LP64 */
    int     len;
}

static int
xxioctl(dev_t dev, int cmd, intptr_t arg, int mode,
    cred_t *credp, int *rvalp)
{
    struct  xxstate  *xsp;
    struct  args     a;
    xsp = ddi_get_soft_state(statep, getminor(dev));
    if (xsp == NULL) {
        return (ENXIO);
    }
    switch (cmd) {
    case XX_COPYIN_DATA:
        switch(ddi_model_convert_from(mode)) {
        case DDI_MODEL_ILP32:
        {
            struct args32 a32;

            /* copy 32-bit args data shape */
            if (ddi_copyin((void *)arg, &amp;a32,
                sizeof (struct args32), mode) != 0) {
                return (EFAULT);
            }
            /* convert 32-bit to 64-bit args data shape */
            a.addr = a32.addr;
            a.len = a32.len;
            break;
        }
        case DDI_MODEL_NONE:
            /* application and driver have same data model. */
            if (ddi_copyin((void *)arg, &amp;a, sizeof (struct args),
                mode) != 0) {
                return (EFAULT);
            }
        }
        /* continue using data shape in native driver data model. */
        break;

    case XX_COPYOUT_DATA:
        /* copyout handling */
        break;
    default:
        /* generic "ioctl unknown" error */
        return (ENOTTY);
    }
    return (0);
}</programlisting>
</example>
</sect2><sect2 id="character-5"><title>Handling <function>copyout</function> Overflow</title><para>Sometimes a driver needs to copy out a native quantity that no longer
fits in the 32-bit sized structure. In this case, the driver should return <errorcode>EOVERFLOW</errorcode> to the caller. <errorcode>EOVERFLOW</errorcode> serves
as an indication that the data type in the interface is too small to hold
the value to be returned, as shown in the following example.</para><example id="character-ex-6"><title>Handling <citerefentry><refentrytitle>copyout</refentrytitle><manvolnum>9F</manvolnum></citerefentry> Overflow</title><programlisting>int
    xxioctl(dev_t dev, int cmd, intptr_t arg, int mode,
     cred_t *cr, int *rval_p)
    {
        struct resdata res;
        /* body of driver */
        switch (ddi_model_convert_from(mode &amp; FMODELS)) {
        case DDI_MODEL_ILP32: {
            struct resdata32 res32;

            if (res.size &gt; UINT_MAX)
                    return (EOVERFLOW);
            res32.size = (size32_t)res.size;
            res32.flag = res.flag;
            if (ddi_copyout(&amp;res32,
                (void *)arg, sizeof (res32), mode))
                    return (EFAULT);
        }
        break;

        case DDI_MODEL_NONE:
            if (ddi_copyout(&amp;res, (void *)arg, sizeof (res), mode))
                    return (EFAULT);
            break;
        }
        return (0);
    }</programlisting>
</example>
</sect2>
</sect1><sect1 id="character-17"><title>32-bit and 64-bit Data Structure Macros</title><para>The method in <olink targetptr="character-ex-6" remap="internal">Example&nbsp;15&ndash;15</olink> works
well for many drivers. An alternate scheme is to use the data structure macros
that are provided in <filename>&lt;sys/model.h&gt;</filename>to move data between
the application and the kernel. These macros make the code less cluttered
and behave identically, from a functional perspective.</para><example id="character-ex-8"><title>Using Data Structure Macros to Move Data</title><programlisting>int
    xxioctl(dev_t dev, int cmd, intptr_t arg, int mode,
        cred_t *cr, int *rval_p)
    {    
        STRUCT_DECL(opdata, op);

        if (cmd != OPONE)
            return (ENOTTY);

        STRUCT_INIT(op, mode);

        if (copyin((void *)arg,
            STRUCT_BUF(op), STRUCT_SIZE(op)))
                return (EFAULT);

        if (STRUCT_FGET(op, flag) != XXACTIVE ||     
            STRUCT_FGET(op, size) &gt; XXSIZE)
                return (EINVAL);
        xxdowork(device_state, STRUCT_FGET(op, size));
        return (0);
}</programlisting>
</example><sect2 id="character-29"><title>How Do the Structure Macros Work?</title><para>In a 64-bit device driver, structure macros enable the use of the same
piece of kernel memory by data structures of both sizes. The memory buffer
holds the contents of the native form of the data structure, that is, the
LP64 form, and the ILP32 form. Each structure access is implemented by a conditional
expression. When compiled as a 32-bit driver, only one data model, the native
form, is supported. No conditional expression is used.</para><para>The 64-bit versions of the macros depend on the definition of a shadow
version of the data structure. The shadow version describes the 32-bit interface
with fixed-width types. The name of the shadow data structure is formed by
appending &ldquo;32&rdquo; to the name of the native data structure. For convenience,
place the definition of the shadow structure in the same file as the native
structure to ease future maintenance costs.</para><para>The macros can take the following arguments:</para><variablelist><varlistentry><term><replaceable>structname</replaceable></term><listitem><para>The structure name of the native form of the data structure
as entered after the <literal>struct</literal> keyword.</para>
</listitem>
</varlistentry><varlistentry><term><replaceable>umodel</replaceable></term><listitem><para>A flag word that contains the user data model, such as <literal>FILP32</literal> or <literal>FLP64</literal>, extracted from the mode parameter
of <olink targetdoc="group-refman" targetptr="ioctl-9e" remap="external"><citerefentry><refentrytitle>ioctl</refentrytitle><manvolnum>9E</manvolnum></citerefentry></olink>.</para>
</listitem>
</varlistentry><varlistentry><term><replaceable>handle</replaceable></term><listitem><para>The name used to refer to a particular instance of a structure
that is manipulated by these macros.</para>
</listitem>
</varlistentry><varlistentry><term><replaceable>fieldname</replaceable></term><listitem><para>The name of the field within the structure.</para>
</listitem>
</varlistentry>
</variablelist>
</sect2><sect2 id="character-30"><title>When to Use Structure Macros</title><para>Macros enable you to make in-place references only to the fields of
a data item. Macros do not provide a way to take separate code paths that
are based on the data model. Macros should be avoided if the number of fields
in the data structure is large. Macros should also be avoided if the frequency
of references to these fields is high.</para><para>Macros hide many of the differences between data models in the implementation
of the macros. As a result, code written with this interface is generally
easier to read. When compiled as a 32-bit driver, the resulting code is compact
without needing clumsy <literal>#ifdefs</literal>, but still preserves type
checking.</para>
</sect2><sect2 id="character-41"><title>Declaring and Initializing Structure Handles</title><para><olink targetdoc="group-refman" targetptr="struct-decl-9f" remap="external"><citerefentry><refentrytitle>STRUCT_DECL</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> and <olink targetdoc="group-refman" targetptr="struct-init-9f" remap="external"><citerefentry><refentrytitle>STRUCT_INIT</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> can be used to declare and
initialize a handle and space for decoding an <literal>ioctl</literal> on
the stack. <olink targetdoc="group-refman" targetptr="struct-handle-9f" remap="external"><citerefentry><refentrytitle>STRUCT_HANDLE</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> and <olink targetdoc="group-refman" targetptr="struct-set-handle-9f" remap="external"><citerefentry><refentrytitle>STRUCT_SET_HANDLE</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> declare and initialize a
handle without allocating space on the stack. The latter macros can be useful
if the structure is very large, or is contained in some other data structure.</para><note><para>Because the <olink targetdoc="group-refman" targetptr="struct-decl-9f" remap="external"><citerefentry><refentrytitle>STRUCT_DECL</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> and <olink targetdoc="group-refman" targetptr="struct-handle-9f" remap="external"><citerefentry><refentrytitle>STRUCT_HANDLE</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink> macros expand to data structure declarations, these
macros should be grouped with such declarations in C code.</para>
</note><para>The macros for declaring and initializing structures are as follows:</para><variablelist termlength="wholeline"><varlistentry><term><literal>STRUCT_DECL(</literal><replaceable>structname</replaceable><literal>,</literal> <replaceable>handle</replaceable><literal>)</literal></term><listitem><para>Declares a <emphasis>structure handle</emphasis>that is called <literal>handle</literal> for a <replaceable>structname</replaceable> data structure. <structname>STRUCT_DECL</structname> allocates space for its native form on the stack.
The native form is assumed to be larger than or equal to the ILP32 form of
the structure.</para>
</listitem>
</varlistentry><varlistentry><term><literal>STRUCT_INIT(</literal><replaceable>handle</replaceable><literal>,</literal> <replaceable>umodel</replaceable><literal>)</literal></term><listitem><para>Initializes the data model for <replaceable>handle</replaceable> to <literal>umodel</literal>. This macro must be invoked before any access is made to
a structure handle declared with <olink targetdoc="group-refman" targetptr="struct-decl-9f" remap="external"><citerefentry><refentrytitle>STRUCT_DECL</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink>.</para>
</listitem>
</varlistentry><varlistentry><term><literal>STRUCT_HANDLE(</literal><replaceable>structname</replaceable><literal>,</literal> <replaceable>handle</replaceable><literal>)</literal></term><listitem><para>Declares a <emphasis>structure handle</emphasis> that is called <literal>handle</literal>. Contrast with <olink targetdoc="group-refman" targetptr="struct-decl-9f" remap="external"><citerefentry><refentrytitle>STRUCT_DECL</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink>.</para>
</listitem>
</varlistentry><varlistentry><term><literal>STRUCT_SET_HANDLE(</literal><replaceable>handle</replaceable><literal>,</literal> <replaceable>umodel</replaceable><literal>,</literal> <replaceable>addr</replaceable><literal>)</literal></term><listitem><para>Initializes the data model for <replaceable>handle</replaceable> to <replaceable>umodel</replaceable>, and sets <replaceable>addr</replaceable> as the buffer
used for subsequent manipulation. Invoke this macro before accessing a structure
handle declared with <olink targetdoc="group-refman" targetptr="struct-decl-9f" remap="external"><citerefentry><refentrytitle>STRUCT_DECL</refentrytitle><manvolnum>9F</manvolnum></citerefentry></olink>.</para>
</listitem>
</varlistentry>
</variablelist>
</sect2><sect2 id="character-42"><title>Operations on Structure Handles</title><para>The macros for performing operations on structures are as follows:</para><variablelist termlength="wholeline"><varlistentry><term><literal>size_t STRUCT_SIZE(</literal><replaceable>handle</replaceable><literal>)</literal></term><listitem><para>Returns the size of the structure referred to by <replaceable>handle</replaceable>, according to its embedded data model.</para>
</listitem>
</varlistentry><varlistentry><term><literal>typeof</literal> <replaceable>fieldname</replaceable> <literal>STRUCT_FGET(</literal><replaceable>handle</replaceable><literal>,</literal> <replaceable>fieldname</replaceable><literal>)</literal></term><listitem><para>Returns the indicated field in the data structure referred
to by <replaceable>handle</replaceable>. This field is a non-pointer type.</para>
</listitem>
</varlistentry><varlistentry><term><literal>typeof</literal> <replaceable>fieldname</replaceable> <literal>STRUCT_FGETP(</literal><replaceable>handle</replaceable><literal>,</literal> <replaceable>fieldname</replaceable><literal>)</literal></term><listitem><para>Returns the indicated field in the data structure referred
to by <replaceable>handle</replaceable>. This field is a pointer type.</para>
</listitem>
</varlistentry><varlistentry><term><literal>STRUCT_FSET(</literal><replaceable>handle</replaceable><literal>,</literal> <replaceable>fieldname</replaceable><literal>,</literal> <replaceable>val</replaceable><literal>)</literal></term><listitem><para>Sets the indicated field in the data structure referred to
by <replaceable>handle</replaceable> to value <replaceable>val</replaceable>.
The type of <replaceable>val</replaceable> should match the type of <replaceable>fieldname</replaceable>. The field is a non-pointer type.</para>
</listitem>
</varlistentry><varlistentry><term><literal>STRUCT_FSETP(</literal><replaceable>handle</replaceable><literal>,</literal> <replaceable>fieldname</replaceable><literal>,</literal> <replaceable>val</replaceable><literal>)</literal></term><listitem><para>Sets the indicated field in the data structure referred to
by <replaceable>handle</replaceable> to value <replaceable>val</replaceable>.
The field is a pointer type.</para>
</listitem>
</varlistentry><varlistentry><term><literal>typeof</literal> <replaceable>fieldname</replaceable> <literal>*STRUCT_FADDR(</literal><replaceable>handle</replaceable><literal>,</literal> <replaceable>fieldname</replaceable><literal>)</literal></term><listitem><para>Returns the address of the indicated field in the data structure
referred to by <replaceable>handle</replaceable>.</para>
</listitem>
</varlistentry><varlistentry><term><literal>struct structname *STRUCT_BUF(</literal><replaceable>handle</replaceable><literal>)</literal></term><listitem><para>Returns a pointer to the native structure described by <replaceable>handle</replaceable>.</para>
</listitem>
</varlistentry>
</variablelist>
</sect2><sect2 id="character-43"><title>Other Operations</title><para>Some miscellaneous structure macros follow:</para><variablelist termlength="wholeline"><varlistentry><term><literal>size_t SIZEOF_STRUCT(</literal><replaceable>struct_name</replaceable><literal>,</literal> <replaceable>datamodel</replaceable><literal>)</literal></term><listitem><para>Returns the size of <replaceable>struct_name</replaceable>,
which is  based on the given data model.</para>
</listitem>
</varlistentry><varlistentry><term><literal>size_t SIZEOF_PTR(</literal><replaceable>datamodel</replaceable><literal>)</literal></term><listitem><para>Returns the size of a pointer based on the given data model.</para>
</listitem>
</varlistentry>
</variablelist>
</sect2>
</sect1>
</chapter><?Pub *0000105262 0?>