Index: doc/ChangeLog
===================================================================
--- doc/ChangeLog	(revision 24df6ddfb44ae0010e2c018719a88575309069d0)
+++ doc/ChangeLog	(revision 47eab0ac2212e6a08c81318dcd013743c09a1547)
@@ -1,2 +1,10 @@
+2008-12-11	Sebastian Huber <sebastian.huber@embedded-brains.de>
+                Joel Sherrrill <joel.sherrill@oarcorp.com>
+
+	* bsp_howto/Makefile.am, bsp_howto/console.t: Sebastian improved
+	 documentation for termios device drivers.
+	* bsp_howto/TERMIOSFlow.eps, bsp_howto/TERMIOSFlow.png: New files.
+	Joel added Termios Flow figure from RTEMS Open Class material.
+
 2008-12-01	Joel Sherrill <joel.sherrill@OARcorp.com>
 
Index: doc/bsp_howto/Makefile.am
===================================================================
--- doc/bsp_howto/Makefile.am	(revision 24df6ddfb44ae0010e2c018719a88575309069d0)
+++ doc/bsp_howto/Makefile.am	(revision 47eab0ac2212e6a08c81318dcd013743c09a1547)
@@ -20,5 +20,6 @@
 COMMON_FILES += $(top_srcdir)/common/cpright.texi
 
-PNG_FILES = Developer-User-Timeline.png BSPInitFlowchart-49.png
+PNG_FILES = Developer-User-Timeline.png BSPInitFlowchart-49.png \
+    TERMIOSFlow.png
 
 if USE_HTML
Index: doc/bsp_howto/console.t
===================================================================
--- doc/bsp_howto/console.t	(revision 24df6ddfb44ae0010e2c018719a88575309069d0)
+++ doc/bsp_howto/console.t	(revision 47eab0ac2212e6a08c81318dcd013743c09a1547)
@@ -1,4 +1,4 @@
 @c
-@c  COPYRIGHT (c) 1988-2002.
+@c  COPYRIGHT (c) 1988-2008.
 @c  On-Line Applications Research Corporation (OAR).
 @c  All rights reserved.
@@ -37,7 +37,15 @@
 @section Termios
 
-Termios is a standard for terminal management, included in the POSIX 1003.1b
-standard.  It is commonly provided on UNIX implementations.  
-Having RTEMS support for Termios is beneficial:
+Termios is a standard for terminal management, included in the POSIX
+1003.1b standard.  As part of the POSIX and Open Group Single UNIX
+Specification, is commonly provided on UNIX implementations.  The
+Open Group has the termios portion of the POSIX standard online
+at @uref{http://opengroup.org/onlinepubs/007908775/xbd/termios.html
+,http://opengroup.org/onlinepubs/007908775/xbd/termios.html}. 
+The requirements for the @code{<termios.h>} file are also provided
+and are at @uref{http://opengroup.org/onlinepubs/007908775/xsh/termios.h.html,
+http://opengroup.org/onlinepubs/007908775/xsh/termios.h.html}.
+
+Having RTEMS support for Termios is beneficial because:
 
 @itemize @bullet
@@ -51,4 +59,8 @@
 Early RTEMS console device drivers also did their own special
 character processing.
+
+@item it is part of an internationally recognized standard.
+
+@item it makes porting code from other environments easier.
 
 @end itemize
@@ -119,7 +131,22 @@
 The following Figure shows how a Termios driven serial driver works: 
 
-@example
-Figure not included in this draft
-@end example
+@ifset use-ascii
+@center Figure not included in ASCII version
+@end ifset
+
+@ifset use-tex
+@sp1
+@center{@image{TERMIOSFlow,,6in}}
+@end ifset
+
+@ifset use-html
+@html
+<P ALIGN="center"><IMG SRC="TERMIOSFlow.png"
+     WIDTH=800 HEIGHT=610 ALT="Termios Flow"></P>
+@end html
+@end ifset
+
+The most significant five bits are the object class.  The next
+three bits indicate the API to which the object class belongs.
 
 The following list describes the basic flow.
@@ -130,7 +157,7 @@
 scanf, read, write, etc.),
 
-@item C library (in fact that's Cygnus Newlib) calls RTEMS 
-system call interface. This code can be found in the 
-@code{c/src/lib/libc} directory.
+@item C library (e.g. RedHat (formerly Cygnus) Newlib) calls
+the RTEMS system call interface.  This code can be found in the
+@code{cpukit/libcsupport/src} directory.
 
 @item Glue code calls the serial driver entry routines. 
@@ -138,106 +165,241 @@
 @end itemize
 
-@subsection Termios and Polled I/O
+@subsection Basics
+
+You need to include the following header files in your Termios device driver
+source file:
+@example
+@group
+#include <unistd.h>
+#include <termios.h>
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <rtems/console.h>
+@end group
+@end example
+
+You need to provide a data structure for the Termios driver interface.  The
+functions are described later in this chapter.  The functions should return
+zero on succes and minus one in case of an error.  Currently the return value
+will be not checked from the Termios infrastructure in most cases.  One notable
+exception is the polled read function, here is the return value important.
+
+If you want to use polled IO it should look like the following.  You may also
+have a look at @code{c/src/lib/libbsp/shared/console-polled.c} for a shared
+implementation of the basic framework.  Termios must be told the addresses of
+the functions that are to be used for simple character IO, i.e. pointers to the
+@code{my_driver_poll_read} and @code{my_driver_poll_write} functions described
+later in @ref{Console Driver Termios and Polled IO}.
+
+@example
+@group
+static const rtems_termios_callbacks my_driver_callbacks_polled = @{
+    .firstOpen = my_driver_first_open,
+    .lastClose = my_driver_last_close,
+    .pollRead = my_driver_poll_read,
+    .write = my_driver_poll_write,
+    .setAttributes = my_driver_set_attributes,
+    .stopRemoteTx = NULL,
+    .startRemoteTx = NULL,
+    .outputUsesInterrupts = TERMIOS_POLLED
+@};
+@end group
+@end example
+
+For an interrupt driven implementation you need the following.  The driver
+functioning is quite different in this mode.  There is no device driver read
+function to be passed to Termios.  Indeed a @code{console_read} call returns
+the contents of Termios input buffer.  This buffer is filled in the driver
+interrupt subroutine, see also
+@ref{Console Driver Termios and Interrupt Driven IO}.
+The driver is responsible for providing a pointer to the
+@code{my_driver_interrupt_write} function. 
+
+@example
+@group
+static const rtems_termios_callbacks my_driver_callbacks_interrupt = @{
+    .firstOpen = my_driver_first_open,
+    .lastClose = my_driver_last_close,
+    .pollRead = NULL,
+    .write = my_driver_interrupt_write,
+    .setAttributes = my_driver_set_attributes,
+    .stopRemoteTx = NULL,
+    .startRemoteTx = NULL,
+    .outputUsesInterrupts = TERMIOS_IRQ_DRIVEN
+@};
+@end group
+@end example
+
+You can also provide callback functions for remote transmission control.  This
+is not covered in this manual, so thay are set to @code{NULL} in the above
+examples.
+
+Normally the device specific data structures are stored in a table which is
+indexed by the minor number.  You may need an entry for the Termios handler
+pointer in your data structure.  For simplicity of the console initialization
+example the device name is also present.
+
+@example
+@group
+/* Driver specific data structure */
+typedef struct @{
+    const char *device_name;
+    struct rtems_termios_tty *tty;
+@} my_driver_entry;
+
+/*
+ * This table contains the driver specific data.  It is later
+ * indexed by the minor number.
+ */
+static my_driver_entry my_driver_table [MY_DRIVER_DEVICE_NUMBER];
+@end group
+@end example
+
+@subsection Termios and Polled IO
 
 The following functions are provided by the driver and invoked by
-Termios for simple character input/output.  The specific names of
-these routines are not important as Termios invokes them indirectly
-via function pointers.
-
-@subsubsection pollWrite
-
-The @code{pollWrite} routine is responsible for writing @code{len} characters
-from @code{buf} to the serial device specified by @code{minor}.
-
-@example
-@group
-int pollWrite (int minor, const char *buf, int len) 
-@{
-  for (i=0; i<len; i++) @{
-     put buf[i] into the UART channel minor
-     wait for the character to be transmitted
-     on the serial line
-  @}
-  return 0
-@}
-@end group
-@end example
-
-@subsubsection pollRead
-
-The @code{pollRead} routine is responsible for reading a single character
-from the serial device specified by @code{minor}.  If no character is
-available, then the routine should return -1.
-
-@example
-@group
-int pollRead(int minor)
-@{
-   read status of UART
-   if status indicates a character is available
-     return character
-   return -1
-@}
-@end group
-@end example
-
-@subsection Termios and Interrupt Driven I/O
-
-The UART generally generates interrupts when it is ready to accept or to
-emit a number of characters. In this mode, the interrupt subroutine is the
-core of the driver.
-
-@subsubsection InterruptHandler
-
-The @code{InterruptHandler} is responsible for processing asynchronous
-interrupts from the UART.  There may be multiple interrupt handlers for
-a single UART.  Some UARTs can generate a unique interrupt vector for
-each interrupt source such as a character has been received or the
+Termios for simple character IO.
+
+The @code{my_driver_poll_write} routine is responsible for writing @code{n}
+characters from @code{buf} to the serial device specified by @code{minor}.
+
+@example
+@group
+static int my_driver_poll_write(int minor, const char *buf, int n)
+@{
+    my_driver_entry *e = &my_driver_table [minor];
+    int i = 0;
+    
+    /*
+     * There is no need to check the minor number since it is derived
+     * from a file descriptor.  The upper layer takes care that it is
+     * in a valid range.
+     */
+    
+    /* Write */
+    for (i = 0; i < n; ++i) @{
+        my_driver_write_char(e, buf [i]);
+    @}
+    
+    return 0;
+@}
+@end group
+@end example
+
+The @code{my_driver_poll_read} routine is responsible for reading a single
+character from the serial device specified by @code{minor}.  If no character is
+available, then the routine should return minus one.
+
+@example
+@group
+static int my_driver_poll_read(int minor)
+@{
+    my_driver_entry *e = &my_driver_table [minor];
+    
+    /*
+     * There is no need to check the minor number since it is derived
+     * from a file descriptor.  The upper layer takes care that it is
+     * in a valid range.
+     */
+
+    /* Check if a character is available */
+    if (my_driver_can_read_char(e)) @{
+        /* Return the character */
+        return my_driver_read_char(e);
+    @} else @{
+        /* Return an error status */
+        return -1;
+    @}
+@}
+@end group
+@end example
+
+@subsection Termios and Interrupt Driven IO
+
+The UART generally generates interrupts when it is ready to accept or to emit a
+number of characters.  In this mode, the interrupt subroutine is the core of
+the driver.
+
+The @code{my_driver_interrupt_handler} is responsible for processing
+asynchronous interrupts from the UART.  There may be multiple interrupt
+handlers for a single UART.  Some UARTs can generate a unique interrupt vector
+for each interrupt source such as a character has been received or the
 transmitter is ready for another character.
 
-In the simplest case, the @code{InterruptHandler} will have to check 
-the status of the UART and determine what caused the interrupt.
-The following describes the operation of an @code{InterruptHandler} 
-which has to do this:
-
-@example
-@group
-rtems_isr InterruptHandler (rtems_vector_number v)
-@{
-  check whether there was an error
-
-  if some characters were received: 
-     Ask Termios to put them on his input buffer
-
-  if some characters have been transmitted
-        (i.e. the UART output buffer is empty)
-     Tell TERMIOS that the characters have been
-     transmitted. The TERMIOS routine will call
-     the InterruptWrite function with the number
-     of characters not transmitted yet if it is
-     not zero.
-@}
-@end group
-@end example
-
-@subsubsection InterruptWrite
-
-The @code{InterruptWrite} is responsible for telling the UART 
-that the @code{len} characters at @code{buf} are to be transmitted.
-
-@example
-static int InterruptWrite(int minor, const char *buf, int len)
-@{
-  tell the UART to transmit len characters from buf
-  return 0
-@}
-@end example
-
-The driver has to put the @i{n} first buf characters in the UART channel minor
-buffer (@i{n} is the UART channel size, @i{n}=1 on the MC68640). Generally, an
-interrupt is raised after these @i{n} characters being transmitted. So
-UART interrupts may have to be enabled after putting the characters in the
-UART. 
-
+In the simplest case, the @code{my_driver_interrupt_handler} will have to check
+the status of the UART and determine what caused the interrupt.  The following
+describes the operation of an @code{my_driver_interrupt_handler} which has to
+do this:
+
+@example
+@group
+static void my_driver_interrupt_handler(
+    rtems_vector_number vector,
+    void *arg
+)
+@{
+    my_driver_entry *e = (my_driver_entry *) arg;
+    char buf [N];
+    int n = 0;
+
+    /*
+     * Check if we have received something.  The function reads the
+     * received characters from the device and stores them in the
+     * buffer.  It returns the number of read characters.
+     */
+    n = my_driver_read_received_chars(e, buf, N);
+    if (n > 0) @{
+        /* Hand the data over to the Termios infrastructure */
+        rtems_termios_enqueue_raw_characters(e->tty, buf, n);
+    @}
+
+    /*
+     * Check if we have something transmitted.  The functions returns
+     * the number of transmitted characters since the last write to the
+     * device.
+     */
+    n = my_driver_transmitted_chars(e);
+    if (n > 0) @{
+        /*
+         * Notify Termios that we have transmitted some characters.  It
+         * will call now the interrupt write function if more characters
+         * are ready for transmission.
+         */
+        rtems_termios_dequeue_characters(e->tty, n);
+    @}
+@}
+@end group
+@end example
+
+The @code{my_driver_interrupt_write} function is responsible for telling the
+device that the @code{n} characters at @code{buf} are to be transmitted.  The
+return value may be arbitrary since it is not checked from Termios.
+
+@example
+@group
+static int my_driver_interrupt_write(int minor, const char *buf, int n)
+@{
+    my_driver_entry *e = &my_driver_table [minor];
+    
+    /*
+     * There is no need to check the minor number since it is derived
+     * from a file descriptor.  The upper layer takes care that it is
+     * in a valid range.
+     */
+
+    /*
+     * Tell the device to transmit some characters from buf (less than
+     * or equal to n).  If the device is finished it should raise an
+     * interrupt.  The interrupt handler will notify Termios that these
+     * characters have been transmitted and this may trigger this write
+     * function again.  You may have to store the number of outstanding
+     * characters in the device data structure.
+     */
+
+    return 0;
+@}
+@end group
+@end example
 
 @subsection Initialization
@@ -246,132 +408,270 @@
 process. 
 
-The @code{console_initialize} function has to: 
-
-@itemize @bullet
-
-@item initialize Termios support: call @code{rtems_termios_initialize()}.  If
-Termios has already been initialized by another device driver, then
-this call will have no effect.
-
-@item Initialize the UART: This procedure should
-be described in the UART manual.  This procedure @b{MUST} be
-followed precisely.  This procedure varies but 
-usually consists of: 
-
-@itemize @bullet
-@item reinitialize the UART channels
-
-@item set the channels configuration to the Termios default:
-9600 bauds, no parity, 1 stop bit, and 8 bits per character
-@end itemize
-
-@item If interrupt driven, register the console interrupt routine to RTEMS:
-
-@example
-rtems_interrupt_catch(
-    InterruptHandler, CONSOLE_VECTOR, &old_handler);
-@end example
-
-@item enable the UART channels.
-
-@item register the device name: in order to use the console (i.e. being
-able to do printf/scanf on stdin, stdout, and stderr), some device
-must be registered as "/dev/console":
-
-@example
-rtems_io_register_name ("dev/console", major, i);
-@end example
-
-@end itemize
+The @code{console_initialize} function may look like this:
+
+@example
+@group
+rtems_device_driver console_initialize(
+    rtems_device_major_number major,
+    rtems_device_minor_number minor,
+    void *arg
+)
+@{
+    rtems_status_code sc = RTEMS_SUCCESSFUL;
+    rtems_device_minor_number i = 0;
+
+    /*
+     * Initialize the Termios infrastructure.  If Termios has already
+     * been initialized by another device driver, then this call will
+     * have no effect.
+     */
+    rtems_termios_initialize();
+    
+    /* Initialize each device */
+    for (i = 0; i < MY_DRIVER_DEVICE_NUMBER; ++i) @{
+        my_driver_entry *e = &my_driver_table [i];
+
+        /*
+         * Register this device in the file system.  In order to use the
+         * console (i.e. being able to do printf, scanf etc. on stdin,
+         * stdout and stderr), some device must be registered
+         * as "/dev/console" (CONSOLE_DEVICE_NAME).
+         */
+        sc = rtems_io_register_name (e->device_name, major, i);
+        RTEMS_CHECK_SC(sc, "Register IO device");
+
+        /*
+         * Initialize this device and install the interrupt handler if
+         * necessary.  You may also initialize the device in the first
+         * open call.
+         */
+    @}
+
+    return RTEMS_SUCCESSFUL;
+@}
+@end group
+@end example
 
 @subsection Opening a serial device
 
-The @code{console_open} function is called whenever a serial
-device is opened.  The device registered as @code{"/dev/console"}
-is opened automatically during RTEMS initialization.
-For instance, if UART channel 2 is registered as "/dev/tty1",
-the @code{console_open} entry point will be called as
-the result of an @code{fopen("/dev/tty1", mode)} in the
+The @code{console_open} function is called whenever a serial device is opened.
+The device registered as @code{"/dev/console"} (@code{CONSOLE_DEVICE_NAME}) is
+opened automatically during RTEMS initialization.  For instance, if UART
+channel 2 is registered as "/dev/tty1", the @code{console_open} entry point
+will be called as the result of an @code{fopen("/dev/tty1", mode)} in the
 application. 
 
 The @code{console_open} function has to inform Termios of the low-level
-functions for serial line support; the "callbacks". 
-
-The gen68340 BSP defines two sets of callback tables: 
-
-@itemize @bullet
-
-@item one with functions for polled input/output
-
-@item another with functions for interrupt driven input/output 
-
-@end itemize
-
-This code can be found in the file @code{$BSPROOT/console/console.c}.
-
-@subsubsection Polled I/O
-
-Termios must be told the addresses of the functions that are to be 
-used for simple character input/output, i.e. pointers to the
-@code{pollWrite} and @code{pollRead} functions
-defined earlier in @ref{Console Driver Termios and Polled I/O}.
-
-@subsubsection Interrupt Driven I/O
-
-Driver functioning is quite different in this mode.  There is no
-device driver read function to be passed to Termios. Indeed a
-@code{console_read} call returns the contents of Termios input buffer.
-This buffer is filled in the driver interrupt subroutine
-(see @ref{Console Driver Termios and Interrupt Driven I/O}).
-
-The driver is responsible for providing a pointer to the 
-@code{InterruptWrite} function. 
+functions for serial line support. 
+
+@example
+@group
+rtems_device_driver console_open(
+    rtems_device_major_number major,
+    rtems_device_minor_number minor,
+    void *arg
+)
+@{
+    struct rtems_termios_callbacks *callbacks =
+        &my_driver_callbacks_polled;
+
+    /*
+     * Check the minor number.  Termios does currently not check
+     * the return value of the first open call so the minor
+     * number must be checked here.
+     */
+    if (MY_DRIVER_IS_MINOR_INVALID(minor)) @{
+        return RTEMS_INVALID_NUMBER;
+    @}
+
+    /*
+     * Depending on the IO mode you need to pass a different set of
+     * callback functions to Termios.
+     */
+    if (MY_DRIVER_USES_INTERRUPTS(minor)) @{
+        callbacks = &my_driver_callbacks_interrupt;
+    @}
+
+    return rtems_termios_open(major, minor, arg, callbacks);
+@}
+@end group
+@end example
+
+During the first open of the device Termios will call @code{my_driver_first_open}.
+
+@example
+@group
+static int my_driver_first_open(int major, int minor, void *arg)
+@{
+    my_driver_entry *e = &my_driver_table [minor];
+    struct rtems_termios_tty *tty =
+        ((rtems_libio_open_close_args_t *) arg)->iop->data1;
+    
+    /* Check minor number */
+    if (MY_DRIVER_IS_MINOR_INVALID(minor)) @{
+        return -1;
+    @}
+
+    /* Connect the TTY data structure */
+    e->tty = tty;
+
+    /*
+     * You may add some initialization code here.
+     */
+
+    /*
+     * Sets the inital baud rate.  This should be set to the value of
+     * the boot loader.
+     */
+    return rtems_termios_set_initial_baud(e->tty, MY_DRIVER_BAUD_RATE);
+@}
+@end group
+@end example
 
 @subsection Closing a Serial Device
 
-The @code{console_close} is invoked when the serial device is to
-be closed.  This entry point corresponds to the device driver
-close entry point.
-
-This routine is responsible for notifying Termios that the serial
-device was closed.  This is done with a call to @code{rtems_termios_close}. 
-
-@subsection Reading Characters From a Serial Device
-
-The @code{console_read} is invoked when the serial device is to
-be read from.  This entry point corresponds to the device driver
-read entry point.
-
-This routine is responsible for returning the content of the
-Termios input buffer.   This is done by invoking the
-@code{rtems_termios_read} routine. 
+The @code{console_close} is invoked when the serial device is to be closed.
+This entry point corresponds to the device driver close entry point.
+
+This routine is responsible for notifying Termios that the serial device was
+closed.  This is done with a call to @code{rtems_termios_close}. 
+
+@example
+@group
+rtems_device_driver console_close(
+    rtems_device_major_number major,
+    rtems_device_minor_number minor,
+    void *arg
+)
+@{
+    return rtems_termios_close(arg);
+@}
+@end group
+@end example
+
+Termios will call the @code{my_driver_last_close} function if the last close
+happens on the device.
+@example
+@group
+static int my_driver_last_close(int major, int minor, void *arg)
+@{
+    my_driver_entry *e = &my_driver_table [minor];
+    
+    /*
+     * There is no need to check the minor number since it is derived
+     * from a file descriptor.  The upper layer takes care that it is
+     * in a valid range.
+     */
+
+    /* Disconnect the TTY data structure */
+    e->tty = NULL;
+
+    /*
+     * The driver may do some cleanup here.
+     */
+
+    return 0;
+@}
+@end group
+@end example
+
+@subsection Reading Characters from a Serial Device
+
+The @code{console_read} is invoked when the serial device is to be read from.
+This entry point corresponds to the device driver read entry point.
+
+This routine is responsible for returning the content of the Termios input
+buffer.  This is done by invoking the @code{rtems_termios_read} routine. 
+
+@example
+@group
+rtems_device_driver console_read(
+    rtems_device_major_number major,
+    rtems_device_minor_number minor,
+    void *arg
+)
+@{
+    return rtems_termios_read(arg);
+@}
+@end group
+@end example
 
 @subsection Writing Characters to a Serial Device
 
-The @code{console_write} is invoked when the serial device is to
-be written to.  This entry point corresponds to the device driver
-write entry point.
-
-This routine is responsible for adding the requested characters to
-the Termios output queue for this device.  This is done by
-calling the routine @code{rtems_termios_write} 
-to add the characters at the end of the Termios output
-buffer. 
+The @code{console_write} is invoked when the serial device is to be written to.
+This entry point corresponds to the device driver write entry point.
+
+This routine is responsible for adding the requested characters to the Termios
+output queue for this device.  This is done by calling the routine
+@code{rtems_termios_write} to add the characters at the end of the Termios
+output buffer. 
+
+@example
+@group
+rtems_device_driver console_write(
+    rtems_device_major_number major,
+    rtems_device_minor_number minor,
+    void *arg
+)
+@{
+    return rtems_termios_write(arg);
+@}
+@end group
+@end example
 
 @subsection Changing Serial Line Parameters
 
-The @code{console_control} is invoked when the line parameters
-for a particular serial device are to be changed.
-This entry point corresponds to the device driver
-io_control entry point.
-
-The application write is able to control the serial line configuration
-with Termios calls (such as the @code{ioctl} command, see 
-the Termios documentation for
-more details). If the driver is to support dynamic configuration, then
-is must have the @code{console_control} piece of code. Refer to the gen68340
-BSP for an example of how it is done.  Basically @code{ioctl} 
-commands call @code{console_control} with the serial line
-configuration in a Termios defined data structure. The driver
-is responsible for reinitializing the UART with the correct settings. 
-
+The @code{console_control} is invoked when the line parameters for a particular
+serial device are to be changed.  This entry point corresponds to the device
+driver io_control entry point.
+
+The application writer is able to control the serial line configuration with
+Termios calls (such as the @code{ioctl} command, see the Termios documentation
+for more details).  If the driver is to support dynamic configuration, then it
+must have the @code{console_control} piece of code.  Basically @code{ioctl}
+commands call @code{console_control} with the serial line configuration in a
+Termios defined data structure.
+
+@example
+@group
+rtems_device_driver console_control(
+    rtems_device_major_number major,
+    rtems_device_minor_number minor,
+    void *arg
+)
+@{
+    return rtems_termios_ioctl(arg);
+@}
+@end group
+@end example
+
+The driver is responsible for reinitializing the device with the correct
+settings.  For this purpuse Termios calls the @code{my_driver_set_attributes}
+function.
+
+@example
+@group
+static int my_driver_set_attributes(
+    int minor,
+    const struct termios *t
+)
+@{
+    my_driver_entry *e = &my_driver_table [minor];
+    
+    /*
+     * There is no need to check the minor number since it is derived
+     * from a file descriptor.  The upper layer takes care that it is
+     * in a valid range.
+     */
+
+    /*
+     * Inspect the termios data structure and configure the device
+     * appropriately.  The driver should only be concerned with the
+     * parts of the structure that specify hardware setting for the
+     * communications channel such as baud, character size, etc.
+     */
+
+    return 0;
+@}
+@end group
+@end example
