Index: generic/src/ipc/ipc.c
===================================================================
--- generic/src/ipc/ipc.c	(revision d8f7362433d8362e6786d4323938f5439281167a)
+++ generic/src/ipc/ipc.c	(revision bffa0b06adea1b03489a7f0c461606f20a0da9b2)
@@ -336,8 +336,5 @@
 		list_append(&request->link, &box->dispatched_calls);
 	} else {
-		/* This can happen regularly after ipc_cleanup, remove
-		 * the warning in the future when the IPC is
-		 * more debugged */
-		printf("WARNING: Spurious IPC wakeup.\n");
+		/* This can happen regularly after ipc_cleanup */
 		spinlock_unlock(&box->lock);
 		goto restart;
Index: generic/src/ipc/irq.c
===================================================================
--- generic/src/ipc/irq.c	(revision d8f7362433d8362e6786d4323938f5439281167a)
+++ generic/src/ipc/irq.c	(revision bffa0b06adea1b03489a7f0c461606f20a0da9b2)
@@ -157,14 +157,15 @@
 {
 	ipl_t ipl;
+	int mq = irq + IPC_IRQ_RESERVED_VIRTUAL;
 
 	ipl = interrupts_disable();
-	spinlock_lock(&irq_conns[irq].lock);
-	if (irq_conns[irq].box == box) {
-		irq_conns[irq].box = NULL;
-		code_free(irq_conns[irq].code);
-		irq_conns[irq].code = NULL;
-	}
-
-	spinlock_unlock(&irq_conns[irq].lock);
+	spinlock_lock(&irq_conns[mq].lock);
+	if (irq_conns[mq].box == box) {
+		irq_conns[mq].box = NULL;
+		code_free(irq_conns[mq].code);
+		irq_conns[mq].code = NULL;
+	}
+
+	spinlock_unlock(&irq_conns[mq].lock);
 	interrupts_restore(ipl);
 }
@@ -175,4 +176,5 @@
 	ipl_t ipl;
 	irq_code_t *code;
+	int mq = irq + IPC_IRQ_RESERVED_VIRTUAL;
 
 	ASSERT(irq_conns);
@@ -186,16 +188,16 @@
 
 	ipl = interrupts_disable();
-	spinlock_lock(&irq_conns[irq].lock);
-
-	if (irq_conns[irq].box) {
-		spinlock_unlock(&irq_conns[irq].lock);
+	spinlock_lock(&irq_conns[mq].lock);
+
+	if (irq_conns[mq].box) {
+		spinlock_unlock(&irq_conns[mq].lock);
 		interrupts_restore(ipl);
 		code_free(code);
 		return EEXISTS;
 	}
-	irq_conns[irq].box = box;
-	irq_conns[irq].code = code;
-	atomic_set(&irq_conns[irq].counter, 0);
-	spinlock_unlock(&irq_conns[irq].lock);
+	irq_conns[mq].box = box;
+	irq_conns[mq].code = code;
+	atomic_set(&irq_conns[mq].counter, 0);
+	spinlock_unlock(&irq_conns[mq].lock);
 	interrupts_restore(ipl);
 
@@ -203,19 +205,30 @@
 }
 
-/** Notify process that an irq had happend
- *
- * We expect interrupts to be disabled
- */
-void ipc_irq_send_notif(int irq)
+/** Add call to proper answerbox queue
+ *
+ * Assume irq_conns[mq].lock is locked */
+static void send_call(int mq, call_t *call)
+{
+	spinlock_lock(&irq_conns[mq].box->irq_lock);
+	list_append(&call->link, &irq_conns[mq].box->irq_notifs);
+	spinlock_unlock(&irq_conns[mq].box->irq_lock);
+		
+	waitq_wakeup(&irq_conns[mq].box->wq, 0);
+}
+
+/** Send notification message
+ *
+ */
+void ipc_irq_send_msg(int irq, __native a2, __native a3)
 {
 	call_t *call;
-
-	ASSERT(irq_conns);
-	spinlock_lock(&irq_conns[irq].lock);
-
-	if (irq_conns[irq].box) {
+	int mq = irq + IPC_IRQ_RESERVED_VIRTUAL;
+
+	spinlock_lock(&irq_conns[mq].lock);
+
+	if (irq_conns[mq].box) {
 		call = ipc_call_alloc(FRAME_ATOMIC);
 		if (!call) {
-			spinlock_unlock(&irq_conns[irq].lock);
+			spinlock_unlock(&irq_conns[mq].lock);
 			return;
 		}
@@ -223,24 +236,54 @@
 		IPC_SET_METHOD(call->data, IPC_M_INTERRUPT);
 		IPC_SET_ARG1(call->data, irq);
-		IPC_SET_ARG3(call->data, atomic_preinc(&irq_conns[irq].counter));
+		IPC_SET_ARG2(call->data, a2);
+		IPC_SET_ARG3(call->data, a3);
+		
+		send_call(mq, call);
+	}
+	spinlock_unlock(&irq_conns[mq].lock);
+}
+
+/** Notify process that an irq had happend
+ *
+ * We expect interrupts to be disabled
+ */
+void ipc_irq_send_notif(int irq)
+{
+	call_t *call;
+	int mq = irq + IPC_IRQ_RESERVED_VIRTUAL;
+
+	ASSERT(irq_conns);
+	spinlock_lock(&irq_conns[mq].lock);
+
+	if (irq_conns[mq].box) {
+		call = ipc_call_alloc(FRAME_ATOMIC);
+		if (!call) {
+			spinlock_unlock(&irq_conns[mq].lock);
+			return;
+		}
+		call->flags |= IPC_CALL_NOTIF;
+		IPC_SET_METHOD(call->data, IPC_M_INTERRUPT);
+		IPC_SET_ARG1(call->data, irq);
+		IPC_SET_ARG3(call->data, atomic_preinc(&irq_conns[mq].counter));
 
 		/* Execute code to handle irq */
-		code_execute(call, irq_conns[irq].code);
-
-		spinlock_lock(&irq_conns[irq].box->irq_lock);
-		list_append(&call->link, &irq_conns[irq].box->irq_notifs);
-		spinlock_unlock(&irq_conns[irq].box->irq_lock);
-
-		waitq_wakeup(&irq_conns[irq].box->wq, 0);
-	}
+		code_execute(call, irq_conns[mq].code);
 		
-	spinlock_unlock(&irq_conns[irq].lock);
-}
-
-
-/** Initialize table of interrupt handlers */
+		send_call(mq, call);
+	}
+		
+	spinlock_unlock(&irq_conns[mq].lock);
+}
+
+
+/** Initialize table of interrupt handlers
+ *
+ * @param irqcount Count of required hardware IRQs to be supported
+ */
 void ipc_irq_make_table(int irqcount)
 {
 	int i;
+
+	irqcount +=  IPC_IRQ_RESERVED_VIRTUAL;
 
 	irq_conns_size = irqcount;
Index: generic/src/ipc/sysipc.c
===================================================================
--- generic/src/ipc/sysipc.c	(revision d8f7362433d8362e6786d4323938f5439281167a)
+++ generic/src/ipc/sysipc.c	(revision bffa0b06adea1b03489a7f0c461606f20a0da9b2)
@@ -554,12 +554,12 @@
 
 /** Connect irq handler to task */
-__native sys_ipc_register_irq(__native irq, irq_code_t *ucode)
+__native sys_ipc_register_irq(int irq, irq_code_t *ucode)
 {
 	if (!(cap_get(TASK) & CAP_IRQ_REG))
 		return EPERM;
 
-	if (irq >= IRQ_COUNT)
+	if (irq >= IRQ_COUNT || irq <= -IPC_IRQ_RESERVED_VIRTUAL)
 		return (__native) ELIMIT;
-
+	
 	irq_ipc_bind_arch(irq);
 
@@ -568,10 +568,10 @@
 
 /* Disconnect irq handler from task */
-__native sys_ipc_unregister_irq(__native irq)
+__native sys_ipc_unregister_irq(int irq)
 {
 	if (!(cap_get(TASK) & CAP_IRQ_REG))
 		return EPERM;
 
-	if (irq >= IRQ_COUNT)
+	if (irq >= IRQ_COUNT || irq <= -IPC_IRQ_RESERVED_VIRTUAL)
 		return (__native) ELIMIT;
 
