Index: kernel/arch/ia64/src/ia64.c
===================================================================
--- kernel/arch/ia64/src/ia64.c	(revision 91825d906871fb7aacdd0e8161dca09a9de0ef6e)
+++ kernel/arch/ia64/src/ia64.c	(revision 013c4d666a79f5b3ee840b780dc07c7530965584)
@@ -66,5 +66,4 @@
 /* NS16550 as a COM 1 */
 #define NS16550_IRQ	(4 + LEGACY_INTERRUPT_BASE)
-#define NS16550_PORT	0x3f8
 
 bootinfo_t *bootinfo;
@@ -165,5 +164,6 @@
 
 #ifdef CONFIG_NS16550
-	ns16550_init(kbd, NS16550_PORT, NS16550_IRQ, NULL, NULL);
+	(void) ns16550_init((ns16550_t *)NS16550_BASE, kbd, NS16550_IRQ, NULL,
+	     NULL);
 #else
 	devno_t mouse = device_assign_devno();
@@ -250,5 +250,5 @@
 void arch_reboot(void)
 {
-	pio_write_8(0x64, 0xfe);
+	pio_write_8((ioport8_t *)0x64, 0xfe);
 	while (1)
 		;
Index: kernel/arch/ia64/src/smp/smp.c
===================================================================
--- kernel/arch/ia64/src/smp/smp.c	(revision 91825d906871fb7aacdd0e8161dca09a9de0ef6e)
+++ kernel/arch/ia64/src/smp/smp.c	(revision 013c4d666a79f5b3ee840b780dc07c7530965584)
@@ -52,5 +52,4 @@
 #include <ddi/irq.h>
 #include <ddi/device.h>
-#include <arch/drivers/ega.h>
 #include <arch/bootinfo.h>
 #include <genarch/kbd/i8042.h>
Index: kernel/genarch/include/drivers/legacy/ia32/io.h
===================================================================
--- kernel/genarch/include/drivers/legacy/ia32/io.h	(revision 91825d906871fb7aacdd0e8161dca09a9de0ef6e)
+++ kernel/genarch/include/drivers/legacy/ia32/io.h	(revision 013c4d666a79f5b3ee840b780dc07c7530965584)
@@ -40,8 +40,10 @@
 #include <arch/types.h>
 
-#define i8042_BASE	((ioport8_t *)0x60)
+#define I8042_BASE	((ioport8_t *)0x60)
 
 #define EGA_VIDEORAM 	0xb8000
 #define EGA_BASE	((ioport8_t *)0x3d4)
+
+#define NS16550_BASE	((ioport8_t *)0x3f8)
 
 #endif
Index: kernel/genarch/include/kbd/i8042.h
===================================================================
--- kernel/genarch/include/kbd/i8042.h	(revision 91825d906871fb7aacdd0e8161dca09a9de0ef6e)
+++ kernel/genarch/include/kbd/i8042.h	(revision 013c4d666a79f5b3ee840b780dc07c7530965584)
@@ -37,5 +37,5 @@
 
 #include <arch/types.h>
-#include <console/chardev.h>
+#include <typedefs.h>
 
 struct i8042 {
@@ -53,5 +53,4 @@
 extern void i8042_grab(void);
 extern void i8042_release(void);
-extern char i8042_key_read(chardev_t *d);
 
 #endif
Index: kernel/genarch/include/kbd/ns16550.h
===================================================================
--- kernel/genarch/include/kbd/ns16550.h	(revision 91825d906871fb7aacdd0e8161dca09a9de0ef6e)
+++ kernel/genarch/include/kbd/ns16550.h	(revision 013c4d666a79f5b3ee840b780dc07c7530965584)
@@ -38,27 +38,7 @@
 #define KERN_NS16550_H_
 
-#include <console/chardev.h>
 #include <ddi/irq.h>
-#include <ipc/irq.h>
-
-extern void ns16550_init(devno_t, uintptr_t, inr_t, cir_t, void *);
-extern void ns16550_poll(void);
-extern void ns16550_grab(void);
-extern void ns16550_release(void);
-extern char ns16550_key_read(chardev_t *);
-extern irq_ownership_t ns16550_claim(void *);
-extern void ns16550_irq_handler(irq_t *);
-
 #include <arch/types.h>
 #include <arch/drivers/kbd.h>
-
-/* NS16550 registers */
-#define RBR_REG		0	/** Receiver Buffer Register. */
-#define IER_REG		1	/** Interrupt Enable Register. */
-#define IIR_REG		2	/** Interrupt Ident Register (read). */
-#define FCR_REG		2	/** FIFO control register (write). */
-#define LCR_REG		3	/** Line Control register. */
-#define MCR_REG		4	/** Modem Control Register. */
-#define LSR_REG		5	/** Line Status Register. */
 
 #define IER_ERBFI	0x01	/** Enable Receive Buffer Full Interrupt. */
@@ -68,64 +48,30 @@
 #define MCR_OUT2	0x08	/** OUT2. */
 
+/** NS16550 registers. */
+struct ns16550 {
+	ioport8_t rbr;	/**< Receiver Buffer Register. */
+	ioport8_t ier;	/**< Interrupt Enable Register. */
+	union {
+		ioport8_t iir;	/**< Interrupt Ident Register (read). */
+		ioport8_t fcr;	/**< FIFO control register (write). */
+	} __attribute__ ((packed));
+	ioport8_t lcr;	/**< Line Control register. */
+	ioport8_t mcr;	/**< Modem Control Register. */
+	ioport8_t lsr;	/**< Line Status Register. */
+} __attribute__ ((packed));
+typedef struct ns16550 ns16550_t;
+
 /** Structure representing the ns16550 device. */
-typedef struct {
+typedef struct ns16550_instance {
 	devno_t devno;
-	/** Memory mapped registers of the ns16550. */
-	volatile ioport_t io_port;
-} ns16550_t;
+	ns16550_t *ns16550;
+	irq_t *irq;
+} ns16550_instance_t;
 
-static inline uint8_t ns16550_rbr_read(ns16550_t *dev)
-{
-	return pio_read_8(dev->io_port + RBR_REG);
-}
-static inline void ns16550_rbr_write(ns16550_t *dev, uint8_t v)
-{
-	pio_write_8(dev->io_port + RBR_REG, v);
-}
-
-static inline uint8_t ns16550_ier_read(ns16550_t *dev)
-{
-	return pio_read_8(dev->io_port + IER_REG);
-}
-
-static inline void ns16550_ier_write(ns16550_t *dev, uint8_t v)
-{
-	pio_write_8(dev->io_port + IER_REG, v);
-}
-
-static inline uint8_t ns16550_iir_read(ns16550_t *dev)
-{
-	return pio_read_8(dev->io_port + IIR_REG);
-}
-
-static inline void ns16550_fcr_write(ns16550_t *dev, uint8_t v)
-{
-	pio_write_8(dev->io_port + FCR_REG, v);
-}
-
-static inline uint8_t ns16550_lcr_read(ns16550_t *dev)
-{
-	return pio_read_8(dev->io_port + LCR_REG);
-}
-
-static inline void ns16550_lcr_write(ns16550_t *dev, uint8_t v)
-{
-	pio_write_8(dev->io_port + LCR_REG, v);
-}
-
-static inline uint8_t ns16550_lsr_read(ns16550_t *dev)
-{
-	return pio_read_8(dev->io_port + LSR_REG);
-}
-
-static inline uint8_t ns16550_mcr_read(ns16550_t *dev)
-{
-	return pio_read_8(dev->io_port + MCR_REG);
-}
-
-static inline void ns16550_mcr_write(ns16550_t *dev, uint8_t v)
-{
-	pio_write_8(dev->io_port + MCR_REG, v);
-}
+extern bool ns16550_init(ns16550_t *, devno_t, inr_t, cir_t, void *);
+extern void ns16550_grab(void);
+extern void ns16550_release(void);
+extern irq_ownership_t ns16550_claim(void *);
+extern void ns16550_irq_handler(irq_t *);
 
 #endif
Index: kernel/genarch/src/kbd/i8042.c
===================================================================
--- kernel/genarch/src/kbd/i8042.c	(revision 91825d906871fb7aacdd0e8161dca09a9de0ef6e)
+++ kernel/genarch/src/kbd/i8042.c	(revision 013c4d666a79f5b3ee840b780dc07c7530965584)
@@ -53,5 +53,5 @@
 
 i8042_instance_t lgcy_i8042_instance = {
-	.i8042 = (i8042_t *) i8042_BASE,
+	.i8042 = (i8042_t *) I8042_BASE,
 };
 
@@ -89,5 +89,4 @@
 	.suspend = i8042_suspend,
 	.resume = i8042_resume,
-	.read = i8042_key_read
 };
 
@@ -229,24 +228,4 @@
 }
 
-char i8042_key_read(chardev_t *d)
-{
-	i8042_t *dev = lgcy_i8042_instance.i8042;
-	char ch;
-	
-	while (!(ch = active_read_buff_read())) {
-		uint8_t x;
-		
-		while (!(pio_read_8(&dev->status) & i8042_BUFFER_FULL_MASK))
-			;
-		
-		x = pio_read_8(&dev->data);
-		if (x & KEY_RELEASE)
-			key_released(x ^ KEY_RELEASE);
-		else
-			active_read_key_pressed(x);
-	}
-	return ch;
-}
-
 /** @}
  */
Index: kernel/genarch/src/kbd/ns16550.c
===================================================================
--- kernel/genarch/src/kbd/ns16550.c	(revision 91825d906871fb7aacdd0e8161dca09a9de0ef6e)
+++ kernel/genarch/src/kbd/ns16550.c	(revision 013c4d666a79f5b3ee840b780dc07c7530965584)
@@ -51,12 +51,9 @@
 #include <sysinfo/sysinfo.h>
 #include <synch/spinlock.h>
+#include <mm/slab.h>
 
 #define LSR_DATA_READY	0x01
 
-/** Structure representing the ns16550. */
-static ns16550_t ns16550;
-
-/** Structure for ns16550's IRQ. */
-static irq_t ns16550_irq;
+static irq_t *ns16550_irq;
 
 /*
@@ -71,8 +68,5 @@
 	.suspend = ns16550_suspend,
 	.resume = ns16550_resume,
-	.read = ns16550_key_read
 };
-
-void ns16550_interrupt(void);
 
 /** Initialize keyboard and service interrupts using kernel routine */
@@ -80,13 +74,7 @@
 {
 	ipl_t ipl = interrupts_disable();
-
-	ns16550_ier_write(&ns16550, IER_ERBFI);		/* enable receiver interrupt */
-	
-	while (ns16550_lsr_read(&ns16550) & LSR_DATA_READY)
-		(void) ns16550_rbr_read(&ns16550);
-
-	spinlock_lock(&ns16550_irq.lock);
-	ns16550_irq.notif_cfg.notify = false;
-	spinlock_unlock(&ns16550_irq.lock);
+	spinlock_lock(&ns16550_irq->lock);
+	ns16550_irq->notif_cfg.notify = false;
+	spinlock_unlock(&ns16550_irq->lock);
 	interrupts_restore(ipl);
 }
@@ -96,8 +84,8 @@
 {
 	ipl_t ipl = interrupts_disable();
-	spinlock_lock(&ns16550_irq.lock);
-	if (ns16550_irq.notif_cfg.answerbox)
-		ns16550_irq.notif_cfg.notify = true;
-	spinlock_unlock(&ns16550_irq.lock);
+	spinlock_lock(&ns16550_irq->lock);
+	if (ns16550_irq->notif_cfg.answerbox)
+		ns16550_irq->notif_cfg.notify = true;
+	spinlock_unlock(&ns16550_irq->lock);
 	interrupts_restore(ipl);
 }
@@ -105,30 +93,49 @@
 /** Initialize ns16550.
  *
+ * @param dev		Addrress of the beginning of the device in I/O space.
  * @param devno		Device number.
- * @param port		Virtual/IO address of device's registers.
  * @param inr		Interrupt number.
  * @param cir		Clear interrupt function.
  * @param cir_arg	First argument to cir.
- */
-void
-ns16550_init(devno_t devno, ioport_t port, inr_t inr, cir_t cir, void *cir_arg)
-{
+ *
+ * @return		True on success, false on failure.
+ */
+bool
+ns16550_init(ns16550_t *dev, devno_t devno, inr_t inr, cir_t cir, void *cir_arg)
+{
+	ns16550_instance_t *instance;
+	irq_t *irq;
+
 	chardev_initialize("ns16550_kbd", &kbrd, &ops);
 	stdin = &kbrd;
 	
-	ns16550.devno = devno;
-	ns16550.io_port = port;
-	
-	irq_initialize(&ns16550_irq);
-	ns16550_irq.devno = devno;
-	ns16550_irq.inr = inr;
-	ns16550_irq.claim = ns16550_claim;
-	ns16550_irq.handler = ns16550_irq_handler;
-	ns16550_irq.cir = cir;
-	ns16550_irq.cir_arg = cir_arg;
-	irq_register(&ns16550_irq);
-	
-	while ((ns16550_lsr_read(&ns16550) & LSR_DATA_READY)) 
-		ns16550_rbr_read(&ns16550);
+	instance = malloc(sizeof(ns16550_instance_t), FRAME_ATOMIC);
+	if (!instance)
+		return false;
+
+	irq = malloc(sizeof(irq_t), FRAME_ATOMIC);
+	if (!irq) {
+		free(instance);
+		return false;
+	}
+
+	instance->devno = devno;
+	instance->ns16550 = dev;
+	instance->irq = irq;
+	
+	irq_initialize(irq);
+	irq->devno = devno;
+	irq->inr = inr;
+	irq->claim = ns16550_claim;
+	irq->handler = ns16550_irq_handler;
+	irq->instance = instance;
+	irq->cir = cir;
+	irq->cir_arg = cir_arg;
+	irq_register(irq);
+
+	ns16550_irq = irq;	/* TODO: remove me soon */
+	
+	while ((pio_read_8(&dev->lsr) & LSR_DATA_READY)) 
+		(void) pio_read_8(&dev->rbr);
 	
 	sysinfo_set_item_val("kbd", NULL, true);
@@ -136,26 +143,14 @@
 	sysinfo_set_item_val("kbd.devno", NULL, devno);
 	sysinfo_set_item_val("kbd.inr", NULL, inr);
-	sysinfo_set_item_val("kbd.address.virtual", NULL, port);
-	sysinfo_set_item_val("kbd.port", NULL, port);
+	sysinfo_set_item_val("kbd.address.virtual", NULL, (uintptr_t) dev);
+	sysinfo_set_item_val("kbd.port", NULL, (uintptr_t) dev);
 	
 	/* Enable interrupts */
-	ns16550_ier_write(&ns16550, IER_ERBFI);
-	ns16550_mcr_write(&ns16550, MCR_OUT2);
-	
-	uint8_t c;
-	// This switches rbr & ier to mode when accept baudrate constant
-	c = ns16550_lcr_read(&ns16550);
-	ns16550_lcr_write(&ns16550, 0x80 | c);
-	ns16550_rbr_write(&ns16550, 0x0c);
-	ns16550_ier_write(&ns16550, 0x00);
-	ns16550_lcr_write(&ns16550, c);
+	pio_write_8(&dev->ier, IER_ERBFI);
+	pio_write_8(&dev->mcr, MCR_OUT2);
 	
 	ns16550_grab();
-}
-
-/** Process ns16550 interrupt. */
-void ns16550_interrupt(void)
-{
-	ns16550_poll();
+	
+	return true;
 }
 
@@ -170,35 +165,32 @@
 }
 
-
-char ns16550_key_read(chardev_t *d)
-{
-	char ch;	
-
-	while(!(ch = active_read_buff_read())) {
-		uint8_t x;
-		while (!(ns16550_lsr_read(&ns16550) & LSR_DATA_READY));
-		
-		x = ns16550_rbr_read(&ns16550);
-		
-		if (x != IGNORE_CODE) {
-			if (x & KEY_RELEASE)
-				key_released(x ^ KEY_RELEASE);
-			else
-				active_read_key_pressed(x);
-		}
+irq_ownership_t ns16550_claim(void *instance)
+{
+	ns16550_instance_t *ns16550_instance = instance;
+	ns16550_t *dev = ns16550_instance->ns16550;
+
+	if (pio_read_8(&dev->lsr) & LSR_DATA_READY)
+		return IRQ_ACCEPT;
+	else
+		return IRQ_DECLINE;
+}
+
+void ns16550_irq_handler(irq_t *irq)
+{
+	if (irq->notif_cfg.notify && irq->notif_cfg.answerbox) {
+		/*
+		 * This will hopefully go to the IRQ dispatch code soon.
+		 */
+		ipc_irq_send_notif(irq);
+		return;
 	}
-	return ch;
-}
-
-/** Poll for key press and release events.
- *
- * This function can be used to implement keyboard polling.
- */
-void ns16550_poll(void)
-{
-	while (ns16550_lsr_read(&ns16550) & LSR_DATA_READY) {
+
+	ns16550_instance_t *ns16550_instance = irq->instance;
+	ns16550_t *dev = ns16550_instance->ns16550;
+
+	if (pio_read_8(&dev->lsr) & LSR_DATA_READY) {
 		uint8_t x;
 		
-		x = ns16550_rbr_read(&ns16550);
+		x = pio_read_8(&dev->rbr);
 		
 		if (x != IGNORE_CODE) {
@@ -209,17 +201,5 @@
 		}
 	}
-}
-
-irq_ownership_t ns16550_claim(void *instance)
-{
-	return (ns16550_lsr_read(&ns16550) & LSR_DATA_READY);
-}
-
-void ns16550_irq_handler(irq_t *irq)
-{
-	if (irq->notif_cfg.notify && irq->notif_cfg.answerbox)
-		ipc_irq_send_notif(irq);
-	else
-		ns16550_interrupt();
+
 }
 
