Index: kernel/genarch/include/genarch/drivers/ns16550/ns16550.h
===================================================================
--- kernel/genarch/include/genarch/drivers/ns16550/ns16550.h	(revision 6eeb4a3e81a72dcdffeb1256ea248c75983514ab)
+++ kernel/genarch/include/genarch/drivers/ns16550/ns16550.h	(revision 644352c77e9f5ec8e47d7af6d0d8a4c3b0277eda)
@@ -38,4 +38,5 @@
 #define KERN_NS16550_H_
 
+#include <ddi/ddi.h>
 #include <ddi/irq.h>
 #include <typedefs.h>
@@ -50,5 +51,8 @@
 /** NS16550 registers. */
 typedef struct {
-	ioport8_t rbr;      /**< Receiver Buffer Register. */
+	union {
+		ioport8_t rbr;      /**< Receiver Buffer Register (read). */
+		ioport8_t thr;      /**< Transmitter Holder Register (write). */
+	} __attribute__ ((packed));
 	ioport8_t ier;      /**< Interrupt Enable Register. */
 	union {
@@ -65,8 +69,11 @@
 	irq_t irq;
 	ns16550_t *ns16550;
-	indev_t *kbrdin;
+	indev_t *input;
+	outdev_t *output;
+	parea_t parea;
 } ns16550_instance_t;
 
-extern ns16550_instance_t *ns16550_init(ns16550_t *, inr_t, cir_t, void *);
+extern ns16550_instance_t *ns16550_init(ns16550_t *, inr_t, cir_t, void *,
+    outdev_t **);
 extern void ns16550_wire(ns16550_instance_t *, indev_t *);
 
Index: kernel/genarch/src/drivers/ns16550/ns16550.c
===================================================================
--- kernel/genarch/src/drivers/ns16550/ns16550.c	(revision 6eeb4a3e81a72dcdffeb1256ea248c75983514ab)
+++ kernel/genarch/src/drivers/ns16550/ns16550.c	(revision 644352c77e9f5ec8e47d7af6d0d8a4c3b0277eda)
@@ -41,6 +41,8 @@
 #include <mm/slab.h>
 #include <ddi/device.h>
+#include <str.h>
 
 #define LSR_DATA_READY  0x01
+#define LSR_TH_READY    0x20
 
 static irq_ownership_t ns16550_claim(irq_t *irq)
@@ -62,5 +64,5 @@
 	if (pio_read_8(&dev->lsr) & LSR_DATA_READY) {
 		uint8_t data = pio_read_8(&dev->rbr);
-		indev_push_character(instance->kbrdin, data);
+		indev_push_character(instance->input, data);
 	}
 }
@@ -73,16 +75,43 @@
 }
 
+static void ns16550_sendb(ns16550_t *dev, uint8_t byte)
+{
+	while (!(pio_read_8(&dev->lsr) & LSR_TH_READY))
+		;
+	pio_write_8(&dev->thr, byte);
+}
+
+static void ns16550_putchar(outdev_t *dev, wchar_t ch)
+{
+	ns16550_instance_t *instance = (ns16550_instance_t *) dev->data;
+	
+	if ((!instance->parea.mapped) || (console_override)) {
+		if (ascii_check(ch))
+			ns16550_sendb(instance->ns16550, (uint8_t) ch);
+		else
+			ns16550_sendb(instance->ns16550, U_SPECIAL);
+	}
+}
+
+static outdev_operations_t ns16550_ops = {
+	.write = ns16550_putchar,
+	.redraw = NULL
+};
+
 /** Initialize ns16550.
  *
  * @param dev      Addrress of the beginning of the device in I/O space.
- * @param devno    Device number.
  * @param inr      Interrupt number.
  * @param cir      Clear interrupt function.
  * @param cir_arg  First argument to cir.
+ * @param output   Where to store pointer to the output device
+ *                 or NULL if the caller is not interested in
+ *                 writing to the serial port.
  *
  * @return Keyboard instance or NULL on failure.
  *
  */
-ns16550_instance_t *ns16550_init(ns16550_t *dev, inr_t inr, cir_t cir, void *cir_arg)
+ns16550_instance_t *ns16550_init(ns16550_t *dev, inr_t inr, cir_t cir,
+    void *cir_arg, outdev_t **output)
 {
 	ns16550_instance_t *instance
@@ -90,5 +119,20 @@
 	if (instance) {
 		instance->ns16550 = dev;
-		instance->kbrdin = NULL;
+		instance->input = NULL;
+		instance->output = NULL;
+		
+		if (output) {
+			instance->output = malloc(sizeof(outdev_t),
+			    FRAME_ATOMIC);
+			if (!instance->output) {
+				free(instance);
+				return NULL;
+			}
+			
+			outdev_initialize("ns16550", instance->output,
+			    &ns16550_ops);
+			instance->output->data = instance;
+			*output = instance->output;
+		}
 		
 		irq_initialize(&instance->irq);
@@ -100,4 +144,10 @@
 		instance->irq.cir = cir;
 		instance->irq.cir_arg = cir_arg;
+		
+		instance->parea.pbase = (uintptr_t) dev;
+		instance->parea.frames = 1;
+		instance->parea.unpriv = false;
+		instance->parea.mapped = false;
+		ddi_parea_register(&instance->parea);
 	}
 	
@@ -105,10 +155,10 @@
 }
 
-void ns16550_wire(ns16550_instance_t *instance, indev_t *kbrdin)
+void ns16550_wire(ns16550_instance_t *instance, indev_t *input)
 {
 	ASSERT(instance);
-	ASSERT(kbrdin);
+	ASSERT(input);
 	
-	instance->kbrdin = kbrdin;
+	instance->input = input;
 	irq_register(&instance->irq);
 	
