Index: arch/amd64/src/interrupt.c
===================================================================
--- arch/amd64/src/interrupt.c	(revision 407862eaba1d17531867b62b28be806c2792f52b)
+++ arch/amd64/src/interrupt.c	(revision 5626277b8459d4e7f87105bacfa7b3ef4aa4e53b)
@@ -45,4 +45,6 @@
 #include <synch/spinlock.h>
 #include <arch/ddi/ddi.h>
+#include <interrupt.h>
+#include <ipc/sysipc.h>
 
 void print_info_errcode(int n, istate_t *istate)
@@ -154,2 +156,17 @@
 
 }
+
+static void ipc_int(int n, istate_t *istate)
+{
+	trap_virtual_eoi();
+	ipc_irq_send_notif(n-IVT_IRQBASE);
+}
+
+
+/* Reregister irq to be IPC-ready */
+void irq_ipc_bind_arch(__native irq)
+{
+	if (irq == IRQ_CLK)
+		return;
+	exc_register(IVT_IRQBASE+irq, "ipc_int", ipc_int);
+}
Index: arch/ia32/src/interrupt.c
===================================================================
--- arch/ia32/src/interrupt.c	(revision 407862eaba1d17531867b62b28be806c2792f52b)
+++ arch/ia32/src/interrupt.c	(revision 5626277b8459d4e7f87105bacfa7b3ef4aa4e53b)
@@ -44,4 +44,6 @@
 #include <synch/spinlock.h>
 #include <arch/ddi/ddi.h>
+#include <ipc/sysipc.h>
+#include <interrupt.h>
 
 /*
@@ -185,2 +187,17 @@
 
 }
+
+static void ipc_int(int n, istate_t *istate)
+{
+	trap_virtual_eoi();
+	ipc_irq_send_notif(n-IVT_IRQBASE);
+}
+
+
+/* Reregister irq to be IPC-ready */
+void irq_ipc_bind_arch(__native irq)
+{
+	if (irq == IRQ_CLK)
+		return;
+	exc_register(IVT_IRQBASE+irq, "ipc_int", ipc_int);
+}
Index: arch/mips32/include/interrupt.h
===================================================================
--- arch/mips32/include/interrupt.h	(revision 407862eaba1d17531867b62b28be806c2792f52b)
+++ arch/mips32/include/interrupt.h	(revision 5626277b8459d4e7f87105bacfa7b3ef4aa4e53b)
@@ -34,4 +34,5 @@
 #define IVT_ITEMS   40
 #define INT_OFFSET  32
+#define IRQ_COUNT   8
 
 #define int_register(it, name, handler) exc_register(((it)+INT_OFFSET),name,handler)
Index: arch/mips32/src/interrupt.c
===================================================================
--- arch/mips32/src/interrupt.c	(revision 407862eaba1d17531867b62b28be806c2792f52b)
+++ arch/mips32/src/interrupt.c	(revision 5626277b8459d4e7f87105bacfa7b3ef4aa4e53b)
@@ -34,4 +34,6 @@
 #include <time/clock.h>
 #include <arch/drivers/arc.h>
+
+#include <ipc/sysipc.h>
 
 /** Disable interrupts.
@@ -84,4 +86,5 @@
 {
 	cp0_cause_write(cp0_cause_read() & ~(1 << 8)); /* clear SW0 interrupt */
+	ipc_irq_send_notif(0);
 }
 
@@ -89,4 +92,5 @@
 {
 	cp0_cause_write(cp0_cause_read() & ~(1 << 9)); /* clear SW1 interrupt */
+	ipc_irq_send_notif(1);
 }
 
@@ -98,2 +102,18 @@
 	int_register(1, "swint1", swint1);
 }
+
+#include <print.h>
+static void ipc_int(int n, istate_t *istate)
+{
+	ipc_irq_send_notif(n-INT_OFFSET);
+}
+
+/* Reregister irq to be IPC-ready */
+void irq_ipc_bind_arch(__native irq)
+{
+	/* Do not allow to redefine timer */
+	/* Swint0, Swint1 are already handled */
+	if (irq == TIMER_IRQ || irq < 2)
+		return;
+	int_register(irq, "ipc_int", ipc_int);
+}
Index: generic/include/errno.h
===================================================================
--- generic/include/errno.h	(revision 407862eaba1d17531867b62b28be806c2792f52b)
+++ generic/include/errno.h	(revision 5626277b8459d4e7f87105bacfa7b3ef4aa4e53b)
@@ -41,4 +41,5 @@
 			* to close the connection. Used by answerbox
 			* to close the connection.  */
+#define EEXISTS    -8  /* Entry already exists */
 
 #endif
Index: generic/include/ipc/ipc.h
===================================================================
--- generic/include/ipc/ipc.h	(revision 407862eaba1d17531867b62b28be806c2792f52b)
+++ generic/include/ipc/ipc.h	(revision 5626277b8459d4e7f87105bacfa7b3ef4aa4e53b)
@@ -44,4 +44,5 @@
 #define IPC_CALL_FORWARDED      (1<<3) /* Call was forwarded */
 #define IPC_CALL_CONN_ME_TO     (1<<4) /* Identify connect_me_to */
+#define IPC_CALL_NOTIF          (1<<5) /* Interrupt notification */
 
 /* Flags for ipc_wait_for_call */
@@ -120,4 +121,6 @@
  */
 #define IPC_M_PHONE_HUNGUP      3
+/** Interrupt notification */
+#define IPC_M_INTERRUPT         4
 
 
@@ -155,4 +158,7 @@
 
 	link_t answers;          /**< Answered calls */
+
+	SPINLOCK_DECLARE(irq_lock);
+	link_t irq_notifs;       /**< Notifications from IRQ handlers */
 };
 
@@ -196,5 +202,5 @@
 extern void ipc_phone_connect(phone_t *phone, answerbox_t *box);
 extern void ipc_call_free(call_t *call);
-extern call_t * ipc_call_alloc(void);
+extern call_t * ipc_call_alloc(int flags);
 extern void ipc_answerbox_init(answerbox_t *box);
 extern void ipc_call_static_init(call_t *call);
@@ -205,4 +211,9 @@
 extern void ipc_backsend_err(phone_t *phone, call_t *call, __native err);
 
+extern int ipc_irq_register(answerbox_t *box, int irq);
+extern void ipc_irq_send_notif(int irq);
+extern void ipc_irq_unregister(answerbox_t *box, int irq);
+
+
 extern answerbox_t *ipc_phone_0;
 
Index: generic/include/ipc/sysipc.h
===================================================================
--- generic/include/ipc/sysipc.h	(revision 407862eaba1d17531867b62b28be806c2792f52b)
+++ generic/include/ipc/sysipc.h	(revision 5626277b8459d4e7f87105bacfa7b3ef4aa4e53b)
@@ -30,4 +30,6 @@
 #define __SYSIPC_H__
 
+#include <ipc/ipc.h>
+
 __native sys_ipc_call_sync_fast(__native phoneid, __native method, 
 				__native arg1, ipc_data_t *data);
@@ -44,5 +46,8 @@
 			      __native method, __native arg1);
 __native sys_ipc_hangup(int phoneid);
+__native sys_ipc_register_irq(__native irq);
+__native sys_ipc_unregister_irq(__native irq);
 
+void irq_ipc_bind_arch(__native irq);
 
 #endif
Index: generic/include/syscall/syscall.h
===================================================================
--- generic/include/syscall/syscall.h	(revision 407862eaba1d17531867b62b28be806c2792f52b)
+++ generic/include/syscall/syscall.h	(revision 5626277b8459d4e7f87105bacfa7b3ef4aa4e53b)
@@ -52,4 +52,6 @@
 	SYS_IPC_WAIT,
 	SYS_IPC_HANGUP,
+	SYS_IPC_REGISTER_IRQ,
+	SYS_IPC_UNREGISTER_IRQ,
 	SYS_MAP_PHYSMEM,
 	SYS_IOSPACE_ENABLE,
Index: generic/src/ipc/ipc.c
===================================================================
--- generic/src/ipc/ipc.c	(revision 407862eaba1d17531867b62b28be806c2792f52b)
+++ generic/src/ipc/ipc.c	(revision 5626277b8459d4e7f87105bacfa7b3ef4aa4e53b)
@@ -44,4 +44,5 @@
 #include <print.h>
 #include <proc/thread.h>
+#include <arch/interrupt.h>
 
 /* Open channel that is assigned automatically to new tasks */
@@ -49,4 +50,12 @@
 
 static slab_cache_t *ipc_call_slab;
+
+typedef struct {
+	SPINLOCK_DECLARE(lock);
+	answerbox_t *box;
+} ipc_irq_t;
+
+static ipc_irq_t *irq_conns = NULL;
+static int irq_conns_size;
 
 /* Initialize new call */
@@ -62,10 +71,12 @@
  * The call is initialized, so that the reply will be directed
  * to TASK->answerbox
- */
-call_t * ipc_call_alloc(void)
+ *
+ * @param flags Parameters for slab_alloc (ATOMIC, etc.)
+ */
+call_t * ipc_call_alloc(int flags)
 {
 	call_t *call;
 
-	call = slab_alloc(ipc_call_slab, 0);
+	call = slab_alloc(ipc_call_slab, flags);
 	_ipc_call_init(call);
 
@@ -91,4 +102,5 @@
 {
 	spinlock_initialize(&box->lock, "ipc_box_lock");
+	spinlock_initialize(&box->irq_lock, "ipc_box_irqlock");
 	waitq_initialize(&box->wq);
 	list_initialize(&box->connected_phones);
@@ -96,4 +108,5 @@
 	list_initialize(&box->dispatched_calls);
 	list_initialize(&box->answers);
+	list_initialize(&box->irq_notifs);
 	box->task = TASK;
 }
@@ -262,5 +275,5 @@
 	spinlock_unlock(&box->lock);
 
-	call = ipc_call_alloc();
+	call = ipc_call_alloc(0);
 	IPC_SET_METHOD(call->data, IPC_M_PHONE_HUNGUP);
 	call->flags |= IPC_CALL_DISCARD_ANSWER;
@@ -302,4 +315,5 @@
 {
 	call_t *request;
+	ipl_t ipl;
 
 restart:      
@@ -311,5 +325,14 @@
 	
 	spinlock_lock(&box->lock);
-	if (!list_empty(&box->answers)) {
+	if (!list_empty(&box->irq_notifs)) {
+		ipl = interrupts_disable();
+		spinlock_lock(&box->irq_lock);
+
+		request = list_get_instance(box->answers.next, call_t, list);
+		list_remove(&request->list);
+
+		spinlock_unlock(&box->irq_lock);
+		interrupts_restore(ipl);
+	} else if (!list_empty(&box->answers)) {
 		/* Handle asynchronous answers */
 		request = list_get_instance(box->answers.next, call_t, list);
@@ -334,13 +357,4 @@
 }
 
-/** Initilize ipc subsystem */
-void ipc_init(void)
-{
-	ipc_call_slab = slab_cache_create("ipc_call",
-					  sizeof(call_t),
-					  0,
-					  NULL, NULL, 0);
-}
-
 /** Answer all calls from list with EHANGUP msg */
 static void ipc_cleanup_call_list(link_t *lst)
@@ -354,4 +368,24 @@
 		IPC_SET_RETVAL(call->data, EHANGUP);
 		_ipc_answer_free_call(call);
+	}
+}
+
+/** Disconnect all irq's notifications
+ *
+ * TODO: It may be better to do some linked list, so that
+ *       we wouldn't need to go through whole array every cleanup
+ */
+static void ipc_irq_cleanup(answerbox_t *box)
+{
+	int i;
+	ipl_t ipl;
+	
+	for (i=0; i < irq_conns_size; i++) {
+		ipl = interrupts_disable();
+		spinlock_lock(&irq_conns[i].lock);
+		if (irq_conns[i].box == box)
+			irq_conns[i].box = NULL;
+		spinlock_unlock(&irq_conns[i].lock);
+		interrupts_restore(ipl);
 	}
 }
@@ -370,4 +404,7 @@
 	for (i=0;i < IPC_MAX_PHONES; i++)
 		ipc_phone_hangup(&task->phones[i]);
+
+	/* Disconnect all connected irqs */
+	ipc_irq_cleanup(&task->answerbox);
 
 	/* Disconnect all phones connected to our answerbox */
@@ -406,2 +443,88 @@
 	}
 }
+
+/** Initialize table of interrupt handlers */
+static void ipc_irq_make_table(int irqcount)
+{
+	int i;
+
+	irq_conns_size = irqcount;
+	irq_conns = malloc(irqcount * (sizeof(*irq_conns)), 0);
+	for (i=0; i < irqcount; i++) {
+		spinlock_initialize(&irq_conns[i].lock, "irq_ipc_lock");
+		irq_conns[i].box = NULL;
+	}
+}
+
+void ipc_irq_unregister(answerbox_t *box, int irq)
+{
+	ipl_t ipl;
+
+	ipl = interrupts_disable();
+	spinlock_lock(&irq_conns[irq].lock);
+	if (irq_conns[irq].box == box)
+		irq_conns[irq].box = NULL;
+
+	spinlock_unlock(&irq_conns[irq].lock);
+	interrupts_restore(ipl);
+}
+
+/** Register an answerbox as a receiving end of interrupts notifications */
+int ipc_irq_register(answerbox_t *box, int irq)
+{
+	ipl_t ipl;
+
+	ASSERT(irq_conns);
+
+	ipl = interrupts_disable();
+	spinlock_lock(&irq_conns[irq].lock);
+
+	if (irq_conns[irq].box) {
+		spinlock_unlock(&irq_conns[irq].lock);
+		interrupts_restore(ipl);
+		return EEXISTS;
+	}
+	irq_conns[irq].box = box;
+	spinlock_unlock(&irq_conns[irq].lock);
+	interrupts_restore(ipl);
+
+	return 0;
+}
+
+/** Notify process that an irq had happend
+ *
+ * We expect interrupts to be disabled
+ */
+void ipc_irq_send_notif(int irq)
+{
+	call_t *call;
+
+	ASSERT(irq_conns);
+	spinlock_lock(&irq_conns[irq].lock);
+
+	if (irq_conns[irq].box) {
+		call = ipc_call_alloc(FRAME_ATOMIC);
+		call->flags |= IPC_CALL_NOTIF;
+		IPC_SET_METHOD(call->data, IPC_M_INTERRUPT);
+		IPC_SET_ARG1(call->data, irq);
+
+		spinlock_lock(&irq_conns[irq].box->irq_lock);
+		list_append(&call->list, &irq_conns[irq].box->irq_notifs);
+		spinlock_unlock(&irq_conns[irq].box->irq_lock);
+
+		waitq_wakeup(&irq_conns[irq].box->wq, 0);
+	}
+		
+	spinlock_unlock(&irq_conns[irq].lock);
+}
+
+/** Initilize ipc subsystem */
+void ipc_init(void)
+{
+	ipc_call_slab = slab_cache_create("ipc_call",
+					  sizeof(call_t),
+					  0,
+					  NULL, NULL, 0);
+	ipc_irq_make_table(IRQ_COUNT);
+}
+
Index: generic/src/ipc/sysipc.c
===================================================================
--- generic/src/ipc/sysipc.c	(revision 407862eaba1d17531867b62b28be806c2792f52b)
+++ generic/src/ipc/sysipc.c	(revision 5626277b8459d4e7f87105bacfa7b3ef4aa4e53b)
@@ -37,5 +37,5 @@
 #include <ipc/sysipc.h>
 #include <ipc/ipcrsc.h>
-
+#include <arch/interrupt.h>
 
 #include <print.h>
@@ -275,5 +275,5 @@
 	GET_CHECK_PHONE(phone, phoneid, return IPC_CALLRET_FATAL);
 
-	call = ipc_call_alloc();
+	call = ipc_call_alloc(0);
 	IPC_SET_METHOD(call->data, method);
 	IPC_SET_ARG1(call->data, arg1);
@@ -303,5 +303,5 @@
 	GET_CHECK_PHONE(phone, phoneid, return IPC_CALLRET_FATAL);
 
-	call = ipc_call_alloc();
+	call = ipc_call_alloc(0);
 	copy_from_uspace(&call->data.args, &data->args, sizeof(call->data.args));
 	if (!(res=request_preprocess(call)))
@@ -442,4 +442,12 @@
 		return 0;
 
+	if (call->flags & IPC_CALL_NOTIF) {
+		ASSERT(! (call->flags & IPC_CALL_STATIC_ALLOC));
+		STRUCT_TO_USPACE(&calldata->args, &call->data.args);
+		ipc_call_free(call);
+		
+		return ((__native)call) | IPC_CALLID_NOTIFICATION;
+	}
+
 	if (call->flags & IPC_CALL_ANSWERED) {
 		process_answer(call);
@@ -468,2 +476,23 @@
 	return (__native)call;
 }
+
+/** Connect irq handler to task */
+__native sys_ipc_register_irq(__native irq)
+{
+	if (irq >= IRQ_COUNT)
+		return -ELIMIT;
+
+	irq_ipc_bind_arch(irq);
+	return ipc_irq_register(&TASK->answerbox, irq);
+}
+
+/* Disconnect irq handler from task */
+__native sys_ipc_unregister_irq(__native irq)
+{
+	if (irq >= IRQ_COUNT)
+		return -ELIMIT;
+
+	ipc_irq_unregister(&TASK->answerbox, irq);
+
+	return 0;
+}
Index: generic/src/syscall/syscall.c
===================================================================
--- generic/src/syscall/syscall.c	(revision 407862eaba1d17531867b62b28be806c2792f52b)
+++ generic/src/syscall/syscall.c	(revision 5626277b8459d4e7f87105bacfa7b3ef4aa4e53b)
@@ -97,5 +97,7 @@
 	sys_ipc_wait_for_call,
 	sys_ipc_hangup,
-	
+	sys_ipc_register_irq,
+	sys_ipc_unregister_irq,
+
 	/* DDI related syscalls. */
 	sys_physmem_map,
