Index: kernel/Makefile
===================================================================
--- kernel/Makefile	(revision 4c4ddbe923f125d8dae99621981ab35bb07bb632)
+++ kernel/Makefile	(revision 3e53ab7b0eacdf72743712841abf0bf6d897b956)
@@ -125,4 +125,8 @@
 ifeq ($(CONFIG_NS16550),y)
 	DEFS += -DCONFIG_NS16550
+endif
+
+ifeq ($(CONFIG_NS16550_INTERRUPT_DRIVEN),y)
+	DEFS += -DCONFIG_NS16550_INTERRUPT_DRIVEN
 endif
 
Index: kernel/arch/sparc64/src/console.c
===================================================================
--- kernel/arch/sparc64/src/console.c	(revision 4c4ddbe923f125d8dae99621981ab35bb07bb632)
+++ kernel/arch/sparc64/src/console.c	(revision 3e53ab7b0eacdf72743712841abf0bf6d897b956)
@@ -113,8 +113,20 @@
 #endif
 
+#ifdef CONFIG_NS16550
+#ifdef CONFIG_NS16550_INTERRUPT_DRIVEN
+	if (kbd_type == KBD_NS16550) {
+		/*
+		 * The ns16550 driver is interrupt-driven.
+		 */
+		return;
+	}
+#endif
+#endif
 	while (1) {
 #ifdef CONFIG_NS16550
+#ifndef CONFIG_NS16550_INTERRUPT_DRIVEN
 		if (kbd_type == KBD_NS16550)
 			ns16550_poll();
+#endif
 #endif
 		thread_usleep(KEYBOARD_POLL_PAUSE);
Index: kernel/arch/sparc64/src/drivers/kbd.c
===================================================================
--- kernel/arch/sparc64/src/drivers/kbd.c	(revision 4c4ddbe923f125d8dae99621981ab35bb07bb632)
+++ kernel/arch/sparc64/src/drivers/kbd.c	(revision 3e53ab7b0eacdf72743712841abf0bf6d897b956)
@@ -104,9 +104,11 @@
 	case KBD_Z8530:
 		size = ((ofw_fhc_reg_t *) prop->value)->size;
-		if (!ofw_fhc_apply_ranges(node->parent, ((ofw_fhc_reg_t *) prop->value) , &pa)) {
+		if (!ofw_fhc_apply_ranges(node->parent,
+		    ((ofw_fhc_reg_t *) prop->value), &pa)) {
 			printf("Failed to determine keyboard address.\n");
 			return;
 		}
-		if (!ofw_fhc_map_interrupt(node->parent, ((ofw_fhc_reg_t *) prop->value), interrupts, &inr)) {
+		if (!ofw_fhc_map_interrupt(node->parent,
+		    ((ofw_fhc_reg_t *) prop->value), interrupts, &inr)) {
 			printf("Failed to determine keyboard interrupt.\n");
 			return;
@@ -116,9 +118,11 @@
 	case KBD_NS16550:
 		size = ((ofw_ebus_reg_t *) prop->value)->size;
-		if (!ofw_ebus_apply_ranges(node->parent, ((ofw_ebus_reg_t *) prop->value) , &pa)) {
+		if (!ofw_ebus_apply_ranges(node->parent,
+		    ((ofw_ebus_reg_t *) prop->value), &pa)) {
 			printf("Failed to determine keyboard address.\n");
 			return;
 		}
-		if (!ofw_ebus_map_interrupt(node->parent, ((ofw_ebus_reg_t *) prop->value), interrupts, &inr)) {
+		if (!ofw_ebus_map_interrupt(node->parent,
+		    ((ofw_ebus_reg_t *) prop->value), interrupts, &inr)) {
 			printf("Failed to determine keyboard interrupt.\n");
 			return;
@@ -152,5 +156,6 @@
 #endif
 	default:
-		printf("Kernel is not compiled with the necessary keyboard driver this machine requires.\n");
+		printf("Kernel is not compiled with the necessary keyboard "
+		    "driver this machine requires.\n");
 	}
 }
Index: kernel/genarch/include/kbd/ns16550.h
===================================================================
--- kernel/genarch/include/kbd/ns16550.h	(revision 4c4ddbe923f125d8dae99621981ab35bb07bb632)
+++ kernel/genarch/include/kbd/ns16550.h	(revision 3e53ab7b0eacdf72743712841abf0bf6d897b956)
@@ -59,4 +59,5 @@
 #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. */
 
@@ -65,55 +66,66 @@
 #define LCR_DLAB	0x80	/** Divisor Latch Access bit. */
 
+#define MCR_OUT2	0x08	/** OUT2. */
+
 /** Structure representing the ns16550 device. */
 typedef struct {
 	devno_t devno;
-	volatile ioport_t io_port;	/** Memory mapped registers of the ns16550. */
+	/** Memory mapped registers of the ns16550. */
+	volatile ioport_t io_port;
 } ns16550_t;
 
 static inline uint8_t ns16550_rbr_read(ns16550_t *dev)
 {
-	return inb(dev->io_port+RBR_REG);
+	return inb(dev->io_port + RBR_REG);
 }
 static inline void ns16550_rbr_write(ns16550_t *dev, uint8_t v)
 {
-	outb(dev->io_port+RBR_REG,v);
+	outb(dev->io_port + RBR_REG, v);
 }
 
 static inline uint8_t ns16550_ier_read(ns16550_t *dev)
 {
-	return inb(dev->io_port+IER_REG);
+	return inb(dev->io_port + IER_REG);
 }
 
 static inline void ns16550_ier_write(ns16550_t *dev, uint8_t v)
 {
-	outb(dev->io_port+IER_REG,v);
+	outb(dev->io_port + IER_REG, v);
 }
 
 static inline uint8_t ns16550_iir_read(ns16550_t *dev)
 {
-	return inb(dev->io_port+IIR_REG);
+	return inb(dev->io_port + IIR_REG);
 }
 
 static inline void ns16550_fcr_write(ns16550_t *dev, uint8_t v)
 {
-	outb(dev->io_port+FCR_REG,v);
+	outb(dev->io_port + FCR_REG, v);
 }
 
 static inline uint8_t ns16550_lcr_read(ns16550_t *dev)
 {
-	return inb(dev->io_port+LCR_REG);
+	return inb(dev->io_port + LCR_REG);
 }
 
 static inline void ns16550_lcr_write(ns16550_t *dev, uint8_t v)
 {
-	outb(dev->io_port+LCR_REG,v);
+	outb(dev->io_port + LCR_REG, v);
 }
 
 static inline uint8_t ns16550_lsr_read(ns16550_t *dev)
 {
-	return inb(dev->io_port+LSR_REG);
+	return inb(dev->io_port + LSR_REG);
 }
 
+static inline uint8_t ns16550_mcr_read(ns16550_t *dev)
+{
+	return inb(dev->io_port + MCR_REG);
+}
 
+static inline void ns16550_mcr_write(ns16550_t *dev, uint8_t v)
+{
+	outb(dev->io_port + MCR_REG, v);
+}
 
 #endif
Index: kernel/genarch/src/kbd/ns16550.c
===================================================================
--- kernel/genarch/src/kbd/ns16550.c	(revision 4c4ddbe923f125d8dae99621981ab35bb07bb632)
+++ kernel/genarch/src/kbd/ns16550.c	(revision 3e53ab7b0eacdf72743712841abf0bf6d897b956)
@@ -135,4 +135,10 @@
 	sysinfo_set_item_val("kbd.address.virtual", NULL, port);
 
+#ifdef CONFIG_NS16550_INTERRUPT_DRIVEN
+	/* Enable interrupts */
+    	ns16550_ier_write(&ns16550, IER_ERBFI);
+	ns16550_mcr_write(&ns16550, MCR_OUT2);
+#endif
+
 #ifdef ia64
     	uint8_t c;
@@ -150,8 +156,5 @@
 void ns16550_interrupt(void)
 {
-	/* TODO
-	 *
-	 * ns16550 works in the polled mode so far.
-	 */
+	ns16550_poll();
 }
 
@@ -202,4 +205,5 @@
 void ns16550_poll(void)
 {
+#ifndef CONFIG_NS16550_INTERRUPT_DRIVEN 
 	ipl_t ipl;
 
@@ -221,4 +225,5 @@
 	spinlock_unlock(&ns16550_irq.lock);
 	interrupts_restore(ipl);
+#endif
 
 	while (ns16550_lsr_read(&ns16550) & LSR_DATA_READY) {
@@ -252,5 +257,8 @@
 void ns16550_irq_handler(irq_t *irq, void *arg, ...)
 {
-	panic("Not yet implemented, ns16550 works in polled mode.\n");
+	if (irq->notif_cfg.notify && irq->notif_cfg.answerbox)
+		ipc_irq_send_notif(irq);
+	else
+		ns16550_interrupt();
 }
 
Index: kernel/kernel.config
===================================================================
--- kernel/kernel.config	(revision 4c4ddbe923f125d8dae99621981ab35bb07bb632)
+++ kernel/kernel.config	(revision 3e53ab7b0eacdf72743712841abf0bf6d897b956)
@@ -142,4 +142,6 @@
 ! [ARCH=sparc64|ARCH=ia64] CONFIG_NS16550 (y/n)
 
+# Interrupt-driven driver for NS16550?
+! [CONFIG_NS16550=y] CONFIG_NS16550_INTERRUPT_DRIVEN (n/y)
 
 # Virtually indexed D-cache support
