[rtems commit] termios: Partially hide rtems_termios_tty

Sebastian Huber sebh at rtems.org
Wed Oct 8 05:36:11 UTC 2014


Module:    rtems
Branch:    master
Commit:    7fd5e89c96cc92254e36012eee733748d255ff29
Changeset: http://git.rtems.org/rtems/commit/?id=7fd5e89c96cc92254e36012eee733748d255ff29

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Tue Oct  7 16:28:04 2014 +0200

termios: Partially hide rtems_termios_tty

Move interrupt lock to device context and expose only this structure to
the read, write and set attributes device handler.  This makes these
device handler independent of the general Termios infrastructure
suitable for direct use in printk() support.

---

 c/src/lib/libbsp/arm/tms570/console/tms570-sci.c   |   74 ++++++----
 .../libbsp/arm/tms570/include/tms570-sci-driver.h  |    1 +
 c/src/lib/libbsp/sparc/leon3/console/console.c     |   10 +-
 .../libbsp/sparc/shared/include/apbuart_termios.h  |    1 +
 .../lib/libbsp/sparc/shared/uart/apbuart_termios.c |   45 ++++---
 cpukit/libcsupport/include/rtems/termiostypes.h    |  146 +++++++++++++-------
 cpukit/libcsupport/src/termios.c                   |  142 ++++++++++++-------
 cpukit/libcsupport/src/termios_setbestbaud.c       |    6 +-
 cpukit/libnetworking/net/if_ppp.c                  |    2 +-
 cpukit/libnetworking/net/ppp_tty.c                 |    5 +-
 doc/bsp_howto/console.t                            |   38 +++---
 testsuites/libtests/termios01/init.c               |   52 +++++---
 12 files changed, 325 insertions(+), 197 deletions(-)

diff --git a/c/src/lib/libbsp/arm/tms570/console/tms570-sci.c b/c/src/lib/libbsp/arm/tms570/console/tms570-sci.c
index 961754e..3f10300 100644
--- a/c/src/lib/libbsp/arm/tms570/console/tms570-sci.c
+++ b/c/src/lib/libbsp/arm/tms570/console/tms570-sci.c
@@ -26,7 +26,6 @@
 #include <bspopts.h>
 #include <termios.h>
 #include <rtems/termiostypes.h>
-#include <libchip/sersupp.h>
 #include <bsp/tms570-sci.h>
 #include <bsp/tms570-sci-driver.h>
 #include <rtems/console.h>
@@ -43,11 +42,13 @@
  */
 const tms570_sci_context driver_context_table[] = {
   {
+    .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("TMS570 SCI1"),
     .device_name = "/dev/console",
     .regs = &TMS570_SCI,
     .irq = TMS570_IRQ_SCI_LEVEL_0,
   },
   {
+    .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("TMS570 SCI2"),
     .device_name = "/dev/ttyS1",
     .regs = &TMS570_SCI2,
     .irq = TMS570_IRQ_SCI2_LEVEL_0,
@@ -104,7 +105,7 @@ rtems_device_driver console_initialize(
         minor,
         handler,
 	NULL,
-        (void *) ctx
+        RTEMS_DECONST(rtems_termios_device_context *, &ctx->base)
     );
     if ( sc != RTEMS_SUCCESSFUL ) {
       bsp_fatal(BSP_FATAL_CONSOLE_NO_DEV);
@@ -196,21 +197,21 @@ static int tms570_sci_transmitted_chars(tms570_sci_context * ctx)
  *
  * Sets attributes of the HW peripheral (parity, baud rate, etc.)
  *
- * @param[in] tty rtems_termios_tty
+ * @param[in] base context of the driver
  * @param[in] t termios driver
  * @retval true peripheral setting is changed
  */
 static bool tms570_sci_set_attributes(
-  rtems_termios_tty    *tty,
+  rtems_termios_device_context *base,
   const struct termios *t
 )
 {
-  tms570_sci_context *ctx = rtems_termios_get_device_context(tty);
+  tms570_sci_context *ctx = (tms570_sci_context *) base;
   rtems_interrupt_lock_context lock_context;
   int32_t bauddiv;
   int32_t baudrate;
 
-  rtems_termios_interrupt_lock_acquire(tty, &lock_context);
+  rtems_termios_device_lock_acquire(base, &lock_context);
 
   ctx->regs->SCIGCR1 &= ~( (1<<7) | (1<<25) | (1<<24) );
 
@@ -245,7 +246,7 @@ static bool tms570_sci_set_attributes(
 
   ctx->regs->SCIGCR1 |= (1<<7) | (1<<25) | (1<<24);
 
-  rtems_termios_interrupt_lock_release(tty, &lock_context);
+  rtems_termios_device_lock_release(base, &lock_context);
 
   return true;
 }
@@ -300,18 +301,18 @@ static void tms570_sci_interrupt_handler(void * arg)
  * TMS570 does not have write data buffer asociated with SCI
  * so only one character can be written.
  *
- * @param[in] tty rtems_termios_tty
+ * @param[in] base context of the driver
  * @param[in] buf buffer of characters pending to send
  * @param[in] len size of the buffer
  * @retval Void
  */
 static void tms570_sci_interrupt_write(
-  rtems_termios_tty *tty,
+  rtems_termios_device_context *base,
   const char *buf,
   size_t len
 )
 {
-  tms570_sci_context *ctx = rtems_termios_get_device_context(tty);
+  tms570_sci_context *ctx = (tms570_sci_context *) base;
 
   if ( len > 0 ) {
     /* start UART TX, this will result in an interrupt when done */
@@ -334,18 +335,18 @@ static void tms570_sci_interrupt_write(
  * Blocking write function. Waits until HW peripheral is ready and then writes
  * character to HW peripheral. Writes all characters in the buffer.
  *
- * @param[in] tty rtems_termios_tty
+ * @param[in] base context of the driver
  * @param[in] buf buffer of characters pending to send
  * @param[in] len size of the buffer
  * @retval Void
  */
 static void tms570_sci_poll_write(
-  rtems_termios_tty *tty,
-  const char        *buf,
-  size_t             n
+  rtems_termios_device_context *base,
+  const char *buf,
+  size_t n
 )
 {
-  tms570_sci_context *ctx = rtems_termios_get_device_context(tty);
+  tms570_sci_context *ctx = (tms570_sci_context *) base;
   size_t i;
 
   /* Write */
@@ -394,13 +395,13 @@ static char TMS570_sci_read_char(
  *
  * check if there is recieved character to be read and reads it.
  *
- * @param[in] tty rtems_termios_tty (context of the driver)
+ * @param[in] base context of the driver
  * @retval -1 No character to be read
  * @retval x Read character
  */
-static int tms570_sci_poll_read(rtems_termios_tty *tty)
+static int tms570_sci_poll_read(rtems_termios_device_context *base)
 {
-  tms570_sci_context *ctx = rtems_termios_get_device_context(tty);
+  tms570_sci_context *ctx = (tms570_sci_context *) base;
 
   /* Check if a character is available */
   if ( TMS570_sci_can_read_char(ctx) ) {
@@ -416,20 +417,24 @@ static int tms570_sci_poll_read(rtems_termios_tty *tty)
  * initialization of the HW peripheral specified in contex of the driver.
  * This function is called only once when opening the driver.
  *
- * @param[in] tty context of the driver
+ * @param[in] tty Termios control
+ * @param[in] ctx context of the driver
+ * @param[in] term Termios attributes
  * @param[in] args
  * @retval false Error occured during initialization
  * @retval true Driver is open and ready
  */
 static bool tms570_sci_poll_first_open(
   rtems_termios_tty             *tty,
+  rtems_termios_device_context  *ctx,
+  struct termios                *term,
   rtems_libio_open_close_args_t *args
 )
 {
   bool ok;
 
-  rtems_termios_set_best_baud(tty, TMS570_SCI_BAUD_RATE);
-  ok = tms570_sci_set_attributes(tty, rtems_termios_get_termios(tty));
+  rtems_termios_set_best_baud(term, TMS570_SCI_BAUD_RATE);
+  ok = tms570_sci_set_attributes(ctx, term);
   if ( !ok ) {
     return false;
   }
@@ -442,21 +447,24 @@ static bool tms570_sci_poll_first_open(
  * calls tms570_sci_poll_first_open function.
  * install and enables interrupts.
  *
- * @param[in] tty context of the driver
+ * @param[in] tty Termios control
+ * @param[in] base context of the driver
  * @param[in] args
  * @retval false Error occured during initialization
  * @retval true Driver is open and ready
  */
 static bool tms570_sci_interrupt_first_open(
   rtems_termios_tty             *tty,
+  rtems_termios_device_context  *base,
+  struct termios                *term,
   rtems_libio_open_close_args_t *args
 )
 {
-  tms570_sci_context *ctx = rtems_termios_get_device_context(tty);
+  tms570_sci_context *ctx = (tms570_sci_context *) base;
   rtems_status_code sc;
   bool ret;
 
-  ret = tms570_sci_poll_first_open(tty,args);
+  ret = tms570_sci_poll_first_open(tty, base, term, args);
   if ( ret == false ) {
     return false;
   }
@@ -471,20 +479,22 @@ static bool tms570_sci_interrupt_first_open(
   if ( sc != RTEMS_SUCCESSFUL ) {
     return false;
   }
-  tms570_sci_enable_interrupts(rtems_termios_get_device_context(tty));
+  tms570_sci_enable_interrupts(ctx);
   return true;
 }
 
 /**
  * @brief closes sci peripheral
  *
- * @param[in] tty context of the driver
+ * @param[in] tty Termios control
+ * @param[in] base context of the driver
  * @param[in] args
  * @retval false Error occured during initialization
  * @retval true Driver is open and ready
  */
 static void tms570_sci_poll_last_close(
   rtems_termios_tty             *tty,
+  rtems_termios_device_context  *base,
   rtems_libio_open_close_args_t *args
 )
 {
@@ -496,23 +506,25 @@ static void tms570_sci_poll_last_close(
  *
  * calls tms570_sci_poll_last_close and disables interrupts
  *
- * @param[in] tty context of the driver
+ * @param[in] tty Termios control
+ * @param[in] base context of the driver
  * @param[in] args
  * @retval false Error occured during initialization
  * @retval true Driver is open and ready
  */
 static void tms570_sci_interrupt_last_close(
   rtems_termios_tty             *tty,
+  rtems_termios_device_context  *base,
   rtems_libio_open_close_args_t *args
 )
 {
-  tms570_sci_context *ctx = rtems_termios_get_device_context(tty);
+  tms570_sci_context *ctx = (tms570_sci_context *) base;
   rtems_interrupt_lock_context lock_context;
 
   /* Turn off RX interrupts */
-  rtems_termios_interrupt_lock_acquire(tty, &lock_context);
+  rtems_termios_device_lock_acquire(base, &lock_context);
   tms570_sci_disable_interrupts(ctx);
-  rtems_termios_interrupt_lock_release(tty, &lock_context);
+  rtems_termios_device_lock_release(base, &lock_context);
 
   /* Flush device */
   while ( ( ctx->regs->SCIFLR & (1<<11) ) > 0 ) {
@@ -522,7 +534,7 @@ static void tms570_sci_interrupt_last_close(
   /* uninstall ISR */
   rtems_interrupt_handler_remove(ctx->irq, tms570_sci_interrupt_handler, tty);
 
-  tms570_sci_poll_last_close(tty,args);
+  tms570_sci_poll_last_close(tty, base, args);
 }
 
 /**
diff --git a/c/src/lib/libbsp/arm/tms570/include/tms570-sci-driver.h b/c/src/lib/libbsp/arm/tms570/include/tms570-sci-driver.h
index 5f38908..f32eaea 100644
--- a/c/src/lib/libbsp/arm/tms570/include/tms570-sci-driver.h
+++ b/c/src/lib/libbsp/arm/tms570/include/tms570-sci-driver.h
@@ -36,6 +36,7 @@ extern "C" {
 
 /* Low-level driver specific data structure */
 typedef struct {
+  rtems_termios_device_context base;
   const char *device_name;
   volatile tms570_sci_t *regs;
   int tx_chars_in_hw;
diff --git a/c/src/lib/libbsp/sparc/leon3/console/console.c b/c/src/lib/libbsp/sparc/leon3/console/console.c
index 513d45d..35767ce 100644
--- a/c/src/lib/libbsp/sparc/leon3/console/console.c
+++ b/c/src/lib/libbsp/sparc/leon3/console/console.c
@@ -36,7 +36,7 @@ int syscon_uart_index __attribute__((weak)) = 0;
 static struct apbuart_context apbuarts[BSP_NUMBER_OF_TERMIOS_PORTS];
 static int uarts = 0;
 
-static struct apbuart_context *leon3_console_get_uart(int minor)
+static rtems_termios_device_context *leon3_console_get_context(int minor)
 {
   struct apbuart_context *uart;
 
@@ -45,7 +45,9 @@ static struct apbuart_context *leon3_console_get_uart(int minor)
   else
     uart = &apbuarts[minor - 1];
 
-  return uart;
+  rtems_termios_device_context_initialize(&uart->base, "APBUART");
+
+  return &uart->base;
 }
 
 /* AMBA PP find routine. Extract AMBA PnP information into data structure. */
@@ -132,7 +134,7 @@ rtems_device_driver console_initialize(
       minor,
       handler,
       NULL,
-      leon3_console_get_uart(syscon_uart_index)
+      leon3_console_get_context(syscon_uart_index)
     );
     if (status != RTEMS_SUCCESSFUL)
       bsp_fatal(LEON3_FATAL_CONSOLE_REGISTER_DEV);
@@ -149,7 +151,7 @@ rtems_device_driver console_initialize(
       minor,
       handler,
       NULL,
-      leon3_console_get_uart(syscon_uart_index)
+      leon3_console_get_context(syscon_uart_index)
     );
   }
 
diff --git a/c/src/lib/libbsp/sparc/shared/include/apbuart_termios.h b/c/src/lib/libbsp/sparc/shared/include/apbuart_termios.h
index ba5f049..40377c1 100644
--- a/c/src/lib/libbsp/sparc/shared/include/apbuart_termios.h
+++ b/c/src/lib/libbsp/sparc/shared/include/apbuart_termios.h
@@ -22,6 +22,7 @@ extern "C" {
 #endif /* __cplusplus */
 
 struct apbuart_context {
+  rtems_termios_device_context base;
   struct apbuart_regs *regs;
   unsigned int freq_hz;
   rtems_vector_number irq;
diff --git a/c/src/lib/libbsp/sparc/shared/uart/apbuart_termios.c b/c/src/lib/libbsp/sparc/shared/uart/apbuart_termios.c
index dd3ca5d..05bd608 100644
--- a/c/src/lib/libbsp/sparc/shared/uart/apbuart_termios.c
+++ b/c/src/lib/libbsp/sparc/shared/uart/apbuart_termios.c
@@ -41,12 +41,12 @@ static void apbuart_isr(void *arg)
 }
 
 static void apbuart_write_support(
-  rtems_termios_tty *tty,
+  rtems_termios_device_context *base,
   const char *buf,
   size_t len
 )
 {
-  struct apbuart_context *uart = rtems_termios_get_device_context(tty);
+  struct apbuart_context *uart = (struct apbuart_context *) base;
   int sending;
 
   if (len > 0) {
@@ -69,12 +69,12 @@ static void apbuart_write_support(
 }
 
 static void apbuart_write_polled(
-  rtems_termios_tty *tty,
+  rtems_termios_device_context *base,
   const char *buf,
   size_t len
 )
 {
-  struct apbuart_context *uart = rtems_termios_get_device_context(tty);
+  struct apbuart_context *uart = (struct apbuart_context *) base;
   size_t nwrite = 0;
 
   while (nwrite < len) {
@@ -83,19 +83,19 @@ static void apbuart_write_polled(
   }
 }
 
-static int apbuart_poll_read(rtems_termios_tty *tty)
+static int apbuart_poll_read(rtems_termios_device_context *base)
 {
-  struct apbuart_context *uart = rtems_termios_get_device_context(tty);
+  struct apbuart_context *uart = (struct apbuart_context *) base;
 
   return apbuart_inbyte_nonblocking(uart->regs);
 }
 
 static bool apbuart_set_attributes(
-  rtems_termios_tty *tty,
+  rtems_termios_device_context *base,
   const struct termios *t
 )
 {
-  struct apbuart_context *uart = rtems_termios_get_device_context(tty);
+  struct apbuart_context *uart = (struct apbuart_context *) base;
   rtems_interrupt_lock_context lock_context;
   unsigned int scaler;
   unsigned int ctrl;
@@ -112,7 +112,7 @@ static bool apbuart_set_attributes(
       break;
   }
 
-  rtems_termios_interrupt_lock_acquire(tty, &lock_context);
+  rtems_termios_device_lock_acquire(base, &lock_context);
 
   /* Read out current value */
   ctrl = uart->regs->ctrl;
@@ -145,7 +145,7 @@ static bool apbuart_set_attributes(
   /* Update new settings */
   uart->regs->ctrl = ctrl;
 
-  rtems_termios_interrupt_lock_release(tty, &lock_context);
+  rtems_termios_device_lock_release(base, &lock_context);
 
   /* Baud rate */
   baud = rtems_termios_baud_to_number(t->c_cflag);
@@ -161,23 +161,25 @@ static bool apbuart_set_attributes(
 }
 
 static void apbuart_set_best_baud(
-  rtems_termios_tty *tty,
-  const struct apbuart_context *uart
+  const struct apbuart_context *uart,
+  struct termios *term
 )
 {
   uint32_t baud = (uart->freq_hz * 10) / ((uart->regs->scaler * 10 + 5) * 8);
 
-  rtems_termios_set_best_baud(tty, baud);
+  rtems_termios_set_best_baud(term, baud);
 }
 
 static bool apbuart_first_open_polled(
   rtems_termios_tty *tty,
+  rtems_termios_device_context *base,
+  struct termios *term,
   rtems_libio_open_close_args_t *args
 )
 {
-  struct apbuart_context *uart = rtems_termios_get_device_context(tty);
+  struct apbuart_context *uart = (struct apbuart_context *) base;
 
-  apbuart_set_best_baud(tty, uart);
+  apbuart_set_best_baud(uart, term);
 
   /* Initialize UART on opening */
   uart->regs->ctrl |= APBUART_CTRL_RE | APBUART_CTRL_TE;
@@ -188,13 +190,15 @@ static bool apbuart_first_open_polled(
 
 static bool apbuart_first_open_interrupt(
   rtems_termios_tty *tty,
+  rtems_termios_device_context *base,
+  struct termios *term,
   rtems_libio_open_close_args_t *args
 )
 {
-  struct apbuart_context *uart = rtems_termios_get_device_context(tty);
+  struct apbuart_context *uart = (struct apbuart_context *) base;
   rtems_status_code sc;
 
-  apbuart_set_best_baud(tty, uart);
+  apbuart_set_best_baud(uart, term);
 
   /* Register Interrupt handler */
   sc = rtems_interrupt_handler_install(uart->irq, "console",
@@ -217,16 +221,17 @@ static bool apbuart_first_open_interrupt(
 
 static void apbuart_last_close_interrupt(
   rtems_termios_tty *tty,
+  rtems_termios_device_context *base,
   rtems_libio_open_close_args_t *args
 )
 {
-  struct apbuart_context *uart = rtems_termios_get_device_context(tty);
+  struct apbuart_context *uart = (struct apbuart_context *) base;
   rtems_interrupt_lock_context lock_context;
 
   /* Turn off RX interrupts */
-  rtems_termios_interrupt_lock_acquire(tty, &lock_context);
+  rtems_termios_device_lock_acquire(base, &lock_context);
   uart->regs->ctrl &= ~(APBUART_CTRL_RI);
-  rtems_termios_interrupt_lock_release(tty, &lock_context);
+  rtems_termios_device_lock_release(base, &lock_context);
 
   /**** Flush device ****/
   while (uart->sending) {
diff --git a/cpukit/libcsupport/include/rtems/termiostypes.h b/cpukit/libcsupport/include/rtems/termiostypes.h
index 045a91f..71be95f 100644
--- a/cpukit/libcsupport/include/rtems/termiostypes.h
+++ b/cpukit/libcsupport/include/rtems/termiostypes.h
@@ -63,6 +63,42 @@ typedef enum {
 struct rtems_termios_tty;
 
 /**
+ * @brief Termios device context.
+ *
+ * @see RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER(),
+ * rtems_termios_device_context_initialize() and
+ * rtems_termios_device_install().
+ */
+typedef struct rtems_termios_device_context {
+  rtems_interrupt_lock interrupt_lock;
+} rtems_termios_device_context;
+
+/**
+ * @brief Initializes a device context.
+ *
+ * @param[in] context The Termios device context.
+ * @param[in] name The name for the interrupt lock.  This name must be a
+ *   string persistent throughout the life time of this lock.  The name is only
+ *   used if profiling is enabled.
+ */
+RTEMS_INLINE_ROUTINE void rtems_termios_device_context_initialize(
+  rtems_termios_device_context *context,
+  const char                   *name
+)
+{
+  rtems_interrupt_lock_initialize( &context->interrupt_lock, name );
+}
+
+/**
+ * @brief Initializer for static initialization of Termios device contexts.
+ *
+ * @param name The name for the interrupt lock.  It must be a string.  The name
+ *   is only used if profiling is enabled.
+ */
+#define RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER( name ) \
+  { RTEMS_INTERRUPT_LOCK_INITIALIZER( name ) }
+
+/**
  * @brief Termios device handler.
  *
  * @see rtems_termios_device_install().
@@ -71,18 +107,24 @@ typedef struct {
   /**
    * @brief First open of this device.
    *
-   * @param[in] tty The Termios control.
+   * @param[in] tty The Termios control.  This parameter may be passed to
+   *   interrupt service routines since it must be provided for the
+   *   rtems_termios_enqueue_raw_characters() and
+   *   rtems_termios_dequeue_characters() functions.
+   * @param[in] context The Termios device context.
+   * @param[in] term The current Termios attributes.
    * @param[in] args The open/close arguments.  This is parameter provided to
    *   support legacy drivers.  It must not be used by new drivers.
    *
    * @retval true Successful operation.
    * @retval false Cannot open device.
    *
-   * @see rtems_termios_get_device_context(), rtems_termios_set_best_baud() and
-   *   rtems_termios_get_termios().
+   * @see rtems_termios_get_device_context() and rtems_termios_set_best_baud().
    */
   bool (*first_open)(
     struct rtems_termios_tty      *tty,
+    rtems_termios_device_context  *context,
+    struct termios                *term,
     rtems_libio_open_close_args_t *args
   );
 
@@ -90,13 +132,13 @@ typedef struct {
    * @brief Last close of this device.
    *
    * @param[in] tty The Termios control.
+   * @param[in] context The Termios device context.
    * @param[in] args The open/close arguments.  This is parameter provided to
    *   support legacy drivers.  It must not be used by new drivers.
-   *
-   * @see rtems_termios_get_device_context().
    */
   void (*last_close)(
     struct rtems_termios_tty      *tty,
+    rtems_termios_device_context  *context,
     rtems_libio_open_close_args_t *args
   );
 
@@ -106,41 +148,39 @@ typedef struct {
    * In case mode is TERMIOS_IRQ_DRIVEN or TERMIOS_TASK_DRIVEN, then data is
    * received via rtems_termios_enqueue_raw_characters().
    *
-   * @param[in] tty The Termios control.
+   * @param[in] context The Termios device context.
    *
    * @retval char The received data encoded as unsigned char.
    * @retval -1 No data currently available.
-   *
-   * @see rtems_termios_get_device_context().
    */
-  int (*poll_read)(struct rtems_termios_tty *tty);
+  int (*poll_read)(rtems_termios_device_context *context);
 
   /**
    * @brief Polled write in case mode is TERMIOS_POLLED or write support
    * otherwise.
    *
-   * @param[in] tty The Termios control.
+   * @param[in] context The Termios device context.
    * @param[in] buf The output buffer.
    * @param[in] len The output buffer length in characters.
-   *
-   * @see rtems_termios_get_device_context().
    */
-  void (*write)(struct rtems_termios_tty *tty, const char *buf, size_t len);
+  void (*write)(
+    rtems_termios_device_context *context,
+    const char *buf,
+    size_t len
+  );
 
   /**
    * @brief Set attributes after a Termios settings change.
    *
-   * @param[in] tty The Termios control.
+   * @param[in] context The Termios device context.
    * @param[in] term The new Termios attributes.
    *
    * @retval true Successful operation.
    * @retval false Invalid attributes.
-   *
-   * @see rtems_termios_get_device_context().
    */
   bool (*set_attributes)(
-    struct rtems_termios_tty *tty,
-    const struct termios     *term
+    rtems_termios_device_context *context,
+    const struct termios         *term
   );
 
   /**
@@ -158,20 +198,16 @@ typedef struct {
   /**
    * @brief Indicate to stop remote transmitter.
    *
-   * @param[in] tty The Termios control.
-   *
-   * @see rtems_termios_get_device_context().
+   * @param[in] context The Termios device context.
    */
-  void (*stop_remote_tx)(struct rtems_termios_tty *tty);
+  void (*stop_remote_tx)(rtems_termios_device_context *context);
 
   /**
    * @brief Indicate to start remote transmitter.
    *
-   * @param[in] tty The Termios control.
-   *
-   * @see rtems_termios_get_device_context().
+   * @param[in] context The Termios device context.
    */
-  void (*start_remote_tx)(struct rtems_termios_tty *tty);
+  void (*start_remote_tx)(rtems_termios_device_context *context);
 } rtems_termios_device_flow;
 
 /**
@@ -185,7 +221,7 @@ typedef struct rtems_termios_device_node {
   rtems_device_minor_number           minor;
   const rtems_termios_device_handler *handler;
   const rtems_termios_device_flow    *flow;
-  void                               *context;
+  rtems_termios_device_context       *context;
   struct rtems_termios_tty           *tty;
 } rtems_termios_device_node;
 
@@ -258,6 +294,11 @@ typedef struct rtems_termios_tty {
   rtems_termios_callbacks  device;
 
   /**
+   * @brief Context for legacy devices using the callbacks.
+   */
+  rtems_termios_device_context legacy_device_context;
+
+  /**
    * @brief The device handler.
    */
   rtems_termios_device_handler handler;
@@ -289,8 +330,6 @@ typedef struct rtems_termios_tty {
   struct ttywakeup tty_rcv;
   int              tty_rcvwakeup;
 
-  rtems_interrupt_lock interrupt_lock;
-
   /**
    * @brief Corresponding device node.
    */
@@ -298,10 +337,8 @@ typedef struct rtems_termios_tty {
 
   /**
    * @brief Context for device driver.
-   *
-   * @see rtems_termios_get_device_context().
    */
-  void *device_context;
+  rtems_termios_device_context *device_context;
 } rtems_termios_tty;
 
 /**
@@ -335,7 +372,7 @@ rtems_status_code rtems_termios_device_install(
   rtems_device_minor_number           minor,
   const rtems_termios_device_handler *handler,
   const rtems_termios_device_flow    *flow,
-  void                               *context
+  rtems_termios_device_context       *context
 );
 
 /**
@@ -382,6 +419,8 @@ rtems_status_code rtems_termios_device_close(void *arg);
 
 /**
  * @brief Returns the device context of an installed Termios device.
+ *
+ * @param[in] tty The Termios control.
  */
 RTEMS_INLINE_ROUTINE void *rtems_termios_get_device_context(
   const rtems_termios_tty *tty
@@ -391,16 +430,33 @@ RTEMS_INLINE_ROUTINE void *rtems_termios_get_device_context(
 }
 
 /**
- * @brief Returns the Termios structure.
+ * @brief Acquires the device lock.
  *
- * It can be used for example in the first open handler to adjust or obtain the
- * initial attributes.
+ * @param[in] context The device context.
+ * @param[in] lock_context The local interrupt lock context for an acquire and
+ *   release pair.
  */
-RTEMS_INLINE_ROUTINE struct termios *rtems_termios_get_termios(
-  rtems_termios_tty *tty
+RTEMS_INLINE_ROUTINE void rtems_termios_device_lock_acquire(
+  rtems_termios_device_context *context,
+  rtems_interrupt_lock_context *lock_context
 )
 {
-  return &tty->termios;
+  rtems_interrupt_lock_acquire( &context->interrupt_lock, lock_context );
+}
+
+/**
+ * @brief Releases the device lock.
+ *
+ * @param[in] context The device context.
+ * @param[in] lock_context The local interrupt lock context for an acquire and
+ *   release pair.
+ */
+RTEMS_INLINE_ROUTINE void rtems_termios_device_lock_release(
+  rtems_termios_device_context *context,
+  rtems_interrupt_lock_context *lock_context
+)
+{
+  rtems_interrupt_lock_release( &context->interrupt_lock, lock_context );
 }
 
 /**
@@ -409,12 +465,12 @@ RTEMS_INLINE_ROUTINE struct termios *rtems_termios_get_termios(
  * The valid Termios baud values are between 0 and 460800.  The Termios baud
  * value is chosen which minimizes the difference to the value specified.
  *
- * @param[in] tty The Termios control.
+ * @param[in] term The Termios attributes.
  * @param[in] baud The current baud setting of the device.
  */
 void rtems_termios_set_best_baud(
-  rtems_termios_tty *tty,
-  uint32_t           baud
+  struct termios *term,
+  uint32_t        baud
 );
 
 struct rtems_termios_linesw {
@@ -498,12 +554,6 @@ int rtems_termios_set_initial_baud(
   rtems_termios_baud_t baud
 );
 
-#define rtems_termios_interrupt_lock_acquire(tty, level) \
-  rtems_interrupt_lock_acquire(&tty->interrupt_lock, level)
-
-#define rtems_termios_interrupt_lock_release(tty, level) \
-  rtems_interrupt_lock_release(&tty->interrupt_lock, level)
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/cpukit/libcsupport/src/termios.c b/cpukit/libcsupport/src/termios.c
index 6119b22..f0ecad0 100644
--- a/cpukit/libcsupport/src/termios.c
+++ b/cpukit/libcsupport/src/termios.c
@@ -134,7 +134,7 @@ rtems_status_code rtems_termios_device_install(
   rtems_device_minor_number           minor,
   const rtems_termios_device_handler *handler,
   const rtems_termios_device_flow    *flow,
-  void                               *context
+  rtems_termios_device_context       *context
 )
 {
   rtems_status_code          sc;
@@ -227,12 +227,23 @@ rtems_status_code rtems_termios_device_remove(
   return RTEMS_SUCCESSFUL;
 }
 
+static rtems_termios_tty *
+legacyContextToTTY (rtems_termios_device_context *ctx)
+{
+  return RTEMS_CONTAINER_OF (ctx, rtems_termios_tty, legacy_device_context);
+}
+
 static bool
 rtems_termios_callback_firstOpen(
   rtems_termios_tty             *tty,
+  rtems_termios_device_context  *ctx,
+  struct termios                *term,
   rtems_libio_open_close_args_t *args
 )
 {
+  (void) ctx;
+  (void) term;
+
   (*tty->device.firstOpen) (tty->major, tty->minor, args);
 
   return true;
@@ -241,48 +252,61 @@ rtems_termios_callback_firstOpen(
 static void
 rtems_termios_callback_lastClose(
   rtems_termios_tty             *tty,
+  rtems_termios_device_context  *ctx,
   rtems_libio_open_close_args_t *args
 )
 {
+  (void) ctx;
+
   (*tty->device.lastClose) (tty->major, tty->minor, args);
 }
 
 static int
-rtems_termios_callback_pollRead (struct rtems_termios_tty *tty)
+rtems_termios_callback_pollRead (rtems_termios_device_context *ctx)
 {
+  rtems_termios_tty *tty = legacyContextToTTY (ctx);
+
   return (*tty->device.pollRead) (tty->minor);
 }
 
 static void
 rtems_termios_callback_write(
-  rtems_termios_tty *tty,
-  const char        *buf,
-  size_t             len
+  rtems_termios_device_context *ctx,
+  const char                   *buf,
+  size_t                        len
 )
 {
+  rtems_termios_tty *tty = legacyContextToTTY (ctx);
+
   (*tty->device.write) (tty->minor, buf, len);
 }
 
 static bool
 rtems_termios_callback_setAttributes(
-  rtems_termios_tty    *tty,
-  const struct termios *term
+  rtems_termios_device_context *ctx,
+  const struct termios         *term
 )
 {
+  rtems_termios_tty *tty = legacyContextToTTY (ctx);
+
   (*tty->device.setAttributes) (tty->minor, term);
 
   return true;
 }
 
 static void
-rtems_termios_callback_stopRemoteTx (rtems_termios_tty *tty)
+rtems_termios_callback_stopRemoteTx (rtems_termios_device_context *ctx)
 {
+  rtems_termios_tty *tty = legacyContextToTTY (ctx);
+
   (*tty->device.stopRemoteTx) (tty->minor);
 }
 
 static void
-rtems_termios_callback_startRemoteTx (rtems_termios_tty *tty)
+rtems_termios_callback_startRemoteTx (rtems_termios_device_context *ctx)
 {
+  rtems_termios_tty *tty = legacyContextToTTY (ctx);
+
   (*tty->device.startRemoteTx) (tty->minor);
 }
 
@@ -292,21 +316,22 @@ rtems_termios_callback_startRemoteTx (rtems_termios_tty *tty)
 static void
 drainOutput (struct rtems_termios_tty *tty)
 {
+  rtems_termios_device_context *ctx = tty->device_context;
   rtems_interrupt_lock_context lock_context;
   rtems_status_code sc;
 
   if (tty->handler.mode != TERMIOS_POLLED) {
-    rtems_termios_interrupt_lock_acquire (tty, &lock_context);
+    rtems_termios_device_lock_acquire (ctx, &lock_context);
     while (tty->rawOutBuf.Tail != tty->rawOutBuf.Head) {
       tty->rawOutBufState = rob_wait;
-      rtems_termios_interrupt_lock_release (tty, &lock_context);
+      rtems_termios_device_lock_release (ctx, &lock_context);
       sc = rtems_semaphore_obtain(
         tty->rawOutBuf.Semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
       if (sc != RTEMS_SUCCESSFUL)
         rtems_fatal_error_occurred (sc);
-      rtems_termios_interrupt_lock_acquire (tty, &lock_context);
+      rtems_termios_device_lock_acquire (ctx, &lock_context);
     }
-    rtems_termios_interrupt_lock_release (tty, &lock_context);
+    rtems_termios_device_lock_release (ctx, &lock_context);
   }
 }
 
@@ -344,7 +369,7 @@ rtems_termios_destroy_tty (rtems_termios_tty *tty, void *arg, bool last_close)
       rtems_fatal_error_occurred (sc);
   }
   if (last_close && tty->handler.last_close)
-     (*tty->handler.last_close)(tty, arg);
+     (*tty->handler.last_close)(tty, tty->device_context, arg);
 
   if (tty->device_node != NULL)
     tty->device_node->tty = NULL;
@@ -355,7 +380,10 @@ rtems_termios_destroy_tty (rtems_termios_tty *tty, void *arg, bool last_close)
   if ((tty->handler.poll_read == NULL) ||
       (tty->handler.mode == TERMIOS_TASK_DRIVEN))
     rtems_semaphore_delete (tty->rawInBuf.Semaphore);
-  rtems_interrupt_lock_destroy (&tty->interrupt_lock);
+
+  if (tty->device_context == &tty->legacy_device_context)
+    rtems_interrupt_lock_destroy (&tty->legacy_device_context.interrupt_lock);
+
   free (tty->rawInBuf.theBuf);
   free (tty->rawOutBuf.theBuf);
   free (tty->cbuf);
@@ -489,7 +517,10 @@ rtems_termios_open_tty(
       tty->device = *callbacks;
     }
 
-    rtems_interrupt_lock_initialize (&tty->interrupt_lock, "Termios");
+    if (tty->device_context == NULL) {
+      tty->device_context = &tty->legacy_device_context;
+      rtems_termios_device_context_initialize (tty->device_context, "Termios");
+    }
 
     /*
      * Create I/O tasks
@@ -569,8 +600,8 @@ rtems_termios_open_tty(
   }
   args->iop->data1 = tty;
   if (!tty->refcount++) {
-    if (tty->handler.first_open &&
-        !(*tty->handler.first_open)(tty, args)) {
+    if (tty->handler.first_open && !(*tty->handler.first_open)(
+        tty, tty->device_context, &tty->termios, args)) {
       rtems_termios_destroy_tty(tty, args, false);
       return NULL;
     }
@@ -683,24 +714,26 @@ rtems_termios_open (
 static void
 flushOutput (struct rtems_termios_tty *tty)
 {
+  rtems_termios_device_context *ctx = tty->device_context;
   rtems_interrupt_lock_context lock_context;
 
-  rtems_termios_interrupt_lock_acquire (tty, &lock_context);
+  rtems_termios_device_lock_acquire (ctx, &lock_context);
   tty->rawOutBuf.Tail = 0;
   tty->rawOutBuf.Head = 0;
   tty->rawOutBufState = rob_idle;
-  rtems_termios_interrupt_lock_release (tty, &lock_context);
+  rtems_termios_device_lock_release (ctx, &lock_context);
 }
 
 static void
 flushInput (struct rtems_termios_tty *tty)
 {
+  rtems_termios_device_context *ctx = tty->device_context;
   rtems_interrupt_lock_context lock_context;
 
-  rtems_termios_interrupt_lock_acquire (tty, &lock_context);
+  rtems_termios_device_lock_acquire (ctx, &lock_context);
   tty->rawInBuf.Tail = 0;
   tty->rawInBuf.Head = 0;
-  rtems_termios_interrupt_lock_release (tty, &lock_context);
+  rtems_termios_device_lock_release (ctx, &lock_context);
 }
 
 static void
@@ -784,6 +817,7 @@ rtems_status_code rtems_termios_bufsize (
 static void
 termios_set_flowctrl(struct rtems_termios_tty *tty)
 {
+  rtems_termios_device_context *ctx = tty->device_context;
   rtems_interrupt_lock_context lock_context;
   /*
    * check for flow control options to be switched off
@@ -798,16 +832,16 @@ termios_set_flowctrl(struct rtems_termios_tty *tty)
     /* has output been stopped due to received XOFF? */
     if (tty->flow_ctrl & FL_OSTOP) {
       /* disable interrupts    */
-      rtems_termios_interrupt_lock_acquire (tty, &lock_context);
+      rtems_termios_device_lock_acquire (ctx, &lock_context);
       tty->flow_ctrl &= ~FL_OSTOP;
       /* check for chars in output buffer (or rob_state?) */
       if (tty->rawOutBufState != rob_idle) {
         /* if chars available, call write function... */
         (*tty->handler.write)(
-          tty, &tty->rawOutBuf.theBuf[tty->rawOutBuf.Tail],1);
+          ctx, &tty->rawOutBuf.theBuf[tty->rawOutBuf.Tail],1);
       }
       /* reenable interrupts */
-      rtems_termios_interrupt_lock_release (tty, &lock_context);
+      rtems_termios_device_lock_release (ctx, &lock_context);
     }
   }
   /* check for incoming XON/XOFF flow control switched off */
@@ -826,7 +860,7 @@ termios_set_flowctrl(struct rtems_termios_tty *tty)
     /* restart remote Tx, if it was stopped */
     if ((tty->flow_ctrl & FL_IRTSOFF) &&
         (tty->flow.start_remote_tx != NULL)) {
-      tty->flow.start_remote_tx(tty);
+      tty->flow.start_remote_tx(ctx);
     }
     tty->flow_ctrl &= ~(FL_IRTSOFF);
   }
@@ -906,7 +940,7 @@ rtems_termios_ioctl (void *arg)
       }
     }
     if (tty->handler.set_attributes) {
-      sc = (*tty->handler.set_attributes)(tty, &tty->termios) ?
+      sc = (*tty->handler.set_attributes)(tty->device_context, &tty->termios) ?
         RTEMS_SUCCESSFUL : RTEMS_IO_ERROR;
     }
     break;
@@ -1003,7 +1037,7 @@ startXmit (
     nToSend = 0;
     /* stop transmitter */
     if (transmitting) {
-      (*tty->handler.write) (tty, NULL, 0);
+      (*tty->handler.write) (tty->device_context, NULL, 0);
     }
   } else {
     /* when flow control XON or XOF, don't send blocks of data     */
@@ -1017,7 +1051,7 @@ startXmit (
       nToSend = tty->rawOutBuf.Head - newTail;
 
     (*tty->handler.write)(
-        tty, &tty->rawOutBuf.theBuf[newTail], nToSend);
+        tty->device_context, &tty->rawOutBuf.theBuf[newTail], nToSend);
   }
 
   return nToSend;
@@ -1032,11 +1066,12 @@ rtems_termios_puts (
 {
   const char *buf = _buf;
   unsigned int newHead;
+  rtems_termios_device_context *ctx = tty->device_context;
   rtems_interrupt_lock_context lock_context;
   rtems_status_code sc;
 
   if (tty->handler.mode == TERMIOS_POLLED) {
-    (*tty->handler.write)(tty, buf, len);
+    (*tty->handler.write)(ctx, buf, len);
     return;
   }
 
@@ -1049,15 +1084,15 @@ rtems_termios_puts (
     if (newHead >= tty->rawOutBuf.Size)
       newHead -= tty->rawOutBuf.Size;
 
-    rtems_termios_interrupt_lock_acquire (tty, &lock_context);
+    rtems_termios_device_lock_acquire (ctx, &lock_context);
     while (newHead == tty->rawOutBuf.Tail) {
       tty->rawOutBufState = rob_wait;
-      rtems_termios_interrupt_lock_release (tty, &lock_context);
+      rtems_termios_device_lock_release (ctx, &lock_context);
       sc = rtems_semaphore_obtain(
         tty->rawOutBuf.Semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
       if (sc != RTEMS_SUCCESSFUL)
         rtems_fatal_error_occurred (sc);
-      rtems_termios_interrupt_lock_acquire (tty, &lock_context);
+      rtems_termios_device_lock_acquire (ctx, &lock_context);
     }
 
     /* Determine free space up to current tail or end of ring buffer */
@@ -1090,7 +1125,7 @@ rtems_termios_puts (
       startXmit (tty, tty->rawOutBuf.Tail, false);
     }
 
-    rtems_termios_interrupt_lock_release (tty, &lock_context);
+    rtems_termios_device_lock_release (ctx, &lock_context);
 
     buf += nToCopy;
     len -= nToCopy;
@@ -1371,7 +1406,7 @@ fillBufferPoll (struct rtems_termios_tty *tty)
 
   if (tty->termios.c_lflag & ICANON) {
     for (;;) {
-      n = (*tty->handler.poll_read)(tty);
+      n = (*tty->handler.poll_read)(tty->device_context);
       if (n < 0) {
         rtems_task_wake_after (1);
       } else {
@@ -1384,7 +1419,7 @@ fillBufferPoll (struct rtems_termios_tty *tty)
 
     then = rtems_clock_get_ticks_since_boot();
     for (;;) {
-      n = (*tty->handler.poll_read)(tty);
+      n = (*tty->handler.poll_read)(tty->device_context);
       if (n < 0) {
         if (tty->termios.c_cc[VMIN]) {
           if (tty->termios.c_cc[VTIME] && tty->ccount) {
@@ -1447,12 +1482,12 @@ fillBufferQueue (struct rtems_termios_tty *tty)
           || (tty->flow_ctrl & FL_OSTOP))) {
           /* XON should be sent now... */
           (*tty->handler.write)(
-            tty, (void *)&(tty->termios.c_cc[VSTART]), 1);
+            tty->device_context, (void *)&(tty->termios.c_cc[VSTART]), 1);
         } else if (tty->flow_ctrl & FL_MDRTS) {
           tty->flow_ctrl &= ~FL_IRTSOFF;
           /* activate RTS line */
           if (tty->flow.start_remote_tx != NULL) {
-            tty->flow.start_remote_tx(tty);
+            tty->flow.start_remote_tx(tty->device_context);
           }
         }
       }
@@ -1550,6 +1585,7 @@ rtems_termios_enqueue_raw_characters (void *ttyp, const char *buf, int len)
   char c;
   int dropped = 0;
   bool flow_rcv = false; /* true, if flow control char received */
+  rtems_termios_device_context *ctx = tty->device_context;
   rtems_interrupt_lock_context lock_context;
 
   if (rtems_termios_linesw[tty->t_line].l_rint != NULL) {
@@ -1598,21 +1634,21 @@ rtems_termios_enqueue_raw_characters (void *ttyp, const char *buf, int len)
       /* restart output according to FL_ORCVXOF flag */
       if ((tty->flow_ctrl & (FL_ORCVXOF | FL_OSTOP)) == FL_OSTOP) {
         /* disable interrupts    */
-        rtems_termios_interrupt_lock_acquire (tty, &lock_context);
+        rtems_termios_device_lock_acquire (ctx, &lock_context);
         tty->flow_ctrl &= ~FL_OSTOP;
         /* check for chars in output buffer (or rob_state?) */
         if (tty->rawOutBufState != rob_idle) {
           /* if chars available, call write function... */
           (*tty->handler.write)(
-            tty, &tty->rawOutBuf.theBuf[tty->rawOutBuf.Tail], 1);
+            ctx, &tty->rawOutBuf.theBuf[tty->rawOutBuf.Tail], 1);
         }
         /* reenable interrupts */
-        rtems_termios_interrupt_lock_release (tty, &lock_context);
+        rtems_termios_device_lock_release (ctx, &lock_context);
       }
     } else {
       newTail = (tty->rawInBuf.Tail + 1) % tty->rawInBuf.Size;
       /* if chars_in_buffer > highwater                */
-      rtems_termios_interrupt_lock_acquire (tty, &lock_context);
+      rtems_termios_device_lock_acquire (ctx, &lock_context);
       if ((((newTail - tty->rawInBuf.Head + tty->rawInBuf.Size)
             % tty->rawInBuf.Size) > tty->highwater) &&
           !(tty->flow_ctrl & FL_IREQXOF)) {
@@ -1625,20 +1661,20 @@ rtems_termios_enqueue_raw_characters (void *ttyp, const char *buf, int len)
             /* if tx is stopped due to XOFF or out of data */
             /*    call write function here                 */
             tty->flow_ctrl |= FL_ISNTXOF;
-            (*tty->handler.write)(tty,
+            (*tty->handler.write)(ctx,
                 (void *)&(tty->termios.c_cc[VSTOP]), 1);
           }
         } else if ((tty->flow_ctrl & (FL_MDRTS | FL_IRTSOFF)) == (FL_MDRTS) ) {
           tty->flow_ctrl |= FL_IRTSOFF;
           /* deactivate RTS line */
           if (tty->flow.stop_remote_tx != NULL) {
-            tty->flow.stop_remote_tx(tty);
+            tty->flow.stop_remote_tx(ctx);
           }
         }
       }
 
       /* reenable interrupts */
-      rtems_termios_interrupt_lock_release (tty, &lock_context);
+      rtems_termios_device_lock_release (ctx, &lock_context);
 
       if (newTail == tty->rawInBuf.Head) {
         dropped++;
@@ -1672,16 +1708,17 @@ rtems_termios_refill_transmitter (struct rtems_termios_tty *tty)
   bool wakeUpWriterTask = false;
   unsigned int newTail;
   int nToSend;
+  rtems_termios_device_context *ctx = tty->device_context;
   rtems_interrupt_lock_context lock_context;
   int len;
 
-  rtems_termios_interrupt_lock_acquire (tty, &lock_context);
+  rtems_termios_device_lock_acquire (ctx, &lock_context);
 
   /* check for XOF/XON to send */
   if ((tty->flow_ctrl & (FL_MDXOF | FL_IREQXOF | FL_ISNTXOF))
       == (FL_MDXOF | FL_IREQXOF)) {
     /* XOFF should be sent now... */
-    (*tty->handler.write)(tty, (void *)&(tty->termios.c_cc[VSTOP]), 1);
+    (*tty->handler.write)(ctx, (void *)&(tty->termios.c_cc[VSTOP]), 1);
 
     tty->t_dqlen--;
     tty->flow_ctrl |= FL_ISNTXOF;
@@ -1697,7 +1734,7 @@ rtems_termios_refill_transmitter (struct rtems_termios_tty *tty)
      * buffer, although the corresponding data is not yet out!
      * Therefore the dequeue "length" should be reduced by 1
      */
-    (*tty->handler.write)(tty, (void *)&(tty->termios.c_cc[VSTART]), 1);
+    (*tty->handler.write)(ctx, (void *)&(tty->termios.c_cc[VSTART]), 1);
 
     tty->t_dqlen--;
     tty->flow_ctrl &= ~FL_ISNTXOF;
@@ -1714,7 +1751,7 @@ rtems_termios_refill_transmitter (struct rtems_termios_tty *tty)
       wakeUpWriterTask = true;
     }
 
-    (*tty->handler.write) (tty, NULL, 0);
+    (*tty->handler.write) (ctx, NULL, 0);
     nToSend = 0;
   } else {
     len = tty->t_dqlen;
@@ -1734,7 +1771,7 @@ rtems_termios_refill_transmitter (struct rtems_termios_tty *tty)
        * Buffer has become empty
        */
       tty->rawOutBufState = rob_idle;
-      (*tty->handler.write) (tty, NULL, 0);
+      (*tty->handler.write) (ctx, NULL, 0);
       nToSend = 0;
 
       /*
@@ -1751,7 +1788,7 @@ rtems_termios_refill_transmitter (struct rtems_termios_tty *tty)
     }
   }
 
-  rtems_termios_interrupt_lock_release (tty, &lock_context);
+  rtems_termios_device_lock_release (ctx, &lock_context);
 
   if (wakeUpWriterTask) {
     rtems_semaphore_release (tty->rawOutBuf.Semaphore);
@@ -1854,6 +1891,7 @@ static rtems_task rtems_termios_txdaemon(rtems_task_argument argument)
 static rtems_task rtems_termios_rxdaemon(rtems_task_argument argument)
 {
   struct rtems_termios_tty *tty = (struct rtems_termios_tty *)argument;
+  rtems_termios_device_context *ctx = tty->device_context;
   rtems_event_set the_event;
   int c;
   char c_buf;
@@ -1876,7 +1914,7 @@ static rtems_task rtems_termios_rxdaemon(rtems_task_argument argument)
     /*
      * do something
      */
-    c = tty->handler.poll_read(tty);
+    c = tty->handler.poll_read(ctx);
     if (c != EOF) {
       /*
        * poll_read did call enqueue on its own
diff --git a/cpukit/libcsupport/src/termios_setbestbaud.c b/cpukit/libcsupport/src/termios_setbestbaud.c
index 3d7a3a8..7680118 100644
--- a/cpukit/libcsupport/src/termios_setbestbaud.c
+++ b/cpukit/libcsupport/src/termios_setbestbaud.c
@@ -19,8 +19,8 @@
 #include <rtems/termiostypes.h>
 
 void rtems_termios_set_best_baud(
-  rtems_termios_tty *tty,
-  uint32_t           baud
+  struct termios *term,
+  uint32_t        baud
 )
 {
   const rtems_assoc_t *current = &rtems_termios_baud_table[ 0 ];
@@ -41,5 +41,5 @@ void rtems_termios_set_best_baud(
     cbaud = B460800;
   }
 
-  tty->termios.c_cflag = (tty->termios.c_cflag & ~cbaud_mask) | cbaud;
+  term->c_cflag = (term->c_cflag & ~cbaud_mask) | cbaud;
 }
diff --git a/cpukit/libnetworking/net/if_ppp.c b/cpukit/libnetworking/net/if_ppp.c
index a1d7a62..95fa556 100644
--- a/cpukit/libnetworking/net/if_ppp.c
+++ b/cpukit/libnetworking/net/if_ppp.c
@@ -387,7 +387,7 @@ static rtems_task ppp_txdaemon(rtems_task_argument arg)
   
         /* write out frame byte to start the transmission */
 		sc->sc_outchar = (u_char)PPP_FLAG;
-        (*tp->handler.write)(tp, (char *)&sc->sc_outchar, 1);
+        (*tp->handler.write)(tp->device_context, (char *)&sc->sc_outchar, 1);
       }
 
       /* check to see if we need to free some empty mbufs */
diff --git a/cpukit/libnetworking/net/ppp_tty.c b/cpukit/libnetworking/net/ppp_tty.c
index 613d9c5..85a336c 100644
--- a/cpukit/libnetworking/net/ppp_tty.c
+++ b/cpukit/libnetworking/net/ppp_tty.c
@@ -568,6 +568,7 @@ pppstart(struct rtems_termios_tty *tp)
   u_long              ioffset = (u_long       )0;
   struct mbuf        *m       = (struct mbuf *)0;
   struct ppp_softc   *sc      = tp->t_sc;
+  rtems_termios_device_context *ctx = rtems_termios_get_device_context(tp);
 
   /* ensure input is valid and we are busy */
   if (( sc != NULL ) && ( sc->sc_outflag & SC_TX_BUSY )) {
@@ -606,7 +607,7 @@ pppstart(struct rtems_termios_tty *tp)
         sc->sc_outflag |= SC_TX_LASTCHAR;
         sc->sc_outflag &=~(SC_TX_FCS);
 		sc->sc_outchar = (u_char)PPP_FLAG;
-        (*tp->handler.write)(tp, (char *)&sc->sc_outchar, 1);
+        (*tp->handler.write)(ctx, (char *)&sc->sc_outchar, 1);
         return(0);
       }
     }
@@ -643,7 +644,7 @@ pppstart(struct rtems_termios_tty *tp)
       }
 
       /* write out the character(s) and update the stats */
-      (*tp->handler.write)(tp, (char *)sendBegin, (ioffset > 0) ? ioffset : 1);
+      (*tp->handler.write)(ctx, (char *)sendBegin, (ioffset > 0) ? ioffset : 1);
       sc->sc_stats.ppp_obytes += (ioffset > 0) ? ioffset : 1;
       sc->sc_outoff += ioffset;
     }
diff --git a/doc/bsp_howto/console.t b/doc/bsp_howto/console.t
index a165f72..687ecda 100644
--- a/doc/bsp_howto/console.t
+++ b/doc/bsp_howto/console.t
@@ -274,6 +274,7 @@ initialization example the device name is also present.  Her is an example heade
 
 /* Low-level driver specific data structure */
 typedef struct @{
+  rtems_termios_device_context base;
   const char *device_name;
   volatile module_register_block *regs;
   /* More stuff */
@@ -298,12 +299,12 @@ characters from @code{buf} to the serial device specified by @code{tty}.
 @example
 @group
 static void my_driver_poll_write(
-  rtems_termios_tty *tty,
-  const char        *buf,
-  size_t             n
+  rtems_termios_device_context *base,
+  const char                   *buf,
+  size_t                        n
 )
 @{
-  my_driver_context *ctx = rtems_termios_get_device_context(tty);
+  my_driver_context *ctx = (my_driver_context *) base;
   size_t i;
 
   /* Write */
@@ -320,9 +321,9 @@ available, then the routine should return minus one.
 
 @example
 @group
-static int my_driver_poll_read(rtems_termios_tty *tty)
+static int my_driver_poll_read(rtems_termios_device_context *base)
 @{
-  my_driver_context *ctx = rtems_termios_get_device_context(tty);
+  my_driver_context *ctx = (my_driver_context *) base;
 
   /* Check if a character is available */
   if (my_driver_can_read_char(ctx)) @{
@@ -409,12 +410,12 @@ character.
 @example
 @group
 static void my_driver_interrupt_write(
-  rtems_termios_tty *tty,
-  const char        *buf,
-  size_t             n
+  rtems_termios_device_context  *base,
+  const char                    *buf,
+  size_t                         n
 )
 @{
-  my_driver_context *ctx = rtems_termios_get_device_context(tty);
+  my_driver_context *ctx = (my_driver_context *) base;
 
   /*
    * Tell the device to transmit some characters from buf (less than
@@ -518,10 +519,12 @@ During the first open of the device Termios will call the
 @group
 static bool my_driver_first_open(
   rtems_termios_tty             *tty,
+  rtems_termios_device_context  *base,
+  struct termios                *term,
   rtems_libio_open_close_args_t *args
 )
 @{
-  my_driver_context *ctx = rtems_termios_get_device_context(tty);
+  my_driver_context *ctx = (my_driver_context *) base;
   rtems_status_code sc;
   bool ok;
 
@@ -542,13 +545,13 @@ static bool my_driver_first_open(
   /*
    * Alternatively you can set the best baud.
    */
-  rtems_termios_set_best_baud(tty, MY_DRIVER_BAUD_RATE);
+  rtems_termios_set_best_baud(term, MY_DRIVER_BAUD_RATE);
 
   /*
    * To propagate the initial Termios attributes to the device use
    * this.
    */
-  ok = my_driver_set_attributes(tty, rtems_termios_get_termios(tty));
+  ok = my_driver_set_attributes(base, term);
   if (!ok) @{
     /* This is bad */
   @}
@@ -574,10 +577,11 @@ happens on the device.
 @group
 static void my_driver_last_close(
   rtems_termios_tty             *tty,
+  rtems_termios_device_context  *base,
   rtems_libio_open_close_args_t *args
 )
 @{
-  my_driver_context *ctx = rtems_termios_get_device_context(tty);
+  my_driver_context *ctx = (my_driver_context *) base;
 
   /*
    * The driver may do some cleanup here.
@@ -618,11 +622,11 @@ handler.
 @example
 @group
 static bool my_driver_set_attributes(
-  rtems_termios_tty    *tty,
-  const struct termios *term
+  rtems_termios_device_context *base,
+  const struct termios         *term
 )
 @{
-  my_driver_context *ctx = rtems_termios_get_device_context(tty);
+  my_driver_context *ctx = (my_driver_context *) base;
 
   /*
    * Inspect the termios data structure and configure the device
diff --git a/testsuites/libtests/termios01/init.c b/testsuites/libtests/termios01/init.c
index 080363f..c836b3d 100644
--- a/testsuites/libtests/termios01/init.c
+++ b/testsuites/libtests/termios01/init.c
@@ -517,6 +517,11 @@ static void test_termios_cfmakeraw(void)
   rtems_test_assert( term.c_cflag & CS8 );
 }
 
+typedef struct {
+  rtems_termios_device_context base;
+  bool done;
+} device_context;
+
 static rtems_status_code test_early_device_install_remove(
   rtems_device_major_number major,
   rtems_device_minor_number minor,
@@ -528,7 +533,7 @@ static rtems_status_code test_early_device_install_remove(
 
   rtems_resource_snapshot_take( &snapshot );
 
-  sc = rtems_termios_device_install( "/", 0, 0, NULL, NULL );
+  sc = rtems_termios_device_install( "/", 0, 0, NULL, NULL, NULL );
   rtems_test_assert( sc == RTEMS_INCORRECT_STATE );
 
   sc = rtems_termios_device_remove( "/", 0, 0 );
@@ -630,14 +635,18 @@ static void test_device_install_remove(void)
 
 static bool first_open_error(
   rtems_termios_tty *tty,
+  rtems_termios_device_context *base,
+  struct termios *term,
   rtems_libio_open_close_args_t *args
 )
 {
-  bool *done = rtems_termios_get_device_context( tty );
+  device_context *ctx = (device_context *) base;
 
+  (void) tty;
+  (void) term;
   (void) args;
 
-  *done = true;
+  ctx->done = true;
 
   return false;
 }
@@ -655,7 +664,10 @@ static void test_first_open_error(void)
   rtems_status_code sc;
   rtems_libio_t iop;
   rtems_libio_open_close_args_t args;
-  bool done = false;
+  device_context ctx = {
+    .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER( "abc" ),
+    .done = false
+  };
 
   rtems_resource_snapshot_take( &snapshot );
 
@@ -665,7 +677,7 @@ static void test_first_open_error(void)
     minor,
     &handler,
     NULL,
-    &done
+    &ctx.base
   );
   rtems_test_assert( sc == RTEMS_SUCCESSFUL );
 
@@ -673,10 +685,10 @@ static void test_first_open_error(void)
   memset( &args, 0, sizeof( args ) );
   args.iop = &iop;
 
-  rtems_test_assert( !done );
+  rtems_test_assert( !ctx.done );
   sc = rtems_termios_device_open( major, minor, &args );
   rtems_test_assert( sc == RTEMS_NO_MEMORY );
-  rtems_test_assert( done );
+  rtems_test_assert( ctx.done );
 
   sc = rtems_termios_device_remove( &dev[0], major, minor );
   rtems_test_assert( sc == RTEMS_SUCCESSFUL );
@@ -685,15 +697,15 @@ static void test_first_open_error(void)
 }
 
 static bool set_attributes_error(
-  rtems_termios_tty *tty,
+  rtems_termios_device_context *base,
   const struct termios *term
 )
 {
-  bool *done = rtems_termios_get_device_context( tty );
+  device_context *ctx = (device_context *) base;
 
   (void) term;
 
-  *done = true;
+  ctx->done = true;
 
   return false;
 }
@@ -713,7 +725,10 @@ static void test_set_attributes_error(void)
   rtems_libio_open_close_args_t oc_args;
   rtems_libio_ioctl_args_t io_args;
   struct termios term;
-  bool done = false;
+  device_context ctx = {
+    .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER( "abc" ),
+    .done = false
+  };
 
   rtems_resource_snapshot_take( &snapshot );
 
@@ -723,7 +738,7 @@ static void test_set_attributes_error(void)
     minor,
     &handler,
     NULL,
-    &done
+    &ctx.base
   );
   rtems_test_assert( sc == RTEMS_SUCCESSFUL );
 
@@ -739,10 +754,10 @@ static void test_set_attributes_error(void)
   io_args.command = RTEMS_IO_SET_ATTRIBUTES;
   io_args.buffer = &term;
 
-  rtems_test_assert( !done );
+  rtems_test_assert( !ctx.done );
   sc = rtems_termios_ioctl( &io_args );
   rtems_test_assert( sc == RTEMS_IO_ERROR );
-  rtems_test_assert( done );
+  rtems_test_assert( ctx.done );
 
   sc = rtems_termios_device_close( &oc_args );
   rtems_test_assert( sc == RTEMS_SUCCESSFUL );
@@ -790,15 +805,14 @@ static void test_set_best_baud(void)
   size_t i;
 
   for ( i = 0; i < n; ++i ) {
-    rtems_termios_tty tty;
-    struct termios *term = rtems_termios_get_termios( &tty );
+    struct termios term;
     tcflag_t cbaud_mask = CBAUD;
 
-    memset( &tty, 0xff, sizeof( tty ) );
-    rtems_termios_set_best_baud( &tty, baud_to_cflag_table[ i ].baud );
+    memset( &term, 0xff, sizeof( term ) );
+    rtems_termios_set_best_baud( &term, baud_to_cflag_table[ i ].baud );
 
     rtems_test_assert(
-      (term->c_cflag & cbaud_mask) == baud_to_cflag_table[ i ].cflag
+      (term.c_cflag & cbaud_mask) == baud_to_cflag_table[ i ].cflag
     );
   }
 }



More information about the vc mailing list