Index: kernel/arch/sparc64/src/drivers/kbd.c
===================================================================
--- kernel/arch/sparc64/src/drivers/kbd.c	(revision 8ce84991b196fbdd0b7d639a36b146cf784f38fb)
+++ kernel/arch/sparc64/src/drivers/kbd.c	(revision 0d107f313852cf9ca1abc289a98baf2c22f6c95c)
@@ -41,5 +41,5 @@
 #include <genarch/kbd/ns16550.h>
 #endif
-
+#include <irq.h>
 #include <arch/mm/page.h>
 #include <arch/types.h>
@@ -52,4 +52,6 @@
 
 kbd_type_t kbd_type = KBD_UNKNOWN;
+
+static irq_t kbd_irq;
 
 /** Initialize keyboard.
@@ -102,4 +104,6 @@
 	int inr;
 	
+	irq_initialize(&kbd_irq);
+	
 	switch (kbd_type) {
 	case KBD_Z8530:
@@ -112,6 +116,14 @@
 			printf("Failed to determine keyboard interrupt.\n");
 			return;
+		} else {
+			kbd_irq.inr = inr;
+			kbd_irq.devno = 0;			/* FIXME: assign unique devno */
+			kbd_irq.trigger = IRQ_TRIGGER_LEVEL;
+			kbd_irq.claim = z8530_claim;
+			kbd_irq.handler = z8530_irq_handler;
+			irq_register(&kbd_irq);
 		}
 		break;
+		
 	case KBD_NS16550:
 		size = ((ofw_ebus_reg_t *) prop->value)->size;
@@ -123,6 +135,14 @@
 			printf("Failed to determine keyboard interrupt.\n");
 			return;
+		} else {
+			kbd_irq.inr = inr;
+			kbd_irq.devno = 0;			/* FIXME: assign unique devno */
+			kbd_irq.trigger = IRQ_TRIGGER_LEVEL;
+			kbd_irq.claim = ns16550_claim;
+			kbd_irq.handler = ns16550_irq_handler;
+			irq_register(&kbd_irq);
 		}
 		break;
+
 	default:
 		panic("Unexpected type.\n");
Index: kernel/arch/sparc64/src/sparc64.c
===================================================================
--- kernel/arch/sparc64/src/sparc64.c	(revision 8ce84991b196fbdd0b7d639a36b146cf784f38fb)
+++ kernel/arch/sparc64/src/sparc64.c	(revision 0d107f313852cf9ca1abc289a98baf2c22f6c95c)
@@ -47,4 +47,5 @@
 #include <genarch/ofw/ofw_tree.h>
 #include <userspace.h>
+#include <irq.h>
 
 bootinfo_t bootinfo;
@@ -77,6 +78,8 @@
 void arch_post_mm_init(void)
 {
-	if (config.cpu_active == 1)
+	if (config.cpu_active == 1) {
+		irq_init(1<<11, 128);
 		standalone_sparc64_console_init();
+	}
 }
 
Index: kernel/arch/sparc64/src/trap/interrupt.c
===================================================================
--- kernel/arch/sparc64/src/trap/interrupt.c	(revision 8ce84991b196fbdd0b7d639a36b146cf784f38fb)
+++ kernel/arch/sparc64/src/trap/interrupt.c	(revision 0d107f313852cf9ca1abc289a98baf2c22f6c95c)
@@ -36,6 +36,5 @@
 #include <arch/trap/interrupt.h>
 #include <interrupt.h>
-#include <arch/drivers/fhc.h>
-#include <arch/drivers/kbd.h>
+#include <irq.h>
 #include <typedefs.h>
 #include <arch/types.h>
@@ -45,8 +44,13 @@
 #include <arch/barrier.h>
 #include <print.h>
-#include <genarch/kbd/z8530.h>
 #include <arch.h>
 #include <mm/tlb.h>
 #include <config.h>
+
+/*
+ * To be removed once we get rid of the dependency in ipc_irq_bind_arch().
+ */
+#include <arch/drivers/kbd.h>
+#include <genarch/kbd/z8530.h>
 
 /** Register Interrupt Level Handler.
@@ -72,4 +76,9 @@
 }
 
+/** Process hardware interrupt.
+ *
+ * @param n Ignored.
+ * @param istate Ignored.
+ */
 void interrupt(int n, istate_t *istate)
 {
@@ -80,43 +89,29 @@
 	data0 = asi_u64_read(ASI_UDB_INTR_R, ASI_UDB_INTR_R_DATA_0);
 
-	switch (data0) {
-#ifdef CONFIG_Z8530
-	case Z8530_INTRCV_DATA0:
-		if (kbd_type != KBD_Z8530)
-			break;
+	irq_t *irq = irq_dispatch(data0);
+	if (irq) {
 		/*
-		 * So far, we know we got this interrupt through the FHC.
-		 * Since we don't have enough information about the FHC and
-		 * because the interrupt looks like level sensitive,
-		 * we cannot handle it by scheduling one of the level
-		 * interrupt traps. Call the interrupt handler directly.
+		 * The IRQ handler was found.
 		 */
-
-		if (z8530_belongs_to_kernel)
-			z8530_interrupt();
-		else
-			ipc_irq_send_notif(0);
-		fhc_clear_interrupt(central_fhc, data0);
-		break;
-
+		irq->handler(irq, irq->arg);
+	} else if (data0 > config.base) {
+		/*
+		 * This is a cross-call.
+		 * data0 contains address of kernel function.
+		 * We call the function only after we verify
+		 * it is on of the supported ones.
+		 */
+#ifdef CONFIG_SMP
+		if (data0 == (uintptr_t) tlb_shootdown_ipi_recv) {
+			tlb_shootdown_ipi_recv();
+		}
 #endif
-	default:
-		if (data0 > config.base) {
-			/*
-			 * This is a cross-call.
-			 * data0 contains address of kernel function.
-			 * We call the function only after we verify
-			 * it is on of the supported ones.
-			 */
-#ifdef CONFIG_SMP
-			if (data0 == (uintptr_t) tlb_shootdown_ipi_recv) {
-				tlb_shootdown_ipi_recv();
-				break;
-			}
+	} else {
+		/*
+		 * Spurious interrupt.
+		 */
+#ifdef CONFIG_DEBUG
+		printf("cpu%d: spurious interrupt (intrcv=%#llx, data0=%#llx)\n", CPU->id, intrcv, data0);
 #endif
-		}
-			
-		printf("cpu%d: spurious interrupt (intrcv=%#llx, data0=%#llx)\n", CPU->id, intrcv, data0);
-		break;
 	}
 
