Index: kernel/arch/ia64/include/drivers/it.h
===================================================================
--- kernel/arch/ia64/include/drivers/it.h	(revision 6fb30a1a9fb76291a876ee61b596d65482cc7302)
+++ kernel/arch/ia64/include/drivers/it.h	(revision de57e0601410d3336e18d797fc95a74b2dce44c0)
@@ -45,5 +45,4 @@
 
 extern void it_init(void);
-extern void it_interrupt(void);
 
 #endif
Index: kernel/arch/ia64/include/interrupt.h
===================================================================
--- kernel/arch/ia64/include/interrupt.h	(revision 6fb30a1a9fb76291a876ee61b596d65482cc7302)
+++ kernel/arch/ia64/include/interrupt.h	(revision de57e0601410d3336e18d797fc95a74b2dce44c0)
@@ -40,6 +40,14 @@
 #include <arch/register.h>
 
-#define IRQ_COUNT               257 /* 256 NOT suppotred IRQS*//* TODO */
-#define IRQ_KBD                 256 /* One simulated interrupt for ski simulator keyboard*/
+/** ia64 has 256 INRs. */
+#define INR_COUNT	256
+
+/*
+ * We need to keep this just to compile.
+ * We might eventually move interrupt/ stuff
+ * to genarch.
+ */
+#define IVT_ITEMS       0
+#define IVT_FIRST       0
 
 /** External Interrupt vectors. */
@@ -127,5 +135,5 @@
 static inline int istate_from_uspace(istate_t *istate)
 {
-	return (istate->cr_iip)<0xe000000000000000ULL;
+	return (istate->cr_iip) < 0xe000000000000000ULL;
 }
 
@@ -137,5 +145,4 @@
 extern void nop_handler(uint64_t vector, istate_t *istate);
 extern void external_interrupt(uint64_t vector, istate_t *istate);
-extern void virtual_interrupt(uint64_t irq, void *param);
 extern void disabled_fp_register(uint64_t vector, istate_t *istate);
 
Index: kernel/arch/ia64/include/ski/ski.h
===================================================================
--- kernel/arch/ia64/include/ski/ski.h	(revision 6fb30a1a9fb76291a876ee61b596d65482cc7302)
+++ kernel/arch/ia64/include/ski/ski.h	(revision de57e0601410d3336e18d797fc95a74b2dce44c0)
@@ -43,10 +43,12 @@
 #define SKI_PUTCHAR		31
 
+extern chardev_t ski_uconsole;
+
 extern void ski_init_console(void);
 extern void ski_set_console_sysinfo(void);
 extern void poll_keyboard(void);
 
-extern chardev_t ski_uconsole;
-extern int kbd_uspace;
+extern void ski_kbd_grab(void);
+extern void ski_kbd_release(void);
 
 #endif
Index: kernel/arch/ia64/src/drivers/it.c
===================================================================
--- kernel/arch/ia64/src/drivers/it.c	(revision 6fb30a1a9fb76291a876ee61b596d65482cc7302)
+++ kernel/arch/ia64/src/drivers/it.c	(revision de57e0601410d3336e18d797fc95a74b2dce44c0)
@@ -42,8 +42,14 @@
 #include <arch/barrier.h>
 #include <time/clock.h>
+#include <ddi/irq.h>
+#include <ddi/device.h>
 #include <arch.h>
 
+#define IT_SERVICE_CLOCKS 64
 
-#define IT_SERVICE_CLOCKS 64
+static irq_t it_irq;
+
+static irq_ownership_t it_claim(void);
+static void it_interrupt(irq_t *irq, void *arg, ...);
 
 /** Initialize Interval Timer. */
@@ -51,4 +57,11 @@
 {
 	cr_itv_t itv;
+
+	irq_initialize(&it_irq);
+	it_irq.inr = INTERRUPT_TIMER;
+	it_irq.devno = device_assign_devno();
+	it_irq.claim = it_claim;
+	it_irq.handler = it_interrupt;
+	irq_register(&it_irq);
 
 	/* initialize Interval Timer external interrupt vector */
@@ -68,7 +81,17 @@
 }
 
+/** Always claim ownership for this IRQ.
+ *
+ * Other devices are responsible to avoid using INR 0.
+ *
+ * @return Always IRQ_ACCEPT.
+ */
+irq_ownership_t it_claim(void)
+{
+	return IRQ_ACCEPT;
+}
 
 /** Process Interval Timer interrupt. */
-void it_interrupt(void)
+void it_interrupt(irq_t *irq, void *arg, ...)
 {
 	int64_t c;
@@ -84,5 +107,5 @@
 
 		m += IT_DELTA;
-		if (m-c<0)
+		if (m - c < 0)
 			CPU->missed_clock_ticks++;
 		else
@@ -94,4 +117,9 @@
 	
 	clock();
+	
+	/*
+	 * This one is a good candidate for moving to a separate
+	 * kernel thread private to ski.c
+	 */
 	poll_keyboard();
 }
Index: kernel/arch/ia64/src/ia64.c
===================================================================
--- kernel/arch/ia64/src/ia64.c	(revision 6fb30a1a9fb76291a876ee61b596d65482cc7302)
+++ kernel/arch/ia64/src/ia64.c	(revision de57e0601410d3336e18d797fc95a74b2dce44c0)
@@ -50,6 +50,5 @@
 #include <proc/uarg.h>
 #include <syscall/syscall.h>
-
-static int kbd_release=0;
+#include <ddi/irq.h>
 
 void arch_pre_main(void)
@@ -81,10 +80,11 @@
 	srlz_d();
 	
-	ski_init_console();
-	it_init();	
 }
 
 void arch_post_mm_init(void)
 {
+	irq_init(INR_COUNT, INR_COUNT);
+	ski_init_console();
+	it_init();	
 	ski_set_console_sysinfo();
 }
@@ -146,6 +146,5 @@
 void arch_grab_console(void)
 {
-    kbd_release=kbd_uspace;
-    kbd_uspace=0;
+	ski_kbd_grab();
 }
 /** Return console to userspace
@@ -154,5 +153,5 @@
 void arch_release_console(void)
 {
-    kbd_uspace=kbd_release;
+	ski_kbd_release();
 }
 
Index: kernel/arch/ia64/src/interrupt.c
===================================================================
--- kernel/arch/ia64/src/interrupt.c	(revision 6fb30a1a9fb76291a876ee61b596d65482cc7302)
+++ kernel/arch/ia64/src/interrupt.c	(revision de57e0601410d3336e18d797fc95a74b2dce44c0)
@@ -35,6 +35,10 @@
 
 #include <arch/interrupt.h>
+#include <interrupt.h>
+#include <ddi/irq.h>
 #include <panic.h>
 #include <print.h>
+#include <symtab.h>
+#include <debug.h>
 #include <console/console.h>
 #include <arch/types.h>
@@ -42,8 +46,5 @@
 #include <arch/barrier.h>
 #include <arch/register.h>
-#include <arch/drivers/it.h>
 #include <arch.h>
-#include <symtab.h>
-#include <debug.h>
 #include <syscall/syscall.h>
 #include <print.h>
@@ -52,6 +53,5 @@
 #include <ipc/irq.h>
 #include <ipc/ipc.h>
-#include <interrupt.h>
-
+#include <synch/spinlock.h>
 
 #define VECTORS_64_BUNDLE	20
@@ -61,5 +61,4 @@
 
 #define BUNDLE_SIZE		16
-
 
 char *vector_names_64_bundle[VECTORS_64_BUNDLE] = {
@@ -198,9 +197,7 @@
 }
 
-
 void nop_handler(uint64_t vector, istate_t *istate)
 {
 }
-
 
 /** Handle syscall. */
@@ -229,4 +226,5 @@
 void external_interrupt(uint64_t vector, istate_t *istate)
 {
+	irq_t *irq;
 	cr_ivr_t ivr;
 	
@@ -234,30 +232,23 @@
 	srlz_d();
 
-	switch(ivr.vector) {
-	case INTERRUPT_TIMER:
-		it_interrupt();
-		break;
-	case INTERRUPT_SPURIOUS:
-	    	printf("cpu%d: spurious interrupt\n", CPU->id);
-		break;
-	default:
-		panic("\nUnhandled External Interrupt Vector %d\n", ivr.vector);
-		break;
+	irq = irq_dispatch_and_lock(ivr.vector);
+	if (irq) {
+		irq->handler(irq, irq->arg);
+		spinlock_unlock(&irq->lock);
+	} else {
+		switch (ivr.vector) {
+		case INTERRUPT_SPURIOUS:
+#ifdef CONFIG_DEBUG
+	 		printf("cpu%d: spurious interrupt\n", CPU->id);
+#endif
+			break;
+
+		default:
+			panic("\nUnhandled External Interrupt Vector %d\n", ivr.vector);
+			break;
+		}
 	}
 }
 
-void virtual_interrupt(uint64_t irq, void *param)
-{
-	switch(irq) {
-	case IRQ_KBD:
-		if (kbd_uspace)
-			ipc_irq_send_notif(irq);
-		break;
-	default:
-		panic("\nUnhandled Virtual Interrupt request %d\n", irq);
-		break;
-	}
-}
-
 /** @}
  */
Index: kernel/arch/ia64/src/ski/ski.c
===================================================================
--- kernel/arch/ia64/src/ski/ski.c	(revision 6fb30a1a9fb76291a876ee61b596d65482cc7302)
+++ kernel/arch/ia64/src/ski/ski.c	(revision de57e0601410d3336e18d797fc95a74b2dce44c0)
@@ -38,9 +38,21 @@
 #include <arch/interrupt.h>
 #include <sysinfo/sysinfo.h>
+#include <arch/types.h>
+#include <typedefs.h>
+#include <ddi/device.h>
+#include <ddi/irq.h>
+#include <ipc/irq.h>
+#include <synch/spinlock.h>
+#include <arch/asm.h>
+
+#define SKI_KBD_INR	0
+
+static irq_t ski_kbd_irq;
+static devno_t ski_kbd_devno;
 
 chardev_t ski_console;
 chardev_t ski_uconsole;
-static bool kb_disable;
-int kbd_uspace=0;
+
+static bool kbd_disabled;
 
 static void ski_putchar(chardev_t *d, const char ch);
@@ -58,6 +70,6 @@
 {
 	__asm__ volatile (
-		"mov r15=%0\n"
-		"mov r32=%1\n"		/* r32 is in0 */
+		"mov r15 = %0\n"
+		"mov r32 = %1\n"	/* r32 is in0 */
 		"break 0x80000\n"	/* modifies r8 */
 		:
@@ -84,11 +96,11 @@
 	
 	__asm__ volatile (
-		"mov r15=%1\n"
+		"mov r15 = %1\n"
 		"break 0x80000;;\n"	/* modifies r8 */
-		"mov %0=r8;;\n"		
+		"mov %0 = r8;;\n"		
 
 		: "=r" (ch)
 		: "i" (SKI_GETCHAR)
-		: "r15",  "r8"
+		: "r15", "r8"
 	);
 
@@ -104,5 +116,5 @@
 	int ch;
 
-	while(!(ch=ski_getchar()))
+	while(!(ch = ski_getchar()))
 		;
 	if(ch == '\r')
@@ -116,50 +128,69 @@
 	char ch;
 	static char last; 
-
-	if (kb_disable)
+	ipl_t ipl;
+
+	ipl = interrupts_disable();
+
+	if (kbd_disabled) {
+		interrupts_restore(ipl);
 		return;
+	}
+		
+	spinlock_lock(&ski_kbd_irq.lock);
 
 	ch = ski_getchar();
 	if(ch == '\r')
 		ch = '\n'; 
-	if (ch){
-		if(kbd_uspace){
+	if (ch) {
+		if (ski_kbd_irq.notif_cfg.notify && ski_kbd_irq.notif_cfg.answerbox) {
 			chardev_push_character(&ski_uconsole, ch);
-			virtual_interrupt(IRQ_KBD,NULL);
-		}
-		else {
+			ipc_irq_send_notif(&ski_kbd_irq);
+		} else {
 			chardev_push_character(&ski_console, ch);
 		}	
-		last = ch;		
+		last = ch;
+		spinlock_unlock(&ski_kbd_irq.lock);
+		interrupts_restore(ipl);
 		return;
-	}	
-
-	if (last){
-		if(kbd_uspace){
+	}
+
+	if (last) {
+		if (ski_kbd_irq.notif_cfg.notify && ski_kbd_irq.notif_cfg.answerbox) {
 			chardev_push_character(&ski_uconsole, 0);
-			virtual_interrupt(IRQ_KBD,NULL);
+			ipc_irq_send_notif(&ski_kbd_irq);
 		}
-		else {
-		}	
-		last = 0;		
-	}	
-
+		last = 0;
+	}
+
+	spinlock_unlock(&ski_kbd_irq.lock);
+	interrupts_restore(ipl);
 }
 
 /* Called from getc(). */
-static void ski_kb_enable(chardev_t *d)
-{
-	kb_disable = false;
+static void ski_kbd_enable(chardev_t *d)
+{
+	kbd_disabled = false;
 }
 
 /* Called from getc(). */
-static void ski_kb_disable(chardev_t *d)
-{
-	kb_disable = true;	
+static void ski_kbd_disable(chardev_t *d)
+{
+	kbd_disabled = true;	
+}
+
+/** Decline to service hardware IRQ.
+ *
+ * This is only a virtual IRQ, so always decline.
+ *
+ * @return Always IRQ_DECLINE.
+ */
+static irq_ownership_t ski_kbd_claim(void)
+{
+	return IRQ_DECLINE;
 }
 
 static chardev_operations_t ski_ops = {
-	.resume = ski_kb_enable,
-	.suspend = ski_kb_disable,
+	.resume = ski_kbd_enable,
+	.suspend = ski_kbd_disable,
 	.write = ski_putchar,
 	.read = ski_getchar_blocking
@@ -174,5 +205,5 @@
 {
 	__asm__ volatile (
-		"mov r15=%0\n"
+		"mov r15 = %0\n"
 		"break 0x80000\n"
 		:
@@ -186,4 +217,12 @@
 	stdout = &ski_console;
 
+	ski_kbd_devno = device_assign_devno();
+	
+	irq_initialize(&ski_kbd_irq);
+	ski_kbd_irq.inr = SKI_KBD_INR;
+	ski_kbd_irq.devno = ski_kbd_devno;
+	ski_kbd_irq.claim = ski_kbd_claim;
+	irq_register(&ski_kbd_irq);
+
 }
 
@@ -196,6 +235,18 @@
 void ski_set_console_sysinfo(void)
 {
-	sysinfo_set_item_val("kbd",NULL,true);
-	sysinfo_set_item_val("kbd.irq",NULL,IRQ_KBD);
+	sysinfo_set_item_val("kbd", NULL, true);
+	sysinfo_set_item_val("kbd.inr", NULL, SKI_KBD_INR);
+	sysinfo_set_item_val("kbd.devno", NULL, ski_kbd_devno);
+}
+
+void ski_kbd_grab(void)
+{
+	ski_kbd_irq.notif_cfg.notify = false;
+}
+
+void ski_kbd_release(void)
+{
+	if (ski_kbd_irq.notif_cfg.answerbox)
+		ski_kbd_irq.notif_cfg.notify = true;
 }
 
