Index: bsps/i386/pc386/console/conscfg.c
===================================================================
--- bsps/i386/pc386/console/conscfg.c	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
+++ bsps/i386/pc386/console/conscfg.c	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
@@ -0,0 +1,198 @@
+/**
+ * @file
+ *
+ * This file contains the libchip configuration information
+ * to instantiate the libchip driver for the VGA console
+ * and serial ports on a PC.
+ */
+
+/*
+ *  COPYRIGHT (c) 1989-2014, 2016.
+ *  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 <bsp.h>
+#include <bsp/bspimpl.h>
+#include <libchip/serial.h>
+#include <libchip/ns16550.h>
+#if BSP_ENABLE_VGA
+#include <rtems/vgacons.h>
+#endif
+#include <bsp/irq.h>
+#include "../../shared/dev/serial/legacy-console.h"
+
+#if BSP_ENABLE_VGA
+#define VGA_CONSOLE_FUNCTIONS  &vgacons_fns
+#endif
+
+#if BSP_ENABLE_COM1_COM4
+  #if 0
+  #define COM_CONSOLE_FUNCTIONS  &ns16550_fns_polled
+  #else
+  #define COM_CONSOLE_FUNCTIONS  &ns16550_fns
+  #endif
+
+  /*
+   * Base IO for UART
+   */
+  #define COM1_BASE_IO  0x3F8
+  #define COM2_BASE_IO  0x3E8
+  #define COM3_BASE_IO  0x2F8
+  #define COM4_BASE_IO  0x2E8
+
+  #define CLOCK_RATE    (115200 * 16)
+
+  static uint8_t com_get_register(uint32_t addr, uint8_t i)
+  {
+    register uint8_t val;
+
+    inport_byte( (addr + i), val );
+    return val;
+  }
+
+  static void com_set_register(uint32_t addr, uint8_t i, uint8_t val)
+  {
+    outport_byte( (addr + i), val );
+  }
+#endif
+
+/*
+ * Default to the PC VGA console if present and configured.
+ */
+console_tbl Console_Configuration_Ports[] = {
+#if BSP_ENABLE_VGA
+  /*
+   * If present the VGA console must always be minor 0.
+   * See console_control.
+   */
+  {
+    "/dev/vgacons",                        /* sDeviceName */
+    VGA_CONSOLE,                           /* deviceType */
+    VGA_CONSOLE_FUNCTIONS,                 /* pDeviceFns */
+    vgacons_probe,                         /* deviceProbe */
+    NULL,                                  /* pDeviceFlow */
+    16,                                    /* ulMargin */
+    8,                                     /* ulHysteresis */
+    (void *) NULL,              /* NULL */ /* pDeviceParams */
+    0x00000000,                            /* ulCtrlPort1 */
+    0x00000000,                            /* ulCtrlPort2 */
+    0x00000000,                            /* ulDataPort */
+    NULL,                                  /* getRegister */
+    NULL,                                  /* setRegister */
+    NULL,/* unused */                      /* getData */
+    NULL,/* unused */                      /* setData */
+    0x0,                                   /* ulClock */
+    0x0                                    /* ulIntVector -- base for port */
+  },
+#endif
+};
+
+unsigned long Console_Configuration_Count =
+    (sizeof(Console_Configuration_Ports)/sizeof(console_tbl));
+
+static console_tbl Legacy_Ports[] = {
+#if BSP_ENABLE_COM1_COM4
+  {
+    "/dev/com1",                           /* sDeviceName */
+    SERIAL_NS16550,                        /* deviceType */
+    COM_CONSOLE_FUNCTIONS,                 /* pDeviceFns */
+    NULL,                                  /* deviceProbe */
+    NULL,                                  /* pDeviceFlow */
+    16,                                    /* ulMargin */
+    8,                                     /* ulHysteresis */
+    (void *) 9600,         /* Baud Rate */ /* pDeviceParams */
+    COM1_BASE_IO,                          /* ulCtrlPort1 */
+    0x00000000,                            /* ulCtrlPort2 */
+    COM1_BASE_IO,                          /* ulDataPort */
+    com_get_register,                      /* getRegister */
+    com_set_register,                      /* setRegister */
+    NULL,/* unused */                      /* getData */
+    NULL,/* unused */                      /* setData */
+    CLOCK_RATE,                            /* ulClock */
+    BSP_UART_COM1_IRQ                      /* ulIntVector -- base for port */
+  },
+  {
+    "/dev/com2",                           /* sDeviceName */
+    SERIAL_NS16550,                        /* deviceType */
+    COM_CONSOLE_FUNCTIONS,                 /* pDeviceFns */
+    NULL,                                  /* deviceProbe */
+    NULL,                                  /* pDeviceFlow */
+    16,                                    /* ulMargin */
+    8,                                     /* ulHysteresis */
+    (void *) 9600,         /* Baud Rate */ /* pDeviceParams */
+    COM2_BASE_IO,                          /* ulCtrlPort1 */
+    0x00000000,                            /* ulCtrlPort2 */
+    COM2_BASE_IO,                          /* ulDataPort */
+    com_get_register,                      /* getRegister */
+    com_set_register,                      /* setRegister */
+    NULL,/* unused */                      /* getData */
+    NULL,/* unused */                      /* setData */
+    CLOCK_RATE,                            /* ulClock */
+    BSP_UART_COM2_IRQ                      /* ulIntVector -- base for port */
+  },
+  {
+    "/dev/com3",                           /* sDeviceName */
+    SERIAL_NS16550,                        /* deviceType */
+    COM_CONSOLE_FUNCTIONS,                 /* pDeviceFns */
+    NULL,                                  /* deviceProbe */
+    NULL,                                  /* pDeviceFlow */
+    16,                                    /* ulMargin */
+    8,                                     /* ulHysteresis */
+    (void *) 9600,         /* Baud Rate */ /* pDeviceParams */
+    COM3_BASE_IO,                          /* ulCtrlPort1 */
+    0x00000000,                            /* ulCtrlPort2 */
+    COM3_BASE_IO,                          /* ulDataPort */
+    com_get_register,                      /* getRegister */
+    com_set_register,                      /* setRegister */
+    NULL,/* unused */                      /* getData */
+    NULL,/* unused */                      /* setData */
+    CLOCK_RATE,                            /* ulClock */
+    BSP_UART_COM3_IRQ                      /* ulIntVector -- base for port */
+  },
+  {
+    "/dev/com4",                           /* sDeviceName */
+    SERIAL_NS16550,                        /* deviceType */
+    COM_CONSOLE_FUNCTIONS,                 /* pDeviceFns */
+    NULL,                                  /* deviceProbe */
+    NULL,                                  /* pDeviceFlow */
+    16,                                    /* ulMargin */
+    8,                                     /* ulHysteresis */
+    (void *) 9600,         /* Baud Rate */ /* pDeviceParams */
+    COM4_BASE_IO,                          /* ulCtrlPort1 */
+    0x00000000,                            /* ulCtrlPort2 */
+    COM4_BASE_IO,                          /* ulDataPort */
+    com_get_register,                      /* getRegister */
+    com_set_register,                      /* setRegister */
+    NULL,/* unused */                      /* getData */
+    NULL,/* unused */                      /* setData */
+    CLOCK_RATE,                            /* ulClock */
+    BSP_UART_COM4_IRQ                      /* ulIntVector -- base for port */
+  },
+#endif
+};
+
+#define Legacy_Port_Count \
+    (sizeof(Legacy_Ports)/sizeof(console_tbl))
+
+void legacy_uart_probe(void)
+{
+#if BSP_ENABLE_COM1_COM4
+  const char *opt;
+  /*
+   * Check the command line to see if com1-com4 are disabled.
+   */
+  opt = bsp_cmdline_arg("--disable-com1-com4");
+  if ( opt ) {
+    printk( "COM1-COM4: disabled\n" );
+  } else {
+    if (Legacy_Port_Count) {
+      printk("Legacy UART Ports: COM1-COM4\n");
+      console_register_devices( Legacy_Ports, Legacy_Port_Count );
+    }
+  }
+#endif
+}
Index: bsps/i386/pc386/console/console_control.c
===================================================================
--- bsps/i386/pc386/console/console_control.c	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
+++ bsps/i386/pc386/console/console_control.c	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
@@ -0,0 +1,71 @@
+/*
+ *  This file is an extension of the generic console driver
+ *  shell used by all console drivers using libchip, it contains
+ *  the console_control routine,  This bsp needs its own version
+ *  of this method to handle the keyboard and mouse as a single
+ *  device.
+ */
+
+/*
+ *  COPYRIGHT (c) 1989-2011.
+ *  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 <bsp.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <termios.h>
+#include <rtems/libio.h>
+#include <rtems/console.h>
+
+#include <bsp/irq.h>
+
+#include <rtems/termiostypes.h>
+#include <libchip/serial.h>
+#include <rtems/mouse_parser.h>
+#if BSP_ENABLE_VGA
+#include <rtems/keyboard.h>
+#endif
+#include "../../shared/dev/serial/legacy-console.h"
+
+/*
+ *  console_control
+ *
+ *  this routine uses the termios driver to process io
+ */
+rtems_device_driver console_control(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void                    * arg
+)
+{
+#if BSP_ENABLE_VGA
+  if (minor == 0) {
+    rtems_libio_ioctl_args_t *args = arg;
+
+    switch (args->command) {
+      default:
+        if( vt_ioctl( args->command, (unsigned long)args->buffer ) != 0 )
+          return rtems_termios_ioctl (arg);
+        break;
+
+      case MW_UID_REGISTER_DEVICE:
+        printk( "SerialMouse: reg=%s\n", (const char*) args->buffer );
+        register_kbd_msg_queue( args->buffer, 0 );
+        break;
+
+      case MW_UID_UNREGISTER_DEVICE:
+        unregister_kbd_msg_queue( 0 );
+        break;
+    }
+
+    args->ioctl_return = 0;
+    return RTEMS_SUCCESSFUL;
+  }
+#endif
+  return rtems_termios_ioctl (arg);
+}
Index: bsps/i386/pc386/console/console_select.c
===================================================================
--- bsps/i386/pc386/console/console_select.c	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
+++ bsps/i386/pc386/console/console_select.c	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
@@ -0,0 +1,250 @@
+/**
+ * @file
+ *
+ * @ingroup Console
+ *
+ * @brief pc386 console select
+ *
+ * This file contains a routine to select the console based upon a number
+ * of criteria.
+ */
+
+/*
+ *  COPYRIGHT (c) 2011-2012, 2016.
+ *  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 <limits.h>
+#include <stdlib.h>
+#include <termios.h>
+
+#include <bsp.h>
+#include <libchip/serial.h>
+#include <rtems/libio.h>
+#include <rtems/console.h>
+#include <rtems/termiostypes.h>
+#include <bsp/bspimpl.h>
+
+#include "../../shared/dev/serial/legacy-console.h"
+#ifdef RTEMS_RUNTIME_CONSOLE_SELECT
+  #include <crt.h>
+#endif
+
+/*
+ * Method to return true if the device associated with the
+ * minor number probs available.
+ */
+static bool bsp_Is_Available( rtems_device_minor_number minor )
+{
+  console_tbl  *cptr = Console_Port_Tbl[minor];
+
+  /*
+   * First perform the configuration dependent probe, then the
+   * device dependent probe
+   */
+  if ((!cptr->deviceProbe || cptr->deviceProbe(minor)) &&
+       cptr->pDeviceFns->deviceProbe(minor)) {
+    return true;
+  }
+  return false;
+}
+
+/*
+ * Method to return the first available device.
+ */
+static rtems_device_minor_number bsp_First_Available_Device( void )
+{
+  rtems_device_minor_number minor;
+
+  for (minor=0; minor < Console_Port_Count ; minor++) {
+    console_tbl  *cptr = Console_Port_Tbl[minor];
+
+    /*
+     * First perform the configuration dependent probe, then the
+     * device dependent probe
+     */
+
+    if ((!cptr->deviceProbe || cptr->deviceProbe(minor)) &&
+         cptr->pDeviceFns->deviceProbe(minor)) {
+      return minor;
+    }
+  }
+
+  /*
+   *  Error No devices were found.  We will want to bail here.
+   */
+  rtems_fatal_error_occurred(RTEMS_IO_ERROR);
+}
+
+static bool parse_printk_or_console(
+  const char                *param,
+  rtems_device_minor_number *minor_out
+)
+{
+  static const char         *opt;
+  const char                *option;
+  const char                *comma;
+  size_t                     length;
+  size_t                     index;
+  rtems_device_minor_number  minor;
+  console_tbl               *conscfg;
+
+  /*
+   * Check the command line for the type of mode the console is.
+   */
+  opt = bsp_cmdline_arg(param);
+  if ( !opt ) {
+    return false;
+  }
+
+  /*
+   * Fine the length, there can be more command line visible.
+   */
+  length = 0;
+  while ((opt[length] != ' ') && (opt[length] != '\0')) {
+    ++length;
+    if (length > NAME_MAX) {
+      printk("invalid option (%s): too long\n", param);
+      return false;
+    }
+  }
+
+  /*
+   * Only match up to a comma or NULL
+   */
+  index = 0;
+  while ((opt[index] != '=') && (index < length)) {
+    ++index;
+  }
+
+  if (opt[index] != '=') {
+    printk("invalid option (%s): no equals\n", param);
+    return false;
+  }
+
+  ++index;
+  option = &opt[index];
+
+  while ((opt[index] != ',') && (index < length)) {
+    ++index;
+  }
+
+  if (opt[index] == ',')
+    comma = &opt[index];
+  else
+    comma = NULL;
+
+  length = &opt[index] - option;
+
+  conscfg = console_find_console_entry( option, length, &minor );
+  if ( conscfg == NULL ) {
+    return false;
+  }
+
+  *minor_out = minor;
+  if (comma) {
+    option = comma + 1;
+    if (strncmp (option, "115200", sizeof ("115200") - 1) == 0)
+      conscfg->pDeviceParams = (void *)115200;
+    else if (strncmp (option, "57600", sizeof ("57600") - 1) == 0)
+      conscfg->pDeviceParams = (void *)57600;
+    else if (strncmp (option, "38400", sizeof ("38400") - 1) == 0)
+      conscfg->pDeviceParams = (void *)38400;
+    else if (strncmp (option, "19200", sizeof ("19200") - 1) == 0)
+      conscfg->pDeviceParams = (void *)19200;
+    else if (strncmp (option, "9600", sizeof ("9600") - 1) == 0)
+      conscfg->pDeviceParams = (void *)9600;
+    else if (strncmp (option, "4800", sizeof ("4800") - 1) == 0)
+      conscfg->pDeviceParams = (void *)4800;
+  }
+
+  return true;
+}
+
+/*
+ * Helper to retrieve device name
+ */
+static inline const char *get_name(
+  rtems_device_minor_number  minor
+)
+{
+  return Console_Port_Tbl[minor]->sDeviceName;
+}
+
+/*
+ * Parse the arguments early so the printk and console ports are
+ * set appropriately.
+ */
+void pc386_parse_console_arguments(void)
+{
+  rtems_device_minor_number minor;
+  rtems_device_minor_number minor_console = 0;
+  rtems_device_minor_number minor_printk = 0;
+
+  /*
+   * Assume that if only --console is specified, that printk() should
+   * follow that selection by default.
+   */
+  if ( parse_printk_or_console( "--console=", &minor ) ) {
+    minor_console = minor;
+    minor_printk = minor;
+  }
+
+  /*
+   * But if explicitly specified, attempt to honor it.
+   */
+  if ( parse_printk_or_console( "--printk=",  &minor ) ) {
+    minor_printk = minor;
+  }
+
+  printk( "Console: %s printk: %s\n",
+          get_name(minor_console),get_name(minor_printk) );
+
+  /*
+   * Any output after this can cause problems until termios is initialised.
+   */
+  Console_Port_Minor = minor_console;
+  BSPPrintkPort = minor_printk;
+}
+
+/*
+ *  This handles the selection of the console after the devices are
+ *  initialized.
+ */
+void bsp_console_select(void)
+{
+  #ifdef RTEMS_RUNTIME_CONSOLE_SELECT
+    /*
+     * WARNING: This code is really needed any more and should be removed.
+     *          references to COM1 and COM2 like they are wrong.
+     */
+    if ( BSP_runtime_console_select )
+      BSP_runtime_console_select(&BSPPrintkPort, &Console_Port_Minor);
+
+    /*
+     * If no video card, fall back to serial port console
+     */
+    if((Console_Port_Minor == BSP_CONSOLE_VGA)
+     && (*(unsigned char*) NB_MAX_ROW_ADDR == 0)
+     && (*(unsigned short*)NB_MAX_COL_ADDR == 0)) {
+      Console_Port_Minor = BSP_CONSOLE_COM2;
+      BSPPrintkPort      = BSP_CONSOLE_COM1;
+    }
+  #endif
+
+  /*
+   * If the device that was selected isn't available then
+   * let the user know and select the first available device.
+   */
+  if ( !bsp_Is_Available( Console_Port_Minor ) ) {
+    printk(
+      "Error finding %s setting console to first available\n",
+      get_name(Console_Port_Minor)
+    );
+    Console_Port_Minor = bsp_First_Available_Device();
+  }
+}
Index: bsps/i386/pc386/console/defkeymap.c
===================================================================
--- bsps/i386/pc386/console/defkeymap.c	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
+++ bsps/i386/pc386/console/defkeymap.c	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
@@ -0,0 +1,262 @@
+/* Do not edit this file! It was automatically generated by   */
+/*    loadkeys --mktable defkeymap.map > defkeymap.c          */
+
+#include <sys/types.h>
+#include <rtems/keyboard.h>
+#include <rtems/kd.h>
+
+u_short plain_map[NR_KEYS] = {
+	0xf200,	0xf01b,	0xf031,	0xf032,	0xf033,	0xf034,	0xf035,	0xf036,
+	0xf037,	0xf038,	0xf039,	0xf030,	0xf02d,	0xf03d,	0xf07f,	0xf009,
+	0xfb71,	0xfb77,	0xfb65,	0xfb72,	0xfb74,	0xfb79,	0xfb75,	0xfb69,
+	0xfb6f,	0xfb70,	0xf05b,	0xf05d,	0xf201,	0xf702,	0xfb61,	0xfb73,
+	0xfb64,	0xfb66,	0xfb67,	0xfb68,	0xfb6a,	0xfb6b,	0xfb6c,	0xf03b,
+	0xf027,	0xf060,	0xf700,	0xf05c,	0xfb7a,	0xfb78,	0xfb63,	0xfb76,
+	0xfb62,	0xfb6e,	0xfb6d,	0xf02c,	0xf02e,	0xf02f,	0xf700,	0xf30c,
+	0xf703,	0xf020,	0xf207,	0xf100,	0xf101,	0xf102,	0xf103,	0xf104,
+	0xf105,	0xf106,	0xf107,	0xf108,	0xf109,	0xf208,	0xf209,	0xf307,
+	0xf308,	0xf309,	0xf30b,	0xf304,	0xf305,	0xf306,	0xf30a,	0xf301,
+	0xf302,	0xf303,	0xf300,	0xf310,	0xf206,	0xf200,	0xf03c,	0xf10a,
+	0xf10b,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+	0xf30e,	0xf702,	0xf30d,	0xf01c,	0xf701,	0xf205,	0xf114,	0xf603,
+	0xf118,	0xf601,	0xf602,	0xf117,	0xf600,	0xf119,	0xf115,	0xf116,
+	0xf11a,	0xf10c,	0xf10d,	0xf11b,	0xf11c,	0xf110,	0xf311,	0xf11d,
+	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+};
+
+u_short shift_map[NR_KEYS] = {
+	0xf200,	0xf01b,	0xf021,	0xf040,	0xf023,	0xf024,	0xf025,	0xf05e,
+	0xf026,	0xf02a,	0xf028,	0xf029,	0xf05f,	0xf02b,	0xf07f,	0xf009,
+	0xfb51,	0xfb57,	0xfb45,	0xfb52,	0xfb54,	0xfb59,	0xfb55,	0xfb49,
+	0xfb4f,	0xfb50,	0xf07b,	0xf07d,	0xf201,	0xf702,	0xfb41,	0xfb53,
+	0xfb44,	0xfb46,	0xfb47,	0xfb48,	0xfb4a,	0xfb4b,	0xfb4c,	0xf03a,
+	0xf022,	0xf07e,	0xf700,	0xf07c,	0xfb5a,	0xfb58,	0xfb43,	0xfb56,
+	0xfb42,	0xfb4e,	0xfb4d,	0xf03c,	0xf03e,	0xf03f,	0xf700,	0xf30c,
+	0xf703,	0xf020,	0xf207,	0xf10a,	0xf10b,	0xf10c,	0xf10d,	0xf10e,
+	0xf10f,	0xf110,	0xf111,	0xf112,	0xf113,	0xf213,	0xf203,	0xf307,
+	0xf308,	0xf309,	0xf30b,	0xf304,	0xf305,	0xf306,	0xf30a,	0xf301,
+	0xf302,	0xf303,	0xf300,	0xf310,	0xf206,	0xf200,	0xf03e,	0xf10a,
+	0xf10b,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+	0xf30e,	0xf702,	0xf30d,	0xf200,	0xf701,	0xf205,	0xf114,	0xf603,
+	0xf20b,	0xf601,	0xf602,	0xf117,	0xf600,	0xf20a,	0xf115,	0xf116,
+	0xf11a,	0xf10c,	0xf10d,	0xf11b,	0xf11c,	0xf110,	0xf311,	0xf11d,
+	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+};
+
+u_short altgr_map[NR_KEYS] = {
+	0xf200,	0xf200,	0xf200,	0xf040,	0xf200,	0xf024,	0xf200,	0xf200,
+	0xf07b,	0xf05b,	0xf05d,	0xf07d,	0xf05c,	0xf200,	0xf200,	0xf200,
+	0xfb71,	0xfb77,	0xf918,	0xfb72,	0xfb74,	0xfb79,	0xfb75,	0xfb69,
+	0xfb6f,	0xfb70,	0xf200,	0xf07e,	0xf201,	0xf702,	0xf914,	0xfb73,
+	0xf917,	0xf919,	0xfb67,	0xfb68,	0xfb6a,	0xfb6b,	0xfb6c,	0xf200,
+	0xf200,	0xf200,	0xf700,	0xf200,	0xfb7a,	0xfb78,	0xf916,	0xfb76,
+	0xf915,	0xfb6e,	0xfb6d,	0xf200,	0xf200,	0xf200,	0xf700,	0xf30c,
+	0xf703,	0xf200,	0xf207,	0xf50c,	0xf50d,	0xf50e,	0xf50f,	0xf510,
+	0xf511,	0xf512,	0xf513,	0xf514,	0xf515,	0xf208,	0xf202,	0xf911,
+	0xf912,	0xf913,	0xf30b,	0xf90e,	0xf90f,	0xf910,	0xf30a,	0xf90b,
+	0xf90c,	0xf90d,	0xf90a,	0xf310,	0xf206,	0xf200,	0xf07c,	0xf516,
+	0xf517,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+	0xf30e,	0xf702,	0xf30d,	0xf200,	0xf701,	0xf205,	0xf114,	0xf603,
+	0xf118,	0xf601,	0xf602,	0xf117,	0xf600,	0xf119,	0xf115,	0xf116,
+	0xf11a,	0xf10c,	0xf10d,	0xf11b,	0xf11c,	0xf110,	0xf311,	0xf11d,
+	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+};
+
+u_short ctrl_map[NR_KEYS] = {
+	0xf200,	0xf200,	0xf200,	0xf000,	0xf01b,	0xf01c,	0xf01d,	0xf01e,
+	0xf01f,	0xf07f,	0xf200,	0xf200,	0xf01f,	0xf200,	0xf008,	0xf200,
+	0xf011,	0xf017,	0xf005,	0xf012,	0xf014,	0xf019,	0xf015,	0xf009,
+	0xf00f,	0xf010,	0xf01b,	0xf01d,	0xf201,	0xf702,	0xf001,	0xf013,
+	0xf004,	0xf006,	0xf007,	0xf008,	0xf00a,	0xf00b,	0xf00c,	0xf200,
+	0xf007,	0xf000,	0xf700,	0xf01c,	0xf01a,	0xf018,	0xf003,	0xf016,
+	0xf002,	0xf00e,	0xf00d,	0xf200,	0xf20e,	0xf07f,	0xf700,	0xf30c,
+	0xf703,	0xf000,	0xf207,	0xf100,	0xf101,	0xf102,	0xf103,	0xf104,
+	0xf105,	0xf106,	0xf107,	0xf108,	0xf109,	0xf208,	0xf204,	0xf307,
+	0xf308,	0xf309,	0xf30b,	0xf304,	0xf305,	0xf306,	0xf30a,	0xf301,
+	0xf302,	0xf303,	0xf300,	0xf310,	0xf206,	0xf200,	0xf200,	0xf10a,
+	0xf10b,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+	0xf30e,	0xf702,	0xf30d,	0xf01c,	0xf701,	0xf205,	0xf114,	0xf603,
+	0xf118,	0xf601,	0xf602,	0xf117,	0xf600,	0xf119,	0xf115,	0xf116,
+	0xf11a,	0xf10c,	0xf10d,	0xf11b,	0xf11c,	0xf110,	0xf311,	0xf11d,
+	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+};
+
+u_short shift_ctrl_map[NR_KEYS] = {
+	0xf200,	0xf200,	0xf200,	0xf000,	0xf200,	0xf200,	0xf200,	0xf200,
+	0xf200,	0xf200,	0xf200,	0xf200,	0xf01f,	0xf200,	0xf200,	0xf200,
+	0xf011,	0xf017,	0xf005,	0xf012,	0xf014,	0xf019,	0xf015,	0xf009,
+	0xf00f,	0xf010,	0xf200,	0xf200,	0xf201,	0xf702,	0xf001,	0xf013,
+	0xf004,	0xf006,	0xf007,	0xf008,	0xf00a,	0xf00b,	0xf00c,	0xf200,
+	0xf200,	0xf200,	0xf700,	0xf200,	0xf01a,	0xf018,	0xf003,	0xf016,
+	0xf002,	0xf00e,	0xf00d,	0xf200,	0xf200,	0xf200,	0xf700,	0xf30c,
+	0xf703,	0xf200,	0xf207,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf208,	0xf200,	0xf307,
+	0xf308,	0xf309,	0xf30b,	0xf304,	0xf305,	0xf306,	0xf30a,	0xf301,
+	0xf302,	0xf303,	0xf300,	0xf310,	0xf206,	0xf200,	0xf200,	0xf200,
+	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+	0xf30e,	0xf702,	0xf30d,	0xf200,	0xf701,	0xf205,	0xf114,	0xf603,
+	0xf118,	0xf601,	0xf602,	0xf117,	0xf600,	0xf119,	0xf115,	0xf116,
+	0xf11a,	0xf10c,	0xf10d,	0xf11b,	0xf11c,	0xf110,	0xf311,	0xf11d,
+	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+};
+
+u_short alt_map[NR_KEYS] = {
+	0xf200,	0xf81b,	0xf831,	0xf832,	0xf833,	0xf834,	0xf835,	0xf836,
+	0xf837,	0xf838,	0xf839,	0xf830,	0xf82d,	0xf83d,	0xf87f,	0xf809,
+	0xf871,	0xf877,	0xf865,	0xf872,	0xf874,	0xf879,	0xf875,	0xf869,
+	0xf86f,	0xf870,	0xf85b,	0xf85d,	0xf80d,	0xf702,	0xf861,	0xf873,
+	0xf864,	0xf866,	0xf867,	0xf868,	0xf86a,	0xf86b,	0xf86c,	0xf83b,
+	0xf827,	0xf860,	0xf700,	0xf85c,	0xf87a,	0xf878,	0xf863,	0xf876,
+	0xf862,	0xf86e,	0xf86d,	0xf82c,	0xf82e,	0xf82f,	0xf700,	0xf30c,
+	0xf703,	0xf820,	0xf207,	0xf500,	0xf501,	0xf502,	0xf503,	0xf504,
+	0xf505,	0xf506,	0xf507,	0xf508,	0xf509,	0xf208,	0xf209,	0xf907,
+	0xf908,	0xf909,	0xf30b,	0xf904,	0xf905,	0xf906,	0xf30a,	0xf901,
+	0xf902,	0xf903,	0xf900,	0xf310,	0xf206,	0xf200,	0xf83c,	0xf50a,
+	0xf50b,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+	0xf30e,	0xf702,	0xf30d,	0xf01c,	0xf701,	0xf205,	0xf114,	0xf603,
+	0xf118,	0xf210,	0xf211,	0xf117,	0xf600,	0xf119,	0xf115,	0xf116,
+	0xf11a,	0xf10c,	0xf10d,	0xf11b,	0xf11c,	0xf110,	0xf311,	0xf11d,
+	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+};
+
+u_short ctrl_alt_map[NR_KEYS] = {
+	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+	0xf811,	0xf817,	0xf805,	0xf812,	0xf814,	0xf819,	0xf815,	0xf809,
+	0xf80f,	0xf810,	0xf200,	0xf200,	0xf201,	0xf702,	0xf801,	0xf813,
+	0xf804,	0xf806,	0xf807,	0xf808,	0xf80a,	0xf80b,	0xf80c,	0xf200,
+	0xf200,	0xf200,	0xf700,	0xf200,	0xf81a,	0xf818,	0xf803,	0xf816,
+	0xf802,	0xf80e,	0xf80d,	0xf200,	0xf200,	0xf200,	0xf700,	0xf30c,
+	0xf703,	0xf200,	0xf207,	0xf500,	0xf501,	0xf502,	0xf503,	0xf504,
+	0xf505,	0xf506,	0xf507,	0xf508,	0xf509,	0xf208,	0xf200,	0xf307,
+	0xf308,	0xf309,	0xf30b,	0xf304,	0xf305,	0xf306,	0xf30a,	0xf301,
+	0xf302,	0xf303,	0xf300,	0xf20c,	0xf206,	0xf200,	0xf200,	0xf50a,
+	0xf50b,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+	0xf30e,	0xf702,	0xf30d,	0xf200,	0xf701,	0xf205,	0xf114,	0xf603,
+	0xf118,	0xf601,	0xf602,	0xf117,	0xf600,	0xf119,	0xf115,	0xf20c,
+	0xf11a,	0xf10c,	0xf10d,	0xf11b,	0xf11c,	0xf110,	0xf311,	0xf11d,
+	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
+};
+
+ushort *key_maps[MAX_NR_KEYMAPS] = {
+	plain_map, shift_map, altgr_map, 0,
+	ctrl_map, shift_ctrl_map, 0, 0,
+	alt_map, 0, 0, 0,
+	ctrl_alt_map,	0
+};
+
+unsigned int keymap_count = 7;
+
+/*
+ * Philosophy: most people do not define more strings, but they who do
+ * often want quite a lot of string space. So, we statically allocate
+ * the default and allocate dynamically in chunks of 512 bytes.
+ */
+
+char func_buf[] = {
+	'\033', '[', '[', 'A', 0,
+	'\033', '[', '[', 'B', 0,
+	'\033', '[', '[', 'C', 0,
+	'\033', '[', '[', 'D', 0,
+	'\033', '[', '[', 'E', 0,
+	'\033', '[', '1', '7', '~', 0,
+	'\033', '[', '1', '8', '~', 0,
+	'\033', '[', '1', '9', '~', 0,
+	'\033', '[', '2', '0', '~', 0,
+	'\033', '[', '2', '1', '~', 0,
+	'\033', '[', '2', '3', '~', 0,
+	'\033', '[', '2', '4', '~', 0,
+	'\033', '[', '2', '5', '~', 0,
+	'\033', '[', '2', '6', '~', 0,
+	'\033', '[', '2', '8', '~', 0,
+	'\033', '[', '2', '9', '~', 0,
+	'\033', '[', '3', '1', '~', 0,
+	'\033', '[', '3', '2', '~', 0,
+	'\033', '[', '3', '3', '~', 0,
+	'\033', '[', '3', '4', '~', 0,
+	'\033', '[', '1', '~', 0,
+	'\033', '[', '2', '~', 0,
+	'\033', '[', '3', '~', 0,
+	'\033', '[', '4', '~', 0,
+	'\033', '[', '5', '~', 0,
+	'\033', '[', '6', '~', 0,
+	'\033', '[', 'M', 0,
+	'\033', '[', 'P', 0,
+};
+
+char *funcbufptr = func_buf;
+int funcbufsize = sizeof(func_buf);
+int funcbufleft = 0;          /* space left */
+
+char *func_table[MAX_NR_FUNC] = {
+	func_buf + 0,
+	func_buf + 5,
+	func_buf + 10,
+	func_buf + 15,
+	func_buf + 20,
+	func_buf + 25,
+	func_buf + 31,
+	func_buf + 37,
+	func_buf + 43,
+	func_buf + 49,
+	func_buf + 55,
+	func_buf + 61,
+	func_buf + 67,
+	func_buf + 73,
+	func_buf + 79,
+	func_buf + 85,
+	func_buf + 91,
+	func_buf + 97,
+	func_buf + 103,
+	func_buf + 109,
+	func_buf + 115,
+	func_buf + 120,
+	func_buf + 125,
+	func_buf + 130,
+	func_buf + 135,
+	func_buf + 140,
+	func_buf + 145,
+	0,
+	0,
+	func_buf + 149,
+	0,
+};
+
+struct kbdiacr accent_table[MAX_DIACR] = {
+	{'`', 'A', '\300'},	{'`', 'a', '\340'},
+	{'\'', 'A', '\301'},	{'\'', 'a', '\341'},
+	{'^', 'A', '\302'},	{'^', 'a', '\342'},
+	{'~', 'A', '\303'},	{'~', 'a', '\343'},
+	{'"', 'A', '\304'},	{'"', 'a', '\344'},
+	{'O', 'A', '\305'},	{'o', 'a', '\345'},
+	{'0', 'A', '\305'},	{'0', 'a', '\345'},
+	{'A', 'A', '\305'},	{'a', 'a', '\345'},
+	{'A', 'E', '\306'},	{'a', 'e', '\346'},
+	{',', 'C', '\307'},	{',', 'c', '\347'},
+	{'`', 'E', '\310'},	{'`', 'e', '\350'},
+	{'\'', 'E', '\311'},	{'\'', 'e', '\351'},
+	{'^', 'E', '\312'},	{'^', 'e', '\352'},
+	{'"', 'E', '\313'},	{'"', 'e', '\353'},
+	{'`', 'I', '\314'},	{'`', 'i', '\354'},
+	{'\'', 'I', '\315'},	{'\'', 'i', '\355'},
+	{'^', 'I', '\316'},	{'^', 'i', '\356'},
+	{'"', 'I', '\317'},	{'"', 'i', '\357'},
+	{'-', 'D', '\320'},	{'-', 'd', '\360'},
+	{'~', 'N', '\321'},	{'~', 'n', '\361'},
+	{'`', 'O', '\322'},	{'`', 'o', '\362'},
+	{'\'', 'O', '\323'},	{'\'', 'o', '\363'},
+	{'^', 'O', '\324'},	{'^', 'o', '\364'},
+	{'~', 'O', '\325'},	{'~', 'o', '\365'},
+	{'"', 'O', '\326'},	{'"', 'o', '\366'},
+	{'/', 'O', '\330'},	{'/', 'o', '\370'},
+	{'`', 'U', '\331'},	{'`', 'u', '\371'},
+	{'\'', 'U', '\332'},	{'\'', 'u', '\372'},
+	{'^', 'U', '\333'},	{'^', 'u', '\373'},
+	{'"', 'U', '\334'},	{'"', 'u', '\374'},
+	{'\'', 'Y', '\335'},	{'\'', 'y', '\375'},
+	{'T', 'H', '\336'},	{'t', 'h', '\376'},
+	{'s', 's', '\337'},	{'"', 'y', '\377'},
+	{'s', 'z', '\337'},	{'i', 'j', '\377'},
+};
+
+unsigned int accent_table_size = 68;
Index: bsps/i386/pc386/console/exar17d15x.c
===================================================================
--- bsps/i386/pc386/console/exar17d15x.c	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
+++ bsps/i386/pc386/console/exar17d15x.c	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
@@ -0,0 +1,224 @@
+/**
+ * @file
+ *
+ * @brief Driver for Exar XR17D15x Multiport UARTs
+ *
+ * This driver supports 2, 4 or 8 port Exar parts which are NS16550
+ * compatible.
+ */
+
+/*
+ *  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 <bsp.h>
+#include <termios.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <rtems/termiostypes.h>
+#include <libchip/serial.h>
+#include <libchip/ns16550.h>
+#include <rtems/bspIo.h>
+#include <rtems/pci.h>
+#include <bsp/exar17d15x.h>
+#include "../../shared/dev/serial/legacy-console.h"
+
+#define MAX_BOARDS 4
+
+/*
+ *  This is the rate for the clock internal to the parts.
+ */
+#define EXAR_CLOCK_RATE  (921600*16)
+
+/*
+ *  Supported PCI Ids
+ */
+#define PCI_VENDOR_ID_EXAR 0x13A8
+#define PCI_VENDOR_ID_EXAR_XR17D158 0x0158
+#define PCI_VENDOR_ID_EXAR_XR17D154 0x0154
+#define PCI_VENDOR_ID_EXAR_XR17D152 0x0152
+
+/*
+ * Structure to manage each instance found.
+ */
+typedef struct {
+  uint16_t  vendor;
+  uint16_t  device;
+  uint8_t   ports;
+} exar_parts_t;
+
+static exar_parts_t Supported[] = {
+  { PCI_VENDOR_ID_EXAR, PCI_VENDOR_ID_EXAR_XR17D158, 8 },
+  { PCI_VENDOR_ID_EXAR, PCI_VENDOR_ID_EXAR_XR17D154, 4 },
+  { PCI_VENDOR_ID_EXAR, PCI_VENDOR_ID_EXAR_XR17D152, 2 },
+  { 0, 0, 0 }
+};
+
+/*
+ * Information saved from PCI scan
+ */
+typedef struct {
+  bool      found;
+  uint32_t  base;
+  uint8_t   irq;
+  uint8_t   bus;
+  uint8_t   slot;
+  uint8_t   ports;
+} exar17d15x_conf_t;
+
+/*
+ *  Register Access Routines
+ */
+static uint8_t xr17d15x_get_register(uint32_t addr, uint8_t i)
+{
+  uint8_t          val = 0;
+  volatile uint8_t *reg = (volatile uint8_t *)(addr + i);
+
+  val = *reg;
+  // printk( "RD %p -> 0x%02x\n", reg, val );
+  return val;
+}
+
+static void xr17d15x_set_register(uint32_t addr, uint8_t i, uint8_t val)
+{
+  volatile uint8_t *reg = (volatile uint8_t *)(addr + i);
+
+  // printk( "WR %p <- 0x%02x\n", reg, val );
+  *reg = val;
+}
+
+rtems_device_driver exar17d15x_initialize(
+  rtems_device_major_number  major,
+  rtems_device_minor_number  minor_arg,
+  void                      *arg
+)
+{
+  // int  pbus, pdev, pfun;
+  exar17d15x_conf_t  conf[MAX_BOARDS];
+  int              boards = 0;
+  int              b = 0;
+  int              p;
+  console_tbl     *ports;
+  console_tbl     *port_p;
+  int              pbus;
+  int              pdev;
+  int              pfun;
+  int              status;
+  int              instance;
+  int              i;
+  int              total_ports = 0;
+
+  for ( b=0 ; b<MAX_BOARDS ; b++ ) {
+    conf[b].found = false;
+  }
+
+  /*
+   *  Scan for Serial port boards
+   *
+   *  NOTE: There appear to be Exar parts with 2 and 4 ports which would
+   *        be easy to support.  Just change the hard-coded 8 ports per
+   *        board to variable and adjust.
+   *
+   *  NOTE: There are likely other board vendors which could be supported
+   *        by this.
+   */
+  for ( instance=0 ; instance < MAX_BOARDS ; instance++ ) {
+
+    for ( i=0 ; Supported[i].ports != 0 ; i++ ) {
+      status = pci_find_device(
+        Supported[i].vendor,
+        Supported[i].device,
+        instance,
+        &pbus,
+        &pdev,
+        &pfun
+      );
+      if ( status == PCIB_ERR_SUCCESS ) {
+        boards++;
+        conf[instance].found = true;
+        conf[instance].ports = Supported[i].ports;
+        total_ports += conf[instance].ports;
+        break;
+      }
+    }
+
+    if ( status != PCIB_ERR_SUCCESS )
+      continue;
+
+    pci_read_config_byte(
+      pbus,
+      pdev,
+      pfun,
+      PCI_INTERRUPT_LINE,
+      &conf[instance].irq
+    );
+    pci_read_config_dword(
+      pbus,
+      pdev,
+      pfun,
+      PCI_BASE_ADDRESS_0,
+      &conf[instance].base
+    );
+    printk(
+      "Found Exar 17D15x %d at 0x%08lx IRQ %d with %d ports\n",
+      instance,
+      conf[instance].base,
+      conf[instance].irq,
+      conf[instance].ports
+    );
+  }
+
+  /*
+   *  Now allocate array of device structures and fill them in
+   */
+  ports = calloc( total_ports, sizeof( console_tbl ) );
+  port_p = ports;
+  for ( b=0 ; b<MAX_BOARDS ; b++ ) {
+    if ( conf[b].found == false )
+      continue;
+    for ( p=0 ; p<conf[b].ports ; p++ ) {
+      char name[32];
+
+      sprintf( name, "/dev/exar17d15x_%d_%d", b, p );
+      //printk("Found %s\n", name );
+      port_p->sDeviceName   = strdup( name );
+      port_p->deviceType    = SERIAL_NS16550;
+      #if 1
+        port_p->pDeviceFns    = &ns16550_fns_polled;
+      #else
+        port_p->pDeviceFns    = &ns16550_fns;
+      #endif
+
+      port_p->deviceProbe   = NULL;
+      port_p->pDeviceFlow   = NULL;
+      port_p->ulMargin      = 16;
+      port_p->ulHysteresis  = 8;
+      port_p->pDeviceParams = (void *) 9600;
+      port_p->ulCtrlPort1   = conf[b].base + (p * 0x0200);
+      port_p->ulCtrlPort2   = 0;                   /* NA */
+      port_p->ulDataPort    = 0;                   /* NA */
+      port_p->getRegister   = xr17d15x_get_register;
+      port_p->setRegister   = xr17d15x_set_register;
+      port_p->getData       = NULL;                /* NA */
+      port_p->setData       = NULL;                /* NA */
+      port_p->ulClock       = EXAR_CLOCK_RATE;
+      port_p->ulIntVector   = conf[b].irq;
+
+      port_p++;
+    }  /* end ports */
+  }    /* end boards */
+
+  /*
+   *  Register the devices
+   */
+  if ( boards )
+    console_register_devices( ports, total_ports );
+
+  return RTEMS_SUCCESSFUL;
+}
Index: bsps/i386/pc386/console/fb_cirrus.c
===================================================================
--- bsps/i386/pc386/console/fb_cirrus.c	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
+++ bsps/i386/pc386/console/fb_cirrus.c	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
@@ -0,0 +1,766 @@
+/*
+ *  FB driver for Cirrus GD5446 graphic hardware.
+ *  Tested to be compatible with QEMU GD5446 emulation but not on real HW.
+ *
+ *  Copyright (c) 2012 - Alexandru-Sever Horin (alex.sever.h@gmail.com).
+ *
+ *  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.
+ *
+ *  The code is based on next information sources:
+ *    - CL-GD5446 Technical Reference Manual, 1996, Second Edition
+ *    - RTEMS fb_vga.c - Rosimildo da Silva ( rdasilva@connecttel.com )
+ *    - Cirrus xf86 driver - used as VGA hardware setup sequence documentation
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <pthread.h>
+
+#include <bsp.h>
+#include <bsp/irq.h>
+#include <rtems/libio.h>
+#include <rtems/pci.h>
+
+#include <rtems/fb.h>
+#include <rtems/framebuffer.h>
+#include <rtems/score/atomic.h>
+
+/* flag to limit driver to protect against multiple opens */
+static Atomic_Flag driver_mutex;
+
+/* screen information for the VGA driver
+ * standard structures
+ */
+static struct fb_var_screeninfo fb_var;
+static struct fb_fix_screeninfo fb_fix;
+
+#define CIRRUS_VENDOR_ID         0x1013
+#define CIRRUS_GD5446_DEVICE_ID  0x00b8
+
+typedef struct _DisplayModeRec {
+  struct _DisplayModeRec *prev;
+  struct _DisplayModeRec *next;
+  char *name;                 /* identifier for the mode */
+  int type;
+
+  /* These are the values that the user sees/provides */
+  int Clock;                  /* pixel clock freq (kHz) */
+  int HDisplay;               /* horizontal timing */
+  int HSyncStart;
+  int HSyncEnd;
+  int HTotal;
+  int HSkew;
+  int VDisplay;               /* vertical timing */
+  int VSyncStart;
+  int VSyncEnd;
+  int VTotal;
+  int VScan;
+  int Flags;
+
+  /* These are the values the hardware uses */
+  int ClockIndex;
+  int SynthClock;             /* Actual clock freq to
+   * be programmed  (kHz) */
+  int CrtcHDisplay;
+  int CrtcHBlankStart;
+  int CrtcHSyncStart;
+  int CrtcHSyncEnd;
+  int CrtcHBlankEnd;
+  int CrtcHTotal;
+  int CrtcHSkew;
+  int CrtcVDisplay;
+  int CrtcVBlankStart;
+  int CrtcVSyncStart;
+  int CrtcVSyncEnd;
+  int CrtcVBlankEnd;
+  int CrtcVTotal;
+  int CrtcHAdjusted;
+  int CrtcVAdjusted;
+  int PrivSize;
+  int32_t *Private;
+  int PrivFlags;
+
+  float HSync, VRefresh;
+} DisplayModeRec, *DisplayModePtr;
+
+static DisplayModeRec available_modes[] = {
+    {
+        .Clock      = 31500 ,
+        .HDisplay   = 640 ,
+        .HSyncStart = 664 ,
+        .HSyncEnd   = 704 ,
+        .HTotal     = 832 ,
+        .HSkew      = 0 ,
+        .VDisplay   = 480 ,       /* vertical timing */
+        .VSyncStart = 489 ,
+        .VSyncEnd   = 491 ,
+        .VTotal     = 520 ,
+        .VScan      = 0,
+        .Flags      = 0
+    },
+    {
+        .Clock      = 40000 ,
+        .HDisplay   = 800 ,
+        .HSyncStart = 840 ,
+        .HSyncEnd   = 968 ,
+        .HTotal     = 1056 ,
+        .HSkew      = 0 ,
+        .VDisplay   = 600 ,       /* vertical timing */
+        .VSyncStart = 601 ,
+        .VSyncEnd   = 605 ,
+        .VTotal     = 628 ,
+        .VScan      = 0,
+        .Flags      = 0
+    },
+};
+static DisplayModePtr active_mode;
+
+/* The display mode used for the board hardcoded in the following define
+ * Index in above structure
+ */
+#define CIRRUS_DISPLAY_MODE  0
+
+/* The display bytes per pixel used for the board hardcoded in the following define
+ * Index in above structure
+ */
+#define CIRRUS_DEFAULT_BPP 24
+
+/* cirrus board information */
+struct cirrus_board_str{
+  int    pci_bus;
+  int    pci_device;
+  int    pci_function;
+  void  *reg_base;
+};
+
+static struct cirrus_board_str cirrus_board_info;
+
+/*
+ * get information from the board
+ */
+static int
+cirrus_pci_read( struct cirrus_board_str *cirrus_board, uint32_t *mem_base, uint32_t *cirrus_register_base)
+{
+  int r;
+
+  r = pci_read_config_dword(
+      cirrus_board->pci_bus, cirrus_board->pci_device, cirrus_board->pci_function,
+      PCI_BASE_ADDRESS_0, mem_base);
+  if( r != PCIB_ERR_SUCCESS)
+    return RTEMS_UNSATISFIED;
+
+  r = pci_read_config_dword(
+      cirrus_board->pci_bus, cirrus_board->pci_device, cirrus_board->pci_function,
+      PCI_BASE_ADDRESS_1, cirrus_register_base);
+  if( r != PCIB_ERR_SUCCESS)
+    return RTEMS_UNSATISFIED;
+
+  *mem_base &= PCI_BASE_ADDRESS_MEM_MASK;
+  *cirrus_register_base     &= PCI_BASE_ADDRESS_MEM_MASK;
+
+  return RTEMS_SUCCESSFUL;
+}
+
+static inline int
+fb_cirrus_read_config_dword(
+    struct cirrus_board_str *fbst,
+    unsigned char where,
+    uint32_t     *pval)
+{
+  return pci_read_config_dword(
+      fbst->pci_bus, fbst->pci_device, fbst->pci_function,
+      where, pval);
+}
+
+static inline int
+fb_cirrus_write_config_dword(
+    struct cirrus_board_str *fbst,
+    unsigned char where,
+    uint32_t     val)
+{
+  return pci_write_config_dword(
+      fbst->pci_bus, fbst->pci_device, fbst->pci_function,
+      where, val);
+}
+
+static inline void
+fb_cirrus_write_reg8 (
+    const struct cirrus_board_str *fbst,
+    unsigned int reg,
+    unsigned int val)
+{
+  *(volatile uint8_t*)((char *)fbst->reg_base + reg) = val;
+}
+
+static inline unsigned int
+fb_cirrus_read_reg8 (
+    const struct cirrus_board_str *fbst,
+    unsigned int reg)
+{
+  return *(volatile uint8_t*)((char *)fbst->reg_base + reg);
+}
+
+#define SEQ_INDEX 0x04
+#define SEQ_DATA 0x05
+
+static inline void
+fb_cirrus_write_seq_reg (
+    const struct cirrus_board_str *fbst,
+    unsigned int reg,
+    unsigned int val)
+{
+  fb_cirrus_write_reg8(fbst, SEQ_INDEX, reg);
+  fb_cirrus_write_reg8(fbst, SEQ_DATA, val);
+}
+
+static inline unsigned int
+fb_cirrus_read_seq_reg (
+    const struct cirrus_board_str *fbst,
+    unsigned int reg)
+{
+  fb_cirrus_write_reg8(fbst, SEQ_INDEX, reg);
+  return fb_cirrus_read_reg8(fbst, SEQ_DATA);
+}
+
+#define CRT_INDEX 0x14
+#define CRT_DATA 0x15
+
+static inline void
+fb_cirrus_write_crt_reg (
+    const struct cirrus_board_str *fbst,
+    unsigned int reg,
+    unsigned int val)
+{
+  fb_cirrus_write_reg8(fbst, CRT_INDEX, reg);
+  fb_cirrus_write_reg8(fbst, CRT_DATA, val);
+}
+
+static inline unsigned int
+fb_cirrus_read_crt_reg (
+    const struct cirrus_board_str *fbst,
+    unsigned int reg)
+{
+  fb_cirrus_write_reg8(fbst, CRT_INDEX, reg);
+  return fb_cirrus_read_reg8(fbst, CRT_DATA);
+}
+
+#define GDC_INDEX 0x0E
+#define GDC_DATA 0x0F
+
+static inline void
+fb_cirrus_write_gdc_reg (
+    const struct cirrus_board_str *fbst,
+    unsigned int reg,
+    unsigned int val)
+{
+  fb_cirrus_write_reg8(fbst, GDC_INDEX, reg);
+  fb_cirrus_write_reg8(fbst, GDC_DATA, val);
+}
+
+static inline unsigned int
+fb_cirrus_read_gdc_reg (
+    const struct cirrus_board_str *fbst,
+    unsigned int reg)
+{
+  fb_cirrus_write_reg8(fbst, GDC_INDEX, reg);
+  return fb_cirrus_read_reg8(fbst, GDC_DATA);
+}
+
+#define VGA_DAC_MASK 0x06
+
+static inline void
+fb_cirrus_write_hdr_reg (
+    const struct cirrus_board_str *fbst,
+    unsigned int val)
+{
+  volatile unsigned int dummy RTEMS_UNUSED;
+  dummy = fb_cirrus_read_reg8(fbst, VGA_DAC_MASK);
+  dummy = fb_cirrus_read_reg8(fbst, VGA_DAC_MASK);
+  dummy = fb_cirrus_read_reg8(fbst, VGA_DAC_MASK);
+  dummy = fb_cirrus_read_reg8(fbst, VGA_DAC_MASK);
+  fb_cirrus_write_reg8(fbst, VGA_DAC_MASK, val);
+}
+
+/* Functionality to support multiple VGA frame buffers can be added easily,
+ * but is not supported at this moment because there is no need for two or
+ * more "classic" VGA adapters.  Multiple frame buffer drivers may be
+ * implemented and If we had implement it they would be named as "/dev/fb0",
+ * "/dev/fb1", "/dev/fb2" and so on.
+ */
+
+/*
+ * fb_cirrus device driver INITIALIZE entry point.
+ */
+rtems_device_driver
+frame_buffer_initialize(
+    rtems_device_major_number  major,
+    rtems_device_minor_number  minor,
+    void                      *arg
+)
+{
+  rtems_status_code status;
+  int res;
+
+  printk( "FB_CIRRUS -- driver initializing..\n" );
+
+  res = pci_find_device(
+      CIRRUS_VENDOR_ID,
+      CIRRUS_GD5446_DEVICE_ID,
+      minor,
+      &cirrus_board_info.pci_bus,
+      &cirrus_board_info.pci_device,
+      &cirrus_board_info.pci_function
+  );
+
+  if ( res != PCIB_ERR_SUCCESS ) {
+      printk( "FB_CIRRUS initialize -- device not found\n" );
+
+      return RTEMS_UNSATISFIED;
+  }
+  else{
+      printk( "FB_CIRRUS -- driver initializing..\n" );
+      /*
+       * Register the device
+       */
+      status = rtems_io_register_name (FRAMEBUFFER_DEVICE_0_NAME, major, 0);
+      if (status != RTEMS_SUCCESSFUL) {
+          printk("Error registering " FRAMEBUFFER_DEVICE_0_NAME
+                 " FB_CIRRUS framebuffer device!\n");
+          rtems_fatal_error_occurred( status );
+      }
+
+      _Atomic_Flag_clear(&driver_mutex, ATOMIC_ORDER_RELEASE);
+
+      return RTEMS_SUCCESSFUL;
+  }
+}
+
+/*
+ * This function is used to initialize the Start Address - the first
+ * displayed location in the video memory.
+ * Usually mandatory
+ */
+static void
+cirrus_adjust_frame( struct cirrus_board_str *board, int x, int y)
+{
+  uint32_t Base;
+  uint8_t tmp;
+
+  Base = ((y * fb_var.xres + x) >> 3);
+  if (fb_var.bits_per_pixel != 1)
+    Base *= (fb_var.bits_per_pixel >> 2);
+
+  printk("FB_CIRRUS: cirrus_adjust_frame %d %d >>> %d %x\n", x, y, Base, Base);
+
+  if ((Base & ~0x000FFFFF) != 0) {
+      printk("FB_CIRRUS: Internal error: cirrus_adjust_frame: cannot handle overflow\n");
+      return;
+  }
+
+  fb_cirrus_write_crt_reg( board,  0x0C, (Base >> 8) & 0xff);
+  fb_cirrus_write_crt_reg( board,  0x0D, Base & 0xff);
+
+  tmp = fb_cirrus_read_crt_reg( board,  0x1B);
+  tmp &= 0xF2;
+  tmp |= (Base >> 16) & 0x01;
+  tmp |= (Base >> 15) & 0x0C;
+  fb_cirrus_write_crt_reg( board,  0x1B, tmp);
+
+  tmp = fb_cirrus_read_crt_reg( board, 0x1D);
+  tmp &= 0x7F;
+  tmp |= (Base >> 12) & 0x80;
+  fb_cirrus_write_crt_reg( board,  0x1D, tmp);
+}
+
+static int
+cirrus_set_mode(DisplayModePtr mode)
+{
+  int depthcode = fb_var.bits_per_pixel;;
+  int width;
+  int HDiv2 = 0, VDiv2 = 0;
+  const struct cirrus_board_str *cirrus_board_ptr = &cirrus_board_info;
+  int temp;
+  int hdr = -1;
+
+  printk("FB_CIRRUS: mode  %d bpp, %d Hz    %d %d %d %d   %d %d %d %d\n",
+      fb_var.bits_per_pixel,
+      mode->Clock,
+      mode->HDisplay,
+      mode->HSyncStart,
+      mode->HSyncEnd,
+      mode->HTotal,
+      mode->VDisplay,
+      mode->VSyncStart,
+      mode->VSyncEnd,
+      mode->VTotal);
+
+  if ( mode->Clock >  85500 ) {
+      /* The actual DAC register value is set later. */
+      /* The CRTC is clocked at VCLK / 2, so we must half the */
+      /* horizontal timings. */
+      if (!mode->CrtcHAdjusted) {
+          mode->HDisplay >>= 1;
+          mode->HSyncStart >>= 1;
+          mode->HTotal >>= 1;
+          mode->HSyncEnd >>= 1;
+          mode->SynthClock >>= 1;
+          mode->CrtcHAdjusted = TRUE;
+      }
+      depthcode += 64;
+      HDiv2 = 1;
+  }
+  if (mode->VTotal >= 1024 ) {
+      /* For non-interlaced vertical timing >= 1024, the vertical timings */
+      /* are divided by 2 and VGA CRTC 0x17 bit 2  is set. */
+      if (!mode->CrtcVAdjusted) {
+          mode->VDisplay >>= 1;
+          mode->VSyncStart >>= 1;
+          mode->VSyncEnd >>= 1;
+          mode->VTotal >>= 1;
+          mode->CrtcVAdjusted = TRUE;
+      }
+      VDiv2 = 1;
+  }
+
+  /****************************************************
+   * Sequential registers
+   */
+  fb_cirrus_write_seq_reg(cirrus_board_ptr, 0x00, 0x00);
+  fb_cirrus_write_seq_reg(cirrus_board_ptr, 0x01, 0x01);
+  fb_cirrus_write_seq_reg(cirrus_board_ptr, 0x02, 0x0F);
+  fb_cirrus_write_seq_reg(cirrus_board_ptr, 0x03, 0x00);
+  fb_cirrus_write_seq_reg(cirrus_board_ptr, 0x04, 0x0E);
+
+  /****************************************************
+   * CRTC Controller Registers
+   */
+  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x00, (mode->HTotal >> 3) - 5 );
+  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x01, (mode->HDisplay >> 3) - 1);
+  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x02, (mode->HSyncStart >> 3) - 1);
+  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x03, ((mode->HSyncEnd >> 3) & 0x1F) | 0x80);
+  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x04, (mode->HSyncStart >> 3));
+  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x05,
+      (((mode->HSyncEnd >> 3) & 0x20 ) << 2 )
+      | (((mode->HSyncEnd >> 3)) & 0x1F));
+  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x06, (mode->VTotal - 2) & 0xFF);
+  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x07,
+      (((mode->VTotal -2) & 0x100) >> 8 )
+      | (((mode->VDisplay -1) & 0x100) >> 7 )
+      | ((mode->VSyncStart & 0x100) >> 6 )
+      | (((mode->VSyncStart) & 0x100) >> 5 )
+      | 0x10
+      | (((mode->VTotal -2) & 0x200)   >> 4 )
+      | (((mode->VDisplay -1) & 0x200) >> 3 )
+      | ((mode->VSyncStart & 0x200) >> 2 ));
+  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x08, 0x00);
+  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x09, ((mode->VSyncStart & 0x200) >>4) | 0x40);
+  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x0A, 0x00);
+  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x0B, 0x00);
+  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x0C, 0x00);
+  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x0D, 0x00);
+  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x0E, 0x00);
+  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x0F, 0x00);
+  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x10, mode->VSyncStart & 0xFF);
+  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x11, (mode->VSyncEnd & 0x0F) | 0x20);
+  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x12, (mode->VDisplay -1) & 0xFF);
+  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x13, 0x00);  /* no interlace */
+  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x14, 0x00);
+  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x15, mode->VSyncStart & 0xFF);
+  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x16, (mode->VSyncStart +1) & 0xFF);
+
+  temp = 0xAF;
+  if(VDiv2)
+    temp |= 0x04;
+  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x17, temp);
+
+  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x18, 0xFF);
+
+  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x1A ,
+      (((mode->HTotal >> 3) & 0xC0 ) >> 2)
+      | (((mode->VTotal - 2) & 0x300 ) >> 2));
+
+  width = fb_fix.line_length >> 3;
+  if (fb_var.bits_per_pixel == 1)
+    width <<= 2;
+  if(width >= 0xFF)
+    printk("FB_CIRRUS: Warning line size over the limit ... reduce bpp or width resolution");
+  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x13,  width);
+  /* Offset extension (see CR13) */
+  temp = fb_cirrus_read_crt_reg( cirrus_board_ptr, 0x1B);
+  temp &= 0xAF;
+  temp |= (width >> (3+4)) & 0x10;
+  temp |= (width >> (3+3)) & 0x40;
+  temp |= 0x22;
+  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x1B,  temp);
+
+  /****************************************************
+   * Sequential register
+   * Enable linear mode and high-res packed pixel mode
+   */
+  temp = fb_cirrus_read_seq_reg( cirrus_board_ptr, 0x07);
+  temp &= 0xe0;
+  switch (depthcode) {
+  case 1:
+  case 4:
+    temp |= 0x10;
+    break;
+  case 8:
+    temp |= 0x11;
+    break;
+  case 64+8:
+  temp |= 0x17;
+  break;
+  case 15:
+    temp |= 0x17;
+    hdr = 0xC0; /* 5:5:5 Sierra */
+    break;
+  case 16:
+    temp |= 0x17;
+    hdr = 0xC1; /* 5:6:5 XGA mode */
+    break;
+  case 24:
+    temp |= 0x15;
+    hdr = 0xC5; /* 8:8:8 16M colors */
+    break;
+  case 32:
+    temp |= 0x19;
+    hdr = 0xC5; /* 8:8:8 16M colors */
+    break;
+  default:
+    printk("FB_CIRRUS: Cannot Initialize display to requested mode\n");
+    printk("FB_CIRRUS: returning RTEMS_UNSATISFIED on depthcode %d\n", depthcode);
+    return RTEMS_UNSATISFIED;
+  }
+  fb_cirrus_write_seq_reg( cirrus_board_ptr, 0x07, temp);
+  /* this just set  packed pixel mode with according bpp */
+
+  /****************************************************
+   * HDR Register
+   */
+  if(hdr > 0)
+    fb_cirrus_write_hdr_reg( cirrus_board_ptr, hdr);
+
+  /****************************************************
+   * Graphic Data Controller Registers
+   */
+  temp = fb_cirrus_read_gdc_reg( cirrus_board_ptr, 0x12);
+  if (HDiv2)
+    temp |= 0x20;
+  else
+    temp &= ~0x20;
+  fb_cirrus_write_gdc_reg( cirrus_board_ptr, 0x12, temp);
+
+  /* Enable high-color modes */
+  fb_cirrus_write_gdc_reg(cirrus_board_ptr, 0x05, 0x40);
+
+  /* VGA graphics mode */
+  fb_cirrus_write_gdc_reg(cirrus_board_ptr, 0x06, 0x01);
+
+  return TRUE;
+}
+
+static void
+cirrus_prepare_mode( void )
+{
+
+  active_mode = &available_modes[CIRRUS_DISPLAY_MODE];
+
+  fb_var.bits_per_pixel = CIRRUS_DEFAULT_BPP;
+
+  fb_var.xres  = active_mode->HDisplay;
+  fb_var.yres  = active_mode->VDisplay;
+
+  fb_fix.line_length = (fb_var.xres * fb_var.bits_per_pixel + 7) / 8;
+
+  fb_fix.type   = FB_TYPE_PACKED_PIXELS;
+  fb_fix.visual = FB_VISUAL_TRUECOLOR;
+
+}
+
+/*
+ * fb_cirrus device driver OPEN entry point
+ */
+rtems_device_driver
+frame_buffer_open(
+    rtems_device_major_number  major,
+    rtems_device_minor_number  minor,
+    void                      *arg
+)
+{
+  int r;
+  uint32_t smem_start, regs_start;
+
+  if (_Atomic_Flag_test_and_set(&driver_mutex, ATOMIC_ORDER_ACQUIRE) != 0 ) {
+      printk( "FB_CIRRUS could not lock driver_mutex\n" );
+
+      return RTEMS_UNSATISFIED;
+  }
+
+  r = cirrus_pci_read(&cirrus_board_info, &smem_start, &regs_start);
+  if ( r == RTEMS_UNSATISFIED )
+    return RTEMS_UNSATISFIED;
+
+  fb_fix.smem_start  = (volatile char *)smem_start;
+  fb_fix.smem_len    = 0x1000000;
+  cirrus_board_info.reg_base = (void *)regs_start;
+
+  cirrus_prepare_mode();
+
+  cirrus_set_mode( active_mode );
+
+  cirrus_adjust_frame( &cirrus_board_info, 0, 0);
+
+  if (1) {
+      uint32_t pixmask;
+      int x, y;
+
+      if(fb_var.bits_per_pixel == 32)
+        pixmask = 0xffffff;
+      else
+        pixmask = (1 << fb_var.bits_per_pixel) - 1;
+
+      printk("FB_CIRRUS: mode set, test patter output\n");
+
+      for(y = 0; y < fb_var.yres; y++) {
+          for(x = 0; x < fb_var.xres; x++) {
+              uint32_t color;
+              char *addr = (char *)fb_fix.smem_start;
+              addr += y * fb_fix.line_length;
+              addr += x * fb_var.bits_per_pixel / 8;
+              color = x & 1 ? 0 : y & 1 ? pixmask & 0x000ff00f : pixmask;
+              if(y == fb_var.yres - 1) {
+                  if((x > 0) && (x < fb_var.xres-1))
+                    color = pixmask & 0x00555555;
+              }
+              switch (fb_var.bits_per_pixel) {
+              case 8:  *(volatile uint8_t*) addr = color;
+              break;
+              case 16: *(volatile uint16_t*) addr = color;
+              break;
+              case 24: *(volatile uint32_t*) addr =
+                  (*(volatile uint32_t*) addr & 0xff000000) | color;
+              break;
+              case 32: *(volatile uint32_t*) addr = color;
+              break;
+              }
+          }
+      }
+  }
+
+  return RTEMS_SUCCESSFUL;
+
+}
+
+/*
+ * fb_cirrus device driver CLOSE entry point
+ */
+rtems_device_driver
+frame_buffer_close(
+    rtems_device_major_number  major,
+    rtems_device_minor_number  minor,
+    void                      *arg
+)
+{
+  _Atomic_Flag_clear(&driver_mutex, ATOMIC_ORDER_RELEASE);
+
+  /* restore previous state.  for VGA this means return to text mode.
+   * leave out if graphics hardware has been initialized in
+   * frame_buffer_initialize() */
+
+  /* VGA text mode */
+  fb_cirrus_write_gdc_reg(&cirrus_board_info, 0x06, 0x00);
+
+  printk( "FB_CIRRUS: close called.\n" );
+  return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * fb_cirrus device driver READ entry point.
+ */
+rtems_device_driver
+frame_buffer_read(
+    rtems_device_major_number  major,
+    rtems_device_minor_number  minor,
+    void                      *arg
+)
+{
+  rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
+  rw_args->bytes_moved = ((rw_args->offset + rw_args->count) > fb_fix.smem_len ) ? (fb_fix.smem_len - rw_args->offset) : rw_args->count;
+  memcpy(rw_args->buffer, (const void *) (fb_fix.smem_start + rw_args->offset), rw_args->bytes_moved);
+  return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * frame_buffer device driver WRITE entry point.
+ */
+rtems_device_driver
+frame_buffer_write(
+    rtems_device_major_number  major,
+    rtems_device_minor_number  minor,
+    void                      *arg
+)
+{
+  rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
+  rw_args->bytes_moved = ((rw_args->offset + rw_args->count) > fb_fix.smem_len ) ? (fb_fix.smem_len - rw_args->offset) : rw_args->count;
+  memcpy( (void *) (fb_fix.smem_start + rw_args->offset), rw_args->buffer, rw_args->bytes_moved);
+  return RTEMS_SUCCESSFUL;
+}
+
+static int
+get_fix_screen_info( struct fb_fix_screeninfo *info )
+{
+  *info = fb_fix;
+  return 0;
+}
+
+static int
+get_var_screen_info( struct fb_var_screeninfo *info )
+{
+  *info =  fb_var;
+  return 0;
+}
+
+/*
+ * IOCTL entry point -- This method is called to carry
+ * all services of this interface.
+ */
+rtems_device_driver
+frame_buffer_control(
+    rtems_device_major_number  major,
+    rtems_device_minor_number  minor,
+    void                      *arg
+)
+{
+  rtems_libio_ioctl_args_t *args = arg;
+
+  printk( "FB_CIRRUS ioctl called, cmd=%x\n", args->command  );
+
+  switch( args->command ) {
+  case FBIOGET_FSCREENINFO:
+    args->ioctl_return =  get_fix_screen_info( ( struct fb_fix_screeninfo * ) args->buffer );
+    break;
+  case FBIOGET_VSCREENINFO:
+    args->ioctl_return =  get_var_screen_info( ( struct fb_var_screeninfo * ) args->buffer );
+    break;
+  case FBIOPUT_VSCREENINFO:
+    /* not implemented yet */
+    args->ioctl_return = -1;
+    return RTEMS_UNSATISFIED;
+  case FBIOGETCMAP:
+    /* no palette - truecolor mode */
+    args->ioctl_return = -1;
+    return RTEMS_UNSATISFIED;
+  case FBIOPUTCMAP:
+    /* no palette - truecolor mode */
+    args->ioctl_return = -1;
+    return RTEMS_UNSATISFIED;
+  default:
+    args->ioctl_return = 0;
+    break;
+  }
+  return RTEMS_SUCCESSFUL;
+}
Index: bsps/i386/pc386/console/fb_vesa_rm.c
===================================================================
--- bsps/i386/pc386/console/fb_vesa_rm.c	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
+++ bsps/i386/pc386/console/fb_vesa_rm.c	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
@@ -0,0 +1,1004 @@
+/**
+ * @file fb_vesa_rm.c
+ *
+ * @ingroup i386_pc386
+ *
+ * @brief FB driver for graphic hardware compatible with VESA Bios Extension
+ *     Real mode interface utilized
+ *     Tested on real HW.
+ *
+ * Public sources related:
+ *   - VESA BIOS EXTENSION (VBE) Core Function Standard, Ver: 3.0, Sep 16, 1998
+ *   - VESA Enhanced Extended Display Identification Data (E-EDID) Standard
+ *     Release A, Revision 2, September 25, 2006
+ *
+ * Hardware is completely initialized upon boot of the system.
+ * Therefore there is no way to change graphics mode later.
+ *
+ * Interrupt 0x10 is used for entering graphics BIOS.
+ *
+ * Driver reads parameter from multiboot command line to setup video:
+ * "--video=<resX>x<resY>[-<bpp>]"
+ * "--video=auto" - try EDID to find mode that fits the display attached best
+ * "--video=none" / "--video=off" - do not initialize the driver
+ * If cmdline parameter is not specified the rtems_fb_default_mode
+ * variable content is tested (see doc below).
+ * Command line option has higher priority. rtems_fb_default_mode is probed
+ * only if cmdline "--video=" is not specified at all.
+ *
+ * If neither of the above options is specified the driver is not initialized.
+ */
+
+/*
+ * Copyright (c) 2014 - CTU in Prague
+ *                      Jan DoleÅŸal ( dolezj21@fel.cvut.cz )
+ *
+ * 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.
+ *
+ * The code for rtems_buffer_* functions was greatly
+ * inspired or coppied from:
+ *   - RTEMS fb_cirrus.c - Alexandru-Sever Horin (alex.sever.h@gmail.com)
+ */
+
+#include <inttypes.h>
+
+#include <bsp.h>
+
+#include <bsp/fb_default_mode.h>
+#include <bsp/fb_vesa.h>
+#include <bsp/realmode_int.h>
+
+#include <pthread.h>
+
+#include <rtems/libio.h>
+
+#include <rtems/fb.h>
+#include <rtems/framebuffer.h>
+
+#include <rtems/score/atomic.h>
+
+#include <stdlib.h>
+
+#define FB_VESA_NAME    "FB_VESA_RM"
+
+/**
+ * @brief Allows to enable initialization of VESA real mode driver from
+ * an application by setting the value of this variable to non null value in
+ * user's module. The value of this variable will be then updated
+ * when linked with application's object.
+ *
+ * Further the value should point to string in the following format:
+ * "<resX>x<resY>[-<bpp>]" - e.g. "1024x768-32"
+ * "auto" - try EDID to find mode that fits the display attached best
+ * "none" / "off" - do not initialize the driver
+ * the given parameters are used if applicable.
+ *
+ * Command line argument "--video=" has priority over this string.
+ */
+const char * const rtems_fb_default_mode;
+
+/**
+ * @brief Initializes VBE framebuffer during bootup.
+ *
+ * utilizes switches to real mode interrupts and therefore must be
+ * called during bootup before tick is set up and real-time
+ * interrupt vectors utilized
+ */
+void vesa_realmode_bootup_init(void);
+
+/* flag to limit driver to protect against multiple opens */
+static Atomic_Flag driver_mutex;
+
+/* screen information for the VGA driver
+ * standard structures - from RTEMS fb interface
+ */
+static struct fb_var_screeninfo fb_var;
+static struct fb_fix_screeninfo fb_fix;
+
+static int32_t vbe_used_mode;
+
+uint32_t VBE_controller_information( VBE_vbe_info_block *info_block,
+                                            uint16_t queried_VBE_Version)
+{
+    uint16_t size;
+    VBE_vbe_info_block *VBE_buffer =
+        (VBE_vbe_info_block *)i386_get_default_rm_buffer(&size);
+    i386_realmode_interrupt_registers parret;
+    parret.reg_eax = VBE_RetVBEConInf;
+    uint16_t seg, off;
+    i386_Physical_to_real(VBE_buffer, &seg, &off);
+    parret.reg_edi = (uint32_t)off;
+    parret.reg_es = seg;
+    /* indicate to graphic's bios that VBE2.0 extended information is desired */
+    if (queried_VBE_Version >= 0x200)
+    {
+        memcpy(
+            &VBE_buffer->VbeSignature,
+            VBE20plus_SIGNATURE,
+            sizeof(VBE_buffer->VbeSignature)
+        );
+    }
+    if (i386_real_interrupt_call(INTERRUPT_NO_VIDEO_SERVICES, &parret) == 0)
+        return -1;
+    if ((parret.reg_eax & 0xFFFF) ==
+        (VBE_callSuccessful<<8 | VBE_functionSupported))
+    {
+        *info_block = *VBE_buffer;
+    }
+    return (parret.reg_eax & 0xFFFF);
+}
+
+uint32_t VBE_mode_information( VBE_mode_info_block *info_block,
+                                    uint16_t mode_number)
+{
+    uint16_t size;
+    VBE_mode_info_block *VBE_buffer =
+        (VBE_mode_info_block *)i386_get_default_rm_buffer(&size);
+    i386_realmode_interrupt_registers parret;
+    parret.reg_eax = VBE_RetVBEModInf;
+    parret.reg_ecx = mode_number;
+    uint16_t seg, off;
+    i386_Physical_to_real(VBE_buffer, &seg, &off);
+    parret.reg_edi = (uint32_t)off;
+    parret.reg_es = seg;
+    if (i386_real_interrupt_call(INTERRUPT_NO_VIDEO_SERVICES, &parret) == 0)
+        return -1;
+    if ((parret.reg_eax & 0xFFFF) ==
+        (VBE_callSuccessful<<8 | VBE_functionSupported))
+    {
+        *info_block = *VBE_buffer;
+    }
+    return (parret.reg_eax & 0xFFFF);
+}
+
+uint32_t VBE_set_mode( uint16_t mode_number,
+                            VBE_CRTC_info_block *info_block)
+{
+    uint16_t size;
+    VBE_CRTC_info_block *VBE_buffer =
+        (VBE_CRTC_info_block *)i386_get_default_rm_buffer(&size);
+    i386_realmode_interrupt_registers parret;
+    /* copy CRTC */
+    *VBE_buffer = *info_block;
+    parret.reg_eax = VBE_SetVBEMod;
+    parret.reg_ebx = mode_number;
+    uint16_t seg, off;
+    i386_Physical_to_real(VBE_buffer, &seg, &off);
+    parret.reg_edi = (uint32_t)off;
+    parret.reg_es = seg;
+    if (i386_real_interrupt_call(INTERRUPT_NO_VIDEO_SERVICES, &parret) == 0)
+        return -1;
+    return (parret.reg_eax & 0xFFFF);
+}
+
+uint32_t VBE_current_mode(uint16_t *mode_number)
+{
+    i386_realmode_interrupt_registers parret;
+    parret.reg_eax = VBE_RetCurVBEMod;
+    if (i386_real_interrupt_call(INTERRUPT_NO_VIDEO_SERVICES, &parret) == 0)
+        return -1;
+    *mode_number = (uint16_t)parret.reg_ebx;
+    return (parret.reg_eax & 0xFFFF);
+}
+
+uint32_t VBE_report_DDC_capabilities(uint16_t controller_unit_number,
+                                        uint8_t *seconds_to_transfer_EDID_block,
+                                        uint8_t *DDC_level_supported)
+{
+    i386_realmode_interrupt_registers parret;
+    parret.reg_eax = VBE_DisDatCha;
+    parret.reg_ebx = VBEDDC_Capabilities;
+    parret.reg_ecx = controller_unit_number;
+    parret.reg_edi = 0;
+    parret.reg_es = 0;
+    if (i386_real_interrupt_call(INTERRUPT_NO_VIDEO_SERVICES, &parret) == 0)
+        return -1;
+    *seconds_to_transfer_EDID_block = (uint8_t)parret.reg_ebx >> 8;
+    *DDC_level_supported = (uint8_t)parret.reg_ebx;
+    return (parret.reg_eax & 0xFFFF);
+}
+
+uint32_t VBE_read_EDID(uint16_t controller_unit_number,
+                            uint16_t EDID_block_number,
+                            EDID_edid1 *buffer)
+{
+    uint16_t size;
+    EDID_edid1 *VBE_buffer = (EDID_edid1*)i386_get_default_rm_buffer(&size);
+    i386_realmode_interrupt_registers parret;
+    parret.reg_eax = VBE_DisDatCha;
+    parret.reg_ebx = VBEDDC_ReadEDID;
+    parret.reg_ecx = controller_unit_number;
+    parret.reg_edx = EDID_block_number;
+    uint16_t seg, off;
+    i386_Physical_to_real(VBE_buffer, &seg, &off);
+    parret.reg_edi = (uint32_t)off;
+    parret.reg_es = seg;
+    if (i386_real_interrupt_call(INTERRUPT_NO_VIDEO_SERVICES, &parret) == 0)
+        return -1;
+    if ((parret.reg_eax & 0xFFFF) ==
+        (VBE_callSuccessful<<8 | VBE_functionSupported))
+    {
+        *buffer = *VBE_buffer;
+    }
+    return (parret.reg_eax & 0xFFFF);
+}
+
+/**
+ * @brief Basic graphic's mode parameters
+ */
+typedef struct {
+    /** number of the graphic's mode */
+    uint16_t mode_number;
+    /** number of pixels in one line */
+    uint16_t resX;
+    /** number of lines */
+    uint16_t resY;
+    /** bits per pixel */
+    uint8_t bpp;
+} Mode_params;
+
+typedef enum {
+    NO_SUITABLE_MODE    = -1,
+    BAD_FORMAT          = -2,
+    AUTO_SELECT         = -3,
+    DONT_INIT           = -4,
+    NO_MODE_REQ         = -5,
+} mode_err_ret_val;
+
+/**
+ * @brief Find mode by resolution in the given list of modes
+ *
+ * finds mode in \p mode_list of \p list_length length according to resolution
+ * given in \p searched_resolution . If bpp is given in that struct as well
+ * mode with such color depth and resolution is searched for. Otherwise bpp
+ * has to be zero. Mode number found is returned and also filled into
+ * \p searched_resolution . bpp is also filled into \p searchedResolution if it
+ * was 0 before call.
+ *
+ * @param[in] mode_list list of modes to be searched
+ * @param[in] list_length number of modes in the list
+ * @param[in,out] searched_resolution element filled with searched resolution
+ *                or/and bpp; mode_number is filled in if appropriate mode found
+ * @retval mode number satisfying given parameters
+ * @retval -1 no suitable mode found
+ */
+static int32_t find_mode_by_resolution(Mode_params *mode_list,
+                                        uint8_t list_length,
+                                        Mode_params *searched_resolution)
+{
+    uint8_t i = 0;
+    while (i < list_length)
+    {
+        if (searched_resolution->resX == mode_list[i].resX &&
+            searched_resolution->resY == mode_list[i].resY)
+        {
+            if (searched_resolution->bpp==0 ||
+                searched_resolution->bpp==mode_list[i].bpp)
+            {
+                searched_resolution->bpp = mode_list[i].bpp;
+                searched_resolution->mode_number = mode_list[i].mode_number;
+                return mode_list[i].mode_number;
+            }
+        }
+        i++;
+    }
+    return NO_SUITABLE_MODE;
+}
+
+/**
+ * @brief Find mode given in string format.
+ *
+ *  expected format
+ *  <resX>x<resY>[-<bpp>]
+ *  numbers <resX>, <resY> and <bpp> are decadic
+ *
+ * @param[in] mode_list list of modes to be searched
+ * @param[in] list_length number of modes in the list
+ * @param[in] video_string string to be parsed
+ * @retval video mode number to be set
+ * @retval -1 no suitable mode found
+ * @retval -2 bad format of the video_string
+ * @retval -3 automatic mode selection requested
+ * @retval -4 request to not initialize graphics
+ * @retval -5 no mode requested/empty video string
+ */
+static int32_t find_mode_from_string(Mode_params *mode_list,
+                                      uint8_t list_length,
+                                      const char *video_string)
+{
+    const char* opt;
+    Mode_params cmdline_mode;
+    char* endptr;
+    cmdline_mode.bpp = 16; /* default bpp */
+    opt = video_string;
+    if (opt)
+    {
+        if (strncmp(opt, "auto", 4) == 0)
+            return AUTO_SELECT;
+        if (strncmp(opt, "none", 4) == 0 ||
+            strncmp(opt, "off", 3) == 0)
+        {
+            return DONT_INIT;
+        }
+        cmdline_mode.resX = strtol(opt, &endptr, 10);
+        if (*endptr != 'x')
+        {
+            return BAD_FORMAT;
+        }
+        opt = endptr+1;
+        cmdline_mode.resY = strtol(opt, &endptr, 10);
+        switch (*endptr)
+        {
+            case '-':
+                opt = endptr+1;
+                if (strlen(opt) <= 2)
+                    cmdline_mode.bpp = strtol(opt, &endptr, 10);
+                else
+                {
+                    cmdline_mode.bpp = strtol(opt, &endptr, 10);
+                    if (*endptr != ' ')
+                    {
+                        return BAD_FORMAT;
+                    }
+                }
+            case ' ':
+            case 0:
+                break;
+            default:
+                return BAD_FORMAT;
+        }
+
+        return find_mode_by_resolution(mode_list, list_length, &cmdline_mode);
+    }
+    return NO_MODE_REQ;
+}
+
+/**
+ * @brief Find mode given within command line.
+ *
+ * Parse command line option "--video=" if available.
+ *  expected format
+ *  --video=<resX>x<resY>[-<bpp>]
+ *  numbers <resX>, <resY> and <bpp> are decadic
+ *
+ * @param[in] mode_list list of modes to be searched
+ * @param[in] list_length number of modes in the list
+ * @retval video mode number to be set
+ * @retval -1 no suitable mode found
+ * @retval -2 bad format of the video_string
+ * @retval -3 automatic mode selection requested
+ * @retval -4 request to not initialize graphics
+ * @retval -5 no mode requested/empty video string
+ */
+static int32_t find_mode_using_cmdline(Mode_params *mode_list,
+                                        uint8_t list_length)
+{
+    const char* opt;
+    opt = bsp_cmdline_arg("--video=");
+    if (opt)
+    {
+        opt += sizeof("--video=")-1;
+        return find_mode_from_string(mode_list, list_length, opt);
+    }
+    return NO_MODE_REQ;
+}
+
+/**
+ * @brief Find mode number best fitting to monitor attached
+ *
+ * @param[in] mode_list list of modes to be searched
+ * @param[in] list_length number of modes in the list
+ * @retval video mode number to be set
+ * @retval -1 on parsing error or when no suitable mode found
+ */
+static int32_t find_mode_using_EDID( Mode_params *mode_list,
+                                      uint8_t list_length)
+{
+    EDID_edid1 edid;
+    uint8_t checksum, iterator;
+    uint8_t index, j;
+    Mode_params EDIDmode;
+    checksum = 0;
+    iterator = 0;
+    EDIDmode.bpp = 0;
+    if (VBE_read_EDID(0, 0, &edid) !=
+        (VBE_callSuccessful<<8 | VBE_functionSupported))
+    {
+        printk(FB_VESA_NAME " Function 15h (read EDID) not supported.\n");
+        return -1;
+    }
+/* version of EDID structure */
+    if (edid.Version == 1)
+    { /* EDID version 1 */
+        while (iterator < sizeof(EDID_edid1))
+        {
+            checksum += *((uint8_t *)&edid+iterator);
+            iterator++;
+        }
+        if (checksum)
+            /* not implemented: try to read EDID again */
+            printk(FB_VESA_NAME " EDID v1 checksum failed\n");
+
+        /* try to find Detailed Timing Descriptor (defined in BASE EDID)
+           in controller mode list; first should be preffered mode */
+        index = 0;
+        while (index < 4)
+        {
+            /* skip if it is monitor descriptor */
+            if (edid.dtd_md[index].md.Flag0[0] == 0 &&
+                edid.dtd_md[index].md.Flag0[1] == 0 &&
+                edid.dtd_md[index].md.Flag1 == 0)
+            {
+                index++;
+                continue;
+            }
+            EDIDmode.resX = DTD_horizontal_active(&edid.dtd_md[0].dtd);
+            EDIDmode.resY = DTD_vertical_active(&edid.dtd_md[0].dtd);
+            if (find_mode_by_resolution(mode_list, list_length, &EDIDmode) !=
+                -1)
+                return EDIDmode.mode_number;
+
+            index++;
+        }
+        /* try to find Detailed Timing Descriptor (defined in optional EXTENSION
+        Blocks) in controller mode list */
+        if (edid.ExtensionFlag > 0)
+        {
+            /* not implemented */
+        }
+        /* try to find CVT (defined in BASE EDID) in controller mode list */
+        index = 1;
+        while (index < 4)
+        {
+            if (edid.dtd_md[index].md.DataTypeTag ==
+                    EDID_DTT_CVT3ByteTimingCodes     &&
+                edid.dtd_md[index].md.Flag0[0] == 0  &&
+                edid.dtd_md[index].md.Flag0[1] == 0  &&
+                edid.dtd_md[index].md.Flag1 == 0     &&
+                edid.dtd_md[index].md.Flag2 == 0)
+            {
+                EDID_CVT_timing_codes_3B *cvt = (EDID_CVT_timing_codes_3B *)
+                    &edid.dtd_md[index].md.DescriptorData[0];
+                j = 0;
+                while (j < 4)
+                {
+                    EDIDmode.resY = edid1_CVT_addressable_lines_high(
+                        &cvt->cvt[j]
+                    );
+                    switch (edid1_CVT_aspect_ratio(&cvt->cvt[j]))
+                    {
+                        case EDID_CVT_AspectRatio_4_3:
+                            EDIDmode.resX = (EDIDmode.resY*4)/3;
+                            break;
+                        case EDID_CVT_AspectRatio_16_9:
+                            EDIDmode.resX = (EDIDmode.resY*16)/9;
+                            break;
+                        case EDID_CVT_AspectRatio_16_10:
+                            EDIDmode.resX = (EDIDmode.resY*16)/10;
+                            break;
+                        case EDID_CVT_AspectRatio_15_9:
+                            EDIDmode.resX = (EDIDmode.resY*15)/9;
+                            break;
+                    }
+                    EDIDmode.resX = (EDIDmode.resX/8)*8;
+                    if (find_mode_by_resolution(
+                            mode_list, list_length, &EDIDmode) != -1)
+                        return EDIDmode.mode_number;
+
+                    j++;
+                }
+            }
+            index++;
+        }
+        /* try to find CVT (defined in optional EXTENSION Blocks)
+        in controller mode list */
+        /* not implemented */
+        /* try to find Standard Timings (listed in BASE EDID)
+        in controller mode list */
+        index = 0;
+        while (index < 8)
+        {
+            /* check if descriptor is unused */
+            if (edid1_STI_is_unused(&edid.STI[index]))
+            {
+                index++;
+                continue;
+            }
+            EDIDmode.resX = (edid.STI[index].HorizontalActivePixels+31)*8;
+            switch (edid.STI[index].ImageAspectRatio_RefreshRate &
+                    EDID1_STI_ImageAspectRatioMask)
+            {
+                case EDID_STI_AspectRatio_16_10:
+                    EDIDmode.resY = (EDIDmode.resX*10)/16;
+                    break;
+                case EDID_STI_AspectRatio_4_3:
+                    EDIDmode.resY = (EDIDmode.resX*3)/4;
+                    break;
+                case EDID_STI_AspectRatio_5_4:
+                    EDIDmode.resY = (EDIDmode.resX*4)/5;
+                    break;
+                case EDID_STI_AspectRatio_16_9:
+                    EDIDmode.resY = (EDIDmode.resX*9)/16;
+                    break;
+            }
+            if (find_mode_by_resolution(mode_list, list_length, &EDIDmode) !=
+                -1)
+                return EDIDmode.mode_number;
+
+            index++;
+        }
+        /* try to find Standard Timings (listed in optional EXTENSION Blocks)
+        in controller mode list */
+        /* not implemented */
+        /* use Established Timings */
+        if (edid1_established_tim(&edid, EST_1280x1024_75Hz))
+        {
+            EDIDmode.resX = 1280;
+            EDIDmode.resY = 1024;
+            EDIDmode.bpp = 0;
+            if (find_mode_by_resolution(mode_list, list_length, &EDIDmode) !=
+                -1)
+                return EDIDmode.mode_number;
+        }
+        if (edid1_established_tim(&edid, EST_1152x870_75Hz))
+        {
+            EDIDmode.resX = 1152;
+            EDIDmode.resY = 870;
+            EDIDmode.bpp = 0;
+            if (find_mode_by_resolution(mode_list, list_length, &EDIDmode) !=
+                -1)
+                return EDIDmode.mode_number;
+        }
+        if (edid1_established_tim(&edid, EST_1024x768_75Hz) ||
+            edid1_established_tim(&edid, EST_1024x768_70Hz) ||
+            edid1_established_tim(&edid, EST_1024x768_60Hz) ||
+            edid1_established_tim(&edid, EST_1024x768_87Hz))
+        {
+            EDIDmode.resX = 1024;
+            EDIDmode.resY = 768;
+            EDIDmode.bpp = 0;
+            if (find_mode_by_resolution(mode_list, list_length, &EDIDmode) !=
+                -1)
+                return EDIDmode.mode_number;
+        }
+        if (edid1_established_tim(&edid, EST_832x624_75Hz))
+        {
+            EDIDmode.resX = 832;
+            EDIDmode.resY = 624;
+            EDIDmode.bpp = 0;
+            if (find_mode_by_resolution(mode_list, list_length, &EDIDmode) !=
+                -1)
+                return EDIDmode.mode_number;
+        }
+        if (edid1_established_tim(&edid, EST_800x600_60Hz) ||
+            edid1_established_tim(&edid, EST_800x600_56Hz) ||
+            edid1_established_tim(&edid, EST_800x600_75Hz) ||
+            edid1_established_tim(&edid, EST_800x600_72Hz))
+        {
+            EDIDmode.resX = 800;
+            EDIDmode.resY = 600;
+            EDIDmode.bpp = 0;
+            if (find_mode_by_resolution(mode_list, list_length, &EDIDmode) !=
+                -1)
+                return EDIDmode.mode_number;
+        }
+        if (edid1_established_tim(&edid, EST_720x400_88Hz) ||
+            edid1_established_tim(&edid, EST_720x400_70Hz))
+        {
+            EDIDmode.resX = 720;
+            EDIDmode.resY = 400;
+            EDIDmode.bpp = 0;
+            if (find_mode_by_resolution(mode_list, list_length, &EDIDmode) !=
+                -1)
+                return EDIDmode.mode_number;
+        }
+        if (edid1_established_tim(&edid, EST_640x480_75Hz) ||
+            edid1_established_tim(&edid, EST_640x480_72Hz) ||
+            edid1_established_tim(&edid, EST_640x480_67Hz) ||
+            edid1_established_tim(&edid, EST_640x480_60Hz))
+        {
+            EDIDmode.resX = 640;
+            EDIDmode.resY = 480;
+            EDIDmode.bpp = 0;
+            if (find_mode_by_resolution(mode_list, list_length, &EDIDmode) !=
+                -1)
+                return EDIDmode.mode_number;
+        }
+    }
+    else
+        printk(FB_VESA_NAME " error reading EDID: unsupported version\n");
+    return -1;
+}
+
+void vesa_realmode_bootup_init(void)
+{
+    uint32_t vbe_ret_val;
+    uint16_t size;
+    VBE_vbe_info_block *vib = (VBE_vbe_info_block *)
+        i386_get_default_rm_buffer(&size);
+    vbe_ret_val = VBE_controller_information(vib, 0x300);
+    if (vbe_ret_val == -1)
+    {
+        printk(FB_VESA_NAME " error calling real mode interrupt.\n");
+        return;
+    }
+    if (vbe_ret_val != (VBE_callSuccessful<<8 | VBE_functionSupported))
+    {
+        printk(FB_VESA_NAME " Function 00h (read VBE info block)"
+            "not supported.\n");
+    }
+/*  Helper array is later filled with mode numbers and their parameters
+    sorted from the biggest values to the smalest where priorities of
+    parameters are from the highest to the lowest: resolution X,
+    resolution Y, bits per pixel.
+    The array is used for search the monitor provided parameters in EDID
+    structure and if found we set such mode using corresponding
+    VESA function. */
+#define MAX_NO_OF_SORTED_MODES 100
+    Mode_params sorted_mode_params[MAX_NO_OF_SORTED_MODES];
+
+    uint16_t *vmpSegOff = (uint16_t *)&vib->VideoModePtr;
+    uint16_t *modeNOPtr = (uint16_t*)
+        i386_Real_to_physical(*(vmpSegOff+1), *vmpSegOff);
+    uint16_t iterator = 0;
+
+    if (*(uint16_t*)vib->VideoModePtr == VBE_STUB_VideoModeList)
+    {
+        printk(FB_VESA_NAME " VBE Core not implemented!\n");
+    }
+    else
+    {
+        /* prepare list of modes */
+        while (*(modeNOPtr+iterator) != VBE_END_OF_VideoModeList &&
+            *(modeNOPtr+iterator) != 0)
+        { /* some bios implementations ends the list incorrectly with 0 */
+            if (iterator < MAX_NO_OF_SORTED_MODES)
+            {
+                sorted_mode_params[iterator].mode_number =*(modeNOPtr+iterator);
+                iterator ++;
+            }
+            else
+                break;
+        }
+        if (iterator < MAX_NO_OF_SORTED_MODES)
+            sorted_mode_params[iterator].mode_number = 0;
+    }
+
+    VBE_mode_info_block *mib = (VBE_mode_info_block *)
+        i386_get_default_rm_buffer(&size);
+    iterator = 0;
+    uint8_t nextFilteredMode = 0;
+    uint16_t required_mode_attributes = VBE_modSupInHWMask |
+        VBE_ColorModeMask | VBE_GraphicsModeMask | VBE_LinFraBufModeAvaiMask;
+    /* get parameters of modes and filter modes according to set
+        required parameters */
+    while (iterator < MAX_NO_OF_SORTED_MODES &&
+        sorted_mode_params[iterator].mode_number!=0)
+    {
+        VBE_mode_information(mib, sorted_mode_params[iterator].mode_number);
+        if ((mib->ModeAttributes&required_mode_attributes) ==
+            required_mode_attributes)
+        {
+            sorted_mode_params[nextFilteredMode].mode_number =
+                sorted_mode_params[iterator].mode_number;
+            sorted_mode_params[nextFilteredMode].resX = mib->XResolution;
+            sorted_mode_params[nextFilteredMode].resY = mib->YResolution;
+            sorted_mode_params[nextFilteredMode].bpp  = mib->BitsPerPixel;
+            nextFilteredMode ++;
+        }
+        iterator ++;
+    }
+    sorted_mode_params[nextFilteredMode].mode_number = 0;
+
+    uint8_t number_of_modes = nextFilteredMode;
+
+    /* first search for video argument in multiboot options */
+    vbe_used_mode = find_mode_using_cmdline(sorted_mode_params,
+                                            number_of_modes);
+
+    if (vbe_used_mode == NO_MODE_REQ) {
+        vbe_used_mode = find_mode_from_string(sorted_mode_params,
+                            number_of_modes, rtems_fb_default_mode);
+        if (vbe_used_mode != NO_MODE_REQ) {
+            printk(FB_VESA_NAME " using application option to select"
+                " video mode\n");
+        }
+    }
+    else
+    {
+        printk(FB_VESA_NAME " using command line option '--video='"
+            "to select video mode\n");
+    }
+
+    switch (vbe_used_mode) {
+        case NO_SUITABLE_MODE:
+            printk(FB_VESA_NAME " requested mode not found\n");
+            return;
+        case BAD_FORMAT:
+            printk(FB_VESA_NAME " bad format of video requested\n");
+            return;
+        case DONT_INIT:
+            printk(FB_VESA_NAME " selected not to initialize graphics\n");
+            return;
+        case NO_MODE_REQ:
+            printk(FB_VESA_NAME " not initialized, no video selected\n");
+            return;
+    }
+
+    /* sort filtered modes */
+    Mode_params modeXchgPlace;
+    iterator = 0;
+    uint8_t j;
+    uint8_t idxBestMode;
+    while (iterator < number_of_modes)
+    {
+        idxBestMode = iterator;
+        j = iterator+1;
+        while (j < number_of_modes)
+        {
+            if (sorted_mode_params[j].resX >
+                    sorted_mode_params[idxBestMode].resX)
+                idxBestMode = j;
+            else if (sorted_mode_params[j].resX ==
+                     sorted_mode_params[idxBestMode].resX)
+            {
+                if (sorted_mode_params[j].resY >
+                        sorted_mode_params[idxBestMode].resY)
+                    idxBestMode = j;
+                else if (sorted_mode_params[j].resY ==
+                    sorted_mode_params[idxBestMode].resY)
+                {
+                    if (sorted_mode_params[j].bpp >
+                            sorted_mode_params[idxBestMode].bpp)
+                        idxBestMode = j;
+                }
+            }
+            j++;
+        }
+        if (idxBestMode != iterator)
+        {
+            modeXchgPlace = sorted_mode_params[iterator];
+            sorted_mode_params[iterator] = sorted_mode_params[idxBestMode];
+            sorted_mode_params[idxBestMode] = modeXchgPlace;
+        }
+        iterator++;
+    }
+
+    if (vbe_used_mode == AUTO_SELECT)
+    {
+        printk(FB_VESA_NAME " auto video mode selected"
+            "\n\ttrying EDID ...\n");
+        /* second search monitor for good resolution */
+        vbe_used_mode = find_mode_using_EDID(sorted_mode_params,
+                                             number_of_modes);
+        if (vbe_used_mode == -1)
+        {
+            printk(FB_VESA_NAME" monitor's EDID video parameters not supported"
+                               "\n\tusing mode with highest resolution, bpp\n");
+            /* third set highest values */
+            vbe_used_mode = sorted_mode_params[0].mode_number;
+        }
+    }
+
+    /* fill framebuffer structs with info about selected mode */
+    vbe_ret_val = VBE_mode_information(mib, vbe_used_mode);
+    if ((vbe_ret_val&0xff)!=VBE_functionSupported ||
+        (vbe_ret_val>>8)!=VBE_callSuccessful)
+    {
+        printk(FB_VESA_NAME " Cannot get mode info anymore. ax=0x%lx\n",
+            vbe_ret_val);
+    }
+
+    fb_var.xres = mib->XResolution;
+    fb_var.yres = mib->YResolution;
+    fb_var.bits_per_pixel = mib->BitsPerPixel;
+    fb_var.red.offset =      mib->LinRedFieldPosition;
+    fb_var.red.length =      mib->LinRedMaskSize;
+    fb_var.red.msb_right =   0;
+    fb_var.green.offset =    mib->LinGreenFieldPosition;
+    fb_var.green.length =    mib->LinGreenMaskSize;
+    fb_var.green.msb_right = 0;
+    fb_var.blue.offset =     mib->LinBlueFieldPosition;
+    fb_var.blue.length =     mib->LinBlueMaskSize;
+    fb_var.blue.msb_right =  0;
+    fb_var.transp.offset =   mib->LinRsvdFieldPosition;
+    fb_var.transp.length =   mib->LinRsvdMaskSize;
+    fb_var.transp.msb_right =0;
+
+    fb_fix.smem_start  = (char *)mib->PhysBasePtr;
+    fb_fix.line_length = mib->LinBytesPerScanLine;
+    fb_fix.smem_len    = fb_fix.line_length*fb_var.yres;
+    fb_fix.type        = FB_TYPE_PACKED_PIXELS;
+    if (fb_var.bits_per_pixel < 24)
+        fb_fix.visual  = FB_VISUAL_DIRECTCOLOR;
+    else
+        fb_fix.visual  = FB_VISUAL_TRUECOLOR;
+
+    /* set selected mode */
+    vbe_ret_val = VBE_set_mode(vbe_used_mode | VBE_linearFlatFrameBufMask,
+        (VBE_CRTC_info_block *)(i386_get_default_rm_buffer(&size)));
+    if (vbe_ret_val>>8 == VBE_callFailed)
+        printk(FB_VESA_NAME " VBE: Requested mode is not available.");
+
+    if ((vbe_ret_val&0xff)!= (VBE_functionSupported | VBE_callSuccessful<<8))
+        printk(FB_VESA_NAME " Call to function 2h (set VBE mode) failed. "
+            "ax=0x%" PRIx32 "\n", vbe_ret_val);
+
+    vib = (void *) 0;
+    mib = (void *) 0;
+}
+
+/*
+ * fb_vesa device driver INITIALIZE entry point.
+ */
+rtems_device_driver
+frame_buffer_initialize(
+    rtems_device_major_number  major,
+    rtems_device_minor_number  minor,
+    void                      *arg
+)
+{
+    rtems_status_code status;
+
+    printk(FB_VESA_NAME " frame buffer -- driver initializing..\n" );
+
+   /*
+    * Register the device.
+    */
+    status = rtems_io_register_name(FRAMEBUFFER_DEVICE_0_NAME, major, 0);
+    if (status != RTEMS_SUCCESSFUL)
+    {
+        printk("Error registering " FRAMEBUFFER_DEVICE_0_NAME
+        " - " FB_VESA_NAME " frame buffer device!\n");
+        rtems_fatal_error_occurred( status );
+    }
+
+    _Atomic_Flag_clear(&driver_mutex, ATOMIC_ORDER_RELEASE);
+
+    return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * fb_vesa device driver OPEN entry point
+ */
+rtems_device_driver
+frame_buffer_open(
+    rtems_device_major_number  major,
+    rtems_device_minor_number  minor,
+    void                      *arg
+)
+{
+    printk( FB_VESA_NAME " open device\n" );
+
+    if (_Atomic_Flag_test_and_set(&driver_mutex, ATOMIC_ORDER_ACQUIRE) != 0 )
+    {
+        printk( FB_VESA_NAME " could not lock vesa_mutex\n" );
+
+        return RTEMS_UNSATISFIED;
+    }
+
+    return RTEMS_SUCCESSFUL;
+
+}
+
+/*
+ * fb_vesa device driver CLOSE entry point
+ */
+rtems_device_driver
+frame_buffer_close(
+    rtems_device_major_number  major,
+    rtems_device_minor_number  minor,
+    void                      *arg
+)
+{
+  printk( FB_VESA_NAME " close device\n" );
+  _Atomic_Flag_clear(&driver_mutex, ATOMIC_ORDER_RELEASE);
+  /* restore previous state.  for VGA this means return to text mode.
+   * leave out if graphics hardware has been initialized in
+   * frame_buffer_initialize() */
+
+  printk(FB_VESA_NAME ": close called.\n" );
+  return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * fb_vesa device driver READ entry point.
+ */
+rtems_device_driver
+frame_buffer_read(
+    rtems_device_major_number  major,
+    rtems_device_minor_number  minor,
+    void                      *arg
+)
+{
+  printk( FB_VESA_NAME " read device\n" );
+  rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
+  rw_args->bytes_moved =
+    ((rw_args->offset + rw_args->count) > fb_fix.smem_len ) ?
+        (fb_fix.smem_len - rw_args->offset) :
+        rw_args->count;
+  memcpy(rw_args->buffer, (const void *)
+    (fb_fix.smem_start + rw_args->offset), rw_args->bytes_moved);
+  return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * frame_vesa device driver WRITE entry point.
+ */
+rtems_device_driver
+frame_buffer_write(
+    rtems_device_major_number  major,
+    rtems_device_minor_number  minor,
+    void                      *arg
+)
+{
+  printk( FB_VESA_NAME " write device\n" );
+  rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
+  rw_args->bytes_moved =
+    ((rw_args->offset + rw_args->count) > fb_fix.smem_len ) ?
+        (fb_fix.smem_len - rw_args->offset) :
+        rw_args->count;
+  memcpy( (void *) (fb_fix.smem_start + rw_args->offset),
+    rw_args->buffer, rw_args->bytes_moved);
+  return RTEMS_SUCCESSFUL;
+}
+
+static int get_fix_screen_info( struct fb_fix_screeninfo *info )
+{
+  *info = fb_fix;
+  return 0;
+}
+
+static int get_var_screen_info( struct fb_var_screeninfo *info )
+{
+  *info =  fb_var;
+  return 0;
+}
+
+/*
+ * IOCTL entry point -- This method is called to carry
+ * all services of this interface.
+ */
+rtems_device_driver
+frame_buffer_control(
+    rtems_device_major_number  major,
+    rtems_device_minor_number  minor,
+    void                      *arg
+)
+{
+  rtems_libio_ioctl_args_t *args = arg;
+
+  printk( FB_VESA_NAME " ioctl called, cmd=%" PRIx32 "\n", args->command  );
+    printk("fbxres %lu, fbyres %lu\n", fb_var.xres, fb_var.yres);
+    printk("fbbpp %lu\n", fb_var.bits_per_pixel);
+
+  switch (args->command)
+  {
+  case FBIOGET_FSCREENINFO:
+      args->ioctl_return =
+        get_fix_screen_info( ( struct fb_fix_screeninfo * ) args->buffer );
+      break;
+  case FBIOGET_VSCREENINFO:
+      args->ioctl_return =
+        get_var_screen_info( ( struct fb_var_screeninfo * ) args->buffer );
+      break;
+  case FBIOPUT_VSCREENINFO:
+    /* not implemented yet */
+    args->ioctl_return = -1;
+    return RTEMS_UNSATISFIED;
+  case FBIOGETCMAP:
+    /* no palette - truecolor mode */
+    args->ioctl_return = -1;
+    return RTEMS_UNSATISFIED;
+  case FBIOPUTCMAP:
+    /* no palette - truecolor mode */
+    args->ioctl_return = -1;
+    return RTEMS_UNSATISFIED;
+  default:
+    args->ioctl_return = 0;
+    break;
+  }
+  return RTEMS_SUCCESSFUL;
+}
Index: bsps/i386/pc386/console/fb_vga.c
===================================================================
--- bsps/i386/pc386/console/fb_vga.c	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
+++ bsps/i386/pc386/console/fb_vga.c	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
@@ -0,0 +1,245 @@
+/*
+ * Copyright (c) 2000 - Rosimildo da Silva ( rdasilva@connecttel.com )
+ *
+ * MODULE DESCRIPTION:
+ * This module implements FB driver for "Bare VGA". It uses the
+ * routines for "bare hardware" found in vgainit.c.
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <pthread.h>
+
+#include <bsp.h>
+#include <bsp/irq.h>
+#include <rtems/libio.h>
+
+#include <rtems/fb.h>
+#include <rtems/framebuffer.h>
+
+#include <rtems/score/atomic.h>
+
+/* these routines are defined in vgainit.c.*/
+extern void ega_hwinit( void );
+extern void ega_hwterm( void );
+
+/* flag to limit driver to protect against multiple opens */
+static Atomic_Flag driver_mutex;
+
+/* screen information for the VGA driver */
+static struct fb_var_screeninfo fb_var =
+{
+  .xres                = 640,
+  .yres                = 480,
+  .bits_per_pixel      = 4
+};
+
+static struct fb_fix_screeninfo fb_fix =
+{
+  .smem_start          = (volatile char *)0xA0000,     /* buffer pointer    */
+  .smem_len            = 0x10000,                      /* buffer size       */
+  .type                = FB_TYPE_VGA_PLANES,           /* type of dsplay    */
+  .visual              = FB_VISUAL_PSEUDOCOLOR,        /* color scheme used */
+  .line_length         = 80                            /* chars per line    */
+};
+
+
+static uint16_t red16[] = {
+   0x0000, 0x0000, 0x0000, 0x0000, 0xaaaa, 0xaaaa, 0xaaaa, 0xaaaa,
+   0x5555, 0x5555, 0x5555, 0x5555, 0xffff, 0xffff, 0xffff, 0xffff
+};
+static uint16_t green16[] = {
+   0x0000, 0x0000, 0xaaaa, 0xaaaa, 0x0000, 0x0000, 0x5555, 0xaaaa,
+   0x5555, 0x5555, 0xffff, 0xffff, 0x5555, 0x5555, 0xffff, 0xffff
+};
+static uint16_t blue16[] = {
+   0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa,
+   0x5555, 0xffff, 0x5555, 0xffff, 0x5555, 0xffff, 0x5555, 0xffff
+};
+
+/* Functionality to support multiple VGA frame buffers can be added easily,
+ * but is not supported at this moment because there is no need for two or
+ * more "classic" VGA adapters.  Multiple frame buffer drivers may be
+ * implemented and If we had implement it they would be named as "/dev/fb0",
+ * "/dev/fb1", "/dev/fb2" and so on.
+ */
+/*
+ * fbvga device driver INITIALIZE entry point.
+ */
+rtems_device_driver frame_buffer_initialize(
+  rtems_device_major_number  major,
+  rtems_device_minor_number  minor,
+  void                      *arg
+)
+{
+  rtems_status_code status;
+
+  printk( "FBVGA -- driver initializing..\n" );
+
+  /*
+   * Register the device
+   */
+  status = rtems_io_register_name (FRAMEBUFFER_DEVICE_0_NAME, major, 0);
+  if (status != RTEMS_SUCCESSFUL) {
+    printk("Error registering " FRAMEBUFFER_DEVICE_0_NAME
+           " FBVGA framebuffer device!\n");
+    rtems_fatal_error_occurred( status );
+  }
+
+  _Atomic_Flag_clear(&driver_mutex, ATOMIC_ORDER_RELEASE);
+
+  return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * fbvga device driver OPEN entry point
+ */
+rtems_device_driver frame_buffer_open(
+  rtems_device_major_number  major,
+  rtems_device_minor_number  minor,
+  void                      *arg
+)
+{
+  if (_Atomic_Flag_test_and_set(&driver_mutex, ATOMIC_ORDER_ACQUIRE) != 0 ) {
+      /* restore previous state.  for VGA this means return to text mode.
+       * leave out if graphics hardware has been initialized in
+       * frame_buffer_initialize()
+       */
+      ega_hwinit();
+      printk( "FBVGA open called.\n" );
+      return RTEMS_SUCCESSFUL;
+  }
+
+  return RTEMS_UNSATISFIED;
+}
+
+/*
+ * fbvga device driver CLOSE entry point
+ */
+rtems_device_driver frame_buffer_close(
+  rtems_device_major_number  major,
+  rtems_device_minor_number  minor,
+  void                      *arg
+)
+{
+  _Atomic_Flag_clear(&driver_mutex, ATOMIC_ORDER_RELEASE);
+  /* restore previous state.  for VGA this means return to text mode.
+   * leave out if graphics hardware has been initialized in
+   * frame_buffer_initialize() */
+  ega_hwterm();
+  printk( "FBVGA close called.\n" );
+  return RTEMS_SUCCESSFUL;
+
+/*
+ * fbvga device driver READ entry point.
+ */
+rtems_device_driver frame_buffer_read(
+  rtems_device_major_number  major,
+  rtems_device_minor_number  minor,
+  void                      *arg
+)
+{
+  rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
+  rw_args->bytes_moved = ((rw_args->offset + rw_args->count) > fb_fix.smem_len ) ? (fb_fix.smem_len - rw_args->offset) : rw_args->count;
+  memcpy(rw_args->buffer, (const void *) (fb_fix.smem_start + rw_args->offset), rw_args->bytes_moved);
+  return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * frame_buffer device driver WRITE entry point.
+ */
+rtems_device_driver frame_buffer_write(
+  rtems_device_major_number  major,
+  rtems_device_minor_number  minor,
+  void                      *arg
+)
+{
+  rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
+  rw_args->bytes_moved = ((rw_args->offset + rw_args->count) > fb_fix.smem_len ) ? (fb_fix.smem_len - rw_args->offset) : rw_args->count;
+  memcpy( (void *) (fb_fix.smem_start + rw_args->offset), rw_args->buffer, rw_args->bytes_moved);
+  return RTEMS_SUCCESSFUL;
+}
+
+static int get_fix_screen_info( struct fb_fix_screeninfo *info )
+{
+  *info = fb_fix;
+  return 0;
+}
+
+static int get_var_screen_info( struct fb_var_screeninfo *info )
+{
+  *info =  fb_var;
+  return 0;
+}
+
+static int get_palette( struct fb_cmap *cmap )
+{
+  uint32_t i;
+
+  if ( cmap->start + cmap->len >= 16 )
+    return 1;
+
+  for( i = 0; i < cmap->len; i++ ) {
+    cmap->red[ cmap->start + i ]   = red16[ cmap->start + i ];
+    cmap->green[ cmap->start + i ] = green16[ cmap->start + i ];
+    cmap->blue[ cmap->start + i ]  = blue16[ cmap->start + i ];
+  }
+  return 0;
+}
+
+static int set_palette( struct fb_cmap *cmap )
+{
+  uint32_t i;
+
+  if ( cmap->start + cmap->len >= 16 )
+    return 1;
+
+  for( i = 0; i < cmap->len; i++ ) {
+    red16[ cmap->start + i ] = cmap->red[ cmap->start + i ];
+    green16[ cmap->start + i ] = cmap->green[ cmap->start + i ];
+    blue16[ cmap->start + i ] = cmap->blue[ cmap->start + i ];
+  }
+  return 0;
+}
+
+/*
+ * IOCTL entry point -- This method is called to carry
+ * all services of this interface.
+ */
+rtems_device_driver frame_buffer_control(
+  rtems_device_major_number  major,
+  rtems_device_minor_number  minor,
+  void                      *arg
+)
+{
+  rtems_libio_ioctl_args_t *args = arg;
+
+  printk( "FBVGA ioctl called, cmd=%x\n", args->command  );
+
+  switch( args->command ) {
+    case FBIOGET_FSCREENINFO:
+      args->ioctl_return =  get_fix_screen_info( ( struct fb_fix_screeninfo * ) args->buffer );
+      break;
+    case FBIOGET_VSCREENINFO:
+      args->ioctl_return =  get_var_screen_info( ( struct fb_var_screeninfo * ) args->buffer );
+      break;
+    case FBIOPUT_VSCREENINFO:
+      /* not implemented yet*/
+      args->ioctl_return = -1;
+      return RTEMS_UNSATISFIED;
+    case FBIOGETCMAP:
+      args->ioctl_return =  get_palette( ( struct fb_cmap * ) args->buffer );
+      break;
+    case FBIOPUTCMAP:
+      args->ioctl_return =  set_palette( ( struct fb_cmap * ) args->buffer );
+      break;
+
+    default:
+     args->ioctl_return = 0;
+     break;
+  }
+  return RTEMS_SUCCESSFUL;
+}
Index: bsps/i386/pc386/console/gdb_select.c
===================================================================
--- bsps/i386/pc386/console/gdb_select.c	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
+++ bsps/i386/pc386/console/gdb_select.c	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
@@ -0,0 +1,170 @@
+/**
+ * @file
+ *
+ * @ingroup GDB
+ *
+ * @brief pc386 gdb select
+ *
+ * This file contains a routine to enable and select the UART the gdb stub
+ * connects too. Currently limited to COM1 and COM2. See
+ * shared/comm/i386-stub-glue.c file.
+ */
+
+/*
+ *  COPYRIGHT (c) 2016.
+ *  Chris Johns <chrisj@rtems.org>
+ *
+ *  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 <limits.h>
+
+#include <bsp.h>
+#include <rtems/libio.h>
+#include <rtems/console.h>
+#include <rtems/termiostypes.h>
+#include <libchip/serial.h>
+#include <libchip/ns16550.h>
+#include <bsp/bspimpl.h>
+
+#include "../../shared/dev/serial/legacy-console.h"
+
+/*
+ * Used in the stub to print output.
+ */
+int remote_debug;
+/*
+ * Defined in the stub, used here.
+ */
+void set_debug_traps(void);
+
+/*
+ * Added here to get a valid baudrate. Needs to go once we
+ * move to the standard UART driver.
+ */
+int BSPBaseBaud;
+
+static bool gdb_port_probe(int minor)
+{
+  /* Return false as GDB has claimed the port */
+  return false;
+}
+
+void pc386_parse_gdb_arguments(void)
+{
+  static const char *opt;
+
+  /*
+   * Check the command line to see if com1-com4 are disabled.
+   */
+  opt = bsp_cmdline_arg("--gdb=");
+  if ( opt ) {
+    const char                *option;
+    const char                *comma;
+    size_t                     length;
+    size_t                     index;
+    rtems_device_minor_number  minor;
+    uint32_t                   baudrate = 115200;
+    bool                       halt = false;
+    console_tbl               *port;
+
+    /*
+     * Fine the length, there can be more command line visible.
+     */
+    length = 0;
+    while ((opt[length] != ' ') && (opt[length] != '\0')) {
+      ++length;
+      if (length > NAME_MAX) {
+        printk("invalid option (--gdb): too long\n");
+        return;
+      }
+    }
+
+    /*
+     * Only match up to a comma or NULL
+     */
+    index = 0;
+    while ((opt[index] != '=') && (index < length)) {
+      ++index;
+    }
+
+    if (opt[index] != '=') {
+      printk("invalid option (--gdb): no equals\n");
+      return;
+    }
+
+    ++index;
+    option = &opt[index];
+
+    while ((opt[index] != ',') && (index < length)) {
+      ++index;
+    }
+
+    if (opt[index] == ',')
+      comma = &opt[index];
+    else
+      comma = NULL;
+
+    length = &opt[index] - option;
+
+    port = console_find_console_entry( option, length, &minor );
+
+    if ( port == NULL ) {
+      printk("invalid option (--gdb): port not found\n");
+      return;
+    }
+
+    if (comma) {
+      option = comma + 1;
+      baudrate = strtoul(option, 0, 10);
+      switch (baudrate) {
+        case 115200:
+        case 57600:
+        case 38400:
+        case 19200:
+        case 9600:
+        case 4800:
+          port->pDeviceParams = (void*) baudrate;
+          BSPBaseBaud = baudrate; /* REMOVE ME */
+          break;
+        default:
+          printk("invalid option (--gdb): bad baudrate\n");
+          return;
+      }
+    }
+
+    /*
+     * Provide a probe that fails so the device is not part of termios. All
+     * functions are polling.
+     */
+    port->deviceProbe = gdb_port_probe;
+    port->pDeviceFns = &ns16550_fns_polled;
+
+    opt = bsp_cmdline_arg("--gdb-remote-debug");
+    if ( opt ) {
+      remote_debug = 1;
+    }
+
+    opt = bsp_cmdline_arg("--gdb-break");
+    if ( opt ) {
+      halt = true;
+    }
+
+    printk("GDB stub: enable %s%s%s\n",
+           port->sDeviceName,
+           remote_debug ? ", remote-debug" : "",
+           halt ? ", halting" : "");
+
+    i386_stub_glue_init(minor);
+    set_debug_traps();
+    i386_stub_glue_init_breakin();
+
+    if ( halt ) {
+      printk("GDB stub: waiting for remote connection..\n");
+      breakpoint();
+    }
+  }
+}
Index: bsps/i386/pc386/console/i386kbd.h
===================================================================
--- bsps/i386/pc386/console/i386kbd.h	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
+++ bsps/i386/pc386/console/i386kbd.h	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
@@ -0,0 +1,192 @@
+/**
+ * @file
+ * 
+ * @ingroup i386_pc386
+ *
+ * @brief I386 keyboard definitions.
+ */
+
+/*
+ *  linux/include/asm-i386/keyboard.h
+ *
+ *  Created 3 Nov 1996 by Geert Uytterhoeven
+ */
+
+/*
+ *  This file contains the i386 architecture specific keyboard definitions
+ */
+
+#ifndef _I386_KEYBOARD_H
+#define _I386_KEYBOARD_H
+
+#include  <i386_io.h>
+
+#define KEYBOARD_IRQ			1
+#define DISABLE_KBD_DURING_INTERRUPTS	0
+
+extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
+extern int pckbd_getkeycode(unsigned int scancode);
+extern int pckbd_translate(unsigned char scancode, unsigned char *keycode,
+			   char raw_mode);
+extern char pckbd_unexpected_up(unsigned char keycode);
+extern void pckbd_leds(unsigned char leds);
+extern void pckbd_init_hw(void);
+extern unsigned char pckbd_sysrq_xlate[128];
+
+#define kbd_setkeycode		pckbd_setkeycode
+#define kbd_getkeycode		pckbd_getkeycode
+#define kbd_translate		pckbd_translate
+#define kbd_unexpected_up	pckbd_unexpected_up
+#define kbd_leds		      pckbd_leds
+#define kbd_init_hw		   pckbd_init_hw
+#define kbd_sysrq_xlate		pckbd_sysrq_xlate
+
+#define SYSRQ_KEY 0x54
+
+/* resource allocation */
+#define kbd_request_region()     /* request_region(0x60, 16, "keyboard") */
+#define kbd_request_irq(handler) /* request_irq(KEYBOARD_IRQ, handler, 0, "keyboard", NULL) */
+
+/* How to access the keyboard macros on this platform.  */
+#define kbd_read_input() inb(KBD_DATA_REG)
+#define kbd_read_status() inb(KBD_STATUS_REG)
+#define kbd_write_output(val) outb(val, KBD_DATA_REG)
+#define kbd_write_command(val) outb(val, KBD_CNTL_REG)
+
+/* Some stoneage hardware needs delays after some operations.  */
+#define kbd_pause() do { } while(0)
+
+/*
+ * Machine specific bits for the PS/2 driver
+ */
+
+#define AUX_IRQ 12
+
+#define aux_request_irq(hand, dev_id)  /* request_irq(AUX_IRQ, hand, SA_SHIRQ, "PS/2 Mouse", dev_id) */
+
+#define aux_free_irq(dev_id)   /* free_irq(AUX_IRQ, dev_id) */
+
+/*
+ *	include/linux/pc_keyb.h
+ *
+ *	PC Keyboard And Keyboard Controller
+ *
+ *	(c) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ */
+
+/*
+ *	Configuration Switches
+ */
+
+#undef KBD_REPORT_ERR			/* Report keyboard errors */
+#define KBD_REPORT_UNKN			/* Report unknown scan codes */
+#define KBD_REPORT_TIMEOUTS		/* Report keyboard timeouts */
+#undef KBD_IS_FOCUS_9000		/* We have the brain-damaged FOCUS-9000 keyboard */
+#undef INITIALIZE_MOUSE			/* Define if your PS/2 mouse needs initialization. */
+
+#define KBD_INIT_TIMEOUT 1000		/* Timeout in ms for initializing the keyboard */
+#define KBC_TIMEOUT 250			/* Timeout in ms for sending to keyboard controller */
+#define KBD_TIMEOUT 1000		/* Timeout in ms for keyboard command acknowledge */
+
+/*
+ *	Internal variables of the driver
+ */
+
+extern unsigned char pckbd_read_mask;
+extern unsigned char aux_device_present;
+
+/*
+ *	Keyboard Controller Registers on normal PCs.
+ */
+
+#define KBD_STATUS_REG		0x64	/* Status register (R) */
+#define KBD_CNTL_REG		0x64	/* Controller command register (W) */
+#define KBD_DATA_REG		0x60	/* Keyboard data register (R/W) */
+
+/*
+ *	Keyboard Controller Commands
+ */
+
+#define KBD_CCMD_READ_MODE	0x20	/* Read mode bits */
+#define KBD_CCMD_WRITE_MODE	0x60	/* Write mode bits */
+#define KBD_CCMD_GET_VERSION	0xA1	/* Get controller version */
+#define KBD_CCMD_MOUSE_DISABLE	0xA7	/* Disable mouse interface */
+#define KBD_CCMD_MOUSE_ENABLE	0xA8	/* Enable mouse interface */
+#define KBD_CCMD_TEST_MOUSE	0xA9	/* Mouse interface test */
+#define KBD_CCMD_SELF_TEST	0xAA	/* Controller self test */
+#define KBD_CCMD_KBD_TEST	0xAB	/* Keyboard interface test */
+#define KBD_CCMD_KBD_DISABLE	0xAD	/* Keyboard interface disable */
+#define KBD_CCMD_KBD_ENABLE	0xAE	/* Keyboard interface enable */
+#define KBD_CCMD_WRITE_AUX_OBUF	0xD3    /* Write to output buffer as if
+					   initiated by the auxiliary device */
+#define KBD_CCMD_WRITE_MOUSE	0xD4	/* Write the following byte to the mouse */
+
+/*
+ *	Keyboard Commands
+ */
+
+#define KBD_CMD_SET_LEDS	0xED	/* Set keyboard leds */
+#define KBD_CMD_SET_RATE	0xF3	/* Set typematic rate */
+#define KBD_CMD_ENABLE		0xF4	/* Enable scanning */
+#define KBD_CMD_DISABLE		0xF5	/* Disable scanning */
+#define KBD_CMD_RESET		0xFF	/* Reset */
+
+/*
+ *	Keyboard Replies
+ */
+
+#define KBD_REPLY_POR		0xAA	/* Power on reset */
+#define KBD_REPLY_ACK		0xFA	/* Command ACK */
+#define KBD_REPLY_RESEND	0xFE	/* Command NACK, send the cmd again */
+
+/*
+ *	Status Register Bits
+ */
+
+#define KBD_STAT_OBF 		0x01	/* Keyboard output buffer full */
+#define KBD_STAT_IBF 		0x02	/* Keyboard input buffer full */
+#define KBD_STAT_SELFTEST	0x04	/* Self test successful */
+#define KBD_STAT_CMD		0x08	/* Last write was a command write (0=data) */
+#define KBD_STAT_UNLOCKED	0x10	/* Zero if keyboard locked */
+#define KBD_STAT_MOUSE_OBF	0x20	/* Mouse output buffer full */
+#define KBD_STAT_GTO 		0x40	/* General receive/xmit timeout */
+#define KBD_STAT_PERR 		0x80	/* Parity error */
+
+#define AUX_STAT_OBF (KBD_STAT_OBF | KBD_STAT_MOUSE_OBF)
+
+/*
+ *	Controller Mode Register Bits
+ */
+
+#define KBD_MODE_KBD_INT	0x01	/* Keyboard data generate IRQ1 */
+#define KBD_MODE_MOUSE_INT	0x02	/* Mouse data generate IRQ12 */
+#define KBD_MODE_SYS 		0x04	/* The system flag (?) */
+#define KBD_MODE_NO_KEYLOCK	0x08	/* The keylock doesn't affect the keyboard if set */
+#define KBD_MODE_DISABLE_KBD	0x10	/* Disable keyboard interface */
+#define KBD_MODE_DISABLE_MOUSE	0x20	/* Disable mouse interface */
+#define KBD_MODE_KCC 		0x40	/* Scan code conversion to PC format */
+#define KBD_MODE_RFU		0x80
+
+/*
+ *	Mouse Commands
+ */
+
+#define AUX_SET_RES		0xE8	/* Set resolution */
+#define AUX_SET_SCALE11		0xE6	/* Set 1:1 scaling */
+#define AUX_SET_SCALE21		0xE7	/* Set 2:1 scaling */
+#define AUX_GET_SCALE		0xE9	/* Get scaling factor */
+#define AUX_SET_STREAM		0xEA	/* Set stream mode */
+#define AUX_SET_SAMPLE		0xF3	/* Set sample rate */
+#define AUX_ENABLE_DEV		0xF4	/* Enable aux device */
+#define AUX_DISABLE_DEV		0xF5	/* Disable aux device */
+#define AUX_RESET		0xFF	/* Reset aux device */
+#define AUX_ACK			0xFA	/* Command byte ACK. */
+
+#define AUX_BUF_SIZE		2048	/* This might be better divisible by
+					   three to make overruns stay in sync
+					   but then the read function would need
+					   a lock etc - ick */
+
+#define  mark_bh(x)
+
+#endif /* _I386_KEYBOARD_H */
Index: bsps/i386/pc386/console/inch.c
===================================================================
--- bsps/i386/pc386/console/inch.c	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
+++ bsps/i386/pc386/console/inch.c	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
@@ -0,0 +1,300 @@
+/*-------------------------------------------------------------------------+
+| inch.c v1.1 - PC386 BSP - 1997/08/07
++--------------------------------------------------------------------------+
+| (C) Copyright 1997 -
+| - NavIST Group - Real-Time Distributed Systems and Industrial Automation
+|
+| http://pandora.ist.utl.pt
+|
+| Instituto Superior Tecnico * Lisboa * PORTUGAL
++--------------------------------------------------------------------------+
+| Disclaimer:
+|
+| This file is provided "AS IS" without warranty of any kind, either
+| expressed or implied.
++--------------------------------------------------------------------------+
+| This code is based on:
+|   inch.c,v 1.3 1995/12/19 20:07:25 joel Exp - go32 BSP
+| With the following copyright notice:
+| With the following copyright notice:
+| **************************************************************************
+| *  COPYRIGHT (c) 1989-1998.
+| *  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 <bsp.h>
+#include <bsp/bootcard.h>
+#include <bsp/irq.h>
+
+/*-------------------------------------------------------------------------+
+| Constants
++--------------------------------------------------------------------------*/
+#define KBD_CTL      0x61  /* -------------------------------- */
+#define KBD_DATA     0x60  /* Ports for PC keyboard controller */
+#define KBD_STATUS   0x64  /* -------------------------------- */
+
+#define KBD_BUF_SIZE 256
+
+/*-------------------------------------------------------------------------+
+| Global Variables
++--------------------------------------------------------------------------*/
+static char key_map[] =
+{
+  0,033,'1','2','3','4','5','6','7','8','9','0','-','=','\b','\t',
+  'q','w','e','r','t','y','u','i','o','p','[',']',015,0x80,
+  'a','s','d','f','g','h','j','k','l',';',047,0140,0x80,
+  0134,'z','x','c','v','b','n','m',',','.','/',0x80,
+  '*',0x80,' ',0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+  0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+  0x80,0x80,0x80,'0',0177
+}; /* Keyboard scancode -> character map with no modifiers.       */
+
+static char shift_map[] =
+{
+  0,033,'!','@','#','$','%','^','&','*','(',')','_','+','\b','\t',
+  'Q','W','E','R','T','Y','U','I','O','P','{','}',015,0x80,
+  'A','S','D','F','G','H','J','K','L',':',042,'~',0x80,
+  '|','Z','X','C','V','B','N','M','<','>','?',0x80,
+  '*',0x80,' ',0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+  0x80,0x80,0x80,0x80,'7','8','9',0x80,'4','5','6',0x80,
+  '1','2','3','0',177
+}; /* Keyboard scancode -> character map with SHIFT key modifier. */
+
+static unsigned short   kbd_buffer[KBD_BUF_SIZE];
+static uint16_t         kbd_first = 0;
+static uint16_t         kbd_last  = 0;
+static uint16_t         kbd_end   = KBD_BUF_SIZE - 1;
+
+/*-------------------------------------------------------------------------+
+|         Function: _IBMPC_scankey
+|      Description: This function can be called during a poll for input, or by
+|                   an ISR. Basically any time you want to process a keypress.
+| Global Variables: key_map, shift_map.
+|        Arguments: outChar - character read in case of a valid reading,
+|                   otherwise unchanged.
+|          Returns: TRUE in case a valid character has been read,
+|                   FALSE otherwise.
++--------------------------------------------------------------------------*/
+static bool
+_IBMPC_scankey(char *outChar)
+{
+  unsigned char inChar;
+  static int alt_pressed   = 0;
+  static int ctrl_pressed  = 0;
+  static int shift_pressed = 0;
+  static int caps_pressed  = 0;
+  static int extended      = 0;
+
+  *outChar = '\0'; /* default value if we return false */
+
+  /* Read keyboard controller, toggle enable */
+  inport_byte(KBD_CTL, inChar);
+  outport_byte(KBD_CTL, inChar & ~0x80);
+  outport_byte(KBD_CTL, inChar | 0x80);
+  outport_byte(KBD_CTL, inChar & ~0x80);
+
+  /* See if it has data */
+  inport_byte(KBD_STATUS, inChar);
+  if ((inChar & 0x01) == 0)
+    return false;
+
+  /* Read the data.  Handle nonsense with shift, control, etc. */
+  inport_byte(KBD_DATA, inChar);
+
+  if (extended)
+    extended--;
+
+  switch (inChar)
+  {
+    case 0xe0:
+      extended = 2;
+      return false;
+      break;
+
+    case 0x38:
+      alt_pressed = 1;
+      return false;
+      break;
+    case 0xb8:
+      alt_pressed = 0;
+      return false;
+      break;
+
+    case 0x1d:
+      ctrl_pressed = 1;
+      return false;
+      break;
+    case 0x9d:
+      ctrl_pressed = 0;
+      return false;
+      break;
+
+    case 0x2a:
+      if (extended)
+        return false;
+    case 0x36:
+      shift_pressed = 1;
+      return false;
+      break;
+    case 0xaa:
+      if (extended)
+        return false;
+    case 0xb6:
+      shift_pressed = 0;
+      return false;
+      break;
+
+    case 0x3a:
+      caps_pressed = 1;
+      return false;
+      break;
+    case 0xba:
+      caps_pressed = 0;
+      return false;
+      break;
+
+    case 0x53:
+      if (ctrl_pressed && alt_pressed)
+        bsp_reset(); /* ctrl+alt+del -> reboot */
+      break;
+
+    /*
+     * Ignore unrecognized keys--usually arrow and such
+     */
+    default:
+      if ((inChar & 0x80) || (inChar > 0x39))
+      /* High-bit on means key is being released, not pressed */
+        return false;
+      break;
+  } /* switch */
+
+  /* Strip high bit, look up in our map */
+  inChar &= 0x7f;
+  if (ctrl_pressed)
+  {
+    *outChar = key_map[inChar];
+    *outChar &= 037;
+  }
+  else
+  {
+    *outChar = shift_pressed ? shift_map[inChar] : key_map[inChar];
+    if (caps_pressed)
+    {
+      if (*outChar >= 'A' && *outChar <= 'Z')
+        *outChar += 'a' - 'A';
+      else if (*outChar >= 'a' && *outChar <= 'z')
+        *outChar -= 'a' - 'A';
+    }
+  }
+
+  return true;
+} /* _IBMPC_scankey */
+
+/*-------------------------------------------------------------------------+
+|         Function: _IBMPC_chrdy
+|      Description: Check keyboard ISR buffer and return character if not empty.
+| Global Variables: kbd_buffer, kbd_first, kbd_last.
+|        Arguments: c - character read if keyboard buffer not empty, otherwise
+|                   unchanged.
+|          Returns: TRUE if keyboard buffer not empty, FALSE otherwise.
++--------------------------------------------------------------------------*/
+static bool
+_IBMPC_chrdy(char *c)
+{
+#if CCJ_REMOVED_NO_IDEA_ABOUT_THIS_CODE_OR_COMMENT
+  /* FIX ME!!! It doesn't work without something like the following line.
+     Find out why! */
+  printk("");
+#endif
+
+  /* Check buffer our ISR builds */
+  if (kbd_first != kbd_last)
+  {
+    *c = kbd_buffer[kbd_first];
+
+    kbd_first = (kbd_first + 1) % KBD_BUF_SIZE;
+    return true;
+  }
+  else
+    return false;
+} /* _IBMPC_chrdy */
+
+/*-------------------------------------------------------------------------+
+|         Function: _IBMPC_inch
+|      Description: Poll keyboard until a character is ready and return it.
+| Global Variables: None.
+|        Arguments: None.
+|          Returns: character read from keyboard.
++--------------------------------------------------------------------------*/
+char
+_IBMPC_inch(void)
+{
+    char c;
+    while (!_IBMPC_chrdy(&c))
+      continue;
+
+    return c;
+} /* _IBMPC_inch */
+
+/*
+ * Routine that can be used before interrupt management is initialized.
+ */
+int BSP_wait_polled_input(void)
+{
+  char c;
+  while (!_IBMPC_scankey(&c))
+    continue;
+
+  return c;
+}
+
+/*
+ * Check if a key has been pressed. This is a non-destructive
+ * call, meaning, it keeps the key in the buffer.
+ */
+int rtems_kbpoll( void )
+{
+  int                    rc;
+
+  /*
+   * The locking or disable of interrupts does not help
+   * there because if interrupts are enabled after leave of this
+   * function the state can change without notice anyway.
+   */
+  RTEMS_COMPILER_MEMORY_BARRIER();
+
+  rc = ( kbd_first != kbd_last ) ? TRUE : FALSE;
+
+  RTEMS_COMPILER_MEMORY_BARRIER();
+
+  return rc;
+}
+
+int getch( void )
+{
+  int c;
+
+  while( kbd_first == kbd_last )
+  {
+     rtems_task_wake_after( 10 );
+  }
+  c = kbd_buffer[ kbd_first ];
+  kbd_first = (kbd_first + 1) % KBD_BUF_SIZE;
+  return c;
+}
+
+void add_to_queue( unsigned short b )
+{
+ unsigned int next;
+ kbd_buffer[ kbd_last ] = b;
+ next = (kbd_last == kbd_end) ? 0 : kbd_last + 1;
+ if( next != kbd_first )
+ {
+    kbd_last = next;
+ }
+}
Index: bsps/i386/pc386/console/kbd_parser.c
===================================================================
--- bsps/i386/pc386/console/kbd_parser.c	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
+++ bsps/i386/pc386/console/kbd_parser.c	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
@@ -0,0 +1,47 @@
+/*
+ *  The contents of this file were formerly in console.c which
+ *  had the following copyright notice:
+ *
+ *  (C) Copyright 1997
+ *  NavIST Group - Real-Time Distributed Systems and Industrial Automation
+ *  http://pandora.ist.utl.pt
+ *  Instituto Superior Tecnico * Lisboa * PORTUGAL
+ *
+ *  The original code and subsequent modifications are:
+ *
+ *  COPYRIGHT (c) 1989-2011.
+ *  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 <rtems.h>
+#include <rtems/keyboard.h>
+#include <rtems/mw_uid.h>
+
+/* adds a kbd message to the queue */
+static void kbd_parser( void *ptr, unsigned short keycode, unsigned long mods )
+{
+  struct MW_UID_MESSAGE m;
+  struct kbd_struct * kbd = (struct kbd_struct *)ptr;
+
+  m.type = MV_UID_KBD;
+  m.m.kbd.code       = keycode;
+  m.m.kbd.modifiers  = kbd->ledflagstate;
+  m.m.kbd.mode       = kbd->kbdmode;
+  /*  printk( "kbd: msg: keycode=%X, mod=%X\n", keycode, mods );  */
+
+  uid_send_message( &m );
+}
+
+void register_kbd_msg_queue( char *q_name, int port )
+{
+  kbd_set_driver_handler( kbd_parser );
+}
+
+void unregister_kbd_msg_queue( int port )
+{
+   kbd_set_driver_handler( NULL );
+}
Index: bsps/i386/pc386/console/keyboard.c
===================================================================
--- bsps/i386/pc386/console/keyboard.c	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
+++ bsps/i386/pc386/console/keyboard.c	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
@@ -0,0 +1,881 @@
+/*
+ *   Rosimildo da Silva:  rdasilva@connecttel.com
+ */
+
+#include <limits.h>
+#include <sys/types.h>
+#include <rtems/keyboard.h>
+#include "i386kbd.h"
+#include <rtems/kd.h>
+#include <bsp.h>
+#include <bsp/bootcard.h>
+#include <stdatomic.h>
+
+#define SIZE(x) (sizeof(x)/sizeof((x)[0]))
+
+#ifndef KBD_DEFMODE
+#define KBD_DEFMODE ((1 << VC_REPEAT) | (1 << VC_META))
+#endif
+
+#ifndef KBD_DEFLEDS
+/*
+ * Some laptops take the 789uiojklm,. keys as number pad when NumLock
+ * is on. This seems a good reason to start with NumLock off.
+ */
+#define KBD_DEFLEDS 0
+#endif
+
+#ifndef KBD_DEFLOCK
+#define KBD_DEFLOCK 0
+#endif
+
+static int kbd_test_and_set_bit(int nr, atomic_uint_least32_t * addr)
+{
+  uint_least32_t        mask;
+  int                   retval;
+
+  addr += nr >> 5;
+  mask = 1UL << (nr & 0x1f);
+
+  retval = (atomic_fetch_or(addr, mask) & mask) != 0;
+
+  return retval;
+}
+
+static int kbd_test_and_clear_bit(int nr, atomic_uint_least32_t * addr)
+{
+  uint_least32_t        mask;
+  int                   retval;
+
+  addr += nr >> 5;
+  mask = 1UL << (nr & 0x1f);
+
+  retval = (atomic_fetch_and(addr, ~mask) & mask) != 0;
+
+  return retval;
+}
+
+static int kbd_test_bit(int nr, atomic_uint_least32_t * addr)
+{
+  unsigned long  mask;
+
+  addr += nr >> 5;
+  mask = 1 << (nr & 0x1f);
+  return ((mask & atomic_load(addr)) != 0);
+}
+
+/*
+ * global state includes the following, and various static variables
+ * in this module: prev_scancode, shift_state, diacr, npadch, dead_key_next.
+ * (last_console is now a global variable)
+ */
+#define  KBD_BITS_PER_ELEMENT (sizeof(atomic_uint_least32_t)*CHAR_BIT)
+
+/* shift state counters.. */
+static unsigned char k_down[NR_SHIFT] = {0, };
+/* keyboard key bitmap */
+static atomic_uint_least32_t
+  key_down[(256 + KBD_BITS_PER_ELEMENT - 1) / KBD_BITS_PER_ELEMENT] = { 0, };
+
+static int dead_key_next = 0;
+/*
+ * In order to retrieve the shift_state (for the mouse server), either
+ * the variable must be global, or a new procedure must be created to
+ * return the value. I chose the former way.
+ */
+int shift_state = 0;
+static int npadch = -1;      /* -1 or number assembled on pad */
+static unsigned char diacr = 0;
+static char rep = 0;      /* flag telling character repeat */
+
+/* default console for RTEMS */
+static int  fg_console = 0;
+
+struct kbd_struct kbd_table[MAX_NR_CONSOLES];
+static struct kbd_struct * kbd = kbd_table;
+
+void compute_shiftstate(void);
+
+typedef void (*k_hand)(unsigned char value, char up_flag);
+typedef void (k_handfn)(unsigned char value, char up_flag);
+
+static k_handfn
+  do_self, do_fn, do_spec, do_pad, do_dead, do_cons, do_cur, do_shift,
+  do_meta, do_ascii, do_lock, do_lowercase, do_slock, do_dead2,
+  do_ignore;
+
+static k_hand key_handler[16] = {
+  do_self, do_fn, do_spec, do_pad, do_dead, do_cons, do_cur, do_shift,
+  do_meta, do_ascii, do_lock, do_lowercase, do_slock, do_dead2,
+  do_ignore, do_ignore
+};
+
+/* Key types processed even in raw modes */
+
+#define TYPES_ALLOWED_IN_RAW_MODE ((1 << KT_SPEC) | (1 << KT_SHIFT))
+
+typedef void (*void_fnp)(void);
+typedef void (void_fn)(void);
+
+static void show_mem(void)
+{
+}
+static void show_state(void)
+{
+}
+
+static void_fn do_null, enter, show_ptregs, send_intr, lastcons, caps_toggle,
+  num, hold, scroll_forw, scroll_back, caps_on, compose,
+  SAK, decr_console, incr_console, spawn_console, bare_num;
+
+static void_fnp spec_fn_table[] = {
+  do_null,  enter,    show_ptregs,  show_mem,
+  show_state,  send_intr,  lastcons,  caps_toggle,
+  num,    hold,    scroll_forw,  scroll_back,
+  bsp_reset,  caps_on,  compose,  SAK,
+  decr_console,  incr_console,  spawn_console,  bare_num
+};
+
+#define SPECIALS_ALLOWED_IN_RAW_MODE (1 << KVAL(K_SAK))
+
+/* maximum values each key_handler can handle */
+const int max_vals[] = {
+  255, SIZE(func_table) - 1, SIZE(spec_fn_table) - 1, NR_PAD - 1,
+  NR_DEAD - 1, 255, 3, NR_SHIFT - 1,
+  255, NR_ASCII - 1, NR_LOCK - 1, 255,
+  NR_LOCK - 1, 255
+};
+
+const int NR_TYPES = SIZE(max_vals);
+
+/* N.B. drivers/macintosh/mac_keyb.c needs to call put_queue */
+static void put_queue(int);
+static unsigned char handle_diacr(unsigned char);
+
+#ifdef CONFIG_MAGIC_SYSRQ
+static int sysrq_pressed;
+#endif
+
+/*
+ * Many other routines do put_queue, but I think either
+ * they produce ASCII, or they produce some user-assigned
+ * string, and in both cases we might assume that it is
+ * in utf-8 already.
+ */
+static void to_utf8(ushort c)
+{
+  if (c < 0x80)
+    put_queue(c);                  /*  0*******  */
+  else if (c < 0x800) {
+    put_queue(0xc0 | (c >> 6));    /*  110***** 10******  */
+    put_queue(0x80 | (c & 0x3f));
+  } else {
+    put_queue(0xe0 | (c >> 12));   /*  1110**** 10****** 10******  */
+    put_queue(0x80 | ((c >> 6) & 0x3f));
+    put_queue(0x80 | (c & 0x3f));
+  }
+  /* UTF-8 is defined for words of up to 31 bits,
+     but we need only 16 bits here */
+}
+
+/*
+ * Translation of escaped scancodes to keycodes.
+ * This is now user-settable (for machines were it makes sense).
+ */
+
+int setkeycode(unsigned int scancode, unsigned int keycode)
+{
+    return kbd_setkeycode(scancode, keycode);
+}
+
+int getkeycode(unsigned int scancode)
+{
+    return kbd_getkeycode(scancode);
+}
+
+void handle_scancode(unsigned char scancode, int down)
+{
+  unsigned char keycode;
+  char up_flag = down ? 0 : 0200;
+  char raw_mode;
+
+  mark_bh(CONSOLE_BH);
+
+#if 0
+  tty = ttytab? ttytab[fg_console]: NULL;
+  if (tty && (!tty->driver_data)) {
+    /*
+     * We touch the tty structure via the the ttytab array
+     * without knowing whether or not tty is open, which
+     * is inherently dangerous.  We currently rely on that
+     * fact that console_open sets tty->driver_data when
+     * it opens it, and clears it when it closes it.
+     */
+    tty = NULL;
+  }
+#endif
+
+  kbd = kbd_table + fg_console;
+  if ((raw_mode = (kbd->kbdmode == VC_RAW))) {
+    put_queue(scancode | up_flag);
+    /* we do not return yet, because we want to maintain
+       the key_down array, so that we have the correct
+       values when finishing RAW mode or when changing VT's */
+  }
+
+  /*
+   *  Convert scancode to keycode
+   */
+  if (!kbd_translate(scancode, &keycode, raw_mode))
+      return;
+
+  /*
+   * At this point the variable `keycode' contains the keycode.
+   * Note: the keycode must not be 0 (++Geert: on m68k 0 is valid).
+   * We keep track of the up/down status of the key, and
+   * return the keycode if in MEDIUMRAW mode.
+   */
+
+  if (up_flag) {
+    rep = 0;
+    if(!kbd_test_and_clear_bit(keycode, key_down))
+        up_flag = kbd_unexpected_up(keycode);
+  } else
+    rep = kbd_test_and_set_bit(keycode, key_down);
+
+#ifdef CONFIG_MAGIC_SYSRQ    /* Handle the SysRq Hack */
+  if (keycode == SYSRQ_KEY) {
+    sysrq_pressed = !up_flag;
+    return;
+  } else if (sysrq_pressed) {
+    if (!up_flag && sysrq_enabled)
+      handle_sysrq(kbd_sysrq_xlate[keycode], kbd_pt_regs, kbd, tty);
+    return;
+  }
+#endif
+
+  if (kbd->kbdmode == VC_MEDIUMRAW) {
+    /* soon keycodes will require more than one byte */
+    put_queue(keycode + up_flag);
+    raw_mode = 1;  /* Most key classes will be ignored */
+  }
+  /*
+   * Small change in philosophy: earlier we defined repetition by
+   *   rep = keycode == prev_keycode;
+   *   prev_keycode = keycode;
+   * but now by the fact that the depressed key was down already.
+   * Does this ever make a difference? Yes.
+   */
+
+  /*
+   *  Repeat a key only if the input buffers are empty or the
+   *  characters get echoed locally. This makes key repeat usable
+   *  with slow applications and under heavy loads.
+   */
+  if (!rep || vc_kbd_mode(kbd,VC_REPEAT) ) {
+/*
+  ||  (vc_kbd_mode(kbd,VC_REPEAT) && tty &&
+       (L_ECHO(tty) || (tty->driver.chars_in_buffer(tty) == 0)))) {
+*/
+    u_short keysym;
+    u_char type;
+
+    /* the XOR below used to be an OR */
+    int shift_final = shift_state ^ kbd->lockstate ^ kbd->slockstate;
+    ushort *key_map = key_maps[shift_final];
+
+    if (key_map != NULL) {
+      keysym = key_map[keycode];
+      type = KTYP(keysym);
+
+      if (type >= 0xf0) {
+          type -= 0xf0;
+          if (raw_mode && ! (TYPES_ALLOWED_IN_RAW_MODE & (1 << type)))
+        return;
+         if (type == KT_LETTER) {
+        type = KT_LATIN;
+        if (vc_kbd_led(kbd, VC_CAPSLOCK)) {
+            key_map = key_maps[shift_final ^ (1<<KG_SHIFT)];
+            if (key_map)
+              keysym = key_map[keycode];
+        }
+          }
+
+          (*key_handler[type])(keysym & 0xff, up_flag);
+
+          if (type != KT_SLOCK)
+            kbd->slockstate = 0;
+
+      } else {
+          /* maybe only if (kbd->kbdmode == VC_UNICODE) ? */
+          if (!up_flag && !raw_mode)
+            to_utf8(keysym);
+      }
+    } else {
+      /* maybe beep? */
+      /* we have at least to update shift_state */
+#if 1      /* how? two almost equivalent choices follow */
+      compute_shiftstate();
+#else
+      keysym = U(plain_map[keycode]);
+      type = KTYP(keysym);
+      if (type == KT_SHIFT)
+        (*key_handler[type])(keysym & 0xff, up_flag);
+#endif
+    }
+  }
+}
+
+static void ( *driver_input_handler_kbd )( void *, unsigned short, unsigned long ) = 0;
+/*
+ */
+void kbd_set_driver_handler(
+  void ( *handler )( void *, unsigned short, unsigned long )
+)
+{
+  driver_input_handler_kbd = handler;
+}
+
+static void put_queue(int ch)
+{
+  if ( driver_input_handler_kbd ) {
+    driver_input_handler_kbd(  ( void *)kbd, (unsigned short)ch,  0 );
+  } else {
+    add_to_queue( ch );
+  }
+}
+
+static void puts_queue(char *cp)
+{
+  while (*cp) {
+     put_queue( *cp );
+    cp++;
+  }
+}
+
+static void applkey(int key, char mode)
+{
+  static char buf[] = { 0x1b, 'O', 0x00, 0x00 };
+
+  buf[1] = (mode ? 'O' : '[');
+  buf[2] = key;
+  puts_queue(buf);
+}
+
+static void enter(void)
+{
+  if (diacr) {
+    put_queue(diacr);
+    diacr = 0;
+  }
+  put_queue(13);
+
+  if (vc_kbd_mode(kbd,VC_CRLF))
+    put_queue(10);
+}
+
+static void caps_toggle(void)
+{
+  if (rep)
+    return;
+  chg_vc_kbd_led(kbd, VC_CAPSLOCK);
+}
+
+static void caps_on(void)
+{
+  if (rep)
+    return;
+  set_vc_kbd_led(kbd, VC_CAPSLOCK);
+}
+
+static void show_ptregs(void)
+{
+}
+
+static void hold(void)
+{
+  if (rep )
+    return;
+   chg_vc_kbd_led(kbd, VC_SCROLLOCK );
+}
+
+static void num(void)
+{
+  if (vc_kbd_mode(kbd,VC_APPLIC))
+    applkey('P', 1);
+  else
+    bare_num();
+}
+
+/*
+ * Bind this to Shift-NumLock if you work in application keypad mode
+ * but want to be able to change the NumLock flag.
+ * Bind this to NumLock if you prefer that the NumLock key always
+ * changes the NumLock flag.
+ */
+static void bare_num(void)
+{
+  if (!rep)
+    chg_vc_kbd_led(kbd,VC_NUMLOCK);
+}
+
+static void lastcons(void)
+{
+}
+
+static void decr_console(void)
+{
+}
+
+static void incr_console(void)
+{
+}
+
+static void send_intr(void)
+{
+}
+
+static void scroll_forw(void)
+{
+}
+
+static void scroll_back(void)
+{
+}
+
+static void compose(void)
+{
+  dead_key_next = 1;
+}
+
+int spawnpid, spawnsig;
+
+static void spawn_console(void)
+{
+}
+
+static void SAK(void)
+{
+}
+
+static void do_ignore(unsigned char value, char up_flag)
+{
+}
+
+static void do_null()
+{
+  compute_shiftstate();
+}
+
+static void do_spec(unsigned char value, char up_flag)
+{
+  if (up_flag)
+    return;
+  if (value >= SIZE(spec_fn_table))
+    return;
+
+  if ((kbd->kbdmode == VC_RAW || kbd->kbdmode == VC_MEDIUMRAW) &&
+      !(SPECIALS_ALLOWED_IN_RAW_MODE & (1 << value)))
+    return;
+
+  spec_fn_table[value]();
+}
+
+static void do_lowercase(unsigned char value, char up_flag)
+{
+}
+
+static void do_self(unsigned char value, char up_flag)
+{
+  if (up_flag)
+    return;    /* no action, if this is a key release */
+
+  if (diacr)
+    value = handle_diacr(value);
+
+  if (dead_key_next) {
+    dead_key_next = 0;
+    diacr = value;
+    return;
+  }
+  put_queue(value);
+}
+
+#define A_GRAVE  '`'
+#define A_ACUTE  '\''
+#define A_CFLEX  '^'
+#define A_TILDE  '~'
+#define A_DIAER  '"'
+#define A_CEDIL  ','
+static unsigned char ret_diacr[NR_DEAD] =
+  {A_GRAVE, A_ACUTE, A_CFLEX, A_TILDE, A_DIAER, A_CEDIL };
+
+/* Obsolete - for backwards compatibility only */
+static void do_dead(unsigned char value, char up_flag)
+{
+  value = ret_diacr[value];
+   printk( " do_dead( %X ) ", value );
+  do_dead2(value,up_flag);
+}
+
+/*
+ * Handle dead key. Note that we now may have several
+ * dead keys modifying the same character. Very useful
+ * for Vietnamese.
+ */
+static void do_dead2(unsigned char value, char up_flag)
+{
+  if (up_flag)
+    return;
+  diacr = (diacr ? handle_diacr(value) : value);
+}
+
+/*
+ * We have a combining character DIACR here, followed by the character CH.
+ * If the combination occurs in the table, return the corresponding value.
+ * Otherwise, if CH is a space or equals DIACR, return DIACR.
+ * Otherwise, conclude that DIACR was not combining after all,
+ * queue it and return CH.
+ */
+unsigned char handle_diacr(unsigned char ch)
+{
+  int d = diacr;
+  int i;
+
+  diacr = 0;
+
+  for (i = 0; i < accent_table_size; i++) {
+    if (accent_table[i].diacr == d && accent_table[i].base == ch)
+      return accent_table[i].result;
+  }
+  if (ch == ' ' || ch == d)
+    return d;
+
+  put_queue(d);
+  return ch;
+}
+
+static void do_cons(unsigned char value, char up_flag)
+{
+  if (up_flag)
+    return;
+}
+
+static void do_fn(unsigned char value, char up_flag)
+{
+  if (up_flag)
+    return;
+
+  if (value < SIZE(func_table)) {
+    if (func_table[value])
+      puts_queue(func_table[value]);
+  } else
+    printk( "do_fn called with value=%d\n", value);
+}
+
+static void do_pad(unsigned char value, char up_flag)
+{
+  static const char *pad_chars = "0123456789+-*/\015,.?()";
+  static const char *app_map = "pqrstuvwxylSRQMnnmPQ";
+
+  if (up_flag)
+    return;    /* no action, if this is a key release */
+
+  /* kludge... shift forces cursor/number keys */
+  if (vc_kbd_mode(kbd,VC_APPLIC) && !k_down[KG_SHIFT]) {
+    applkey(app_map[value], 1);
+    return;
+  }
+  if (!vc_kbd_led(kbd,VC_NUMLOCK))
+    switch (value) {
+      case KVAL(K_PCOMMA):
+      case KVAL(K_PDOT):
+        do_fn(KVAL(K_REMOVE), 0);
+        return;
+      case KVAL(K_P0):
+        do_fn(KVAL(K_INSERT), 0);
+        return;
+      case KVAL(K_P1):
+        do_fn(KVAL(K_SELECT), 0);
+        return;
+      case KVAL(K_P2):
+        do_cur(KVAL(K_DOWN), 0);
+        return;
+      case KVAL(K_P3):
+        do_fn(KVAL(K_PGDN), 0);
+        return;
+      case KVAL(K_P4):
+        do_cur(KVAL(K_LEFT), 0);
+        return;
+      case KVAL(K_P6):
+        do_cur(KVAL(K_RIGHT), 0);
+        return;
+      case KVAL(K_P7):
+        do_fn(KVAL(K_FIND), 0);
+        return;
+      case KVAL(K_P8):
+        do_cur(KVAL(K_UP), 0);
+        return;
+      case KVAL(K_P9):
+        do_fn(KVAL(K_PGUP), 0);
+        return;
+      case KVAL(K_P5):
+        applkey('G', vc_kbd_mode(kbd, VC_APPLIC));
+        return;
+    }
+
+  put_queue(pad_chars[value]);
+
+  if (value == KVAL(K_PENTER) && vc_kbd_mode(kbd, VC_CRLF))
+    put_queue(10);
+
+}
+
+static void do_cur(unsigned char value, char up_flag)
+{
+  static const char *cur_chars = "BDCA";
+  if (up_flag)
+    return;
+
+  applkey(cur_chars[value], vc_kbd_mode(kbd,VC_CKMODE));
+}
+
+static void do_shift(unsigned char value, char up_flag)
+{
+  int old_state = shift_state;
+
+  if (rep)
+    return;
+
+  /* Mimic typewriter:
+     a CapsShift key acts like Shift but undoes CapsLock */
+  if (value == KVAL(K_CAPSSHIFT)) {
+    value = KVAL(K_SHIFT);
+    if (!up_flag)
+      clr_vc_kbd_led(kbd, VC_CAPSLOCK);
+  }
+
+  if (up_flag) {
+    /* handle the case that two shift or control
+       keys are depressed simultaneously */
+    if (k_down[value])
+      k_down[value]--;
+  } else
+    k_down[value]++;
+
+  if (k_down[value])
+    shift_state |= (1 << value);
+  else
+    shift_state &= ~ (1 << value);
+
+  /* kludge */
+  if (up_flag && shift_state != old_state && npadch != -1) {
+    if (kbd->kbdmode == VC_UNICODE)
+      to_utf8(npadch & 0xffff);
+    else
+     put_queue(npadch & 0xff);
+    npadch = -1;
+  }
+}
+
+/* called after returning from RAW mode or when changing consoles -
+   recompute k_down[] and shift_state from key_down[] */
+/* maybe called when keymap is undefined, so that shiftkey release is seen */
+void compute_shiftstate(void)
+{
+  int i, j, k, sym, val;
+
+  shift_state = 0;
+  for(i=0; i < SIZE(k_down); i++)
+    k_down[i] = 0;
+
+  for(i=0; i < SIZE(key_down); i++)
+    if(atomic_load(key_down + i)) {  /* skip this word if not a single bit on */
+      k = i*KBD_BITS_PER_ELEMENT;
+      for(j=0; j<KBD_BITS_PER_ELEMENT; j++,k++)
+        if(kbd_test_bit(k, key_down)) {
+    sym = U(plain_map[k]);
+    if(KTYP(sym) == KT_SHIFT) {
+      val = KVAL(sym);
+      if (val == KVAL(K_CAPSSHIFT))
+        val = KVAL(K_SHIFT);
+      k_down[val]++;
+      shift_state |= (1<<val);
+    }
+        }
+    }
+}
+
+static void do_meta(unsigned char value, char up_flag)
+{
+  if (up_flag)
+    return;
+
+  if (vc_kbd_mode(kbd, VC_META)) {
+    put_queue('\033');
+    put_queue(value);
+  } else
+    put_queue(value | 0x80);
+}
+
+static void do_ascii(unsigned char value, char up_flag)
+{
+  int base;
+
+  if (up_flag)
+    return;
+
+  if (value < 10)    /* decimal input of code, while Alt depressed */
+      base = 10;
+  else {       /* hexadecimal input of code, while AltGr depressed */
+      value -= 10;
+      base = 16;
+  }
+
+  if (npadch == -1)
+    npadch = value;
+  else
+    npadch = npadch * base + value;
+}
+
+static void do_lock(unsigned char value, char up_flag)
+{
+  if (up_flag || rep)
+    return;
+  chg_vc_kbd_lock(kbd, value);
+}
+
+static void do_slock(unsigned char value, char up_flag)
+{
+  if (up_flag || rep)
+    return;
+
+  chg_vc_kbd_slock(kbd, value);
+}
+
+/*
+ * The leds display either (i) the status of NumLock, CapsLock, ScrollLock,
+ * or (ii) whatever pattern of lights people want to show using KDSETLED,
+ * or (iii) specified bits of specified words in kernel memory.
+ */
+
+static unsigned char ledstate = 0xff; /* undefined */
+static unsigned char ledioctl;
+
+unsigned char getledstate(void) {
+  return ledstate;
+}
+
+void setledstate(struct kbd_struct *kbd, unsigned int led) {
+  if (!(led & ~7)) {
+    ledioctl = led;
+     kbd->ledmode = LED_SHOW_IOCTL;
+  } else
+    ;
+  kbd->ledmode = LED_SHOW_FLAGS;
+  set_leds();
+}
+
+static struct ledptr {
+  unsigned int *addr;
+  unsigned int mask;
+  unsigned char valid:1;
+} ledptrs[3];
+
+void register_leds(
+  int console,
+  unsigned int led,
+  unsigned int *addr,
+  unsigned int mask
+)
+{
+  struct kbd_struct *kbd = kbd_table + console;
+
+  if (led < 3) {
+    ledptrs[led].addr = addr;
+    ledptrs[led].mask = mask;
+    ledptrs[led].valid = 1;
+    kbd->ledmode = LED_SHOW_MEM;
+  } else
+    kbd->ledmode = LED_SHOW_FLAGS;
+}
+
+static inline unsigned char getleds(void)
+{
+
+    struct kbd_struct *kbd = kbd_table + fg_console;
+
+    unsigned char leds;
+
+    if (kbd->ledmode == LED_SHOW_IOCTL)
+      return ledioctl;
+    leds = kbd->ledflagstate;
+    if (kbd->ledmode == LED_SHOW_MEM) {
+  if (ledptrs[0].valid) {
+      if (*ledptrs[0].addr & ledptrs[0].mask)
+        leds |= 1;
+      else
+        leds &= ~1;
+  }
+  if (ledptrs[1].valid) {
+      if (*ledptrs[1].addr & ledptrs[1].mask)
+        leds |= 2;
+      else
+        leds &= ~2;
+  }
+  if (ledptrs[2].valid) {
+      if (*ledptrs[2].addr & ledptrs[2].mask)
+        leds |= 4;
+      else
+        leds &= ~4;
+  }
+    }
+   return leds;
+}
+
+/*
+ * This routine is the bottom half of the keyboard interrupt
+ * routine, and runs with all interrupts enabled. It does
+ * console changing, led setting and copy_to_cooked, which can
+ * take a reasonably long time.
+ *
+ * Aside from timing (which isn't really that important for
+ * keyboard interrupts as they happen often), using the software
+ * interrupt routines for this thing allows us to easily mask
+ * this when we don't want any of the above to happen. Not yet
+ * used, but this allows for easy and efficient race-condition
+ * prevention later on.
+ */
+static void kbd_bh(void)
+{
+  unsigned char leds = getleds();
+  if (leds != ledstate) {
+    ledstate = leds;
+    kbd_leds(leds);
+  }
+}
+
+void set_leds(void)
+{
+  kbd_bh();
+}
+
+int kbd_init(void)
+{
+
+  int i;
+  struct kbd_struct kbd0;
+  kbd0.ledflagstate = kbd0.default_ledflagstate = KBD_DEFLEDS;
+   kbd0.ledmode = LED_SHOW_MEM;
+  kbd0.lockstate = KBD_DEFLOCK;
+  kbd0.slockstate = 0;
+  kbd0.modeflags = KBD_DEFMODE;
+  kbd0.kbdmode = VC_XLATE;
+
+  for (i = 0 ; i < MAX_NR_CONSOLES ; i++)
+    kbd_table[i] = kbd0;
+
+  kbd_init_hw();
+  mark_bh(KEYBOARD_BH);
+  return 0;
+}
Index: bsps/i386/pc386/console/outch.c
===================================================================
--- bsps/i386/pc386/console/outch.c	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
+++ bsps/i386/pc386/console/outch.c	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
@@ -0,0 +1,328 @@
+/*
+ * outch.c  - This file contains code for displaying characters
+ *	      on the console uisng information that should be
+ *	      maintained by the BIOS in its data Area.
+ *
+ * Copyright (C) 1998  Eric Valette (valette@crf.canon.fr)
+ *                     Canon Centre Recherche France.
+ *
+ *  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.
+ *
+ * Till Straumann <strauman@slac.stanford.edu>, 2003/9:
+ *  - added handling of basic escape sequences (cursor movement
+ *    and erasing; just enough for the line editor 'libtecla' to
+ *    work...)
+ */
+
+#include <bsp.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <crt.h>
+
+extern void wr_cursor(int, unsigned short);
+
+#define TAB_SPACE 4
+static unsigned short *bitMapBaseAddr;
+static unsigned short ioCrtBaseAddr;
+static unsigned short maxCol;
+static unsigned short maxRow;
+static unsigned char  row;
+static unsigned char  column;
+static unsigned short attribute;
+static unsigned int   nLines;
+
+static void
+scroll(void)
+{
+    int i, j;				    /* Counters	*/
+    unsigned short *pt_scroll, *pt_bitmap;  /* Pointers on the bit-map	*/
+
+    pt_bitmap = bitMapBaseAddr;
+    j = 0;
+    pt_bitmap = pt_bitmap + j;
+    pt_scroll = pt_bitmap + maxCol;
+    for (i = j; i < (maxRow - 1) * maxCol; i++) {
+	*pt_bitmap++ = *pt_scroll++;
+    }
+
+    /*
+     * Blank characters are displayed on the last line.
+     */
+    for (i = 0; i < maxCol; i++) {
+	*pt_bitmap++ = (short) (' ' | attribute);
+    }
+}
+
+static void
+doCRNL(int cr, int nl)
+{
+	if (nl) {
+    if (++row == maxRow) {
+	scroll(); 	/* Scroll the screen now */
+	row = maxRow - 1;
+    }
+    nLines++;
+	}
+	if (cr)
+    	column = 0;
+    /* Move cursor on the next location  */
+	if (cr || nl)
+    	wr_cursor(row * maxCol + column, ioCrtBaseAddr);
+}
+
+int (*videoHook)(char, int *)=0;
+
+static void
+advanceCursor(void)
+{
+  if (++column == maxCol)
+	doCRNL(1,1);
+  else
+	wr_cursor(row * maxCol + column, ioCrtBaseAddr);
+}
+
+static void
+gotorc(int r, int c)
+{
+	column = c;
+	row    = r;
+
+  	wr_cursor(row * maxCol + column, ioCrtBaseAddr);
+}
+
+#define ESC		((char)27)
+/* erase current location without moving the cursor */
+#define BLANK	((char)0x7f)
+
+static void
+videoPutChar(char car)
+{
+    unsigned short *pt_bitmap = bitMapBaseAddr + row * maxCol + column;
+
+    switch (car) {
+    case '\b': {
+	    if (column) column--;
+	    /* Move cursor on the previous location  */
+	    wr_cursor(row * maxCol + column, ioCrtBaseAddr);
+	    return;
+	}
+	case '\t': {
+	    int i;
+
+	    i = TAB_SPACE - (column & (TAB_SPACE - 1));
+	    column += i;
+	    if (column >= maxCol) {
+		doCRNL(1,1);
+		return;
+	    }
+	    while (i--)	*pt_bitmap++ = ' ' | attribute;
+	    wr_cursor(row * maxCol + column, ioCrtBaseAddr);
+	    return;
+	}
+	case '\n': {
+	    doCRNL(0,1);
+	    return;
+	}
+    case 7:		{	/* Bell code must be inserted here */
+	    return;
+	}
+	case '\r' : {
+		doCRNL(1,0);
+	    return;
+	}
+	case BLANK: {
+	    *pt_bitmap = ' ' | attribute;
+		/* DONT move the cursor... */
+		return;
+	}
+   	default: {
+	    *pt_bitmap = (unsigned char)car | attribute;
+		advanceCursor();
+	    return;
+	}
+    }
+}
+
+/* trivial state machine to handle escape sequences:
+ *
+ *                    ---------------------------------
+ *                   |                                 |
+ *                   |                                 |
+ * KEY:        esc   V    [          DCABHKJ       esc |
+ * STATE:   0 -----> 27 -----> '[' ----------> -1 -----
+ *          ^\        \          \               \
+ * KEY:     | \other   \ other    \ other         \ other
+ *           <-------------------------------------
+ *
+ * in state '-1', the DCABHKJ cases are handled
+ *
+ * (cursor motion and screen clearing)
+ */
+
+#define DONE  (-1)
+
+static int
+handleEscape(int oldState, char car)
+{
+int rval = 0;
+int ro,co;
+
+	switch ( oldState ) {
+		case DONE:	/*  means the previous char terminated an ESC sequence... */
+		case 0:
+			if ( 27 == car ) {
+				rval = 27;	 /* START of an ESC sequence */
+			}
+		break;
+
+		case 27:
+			if ( '[' == car ) {
+				rval = car;  /* received ESC '[', so far */
+			} else {
+				/* dump suppressed 'ESC'; outch will append the char */
+				videoPutChar(ESC);
+			}
+		break;
+
+		case '[':
+			/* handle 'ESC' '[' sequences here */
+			ro = row; co = column;
+			rval = DONE; /* done */
+
+			switch (car) {
+				case 'D': /* left */
+					if ( co > 0 )      co--;
+				break;
+				case 'C': /* right */
+					if ( co < maxCol ) co++;
+				break;
+				case 'A': /* up    */
+					if ( ro > 0 )      ro--;
+				break;
+				case 'B': /* down */
+					if ( ro < maxRow ) ro++;
+				break;
+				case 'H': /* home */
+					ro = co = 0;
+				break;
+				case 'K': /* clear to end of line */
+					while ( column < maxCol - 1 )
+                		videoPutChar(' ');
+            		videoPutChar(BLANK);
+        		break;
+        		case 'J': /* clear to end of screen */
+					while (  ((row < maxRow-1) || (column < maxCol-1)) )
+						videoPutChar(' ');
+					videoPutChar(BLANK);
+        		break;
+        		default:
+            		videoPutChar(ESC);
+            		videoPutChar('[');
+					/* DONT move the cursor */
+					ro   = -1;
+					rval = 0;
+        		break;
+			}
+			/* reset cursor */
+			if ( ro >= 0)
+				gotorc(ro,co);
+
+		default:
+		break;
+
+	}
+
+	return rval;
+}
+
+static void
+clear_screen(void)
+{
+    int i,j;
+
+    for (j = 0; j <= maxRow; j++) {
+      for (i = 0; i <= maxCol; i++) {
+	videoPutChar(' ');
+      }
+    }
+    column  = 0;
+    row     = 0;
+}
+
+/*-------------------------------------------------------------------------+
+|         Function: _IBMPC_outch
+|      Description: Higher level (console) interface to consPutc.
+| Global Variables: None.
+|        Arguments: c - character to write to console.
+|          Returns: Nothing.
++--------------------------------------------------------------------------*/
+void
+_IBMPC_outch(char c)
+{
+static int escaped = 0;
+
+  if ( ! (escaped = handleEscape(escaped, c)) ) {
+    if ( '\n' == c )
+      videoPutChar('\r');
+  	videoPutChar(c);
+  }
+} /* _IBMPC_outch */
+
+/*-------------------------------------------------------------------------+
+|         Function: _IBMPC_initVideo
+|      Description: Video system initialization. Hook for any early setup.
+| Global Variables: bitMapBaseAddr, ioCrtBaseAddr, maxCol, maxRow, row
+|		    column, attribute, nLines;
+|        Arguments: None.
+|          Returns: Nothing.
++--------------------------------------------------------------------------*/
+void
+_IBMPC_initVideo(void)
+{
+    unsigned char* pt = (unsigned char*) (VIDEO_MODE_ADDR);
+
+    if (*pt == VGAMODE7) {
+      bitMapBaseAddr = (unsigned short*) V_MONO;
+    }
+    else {
+      bitMapBaseAddr = (unsigned short*) V_COLOR;
+    }
+    ioCrtBaseAddr = *(unsigned short*) DISPLAY_CRT_BASE_IO_ADDR;
+    maxCol  = * (unsigned short*) NB_MAX_COL_ADDR;
+    maxRow  = * (unsigned char*)  NB_MAX_ROW_ADDR;
+    column  = 0;
+    row     = 0;
+    attribute = ((BLACK << 4) | WHITE)<<8;
+    nLines = 0;
+    clear_screen();
+#ifdef DEBUG_EARLY_STAGE
+    printk("bitMapBaseAddr = %X, display controller base IO = %X\n",
+	   (unsigned) bitMapBaseAddr,
+	   (unsigned) ioCrtBaseAddr);
+    videoPrintf("maxCol = %d, maxRow = %d\n", (unsigned) maxCol, (unsigned) maxRow);
+#endif
+} /* _IBMPC_initVideo */
+
+/* for old DOS compatibility n-curses type of applications */
+void gotoxy( int x, int y );
+int whereX( void );
+int whereY( void );
+
+void gotoxy( int x, int y )
+{
+  gotorc(y,x);
+}
+
+int whereX( void )
+{
+  return row;
+}
+
+int whereY( void )
+{
+  return column;
+}
Index: bsps/i386/pc386/console/pc_keyb.c
===================================================================
--- bsps/i386/pc386/console/pc_keyb.c	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
+++ bsps/i386/pc386/console/pc_keyb.c	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
@@ -0,0 +1,627 @@
+/*
+ * linux/drivers/char/pc_keyb.c
+ *
+ * Separation of the PC low-level part by Geert Uytterhoeven, May 1997
+ * See keyboard.c for the whole history.
+ *
+ * Major cleanup by Martin Mares, May 1997
+ *
+ * Combined the keyboard and PS/2 mouse handling into one file,
+ * because they share the same hardware.
+ * Johan Myreen <jem@iki.fi> 1998-10-08.
+ *
+ * Code fixes to handle mouse ACKs properly.
+ * C. Scott Ananian <cananian@alumni.princeton.edu> 1999-01-29.
+ *
+ * Ported to RTEMS by Rosimildo da Silva
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include <bsp.h>
+#include <rtems/keyboard.h>
+#include "i386kbd.h"
+
+static unsigned char handle_kbd_event(void);
+static void kbd_write_command_w(int data);
+static void kbd_write_output_w(int data);
+
+/* Some configuration switches are present in the include file... */
+
+/* Simple translation table for the SysRq keys */
+
+#ifdef CONFIG_MAGIC_SYSRQ
+unsigned char pckbd_sysrq_xlate[128] =
+	"\000\0331234567890-=\177\t"			/* 0x00 - 0x0f */
+	"qwertyuiop[]\r\000as"				/* 0x10 - 0x1f */
+	"dfghjkl;'`\000\\zxcv"				/* 0x20 - 0x2f */
+	"bnm,./\000*\000 \000\201\202\203\204\205"	/* 0x30 - 0x3f */
+	"\206\207\210\211\212\000\000789-456+1"		/* 0x40 - 0x4f */
+	"230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
+	"\r\000/";					/* 0x60 - 0x6f */
+#endif
+
+/* used only by send_data - set by keyboard_interrupt */
+static volatile unsigned char reply_expected = 0;
+static volatile unsigned char acknowledge = 0;
+static volatile unsigned char resend = 0;
+
+/*
+ * Translation of escaped scancodes to keycodes.
+ * This is now user-settable.
+ * The keycodes 1-88,96-111,119 are fairly standard, and
+ * should probably not be changed - changing might confuse X.
+ * X also interprets scancode 0x5d (KEY_Begin).
+ *
+ * For 1-88 keycode equals scancode.
+ */
+
+#define E0_KPENTER 96
+#define E0_RCTRL   97
+#define E0_KPSLASH 98
+#define E0_PRSCR   99
+#define E0_RALT    100
+#define E0_BREAK   101  /* (control-pause) */
+#define E0_HOME    102
+#define E0_UP      103
+#define E0_PGUP    104
+#define E0_LEFT    105
+#define E0_RIGHT   106
+#define E0_END     107
+#define E0_DOWN    108
+#define E0_PGDN    109
+#define E0_INS     110
+#define E0_DEL     111
+
+#define E1_PAUSE   119
+
+/*
+ * The keycodes below are randomly located in 89-95,112-118,120-127.
+ * They could be thrown away (and all occurrences below replaced by 0),
+ * but that would force many users to use the `setkeycodes' utility, where
+ * they needed not before. It does not matter that there are duplicates, as
+ * long as no duplication occurs for any single keyboard.
+ */
+#define SC_LIM 89
+
+#define FOCUS_PF1 85           /* actual code! */
+#define FOCUS_PF2 89
+#define FOCUS_PF3 90
+#define FOCUS_PF4 91
+#define FOCUS_PF5 92
+#define FOCUS_PF6 93
+#define FOCUS_PF7 94
+#define FOCUS_PF8 95
+#define FOCUS_PF9 120
+#define FOCUS_PF10 121
+#define FOCUS_PF11 122
+#define FOCUS_PF12 123
+
+#define JAP_86     124
+/* tfj@olivia.ping.dk:
+ * The four keys are located over the numeric keypad, and are
+ * labelled A1-A4. It's an rc930 keyboard, from
+ * Regnecentralen/RC International, Now ICL.
+ * Scancodes: 59, 5a, 5b, 5c.
+ */
+#define RGN1 124
+#define RGN2 125
+#define RGN3 126
+#define RGN4 127
+
+static unsigned char high_keys[128 - SC_LIM] = {
+  RGN1, RGN2, RGN3, RGN4, 0, 0, 0,                   /* 0x59-0x5f */
+  0, 0, 0, 0, 0, 0, 0, 0,                            /* 0x60-0x67 */
+  0, 0, 0, 0, 0, FOCUS_PF11, 0, FOCUS_PF12,          /* 0x68-0x6f */
+  0, 0, 0, FOCUS_PF2, FOCUS_PF9, 0, 0, FOCUS_PF3,    /* 0x70-0x77 */
+  FOCUS_PF4, FOCUS_PF5, FOCUS_PF6, FOCUS_PF7,        /* 0x78-0x7b */
+  FOCUS_PF8, JAP_86, FOCUS_PF10, 0                   /* 0x7c-0x7f */
+};
+
+/* BTC */
+#define E0_MACRO   112
+/* LK450 */
+#define E0_F13     113
+#define E0_F14     114
+#define E0_HELP    115
+#define E0_DO      116
+#define E0_F17     117
+#define E0_KPMINPLUS 118
+/*
+ * My OmniKey generates e0 4c for  the "OMNI" key and the
+ * right alt key does nada. [kkoller@nyx10.cs.du.edu]
+ */
+#define E0_OK	124
+/*
+ * New microsoft keyboard is rumoured to have
+ * e0 5b (left window button), e0 5c (right window button),
+ * e0 5d (menu button). [or: LBANNER, RBANNER, RMENU]
+ * [or: Windows_L, Windows_R, TaskMan]
+ */
+#define E0_MSLW	125
+#define E0_MSRW	126
+#define E0_MSTM	127
+
+static unsigned char e0_keys[128] = {
+  0, 0, 0, 0, 0, 0, 0, 0,			      /* 0x00-0x07 */
+  0, 0, 0, 0, 0, 0, 0, 0,			      /* 0x08-0x0f */
+  0, 0, 0, 0, 0, 0, 0, 0,			      /* 0x10-0x17 */
+  0, 0, 0, 0, E0_KPENTER, E0_RCTRL, 0, 0,	      /* 0x18-0x1f */
+  0, 0, 0, 0, 0, 0, 0, 0,			      /* 0x20-0x27 */
+  0, 0, 0, 0, 0, 0, 0, 0,			      /* 0x28-0x2f */
+  0, 0, 0, 0, 0, E0_KPSLASH, 0, E0_PRSCR,	      /* 0x30-0x37 */
+  E0_RALT, 0, 0, 0, 0, E0_F13, E0_F14, E0_HELP,	      /* 0x38-0x3f */
+  E0_DO, E0_F17, 0, 0, 0, 0, E0_BREAK, E0_HOME,	      /* 0x40-0x47 */
+  E0_UP, E0_PGUP, 0, E0_LEFT, E0_OK, E0_RIGHT, E0_KPMINPLUS, E0_END,/* 0x48-0x4f */
+  E0_DOWN, E0_PGDN, E0_INS, E0_DEL, 0, 0, 0, 0,	      /* 0x50-0x57 */
+  0, 0, 0, E0_MSLW, E0_MSRW, E0_MSTM, 0, 0,	      /* 0x58-0x5f */
+  0, 0, 0, 0, 0, 0, 0, 0,			      /* 0x60-0x67 */
+  0, 0, 0, 0, 0, 0, 0, E0_MACRO,		      /* 0x68-0x6f */
+  0, 0, 0, 0, 0, 0, 0, 0,			      /* 0x70-0x77 */
+  0, 0, 0, 0, 0, 0, 0, 0			      /* 0x78-0x7f */
+};
+
+static void mdelay( unsigned long t )
+{
+   Wait_X_ms( t );
+}
+
+int pckbd_setkeycode(unsigned int scancode, unsigned int keycode)
+{
+	if (scancode < SC_LIM || scancode > 255 || keycode > 127)
+	  return -EINVAL;
+	if (scancode < 128)
+	  high_keys[scancode - SC_LIM] = keycode;
+	else
+	  e0_keys[scancode - 128] = keycode;
+	return 0;
+}
+
+int pckbd_getkeycode(unsigned int scancode)
+{
+	return
+	  (scancode < SC_LIM || scancode > 255) ? -EINVAL :
+	  (scancode < 128) ? high_keys[scancode - SC_LIM] :
+	    e0_keys[scancode - 128];
+}
+
+static int do_acknowledge(unsigned char scancode)
+{
+	if (reply_expected) {
+	  /* Unfortunately, we must recognise these codes only if we know they
+	   * are known to be valid (i.e., after sending a command), because there
+	   * are some brain-damaged keyboards (yes, FOCUS 9000 again) which have
+	   * keys with such codes :(
+	   */
+		if (scancode == KBD_REPLY_ACK) {
+			acknowledge = 1;
+			reply_expected = 0;
+			return 0;
+		} else if (scancode == KBD_REPLY_RESEND) {
+			resend = 1;
+			reply_expected = 0;
+			return 0;
+		}
+		/* Should not happen... */
+		printk( "keyboard reply expected - got %02x\n", scancode);
+	}
+	return 1;
+}
+
+int pckbd_translate(unsigned char scancode, unsigned char *keycode,
+		    char raw_mode)
+{
+	static int prev_scancode = 0;
+
+	/* special prefix scancodes.. */
+	if (scancode == 0xe0 || scancode == 0xe1) {
+		prev_scancode = scancode;
+		return 0;
+	}
+
+	/* 0xFF is sent by a few keyboards, ignore it. 0x00 is error */
+	if (scancode == 0x00 || scancode == 0xff) {
+		prev_scancode = 0;
+		return 0;
+	}
+
+	scancode &= 0x7f;
+
+	if (prev_scancode) {
+	  /*
+	   * usually it will be 0xe0, but a Pause key generates
+	   * e1 1d 45 e1 9d c5 when pressed, and nothing when released
+	   */
+	  if (prev_scancode != 0xe0) {
+	      if (prev_scancode == 0xe1 && scancode == 0x1d) {
+		  prev_scancode = 0x100;
+		  return 0;
+	      } else if (prev_scancode == 0x100 && scancode == 0x45) {
+		  *keycode = E1_PAUSE;
+		  prev_scancode = 0;
+	      } else {
+#ifdef KBD_REPORT_UNKN
+		  if (!raw_mode)
+		    printk("keyboard: unknown e1 escape sequence\n");
+#endif
+		  prev_scancode = 0;
+		  return 0;
+	      }
+	  } else {
+	      prev_scancode = 0;
+	      /*
+	       *  The keyboard maintains its own internal caps lock and
+	       *  num lock statuses. In caps lock mode E0 AA precedes make
+	       *  code and E0 2A follows break code. In num lock mode,
+	       *  E0 2A precedes make code and E0 AA follows break code.
+	       *  We do our own book-keeping, so we will just ignore these.
+	       */
+	      /*
+	       *  For my keyboard there is no caps lock mode, but there are
+	       *  both Shift-L and Shift-R modes. The former mode generates
+	       *  E0 2A / E0 AA pairs, the latter E0 B6 / E0 36 pairs.
+	       *  So, we should also ignore the latter. - aeb@cwi.nl
+	       */
+	      if (scancode == 0x2a || scancode == 0x36)
+		return 0;
+
+	      if (e0_keys[scancode])
+		*keycode = e0_keys[scancode];
+	      else {
+#ifdef KBD_REPORT_UNKN
+		  if (!raw_mode)
+		    printk( "keyboard: unknown scancode e0 %02x\n",
+			   scancode);
+#endif
+		  return 0;
+	      }
+	  }
+	} else if (scancode >= SC_LIM) {
+	    /* This happens with the FOCUS 9000 keyboard
+	       Its keys PF1..PF12 are reported to generate
+	       55 73 77 78 79 7a 7b 7c 74 7e 6d 6f
+	       Moreover, unless repeated, they do not generate
+	       key-down events, so we have to zero up_flag below */
+	    /* Also, Japanese 86/106 keyboards are reported to
+	       generate 0x73 and 0x7d for \ - and \ | respectively. */
+	    /* Also, some Brazilian keyboard is reported to produce
+	       0x73 and 0x7e for \ ? and KP-dot, respectively. */
+
+	  *keycode = high_keys[scancode - SC_LIM];
+	  if (!*keycode) {
+	      if (!raw_mode) {
+#ifdef KBD_REPORT_UNKN
+		  printk( "keyboard: unrecognized scancode (%02x)"
+			 " - ignored\n", scancode);
+#endif
+	      }
+	      return 0;
+	  }
+ 	} else
+	  *keycode = scancode;
+ 	return 1;
+}
+
+char pckbd_unexpected_up(unsigned char keycode)
+{
+	/* unexpected, but this can happen: maybe this was a key release for a
+	   FOCUS 9000 PF key; if we want to see it, we have to clear up_flag */
+	if (keycode >= SC_LIM || keycode == 85)
+	    return 0;
+	else
+	    return 0200;
+}
+
+static void kb_wait(void)
+{
+	unsigned long timeout = KBC_TIMEOUT;
+
+	do {
+		/*
+		 * "handle_kbd_event()" will handle any incoming events
+		 * while we wait - keypresses or mouse movement.
+		 */
+		unsigned char status = handle_kbd_event();
+
+		if (! (status & KBD_STAT_IBF))
+			return;
+		mdelay(1);
+		timeout--;
+	} while (timeout);
+#ifdef KBD_REPORT_TIMEOUTS
+	printk( "Keyboard timed out[1]\n");
+#endif
+}
+
+/*
+ * This reads the keyboard status port, and does the
+ * appropriate action.
+ *
+ * It requires that we hold the keyboard controller
+ * spinlock.
+ */
+static unsigned char handle_kbd_event(void)
+{
+	unsigned char status = kbd_read_status();
+	unsigned int work = 10000;
+
+	while (status & KBD_STAT_OBF) {
+		unsigned char scancode;
+
+		scancode = kbd_read_input();
+		if (status & KBD_STAT_MOUSE_OBF) {
+#if 0
+			handle_mouse_event(scancode);
+#endif
+		} else {
+			if (do_acknowledge(scancode))
+				handle_scancode(scancode, !(scancode & 0x80));
+			mark_bh(KEYBOARD_BH);
+		}
+
+		status = kbd_read_status();
+
+		if(!work--)
+		{
+			printk( "pc_keyb: controller jammed (0x%02X).\n", status);
+			break;
+		}
+      return status;
+	}
+
+   /*
+    * the commands to set the leds for some reason, returns 0x14, 0x16
+    * and I am intepreting as an ACK, because the original code from
+    * Linux was timeing out here...
+    */
+	acknowledge = 1;
+	reply_expected = 0;
+	resend = 0;
+	return status;
+}
+
+void keyboard_interrupt(void *unused)
+{
+	handle_kbd_event();
+}
+
+/*
+ * send_data sends a character to the keyboard and waits
+ * for an acknowledge, possibly retrying if asked to. Returns
+ * the success status.
+ *
+ * Don't use 'jiffies', so that we don't depend on interrupts
+ */
+static int send_data(unsigned char data)
+{
+	int retries = 3;
+
+	do {
+		unsigned long timeout = KBD_TIMEOUT;
+
+		acknowledge = 0; /* Set by interrupt routine on receipt of ACK. */
+		resend = 0;
+		reply_expected = 1;
+		kbd_write_output_w(data);
+		for (;;) {
+			if (acknowledge)
+				return 1;
+			if (resend)
+				break;
+			mdelay(1);
+			if (!--timeout) {
+#ifdef KBD_REPORT_TIMEOUTS
+				printk("Keyboard timeout[2]\n");
+#endif
+				return 0;
+			}
+		}
+	} while (retries-- > 0);
+#ifdef KBD_REPORT_TIMEOUTS
+	printk( "keyboard: Too many NACKs -- noisy kbd cable?\n");
+#endif
+	return 0;
+}
+
+void pckbd_leds(unsigned char leds)
+{
+	if (!send_data(KBD_CMD_SET_LEDS) || !send_data(leds))
+	    send_data(KBD_CMD_ENABLE);	/* re-enable kbd if any errors */
+}
+
+/*
+ * In case we run on a non-x86 hardware we need to initialize both the
+ * keyboard controller and the keyboard.  On a x86, the BIOS will
+ * already have initialized them.
+ *
+ * Some x86 BIOSes do not correctly initialize the keyboard, so the
+ * "kbd-reset" command line options can be given to force a reset.
+ * [Ranger]
+ */
+#ifdef __i386__
+ int kbd_startup_reset = 0;
+#else
+ int kbd_startup_reset = 1;
+#endif
+
+/* for "kbd-reset" cmdline param */
+void kbd_reset_setup(char *str, int *ints)
+{
+	kbd_startup_reset = 1;
+}
+
+#define KBD_NO_DATA	(-1)	/* No data */
+#define KBD_BAD_DATA	(-2)	/* Parity or other error */
+
+static int kbd_read_data(void)
+{
+	int retval = KBD_NO_DATA;
+	unsigned char status;
+
+	status = kbd_read_status();
+	if (status & KBD_STAT_OBF) {
+		unsigned char data = kbd_read_input();
+
+		retval = data;
+		if (status & (KBD_STAT_GTO | KBD_STAT_PERR))
+			retval = KBD_BAD_DATA;
+	}
+	return retval;
+}
+
+static void kbd_clear_input(void)
+{
+	int maxread = 100;	/* Random number */
+
+	do {
+		if (kbd_read_data() == KBD_NO_DATA)
+			break;
+	} while (--maxread);
+}
+
+static int kbd_wait_for_input(void)
+{
+	long timeout = KBD_INIT_TIMEOUT;
+
+	do {
+		int retval = kbd_read_data();
+		if (retval >= 0)
+			return retval;
+		mdelay(1);
+	} while (--timeout);
+	return -1;
+}
+
+static void kbd_write_command_w(int data)
+{
+	kb_wait();
+	kbd_write_command(data);
+}
+
+static void kbd_write_output_w(int data)
+{
+	kb_wait();
+	kbd_write_output(data);
+}
+
+static char * initialize_kbd(void)
+{
+	int status;
+
+	/*
+	 * Test the keyboard interface.
+	 * This seems to be the only way to get it going.
+	 * If the test is successful a x55 is placed in the input buffer.
+	 */
+	kbd_write_command_w(KBD_CCMD_SELF_TEST);
+	if (kbd_wait_for_input() != 0x55)
+		return "Keyboard failed self test";
+
+	/*
+	 * Perform a keyboard interface test.  This causes the controller
+	 * to test the keyboard clock and data lines.  The results of the
+	 * test are placed in the input buffer.
+	 */
+	kbd_write_command_w(KBD_CCMD_KBD_TEST);
+	if (kbd_wait_for_input() != 0x00)
+		return "Keyboard interface failed self test";
+
+	/*
+	 * Enable the keyboard by allowing the keyboard clock to run.
+	 */
+	kbd_write_command_w(KBD_CCMD_KBD_ENABLE);
+
+	/*
+	 * Reset keyboard. If the read times out
+	 * then the assumption is that no keyboard is
+	 * plugged into the machine.
+	 * This defaults the keyboard to scan-code set 2.
+	 *
+	 * Set up to try again if the keyboard asks for RESEND.
+	 */
+	do {
+		kbd_write_output_w(KBD_CMD_RESET);
+		status = kbd_wait_for_input();
+		if (status == KBD_REPLY_ACK)
+			break;
+		if (status != KBD_REPLY_RESEND)
+			return "Keyboard reset failed, no ACK";
+	} while (1);
+
+	if (kbd_wait_for_input() != KBD_REPLY_POR)
+		return "Keyboard reset failed, no POR";
+
+	/*
+	 * Set keyboard controller mode. During this, the keyboard should be
+	 * in the disabled state.
+	 *
+	 * Set up to try again if the keyboard asks for RESEND.
+	 */
+	do {
+		kbd_write_output_w(KBD_CMD_DISABLE);
+		status = kbd_wait_for_input();
+		if (status == KBD_REPLY_ACK)
+			break;
+		if (status != KBD_REPLY_RESEND)
+			return "Disable keyboard: no ACK";
+	} while (1);
+
+	kbd_write_command_w(KBD_CCMD_WRITE_MODE);
+	kbd_write_output_w(KBD_MODE_KBD_INT
+			      | KBD_MODE_SYS
+			      | KBD_MODE_DISABLE_MOUSE
+			      | KBD_MODE_KCC);
+
+	/* ibm powerpc portables need this to use scan-code set 1 -- Cort */
+	kbd_write_command_w(KBD_CCMD_READ_MODE);
+	if (!(kbd_wait_for_input() & KBD_MODE_KCC)) {
+		/*
+		 * If the controller does not support conversion,
+		 * Set the keyboard to scan-code set 1.
+		 */
+		kbd_write_output_w(0xF0);
+		kbd_wait_for_input();
+		kbd_write_output_w(0x01);
+		kbd_wait_for_input();
+	}
+
+	kbd_write_output_w(KBD_CMD_ENABLE);
+	if (kbd_wait_for_input() != KBD_REPLY_ACK)
+		return "Enable keyboard: no ACK";
+	/*
+	 * Finally, set the typematic rate to maximum.
+	 */
+	kbd_write_output_w(KBD_CMD_SET_RATE);
+	if (kbd_wait_for_input() != KBD_REPLY_ACK)
+		return "Set rate: no ACK";
+	kbd_write_output_w(0x00);
+	if (kbd_wait_for_input() != KBD_REPLY_ACK)
+		return "Set rate: no ACK";
+	return NULL;
+}
+
+void pckbd_init_hw(void)
+{
+	/* kbd_request_region();  */
+
+	/*  Flush any pending input. */
+	kbd_clear_input();
+
+	if (kbd_startup_reset) {
+		char *msg = initialize_kbd();
+		if (msg)
+			printk( "initialize_kbd: %s\n", msg);
+	}
+
+#if defined CONFIG_PSMOUSE
+	psaux_init();
+#endif
+
+	/* Ok, finally allocate the IRQ, and off we go.. */
+#if 0
+	kbd_request_irq( keyboard_interrupt );
+#endif
+
+}
Index: bsps/i386/pc386/console/printk_support.c
===================================================================
--- bsps/i386/pc386/console/printk_support.c	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
+++ bsps/i386/pc386/console/printk_support.c	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
@@ -0,0 +1,84 @@
+/*
+ * @file
+ *
+ * @ingroup Console
+ *
+ * @brief printk support routines
+ *
+ * This file contains the required printk support.
+ */
+
+/*
+ *  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 <rtems.h>
+#include <rtems/bspIo.h>
+#if BSP_ENABLE_VGA
+  #include <rtems/keyboard.h>
+#endif
+#include <bsp.h>
+#include <libchip/serial.h>
+#include <libchip/ns16550.h>
+#include "../../shared/dev/serial/legacy-console.h"
+
+rtems_device_minor_number BSPPrintkPort = 0;
+
+void BSP_outch(char ch);
+int BSP_inch(void);
+
+void BSP_outch(char ch)
+{
+  #if BSP_ENABLE_VGA
+    bool isVga =  BSPPrintkPort == BSP_CONSOLE_VGA;
+  #else
+    bool isVga = false;
+  #endif
+
+  if ( !isVga ) {
+    console_tbl *port = Console_Port_Tbl[BSPPrintkPort];
+    if (port->pDeviceFns && port->pDeviceFns->deviceWritePolled) {
+      port->pDeviceFns->deviceWritePolled( BSPPrintkPort, ch );
+    }
+    return;
+  }
+
+  #if BSP_ENABLE_VGA
+    _IBMPC_outch( ch );
+  #endif
+}
+
+int BSP_inch(void)
+{
+  #if BSP_ENABLE_VGA
+    bool isVga =  BSPPrintkPort == BSP_CONSOLE_VGA;
+  #else
+    bool isVga = false;
+  #endif
+
+  int result = -1;
+
+  if ( !isVga ) {
+    console_tbl *port = Console_Port_Tbl[BSPPrintkPort];
+    if (port->pDeviceFns && port->pDeviceFns->deviceRead) {
+      do {
+        result = port->pDeviceFns->deviceRead( BSPPrintkPort );
+      } while (result == -1);
+      return result;
+    }
+  }
+
+  #if BSP_ENABLE_VGA
+    result = BSP_wait_polled_input();
+  #endif
+
+  return result;
+}
+
+BSP_output_char_function_type     BSP_output_char = BSP_outch;
+BSP_polling_getchar_function_type BSP_poll_char = BSP_inch;
Index: bsps/i386/pc386/console/ps2_mouse.c
===================================================================
--- bsps/i386/pc386/console/ps2_mouse.c	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
+++ bsps/i386/pc386/console/ps2_mouse.c	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
@@ -0,0 +1,562 @@
+/*
+ * linux/drivers/char/pc_keyb.c
+ * Separation of the PC low-level part by Geert Uytterhoeven, May 1997
+ * See keyboard.c for the whole history.
+ * Major cleanup by Martin Mares, May 1997
+ * Combined the keyboard and PS/2 mouse handling into one file,
+ * because they share the same hardware.
+ * Johan Myreen <jem@iki.fi> 1998-10-08.
+ * Code fixes to handle mouse ACKs properly.
+ * C. Scott Ananian <cananian@alumni.princeton.edu> 1999-01-29.
+ *
+ *  RTEMS port: by Rosimildo da Silva.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <assert.h>
+
+#include <bsp.h>
+#include <bsp/irq.h>
+#include <rtems/libio.h>
+#include <termios.h>
+#include <i386_io.h>
+#include <rtems/mw_uid.h>
+#include <rtems/mouse_parser.h>
+
+#define  INITIALIZE_MOUSE
+/* Some configuration switches are present in the include file... */
+#include <rtems/ps2_drv.h>
+#include "ps2_mouse.h"
+
+static void kbd_write_command_w(int data);
+#if 0
+static void kbd_write_output_w(int data);
+#endif
+
+static unsigned char handle_kbd_event(void);
+static void ps2_set_driver_handler(int port, mouse_parser_enqueue_handler handler);
+
+/* used only by send_data - set by keyboard_interrupt */
+static volatile unsigned char reply_expected = 0;
+static volatile unsigned char acknowledge = 0;
+static volatile unsigned char resend = 0;
+
+/*
+ *	PS/2 Auxiliary Device
+ */
+static int psaux_init(void);
+
+static struct aux_queue *queue;	/* Mouse data buffer. */
+static int aux_count = 0;
+/* used when we send commands to the mouse that expect an ACK. */
+static unsigned char mouse_reply_expected = 0;
+
+#define AUX_INTS_OFF (KBD_MODE_KCC | KBD_MODE_DISABLE_MOUSE | KBD_MODE_SYS | KBD_MODE_KBD_INT)
+#define AUX_INTS_ON  (KBD_MODE_KCC | KBD_MODE_SYS | KBD_MODE_MOUSE_INT | KBD_MODE_KBD_INT)
+#define MAX_RETRIES	60		/* some aux operations take long time*/
+
+static void ps2_mouse_interrupt(void *);
+static mouse_parser_enqueue_handler driver_input_handler_ps2 = NULL;
+
+/*
+ * This routine sets the handler to handle the characters received
+ * from the serial port.
+ */
+static void ps2_set_driver_handler(
+  int                          port,
+  mouse_parser_enqueue_handler handler
+)
+{
+  driver_input_handler_ps2 = handler;
+}
+
+static void mdelay( unsigned long t )
+{
+  Wait_X_ms( t );
+}
+
+static void*    termios_ttyp_paux = NULL;
+
+/*
+ * Wait for keyboard controller input buffer to drain.
+ *
+ * Don't use 'jiffies' so that we don't depend on
+ * interrupts..
+ *
+ * Quote from PS/2 System Reference Manual:
+ *
+ * "Address hex 0060 and address hex 0064 should be written only when
+ * the input-buffer-full bit and output-buffer-full bit in the
+ * Controller Status register are set 0."
+ */
+
+static void kb_wait(void)
+{
+  unsigned long timeout = KBC_TIMEOUT;
+
+  do {
+    /*
+     * "handle_kbd_event()" will handle any incoming events
+     * while we wait - keypresses or mouse movement.
+     */
+    unsigned char status = handle_kbd_event();
+
+    if (! (status & KBD_STAT_IBF))
+      return;
+
+    mdelay(1);
+    timeout--;
+  } while (timeout);
+
+  #ifdef KBD_REPORT_TIMEOUTS
+    printk( "Keyboard timed out[1]\n");
+  #endif
+}
+
+static int do_acknowledge(unsigned char scancode)
+{
+  if (reply_expected) {
+
+    /* Unfortunately, we must recognise these codes only if we know they
+     * are known to be valid (i.e., after sending a command), because there
+     * are some brain-damaged keyboards (yes, FOCUS 9000 again) which have
+     * keys with such codes :(
+     */
+    if (scancode == KBD_REPLY_ACK) {
+      acknowledge = 1;
+      reply_expected = 0;
+      return 0;
+    } else if (scancode == KBD_REPLY_RESEND) {
+      resend = 1;
+      reply_expected = 0;
+      return 0;
+    }
+
+    /* Should not happen... */
+    #if 0
+      printk( "keyboard reply expected - got %02x\n", scancode);
+    #endif
+  }
+  return 1;
+}
+
+static inline void handle_mouse_event(unsigned char scancode)
+{
+  if (mouse_reply_expected) {
+    if (scancode == AUX_ACK) {
+      mouse_reply_expected--;
+      return;
+    }
+    mouse_reply_expected = 0;
+  }
+
+  if (aux_count) {
+    int head = queue->head;
+    queue->buf[head] = scancode;
+    head = (head + 1) & (AUX_BUF_SIZE-1);
+    if (head != queue->tail) {
+      queue->head = head;
+    }
+
+    /* if the input queue is active, add to it */
+    if( driver_input_handler_ps2 ) {
+      driver_input_handler_ps2( &scancode, 1 );
+    } else {
+      /* post this byte to termios */
+      rtems_termios_enqueue_raw_characters( termios_ttyp_paux, (char *)&scancode, 1 );
+    }
+  }
+}
+
+/*
+ * This reads the keyboard status port, and does the
+ * appropriate action.
+ *
+ * It requires that we hold the keyboard controller
+ * spinlock.
+ */
+static unsigned char handle_kbd_event(void)
+{
+  unsigned char status = kbd_read_status();
+  unsigned int work = 10000;
+
+  while (status & KBD_STAT_OBF) {
+    unsigned char scancode;
+    scancode = kbd_read_input();
+    if (status & KBD_STAT_MOUSE_OBF) {
+      handle_mouse_event(scancode);
+    } else {
+      do_acknowledge(scancode);
+      printk("pc_keyb: %X ", scancode );
+    }
+    status = kbd_read_status();
+    if(!work--) {
+      printk("pc_keyb: controller jammed (0x%02X).\n", status);
+      break;
+    }
+  }
+  return status;
+}
+
+static void ps2_mouse_interrupt(void * unused)
+{
+  handle_kbd_event();
+}
+
+static void kbd_write_command_w(int data)
+{
+  kb_wait();
+  kbd_write_command(data);
+}
+
+static void kbd_write_cmd(int cmd)
+{
+  kb_wait();
+  kbd_write_command(KBD_CCMD_WRITE_MODE);
+  kb_wait();
+  kbd_write_output(cmd);
+}
+
+/*
+ * Check if this is a dual port controller.
+ */
+static int detect_auxiliary_port(void)
+{
+  int loops = 10;
+  int retval = 0;
+
+  /* Put the value 0x5A in the output buffer using the "Write
+   * Auxiliary Device Output Buffer" command (0xD3). Poll the
+   * Status Register for a while to see if the value really
+   * turns up in the Data Register. If the KBD_STAT_MOUSE_OBF
+   * bit is also set to 1 in the Status Register, we assume this
+   * controller has an Auxiliary Port (a.k.a. Mouse Port).
+   */
+  kb_wait();
+  kbd_write_command(KBD_CCMD_WRITE_AUX_OBUF);
+
+  kb_wait();
+  kbd_write_output(0x5a); /* 0x5a is a random dummy value. */
+
+  do {
+    unsigned char status = kbd_read_status();
+    if (status & KBD_STAT_OBF) {
+      kbd_read_input();
+      if (status & KBD_STAT_MOUSE_OBF) {
+        printk( "Detected PS/2 Mouse Port.\n");
+        retval = 1;
+      }
+      break;
+    }
+    mdelay(1);
+  } while (--loops);
+  return retval;
+}
+
+/*
+ * Send a byte to the mouse.
+ */
+static void aux_write_dev(int val)
+{
+  kb_wait();
+  kbd_write_command(KBD_CCMD_WRITE_MOUSE);
+  kb_wait();
+  kbd_write_output(val);
+}
+
+/*
+ * Send a byte to the mouse & handle returned ack
+ */
+static void aux_write_ack(int val)
+{
+  kb_wait();
+  kbd_write_command(KBD_CCMD_WRITE_MOUSE);
+  kb_wait();
+  kbd_write_output(val);
+  /* we expect an ACK in response. */
+  mouse_reply_expected++;
+  kb_wait();
+}
+
+static unsigned char get_from_queue(void)
+{
+  unsigned char result;
+  result = queue->buf[queue->tail];
+  queue->tail = (queue->tail + 1) & (AUX_BUF_SIZE-1);
+  return result;
+}
+
+static int queue_empty(void)
+{
+  return queue->head == queue->tail;
+}
+
+/*
+ * Random magic cookie for the aux device
+ */
+#define AUX_DEV ((void *)queue)
+
+static int release_aux(void)
+{
+  rtems_status_code status;
+  if (--aux_count)
+    return 0;
+  kbd_write_cmd(AUX_INTS_OFF);			    /* Disable controller ints */
+  kbd_write_command_w(KBD_CCMD_MOUSE_DISABLE);
+  status = rtems_interrupt_handler_remove(
+    AUX_IRQ,
+    ps2_mouse_interrupt,
+    NULL
+  );
+  assert(status == RTEMS_SUCCESSFUL);
+  return 0;
+}
+
+/*
+ * Install interrupt handler.
+ * Enable auxiliary device.
+ */
+
+static int open_aux(void)
+{
+  rtems_status_code status;
+
+  if (aux_count++) {
+    return 0;
+  }
+  queue->head = queue->tail = 0;		/* Flush input queue */
+
+  status = rtems_interrupt_handler_install(
+    AUX_IRQ,
+    "ps2_mouse",
+    RTEMS_INTERRUPT_UNIQUE,
+    ps2_mouse_interrupt,
+    NULL
+  );
+  assert(status == RTEMS_SUCCESSFUL);
+
+  kbd_write_command_w(KBD_CCMD_MOUSE_ENABLE); /* Enable the auxiliary port on
+                                                 controller. */
+  aux_write_ack(AUX_ENABLE_DEV); /* Enable aux device */
+  kbd_write_cmd(AUX_INTS_ON); /* Enable controller ints */
+  return 0;
+}
+
+/*
+ * Put bytes from input queue to buffer.
+ */
+size_t read_aux(char * buffer, size_t count )
+{
+  size_t i = count;
+  unsigned char c;
+
+  if (queue_empty()) {
+    return 0;
+  }
+  while (i > 0 && !queue_empty()) {
+    c = get_from_queue();
+    *buffer++ = c;
+    i--;
+  }
+  return count-i;
+}
+
+/*
+ * Write to the aux device.
+ */
+static int write_aux( int minor, const char * buffer, int count )
+{
+  int retval = 0;
+
+  if (count) {
+    int written = 0;
+    if (count > 32)
+      count = 32; /* Limit to 32 bytes. */
+    do {
+      char c;
+      c = *buffer++;
+      aux_write_dev(c);
+      written++;
+    } while (--count);
+    retval = -EIO;
+    if (written) {
+      retval = written;
+    }
+  }
+  return retval;
+}
+
+static int psaux_init( void )
+{
+  if( !detect_auxiliary_port() ) {
+    printk( "PS/2 - mouse not found.\n" );
+    return -EIO;
+  }
+  queue = (struct aux_queue *)malloc( sizeof(*queue) );
+  memset(queue, 0, sizeof(*queue));
+  queue->head = queue->tail = 0;
+  queue->proc_list = NULL;
+
+  #ifdef INITIALIZE_MOUSE
+    kbd_write_command_w(KBD_CCMD_MOUSE_ENABLE); /* Enable Aux. */
+    aux_write_ack(AUX_SET_SAMPLE);
+    aux_write_ack(100);			      /* 100 samples/sec */
+    aux_write_ack(AUX_SET_RES);
+    aux_write_ack(3);			         /* 8 counts per mm */
+    aux_write_ack(AUX_SET_SCALE21);	/* 2:1 scaling */
+  #endif /* INITIALIZE_MOUSE */
+  kbd_write_command(KBD_CCMD_MOUSE_DISABLE); /* Disable aux device. */
+  kbd_write_cmd(AUX_INTS_OFF); /* Disable controller ints. */
+  return 0;
+}
+
+/*
+ * paux device driver INITIALIZE entry point.
+ */
+rtems_device_driver paux_initialize(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void                      *arg)
+{
+  rtems_status_code status;
+
+  /*
+   * Set up TERMIOS
+   */
+  rtems_termios_initialize();
+
+  printk( "PS/2 mouse probe.\n" );
+  if( psaux_init() < 0 ) {
+    printk("Error detecting PS/2 mouse --\n");
+    /* we might want to finish the application here !!! */
+  }
+  open_aux();
+
+  /*
+   * Register the device
+   */
+  status = rtems_io_register_name ("/dev/mouse", major, 0);
+  if (status != RTEMS_SUCCESSFUL) {
+    printk("Error registering paux device!\n");
+    rtems_fatal_error_occurred (status);
+  }
+  return RTEMS_SUCCESSFUL;
+} /* tty_initialize */
+
+static int paux_last_close(int major, int minor, void *arg)
+{
+  release_aux();
+  return 0;
+}
+
+/*
+ * Write to the aux device. This routine is invoked by the
+ * termios framework whenever the "ECHO" feature is on.
+ * It does nothing write now.
+ */
+static ssize_t write_aux_echo( int minor, const char * buffer, size_t count )
+{
+  return 0;
+}
+
+/*
+ * paux device driver OPEN entry point
+ */
+rtems_device_driver paux_open(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void                      *arg)
+{
+  rtems_status_code              status;
+  static rtems_termios_callbacks cb =
+  {
+    NULL,	          /* firstOpen */
+    paux_last_close,      /* lastClose */
+    NULL,                 /* poll read  */
+    write_aux_echo,       /* write */
+    NULL,	          /* setAttributes */
+    NULL,	          /* stopRemoteTx */
+    NULL,	          /* startRemoteTx */
+    0		          /* outputUsesInterrupts */
+  };
+
+  status = rtems_termios_open (major, minor, arg, &cb );
+  termios_ttyp_paux = ( (rtems_libio_open_close_args_t *)arg)->iop->data1;
+  return status;
+}
+
+/*
+ * paux device driver CLOSE entry point
+ */
+rtems_device_driver paux_close(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void                      *arg)
+{
+  return (rtems_termios_close (arg));
+}
+
+/*
+ * paux device driver READ entry point.
+ * Read characters from the PS/2 mouse.
+ */
+rtems_device_driver paux_read(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void                      *arg)
+{
+  return rtems_termios_read (arg);
+} /* tty_read */
+
+/*
+ * paux device driver WRITE entry point.
+ * Write characters to the PS/2 mouse.
+ */
+rtems_device_driver  paux_write(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void                      *arg)
+{
+  rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
+  char                  *buffer  = rw_args->buffer;
+  int                    maximum  = rw_args->count;
+  rw_args->bytes_moved = write_aux( minor, buffer, maximum );
+  return RTEMS_SUCCESSFUL;
+} /* tty_write */
+
+/*
+ * Handle ioctl request.
+ */
+rtems_device_driver paux_control(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void                      *arg
+)
+{
+  rtems_libio_ioctl_args_t *args = arg;
+
+  switch( args->command ) {
+    default:
+      return rtems_termios_ioctl (arg);
+      break;
+
+    case MW_UID_REGISTER_DEVICE:
+      printk( "PS2 Mouse: registering\n" );
+      mouse_parser_initialize( "ps2" );
+      ps2_set_driver_handler( minor, mouse_parser_enqueue );
+      break;
+
+    case MW_UID_UNREGISTER_DEVICE:
+/*
+      unregister_mou_msg_queue( -1 );
+*/
+      ps2_set_driver_handler( minor, NULL );
+      break;
+  }
+  args->ioctl_return = 0;
+  return RTEMS_SUCCESSFUL;
+}
Index: bsps/i386/pc386/console/ps2_mouse.h
===================================================================
--- bsps/i386/pc386/console/ps2_mouse.h	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
+++ bsps/i386/pc386/console/ps2_mouse.h	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
@@ -0,0 +1,151 @@
+/**
+ * @file
+ *
+ * @ingroup i386_pc386
+ *
+ * @brief Keyboard and mouse definitions.
+ */
+
+/*
+ *	include/linux/pc_keyb.h
+ *	PC Keyboard And Keyboard Controller
+ *	(c) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ *
+ * RTEMS port: by Rosimildo da Silva.
+ *
+ * This module was ported from Linux.
+ *
+ */
+
+/*
+ *	Configuration Switches
+ */
+
+#undef KBD_REPORT_ERR			/* Report keyboard errors */
+#define KBD_REPORT_UNKN			/* Report unknown scan codes */
+#define KBD_REPORT_TIMEOUTS		/* Report keyboard timeouts */
+#undef KBD_IS_FOCUS_9000		/* We have the brain-damaged FOCUS-9000 keyboard */
+#undef INITIALIZE_MOUSE			/* Define if your PS/2 mouse needs initialization. */
+
+#define KBD_INIT_TIMEOUT 1000		/* Timeout in ms for initializing the keyboard */
+#define KBC_TIMEOUT 250			/* Timeout in ms for sending to keyboard controller */
+#define KBD_TIMEOUT 1000		/* Timeout in ms for keyboard command acknowledge */
+
+/*
+ *	Internal variables of the driver
+ */
+
+extern unsigned char pckbd_read_mask;
+extern unsigned char aux_device_present;
+
+/*
+ *	Keyboard Controller Registers on normal PCs.
+ */
+
+#define KBD_STATUS_REG		0x64	/* Status register (R) */
+#define KBD_CNTL_REG		0x64	/* Controller command register (W) */
+#define KBD_DATA_REG		0x60	/* Keyboard data register (R/W) */
+
+/*
+ *	Keyboard Controller Commands
+ */
+
+#define KBD_CCMD_READ_MODE	0x20	/* Read mode bits */
+#define KBD_CCMD_WRITE_MODE	0x60	/* Write mode bits */
+#define KBD_CCMD_GET_VERSION	0xA1	/* Get controller version */
+#define KBD_CCMD_MOUSE_DISABLE	0xA7	/* Disable mouse interface */
+#define KBD_CCMD_MOUSE_ENABLE	0xA8	/* Enable mouse interface */
+#define KBD_CCMD_TEST_MOUSE	0xA9	/* Mouse interface test */
+#define KBD_CCMD_SELF_TEST	0xAA	/* Controller self test */
+#define KBD_CCMD_KBD_TEST	0xAB	/* Keyboard interface test */
+#define KBD_CCMD_KBD_DISABLE	0xAD	/* Keyboard interface disable */
+#define KBD_CCMD_KBD_ENABLE	0xAE	/* Keyboard interface enable */
+#define KBD_CCMD_WRITE_AUX_OBUF	0xD3    /* Write to output buffer as if
+					   initiated by the auxiliary device */
+#define KBD_CCMD_WRITE_MOUSE	0xD4	/* Write the following byte to the mouse */
+
+/*
+ *	Keyboard Commands
+ */
+
+#define KBD_CMD_SET_LEDS	0xED	/* Set keyboard leds */
+#define KBD_CMD_SET_RATE	0xF3	/* Set typematic rate */
+#define KBD_CMD_ENABLE		0xF4	/* Enable scanning */
+#define KBD_CMD_DISABLE		0xF5	/* Disable scanning */
+#define KBD_CMD_RESET		0xFF	/* Reset */
+
+/*
+ *	Keyboard Replies
+ */
+
+#define KBD_REPLY_POR		0xAA	/* Power on reset */
+#define KBD_REPLY_ACK		0xFA	/* Command ACK */
+#define KBD_REPLY_RESEND	0xFE	/* Command NACK, send the cmd again */
+
+/*
+ *	Status Register Bits
+ */
+
+#define KBD_STAT_OBF 		0x01	/* Keyboard output buffer full */
+#define KBD_STAT_IBF 		0x02	/* Keyboard input buffer full */
+#define KBD_STAT_SELFTEST	0x04	/* Self test successful */
+#define KBD_STAT_CMD		0x08	/* Last write was a command write (0=data) */
+#define KBD_STAT_UNLOCKED	0x10	/* Zero if keyboard locked */
+#define KBD_STAT_MOUSE_OBF	0x20	/* Mouse output buffer full */
+#define KBD_STAT_GTO 		0x40	/* General receive/xmit timeout */
+#define KBD_STAT_PERR 		0x80	/* Parity error */
+
+#define AUX_STAT_OBF (KBD_STAT_OBF | KBD_STAT_MOUSE_OBF)
+
+/*
+ *	Controller Mode Register Bits
+ */
+
+#define KBD_MODE_KBD_INT	0x01	/* Keyboard data generate IRQ1 */
+#define KBD_MODE_MOUSE_INT	0x02	/* Mouse data generate IRQ12 */
+#define KBD_MODE_SYS 		0x04	/* The system flag (?) */
+#define KBD_MODE_NO_KEYLOCK	0x08	/* The keylock doesn't affect the keyboard if set */
+#define KBD_MODE_DISABLE_KBD	0x10	/* Disable keyboard interface */
+#define KBD_MODE_DISABLE_MOUSE	0x20	/* Disable mouse interface */
+#define KBD_MODE_KCC 		0x40	/* Scan code conversion to PC format */
+#define KBD_MODE_RFU		0x80
+
+/*
+ *	Mouse Commands
+ */
+
+#define AUX_SET_RES		0xE8	/* Set resolution */
+#define AUX_SET_SCALE11		0xE6	/* Set 1:1 scaling */
+#define AUX_SET_SCALE21		0xE7	/* Set 2:1 scaling */
+#define AUX_GET_SCALE		0xE9	/* Get scaling factor */
+#define AUX_SET_STREAM		0xEA	/* Set stream mode */
+#define AUX_SET_SAMPLE		0xF3	/* Set sample rate */
+#define AUX_ENABLE_DEV		0xF4	/* Enable aux device */
+#define AUX_DISABLE_DEV		0xF5	/* Disable aux device */
+#define AUX_RESET		0xFF	/* Reset aux device */
+#define AUX_ACK			0xFA	/* Command byte ACK. */
+
+#define AUX_BUF_SIZE		512	/* This might be better divisible by
+					   three to make overruns stay in sync
+					   but then the read function would need
+					   a lock etc - ick */
+
+struct aux_queue {
+	unsigned long head;
+	unsigned long tail;
+	struct wait_queue *proc_list;
+	struct fasync_struct *fasync;
+	unsigned char buf[AUX_BUF_SIZE];
+};
+
+/* How to access the keyboard macros on this platform.  */
+#define kbd_read_input() inb(KBD_DATA_REG)
+#define kbd_read_status() inb(KBD_STATUS_REG)
+#define kbd_write_output(val) outb(val, KBD_DATA_REG)
+#define kbd_write_command(val) outb(val, KBD_CNTL_REG)
+
+/*
+ * Machine specific bits for the PS/2 driver
+ */
+
+#define AUX_IRQ 12
Index: bsps/i386/pc386/console/rtd316.c
===================================================================
--- bsps/i386/pc386/console/rtd316.c	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
+++ bsps/i386/pc386/console/rtd316.c	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
@@ -0,0 +1,109 @@
+/**
+ *  @file
+ *
+ *  @brief Driver for RTD316 ISA SCC Board
+ *
+ *  The RTD316 has a single Z85C30.
+ */
+
+/*
+ *  COPYRIGHT (c) 1989-2014.
+ *  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 <bsp.h>
+#include <termios.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <rtems/termiostypes.h>
+#include <libchip/serial.h>
+#include <libchip/z85c30.h>
+#include <rtems/bspIo.h>
+#include <bsp/rtd316.h>
+#include <rtems/score/i386.h>
+#include "../../shared/dev/serial/legacy-console.h"
+
+#define RTD_CLOCK_RATE  (460800 * 32)
+
+uint8_t rtd316_com_get_register(uint32_t addr, uint8_t reg)
+{
+  register uint8_t val = 0;
+
+  outport_byte( addr, reg );
+  /* It appears the no delay is needed between the accesses. */
+  inport_byte( addr, val );
+
+  return val;
+}
+
+void rtd316_com_set_register(uint32_t addr,uint8_t reg, uint8_t val)
+{
+  outport_byte( addr, reg );
+  /* It appears the no delay is needed between the accesses. */
+  outport_byte( addr, val );
+}
+
+rtems_device_driver rtd316_initialize(
+  rtems_device_major_number  major,
+  rtems_device_minor_number  minor_arg,
+  void                      *arg
+)
+{
+  int           p;
+  console_tbl  *ports;
+  console_tbl  *port_p;
+
+  /*
+   *  Now allocate array of device structures and fill them in
+   */
+  ports = calloc( 2, sizeof( console_tbl ) );
+  port_p = ports;
+
+  for ( p=0 ; p<2 ; p++ ) {
+    char name[32];
+    sprintf( name, "/dev/rtd316_1_%d", p );
+    printk("Found %s\n", name );
+    port_p->sDeviceName   = strdup( name );
+    port_p->deviceType    = SERIAL_Z85C30;
+    #if 0
+      port_p->pDeviceFns  = &z85c30_fns_polled;
+    #else
+      port_p->pDeviceFns  = &z85c30_fns;
+    #endif
+
+    port_p->deviceProbe   = NULL;
+    port_p->pDeviceFlow   = NULL;
+    port_p->ulMargin      = 16;
+    port_p->ulHysteresis  = 8;
+    port_p->pDeviceParams = (void *) 9600;
+    port_p->getRegister   = rtd316_com_get_register;
+    port_p->setRegister   = rtd316_com_set_register;
+    port_p->getData       = NULL;
+    port_p->setData       = NULL;
+    port_p->ulClock       = RTD_CLOCK_RATE;
+    port_p->ulIntVector   = 9;
+
+    if ( p==0 ) {
+      port_p->ulDataPort    = 0;
+      port_p->ulCtrlPort1   = 0x340;
+      port_p->ulCtrlPort2   = 0x341;
+    } else {
+      port_p->ulDataPort    = 1;
+      port_p->ulCtrlPort1   = 0x342;
+      port_p->ulCtrlPort2   = 0x343;
+    }
+    port_p++;
+  }  /* end ports */
+
+  /*
+   *  Register the devices
+   */
+  console_register_devices( ports, 2 );
+
+  return RTEMS_SUCCESSFUL;
+}
Index: bsps/i386/pc386/console/serial_mouse_config.c
===================================================================
--- bsps/i386/pc386/console/serial_mouse_config.c	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
+++ bsps/i386/pc386/console/serial_mouse_config.c	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
@@ -0,0 +1,48 @@
+/*
+ *  COPYRIGHT (c) 1989-2011.
+ *  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 <stdio.h>
+#include <stdlib.h>
+#include <bsp.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <libchip/serial.h>
+#include "../../shared/dev/serial/legacy-console.h"
+
+/* select which serial port the mouse is connected to */
+#if defined(SERIAL_MOUSE_COM2)
+  #define MOUSE_DEVICE "/dev/com2"
+#else
+  #define MOUSE_DEVICE "/dev/com1"
+#endif
+
+static const char *SerialMouseDevice = MOUSE_DEVICE;
+
+bool bsp_get_serial_mouse_device(
+  const char **name,
+  const char **type
+)
+{
+  const char *consname;
+
+  *name = SerialMouseDevice;
+  *type = "ms";
+
+  /* Check if this port is not been used as console */
+  consname = Console_Port_Tbl[ Console_Port_Minor ]->sDeviceName;
+  if ( !strcmp(MOUSE_DEVICE, consname) ) {
+    printk( "SERIAL MOUSE: port selected as console.(%s)\n", *name );
+    rtems_fatal_error_occurred( -1 );
+  }
+
+  printk("Mouse Device: %s\n", *name );
+  return name;
+}
Index: bsps/i386/pc386/console/uart_bus_pci.c
===================================================================
--- bsps/i386/pc386/console/uart_bus_pci.c	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
+++ bsps/i386/pc386/console/uart_bus_pci.c	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
@@ -0,0 +1,477 @@
+/*
+ * This file was brought over from FreeBSD for the PCI device table.
+ * The code for using the table is RTEMS specific is also under the
+ * FreeBSD license.
+ *
+ * COPYRIGHT (c) 1989-2012.
+ * On-Line Applications Research Corporation (OAR).
+ */
+
+/*-
+ * Copyright (c) 2006 Marcel Moolenaar
+ * Copyright (c) 2001 M. Warner Losh
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef __rtems__
+#include <stddef.h>
+#include <stdint.h>
+#include <i386_io.h>
+#else
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <machine/resource.h>
+
+#include <dev/pci/pcivar.h>
+
+#include <dev/uart/uart.h>
+#include <dev/uart/uart_bus.h>
+
+#endif
+
+#define	DEFAULT_RCLK	1843200
+
+#ifndef __rtems__
+static int uart_pci_probe(device_t dev);
+
+static device_method_t uart_pci_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		uart_pci_probe),
+	DEVMETHOD(device_attach,	uart_bus_attach),
+	DEVMETHOD(device_detach,	uart_bus_detach),
+	DEVMETHOD(device_resume,	uart_bus_resume),
+	DEVMETHOD_END
+};
+
+static driver_t uart_pci_driver = {
+	uart_driver_name,
+	uart_pci_methods,
+	sizeof(struct uart_softc),
+};
+#endif
+
+struct pci_id {
+	uint16_t	vendor;
+	uint16_t	device;
+	uint16_t	subven;
+	uint16_t	subdev;
+	const char	*desc;
+	int		rid;
+	int		rclk;
+	int		regshft;
+};
+
+static const struct pci_id pci_ns8250_ids[] = {
+{ 0x1028, 0x0008, 0xffff, 0, "Dell Remote Access Card III", 0x14,
+	128 * DEFAULT_RCLK },
+{ 0x1028, 0x0012, 0xffff, 0, "Dell RAC 4 Daughter Card Virtual UART", 0x14,
+	128 * DEFAULT_RCLK },
+{ 0x1033, 0x0074, 0x1033, 0x8014, "NEC RCV56ACF 56k Voice Modem", 0x10 },
+{ 0x1033, 0x007d, 0x1033, 0x8012, "NEC RS232C", 0x10 },
+{ 0x103c, 0x1048, 0x103c, 0x1227, "HP Diva Serial [GSP] UART - Powerbar SP2",
+	0x10 },
+{ 0x103c, 0x1048, 0x103c, 0x1301, "HP Diva RMP3", 0x14 },
+{ 0x103c, 0x1290, 0xffff, 0, "HP Auxiliary Diva Serial Port", 0x18 },
+{ 0x103c, 0x3301, 0xffff, 0, "HP iLO serial port", 0x10 },
+{ 0x11c1, 0x0480, 0xffff, 0, "Agere Systems Venus Modem (V90, 56KFlex)", 0x14 },
+{ 0x115d, 0x0103, 0xffff, 0, "Xircom Cardbus Ethernet + 56k Modem", 0x10 },
+{ 0x1282, 0x6585, 0xffff, 0, "Davicom 56PDV PCI Modem", 0x10 },
+{ 0x12b9, 0x1008, 0xffff, 0, "3Com 56K FaxModem Model 5610", 0x10 },
+{ 0x131f, 0x1000, 0xffff, 0, "Siig CyberSerial (1-port) 16550", 0x18 },
+{ 0x131f, 0x1001, 0xffff, 0, "Siig CyberSerial (1-port) 16650", 0x18 },
+{ 0x131f, 0x1002, 0xffff, 0, "Siig CyberSerial (1-port) 16850", 0x18 },
+{ 0x131f, 0x2000, 0xffff, 0, "Siig CyberSerial (1-port) 16550", 0x10 },
+{ 0x131f, 0x2001, 0xffff, 0, "Siig CyberSerial (1-port) 16650", 0x10 },
+{ 0x131f, 0x2002, 0xffff, 0, "Siig CyberSerial (1-port) 16850", 0x10 },
+{ 0x135c, 0x0190, 0xffff, 0, "Quatech SSCLP-100", 0x18 },
+{ 0x135c, 0x01c0, 0xffff, 0, "Quatech SSCLP-200/300", 0x18 },
+{ 0x135e, 0x7101, 0xffff, 0, "Sealevel Systems Single Port RS-232/422/485/530",
+	0x18 },
+{ 0x1407, 0x0110, 0xffff, 0, "Lava Computer mfg DSerial-PCI Port A", 0x10 },
+{ 0x1407, 0x0111, 0xffff, 0, "Lava Computer mfg DSerial-PCI Port B", 0x10 },
+{ 0x1407, 0x0510, 0xffff, 0, "Lava SP Serial 550 PCI", 0x10 },
+{ 0x1409, 0x7168, 0x1409, 0x4025, "Timedia Technology Serial Port", 0x10,
+	8 * DEFAULT_RCLK },
+{ 0x1409, 0x7168, 0x1409, 0x4027, "Timedia Technology Serial Port", 0x10,
+	8 * DEFAULT_RCLK },
+{ 0x1409, 0x7168, 0x1409, 0x4028, "Timedia Technology Serial Port", 0x10,
+	8 * DEFAULT_RCLK },
+{ 0x1409, 0x7168, 0x1409, 0x5025, "Timedia Technology Serial Port", 0x10,
+	8 * DEFAULT_RCLK },
+{ 0x1409, 0x7168, 0x1409, 0x5027, "Timedia Technology Serial Port", 0x10,
+	8 * DEFAULT_RCLK },
+{ 0x1415, 0x950b, 0xffff, 0, "Oxford Semiconductor OXCB950 Cardbus 16950 UART",
+	0x10, 16384000 },
+{ 0x1415, 0xc120, 0xffff, 0, "Oxford Semiconductor OXPCIe952 PCIe 16950 UART",
+	0x10 },
+{ 0x14e4, 0x4344, 0xffff, 0, "Sony Ericsson GC89 PC Card", 0x10},
+{ 0x151f, 0x0000, 0xffff, 0, "TOPIC Semiconductor TP560 56k modem", 0x10 },
+{ 0x1fd4, 0x1999, 0x1fd4, 0x0001, "Sunix SER5xxxx Serial Port", 0x10,
+	8 * DEFAULT_RCLK },
+{ 0x8086, 0x0f0a, 0xffff, 0, "Intel ValleyView LPIO1 HSUART#1", 0x10,
+	24 * DEFAULT_RCLK, 2 },
+{ 0x8086, 0x0f0c, 0xffff, 0, "Intel ValleyView LPIO1 HSUART#2", 0x10,
+	24 * DEFAULT_RCLK, 2 },
+{ 0x8086, 0x1c3d, 0xffff, 0, "Intel AMT - KT Controller", 0x10 },
+{ 0x8086, 0x1d3d, 0xffff, 0, "Intel C600/X79 Series Chipset KT Controller", 0x10 },
+{ 0x8086, 0x2a07, 0xffff, 0, "Intel AMT - PM965/GM965 KT Controller", 0x10 },
+{ 0x8086, 0x2a47, 0xffff, 0, "Mobile 4 Series Chipset KT Controller", 0x10 },
+{ 0x8086, 0x2e17, 0xffff, 0, "4 Series Chipset Serial KT Controller", 0x10 },
+{ 0x8086, 0x3b67, 0xffff, 0, "5 Series/3400 Series Chipset KT Controller",
+	0x10 },
+{ 0x8086, 0x8811, 0xffff, 0, "Intel EG20T Serial Port 0", 0x10 },
+{ 0x8086, 0x8812, 0xffff, 0, "Intel EG20T Serial Port 1", 0x10 },
+{ 0x8086, 0x8813, 0xffff, 0, "Intel EG20T Serial Port 2", 0x10 },
+{ 0x8086, 0x8814, 0xffff, 0, "Intel EG20T Serial Port 3", 0x10 },
+{ 0x8086, 0x8c3d, 0xffff, 0, "Intel Lynx Point KT Controller", 0x10 },
+{ 0x8086, 0x8cbd, 0xffff, 0, "Intel Wildcat Point KT Controller", 0x10 },
+{ 0x8086, 0x9c3d, 0xffff, 0, "Intel Lynx Point-LP HECI KT", 0x10 },
+{ 0x9710, 0x9820, 0x1000, 1, "NetMos NM9820 Serial Port", 0x10 },
+{ 0x9710, 0x9835, 0x1000, 1, "NetMos NM9835 Serial Port", 0x10 },
+{ 0x9710, 0x9865, 0xa000, 0x1000, "NetMos NM9865 Serial Port", 0x10 },
+{ 0x9710, 0x9900, 0xa000, 0x1000,
+	"MosChip MCS9900 PCIe to Peripheral Controller", 0x10 },
+{ 0x9710, 0x9901, 0xa000, 0x1000,
+	"MosChip MCS9901 PCIe to Peripheral Controller", 0x10 },
+{ 0x9710, 0x9904, 0xa000, 0x1000,
+	"MosChip MCS9904 PCIe to Peripheral Controller", 0x10 },
+{ 0x9710, 0x9922, 0xa000, 0x1000,
+	"MosChip MCS9922 PCIe to Peripheral Controller", 0x10 },
+{ 0xdeaf, 0x9051, 0xffff, 0, "Middle Digital PC Weasel Serial Port", 0x10 },
+{ 0xffff, 0, 0xffff, 0, NULL, 0, 0}
+};
+
+#ifndef __rtems__
+const static struct pci_id *
+uart_pci_match(device_t dev, const struct pci_id *id)
+{
+	uint16_t device, subdev, subven, vendor;
+
+	vendor = pci_get_vendor(dev);
+	device = pci_get_device(dev);
+	while (id->vendor != 0xffff &&
+	    (id->vendor != vendor || id->device != device))
+		id++;
+	if (id->vendor == 0xffff)
+		return (NULL);
+	if (id->subven == 0xffff)
+		return (id);
+	subven = pci_get_subvendor(dev);
+	subdev = pci_get_subdevice(dev);
+	while (id->vendor == vendor && id->device == device &&
+	    (id->subven != subven || id->subdev != subdev))
+		id++;
+	return ((id->vendor == vendor && id->device == device) ? id : NULL);
+}
+
+static int
+uart_pci_probe(device_t dev)
+{
+	struct uart_softc *sc;
+	const struct pci_id *id;
+	int result;
+
+	sc = device_get_softc(dev);
+
+	id = uart_pci_match(dev, pci_ns8250_ids);
+	if (id != NULL) {
+		sc->sc_class = &uart_ns8250_class;
+		goto match;
+	}
+	/* Add checks for non-ns8250 IDs here. */
+	return (ENXIO);
+
+ match:
+	result = uart_bus_probe(dev, id->regshft, id->rclk, id->rid, 0);
+	/* Bail out on error. */
+	if (result > 0)
+		return (result);
+	/* Set/override the device description. */
+	if (id->desc)
+		device_set_desc(dev, id->desc);
+	return (result);
+}
+
+DRIVER_MODULE(uart, pci, uart_pci_driver, uart_devclass, NULL, NULL);
+#endif
+
+#ifdef __rtems__
+
+#include <bsp.h>
+#include <bsp/bspimpl.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <libchip/serial.h>
+#include <libchip/ns16550.h>
+#include <rtems/bspIo.h>
+#include <rtems/pci.h>
+#include "../../shared/dev/serial/legacy-console.h"
+
+#define MAX_BOARDS 4
+
+/*
+ * Information saved from PCI scan
+ */
+typedef struct {
+  bool        found;
+  const char* desc;
+  uint32_t    base;
+  uint8_t     irq;
+  uint8_t     bus;
+  uint8_t     slot;
+  int         ports;
+  uint32_t    clock;
+} port_instance_conf_t;
+
+/*
+ *  Memory Mapped Register Access Routines
+ */
+
+#define UART_PCI_IO (0)
+
+static uint8_t pci_ns16550_mem_get_register(uint32_t addr, uint8_t i)
+{
+  uint8_t          val = 0;
+  volatile uint32_t *reg = (volatile uint32_t *)(addr + (i*4));
+  val = *reg;
+  if (UART_PCI_IO)
+    printk( "RD(%p -> 0x%02x) ", reg, val );
+  return val;
+}
+
+static void pci_ns16550_mem_set_register(uint32_t addr, uint8_t i, uint8_t val)
+{
+  volatile uint32_t *reg = (volatile uint32_t *)(addr + (i*4));
+  if (UART_PCI_IO)
+    printk( "WR(%p <- 0x%02x) ", reg, val );
+  *reg = val;
+}
+
+/*
+ *  IO Register Access Routines
+ */
+static uint8_t pci_ns16550_io_get_register(uint32_t addr, uint8_t i)
+{
+  uint8_t val = rtems_inb(addr + i);
+  if (UART_PCI_IO)
+    printk( "RD(%p -> 0x%02x) ", (void*) addr + i, val );
+  return val;
+}
+
+static void pci_ns16550_io_set_register(uint32_t addr, uint8_t i, uint8_t val)
+{
+  if (UART_PCI_IO)
+    printk( "WR(%p <- 0x%02x) ", (void*) addr + i, val );
+  rtems_outb(addr + i, val);
+}
+
+void pci_uart_probe(void)
+{
+  port_instance_conf_t  conf[MAX_BOARDS];
+  int                   boards = 0;
+  int                   b = 0;
+  console_tbl          *ports;
+  console_tbl          *port_p;
+  int                   bus;
+  int                   dev;
+  int                   fun;
+  int                   status;
+  int                   instance;
+  int                   i;
+  int                   total_ports = 0;
+
+  for ( b=0 ; b<MAX_BOARDS ; b++ ) {
+    conf[b].found = false;
+  }
+
+  /*
+   *  Scan for Serial port boards
+   */
+  for ( instance=0 ; instance < MAX_BOARDS ; instance++ ) {
+
+    for ( i=0 ; pci_ns8250_ids[i].vendor != 0xffff ; i++ ) {
+      if ( pci_ns8250_ids[i].vendor == 0xffff ) {
+        break;
+      }
+/*
+      printk("Looking for 0x%04x:0x%04x\n",
+        pci_ns8250_ids[i].vendor,
+        pci_ns8250_ids[i].device);
+*/
+      status = pci_find_device(
+        pci_ns8250_ids[i].vendor,
+        pci_ns8250_ids[i].device,
+        instance,
+        &bus,
+        &dev,
+        &fun
+      );
+      if ( status == PCIB_ERR_SUCCESS ) {
+	uint8_t  irq;
+	uint32_t base;
+	bool io;
+
+	pci_read_config_dword( bus, dev, fun, PCI_BASE_ADDRESS_0, &base );
+
+	/*
+	 * Reject memory mapped 64-bit boards. We need 2 BAR registers and the
+	 * driver's base field is only 32-bits any way.
+	 */
+	io = (base & 1) == 1;
+	if (io || (!io && (((base >> 1) & 3) != 2))) {
+	  boards++;
+	  conf[instance].found = true;
+	  conf[instance].desc = pci_ns8250_ids[i].desc;
+	  conf[instance].clock =  pci_ns8250_ids[i].rclk;
+	  conf[instance].ports = 1;
+	  total_ports += conf[instance].ports;
+
+	  pci_read_config_byte( bus, dev, fun, PCI_INTERRUPT_LINE, &irq );
+
+	  conf[instance].irq  = irq;
+	  conf[instance].base = base;
+	}
+      }
+    }
+  }
+
+  /*
+   *  Now allocate array of device structures and fill them in
+   */
+  if (boards) {
+    int device_instance;
+
+    ports = calloc( total_ports, sizeof( console_tbl ) );
+    if (ports != NULL) {
+      port_p = ports;
+      device_instance = 1;
+      for (b = 0; b < MAX_BOARDS; b++) {
+	uint32_t base = 0;
+	bool io;
+	const char* locatable = "";
+	const char* prefectable = locatable;
+	char name[32];
+	if ( conf[b].found == false )
+	  continue;
+	sprintf( name, "/dev/pcicom%d", device_instance++ );
+	port_p->sDeviceName   = strdup( name );
+	port_p->deviceType    = SERIAL_NS16550;
+	if ( conf[b].irq <= 15 ) {
+	  port_p->pDeviceFns    = &ns16550_fns;
+	} else {
+	  printk(
+            "%s IRQ=%d >= 16 requires APIC support, using polling\n",
+	    name,
+	    conf[b].irq
+          );
+	  port_p->pDeviceFns    = &ns16550_fns_polled;
+	}
+
+	/*
+	 * PCI BAR (http://wiki.osdev.org/PCI#Base_Address_Registers):
+	 *
+	 *  Bit 0: 0 = memory, 1 = IO
+	 *
+	 * Memory:
+	 *  Bit 2-1  : 0 = any 32bit address,
+	 *             1 = < 1M
+	 *             2 = any 64bit address
+	 *  Bit 3    : 0 = no, 1 = yes
+	 *  Bit 31-4 : base address (16-byte aligned)
+	 *
+	 * IO:
+	 *  Bit 1    : reserved
+	 *  Bit 31-2 : base address (4-byte aligned)
+	 */
+
+	io = (conf[b].base & 1) == 1;
+
+	if (io) {
+	  base = conf[b].base & 0xfffffffc;
+	} else {
+	  int loc = (conf[b].base >> 1) & 3;
+	  if (loc == 0) {
+	    base = conf[b].base & 0xfffffff0;
+	    locatable = ",A32";
+	  } else if (loc == 1) {
+	    base = conf[b].base & 0x0000fff0;
+	    locatable = ",A16";
+	  }
+	  prefectable = (conf[b].base & (1 << 3)) == 0 ? ",no-prefech" : ",prefetch";
+	}
+
+	port_p->deviceProbe   = NULL;
+	port_p->pDeviceFlow   = NULL;
+	port_p->ulMargin      = 16;
+	port_p->ulHysteresis  = 8;
+	port_p->pDeviceParams = (void *) 9600;
+	port_p->ulCtrlPort1   = base;
+	port_p->ulCtrlPort2   = 0;                   /* NA */
+	port_p->ulDataPort    = 0;                   /* NA */
+	if (io) {
+	  port_p->getRegister = pci_ns16550_io_get_register;
+	  port_p->setRegister = pci_ns16550_io_set_register;
+	} else {
+	  port_p->getRegister = pci_ns16550_mem_get_register;
+	  port_p->setRegister = pci_ns16550_mem_set_register;
+	}
+	port_p->getData       = NULL;                /* NA */
+	port_p->setData       = NULL;                /* NA */
+	port_p->ulClock       = conf[b].clock;
+	port_p->ulIntVector   = conf[b].irq;
+
+
+        printk(
+          "%s:%d:%s,%s:0x%lx%s%s,irq:%d,clk:%lu\n", /*  */
+	  name, b, conf[b].desc,
+	  io ? "io" : "mem", base, locatable, prefectable,
+	  conf[b].irq, conf[b].clock
+        );
+
+
+	port_p++;
+      }    /* end boards */
+
+      /*
+       *  Register the devices
+       */
+      console_register_devices( ports, total_ports );
+
+      /*
+       *  Do not free the ports memory, the console hold this memory for-ever.
+       */
+    }
+  }
+}
+#endif
Index: bsps/i386/pc386/console/vgacons.c
===================================================================
--- bsps/i386/pc386/console/vgacons.c	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
+++ bsps/i386/pc386/console/vgacons.c	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
@@ -0,0 +1,191 @@
+/*
+ *  This file contains the termios TTY driver for the i386
+ *  vga.
+ *
+ *  COPYRIGHT (c) 1989-2011.
+ *  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 <rtems.h>
+#include <rtems/libio.h>
+#include <stdlib.h>
+#include <libchip/serial.h>
+#include <rtems/vgacons.h>
+#include <rtems/keyboard.h>
+#include <libchip/sersupp.h>
+#include <bsp/irq.h>
+#include <bsp.h>
+#include <crt.h>
+#include <assert.h>
+#include <rtems/keyboard.h>
+
+#define VGACONS_STATIC static
+
+/*
+ *  vgacons_init
+ *
+ *  This function initializes the VGA console to a quiecsent state.
+ */
+VGACONS_STATIC void vgacons_init(int minor)
+{
+  /*
+   * Note:  We do not initialize the KBD interface here since
+   *        it was initialized regardless of whether the
+   *        vga is available or not.  Therefore it is initialized
+   *        in bsp_start.
+   */
+}
+
+/*
+ *  vgacons_open
+ *
+ *  This function opens a port for communication.
+ *
+ *  Default state is 9600 baud, 8 bits, No parity, and 1 stop bit.
+ */
+VGACONS_STATIC int vgacons_open(
+  int      major,
+  int      minor,
+  void    *arg
+)
+{
+  return RTEMS_SUCCESSFUL;
+}
+
+/*
+ *  vgacons_close
+ *
+ *  This function shuts down the requested port.
+ */
+VGACONS_STATIC int vgacons_close(
+  int      major,
+  int      minor,
+  void    *arg
+)
+{
+  return(RTEMS_SUCCESSFUL);
+}
+
+/*
+ *  vgacons_write_polled
+ *
+ *  This routine polls out the requested character.
+ */
+VGACONS_STATIC void vgacons_write_polled(
+  int   minor,
+  char  c
+)
+{
+  _IBMPC_outch( c );
+  if( c == '\n')
+    _IBMPC_outch( '\r' );            /* LF = LF + CR */
+}
+
+/*
+ *  vgacons_write_support_polled
+ *
+ *  Console Termios output entry point when using polled output.
+ *
+ */
+VGACONS_STATIC ssize_t vgacons_write_support_polled(
+  int         minor,
+  const char *buf,
+  size_t      len
+)
+{
+  int nwrite = 0;
+
+  /*
+   * poll each byte in the string out of the port.
+   */
+  while (nwrite < len) {
+    vgacons_write_polled(minor, *buf++);
+    nwrite++;
+  }
+
+  /*
+   * return the number of bytes written.
+   */
+  return nwrite;
+}
+
+/*
+ *  vgacons_inbyte_nonblocking_polled
+ *
+ *  Console Termios polling input entry point.
+ */
+VGACONS_STATIC int vgacons_inbyte_nonblocking_polled(
+  int minor
+)
+{
+  if( rtems_kbpoll() ) {
+    int c = getch();
+    return c;
+  }
+
+  return -1;
+}
+
+/*
+ *  vgacons_set_attributes
+ *
+ *  This function sets the UART channel to reflect the requested termios
+ *  port settings.
+ */
+VGACONS_STATIC int vgacons_set_attributes(
+  int minor,
+  const struct termios *t
+)
+{
+  return 0;
+}
+
+bool vgacons_probe(
+  int minor
+)
+{
+  rtems_status_code status;
+  static bool firstTime = true;
+
+  if ((*(unsigned char*) NB_MAX_ROW_ADDR == 0) &&
+      (*(unsigned short*)NB_MAX_COL_ADDR == 0)) {
+    return false;
+  }
+
+  /*
+   *  If there is a video card, let's assume there is also a keyboard.
+   *  The means that we need the ISR installed in case someone wants to
+   *  use the Keyboard or PS2 Mouse.  With Microwindows, the console
+   *  can be COM1 and you can still use the mouse/VGA for graphics.
+   */
+  if ( firstTime ) {
+    status = rtems_interrupt_handler_install(
+      BSP_KEYBOARD,
+      "vgacons",
+      RTEMS_INTERRUPT_UNIQUE,
+      keyboard_interrupt,
+      NULL
+    );
+    assert(status == RTEMS_SUCCESSFUL);
+  }
+  firstTime = false;
+
+  return true;
+}
+
+const console_fns vgacons_fns =
+{
+  libchip_serial_default_probe,        /* deviceProbe */
+  vgacons_open,                        /* deviceFirstOpen */
+  vgacons_close,                       /* deviceLastClose */
+  vgacons_inbyte_nonblocking_polled,   /* deviceRead */
+  vgacons_write_support_polled,        /* deviceWrite */
+  vgacons_init,                        /* deviceInitialize */
+  vgacons_write_polled,                /* deviceWritePolled */
+  vgacons_set_attributes,              /* deviceSetAttributes */
+  FALSE,                               /* deviceOutputUsesInterrupts */
+};
Index: bsps/i386/pc386/console/vgainit.c
===================================================================
--- bsps/i386/pc386/console/vgainit.c	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
+++ bsps/i386/pc386/console/vgainit.c	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
@@ -0,0 +1,757 @@
+/*
+ * Copyright (c) 1999 Greg Haerr <greg@censoft.com>
+ * Copyright (c) 1991 David I. Bell
+ * Permission is granted to use, distribute, or modify this source,
+ * provided that this copyright notice remains intact.
+ *
+ * Alternate EGA/VGA Screen Driver Init, direct hw programming
+ */
+#include <i386_io.h>
+
+#ifdef __rtems__
+#define ROMFONT		0	/* =0 no bios rom fonts available*/
+#else
+#define ROMFONT		1	/* =1 uses PC rom fonts */
+#endif
+
+/* defines are defined in device.h of the MicroWindows package */
+#define	MODE_SET	0	/* draw pixels as given (default) */
+#define	MODE_XOR	1	/* draw pixels using XOR */
+#define	MODE_OR	2	/* draw pixels using OR (notimp)*/
+#define	MODE_AND	3	/* draw pixels using AND (notimp)*/
+#define  MODE_MAX	3
+typedef int MODE;    /* drawing mode*/
+
+/* Define one and only one of the following to be nonzero*/
+#define	VGA_ET4000	0	/* TSENG LABS ET4000 chip 800x600*/
+#define	VGA_STANDARD	1	/* standard VGA 640x480*/
+#define	EGA_STANDARD	0	/* standard EGA 640x350*/
+
+#define	DONE	0
+#define	IN	1
+#define	OUT	2
+
+#define	RAM_SCAN_LINES	32	/* number of scan lines in fonts in RAM */
+#define	FONT_CHARS	256	/* number of characters in font tables */
+#define	CHAR_WIDTH	8	/* number of pixels for character width */
+
+#define	PALREG	0x3c0
+#define	SEQREG	0x3c4
+#define	SEQVAL	0x3c5
+#define	GRREG	0x3ce
+#define	GRVAL	0x3cf
+#define	ATTRREG	0x3da
+#define	CRTCREG	0x3d4
+#define	CRTCVAL	0x3d5
+
+#define	GENREG1	0x3c2
+#define	GENREG2	0x3cc
+#define	GENREG3	0x3ca
+
+#define	DATA_ROTATE	3	/* register number for data rotate */
+
+typedef struct {
+  int action;
+  int port1;
+  int data1;
+  int port2;
+  int data2;
+} REGIO;
+
+#if ROMFONT
+extern FARADDR 		rom_char_addr;		/* address of ROM font*/
+extern int		ROM_CHAR_HEIGHT;	/* ROM character height*/
+#endif
+
+/* local data*/
+static REGIO 		graphics_on[];
+static REGIO 		graph_off[];
+
+/* entry points*/
+void		ega_hwinit(void);
+void		ega_hwterm(void);
+
+/* local routines*/
+static void writeregs(REGIO *rp);
+static void out_word(unsigned int p,unsigned int d);
+static void setmode(MODE mode);
+
+void
+ega_hwinit(void)
+{
+	writeregs(graphics_on);
+}
+
+void
+ega_hwterm(void)
+{
+  setmode(MODE_SET);
+
+  /* Copy character table from ROM back into bit plane 2 before turning
+   * off graphics.
+   */
+  out_word(SEQREG, 0x0100);	/* syn reset */
+  out_word(SEQREG, 0x0402);	/* cpu writes only to map 2 */
+  out_word(SEQREG, 0x0704);	/* sequential addressing */
+  out_word(SEQREG, 0x0300);	/* clear synchronous reset */
+
+  out_word(GRREG, 0x0204);	/* select map 2 for CPU reads */
+  out_word(GRREG, 0x0005);	/* disable odd-even addressing */
+
+#if ROMFONT
+  {
+	  FARADDR	srcoffset;
+	  FARADDR	destoffset;
+	  int 		data;
+	  int 		ch;
+	  int 		row;
+
+	  srcoffset = rom_char_addr;
+	  destoffset = EGA_BASE;
+	  for (ch = 0; ch < FONT_CHARS; ch++) {
+		for(row = 0; row < ROM_CHAR_HEIGHT; row++) {
+			data = GETBYTE_FP(srcoffset++);
+			PUTBYTE_FP(destoffset++, data);
+		}
+		destoffset += (RAM_SCAN_LINES - ROM_CHAR_HEIGHT);
+	  }
+  }
+#endif
+
+  /* Finally set the registers back for text mode. */
+  writeregs(graph_off);
+}
+
+/* Set the graphics registers as indicated by the given table */
+static void
+writeregs(REGIO *rp)
+{
+  for (; rp->action != DONE; rp++) {
+	switch (rp->action) {
+	    case IN:
+			inp(rp->port1);
+			break;
+	    case OUT:
+			outp(rp->port1, rp->data1);
+			if (rp->port2)
+				outp(rp->port2, rp->data2);
+			break;
+	}
+  }
+}
+
+/* Output a word to an I/O port. */
+static void
+out_word(unsigned int p,unsigned int d)
+{
+  outp(p, d & 0xff);
+  outp(p + 1, (d >> 8) & 0xff);
+}
+
+/* Values for the data rotate register to implement drawing modes. */
+static unsigned char mode_table[MODE_MAX + 1] = {
+  0x00, 0x18, 0x10, 0x08
+};
+
+/* Set the drawing mode.
+ * This is either SET, OR, AND, or XOR.
+ */
+static void
+setmode(MODE mode)
+{
+  if (mode > MODE_MAX)
+  	return;
+  outp(GRREG, DATA_ROTATE);
+  outp(GRVAL, mode_table[mode]);
+}
+
+#if VGA_ET4000
+
+/* VGA 800x600 16-color graphics (BIOS mode 0x29).
+ */
+REGIO graphics_on[] = {
+  /* Reset attr F/F */
+  IN, ATTRREG, 0, 0, 0,
+
+  /* Disable palette */
+  OUT, PALREG, 0, 0, 0,
+
+  /* Reset sequencer regs */
+  OUT, SEQREG, 0, SEQVAL, 0,
+  OUT, SEQREG, 1, SEQVAL, 1,
+  OUT, SEQREG, 2, SEQVAL, 0x0f,
+  OUT, SEQREG, 3, SEQVAL, 0,
+  OUT, SEQREG, 4, SEQVAL, 6,
+
+  /* Misc out reg */
+  OUT, GENREG1, 0xe3, 0, 0,
+
+  /* Sequencer enable */
+  OUT, SEQREG, 0, SEQVAL, 0x03,
+
+  /* Unprotect crtc regs 0-7 */
+  OUT, CRTCREG, 0x11, CRTCVAL, 0,
+
+  /* Crtc */
+  OUT, CRTCREG, 0, CRTCVAL, 0x7a,
+  OUT, CRTCREG, 1, CRTCVAL, 0x63,
+  OUT, CRTCREG, 2, CRTCVAL, 0x64,
+  OUT, CRTCREG, 3, CRTCVAL, 0x1d,
+  OUT, CRTCREG, 4, CRTCVAL, 0x68,
+  OUT, CRTCREG, 5, CRTCVAL, 0x9a,
+  OUT, CRTCREG, 6, CRTCVAL, 0x78,
+  OUT, CRTCREG, 7, CRTCVAL, 0xf0,
+  OUT, CRTCREG, 8, CRTCVAL, 0x00,
+  OUT, CRTCREG, 9, CRTCVAL, 0x60,
+  OUT, CRTCREG, 10, CRTCVAL, 0x00,
+  OUT, CRTCREG, 11, CRTCVAL, 0x00,
+  OUT, CRTCREG, 12, CRTCVAL, 0x00,
+  OUT, CRTCREG, 13, CRTCVAL, 0x00,
+  OUT, CRTCREG, 14, CRTCVAL, 0x00,
+  OUT, CRTCREG, 15, CRTCVAL, 0x00,
+  OUT, CRTCREG, 16, CRTCVAL, 0x5c,
+  OUT, CRTCREG, 17, CRTCVAL, 0x8e,
+  OUT, CRTCREG, 18, CRTCVAL, 0x57,
+  OUT, CRTCREG, 19, CRTCVAL, 0x32,
+  OUT, CRTCREG, 20, CRTCVAL, 0x00,
+  OUT, CRTCREG, 21, CRTCVAL, 0x5b,
+  OUT, CRTCREG, 22, CRTCVAL, 0x75,
+  OUT, CRTCREG, 23, CRTCVAL, 0xc3,
+  OUT, CRTCREG, 24, CRTCVAL, 0xff,
+
+  /* Graphics controller */
+  OUT, GENREG2, 0x00, 0, 0,
+  OUT, GENREG3, 0x01, 0, 0,
+  OUT, GRREG, 0, GRVAL, 0x00,
+  OUT, GRREG, 1, GRVAL, 0x00,
+  OUT, GRREG, 2, GRVAL, 0x00,
+  OUT, GRREG, 3, GRVAL, 0x00,
+  OUT, GRREG, 4, GRVAL, 0x00,
+  OUT, GRREG, 5, GRVAL, 0x00,
+  OUT, GRREG, 6, GRVAL, 0x05,
+  OUT, GRREG, 7, GRVAL, 0x0f,
+  OUT, GRREG, 8, GRVAL, 0xff,
+
+  /* Reset attribute flip/flop */
+  IN, ATTRREG, 0, 0, 0,
+
+  /* Palette */
+  OUT, PALREG, 0, PALREG, 0x00,
+  OUT, PALREG, 1, PALREG, 0x01,
+  OUT, PALREG, 2, PALREG, 0x02,
+  OUT, PALREG, 3, PALREG, 0x03,
+  OUT, PALREG, 4, PALREG, 0x04,
+  OUT, PALREG, 5, PALREG, 0x05,
+  OUT, PALREG, 6, PALREG, 0x06,
+  OUT, PALREG, 7, PALREG, 0x07,
+  OUT, PALREG, 8, PALREG, 0x38,
+  OUT, PALREG, 9, PALREG, 0x39,
+  OUT, PALREG, 10, PALREG, 0x3a,
+  OUT, PALREG, 11, PALREG, 0x3b,
+  OUT, PALREG, 12, PALREG, 0x3c,
+  OUT, PALREG, 13, PALREG, 0x3d,
+  OUT, PALREG, 14, PALREG, 0x3e,
+  OUT, PALREG, 15, PALREG, 0x3f,
+  OUT, PALREG, 16, PALREG, 0x01,
+  OUT, PALREG, 17, PALREG, 0x00,
+  OUT, PALREG, 18, PALREG, 0x0f,
+  OUT, PALREG, 19, PALREG, 0x00,
+
+  /* Enable palette */
+  OUT, PALREG, 0x20, 0, 0,
+
+  /* End of table */
+  DONE, 0, 0, 0, 0
+};
+
+/* VGA 80x25 text (BIOS mode 3).
+ */
+static REGIO graph_off[] = {
+  /* Reset attr F/F */
+  IN, ATTRREG, 0, 0, 0,
+
+  /* Disable palette */
+  OUT, PALREG, 0, 0, 0,
+
+  /* Reset sequencer regs */
+  OUT, SEQREG, 0, SEQVAL, 1,
+  OUT, SEQREG, 1, SEQVAL, 1,
+  OUT, SEQREG, 2, SEQVAL, 3,
+  OUT, SEQREG, 3, SEQVAL, 0,
+  OUT, SEQREG, 4, SEQVAL, 2,
+
+  /* Misc out reg */
+  OUT, GENREG1, 0x63, 0, 0,
+
+  /* Sequencer enable */
+  OUT, SEQREG, 0, SEQVAL, 3,
+
+  /* Unprotect crtc regs 0-7 */
+  OUT, CRTCREG, 0x11, CRTCVAL, 0,
+
+  /* Crtc */
+  OUT, CRTCREG, 0, CRTCVAL, 0x5f,	/* horiz total */
+  OUT, CRTCREG, 1, CRTCVAL, 0x4f,	/* horiz end */
+  OUT, CRTCREG, 2, CRTCVAL, 0x50,	/* horiz blank */
+  OUT, CRTCREG, 3, CRTCVAL, 0x82,	/* end blank */
+  OUT, CRTCREG, 4, CRTCVAL, 0x55,	/* horiz retrace */
+  OUT, CRTCREG, 5, CRTCVAL, 0x81,	/* end retrace */
+  OUT, CRTCREG, 6, CRTCVAL, 0xbf,	/* vert total */
+  OUT, CRTCREG, 7, CRTCVAL, 0x1f,	/* overflows */
+  OUT, CRTCREG, 8, CRTCVAL, 0x00,	/* row scan */
+  OUT, CRTCREG, 9, CRTCVAL, 0x4f,	/* max scan line */
+  OUT, CRTCREG, 10, CRTCVAL, 0x00,	/* cursor start */
+  OUT, CRTCREG, 11, CRTCVAL, 0x0f,	/* cursor end */
+  OUT, CRTCREG, 12, CRTCVAL, 0x0e,	/* start high addr */
+  OUT, CRTCREG, 13, CRTCVAL, 0xb0,	/* low addr */
+  OUT, CRTCREG, 14, CRTCVAL, 0x16,	/* cursor high */
+  OUT, CRTCREG, 15, CRTCVAL, 0x30,	/* cursor low */
+  OUT, CRTCREG, 16, CRTCVAL, 0x9c,	/* vert retrace */
+  OUT, CRTCREG, 17, CRTCVAL, 0x8e,	/* retrace end */
+  OUT, CRTCREG, 18, CRTCVAL, 0x8f,	/* vert end */
+  OUT, CRTCREG, 19, CRTCVAL, 0x28,	/* offset */
+  OUT, CRTCREG, 20, CRTCVAL, 0x1f,	/* underline */
+  OUT, CRTCREG, 21, CRTCVAL, 0x96,	/* vert blank */
+  OUT, CRTCREG, 22, CRTCVAL, 0xb9,	/* end blank */
+  OUT, CRTCREG, 23, CRTCVAL, 0xa3,	/* crt mode */
+  OUT, CRTCREG, 24, CRTCVAL, 0xff,	/* line compare */
+
+  /* Graphics controller */
+  OUT, GENREG2, 0x00, 0, 0,
+  OUT, GENREG3, 0x01, 0, 0,
+  OUT, GRREG, 0, GRVAL, 0x00,
+  OUT, GRREG, 1, GRVAL, 0x00,
+  OUT, GRREG, 2, GRVAL, 0x00,
+  OUT, GRREG, 3, GRVAL, 0x00,
+  OUT, GRREG, 4, GRVAL, 0x00,
+  OUT, GRREG, 5, GRVAL, 0x10,
+  OUT, GRREG, 6, GRVAL, 0x0e,
+  OUT, GRREG, 7, GRVAL, 0x00,
+  OUT, GRREG, 8, GRVAL, 0xff,
+
+  /* Reset attribute flip/flop */
+  IN, ATTRREG, 0, 0, 0,
+
+  /* Palette */
+  OUT, PALREG, 0, PALREG, 0x00,
+  OUT, PALREG, 1, PALREG, 0x01,
+  OUT, PALREG, 2, PALREG, 0x02,
+  OUT, PALREG, 3, PALREG, 0x03,
+  OUT, PALREG, 4, PALREG, 0x04,
+  OUT, PALREG, 5, PALREG, 0x05,
+  OUT, PALREG, 6, PALREG, 0x06,
+  OUT, PALREG, 7, PALREG, 0x07,
+  OUT, PALREG, 8, PALREG, 0x10,
+  OUT, PALREG, 9, PALREG, 0x11,
+  OUT, PALREG, 10, PALREG, 0x12,
+  OUT, PALREG, 11, PALREG, 0x13,
+  OUT, PALREG, 12, PALREG, 0x14,
+  OUT, PALREG, 13, PALREG, 0x15,
+  OUT, PALREG, 14, PALREG, 0x16,
+  OUT, PALREG, 15, PALREG, 0x17,
+  OUT, PALREG, 16, PALREG, 0x08,
+  OUT, PALREG, 17, PALREG, 0x00,
+  OUT, PALREG, 18, PALREG, 0x0f,
+  OUT, PALREG, 19, PALREG, 0x00,
+
+  /* Enable palette */
+  OUT, PALREG, 0x20, 0, 0,
+
+  /* End of table */
+  DONE, 0, 0, 0, 0
+};
+
+#endif
+
+#if VGA_STANDARD
+
+/* VGA 640x480 16-color graphics (BIOS mode 0x12).
+ */
+static REGIO graphics_on[] = {
+  /* Reset attr F/F */
+  { IN, ATTRREG, 0, 0, 0 },
+
+  /* Disable palette */
+  { OUT, PALREG, 0, 0, 0 },
+
+  /* Reset sequencer regs */
+  { OUT, SEQREG, 0, SEQVAL, 0 },
+  { OUT, SEQREG, 1, SEQVAL, 1 },
+  { OUT, SEQREG, 2, SEQVAL, 0x0f },
+  { OUT, SEQREG, 3, SEQVAL, 0 },
+  { OUT, SEQREG, 4, SEQVAL, 6 },
+
+  /* Misc out reg */
+  { OUT, GENREG1, 0xe3, 0, 0 },
+
+  /* Sequencer enable */
+  { OUT, SEQREG, 0, SEQVAL, 0x03 },
+
+  /* Unprotect crtc regs 0-7 */
+  { OUT, CRTCREG, 0x11, CRTCVAL, 0 },
+
+  /* Crtc */
+  { OUT, CRTCREG, 0, CRTCVAL, 0x5f },
+  { OUT, CRTCREG, 1, CRTCVAL, 0x4f },
+  { OUT, CRTCREG, 2, CRTCVAL, 0x50 },
+  { OUT, CRTCREG, 3, CRTCVAL, 0x82 },
+  { OUT, CRTCREG, 4, CRTCVAL, 0x54 },
+  { OUT, CRTCREG, 5, CRTCVAL, 0x80 },
+  { OUT, CRTCREG, 6, CRTCVAL, 0x0b },
+  { OUT, CRTCREG, 7, CRTCVAL, 0x3e },
+  { OUT, CRTCREG, 8, CRTCVAL, 0x00 },
+  { OUT, CRTCREG, 9, CRTCVAL, 0x40 },
+  { OUT, CRTCREG, 10, CRTCVAL, 0x00 },
+  { OUT, CRTCREG, 11, CRTCVAL, 0x00 },
+  { OUT, CRTCREG, 12, CRTCVAL, 0x00 },
+  { OUT, CRTCREG, 13, CRTCVAL, 0x00 },
+  { OUT, CRTCREG, 14, CRTCVAL, 0x00 },
+  { OUT, CRTCREG, 15, CRTCVAL, 0x59 },
+  { OUT, CRTCREG, 16, CRTCVAL, 0xea },
+  { OUT, CRTCREG, 17, CRTCVAL, 0x8c },
+  { OUT, CRTCREG, 18, CRTCVAL, 0xdf },
+  { OUT, CRTCREG, 19, CRTCVAL, 0x28 },
+  { OUT, CRTCREG, 20, CRTCVAL, 0x00 },
+  { OUT, CRTCREG, 21, CRTCVAL, 0xe7 },
+  { OUT, CRTCREG, 22, CRTCVAL, 0x04 },
+  { OUT, CRTCREG, 23, CRTCVAL, 0xe3 },
+  { OUT, CRTCREG, 24, CRTCVAL, 0xff },
+
+  /* Graphics controller */
+  { OUT, GENREG2, 0x00, 0, 0 },
+  { OUT, GENREG3, 0x01, 0, 0 },
+  { OUT, GRREG, 0, GRVAL, 0x00 },
+  { OUT, GRREG, 1, GRVAL, 0x00 },
+  { OUT, GRREG, 2, GRVAL, 0x00 },
+  { OUT, GRREG, 3, GRVAL, 0x00 },
+  { OUT, GRREG, 4, GRVAL, 0x00 },
+  { OUT, GRREG, 5, GRVAL, 0x00 },
+  { OUT, GRREG, 6, GRVAL, 0x05 },
+  { OUT, GRREG, 7, GRVAL, 0x0f },
+  { OUT, GRREG, 8, GRVAL, 0xff },
+
+  /* Reset attribute flip/flop */
+  { IN, ATTRREG, 0, 0, 0 },
+
+  /* Palette */
+  { OUT, PALREG, 0, PALREG, 0x00 },
+  { OUT, PALREG, 1, PALREG, 0x01 },
+  { OUT, PALREG, 2, PALREG, 0x02 },
+  { OUT, PALREG, 3, PALREG, 0x03 },
+  { OUT, PALREG, 4, PALREG, 0x04 },
+  { OUT, PALREG, 5, PALREG, 0x05 },
+  { OUT, PALREG, 6, PALREG, 0x06 },
+  { OUT, PALREG, 7, PALREG, 0x07 },
+  { OUT, PALREG, 8, PALREG, 0x38 },
+  { OUT, PALREG, 9, PALREG, 0x39 },
+  { OUT, PALREG, 10, PALREG, 0x3a },
+  { OUT, PALREG, 11, PALREG, 0x3b },
+  { OUT, PALREG, 12, PALREG, 0x3c },
+  { OUT, PALREG, 13, PALREG, 0x3d },
+  { OUT, PALREG, 14, PALREG, 0x3e },
+  { OUT, PALREG, 15, PALREG, 0x3f },
+  { OUT, PALREG, 16, PALREG, 0x01 },
+  { OUT, PALREG, 17, PALREG, 0x00 },
+  { OUT, PALREG, 18, PALREG, 0x0f },
+  { OUT, PALREG, 19, PALREG, 0x00 },
+
+  /* Enable palette */
+  { OUT, PALREG, 0x20, 0, 0 },
+
+  /* End of table */
+  { DONE, 0, 0, 0, 0 }
+};
+
+/* VGA 80x25 text (BIOS mode 3).
+ */
+static REGIO graph_off[] = {
+  /* Reset attr F/F */
+  { IN, ATTRREG, 0, 0, 0 },
+
+  /* Disable palette */
+  { OUT, PALREG, 0, 0, 0 },
+
+  /* Reset sequencer regs */
+  { OUT, SEQREG, 0, SEQVAL, 1 },
+  { OUT, SEQREG, 1, SEQVAL, 1 },
+  { OUT, SEQREG, 2, SEQVAL, 3 },
+  { OUT, SEQREG, 3, SEQVAL, 0 },
+  { OUT, SEQREG, 4, SEQVAL, 2 },
+
+  /* Misc out reg */
+  { OUT, GENREG1, 0x63, 0, 0 },
+
+  /* Sequencer enable */
+  { OUT, SEQREG, 0, SEQVAL, 3 },
+
+  /* Unprotect crtc regs 0-7 */
+  { OUT, CRTCREG, 0x11, CRTCVAL, 0 },
+
+  /* Crtc */
+  { OUT, CRTCREG, 0, CRTCVAL, 0x5f },	/* horiz total */
+  { OUT, CRTCREG, 1, CRTCVAL, 0x4f },	/* horiz end */
+  { OUT, CRTCREG, 2, CRTCVAL, 0x50 },	/* horiz blank */
+  { OUT, CRTCREG, 3, CRTCVAL, 0x82 },	/* end blank */
+  { OUT, CRTCREG, 4, CRTCVAL, 0x55 },	/* horiz retrace */
+  { OUT, CRTCREG, 5, CRTCVAL, 0x81 },	/* end retrace */
+  { OUT, CRTCREG, 6, CRTCVAL, 0xbf },	/* vert total */
+  { OUT, CRTCREG, 7, CRTCVAL, 0x1f },	/* overflows */
+  { OUT, CRTCREG, 8, CRTCVAL, 0x00 },	/* row scan */
+  { OUT, CRTCREG, 9, CRTCVAL, 0x4f },	/* max scan line */
+  { OUT, CRTCREG, 10, CRTCVAL, 0x00 },	/* cursor start */
+  { OUT, CRTCREG, 11, CRTCVAL, 0x0f },	/* cursor end */
+  { OUT, CRTCREG, 12, CRTCVAL, 0x0e },	/* start high addr */
+  { OUT, CRTCREG, 13, CRTCVAL, 0xb0 },	/* low addr */
+  { OUT, CRTCREG, 14, CRTCVAL, 0x16 },	/* cursor high */
+  { OUT, CRTCREG, 15, CRTCVAL, 0x30 },	/* cursor low */
+  { OUT, CRTCREG, 16, CRTCVAL, 0x9c },	/* vert retrace */
+  { OUT, CRTCREG, 17, CRTCVAL, 0x8e },	/* retrace end */
+  { OUT, CRTCREG, 18, CRTCVAL, 0x8f },	/* vert end */
+  { OUT, CRTCREG, 19, CRTCVAL, 0x28 },	/* offset */
+  { OUT, CRTCREG, 20, CRTCVAL, 0x1f },	/* underline */
+  { OUT, CRTCREG, 21, CRTCVAL, 0x96 },	/* vert blank */
+  { OUT, CRTCREG, 22, CRTCVAL, 0xb9 },	/* end blank */
+  { OUT, CRTCREG, 23, CRTCVAL, 0xa3 },	/* crt mode */
+  { OUT, CRTCREG, 24, CRTCVAL, 0xff },	/* line compare */
+
+  /* Graphics controller */
+  { OUT, GENREG2, 0x00, 0, 0 },
+  { OUT, GENREG3, 0x01, 0, 0 },
+  { OUT, GRREG, 0, GRVAL, 0x00 },
+  { OUT, GRREG, 1, GRVAL, 0x00 },
+  { OUT, GRREG, 2, GRVAL, 0x00 },
+  { OUT, GRREG, 3, GRVAL, 0x00 },
+  { OUT, GRREG, 4, GRVAL, 0x00 },
+  { OUT, GRREG, 5, GRVAL, 0x10 },
+  { OUT, GRREG, 6, GRVAL, 0x0e },
+  { OUT, GRREG, 7, GRVAL, 0x00 },
+  { OUT, GRREG, 8, GRVAL, 0xff },
+
+  /* Reset attribute flip/flop */
+  { IN, ATTRREG, 0, 0, 0 },
+
+  /* Palette */
+  { OUT, PALREG, 0, PALREG, 0x00 },
+  { OUT, PALREG, 1, PALREG, 0x01 },
+  { OUT, PALREG, 2, PALREG, 0x02 },
+  { OUT, PALREG, 3, PALREG, 0x03 },
+  { OUT, PALREG, 4, PALREG, 0x04 },
+  { OUT, PALREG, 5, PALREG, 0x05 },
+  { OUT, PALREG, 6, PALREG, 0x06 },
+  { OUT, PALREG, 7, PALREG, 0x07 },
+  { OUT, PALREG, 8, PALREG, 0x10 },
+  { OUT, PALREG, 9, PALREG, 0x11 },
+  { OUT, PALREG, 10, PALREG, 0x12 },
+  { OUT, PALREG, 11, PALREG, 0x13 },
+  { OUT, PALREG, 12, PALREG, 0x14 },
+  { OUT, PALREG, 13, PALREG, 0x15 },
+  { OUT, PALREG, 14, PALREG, 0x16 },
+  { OUT, PALREG, 15, PALREG, 0x17 },
+  { OUT, PALREG, 16, PALREG, 0x08 },
+  { OUT, PALREG, 17, PALREG, 0x00 },
+  { OUT, PALREG, 18, PALREG, 0x0f },
+  { OUT, PALREG, 19, PALREG, 0x00 },
+
+  /* Enable palette */
+  { OUT, PALREG, 0x20, 0, 0 },
+
+  /* End of table */
+  { DONE, 0, 0, 0, 0 }
+};
+
+#endif
+
+#if EGA_STANDARD
+
+/* EGA 640x350 16-color graphics (BIOS mode 0x10).
+ */
+static REGIO graphics_on[] = {
+  /* Reset attr F/F */
+  IN, ATTRREG, 0, 0, 0,
+
+  /* Disable palette */
+  OUT, PALREG, 0, 0, 0,
+
+  /* Reset sequencer regs */
+  OUT, SEQREG, 0, SEQVAL, 0,
+  OUT, SEQREG, 1, SEQVAL, 1,
+  OUT, SEQREG, 2, SEQVAL, 0x0f,
+  OUT, SEQREG, 3, SEQVAL, 0,
+  OUT, SEQREG, 4, SEQVAL, 6,
+
+  /* Misc out reg */
+  OUT, GENREG1, 0xa7, 0, 0,
+
+  /* Sequencer enable */
+  OUT, SEQREG, 0, SEQVAL, 0x03,
+
+  /* Unprotect crtc regs 0-7 */
+  OUT, CRTCREG, 0x11, CRTCVAL, 0,
+
+  /* Crtc */
+  OUT, CRTCREG, 0, CRTCVAL, 0x5b,
+  OUT, CRTCREG, 1, CRTCVAL, 0x4f,
+  OUT, CRTCREG, 2, CRTCVAL, 0x53,
+  OUT, CRTCREG, 3, CRTCVAL, 0x37,
+  OUT, CRTCREG, 4, CRTCVAL, 0x52,
+  OUT, CRTCREG, 5, CRTCVAL, 0x00,
+  OUT, CRTCREG, 6, CRTCVAL, 0x6c,
+  OUT, CRTCREG, 7, CRTCVAL, 0x1f,
+  OUT, CRTCREG, 8, CRTCVAL, 0x00,
+  OUT, CRTCREG, 9, CRTCVAL, 0x00,
+  OUT, CRTCREG, 10, CRTCVAL, 0x00,
+  OUT, CRTCREG, 11, CRTCVAL, 0x00,
+  OUT, CRTCREG, 12, CRTCVAL, 0x00,
+  OUT, CRTCREG, 13, CRTCVAL, 0x00,
+  OUT, CRTCREG, 14, CRTCVAL, 0x00,
+  OUT, CRTCREG, 15, CRTCVAL, 0x00,
+  OUT, CRTCREG, 16, CRTCVAL, 0x5e,
+  OUT, CRTCREG, 17, CRTCVAL, 0x2b,
+  OUT, CRTCREG, 18, CRTCVAL, 0x5d,
+  OUT, CRTCREG, 19, CRTCVAL, 0x28,
+  OUT, CRTCREG, 20, CRTCVAL, 0x0f,
+  OUT, CRTCREG, 21, CRTCVAL, 0x5f,
+  OUT, CRTCREG, 22, CRTCVAL, 0x0a,
+  OUT, CRTCREG, 23, CRTCVAL, 0xe3,
+  OUT, CRTCREG, 24, CRTCVAL, 0xff,
+
+  /* Graphics controller */
+  OUT, GENREG2, 0x00, 0, 0,
+  OUT, GENREG3, 0x01, 0, 0,
+  OUT, GRREG, 0, GRVAL, 0x00,
+  OUT, GRREG, 1, GRVAL, 0x00,
+  OUT, GRREG, 2, GRVAL, 0x00,
+  OUT, GRREG, 3, GRVAL, 0x00,
+  OUT, GRREG, 4, GRVAL, 0x00,
+  OUT, GRREG, 5, GRVAL, 0x00,
+  OUT, GRREG, 6, GRVAL, 0x05,
+  OUT, GRREG, 7, GRVAL, 0x0f,
+  OUT, GRREG, 8, GRVAL, 0xff,
+
+  /* Reset attribute flip/flop */
+  IN, ATTRREG, 0, 0, 0,
+
+  /* Palette */
+  OUT, PALREG, 0, PALREG, 0x00,
+  OUT, PALREG, 1, PALREG, 0x01,
+  OUT, PALREG, 2, PALREG, 0x02,
+  OUT, PALREG, 3, PALREG, 0x03,
+  OUT, PALREG, 4, PALREG, 0x04,
+  OUT, PALREG, 5, PALREG, 0x05,
+  OUT, PALREG, 6, PALREG, 0x06,
+  OUT, PALREG, 7, PALREG, 0x07,
+  OUT, PALREG, 8, PALREG, 0x38,
+  OUT, PALREG, 9, PALREG, 0x39,
+  OUT, PALREG, 10, PALREG, 0x3a,
+  OUT, PALREG, 11, PALREG, 0x3b,
+  OUT, PALREG, 12, PALREG, 0x3c,
+  OUT, PALREG, 13, PALREG, 0x3d,
+  OUT, PALREG, 14, PALREG, 0x3e,
+  OUT, PALREG, 15, PALREG, 0x3f,
+  OUT, PALREG, 16, PALREG, 0x01,
+  OUT, PALREG, 17, PALREG, 0x00,
+  OUT, PALREG, 18, PALREG, 0x0f,
+  OUT, PALREG, 19, PALREG, 0x00,
+
+  /* Enable palette */
+  OUT, PALREG, 0x20, 0, 0,
+
+  /* End of table */
+  DONE, 0, 0, 0, 0
+};
+
+/* EGA 80x25 text (BIOS mode 3).
+ */
+static REGIO graph_off[] = {
+  /* Reset attr F/F */
+  IN, ATTRREG, 0, 0, 0,
+
+  /* Disable palette */
+  OUT, PALREG, 0, 0, 0,
+
+  /* Reset sequencer regs */
+  OUT, SEQREG, 0, SEQVAL, 1,
+  OUT, SEQREG, 1, SEQVAL, 1,
+  OUT, SEQREG, 2, SEQVAL, 3,
+  OUT, SEQREG, 3, SEQVAL, 0,
+  OUT, SEQREG, 4, SEQVAL, 3,
+
+  /* Misc out reg */
+  OUT, GENREG1, 0xa7, 0, 0,
+
+  /* Sequencer enable */
+  OUT, SEQREG, 0, SEQVAL, 3,
+
+  /* Crtc */
+  OUT, CRTCREG, 0, CRTCVAL, 0x5b,	/* horiz total */
+  OUT, CRTCREG, 1, CRTCVAL, 0x4f,	/* horiz end */
+  OUT, CRTCREG, 2, CRTCVAL, 0x53,	/* horiz blank */
+  OUT, CRTCREG, 3, CRTCVAL, 0x37,	/* end blank */
+  OUT, CRTCREG, 4, CRTCVAL, 0x51,	/* horiz retrace */
+  OUT, CRTCREG, 5, CRTCVAL, 0x5b,	/* end retrace */
+  OUT, CRTCREG, 6, CRTCVAL, 0x6c,	/* vert total */
+  OUT, CRTCREG, 7, CRTCVAL, 0x1f,	/* overflows */
+  OUT, CRTCREG, 8, CRTCVAL, 0x00,	/* row scan */
+  OUT, CRTCREG, 9, CRTCVAL, 0x0d,	/* max scan line */
+  OUT, CRTCREG, 10, CRTCVAL, 0x00,	/* cursor start */
+  OUT, CRTCREG, 11, CRTCVAL, 0x0f,	/* cursor end */
+  OUT, CRTCREG, 12, CRTCVAL, 0x00,	/* start high addr */
+  OUT, CRTCREG, 13, CRTCVAL, 0x00,	/* low addr */
+  OUT, CRTCREG, 14, CRTCVAL, 0x00,	/* cursor high */
+  OUT, CRTCREG, 15, CRTCVAL, 0x00,	/* cursor low */
+  OUT, CRTCREG, 16, CRTCVAL, 0x5e,	/* vert retrace */
+  OUT, CRTCREG, 17, CRTCVAL, 0x2b,	/* retrace end */
+  OUT, CRTCREG, 18, CRTCVAL, 0x5d,	/* vert end */
+  OUT, CRTCREG, 19, CRTCVAL, 0x28,	/* offset */
+  OUT, CRTCREG, 20, CRTCVAL, 0x0f,	/* underline */
+  OUT, CRTCREG, 21, CRTCVAL, 0x5e,	/* vert blank */
+  OUT, CRTCREG, 22, CRTCVAL, 0x0a,	/* end blank */
+  OUT, CRTCREG, 23, CRTCVAL, 0xa3,	/* crt mode */
+  OUT, CRTCREG, 24, CRTCVAL, 0xff,	/* line compare */
+
+  /* Graphics controller */
+  OUT, GENREG2, 0x00, 0, 0,
+  OUT, GENREG3, 0x01, 0, 0,
+  OUT, GRREG, 0, GRVAL, 0x00,
+  OUT, GRREG, 1, GRVAL, 0x00,
+  OUT, GRREG, 2, GRVAL, 0x00,
+  OUT, GRREG, 3, GRVAL, 0x00,
+  OUT, GRREG, 4, GRVAL, 0x00,
+  OUT, GRREG, 5, GRVAL, 0x10,
+  OUT, GRREG, 6, GRVAL, 0x0e,
+  OUT, GRREG, 7, GRVAL, 0x00,
+  OUT, GRREG, 8, GRVAL, 0xff,
+
+  /* Reset attribute flip/flop */
+  IN, ATTRREG, 0, 0, 0,
+
+  /* Palette */
+  OUT, PALREG, 0, PALREG, 0x00,
+  OUT, PALREG, 1, PALREG, 0x01,
+  OUT, PALREG, 2, PALREG, 0x02,
+  OUT, PALREG, 3, PALREG, 0x03,
+  OUT, PALREG, 4, PALREG, 0x04,
+  OUT, PALREG, 5, PALREG, 0x05,
+  OUT, PALREG, 6, PALREG, 0x14,
+  OUT, PALREG, 7, PALREG, 0x07,
+  OUT, PALREG, 8, PALREG, 0x38,
+  OUT, PALREG, 9, PALREG, 0x39,
+  OUT, PALREG, 10, PALREG, 0x3a,
+  OUT, PALREG, 11, PALREG, 0x3b,
+  OUT, PALREG, 12, PALREG, 0x3c,
+  OUT, PALREG, 13, PALREG, 0x3d,
+  OUT, PALREG, 14, PALREG, 0x3e,
+  OUT, PALREG, 15, PALREG, 0x3f,
+  OUT, PALREG, 16, PALREG, 0x08,
+  OUT, PALREG, 17, PALREG, 0x00,
+  OUT, PALREG, 18, PALREG, 0x0f,
+  OUT, PALREG, 19, PALREG, 0x00,
+
+  /* Enable palette */
+  OUT, PALREG, 0x20, 0, 0,
+
+  /* End of table */
+  DONE, 0, 0, 0, 0
+};
+
+#endif
Index: bsps/i386/pc386/console/videoAsm.S
===================================================================
--- bsps/i386/pc386/console/videoAsm.S	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
+++ bsps/i386/pc386/console/videoAsm.S	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
@@ -0,0 +1,48 @@
+/*
+ * videoAsm.S  - This file contains code for displaying cursor on the console
+ *
+ * Copyright (C) 1998  valette@crf.canon.fr
+ *
+ * This code is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This code is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+	.file "videoAsm.s"
+
+#include <crt.h>
+
+	.text
+	.align 4
+    	.globl  wr_cursor	/* Move cursor position */
+
+/*
+ *   	void wr_cursor(newPosition, ioBaseAddr)
+ */
+
+wr_cursor:	pushl	%ecx
+		movl	8(%esp), %ecx		/* Get new cursor position */
+		movb	$CC_CURSHIGH, %al	/* Cursor high location */
+		movl	12(%esp), %edx		/* Get IO base address */
+		outb	(%dx)
+		incw	%dx			/* Program Data register */
+		movb	%ch, %al
+		outb	(%dx)			/* Update high location cursor */
+		decw	%dx			/* Program Index Register */
+		movb	$CC_CURSLOW, %al	/* Cursor low location */
+		outb	(%dx)
+		incw	%dx			/* Program Data Register */
+		movb	%cl, %al
+		outb	(%dx)			/* Update low location cursor */
+		popl	%ecx
+		ret
Index: bsps/i386/pc386/console/vt.c
===================================================================
--- bsps/i386/pc386/console/vt.c	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
+++ bsps/i386/pc386/console/vt.c	(revision d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc)
@@ -0,0 +1,348 @@
+/*
+ *  linux/drivers/char/vt.c
+ *
+ *  Copyright (C) 1992 obz under the linux copyright
+ *
+ *  Dynamic diacritical handling - aeb@cwi.nl - Dec 1993
+ *  Dynamic keymap and string allocation - aeb@cwi.nl - May 1994
+ *  Restrict VT switching via ioctl() - grif@cs.ucr.edu - Dec 1995
+ *  Some code moved for less code duplication - Andi Kleen - Mar 1997
+ *
+ *
+ * by: Rosimildo da Silva --
+ * Ported to RTEMS to provide the basic interface to the console
+ * driver. Removed all stuff not required, such as VT_, Fonts, etc.
+ */
+
+#include <string.h>  /* memcpy */
+#include <sys/types.h>
+#include <errno.h>
+
+#include <bsp.h>
+#include <i386_io.h>
+#include <rtems.h>
+#include <rtems/kd.h>
+#include <rtems/keyboard.h>
+
+/*
+ * Console (vt and kd) routines, as defined by USL SVR4 manual, and by
+ * experimentation and study of X386 SYSV handling.
+ *
+ * One point of difference: SYSV vt's are /dev/vtX, which X >= 0, and
+ * /dev/console is a separate ttyp. Under Linux, /dev/tty0 is /dev/console,
+ * and the vc start at /dev/ttyX, X >= 1. We maintain that here, so we will
+ * always treat our set of vt as numbered 1..MAX_NR_CONSOLES (corresponding to
+ * ttys 0..MAX_NR_CONSOLES-1). Explicitly naming VT 0 is illegal, but using
+ * /dev/tty0 (fg_console) as a target is legal, since an implicit aliasing
+ * to the current console is done by the main ioctl code.
+ */
+
+struct vt_struct *vt_cons[MAX_NR_CONSOLES];
+
+/* Keyboard type: Default is KB_101, but can be set by machine
+ * specific code.
+ */
+unsigned char keyboard_type = KB_101;
+
+/*
+ * Generates sound of some frequency for some number of clock ticks
+ *
+ * If freq is 0, will turn off sound, else will turn it on for that time.
+ * If msec is 0, will return immediately, else will sleep for msec time, then
+ * turn sound off.
+ *
+ * We also return immediately, which is what was implied within the X
+ * comments - KDMKTONE doesn't put the process to sleep.
+ */
+
+#if defined(__i386__) || defined(__alpha__) || defined(__powerpc__) \
+    || (defined(__mips__) && !defined(CONFIG_SGI))
+
+static void
+kd_nosound(unsigned long ignored)
+{
+  /* disable counter 2 */
+  outb(inb_p(0x61)&0xFC, 0x61);
+  return;
+}
+
+static void
+_kd_mksound(unsigned int hz, unsigned int ticks)
+{
+  unsigned int          count = 0;
+  rtems_interrupt_lock_context lock_context;
+
+  if (hz > 20 && hz < 32767)
+    count = 1193180 / hz;
+
+  rtems_interrupt_lock_acquire(&rtems_i386_i8254_access_lock, &lock_context);
+/*  del_timer(&sound_timer);  */
+  if (count) {
+    /* enable counter 2 */
+    outb_p(inb_p(0x61)|3, 0x61);
+    /* set command for counter 2, 2 byte write */
+    outb_p(0xB6, TIMER_MODE);
+    /* select desired HZ */
+    outb_p(count & 0xff, TIMER_CNTR2);
+    outb((count >> 8) & 0xff, TIMER_CNTR2);
+
+/*
+    if (ticks) {
+      sound_timer.expires = jiffies+ticks;
+      add_timer(&sound_timer);
+    }
+*/
+  } else
+    kd_nosound(0);
+
+  rtems_interrupt_lock_release(&rtems_i386_i8254_access_lock, &lock_context);
+  return;
+}
+
+#else
+
+void
+_kd_mksound(unsigned int hz, unsigned int ticks)
+{
+}
+
+#endif
+
+void (*kd_mksound)(unsigned int hz, unsigned int ticks) = _kd_mksound;
+
+#define i (tmp.kb_index)
+#define s (tmp.kb_table)
+#define v (tmp.kb_value)
+static inline int
+do_kdsk_ioctl(int cmd, struct kbentry *user_kbe, int perm, struct kbd_struct *kbd)
+{
+  struct kbentry tmp;
+  ushort *key_map, val;
+
+  tmp = *user_kbe;
+  if (i >= NR_KEYS)  /*  s cannot be >= MAX_NR_KEYMAPS */
+    return -EINVAL;
+
+  switch (cmd) {
+  case KDGKBENT:
+    key_map = key_maps[s];
+    if (key_map) {
+        val = U(key_map[i]);
+        if (kbd->kbdmode != VC_UNICODE && KTYP(val) >= NR_TYPES)
+      val = K_HOLE;
+    } else
+        val = (i ? K_HOLE : K_NOSUCHMAP);
+    user_kbe->kb_value = val;
+    return 0;
+
+  case KDSKBENT:
+    return -EINVAL;
+  }
+  return 0;
+}
+#undef i
+#undef s
+#undef v
+
+#define  HZ  100
+
+static inline int
+do_kbkeycode_ioctl(int cmd, struct kbkeycode *user_kbkc, int perm)
+{
+  struct kbkeycode tmp;
+  int kc = 0;
+
+  tmp = *user_kbkc;
+  switch (cmd) {
+  case KDGETKEYCODE:
+    kc = getkeycode(tmp.scancode);
+    if (kc >= 0)
+      user_kbkc->keycode = kc;
+    break;
+  case KDSETKEYCODE:
+    if (!perm)
+      return -EPERM;
+    kc = setkeycode(tmp.scancode, tmp.keycode);
+    break;
+  }
+  return kc;
+}
+
+static inline int
+do_kdgkb_ioctl(int cmd, struct kbsentry *user_kdgkb, int perm)
+{
+  return -EINVAL;
+}
+
+/*
+ * We handle the console-specific ioctl's here.  We allow the
+ * capability to modify any console, not just the fg_console.
+ */
+int vt_ioctl( unsigned int cmd, unsigned long arg)
+{
+  int perm;
+  unsigned int console;
+  unsigned char ucval;
+  struct kbd_struct * kbd;
+
+   console = 0;
+  /*
+   * To have permissions to do most of the vt ioctls, we either have
+   * to be the owner of the tty, or super-user.
+   */
+  perm = 1;
+  kbd = kbd_table + console;
+  switch (cmd) {
+  case KIOCSOUND:
+    if (!perm)
+      return -EPERM;
+    if (arg)
+      arg = 1193180 / arg;
+    kd_mksound(arg, 0);
+    return 0;
+
+  case KDMKTONE:
+    if (!perm)
+      return -EPERM;
+  {
+    unsigned int ticks, count;
+
+    /*
+     * Generate the tone for the appropriate number of ticks.
+     * If the time is zero, turn off sound ourselves.
+     */
+    ticks = HZ * ((arg >> 16) & 0xffff) / 1000;
+    count = ticks ? (arg & 0xffff) : 0;
+    if (count)
+      count = 1193180 / count;
+    kd_mksound(count, ticks);
+    return 0;
+  }
+
+  case KDGKBTYPE:
+    /*
+     * this is naive.
+     */
+    ucval = keyboard_type;
+    goto setchar;
+
+  case KDSETMODE:
+  case KDGETMODE:
+    return -EINVAL;
+
+  case KDSKBMODE:
+    if (!perm)
+      return -EPERM;
+    switch(arg) {
+      case K_RAW:
+      kbd->kbdmode = VC_RAW;
+      break;
+      case K_MEDIUMRAW:
+      kbd->kbdmode = VC_MEDIUMRAW;
+      break;
+      case K_XLATE:
+      kbd->kbdmode = VC_XLATE;
+      compute_shiftstate();
+      break;
+      case K_UNICODE:
+      kbd->kbdmode = VC_UNICODE;
+      compute_shiftstate();
+      break;
+      default:
+      return -EINVAL;
+    }
+    return 0;
+
+  case KDGKBMODE:
+    ucval = ((kbd->kbdmode == VC_RAW) ? K_RAW :
+         (kbd->kbdmode == VC_MEDIUMRAW) ? K_MEDIUMRAW :
+         (kbd->kbdmode == VC_UNICODE) ? K_UNICODE :
+         K_XLATE);
+    goto setint;
+
+  /* this could be folded into KDSKBMODE, but for compatibility
+     reasons it is not so easy to fold KDGKBMETA into KDGKBMODE */
+  case KDSKBMETA:
+    switch(arg) {
+      case K_METABIT:
+      clr_vc_kbd_mode(kbd, VC_META);
+      break;
+      case K_ESCPREFIX:
+      set_vc_kbd_mode(kbd, VC_META);
+      break;
+      default:
+      return -EINVAL;
+    }
+    return 0;
+
+  case KDGKBMETA:
+    ucval = (vc_kbd_mode(kbd, VC_META) ? K_ESCPREFIX : K_METABIT);
+  setint:
+    *(int *)arg = ucval;
+    return 0;
+
+  case KDGETKEYCODE:
+  case KDSETKEYCODE:
+    return do_kbkeycode_ioctl(cmd, (struct kbkeycode *)arg, perm);
+
+  case KDGKBENT:
+  case KDSKBENT:
+    return do_kdsk_ioctl(cmd, (struct kbentry *)arg, perm, kbd);
+
+  case KDGKBDIACR:
+  {
+    struct kbdiacrs *a = (struct kbdiacrs *)arg;
+    a->kb_cnt = accent_table_size;
+    memcpy( a->kbdiacr, accent_table, accent_table_size*sizeof(struct kbdiacr) );
+    return 0;
+  }
+
+  case KDSKBDIACR:
+  {
+    struct kbdiacrs *a = (struct kbdiacrs *)arg;
+    unsigned int ct;
+
+    if (!perm)
+      return -EPERM;
+    ct = a->kb_cnt;
+    if (ct >= MAX_DIACR)
+      return -EINVAL;
+    accent_table_size = ct;
+    memcpy(accent_table, a->kbdiacr, ct*sizeof(struct kbdiacr));
+    return 0;
+  }
+
+  /* the ioctls below read/set the flags usually shown in the leds */
+  /* don't use them - they will go away without warning */
+  case KDGKBLED:
+    ucval = kbd->ledflagstate | (kbd->default_ledflagstate << 4);
+    goto setchar;
+
+  case KDSKBLED:
+    if (!perm)
+      return -EPERM;
+    if (arg & ~0x77)
+      return -EINVAL;
+    kbd->ledflagstate = (arg & 7);
+    kbd->default_ledflagstate = ((arg >> 4) & 7);
+    set_leds();
+    return 0;
+
+  /* the ioctls below only set the lights, not the functions */
+  /* for those, see KDGKBLED and KDSKBLED above */
+  case KDGETLED:
+    ucval = getledstate();
+  setchar:
+    *(char*)arg = ucval;
+      return 0;
+
+  case KDSETLED:
+    if (!perm)
+      return -EPERM;
+    setledstate(kbd, arg);
+    return 0;
+
+  default:
+    return -EINVAL;
+  }
+}
