Index: kernel/genarch/src/kbd/ns16550.c
===================================================================
--- kernel/genarch/src/kbd/ns16550.c	(revision fc468841de2b95bece0894c87ba698651aa540fe)
+++ kernel/genarch/src/kbd/ns16550.c	(revision 8513ad77da21520006dc3e18de1e95a2b6f59c6f)
@@ -39,7 +39,8 @@
 #include <genarch/kbd/scanc.h>
 #include <genarch/kbd/scanc_sun.h>
+#include <arch/drivers/kbd.h>
 #include <arch/drivers/ns16550.h>
 #include <ddi/irq.h>
-#include <arch/interrupt.h>
+#include <ipc/irq.h>
 #include <cpu.h>
 #include <arch/asm.h>
@@ -49,5 +50,7 @@
 #include <console/console.h>
 #include <interrupt.h>
+#include <arch/interrupt.h>
 #include <sysinfo/sysinfo.h>
+#include <synch/spinlock.h>
 
 #define LSR_DATA_READY	0x01
@@ -58,4 +61,6 @@
 /** Structure for ns16550's IRQ. */
 static irq_t ns16550_irq;
+
+static ipc_notif_cfg_t saved_notif_cfg;
 
 /*
@@ -73,11 +78,21 @@
 };
 
-void ns16550_interrupt(int n, istate_t *istate);
-void ns16550_wait(void);
+void ns16550_interrupt(void);
 
 /** Initialize keyboard and service interrupts using kernel routine */
 void ns16550_grab(void)
 {
-	/* TODO */
+	ns16550_ier_write(&ns16550, IER_ERBFI);		/* enable receiver interrupt */
+	
+	while (ns16550_lsr_read(&ns16550) & LSR_DATA_READY)
+		(void) ns16550_rbr_read(&ns16550);
+
+	if (ns16550_irq.notif_cfg.answerbox) {
+		saved_notif_cfg = ns16550_irq.notif_cfg;
+		ns16550_irq.notif_cfg.answerbox = NULL;
+		ns16550_irq.notif_cfg.code = NULL;
+		ns16550_irq.notif_cfg.method = 0;
+		ns16550_irq.notif_cfg.counter = 0;
+	}
 }
 
@@ -85,5 +100,6 @@
 void ns16550_release(void)
 {
-	/* TODO */
+	if (saved_notif_cfg.answerbox)
+		ns16550_irq.notif_cfg = saved_notif_cfg;
 }
 
@@ -96,5 +112,4 @@
 void ns16550_init(devno_t devno, inr_t inr, uintptr_t vaddr)
 {
-	ns16550_grab();
 	chardev_initialize("ns16550_kbd", &kbrd, &ops);
 	stdin = &kbrd;
@@ -111,27 +126,19 @@
 	
 	sysinfo_set_item_val("kbd", NULL, true);
+	sysinfo_set_item_val("kbd.type", NULL, KBD_NS16550);
 	sysinfo_set_item_val("kbd.devno", NULL, devno);
 	sysinfo_set_item_val("kbd.inr", NULL, inr);
 	sysinfo_set_item_val("kbd.address.virtual", NULL, vaddr);
 	
-	ns16550_ier_write(&ns16550, IER_ERBFI);		/* enable receiver interrupt */
-	
-	while (ns16550_lsr_read(&ns16550) & LSR_DATA_READY)
-		(void) ns16550_rbr_read(&ns16550);
-}
-
-/** Process ns16550 interrupt.
- *
- * @param n Interrupt vector.
- * @param istate Interrupted state.
- */
-void ns16550_interrupt(int n, istate_t *istate)
-{
-	/* TODO */
-}
-
-/** Wait until the controller reads its data. */
-void ns16550_wait(void)
-{
+	ns16550_grab();
+}
+
+/** Process ns16550 interrupt. */
+void ns16550_interrupt(void)
+{
+	/* TODO
+	 *
+	 * ns16550 works in the polled mode so far.
+	 */
 }
 
@@ -171,7 +178,27 @@
 void ns16550_poll(void)
 {
-	uint8_t x;
+	ipl_t ipl;
+
+	ipl = interrupts_disable();
+	spinlock_lock(&ns16550_irq.lock);
+
+	if (ns16550_lsr_read(&ns16550) & LSR_DATA_READY) {
+		if (ns16550_irq.notif_cfg.answerbox) {
+			/*
+			 * Send IPC notification.
+			 */
+			ipc_irq_send_notif(&ns16550_irq);
+			spinlock_unlock(&ns16550_irq.lock);
+			interrupts_restore(ipl);
+			return;
+		}
+	}
+
+	spinlock_unlock(&ns16550_irq.lock);
+	interrupts_restore(ipl);
 
 	while (ns16550_lsr_read(&ns16550) & LSR_DATA_READY) {
+		uint8_t x;
+		
 		x = ns16550_rbr_read(&ns16550);
 		if (x != IGNORE_CODE) {
@@ -186,11 +213,10 @@
 irq_ownership_t ns16550_claim(void)
 {
-	/* TODO */
-	return IRQ_ACCEPT;
+	return (ns16550_lsr_read(&ns16550) & LSR_DATA_READY);
 }
 
 void ns16550_irq_handler(irq_t *irq, void *arg, ...)
 {
-	panic("Not yet implemented.\n");
+	panic("Not yet implemented, ns16550 works in polled mode.\n");
 }
 
Index: kernel/genarch/src/kbd/z8530.c
===================================================================
--- kernel/genarch/src/kbd/z8530.c	(revision fc468841de2b95bece0894c87ba698651aa540fe)
+++ kernel/genarch/src/kbd/z8530.c	(revision 8513ad77da21520006dc3e18de1e95a2b6f59c6f)
@@ -125,4 +125,5 @@
 
 	sysinfo_set_item_val("kbd", NULL, true);
+	sysinfo_set_item_val("kbd.type", NULL, KBD_Z8530);
 	sysinfo_set_item_val("kbd.devno", NULL, devno);
 	sysinfo_set_item_val("kbd.inr", NULL, inr);
