Index: generic/src/ipc/ipc.c
===================================================================
--- generic/src/ipc/ipc.c	(revision 4e49572dad56d20917516259581d99e2ff0d8c6c)
+++ generic/src/ipc/ipc.c	(revision ba81cab60a5926ed0eb9888e74ef22a77ec9792e)
@@ -50,4 +50,12 @@
 static slab_cache_t *ipc_call_slab;
 
+/* Initialize new call */
+static void _ipc_call_init(call_t *call)
+{
+	memsetb((__address)call, sizeof(*call), 0);
+	call->callerbox = &TASK->answerbox;
+	call->sender = TASK;
+}
+
 /** Allocate & initialize call structure
  * 
@@ -60,7 +68,5 @@
 
 	call = slab_alloc(ipc_call_slab, 0);
-	memsetb((__address)call, sizeof(*call), 0);
-	call->callerbox = &TASK->answerbox;
-	call->sender = TASK;
+	_ipc_call_init(call);
 
 	return call;
@@ -68,9 +74,8 @@
 
 /** Initialize allocated call */
-void ipc_call_init(call_t *call)
-{
-	call->callerbox = &TASK->answerbox;
-	call->flags = IPC_CALL_STATIC_ALLOC;
-	call->sender = TASK;
+void ipc_call_static_init(call_t *call)
+{
+	_ipc_call_init(call);
+	call->flags |= IPC_CALL_STATIC_ALLOC;
 }
 
@@ -97,4 +102,6 @@
 void ipc_phone_connect(phone_t *phone, answerbox_t *box)
 {
+	spinlock_lock(&phone->lock);
+
 	ASSERT(!phone->callee);
 	phone->busy = 1;
@@ -104,4 +111,6 @@
 	list_append(&phone->list, &box->connected_phones);
 	spinlock_unlock(&box->lock);
+
+	spinlock_unlock(&phone->lock);
 }
 
@@ -115,5 +124,8 @@
 }
 
-/** Disconnect phone from answerbox */
+/** Disconnect phone from answerbox
+ *
+ * It is allowed to call disconnect on already disconnected phone\
+ */
 void ipc_phone_destroy(phone_t *phone)
 {
@@ -122,7 +134,14 @@
 	ASSERT(box);
 
-	spinlock_lock(&box->lock);
-	list_remove(&phone->list);
-	spinlock_unlock(&box->lock);
+	spinlock_lock(&phone->lock);
+	spinlock_lock(&box->lock);
+
+	if (phone->callee) {
+		list_remove(&phone->list);
+		phone->callee = NULL;
+	}
+
+	spinlock_unlock(&box->lock);
+	spinlock_unlock(&phone->lock);
 }
 
@@ -141,4 +160,35 @@
 }
 
+/** Answer message that was not dispatched and is not entered in
+ * any queue
+ */
+static void _ipc_answer_free_call(call_t *call)
+{
+	answerbox_t *callerbox = call->callerbox;
+
+	call->flags &= ~IPC_CALL_DISPATCHED;
+	call->flags |= IPC_CALL_ANSWERED;
+
+	spinlock_lock(&callerbox->lock);
+	list_append(&call->list, &callerbox->answers);
+	spinlock_unlock(&callerbox->lock);
+	waitq_wakeup(&callerbox->wq, 0);
+}
+
+/** Answer message, that is in callee queue
+ *
+ * @param box Answerbox that is answering the message
+ * @param call Modified request that is being sent back
+ */
+void ipc_answer(answerbox_t *box, call_t *call)
+{
+	/* Remove from active box */
+	spinlock_lock(&box->lock);
+	list_remove(&call->list);
+	spinlock_unlock(&box->lock);
+	/* Send back answer */
+	_ipc_answer_free_call(call);
+}
+
 /** Send a asynchronous request using phone to answerbox
  *
@@ -148,7 +198,14 @@
 void ipc_call(phone_t *phone, call_t *call)
 {
-	answerbox_t *box = phone->callee;
-
-	ASSERT(box);
+	answerbox_t *box;
+
+	spinlock_lock(&phone->lock);
+	box = phone->callee;
+	if (!box) {
+		/* Trying to send over disconnected phone */
+		IPC_SET_RETVAL(call->data, ENOENT);
+		_ipc_answer_free_call(call);
+		return;
+	}
 
 	spinlock_lock(&box->lock);
@@ -156,4 +213,6 @@
 	spinlock_unlock(&box->lock);
 	waitq_wakeup(&box->wq, 0);
+	
+	spinlock_unlock(&phone->lock);
 }
 
@@ -164,5 +223,5 @@
  * @param oldbox Old answerbox
  */
-void ipc_forward(call_t *call, answerbox_t *newbox, answerbox_t *oldbox)
+void ipc_forward(call_t *call, phone_t *newphone, answerbox_t *oldbox)
 {
 	spinlock_lock(&oldbox->lock);
@@ -170,31 +229,7 @@
 	spinlock_unlock(&oldbox->lock);
 
-	spinlock_lock(&newbox->lock);
-	list_append(&call->list, &newbox->calls);
-	spinlock_lock(&newbox->lock);
-	waitq_wakeup(&newbox->wq, 0);
-}
-
-/** Answer message back to phone
- *
- * @param box Answerbox that is answering the message
- * @param request Modified request that is being sent back
- */
-void ipc_answer(answerbox_t *box, call_t *request)
-{
-	answerbox_t *callerbox = request->callerbox;
-
-	request->flags &= ~IPC_CALL_DISPATCHED;
-	request->flags |= IPC_CALL_ANSWERED;
-
-	spinlock_lock(&box->lock);
-	list_remove(&request->list);
-	spinlock_unlock(&box->lock);
-
-	spinlock_lock(&callerbox->lock);
-	list_append(&request->list, &callerbox->answers);
-	spinlock_unlock(&callerbox->lock);
-	waitq_wakeup(&callerbox->wq, 0);
-}
+	ipc_call(newphone, call);
+}
+
 
 /** Wait for phone call 
