[PATCH] doc: Update console driver documentation

Sebastian Huber sebastian.huber at embedded-brains.de
Fri Jul 11 11:29:53 UTC 2014


---
 doc/bsp_howto/console.t |  716 ++++++++++++++++++++++-------------------------
 1 files changed, 331 insertions(+), 385 deletions(-)

diff --git a/doc/bsp_howto/console.t b/doc/bsp_howto/console.t
index 555cf04..e35ca36 100644
--- a/doc/bsp_howto/console.t
+++ b/doc/bsp_howto/console.t
@@ -7,7 +7,7 @@
 
 @section Introduction
 
-This chapter describes the operation of a console driver using 
+This chapter describes the operation of a console driver using
 the RTEMS POSIX Termios support.  Traditionally RTEMS has referred
 to all serial device drivers as console device drivers.  A
 console driver can be used to do raw data processing in addition
@@ -16,20 +16,20 @@ of a console.
 
 The serial driver may be called as the consequence of a C Library
 call such as @code{printf} or @code{scanf} or directly via the
- at code{read} or @code{write} system calls. 
-There are two main functioning modes: 
+ at code{read} or @code{write} system calls.
+There are two main functioning modes:
 
 @itemize @bullet
 
 @item console: formatted input/output, with special characters (end of
 line, tabulations, etc.) recognition and processing,
 
- at item raw: permits raw data processing. 
+ at item raw: permits raw data processing.
 
 @end itemize
 
 One may think that two serial drivers are needed to handle these two types
-of data, but Termios permits having only one driver. 
+of data, but Termios permits having only one driver.
 
 @section Termios
 
@@ -38,7 +38,7 @@ Termios is a standard for terminal management, included in the POSIX
 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}. 
+,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}.
@@ -49,10 +49,10 @@ Having RTEMS support for Termios is beneficial because:
 
 @item from the user's side because it provides standard primitive operations
 to access the terminal and change configuration settings.  These operations
-are the same under UNIX and RTEMS. 
+are the same under UNIX and RTEMS.
 
 @item from the BSP developer's side because it frees the
-developer from dealing with buffer states and mutual exclusions on them. 
+developer from dealing with buffer states and mutual exclusions on them.
 Early RTEMS console device drivers also did their own special
 character processing.
 
@@ -62,14 +62,14 @@ character processing.
 
 @end itemize
 
-Termios support includes: 
+Termios support includes:
 
 @itemize @bullet
 
 @item raw and console handling,
 
 @item blocking or non-blocking characters receive, with or without
-Timeout. 
+Timeout.
 
 @end itemize
 
@@ -81,18 +81,19 @@ at
 
 @section Driver Functioning Modes
 
-There are generally two main functioning modes for an UART (Universal
-Asynchronous Receiver-Transmitter, i.e. the serial chip): 
+There are generally three main functioning modes for an UART (Universal
+Asynchronous Receiver-Transmitter, i.e. the serial chip):
 
 @itemize @bullet
 
 @item polled mode
 @item interrupt driven mode
+ at item task driven mode
 
 @end itemize
 
 In polled mode, the processor blocks on sending/receiving characters.
-This mode is not the most efficient way to utilize the UART. But 
+This mode is not the most efficient way to utilize the UART. But
 polled mode is usually necessary when one wants to print an
 error message in the event of a fatal error such as a fatal error
 in the BSP.  This is also the simplest mode to
@@ -120,12 +121,15 @@ one or more characters in the UART (the exact number depends on the UART)
 An interrupt will be raised when all the characters have been transmitted.
 The interrupt service routine has to send the characters
 remaining in the output buffer the same way.   When the transmitting side
-of the UART is idle, it is typically necessary to prime the transmitter 
+of the UART is idle, it is typically necessary to prime the transmitter
 before the first interrupt will occur.
 
+The task driven mode is similar to interrupt driven mode, but the actual data
+processing is done in dedicated tasks instead of interrupt routines.
+
 @section Serial Driver Functioning Overview
 
-The following Figure shows how a Termios driven serial driver works: 
+The following Figure shows how a Termios driven serial driver works:
 
 @ifset use-ascii
 @center Figure not included in ASCII version
@@ -149,167 +153,185 @@ The following list describes the basic flow.
 @item the application programmer uses standard C library call (printf,
 scanf, read, write, etc.),
 
- at item C library (e.g. RedHat (formerly Cygnus) Newlib) calls
+ at item C library (ctx.g. RedHat (formerly Cygnus) Newlib) calls
 the RTEMS system call interface.  This code can be found in the
- at code{cpukit/libcsupport/src} directory.
+ at file{cpukit/libcsupport/src} directory.
 
- at item Glue code calls the serial driver entry routines. 
+ at item Glue code calls the serial driver entry routines.
 
 @end itemize
 
 @subsection Basics
 
-You need to include the following header files in your Termios device driver
-source file:
+The low-level driver API changed between RTEMS 4.10 and RTEMS 4.11.  The legacy
+callback API is still supported, but its use is discouraged.  The following
+functions are deprecated:
+
+ at itemize @bullet
+
+ at item @code{rtems_termios_open()} - use @code{rtems_termios_device_open()} in
+combination with @code{rtems_termios_device_install()} instead.
+
+ at item @code{rtems_termios_close()} - use @code{rtems_termios_device_close()}
+instead.
+
+ at end itemize
+
+This manual describes the new API.  A new console driver should consist of
+three parts.
+
+ at enumerate
+
+ at item The basic console driver functions using the Termios support.  Add this
+the BSPs Makefile.am:
+
 @example
 @group
-#include <unistd.h>
-#include <termios.h>
-
-#include <rtems.h>
-#include <rtems/libio.h>
-#include <rtems/console.h>
+[...]
+libbsp_a_SOURCES += ../../shared/console-termios.c
+[...]
 @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.
+ at item A general serial module specific low-level driver providing the handler
+table for the Termios @code{rtems_termios_device_install()} function.  This
+low-level driver could be used for more than one BSP.
+
+ at item A BSP specific initialization routine @code{console_initialize()}, that
+calls @code{rtems_termios_device_install()} providing a low-level driver
+context for each installed device.
+
+ at end enumerate
 
-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
- at code{my_driver_poll_read} and @code{my_driver_poll_write} functions described
-later in @ref{Console Driver Termios and Polled IO}.
+You need to provide a device handler structure for the Termios device
+interface.  The functions are described later in this chapter.  The first open
+and set attributes handler return a boolean status to indicate success (true)
+or failure (false).  The polled read function returns an unsigned character in
+case one is available or minus one otherwise.
+
+If you want to use polled IO it should look like the following.  Termios must
+be told the addresses of the handler that are to be used for simple character
+IO, i.e. pointers to the @code{my_driver_poll_read()} and
+ at 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
-@};
+const rtems_termios_handler my_driver_handler_polled = @{
+  .first_open = my_driver_first_open,
+  .last_close = my_driver_last_close,
+  .poll_read = my_driver_poll_read,
+  .write = my_driver_poll_write,
+  .set_attributes = my_driver_set_attributes,
+  .stop_remote_tx = NULL,
+  .start_remote_tx = NULL,
+  .mode = 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
- at ref{Console Driver Termios and Interrupt Driven IO}.
-The driver is responsible for providing a pointer to the
- at code{my_driver_interrupt_write} function. 
+handler 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
+ at 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
+const rtems_termios_handler my_driver_handler_interrupt = @{
+  .first_open = my_driver_first_open,
+  .last_close = my_driver_last_close,
+  .poll_read = NULL,
+  .write = my_driver_interrupt_write,
+  .set_attributes = my_driver_set_attributes,
+  .stopRemoteTx = NULL,
+  .stop_remote_tx = NULL,
+  .start_remote_tx = NULL,
+  .mode = 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
+You can also provide hander for remote transmission control.  This
+is not covered in this manual, so they 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.
+The low-level driver should provide a data structure for its device context.
+The initialization routine must provide a context for each installed device via
+ at code{rtems_termios_device_install()}.  For simplicity of the console
+initialization example the device name is also present.  Her is an example header file.
 
 @example
 @group
-/* Driver specific data structure */
+#ifndef MY_DRIVER_H
+#define MY_DRIVER_H
+
+#include <rtems/termiostypes.h>
+
+#include <some-chip-header.h>
+
+/* Low-level driver specific data structure */
 typedef struct @{
-    const char *device_name;
-    struct rtems_termios_tty *tty;
-@} my_driver_entry;
+  const char *device_name;
+  volatile module_register_block *regs;
+  /* More stuff */
+@} my_driver_context;
+
+extern const rtems_termios_handler my_driver_handler_polled;
+
+extern const rtems_termios_handler my_driver_handler_interrupt;
 
-/*
- * 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];
+#endif /* MY_DRIVER_H */
 @end group
 @end example
 
 @subsection Termios and Polled IO
 
-The following functions are provided by the driver and invoked by
+The following handler are provided by the low-level driver and invoked by
 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}.
-
-On success, the number of bytes written is returned (zero indicates nothing
-was written).  On error, @code{-1} is returned.
-
-NOTE: Due to the current implementation of termios, any data passed into
-  the write function will be lost. 
+The @code{my_driver_poll_write()} routine is responsible for writing @code{n}
+characters from @code{buf} to the serial device specified by @code{tty}.
 
 @example
 @group
-static ssize_t my_driver_poll_write(int minor, const char *buf, size_t n)
+static void my_driver_poll_write(
+  rtems_termios_tty *tty,
+  const char        *buf,
+  size_t             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 n;
+  my_driver_context *ctx = rtems_termios_get_device_context(tty);
+  size_t i;
+
+  /* Write */
+  for (i = 0; i < n; ++i) @{
+    my_driver_write_char(ctx, buf[i]);
+  @}
 @}
 @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
+character from the serial device specified by @code{tty}.  If no character is
 available, then the routine should return minus one.
 
 @example
 @group
-static int my_driver_poll_read(int minor)
+static int my_driver_poll_read(rtems_termios_tty *tty)
 @{
-    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.
-     */
+  my_driver_context *ctx = rtems_termios_get_device_context(tty);
 
-    /* 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;
-    @}
+  /* Check if a character is available */
+  if (my_driver_can_read_char(ctx)) @{
+    /* Return the character */
+    return my_driver_read_char(ctx);
+  @} else @{
+    /* Return an error status */
+    return -1;
+  @}
 @}
 @end group
 @end example
@@ -320,13 +342,13 @@ 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
+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{my_driver_interrupt_handler} will have to check
+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:
@@ -334,361 +356,285 @@ do this:
 @example
 @group
 static void my_driver_interrupt_handler(
-    rtems_vector_number vector,
-    void *arg
+  rtems_vector_number  vector,
+  void                *arg
 )
 @{
-    my_driver_entry *e = (my_driver_entry *) arg;
-    char buf [N];
-    int n = 0;
+  rtems_termios_tty *tty = arg;
+  my_driver_context *ctx = rtems_termios_get_device_context(tty);
+  char buf[N];
+  size_t n;
 
-    /*
-     * 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 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(ctx, buf, N);
+  if (n > 0) @{
+    /* Hand the data over to the Termios infrastructure */
+    rtems_termios_enqueue_raw_characters(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(ctx);
+  if (n > 0) @{
     /*
-     * Check if we have something transmitted.  The functions returns
-     * the number of transmitted characters since the last write to the
-     * device.
+     * Notify Termios that we have transmitted some characters.  It
+     * will call now the interrupt write function if more characters
+     * are ready for transmission.
      */
-    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);
-    @}
+    rtems_termios_dequeue_characters(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.  It is
-guaranteed that @code{n} is greater than zero.  This routine is invoked either
-from task context with disabled interrupts to start a new transmission process
-with exactly one character in case of an idle output state or from the
+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.  It
+the value @code{n} is zero to indicate that no more characters are to send.
+The driver can disable the transmit interrupts now.  This routine is invoked
+either from task context with disabled interrupts to start a new transmission
+process with exactly one character in case of an idle output state or from the
 interrupt handler to refill the transmitter.  If the routine is invoked to
 start the transmit process the output state will become busy and Termios starts
 to fill the output buffer.  If the transmit interrupt arises before Termios was
 able to fill the transmit buffer you will end up with one interrupt per
 character.
 
-On error, the function should return @code{-1}. On success, it should return
- at code{0}, since it the interrupt handler will report the actual number of
-characters transmitted.
- 
 @example
 @group
-static ssize_t my_driver_interrupt_write(int minor, const char *buf, size_t n)
+static void my_driver_interrupt_write(
+  rtems_termios_tty *tty,
+  const char        *buf,
+  size_t             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.
-     */
+  my_driver_context *ctx = rtems_termios_get_device_context(tty);
 
-    /*
-     * Tell the device to transmit some characters from buf (less than
-     * or equal to n).  When 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.
-     */
-
-    /*
-     * Termios will set n to zero to indicate that the transmitter is
-     * now inactive.  The output buffer is empty in this case.  The
-     * driver may disable the transmit interrupts now.
-     */
+  /*
+   * Tell the device to transmit some characters from buf (less than
+   * or equal to n).  When 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;
+  /*
+   * Termios will set n to zero to indicate that the transmitter is
+   * now inactive.  The output buffer is empty in this case.  The
+   * driver may disable the transmit interrupts now.
+   */
 @}
 @end group
 @end example
 
 @subsection Initialization
 
-The driver initialization is called once during the RTEMS initialization
-process. 
+The BSP specific driver initialization is called once during the RTEMS
+initialization process.
 
-The @code{console_initialize} function may look like this:
+The @code{console_initialize()} function may look like this:
 
 @example
 @group
+#include <my-driver.h>
+#include <rtems/console.h>
+#include <bsp.h>
+#include <bsp/fatal.h>
+
+static my_driver_context driver_context_table[M] = @{ /* Some values */ @};
+
 rtems_device_driver console_initialize(
-    rtems_device_major_number major,
-    rtems_device_minor_number minor,
-    void *arg
+  rtems_device_major_number  major,
+  rtems_device_minor_number  minor,
+  void                      *arg
 )
 @{
-    rtems_status_code sc = RTEMS_SUCCESSFUL;
-    rtems_device_minor_number i = 0;
+  rtems_status_code sc;
+#ifdef SOME_BSP_USE_INTERRUPTS
+  const rtems_termios_handler *handler = &my_driver_handler_interrupt;
+#else
+  const rtems_termios_handler *handler = &my_driver_handler_polled;
+#endif
 
-    /*
-     * 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];
+  /*
+   * Initialize the Termios infrastructure.  If Termios has already
+   * been initialized by another device driver, then this call will
+   * have no effect.
+   */
+  rtems_termios_initialize();
 
-        /*
-         * 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 each device */
+  for (
+    minor = 0;
+    minor < RTEMS_ARRAY_SIZE(driver_context_table);
+    ++minor
+  ) @{
+    my_driver_context *ctx = &driver_context_table[minor];
 
-        /*
-         * Initialize this device and install the interrupt handler if
-         * necessary.  You may also initialize the device in the first
-         * open call.
-         */
+    /*
+     * Install this device in the file system and Termios.  In order
+     * to use the console (i.e. being able to do printf, scanf etc.
+     * on stdin, stdout and stderr), one device must be registered as
+     * "/dev/console" (CONSOLE_DEVICE_NAME).
+     */
+    sc = rtems_termios_device_install(
+      ctx->device_name,
+      major,
+      minor,
+      handler,
+      ctx
+    );
+    if (sc != RTEMS_SUCCESSFUL) @{
+      bsp_fatal(SOME_BSP_FATAL_CONSOLE_DEVICE_INSTALL);
     @}
+  @}
 
-    return RTEMS_SUCCESSFUL;
+  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"} (@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 provided by @file{console-termios.c} is
+called whenever a serial device is opened.  The device registered as
+ at code{"/dev/console"} (@code{CONSOLE_DEVICE_NAME}) is opened automatically
+during RTEMS initialization.  For instance, if UART channel 2 is registered as
+ at code{"/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. 
+During the first open of the device Termios will call the
+ at code{my_driver_first_open()} handler.
 
 @example
 @group
-rtems_device_driver console_open(
-    rtems_device_major_number major,
-    rtems_device_minor_number minor,
-    void *arg
+static bool my_driver_first_open(
+  rtems_termios_tty             *tty,
+  rtems_libio_open_close_args_t *args
 )
 @{
-    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;
-    @}
+  my_driver_context *ctx = rtems_termios_get_device_context(tty);
+  rtems_status_code sc;
+  bool ok;
 
-    return rtems_termios_open(major, minor, arg, callbacks);
-@}
- at end group
- at end example
+  /*
+   * You may add some initialization code here.
+   */
 
-During the first open of the device Termios will call @code{my_driver_first_open}.
+  /*
+   * Sets the initial baud rate.  This should be set to the value of
+   * the boot loader.  This function accepts only exact Termios baud
+   * values.
+   */
+  sc = rtems_termios_set_initial_baud(tty, MY_DRIVER_BAUD_RATE);
+  if (sc != RTEMS_SUCCESSFUL) @{
+    /* Not a valid Termios baud */
+  @}
 
- at example
- at 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;
-    @}
+  /*
+   * Alternatively you can set the best baud.
+   */
+  rtems_termios_set_best_baud(tty, MY_DRIVER_BAUD_RATE);
 
-    /* Connect the TTY data structure */
-    e->tty = tty;
+  /*
+   * To propagate the initial Termios attributes to the device use
+   * this.
+   */
+  ok = my_driver_set_attributes(tty, rtems_termios_get_termios(tty));
+  if (!ok) @{
+    /* This is bad */
+  @}
 
-    /*
-     * 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);
+  /*
+   * Return true to indicate a successful set attributes, and false
+   * otherwise.
+   */
+  return true;
 @}
 @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}. 
-
- at example
- at group
-rtems_device_driver console_close(
-    rtems_device_major_number major,
-    rtems_device_minor_number minor,
-    void *arg
-)
-@{
-    return rtems_termios_close(arg);
-@}
- at end group
- at end example
+The @code{console_close()} provided by @file{console-termios.c} is invoked when
+the serial device is to be closed.  This entry point corresponds to the device
+driver close entry point.
 
-Termios will call the @code{my_driver_last_close} function if the last close
+Termios will call the @code{my_driver_last_close()} handler if the last close
 happens on the device.
 @example
 @group
-static int my_driver_last_close(int major, int minor, void *arg)
+static void my_driver_last_close(
+  rtems_termios_tty             *tty,
+  rtems_libio_open_close_args_t *args
+)
 @{
-    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.
-     */
+  my_driver_context *ctx = rtems_termios_get_device_context(tty);
 
-    /* Disconnect the TTY data structure */
-    e->tty = NULL;
-
-    /*
-     * The driver may do some cleanup here.
-     */
-
-    return 0;
+  /*
+   * The driver may do some cleanup here.
+   */
 @}
 @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. 
-
- at example
- at group
-rtems_device_driver console_read(
-    rtems_device_major_number major,
-    rtems_device_minor_number minor,
-    void *arg
-)
-@{
-    return rtems_termios_read(arg);
-@}
- at end group
- at end example
+The @code{console_read()} provided by @file{console-termios.c} is invoked when
+the serial device is to be read from.  This entry point corresponds to the
+device driver read entry point.
 
 @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
- at code{rtems_termios_write} to add the characters at the end of the Termios
-output buffer. 
-
- at example
- at group
-rtems_device_driver console_write(
-    rtems_device_major_number major,
-    rtems_device_minor_number minor,
-    void *arg
-)
-@{
-    return rtems_termios_write(arg);
-@}
- at end group
- at end example
+The @code{console_write()} provided by @file{console-termios.c} is invoked when
+the serial device is to be written to.  This entry point corresponds to the
+device driver write entry point.
 
 @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 @code{console_control()} provided by @file{console-termios.c} 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.
-
- at example
- at group
-rtems_device_driver console_control(
-    rtems_device_major_number major,
-    rtems_device_minor_number minor,
-    void *arg
-)
-@{
-    return rtems_termios_ioctl(arg);
-@}
- at end group
- at end example
+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.
 
 The driver is responsible for reinitializing the device with the correct
-settings.  For this purpuse Termios calls the @code{my_driver_set_attributes}
-function.
+settings.  For this purpose Termios calls the @code{my_driver_set_attributes()}
+handler.
 
 @example
 @group
-static int my_driver_set_attributes(
-    int minor,
-    const struct termios *t
+static bool my_driver_set_attributes(
+  rtems_termios_tty    *tty,
+  const struct termios *term
 )
 @{
-    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.
-     */
+  my_driver_context *ctx = rtems_termios_get_device_context(tty);
 
-    /*
-     * 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.
-     */
+  /*
+   * 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;
+  /*
+   * Return true to indicate a successful set attributes, and false
+   * otherwise.
+   */
+  return true;
 @}
 @end group
 @end example
-- 
1.7.7



More information about the devel mailing list