[rtems commit] libchip/serial: Add alternative NS16550 driver

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


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

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

libchip/serial: Add alternative NS16550 driver

Use the Termios device API.

---

 c/src/lib/libbsp/arm/altera-cyclone-v/Makefile.am  |    7 +-
 .../arm/altera-cyclone-v/console/console-config.c  |  159 ++---
 c/src/lib/libbsp/arm/lpc176x/Makefile.am           |    7 +-
 .../libbsp/arm/lpc176x/console/console-config.c    |  168 +++---
 c/src/lib/libbsp/arm/lpc24xx/Makefile.am           |    7 +-
 .../libbsp/arm/lpc24xx/console/console-config.c    |  151 +++---
 .../lib/libbsp/arm/lpc24xx/console/uart-probe-1.c  |   10 +-
 .../lib/libbsp/arm/lpc24xx/console/uart-probe-2.c  |   10 +-
 .../lib/libbsp/arm/lpc24xx/console/uart-probe-3.c  |   10 +-
 c/src/lib/libbsp/arm/lpc24xx/include/bsp.h         |   12 +-
 c/src/lib/libbsp/arm/lpc32xx/Makefile.am           |   12 +-
 .../libbsp/arm/lpc32xx/console/console-config.c    |  259 ++++----
 c/src/lib/libbsp/arm/lpc32xx/console/hsu.c         |  192 +++---
 c/src/lib/libbsp/arm/lpc32xx/include/hsu.h         |   68 ++
 c/src/lib/libbsp/arm/lpc32xx/preinstall.am         |    4 +
 c/src/lib/libbsp/powerpc/gen83xx/Makefile.am       |   10 +-
 .../powerpc/gen83xx/console/console-config.c       |  114 ++--
 .../lib/libbsp/powerpc/gen83xx/startup/bspstart.c  |   34 +-
 c/src/lib/libbsp/powerpc/qoriq/Makefile.am         |   14 +-
 .../libbsp/powerpc/qoriq/console/console-config.c  |  195 +++---
 .../powerpc/qoriq/console/uart-bridge-master.c     |   88 ++--
 .../powerpc/qoriq/console/uart-bridge-slave.c      |  114 ++--
 .../lib/libbsp/powerpc/qoriq/include/uart-bridge.h |   18 +-
 c/src/lib/libbsp/powerpc/qoriq/startup/bspstart.c  |   40 +-
 c/src/libchip/Makefile.am                          |    1 +
 c/src/libchip/serial/ns16550-context.c             |  677 ++++++++++++++++++++
 c/src/libchip/serial/ns16550.c                     |  100 +++-
 c/src/libchip/serial/ns16550.h                     |   32 +
 c/src/libchip/serial/ns16550_p.h                   |   76 ---
 29 files changed, 1640 insertions(+), 949 deletions(-)

diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/Makefile.am b/c/src/lib/libbsp/arm/altera-cyclone-v/Makefile.am
index fdae4f2..6e2d431 100644
--- a/c/src/lib/libbsp/arm/altera-cyclone-v/Makefile.am
+++ b/c/src/lib/libbsp/arm/altera-cyclone-v/Makefile.am
@@ -190,11 +190,8 @@ libbsp_a_SOURCES += ../shared/arm-gic-irq.c
 libbsp_a_SOURCES += network/network.c
 
 # Console
-libbsp_a_SOURCES += ../../shared/console.c
-libbsp_a_SOURCES += ../../shared/console_control.c
-libbsp_a_SOURCES += ../../shared/console_read.c
-libbsp_a_SOURCES += ../../shared/console_select_simple.c
-libbsp_a_SOURCES += ../../shared/console_write.c
+libbsp_a_SOURCES += ../../shared/console-termios-init.c
+libbsp_a_SOURCES += ../../shared/console-termios.c
 libbsp_a_SOURCES += console/console-config.c
 
 # Clock
diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/console/console-config.c b/c/src/lib/libbsp/arm/altera-cyclone-v/console/console-config.c
index c2a287c..5cc7849 100644
--- a/c/src/lib/libbsp/arm/altera-cyclone-v/console/console-config.c
+++ b/c/src/lib/libbsp/arm/altera-cyclone-v/console/console-config.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013 embedded brains GmbH.  All rights reserved.
+ * Copyright (c) 2013-2014 embedded brains GmbH.  All rights reserved.
  *
  *  embedded brains GmbH
  *  Dornierstr. 4
@@ -12,28 +12,23 @@
  * http://www.rtems.org/license/LICENSE.
  */
 
-#include <assert.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <libchip/serial.h>
 #include <libchip/ns16550.h>
 
 #include <bsp.h>
 #include <bsp/irq.h>
 #include <bsp/alt_clock_manager.h>
+#include <bsp/console-termios.h>
 #include "socal/alt_rstmgr.h"
 #include "socal/socal.h"
 #include "socal/alt_uart.h"
 #include "socal/hps.h"
 
 #ifdef BSP_USE_UART_INTERRUPTS
-  #define DEVICE_FNS &ns16550_fns
+  #define DEVICE_FNS &ns16550_handler_interrupt
 #else
-  #define DEVICE_FNS &ns16550_fns_polled
+  #define DEVICE_FNS &ns16550_handler_polled
 #endif
 
-static bool altera_cyclone_v_uart_probe( int minor );
-
 static uint8_t altera_cyclone_v_uart_get_register(uintptr_t addr, uint8_t i)
 {
   volatile uint32_t *reg = (volatile uint32_t *) addr;
@@ -48,92 +43,25 @@ static void altera_cyclone_v_uart_set_register(uintptr_t addr, uint8_t i, uint8_
   reg [i] = val;
 }
 
-console_tbl Console_Configuration_Ports[] = {
-#ifdef CYCLONE_V_CONFIG_CONSOLE
-  {
-    .sDeviceName   = "/dev/ttyS0",
-    .deviceType    = SERIAL_NS16550,
-    .pDeviceFns    = DEVICE_FNS,
-    .deviceProbe   = altera_cyclone_v_uart_probe,
-    .pDeviceFlow   = NULL,
-    .ulMargin      = 16,
-    .ulHysteresis  = 8,
-    .pDeviceParams = (void *)CYCLONE_V_UART_BAUD,
-    .ulCtrlPort1   = (uint32_t)ALT_UART0_ADDR,
-    .ulCtrlPort2   = 0,
-    .ulDataPort    = (uint32_t)ALT_UART0_ADDR,
-    .getRegister   = altera_cyclone_v_uart_get_register,
-    .setRegister   = altera_cyclone_v_uart_set_register,
-    .getData       = NULL,
-    .setData       = NULL,
-    .ulClock       = 0,
-    .ulIntVector   = ALT_INT_INTERRUPT_UART0
-  },
-#endif
-#ifdef CYCLONE_V_CONFIG_UART_1
-  {
-    .sDeviceName   = "/dev/ttyS1",
-    .deviceType    = SERIAL_NS16550,
-    .pDeviceFns    = DEVICE_FNS,
-    .deviceProbe   = altera_cyclone_v_uart_probe,
-    .pDeviceFlow   = NULL,
-    .ulMargin      = 16,
-    .ulHysteresis  = 8,
-    .pDeviceParams = (void *)CYCLONE_V_UART_BAUD,
-    .ulCtrlPort1   = (uint32_t)ALT_UART1_ADDR,
-    .ulCtrlPort2   = 0,
-    .ulDataPort    = (uint32_t)ALT_UART1_ADDR,
-    .getRegister   = altera_cyclone_v_uart_get_register,
-    .setRegister   = altera_cyclone_v_uart_set_register,
-    .getData       = NULL,
-    .setData       = NULL,
-    .ulClock       = 0,
-    .ulIntVector   = ALT_INT_INTERRUPT_UART1
-  }
-#endif
-};
-
-unsigned long Console_Configuration_Count =
-  RTEMS_ARRAY_SIZE(Console_Configuration_Ports);
-
-bool altera_cyclone_v_uart_probe(int minor)
+static bool altera_cyclone_v_uart_probe(
+  rtems_termios_device_context *base,
+  uint32_t uart_set_mask
+)
 {
+  ns16550_context *ctx = (ns16550_context *) base;
   bool            ret           = true;
-  uint32_t        uart_set_mask;
   uint32_t        ucr;
   ALT_STATUS_CODE sc;
-  void*           location;
+  void*           location = (void *) ctx->port;
 
   /* The ALT_CLK_L4_SP is required for all SoCFPGA UARTs. 
    * Check that it's enabled. */
-  assert( alt_clk_is_enabled(ALT_CLK_L4_SP) == ALT_E_TRUE );
   if ( alt_clk_is_enabled(ALT_CLK_L4_SP) != ALT_E_TRUE ) {
     ret = false;
   }
 
   if ( ret ) {
-    switch(minor)
-    {
-      case(0):
-        /* UART 0 */
-        uart_set_mask = ALT_RSTMGR_PERMODRST_UART0_SET_MSK;
-        location      = ALT_UART0_ADDR;
-      break;
-      case(1):
-        /* UART 1 */
-        uart_set_mask = ALT_RSTMGR_PERMODRST_UART1_SET_MSK;
-        location      = ALT_UART1_ADDR;
-      break;
-      default:
-        /* Unknown case */
-        assert( minor == 0 || minor == 1 );
-        ret = false;
-      break;
-    }
-  }
-  if ( ret ) {
-    sc = alt_clk_freq_get(ALT_CLK_L4_SP, &Console_Configuration_Ports[minor].ulClock);
-    assert( sc == ALT_E_SUCCESS );
+    sc = alt_clk_freq_get(ALT_CLK_L4_SP, &ctx->clock);
     if ( sc != ALT_E_SUCCESS ) {
       ret = false;
     }
@@ -145,8 +73,6 @@ bool altera_cyclone_v_uart_probe(int minor)
 
     // Verify the UCR (UART Component Version)
     ucr = alt_read_word( ALT_UART_UCV_ADDR( location ) );
-
-    assert( ucr == ALT_UART_UCV_UART_COMPONENT_VER_RESET );
     if ( ucr != ALT_UART_UCV_UART_COMPONENT_VER_RESET ) {
       ret = false;
     }
@@ -158,22 +84,75 @@ bool altera_cyclone_v_uart_probe(int minor)
 
     // Read the MSR to work around case:119085.
     (void)alt_read_word( ALT_UART_MSR_ADDR( location ) );
+
+    ret = ns16550_probe( base );
   }
 
   return ret;
 }
 
+#ifdef CYCLONE_V_CONFIG_CONSOLE
+static bool altera_cyclone_v_uart_probe_0(rtems_termios_device_context *base)
+{
+  return altera_cyclone_v_uart_probe(base, ALT_RSTMGR_PERMODRST_UART0_SET_MSK);
+}
+
+static ns16550_context altera_cyclone_v_uart_context_0 = {
+  .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 0"),
+  .get_reg = altera_cyclone_v_uart_get_register,
+  .set_reg = altera_cyclone_v_uart_set_register,
+  .port = (uintptr_t) ALT_UART0_ADDR,
+  .irq = ALT_INT_INTERRUPT_UART0,
+  .initial_baud = CYCLONE_V_UART_BAUD
+};
+#endif
+
+#ifdef CYCLONE_V_CONFIG_CONSOLE
+static bool altera_cyclone_v_uart_probe_1(rtems_termios_device_context *base)
+{
+  return altera_cyclone_v_uart_probe(base, ALT_RSTMGR_PERMODRST_UART1_SET_MSK);
+}
+
+static ns16550_context altera_cyclone_v_uart_context_1 = {
+  .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 1"),
+  .get_reg = altera_cyclone_v_uart_get_register,
+  .set_reg = altera_cyclone_v_uart_set_register,
+  .port = (uintptr_t) ALT_UART1_ADDR,
+  .irq = ALT_INT_INTERRUPT_UART1,
+  .initial_baud = CYCLONE_V_UART_BAUD
+};
+#endif
+
+const console_device console_device_table[] = {
+  #ifdef CYCLONE_V_CONFIG_CONSOLE
+    {
+      .device_file = "/dev/ttyS0",
+      .probe = altera_cyclone_v_uart_probe_0,
+      .handler = DEVICE_FNS,
+      .context = &altera_cyclone_v_uart_context_0.base
+    },
+  #endif
+  #ifdef CYCLONE_V_CONFIG_UART_1
+    {
+      .device_file = "/dev/ttyS1",
+      .probe = altera_cyclone_v_uart_probe_1,
+      .handler = DEVICE_FNS,
+      .context = &altera_cyclone_v_uart_context_1.base
+    },
+  #endif
+};
+
+const size_t console_device_count = RTEMS_ARRAY_SIZE(console_device_table);
+
 static void output_char(char c)
 {
-  int minor = (int) Console_Port_Minor;
-  console_tbl *ct = Console_Port_Tbl != NULL ?
-    Console_Port_Tbl[minor] : &Console_Configuration_Ports[minor];
+  rtems_termios_device_context *ctx = console_device_table[0].context;
 
   if (c == '\n') {
-    ns16550_outch_polled( ct, '\r' );
+    ns16550_polled_putchar( ctx, '\r' );
   }
 
-  ns16550_outch_polled( ct, c );
+  ns16550_polled_putchar( ctx, c );
 }
 
 BSP_output_char_function_type BSP_output_char = output_char;
diff --git a/c/src/lib/libbsp/arm/lpc176x/Makefile.am b/c/src/lib/libbsp/arm/lpc176x/Makefile.am
index bbd2fec..3f60f23 100644
--- a/c/src/lib/libbsp/arm/lpc176x/Makefile.am
+++ b/c/src/lib/libbsp/arm/lpc176x/Makefile.am
@@ -110,11 +110,8 @@ libbsp_a_SOURCES += ../shared/armv7m/irq/armv7m-irq-dispatch.c
 libbsp_a_SOURCES += irq/irq.c
 
 # Console
-libbsp_a_SOURCES += ../../shared/console.c
-libbsp_a_SOURCES += ../../shared/console_control.c
-libbsp_a_SOURCES += ../../shared/console_read.c
-libbsp_a_SOURCES += ../../shared/console_select.c
-libbsp_a_SOURCES += ../../shared/console_write.c
+libbsp_a_SOURCES += ../../shared/console-termios-init.c
+libbsp_a_SOURCES += ../../shared/console-termios.c
 libbsp_a_SOURCES += console/console-config.c
 
 # Clock
diff --git a/c/src/lib/libbsp/arm/lpc176x/console/console-config.c b/c/src/lib/libbsp/arm/lpc176x/console/console-config.c
index 246a9e6..3b56a2c 100644
--- a/c/src/lib/libbsp/arm/lpc176x/console/console-config.c
+++ b/c/src/lib/libbsp/arm/lpc176x/console/console-config.c
@@ -7,10 +7,10 @@
  */
 
 /*
- * Copyright (c) 2008-2011 embedded brains GmbH.  All rights reserved.
+ * Copyright (c) 2008-2014 embedded brains GmbH.  All rights reserved.
  *
  *  embedded brains GmbH
- *  Obere Lagerstr. 30
+ *  Dornierstr. 4
  *  82178 Puchheim
  *  Germany
  *  <rtems at embedded-brains.de>
@@ -20,12 +20,12 @@
  * http://www.rtems.com/license/LICENSE.
  */
 
-#include <libchip/serial.h>
 #include <libchip/ns16550.h>
 
 #include <bsp.h>
 #include <bsp/io.h>
 #include <bsp/irq.h>
+#include <bsp/console-termios.h>
 
 /**
  * @brief Gets the uart register according to the current address.
@@ -62,97 +62,91 @@ static inline void lpc176x_uart_set_register(
   reg[ i ] = val;
 }
 
-/**
- * @brief Represents the uart configuration ports.
- */
-console_tbl Console_Configuration_Ports[] = {
 #ifdef LPC176X_CONFIG_CONSOLE
-  {
-    .sDeviceName = "/dev/ttyS0",
-    .deviceType = SERIAL_NS16550_WITH_FDR,
-    .pDeviceFns = &ns16550_fns,
-    .deviceProbe = NULL,
-    .pDeviceFlow = NULL,
-    .ulMargin = 16,
-    .ulHysteresis = 8,
-    .pDeviceParams = (void *) LPC176X_UART_BAUD,
-    .ulCtrlPort1 = UART0_BASE_ADDR,
-    .ulCtrlPort2 = 0,
-    .ulDataPort = UART0_BASE_ADDR,
-    .getRegister = lpc176x_uart_get_register,
-    .setRegister = lpc176x_uart_set_register,
-    .getData = NULL,
-    .setData = NULL,
-    .ulClock = LPC176X_PCLK,
-    .ulIntVector = LPC176X_IRQ_UART_0
-  },
+static ns16550_context lpc176x_uart_context_0 = {
+  .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 0"),
+  .get_reg = lpc176x_uart_get_register,
+  .set_reg = lpc176x_uart_set_register,
+  .port = UART0_BASE_ADDR,
+  .irq = LPC176X_IRQ_UART_0,
+  .clock = LPC176X_PCLK,
+  .initial_baud = LPC176X_UART_BAUD,
+  .has_fractional_divider_register = true
+};
 #endif
+
 #ifdef LPC176X_CONFIG_UART_1
-  {
-    .sDeviceName = "/dev/ttyS1",
-    .deviceType = SERIAL_NS16550_WITH_FDR,
-    .pDeviceFns = &ns16550_fns,
-    .deviceProbe = lpc176x_uart_probe_1,
-    .pDeviceFlow = NULL,
-    .ulMargin = 16,
-    .ulHysteresis = 8,
-    .pDeviceParams = (void *) LPC176X_UART_BAUD,
-    .ulCtrlPort1 = UART1_BASE_ADDR,
-    .ulCtrlPort2 = 0,
-    .ulDataPort = UART1_BASE_ADDR,
-    .getRegister = lpc176x_uart_get_register,
-    .setRegister = lpc176x_uart_set_register,
-    .getData = NULL,
-    .setData = NULL,
-    .ulClock = LPC176X_PCLK,
-    .ulIntVector = LPC176X_IRQ_UART_1
-  },
+static ns16550_context lpc176x_uart_context_1 = {
+  .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 1"),
+  .get_reg = lpc176x_uart_get_register,
+  .set_reg = lpc176x_uart_set_register,
+  .port = UART1_BASE_ADDR,
+  .irq = LPC176X_IRQ_UART_1,
+  .clock = LPC176X_PCLK,
+  .initial_baud = LPC176X_UART_BAUD,
+  .has_fractional_divider_register = true
+};
 #endif
+
 #ifdef LPC176X_CONFIG_UART_2
-  {
-    .sDeviceName = "/dev/ttyS2",
-    .deviceType = SERIAL_NS16550_WITH_FDR,
-    .pDeviceFns = &ns16550_fns,
-    .deviceProbe = lpc176x_uart_probe_2,
-    .pDeviceFlow = NULL,
-    .ulMargin = 16,
-    .ulHysteresis = 8,
-    .pDeviceParams = (void *) LPC176X_UART_BAUD,
-    .ulCtrlPort1 = UART2_BASE_ADDR,
-    .ulCtrlPort2 = 0,
-    .ulDataPort = UART2_BASE_ADDR,
-    .getRegister = lpc176x_uart_get_register,
-    .setRegister = lpc176x_uart_set_register,
-    .getData = NULL,
-    .setData = NULL,
-    .ulClock = LPC176X_PCLK,
-    .ulIntVector = LPC176X_IRQ_UART_2
-  },
+static ns16550_context lpc176x_uart_context_2 = {
+  .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 2"),
+  .get_reg = lpc176x_uart_get_register,
+  .set_reg = lpc176x_uart_set_register,
+  .port = UART2_BASE_ADDR,
+  .irq = LPC176X_IRQ_UART_2,
+  .clock = LPC176X_PCLK,
+  .initial_baud = LPC176X_UART_BAUD,
+  .has_fractional_divider_register = true
+};
 #endif
+
 #ifdef LPC176X_CONFIG_UART_3
-  {
-    .sDeviceName = "/dev/ttyS3",
-    .deviceType = SERIAL_NS16550_WITH_FDR,
-    .pDeviceFns = &ns16550_fns,
-    .deviceProbe = lpc176x_uart_probe_3,
-    .pDeviceFlow = NULL,
-    .ulMargin = 16,
-    .ulHysteresis = 8,
-    .pDeviceParams = (void *) LPC176X_UART_BAUD,
-    .ulCtrlPort1 = UART3_BASE_ADDR,
-    .ulCtrlPort2 = 0,
-    .ulDataPort = UART3_BASE_ADDR,
-    .getRegister = lpc176x_uart_get_register,
-    .setRegister = lpc176x_uart_set_register,
-    .getData = NULL,
-    .setData = NULL,
-    .ulClock = LPC176X_PCLK,
-    .ulIntVector = LPC176X_IRQ_UART_3
-  },
-#endif
+static ns16550_context lpc176x_uart_context_3 = {
+  .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 3"),
+  .get_reg = lpc176x_uart_get_register,
+  .set_reg = lpc176x_uart_set_register,
+  .port = UART3_BASE_ADDR,
+  .irq = LPC176X_IRQ_UART_3,
+  .clock = LPC176X_PCLK,
+  .initial_baud = LPC176X_UART_BAUD,
+  .has_fractional_divider_register = true
 };
+#endif
 
-#define LPC176X_UART_COUNT ( sizeof( Console_Configuration_Ports ) \
-                             / sizeof( Console_Configuration_Ports[ 0 ] ) )
+const console_device console_device_table[] = {
+  #ifdef LPC176X_CONFIG_CONSOLE
+    {
+      .device_file = "/dev/ttyS0",
+      .probe = console_device_probe_default,
+      .handler = &ns16550_handler_interrupt,
+      .context = &lpc176x_uart_context_0.base
+    },
+  #endif
+  #ifdef LPC176X_CONFIG_UART_1
+    {
+      .device_file = "/dev/ttyS1",
+      .probe = ns16550_probe,
+      .handler = &ns16550_handler_interrupt,
+      .context = &lpc176x_uart_context_1.base
+    },
+  #endif
+  #ifdef LPC176X_CONFIG_UART_2
+    {
+      .device_file = "/dev/ttyS2",
+      .probe = ns16550_probe,
+      .handler = &ns16550_handler_interrupt,
+      .context = &lpc176x_uart_context_2.base
+    },
+  #endif
+  #ifdef LPC176X_CONFIG_UART_3
+    {
+      .device_file = "/dev/ttyS3",
+      .probe = ns16550_probe,
+      .handler = &ns16550_handler_interrupt,
+      .context = &lpc176x_uart_context_3.base
+    },
+  #endif
+};
 
-unsigned long Console_Configuration_Count = LPC176X_UART_COUNT;
+const size_t console_device_count = RTEMS_ARRAY_SIZE(console_device_table);
diff --git a/c/src/lib/libbsp/arm/lpc24xx/Makefile.am b/c/src/lib/libbsp/arm/lpc24xx/Makefile.am
index 3ff85d6..c7fcb86 100644
--- a/c/src/lib/libbsp/arm/lpc24xx/Makefile.am
+++ b/c/src/lib/libbsp/arm/lpc24xx/Makefile.am
@@ -121,11 +121,8 @@ libbsp_a_SOURCES += irq/irq.c
 libbsp_a_SOURCES += irq/irq-dispatch.c
 
 # Console
-libbsp_a_SOURCES += ../../shared/console.c
-libbsp_a_SOURCES += ../../shared/console_control.c
-libbsp_a_SOURCES += ../../shared/console_read.c
-libbsp_a_SOURCES += ../../shared/console_select.c
-libbsp_a_SOURCES += ../../shared/console_write.c
+libbsp_a_SOURCES += ../../shared/console-termios-init.c
+libbsp_a_SOURCES += ../../shared/console-termios.c
 libbsp_a_SOURCES += console/console-config.c
 libbsp_a_SOURCES += console/uart-probe-1.c
 libbsp_a_SOURCES += console/uart-probe-2.c
diff --git a/c/src/lib/libbsp/arm/lpc24xx/console/console-config.c b/c/src/lib/libbsp/arm/lpc24xx/console/console-config.c
index cce146f..de94552 100644
--- a/c/src/lib/libbsp/arm/lpc24xx/console/console-config.c
+++ b/c/src/lib/libbsp/arm/lpc24xx/console/console-config.c
@@ -7,10 +7,10 @@
  */
 
 /*
- * Copyright (c) 2008-2011 embedded brains GmbH.  All rights reserved.
+ * Copyright (c) 2008-2014 embedded brains GmbH.  All rights reserved.
  *
  *  embedded brains GmbH
- *  Obere Lagerstr. 30
+ *  Dornierstr. 4
  *  82178 Puchheim
  *  Germany
  *  <rtems at embedded-brains.de>
@@ -20,13 +20,15 @@
  * http://www.rtems.org/license/LICENSE.
  */
 
-#include <libchip/serial.h>
+#include <rtems/console.h>
+
 #include <libchip/ns16550.h>
 
 #include <bsp.h>
 #include <bsp/lpc24xx.h>
 #include <bsp/irq.h>
 #include <bsp/io.h>
+#include <bsp/console-termios.h>
 
 static uint8_t lpc24xx_uart_get_register(uintptr_t addr, uint8_t i)
 {
@@ -42,94 +44,91 @@ static void lpc24xx_uart_set_register(uintptr_t addr, uint8_t i, uint8_t val)
   reg [i] = val;
 }
 
-console_tbl Console_Configuration_Ports [] = {
+#ifdef LPC24XX_CONFIG_CONSOLE
+static ns16550_context lpc24xx_uart_context_0 = {
+  .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 0"),
+  .get_reg = lpc24xx_uart_get_register,
+  .set_reg = lpc24xx_uart_set_register,
+  .port = UART0_BASE_ADDR,
+  .irq = LPC24XX_IRQ_UART_0,
+  .clock = LPC24XX_PCLK,
+  .initial_baud = LPC24XX_UART_BAUD,
+  .has_fractional_divider_register = true
+};
+#endif
+
+#ifdef LPC24XX_CONFIG_UART_1
+static ns16550_context lpc24xx_uart_context_1 = {
+  .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 1"),
+  .get_reg = lpc24xx_uart_get_register,
+  .set_reg = lpc24xx_uart_set_register,
+  .port = UART1_BASE_ADDR,
+  .irq = LPC24XX_IRQ_UART_1,
+  .clock = LPC24XX_PCLK,
+  .initial_baud = LPC24XX_UART_BAUD,
+  .has_fractional_divider_register = true
+};
+#endif
+
+#ifdef LPC24XX_CONFIG_UART_2
+static ns16550_context lpc24xx_uart_context_2 = {
+  .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 2"),
+  .get_reg = lpc24xx_uart_get_register,
+  .set_reg = lpc24xx_uart_set_register,
+  .port = UART2_BASE_ADDR,
+  .irq = LPC24XX_IRQ_UART_2,
+  .clock = LPC24XX_PCLK,
+  .initial_baud = LPC24XX_UART_BAUD,
+  .has_fractional_divider_register = true
+};
+#endif
+
+#ifdef LPC24XX_CONFIG_UART_3
+static ns16550_context lpc24xx_uart_context_3 = {
+  .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 3"),
+  .get_reg = lpc24xx_uart_get_register,
+  .set_reg = lpc24xx_uart_set_register,
+  .port = UART3_BASE_ADDR,
+  .irq = LPC24XX_IRQ_UART_3,
+  .clock = LPC24XX_PCLK,
+  .initial_baud = LPC24XX_UART_BAUD,
+  .has_fractional_divider_register = true
+};
+#endif
+
+const console_device console_device_table[] = {
   #ifdef LPC24XX_CONFIG_CONSOLE
     {
-      .sDeviceName = "/dev/ttyS0",
-      .deviceType = SERIAL_NS16550_WITH_FDR,
-      .pDeviceFns = &ns16550_fns,
-      .deviceProbe = NULL,
-      .pDeviceFlow = NULL,
-      .ulMargin = 16,
-      .ulHysteresis = 8,
-      .pDeviceParams = (void *) LPC24XX_UART_BAUD,
-      .ulCtrlPort1 = UART0_BASE_ADDR,
-      .ulCtrlPort2 = 0,
-      .ulDataPort = UART0_BASE_ADDR,
-      .getRegister = lpc24xx_uart_get_register,
-      .setRegister = lpc24xx_uart_set_register,
-      .getData = NULL,
-      .setData = NULL,
-      .ulClock = LPC24XX_PCLK,
-      .ulIntVector = LPC24XX_IRQ_UART_0
+      .device_file = "/dev/ttyS0",
+      .probe = console_device_probe_default,
+      .handler = &ns16550_handler_interrupt,
+      .context = &lpc24xx_uart_context_0.base
     },
   #endif
   #ifdef LPC24XX_CONFIG_UART_1
     {
-      .sDeviceName = "/dev/ttyS1",
-      .deviceType = SERIAL_NS16550_WITH_FDR,
-      .pDeviceFns = &ns16550_fns,
-      .deviceProbe = lpc24xx_uart_probe_1,
-      .pDeviceFlow = NULL,
-      .ulMargin = 16,
-      .ulHysteresis = 8,
-      .pDeviceParams = (void *) LPC24XX_UART_BAUD,
-      .ulCtrlPort1 = UART1_BASE_ADDR,
-      .ulCtrlPort2 = 0,
-      .ulDataPort = UART1_BASE_ADDR,
-      .getRegister = lpc24xx_uart_get_register,
-      .setRegister = lpc24xx_uart_set_register,
-      .getData = NULL,
-      .setData = NULL,
-      .ulClock = LPC24XX_PCLK,
-      .ulIntVector = LPC24XX_IRQ_UART_1
+      .device_file = "/dev/ttyS1",
+      .probe = lpc24xx_uart_probe_1,
+      .handler = &ns16550_handler_interrupt,
+      .context = &lpc24xx_uart_context_1.base
     },
   #endif
   #ifdef LPC24XX_CONFIG_UART_2
     {
-      .sDeviceName = "/dev/ttyS2",
-      .deviceType = SERIAL_NS16550_WITH_FDR,
-      .pDeviceFns = &ns16550_fns,
-      .deviceProbe = lpc24xx_uart_probe_2,
-      .pDeviceFlow = NULL,
-      .ulMargin = 16,
-      .ulHysteresis = 8,
-      .pDeviceParams = (void *) LPC24XX_UART_BAUD,
-      .ulCtrlPort1 = UART2_BASE_ADDR,
-      .ulCtrlPort2 = 0,
-      .ulDataPort = UART2_BASE_ADDR,
-      .getRegister = lpc24xx_uart_get_register,
-      .setRegister = lpc24xx_uart_set_register,
-      .getData = NULL,
-      .setData = NULL,
-      .ulClock = LPC24XX_PCLK,
-      .ulIntVector = LPC24XX_IRQ_UART_2
+      .device_file = "/dev/ttyS2",
+      .probe = lpc24xx_uart_probe_2,
+      .handler = &ns16550_handler_interrupt,
+      .context = &lpc24xx_uart_context_2.base
     },
   #endif
   #ifdef LPC24XX_CONFIG_UART_3
     {
-      .sDeviceName = "/dev/ttyS3",
-      .deviceType = SERIAL_NS16550_WITH_FDR,
-      .pDeviceFns = &ns16550_fns,
-      .deviceProbe = lpc24xx_uart_probe_3,
-      .pDeviceFlow = NULL,
-      .ulMargin = 16,
-      .ulHysteresis = 8,
-      .pDeviceParams = (void *) LPC24XX_UART_BAUD,
-      .ulCtrlPort1 = UART3_BASE_ADDR,
-      .ulCtrlPort2 = 0,
-      .ulDataPort = UART3_BASE_ADDR,
-      .getRegister = lpc24xx_uart_get_register,
-      .setRegister = lpc24xx_uart_set_register,
-      .getData = NULL,
-      .setData = NULL,
-      .ulClock = LPC24XX_PCLK,
-      .ulIntVector = LPC24XX_IRQ_UART_3
+      .device_file = "/dev/ttyS3",
+      .probe = lpc24xx_uart_probe_3,
+      .handler = &ns16550_handler_interrupt,
+      .context = &lpc24xx_uart_context_3.base
     },
   #endif
 };
 
-#define LPC24XX_UART_COUNT \
-  (sizeof(Console_Configuration_Ports) \
-    / sizeof(Console_Configuration_Ports [0]))
-unsigned long Console_Configuration_Count = LPC24XX_UART_COUNT;
+const size_t console_device_count = RTEMS_ARRAY_SIZE(console_device_table);
diff --git a/c/src/lib/libbsp/arm/lpc24xx/console/uart-probe-1.c b/c/src/lib/libbsp/arm/lpc24xx/console/uart-probe-1.c
index e3af151..3b5f080 100644
--- a/c/src/lib/libbsp/arm/lpc24xx/console/uart-probe-1.c
+++ b/c/src/lib/libbsp/arm/lpc24xx/console/uart-probe-1.c
@@ -7,10 +7,10 @@
  */
 
 /*
- * Copyright (c) 2011-2013 embedded brains GmbH.  All rights reserved.
+ * Copyright (c) 2011-2014 embedded brains GmbH.  All rights reserved.
  *
  *  embedded brains GmbH
- *  Obere Lagerstr. 30
+ *  Dornierstr. 4
  *  82178 Puchheim
  *  Germany
  *  <rtems at embedded-brains.de>
@@ -20,10 +20,12 @@
  * http://www.rtems.org/license/LICENSE.
  */
 
+#include <libchip/ns16550.h>
+
 #include <bsp.h>
 #include <bsp/io.h>
 
-bool lpc24xx_uart_probe_1(int minor)
+bool lpc24xx_uart_probe_1(rtems_termios_device_context *context)
 {
   static const lpc24xx_pin_range pins [] = {
     LPC24XX_PIN_UART_1_TXD_P0_15,
@@ -34,5 +36,5 @@ bool lpc24xx_uart_probe_1(int minor)
   lpc24xx_module_enable(LPC24XX_MODULE_UART_1, LPC24XX_MODULE_PCLK_DEFAULT);
   lpc24xx_pin_config(&pins [0], LPC24XX_PIN_SET_FUNCTION);
 
-  return true;
+  return ns16550_probe(context);
 }
diff --git a/c/src/lib/libbsp/arm/lpc24xx/console/uart-probe-2.c b/c/src/lib/libbsp/arm/lpc24xx/console/uart-probe-2.c
index 4f69d7f..d45dbb7 100644
--- a/c/src/lib/libbsp/arm/lpc24xx/console/uart-probe-2.c
+++ b/c/src/lib/libbsp/arm/lpc24xx/console/uart-probe-2.c
@@ -7,10 +7,10 @@
  */
 
 /*
- * Copyright (c) 2011-2013 embedded brains GmbH.  All rights reserved.
+ * Copyright (c) 2011-2014 embedded brains GmbH.  All rights reserved.
  *
  *  embedded brains GmbH
- *  Obere Lagerstr. 30
+ *  Dornierstr. 4
  *  82178 Puchheim
  *  Germany
  *  <rtems at embedded-brains.de>
@@ -20,10 +20,12 @@
  * http://www.rtems.org/license/LICENSE.
  */
 
+#include <libchip/ns16550.h>
+
 #include <bsp.h>
 #include <bsp/io.h>
 
-bool lpc24xx_uart_probe_2(int minor)
+bool lpc24xx_uart_probe_2(rtems_termios_device_context *context)
 {
   static const lpc24xx_pin_range pins [] = {
     LPC24XX_PIN_UART_2_TXD_P0_10,
@@ -34,5 +36,5 @@ bool lpc24xx_uart_probe_2(int minor)
   lpc24xx_module_enable(LPC24XX_MODULE_UART_2, LPC24XX_MODULE_PCLK_DEFAULT);
   lpc24xx_pin_config(&pins [0], LPC24XX_PIN_SET_FUNCTION);
 
-  return true;
+  return ns16550_probe(context);
 }
diff --git a/c/src/lib/libbsp/arm/lpc24xx/console/uart-probe-3.c b/c/src/lib/libbsp/arm/lpc24xx/console/uart-probe-3.c
index d71002f..fad932e 100644
--- a/c/src/lib/libbsp/arm/lpc24xx/console/uart-probe-3.c
+++ b/c/src/lib/libbsp/arm/lpc24xx/console/uart-probe-3.c
@@ -7,10 +7,10 @@
  */
 
 /*
- * Copyright (c) 2011-2013 embedded brains GmbH.  All rights reserved.
+ * Copyright (c) 2011-2014 embedded brains GmbH.  All rights reserved.
  *
  *  embedded brains GmbH
- *  Obere Lagerstr. 30
+ *  Dornierstr. 4
  *  82178 Puchheim
  *  Germany
  *  <rtems at embedded-brains.de>
@@ -20,10 +20,12 @@
  * http://www.rtems.org/license/LICENSE.
  */
 
+#include <libchip/ns16550.h>
+
 #include <bsp.h>
 #include <bsp/io.h>
 
-bool lpc24xx_uart_probe_3(int minor)
+bool lpc24xx_uart_probe_3(rtems_termios_device_context *context)
 {
   static const lpc24xx_pin_range pins [] = {
     LPC24XX_PIN_UART_3_TXD_P0_0,
@@ -34,5 +36,5 @@ bool lpc24xx_uart_probe_3(int minor)
   lpc24xx_module_enable(LPC24XX_MODULE_UART_3, LPC24XX_MODULE_PCLK_DEFAULT);
   lpc24xx_pin_config(&pins [0], LPC24XX_PIN_SET_FUNCTION);
 
-  return true;
+  return ns16550_probe(context);
 }
diff --git a/c/src/lib/libbsp/arm/lpc24xx/include/bsp.h b/c/src/lib/libbsp/arm/lpc24xx/include/bsp.h
index fad125a..e8c5d9a 100644
--- a/c/src/lib/libbsp/arm/lpc24xx/include/bsp.h
+++ b/c/src/lib/libbsp/arm/lpc24xx/include/bsp.h
@@ -7,10 +7,10 @@
  */
 
 /*
- * Copyright (c) 2008-2013 embedded brains GmbH.  All rights reserved.
+ * Copyright (c) 2008-2014 embedded brains GmbH.  All rights reserved.
  *
  *  embedded brains GmbH
- *  Obere Lagerstr. 30
+ *  Dornierstr. 4
  *  82178 Puchheim
  *  Germany
  *  <rtems at embedded-brains.de>
@@ -53,6 +53,8 @@ extern "C" {
 
 struct rtems_bsdnet_ifconfig;
 
+struct rtems_termios_device_context;
+
 /**
  * @defgroup lpc24xx LPC24XX Support
  *
@@ -111,11 +113,11 @@ void *bsp_idle_thread(uintptr_t ignored);
 
 void bsp_restart(void *addr);
 
-bool lpc24xx_uart_probe_1(int minor);
+bool lpc24xx_uart_probe_1(struct rtems_termios_device_context *context);
 
-bool lpc24xx_uart_probe_2(int minor);
+bool lpc24xx_uart_probe_2(struct rtems_termios_device_context *context);
 
-bool lpc24xx_uart_probe_3(int minor);
+bool lpc24xx_uart_probe_3(struct rtems_termios_device_context *context);
 
 /** @} */
 
diff --git a/c/src/lib/libbsp/arm/lpc32xx/Makefile.am b/c/src/lib/libbsp/arm/lpc32xx/Makefile.am
index 0eef512..524d07e 100644
--- a/c/src/lib/libbsp/arm/lpc32xx/Makefile.am
+++ b/c/src/lib/libbsp/arm/lpc32xx/Makefile.am
@@ -48,6 +48,7 @@ include_bsp_HEADERS += include/lpc-clock-config.h
 include_bsp_HEADERS += include/lpc-ethernet-config.h
 include_bsp_HEADERS += include/nand-mlc.h
 include_bsp_HEADERS += include/boot.h
+include_bsp_HEADERS += include/hsu.h
 include_bsp_HEADERS += include/i2c.h
 include_bsp_HEADERS += include/emc.h
 
@@ -111,13 +112,10 @@ libbsp_a_SOURCES += ../../shared/src/irq-shell.c
 libbsp_a_SOURCES += irq/irq.c
 
 # Console
-libbsp_a_SOURCES += ../../shared/console.c \
-        ../../shared/console_select.c \
-	console/console-config.c \
-	console/hsu.c \
-        ../../shared/console_read.c \
-        ../../shared/console_write.c \
-        ../../shared/console_control.c
+libbsp_a_SOURCES += ../../shared/console-termios-init.c
+libbsp_a_SOURCES += ../../shared/console-termios.c
+libbsp_a_SOURCES += console/console-config.c
+libbsp_a_SOURCES += console/hsu.c
 
 # Clock
 libbsp_a_SOURCES += ../shared/lpc/clock/lpc-clock-config.c
diff --git a/c/src/lib/libbsp/arm/lpc32xx/console/console-config.c b/c/src/lib/libbsp/arm/lpc32xx/console/console-config.c
index d288985..17e6b0a 100644
--- a/c/src/lib/libbsp/arm/lpc32xx/console/console-config.c
+++ b/c/src/lib/libbsp/arm/lpc32xx/console/console-config.c
@@ -7,26 +7,26 @@
  */
 
 /*
- * Copyright (c) 2009
- * embedded brains GmbH
- * Obere Lagerstr. 30
- * D-82178 Puchheim
- * Germany
- * <rtems at embedded-brains.de>
+ * Copyright (c) 2009-2014 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Dornierstr. 4
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
  *
  * The license and distribution terms for this file may be
  * found in the file LICENSE in this distribution or at
  * http://www.rtems.org/license/LICENSE.
  */
 
-#include <libchip/serial.h>
 #include <libchip/ns16550.h>
 
 #include <bsp.h>
 #include <bsp/lpc32xx.h>
 #include <bsp/irq.h>
-
-extern const console_fns lpc32xx_hsu_fns;
+#include <bsp/hsu.h>
+#include <bsp/console-termios.h>
 
 static uint8_t lpc32xx_uart_get_register(uintptr_t addr, uint8_t i)
 {
@@ -43,18 +43,18 @@ static void lpc32xx_uart_set_register(uintptr_t addr, uint8_t i, uint8_t val)
 }
 
 #ifdef LPC32XX_UART_3_BAUD
-  static bool lpc32xx_uart_probe_3(int minor)
+  static bool lpc32xx_uart_probe_3(rtems_termios_device_context *context)
   {
     LPC32XX_UARTCLK_CTRL |= BSP_BIT32(0);
     LPC32XX_U3CLK = LPC32XX_CONFIG_U3CLK;
     LPC32XX_UART_CLKMODE = BSP_FLD32SET(LPC32XX_UART_CLKMODE, 0x2, 4, 5);
 
-    return true;
+    return ns16550_probe(context);
   }
 #endif
 
 #ifdef LPC32XX_UART_4_BAUD
-  static bool lpc32xx_uart_probe_4(int minor)
+  static bool lpc32xx_uart_probe_4(rtems_termios_device_context *context)
   {
     volatile lpc32xx_gpio *gpio = &lpc32xx.gpio;
 
@@ -68,12 +68,12 @@ static void lpc32xx_uart_set_register(uintptr_t addr, uint8_t i, uint8_t val)
     LPC32XX_U4CLK = LPC32XX_CONFIG_U4CLK;
     LPC32XX_UART_CLKMODE = BSP_FLD32SET(LPC32XX_UART_CLKMODE, 0x2, 6, 7);
 
-    return true;
+    return ns16550_probe(context);
   }
 #endif
 
 #ifdef LPC32XX_UART_6_BAUD
-  static bool lpc32xx_uart_probe_6(int minor)
+  static bool lpc32xx_uart_probe_6(rtems_termios_device_context *context)
   {
     /* Bypass the IrDA modulator/demodulator */
     LPC32XX_UART_CTRL |= BSP_BIT32(5);
@@ -82,163 +82,144 @@ static void lpc32xx_uart_set_register(uintptr_t addr, uint8_t i, uint8_t val)
     LPC32XX_U6CLK = LPC32XX_CONFIG_U6CLK;
     LPC32XX_UART_CLKMODE = BSP_FLD32SET(LPC32XX_UART_CLKMODE, 0x2, 10, 11);
 
-    return true;
+    return ns16550_probe(context);
   }
 #endif
 
 /* FIXME: Console selection */
 
-console_tbl Console_Configuration_Ports [] = {
+#ifdef LPC32XX_UART_5_BAUD
+static ns16550_context lpc32xx_uart_context_5 = {
+  .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 5"),
+  .get_reg = lpc32xx_uart_get_register,
+  .set_reg = lpc32xx_uart_set_register,
+  .port = LPC32XX_BASE_UART_5,
+  .irq = LPC32XX_IRQ_UART_5,
+  .clock = 16 * LPC32XX_UART_5_BAUD,
+  .initial_baud = LPC32XX_UART_5_BAUD
+};
+#endif
+
+#ifdef LPC32XX_UART_3_BAUD
+static ns16550_context lpc32xx_uart_context_3 = {
+  .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 3"),
+  .get_reg = lpc32xx_uart_get_register,
+  .set_reg = lpc32xx_uart_set_register,
+  .port = LPC32XX_BASE_UART_3,
+  .irq = LPC32XX_IRQ_UART_3,
+  .clock = 16 * LPC32XX_UART_3_BAUD,
+  .initial_baud = LPC32XX_UART_3_BAUD
+};
+#endif
+
+#ifdef LPC32XX_UART_4_BAUD
+static ns16550_context lpc32xx_uart_context_4 = {
+  .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 4"),
+  .get_reg = lpc32xx_uart_get_register,
+  .set_reg = lpc32xx_uart_set_register,
+  .port = LPC32XX_BASE_UART_4,
+  .irq = LPC32XX_IRQ_UART_4,
+  .clock = 16 * LPC32XX_UART_4_BAUD,
+  .initial_baud = LPC32XX_UART_4_BAUD
+};
+#endif
+
+#ifdef LPC32XX_UART_6_BAUD
+static ns16550_context lpc32xx_uart_context_6 = {
+  .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 6"),
+  .get_reg = lpc32xx_uart_get_register,
+  .set_reg = lpc32xx_uart_set_register,
+  .port = LPC32XX_BASE_UART_6,
+  .irq = LPC32XX_IRQ_UART_6,
+  .clock = 16 * LPC32XX_UART_6_BAUD,
+  .initial_baud = LPC32XX_UART_6_BAUD
+};
+#endif
+
+#ifdef LPC32XX_UART_1_BAUD
+static lpc32xx_hsu_context lpc32xx_uart_context_1 = {
+  .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 1"),
+  .hsu = (volatile lpc32xx_hsu *) LPC32XX_BASE_UART_1,
+  .irq = LPC32XX_IRQ_UART_1,
+  .initial_baud = LPC32XX_UART_1_BAUD
+};
+#endif
+
+#ifdef LPC32XX_UART_2_BAUD
+static lpc32xx_hsu_context lpc32xx_uart_context_2 = {
+  .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 2"),
+  .hsu = (volatile lpc32xx_hsu *) LPC32XX_BASE_UART_2,
+  .irq = LPC32XX_IRQ_UART_2,
+  .initial_baud = LPC32XX_UART_2_BAUD
+};
+#endif
+
+#ifdef LPC32XX_UART_7_BAUD
+static lpc32xx_hsu_context lpc32xx_uart_context_7 = {
+  .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 7"),
+  .hsu = (volatile lpc32xx_hsu *) LPC32XX_BASE_UART_7,
+  .irq = LPC32XX_IRQ_UART_7,
+  .initial_baud = LPC32XX_UART_7_BAUD
+};
+#endif
+
+const console_device console_device_table[] = {
   #ifdef LPC32XX_UART_5_BAUD
     {
-      .sDeviceName = "/dev/ttyS5",
-      .deviceType = SERIAL_NS16550,
-      .pDeviceFns = &ns16550_fns,
-      .deviceProbe = NULL,
-      .pDeviceFlow = NULL,
-      .ulMargin = 16,
-      .ulHysteresis = 8,
-      .pDeviceParams = (void *) LPC32XX_UART_5_BAUD,
-      .ulCtrlPort1 = LPC32XX_BASE_UART_5,
-      .ulCtrlPort2 = 0,
-      .ulDataPort = LPC32XX_BASE_UART_5,
-      .getRegister = lpc32xx_uart_get_register,
-      .setRegister = lpc32xx_uart_set_register,
-      .getData = NULL,
-      .setData = NULL,
-      .ulClock = 16 * LPC32XX_UART_5_BAUD,
-      .ulIntVector = LPC32XX_IRQ_UART_5
+      .device_file = "/dev/ttyS5",
+      .probe = console_device_probe_default,
+      .handler = &ns16550_handler_interrupt,
+      .context = &lpc32xx_uart_context_5.base
     },
   #endif
   #ifdef LPC32XX_UART_3_BAUD
     {
-      .sDeviceName = "/dev/ttyS3",
-      .deviceType = SERIAL_NS16550,
-      .pDeviceFns = &ns16550_fns,
-      .deviceProbe = lpc32xx_uart_probe_3,
-      .pDeviceFlow = NULL,
-      .ulMargin = 16,
-      .ulHysteresis = 8,
-      .pDeviceParams = (void *) LPC32XX_UART_3_BAUD,
-      .ulCtrlPort1 = LPC32XX_BASE_UART_3,
-      .ulCtrlPort2 = 0,
-      .ulDataPort = LPC32XX_BASE_UART_3,
-      .getRegister = lpc32xx_uart_get_register,
-      .setRegister = lpc32xx_uart_set_register,
-      .getData = NULL,
-      .setData = NULL,
-      .ulClock = 16 * LPC32XX_UART_3_BAUD,
-      .ulIntVector = LPC32XX_IRQ_UART_3
+      .device_file = "/dev/ttyS3",
+      .probe = lpc32xx_uart_probe_3,
+      .handler = &ns16550_handler_interrupt,
+      .context = &lpc32xx_uart_context_3.base
     },
   #endif
   #ifdef LPC32XX_UART_4_BAUD
     {
-      .sDeviceName = "/dev/ttyS4",
-      .deviceType = SERIAL_NS16550,
-      .pDeviceFns = &ns16550_fns,
-      .deviceProbe = lpc32xx_uart_probe_4,
-      .pDeviceFlow = NULL,
-      .ulMargin = 16,
-      .ulHysteresis = 8,
-      .pDeviceParams = (void *) LPC32XX_UART_4_BAUD,
-      .ulCtrlPort1 = LPC32XX_BASE_UART_4,
-      .ulCtrlPort2 = 0,
-      .ulDataPort = LPC32XX_BASE_UART_4,
-      .getRegister = lpc32xx_uart_get_register,
-      .setRegister = lpc32xx_uart_set_register,
-      .getData = NULL,
-      .setData = NULL,
-      .ulClock = 16 * LPC32XX_UART_4_BAUD,
-      .ulIntVector = LPC32XX_IRQ_UART_4
+      .device_file = "/dev/ttyS4",
+      .probe = lpc32xx_uart_probe_4,
+      .handler = &ns16550_handler_interrupt,
+      .context = &lpc32xx_uart_context_4.base
     },
   #endif
   #ifdef LPC32XX_UART_6_BAUD
     {
-      .sDeviceName = "/dev/ttyS6",
-      .deviceType = SERIAL_NS16550,
-      .pDeviceFns = &ns16550_fns,
-      .deviceProbe = lpc32xx_uart_probe_6,
-      .pDeviceFlow = NULL,
-      .ulMargin = 16,
-      .ulHysteresis = 8,
-      .pDeviceParams = (void *) LPC32XX_UART_6_BAUD,
-      .ulCtrlPort1 = LPC32XX_BASE_UART_6,
-      .ulCtrlPort2 = 0,
-      .ulDataPort = LPC32XX_BASE_UART_6,
-      .getRegister = lpc32xx_uart_get_register,
-      .setRegister = lpc32xx_uart_set_register,
-      .getData = NULL,
-      .setData = NULL,
-      .ulClock = 16 * LPC32XX_UART_6_BAUD,
-      .ulIntVector = LPC32XX_IRQ_UART_6
+      .device_file = "/dev/ttyS6",
+      .probe = lpc32xx_uart_probe_6,
+      .handler = &ns16550_handler_interrupt,
+      .context = &lpc32xx_uart_context_6.base
     },
   #endif
   #ifdef LPC32XX_UART_1_BAUD
     {
-      .sDeviceName = "/dev/ttyS1",
-      .deviceType = SERIAL_CUSTOM,
-      .pDeviceFns = &lpc32xx_hsu_fns,
-      .deviceProbe = NULL,
-      .pDeviceFlow = NULL,
-      .ulMargin = 16,
-      .ulHysteresis = 8,
-      .pDeviceParams = (void *) LPC32XX_UART_1_BAUD,
-      .ulCtrlPort1 = LPC32XX_BASE_UART_1,
-      .ulCtrlPort2 = 0,
-      .ulDataPort = 0,
-      .getRegister = NULL,
-      .setRegister = NULL,
-      .getData = NULL,
-      .setData = NULL,
-      .ulClock = 16,
-      .ulIntVector = LPC32XX_IRQ_UART_1
+      .device_file = "/dev/ttyS1",
+      .probe = lpc32xx_hsu_probe,
+      .handler = &lpc32xx_hsu_fns,
+      .context = &lpc32xx_uart_context_1.base
     },
   #endif
   #ifdef LPC32XX_UART_2_BAUD
     {
-      .sDeviceName = "/dev/ttyS2",
-      .deviceType = SERIAL_CUSTOM,
-      .pDeviceFns = &lpc32xx_hsu_fns,
-      .deviceProbe = NULL,
-      .pDeviceFlow = NULL,
-      .ulMargin = 16,
-      .ulHysteresis = 8,
-      .pDeviceParams = (void *) LPC32XX_UART_2_BAUD,
-      .ulCtrlPort1 = LPC32XX_BASE_UART_2,
-      .ulCtrlPort2 = 0,
-      .ulDataPort = 0,
-      .getRegister = NULL,
-      .setRegister = NULL,
-      .getData = NULL,
-      .setData = NULL,
-      .ulClock = 16,
-      .ulIntVector = LPC32XX_IRQ_UART_2
+      .device_file = "/dev/ttyS2",
+      .probe = lpc32xx_hsu_probe,
+      .handler = &lpc32xx_hsu_fns,
+      .context = &lpc32xx_uart_context_2.base
     },
   #endif
   #ifdef LPC32XX_UART_7_BAUD
     {
-      .sDeviceName = "/dev/ttyS7",
-      .deviceType = SERIAL_CUSTOM,
-      .pDeviceFns = &lpc32xx_hsu_fns,
-      .deviceProbe = NULL,
-      .pDeviceFlow = NULL,
-      .ulMargin = 16,
-      .ulHysteresis = 8,
-      .pDeviceParams = (void *) LPC32XX_UART_7_BAUD,
-      .ulCtrlPort1 = LPC32XX_BASE_UART_7,
-      .ulCtrlPort2 = 0,
-      .ulDataPort = 0,
-      .getRegister = NULL,
-      .setRegister = NULL,
-      .getData = NULL,
-      .setData = NULL,
-      .ulClock = 16,
-      .ulIntVector = LPC32XX_IRQ_UART_7
+      .device_file = "/dev/ttyS7",
+      .probe = lpc32xx_hsu_probe,
+      .handler = &lpc32xx_hsu_fns,
+      .context = &lpc32xx_uart_context_7.base
     },
   #endif
 };
 
-#define LPC32XX_UART_COUNT \
-  (sizeof(Console_Configuration_Ports) / sizeof(Console_Configuration_Ports [0]))
-
-unsigned long Console_Configuration_Count = LPC32XX_UART_COUNT;
+const size_t console_device_count = RTEMS_ARRAY_SIZE(console_device_table);
diff --git a/c/src/lib/libbsp/arm/lpc32xx/console/hsu.c b/c/src/lib/libbsp/arm/lpc32xx/console/hsu.c
index 0dc4a61..8beeeef 100644
--- a/c/src/lib/libbsp/arm/lpc32xx/console/hsu.c
+++ b/c/src/lib/libbsp/arm/lpc32xx/console/hsu.c
@@ -7,36 +7,23 @@
  */
 
 /*
- * Copyright (c) 2010
- * embedded brains GmbH
- * Obere Lagerstr. 30
- * D-82178 Puchheim
- * Germany
- * <rtems at embedded-brains.de>
+ * Copyright (c) 2010-2014 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Dornierstr. 4
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
  *
  * The license and distribution terms for this file may be
  * found in the file LICENSE in this distribution or at
  * http://www.rtems.org/license/LICENSE.
  */
 
-#include <rtems.h>
-#include <rtems/libio.h>
-#include <rtems/termiostypes.h>
-
-#include <libchip/serial.h>
-#include <libchip/sersupp.h>
-
 #include <bsp.h>
 #include <bsp/lpc32xx.h>
 #include <bsp/irq.h>
-
-typedef struct {
-  uint32_t fifo;
-  uint32_t level;
-  uint32_t iir;
-  uint32_t ctrl;
-  uint32_t rate;
-} lpc32xx_hsu;
+#include <bsp/hsu.h>
 
 #define HSU_FIFO_SIZE 64
 
@@ -60,54 +47,29 @@ typedef struct {
 /* We are interested in RX timeout, RX trigger and TX trigger interrupts */
 #define HSU_IIR_MASK 0x7U
 
-static int lpc32xx_hsu_first_open(int major, int minor, void *arg)
-{
-  rtems_libio_open_close_args_t *oca = arg;
-  struct rtems_termios_tty *tty = oca->iop->data1;
-  console_tbl *ct = Console_Port_Tbl [minor];
-  console_data *cd = &Console_Port_Data [minor];
-  volatile lpc32xx_hsu *hsu = (volatile lpc32xx_hsu *) ct->ulCtrlPort1;
-
-  cd->termios_data = tty;
-  rtems_termios_set_initial_baud(tty, (int32_t) ct->pDeviceParams);
-  hsu->ctrl = HSU_CTRL_RX_INTR_ENABLED;
-
-  return 0;
-}
-
-static ssize_t lpc32xx_hsu_write(int minor, const char *buf, size_t len)
+bool lpc32xx_hsu_probe(rtems_termios_device_context *base)
 {
-  console_tbl *ct = Console_Port_Tbl [minor];
-  console_data *cd = &Console_Port_Data [minor];
-  volatile lpc32xx_hsu *hsu = (volatile lpc32xx_hsu *) ct->ulCtrlPort1;
-  size_t tx_level = (hsu->level & HSU_LEVEL_TX_MASK) >> HSU_LEVEL_TX_SHIFT;
-  size_t tx_free = HSU_FIFO_SIZE - tx_level;
-  size_t i = 0;
-  size_t out = len > tx_free ? tx_free : len;
+  lpc32xx_hsu_context *ctx = (lpc32xx_hsu_context *) base;
+  volatile lpc32xx_hsu *hsu = ctx->hsu;
 
-  for (i = 0; i < out; ++i) {
-    hsu->fifo = buf [i];
-  }
+  hsu->ctrl = HSU_CTRL_INTR_DISABLED;
 
-  if (len > 0) {
-    cd->pDeviceContext = (void *) out;
-    cd->bActive = true;
-    hsu->ctrl = HSU_CTRL_RX_AND_TX_INTR_ENABLED;
+  /* Drain FIFOs */
+  while (hsu->level != 0) {
+    hsu->fifo;
   }
 
-  return 0;
+  return true;
 }
 
 static void lpc32xx_hsu_interrupt_handler(void *arg)
 {
-  int minor = (int) arg;
-  console_tbl *ct = Console_Port_Tbl [minor];
-  console_data *cd = &Console_Port_Data [minor];
-  volatile lpc32xx_hsu *hsu = (volatile lpc32xx_hsu *) ct->ulCtrlPort1;
+  rtems_termios_tty *tty = arg;
+  lpc32xx_hsu_context *ctx = rtems_termios_get_device_context(tty);
+  volatile lpc32xx_hsu *hsu = ctx->hsu;
 
   /* Iterate until no more interrupts are pending */
   do {
-    int chars_to_dequeue = (int) cd->pDeviceContext;
     int rv = 0;
     int i = 0;
     char buf [HSU_FIFO_SIZE];
@@ -125,49 +87,97 @@ static void lpc32xx_hsu_interrupt_handler(void *arg)
         break;
       }
     }
-    rtems_termios_enqueue_raw_characters(cd->termios_data, buf, i);
+    rtems_termios_enqueue_raw_characters(tty, buf, i);
 
     /* Dequeue transmitted characters */
-    cd->pDeviceContext = 0;
-    rv = rtems_termios_dequeue_characters(cd->termios_data, chars_to_dequeue);
+    rv = rtems_termios_dequeue_characters(tty, (int) ctx->chars_in_transmission);
     if (rv == 0) {
       /* Nothing to transmit */
-      cd->bActive = false;
-      hsu->ctrl = HSU_CTRL_RX_INTR_ENABLED;
-      hsu->iir = HSU_IIR_TX;
     }
   } while ((hsu->iir & HSU_IIR_MASK) != 0);
 }
 
-static void lpc32xx_hsu_initialize(int minor)
+static bool lpc32xx_hsu_first_open(
+  struct rtems_termios_tty *tty,
+  rtems_termios_device_context *base,
+  struct termios *term,
+  rtems_libio_open_close_args_t *args
+)
 {
-  console_tbl *ct = Console_Port_Tbl [minor];
-  console_data *cd = &Console_Port_Data [minor];
-  volatile lpc32xx_hsu *hsu = (volatile lpc32xx_hsu *) ct->ulCtrlPort1;
-
-  hsu->ctrl = HSU_CTRL_INTR_DISABLED;
+  lpc32xx_hsu_context *ctx = (lpc32xx_hsu_context *) base;
+  volatile lpc32xx_hsu *hsu = ctx->hsu;
+  rtems_status_code sc;
+  bool ok;
 
-  cd->bActive = false;
-  cd->pDeviceContext = 0;
+  sc = rtems_interrupt_handler_install(
+    ctx->irq,
+    "HSU",
+    RTEMS_INTERRUPT_UNIQUE,
+    lpc32xx_hsu_interrupt_handler,
+    tty
+  );
+  ok = sc == RTEMS_SUCCESSFUL;
 
-  /* Drain FIFOs */
-  while (hsu->level != 0) {
-    hsu->fifo;
+  if (ok) {
+    rtems_termios_set_initial_baud(tty, ctx->initial_baud);
+    hsu->ctrl = HSU_CTRL_RX_INTR_ENABLED;
   }
 
-  rtems_interrupt_handler_install(
-    ct->ulIntVector,
-    "HSU",
-    RTEMS_INTERRUPT_UNIQUE,
+  return ok;
+}
+
+static void lpc32xx_hsu_last_close(
+  struct rtems_termios_tty *tty,
+  rtems_termios_device_context *base,
+  rtems_libio_open_close_args_t *args
+)
+{
+  lpc32xx_hsu_context *ctx = (lpc32xx_hsu_context *) base;
+  volatile lpc32xx_hsu *hsu = ctx->hsu;
+
+  hsu->ctrl = HSU_CTRL_INTR_DISABLED;
+
+  rtems_interrupt_handler_remove(
+    ctx->irq,
     lpc32xx_hsu_interrupt_handler,
-    (void *) minor
+    tty
   );
 }
 
-static int lpc32xx_hsu_set_attributes(int minor, const struct termios *term)
+static void lpc32xx_hsu_write(
+  rtems_termios_device_context *base,
+  const char *buf,
+  size_t len
+)
+{
+  lpc32xx_hsu_context *ctx = (lpc32xx_hsu_context *) base;
+  volatile lpc32xx_hsu *hsu = ctx->hsu;
+  size_t tx_level = (hsu->level & HSU_LEVEL_TX_MASK) >> HSU_LEVEL_TX_SHIFT;
+  size_t tx_free = HSU_FIFO_SIZE - tx_level;
+  size_t i = 0;
+  size_t out = len > tx_free ? tx_free : len;
+
+  for (i = 0; i < out; ++i) {
+    hsu->fifo = buf [i];
+  }
+
+  ctx->chars_in_transmission = out;
+
+  if (len > 0) {
+    hsu->ctrl = HSU_CTRL_RX_AND_TX_INTR_ENABLED;
+  } else {
+    hsu->ctrl = HSU_CTRL_RX_INTR_ENABLED;
+    hsu->iir = HSU_IIR_TX;
+  }
+}
+
+static bool lpc32xx_hsu_set_attributes(
+  rtems_termios_device_context *base,
+  const struct termios *term
+)
 {
-  console_tbl *ct = Console_Port_Tbl [minor];
-  volatile lpc32xx_hsu *hsu = (volatile lpc32xx_hsu *) ct->ulCtrlPort1;
+  lpc32xx_hsu_context *ctx = (lpc32xx_hsu_context *) base;
+  volatile lpc32xx_hsu *hsu = ctx->hsu;
   int baud_flags = term->c_cflag & CBAUD;
 
   if (baud_flags != 0) {
@@ -186,17 +196,13 @@ static int lpc32xx_hsu_set_attributes(int minor, const struct termios *term)
     }
   }
 
-  return 0;
+  return true;
 }
 
-const console_fns lpc32xx_hsu_fns = {
-  .deviceProbe = libchip_serial_default_probe,
-  .deviceFirstOpen = lpc32xx_hsu_first_open,
-  .deviceLastClose = NULL,
-  .deviceRead = NULL,
-  .deviceWrite = lpc32xx_hsu_write,
-  .deviceInitialize = lpc32xx_hsu_initialize,
-  .deviceWritePolled = NULL,
-  .deviceSetAttributes = lpc32xx_hsu_set_attributes,
-  .deviceOutputUsesInterrupts = true
+const rtems_termios_device_handler lpc32xx_hsu_fns = {
+  .first_open = lpc32xx_hsu_first_open,
+  .last_close = lpc32xx_hsu_last_close,
+  .write = lpc32xx_hsu_write,
+  .set_attributes = lpc32xx_hsu_set_attributes,
+  .mode = TERMIOS_IRQ_DRIVEN
 };
diff --git a/c/src/lib/libbsp/arm/lpc32xx/include/hsu.h b/c/src/lib/libbsp/arm/lpc32xx/include/hsu.h
new file mode 100644
index 0000000..ba97dfb
--- /dev/null
+++ b/c/src/lib/libbsp/arm/lpc32xx/include/hsu.h
@@ -0,0 +1,68 @@
+/**
+ * @file
+ *
+ * @ingroup lpc32xx_hsu
+ *
+ * @brief HSU support API.
+ */
+
+/*
+ * Copyright (c) 2010-2014 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Dornierstr. 4
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#ifndef LIBBSP_ARM_LPC32XX_HSU_H
+#define LIBBSP_ARM_LPC32XX_HSU_H
+
+#include <rtems/termiostypes.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup lpc32xx_hsu HSU Support
+ *
+ * @ingroup arm_lpc32xx
+ *
+ * @brief HSU Support
+ *
+ * @{
+ */
+
+typedef struct {
+  uint32_t fifo;
+  uint32_t level;
+  uint32_t iir;
+  uint32_t ctrl;
+  uint32_t rate;
+} lpc32xx_hsu;
+
+typedef struct {
+  rtems_termios_device_context base;
+  volatile lpc32xx_hsu *hsu;
+  size_t chars_in_transmission;
+  rtems_vector_number irq;
+  uint32_t initial_baud;
+} lpc32xx_hsu_context;
+
+extern const rtems_termios_device_handler lpc32xx_hsu_fns;
+
+bool lpc32xx_hsu_probe(rtems_termios_device_context *base);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* LIBBSP_ARM_LPC32XX_HSU_H */
diff --git a/c/src/lib/libbsp/arm/lpc32xx/preinstall.am b/c/src/lib/libbsp/arm/lpc32xx/preinstall.am
index b15e8cd..9a2571e 100644
--- a/c/src/lib/libbsp/arm/lpc32xx/preinstall.am
+++ b/c/src/lib/libbsp/arm/lpc32xx/preinstall.am
@@ -146,6 +146,10 @@ $(PROJECT_INCLUDE)/bsp/boot.h: include/boot.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/boot.h
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/boot.h
 
+$(PROJECT_INCLUDE)/bsp/hsu.h: include/hsu.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/hsu.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/hsu.h
+
 $(PROJECT_INCLUDE)/bsp/i2c.h: include/i2c.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/i2c.h
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/i2c.h
diff --git a/c/src/lib/libbsp/powerpc/gen83xx/Makefile.am b/c/src/lib/libbsp/powerpc/gen83xx/Makefile.am
index 3e24d30..35a093b 100644
--- a/c/src/lib/libbsp/powerpc/gen83xx/Makefile.am
+++ b/c/src/lib/libbsp/powerpc/gen83xx/Makefile.am
@@ -82,12 +82,10 @@ libbsp_a_SOURCES += ../../shared/src/irq-shell.c
 libbsp_a_SOURCES += irq/irq.c
 
 # console
-libbsp_a_SOURCES += ../../shared/console.c \
-        ../../shared/console_select.c \
-	console/console-config.c \
-        ../../shared/console_read.c \
-        ../../shared/console_write.c \
-        ../../shared/console_control.c
+libbsp_a_SOURCES += ../../shared/console-termios-init.c
+libbsp_a_SOURCES += ../../shared/console-termios.c
+libbsp_a_SOURCES += console/console-config.c
+
 # bsp_i2c
 libbsp_a_SOURCES += i2c/i2c_init.c
 # bsp_spi
diff --git a/c/src/lib/libbsp/powerpc/gen83xx/console/console-config.c b/c/src/lib/libbsp/powerpc/gen83xx/console/console-config.c
index b3ccb9c..8dd7249 100644
--- a/c/src/lib/libbsp/powerpc/gen83xx/console/console-config.c
+++ b/c/src/lib/libbsp/powerpc/gen83xx/console/console-config.c
@@ -5,10 +5,10 @@
  */
 
 /*
- * Copyright (c) 2008, 2010 embedded brains GmbH.  All rights reserved.
+ * Copyright (c) 2008-2014 embedded brains GmbH.  All rights reserved.
  *
  *  embedded brains GmbH
- *  Obere Lagerstr. 30
+ *  Dornierstr. 4
  *  82178 Puchheim
  *  Germany
  *  <rtems at embedded-brains.de>
@@ -20,104 +20,92 @@
 
 #include <rtems/bspIo.h>
 
-#include <libchip/serial.h>
 #include <libchip/ns16550.h>
-#include "../../../shared/console_private.h"
 
 #include <mpc83xx/mpc83xx.h>
 
-#include <bspopts.h>
+#include <bsp.h>
 #include <bsp/irq.h>
-
-#ifdef BSP_USE_UART2
-  #define PORT_COUNT 2
-#else
-  #define PORT_COUNT 1
-#endif
+#include <bsp/console-termios.h>
 
 #ifdef BSP_USE_UART_INTERRUPTS
-  #define DEVICE_FNS &ns16550_fns
+  #define DEVICE_FNS &ns16550_handler_interrupt
 #else
-  #define DEVICE_FNS &ns16550_fns_polled
+  #define DEVICE_FNS &ns16550_handler_polled
 #endif
 
-static uint8_t gen83xx_console_get_register(uint32_t addr, uint8_t i)
+static uint8_t gen83xx_console_get_register(uintptr_t addr, uint8_t i)
 {
   volatile uint8_t *reg = (volatile uint8_t *) addr;
 
   return reg [i];
 }
 
-static void gen83xx_console_set_register(uint32_t addr, uint8_t i, uint8_t val)
+static void gen83xx_console_set_register(uintptr_t addr, uint8_t i, uint8_t val)
 {
   volatile uint8_t *reg = (volatile uint8_t *) addr;
 
-  reg [i] = val; 
+  reg [i] = val;
 }
 
-unsigned long Console_Configuration_Count = PORT_COUNT;
-
-console_tbl Console_Configuration_Ports [PORT_COUNT] = {
-  {
-    .sDeviceName = "/dev/ttyS0",
-    .deviceType = SERIAL_NS16550,
-    .pDeviceFns = DEVICE_FNS,
-    .deviceProbe = NULL,
-    .pDeviceFlow = NULL,
-    .ulMargin = 16,
-    .ulHysteresis = 8,
-    .pDeviceParams = (void *) BSP_CONSOLE_BAUD,
-    .ulCtrlPort1 = (uint32_t) &mpc83xx.duart [0],
-    .ulCtrlPort2 = 0,
-    .ulDataPort =  (uint32_t) &mpc83xx.duart [0],
-    .getRegister = gen83xx_console_get_register,
-    .setRegister = gen83xx_console_set_register,
-    .getData = NULL,
-    .setData = NULL,
-    .ulClock = 0,
+static ns16550_context gen83xx_uart_context_0 = {
+  .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 0"),
+  .get_reg = gen83xx_console_get_register,
+  .set_reg = gen83xx_console_set_register,
+  .port = (uintptr_t) &mpc83xx.duart[0],
 #if MPC83XX_CHIP_TYPE / 10 == 830
-    .ulIntVector = BSP_IPIC_IRQ_UART
+   .irq = BSP_IPIC_IRQ_UART,
 #else
-    .ulIntVector = BSP_IPIC_IRQ_UART1
+   .irq = BSP_IPIC_IRQ_UART1,
 #endif
-  }
+  .initial_baud = BSP_CONSOLE_BAUD
+};
+
 #ifdef BSP_USE_UART2
-  , {
-    .sDeviceName = "/dev/ttyS1",
-    .deviceType = SERIAL_NS16550,
-    .pDeviceFns = DEVICE_FNS,
-    .deviceProbe = NULL,
-    .pDeviceFlow = NULL,
-    .ulMargin = 16,
-    .ulHysteresis = 8,
-    .pDeviceParams = (void *) BSP_CONSOLE_BAUD,
-    .ulCtrlPort1 = (uint32_t) &mpc83xx.duart [1],
-    .ulCtrlPort2 = 0,
-    .ulDataPort =  (uint32_t) &mpc83xx.duart [1],
-    .getRegister = gen83xx_console_get_register,
-    .setRegister = gen83xx_console_set_register,
-    .getData = NULL,
-    .setData = NULL,
-    .ulClock = 0,
+static ns16550_context gen83xx_uart_context_1 = {
+  .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 1"),
+  .get_reg = gen83xx_console_get_register,
+  .set_reg = gen83xx_console_set_register,
+  .port = (uintptr_t) &mpc83xx.duart[1],
 #if MPC83XX_CHIP_TYPE / 10 == 830
-    .ulIntVector = BSP_IPIC_IRQ_UART
+  .irq = BSP_IPIC_IRQ_UART,
 #else
-    .ulIntVector = BSP_IPIC_IRQ_UART2
+  .irq = BSP_IPIC_IRQ_UART2,
 #endif
+  .initial_baud = BSP_CONSOLE_BAUD
+};
+#endif
+
+const console_device console_device_table[] = {
+  {
+    .device_file = "/dev/ttyS0",
+    .probe = ns16550_probe,
+    .handler = DEVICE_FNS,
+    .context = &gen83xx_uart_context_0.base
+  }
+#ifdef BSP_USE_UART2
+  , {
+    .device_file = "/dev/ttyS1",
+    .probe = ns16550_probe,
+    .handler = DEVICE_FNS,
+    .context = &gen83xx_uart_context_1.base
   }
 #endif
 };
 
+const size_t console_device_count = RTEMS_ARRAY_SIZE(console_device_table);
+
 static void gen83xx_output_char(char c)
 {
-  const console_fns *console = Console_Port_Tbl [Console_Port_Minor]->pDeviceFns;
-  
+  rtems_termios_device_context *ctx = console_device_table[0].context;
+
   if (c == '\n') {
-    console->deviceWritePolled((int) Console_Port_Minor, '\r');
+    ns16550_polled_putchar(ctx, '\r');
   }
-  console->deviceWritePolled((int) Console_Port_Minor, c);
+
+  ns16550_polled_putchar(ctx, c);
 }
 
-BSP_output_char_function_type  BSP_output_char = gen83xx_output_char;
+BSP_output_char_function_type BSP_output_char = gen83xx_output_char;
 
 BSP_polling_getchar_function_type BSP_poll_char = NULL;
diff --git a/c/src/lib/libbsp/powerpc/gen83xx/startup/bspstart.c b/c/src/lib/libbsp/powerpc/gen83xx/startup/bspstart.c
index 4428b8d..f1ffcac 100644
--- a/c/src/lib/libbsp/powerpc/gen83xx/startup/bspstart.c
+++ b/c/src/lib/libbsp/powerpc/gen83xx/startup/bspstart.c
@@ -7,12 +7,13 @@
  */
 
 /*
- * Copyright (c) 2008
- * Embedded Brains GmbH
- * Obere Lagerstr. 30
- * D-82178 Puchheim
- * Germany
- * rtems at embedded-brains.de
+ * Copyright (c) 2008-2014 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Dornierstr. 4
+ *  82178 Puchheim
+ *  Germany
+ *  <info at embedded-brains.de>
  *
  * The license and distribution terms for this file may be
  * found in the file LICENSE in this distribution or at
@@ -21,7 +22,7 @@
 
 #include <rtems/counter.h>
 
-#include <libchip/serial.h>
+#include <libchip/ns16550.h>
 
 #include <libcpu/powerpc-utility.h>
 
@@ -31,6 +32,7 @@
 #include <bsp/irq-generic.h>
 #include <bsp/linker-symbols.h>
 #include <bsp/u-boot.h>
+#include <bsp/console-termios.h>
 
 /* Configuration parameters for console driver, ... */
 unsigned int BSP_bus_frequency;
@@ -54,6 +56,7 @@ void BSP_panic(char *s)
   rtems_interrupt_level level;
 
   rtems_interrupt_disable(level);
+  (void) level;
 
   printk("%s PANIC %s\n", rtems_get_version_string(), s);
 
@@ -67,6 +70,7 @@ void _BSP_Fatal_error(unsigned n)
   rtems_interrupt_level level;
 
   rtems_interrupt_disable( level);
+  (void) level;
 
   printk( "%s PANIC ERROR %u\n", rtems_get_version_string(), n);
 
@@ -80,15 +84,12 @@ void bsp_start( void)
   rtems_status_code sc = RTEMS_SUCCESSFUL;
   unsigned long i = 0;
 
-  ppc_cpu_id_t myCpu;
-  ppc_cpu_revision_t myCpuRevision;
-
   /*
    * Get CPU identification dynamically. Note that the get_ppc_cpu_type() function
    * store the result in global variables so that it can be used latter...
    */
-  myCpu = get_ppc_cpu_type();
-  myCpuRevision = get_ppc_cpu_revision();
+  get_ppc_cpu_type();
+  get_ppc_cpu_revision();
 
   /* Basic CPU initialization */
   cpu_init();
@@ -122,12 +123,13 @@ void bsp_start( void)
   rtems_counter_initialize_converter(bsp_time_base_frequency);
 
   /* Initialize some console parameters */
-  for (i = 0; i < Console_Configuration_Count; ++i) {
-    Console_Configuration_Ports [i].ulClock = BSP_bus_frequency;
+  for (i = 0; i < console_device_count; ++i) {
+    ns16550_context *ctx = (ns16550_context *) console_device_table[i].context;
+
+    ctx->clock = BSP_bus_frequency;
 
     #ifdef HAS_UBOOT
-      Console_Configuration_Ports [i].pDeviceParams =
-        (void *) bsp_uboot_board_info.bi_baudrate;
+      ctx->initial_baud = bsp_uboot_board_info.bi_baudrate;
     #endif
   }
 
diff --git a/c/src/lib/libbsp/powerpc/qoriq/Makefile.am b/c/src/lib/libbsp/powerpc/qoriq/Makefile.am
index ebd4160..97d97a2 100644
--- a/c/src/lib/libbsp/powerpc/qoriq/Makefile.am
+++ b/c/src/lib/libbsp/powerpc/qoriq/Makefile.am
@@ -92,15 +92,11 @@ libbsp_a_SOURCES += ../../shared/src/irq-shell.c
 libbsp_a_SOURCES += irq/irq.c
 
 # Console
-libbsp_a_SOURCES += ../../shared/console.c \
-        ../../shared/console_select.c \
-	console/uart-bridge-master.c \
-	console/uart-bridge-slave.c \
-	console/console-config.c \
-        ../../shared/console_read.c \
-        ../../shared/console_write.c \
-        ../../shared/console_control.c
-
+libbsp_a_SOURCES += ../../shared/console-termios-init.c
+libbsp_a_SOURCES += ../../shared/console-termios.c
+libbsp_a_SOURCES += console/uart-bridge-master.c
+libbsp_a_SOURCES += console/uart-bridge-slave.c
+libbsp_a_SOURCES += console/console-config.c
 
 # RTC
 libbsp_a_SOURCES += ../../shared/tod.c \
diff --git a/c/src/lib/libbsp/powerpc/qoriq/console/console-config.c b/c/src/lib/libbsp/powerpc/qoriq/console/console-config.c
index 6260fd3..1abefe8 100644
--- a/c/src/lib/libbsp/powerpc/qoriq/console/console-config.c
+++ b/c/src/lib/libbsp/powerpc/qoriq/console/console-config.c
@@ -7,10 +7,10 @@
  */
 
 /*
- * Copyright (c) 2010 embedded brains GmbH.  All rights reserved.
+ * Copyright (c) 2010-2014 embedded brains GmbH.  All rights reserved.
  *
  *  embedded brains GmbH
- *  Obere Lagerstr. 30
+ *  Dornierstr. 4
  *  82178 Puchheim
  *  Germany
  *  <rtems at embedded-brains.de>
@@ -20,25 +20,16 @@
  * http://www.rtems.org/license/LICENSE.
  */
 
-#include <assert.h>
-
 #include <rtems/bspIo.h>
 
-#include <libchip/serial.h>
 #include <libchip/ns16550.h>
-#include "../../../shared/console_private.h"
 
-#include <bspopts.h>
+#include <bsp.h>
 #include <bsp/irq.h>
 #include <bsp/qoriq.h>
 #include <bsp/intercom.h>
 #include <bsp/uart-bridge.h>
-
-#define CONSOLE_COUNT \
-  (QORIQ_UART_0_ENABLE \
-    + QORIQ_UART_1_ENABLE \
-    + QORIQ_UART_BRIDGE_0_ENABLE \
-    + QORIQ_UART_BRIDGE_1_ENABLE)
+#include <bsp/console-termios.h>
 
 #if (QORIQ_UART_0_ENABLE + QORIQ_UART_BRIDGE_0_ENABLE == 2) \
   || (QORIQ_UART_1_ENABLE + QORIQ_UART_BRIDGE_1_ENABLE == 2)
@@ -47,158 +38,156 @@
   #define BRIDGE_SLAVE
 #endif
 
+#ifdef BSP_USE_UART_INTERRUPTS
+  #define DEVICE_FNS &ns16550_handler_interrupt
+#else
+  #define DEVICE_FNS &ns16550_handler_polled
+#endif
+
+#if QORIQ_UART_0_ENABLE || QORIQ_UART_1_ENABLE
+  static uint8_t get_register(uintptr_t addr, uint8_t i)
+  {
+    volatile uint8_t *reg = (uint8_t *) addr;
+
+    return reg [i];
+  }
+
+  static void set_register(uintptr_t addr, uint8_t i, uint8_t val)
+  {
+    volatile uint8_t *reg = (uint8_t *) addr;
+
+    reg [i] = val;
+  }
+#endif
+
+#if QORIQ_UART_0_ENABLE
+static ns16550_context qoriq_uart_context_0 = {
+  .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 0"),
+  .get_reg = get_register,
+  .set_reg = set_register,
+  .port = (uintptr_t) &qoriq.uart_0,
+  .irq = QORIQ_IRQ_DUART,
+  .initial_baud = BSP_CONSOLE_BAUD
+};
+#endif
+
+#if QORIQ_UART_1_ENABLE
+static ns16550_context qoriq_uart_context_1 = {
+  .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 1"),
+  .get_reg = get_register,
+  .set_reg = set_register,
+  .port = (uintptr_t) &qoriq.uart_1,
+  .irq = QORIQ_IRQ_DUART,
+  .initial_baud = BSP_CONSOLE_BAUD
+};
+#endif
+
 #ifdef BRIDGE_MASTER
+  #define BRIDGE_PROBE qoriq_uart_bridge_master_probe
   #define BRIDGE_FNS &qoriq_uart_bridge_master
   #if QORIQ_UART_BRIDGE_0_ENABLE
-    static uart_bridge_master_control bridge_0_control = {
+    static uart_bridge_master_context bridge_0_context = {
+      .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART Bridge 0"),
       .device_path = "/dev/ttyS0",
       .type = INTERCOM_TYPE_UART_0,
       .transmit_fifo = RTEMS_CHAIN_INITIALIZER_EMPTY(
-        bridge_0_control.transmit_fifo
+        bridge_0_context.transmit_fifo
       )
     };
-    #define BRIDGE_0_CONTROL &bridge_0_control
+    #define BRIDGE_0_CONTEXT &bridge_0_context
   #endif
   #if QORIQ_UART_BRIDGE_1_ENABLE
-    static uart_bridge_master_control bridge_1_control = {
+    static uart_bridge_master_context bridge_1_context = {
+      .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART Bridge 1"),
       .device_path = "/dev/ttyS1",
       .type = INTERCOM_TYPE_UART_1,
       .transmit_fifo = RTEMS_CHAIN_INITIALIZER_EMPTY(
-        bridge_1_control.transmit_fifo
+        bridge_1_context.transmit_fifo
       )
     };
-    #define BRIDGE_1_CONTROL &bridge_1_control
+    #define BRIDGE_1_CONTEXT &bridge_1_context
   #endif
 #endif
 
 #ifdef BRIDGE_SLAVE
+  #define BRIDGE_PROBE console_device_probe_default
   #define BRIDGE_FNS &qoriq_uart_bridge_slave
   #if QORIQ_UART_BRIDGE_0_ENABLE
-    static uart_bridge_slave_control bridge_0_control = {
+    static uart_bridge_slave_context bridge_0_context = {
+      .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART Bridge 0"),
       .type = INTERCOM_TYPE_UART_0,
       .transmit_fifo = RTEMS_CHAIN_INITIALIZER_EMPTY(
-        bridge_0_control.transmit_fifo
+        bridge_0_context.transmit_fifo
       )
     };
-    #define BRIDGE_0_CONTROL &bridge_0_control
+    #define BRIDGE_0_CONTEXT &bridge_0_context
   #endif
   #if QORIQ_UART_BRIDGE_1_ENABLE
-    static uart_bridge_slave_control bridge_1_control = {
+    static uart_bridge_slave_context bridge_1_context = {
+      .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART Bridge 1"),
       .type = INTERCOM_TYPE_UART_1,
       .transmit_fifo = RTEMS_CHAIN_INITIALIZER_EMPTY(
-        bridge_1_control.transmit_fifo
+        bridge_1_context.transmit_fifo
       )
     };
-    #define BRIDGE_1_CONTROL &bridge_1_control
+    #define BRIDGE_1_CONTEXT &bridge_1_context
   #endif
 #endif
 
-#ifdef BSP_USE_UART_INTERRUPTS
-  #define DEVICE_FNS &ns16550_fns
-#else
-  #define DEVICE_FNS &ns16550_fns_polled
-#endif
-
-#if QORIQ_UART_0_ENABLE || QORIQ_UART_1_ENABLE
-  static uint8_t get_register(uintptr_t addr, uint8_t i)
-  {
-    volatile uint8_t *reg = (uint8_t *) addr;
-
-    return reg [i];
-  }
-
-  static void set_register(uintptr_t addr, uint8_t i, uint8_t val)
-  {
-    volatile uint8_t *reg = (uint8_t *) addr;
-
-    reg [i] = val; 
-  }
-#endif
-
-unsigned long Console_Configuration_Count = CONSOLE_COUNT;
-console_tbl Console_Configuration_Ports [CONSOLE_COUNT] = {
+const console_device console_device_table[] = {
   #if QORIQ_UART_0_ENABLE
     {
-      .sDeviceName = "/dev/ttyS0",
-      .deviceType = SERIAL_NS16550,
-      .pDeviceFns = DEVICE_FNS,
-      .deviceProbe = NULL,
-      .pDeviceFlow = NULL,
-      .ulMargin = 16,
-      .ulHysteresis = 8,
-      .pDeviceParams = (void *) BSP_CONSOLE_BAUD,
-      .ulCtrlPort1 = (uintptr_t) &qoriq.uart_0,
-      .ulCtrlPort2 = 0,
-      .ulDataPort =  (uintptr_t) &qoriq.uart_0,
-      .getRegister = get_register,
-      .setRegister = set_register,
-      .getData = NULL,
-      .setData = NULL,
-      .ulClock = 0,
-      .ulIntVector = QORIQ_IRQ_DUART
+      .device_file = "/dev/ttyS0",
+      .probe = ns16550_probe,
+      .handler = DEVICE_FNS,
+      .context = &qoriq_uart_context_0.base
     },
   #endif
   #if QORIQ_UART_1_ENABLE
     {
-      .sDeviceName = "/dev/ttyS1",
-      .deviceType = SERIAL_NS16550,
-      .pDeviceFns = DEVICE_FNS,
-      .deviceProbe = NULL,
-      .pDeviceFlow = NULL,
-      .ulMargin = 16,
-      .ulHysteresis = 8,
-      .pDeviceParams = (void *) BSP_CONSOLE_BAUD,
-      .ulCtrlPort1 = (uintptr_t) &qoriq.uart_1,
-      .ulCtrlPort2 = 0,
-      .ulDataPort =  (uintptr_t) &qoriq.uart_1,
-      .getRegister = get_register,
-      .setRegister = set_register,
-      .getData = NULL,
-      .setData = NULL,
-      .ulClock = 0,
-      .ulIntVector = QORIQ_IRQ_DUART
+      .device_file = "/dev/ttyS1",
+      .probe = ns16550_probe,
+      .handler = DEVICE_FNS,
+      .context = &qoriq_uart_context_1.base
     },
   #endif
   #if QORIQ_UART_BRIDGE_0_ENABLE
     {
       #if QORIQ_UART_1_ENABLE
-        .sDeviceName = "/dev/ttyB0",
+        .device_file = "/dev/ttyB0",
       #else
-        .sDeviceName = "/dev/ttyS0",
+        .device_file = "/dev/ttyS0",
       #endif
-      .deviceType = SERIAL_CUSTOM,
-      .pDeviceFns = BRIDGE_FNS,
-      .pDeviceParams = BRIDGE_0_CONTROL
+      .probe = BRIDGE_PROBE,
+      .handler = BRIDGE_FNS,
+      .context = BRIDGE_0_CONTEXT
     },
   #endif
   #if QORIQ_UART_BRIDGE_1_ENABLE
     {
       #if QORIQ_UART_1_ENABLE
-        .sDeviceName = "/dev/ttyB1",
+        .device_file = "/dev/ttyB1",
       #else
-        .sDeviceName = "/dev/ttyS1",
+        .device_file = "/dev/ttyS1",
       #endif
-      .deviceType = SERIAL_CUSTOM,
-      .pDeviceFns = BRIDGE_FNS,
-      .pDeviceParams = BRIDGE_1_CONTROL
+      .probe = BRIDGE_PROBE,
+      .handler = BRIDGE_FNS,
+      .context = BRIDGE_1_CONTEXT
     }
   #endif
 };
 
+const size_t console_device_count = RTEMS_ARRAY_SIZE(console_device_table);
+
 static void output_char(char c)
 {
-  int minor = (int) Console_Port_Minor;
-  const console_tbl **ct_tbl = Console_Port_Tbl;
-
-  if (ct_tbl != NULL) {
-    const console_fns *cf = ct_tbl[minor]->pDeviceFns;
+  rtems_termios_device_context *ctx = console_device_table[0].context;
 
-    if (c == '\n') {
-      (*cf->deviceWritePolled)(minor, '\r');
-    }
-
-    (*cf->deviceWritePolled)(minor, c);
+  if (c == '\n') {
+    ns16550_polled_putchar(ctx, '\r');
   }
+
+  ns16550_polled_putchar(ctx, c);
 }
 
 BSP_output_char_function_type BSP_output_char = output_char;
diff --git a/c/src/lib/libbsp/powerpc/qoriq/console/uart-bridge-master.c b/c/src/lib/libbsp/powerpc/qoriq/console/uart-bridge-master.c
index 939448a..41ad517 100644
--- a/c/src/lib/libbsp/powerpc/qoriq/console/uart-bridge-master.c
+++ b/c/src/lib/libbsp/powerpc/qoriq/console/uart-bridge-master.c
@@ -7,10 +7,10 @@
  */
 
 /*
- * Copyright (c) 2011 embedded brains GmbH.  All rights reserved.
+ * Copyright (c) 2011-2014 embedded brains GmbH.  All rights reserved.
  *
  *  embedded brains GmbH
- *  Obere Lagerstr. 30
+ *  Dornierstr. 4
  *  82178 Puchheim
  *  Germany
  *  <rtems at embedded-brains.de>
@@ -26,8 +26,6 @@
 #include <unistd.h>
 #include <termios.h>
 
-#include <libchip/sersupp.h>
-
 #include <bspopts.h>
 #include <bsp/uart-bridge.h>
 
@@ -55,12 +53,12 @@ static void serial_settings(int fd)
 static void uart_bridge_master_service(intercom_packet *packet, void *arg)
 {
   rtems_status_code sc = RTEMS_SUCCESSFUL;
-  uart_bridge_master_control *control = arg;
+  uart_bridge_master_context *ctx = arg;
 
   sc = rtems_chain_append_with_notification(
-    &control->transmit_fifo,
+    &ctx->transmit_fifo,
     &packet->glue.node,
-    control->transmit_task,
+    ctx->transmit_task,
     TRANSMIT_EVENT
   );
   assert(sc == RTEMS_SUCCESSFUL);
@@ -68,10 +66,10 @@ static void uart_bridge_master_service(intercom_packet *packet, void *arg)
 
 static void receive_task(rtems_task_argument arg)
 {
-  uart_bridge_master_control *control = (uart_bridge_master_control *) arg;
-  intercom_type type = control->type;
+  uart_bridge_master_context *ctx = (uart_bridge_master_context *) arg;
+  intercom_type type = ctx->type;
 
-  int fd = open(control->device_path, O_RDONLY);
+  int fd = open(ctx->device_path, O_RDONLY);
   assert(fd >= 0);
 
   serial_settings(fd);
@@ -94,10 +92,10 @@ static void receive_task(rtems_task_argument arg)
 static void transmit_task(rtems_task_argument arg)
 {
   rtems_status_code sc = RTEMS_SUCCESSFUL;
-  uart_bridge_master_control *control = (uart_bridge_master_control *) arg;
-  rtems_chain_control *fifo = &control->transmit_fifo;
+  uart_bridge_master_context *ctx = (uart_bridge_master_context *) arg;
+  rtems_chain_control *fifo = &ctx->transmit_fifo;
 
-  int fd = open(control->device_path, O_WRONLY);
+  int fd = open(ctx->device_path, O_WRONLY);
   assert(fd >= 0);
 
   serial_settings(fd);
@@ -119,12 +117,12 @@ static void transmit_task(rtems_task_argument arg)
 static rtems_id create_task(
   char name,
   rtems_task_entry entry,
-  uart_bridge_master_control *control
+  uart_bridge_master_context *ctx
 )
 {
   rtems_status_code sc = RTEMS_SUCCESSFUL;
   rtems_id task = RTEMS_ID_NONE;
-  char index = (char) ('0' + control->type - INTERCOM_TYPE_UART_0);
+  char index = (char) ('0' + ctx->type - INTERCOM_TYPE_UART_0);
 
   sc = rtems_task_create(
     rtems_build_name('U', 'B', name, index),
@@ -139,57 +137,45 @@ static rtems_id create_task(
   sc = rtems_task_start(
     task,
     entry,
-    (rtems_task_argument) control
+    (rtems_task_argument) ctx
   );
   assert(sc == RTEMS_SUCCESSFUL);
 
   return task;
 }
 
-static void initialize(int minor)
+bool qoriq_uart_bridge_master_probe(rtems_termios_device_context *base)
 {
-  console_tbl *ct = Console_Port_Tbl [minor];
-  uart_bridge_master_control *control = ct->pDeviceParams;
-  intercom_type type = control->type;
-
-  qoriq_intercom_service_install(type, uart_bridge_master_service, control);
-  create_task('R', receive_task, control);
-  control->transmit_task = create_task('T', transmit_task, control);
-}
+  uart_bridge_master_context *ctx = (uart_bridge_master_context *) base;
+  intercom_type type = ctx->type;
 
-static int first_open(int major, int minor, void *arg)
-{
-  return -1;
-}
+  qoriq_intercom_service_install(type, uart_bridge_master_service, ctx);
+  create_task('R', receive_task, ctx);
+  ctx->transmit_task = create_task('T', transmit_task, ctx);
 
-static int last_close(int major, int minor, void *arg)
-{
-  return -1;
+  return true;
 }
 
-static int read_polled(int minor)
-{
-  return -1;
-}
-
-static void write_polled(int minor, char c)
+static bool first_open(
+  struct rtems_termios_tty *tty,
+  rtems_termios_device_context *base,
+  struct termios *term,
+  rtems_libio_open_close_args_t *args
+)
 {
-  /* Do nothing */
+  return false;
 }
 
-static int set_attributes(int minor, const struct termios *term)
+static bool set_attributes(
+  rtems_termios_device_context *base,
+  const struct termios *term
+)
 {
-  return -1;
+  return false;
 }
 
-const console_fns qoriq_uart_bridge_master = {
-  .deviceProbe = libchip_serial_default_probe,
-  .deviceFirstOpen = first_open,
-  .deviceLastClose = last_close,
-  .deviceRead = read_polled,
-  .deviceWrite = NULL,
-  .deviceInitialize = initialize,
-  .deviceWritePolled = write_polled,
-  .deviceSetAttributes = set_attributes,
-  .deviceOutputUsesInterrupts = false
+const rtems_termios_device_handler qoriq_uart_bridge_master = {
+  .first_open = first_open,
+  .set_attributes = set_attributes,
+  .mode = TERMIOS_POLLED
 };
diff --git a/c/src/lib/libbsp/powerpc/qoriq/console/uart-bridge-slave.c b/c/src/lib/libbsp/powerpc/qoriq/console/uart-bridge-slave.c
index 71969e3..44d4cfb 100644
--- a/c/src/lib/libbsp/powerpc/qoriq/console/uart-bridge-slave.c
+++ b/c/src/lib/libbsp/powerpc/qoriq/console/uart-bridge-slave.c
@@ -50,8 +50,8 @@ static void restore_preemption(rtems_mode prev_mode)
 
 static void uart_bridge_slave_service(intercom_packet *packet, void *arg)
 {
-  uart_bridge_slave_control *control = arg;
-  struct rtems_termios_tty *tty = control->tty;
+  uart_bridge_slave_context *ctx = arg;
+  struct rtems_termios_tty *tty = ctx->tty;
 
   /* Workaround for https://www.rtems.org/bugzilla/show_bug.cgi?id=1736 */
   rtems_mode prev_mode = disable_preemption();
@@ -65,9 +65,9 @@ static void uart_bridge_slave_service(intercom_packet *packet, void *arg)
 static void transmit_task(rtems_task_argument arg)
 {
   rtems_status_code sc = RTEMS_SUCCESSFUL;
-  uart_bridge_slave_control *control = (uart_bridge_slave_control *) arg;
-  rtems_chain_control *fifo = &control->transmit_fifo;
-  struct rtems_termios_tty *tty = control->tty;
+  uart_bridge_slave_context *ctx = (uart_bridge_slave_context *) arg;
+  rtems_chain_control *fifo = &ctx->transmit_fifo;
+  struct rtems_termios_tty *tty = ctx->tty;
 
   while (true) {
     intercom_packet *packet = NULL;
@@ -91,12 +91,12 @@ static void transmit_task(rtems_task_argument arg)
 }
 
 static void create_transmit_task(
-  uart_bridge_slave_control *control
+  uart_bridge_slave_context *ctx
 )
 {
   rtems_status_code sc = RTEMS_SUCCESSFUL;
   rtems_id task = RTEMS_ID_NONE;
-  char index = (char) ('0' + control->type - INTERCOM_TYPE_UART_0);
+  char index = (char) ('0' + ctx->type - INTERCOM_TYPE_UART_0);
 
   sc = rtems_task_create(
     rtems_build_name('U', 'B', 'T', index),
@@ -111,54 +111,53 @@ static void create_transmit_task(
   sc = rtems_task_start(
     task,
     transmit_task,
-    (rtems_task_argument) control
+    (rtems_task_argument) ctx
   );
   assert(sc == RTEMS_SUCCESSFUL);
 
-  control->transmit_task = task;
+  ctx->transmit_task = task;
 }
 
-static void initialize(int minor)
+static bool first_open(
+  struct rtems_termios_tty *tty,
+  rtems_termios_device_context *base,
+  struct termios *term,
+  rtems_libio_open_close_args_t *args
+)
 {
-  /* Do nothing */
-}
+  uart_bridge_slave_context *ctx = (uart_bridge_slave_context *) base;
+  intercom_type type = ctx->type;
 
-static int first_open(int major, int minor, void *arg)
-{
-  rtems_libio_open_close_args_t *oc = (rtems_libio_open_close_args_t *) arg;
-  struct rtems_termios_tty *tty = (struct rtems_termios_tty *) oc->iop->data1;
-  console_tbl *ct = Console_Port_Tbl[minor];
-  console_data *cd = &Console_Port_Data [minor];
-  uart_bridge_slave_control *control = ct->pDeviceParams;
-  intercom_type type = control->type;
-
-  control->tty = tty;
-  cd->termios_data = tty;
+  ctx->tty = tty;
   rtems_termios_set_initial_baud(tty, 115200);
-  create_transmit_task(control);
-  qoriq_intercom_service_install(type, uart_bridge_slave_service, control);
+  create_transmit_task(ctx);
+  qoriq_intercom_service_install(type, uart_bridge_slave_service, ctx);
 
-  return 0;
+  return true;
 }
 
-static int last_close(int major, int minor, void *arg)
+static void last_close(
+  struct rtems_termios_tty *tty,
+  rtems_termios_device_context *base,
+  rtems_libio_open_close_args_t *args
+)
 {
-  console_tbl *ct = Console_Port_Tbl[minor];
-  uart_bridge_slave_control *control = ct->pDeviceParams;
-
-  qoriq_intercom_service_remove(control->type);
+  uart_bridge_slave_context *ctx = (uart_bridge_slave_context *) base;
 
-  return 0;
+  qoriq_intercom_service_remove(ctx->type);
 }
 
-static ssize_t write_with_interrupts(int minor, const char *buf, size_t len)
+static void write_with_interrupts(
+  rtems_termios_device_context *base,
+  const char *buf,
+  size_t len
+)
 {
   if (len > 0) {
     rtems_status_code sc = RTEMS_SUCCESSFUL;
-    console_tbl *ct = Console_Port_Tbl[minor];
-    uart_bridge_slave_control *control = ct->pDeviceParams;
+    uart_bridge_slave_context *ctx = (uart_bridge_slave_context *) base;
     intercom_packet *packet = qoriq_intercom_allocate_packet(
-      control->type,
+      ctx->type,
       INTERCOM_SIZE_64
     );
 
@@ -170,44 +169,27 @@ static ssize_t write_with_interrupts(int minor, const char *buf, size_t len)
      * another context.
      */
     sc = rtems_chain_append_with_notification(
-      &control->transmit_fifo,
+      &ctx->transmit_fifo,
       &packet->glue.node,
-      control->transmit_task,
+      ctx->transmit_task,
       TRANSMIT_EVENT
     );
     assert(sc == RTEMS_SUCCESSFUL);
   }
-
-  return 0;
-}
-
-static void write_polled(int minor, char c)
-{
-  console_tbl *ct = Console_Port_Tbl[minor];
-  uart_bridge_slave_control *control = ct->pDeviceParams;
-  intercom_packet *packet = qoriq_intercom_allocate_packet(
-    control->type,
-    INTERCOM_SIZE_64
-  );
-  char *data = packet->data;
-  data [0] = c;
-  packet->size = 1;
-  qoriq_intercom_send_packet(QORIQ_UART_BRIDGE_MASTER_CORE, packet);
 }
 
-static int set_attribues(int minor, const struct termios *term)
+static bool set_attributes(
+  rtems_termios_device_context *base,
+  const struct termios *term
+)
 {
-  return -1;
+  return false;
 }
 
-const console_fns qoriq_uart_bridge_slave = {
-  .deviceProbe = libchip_serial_default_probe,
-  .deviceFirstOpen = first_open,
-  .deviceLastClose = last_close,
-  .deviceRead = NULL,
-  .deviceWrite = write_with_interrupts,
-  .deviceInitialize = initialize,
-  .deviceWritePolled = write_polled,
-  .deviceSetAttributes = set_attribues,
-  .deviceOutputUsesInterrupts = true
+const rtems_termios_device_handler qoriq_uart_bridge_slave = {
+  .first_open = first_open,
+  .last_close = last_close,
+  .write = write_with_interrupts,
+  .set_attributes = set_attributes,
+  .mode = TERMIOS_IRQ_DRIVEN
 };
diff --git a/c/src/lib/libbsp/powerpc/qoriq/include/uart-bridge.h b/c/src/lib/libbsp/powerpc/qoriq/include/uart-bridge.h
index e94fe20..cd342ff 100644
--- a/c/src/lib/libbsp/powerpc/qoriq/include/uart-bridge.h
+++ b/c/src/lib/libbsp/powerpc/qoriq/include/uart-bridge.h
@@ -7,10 +7,10 @@
  */
 
 /*
- * Copyright (c) 2011 embedded brains GmbH.  All rights reserved.
+ * Copyright (c) 2011-2014 embedded brains GmbH.  All rights reserved.
  *
  *  embedded brains GmbH
- *  Obere Lagerstr. 30
+ *  Dornierstr. 4
  *  82178 Puchheim
  *  Germany
  *  <rtems at embedded-brains.de>
@@ -23,7 +23,7 @@
 #ifndef LIBBSP_POWERPC_QORIQ_UART_BRIDGE_H
 #define LIBBSP_POWERPC_QORIQ_UART_BRIDGE_H
 
-#include <libchip/serial.h>
+#include <rtems/termiostypes.h>
 
 #include <bsp/intercom.h>
 
@@ -42,22 +42,26 @@ extern "C" {
  */
 
 typedef struct {
+  rtems_termios_device_context base;
   const char *device_path;
   intercom_type type;
   rtems_id transmit_task;
   rtems_chain_control transmit_fifo;
-} uart_bridge_master_control;
+} uart_bridge_master_context;
 
 typedef struct {
+  rtems_termios_device_context base;
   struct rtems_termios_tty *tty;
   intercom_type type;
   rtems_id transmit_task;
   rtems_chain_control transmit_fifo;
-} uart_bridge_slave_control;
+} uart_bridge_slave_context;
 
-extern const console_fns qoriq_uart_bridge_master;
+bool qoriq_uart_bridge_master_probe(rtems_termios_device_context *base);
 
-extern const console_fns qoriq_uart_bridge_slave;
+extern const rtems_termios_device_handler qoriq_uart_bridge_master;
+
+extern const rtems_termios_device_handler qoriq_uart_bridge_slave;
 
 /** @} */
 
diff --git a/c/src/lib/libbsp/powerpc/qoriq/startup/bspstart.c b/c/src/lib/libbsp/powerpc/qoriq/startup/bspstart.c
index 5785078..43caabb 100644
--- a/c/src/lib/libbsp/powerpc/qoriq/startup/bspstart.c
+++ b/c/src/lib/libbsp/powerpc/qoriq/startup/bspstart.c
@@ -24,7 +24,7 @@
 #include <rtems/config.h>
 #include <rtems/counter.h>
 
-#include <libchip/serial.h>
+#include <libchip/ns16550.h>
 
 #include <libcpu/powerpc-utility.h>
 
@@ -36,6 +36,7 @@
 #include <bsp/linker-symbols.h>
 #include <bsp/mmu.h>
 #include <bsp/qoriq.h>
+#include <bsp/console-termios.h>
 
 LINKER_SYMBOL(bsp_exc_vector_base);
 
@@ -50,6 +51,7 @@ void BSP_panic(char *s)
   rtems_interrupt_level level;
 
   rtems_interrupt_disable(level);
+  (void) level;
 
   printk("%s PANIC %s\n", rtems_get_version_string(), s);
 
@@ -63,6 +65,7 @@ void _BSP_Fatal_error(unsigned n)
   rtems_interrupt_level level;
 
   rtems_interrupt_disable(level);
+  (void) level;
 
   printk("%s PANIC ERROR %u\n", rtems_get_version_string(), n);
 
@@ -75,15 +78,12 @@ void bsp_start(void)
 {
   unsigned long i = 0;
 
-  ppc_cpu_id_t myCpu;
-  ppc_cpu_revision_t myCpuRevision;
-
   /*
    * Get CPU identification dynamically. Note that the get_ppc_cpu_type() function
    * store the result in global variables so that it can be used latter...
    */
-  myCpu = get_ppc_cpu_type();
-  myCpuRevision = get_ppc_cpu_revision();
+  get_ppc_cpu_type();
+  get_ppc_cpu_revision();
 
   /* Initialize some device driver parameters */
   #ifdef HAS_UBOOT
@@ -93,16 +93,24 @@ void bsp_start(void)
   rtems_counter_initialize_converter(BSP_bus_frequency / 8);
 
   /* Initialize some console parameters */
-  for (i = 0; i < Console_Configuration_Count; ++i) {
-    console_tbl *ct = &Console_Configuration_Ports[i];
-
-    ct->ulClock = BSP_bus_frequency;
-
-    #ifdef HAS_UBOOT
-      if (ct->deviceType == SERIAL_NS16550) {
-        ct->pDeviceParams = (void *) bsp_uboot_board_info.bi_baudrate;
-      }
-    #endif
+  for (i = 0; i < console_device_count; ++i) {
+    const console_device *dev = &console_device_table[i];
+    const rtems_termios_device_handler *ns16550 =
+      #ifdef BSP_USE_UART_INTERRUPTS
+        &ns16550_handler_interrupt;
+      #else
+        &ns16550_handler_polled;
+      #endif
+
+    if (dev->handler == ns16550) {
+      ns16550_context *ctx = (ns16550_context *) dev->context;
+
+      ctx->clock = BSP_bus_frequency;
+
+      #ifdef HAS_UBOOT
+        ctx->initial_baud = bsp_uboot_board_info.bi_baudrate;
+      #endif
+    }
   }
 
   /* Disable decrementer */
diff --git a/c/src/libchip/Makefile.am b/c/src/libchip/Makefile.am
index 003c3c1..904561f 100644
--- a/c/src/libchip/Makefile.am
+++ b/c/src/libchip/Makefile.am
@@ -110,6 +110,7 @@ libserialio_a_SOURCES = serial/mc68681.c serial/mc68681_baud.c \
     serial/mc68681_reg8.c serial/ns16550.c serial/z85c30.c \
     serial/z85c30_reg.c serial/serprobe.c serial/mc68681_p.h \
     serial/z85c30_p.h
+libserialio_a_SOURCES += serial/ns16550-context.c
 
 EXTRA_DIST += serial/README.mc68681 serial/README.ns16550 \
     serial/README.xr88681 serial/README.z85c30 serial/STATUS
diff --git a/c/src/libchip/serial/ns16550-context.c b/c/src/libchip/serial/ns16550-context.c
new file mode 100644
index 0000000..a812271
--- /dev/null
+++ b/c/src/libchip/serial/ns16550-context.c
@@ -0,0 +1,677 @@
+/**
+ *  @file
+ *  
+ *  This file contains the TTY driver for the National Semiconductor NS16550.
+ *
+ *  This part is widely cloned and second sourced.  It is found in a number
+ *  of "Super IO" controllers.
+ *
+ *  This driver uses the termios pseudo driver.
+ */
+
+/*
+ *  COPYRIGHT (c) 1998 by Radstone Technology
+ *
+ *  THIS FILE IS PROVIDED TO YOU, THE USER, "AS IS", WITHOUT WARRANTY OF ANY
+ *  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK
+ *  AS TO THE QUALITY AND PERFORMANCE OF ALL CODE IN THIS FILE IS WITH YOU.
+ *
+ *  You are hereby granted permission to use, copy, modify, and distribute
+ *  this file, provided that this notice, plus the above copyright notice
+ *  and disclaimer, appears in all copies. Radstone Technology will provide
+ *  no support for this code.
+ *
+ *  COPYRIGHT (c) 1989-2012.
+ *  On-Line Applications Research Corporation (OAR).
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.org/license/LICENSE.
+ */
+
+#include <stdlib.h>
+
+#include <rtems/bspIo.h>
+
+#include <bsp.h>
+
+#include "ns16550.h"
+#include "ns16550_p.h"
+
+#if defined(BSP_FEATURE_IRQ_EXTENSION)
+  #include <bsp/irq.h>
+#elif defined(BSP_FEATURE_IRQ_LEGACY)
+  #include <bsp/irq.h>
+#elif defined(__PPC__) || defined(__i386__)
+  #include <bsp/irq.h>
+  #define BSP_FEATURE_IRQ_LEGACY
+  #ifdef BSP_SHARED_HANDLER_SUPPORT
+    #define BSP_FEATURE_IRQ_LEGACY_SHARED_HANDLER_SUPPORT
+  #endif
+#endif
+
+static uint32_t NS16550_GetBaudDivisor(ns16550_context *ctx, uint32_t baud)
+{
+  uint32_t clock = ctx->clock;
+  uint32_t baudDivisor = (clock != 0 ? clock : 115200) / (baud * 16);
+
+  if (ctx->has_fractional_divider_register) {
+    uint32_t fractionalDivider = 0x10;
+    uint32_t err = baud;
+    uint32_t mulVal;
+    uint32_t divAddVal;
+
+    clock /= 16 * baudDivisor;
+    for (mulVal = 1; mulVal < 16; ++mulVal) {
+      for (divAddVal = 0; divAddVal < mulVal; ++divAddVal) {
+        uint32_t actual = (mulVal * clock) / (mulVal + divAddVal);
+        uint32_t newErr = actual > baud ? actual - baud : baud - actual;
+
+        if (newErr < err) {
+          err = newErr;
+          fractionalDivider = (mulVal << 4) | divAddVal;
+        }
+      }
+    }
+
+    (*ctx->set_reg)(
+      ctx->port,
+      NS16550_FRACTIONAL_DIVIDER,
+      fractionalDivider
+    );
+  }
+
+  return baudDivisor;
+}
+
+/*
+ *  ns16550_enable_interrupts
+ *
+ *  This routine initializes the port to have the specified interrupts masked.
+ */
+static void ns16550_enable_interrupts(
+  ns16550_context *ctx,
+  int              mask
+)
+{
+  (*ctx->set_reg)(ctx->port, NS16550_INTERRUPT_ENABLE, mask);
+}
+
+/*
+ *  ns16550_probe
+ */
+
+bool ns16550_probe(rtems_termios_device_context *base)
+{
+  ns16550_context        *ctx = (ns16550_context *) base;
+  uintptr_t               pNS16550;
+  uint8_t                 ucDataByte;
+  uint32_t                ulBaudDivisor;
+  ns16550_set_reg         setReg;
+  ns16550_get_reg         getReg;
+
+  ctx->modem_control = SP_MODEM_IRQ;
+
+  pNS16550 = ctx->port;    
+  setReg   = ctx->set_reg;
+  getReg   = ctx->get_reg;
+
+  /* Clear the divisor latch, clear all interrupt enables,
+   * and reset and
+   * disable the FIFO's.
+   */
+
+  (*setReg)(pNS16550, NS16550_LINE_CONTROL, 0x0);
+  ns16550_enable_interrupts(ctx, NS16550_DISABLE_ALL_INTR );
+
+  /* Set the divisor latch and set the baud rate. */
+
+  ulBaudDivisor = NS16550_GetBaudDivisor(ctx, ctx->initial_baud);
+  ucDataByte = SP_LINE_DLAB;
+  (*setReg)(pNS16550, NS16550_LINE_CONTROL, ucDataByte);
+
+  /* XXX */
+  (*setReg)(pNS16550,NS16550_TRANSMIT_BUFFER,(uint8_t)(ulBaudDivisor & 0xffU));
+  (*setReg)(
+    pNS16550,NS16550_INTERRUPT_ENABLE,
+    (uint8_t)(( ulBaudDivisor >> 8 ) & 0xffU )
+  );
+
+  /* Clear the divisor latch and set the character size to eight bits */
+  /* with one stop bit and no parity checking. */
+  ucDataByte = EIGHT_BITS;
+  (*setReg)(pNS16550, NS16550_LINE_CONTROL, ucDataByte);
+
+  /* Enable and reset transmit and receive FIFOs. TJA     */
+  ucDataByte = SP_FIFO_ENABLE;
+  (*setReg)(pNS16550, NS16550_FIFO_CONTROL, ucDataByte);
+
+  ucDataByte = SP_FIFO_ENABLE | SP_FIFO_RXRST | SP_FIFO_TXRST;
+  (*setReg)(pNS16550, NS16550_FIFO_CONTROL, ucDataByte);
+
+  ns16550_enable_interrupts(ctx, NS16550_DISABLE_ALL_INTR);
+
+  /* Set data terminal ready. */
+  /* And open interrupt tristate line */
+  (*setReg)(pNS16550, NS16550_MODEM_CONTROL,ctx->modem_control);
+
+  (*getReg)(pNS16550, NS16550_LINE_STATUS );
+  (*getReg)(pNS16550, NS16550_RECEIVE_BUFFER );
+
+  return true;
+}
+
+#if defined(BSP_FEATURE_IRQ_EXTENSION) || defined(BSP_FEATURE_IRQ_LEGACY)
+
+/**
+ * @brief Process interrupt.
+ */
+static void ns16550_isr(void *arg)
+{
+  rtems_termios_tty *tty = arg;
+  ns16550_context *ctx = rtems_termios_get_device_context(tty);
+  uint32_t port = ctx->port;
+  ns16550_get_reg get = ctx->get_reg;
+  int i = 0;
+  char buf [SP_FIFO_SIZE];
+
+  /* Iterate until no more interrupts are pending */
+  do {
+    /* Fetch received characters */
+    for (i = 0; i < SP_FIFO_SIZE; ++i) {
+      if ((get( port, NS16550_LINE_STATUS) & SP_LSR_RDY) != 0) {
+        buf [i] = (char) get(port, NS16550_RECEIVE_BUFFER);
+      } else {
+        break;
+      }
+    }
+
+    /* Enqueue fetched characters */
+    rtems_termios_enqueue_raw_characters(tty, buf, i);
+
+    /* Check if we can dequeue transmitted characters */
+    if (ctx->transmit_fifo_chars > 0
+        && (get( port, NS16550_LINE_STATUS) & SP_LSR_THOLD) != 0) {
+
+      /* Dequeue transmitted characters */
+      rtems_termios_dequeue_characters(
+        tty,
+        ctx->transmit_fifo_chars
+      );
+    }
+  } while ((get( port, NS16550_INTERRUPT_ID) & SP_IID_0) == 0);
+}
+#endif
+
+/*
+ *  ns16550_initialize_interrupts
+ *
+ *  This routine initializes the port to operate in interrupt driver mode.
+ */
+static void ns16550_initialize_interrupts(
+  struct rtems_termios_tty *tty,
+  ns16550_context          *ctx
+)
+{
+  #ifdef BSP_FEATURE_IRQ_EXTENSION
+    {
+      rtems_status_code sc = RTEMS_SUCCESSFUL;
+      sc = rtems_interrupt_handler_install(
+        ctx->irq,
+        "NS16550",
+        RTEMS_INTERRUPT_SHARED,
+        ns16550_isr,
+        tty
+      );
+      if (sc != RTEMS_SUCCESSFUL) {
+        /* FIXME */
+        printk( "%s: Error: Install interrupt handler\n", __func__);
+        rtems_fatal_error_occurred( 0xdeadbeef);
+      }
+    }
+  #elif defined(BSP_FEATURE_IRQ_LEGACY)
+    {
+      int rv = 0;
+      #ifdef BSP_FEATURE_IRQ_LEGACY_SHARED_HANDLER_SUPPORT
+        rtems_irq_connect_data cd = {
+          ctx->irq,
+          ns16550_isr,
+          tty,
+          NULL,
+          NULL,
+          NULL,
+          NULL
+        };
+        rv = BSP_install_rtems_shared_irq_handler( &cd);
+      #else
+        rtems_irq_connect_data cd = {
+          ctx->irq,
+          ns16550_isr,
+          tty,
+          NULL,
+          NULL,
+          NULL
+        };
+        rv = BSP_install_rtems_irq_handler( &cd);
+      #endif
+      if (rv == 0) {
+        /* FIXME */
+        printk( "%s: Error: Install interrupt handler\n", __func__);
+        rtems_fatal_error_occurred( 0xdeadbeef);
+      }
+    }
+  #endif
+}
+
+/*
+ *  ns16550_open
+ */
+
+static bool ns16550_open(
+  struct rtems_termios_tty      *tty,
+  rtems_termios_device_context  *base,
+  struct termios                *term,
+  rtems_libio_open_close_args_t *args
+)
+{
+  ns16550_context *ctx = (ns16550_context *) base;
+
+  /* Set initial baud */
+  rtems_termios_set_initial_baud(tty, ctx->initial_baud);
+
+  if (tty->handler.mode == TERMIOS_IRQ_DRIVEN) {
+    ns16550_initialize_interrupts(tty, ctx);
+    ns16550_enable_interrupts(ctx, NS16550_ENABLE_ALL_INTR_EXCEPT_TX);
+  }
+
+  return true;
+}
+
+static void ns16550_cleanup_interrupts(
+  struct rtems_termios_tty *tty,
+  ns16550_context          *ctx
+)
+{
+  #if defined(BSP_FEATURE_IRQ_EXTENSION)
+    rtems_status_code sc = RTEMS_SUCCESSFUL;
+    sc = rtems_interrupt_handler_remove(
+      ctx->irq,
+      ns16550_isr,
+      tty
+    );
+    if (sc != RTEMS_SUCCESSFUL) {
+      /* FIXME */
+      printk("%s: Error: Remove interrupt handler\n", __func__);
+      rtems_fatal_error_occurred(0xdeadbeef);
+    }
+  #elif defined(BSP_FEATURE_IRQ_LEGACY)
+    int rv = 0;
+    rtems_irq_connect_data cd = {
+      .name = ctx->irq,
+      .hdl = ns16550_isr,
+      .handle = tty
+    };
+    rv = BSP_remove_rtems_irq_handler(&cd);
+    if (rv == 0) {
+      /* FIXME */
+      printk("%s: Error: Remove interrupt handler\n", __func__);
+      rtems_fatal_error_occurred(0xdeadbeef);
+    }
+  #endif
+}
+
+/*
+ *  ns16550_close
+ */
+
+static void ns16550_close(
+  struct rtems_termios_tty      *tty,
+  rtems_termios_device_context  *base,
+  rtems_libio_open_close_args_t *args
+)
+{
+  ns16550_context *ctx = (ns16550_context *) base;
+
+  ns16550_enable_interrupts(ctx, NS16550_DISABLE_ALL_INTR);
+
+  if (tty->handler.mode == TERMIOS_IRQ_DRIVEN) {
+    ns16550_cleanup_interrupts(tty, ctx);
+  }
+}
+
+/**
+ * @brief Polled write for NS16550.
+ */
+void ns16550_polled_putchar(rtems_termios_device_context *base, char out)
+{
+  ns16550_context *ctx = (ns16550_context *) base;
+  uintptr_t port = ctx->port;
+  ns16550_get_reg get = ctx->get_reg;
+  ns16550_set_reg set = ctx->set_reg;
+  uint32_t status = 0;
+  rtems_interrupt_lock_context lock_context;
+
+  /* Save port interrupt mask */
+  uint32_t interrupt_mask = get( port, NS16550_INTERRUPT_ENABLE);
+
+  /* Disable port interrupts */
+  ns16550_enable_interrupts(ctx, NS16550_DISABLE_ALL_INTR);
+
+  while (true) {
+    /* Try to transmit the character in a critical section */
+    rtems_termios_device_lock_acquire(&ctx->base, &lock_context);
+
+    /* Read the transmitter holding register and check it */
+    status = get( port, NS16550_LINE_STATUS);
+    if ((status & SP_LSR_THOLD) != 0) {
+      /* Transmit character */
+      set( port, NS16550_TRANSMIT_BUFFER, out);
+
+      /* Finished */
+      rtems_termios_device_lock_release(&ctx->base, &lock_context);
+      break;
+    } else {
+      rtems_termios_device_lock_release(&ctx->base, &lock_context);
+    }
+
+    /* Wait for transmitter holding register to be empty */
+    do {
+      status = get( port, NS16550_LINE_STATUS);
+    } while ((status & SP_LSR_THOLD) == 0);
+  }
+
+  /* Restore port interrupt mask */
+  set( port, NS16550_INTERRUPT_ENABLE, interrupt_mask);
+}
+
+/*
+ * These routines provide control of the RTS and DTR lines
+ */
+
+/*
+ *  ns16550_assert_RTS
+ */
+
+static void ns16550_assert_RTS(rtems_termios_device_context *base)
+{
+  ns16550_context             *ctx = (ns16550_context *) base;
+  rtems_interrupt_lock_context lock_context;
+
+  /*
+   * Assert RTS
+   */
+  rtems_termios_device_lock_acquire(base, &lock_context);
+  ctx->modem_control |= SP_MODEM_RTS;
+  (*ctx->set_reg)(ctx->port, NS16550_MODEM_CONTROL, ctx->modem_control);
+  rtems_termios_device_lock_release(base, &lock_context);
+}
+
+/*
+ *  ns16550_negate_RTS
+ */
+
+static void ns16550_negate_RTS(rtems_termios_device_context *base)
+{
+  ns16550_context             *ctx = (ns16550_context *) base;
+  rtems_interrupt_lock_context lock_context;
+
+  /*
+   * Negate RTS
+   */
+  rtems_termios_device_lock_acquire(base, &lock_context);
+  ctx->modem_control &= ~SP_MODEM_RTS;
+  (*ctx->set_reg)(ctx->port, NS16550_MODEM_CONTROL, ctx->modem_control);
+  rtems_termios_device_lock_release(base, &lock_context);
+}
+
+/*
+ * These flow control routines utilise a connection from the local DTR
+ * line to the remote CTS line
+ */
+
+/*
+ *  ns16550_assert_DTR
+ */
+
+static void ns16550_assert_DTR(rtems_termios_device_context *base)
+{
+  ns16550_context             *ctx = (ns16550_context *) base;
+  rtems_interrupt_lock_context lock_context;
+
+  /*
+   * Assert DTR
+   */
+  rtems_termios_device_lock_acquire(base, &lock_context);
+  ctx->modem_control |= SP_MODEM_DTR;
+  (*ctx->set_reg)(ctx->port, NS16550_MODEM_CONTROL, ctx->modem_control);
+  rtems_termios_device_lock_release(base, &lock_context);
+}
+
+/*
+ *  ns16550_negate_DTR
+ */
+
+static void ns16550_negate_DTR(rtems_termios_device_context *base)
+{
+  ns16550_context             *ctx = (ns16550_context *) base;
+  rtems_interrupt_lock_context lock_context;
+
+  /*
+   * Negate DTR
+   */
+  rtems_termios_device_lock_acquire(base, &lock_context);
+  ctx->modem_control &=~SP_MODEM_DTR;
+  (*ctx->set_reg)(ctx->port, NS16550_MODEM_CONTROL,ctx->modem_control);
+  rtems_termios_device_lock_release(base, &lock_context);
+}
+
+/*
+ *  ns16550_set_attributes
+ *
+ *  This function sets the channel to reflect the requested termios
+ *  port settings.
+ */
+
+static bool ns16550_set_attributes(
+  rtems_termios_device_context *base,
+  const struct termios         *t
+)
+{
+  ns16550_context        *ctx = (ns16550_context *) base;
+  uint32_t                pNS16550;
+  uint32_t                ulBaudDivisor;
+  uint8_t                 ucLineControl;
+  uint32_t                baud_requested;
+  ns16550_set_reg         setReg;
+  rtems_interrupt_lock_context lock_context;
+
+  pNS16550 = ctx->port;
+  setReg   = ctx->set_reg;
+
+  /*
+   *  Calculate the baud rate divisor
+   */
+
+  baud_requested = rtems_termios_baud_to_number(t->c_cflag);
+  ulBaudDivisor = NS16550_GetBaudDivisor(ctx, baud_requested);
+
+  ucLineControl = 0;
+
+  /*
+   *  Parity
+   */
+
+  if (t->c_cflag & PARENB) {
+    ucLineControl |= SP_LINE_PAR;
+    if (!(t->c_cflag & PARODD))
+      ucLineControl |= SP_LINE_ODD;
+  }
+
+  /*
+   *  Character Size
+   */
+
+  if (t->c_cflag & CSIZE) {
+    switch (t->c_cflag & CSIZE) {
+      case CS5:  ucLineControl |= FIVE_BITS;  break;
+      case CS6:  ucLineControl |= SIX_BITS;   break;
+      case CS7:  ucLineControl |= SEVEN_BITS; break;
+      case CS8:  ucLineControl |= EIGHT_BITS; break;
+    }
+  } else {
+    ucLineControl |= EIGHT_BITS;               /* default to 9600,8,N,1 */
+  }
+
+  /*
+   *  Stop Bits
+   */
+
+  if (t->c_cflag & CSTOPB) {
+    ucLineControl |= SP_LINE_STOP;              /* 2 stop bits */
+  } else {
+    ;                                           /* 1 stop bit */
+  }
+
+  /*
+   *  Now actually set the chip
+   */
+
+  rtems_termios_device_lock_acquire(base, &lock_context);
+
+    /*
+     *  Set the baud rate
+     *
+     *  NOTE: When the Divisor Latch Access Bit (DLAB) is set to 1,
+     *        the transmit buffer and interrupt enable registers
+     *        turn into the LSB and MSB divisor latch registers.
+     */
+
+    (*setReg)(pNS16550, NS16550_LINE_CONTROL, SP_LINE_DLAB);
+    (*setReg)(pNS16550, NS16550_TRANSMIT_BUFFER, ulBaudDivisor&0xff);
+    (*setReg)(pNS16550, NS16550_INTERRUPT_ENABLE, (ulBaudDivisor>>8)&0xff);
+
+    /*
+     *  Now write the line control
+     */
+    (*setReg)(pNS16550, NS16550_LINE_CONTROL, ucLineControl );
+
+  rtems_termios_device_lock_release(base, &lock_context);
+
+  return true;
+}
+
+/**
+ * @brief Transmits up to @a len characters from @a buf.
+ *
+ * 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.
+ *
+ * Returns always zero.
+ */
+static void ns16550_write_support_int(
+  rtems_termios_device_context *base,
+  const char                   *buf,
+  size_t                        len
+)
+{
+  ns16550_context *ctx = (ns16550_context *) base;
+  uint32_t port = ctx->port;
+  ns16550_set_reg set = ctx->set_reg;
+  int i = 0;
+  int out = len > SP_FIFO_SIZE ? SP_FIFO_SIZE : len;
+
+  for (i = 0; i < out; ++i) {
+    set( port, NS16550_TRANSMIT_BUFFER, buf [i]);
+  }
+
+  ctx->transmit_fifo_chars = out;
+
+  if (out > 0) {
+    ns16550_enable_interrupts(ctx, NS16550_ENABLE_ALL_INTR);
+  } else {
+    ns16550_enable_interrupts(ctx, NS16550_ENABLE_ALL_INTR_EXCEPT_TX);
+  }
+}
+
+/*
+ *  ns16550_write_support_polled
+ *
+ *  Console Termios output entry point.
+ *
+ */
+
+static void ns16550_write_support_polled(
+  rtems_termios_device_context *base,
+  const char                   *buf,
+  size_t                        len
+)
+{
+  size_t nwrite = 0;
+
+  /*
+   * poll each byte in the string out of the port.
+   */
+  while (nwrite < len) {
+    /*
+     * transmit character
+     */
+    ns16550_polled_putchar(base, *buf++);
+    nwrite++;
+  }
+}
+
+/*
+ *  Debug gets() support
+ */
+int ns16550_polled_getchar(rtems_termios_device_context *base)
+{
+  ns16550_context     *ctx = (ns16550_context *) base;
+  uint32_t             pNS16550;
+  unsigned char        ucLineStatus;
+  uint8_t              cChar;
+  ns16550_get_reg      getReg;
+
+  pNS16550 = ctx->port;
+  getReg   = ctx->get_reg;
+
+  ucLineStatus = (*getReg)(pNS16550, NS16550_LINE_STATUS);
+  if (ucLineStatus & SP_LSR_RDY) {
+    cChar = (*getReg)(pNS16550, NS16550_RECEIVE_BUFFER);
+    return (int)cChar;
+  }
+  return -1;
+}
+
+/*
+ * Flow control is only supported when using interrupts
+ */
+
+const rtems_termios_device_flow ns16550_flow_rtscts = {
+  .stop_remote_tx = ns16550_negate_RTS,
+  .start_remote_tx = ns16550_assert_RTS
+};
+
+const rtems_termios_device_flow ns16550_flow_dtrcts = {
+  .stop_remote_tx = ns16550_negate_DTR,
+  .start_remote_tx = ns16550_assert_DTR
+};
+
+const rtems_termios_device_handler ns16550_handler_interrupt = {
+  .first_open = ns16550_open,
+  .last_close = ns16550_close,
+  .poll_read = NULL,
+  .write = ns16550_write_support_int,
+  .set_attributes = ns16550_set_attributes,
+  .mode = TERMIOS_IRQ_DRIVEN
+};
+
+const rtems_termios_device_handler ns16550_handler_polled = {
+  .first_open = ns16550_open,
+  .last_close = ns16550_close,
+  .poll_read = ns16550_polled_getchar,
+  .write = ns16550_write_support_polled,
+  .set_attributes = ns16550_set_attributes,
+  .mode = TERMIOS_POLLED
+};
diff --git a/c/src/libchip/serial/ns16550.c b/c/src/libchip/serial/ns16550.c
index 390c729..b0aa38f 100644
--- a/c/src/libchip/serial/ns16550.c
+++ b/c/src/libchip/serial/ns16550.c
@@ -58,6 +58,82 @@
   #endif
 #endif
 
+typedef struct {
+  uint8_t ucModemCtrl;
+  int transmitFifoChars;
+} NS16550Context;
+
+/*
+ * Driver functions
+ */
+
+NS16550_STATIC void ns16550_init(int minor);
+
+NS16550_STATIC int ns16550_open(
+  int major,
+  int minor,
+  void  * arg
+);
+
+NS16550_STATIC int ns16550_close(
+  int major,
+  int minor,
+  void  * arg
+);
+
+NS16550_STATIC void ns16550_write_polled(
+  int   minor,
+  char  cChar
+);
+
+NS16550_STATIC int ns16550_assert_RTS(
+  int minor
+);
+
+NS16550_STATIC int ns16550_negate_RTS(
+  int minor
+);
+
+NS16550_STATIC int ns16550_assert_DTR(
+  int minor
+);
+
+NS16550_STATIC int ns16550_negate_DTR(
+  int minor
+);
+
+NS16550_STATIC void ns16550_initialize_interrupts(int minor);
+
+NS16550_STATIC void ns16550_cleanup_interrupts(int minor);
+
+NS16550_STATIC ssize_t ns16550_write_support_int(
+  int   minor,
+  const char *buf,
+  size_t len
+);
+
+NS16550_STATIC ssize_t ns16550_write_support_polled(
+  int   minor,
+  const char *buf,
+  size_t len
+  );
+
+int ns16550_inbyte_nonblocking_polled(
+  int minor
+);
+
+NS16550_STATIC void ns16550_enable_interrupts(
+  console_tbl *c,
+  int         mask
+);
+
+NS16550_STATIC int ns16550_set_attributes(
+  int                   minor,
+  const struct termios *t
+);
+
+NS16550_STATIC void ns16550_isr(void *arg);
+
 static rtems_interrupt_lock ns16550_lock =
   RTEMS_INTERRUPT_LOCK_INITIALIZER("NS16550");
 
@@ -142,12 +218,12 @@ void ns16550_init(int minor)
   uintptr_t               pNS16550;
   uint8_t                 ucDataByte;
   uint32_t                ulBaudDivisor;
-  ns16550_context        *pns16550Context;
+  NS16550Context        *pns16550Context;
   setRegister_f           setReg;
   getRegister_f           getReg;
   console_tbl             *c = Console_Port_Tbl [minor];
 
-  pns16550Context=(ns16550_context *)malloc(sizeof(ns16550_context));
+  pns16550Context=(NS16550Context *)malloc(sizeof(NS16550Context));
 
   if (pns16550Context == NULL) {
     printk( "%s: Error: Not enough memory\n", __func__);
@@ -328,10 +404,10 @@ NS16550_STATIC int ns16550_assert_RTS(int minor)
 {
   uint32_t                pNS16550;
   rtems_interrupt_lock_context lock_context;
-  ns16550_context        *pns16550Context;
+  NS16550Context        *pns16550Context;
   setRegister_f           setReg;
 
-  pns16550Context=(ns16550_context *) Console_Port_Data[minor].pDeviceContext;
+  pns16550Context=(NS16550Context *) Console_Port_Data[minor].pDeviceContext;
 
   pNS16550 = Console_Port_Tbl[minor]->ulCtrlPort1;
   setReg   = Console_Port_Tbl[minor]->setRegister;
@@ -354,10 +430,10 @@ NS16550_STATIC int ns16550_negate_RTS(int minor)
 {
   uint32_t                pNS16550;
   rtems_interrupt_lock_context lock_context;
-  ns16550_context        *pns16550Context;
+  NS16550Context        *pns16550Context;
   setRegister_f           setReg;
 
-  pns16550Context=(ns16550_context *) Console_Port_Data[minor].pDeviceContext;
+  pns16550Context=(NS16550Context *) Console_Port_Data[minor].pDeviceContext;
 
   pNS16550 = Console_Port_Tbl[minor]->ulCtrlPort1;
   setReg   = Console_Port_Tbl[minor]->setRegister;
@@ -385,10 +461,10 @@ NS16550_STATIC int ns16550_assert_DTR(int minor)
 {
   uint32_t                pNS16550;
   rtems_interrupt_lock_context lock_context;
-  ns16550_context        *pns16550Context;
+  NS16550Context        *pns16550Context;
   setRegister_f           setReg;
 
-  pns16550Context=(ns16550_context *) Console_Port_Data[minor].pDeviceContext;
+  pns16550Context=(NS16550Context *) Console_Port_Data[minor].pDeviceContext;
 
   pNS16550 = Console_Port_Tbl[minor]->ulCtrlPort1;
   setReg   = Console_Port_Tbl[minor]->setRegister;
@@ -411,10 +487,10 @@ NS16550_STATIC int ns16550_negate_DTR(int minor)
 {
   uint32_t                pNS16550;
   rtems_interrupt_lock_context lock_context;
-  ns16550_context        *pns16550Context;
+  NS16550Context        *pns16550Context;
   setRegister_f           setReg;
 
-  pns16550Context=(ns16550_context *) Console_Port_Data[minor].pDeviceContext;
+  pns16550Context=(NS16550Context *) Console_Port_Data[minor].pDeviceContext;
 
   pNS16550 = Console_Port_Tbl[minor]->ulCtrlPort1;
   setReg   = Console_Port_Tbl[minor]->setRegister;
@@ -533,7 +609,7 @@ NS16550_STATIC void ns16550_process( int minor)
 {
   console_tbl *c = Console_Port_Tbl [minor];
   console_data *d = &Console_Port_Data [minor];
-  ns16550_context *ctx = d->pDeviceContext;
+  NS16550Context *ctx = d->pDeviceContext;
   uint32_t port = c->ulCtrlPort1;
   getRegister_f get = c->getRegister;
   int i = 0;
@@ -584,7 +660,7 @@ ssize_t ns16550_write_support_int(
 {
   console_tbl *c = Console_Port_Tbl [minor];
   console_data *d = &Console_Port_Data [minor];
-  ns16550_context *ctx = d->pDeviceContext;
+  NS16550Context *ctx = d->pDeviceContext;
   uint32_t port = c->ulCtrlPort1;
   setRegister_f set = c->setRegister;
   int i = 0;
diff --git a/c/src/libchip/serial/ns16550.h b/c/src/libchip/serial/ns16550.h
index 2890566..ef1f9f9 100644
--- a/c/src/libchip/serial/ns16550.h
+++ b/c/src/libchip/serial/ns16550.h
@@ -27,6 +27,7 @@
 #ifndef _NS16550_H_
 #define _NS16550_H_
 
+#include <rtems/termiostypes.h>
 #include <libchip/serial.h>
 
 #ifdef __cplusplus
@@ -53,6 +54,37 @@ extern const console_flow ns16550_flow_DTRCTS;
 void ns16550_outch_polled(console_tbl *c, char out);
 int ns16550_inch_polled(console_tbl *c);
 
+/* Alternative NS16550 driver using the Termios device context */
+
+typedef uint8_t (*ns16550_get_reg)(uintptr_t port, uint8_t reg);
+
+typedef void (*ns16550_set_reg)(uintptr_t port, uint8_t reg, uint8_t value);
+
+typedef struct {
+  rtems_termios_device_context base;
+  ns16550_get_reg get_reg;
+  ns16550_set_reg set_reg;
+  uintptr_t port;
+  rtems_vector_number irq;
+  uint32_t clock;
+  uint32_t initial_baud;
+  bool has_fractional_divider_register;
+  uint8_t modem_control;
+  size_t transmit_fifo_chars;
+} ns16550_context;
+
+extern const rtems_termios_device_handler ns16550_handler_interrupt;
+extern const rtems_termios_device_handler ns16550_handler_polled;
+
+extern const rtems_termios_device_flow ns16550_flow_rtscts;
+extern const rtems_termios_device_flow ns16550_flow_dtrcts;
+
+void ns16550_polled_putchar(rtems_termios_device_context *base, char out);
+
+int ns16550_polled_getchar(rtems_termios_device_context *base);
+
+bool ns16550_probe(rtems_termios_device_context *base);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/c/src/libchip/serial/ns16550_p.h b/c/src/libchip/serial/ns16550_p.h
index 4e6d784..0fe817a 100644
--- a/c/src/libchip/serial/ns16550_p.h
+++ b/c/src/libchip/serial/ns16550_p.h
@@ -131,82 +131,6 @@ extern "C" {
 #define SP_LSR_TX   0x40
 #define SP_LSR_EFIFO  0x80
 
-typedef struct {
-  uint8_t ucModemCtrl;
-  int transmitFifoChars;
-} ns16550_context;
-
-/*
- * Driver functions
- */
-
-void ns16550_init(int minor);
-
-int ns16550_open(
-  int major,
-  int minor,
-  void  * arg
-);
-
-int ns16550_close(
-  int major,
-  int minor,
-  void  * arg
-);
-
-void ns16550_write_polled(
-  int   minor,
-  char  cChar
-);
-
-NS16550_STATIC int ns16550_assert_RTS(
-  int minor
-);
-
-NS16550_STATIC int ns16550_negate_RTS(
-  int minor
-);
-
-NS16550_STATIC int ns16550_assert_DTR(
-  int minor
-);
-
-NS16550_STATIC int ns16550_negate_DTR(
-  int minor
-);
-
-NS16550_STATIC void ns16550_initialize_interrupts(int minor);
-
-NS16550_STATIC void ns16550_cleanup_interrupts(int minor);
-
-ssize_t ns16550_write_support_int(
-  int   minor,
-  const char *buf,
-  size_t len
-);
-
-ssize_t ns16550_write_support_polled(
-  int   minor,
-  const char *buf,
-  size_t len
-  );
-
-int ns16550_inbyte_nonblocking_polled(
-  int minor
-);
-
-NS16550_STATIC void ns16550_enable_interrupts(
-  console_tbl *c,
-  int         mask
-);
-
-int ns16550_set_attributes(
-  int                   minor,
-  const struct termios *t
-);
-
-void ns16550_isr(void *arg);
-
 #ifdef __cplusplus
 }
 #endif



More information about the vc mailing list