Index: c/src/lib/libbsp/sparc/Makefile.am
===================================================================
--- c/src/lib/libbsp/sparc/Makefile.am	(revision 045de3556fd4b3eca1c0cbf2332711108c9869dc)
+++ c/src/lib/libbsp/sparc/Makefile.am	(revision c176410021c40e2596a08fadf21f53c5d0343924)
@@ -50,5 +50,8 @@
 EXTRA_DIST += shared/include/grspw_rasta.h
 
-# UART  (APBUART)
+# UART
+EXTRA_DIST += shared/uart/cons.c
+EXTRA_DIST += shared/uart/apbuart_cons.c
+EXTRA_DIST += shared/include/cons.h
 EXTRA_DIST += shared/uart/apbuart.c
 EXTRA_DIST += shared/uart/apbuart_pci.c
Index: c/src/lib/libbsp/sparc/leon3/Makefile.am
===================================================================
--- c/src/lib/libbsp/sparc/leon3/Makefile.am	(revision 045de3556fd4b3eca1c0cbf2332711108c9869dc)
+++ c/src/lib/libbsp/sparc/leon3/Makefile.am	(revision c176410021c40e2596a08fadf21f53c5d0343924)
@@ -80,4 +80,7 @@
 libbsp_a_SOURCES += ../../shared/console-termios.c
 libbsp_a_SOURCES += console/console.c
+libbsp_a_SOURCES += ../../sparc/shared/uart/cons.c
+libbsp_a_SOURCES += ../../sparc/shared/uart/apbuart_cons.c
+include_HEADERS += ../../sparc/shared/include/cons.h
 # debugio
 libbsp_a_SOURCES += console/printk_support.c
Index: c/src/lib/libbsp/sparc/leon3/include/bsp.h
===================================================================
--- c/src/lib/libbsp/sparc/leon3/include/bsp.h	(revision 045de3556fd4b3eca1c0cbf2332711108c9869dc)
+++ c/src/lib/libbsp/sparc/leon3/include/bsp.h	(revision c176410021c40e2596a08fadf21f53c5d0343924)
@@ -256,4 +256,5 @@
  */
 #define AMBAPPBUS_INFO_AVAIL          /* AMBAPP Bus driver */
+#define APBUART_INFO_AVAIL            /* APBUART Console driver */
 #define GPTIMER_INFO_AVAIL            /* GPTIMER Timer driver */
 
Index: c/src/lib/libbsp/sparc/leon3/include/leon.h
===================================================================
--- c/src/lib/libbsp/sparc/leon3/include/leon.h	(revision 045de3556fd4b3eca1c0cbf2332711108c9869dc)
+++ c/src/lib/libbsp/sparc/leon3/include/leon.h	(revision c176410021c40e2596a08fadf21f53c5d0343924)
@@ -86,4 +86,41 @@
 #define LEON_REG_TIMER_CONTROL_LD    0x00000004  /* 1 = load counter */
                                               /* 0 = no function */
+
+/*
+ *  The following defines the bits in the UART Control Registers.
+ */
+
+#define LEON_REG_UART_CONTROL_RTD  0x000000FF /* RX/TX data */
+
+/*
+ *  The following defines the bits in the LEON UART Status Register.
+ */
+
+#define LEON_REG_UART_STATUS_DR   0x00000001 /* Data Ready */
+#define LEON_REG_UART_STATUS_TSE  0x00000002 /* TX Send Register Empty */
+#define LEON_REG_UART_STATUS_THE  0x00000004 /* TX Hold Register Empty */
+#define LEON_REG_UART_STATUS_BR   0x00000008 /* Break Error */
+#define LEON_REG_UART_STATUS_OE   0x00000010 /* RX Overrun Error */
+#define LEON_REG_UART_STATUS_PE   0x00000020 /* RX Parity Error */
+#define LEON_REG_UART_STATUS_FE   0x00000040 /* RX Framing Error */
+#define LEON_REG_UART_STATUS_TF   0x00000200 /* FIFO Full */
+#define LEON_REG_UART_STATUS_ERR  0x00000078 /* Error Mask */
+
+/*
+ *  The following defines the bits in the LEON UART Control Register.
+ */
+
+#define LEON_REG_UART_CTRL_RE     0x00000001 /* Receiver enable */
+#define LEON_REG_UART_CTRL_TE     0x00000002 /* Transmitter enable */
+#define LEON_REG_UART_CTRL_RI     0x00000004 /* Receiver interrupt enable */
+#define LEON_REG_UART_CTRL_TI     0x00000008 /* Transmitter interrupt enable */
+#define LEON_REG_UART_CTRL_PS     0x00000010 /* Parity select */
+#define LEON_REG_UART_CTRL_PE     0x00000020 /* Parity enable */
+#define LEON_REG_UART_CTRL_FL     0x00000040 /* Flow control enable */
+#define LEON_REG_UART_CTRL_LB     0x00000080 /* Loop Back enable */
+#define LEON_REG_UART_CTRL_DB     0x00000800 /* Debug FIFO enable */
+#define LEON_REG_UART_CTRL_SI     0x00004000 /* TX shift register empty IRQ enable */
+#define LEON_REG_UART_CTRL_FA     0x80000000 /* FIFO Available */
+#define LEON_REG_UART_CTRL_FA_BIT 31
 
 /*
Index: c/src/lib/libbsp/sparc/leon3/preinstall.am
===================================================================
--- c/src/lib/libbsp/sparc/leon3/preinstall.am	(revision 045de3556fd4b3eca1c0cbf2332711108c9869dc)
+++ c/src/lib/libbsp/sparc/leon3/preinstall.am	(revision c176410021c40e2596a08fadf21f53c5d0343924)
@@ -110,4 +110,8 @@
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/tlib.h
 
+$(PROJECT_INCLUDE)/cons.h: ../../sparc/shared/include/cons.h $(PROJECT_INCLUDE)/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/cons.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/cons.h
+
 $(PROJECT_INCLUDE)/bsp/irq-generic.h: ../../shared/include/irq-generic.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/irq-generic.h
Index: c/src/lib/libbsp/sparc/shared/include/cons.h
===================================================================
--- c/src/lib/libbsp/sparc/shared/include/cons.h	(revision c176410021c40e2596a08fadf21f53c5d0343924)
+++ c/src/lib/libbsp/sparc/shared/include/cons.h	(revision c176410021c40e2596a08fadf21f53c5d0343924)
@@ -0,0 +1,42 @@
+/*  Console driver interface to UART drivers
+ *
+ *  - First console device that has System Console flag set will be
+ *    system console.
+ *  - If none of the registered console devices has system console set,
+ *    the first is registered device is used, unless it has 
+ *
+ *  COPYRIGHT (c) 2010.
+ *  Cobham Gaisler AB.
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ */
+
+#ifndef __CONS_H__
+#define __CONS_H__
+
+struct console_dev;
+
+#define CONSOLE_FLAG_SYSCON      0x01
+
+struct console_cons_ops {
+	void (*get_uart_attrs)(struct console_dev *, struct termios *t);
+};
+
+struct console_dev {
+	/* Set to non-zero if this UART should be system console and/or
+	 * debug console.
+	 */
+	int flags;
+	char *fsname; /* File system prefix */
+	const struct rtems_termios_callbacks *callbacks; /* TERMIOS Callbacks */
+	struct console_cons_ops ops;
+};
+
+extern void console_dev_register(struct console_dev *dev);
+#if 0
+extern void console_dev_unregister(struct console_dev *dev);
+#endif
+
+#endif
Index: c/src/lib/libbsp/sparc/shared/include/drvmgr/ambapp_bus.h
===================================================================
--- c/src/lib/libbsp/sparc/shared/include/drvmgr/ambapp_bus.h	(revision 045de3556fd4b3eca1c0cbf2332711108c9869dc)
+++ c/src/lib/libbsp/sparc/shared/include/drvmgr/ambapp_bus.h	(revision c176410021c40e2596a08fadf21f53c5d0343924)
@@ -29,4 +29,5 @@
 
 /*** Gaisler Hardware Device Driver IDs ***/
+#define DRIVER_AMBAPP_GAISLER_APBUART_ID       DRIVER_AMBAPP_ID(VENDOR_GAISLER, GAISLER_APBUART)
 #define DRIVER_AMBAPP_GAISLER_GPTIMER_ID       DRIVER_AMBAPP_ID(VENDOR_GAISLER, GAISLER_GPTIMER)
 
Index: c/src/lib/libbsp/sparc/shared/uart/apbuart_cons.c
===================================================================
--- c/src/lib/libbsp/sparc/shared/uart/apbuart_cons.c	(revision c176410021c40e2596a08fadf21f53c5d0343924)
+++ c/src/lib/libbsp/sparc/shared/uart/apbuart_cons.c	(revision c176410021c40e2596a08fadf21f53c5d0343924)
@@ -0,0 +1,677 @@
+/*  This file contains the driver for the GRLIB APBUART serial port. The driver
+ *  is implemented by using the cons.c console layer. Interrupt/Polling/Task
+ *  driven mode can be configured using driver resources:
+ *
+ *  - mode   (0=Polling, 1=Interrupt, 2=Task-Driven-Interrupt Mode)
+ *  - syscon (0=Force not Ssystem Console, 1=Suggest System Console)
+ *
+ *  The BSP define APBUART_INFO_AVAIL in order to add the info routine
+ *  used for debugging.
+ *
+ *  COPYRIGHT (c) 2010.
+ *  Cobham Gaisler AB.
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ */
+
+/******************* Driver manager interface ***********************/
+#include <bsp.h>
+#include <rtems/libio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <rtems/bspIo.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <drvmgr/drvmgr.h>
+#include <drvmgr/ambapp_bus.h>
+#include <apbuart.h>
+#include <ambapp.h>
+#include <grlib.h>
+#include <cons.h>
+#include <rtems/termiostypes.h>
+
+/*#define DEBUG 1  */
+
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...) 
+#endif
+
+/* LEON3 Low level transmit/receive functions provided by debug-uart code */
+extern void apbuart_outbyte_polled(
+  struct apbuart_regs *regs,
+  unsigned char ch,
+  int do_cr_on_newline,
+  int wait_sent);
+extern int apbuart_inbyte_nonblocking(struct apbuart_regs *regs);
+extern struct apbuart_regs *dbg_uart; /* The debug UART */
+
+struct apbuart_priv {
+	struct console_dev condev;
+	struct drvmgr_dev *dev;
+	struct apbuart_regs *regs;
+	char devName[32];
+	void *cookie;
+	int sending;
+	int mode;
+};
+
+/* TERMIOS Layer Callback functions */
+void apbuart_get_attributes(struct console_dev *condev, struct termios *t);
+int apbuart_set_attributes(int minor, const struct termios *t);
+ssize_t apbuart_write_polled(int minor, const char *buf, size_t len);
+int apbuart_pollRead(int minor);
+ssize_t apbuart_write_intr(int minor, const char *buf, size_t len);
+int apbuart_pollRead_task(int minor);
+int apbuart_firstOpen(int major, int minor, void *arg);
+int apbuart_lastClose(int major, int minor, void *arg);
+
+void apbuart_isr(void *arg);
+int apbuart_get_baud(struct apbuart_priv *uart);
+
+int apbuart_init1(struct drvmgr_dev *dev);
+#ifdef APBUART_INFO_AVAIL
+static int apbuart_info(
+	struct drvmgr_dev *dev,
+	void (*print_line)(void *p, char *str),
+	void *p, int, char *argv[]);
+#define APBUART_INFO_FUNC apbuart_info
+#else
+#define APBUART_INFO_FUNC NULL
+#endif
+
+struct drvmgr_drv_ops apbuart_ops = 
+{
+	.init = {apbuart_init1, NULL, NULL, NULL},
+	.remove = NULL,
+	.info = APBUART_INFO_FUNC
+};
+
+static struct amba_dev_id apbuart_ids[] =
+{
+	{VENDOR_GAISLER, GAISLER_APBUART},
+	{0, 0}		/* Mark end of table */
+};
+
+static struct amba_drv_info apbuart_drv_info =
+{
+	{
+		DRVMGR_OBJ_DRV,				/* Driver */
+		NULL,					/* Next driver */
+		NULL,					/* Device list */
+		DRIVER_AMBAPP_GAISLER_APBUART_ID,	/* Driver ID */
+		"APBUART_DRV",				/* Driver Name */
+		DRVMGR_BUS_TYPE_AMBAPP,			/* Bus Type */
+		&apbuart_ops,
+		NULL,					/* Funcs */
+		0,					/* No devices yet */
+		sizeof(struct apbuart_priv),		/*DrvMgr alloc private*/
+	},
+	&apbuart_ids[0]
+};
+
+void apbuart_cons_register_drv (void)
+{
+	DBG("Registering APBUART Console driver\n");
+	drvmgr_drv_register(&apbuart_drv_info.general);
+}
+
+/* Interrupt mode routines */
+static const rtems_termios_callbacks Callbacks_intr = {
+    apbuart_firstOpen,           /* firstOpen */
+    apbuart_lastClose,           /* lastClose */
+    NULL,                        /* pollRead */
+    apbuart_write_intr,          /* write */
+    apbuart_set_attributes,      /* setAttributes */
+    NULL,                        /* stopRemoteTx */
+    NULL,                        /* startRemoteTx */
+    TERMIOS_IRQ_DRIVEN           /* outputUsesInterrupts */
+};
+
+/* Polling mode routines */
+static const rtems_termios_callbacks Callbacks_task = {
+    apbuart_firstOpen,           /* firstOpen */
+    apbuart_lastClose,           /* lastClose */
+    apbuart_pollRead_task,       /* pollRead */
+    apbuart_write_intr,          /* write */
+    apbuart_set_attributes,      /* setAttributes */
+    NULL,                        /* stopRemoteTx */
+    NULL,                        /* startRemoteTx */
+    TERMIOS_TASK_DRIVEN          /* outputUsesInterrupts */
+};
+
+/* Polling mode routines */
+static const rtems_termios_callbacks Callbacks_poll = {
+    apbuart_firstOpen,           /* firstOpen */
+    apbuart_lastClose,           /* lastClose */
+    apbuart_pollRead,            /* pollRead */
+    apbuart_write_polled,        /* write */
+    apbuart_set_attributes,      /* setAttributes */
+    NULL,                        /* stopRemoteTx */
+    NULL,                        /* startRemoteTx */
+    TERMIOS_POLLED               /* outputUsesInterrupts */
+};
+
+int apbuart_init1(struct drvmgr_dev *dev)
+{
+	struct apbuart_priv *priv;
+	struct amba_dev_info *ambadev;
+	struct ambapp_core *pnpinfo;
+	union drvmgr_key_value *value;
+	char prefix[32];
+	unsigned int db;
+	static int first_uart = 1;
+
+	/* The default operation in AMP is to use APBUART[0] for CPU[0],
+	 * APBUART[1] for CPU[1] and so on. The remaining UARTs is not used
+	 * since we don't know how many CPU-cores there are. Note this only
+	 * affects the on-chip amba bus (the root bus). The user can override
+	 * the default resource sharing by defining driver resources for the
+	 * APBUART devices on each AMP OS instance.
+	 */
+#if defined(RTEMS_MULTIPROCESSING) && defined(LEON3)
+	if (drvmgr_on_rootbus(dev) && dev->minor_drv != LEON3_Cpu_Index &&
+	    drvmgr_keys_get(dev, NULL) != 0) {
+		/* User hasn't configured on-chip APBUART, leave it untouched */
+		return DRVMGR_EBUSY;
+	}
+#endif
+
+	DBG("APBUART[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name);
+	/* Private data was allocated and zeroed by driver manager */
+	priv = dev->priv;
+	if (!priv)
+		return DRVMGR_NOMEM;
+	priv->dev = dev;
+
+	/* Get device information from AMBA PnP information */
+	ambadev = (struct amba_dev_info *)priv->dev->businfo;
+	if (ambadev == NULL)
+		return -1;
+	pnpinfo = &ambadev->info;
+	priv->regs = (struct apbuart_regs *)pnpinfo->apb_slv->start;
+
+	/* Clear HW regs, leave baudrate register as it is */
+	priv->regs->status = 0;
+	/* leave debug bit, and Transmitter/receiver if this is the debug UART */
+#ifdef LEON3
+	if (priv->regs == dbg_uart) {
+		db = priv->regs->ctrl & (LEON_REG_UART_CTRL_DB |
+					LEON_REG_UART_CTRL_RE |
+					LEON_REG_UART_CTRL_TE |
+					LEON_REG_UART_CTRL_FL |
+					LEON_REG_UART_CTRL_PE |
+					LEON_REG_UART_CTRL_PS);
+	} else
+#endif
+		db = priv->regs->ctrl & LEON_REG_UART_CTRL_DB;
+
+	priv->regs->ctrl = db;
+
+	/* The system console and Debug console may depend on this device, so
+	 * initialize it straight away.
+	 *
+	 * We default to have System Console on first APBUART, user may override
+	 * this behaviour by setting the syscon option to 0.
+	 */
+	if (drvmgr_on_rootbus(dev) && first_uart) {
+		priv->condev.flags = CONSOLE_FLAG_SYSCON;
+		first_uart = 0;
+	} else {
+		priv->condev.flags = 0;
+	}
+
+	value = drvmgr_dev_key_get(priv->dev, "syscon", KEY_TYPE_INT);
+	if (value) {
+		if (value->i)
+			priv->condev.flags |= CONSOLE_FLAG_SYSCON;
+		else
+			priv->condev.flags &= ~CONSOLE_FLAG_SYSCON;
+	}
+
+	priv->condev.fsname = NULL;
+	priv->condev.ops.get_uart_attrs = apbuart_get_attributes;
+
+	/* Select 0=Polled, 1=IRQ, 2=Task-Driven UART Mode */
+	value = drvmgr_dev_key_get(priv->dev, "mode", KEY_TYPE_INT);
+	if (value)
+		priv->mode = value->i;
+	else
+		priv->mode = TERMIOS_POLLED;
+	if (priv->mode == TERMIOS_IRQ_DRIVEN) {
+		priv->condev.callbacks = &Callbacks_intr;
+	} else if (priv->mode == TERMIOS_TASK_DRIVEN) {
+		priv->condev.callbacks = &Callbacks_task;
+	} else {
+		priv->condev.callbacks = &Callbacks_poll;
+	}
+
+	/* Get Filesystem name prefix */
+	prefix[0] = '\0';
+	if (drvmgr_get_dev_prefix(dev, prefix)) {
+		/* Got special prefix, this means we have a bus prefix
+		 * And we should use our "bus minor"
+		 */
+		sprintf(priv->devName, "/dev/%sapbuart%d", prefix, dev->minor_bus);
+		priv->condev.fsname = priv->devName;
+	}
+
+	/* Register it as a console device, the console driver will register
+	 * a termios device as well
+	 */
+	console_dev_register(&priv->condev);
+
+	return DRVMGR_OK;
+}
+
+#ifdef APBUART_INFO_AVAIL
+static int apbuart_info(
+	struct drvmgr_dev *dev,
+	void (*print_line)(void *p, char *str),
+	void *p, int argc, char *argv[])
+{
+	struct apbuart_priv *priv = dev->priv;
+	char *str1;
+	char buf[64];
+
+	if (dev->priv == NULL)
+		return -DRVMGR_EINVAL;
+
+	if (priv->mode == TERMIOS_POLLED)
+		str1 = "TERMIOS_POLLED";
+	else if (priv->mode == TERMIOS_TASK_DRIVEN)
+		str1 = "TERMIOS_TASK_DRIVEN";
+	else if (priv->mode == TERMIOS_TASK_DRIVEN)
+		str1 = "TERMIOS_TASK_DRIVEN";
+	else
+		str1 = "BAD MODE";
+
+	sprintf(buf, "UART Mode:   %s", str1);
+	print_line(p, buf);
+	if (priv->condev.fsname) {
+		sprintf(buf, "FS Name:     %s", priv->condev.fsname);
+		print_line(p, buf);
+	}
+	sprintf(buf, "STATUS REG:  0x%x", priv->regs->status);
+	print_line(p, buf);
+	sprintf(buf, "CTRL REG:    0x%x", priv->regs->ctrl);
+	print_line(p, buf);
+	sprintf(buf, "SCALER REG:  0x%x  baud rate %d",
+				priv->regs->scaler, apbuart_get_baud(priv));
+	print_line(p, buf);
+
+	return DRVMGR_OK;
+}
+#endif
+
+#ifndef LEON3
+/* This routine transmits a character, it will busy-wait until on character
+ * fits in the APBUART Transmit FIFO
+ */
+void apbuart_outbyte_polled(
+  struct apbuart_regs *regs,
+  unsigned char ch,
+  int do_cr_on_newline,
+  int wait_sent)
+{
+send:
+	while ((regs->status & LEON_REG_UART_STATUS_THE) == 0) {
+		/* Lower bus utilization while waiting for UART */
+		asm volatile ("nop"::);	asm volatile ("nop"::);
+		asm volatile ("nop"::);	asm volatile ("nop"::);
+		asm volatile ("nop"::);	asm volatile ("nop"::);
+		asm volatile ("nop"::);	asm volatile ("nop"::);
+	}
+	regs->data = (unsigned int) ch;
+
+	if ((ch == '\n') && do_cr_on_newline) {
+		ch = '\r';
+		goto send;
+	}
+
+	/* Wait until the character has been sent? */
+	if (wait_sent) {
+		while ((regs->status & LEON_REG_UART_STATUS_THE) == 0)
+			;
+	}
+}
+
+/* This routine polls for one character, return EOF if no character is available */
+int apbuart_inbyte_nonblocking(struct apbuart_regs *regs)
+{
+	if (regs->status & LEON_REG_UART_STATUS_ERR) {
+		regs->status = ~LEON_REG_UART_STATUS_ERR;
+	}
+
+	if ((regs->status & LEON_REG_UART_STATUS_DR) == 0)
+		return EOF;
+
+	return (int)regs->data;
+}
+#endif
+
+int apbuart_firstOpen(int major, int minor, void *arg)
+{
+	struct apbuart_priv *uart = (struct apbuart_priv *)minor;
+	rtems_libio_open_close_args_t *ioarg = arg;
+
+	if ( ioarg && ioarg->iop )
+		uart->cookie = ioarg->iop->data1;
+	else
+		uart->cookie = NULL;
+
+	/* Enable TX/RX */
+	uart->regs->ctrl |= LEON_REG_UART_CTRL_RE | LEON_REG_UART_CTRL_TE;
+
+	if (uart->mode != TERMIOS_POLLED) {
+		/* Register interrupt and enable it */
+		drvmgr_interrupt_register(uart->dev, 0, "apbuart",
+						apbuart_isr, uart);
+
+		uart->sending = 0;
+		/* Turn on RX interrupts */
+		uart->regs->ctrl |= LEON_REG_UART_CTRL_RI;
+	}
+
+	return 0;
+}
+
+int apbuart_lastClose(int major, int minor, void *arg)
+{
+	struct apbuart_priv *uart = (struct apbuart_priv *)minor;
+
+	if (uart->mode != TERMIOS_POLLED) {
+		/* Turn off RX interrupts */
+		uart->regs->ctrl &= ~(LEON_REG_UART_CTRL_RI);
+
+		/**** Flush device ****/
+		while (uart->sending) {
+			/* Wait until all data has been sent */
+		}
+
+		/* Disable and unregister interrupt handler */
+		drvmgr_interrupt_unregister(uart->dev, 0, apbuart_isr, uart);
+	}
+
+#ifdef LEON3
+	/* Disable TX/RX if not used for DEBUG */
+	if (uart->regs != dbg_uart)
+		uart->regs->ctrl &= ~(LEON_REG_UART_CTRL_RE | LEON_REG_UART_CTRL_TE);
+#endif
+
+	return 0;
+}
+
+int apbuart_pollRead(int minor)
+{
+	struct apbuart_priv *uart = (struct apbuart_priv *)minor;
+
+	return apbuart_inbyte_nonblocking(uart->regs);
+}
+
+int apbuart_pollRead_task(int minor)
+{
+	struct apbuart_priv *uart = (struct apbuart_priv *)minor;
+	int c, tot;
+	char buf[32];
+
+	tot = 0;
+	while ((c=apbuart_inbyte_nonblocking(uart->regs)) != EOF) {
+		buf[tot] = c;
+		tot++;
+		if (tot > 31) {
+			rtems_termios_enqueue_raw_characters(uart->cookie, buf, tot);
+			tot = 0;
+		}
+	}
+	if (tot > 0)
+		rtems_termios_enqueue_raw_characters(uart->cookie, buf, tot);
+
+	return EOF;
+}
+
+struct apbuart_baud {
+	unsigned int num;
+	unsigned int baud;
+};
+struct apbuart_baud apbuart_baud_table[] = {
+	{B50, 50},
+	{B75, 75},
+	{B110, 110},
+	{B134, 134},
+	{B150, 150},
+	{B200, 200},
+	{B300, 300},
+	{B600, 600},
+	{B1200, 1200},
+	{B1800, 1800},
+	{B2400, 2400},
+	{B4800, 4800},
+	{B9600, 9600},
+	{B19200, 19200},
+	{B38400, 38400},
+	{B57600, 57600},
+	{B115200, 115200},
+	{B230400, 230400},
+	{B460800, 460800},
+};
+#define BAUD_NUM (sizeof(apbuart_baud_table)/sizeof(struct apbuart_baud))
+
+int apbuart_baud_num2baud(unsigned int num)
+{
+	int i;
+
+	for(i=0; i<BAUD_NUM; i++)
+		if (apbuart_baud_table[i].num == num)
+			return apbuart_baud_table[i].baud;
+	return -1;
+}
+
+struct apbuart_baud *apbuart_baud_find_closest(unsigned int baud)
+{
+	int i, diff;
+
+	for(i=0; i<BAUD_NUM-1; i++) {
+		diff = apbuart_baud_table[i+1].baud -
+			apbuart_baud_table[i].baud;
+		if (baud < (apbuart_baud_table[i].baud + diff/2))
+			return &apbuart_baud_table[i];
+	}
+	return &apbuart_baud_table[BAUD_NUM-1];
+}
+
+int apbuart_get_baud(struct apbuart_priv *uart)
+{
+	unsigned int core_clk_hz;
+	unsigned int scaler;
+
+	/* Get current scaler setting */
+	scaler = uart->regs->scaler;
+
+	/* Get APBUART core frequency */
+	drvmgr_freq_get(uart->dev, DEV_APB_SLV, &core_clk_hz);
+
+	/* Calculate baud rate from generator "scaler" number */
+	return core_clk_hz / ((scaler + 1) * 8);
+}
+
+struct apbuart_baud *apbuart_get_baud_closest(struct apbuart_priv *uart)
+{
+	return apbuart_baud_find_closest(apbuart_get_baud(uart));
+}
+
+int apbuart_set_attributes(int minor, const struct termios *t)
+{
+	unsigned int core_clk_hz;
+	unsigned int scaler;
+	unsigned int ctrl;
+	int baud;
+	struct apbuart_priv *uart = (struct apbuart_priv *)minor;
+
+	switch(t->c_cflag & CSIZE) {
+		default:
+		case CS5:
+		case CS6:
+		case CS7:
+			/* Hardware doesn't support other than CS8 */
+			return -1;
+		case CS8:
+			break;
+	}
+
+	/* Read out current value */
+	ctrl = uart->regs->ctrl;
+
+	switch(t->c_cflag & (PARENB|PARODD)){
+		case (PARENB|PARODD):
+			/* Odd parity */
+			ctrl |= LEON_REG_UART_CTRL_PE|LEON_REG_UART_CTRL_PS;
+			break;
+
+		case PARENB:
+			/* Even parity */
+			ctrl &= ~LEON_REG_UART_CTRL_PS;
+			ctrl |= LEON_REG_UART_CTRL_PE;
+			break;
+
+		default:
+		case 0:
+		case PARODD:
+			/* No Parity */
+			ctrl &= ~(LEON_REG_UART_CTRL_PS|LEON_REG_UART_CTRL_PE);
+	}
+
+	if (!(t->c_cflag & CLOCAL))
+		ctrl |= LEON_REG_UART_CTRL_FL;
+	else
+		ctrl &= ~LEON_REG_UART_CTRL_FL;
+
+	/* Update new settings */
+	uart->regs->ctrl = ctrl;
+
+	/* Baud rate */
+	baud = apbuart_baud_num2baud(t->c_cflag & CBAUD);
+	if (baud > 0){
+		/* Get APBUART core frequency */
+		drvmgr_freq_get(uart->dev, DEV_APB_SLV, &core_clk_hz);
+
+		/* Calculate Baud rate generator "scaler" number */
+		scaler = (((core_clk_hz*10)/(baud*8))-5)/10;
+
+		/* Set new baud rate by setting scaler */
+		uart->regs->scaler = scaler;
+	}
+
+	return 0;
+}
+
+void apbuart_get_attributes(struct console_dev *condev, struct termios *t)
+{
+	struct apbuart_priv *uart = (struct apbuart_priv *)condev;
+	unsigned int ctrl;
+	struct apbuart_baud *baud;
+
+	t->c_cflag = t->c_cflag & ~(CSIZE|PARENB|PARODD|CLOCAL|CBAUD);
+
+	/* Hardware support only CS8 */
+	t->c_cflag |= CS8;
+
+	/* Read out current parity */
+	ctrl = uart->regs->ctrl;
+	if (ctrl & LEON_REG_UART_CTRL_PE) {
+		if (ctrl & LEON_REG_UART_CTRL_PS)
+			t->c_cflag |= PARENB|PARODD; /* Odd parity */
+		else
+			t->c_cflag |= PARENB; /* Even parity */
+	}
+
+	if ((ctrl & LEON_REG_UART_CTRL_FL) == 0)
+		t->c_cflag |= CLOCAL;
+
+	baud = apbuart_get_baud_closest(uart);
+	t->c_cflag |= baud->num;
+}
+
+ssize_t apbuart_write_polled(int minor, const char *buf, size_t len)
+{
+	int nwrite = 0;
+	struct apbuart_priv *uart = (struct apbuart_priv *)minor;
+
+	while (nwrite < len) {
+		apbuart_outbyte_polled(uart->regs, *buf++, 0, 0);
+		nwrite++;
+	}
+	return nwrite;
+}
+
+ssize_t apbuart_write_intr(int minor, const char *buf, size_t len)
+{
+	struct apbuart_priv *uart = (struct apbuart_priv *)minor;
+	unsigned int oldLevel;
+	unsigned int ctrl;
+
+	rtems_interrupt_disable(oldLevel);
+
+	/* Enable TX interrupt */
+	ctrl = uart->regs->ctrl;
+	uart->regs->ctrl = ctrl | LEON_REG_UART_CTRL_TI;
+
+	if (ctrl & LEON_REG_UART_CTRL_FA) {
+		/* APBUART with FIFO.. Fill as many as FIFO allows */
+		uart->sending = 0;
+		while (((uart->regs->status & LEON_REG_UART_STATUS_TF) == 0) &&
+		       (uart->sending < len)) {
+			uart->regs->data = *buf;
+			buf++;
+			uart->sending++;
+		}
+	} else {
+		/* start UART TX, this will result in an interrupt when done */
+		uart->regs->data = *buf;
+
+		uart->sending = 1;
+	}
+
+	rtems_interrupt_enable(oldLevel);
+
+	return 0;
+}
+
+/* Handle UART interrupts */
+void apbuart_isr(void *arg)
+{
+	struct apbuart_priv *uart = arg;
+	unsigned int status;
+	char data;
+	int cnt;
+
+	/* Get all received characters */
+	if (uart->mode == TERMIOS_TASK_DRIVEN) {
+		if ((status=uart->regs->status) & LEON_REG_UART_STATUS_DR)
+			rtems_termios_rxirq_occured(uart->cookie);
+	} else {
+		while ((status=uart->regs->status) & LEON_REG_UART_STATUS_DR) {
+			/* Data has arrived, get new data */
+			data = uart->regs->data;
+
+			/* Tell termios layer about new character */
+			rtems_termios_enqueue_raw_characters(uart->cookie, &data, 1);
+		}
+	}
+
+	if (uart->sending && (status & LEON_REG_UART_STATUS_THE)) {
+		/* Sent the one char, we disable TX interrupts */
+		uart->regs->ctrl &= ~LEON_REG_UART_CTRL_TI;
+
+		/* Tell close that we sent everything */
+		cnt = uart->sending;
+		uart->sending = 0;
+
+		/* apbuart_write_intr() will get called from this function */
+		rtems_termios_dequeue_characters(uart->cookie, cnt);
+	}
+}
Index: c/src/lib/libbsp/sparc/shared/uart/cons.c
===================================================================
--- c/src/lib/libbsp/sparc/shared/uart/cons.c	(revision c176410021c40e2596a08fadf21f53c5d0343924)
+++ c/src/lib/libbsp/sparc/shared/uart/cons.c	(revision c176410021c40e2596a08fadf21f53c5d0343924)
@@ -0,0 +1,189 @@
+/*  This file contains the TTY driver for the serial ports. The driver
+ *  is layered so that different UART hardware can be used. It is implemented
+ *  using the Driver Manager.
+ *
+ *  This driver uses the termios pseudo driver.
+ *
+ *  COPYRIGHT (c) 2010.
+ *  Cobham Gaisler AB.
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ */
+
+#include <bsp.h>
+#include <stdlib.h>
+#include <rtems/libio.h>
+#include <rtems/bspIo.h>
+#include <cons.h>
+
+#ifdef RTEMS_DRVMGR_STARTUP
+
+/* Note that it is not possible to use the interrupt mode of the driver
+ * together with the "old" APBUART and -u to GRMON. However the new
+ * APBUART core (from 1.0.17-b2710) has the GRMON debug bit and can 
+ * handle interrupts.
+ */
+
+int console_initialized = 0;
+rtems_device_major_number console_major = 0;
+
+#define FLAG_SYSCON 0x01
+struct console_priv {
+	unsigned char flags; /* 0x1=SystemConsole */
+	unsigned char minor;
+	struct console_dev *dev;
+};
+
+#define CONSOLE_MAX BSP_NUMBER_OF_TERMIOS_PORTS
+struct console_priv cons[CONSOLE_MAX] = {{0,0},};
+
+/* Register Console to TERMIOS layer and initialize it */
+void console_dev_init(struct console_priv *con, int minor)
+{
+	char name[16], *fsname;
+	rtems_status_code status;
+
+	if (!con->dev->fsname) {
+		strcpy(name, "/dev/console_a");
+		/* Special console name and MINOR for SYSTEM CONSOLE */
+		if (minor == 0)
+			name[12] = '\0'; /* /dev/console */
+		name[13] += minor; /* when minor=0, this has no effect... */
+		fsname = name;
+	} else {
+		fsname = con->dev->fsname;
+	}
+	status = rtems_io_register_name(fsname, console_major, minor);
+	if ((minor == 0) && (status != RTEMS_SUCCESSFUL))
+		rtems_fatal_error_occurred(status);
+}
+
+void console_dev_register(struct console_dev *dev)
+{
+	int i, minor = 0;
+	struct console_priv *con = NULL;
+
+	if ((dev->flags & CONSOLE_FLAG_SYSCON) && !cons[0].dev) {
+		con = &cons[0];
+		con->flags = FLAG_SYSCON;
+	} else {
+		for (i=1; i<CONSOLE_MAX; i++) {
+			if (!cons[i].dev) {
+				con = &cons[i];
+				con->flags = 0;
+				minor = i;
+				break;
+			}
+		}
+	}
+	if (con == NULL) {
+		/* Not enough console structures */
+		return;
+	}
+
+	/* Assign Console */
+	con->dev = dev;
+	con->minor = minor;
+
+	/* Console layer is already initialized, that means that we can
+	 * register termios interface directly.
+	 */
+	if (console_initialized)
+		console_dev_init(con, minor);
+}
+
+#if 0
+void console_dev_unregister(struct console_dev *dev)
+{
+
+}
+#endif
+
+rtems_device_driver console_initialize(
+	rtems_device_major_number	major,
+	rtems_device_minor_number	minor,
+	void				*arg)
+{
+	int i;
+
+	console_major = major;
+
+	rtems_termios_initialize();
+
+	/* Register all Console a file system device node */
+	for (i=0; i<CONSOLE_MAX; i++) {
+		if (cons[i].dev)
+			console_dev_init(&cons[i], i);
+	}
+
+	console_initialized = 1;
+
+	return RTEMS_SUCCESSFUL;
+}
+
+rtems_device_driver console_open(
+	rtems_device_major_number	major,
+	rtems_device_minor_number	minor,
+	void				*arg)
+{
+	rtems_status_code status;
+	struct termios term;
+
+	if ((minor >= CONSOLE_MAX) || !cons[minor].dev)
+		return RTEMS_INVALID_NUMBER;
+
+	status = rtems_termios_open(
+			major,
+			(int)cons[minor].dev,
+			arg,
+			cons[minor].dev->callbacks);
+
+	/* Inherit UART hardware parameters from bootloader on system console */
+	if ((status == RTEMS_SUCCESSFUL) && (cons[minor].flags & FLAG_SYSCON) &&
+	    (cons[minor].dev->ops.get_uart_attrs != NULL)) {
+		if (tcgetattr(STDIN_FILENO, &term) >= 0) {
+			cons[minor].dev->ops.get_uart_attrs(cons[minor].dev,
+								&term);
+			term.c_oflag |= ONLCR;
+			tcsetattr(STDIN_FILENO, TCSANOW, &term);
+		}
+	}
+
+	return status;
+}
+
+rtems_device_driver console_close(
+	rtems_device_major_number	major,
+	rtems_device_minor_number	minor,
+	void				*arg)
+{
+	return rtems_termios_close(arg);
+}
+
+rtems_device_driver console_read(
+	rtems_device_major_number	major,
+	rtems_device_minor_number	minor,
+	void				*arg)
+{
+	return rtems_termios_read(arg);
+}
+
+rtems_device_driver console_write(
+	rtems_device_major_number	major,
+	rtems_device_minor_number	minor,
+	void				*arg)
+{
+	return rtems_termios_write(arg);
+}
+
+rtems_device_driver console_control(
+	rtems_device_major_number	major,
+	rtems_device_minor_number	minor,
+	void				*arg)
+{
+	return rtems_termios_ioctl(arg);
+}
+
+#endif
